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

✨ Add classNamespace to topology #11352

Open
wants to merge 5 commits into
base: main
Choose a base branch
from

Conversation

Danil-Grigorev
Copy link
Member

@Danil-Grigorev Danil-Grigorev commented Oct 30, 2024

What this PR does / why we need it:

Adding classNamespace variable to the cluster topology, which allows to point to a ClusterClass in a different namespace. This field is dormant, and is used for differentiation only.

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

/area clusterclass

@k8s-ci-robot k8s-ci-robot added area/clusterclass Issues or PRs related to clusterclass cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. size/S Denotes a PR that changes 10-29 lines, ignoring generated files. labels Oct 30, 2024
@Danil-Grigorev Danil-Grigorev changed the title Add classNamespace to topology ✨ Add classNamespace to topology Oct 30, 2024
@Danil-Grigorev Danil-Grigorev force-pushed the class-namespace-addition branch 2 times, most recently from ae1cb19 to 43cb995 Compare October 30, 2024 11:59
@k8s-ci-robot k8s-ci-robot added size/M Denotes a PR that changes 30-99 lines, ignoring generated files. and removed size/S Denotes a PR that changes 10-29 lines, ignoring generated files. labels Oct 30, 2024
@Danil-Grigorev Danil-Grigorev force-pushed the class-namespace-addition branch 2 times, most recently from 2bddeeb to 352fd66 Compare October 30, 2024 15:20
Copy link
Contributor

@salasberryfin salasberryfin left a comment

Choose a reason for hiding this comment

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

Thanks @Danil-Grigorev! I added a small suggestion but I think this looks good.

@salasberryfin
Copy link
Contributor

Thanks @Danil-Grigorev

/lgtm

@k8s-ci-robot k8s-ci-robot added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Oct 31, 2024
@k8s-ci-robot
Copy link
Contributor

LGTM label has been added.

Git tree hash: c4b418743a4683ae623b3264aae7636c41ad5675

@salasberryfin
Copy link
Contributor

/assign @chrischdi

@Danil-Grigorev Danil-Grigorev changed the title ✨ Add classNamespace to topology [WIP] ✨ Add classNamespace to topology Oct 31, 2024
@k8s-ci-robot k8s-ci-robot added the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Oct 31, 2024
@k8s-ci-robot k8s-ci-robot removed the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Oct 31, 2024
@k8s-ci-robot
Copy link
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please ask for approval from chrischdi. For more information see the Kubernetes Code Review Process.

The full list of commands accepted by this bot can be found 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

@k8s-ci-robot k8s-ci-robot added size/L Denotes a PR that changes 100-499 lines, ignoring generated files. and removed size/M Denotes a PR that changes 30-99 lines, ignoring generated files. labels Oct 31, 2024
@Danil-Grigorev Danil-Grigorev changed the title [WIP] ✨ Add classNamespace to topology ✨ Add classNamespace to topology Oct 31, 2024
@k8s-ci-robot k8s-ci-robot removed the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Oct 31, 2024

#### Securing cross-namespace reference to the ClusterClass

It is often desirable to restrict free cross-namespace `ClusterClass` access for the `Cluster` object. This can be implemented by defining a [`ValidatingAdmissionPolicy`](https://kubernetes.io/docs/reference/access-authn-authz/validating-admission-policy/) on the `Cluster` object.
Copy link
Member

@enxebre enxebre Nov 5, 2024

Choose a reason for hiding this comment

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

besides the on admission check which is nice, do we have any rbac recommendation for this?

Copy link
Member Author

Choose a reason for hiding this comment

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

VAP supports secondary authz for added RBAC control, and VAP binding can be used with label selectors, which addresses #5673 (comment). From the proposal itself, it seems using the policy for added restriction on top of RBAC is within the scope.

Webhook allows to use paramRef of any kind, which can be potentially explored with specific CRD to further restrict access beyond admission, with a controller acting on that resource.

Currently, this is just an example of how an on top policy can be defined (if needed) in k8s 1.30+, where a user may decide to use different policy mechanisms to further restrict access, including a more granular RBAC. I’m thinking to showcase it as an option, but to not enforce any specific solution within this PR.

Copy link
Member Author

Choose a reason for hiding this comment

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

There is also an RBAC recommendation in https://kccncna2024.sched.com/event/1hoyX, if a talk considered to be one.

Copy link
Member

@neolit123 neolit123 left a comment

Choose a reason for hiding this comment

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

@Danil-Grigorev did you attempt rebasing a non-namespaced CC to a namespaced CC?
does that work fine?

@Danil-Grigorev
Copy link
Member Author

@neolit123 I tried rebase on the clusterClass in the same namespace, and it works fine. Cross-namespace rebases are not possible, as there is validation to prevent namespace change for templates. This seems like a larger change.

@neolit123
Copy link
Member

@neolit123 I tried rebase on the clusterClass in the same namespace, and it works fine. Cross-namespace rebases are not possible, as there is validation to prevent namespace change for templates. This seems like a larger change.

if this larger change is not added then it's worth mentioning the limitation in the docs.

@Danil-Grigorev
Copy link
Member Author

Maybe to address some comments from the last meeting - extension configs on the initial check seem to work as well, as long as the namespace selector matches.

Copy link
Member

@furkatgofurov7 furkatgofurov7 left a comment

Choose a reason for hiding this comment

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

/lgtm

@k8s-ci-robot k8s-ci-robot added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Nov 11, 2024
@k8s-ci-robot
Copy link
Contributor

LGTM label has been added.

Git tree hash: f7b15d982fdfb8730cff97c2900ccbd9c661e3d9

@@ -332,6 +332,11 @@ type Topology struct {
// The name of the ClusterClass object to create the topology.
Class string `json:"class"`

// The namespace of the ClusterClass object to create the topology.
//
Copy link
Member

Choose a reason for hiding this comment

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

nit

Suggested change
//


<h1>Cluster rebase across namespaces</h1>

Class namespace referenced in the `Cluster` object is equivalent to a cluster being located in the referenced namespace from the validation perspective. Changing `classNamespace` is not allowed, while using a different `CluterClass` from the same namespace is permitted in the Cluster rebase procedure.
Copy link
Member

@fabriziopandini fabriziopandini Nov 25, 2024

Choose a reason for hiding this comment

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

nit

Suggested change
Class namespace referenced in the `Cluster` object is equivalent to a cluster being located in the referenced namespace from the validation perspective. Changing `classNamespace` is not allowed, while using a different `CluterClass` from the same namespace is permitted in the Cluster rebase procedure.
Class namespace referenced in the `Cluster` object is equivalent to a cluster being located in the referenced namespace from the validation perspective. Changing `classNamespace` is not allowed, while using a different `ClusterClass` from the same namespace is permitted in the Cluster rebase procedure.

Also, thinking about:

Class namespace referenced in the Cluster object is equivalent to a cluster being located in the referenced namespace from the validation perspective

I'm not sure if we are surfacing an implementation detail or if we are trying to surface something the users should care about. Could you kindly provide some more context?

policyName: "cluster-class-ref.cluster.x-k8s.io"
validationActions: [Deny]
paramRef:
name: "ref-list"
Copy link
Member

@fabriziopandini fabriziopandini Nov 25, 2024

Choose a reason for hiding this comment

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

might be

Suggested change
name: "ref-list"
name: "allowed-namespaces.cluster-class-ref.cluster.x-k8s.io"

(if we want to keep the "domain like" name, otherwise something with "allowed namespaces")

// The namespace of the ClusterClass object to create the topology.
//
// +optional
ClassNamespace string `json:"classNamespace,omitempty"`
Copy link
Member

@fabriziopandini fabriziopandini Nov 25, 2024

Choose a reason for hiding this comment

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

Out of curiosity.
Are we planning to refactor Class/ClassName down the line or keep as it is (top of mind, having name/namespace for an referenced object inlined in the parent struct/not using a nested ref struct is sort of unique in Cluster API).

cc @vincepri @enxebre @JoelSpeed who might have opinions on API modeling as well

Copy link
Contributor

Choose a reason for hiding this comment

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

In a future version of this API, I'd expect us to move to

class:
  name: ...
  namespace: ...

As part of a clean up, this would then be in-keeping, as you say, with other APIs we have

}

// GetInfrastructureNamespace returns common namespace for the cluster infrastructure.
func (c *Cluster) GetInfrastructureNamespace() string {
Copy link
Member

@fabriziopandini fabriziopandini Nov 25, 2024

Choose a reason for hiding this comment

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

Considering that this func looks at c.Spec.Topology and not at c.Spec.InfrastructureRef, I'm a little bit confused by "Infrastructure" in the name.

Also, if possible, I would prefer to try to keep API package as clean as possible and not use it as a way to share util between packages (I know we did this in the past in a few cases, let's try to not add more).
E.g. we can think about something under internal/topology, or also duplicate this if could work for me

@@ -371,7 +370,9 @@ func (r *Reconciler) clusterClassToCluster(ctx context.Context, o client.Object)
// create a request for each of the clusters.
requests := []ctrl.Request{}
for i := range clusterList.Items {
requests = append(requests, ctrl.Request{NamespacedName: util.ObjectKey(&clusterList.Items[i])})
if clusterList.Items[i].GetInfrastructureNamespace() == clusterClass.Namespace {
Copy link
Member

@fabriziopandini fabriziopandini Nov 25, 2024

Choose a reason for hiding this comment

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

Can we add a unit test ensuring that a change in a CC with a given name triggers reconcile only for clusters using it (and not for clusters using CC with the same name, but in another ns)
Possibly, this should cover both cluster with ClassNamespace set and not.

@@ -380,12 +380,19 @@ func (webhook *ClusterClass) getClustersUsingClusterClass(ctx context.Context, c
clusters := &clusterv1.ClusterList{}
err := webhook.Client.List(ctx, clusters,
client.MatchingFields{index.ClusterClassNameField: clusterClass.Name},
client.InNamespace(clusterClass.Namespace),
Copy link
Member

Choose a reason for hiding this comment

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

Wondering if we should update the index, so it contains both namespace and name of the cluster class


referencedClusters := []clusterv1.Cluster{}
for _, cluster := range clusters.Items {
if cluster.GetInfrastructureNamespace() == clusterClass.Namespace {
Copy link
Member

Choose a reason for hiding this comment

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

Also, in this case, possibly add unit test coverage (similar to clusterClassToCluster above)

@@ -332,6 +332,11 @@ type Topology struct {
// The name of the ClusterClass object to create the topology.
Class string `json:"class"`

// The namespace of the ClusterClass object to create the topology.
//
// +optional
Copy link
Member

Choose a reason for hiding this comment

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

Q: do we care about differentiating between not set and set to empty string?
(I think not, just double checking)

@@ -332,6 +332,11 @@ type Topology struct {
// The name of the ClusterClass object to create the topology.
Class string `json:"class"`

// The namespace of the ClusterClass object to create the topology.
Copy link
Contributor

Choose a reason for hiding this comment

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

What is the behaviour when this is not specified? Can you add that to the description here?

// The namespace of the ClusterClass object to create the topology.
//
// +optional
ClassNamespace string `json:"classNamespace,omitempty"`
Copy link
Contributor

Choose a reason for hiding this comment

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

Please add a minimum and maximum length to all raw string types, since this is a namespace, it follows DNS1123Subdomain and should also be validated as such (there's a regex for this). The maximum length is 253 and the minimum is 1.

Since you have omitempty, you can safely add the MinLength, it will prevent anyone using an unstructured client from persisting classNamespace: "" which would then otherwise not round trip through a structured request

@k8s-ci-robot k8s-ci-robot removed the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Nov 27, 2024
@k8s-ci-robot
Copy link
Contributor

New changes are detected. LGTM label has been removed.

@k8s-ci-robot
Copy link
Contributor

@Danil-Grigorev: The following test failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
pull-cluster-api-verify-main b4b6131 link true /test pull-cluster-api-verify-main

Full PR test history. Your PR dashboard. Please help us cut down on flakes by linking to an open issue when you hit one in your PR.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/clusterclass Issues or PRs related to clusterclass cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. 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.

9 participants