Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Infinite loop if user has been created without ListBucket permission #54

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -205,10 +205,22 @@ spec:
# Content of the policy, as a multiline string
# This should be IAM compliant JSON - follow the guidelines of the actual
# S3 provider you're using, as sometimes only a subset is available.
# The first Statement (Allow ListBucket) should be applied to every user,
# as s3-operator uses this call to verify that credentials are valid when
# reconciling an existing user.
policyContent: >-
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::*"
]
},
{
"Effect": "Allow",
"Action": [
Expand Down
48 changes: 24 additions & 24 deletions controllers/user_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,30 +154,6 @@ func (r *S3UserReconciler) handleS3ExistingUser(ctx context.Context, userResourc
return r.handleS3NewUser(ctx, userResource)
}

// If a matching secret is found, then we check if it is still valid, as in : do the credentials it
// contains still allow authenticating the S3User on the backend ? If not, the user is deleted and recreated.
// credentialsValid, err := r.S3Client.CheckUserCredentialsValid(userResource.Name, userResource.Spec.AccessKey, string(userOwnedSecret.Data["secretKey"]))
credentialsValid, err := r.S3Client.CheckUserCredentialsValid(userResource.Name, string(userOwnedSecret.Data["accessKey"]), string(userOwnedSecret.Data["secretKey"]))
if err != nil {
logger.Error(err, "An error occurred when checking if user credentials were valid", "user", userResource.Name)
return r.setS3UserStatusConditionAndUpdate(ctx, userResource, "OperatorFailed", metav1.ConditionFalse, "S3UserCredentialsCheckFailed",
fmt.Sprintf("Checking the S3User %s's credentials on S3 server has failed", userResource.Name), err)
}

if !credentialsValid {
logger.Info("The secret containing the credentials will be deleted, and the user will be deleted from the S3 backend, then recreated (through another reconcile)")
r.deleteSecret(ctx, &userOwnedSecret)
err = r.S3Client.DeleteUser(userResource.Spec.AccessKey)
if err != nil {
logger.Error(err, "Could not delete user on S3 server", "user", userResource.Name)
return r.setS3UserStatusConditionAndUpdate(ctx, userResource, "OperatorFailed", metav1.ConditionFalse, "S3UserDeletionFailed",
fmt.Sprintf("Deletion of S3user %s on S3 server has failed", userResource.Name), err)
}

return r.handleS3NewUser(ctx, userResource)

}

// --- End Secret management section

logger.Info("Checking user policies")
Expand Down Expand Up @@ -224,6 +200,30 @@ func (r *S3UserReconciler) handleS3ExistingUser(ctx context.Context, userResourc
}
}

// If a matching secret is found, then we check if it is still valid, as in : do the credentials it
// contains still allow authenticating the S3User on the backend ? If not, the user is deleted and recreated.
// credentialsValid, err := r.S3Client.CheckUserCredentialsValid(userResource.Name, userResource.Spec.AccessKey, string(userOwnedSecret.Data["secretKey"]))
credentialsValid, err := r.S3Client.CheckUserCredentialsValid(userResource.Name, string(userOwnedSecret.Data["accessKey"]), string(userOwnedSecret.Data["secretKey"]))
if err != nil {
logger.Error(err, "An error occurred when checking if user credentials were valid", "user", userResource.Name)
return r.setS3UserStatusConditionAndUpdate(ctx, userResource, "OperatorFailed", metav1.ConditionFalse, "S3UserCredentialsCheckFailed",
fmt.Sprintf("Checking the S3User %s's credentials on S3 server has failed", userResource.Name), err)
}

if !credentialsValid {
logger.Info("The secret containing the credentials will be deleted, and the user will be deleted from the S3 backend, then recreated (through another reconcile)")
r.deleteSecret(ctx, &userOwnedSecret)
err = r.S3Client.DeleteUser(userResource.Spec.AccessKey)
if err != nil {
logger.Error(err, "Could not delete user on S3 server", "user", userResource.Name)
return r.setS3UserStatusConditionAndUpdate(ctx, userResource, "OperatorFailed", metav1.ConditionFalse, "S3UserDeletionFailed",
fmt.Sprintf("Deletion of S3user %s on S3 server has failed", userResource.Name), err)
}

return r.handleS3NewUser(ctx, userResource)

}

logger.Info("User was reconciled without error")

// Re-fetch the S3User to ensure we have the latest state after updating the secret
Expand Down