diff --git a/docs/accessing-the-cluster.md b/docs/accessing-the-cluster.md index 58ca2271d52..3497b5d5f1f 100644 --- a/docs/accessing-the-cluster.md +++ b/docs/accessing-the-cluster.md @@ -102,10 +102,10 @@ the `kubernetes` DNS name, which resolves to a Service IP which in turn will be routed to an apiserver. The recommended way to authenticate to the apiserver is with a -[service account](../docs/service_accounts.md). By default, a pod +[service account](service_accounts.md) credential. By default, a pod is associated with a service account, and a credential (token) for that service account is placed into the filesystem tree of each container in that pod, -at `/var/run/secrets/kubernetes.io/serviceaccount`. +at `/var/run/secrets/kubernetes.io/serviceaccount/token`. From within a pod the recommended ways to connect to API are: - run a kubectl proxy as one of the containers in the pod, or as a background @@ -115,6 +115,7 @@ From within a pod the recommended ways to connect to API are: in a pod](../examples/kubectl-container/). - use the Go client library, and create a client using the `client.NewInContainer()` factory. This handles locating and authenticating to the apiserver. +In each case, the credentials of the pod are used to communicate securely with the apiserver. ## Accessing services running on the cluster diff --git a/docs/images.md b/docs/images.md index aeefb1fc0e8..c1f7e9df03c 100644 --- a/docs/images.md +++ b/docs/images.md @@ -68,7 +68,7 @@ This can be used to preload certain images for speed or as an alternative to aut All pods will have read access to any pre-pulled images. -### Specifying ImagePullKeys on a Pod +### Specifying ImagePullSecrets on a Pod Kubernetes supports specifying registry keys on a pod. First, create a `.dockercfg`, such as running `docker login `. diff --git a/docs/secrets.md b/docs/secrets.md index 6492b1b0a6f..d645e065adf 100644 --- a/docs/secrets.md +++ b/docs/secrets.md @@ -5,26 +5,45 @@ passwords, OAuth tokens, and ssh keys. Putting this information in a `secret` is safer and more flexible than putting it verbatim in a `pod` definition or in a docker image. -### Creating and Using Secrets -To make use of secrets requires at least two steps: - 1. create a `secret` resource with secret data - 1. create a pod that has a volume of type `secret` and a container - which mounts that volume. +## Overview of Secrets -This is an example of a simple secret, in json format: -```json -{ - "apiVersion": "v1", - "kind": "Secret", - "metadata" : { - "name": "mysecret", - "namespace": "myns" - }, - "data": { - "username": "dmFsdWUtMQ0K", - "password": "dmFsdWUtMg0K" - } -} + +Creation of secrets can be manual (done by the user) or automatic (done by +automation built into the cluster). + +A secret can be used with a pod in two ways: either as files in a volume mounted on one or more of +its containers, or used by kubelet when pulling images for the pod. + +To use a secret, a pod needs to reference the secret. This reference +can likewise be added manually or automatically. + +A single Pod may use various combination of the above options. + +### Service Accounts Automatically Create and Use Secrets with API Credentials + +Kubernetes automatically creates secrets which contain credentials for +accessing the API and it automatically modifies your pods to use this type of +secret. + +The automatic creation and use of API credentials can be disabled or overridden +if desired. However, if all you need to do is securely access the apiserver, +this is the recommended workflow. + +See the [Service Account](service_accounts.md) documentation for more +information on how Service Accounts work. + +### Creating a Secret Manually + +This is an example of a simple secret, in yaml format: +```yaml +apiVersion: v1 +kind: Secret +metadata: + name: mysecret +type: Opaque +data: + password: dmFsdWUtMg0K + username: dmFsdWUtMQ0K ``` The data field is a map. Its keys must match @@ -33,7 +52,15 @@ allowed. The values are arbitrary data, encoded using base64. The values of username and password in the example above, before base64 encoding, are `value-1` and `value-2`, respectively, with carriage return and newline characters at the end. -This is an example of a pod that uses a secret, in json format: +Create the secret using [`kubectl create`](kubectl-create.md). + +Once the secret is created, you can: + - create pods that automatically use it via a [Service Account](service_accounts.md). + - modify your pod specification to use the secret + +### Manually specifying a Secret to be Mounted on a Pod + +This is an example of a pod that mounts a secret in a volume: ```json { "apiVersion": "v1", @@ -62,6 +89,29 @@ This is an example of a pod that uses a secret, in json format: } ``` +Each secret you want to use needs its own `spec.volumes`. + +If there are multiple containers in the pod, then each container needs its +own `volumeMounts` block, but only one `spec.volumes` is needed per secret. + +You can package many files into one secret, or use many secrets, +whichever is convenient. + +### Manually specifying an imagePullSecret +Use of imagePullSecrets is desribed in the [images documentation]( +images.md#specifying-imagepullsecrets-on-a-pod) +### Automatic use of Manually Created Secrets + +*This feature is planned but not implemented. See [issue +9902](https://github.com/GoogleCloudPlatform/kubernetes/issues/9902).* + +You can reference manually created secrets from a [service account]( +service_accounts.md). +Then, pods which use that service account will have +`volumeMounts` and/or `imagePullSecrets` added to them. +The secrets will be mounted at **TBD**. + +## Details ### Restrictions Secret volume sources are validated to ensure that the specified object reference actually points to an object of type `Secret`. Therefore, a secret @@ -106,7 +156,7 @@ versions of Kubernetes are expected to provide more automation for populating environment variables from files. -## Secret and Pod Lifetime interaction +### Secret and Pod Lifetime interaction When a pod is created via the API, there is no check whether a referenced secret exists. Once a pod is scheduled, the kubelet will try to fetch the @@ -327,6 +377,30 @@ Both containers will have the following files present on their filesystems: Note how the specs for the two pods differ only in one field; this facilitates creating pods with different capabilities from a common pod config template. +You could further simplify the base pod specification by using two service accounts: +one called, say, `prod-user` with the `prod-db-secret`, and one called, say, +`test-user` with the `test-db-secret`. Then, the pod spec can be shortened to, for example: +```json +{ +"kind": "Pod", +"apiVersion": "v1", +"metadata": { + "name": "prod-db-client-pod", + "labels": { + "name": "prod-db-client" + } +}, +"spec": { + "serviceAccount": "prod-db-client", + "containers": [ + { + "name": "db-client-container", + "image": "myClientImage", + } + ] +} +``` + ### Use-case: Secret visible to one container in a pod @@ -344,6 +418,8 @@ With this partitioned approach, an attacker now has to trick the application server into doing something rather arbitrary, which may be harder than getting it to read a file. + + ## Security Properties ### Protections diff --git a/docs/service_accounts.md b/docs/service_accounts.md index 335a2ea2839..bf8555d3c4c 100644 --- a/docs/service_accounts.md +++ b/docs/service_accounts.md @@ -1,14 +1,93 @@ # Service Accounts -A serviceAccount provides an identity for processes that run in a Pod. -The behavior of the the serviceAccount object is implemented via a plugin -called an [Admission Controller]( admission_controllers.md). When this plugin is active -(and it is by default on most distributions), then it does the following when a pod is created or modified: - 1. If the pod does not have a ```ServiceAccount```, it modifies the pod's ```ServiceAccount``` to "default". - 2. It ensures that the ```ServiceAccount``` referenced by a pod exists. - 3. If ```LimitSecretReferences``` is true, it rejects the pod if the pod references ```Secret``` objects which the pods -```ServiceAccount``` does not reference. - 4. If the pod does not contain any ```ImagePullSecrets```, the ```ImagePullSecrets``` of the -```ServiceAccount``` are added to the pod. - 5. If ```MountServiceAccountToken``` is true, it adds a ```VolumeMount``` with the pod's ```ServiceAccount``` API token secret to containers in the pod. + +A service account provides an identity for processes that run in a Pod. + +*This is a user introduction to Service Accounts. See also the +[Cluster Admin Guide to Service Accounts](service_accounts_admin.md).* + +*Note: This document descibes how service accounts behave in a cluster set up +as recommended by the Kubernetes project. Your cluster administrator may have +customized the behavior in your cluster, in which case this documentation may +not apply.* + +When you (a human) access the cluster (e.g. using kubectl), you are +authenticated by the apiserver as a particular User Account (currently this is +usually "admin", unless your cluster administrator has customized your +cluster). Processes in containers inside pods can also contact the apiserver. +When they do, they are authenticated as a particular Service Account (e.g. +"default"). + +## Using the Default Service Account to access the API server. + +When you create a pod, you do not need to specify a service account. It is +automatically assigned the `default` service account of the same namespace. If +you get the raw json or yaml for a pod you have created (e.g. `kubectl get +pods/podname -o yaml`), you can see the `spec.serviceAccount` field has been +[automatically set](working_with_resources.md#resources-are-automatically-modified). + +You can access the API using a proxy or with a client library, as described in +[Accessing the Cluster](accessing-the-cluster.md#accessing-the-api-from-a-pod). + +## Using Multiple Service Accounts + +Every namespace has a default service account resource called "default". +You can list this and any other serviceAccount resources in the namespace with this command: +``` +kubectl get serviceAccounts +$ NAME SECRETS +default 1 +``` + +You can create additional serviceAccounts like this: +``` +$ cat > serviceaccount.yaml < + +## Adding Secrets to a service account. +TODO: Test and explain how to use additional non-K8s secrets with an existing service account. + +TODO explain: + - The token goes to: "/var/run/secrets/kubernetes.io/serviceaccount/$WHATFILENAME" + [![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/docs/service_accounts.md?pixel)]() diff --git a/docs/service_accounts_admin.md b/docs/service_accounts_admin.md new file mode 100644 index 00000000000..f371e2e90af --- /dev/null +++ b/docs/service_accounts_admin.md @@ -0,0 +1,84 @@ +# Cluster Admin Guide to Service Accounts + +*This is a Cluster Administrator guide to service accounts. It assumes knowledge of +the [User Guide to Service Accounts](service_accounts.md).* + +*Support for authorization and user accounts is planned but incomplete. Sometimes +incomplete features are referred to in order to better describe service accounts.* + +## User accounts vs service accounts + +Kubernetes distinguished between the concept of a user account and a service accounts +for a number of reasons: + - User accounts are for humans. Service accounts are for processes, which + run in pods. + - User accounts are intended to be global. Names must be unique across all + namespaces of a cluster, future user resource will not be namespaced). + Service accounts are namespaced. + - Typically, a clusters User accounts might be synced from a corporate + database, where new user account creation requires special privileges and + is tied to complex business processes. Service account creation is intended + to be more lightweight, allowing cluster users to create service accounts for + specific tasks (i.e. principle of least privilege). + - Auditing considerations for humans and service accounts may differ. + - A config bundle for a complex system may include definition of various service + accounts for components of that system. Because service accounts can be created + ad-hoc and have namespaced names, such config is portable. + +## Service account automation + +Three separate components cooperate to implement the automation around service accounts: + - A Service account admission controller + - A Token controller + - A Service account controller + +### Service Account Admission Controller + +The modification of pods is implemented via a plugin +called an [Admission Controller](admission_controllers.md). It is part of the apiserver. +It acts synchronously to modify pods as they are created or updated. When this plugin is active +(and it is by default on most distributions), then it does the following when a pod is created or modified: + 1. If the pod does not have a `ServiceAccount` set, it sets the `ServiceAccount` to `default`. + 2. It ensures that the `ServiceAccount` referenced by the pod exists, and otherwise rejects it. + 4. If the pod does not contain any `ImagePullSecrets`, then `ImagePullSecrets` of the +`ServiceAccount` are added to the pod. + 5. It adds a `volume` to the pod which contains a token for API access. + 6. It adds a `volumeSource` to each container of the pod mounted at `/var/run/secrets/kubernetes.io/serviceaccount`. + +### Token Controller +TokenController runs as part of controller-manager. It acts asynchronously. It: +- observes serviceAccount creation and creates a corresponding Secret to allow API access. +- observes serviceAccount deletion and deletes all corresponding ServiceAccountToken Secrets +- observes secret addition, and ensures the referenced ServiceAccount exists, and adds a token to the secret if needed +- observer secret deleteion and removes a reference from the corresponding ServiceAccount if needed + +#### To create additional API tokens + +A controller loop ensures a secret with an API token exists for each service +account. To create additional API tokens for a service account, create a secret +of type `ServiceAccountToken` with an annotation referencing the service +account, and the controller will update it with a generated token: + +``` +secret.json: +{ + "kind": "Secret", + "metadata": { + "name": "mysecretname", + "annotations": { + "kubernetes.io/service-account.name": "myserviceaccount" + } + } + "type": "kubernetes.io/service-account-token" +} + +$ kubectl create -f secret.json +$ kubectl describe secret mysecretname +``` + +#### To delete/invalidate a service account token: +``` +kubectl delete secret mysecretname +``` + +[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/docs/service_accounts_admin.md?pixel)]()