Private Namespace and Restricted RBAC

A non-admin type user typically does not have permissions for any cluster-scoped resources and only has read and/or write permissions to resources in one or more namespaces.

About this task

Note

All of the RBAC resources for managing non-admin type users, although they may apply to private namespaces, are created in kube-system such that only admin level users can manager non-admin type users, roles, and rolebindings.

The following example creates a non-admin service account called dave-user with read/write type access to a single private namespace (billing-dept-ns).

Note

The following example creates and uses ServiceAccounts as the user mechanism and subject for the rolebindings, however the procedure equally applies to user accounts defined in an external Windows Active Directory as the subject of the rolebindings.

Procedure

  1. If it does not already exist, create a general user role defining restricted permissions for general users.

    This is of the type ClusterRole so that it can be used in the context of any namespace when binding to a user.

    1. Create the user role definition file.

      % cat <<EOF > general-user-clusterrole.yaml
      apiVersion: rbac.authorization.k8s.io/v1
      kind: ClusterRole
      metadata:
        # "namespace" omitted since ClusterRoles are not namespaced
        name: general-user
      
      rules:
      
      # For the core API group (""), allow full access to all resource types
      # EXCEPT for resource policies (limitranges and resourcequotas) only allow read access
      - apiGroups: [""]
        resources: ["bindings", "configmaps", "endpoints", "events", "persistentvolumeclaims", "pods", "podtemplates", "replicationcontrollers", "secrets", "serviceaccounts", "services"]
        verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
      - apiGroups: [""]
        resources: [ "limitranges", "resourcequotas" ]
        verbs: ["get", "list"]
      
      # Allow full access to all resource types of the following explicit list of apiGroups.
      # Notable exceptions here are:
      #     ApiGroup                      ResourceTypes
      #     -------                       -------------
      #     policy                        podsecuritypolicies, poddisruptionbudgets
      #     networking.k8s.io             networkpolicies
      #     admissionregistration.k8s.io  mutatingwebhookconfigurations, validatingwebhookconfigurations
      #
      - apiGroups: ["apps", "batch", "extensions", "autoscaling", "apiextensions.k8s.io", "rbac.authorization.k8s.io"]
        resources: ["*"]
        verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
      
      # Cert Manager API access
      - apiGroups: ["cert-manager.io", "acme.cert-manager.io"]
        resources: ["*"]
        verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
      
      EOF
      
    2. Apply the definition.

      ~(keystone_admin)$ kubectl apply -f general-user-cluster-role.yaml
      
  2. Create the billing-dept-ns namespace, if it does not already exist.

    ~(keystone_admin)$ kubectl create namespace billing-dept-ns
    
  3. Create both the dave-user service account and the namespace-scoped RoleBinding.

    The RoleBinding binds the general-user role to the dave-user ServiceAccount for the billing-dept-ns namespace.

    1. Create the account definition file.

      % cat <<EOF > dave-user.yaml
      apiVersion: v1
      kind: ServiceAccount
      metadata:
        name: dave-user
        namespace: kube-system
      ---
      apiVersion: v1
      kind: Secret
      type: kubernetes.io/service-account-token
      metadata:
        name: dave-user-sa-token
        namespace: kube-system
        annotations:
          kubernetes.io/service-account.name: dave-user
      ---
      apiVersion: rbac.authorization.k8s.io/v1
      kind: RoleBinding
      metadata:
        name: dave-user
        namespace: billing-dept-ns
      roleRef:
        apiGroup: rbac.authorization.k8s.io
        kind: ClusterRole
        name: general-user
      subjects:
      - kind: ServiceAccount
        name: dave-user
        namespace: kube-system
      EOF
      
    2. Apply the definition.

      % kubectl apply -f dave-user.yaml
      
  4. If the user requires use of the local docker registry, create an openstack user account for authenticating with the local docker registry.

    1. If a project does not already exist for this user, create one.

      % openstack project create billing-dept-ns
      
    2. Create an openstack user in this project.

      % openstack user create --password P@ssw0rd \
      --project billing-dept-ns dave-user
      

      Note

      Substitute a password conforming to your password formatting rules for P@ssw0rd.

    3. Create a secret containing these userid/password credentials for use as an ImagePullSecret

      % kubectl create secret docker-registry registry-local-dave-user --docker-server=registry.local:9001 --docker-username=dave-user  --docker-password=P@ssw0rd --docker-email=noreply@windriver.com -n billing-dept-ns
      

    dave-user can now push images to registry.local:9001/dave-user/ and use these images for pods by adding the secret above as an ImagePullSecret in the pod spec.

  5. If the user requires the ability to create persistentVolumeClaims in his namespace, then execute the following commands to enable the rbd-provisioner in the user’s namespace.

    1. Create an RBD namespaces configuration file.

      % cat <<EOF > rbd-namespaces.yaml
      storageClasses:
      - additionalNamespaces: [default, kube-public, billing-dept-ns]
        chunk_size: 64
        crush_rule_name: storage_tier_ruleset
        name: general
        pool_name: kube-rbdkube-system
        replication: 1
        userId: ceph-pool-kube-rbd
        userSecretName: ceph-pool-kube-rbd
      EOF
      
    2. Update the helm overrides.

      ~(keystone_admin)$ system helm-override-update --reuse-values --values rbd-namespaces.yaml \
      platform-integ-apps rbd-provisioner kube-system
      
    3. Apply the application.

      ~(keystone_admin)$ system application-apply platform-integ-apps
      
    4. Monitor the system for the application-apply to finish

      ~(keystone_admin)$ system application-list
      
    5. Apply the secret to the new rbd-provisioner namespace.

      ~(keystone_admin)$ kubectl get secret ceph-pool-kube-rbd -n default -o yaml | grep -v '^\s*namespace:\s' | kubectl apply -n <namespace> -f -
      
  6. If this user requires the ability to use helm, do the following.

    1. Create a ClusterRole for reading namespaces, if one does not already exist.

      % cat <<EOF > namespace-reader-clusterrole.yaml
      apiVersion: rbac.authorization.k8s.io/v1
      kind: ClusterRole
      metadata:
        name: namespace-reader
      rules:
      - apiGroups: [""]
        resources: ["namespaces"]
        verbs: ["get", "watch", "list"]
      EOF
      

      Apply the configuration.

      % kubectl apply -f namespace-reader-clusterrole.yaml
      
    2. Create a RoleBinding for the tiller account of the user’s namespace.

      Note

      The tiller account of the user’s namespace must be named ‘tiller’.

      % cat <<EOF > read-namespaces-billing-dept-ns-tiller.yaml
      apiVersion: rbac.authorization.k8s.io/v1
      kind: ClusterRoleBinding
      metadata:
        name: read-namespaces-billing-dept-ns-tiller
      subjects:
      - kind: ServiceAccount
        name: tiller
        namespace: billing-dept-ns
      roleRef:
        kind: ClusterRole
        name: namespace-reader
        apiGroup: rbac.authorization.k8s.io
      EOF
      

      Apply the configuration.

      % kubectl apply -f read-namespaces-billing-dept-ns-tiller.yaml