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

Implement user impersonation #349

Closed
wants to merge 4 commits into from

Conversation

somtochiama
Copy link
Member

@somtochiama somtochiama commented May 26, 2021

Proof of concept for fluxcd/flux2#582
TLDR: This pull request enables the controller to impersonate a different user when applying and validating manifests from Sources. This reduces the privileges needed by the controller serviceaccount and also moves the ball towards multi-tenancy.

Changes

  • User impersonation in the controller is implemented behind the --user-impersonation flag.
  • The Principal field is added to the the API as an alternative to ServiceAccountName.
type Principal struct {
	// Kind specifies the kind of object to be impersonated
	// The kind could be 'User' or 'ServiceAccount'
	// +kubebuilder:validation:Enum=ServiceAccount;User
	Kind string `json:"kind"`

	// The name of the object to be impersonated
	Name string `json:"name"`
}

The kind can be either User or ServiceAccount.
When Principal is not set and the --user-impersonation flag is set, a default user reconciler is used.

Token impersonation will still be used if:

  • when the user-impersonation flag is not set
  • when serviceAccountName is set and principal is unset regardless of flag passed in by users

When both serviceAccountName and principal is set, the flag set by the user determines the type of impersonation. If --user-impersonation isn't set, token impersonation is user

For remote clusters, user impersonation is only enabled when the user-impersonation flag is set and principal is also set.

Example

The user flux:user:{{namespace}}:{{spec.user}} in this case flux:user:tenant-a:admin has cluster-admin permissions only within the tenant-a namespace and the kustomize-controller can only apply manifest in the tenant-a namespace when impersonating this user.

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: admin
  namespace: tenant-a
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
  - kind: User
    name: flux:user:tenant-a:admin
    namespace: tenant-a
---
apiVersion: kustomize.toolkit.fluxcd.io/v1beta1
kind: Kustomization
metadata:
  name: podinfo
  namespace: tenant-a
spec:
  targetNamespace: tenant-a
  interval: 5m0s
  path: ./kustomize
  prune: true
  sourceRef:
    kind: GitRepository
    name: podinfo
    namespace: flux-system
  validation: client
  principal:
    kind: User
    name: admin

Feedback & Testing

  1. Install flux
flux install
  1. Apply the CRDs from this repository
kubectl apply -k https://github.com/SomtochiAma/kustomize-controller/config/crd?ref=user-multi-tenancy
  1. Create ClusterRole to allow the kustomize-controller to impersonate users and service accounts.
cat << EOF | kubectl apply -f -
apiVersion: v1
kind: ServiceAccount
metadata:
  name: user-impersonation
  namespace: flux-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  creationTimestamp: null
  name: user-impersonation-role
rules:
  - apiGroups:
    - ""
    resources:
      - configmaps
    verbs:
      - get
      - list
      - watch
      - create
      - update
      - patch
      - delete
  - apiGroups:
      - ""
    resources:
      - configmaps/status
    verbs:
      - get
      - update
      - patch
  - apiGroups:
      - ""
    resources:
      - events
    verbs:
      - create
  - apiGroups:
      - "coordination.k8s.io"
    resources:
      - leases
    verbs:
      - get
      - list
      - watch
      - create
      - update
      - patch
      - delete
  - apiGroups:
      - ""
    resources:
      - events
    verbs:
      - create
      - patch
  - apiGroups:
      - ""
    resources:
      - secrets
      - serviceaccounts
    verbs:
      - get
      - list
      - watch
  - apiGroups:
      - kustomize.toolkit.fluxcd.io
    resources:
      - kustomizations
    verbs:
      - create
      - delete
      - get
      - list
      - patch
      - update
      - watch
  - apiGroups:
      - kustomize.toolkit.fluxcd.io
    resources:
      - kustomizations/finalizers
    verbs:
      - create
      - delete
      - get
      - patch
      - update
  - apiGroups:
      - kustomize.toolkit.fluxcd.io
    resources:
      - kustomizations/status
    verbs:
      - get
      - patch
      - update
  - apiGroups:
      - source.toolkit.fluxcd.io
    resources:
      - buckets
      - gitrepositories
    verbs:
      - get
      - list
      - watch
  - apiGroups:
      - source.toolkit.fluxcd.io
    resources:
      - buckets/status
      - gitrepositories/status
    verbs:
      - get
  - apiGroups:
    - ""
    resources:
      - groups
      - users
      - serviceaccounts
    verbs:
      - impersonate
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: user-impersonation
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: user-impersonation-role
subjects:
  - kind: ServiceAccount
    name: user-impersonation
    namespace: flux-system
EOF
  1. Patch the kustomize-controller deployment so that it uses an image build of this PR, enables user-impersonation and runs under the more restricted service account
kubectl patch deploy/kustomize-controller -n flux-system -p "$(cat << EOF
spec:
  template:
    spec:
      containers:
        - name: manager
          args:
          - --watch-all-namespaces=true
          - --log-level=info
          - --log-encoding=json
          - --enable-leader-election
          - --user-impersonation
          image: somma/kustomize-controller:user-imp-4c6938415
      serviceAccountName: user-impersonation
EOF
)"

Signed-off-by: Somtochi Onyekwere somtochionyekwere@gmail.com

config/testdata/impersonation/test.yaml Outdated Show resolved Hide resolved
config/testdata/user-impersonation/test.yaml Outdated Show resolved Hide resolved
config/testdata/user-impersonation/test2.yaml Outdated Show resolved Hide resolved
config/testdata/user-impersonation/patch.yaml Outdated Show resolved Hide resolved
config/testdata/user-impersonation/token-imp.yaml Outdated Show resolved Hide resolved
config/testdata/user-impersonation/token-imp.yaml Outdated Show resolved Hide resolved
config/testdata/user-impersonation/patch.yaml Outdated Show resolved Hide resolved
controllers/kustomization_controller.go Outdated Show resolved Hide resolved
controllers/kustomization_controller.go Outdated Show resolved Hide resolved
main.go Outdated Show resolved Hide resolved
@stefanprodan stefanprodan changed the title Implement multi-tenancy in kustomize-controller Implement user impersonation Jun 4, 2021
controllers/kustomization_controller.go Outdated Show resolved Hide resolved
controllers/kustomization_controller.go Outdated Show resolved Hide resolved
controllers/kustomization_controller.go Outdated Show resolved Hide resolved
@somtochiama somtochiama force-pushed the user-multi-tenancy branch 2 times, most recently from b43e78f to dfb22bd Compare June 8, 2021 13:30
Signed-off-by: Somtochi Onyekwere <somtochionyekwere@gmail.com>
@somtochiama somtochiama force-pushed the user-multi-tenancy branch from dfb22bd to f2486d1 Compare June 8, 2021 14:24
Signed-off-by: Somtochi Onyekwere <somtochionyekwere@gmail.com>
Signed-off-by: Somtochi Onyekwere <somtochionyekwere@gmail.com>
Signed-off-by: Somtochi Onyekwere <somtochionyekwere@gmail.com>
if enableUserImpersonation {
var user string
if kustomization.Spec.Principal == nil {
user = fmt.Sprintf("flux:user:%s:%s", kustomization.Namespace, pkgclient.DefaultUser)
Copy link
Member

Choose a reason for hiding this comment

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

flux:user:%s:%s (and other strings like this) should be defined, if possible with helper utils, in the fluxcd/pkg library.

@somtochiama somtochiama closed this Dec 3, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants