Workload identity for Kubernetes (cert-based authentication)
Security policy can be used to create identities for OpenShift/Kubernetes resources/objects at multiple levels of granularity.
In most cases, you create an identity for your workload based on its service account or based on its controller such as a Deployment or StatefulSet. Then you configure your application Pod to authenticate with Conjur using this identity.
Once configured, the identity can be used by any Pod deployed using the service account or the controller, providing a flexible way of sharing secrets among Pods that may have common access needs.
By assigning identities to Kubernetes resources/objects, you can use security policy to control the granularity and identity of the Kubernetes resources/objects that authenticate to Conjur and that can access secrets. The access usually occurs in the context of a workload-specific policy, where specific roles are granted access to specific secrets.
Define Kubernetes resources/objects as Conjur identities
In security policy, workloads are represented as hosts
and their identities are represented as annotations on the host
resource. These annotations determine the granularity at which authentication is performed and access is granted.
Kubernetes |
Description |
Annotation format |
---|---|---|
Namespace |
Authentication and secret access is by Kubernetes namespace. All resources in the namespace are controlled by the same grants and permissions. Use this level of granularity: if all applications in the namespace share secrets, and if access to the secrets can be managed together. |
|
Namespace Label Selector |
Authentication and secret access is by Kubernetes namespaces that match the configured label selector. The same grants and permissions control all of the resources in the namespaces that match the label selector. The label selector must adhere to the format For example, in a Kubernetes deployment managed by Rancher, namespaces that belong to a specific Rancher project are given a reserved label. To match with a project whose ID is equal to Use this level of granularity: if all applications in a group of namespaces share secrets, and if access to the secrets can be managed together. |
|
Deployment |
Authentication and secret access is by the Kubernetes Deployment name within a namespace. Use this level of granularity: if a group of stateless applications share secrets and access management rules. |
|
DeploymentConfig (OpenShift only) |
Authentication and secret access is by the DeploymentConfig name within an OpenShift project. Use this level of granularity: if a group of stateless applications share secrets and access management rules. |
|
ServiceAccount |
Authentication is by Kubernetes service account name within a namespace. Use this level of granularity (relevant for cert-based authentication only): if you are already using service accounts to control access to secrets. You can build policy on top of the service account access control. In this case, you will be managing both sets of access control for the same secrets. We recommend using this option as a transition, and move towards using the Kubernetes Deployment and StatefulSet resources as app IDs. |
|
StatefulSet |
Authentication is by Kubernetes StatefulSet name within a namespace. Use this level of granularity: if a group of stateful applications share secrets and access management rules. |
|
Pod |
Authentication is by Kubernetes Pod name within a namespace. Use this level of granularity: for testing and proof of concept (POC). Pods tend to stop and restart too often to depend on them for security. |
|
Authentication Container Name |
The name of the container from which the host authenticates with Conjur. This annotation is required whenever the sidecar or init container is given a name other than authenticator. |
|
Workload identity in policy
Once you have decided on the granularity of authentication and secret access that you want to enforce, create the relevant host
in your policy.
For example, to control authentication and secret access by the test-app-namespace namespace, you'd create the following policy:
|
where authn-k8s/authentication-container-name
is the container name from which the host authenticates with Conjur.
When you define the Deployment manifest to deploy your workload, you create a connection to the workload ID (host
) by adding the full host id
path an environment variable in the Deployment manifest.
Examples of host annotations
|
Namespace label security
When you use namespace labels to grant authentication and secret access, you must secure the labels to ensure that only Kubernetes admins can create and label namespaces. Use ClusterRoles and ClusterRoleBindings to grant and restrict namespace access.
ClusterRole and ClusterRoleBinding for read-only access
The following ClusterRole and ClusterRoleBinding pair applies read-only permissions on namespace resources for all authenticated users.
---
apiVersion: rbac.authorization.k8s.io
kind: ClusterRole
metadata:
name: namespace-reader
rules:
- apiGroups: [""]
resources: ["namespaces"]
verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io
kind: ClusterRoleBinding
metadata:
name: namespace-reader
subjects:
- kind: Group
name: system:authenticated
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: namespace-reader
apiGroup: rbac.authorization.k8s.io
When a non-admin user tries to label a namespace with kubectl label
, the command returns the following:
---Error from server (Forbidden): namespaces "<namespace>" is forbidden: User "<authd-user>" cannot patch resource "namespaces" in API group "" in the namespace "<namespace>"
ClusterRole and ClusterRoleBinding for write access
To give a specific group of admin users write access to namespace resources, use the following ClusterRole and ClusterRoleBinding for those admins.
---
apiVersion: rbac.authorization.k8s.io
kind: ClusterRole
metadata:
name: namespace-writer
rules:
- apiGroups: [""]
resources: ["namespaces"]
verbs: ["create", "update", "patch"]
---
apiVersion: rbac.authorization.k8s.io
kind: ClusterRoleBinding
metadata:
name: namespace-writer
subjects:
- kind: Group
name: <group-that-should-have-edit-permission>
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: namespace-editor
apiGroup: rbac.authorization.k8s.io