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

Allow non admin users to manage BSL #6589

Conversation

ahmadhamzh
Copy link
Contributor

What this PR does / why we need it:
Allow non admin users to manage backup storage location.

Which issue(s) this PR fixes:
Fixes #6563

What type of PR is this?
/kind bug

NONE
NONE

@kubermatic-bot kubermatic-bot added kind/bug Categorizes issue or PR as related to a bug. docs/none Denotes a PR that doesn't need documentation (changes). release-note-none Denotes a PR that doesn't merit a release note. dco-signoff: yes Denotes that all commits in the pull request have the valid DCO signoff message. sig/api Denotes a PR or issue as being assigned to SIG API. do-not-merge/code-freeze Indicates that a PR should not merge because it has not been approved for code freeze yet. size/L Denotes a PR that changes 100-499 lines, ignoring generated files. labels Mar 7, 2024
@ahmadhamzh ahmadhamzh changed the title Allow non admin users to manage BSL WIP Allow non admin users to manage BSL Mar 7, 2024
@kubermatic-bot kubermatic-bot added the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Mar 7, 2024
Comment on lines 104 to 110

_, err := userInfoGetter(ctx, req.ProjectID)

if err != nil {
return nil, err
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this essentially only queries the user roles and so on, but since you are not using them to check for anything (like in CreateCSBL), I believe it can be removed

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same for the GetCSBL func

Comment on lines 208 to 210
if user.Roles.Has("viewers") {
return fmt.Errorf("user with a viewer role is not permitted to delete storage locations.")
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

my understanding from other code is that it is possible for a user to have both "viewer" as well as another role. As a result we also need to check if viewers is the only role the user has.

For example like this is done here

if userInfo.Roles.Has("viewers") && userInfo.Roles.Len() == 1 {

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same for Create and Patch as well

@ahmadhamzh ahmadhamzh force-pushed the 6563-remove-admin-checking-for-cluster-backup branch from 6d591f8 to b7ead75 Compare March 12, 2024 11:21
@ahmadhamzh ahmadhamzh added this to the KKP 2.25 milestone Mar 12, 2024
@ahmadhamzh
Copy link
Contributor Author

/retest

@ahmadhamzh ahmadhamzh force-pushed the 6563-remove-admin-checking-for-cluster-backup branch from dc913a9 to 0cc2373 Compare March 13, 2024 15:17
@ahmadhamzh
Copy link
Contributor Author

I changed the approach to using an Impersonated Client, so there is no need to check the role in the API.
@SimonTheLeg

@ahmadhamzh ahmadhamzh changed the title WIP Allow non admin users to manage BSL Allow non admin users to manage BSL Mar 13, 2024
@kubermatic-bot kubermatic-bot removed the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Mar 13, 2024
@ahmadhamzh
Copy link
Contributor Author

@SimonTheLeg sorry but this PR is blocked by kubermatic/kubermatic#13174

@ahmadhamzh ahmadhamzh changed the title Allow non admin users to manage BSL WIP Allow non admin users to manage BSL Mar 13, 2024
@kubermatic-bot kubermatic-bot added the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Mar 13, 2024
@ahmadhamzh ahmadhamzh force-pushed the 6563-remove-admin-checking-for-cluster-backup branch from 55fed9e to c340ace Compare March 14, 2024 12:03
@ahmadhamzh ahmadhamzh force-pushed the 6563-remove-admin-checking-for-cluster-backup branch from c340ace to 543798f Compare March 14, 2024 12:26
@ahmadhamzh ahmadhamzh changed the title WIP Allow non admin users to manage BSL Allow non admin users to manage BSL Mar 14, 2024
@kubermatic-bot kubermatic-bot removed the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Mar 14, 2024
Copy link
Member

@SimonTheLeg SimonTheLeg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall I think this should all work and is in spec what we are doing in other parts of the API. I have some questions regarding the usage of the privileged client in some places. ptal.
But overall I think we are on the right track.

Comment on lines 80 to 82
client := p.privilegedClient

if err := client.List(ctx, cbslList, listOpts); err != nil {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: just to keep this uniform with other code. Let's go back to the previous p.privilegedClient.List notation from before

Comment on lines 93 to 99
cbslList, err := p.List(ctx, userInfo, labelSet)
if err != nil {
return nil, fmt.Errorf("failed to list ClusterBackupStorageLocations: %w", err)
return nil, err
}
for _, cbsl := range cbslList.Items {
if cbsl.Name == name {
return &cbsl, nil
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know this is not part of this PR, but I would appreciate if we could create a ticket to investigate this. Judging from just the code I think it should be fine to create the impersonated client and run a client.Get.

See

masterImpersonatedClient, err := createImpersonationClientWrapperFromUserInfo(userInfo, p.createMasterImpersonatedClient)
if err != nil {
return nil, err
}
existingProject := &kubermaticv1.Project{}
if err := masterImpersonatedClient.Get(ctx, ctrlruntimeclient.ObjectKey{Name: projectInternalName}, existingProject); err != nil {
return nil, err
}
for an example

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason we didn't do a direct Get() here is not because of the client. The problem here is that the CBSL is a project-scoped resources. We assign it to the project using a label. We need the API to only list CBSL's that belong to the correct project. So, we use List() with a label selector and loop over the results. Unfortunately the Get() API doesn't support label selectors.

Comment on lines 261 to 263
if userInfo == nil {
return nil, errors.New("a user is missing but required")
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think since you are checking for userInfo to not be nil always before calling this func, this can be removed.

@@ -110,57 +141,78 @@ func (p *BackupStorageProvider) CreateUnsecured(ctx context.Context, cbslName, p
},
Key: "cloud-credentials",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would recommend to move this into a global const, since we are using this in multiple places in this provider

}
}

func (p *BackupStorageProvider) ListUnsecured(ctx context.Context, labelSet map[string]string) (*kubermaticv1.ClusterBackupStorageLocationList, error) {
func (p *BackupStorageProvider) List(ctx context.Context, userInfo *provider.UserInfo, labelSet map[string]string) (*kubermaticv1.ClusterBackupStorageLocationList, error) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In my opinion this should still be called ListUnsecured, because it uses the priviledged client to access the info

func (p *BackupStorageProvider) GetUnsecured(ctx context.Context, name string, labelSet map[string]string) (*kubermaticv1.ClusterBackupStorageLocation, error) {
// we use List() to filter CBSLs with labels easily, to keep scoped into the owner project.
cbslList, err := p.ListUnsecured(ctx, labelSet)
func (p *BackupStorageProvider) Get(ctx context.Context, userInfo *provider.UserInfo, name string, labelSet map[string]string) (*kubermaticv1.ClusterBackupStorageLocation, error) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In my opinion this should still be called GetUnsecured, because it calls the List which in turn uses the priviledged client.

Comment on lines 169 to 175
cbsl := &kubermaticv1.ClusterBackupStorageLocation{}
if err := p.privilegedClient.Get(ctx, types.NamespacedName{Name: name, Namespace: resources.KubermaticNamespace}, cbsl); err != nil {
if err := client.Get(ctx, types.NamespacedName{Name: name, Namespace: resources.KubermaticNamespace}, cbsl); err != nil {
if apierrors.IsNotFound(err) {
return nil
}
return err
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason why the priviledged client is needed for getting the ClusterBackupStorageLocation? Couldn't the impersonated client be used for this?

Copy link
Contributor

@moelsayed moelsayed Mar 14, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

refactored to use the same client for both operations based on the user role.

Comment on lines 198 to 201
existing := &kubermaticv1.ClusterBackupStorageLocation{}
if err := p.privilegedClient.Get(ctx, types.NamespacedName{Name: cbslName, Namespace: resources.KubermaticNamespace}, existing); err != nil {
if err := client.Get(ctx, types.NamespacedName{Name: cbslName, Namespace: resources.KubermaticNamespace}, existing); err != nil {
return nil, err
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here. Is the priviledged client required, or could we just use the impersonated client for getting it?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@SimonTheLeg
Copy link
Member

/approve
/lgtm

@kubermatic-bot kubermatic-bot added the lgtm Indicates that a PR is ready to be merged. label Mar 14, 2024
@kubermatic-bot
Copy link
Contributor

LGTM label has been added.

Git tree hash: 30e151f61a5867a76a0f97eaf83a81a7a6a78952

@kubermatic-bot
Copy link
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: SimonTheLeg

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@kubermatic-bot kubermatic-bot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Mar 14, 2024
@embik embik added the code-freeze-approved Indicates a PR has been approved by release managers during code freeze. label Mar 14, 2024
@kubermatic-bot kubermatic-bot removed the do-not-merge/code-freeze Indicates that a PR should not merge because it has not been approved for code freeze yet. label Mar 14, 2024
@kubermatic-bot kubermatic-bot merged commit f3bb210 into kubermatic:main Mar 14, 2024
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
approved Indicates a PR has been approved by an approver from all required OWNERS files. code-freeze-approved Indicates a PR has been approved by release managers during code freeze. dco-signoff: yes Denotes that all commits in the pull request have the valid DCO signoff message. docs/none Denotes a PR that doesn't need documentation (changes). kind/bug Categorizes issue or PR as related to a bug. lgtm Indicates that a PR is ready to be merged. release-note-none Denotes a PR that doesn't merit a release note. sig/api Denotes a PR or issue as being assigned to SIG API. size/L Denotes a PR that changes 100-499 lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

In freshly created project constantly see an error message that I "don't have admin right"
5 participants