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

Move pkg/clone/auth to API lib and introduce single dv.Authorize() #2636

Merged
merged 1 commit into from
May 9, 2023

Conversation

akalenyu
Copy link
Collaborator

@akalenyu akalenyu commented Mar 13, 2023

What this PR does / why we need it:
This way other projects don't have to vendor in CDI, the API lib will be enough.
While it's not a huge deal at this point, each existing dependency is an entry door for pulling in more stuff in the future by accident.
Also, these are annoying

github.com/openshift/api v0.0.0
github.com/openshift/client-go v0.0.0

Which issue(s) this PR fixes (optional, in fixes #<issue number>(, fixes #<issue_number>, ...) format, will close the issue(s) when PR gets merged):
Fixes #2552

Special notes for your reviewer:

Release note:

Move clone auth helpers to CDI API library

@kubevirt-bot kubevirt-bot added release-note Denotes a PR that will be considered when it comes time to generate release notes. dco-signoff: yes Indicates the PR's author has DCO signed all their commits. labels Mar 13, 2023
@akalenyu
Copy link
Collaborator Author

/cc @dhiller @mhenriks

@@ -33,8 +33,8 @@ import (
"k8s.io/klog/v2"

cdiv1 "kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1"
cdiv1cloneauth "kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1/clone"
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 kubevirt.io/containerized-data-importer-api/pkg/clone would be better. Let's keep pkg/apis for kubernetes apis

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

So we already have

cdiv1utils "kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1/utils"

Copy link
Member

Choose a reason for hiding this comment

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

That function takes a DataVolume as a parameter though so having multiple versions of the api makes sense. These funcs however do not take any api resources as parameters

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

makes sense, was about to do this, but then realized we have #2552 which will accept a DV

Copy link
Member

Choose a reason for hiding this comment

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

okay then maybe it makes to refactor to do something like:

ok, err := dv.Authorize()

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

so Authorize() will go in ${version}/utils, and we will be able to have different authorization logic for different version?
I am just making sure, I have no issue with moving to kubevirt.io/containerized-data-importer-api/pkg/clone

Copy link
Member

@mhenriks mhenriks Mar 14, 2023

Choose a reason for hiding this comment

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

I guess what I'm saying is do #2552 in this pr and have Authorize be a DataVolume member function. All code will exist under pkg/apis... no pkg/clone

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Posted a first draft just to make sure we are fine with the direction

  • Still missing authorization via SA
  • Feels like the logic is clunky, any pointers are greatly appreciated
  • Would aggregating the proxies into one interface make sense?

@akalenyu akalenyu changed the title Move pkg/clone/auth to API lib Move pkg/clone/auth to API lib and introduce single dv.Authorize() Mar 16, 2023
@akalenyu akalenyu marked this pull request as draft March 16, 2023 13:47
@kubevirt-bot kubevirt-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 16, 2023
@akalenyu
Copy link
Collaborator Author

/test all

@akalenyu
Copy link
Collaborator Author

/test all

Copy link
Member

@mhenriks mhenriks left a comment

Choose a reason for hiding this comment

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

Great start! I'm not that down on this


// Authorize indicates if the creating context is authorized to create the data volume
// For sources other than clone (import/upload/etc), this is a no-op
func (dv *DataVolume) Authorize(requestNamespace, requestName string, sarClient SubjectAccessReviewsProxy, nsClient NamespaceProxy, dsClient DataSourceProxy, userInfo authentication.UserInfo) (bool, string, cloneSourceHandler, error) {
Copy link
Member

Choose a reason for hiding this comment

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

Maybe use the client native interfaces instead of our own proxies, so SubjectAccessReviewsGetter, NamespacesGetter, DataSourcesGetter?

Is that an improvement?

Copy link
Member

Choose a reason for hiding this comment

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

Scratch that, can't have DataSourcesGetter in here (circular dep). But maybe the others? Or will that make the deps situation worse?

Copy link
Collaborator Author

@akalenyu akalenyu Mar 21, 2023

Choose a reason for hiding this comment

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

Introduced a single type AuthorizationHelperProxy interface, hope that is fine

I'm not that down on this

I am not sure if you meant you're not down with the approach (don't like) or don't hate it too much (like~)

@akalenyu
Copy link
Collaborator Author

/test all

@akalenyu
Copy link
Collaborator Author

/test all

@@ -3,9 +3,11 @@ module kubevirt.io/containerized-data-importer-api
go 1.19

require (
github.com/kubernetes-csi/external-snapshotter/client/v6 v6.0.1
Copy link
Member

Choose a reason for hiding this comment

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

Can we get rid of this somehow?

Copy link
Member

Choose a reason for hiding this comment

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

Let's keep this go.mod lean and mean. Copying string consts is fine

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

done

@kubevirt-bot kubevirt-bot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Apr 11, 2023
@kubevirt-bot kubevirt-bot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Apr 13, 2023
@akalenyu akalenyu marked this pull request as ready for review April 13, 2023 13:41
@kubevirt-bot kubevirt-bot removed the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Apr 13, 2023
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@mhenriks do you think it's fine to delete this? should we keep for backwards compatibility?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

gentle ping

type dsGetFunc func(string, string) (*DataSource, error)

// AuthorizationHelperProxy proxies calls to APIs used for DV authorization
type AuthorizationHelperProxy interface {
Copy link
Member

Choose a reason for hiding this comment

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

Can't believe I just thought of this and I'd be remiss to not bring it up, what if our api just takes a dynamic.Interface instead of the proxy?

PRO:
Less code for clients

CON:
more code in api (translating to/from unstructured)
adding client-go to go.mod

Don't care too much either way just want to get your opinion

Copy link
Collaborator Author

@akalenyu akalenyu Apr 18, 2023

Choose a reason for hiding this comment

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

Would have to look up some references but the immediate concern is:
Would we still be able to restrict access to the passed client similarly to how we do with proxy?
I mean, with the proxy, external entities know that CDI doesn't have access to the client itself other than
the implemented Get/Create methods

Copy link
Member

Choose a reason for hiding this comment

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

With the proxy, callers know exactly what calls we are making, and that may be nice, but ultimately there is RBAC in place to keep the SA from doing anything bad. And obviously the code is available to audit and make sure we're not reading secrets or whatever.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yes my concern is that we get passed a general SA that is probably not very limited,
unless you are suggesting to somehow reduce the SA

Copy link
Member

Choose a reason for hiding this comment

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

No I don't think it is practical to create a special client with reduced permissions just to pass to this api. I also don't think passing the dynamic client is a security concern.

Copy link
Collaborator Author

@akalenyu akalenyu Apr 20, 2023

Choose a reason for hiding this comment

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

I also don't think passing the dynamic client is a security concern.

I thought the reason we went with proxy structs in the first place was to avoid passing a full-blown client

Copy link
Member

Choose a reason for hiding this comment

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

I also don't think passing the dynamic client is a security concern.

I thought the reason we went with proxy structs in the first place was to avoid passing a full-blown client

The issue is with the typed client here: https://github.com/kubevirt/containerized-data-importer/blob/main/pkg/client/clientset/versioned/typed/core/v1beta1/datavolume.go#L40

That would cause a circular dependency

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Ahh right.

I thought the reason we went with proxy structs in the first place was to avoid passing a full-blown client

We used the sarProxy prior to this PR though (and thus prior to the circular dep potential), was this^ not the main concern?

Anyway my (not 100% trustworthy) gut is telling me that whipping out a dynamic client
when we have a defined set of actions on objects we know about is not right, so I lean towards current impl

Copy link
Member

Choose a reason for hiding this comment

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

All past decisions are not made with perfect information. If I could go back in time I would probably use the dynamic client. But if you like using this interface, I don't care enough to keep belaboring the discussion.

@kubevirt-bot kubevirt-bot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Apr 19, 2023
@kubevirt-bot kubevirt-bot added size/XL and removed needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. size/XXL labels Apr 19, 2023

// AuthorizeUser indicates if the creating user is authorized to create the data volume
// For sources other than clone (import/upload/etc), this is a no-op
func (dv *DataVolume) AuthorizeUser(requestNamespace, requestName string, proxy AuthorizationHelperProxy, userInfo authentication.UserInfo) (bool, string, CloneSourceHandler, error) {
Copy link
Member

Choose a reason for hiding this comment

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

Rather than returning four vales, how about a new struct that combines the first three?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yep makes sense, added
My biggest worry is still this though:
#2636 (comment)

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 it's fine to delete auth.go. I seriously doubt any project other than kubevirt is importing it

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

awesome

This way other projects don't have to vendor in CDI, the API lib will be enough.
While it's not a huge deal at this point, each existing dependency is an entry door
for pulling in more stuff in the future by accident.

Signed-off-by: Alex Kalenyuk <akalenyu@redhat.com>
@mhenriks
Copy link
Member

/approve

@kubevirt-bot
Copy link
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: mhenriks

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

@kubevirt-bot kubevirt-bot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Apr 28, 2023
"kubevirt.io/containerized-data-importer/tests/framework"
"kubevirt.io/containerized-data-importer/tests/utils"
)

type sarProxy struct {
client kubernetes.Interface
type authProxy struct {
Copy link
Collaborator

Choose a reason for hiding this comment

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

why not using authProxy from datavolume-mutate.go?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I think it's nice that webhook_test.go will showcase all building blocks toward authorizing a data volume
plus, it feels a little "off" to export that struct from datavolume-mutate since it's not really of use to anyone but the tests

@arnongilboa
Copy link
Collaborator

/lgtm

@kubevirt-bot kubevirt-bot added the lgtm Indicates that a PR is ready to be merged. label May 9, 2023
@kubevirt-bot kubevirt-bot merged commit 4b2d633 into kubevirt:main May 9, 2023
akalenyu added a commit to akalenyu/containerized-data-importer that referenced this pull request Sep 18, 2023
This is a partial backport of kubevirt#2636
This tends to flake often, especially in OpenShift testing.

Signed-off-by: Alex Kalenyuk <akalenyu@redhat.com>
kubevirt-bot pushed a commit that referenced this pull request Sep 18, 2023
This is a partial backport of #2636
This tends to flake often, especially in OpenShift testing.

Signed-off-by: Alex Kalenyuk <akalenyu@redhat.com>
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. dco-signoff: yes Indicates the PR's author has DCO signed all their commits. lgtm Indicates that a PR is ready to be merged. release-note Denotes a PR that will be considered when it comes time to generate release notes. size/XXL
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Unify auth in a single AuthorizeDataVolume
4 participants