Reissue PAT if roles changed
[ZITADOPER-1]
This commit is contained in:
@@ -2,9 +2,10 @@ package v1alpha1
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
ConditionTypeReady string = "Ready"
|
ConditionTypeReady string = "Ready"
|
||||||
ConditionTypeBackupRestored string = "BackupRestored"
|
ConditionTypePATUpToDate string = "PATUpToDate"
|
||||||
ConditionTypeReplicationConfigured string = "ReplicationConfigured"
|
|
||||||
ConditionTypeComplete string = "Complete"
|
ConditionReasonRolesChanged string = "RolesChanged"
|
||||||
|
ConditionReasonPATUpToDate string = "UpToDate"
|
||||||
|
|
||||||
ConditionReasonDeploymentNotReady string = "DeploymentNotReady"
|
ConditionReasonDeploymentNotReady string = "DeploymentNotReady"
|
||||||
ConditionReasonDeploymentReady string = "DeploymentReady"
|
ConditionReasonDeploymentReady string = "DeploymentReady"
|
||||||
|
|||||||
@@ -66,6 +66,13 @@ func (d *MachineUserStatus) SetCondition(condition metav1.Condition) {
|
|||||||
meta.SetStatusCondition(&d.Conditions, condition)
|
meta.SetStatusCondition(&d.Conditions, condition)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *MachineUserStatus) GetConditionStatus(conditionType string) bool {
|
||||||
|
if d.Conditions == nil {
|
||||||
|
d.Conditions = make([]metav1.Condition, 0)
|
||||||
|
}
|
||||||
|
return meta.IsStatusConditionTrue(d.Conditions, conditionType)
|
||||||
|
}
|
||||||
|
|
||||||
//+kubebuilder:object:root=true
|
//+kubebuilder:object:root=true
|
||||||
//+kubebuilder:subresource:status
|
//+kubebuilder:subresource:status
|
||||||
|
|
||||||
|
|||||||
@@ -21,10 +21,12 @@ import (
|
|||||||
project "github.com/zitadel/zitadel-go/v2/pkg/client/zitadel/project"
|
project "github.com/zitadel/zitadel-go/v2/pkg/client/zitadel/project"
|
||||||
user "github.com/zitadel/zitadel-go/v2/pkg/client/zitadel/user"
|
user "github.com/zitadel/zitadel-go/v2/pkg/client/zitadel/user"
|
||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/api/errors"
|
||||||
"k8s.io/apimachinery/pkg/types"
|
"k8s.io/apimachinery/pkg/types"
|
||||||
"k8s.io/client-go/util/workqueue"
|
"k8s.io/client-go/util/workqueue"
|
||||||
ctrl "sigs.k8s.io/controller-runtime"
|
ctrl "sigs.k8s.io/controller-runtime"
|
||||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||||
|
clientpkg "sigs.k8s.io/controller-runtime/pkg/client"
|
||||||
ctrlClient "sigs.k8s.io/controller-runtime/pkg/client"
|
ctrlClient "sigs.k8s.io/controller-runtime/pkg/client"
|
||||||
"sigs.k8s.io/controller-runtime/pkg/controller"
|
"sigs.k8s.io/controller-runtime/pkg/controller"
|
||||||
)
|
)
|
||||||
@@ -192,7 +194,15 @@ func (wr *wrappedMachineUserReconciler) reconcilePAT(ctx context.Context, ztdCli
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if token == nil {
|
if token == nil || !wr.MachineUser.Status.GetConditionStatus(zitadelv1alpha1.ConditionTypePATUpToDate) {
|
||||||
|
if token != nil {
|
||||||
|
if _, err = ztdClient.RemovePersonalAccessToken(ctx, &pb.RemovePersonalAccessTokenRequest{
|
||||||
|
UserId: wr.MachineUser.Status.UserId,
|
||||||
|
TokenId: wr.MachineUser.Status.PATId,
|
||||||
|
}); err != nil {
|
||||||
|
return fmt.Errorf("Error removing PAT: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
resp, err := ztdClient.AddPersonalAccessToken(ctx, &pb.AddPersonalAccessTokenRequest{
|
resp, err := ztdClient.AddPersonalAccessToken(ctx, &pb.AddPersonalAccessTokenRequest{
|
||||||
UserId: wr.MachineUser.Status.UserId,
|
UserId: wr.MachineUser.Status.UserId,
|
||||||
})
|
})
|
||||||
@@ -203,7 +213,7 @@ func (wr *wrappedMachineUserReconciler) reconcilePAT(ctx context.Context, ztdCli
|
|||||||
Name: wr.MachineUser.PatSecretName(),
|
Name: wr.MachineUser.PatSecretName(),
|
||||||
Namespace: wr.MachineUser.Namespace,
|
Namespace: wr.MachineUser.Namespace,
|
||||||
}
|
}
|
||||||
patSecret, err := wr.Builder.BuildSecret(builder.SecretOpts{
|
desiredPatSecret, err := wr.Builder.BuildSecret(builder.SecretOpts{
|
||||||
Key: key,
|
Key: key,
|
||||||
Immutable: true,
|
Immutable: true,
|
||||||
Data: map[string][]byte{
|
Data: map[string][]byte{
|
||||||
@@ -214,9 +224,30 @@ func (wr *wrappedMachineUserReconciler) reconcilePAT(ctx context.Context, ztdCli
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("error building PAT Secret: %v", err)
|
return fmt.Errorf("error building PAT Secret: %v", err)
|
||||||
}
|
}
|
||||||
if err := wr.Create(ctx, patSecret); err != nil {
|
|
||||||
return fmt.Errorf("error creating pat-secret Secret: %v", err)
|
{
|
||||||
|
var existingPatSecret corev1.Secret
|
||||||
|
if err := wr.Get(ctx, key, &existingPatSecret); err != nil {
|
||||||
|
if !errors.IsNotFound(err) {
|
||||||
|
return fmt.Errorf("error getting PAT Secret: %v", err)
|
||||||
}
|
}
|
||||||
|
if err := wr.Create(ctx, desiredPatSecret); err != nil {
|
||||||
|
return fmt.Errorf("error creating PAT Secret: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
patch := clientpkg.MergeFrom(existingPatSecret.DeepCopy())
|
||||||
|
existingPatSecret.Data = desiredPatSecret.Data
|
||||||
|
if err = wr.Patch(ctx, &existingPatSecret, patch); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = wr.PatchStatus(ctx, condition.SetPatUpToDate); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
patch := ctrlClient.MergeFrom(wr.MachineUser.DeepCopy())
|
patch := ctrlClient.MergeFrom(wr.MachineUser.DeepCopy())
|
||||||
wr.MachineUser.Status.PATId = resp.TokenId
|
wr.MachineUser.Status.PATId = resp.TokenId
|
||||||
return wr.Client.Status().Patch(ctx, wr.MachineUser, patch)
|
return wr.Client.Status().Patch(ctx, wr.MachineUser, patch)
|
||||||
@@ -268,7 +299,7 @@ func (wr *wrappedMachineUserReconciler) reconcileJWT(ctx context.Context, ztdCli
|
|||||||
}
|
}
|
||||||
patSecret, err := wr.Builder.BuildSecret(builder.SecretOpts{
|
patSecret, err := wr.Builder.BuildSecret(builder.SecretOpts{
|
||||||
Key: key,
|
Key: key,
|
||||||
Immutable: true,
|
Immutable: false,
|
||||||
Data: secretData,
|
Data: secretData,
|
||||||
}, wr.MachineUser)
|
}, wr.MachineUser)
|
||||||
|
|
||||||
@@ -343,6 +374,11 @@ func (wr *wrappedMachineUserReconciler) reconcileUserGrants(ctx context.Context,
|
|||||||
if existingProjectGrant == nil {
|
if existingProjectGrant == nil {
|
||||||
return fmt.Errorf("Error no project granted to user organization: %v", err)
|
return fmt.Errorf("Error no project granted to user organization: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err = wr.PatchStatus(ctx, condition.SetPatOutOfDate); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
_, err = ztdClient.AddUserGrant(ctx, &pb.AddUserGrantRequest{
|
_, err = ztdClient.AddUserGrant(ctx, &pb.AddUserGrantRequest{
|
||||||
UserId: wr.MachineUser.Status.UserId,
|
UserId: wr.MachineUser.Status.UserId,
|
||||||
RoleKeys: userGrant.RoleKeys,
|
RoleKeys: userGrant.RoleKeys,
|
||||||
@@ -357,6 +393,11 @@ func (wr *wrappedMachineUserReconciler) reconcileUserGrants(ctx context.Context,
|
|||||||
sort.Strings(existingUserGrant.RoleKeys)
|
sort.Strings(existingUserGrant.RoleKeys)
|
||||||
sort.Strings(userGrant.RoleKeys)
|
sort.Strings(userGrant.RoleKeys)
|
||||||
if !reflect.DeepEqual(existingUserGrant.RoleKeys, userGrant.RoleKeys) {
|
if !reflect.DeepEqual(existingUserGrant.RoleKeys, userGrant.RoleKeys) {
|
||||||
|
|
||||||
|
if err = wr.PatchStatus(ctx, condition.SetPatOutOfDate); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
_, err := ztdClient.UpdateUserGrant(ctx, &pb.UpdateUserGrantRequest{
|
_, err := ztdClient.UpdateUserGrant(ctx, &pb.UpdateUserGrantRequest{
|
||||||
UserId: wr.MachineUser.Status.UserId,
|
UserId: wr.MachineUser.Status.UserId,
|
||||||
GrantId: existingUserGrant.Id,
|
GrantId: existingUserGrant.Id,
|
||||||
|
|||||||
@@ -1,111 +0,0 @@
|
|||||||
package conditions
|
|
||||||
|
|
||||||
import (
|
|
||||||
zitadelv1alpha1 "bitbucket.org/topmanage-software-engineering/zitadel-k8s-operator/src/api/v1alpha1"
|
|
||||||
batchv1 "k8s.io/api/batch/v1"
|
|
||||||
corev1 "k8s.io/api/core/v1"
|
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
||||||
)
|
|
||||||
|
|
||||||
func SetCompleteWithCronJob(c Conditioner, cronJob *batchv1.CronJob) {
|
|
||||||
setScheduled := func() {
|
|
||||||
c.SetCondition(metav1.Condition{
|
|
||||||
Type: zitadelv1alpha1.ConditionTypeComplete,
|
|
||||||
Status: metav1.ConditionFalse,
|
|
||||||
Reason: zitadelv1alpha1.ConditionReasonCronJobScheduled,
|
|
||||||
Message: "Scheduled",
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
if cronJob.Status.LastScheduleTime == nil || cronJob.Status.LastSuccessfulTime == nil {
|
|
||||||
setScheduled()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if cronJob.Status.LastSuccessfulTime.Before(cronJob.Status.LastScheduleTime) {
|
|
||||||
if len(cronJob.Status.Active) > 0 {
|
|
||||||
c.SetCondition(metav1.Condition{
|
|
||||||
Type: zitadelv1alpha1.ConditionTypeComplete,
|
|
||||||
Status: metav1.ConditionFalse,
|
|
||||||
Reason: zitadelv1alpha1.ConditionReasonCronJobRunning,
|
|
||||||
Message: "Running",
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
c.SetCondition(metav1.Condition{
|
|
||||||
Type: zitadelv1alpha1.ConditionTypeComplete,
|
|
||||||
Status: metav1.ConditionFalse,
|
|
||||||
Reason: zitadelv1alpha1.ConditionReasonCronJobFailed,
|
|
||||||
Message: "Failed",
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if cronJob.Status.LastScheduleTime.Equal(cronJob.Status.LastSuccessfulTime) ||
|
|
||||||
cronJob.Status.LastScheduleTime.Before(cronJob.Status.LastSuccessfulTime) {
|
|
||||||
c.SetCondition(metav1.Condition{
|
|
||||||
Type: zitadelv1alpha1.ConditionTypeComplete,
|
|
||||||
Status: metav1.ConditionTrue,
|
|
||||||
Reason: zitadelv1alpha1.ConditionReasonCronJobSuccess,
|
|
||||||
Message: "Success",
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
setScheduled()
|
|
||||||
}
|
|
||||||
|
|
||||||
func SetCompleteWithJob(c Conditioner, job *batchv1.Job) {
|
|
||||||
switch getJobConditionType(job) {
|
|
||||||
case batchv1.JobFailed:
|
|
||||||
c.SetCondition(metav1.Condition{
|
|
||||||
Type: zitadelv1alpha1.ConditionTypeComplete,
|
|
||||||
Status: metav1.ConditionTrue,
|
|
||||||
Reason: zitadelv1alpha1.ConditionReasonJobFailed,
|
|
||||||
Message: "Failed",
|
|
||||||
})
|
|
||||||
case batchv1.JobComplete:
|
|
||||||
c.SetCondition(metav1.Condition{
|
|
||||||
Type: zitadelv1alpha1.ConditionTypeComplete,
|
|
||||||
Status: metav1.ConditionTrue,
|
|
||||||
Reason: zitadelv1alpha1.ConditionReasonJobComplete,
|
|
||||||
Message: "Success",
|
|
||||||
})
|
|
||||||
case batchv1.JobSuspended:
|
|
||||||
c.SetCondition(metav1.Condition{
|
|
||||||
Type: zitadelv1alpha1.ConditionTypeComplete,
|
|
||||||
Status: metav1.ConditionFalse,
|
|
||||||
Reason: zitadelv1alpha1.ConditionReasonJobSuspended,
|
|
||||||
Message: "Suspended",
|
|
||||||
})
|
|
||||||
default:
|
|
||||||
c.SetCondition(metav1.Condition{
|
|
||||||
Type: zitadelv1alpha1.ConditionTypeComplete,
|
|
||||||
Status: metav1.ConditionFalse,
|
|
||||||
Reason: zitadelv1alpha1.ConditionReasonJobRunning,
|
|
||||||
Message: "Running",
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func SetCompleteFailedWithMessage(c Conditioner, message string) {
|
|
||||||
c.SetCondition(metav1.Condition{
|
|
||||||
Type: zitadelv1alpha1.ConditionTypeComplete,
|
|
||||||
Status: metav1.ConditionFalse,
|
|
||||||
Reason: zitadelv1alpha1.ConditionReasonFailed,
|
|
||||||
Message: message,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func SetCompleteFailed(c Conditioner) {
|
|
||||||
SetCompleteFailedWithMessage(c, "Failed")
|
|
||||||
}
|
|
||||||
|
|
||||||
func getJobConditionType(job *batchv1.Job) batchv1.JobConditionType {
|
|
||||||
for _, c := range job.Status.Conditions {
|
|
||||||
if c.Status == corev1.ConditionFalse {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
return c.Type
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
25
src/pkg/condition/pat.go
Normal file
25
src/pkg/condition/pat.go
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
package conditions
|
||||||
|
|
||||||
|
import (
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
|
||||||
|
zitadelv1alpha1 "bitbucket.org/topmanage-software-engineering/zitadel-k8s-operator/src/api/v1alpha1"
|
||||||
|
)
|
||||||
|
|
||||||
|
func SetPatOutOfDate(c Conditioner) {
|
||||||
|
c.SetCondition(metav1.Condition{
|
||||||
|
Type: zitadelv1alpha1.ConditionTypePATUpToDate,
|
||||||
|
Status: metav1.ConditionFalse,
|
||||||
|
Reason: zitadelv1alpha1.ConditionReasonRolesChanged,
|
||||||
|
Message: "PAT out of date",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetPatUpToDate(c Conditioner) {
|
||||||
|
c.SetCondition(metav1.Condition{
|
||||||
|
Type: zitadelv1alpha1.ConditionTypePATUpToDate,
|
||||||
|
Status: metav1.ConditionTrue,
|
||||||
|
Reason: zitadelv1alpha1.ConditionReasonPATUpToDate,
|
||||||
|
Message: "PAT up to date",
|
||||||
|
})
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user