-
Notifications
You must be signed in to change notification settings - Fork 2.3k
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
Make principals dynamic in Profiles Controller #7310
Make principals dynamic in Profiles Controller #7310
Conversation
dd33303
to
332626c
Compare
@kimwnasptd we also need to add a new principal This is required for the |
You also need to do the KFAM ones (with all the same changes): kubeflow/components/access-management/kfam/bindings.go Lines 79 to 101 in c6c4492
As these were changed in #7032 also. |
Also, let's include the default env-var configs of the environment variables in the manifests (to help distros see this change): We can add them to this ConfigMap, as it sets the environment for
|
@thesuperzapper could you add some more context for this? |
@thesuperzapper why (I'm having the KFP change in mind)? Isn't the The other rules (like allowing requests from the the Notebook controller) should already exist from the AuthorizationPolicy created by the Profile Controller. ACK on making the principal configurable in KFAM for the Istio ingressgateway though. Having in mind above the rest of the changes, in case you meant we would need to bring more changes in KFAM |
Signed-off-by: Kimonas Sotirchos <kimwnasptd@gmail.com>
Signed-off-by: Kimonas Sotirchos <kimwnasptd@gmail.com>
Signed-off-by: Kimonas Sotirchos <kimwnasptd@gmail.com>
332626c
to
9790f97
Compare
@kimwnasptd I was referring to the KFP principal I raised in #7310 (comment), which needs to be created for BOTH non-owners (created by KFAM) and the owners (created by profile controller). This is required for KFP to work correctly (specifically for the "view output artifacts" feature of the pipeline's UI). This is because, internally, the This is what allows each namespace to have different levels of access to the S3 bucket (and probably a few other things I am missing too). |
Thanks for the explanation! I'll modify the code and try to play around with this to make sure I'm fully in sync. In the mean time though, @zijianjoy could you give us your feedback as well? The context is:
Is there something else we need to consider here? Also if you'd have any pointers for this architecture they would be more than welcome 😄 |
So indeed, after playing around with the latest 1.8 RC I'm getting 403 errors in the
After applying the following AuthorizationPolicy, in the user namespace, it worked apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
name: kfp
spec:
rules:
- from:
- source:
principals:
- cluster.local/ns/kubeflow/sa/ml-pipeline-ui But this actually raises a question. Should the profile controller be responsible for this or the existing kfp-profiles-controller (Metacontroller) that already creates the AuthorizationPolicy for the visualization server? cc @zijianjoy |
@kimwnasptd my thoughts are that I don't any straightforward way to use the And for the profile owner bindings, we already the profile-controller creating the Notebooks UI AuthorizaitonPolicy (for the last activity field), so I don't see a harm with adding a pipeline-specific one either. Finally, I want to reduce the size of the Also, the policy needs to require the So we can just put it under the existing rule we are generating to give the user access from the gateway. For example: apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
name: user-user1-example-com-clusterrole-edit
namespace: PROFILE_NAME
annotations:
role: edit
user: "user1@example.com"
spec:
rules:
- from:
- source:
principals:
- cluster.local/ns/deploykf-istio-gateway/sa/deploykf-gateway
- cluster.local/ns/kubeflow/sa/ml-pipeline-ui
when:
- key: request.headers[kubeflow-userid]
values:
- user1@example.com Where:
|
@thesuperzapper this is not on you but on the owners of the component to decide 😄 Are you sure the above AuthorizationPolicy you posted is working for you? I applied it but unless I remove the apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
name: user-user1-example-com-clusterrole-edit
namespace: PROFILE_NAME
annotations:
role: edit
user: "user1@example.com"
spec:
rules:
- from:
- source:
principals:
- cluster.local/ns/deploykf-istio-gateway/sa/deploykf-gateway
- cluster.local/ns/kubeflow/sa/ml-pipeline-ui
when:
- key: request.headers[kubeflow-userid]
values:
- user1@example.com If that's the case this is actually yet one more argument that this should be in the |
Signed-off-by: Kimonas Sotirchos <kimwnasptd@gmail.com>
Signed-off-by: Kimonas Sotirchos <kimwnasptd@gmail.com>
@kimwnasptd lol, I made a typo on the ingress gateway principal, it should be apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
name: user-user1-example-com-clusterrole-edit
namespace: PROFILE_NAME
annotations:
role: edit
user: "user1@example.com"
spec:
rules:
- from:
- source:
principals:
- cluster.local/ns/istio-system/sa/istio-ingressgateway-service-account
- cluster.local/ns/kubeflow/sa/ml-pipeline-ui
when:
- key: request.headers[kubeflow-userid]
values:
- user1@example.com |
@kimwnasptd Also, regarding getting rid of the pipelines profile controlle We had lots of discussions about it in the past, because that python script is very messy and brittle. Personally, I think we can just extend the main profile controller with a new cluster resource that defines resources which should be created in each namespace. There could two modes for this cluster resource:
I think the key features would be:
We might also need to start defining the members in the profile itself, rather than based on magically named RoleBindings (so we actually know who's meant to be a member, and what level of access they should have). |
@thesuperzapper the issue is not in the Istio IGW principal but on the rule for KFP. As I mentioned, in my vanilla installation: ❌ FAILS: Still getting RBAC from Istio
✅ SUCCEEDS
The PR currently has the above change that allows all requests from the The PR currently has the changes that I tested in my cluster and get KFP UI to talk to the per-profile Pods |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@kimwnasptd its important for security that the kfp-ui is not able to proxy arbitrary requests (without userid-header), so let's just extend the from principals as I have proposed here.
NOTE: we don't even need to add a new rule this way, just extend the "from" principal list of the exiting one which has the "when" condition for the userid header.
{ | ||
From: []*istioSecurity.Rule_From{ | ||
{ | ||
// KFP UI needs to talk to ml-pipeline-ui-artifact pods | ||
// in each profile namespace | ||
Source: &istioSecurity.Source{ | ||
Principals: []string{kfpUIPrincipal}, | ||
}, | ||
}, | ||
}, | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This rule should also include the "when" condition, to prevent the pipeline UI from being able to proxy traffic without a userid-header.
Option 1
The best option is to simply add another "from" principal in the first rule, and remove this rule.
{
When: []*istioSecurity.Condition{
{
Key: fmt.Sprintf("request.headers[%v]", r.UserIdHeader),
Values: []string{
r.UserIdPrefix + profileIns.Spec.Owner.Name,
},
},
},
From: []*istioSecurity.Rule_From{{
Source: &istioSecurity.Source{
Principals: []string{
// end-users access via the ingress gateway
istioIGWPrincipal,
// kfp proxies user requests to artifact pods in profile namespaces
kfpUIPrincipal,
},
},
}},
},
Option 2
We could keep it as a separate rule, and add the "when" condition, but this is is less efficient for Envoy, and needless because it has the same effect.
{
// kfp proxies user requests to artifact pods in profile namespaces
When: []*istioSecurity.Condition{
{
Key: fmt.Sprintf("request.headers[%v]", r.UserIdHeader),
Values: []string{
r.UserIdPrefix + profileIns.Spec.Owner.Name,
},
},
},
From: []*istioSecurity.Rule_From{
{
Source: &istioSecurity.Source{
Principals: []string{kfpUIPrincipal},
},
},
},
},
Principals: []string{ | ||
"cluster.local/ns/istio-system/sa/istio-ingressgateway-service-account", | ||
}, | ||
Principals: []string{istioIGWPrincipal}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You also need to add the kfpUIPrincipal
here to allow the KFP UI to proxy requests for non-owners.
So if we define kfpUIPrincipal
like in the profile controller, you can simply extend this list:
From: []*istioSecurity.Rule_From{{
Source: &istioSecurity.Source{
Principals: []string{
// end-users access via the ingress gateway
istioIGWPrincipal,
// kfp proxies user requests to artifact pods in profile namespaces
kfpUIPrincipal,
},
},
}},
@kimwnasptd the problem you were likley having was that KFAM does NOT reconcile its This is actually something we need to address before 1.8! We either need to tell users to remove and re-add ALL members of profiles for this fix to take effect (even the initial one which prevents impersonation by restricting the source to the ingress gateway), or add a reconciliation loop to the profile controller (or possibly KFAM) for the The only "source of truth" around who should be a member of a profile, is the presence of To identify the kubeflow/components/access-management/kfam/bindings.go Lines 40 to 42 in 09917e6
KFAM already does something similar with its "read bindings" API call, which is used by the dashboard (but not for reconciliation): kubeflow/components/access-management/kfam/api_default.go Lines 210 to 256 in 09917e6
|
@thesuperzapper can you confirm that you have applied the following AuthorizationPolicy, in your user's profile namespace, and you don't get apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
name: user-user1-example-com-clusterrole-edit
spec:
rules:
- from:
- source:
principals:
- cluster.local/ns/kubeflow/sa/ml-pipeline-ui
when:
- key: request.headers[kubeflow-userid]
values:
- user1@example.com Because for me even when I manually apply such a policy in the user namespace I'm still getting RBAC errors of Istio. If you don't get errors then I'd suggest you to sent a PR for this, since I don't want to send a PR for something that I can't get make it work. And I focus this PR just on the initial scope of configuring the existing principals for the IGW and Notebook Controller, which was broken in #7032. KFP is completely orthogonal |
@kimwnasptd I can confirm with the manifests from Note I am using two dex static-password users:
AuthorizationPolicy for OwnerNOTE 1: to manually apply this, you need to scale the NOTE 2: You scale to 0 AFTER you are already on the correct pipelines page, because the profile controller being down breaks the ability to navigate on the central dashboard. apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
annotations:
role: admin
user: user@example.com
name: ns-owner-access-istio
namespace: kubeflow-user-example-com
spec:
rules:
- from:
- source:
principals:
- cluster.local/ns/istio-system/sa/istio-ingressgateway-service-account
## \/ added this part \/ ##
- cluster.local/ns/kubeflow/sa/ml-pipeline-ui
when:
- key: request.headers[kubeflow-userid]
values:
- user@example.com
- when:
- key: source.namespace
values:
- kubeflow-user-example-com
- to:
- operation:
paths:
- /healthz
- /metrics
- /wait-for-drain
- from:
- source:
principals:
- cluster.local/ns/kubeflow/sa/notebook-controller-service-account
to:
- operation:
methods:
- GET
paths:
- '*/api/kernels' AuthorizationPolicy for MemberapiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
annotations:
role: edit
user: user1@example.com
name: user-user1-example-com-clusterrole-edit
namespace: kubeflow-user-example-com
spec:
rules:
- from:
- source:
principals:
- cluster.local/ns/istio-system/sa/istio-ingressgateway-service-account
## \/ added this part \/ ##
- cluster.local/ns/kubeflow/sa/ml-pipeline-ui
when:
- key: request.headers[kubeflow-userid]
values:
- user1@example.com |
omg, I found the problem with my testing. The file I was locally applying had Sending the patch |
Signed-off-by: Kimonas Sotirchos <kimwnasptd@gmail.com>
@thesuperzapper I sent the fix. I confirm it works with the Profile controller as well. Apologies for this back and forth, caused by me using different yaml locally from the one above. Once the tests pass we should be good to merge |
@kimwnasptd We MUST make another PR before releasing 1.8, because right now the security fix that was intended by #7032, will not be applied to existing profile members, only new ones. This is because as I was saying in #7310 (comment), while the profile controller will reconcile changes, KFAM will NOT, so all of our updates will only apply to NEW members of profiles. This means we need to add a reconciliation loop to the resources created by KFAM. Proposal for Reconciliation of BindingsAfter thinking about it, the easiest way to do this is to move the reconciliation to the profile controller. This is actually easier than it sounds:
This way the presence of a apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
annotations:
role: edit
user: user1@example.com
name: user-user1-example-com-clusterrole-edit
namespace: kubeflow-user-example-com
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: kubeflow-edit
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: User
name: user1@example.com As you can see, all the info the profile-controller needs is found in the Finally, we should allow seamless "adoption" of old |
/hold @thesuperzapper tbh I don't feel comfortable with either of those. They both seem like too big of changes to introduce in the last minute, when the release is already hugely delayed. My proposal is what I had initially described:
For the KFP functionality it feels like we are trying to patch a security whole the KFP folks didn't think e2e. And all of this in the last minute with adding huge changes while delaying the release. I don't have the cycles to either create the follow up PR, not to properly review it. So I suggest we keep the work of fixing KFP issues as a next effort either in a KF patch release or in 1.8 |
@kimwnasptd This PR is correct as it is, I think we should merge it. The issue I am raising in #7310 (comment) is not really related to KFP or this PR. It's that even though we have updated KFAM to create secure AuthorizationPolicies (which ensure traffic is only coming from the gateway), any existing AuthorizationPolicies won't be updated. So we either need to tell users to remove and re-add every member of each profile (so KFAM makes the new AuthorizationPolicies), or do the small change I am proposing to move the management of I really don't think it's as complex as you are thinking, it's a small amount of code being removed from KFAM, and a small amount of code being added to the profile-controller. |
@kimwnasptd and I had a long discussion, and we think this is safe to merge for now, and rather than doing what I proposed in #7310 (comment), we will tell users who are upgrading, that to get the security benefits of #7032, they must EITHER:
/lgtm |
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: thesuperzapper 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 |
/hold cancel |
* Make principals dynamic in Profiles Controller Signed-off-by: Kimonas Sotirchos <kimwnasptd@gmail.com> * review: Use dynamic principal of IGW in KFAM Signed-off-by: Kimonas Sotirchos <kimwnasptd@gmail.com> * review: Add env vars to manifests Signed-off-by: Kimonas Sotirchos <kimwnasptd@gmail.com> * review: Add pipelines-ui principal Signed-off-by: Kimonas Sotirchos <kimwnasptd@gmail.com> * Update golang to 1.19 for unit tests to succeed Signed-off-by: Kimonas Sotirchos <kimwnasptd@gmail.com> * review: Include KFP UI principle in profiles/kfam Signed-off-by: Kimonas Sotirchos <kimwnasptd@gmail.com> --------- Signed-off-by: Kimonas Sotirchos <kimwnasptd@gmail.com>
* Make principals dynamic in Profiles Controller * review: Use dynamic principal of IGW in KFAM * review: Add env vars to manifests * review: Add pipelines-ui principal * Update golang to 1.19 for unit tests to succeed * review: Include KFP UI principle in profiles/kfam --------- Signed-off-by: Kimonas Sotirchos <kimwnasptd@gmail.com> Co-authored-by: Kimonas Sotirchos <kimwnasptd@gmail.com>
This is a follow-up to address #7032 (comment)
This PR will make all principals in Profile Controller configurable, so they should be changed from any distribution that deploys the components in different namespaces.
/cc @thesuperzapper