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

clusterpool: ensure clusterdeployments namespace has same rbac as cluster-pool-admin #1219

Merged

Conversation

abhinavdahiya
Copy link
Contributor

@abhinavdahiya abhinavdahiya commented Nov 25, 2020

xref: https://issues.redhat.com/browse/CO-1282

Any role bindings in the namespace of the clusterpool that refer the ClusterRole hive-cluster-pool-admin
will be used to provide the subjects the same permission in the namespaces created for various
clusterdeployments for the clusterpool.

The controller performs these additional actions for each reconcile,

  • lists all the rolebindings in clusterpool's namespace that refer the ClusterRole hive-cluster-pool-admin
    to collect all the subjects.
    This makes sure that no work needs to be done when there are such rolebindings. And since k8s ensures that a rolebinding
    cannot be created when the ref doesn't exist, this will ensure that only when the ClusterRole exists would the controller
    run the next steps.
  • lists all the namespaces attached to the clusterpool by using the constants.ClusterPoolNameLabel label selector.
  • creates/updates a rolebinding hive-cluster-pool-admin-binding in each namespace binding to the same ClusterRole.

The controller also adds new watchers,

  • changes to rolebindings in the clusterdeployment namespace
  • changes to any rolebindings with ref to ClusterRole hive-cluster-pool-admin triggers resync for all clusterpools
    in that namespace.

NOTE: the controller can only pass on the permissions that it has i.e. the current hive-cluster-pool-admin cluster role is a subset of the hive-controller's permission. If the controller permissions are less that what the hive-cluster-pool-admin cluster role, then when creating a rolebinding in the clusterdeployment namespace we see an error like

time="2020-11-30T21:21:11.129Z" level=error msg="could not create rolebinding" clusterPool=default/adahiya-pool-1 controller=clusterpool error="rolebindings.rbac.authorization.k8s.io \"hive-cluster-pool-admin-binding\" is forbidden: user \"system:serviceaccount:hive:hive-controllers\" (groups=[\"system:serviceaccounts\" \"system:serviceaccounts:hive\" \"system:authenticated\"]) is attempting to grant RBAC permissions not currently held:\n{APIGroups:[\"\"], Resources:[\"pods/log\"], Verbs:[\"get\" \"list\" \"watch\"]}\n{APIGroups:[\"apiextensions.k8s.io\"], Resources:[\"customresourcedefinitions\"], Verbs:[\"get\" \"list\" \"watch\"]}" reconcileID=gn7pt9sd rolebinding=adahiya-pool-1-kpkbg/hive-cluster-pool-admin-binding

@openshift-ci-robot openshift-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 Nov 25, 2020
Copy link
Contributor

@dgoodwin dgoodwin left a comment

Choose a reason for hiding this comment

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

Looks awesome.

In config/rbac/ you'll see we ship a few utility roles already, you just need to add them to the list of things to apply likely here: https://github.com/openshift/hive/blob/master/pkg/operator/hive/hive.go#L271. The hive_frontend_role.yaml is a good starting point, that's almost what we want here, just bound to a namespace and maybe with less write perms.

This would imply we fully control that role definition and users can't modify it. Does this seem good or should we let them override the role name in HiveConfig, which would then pass that as an env var to the controllers deployment?

if o.Meta.GetName() != resourceName {
return nil
}
clusterName := o.Meta.GetNamespace()
Copy link
Contributor

Choose a reason for hiding this comment

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

I hope this ClusterDeployment.Name == ClusterDeployment.Namespace assumption holds up over time, it's convenient here.

observed.Subjects = desired.Subjects
observed.RoleRef = desired.RoleRef

logger.Info("updating rolebinding")
Copy link
Contributor

Choose a reason for hiding this comment

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

Please also log the subjects and roleref.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

hmm, any reason why that would be useful here?

Copy link
Contributor

Choose a reason for hiding this comment

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

This would be to log an audit trail of what your code determined the desired subjects and role reference is. I'd actually be tempted to log the observed vs desired as well. This is to help debug in a world where external modifications and hotloops can happen.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done with d851c86

name: "no binding referring to cluster role",
existing: []runtime.Object{},
}, {
name: "no binding referring to cluster role",
Copy link
Contributor

Choose a reason for hiding this comment

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

name is duplicated with the test above.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

the name is same because technically it's testing the same thing but just a different permutation really..

go test -v ./pkg/controller/clusterpool/... -run "TestReconcileRBAC/no_binding_referring_to_cluster_role"
=== RUN   TestReconcileRBAC
=== RUN   TestReconcileRBAC/no_binding_referring_to_cluster_role
=== RUN   TestReconcileRBAC/no_binding_referring_to_cluster_role#01
--- PASS: TestReconcileRBAC (0.00s)
    --- PASS: TestReconcileRBAC/no_binding_referring_to_cluster_role (0.00s)
    --- PASS: TestReconcileRBAC/no_binding_referring_to_cluster_role#01 (0.00s)
PASS
ok      github.com/openshift/hive/pkg/controller/clusterpool    0.031s

and go test automatically adds number to the same test name.

should i add one explicitly here?

Copy link
Contributor

Choose a reason for hiding this comment

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

Peculiar, we don't do this anywhere today afaik and typically try to give the tests unique names, this could get a little funky for anyone looking to just go run -test for a specific test, but probably not a huge deal. I think my vote would still be to give them unique names that cover the intent though.

},
},
}, {
name: "binding referring to cluster role but no namespace for pool",
Copy link
Contributor

Choose a reason for hiding this comment

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

Several more dupe test names here.

},
},
}, {
name: "multiple binding referring to cluster role with one namespace for pool",
Copy link
Contributor

Choose a reason for hiding this comment

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

👍

},
},
}, {
name: "pre existing role bindings that are different",
Copy link
Contributor

Choose a reason for hiding this comment

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

Dupe test name.

@abhinavdahiya abhinavdahiya changed the title WIP clusterpool: ensure clusterdeployments namespace has same rbac as cluster-pool-admin clusterpool: ensure clusterdeployments namespace has same rbac as cluster-pool-admin Nov 30, 2020
@openshift-ci-robot openshift-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 Nov 30, 2020
@abhinavdahiya
Copy link
Contributor Author

did some manual testing..

add a rolebinding in the namespace of the clusterpool, see the rolebinding created in the namespace of the cd..

$ oc get rolebindings hive-cluster-pool-admin -oyaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  creationTimestamp: "2020-11-30T21:20:28Z"
  managedFields:
  - apiVersion: rbac.authorization.k8s.io/v1
    fieldsType: FieldsV1
    fieldsV1:
      f:roleRef:
        f:apiGroup: {}
        f:kind: {}
        f:name: {}
      f:subjects: {}
    manager: oc
    operation: Update
    time: "2020-11-30T21:20:28Z"
  name: hive-cluster-pool-admin
  namespace: default
  resourceVersion: "40762"
  selfLink: /apis/rbac.authorization.k8s.io/v1/namespaces/default/rolebindings/hive-cluster-pool-admin
  uid: a0dec8ba-411a-48ee-92f3-432701d96655
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: hive-cluster-pool-admin
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: User
  name: abhinavdahiya
$ oc get rolebindings hive-cluster-pool-admin-binding -n adahiya-pool-1-kpkbg -oyaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  creationTimestamp: "2020-11-30T21:40:23Z"
  managedFields:
  - apiVersion: rbac.authorization.k8s.io/v1
    fieldsType: FieldsV1
    fieldsV1:
      f:roleRef:
        f:apiGroup: {}
        f:kind: {}
        f:name: {}
      f:subjects: {}
    manager: manager
    operation: Update
    time: "2020-11-30T21:40:22Z"
  name: hive-cluster-pool-admin-binding
  namespace: adahiya-pool-1-kpkbg
  resourceVersion: "46557"
  selfLink: /apis/rbac.authorization.k8s.io/v1/namespaces/adahiya-pool-1-kpkbg/rolebindings/hive-cluster-pool-admin-binding
  uid: fa3e9bfa-56bb-4938-bdbe-051108da68c6
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: hive-cluster-pool-admin
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: User
  name: abhinavdahiyahive git:(cluster_pool_admin) oc adm policy add-role-to-group hive-cluster-pool-admin hive-team
Warning: Group 'hive-team' not found
clusterrole.rbac.authorization.k8s.io/hive-cluster-pool-admin added: "hive-team"hive git:(cluster_pool_admin) oc get rolebindings hive-cluster-pool-admin -oyaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  creationTimestamp: "2020-11-30T21:20:28Z"
  managedFields:
  - apiVersion: rbac.authorization.k8s.io/v1
    fieldsType: FieldsV1
    fieldsV1:
      f:roleRef:
        f:apiGroup: {}
        f:kind: {}
        f:name: {}
      f:subjects: {}
    manager: oc
    operation: Update
    time: "2020-11-30T21:20:28Z"
  name: hive-cluster-pool-admin
  namespace: default
  resourceVersion: "40762"
  selfLink: /apis/rbac.authorization.k8s.io/v1/namespaces/default/rolebindings/hive-cluster-pool-admin
  uid: a0dec8ba-411a-48ee-92f3-432701d96655
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: hive-cluster-pool-admin
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: User
  name: abhinavdahiya

Add say a group to rolebinding in the same namespace, it is synced to the clusterdeployment rolebinding.

$ oc adm policy add-role-to-group hive-cluster-pool-admin hive-team
Warning: Group 'hive-team' not found
clusterrole.rbac.authorization.k8s.io/hive-cluster-pool-admin added: "hive-team"
$ oc get rolebindings hive-cluster-pool-admin hive-cluster-pool-admin-0 -oyaml
apiVersion: v1
items:
- apiVersion: rbac.authorization.k8s.io/v1
  kind: RoleBinding
  metadata:
    creationTimestamp: "2020-11-30T21:20:28Z"
    managedFields:
    - apiVersion: rbac.authorization.k8s.io/v1
      fieldsType: FieldsV1
      fieldsV1:
        f:roleRef:
          f:apiGroup: {}
          f:kind: {}
          f:name: {}
        f:subjects: {}
      manager: oc
      operation: Update
      time: "2020-11-30T21:20:28Z"
    name: hive-cluster-pool-admin
    namespace: default
    resourceVersion: "40762"
    selfLink: /apis/rbac.authorization.k8s.io/v1/namespaces/default/rolebindings/hive-cluster-pool-admin
    uid: a0dec8ba-411a-48ee-92f3-432701d96655
  roleRef:
    apiGroup: rbac.authorization.k8s.io
    kind: ClusterRole
    name: hive-cluster-pool-admin
  subjects:
  - apiGroup: rbac.authorization.k8s.io
    kind: User
    name: abhinavdahiya
- apiVersion: rbac.authorization.k8s.io/v1
  kind: RoleBinding
  metadata:
    creationTimestamp: "2020-11-30T21:43:37Z"
    managedFields:
    - apiVersion: rbac.authorization.k8s.io/v1
      fieldsType: FieldsV1
      fieldsV1:
        f:roleRef:
          f:apiGroup: {}
          f:kind: {}
          f:name: {}
        f:subjects: {}
      manager: oc
      operation: Update
      time: "2020-11-30T21:43:37Z"
    name: hive-cluster-pool-admin-0
    namespace: default
    resourceVersion: "47433"
    selfLink: /apis/rbac.authorization.k8s.io/v1/namespaces/default/rolebindings/hive-cluster-pool-admin-0
    uid: a4351b94-069d-4ff3-9e37-1ac90171ec84
  roleRef:
    apiGroup: rbac.authorization.k8s.io
    kind: ClusterRole
    name: hive-cluster-pool-admin
  subjects:
  - apiGroup: rbac.authorization.k8s.io
    kind: Group
    name: hive-team
kind: List
metadata:
  resourceVersion: ""
  selfLink: ""
$ oc get rolebindings hive-cluster-pool-admin-binding -n adahiya-pool-1-kpkbg -oyaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  creationTimestamp: "2020-11-30T21:40:23Z"
  managedFields:
  - apiVersion: rbac.authorization.k8s.io/v1
    fieldsType: FieldsV1
    fieldsV1:
      f:roleRef:
        f:apiGroup: {}
        f:kind: {}
        f:name: {}
      f:subjects: {}
    manager: manager
    operation: Update
    time: "2020-11-30T21:43:38Z"
  name: hive-cluster-pool-admin-binding
  namespace: adahiya-pool-1-kpkbg
  resourceVersion: "47436"
  selfLink: /apis/rbac.authorization.k8s.io/v1/namespaces/adahiya-pool-1-kpkbg/rolebindings/hive-cluster-pool-admin-binding
  uid: fa3e9bfa-56bb-4938-bdbe-051108da68c6
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: hive-cluster-pool-admin
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: Group
  name: hive-team
- apiGroup: rbac.authorization.k8s.io
  kind: User
  name: abhinavdahiya

@abhinavdahiya
Copy link
Contributor Author

/assign @dgoodwin
/cc @abutcher

Copy link
Contributor

@dgoodwin dgoodwin left a comment

Choose a reason for hiding this comment

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

Looks great, just one noteworthy request left, could you write up a short blurb in docs/clusterpools.md covering how to use this? We did decide recently to try to put docs in with the PRs that add the features going forward.

config/controllers/hive_controllers_role.yaml Show resolved Hide resolved
name: "no binding referring to cluster role",
existing: []runtime.Object{},
}, {
name: "no binding referring to cluster role",
Copy link
Contributor

Choose a reason for hiding this comment

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

Peculiar, we don't do this anywhere today afaik and typically try to give the tests unique names, this could get a little funky for anyone looking to just go run -test for a specific test, but probably not a huge deal. I think my vote would still be to give them unique names that cover the intent though.

…ster-pool-admin

Any role bindings in the namespace of the clusterpool that refer the ClusterRole `hive-cluster-pool-admin`
will be used to provide the subjects the same permission in the namespaces created for various
clusterdeployments for the clusterpool.

The controller performs these additional actions for each reconcile,

- lists all the rolebindings in clusterpool's namespace that refer the ClusterRole `hive-cluster-pool-admin`
to collect all the subjects.
  This makes sure that no work needs to be done when there are such rolebindings. And since k8s ensures that a rolebinding
  cannot be created when the ref doesn't exist, this will ensure that only when the ClusterRole exists would the controller
  run the next steps.
- lists all the namespaces attached to the clusterpool by using the constants.ClusterPoolNameLabel label selector.
- creates/updates a rolebinding `hive-cluster-pool-admin-binding` in each namespace binding to the same ClusterRole.

The controller also adds new watchers,

- changes to rolebindings in the clusterdeployment namespace
- changes to any rolebindings with ref to ClusterRole `hive-cluster-pool-admin` triggers resync for all clusterpools
  in that namespace.
the hive controller must have the permissions to give that permission in the clusterdeployments
namespaces when created for a cluster pool.
@dgoodwin
Copy link
Contributor

dgoodwin commented Dec 2, 2020

/lgtm

@openshift-ci-robot openshift-ci-robot added the lgtm Indicates that a PR is ready to be merged. label Dec 2, 2020
@openshift-ci-robot
Copy link

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: abhinavdahiya, dgoodwin

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

@openshift-ci-robot openshift-ci-robot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Dec 2, 2020
@openshift-bot
Copy link

/retest

Please review the full test history for this PR and help us cut down flakes.

@abhinavdahiya
Copy link
Contributor Author

/retest

1 similar comment
@abhinavdahiya
Copy link
Contributor Author

/retest

@openshift-bot
Copy link

/retest

Please review the full test history for this PR and help us cut down flakes.

2 similar comments
@openshift-bot
Copy link

/retest

Please review the full test history for this PR and help us cut down flakes.

@openshift-bot
Copy link

/retest

Please review the full test history for this PR and help us cut down flakes.

@openshift-merge-robot openshift-merge-robot merged commit 2f59e7c into openshift:master Dec 3, 2020
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. lgtm Indicates that a PR is ready to be merged.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants