Kubernetes Security Concepts: Difference between revisions

From NovaOrdis Knowledge Base
Jump to navigation Jump to search
 
(211 intermediate revisions by the same user not shown)
Line 2: Line 2:


* [[Kubernetes_Concepts#Subjects|Kubernetes Concepts]]
* [[Kubernetes_Concepts#Subjects|Kubernetes Concepts]]
* [[Kubernetes Security Operations]]
* [[Linux Security Concepts]]
=Overview=
Kubernetes security covers several areas:
# The Kubernetes cluster must provide infrastructure and configuration capabilities that ensure the API sever is [[#Authentication|only accessible to authenticated identities]]. Once the identity of the caller is established through authentication, the Kubernetes cluster must ensure that [[#Controlling_Access_to_the_Kubernetes_API|access is limited only to resources that are supposed to be accessible]] to the authenticated identity and the access is denied for all other resources.
# Kubernetes clusters runs arbitrary applications in pods, and they must provide mechanisms that prevent a possibly malicious application from accessing node and network resources it is not supposed to access. This subject is covered by [[#Pod_and_Container_Security|Pod and Container Security]] section.
# Kubernetes expects that all API communication in the cluster is encrypted. This subject is covered in [[#Transport_Security|Transport Security]] section.


=Service Account=
=<span id='Authentication'></span><span id='Identity_while_Accessing_the_Cluster'></span>API Server Authentication - Identity while Accessing the Cluster=


A service account provides an identity for processes that run in a Pod.
The [[#Identities|identity]] while accessing the Kubernetes cluster is associated with a (usually human) [[#User|user]], authenticated as part of the request handling, that uses an external CLI tool such as <code>[[kubectl]]</code>, or with a [[#Service_Account|service account]], which provides identity to pods and containers running inside the pods that make API requests as part of their logic. If an API request is not associated with any of these identities, it is treaded as an [[#Anonymous_Request|anonymous request]]. The available [[#API_Authentication_Strategies|API request authentication strategies]] are described below.


TODO:
==Identities==
* https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/
===<span id='User_Account'></span>User===
* https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/
{{External|https://kubernetes.io/docs/reference/access-authn-authz/authentication/}}
Users are sometimes referred to as "users accounts" or "normal users". There is no "User" Kubernetes API resource, and users cannot be added through an API call. It is assumed that a cluster-independent service manages users. That service can be implemented as a username/password file, a user store like Google Accounts,  or an administrator that distributes private keys. When the authentication credentials are presented to the API server, the API server extracts the user name from the credentials (e.g. from the common name field in the "subject" of the certificate, "/CN=alice"). <font color=darkgray>Explain how the Kubernetes authentication token is associated with such a request.</font>
====User Operations====
* [[Kubernetes_User_Operations#Create_a_Normal_User|Create a Normal User]]
* [[Kubernetes User Operations#Add_a_Normal_User_via_a_Certificate|Add a Normal User via a Certificate]]
* Define a user in EKS:
** [[Amazon_EKS_Operations#Associate_an_IAM_Role_with_a_Kubernetes_User|Associate an IAM Role with the Kubernetes User]]


=Role Based Access Control (RBAC)=
===Group===
===Service Account===
{{External|https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/}}
{{External|https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/}}
Processes in containers inside [[Kubernetes_Pod_and_Container_Concepts#Pods_and_Service_Accounts|pods]] can contact the API server, and they need an identity when doing so. A '''service account''' provides the identity for processes that run in a the pod. Processes will authenticate using the identity provided by the service account. By  default, in absence of specific configuration, the pods will authenticate as the [[#Default_Service_Account|default service account]] in the namespace they are running in. A specific service account name can be specified in the [[Kubernetes_Pod_Manifest#serviceAccountName|pod manifest]]. Also see [[#Non-Default_Service_Accounts|Non-Default Service Accounts]] below.
 
Unlike [[#User|users]], the service accounts are resources managed by Kubernetes, in that there is a <code>[[Kubernetes_API_Resources_Concepts#Service_Account|ServiceAccount]]</code> Kubernetes [[Kubernetes_API_Resources_Concepts#API_Resources|API resource]]. Service accounts can be created via API calls, or automatically by the server. The service accounts are bound to specific namespaces. A service account is tied to a set of credentials stored as Secrets, which are mounted into the pod allowing the in-cluster processes to talk to the Kubernetes API. For more details on associating service account with secrets, see [[#Service_Accounts_and_Credentials|Service Accounts and Credentials]] below. Service accounts can be bound to specific roles. For more details on associating service account with roles, see [[#Service_Accounts_and_Roles|Service Accounts and Roles]] below.
 
Service accounts are rendered in logs using their [[#Service_Account_Full_Name|full name]] (e.g. "system:serviceaccount:blue:default)
 
<span id='Kubectl_System_Account_Identity'></span><code>kubectl</code> operations can be conducted under the identity of a specific service account using [[Kubectl#--as|kubectl --as option]]:
<syntaxhighlight lang='bash'>
kubectl --as=system:serviceaccount:<namespace>:<service-account-name> -n <namespace> ...
</syntaxhighlight>
A Secret of type <code>kubernetes.io/service-account-token</code>, which contains the '''system account token''' is automatically created when the Service Account is created. A <code>kubectl</code> context must be configured with this system account token to allow interaction under the identity of the System Account. For more details, see the [[#Service_Account_Token|Service Account Token]] section below.
 
Also see: {{Internal|Kubernetes_Pod_and_Container_Concepts#Pods_and_Service_Accounts|Pod Service Account}}
 
====<span id='Service_Accounts_and_Credentials'></span><span id='Service_Accounts_Credentials_(service-account-token)'></span>Service Account Token====
{{External|https://kubernetes.io/docs/concepts/configuration/secret/#service-account-token-secrets}}
[[File:Service_Account_Token.png|500px]]
 
When a new Service Account is created, a Secret of type <code>kubernetes.io/service-account-token</code> is automatically created for the Service Account. Its name is listed in the Service Account's descriptor:
<syntaxhighlight lang='yaml'>
apiVersion: v1
kind: ServiceAccount
metadata:
  name: some-sa
  [...]
secrets:
- name: some-sa-token-hqmmc
</syntaxhighlight>
The service account token metadata includes the token itself, and the cluster's CA certificate:
<syntaxhighlight lang='yaml'>
apiVersion: v1
metadata:
  name: some-sa-token-hqmmc
  [...]
kind: Secret
type: kubernetes.io/service-account-token
data:
  ca.crt: LS0tL...Cg==
  namespace: ZGlj...w==
  token: ZXlK...Zw==
</syntaxhighlight>
Note that the token is base64-encoded in the descriptor and it will need decoding to be used as credentials.
 
The content of the token, which represents the credentials of the service account, are projected into the filesystem of each container of the pod as a <code>[[Kubernetes_Cluster_Configuration_Concepts#kubernetes.io.2Fservice-account-token| kubernetes.io/service-account-token]]</code>-type secret. The secret content is available to the container processes as <code>/var/run/secrets/kubernetes.io/serviceaccount/ca.crt</code> and by default is auto-mounted. In Kubernetes 1.6+ it can be opted out of auto-mounting by setting <code>[https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#use-the-default-service-account-to-access-the-api-server automountServiceAccountToken]</code> in the service account manifest.
 
The system account token can be used to configure a <code>kubectl</code> context that [[#Kubectl_System_Account_Identity|allows interaction with the API server under the identity of the System Account]]. For that, the token and the CA certificate stored in the Secret associated with the Service Account  must be configured in a <code>kubectl</code> context as shown in the example below. Note that the context of the token must be base64-decoded with:
<syntaxhighlight lang='bash'>
kubectl get secret some-sa-token-hqmmc -o=jsonpath='{.data.token}' | base64 -d
</syntaxhighlight>
The CA certificate does not require decoding.
<syntaxhighlight lang='yaml'>
apiVersion: v1
kind: Config
users:
  - name: some-sa-on-some-cluster
    user:
      token: <base64-decoded_content_of_the_service_account_secret_token>
clusters:
  - name: some-cluster
    cluster:
      server: https://...example.com:443
      certificate-authority-data: <the_content_of_the_service_account_secret_ca_certficate_as_is>
contexts:
  - name: some-context
    context:
      cluster: some-cluster
      namespace: some-namespace
      user: some-sa-on-some-cluster
</syntaxhighlight>
 
{{Warn|⚠️ The service account token is a long-lived, static credential. If it is compromised, lost, or stolen, an attacker may be able to perform all the actions associated with that token until the service account is deleted, so use them sparingly}}
 
<font color=darkkhaki>
Clarify the following:
* The default namespace to be used for namespaced API operations is placed on the filesystem of each container of the pod at <code>/var/run/secrets/kubernetes.io/serviceaccount/namespace</code>.
* What are the default credentials associated with the default service account.
* How can this be association displayed.
* What happens with a newly created service account - does it need to be explicitly associated with those credentials or the association is done automatically upon creation.
</font>
 
====Service Account Full Name====
 
Service accounts can be referred to using their full name <code>system:serviceaccount:<namespace>:<account-name></code> (e.g. <code>system:serviceaccount:blue:default</code>).
 
====Default Service Account====
 
Each namespace comes with a default service account:
 
<syntaxhighlight lang='yaml'>
apiVersion: v1
kind: ServiceAccount
metadata:
  name: default
  namespace: default
secrets:
- name: default-token-dddkl
</syntaxhighlight>
 
A [[Kubernetes_Pod_Manifest#Example|pod]] whose service account was not explicitly configured will run with the default service account for its namespace, its configuration is equivalent with:
<syntaxhighlight lang='yaml'>
apiVersion: v1
kind: Pod
spec:
  containers:
  - name: [...]
    [...]
  serviceAccountName: default
[...]
</syntaxhighlight>
The a specific service account can be configured as such:
<syntaxhighlight lang='yaml'>
apiVersion: v1
kind: Pod
spec:
  containers:
  - name: [...]
    [...]
  serviceAccountName: something
[...]
</syntaxhighlight>
 
====Non-Default Service Accounts====
 
To use a non-default service account, set <code>spec.serviceAccountName</code> field of the [[Kubernetes_Pod_Manifest#serviceAccountName|pod manifest]]. The service account has to exist at the time the pod is created, or it will be rejected. If the pod was already created, the service account cannot be updated.
 
====Service Accounts and Roles====
The recommended way to ensure that an application operates within a specific security scope is to bind a role or a set of roles to an application-specific service account. For more details, see: {{Internal|Kubernetes_Role_Based_Access_Control_Concepts|Role Based Access Control Concepts}}
====Service Account Operations====
* [[Kubernetes_Service_Account_Operations#Details_about_the_Namespace.27s_Default_Service_Account|Details about the Namespace's Default Service Account]]
* [[Kubernetes_Service_Account_Operations#Deploy_a_Service_Account.2C_a_Role_and_a_Role_Binding_with_a_Helm_Chart|Deploy a Service Account, a Role and a Role Binding with a Helm Chart]]
* [[Kubernetes_RBAC_Operations#Assigning_a_Cluster_Role_to_a_Service_Account|Assigning a Cluster Role to a Service Account]]
 
===Anonymous Request===
{{External|https://kubernetes.io/docs/reference/access-authn-authz/authentication/#anonymous-requests}}
When the API server handles a request, it first attempts to authenticate the identity making the request with one of the available authentication methods. If all authentication methods fail, and if anonymous request support is enabled, the identity is treated as anonymous requests, and given a username of <code>system:anonymous</code> and a group of <code>system:unauthenticated</code>.
 
==API Authentication Strategies==
{{External|https://kubernetes.io/docs/reference/access-authn-authz/authentication/#authentication-strategies}}
Kubernetes provides various authentication strategies to be used by the clients that send API requests into the [[Kubernetes_Control_Plane_and_Data_Plane_Concepts#API_Server|Kubernetes API server]]. These authentication strategies are implemented by the server's authentication plugins.
===Client X.509 Certificates===
{{External|https://kubernetes.io/docs/reference/access-authn-authz/authentication/#x509-client-certs}}
===Bearer Tokens===
[[Kubectl#--token|kubectl]] allows specifying a bearer token in-line with <code>--token</code>:
<syntaxhighlight lang='bash'>
kubectl --token aHR0c...NiYg get pods
</syntaxhighlight>
====Webhook Token Authentication====
{{External|https://kubernetes.io/docs/reference/access-authn-authz/authentication/#webhook-token-authentication}}
=====EKS Webhook Token Authentication=====
EKS has native support for webhook token authentication. See: {{Internal|EKS Webhook Token Authentication|EKS Webhook Token Authentication}}
====Service Account Tokens====
{{External|https://kubernetes.io/docs/reference/access-authn-authz/authentication/#service-account-tokens}}
<font color=darkgray>TODO: reconcile Service Account Tokens and <code>service-account-token</code> [[#Service_Accounts_Credentials_.28service-account-token.29|secrets]].</font>
====Static Token File====
{{External|https://kubernetes.io/docs/reference/access-authn-authz/authentication/#static-token-file}}
====Bootstrap Tokens====
{{External|https://kubernetes.io/docs/reference/access-authn-authz/authentication/#bootstrap-tokens}}
===Authenticating Proxy===
{{External|https://kubernetes.io/docs/reference/access-authn-authz/authentication/#authenticating-proxy}}
===HTTP Basic Auth===
===OpenID Connect Tokens===
{{External|https://kubernetes.io/docs/reference/access-authn-authz/authentication/#openid-connect-tokens}}
 
=Controlling Access to the Kubernetes API=
{{External|https://kubernetes.io/docs/reference/access-authn-authz/controlling-access/}}
 
==<span id='Cluster_Administrator'></span>Role Based Access Control (RBAC)==
{{Internal|Kubernetes Role Based Access Control Concepts|Kubernetes Role Based Access Control (RBAC) Concepts}}
 
=<span id='Pod_Security_Context_and_Container_Security_Context'></span><span id='Pod_Security_Context'></span><span id='Pod_Security'></span><span id='Pod_Security_Policies'></span>Pod and Container Security=
 
For more details on pod and container security concepts, including '''pod and container security contexts''' and '''pod security policies''', see:
{{Internal|Kubernetes Pod and Container Security|Pod and Container Security}}
 
=Transport Security=
{{External|https://kubernetes.io/docs/tasks/administer-cluster/securing-a-cluster/#use-transport-layer-security-tls-for-all-api-traffic}}
{{External|https://kubernetes.io/docs/reference/access-authn-authz/#transport-security}}
Kubernetes expects that all API communication in the cluster is encrypted by default with TLS, and the majority of installation methods will allow the necessary certificates to be created and distributed to the cluster components.
==Certificates Required by a Kubernetes Cluster==
{{External|https://kubernetes.io/docs/setup/best-practices/certificates/}}

Latest revision as of 01:33, 30 March 2024

Internal

Overview

Kubernetes security covers several areas:

  1. The Kubernetes cluster must provide infrastructure and configuration capabilities that ensure the API sever is only accessible to authenticated identities. Once the identity of the caller is established through authentication, the Kubernetes cluster must ensure that access is limited only to resources that are supposed to be accessible to the authenticated identity and the access is denied for all other resources.
  2. Kubernetes clusters runs arbitrary applications in pods, and they must provide mechanisms that prevent a possibly malicious application from accessing node and network resources it is not supposed to access. This subject is covered by Pod and Container Security section.
  3. Kubernetes expects that all API communication in the cluster is encrypted. This subject is covered in Transport Security section.

API Server Authentication - Identity while Accessing the Cluster

The identity while accessing the Kubernetes cluster is associated with a (usually human) user, authenticated as part of the request handling, that uses an external CLI tool such as kubectl, or with a service account, which provides identity to pods and containers running inside the pods that make API requests as part of their logic. If an API request is not associated with any of these identities, it is treaded as an anonymous request. The available API request authentication strategies are described below.

Identities

User

https://kubernetes.io/docs/reference/access-authn-authz/authentication/

Users are sometimes referred to as "users accounts" or "normal users". There is no "User" Kubernetes API resource, and users cannot be added through an API call. It is assumed that a cluster-independent service manages users. That service can be implemented as a username/password file, a user store like Google Accounts, or an administrator that distributes private keys. When the authentication credentials are presented to the API server, the API server extracts the user name from the credentials (e.g. from the common name field in the "subject" of the certificate, "/CN=alice"). Explain how the Kubernetes authentication token is associated with such a request.

User Operations

Group

Service Account

https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/
https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/

Processes in containers inside pods can contact the API server, and they need an identity when doing so. A service account provides the identity for processes that run in a the pod. Processes will authenticate using the identity provided by the service account. By default, in absence of specific configuration, the pods will authenticate as the default service account in the namespace they are running in. A specific service account name can be specified in the pod manifest. Also see Non-Default Service Accounts below.

Unlike users, the service accounts are resources managed by Kubernetes, in that there is a ServiceAccount Kubernetes API resource. Service accounts can be created via API calls, or automatically by the server. The service accounts are bound to specific namespaces. A service account is tied to a set of credentials stored as Secrets, which are mounted into the pod allowing the in-cluster processes to talk to the Kubernetes API. For more details on associating service account with secrets, see Service Accounts and Credentials below. Service accounts can be bound to specific roles. For more details on associating service account with roles, see Service Accounts and Roles below.

Service accounts are rendered in logs using their full name (e.g. "system:serviceaccount:blue:default)

kubectl operations can be conducted under the identity of a specific service account using kubectl --as option:

kubectl --as=system:serviceaccount:<namespace>:<service-account-name> -n <namespace> ...

A Secret of type kubernetes.io/service-account-token, which contains the system account token is automatically created when the Service Account is created. A kubectl context must be configured with this system account token to allow interaction under the identity of the System Account. For more details, see the Service Account Token section below.

Also see:

Pod Service Account

Service Account Token

https://kubernetes.io/docs/concepts/configuration/secret/#service-account-token-secrets

Service Account Token.png

When a new Service Account is created, a Secret of type kubernetes.io/service-account-token is automatically created for the Service Account. Its name is listed in the Service Account's descriptor:

 
apiVersion: v1
kind: ServiceAccount
metadata:
  name: some-sa
  [...]
secrets:
- name: some-sa-token-hqmmc

The service account token metadata includes the token itself, and the cluster's CA certificate:

 
apiVersion: v1
metadata:
  name: some-sa-token-hqmmc
  [...]
kind: Secret
type: kubernetes.io/service-account-token
data:
  ca.crt: LS0tL...Cg==
  namespace: ZGlj...w==
  token: ZXlK...Zw==

Note that the token is base64-encoded in the descriptor and it will need decoding to be used as credentials.

The content of the token, which represents the credentials of the service account, are projected into the filesystem of each container of the pod as a kubernetes.io/service-account-token-type secret. The secret content is available to the container processes as /var/run/secrets/kubernetes.io/serviceaccount/ca.crt and by default is auto-mounted. In Kubernetes 1.6+ it can be opted out of auto-mounting by setting automountServiceAccountToken in the service account manifest.

The system account token can be used to configure a kubectl context that allows interaction with the API server under the identity of the System Account. For that, the token and the CA certificate stored in the Secret associated with the Service Account must be configured in a kubectl context as shown in the example below. Note that the context of the token must be base64-decoded with:

 
kubectl get secret some-sa-token-hqmmc -o=jsonpath='{.data.token}' | base64 -d

The CA certificate does not require decoding.

 
apiVersion: v1
kind: Config
users:
  - name: some-sa-on-some-cluster
    user:
      token: <base64-decoded_content_of_the_service_account_secret_token>
clusters:
  - name: some-cluster
    cluster:
      server: https://...example.com:443
      certificate-authority-data: <the_content_of_the_service_account_secret_ca_certficate_as_is>
contexts:
  - name: some-context
    context:
      cluster: some-cluster
      namespace: some-namespace
      user: some-sa-on-some-cluster

⚠️ The service account token is a long-lived, static credential. If it is compromised, lost, or stolen, an attacker may be able to perform all the actions associated with that token until the service account is deleted, so use them sparingly

Clarify the following:

  • The default namespace to be used for namespaced API operations is placed on the filesystem of each container of the pod at /var/run/secrets/kubernetes.io/serviceaccount/namespace.
  • What are the default credentials associated with the default service account.
  • How can this be association displayed.
  • What happens with a newly created service account - does it need to be explicitly associated with those credentials or the association is done automatically upon creation.

Service Account Full Name

Service accounts can be referred to using their full name system:serviceaccount:<namespace>:<account-name> (e.g. system:serviceaccount:blue:default).

Default Service Account

Each namespace comes with a default service account:

apiVersion: v1
kind: ServiceAccount
metadata:
  name: default
  namespace: default
secrets:
- name: default-token-dddkl

A pod whose service account was not explicitly configured will run with the default service account for its namespace, its configuration is equivalent with:

apiVersion: v1
kind: Pod
spec:
  containers:
  - name: [...]
    [...]
  serviceAccountName: default
[...]

The a specific service account can be configured as such:

apiVersion: v1
kind: Pod
spec:
  containers:
  - name: [...]
    [...]
  serviceAccountName: something
[...]

Non-Default Service Accounts

To use a non-default service account, set spec.serviceAccountName field of the pod manifest. The service account has to exist at the time the pod is created, or it will be rejected. If the pod was already created, the service account cannot be updated.

Service Accounts and Roles

The recommended way to ensure that an application operates within a specific security scope is to bind a role or a set of roles to an application-specific service account. For more details, see:

Role Based Access Control Concepts

Service Account Operations

Anonymous Request

https://kubernetes.io/docs/reference/access-authn-authz/authentication/#anonymous-requests

When the API server handles a request, it first attempts to authenticate the identity making the request with one of the available authentication methods. If all authentication methods fail, and if anonymous request support is enabled, the identity is treated as anonymous requests, and given a username of system:anonymous and a group of system:unauthenticated.

API Authentication Strategies

https://kubernetes.io/docs/reference/access-authn-authz/authentication/#authentication-strategies

Kubernetes provides various authentication strategies to be used by the clients that send API requests into the Kubernetes API server. These authentication strategies are implemented by the server's authentication plugins.

Client X.509 Certificates

https://kubernetes.io/docs/reference/access-authn-authz/authentication/#x509-client-certs

Bearer Tokens

kubectl allows specifying a bearer token in-line with --token:

kubectl --token aHR0c...NiYg get pods

Webhook Token Authentication

https://kubernetes.io/docs/reference/access-authn-authz/authentication/#webhook-token-authentication
EKS Webhook Token Authentication

EKS has native support for webhook token authentication. See:

EKS Webhook Token Authentication

Service Account Tokens

https://kubernetes.io/docs/reference/access-authn-authz/authentication/#service-account-tokens

TODO: reconcile Service Account Tokens and service-account-token secrets.

Static Token File

https://kubernetes.io/docs/reference/access-authn-authz/authentication/#static-token-file

Bootstrap Tokens

https://kubernetes.io/docs/reference/access-authn-authz/authentication/#bootstrap-tokens

Authenticating Proxy

https://kubernetes.io/docs/reference/access-authn-authz/authentication/#authenticating-proxy

HTTP Basic Auth

OpenID Connect Tokens

https://kubernetes.io/docs/reference/access-authn-authz/authentication/#openid-connect-tokens

Controlling Access to the Kubernetes API

https://kubernetes.io/docs/reference/access-authn-authz/controlling-access/

Role Based Access Control (RBAC)

Kubernetes Role Based Access Control (RBAC) Concepts

Pod and Container Security

For more details on pod and container security concepts, including pod and container security contexts and pod security policies, see:

Pod and Container Security

Transport Security

https://kubernetes.io/docs/tasks/administer-cluster/securing-a-cluster/#use-transport-layer-security-tls-for-all-api-traffic
https://kubernetes.io/docs/reference/access-authn-authz/#transport-security

Kubernetes expects that all API communication in the cluster is encrypted by default with TLS, and the majority of installation methods will allow the necessary certificates to be created and distributed to the cluster components.

Certificates Required by a Kubernetes Cluster

https://kubernetes.io/docs/setup/best-practices/certificates/