From f09e80a4f97016b22b01a379c3894123ee408c3e Mon Sep 17 00:00:00 2001 From: Shannon Kularathna Date: Fri, 7 Jul 2023 19:32:14 +0000 Subject: [PATCH 1/5] Move use cases higher on the page --- .../en/docs/concepts/configuration/secret.md | 1097 +++++++++-------- 1 file changed, 549 insertions(+), 548 deletions(-) diff --git a/content/en/docs/concepts/configuration/secret.md b/content/en/docs/concepts/configuration/secret.md index cf76ed3f3f37d..b24c02ac79ae3 100644 --- a/content/en/docs/concepts/configuration/secret.md +++ b/content/en/docs/concepts/configuration/secret.md @@ -67,433 +67,297 @@ The Kubernetes control plane also uses Secrets; for example, [bootstrap token Secrets](#bootstrap-token-secrets) are a mechanism to help automate node registration. -### Alternatives to Secrets - -Rather than using a Secret to protect confidential data, you can pick from alternatives. - -Here are some of your options: - -- If your cloud-native component needs to authenticate to another application that you - know is running within the same Kubernetes cluster, you can use a - [ServiceAccount](/docs/reference/access-authn-authz/authentication/#service-account-tokens) - and its tokens to identify your client. -- There are third-party tools that you can run, either within or outside your cluster, - that provide secrets management. For example, a service that Pods access over HTTPS, - that reveals a secret if the client correctly authenticates (for example, with a ServiceAccount - token). -- For authentication, you can implement a custom signer for X.509 certificates, and use - [CertificateSigningRequests](/docs/reference/access-authn-authz/certificate-signing-requests/) - to let that custom signer issue certificates to Pods that need them. -- You can use a [device plugin](/docs/concepts/extend-kubernetes/compute-storage-net/device-plugins/) - to expose node-local encryption hardware to a specific Pod. For example, you can schedule - trusted Pods onto nodes that provide a Trusted Platform Module, configured out-of-band. - -You can also combine two or more of those options, including the option to use Secret objects themselves. - -For example: implement (or deploy) an {{< glossary_tooltip text="operator" term_id="operator-pattern" >}} -that fetches short-lived session tokens from an external service, and then creates Secrets based -on those short-lived session tokens. Pods running in your cluster can make use of the session tokens, -and operator ensures they are valid. This separation means that you can run Pods that are unaware of -the exact mechanisms for issuing and refreshing those session tokens. - -## Types of Secret {#secret-types} - -When creating a Secret, you can specify its type using the `type` field of -the [Secret](/docs/reference/kubernetes-api/config-and-storage-resources/secret-v1/) -resource, or certain equivalent `kubectl` command line flags (if available). -The Secret type is used to facilitate programmatic handling of the Secret data. - -Kubernetes provides several built-in types for some common usage scenarios. -These types vary in terms of the validations performed and the constraints -Kubernetes imposes on them. - -| Built-in Type | Usage | -| ------------------------------------- | --------------------------------------- | -| `Opaque` | arbitrary user-defined data | -| `kubernetes.io/service-account-token` | ServiceAccount token | -| `kubernetes.io/dockercfg` | serialized `~/.dockercfg` file | -| `kubernetes.io/dockerconfigjson` | serialized `~/.docker/config.json` file | -| `kubernetes.io/basic-auth` | credentials for basic authentication | -| `kubernetes.io/ssh-auth` | credentials for SSH authentication | -| `kubernetes.io/tls` | data for a TLS client or server | -| `bootstrap.kubernetes.io/token` | bootstrap token data | - -You can define and use your own Secret type by assigning a non-empty string as the -`type` value for a Secret object (an empty string is treated as an `Opaque` type). +## Use cases -Kubernetes doesn't impose any constraints on the type name. However, if you -are using one of the built-in types, you must meet all the requirements defined -for that type. +### Use case: As container environment variables {#use-case-as-container-environment-variables} -If you are defining a type of secret that's for public use, follow the convention -and structure the secret type to have your domain name before the name, separated -by a `/`. For example: `cloud-hosting.example.net/cloud-api-credentials`. +You can create a Secret and use it to +[set environment variables for a container](/docs/tasks/inject-data-application/distribute-credentials-secure/#define-container-environment-variables-using-secret-data). -### Opaque secrets +### Use case: Pod with SSH keys -`Opaque` is the default Secret type if omitted from a Secret configuration file. -When you create a Secret using `kubectl`, you will use the `generic` -subcommand to indicate an `Opaque` Secret type. For example, the following -command creates an empty Secret of type `Opaque`. +Create a Secret containing some SSH keys: ```shell -kubectl create secret generic empty-secret -kubectl get secret empty-secret +kubectl create secret generic ssh-key-secret --from-file=ssh-privatekey=/path/to/.ssh/id_rsa --from-file=ssh-publickey=/path/to/.ssh/id_rsa.pub ``` -The output looks like: +The output is similar to: ``` -NAME TYPE DATA AGE -empty-secret Opaque 0 2m6s +secret "ssh-key-secret" created ``` -The `DATA` column shows the number of data items stored in the Secret. -In this case, `0` means you have created an empty Secret. - -### Service account token Secrets - -A `kubernetes.io/service-account-token` type of Secret is used to store a -token credential that identifies a -{{< glossary_tooltip text="service account" term_id="service-account" >}}. - -{{< note >}} -Versions of Kubernetes before v1.22 automatically created credentials for -accessing the Kubernetes API. This older mechanism was based on creating token -Secrets that could then be mounted into running Pods. -In more recent versions, including Kubernetes v{{< skew currentVersion >}}, API -credentials are obtained directly by using the -[TokenRequest](/docs/reference/kubernetes-api/authentication-resources/token-request-v1/) -API, and are mounted into Pods using a -[projected volume](/docs/reference/access-authn-authz/service-accounts-admin/#bound-service-account-token-volume). -The tokens obtained using this method have bounded lifetimes, and are -automatically invalidated when the Pod they are mounted into is deleted. - -You can still -[manually create](/docs/tasks/configure-pod-container/configure-service-account/#manually-create-a-service-account-api-token) -a service account token Secret; for example, if you need a token that never -expires. However, using the -[TokenRequest](/docs/reference/kubernetes-api/authentication-resources/token-request-v1/) -subresource to obtain a token to access the API is recommended instead. -You can use the -[`kubectl create token`](/docs/reference/generated/kubectl/kubectl-commands#-em-token-em-) -command to obtain a token from the `TokenRequest` API. -{{< /note >}} - -You should only create a service account token Secret object -if you can't use the `TokenRequest` API to obtain a token, -and the security exposure of persisting a non-expiring token credential -in a readable API object is acceptable to you. +You can also create a `kustomization.yaml` with a `secretGenerator` field containing ssh keys. -When using this Secret type, you need to ensure that the -`kubernetes.io/service-account.name` annotation is set to an existing -service account name. If you are creating both the ServiceAccount and -the Secret objects, you should create the ServiceAccount object first. +{{< caution >}} +Think carefully before sending your own SSH keys: other users of the cluster may have access +to the Secret. -After the Secret is created, a Kubernetes {{< glossary_tooltip text="controller" term_id="controller" >}} -fills in some other fields such as the `kubernetes.io/service-account.uid` annotation, and the -`token` key in the `data` field, which is populated with an authentication token. +You could instead create an SSH private key representing a service identity that you want to be +accessible to all the users with whom you share the Kubernetes cluster, and that you can revoke +if the credentials are compromised. +{{< /caution >}} -The following example configuration declares a service account token Secret: +Now you can create a Pod which references the secret with the SSH key and +consumes it in a volume: ```yaml apiVersion: v1 -kind: Secret +kind: Pod metadata: - name: secret-sa-sample - annotations: - kubernetes.io/service-account.name: "sa-name" -type: kubernetes.io/service-account-token -data: - # You can include additional key value pairs as you do with Opaque Secrets - extra: YmFyCg== + name: secret-test-pod + labels: + name: secret-test +spec: + volumes: + - name: secret-volume + secret: + secretName: ssh-key-secret + containers: + - name: ssh-test-container + image: mySshImage + volumeMounts: + - name: secret-volume + readOnly: true + mountPath: "/etc/secret-volume" ``` -After creating the Secret, wait for Kubernetes to populate the `token` key in the `data` field. - -See the [ServiceAccount](/docs/tasks/configure-pod-container/configure-service-account/) -documentation for more information on how service accounts work. -You can also check the `automountServiceAccountToken` field and the -`serviceAccountName` field of the -[`Pod`](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#pod-v1-core) -for information on referencing service account credentials from within Pods. - -### Docker config Secrets +When the container's command runs, the pieces of the key will be available in: -You can use one of the following `type` values to create a Secret to -store the credentials for accessing a container image registry: +``` +/etc/secret-volume/ssh-publickey +/etc/secret-volume/ssh-privatekey +``` -- `kubernetes.io/dockercfg` -- `kubernetes.io/dockerconfigjson` +The container is then free to use the secret data to establish an SSH connection. -The `kubernetes.io/dockercfg` type is reserved to store a serialized -`~/.dockercfg` which is the legacy format for configuring Docker command line. -When using this Secret type, you have to ensure the Secret `data` field -contains a `.dockercfg` key whose value is content of a `~/.dockercfg` file -encoded in the base64 format. +### Use case: Pods with prod / test credentials -The `kubernetes.io/dockerconfigjson` type is designed for storing a serialized -JSON that follows the same format rules as the `~/.docker/config.json` file -which is a new format for `~/.dockercfg`. -When using this Secret type, the `data` field of the Secret object must -contain a `.dockerconfigjson` key, in which the content for the -`~/.docker/config.json` file is provided as a base64 encoded string. +This example illustrates a Pod which consumes a secret containing production credentials and +another Pod which consumes a secret with test environment credentials. -Below is an example for a `kubernetes.io/dockercfg` type of Secret: +You can create a `kustomization.yaml` with a `secretGenerator` field or run +`kubectl create secret`. -```yaml -apiVersion: v1 -kind: Secret -metadata: - name: secret-dockercfg -type: kubernetes.io/dockercfg -data: - .dockercfg: | - "" +```shell +kubectl create secret generic prod-db-secret --from-literal=username=produser --from-literal=password=Y4nys7f11 ``` -{{< note >}} -If you do not want to perform the base64 encoding, you can choose to use the -`stringData` field instead. -{{< /note >}} - -When you create these types of Secrets using a manifest, the API -server checks whether the expected key exists in the `data` field, and -it verifies if the value provided can be parsed as a valid JSON. The API -server doesn't validate if the JSON actually is a Docker config file. - -When you do not have a Docker config file, or you want to use `kubectl` -to create a Secret for accessing a container registry, you can do: +The output is similar to: -```shell -kubectl create secret docker-registry secret-tiger-docker \ - --docker-email=tiger@acme.example \ - --docker-username=tiger \ - --docker-password=pass1234 \ - --docker-server=my-registry.example:5000 +``` +secret "prod-db-secret" created ``` -That command creates a Secret of type `kubernetes.io/dockerconfigjson`. -If you dump the `.data.dockerconfigjson` field from that new Secret and then -decode it from base64: +You can also create a secret for test environment credentials. ```shell -kubectl get secret secret-tiger-docker -o jsonpath='{.data.*}' | base64 -d +kubectl create secret generic test-db-secret --from-literal=username=testuser --from-literal=password=iluvtests ``` -then the output is equivalent to this JSON document (which is also a valid -Docker configuration file): +The output is similar to: -```json -{ - "auths": { - "my-registry.example:5000": { - "username": "tiger", - "password": "pass1234", - "email": "tiger@acme.example", - "auth": "dGlnZXI6cGFzczEyMzQ=" - } - } -} +``` +secret "test-db-secret" created ``` {{< note >}} -The `auth` value there is base64 encoded; it is obscured but not secret. -Anyone who can read that Secret can learn the registry access bearer token. -{{< /note >}} +Special characters such as `$`, `\`, `*`, `=`, and `!` will be interpreted by your +[shell](https://en.wikipedia.org/wiki/Shell_(computing)) and require escaping. -### Basic authentication Secret +In most shells, the easiest way to escape the password is to surround it with single quotes (`'`). +For example, if your actual password is `S!B\*d$zDsb=`, you should execute the command this way: -The `kubernetes.io/basic-auth` type is provided for storing credentials needed -for basic authentication. When using this Secret type, the `data` field of the -Secret must contain one of the following two keys: +```shell +kubectl create secret generic dev-db-secret --from-literal=username=devuser --from-literal=password='S!B\*d$zDsb=' +``` -- `username`: the user name for authentication -- `password`: the password or token for authentication +You do not need to escape special characters in passwords from files (`--from-file`). +{{< /note >}} -Both values for the above two keys are base64 encoded strings. You can, of -course, provide the clear text content using the `stringData` for Secret -creation. - -The following manifest is an example of a basic authentication Secret: +Now make the Pods: -```yaml +```shell +cat < pod.yaml apiVersion: v1 -kind: Secret -metadata: - name: secret-basic-auth -type: kubernetes.io/basic-auth -stringData: - username: admin # required field for kubernetes.io/basic-auth - password: t0p-Secret # required field for kubernetes.io/basic-auth +kind: List +items: +- kind: Pod + apiVersion: v1 + metadata: + name: prod-db-client-pod + labels: + name: prod-db-client + spec: + volumes: + - name: secret-volume + secret: + secretName: prod-db-secret + containers: + - name: db-client-container + image: myClientImage + volumeMounts: + - name: secret-volume + readOnly: true + mountPath: "/etc/secret-volume" +- kind: Pod + apiVersion: v1 + metadata: + name: test-db-client-pod + labels: + name: test-db-client + spec: + volumes: + - name: secret-volume + secret: + secretName: test-db-secret + containers: + - name: db-client-container + image: myClientImage + volumeMounts: + - name: secret-volume + readOnly: true + mountPath: "/etc/secret-volume" +EOF ``` -The basic authentication Secret type is provided only for convenience. -You can create an `Opaque` type for credentials used for basic authentication. -However, using the defined and public Secret type (`kubernetes.io/basic-auth`) helps other -people to understand the purpose of your Secret, and sets a convention for what key names -to expect. -The Kubernetes API verifies that the required keys are set for a Secret of this type. - -### SSH authentication secrets +Add the pods to the same `kustomization.yaml`: -The builtin type `kubernetes.io/ssh-auth` is provided for storing data used in -SSH authentication. When using this Secret type, you will have to specify a -`ssh-privatekey` key-value pair in the `data` (or `stringData`) field -as the SSH credential to use. +```shell +cat <> kustomization.yaml +resources: +- pod.yaml +EOF +``` -The following manifest is an example of a Secret used for SSH public/private -key authentication: +Apply all those objects on the API server by running: -```yaml -apiVersion: v1 -kind: Secret -metadata: - name: secret-ssh-auth -type: kubernetes.io/ssh-auth -data: - # the data is abbreviated in this example - ssh-privatekey: | - MIIEpQIBAAKCAQEAulqb/Y ... +```shell +kubectl apply -k . ``` -The SSH authentication Secret type is provided only for user's convenience. -You could instead create an `Opaque` type Secret for credentials used for SSH authentication. -However, using the defined and public Secret type (`kubernetes.io/ssh-auth`) helps other -people to understand the purpose of your Secret, and sets a convention for what key names -to expect. -and the API server does verify if the required keys are provided in a Secret configuration. +Both containers will have the following files present on their filesystems with the values +for each container's environment: -{{< caution >}} -SSH private keys do not establish trusted communication between an SSH client and -host server on their own. A secondary means of establishing trust is needed to -mitigate "man in the middle" attacks, such as a `known_hosts` file added to a ConfigMap. -{{< /caution >}} +``` +/etc/secret-volume/username +/etc/secret-volume/password +``` -### TLS secrets +Note how the specs for the two Pods differ only in one field; this facilitates +creating Pods with different capabilities from a common Pod template. -Kubernetes provides a builtin Secret type `kubernetes.io/tls` for storing -a certificate and its associated key that are typically used for TLS. +You could further simplify the base Pod specification by using two service accounts: -One common use for TLS secrets is to configure encryption in transit for -an [Ingress](/docs/concepts/services-networking/ingress/), but you can also use it -with other resources or directly in your workload. -When using this type of Secret, the `tls.key` and the `tls.crt` key must be provided -in the `data` (or `stringData`) field of the Secret configuration, although the API -server doesn't actually validate the values for each key. +1. `prod-user` with the `prod-db-secret` +1. `test-user` with the `test-db-secret` -The following YAML contains an example config for a TLS Secret: +The Pod specification is shortened to: ```yaml apiVersion: v1 -kind: Secret +kind: Pod metadata: - name: secret-tls -type: kubernetes.io/tls -data: - # the data is abbreviated in this example - tls.crt: | - MIIC2DCCAcCgAwIBAgIBATANBgkqh ... - tls.key: | - MIIEpgIBAAKCAQEA7yn3bRHQ5FHMQ ... + name: prod-db-client-pod + labels: + name: prod-db-client +spec: + serviceAccount: prod-db-client + containers: + - name: db-client-container + image: myClientImage ``` -The TLS Secret type is provided for user's convenience. You can create an `Opaque` -for credentials used for TLS server and/or client. However, using the builtin Secret -type helps ensure the consistency of Secret format in your project; the API server -does verify if the required keys are provided in a Secret configuration. +### Use case: dotfiles in a secret volume -When creating a TLS Secret using `kubectl`, you can use the `tls` subcommand -as shown in the following example: +You can make your data "hidden" by defining a key that begins with a dot. +This key represents a dotfile or "hidden" file. For example, when the following secret +is mounted into a volume, `secret-volume`: -```shell -kubectl create secret tls my-tls-secret \ - --cert=path/to/cert/file \ - --key=path/to/key/file +```yaml +apiVersion: v1 +kind: Secret +metadata: + name: dotfile-secret +data: + .secret-file: dmFsdWUtMg0KDQo= +--- +apiVersion: v1 +kind: Pod +metadata: + name: secret-dotfiles-pod +spec: + volumes: + - name: secret-volume + secret: + secretName: dotfile-secret + containers: + - name: dotfile-test-container + image: registry.k8s.io/busybox + command: + - ls + - "-l" + - "/etc/secret-volume" + volumeMounts: + - name: secret-volume + readOnly: true + mountPath: "/etc/secret-volume" ``` -The public/private key pair must exist before hand. The public key certificate -for `--cert` must be DER format as per -[Section 5.1 of RFC 7468](https://datatracker.ietf.org/doc/html/rfc7468#section-5.1), -and must match the given private key for `--key` (PKCS #8 in DER format; -[Section 11 of RFC 7468](https://datatracker.ietf.org/doc/html/rfc7468#section-11)). +The volume will contain a single file, called `.secret-file`, and +the `dotfile-test-container` will have this file present at the path +`/etc/secret-volume/.secret-file`. {{< note >}} -A kubernetes.io/tls Secret stores the Base64-encoded DER data for keys and -certificates. If you're familiar with PEM format for private keys and for certificates, -the base64 data are the same as that format except that you omit -the initial and the last lines that are used in PEM. - -For example, for a certificate, you do **not** include `--------BEGIN CERTIFICATE-----` -and `-------END CERTIFICATE----`. +Files beginning with dot characters are hidden from the output of `ls -l`; +you must use `ls -la` to see them when listing directory contents. {{< /note >}} -### Bootstrap token Secrets - -A bootstrap token Secret can be created by explicitly specifying the Secret -`type` to `bootstrap.kubernetes.io/token`. This type of Secret is designed for -tokens used during the node bootstrap process. It stores tokens used to sign -well-known ConfigMaps. +### Use case: Secret visible to one container in a Pod -A bootstrap token Secret is usually created in the `kube-system` namespace and -named in the form `bootstrap-token-` where `` is a 6 character -string of the token ID. +Consider a program that needs to handle HTTP requests, do some complex business +logic, and then sign some messages with an HMAC. Because it has complex +application logic, there might be an unnoticed remote file reading exploit in +the server, which could expose the private key to an attacker. -As a Kubernetes manifest, a bootstrap token Secret might look like the -following: +This could be divided into two processes in two containers: a frontend container +which handles user interaction and business logic, but which cannot see the +private key; and a signer container that can see the private key, and responds +to simple signing requests from the frontend (for example, over localhost networking). -```yaml -apiVersion: v1 -kind: Secret -metadata: - name: bootstrap-token-5emitj - namespace: kube-system -type: bootstrap.kubernetes.io/token -data: - auth-extra-groups: c3lzdGVtOmJvb3RzdHJhcHBlcnM6a3ViZWFkbTpkZWZhdWx0LW5vZGUtdG9rZW4= - expiration: MjAyMC0wOS0xM1QwNDozOToxMFo= - token-id: NWVtaXRq - token-secret: a3E0Z2lodnN6emduMXAwcg== - usage-bootstrap-authentication: dHJ1ZQ== - usage-bootstrap-signing: dHJ1ZQ== -``` +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. -A bootstrap type Secret has the following keys specified under `data`: +### Alternatives to Secrets -- `token-id`: A random 6 character string as the token identifier. Required. -- `token-secret`: A random 16 character string as the actual token secret. Required. -- `description`: A human-readable string that describes what the token is - used for. Optional. -- `expiration`: An absolute UTC time using [RFC3339](https://datatracker.ietf.org/doc/html/rfc3339) specifying when the token - should be expired. Optional. -- `usage-bootstrap-`: A boolean flag indicating additional usage for - the bootstrap token. -- `auth-extra-groups`: A comma-separated list of group names that will be - authenticated as in addition to the `system:bootstrappers` group. +Rather than using a Secret to protect confidential data, you can pick from alternatives. -The above YAML may look confusing because the values are all in base64 encoded -strings. In fact, you can create an identical Secret using the following YAML: +Here are some of your options: -```yaml -apiVersion: v1 -kind: Secret -metadata: - # Note how the Secret is named - name: bootstrap-token-5emitj - # A bootstrap token Secret usually resides in the kube-system namespace - namespace: kube-system -type: bootstrap.kubernetes.io/token -stringData: - auth-extra-groups: "system:bootstrappers:kubeadm:default-node-token" - expiration: "2020-09-13T04:39:10Z" - # This token ID is used in the name - token-id: "5emitj" - token-secret: "kq4gihvszzgn1p0r" - # This token can be used for authentication - usage-bootstrap-authentication: "true" - # and it can be used for signing - usage-bootstrap-signing: "true" -``` +- If your cloud-native component needs to authenticate to another application that you + know is running within the same Kubernetes cluster, you can use a + [ServiceAccount](/docs/reference/access-authn-authz/authentication/#service-account-tokens) + and its tokens to identify your client. +- There are third-party tools that you can run, either within or outside your cluster, + that provide secrets management. For example, a service that Pods access over HTTPS, + that reveals a secret if the client correctly authenticates (for example, with a ServiceAccount + token). +- For authentication, you can implement a custom signer for X.509 certificates, and use + [CertificateSigningRequests](/docs/reference/access-authn-authz/certificate-signing-requests/) + to let that custom signer issue certificates to Pods that need them. +- You can use a [device plugin](/docs/concepts/extend-kubernetes/compute-storage-net/device-plugins/) + to expose node-local encryption hardware to a specific Pod. For example, you can schedule + trusted Pods onto nodes that provide a Trusted Platform Module, configured out-of-band. + +You can also combine two or more of those options, including the option to use Secret objects themselves. + +For example: implement (or deploy) an {{< glossary_tooltip text="operator" term_id="operator-pattern" >}} +that fetches short-lived session tokens from an external service, and then creates Secrets based +on those short-lived session tokens. Pods running in your cluster can make use of the session tokens, +and operator ensures they are valid. This separation means that you can run Pods that are unaware of +the exact mechanisms for issuing and refreshing those session tokens. ## Working with Secrets @@ -511,7 +375,7 @@ The name of a Secret object must be a valid [DNS subdomain name](/docs/concepts/overview/working-with-objects/names#dns-subdomain-names). You can specify the `data` and/or the `stringData` field when creating a -configuration file for a Secret. The `data` and the `stringData` fields are optional. +configuration file for a Secret. The `data` and the `stringData` fields are optional. The values for all keys in the `data` field have to be base64-encoded strings. If the conversion to base64 string is not desirable, you can choose to specify the `stringData` field instead, which accepts arbitrary strings as values. @@ -535,8 +399,8 @@ number of Secrets (or other resources) in a namespace. You can edit an existing Secret unless it is [immutable](#secret-immutable). To edit a Secret, use one of the following methods: -- [Use `kubectl`](/docs/tasks/configmap-secret/managing-secret-using-kubectl/#edit-secret) -- [Use a configuration file](/docs/tasks/configmap-secret/managing-secret-using-config-file/#edit-secret) +* [Use `kubectl`](/docs/tasks/configmap-secret/managing-secret-using-kubectl/#edit-secret) +* [Use a configuration file](/docs/tasks/configmap-secret/managing-secret-using-config-file/#edit-secret) You can also edit the data in a Secret using the [Kustomize tool](/docs/tasks/configmap-secret/managing-secret-using-kustomize/#edit-secret). However, this method creates a new `Secret` object with the edited data. @@ -576,17 +440,17 @@ metadata: name: mypod spec: containers: - - name: mypod - image: redis - volumeMounts: - - name: foo - mountPath: "/etc/foo" - readOnly: true - volumes: + - name: mypod + image: redis + volumeMounts: - name: foo - secret: - secretName: mysecret - optional: true + mountPath: "/etc/foo" + readOnly: true + volumes: + - name: foo + secret: + secretName: mysecret + optional: true ``` By default, Secrets are required. None of a Pod's containers will start until @@ -697,268 +561,405 @@ for a detailed explanation of that process. You cannot use ConfigMaps or Secrets with {{< glossary_tooltip text="static Pods" term_id="static-pod" >}}. -## Use cases +## Types of Secret {#secret-types} -### Use case: As container environment variables {#use-case-as-container-environment-variables} +When creating a Secret, you can specify its type using the `type` field of +the [Secret](/docs/reference/kubernetes-api/config-and-storage-resources/secret-v1/) +resource, or certain equivalent `kubectl` command line flags (if available). +The Secret type is used to facilitate programmatic handling of the Secret data. -You can create a Secret and use it to -[set environment variables for a container](/docs/tasks/inject-data-application/distribute-credentials-secure/#define-container-environment-variables-using-secret-data). +Kubernetes provides several built-in types for some common usage scenarios. +These types vary in terms of the validations performed and the constraints +Kubernetes imposes on them. -### Use case: Pod with SSH keys +| Built-in Type | Usage | +|--------------|-------| +| `Opaque` | arbitrary user-defined data | +| `kubernetes.io/service-account-token` | ServiceAccount token | +| `kubernetes.io/dockercfg` | serialized `~/.dockercfg` file | +| `kubernetes.io/dockerconfigjson` | serialized `~/.docker/config.json` file | +| `kubernetes.io/basic-auth` | credentials for basic authentication | +| `kubernetes.io/ssh-auth` | credentials for SSH authentication | +| `kubernetes.io/tls` | data for a TLS client or server | +| `bootstrap.kubernetes.io/token` | bootstrap token data | -Create a Secret containing some SSH keys: +You can define and use your own Secret type by assigning a non-empty string as the +`type` value for a Secret object (an empty string is treated as an `Opaque` type). + +Kubernetes doesn't impose any constraints on the type name. However, if you +are using one of the built-in types, you must meet all the requirements defined +for that type. + +If you are defining a type of secret that's for public use, follow the convention +and structure the secret type to have your domain name before the name, separated +by a `/`. For example: `cloud-hosting.example.net/cloud-api-credentials`. + +### Opaque secrets + +`Opaque` is the default Secret type if omitted from a Secret configuration file. +When you create a Secret using `kubectl`, you will use the `generic` +subcommand to indicate an `Opaque` Secret type. For example, the following +command creates an empty Secret of type `Opaque`. ```shell -kubectl create secret generic ssh-key-secret --from-file=ssh-privatekey=/path/to/.ssh/id_rsa --from-file=ssh-publickey=/path/to/.ssh/id_rsa.pub +kubectl create secret generic empty-secret +kubectl get secret empty-secret ``` -The output is similar to: +The output looks like: ``` -secret "ssh-key-secret" created +NAME TYPE DATA AGE +empty-secret Opaque 0 2m6s ``` -You can also create a `kustomization.yaml` with a `secretGenerator` field containing ssh keys. - -{{< caution >}} -Think carefully before sending your own SSH keys: other users of the cluster may have access -to the Secret. - -You could instead create an SSH private key representing a service identity that you want to be -accessible to all the users with whom you share the Kubernetes cluster, and that you can revoke -if the credentials are compromised. -{{< /caution >}} +The `DATA` column shows the number of data items stored in the Secret. +In this case, `0` means you have created an empty Secret. -Now you can create a Pod which references the secret with the SSH key and -consumes it in a volume: +### Service account token Secrets -```yaml -apiVersion: v1 -kind: Pod -metadata: - name: secret-test-pod - labels: - name: secret-test -spec: - volumes: - - name: secret-volume - secret: - secretName: ssh-key-secret - containers: - - name: ssh-test-container - image: mySshImage - volumeMounts: - - name: secret-volume - readOnly: true - mountPath: "/etc/secret-volume" -``` +A `kubernetes.io/service-account-token` type of Secret is used to store a +token credential that identifies a +{{< glossary_tooltip text="service account" term_id="service-account" >}}. -When the container's command runs, the pieces of the key will be available in: +{{< note >}} +Versions of Kubernetes before v1.22 automatically created credentials for +accessing the Kubernetes API. This older mechanism was based on creating token +Secrets that could then be mounted into running Pods. +In more recent versions, including Kubernetes v{{< skew currentVersion >}}, API +credentials are obtained directly by using the +[TokenRequest](/docs/reference/kubernetes-api/authentication-resources/token-request-v1/) +API, and are mounted into Pods using a +[projected volume](/docs/reference/access-authn-authz/service-accounts-admin/#bound-service-account-token-volume). +The tokens obtained using this method have bounded lifetimes, and are +automatically invalidated when the Pod they are mounted into is deleted. -``` -/etc/secret-volume/ssh-publickey -/etc/secret-volume/ssh-privatekey -``` +You can still +[manually create](/docs/tasks/configure-pod-container/configure-service-account/#manually-create-a-service-account-api-token) +a service account token Secret; for example, if you need a token that never +expires. However, using the +[TokenRequest](/docs/reference/kubernetes-api/authentication-resources/token-request-v1/) +subresource to obtain a token to access the API is recommended instead. +You can use the +[`kubectl create token`](/docs/reference/generated/kubectl/kubectl-commands#-em-token-em-) +command to obtain a token from the `TokenRequest` API. +{{< /note >}} -The container is then free to use the secret data to establish an SSH connection. +You should only create a service account token Secret object +if you can't use the `TokenRequest` API to obtain a token, +and the security exposure of persisting a non-expiring token credential +in a readable API object is acceptable to you. -### Use case: Pods with prod / test credentials +When using this Secret type, you need to ensure that the +`kubernetes.io/service-account.name` annotation is set to an existing +service account name. If you are creating both the ServiceAccount and +the Secret objects, you should create the ServiceAccount object first. -This example illustrates a Pod which consumes a secret containing production credentials and -another Pod which consumes a secret with test environment credentials. +After the Secret is created, a Kubernetes {{< glossary_tooltip text="controller" term_id="controller" >}} +fills in some other fields such as the `kubernetes.io/service-account.uid` annotation, and the +`token` key in the `data` field, which is populated with an authentication token. -You can create a `kustomization.yaml` with a `secretGenerator` field or run -`kubectl create secret`. +The following example configuration declares a service account token Secret: -```shell -kubectl create secret generic prod-db-secret --from-literal=username=produser --from-literal=password=Y4nys7f11 +```yaml +apiVersion: v1 +kind: Secret +metadata: + name: secret-sa-sample + annotations: + kubernetes.io/service-account.name: "sa-name" +type: kubernetes.io/service-account-token +data: + # You can include additional key value pairs as you do with Opaque Secrets + extra: YmFyCg== ``` -The output is similar to: +After creating the Secret, wait for Kubernetes to populate the `token` key in the `data` field. -``` -secret "prod-db-secret" created -``` +See the [ServiceAccount](/docs/tasks/configure-pod-container/configure-service-account/) +documentation for more information on how service accounts work. +You can also check the `automountServiceAccountToken` field and the +`serviceAccountName` field of the +[`Pod`](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#pod-v1-core) +for information on referencing service account credentials from within Pods. -You can also create a secret for test environment credentials. +### Docker config Secrets -```shell -kubectl create secret generic test-db-secret --from-literal=username=testuser --from-literal=password=iluvtests -``` +You can use one of the following `type` values to create a Secret to +store the credentials for accessing a container image registry: -The output is similar to: +- `kubernetes.io/dockercfg` +- `kubernetes.io/dockerconfigjson` -``` -secret "test-db-secret" created -``` +The `kubernetes.io/dockercfg` type is reserved to store a serialized +`~/.dockercfg` which is the legacy format for configuring Docker command line. +When using this Secret type, you have to ensure the Secret `data` field +contains a `.dockercfg` key whose value is content of a `~/.dockercfg` file +encoded in the base64 format. -{{< note >}} -Special characters such as `$`, `\`, `*`, `=`, and `!` will be interpreted by your -[shell](https://en.wikipedia.org/wiki/Shell_(computing)) and require escaping. +The `kubernetes.io/dockerconfigjson` type is designed for storing a serialized +JSON that follows the same format rules as the `~/.docker/config.json` file +which is a new format for `~/.dockercfg`. +When using this Secret type, the `data` field of the Secret object must +contain a `.dockerconfigjson` key, in which the content for the +`~/.docker/config.json` file is provided as a base64 encoded string. -In most shells, the easiest way to escape the password is to surround it with single quotes (`'`). -For example, if your actual password is `S!B\*d$zDsb=`, you should execute the command this way: +Below is an example for a `kubernetes.io/dockercfg` type of Secret: -```shell -kubectl create secret generic dev-db-secret --from-literal=username=devuser --from-literal=password='S!B\*d$zDsb=' +```yaml +apiVersion: v1 +kind: Secret +metadata: + name: secret-dockercfg +type: kubernetes.io/dockercfg +data: + .dockercfg: | + "" ``` -You do not need to escape special characters in passwords from files (`--from-file`). +{{< note >}} +If you do not want to perform the base64 encoding, you can choose to use the +`stringData` field instead. {{< /note >}} -Now make the Pods: +When you create these types of Secrets using a manifest, the API +server checks whether the expected key exists in the `data` field, and +it verifies if the value provided can be parsed as a valid JSON. The API +server doesn't validate if the JSON actually is a Docker config file. + +When you do not have a Docker config file, or you want to use `kubectl` +to create a Secret for accessing a container registry, you can do: ```shell -cat < pod.yaml -apiVersion: v1 -kind: List -items: -- kind: Pod - apiVersion: v1 - metadata: - name: prod-db-client-pod - labels: - name: prod-db-client - spec: - volumes: - - name: secret-volume - secret: - secretName: prod-db-secret - containers: - - name: db-client-container - image: myClientImage - volumeMounts: - - name: secret-volume - readOnly: true - mountPath: "/etc/secret-volume" -- kind: Pod - apiVersion: v1 - metadata: - name: test-db-client-pod - labels: - name: test-db-client - spec: - volumes: - - name: secret-volume - secret: - secretName: test-db-secret - containers: - - name: db-client-container - image: myClientImage - volumeMounts: - - name: secret-volume - readOnly: true - mountPath: "/etc/secret-volume" -EOF +kubectl create secret docker-registry secret-tiger-docker \ + --docker-email=tiger@acme.example \ + --docker-username=tiger \ + --docker-password=pass1234 \ + --docker-server=my-registry.example:5000 ``` -Add the pods to the same `kustomization.yaml`: +That command creates a Secret of type `kubernetes.io/dockerconfigjson`. +If you dump the `.data.dockerconfigjson` field from that new Secret and then +decode it from base64: ```shell -cat <> kustomization.yaml -resources: -- pod.yaml -EOF +kubectl get secret secret-tiger-docker -o jsonpath='{.data.*}' | base64 -d ``` -Apply all those objects on the API server by running: +then the output is equivalent to this JSON document (which is also a valid +Docker configuration file): -```shell -kubectl apply -k . +```json +{ + "auths": { + "my-registry.example:5000": { + "username": "tiger", + "password": "pass1234", + "email": "tiger@acme.example", + "auth": "dGlnZXI6cGFzczEyMzQ=" + } + } +} ``` -Both containers will have the following files present on their filesystems with the values -for each container's environment: +{{< note >}} +The `auth` value there is base64 encoded; it is obscured but not secret. +Anyone who can read that Secret can learn the registry access bearer token. +{{< /note >}} -``` -/etc/secret-volume/username -/etc/secret-volume/password -``` +### Basic authentication Secret -Note how the specs for the two Pods differ only in one field; this facilitates -creating Pods with different capabilities from a common Pod template. +The `kubernetes.io/basic-auth` type is provided for storing credentials needed +for basic authentication. When using this Secret type, the `data` field of the +Secret must contain one of the following two keys: -You could further simplify the base Pod specification by using two service accounts: +- `username`: the user name for authentication +- `password`: the password or token for authentication -1. `prod-user` with the `prod-db-secret` -1. `test-user` with the `test-db-secret` +Both values for the above two keys are base64 encoded strings. You can, of +course, provide the clear text content using the `stringData` for Secret +creation. -The Pod specification is shortened to: +The following manifest is an example of a basic authentication Secret: ```yaml apiVersion: v1 -kind: Pod +kind: Secret metadata: - name: prod-db-client-pod - labels: - name: prod-db-client -spec: - serviceAccount: prod-db-client - containers: - - name: db-client-container - image: myClientImage + name: secret-basic-auth +type: kubernetes.io/basic-auth +stringData: + username: admin # required field for kubernetes.io/basic-auth + password: t0p-Secret # required field for kubernetes.io/basic-auth ``` -### Use case: dotfiles in a secret volume +The basic authentication Secret type is provided only for convenience. +You can create an `Opaque` type for credentials used for basic authentication. +However, using the defined and public Secret type (`kubernetes.io/basic-auth`) helps other +people to understand the purpose of your Secret, and sets a convention for what key names +to expect. +The Kubernetes API verifies that the required keys are set for a Secret of this type. -You can make your data "hidden" by defining a key that begins with a dot. -This key represents a dotfile or "hidden" file. For example, when the following secret -is mounted into a volume, `secret-volume`: +### SSH authentication secrets + +The builtin type `kubernetes.io/ssh-auth` is provided for storing data used in +SSH authentication. When using this Secret type, you will have to specify a +`ssh-privatekey` key-value pair in the `data` (or `stringData`) field +as the SSH credential to use. + +The following manifest is an example of a Secret used for SSH public/private +key authentication: ```yaml apiVersion: v1 kind: Secret metadata: - name: dotfile-secret + name: secret-ssh-auth +type: kubernetes.io/ssh-auth data: - .secret-file: dmFsdWUtMg0KDQo= ---- + # the data is abbreviated in this example + ssh-privatekey: | + MIIEpQIBAAKCAQEAulqb/Y ... +``` + +The SSH authentication Secret type is provided only for user's convenience. +You could instead create an `Opaque` type Secret for credentials used for SSH authentication. +However, using the defined and public Secret type (`kubernetes.io/ssh-auth`) helps other +people to understand the purpose of your Secret, and sets a convention for what key names +to expect. +and the API server does verify if the required keys are provided in a Secret configuration. + +{{< caution >}} +SSH private keys do not establish trusted communication between an SSH client and +host server on their own. A secondary means of establishing trust is needed to +mitigate "man in the middle" attacks, such as a `known_hosts` file added to a ConfigMap. +{{< /caution >}} + +### TLS secrets + +Kubernetes provides a builtin Secret type `kubernetes.io/tls` for storing +a certificate and its associated key that are typically used for TLS. + +One common use for TLS secrets is to configure encryption in transit for +an [Ingress](/docs/concepts/services-networking/ingress/), but you can also use it +with other resources or directly in your workload. +When using this type of Secret, the `tls.key` and the `tls.crt` key must be provided +in the `data` (or `stringData`) field of the Secret configuration, although the API +server doesn't actually validate the values for each key. + +The following YAML contains an example config for a TLS Secret: + +```yaml apiVersion: v1 -kind: Pod +kind: Secret metadata: - name: secret-dotfiles-pod -spec: - volumes: - - name: secret-volume - secret: - secretName: dotfile-secret - containers: - - name: dotfile-test-container - image: registry.k8s.io/busybox - command: - - ls - - "-l" - - "/etc/secret-volume" - volumeMounts: - - name: secret-volume - readOnly: true - mountPath: "/etc/secret-volume" + name: secret-tls +type: kubernetes.io/tls +data: + # the data is abbreviated in this example + tls.crt: | + MIIC2DCCAcCgAwIBAgIBATANBgkqh ... + tls.key: | + MIIEpgIBAAKCAQEA7yn3bRHQ5FHMQ ... ``` -The volume will contain a single file, called `.secret-file`, and -the `dotfile-test-container` will have this file present at the path -`/etc/secret-volume/.secret-file`. +The TLS Secret type is provided for user's convenience. You can create an `Opaque` +for credentials used for TLS server and/or client. However, using the builtin Secret +type helps ensure the consistency of Secret format in your project; the API server +does verify if the required keys are provided in a Secret configuration. + +When creating a TLS Secret using `kubectl`, you can use the `tls` subcommand +as shown in the following example: + +```shell +kubectl create secret tls my-tls-secret \ + --cert=path/to/cert/file \ + --key=path/to/key/file +``` + +The public/private key pair must exist before hand. The public key certificate +for `--cert` must be DER format as per +[Section 5.1 of RFC 7468](https://datatracker.ietf.org/doc/html/rfc7468#section-5.1), +and must match the given private key for `--key` (PKCS #8 in DER format; +[Section 11 of RFC 7468](https://datatracker.ietf.org/doc/html/rfc7468#section-11)). {{< note >}} -Files beginning with dot characters are hidden from the output of `ls -l`; -you must use `ls -la` to see them when listing directory contents. +A kubernetes.io/tls Secret stores the Base64-encoded DER data for keys and +certificates. If you're familiar with PEM format for private keys and for certificates, +the base64 data are the same as that format except that you omit +the initial and the last lines that are used in PEM. + +For example, for a certificate, you do **not** include `--------BEGIN CERTIFICATE-----` +and `-------END CERTIFICATE----`. {{< /note >}} -### Use case: Secret visible to one container in a Pod +### Bootstrap token Secrets -Consider a program that needs to handle HTTP requests, do some complex business -logic, and then sign some messages with an HMAC. Because it has complex -application logic, there might be an unnoticed remote file reading exploit in -the server, which could expose the private key to an attacker. +A bootstrap token Secret can be created by explicitly specifying the Secret +`type` to `bootstrap.kubernetes.io/token`. This type of Secret is designed for +tokens used during the node bootstrap process. It stores tokens used to sign +well-known ConfigMaps. -This could be divided into two processes in two containers: a frontend container -which handles user interaction and business logic, but which cannot see the -private key; and a signer container that can see the private key, and responds -to simple signing requests from the frontend (for example, over localhost networking). +A bootstrap token Secret is usually created in the `kube-system` namespace and +named in the form `bootstrap-token-` where `` is a 6 character +string of the token ID. + +As a Kubernetes manifest, a bootstrap token Secret might look like the +following: + +```yaml +apiVersion: v1 +kind: Secret +metadata: + name: bootstrap-token-5emitj + namespace: kube-system +type: bootstrap.kubernetes.io/token +data: + auth-extra-groups: c3lzdGVtOmJvb3RzdHJhcHBlcnM6a3ViZWFkbTpkZWZhdWx0LW5vZGUtdG9rZW4= + expiration: MjAyMC0wOS0xM1QwNDozOToxMFo= + token-id: NWVtaXRq + token-secret: a3E0Z2lodnN6emduMXAwcg== + usage-bootstrap-authentication: dHJ1ZQ== + usage-bootstrap-signing: dHJ1ZQ== +``` + +A bootstrap type Secret has the following keys specified under `data`: + +- `token-id`: A random 6 character string as the token identifier. Required. +- `token-secret`: A random 16 character string as the actual token secret. Required. +- `description`: A human-readable string that describes what the token is + used for. Optional. +- `expiration`: An absolute UTC time using [RFC3339](https://datatracker.ietf.org/doc/html/rfc3339) specifying when the token + should be expired. Optional. +- `usage-bootstrap-`: A boolean flag indicating additional usage for + the bootstrap token. +- `auth-extra-groups`: A comma-separated list of group names that will be + authenticated as in addition to the `system:bootstrappers` group. + +The above YAML may look confusing because the values are all in base64 encoded +strings. In fact, you can create an identical Secret using the following YAML: + +```yaml +apiVersion: v1 +kind: Secret +metadata: + # Note how the Secret is named + name: bootstrap-token-5emitj + # A bootstrap token Secret usually resides in the kube-system namespace + namespace: kube-system +type: bootstrap.kubernetes.io/token +stringData: + auth-extra-groups: "system:bootstrappers:kubeadm:default-node-token" + expiration: "2020-09-13T04:39:10Z" + # This token ID is used in the name + token-id: "5emitj" + token-secret: "kq4gihvszzgn1p0r" + # This token can be used for authentication + usage-bootstrap-authentication: "true" + # and it can be used for signing + usage-bootstrap-signing: "true" +``` -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. ## Immutable Secrets {#secret-immutable} From 5bfb353a4e1a9f0611aa25d23aaae0abc27632b4 Mon Sep 17 00:00:00 2001 From: Shannon Kularathna Date: Fri, 7 Jul 2023 19:48:14 +0000 Subject: [PATCH 2/5] Convert env variables use case and SSH key use case into bullets with links - Link to the actual task topics - Remove the list of uses for secrets that link to anchors on page and replace with links to tasks --- .../en/docs/concepts/configuration/secret.md | 75 +------------------ 1 file changed, 4 insertions(+), 71 deletions(-) diff --git a/content/en/docs/concepts/configuration/secret.md b/content/en/docs/concepts/configuration/secret.md index b24c02ac79ae3..4df55caadf29f 100644 --- a/content/en/docs/concepts/configuration/secret.md +++ b/content/en/docs/concepts/configuration/secret.md @@ -55,83 +55,16 @@ See [Information security for Secrets](#information-security-for-secrets) for mo ## Uses for Secrets -There are three main ways for a Pod to use a Secret: +You can use Secrets for purposes such as the following: -- As [files](#using-secrets-as-files-from-a-pod) in a - {{< glossary_tooltip text="volume" term_id="volume" >}} mounted on one or more of - its containers. -- As [container environment variable](#using-secrets-as-environment-variables). -- By the [kubelet when pulling images](#using-imagepullsecrets) for the Pod. +- [Set environment variables for a container](/docs/tasks/inject-data-application/distribute-credentials-secure/#define-container-environment-variables-using-secret-data). +- [Provide credentials such as SSH keys or passwords to Pods](/docs/tasks/inject-data-application/distribute-credentials-secure/#provide-prod-test-creds). +- [Allow the kubelet to pull container images from private registries](/docs/tasks/configure-pod-container/pull-image-private-registry/). The Kubernetes control plane also uses Secrets; for example, [bootstrap token Secrets](#bootstrap-token-secrets) are a mechanism to help automate node registration. -## Use cases - -### Use case: As container environment variables {#use-case-as-container-environment-variables} - -You can create a Secret and use it to -[set environment variables for a container](/docs/tasks/inject-data-application/distribute-credentials-secure/#define-container-environment-variables-using-secret-data). - -### Use case: Pod with SSH keys - -Create a Secret containing some SSH keys: - -```shell -kubectl create secret generic ssh-key-secret --from-file=ssh-privatekey=/path/to/.ssh/id_rsa --from-file=ssh-publickey=/path/to/.ssh/id_rsa.pub -``` - -The output is similar to: - -``` -secret "ssh-key-secret" created -``` - -You can also create a `kustomization.yaml` with a `secretGenerator` field containing ssh keys. - -{{< caution >}} -Think carefully before sending your own SSH keys: other users of the cluster may have access -to the Secret. - -You could instead create an SSH private key representing a service identity that you want to be -accessible to all the users with whom you share the Kubernetes cluster, and that you can revoke -if the credentials are compromised. -{{< /caution >}} - -Now you can create a Pod which references the secret with the SSH key and -consumes it in a volume: - -```yaml -apiVersion: v1 -kind: Pod -metadata: - name: secret-test-pod - labels: - name: secret-test -spec: - volumes: - - name: secret-volume - secret: - secretName: ssh-key-secret - containers: - - name: ssh-test-container - image: mySshImage - volumeMounts: - - name: secret-volume - readOnly: true - mountPath: "/etc/secret-volume" -``` - -When the container's command runs, the pieces of the key will be available in: - -``` -/etc/secret-volume/ssh-publickey -/etc/secret-volume/ssh-privatekey -``` - -The container is then free to use the secret data to establish an SSH connection. - ### Use case: Pods with prod / test credentials This example illustrates a Pod which consumes a secret containing production credentials and From bbb9572eff8423f7de50eb09085872e6f8ef79bc Mon Sep 17 00:00:00 2001 From: Shannon Kularathna Date: Fri, 7 Jul 2023 19:49:05 +0000 Subject: [PATCH 3/5] Move prod-test use case to task page - no content changes --- .../en/docs/concepts/configuration/secret.md | 137 ------------------ .../distribute-credentials-secure.md | 137 ++++++++++++++++++ 2 files changed, 137 insertions(+), 137 deletions(-) diff --git a/content/en/docs/concepts/configuration/secret.md b/content/en/docs/concepts/configuration/secret.md index 4df55caadf29f..cd6ac0c5205b6 100644 --- a/content/en/docs/concepts/configuration/secret.md +++ b/content/en/docs/concepts/configuration/secret.md @@ -65,143 +65,6 @@ The Kubernetes control plane also uses Secrets; for example, [bootstrap token Secrets](#bootstrap-token-secrets) are a mechanism to help automate node registration. -### Use case: Pods with prod / test credentials - -This example illustrates a Pod which consumes a secret containing production credentials and -another Pod which consumes a secret with test environment credentials. - -You can create a `kustomization.yaml` with a `secretGenerator` field or run -`kubectl create secret`. - -```shell -kubectl create secret generic prod-db-secret --from-literal=username=produser --from-literal=password=Y4nys7f11 -``` - -The output is similar to: - -``` -secret "prod-db-secret" created -``` - -You can also create a secret for test environment credentials. - -```shell -kubectl create secret generic test-db-secret --from-literal=username=testuser --from-literal=password=iluvtests -``` - -The output is similar to: - -``` -secret "test-db-secret" created -``` - -{{< note >}} -Special characters such as `$`, `\`, `*`, `=`, and `!` will be interpreted by your -[shell](https://en.wikipedia.org/wiki/Shell_(computing)) and require escaping. - -In most shells, the easiest way to escape the password is to surround it with single quotes (`'`). -For example, if your actual password is `S!B\*d$zDsb=`, you should execute the command this way: - -```shell -kubectl create secret generic dev-db-secret --from-literal=username=devuser --from-literal=password='S!B\*d$zDsb=' -``` - -You do not need to escape special characters in passwords from files (`--from-file`). -{{< /note >}} - -Now make the Pods: - -```shell -cat < pod.yaml -apiVersion: v1 -kind: List -items: -- kind: Pod - apiVersion: v1 - metadata: - name: prod-db-client-pod - labels: - name: prod-db-client - spec: - volumes: - - name: secret-volume - secret: - secretName: prod-db-secret - containers: - - name: db-client-container - image: myClientImage - volumeMounts: - - name: secret-volume - readOnly: true - mountPath: "/etc/secret-volume" -- kind: Pod - apiVersion: v1 - metadata: - name: test-db-client-pod - labels: - name: test-db-client - spec: - volumes: - - name: secret-volume - secret: - secretName: test-db-secret - containers: - - name: db-client-container - image: myClientImage - volumeMounts: - - name: secret-volume - readOnly: true - mountPath: "/etc/secret-volume" -EOF -``` - -Add the pods to the same `kustomization.yaml`: - -```shell -cat <> kustomization.yaml -resources: -- pod.yaml -EOF -``` - -Apply all those objects on the API server by running: - -```shell -kubectl apply -k . -``` - -Both containers will have the following files present on their filesystems with the values -for each container's environment: - -``` -/etc/secret-volume/username -/etc/secret-volume/password -``` - -Note how the specs for the two Pods differ only in one field; this facilitates -creating Pods with different capabilities from a common Pod template. - -You could further simplify the base Pod specification by using two service accounts: - -1. `prod-user` with the `prod-db-secret` -1. `test-user` with the `test-db-secret` - -The Pod specification is shortened to: - -```yaml -apiVersion: v1 -kind: Pod -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: dotfiles in a secret volume You can make your data "hidden" by defining a key that begins with a dot. diff --git a/content/en/docs/tasks/inject-data-application/distribute-credentials-secure.md b/content/en/docs/tasks/inject-data-application/distribute-credentials-secure.md index aa8efd5e13bb9..500e405f2fefe 100644 --- a/content/en/docs/tasks/inject-data-application/distribute-credentials-secure.md +++ b/content/en/docs/tasks/inject-data-application/distribute-credentials-secure.md @@ -335,6 +335,143 @@ This functionality is available in Kubernetes v1.6 and later. password: 39528$vdg7Jb ``` +### Use case: Pods with prod / test credentials + +This example illustrates a Pod which consumes a secret containing production credentials and +another Pod which consumes a secret with test environment credentials. + +You can create a `kustomization.yaml` with a `secretGenerator` field or run +`kubectl create secret`. + +```shell +kubectl create secret generic prod-db-secret --from-literal=username=produser --from-literal=password=Y4nys7f11 +``` + +The output is similar to: + +``` +secret "prod-db-secret" created +``` + +You can also create a secret for test environment credentials. + +```shell +kubectl create secret generic test-db-secret --from-literal=username=testuser --from-literal=password=iluvtests +``` + +The output is similar to: + +``` +secret "test-db-secret" created +``` + +{{< note >}} +Special characters such as `$`, `\`, `*`, `=`, and `!` will be interpreted by your +[shell](https://en.wikipedia.org/wiki/Shell_(computing)) and require escaping. + +In most shells, the easiest way to escape the password is to surround it with single quotes (`'`). +For example, if your actual password is `S!B\*d$zDsb=`, you should execute the command this way: + +```shell +kubectl create secret generic dev-db-secret --from-literal=username=devuser --from-literal=password='S!B\*d$zDsb=' +``` + +You do not need to escape special characters in passwords from files (`--from-file`). +{{< /note >}} + +Now make the Pods: + +```shell +cat < pod.yaml +apiVersion: v1 +kind: List +items: +- kind: Pod + apiVersion: v1 + metadata: + name: prod-db-client-pod + labels: + name: prod-db-client + spec: + volumes: + - name: secret-volume + secret: + secretName: prod-db-secret + containers: + - name: db-client-container + image: myClientImage + volumeMounts: + - name: secret-volume + readOnly: true + mountPath: "/etc/secret-volume" +- kind: Pod + apiVersion: v1 + metadata: + name: test-db-client-pod + labels: + name: test-db-client + spec: + volumes: + - name: secret-volume + secret: + secretName: test-db-secret + containers: + - name: db-client-container + image: myClientImage + volumeMounts: + - name: secret-volume + readOnly: true + mountPath: "/etc/secret-volume" +EOF +``` + +Add the pods to the same `kustomization.yaml`: + +```shell +cat <> kustomization.yaml +resources: +- pod.yaml +EOF +``` + +Apply all those objects on the API server by running: + +```shell +kubectl apply -k . +``` + +Both containers will have the following files present on their filesystems with the values +for each container's environment: + +``` +/etc/secret-volume/username +/etc/secret-volume/password +``` + +Note how the specs for the two Pods differ only in one field; this facilitates +creating Pods with different capabilities from a common Pod template. + +You could further simplify the base Pod specification by using two service accounts: + +1. `prod-user` with the `prod-db-secret` +1. `test-user` with the `test-db-secret` + +The Pod specification is shortened to: + +```yaml +apiVersion: v1 +kind: Pod +metadata: + name: prod-db-client-pod + labels: + name: prod-db-client +spec: + serviceAccount: prod-db-client + containers: + - name: db-client-container + image: myClientImage +``` + ### References - [Secret](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#secret-v1-core) From 9bdbe903ee21e403109f1b3315fffac1538b58f0 Mon Sep 17 00:00:00 2001 From: Shannon Kularathna Date: Fri, 7 Jul 2023 19:58:17 +0000 Subject: [PATCH 4/5] Improve the prod/test task section - Use numbered lists - Remove kustomization instructions as they were not comprehensive - Move the note pointing out specs are sharing a template to right under the specs - Make the step wording active voice --- .../en/docs/concepts/configuration/secret.md | 427 +++++++++--------- .../distribute-credentials-secure.md | 178 ++++---- 2 files changed, 296 insertions(+), 309 deletions(-) diff --git a/content/en/docs/concepts/configuration/secret.md b/content/en/docs/concepts/configuration/secret.md index cd6ac0c5205b6..7ffe4d731d751 100644 --- a/content/en/docs/concepts/configuration/secret.md +++ b/content/en/docs/concepts/configuration/secret.md @@ -155,208 +155,6 @@ on those short-lived session tokens. Pods running in your cluster can make use o and operator ensures they are valid. This separation means that you can run Pods that are unaware of the exact mechanisms for issuing and refreshing those session tokens. -## Working with Secrets - -### Creating a Secret - -There are several options to create a Secret: - -- [Use `kubectl`](/docs/tasks/configmap-secret/managing-secret-using-kubectl/) -- [Use a configuration file](/docs/tasks/configmap-secret/managing-secret-using-config-file/) -- [Use the Kustomize tool](/docs/tasks/configmap-secret/managing-secret-using-kustomize/) - -#### Constraints on Secret names and data {#restriction-names-data} - -The name of a Secret object must be a valid -[DNS subdomain name](/docs/concepts/overview/working-with-objects/names#dns-subdomain-names). - -You can specify the `data` and/or the `stringData` field when creating a -configuration file for a Secret. The `data` and the `stringData` fields are optional. -The values for all keys in the `data` field have to be base64-encoded strings. -If the conversion to base64 string is not desirable, you can choose to specify -the `stringData` field instead, which accepts arbitrary strings as values. - -The keys of `data` and `stringData` must consist of alphanumeric characters, -`-`, `_` or `.`. All key-value pairs in the `stringData` field are internally -merged into the `data` field. If a key appears in both the `data` and the -`stringData` field, the value specified in the `stringData` field takes -precedence. - -#### Size limit {#restriction-data-size} - -Individual secrets are limited to 1MiB in size. This is to discourage creation -of very large secrets that could exhaust the API server and kubelet memory. -However, creation of many smaller secrets could also exhaust memory. You can -use a [resource quota](/docs/concepts/policy/resource-quotas/) to limit the -number of Secrets (or other resources) in a namespace. - -### Editing a Secret - -You can edit an existing Secret unless it is [immutable](#secret-immutable). To -edit a Secret, use one of the following methods: - -* [Use `kubectl`](/docs/tasks/configmap-secret/managing-secret-using-kubectl/#edit-secret) -* [Use a configuration file](/docs/tasks/configmap-secret/managing-secret-using-config-file/#edit-secret) - -You can also edit the data in a Secret using the [Kustomize tool](/docs/tasks/configmap-secret/managing-secret-using-kustomize/#edit-secret). However, this -method creates a new `Secret` object with the edited data. - -Depending on how you created the Secret, as well as how the Secret is used in -your Pods, updates to existing `Secret` objects are propagated automatically to -Pods that use the data. For more information, refer to [Using Secrets as files from a Pod](#using-secrets-as-files-from-a-pod) section. - -### Using a Secret - -Secrets can be mounted as data volumes or exposed as -{{< glossary_tooltip text="environment variables" term_id="container-env-variables" >}} -to be used by a container in a Pod. Secrets can also be used by other parts of the -system, without being directly exposed to the Pod. For example, Secrets can hold -credentials that other parts of the system should use to interact with external -systems on your behalf. - -Secret volume sources are validated to ensure that the specified object -reference actually points to an object of type Secret. Therefore, a Secret -needs to be created before any Pods that depend on it. - -If the Secret cannot be fetched (perhaps because it does not exist, or -due to a temporary lack of connection to the API server) the kubelet -periodically retries running that Pod. The kubelet also reports an Event -for that Pod, including details of the problem fetching the Secret. - -#### Optional Secrets {#restriction-secret-must-exist} - -When you reference a Secret in a Pod, you can mark the Secret as _optional_, -such as in the following example. If an optional Secret doesn't exist, -Kubernetes ignores it. - -```yaml -apiVersion: v1 -kind: Pod -metadata: - name: mypod -spec: - containers: - - name: mypod - image: redis - volumeMounts: - - name: foo - mountPath: "/etc/foo" - readOnly: true - volumes: - - name: foo - secret: - secretName: mysecret - optional: true -``` - -By default, Secrets are required. None of a Pod's containers will start until -all non-optional Secrets are available. - -If a Pod references a specific key in a non-optional Secret and that Secret -does exist, but is missing the named key, the Pod fails during startup. - -### Using Secrets as files from a Pod {#using-secrets-as-files-from-a-pod} - -If you want to access data from a Secret in a Pod, one way to do that is to -have Kubernetes make the value of that Secret be available as a file inside -the filesystem of one or more of the Pod's containers. - -For instructions, refer to -[Distribute credentials securely using Secrets](/docs/tasks/inject-data-application/distribute-credentials-secure/#create-a-pod-that-has-access-to-the-secret-data-through-a-volume). - -When a volume contains data from a Secret, and that Secret is updated, Kubernetes tracks -this and updates the data in the volume, using an eventually-consistent approach. - -{{< note >}} -A container using a Secret as a -[subPath](/docs/concepts/storage/volumes#using-subpath) volume mount does not receive -automated Secret updates. -{{< /note >}} - -The kubelet keeps a cache of the current keys and values for the Secrets that are used in -volumes for pods on that node. -You can configure the way that the kubelet detects changes from the cached values. The -`configMapAndSecretChangeDetectionStrategy` field in the -[kubelet configuration](/docs/reference/config-api/kubelet-config.v1beta1/) controls -which strategy the kubelet uses. The default strategy is `Watch`. - -Updates to Secrets can be either propagated by an API watch mechanism (the default), based on -a cache with a defined time-to-live, or polled from the cluster API server on each kubelet -synchronisation loop. - -As a result, the total delay from the moment when the Secret is updated to the moment -when new keys are projected to the Pod can be as long as the kubelet sync period + cache -propagation delay, where the cache propagation delay depends on the chosen cache type -(following the same order listed in the previous paragraph, these are: -watch propagation delay, the configured cache TTL, or zero for direct polling). - -### Using Secrets as environment variables - -To use a Secret in an {{< glossary_tooltip text="environment variable" term_id="container-env-variables" >}} -in a Pod: - -1. For each container in your Pod specification, add an environment variable - for each Secret key that you want to use to the - `env[].valueFrom.secretKeyRef` field. -1. Modify your image and/or command line so that the program looks for values - in the specified environment variables. - -For instructions, refer to -[Define container environment variables using Secret data](/docs/tasks/inject-data-application/distribute-credentials-secure/#define-container-environment-variables-using-secret-data). - -#### Invalid environment variables {#restriction-env-from-invalid} - -If your environment variable definitions in your Pod specification are -considered to be invalid environment variable names, those keys aren't made -available to your container. The Pod is allowed to start. - -Kubernetes adds an Event with the reason set to `InvalidVariableNames` and a -message that lists the skipped invalid keys. The following example shows a Pod that refers to a Secret named `mysecret`, where `mysecret` contains 2 invalid keys: `1badkey` and `2alsobad`. - -```shell -kubectl get events -``` - -The output is similar to: - -``` -LASTSEEN FIRSTSEEN COUNT NAME KIND SUBOBJECT TYPE REASON -0s 0s 1 dapi-test-pod Pod Warning InvalidEnvironmentVariableNames kubelet, 127.0.0.1 Keys [1badkey, 2alsobad] from the EnvFrom secret default/mysecret were skipped since they are considered invalid environment variable names. -``` - -### Container image pull secrets {#using-imagepullsecrets} - -If you want to fetch container images from a private repository, you need a way for -the kubelet on each node to authenticate to that repository. You can configure -_image pull secrets_ to make this possible. These secrets are configured at the Pod -level. - -#### Using imagePullSecrets - -The `imagePullSecrets` field is a list of references to secrets in the same namespace. -You can use an `imagePullSecrets` to pass a secret that contains a Docker (or other) image registry -password to the kubelet. The kubelet uses this information to pull a private image on behalf of your Pod. -See the [PodSpec API](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#podspec-v1-core) -for more information about the `imagePullSecrets` field. - -##### Manually specifying an imagePullSecret - -You can learn how to specify `imagePullSecrets` from the -[container images](/docs/concepts/containers/images/#specifying-imagepullsecrets-on-a-pod) -documentation. - -##### Arranging for imagePullSecrets to be automatically attached - -You can manually create `imagePullSecrets`, and reference these from a ServiceAccount. Any Pods -created with that ServiceAccount or created with that ServiceAccount by default, will get their -`imagePullSecrets` field set to that of the service account. -See [Add ImagePullSecrets to a service account](/docs/tasks/configure-pod-container/configure-service-account/#add-imagepullsecrets-to-a-service-account) -for a detailed explanation of that process. - -### Using Secrets with static Pods {#restriction-static-pod} - -You cannot use ConfigMaps or Secrets with {{< glossary_tooltip text="static Pods" term_id="static-pod" >}}. - ## Types of Secret {#secret-types} When creating a Secret, you can specify its type using the `type` field of @@ -368,16 +166,16 @@ Kubernetes provides several built-in types for some common usage scenarios. These types vary in terms of the validations performed and the constraints Kubernetes imposes on them. -| Built-in Type | Usage | -|--------------|-------| -| `Opaque` | arbitrary user-defined data | -| `kubernetes.io/service-account-token` | ServiceAccount token | -| `kubernetes.io/dockercfg` | serialized `~/.dockercfg` file | -| `kubernetes.io/dockerconfigjson` | serialized `~/.docker/config.json` file | -| `kubernetes.io/basic-auth` | credentials for basic authentication | -| `kubernetes.io/ssh-auth` | credentials for SSH authentication | -| `kubernetes.io/tls` | data for a TLS client or server | -| `bootstrap.kubernetes.io/token` | bootstrap token data | +| Built-in Type | Usage | +| ------------------------------------- |---------------------------------------- | +| `Opaque` | arbitrary user-defined data | +| `kubernetes.io/service-account-token` | ServiceAccount token | +| `kubernetes.io/dockercfg` | serialized `~/.dockercfg` file | +| `kubernetes.io/dockerconfigjson` | serialized `~/.docker/config.json` file | +| `kubernetes.io/basic-auth` | credentials for basic authentication | +| `kubernetes.io/ssh-auth` | credentials for SSH authentication | +| `kubernetes.io/tls` | data for a TLS client or server | +| `bootstrap.kubernetes.io/token` | bootstrap token data | You can define and use your own Secret type by assigning a non-empty string as the `type` value for a Secret object (an empty string is treated as an `Opaque` type). @@ -585,7 +383,7 @@ metadata: name: secret-basic-auth type: kubernetes.io/basic-auth stringData: - username: admin # required field for kubernetes.io/basic-auth + username: admin # required field for kubernetes.io/basic-auth password: t0p-Secret # required field for kubernetes.io/basic-auth ``` @@ -615,7 +413,7 @@ type: kubernetes.io/ssh-auth data: # the data is abbreviated in this example ssh-privatekey: | - MIIEpQIBAAKCAQEAulqb/Y ... + MIIEpQIBAAKCAQEAulqb/Y ... ``` The SSH authentication Secret type is provided only for user's convenience. @@ -756,6 +554,207 @@ stringData: usage-bootstrap-signing: "true" ``` +## Working with Secrets + +### Creating a Secret + +There are several options to create a Secret: + +- [Use `kubectl`](/docs/tasks/configmap-secret/managing-secret-using-kubectl/) +- [Use a configuration file](/docs/tasks/configmap-secret/managing-secret-using-config-file/) +- [Use the Kustomize tool](/docs/tasks/configmap-secret/managing-secret-using-kustomize/) + +#### Constraints on Secret names and data {#restriction-names-data} + +The name of a Secret object must be a valid +[DNS subdomain name](/docs/concepts/overview/working-with-objects/names#dns-subdomain-names). + +You can specify the `data` and/or the `stringData` field when creating a +configuration file for a Secret. The `data` and the `stringData` fields are optional. +The values for all keys in the `data` field have to be base64-encoded strings. +If the conversion to base64 string is not desirable, you can choose to specify +the `stringData` field instead, which accepts arbitrary strings as values. + +The keys of `data` and `stringData` must consist of alphanumeric characters, +`-`, `_` or `.`. All key-value pairs in the `stringData` field are internally +merged into the `data` field. If a key appears in both the `data` and the +`stringData` field, the value specified in the `stringData` field takes +precedence. + +#### Size limit {#restriction-data-size} + +Individual secrets are limited to 1MiB in size. This is to discourage creation +of very large secrets that could exhaust the API server and kubelet memory. +However, creation of many smaller secrets could also exhaust memory. You can +use a [resource quota](/docs/concepts/policy/resource-quotas/) to limit the +number of Secrets (or other resources) in a namespace. + +### Editing a Secret + +You can edit an existing Secret unless it is [immutable](#secret-immutable). To +edit a Secret, use one of the following methods: + +- [Use `kubectl`](/docs/tasks/configmap-secret/managing-secret-using-kubectl/#edit-secret) +- [Use a configuration file](/docs/tasks/configmap-secret/managing-secret-using-config-file/#edit-secret) + +You can also edit the data in a Secret using the [Kustomize tool](/docs/tasks/configmap-secret/managing-secret-using-kustomize/#edit-secret). However, this +method creates a new `Secret` object with the edited data. + +Depending on how you created the Secret, as well as how the Secret is used in +your Pods, updates to existing `Secret` objects are propagated automatically to +Pods that use the data. For more information, refer to [Using Secrets as files from a Pod](#using-secrets-as-files-from-a-pod) section. + +### Using a Secret + +Secrets can be mounted as data volumes or exposed as +{{< glossary_tooltip text="environment variables" term_id="container-env-variables" >}} +to be used by a container in a Pod. Secrets can also be used by other parts of the +system, without being directly exposed to the Pod. For example, Secrets can hold +credentials that other parts of the system should use to interact with external +systems on your behalf. + +Secret volume sources are validated to ensure that the specified object +reference actually points to an object of type Secret. Therefore, a Secret +needs to be created before any Pods that depend on it. + +If the Secret cannot be fetched (perhaps because it does not exist, or +due to a temporary lack of connection to the API server) the kubelet +periodically retries running that Pod. The kubelet also reports an Event +for that Pod, including details of the problem fetching the Secret. + +#### Optional Secrets {#restriction-secret-must-exist} + +When you reference a Secret in a Pod, you can mark the Secret as _optional_, +such as in the following example. If an optional Secret doesn't exist, +Kubernetes ignores it. + +```yaml +apiVersion: v1 +kind: Pod +metadata: + name: mypod +spec: + containers: + - name: mypod + image: redis + volumeMounts: + - name: foo + mountPath: "/etc/foo" + readOnly: true + volumes: + - name: foo + secret: + secretName: mysecret + optional: true +``` + +By default, Secrets are required. None of a Pod's containers will start until +all non-optional Secrets are available. + +If a Pod references a specific key in a non-optional Secret and that Secret +does exist, but is missing the named key, the Pod fails during startup. + +### Using Secrets as files from a Pod {#using-secrets-as-files-from-a-pod} + +If you want to access data from a Secret in a Pod, one way to do that is to +have Kubernetes make the value of that Secret be available as a file inside +the filesystem of one or more of the Pod's containers. + +For instructions, refer to +[Distribute credentials securely using Secrets](/docs/tasks/inject-data-application/distribute-credentials-secure/#create-a-pod-that-has-access-to-the-secret-data-through-a-volume). + +When a volume contains data from a Secret, and that Secret is updated, Kubernetes tracks +this and updates the data in the volume, using an eventually-consistent approach. + +{{< note >}} +A container using a Secret as a +[subPath](/docs/concepts/storage/volumes#using-subpath) volume mount does not receive +automated Secret updates. +{{< /note >}} + +The kubelet keeps a cache of the current keys and values for the Secrets that are used in +volumes for pods on that node. +You can configure the way that the kubelet detects changes from the cached values. The +`configMapAndSecretChangeDetectionStrategy` field in the +[kubelet configuration](/docs/reference/config-api/kubelet-config.v1beta1/) controls +which strategy the kubelet uses. The default strategy is `Watch`. + +Updates to Secrets can be either propagated by an API watch mechanism (the default), based on +a cache with a defined time-to-live, or polled from the cluster API server on each kubelet +synchronisation loop. + +As a result, the total delay from the moment when the Secret is updated to the moment +when new keys are projected to the Pod can be as long as the kubelet sync period + cache +propagation delay, where the cache propagation delay depends on the chosen cache type +(following the same order listed in the previous paragraph, these are: +watch propagation delay, the configured cache TTL, or zero for direct polling). + +### Using Secrets as environment variables + +To use a Secret in an {{< glossary_tooltip text="environment variable" term_id="container-env-variables" >}} +in a Pod: + +1. For each container in your Pod specification, add an environment variable + for each Secret key that you want to use to the + `env[].valueFrom.secretKeyRef` field. +1. Modify your image and/or command line so that the program looks for values + in the specified environment variables. + +For instructions, refer to +[Define container environment variables using Secret data](/docs/tasks/inject-data-application/distribute-credentials-secure/#define-container-environment-variables-using-secret-data). + +#### Invalid environment variables {#restriction-env-from-invalid} + +If your environment variable definitions in your Pod specification are +considered to be invalid environment variable names, those keys aren't made +available to your container. The Pod is allowed to start. + +Kubernetes adds an Event with the reason set to `InvalidVariableNames` and a +message that lists the skipped invalid keys. The following example shows a Pod that refers to a Secret named `mysecret`, where `mysecret` contains 2 invalid keys: `1badkey` and `2alsobad`. + +```shell +kubectl get events +``` + +The output is similar to: + +``` +LASTSEEN FIRSTSEEN COUNT NAME KIND SUBOBJECT TYPE REASON +0s 0s 1 dapi-test-pod Pod Warning InvalidEnvironmentVariableNames kubelet, 127.0.0.1 Keys [1badkey, 2alsobad] from the EnvFrom secret default/mysecret were skipped since they are considered invalid environment variable names. +``` + +### Container image pull secrets {#using-imagepullsecrets} + +If you want to fetch container images from a private repository, you need a way for +the kubelet on each node to authenticate to that repository. You can configure +_image pull secrets_ to make this possible. These secrets are configured at the Pod +level. + +#### Using imagePullSecrets + +The `imagePullSecrets` field is a list of references to secrets in the same namespace. +You can use an `imagePullSecrets` to pass a secret that contains a Docker (or other) image registry +password to the kubelet. The kubelet uses this information to pull a private image on behalf of your Pod. +See the [PodSpec API](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#podspec-v1-core) +for more information about the `imagePullSecrets` field. + +##### Manually specifying an imagePullSecret + +You can learn how to specify `imagePullSecrets` from the +[container images](/docs/concepts/containers/images/#specifying-imagepullsecrets-on-a-pod) +documentation. + +##### Arranging for imagePullSecrets to be automatically attached + +You can manually create `imagePullSecrets`, and reference these from a ServiceAccount. Any Pods +created with that ServiceAccount or created with that ServiceAccount by default, will get their +`imagePullSecrets` field set to that of the service account. +See [Add ImagePullSecrets to a service account](/docs/tasks/configure-pod-container/configure-service-account/#add-imagepullsecrets-to-a-service-account) +for a detailed explanation of that process. + +### Using Secrets with static Pods {#restriction-static-pod} + +You cannot use ConfigMaps or Secrets with {{< glossary_tooltip text="static Pods" term_id="static-pod" >}}. ## Immutable Secrets {#secret-immutable} diff --git a/content/en/docs/tasks/inject-data-application/distribute-credentials-secure.md b/content/en/docs/tasks/inject-data-application/distribute-credentials-secure.md index 500e405f2fefe..bb1114486c730 100644 --- a/content/en/docs/tasks/inject-data-application/distribute-credentials-secure.md +++ b/content/en/docs/tasks/inject-data-application/distribute-credentials-secure.md @@ -335,110 +335,101 @@ This functionality is available in Kubernetes v1.6 and later. password: 39528$vdg7Jb ``` -### Use case: Pods with prod / test credentials +## Example: Provide prod/test credentials to Pods using Secrets {#provide-prod-test-creds} This example illustrates a Pod which consumes a secret containing production credentials and another Pod which consumes a secret with test environment credentials. -You can create a `kustomization.yaml` with a `secretGenerator` field or run -`kubectl create secret`. +1. Create a secret for prod environment credentials: -```shell -kubectl create secret generic prod-db-secret --from-literal=username=produser --from-literal=password=Y4nys7f11 -``` - -The output is similar to: - -``` -secret "prod-db-secret" created -``` - -You can also create a secret for test environment credentials. - -```shell -kubectl create secret generic test-db-secret --from-literal=username=testuser --from-literal=password=iluvtests -``` - -The output is similar to: - -``` -secret "test-db-secret" created -``` - -{{< note >}} -Special characters such as `$`, `\`, `*`, `=`, and `!` will be interpreted by your -[shell](https://en.wikipedia.org/wiki/Shell_(computing)) and require escaping. - -In most shells, the easiest way to escape the password is to surround it with single quotes (`'`). -For example, if your actual password is `S!B\*d$zDsb=`, you should execute the command this way: - -```shell -kubectl create secret generic dev-db-secret --from-literal=username=devuser --from-literal=password='S!B\*d$zDsb=' -``` + ```shell + kubectl create secret generic prod-db-secret --from-literal=username=produser --from-literal=password=Y4nys7f11 + ``` -You do not need to escape special characters in passwords from files (`--from-file`). -{{< /note >}} + The output is similar to: -Now make the Pods: + ``` + secret "prod-db-secret" created + ``` -```shell -cat < pod.yaml -apiVersion: v1 -kind: List -items: -- kind: Pod - apiVersion: v1 - metadata: - name: prod-db-client-pod - labels: - name: prod-db-client - spec: - volumes: - - name: secret-volume - secret: - secretName: prod-db-secret - containers: - - name: db-client-container - image: myClientImage - volumeMounts: - - name: secret-volume - readOnly: true - mountPath: "/etc/secret-volume" -- kind: Pod - apiVersion: v1 - metadata: - name: test-db-client-pod - labels: - name: test-db-client - spec: - volumes: - - name: secret-volume - secret: - secretName: test-db-secret - containers: - - name: db-client-container - image: myClientImage - volumeMounts: - - name: secret-volume - readOnly: true - mountPath: "/etc/secret-volume" -EOF -``` +1. Create a secret for test environment credentials. -Add the pods to the same `kustomization.yaml`: + ```shell + kubectl create secret generic test-db-secret --from-literal=username=testuser --from-literal=password=iluvtests + ``` -```shell -cat <> kustomization.yaml -resources: -- pod.yaml -EOF -``` + The output is similar to: -Apply all those objects on the API server by running: + ``` + secret "test-db-secret" created + ``` -```shell -kubectl apply -k . -``` + {{< note >}} + Special characters such as `$`, `\`, `*`, `=`, and `!` will be interpreted by your + [shell](https://en.wikipedia.org/wiki/Shell_(computing)) and require escaping. + + In most shells, the easiest way to escape the password is to surround it with single quotes (`'`). + For example, if your actual password is `S!B\*d$zDsb=`, you should execute the command as follows: + + ```shell + kubectl create secret generic dev-db-secret --from-literal=username=devuser --from-literal=password='S!B\*d$zDsb=' + ``` + + You do not need to escape special characters in passwords from files (`--from-file`). + {{< /note >}} + +1. Create the Pod manifests: + + ```shell + cat < pod.yaml + apiVersion: v1 + kind: List + items: + - kind: Pod + apiVersion: v1 + metadata: + name: prod-db-client-pod + labels: + name: prod-db-client + spec: + volumes: + - name: secret-volume + secret: + secretName: prod-db-secret + containers: + - name: db-client-container + image: myClientImage + volumeMounts: + - name: secret-volume + readOnly: true + mountPath: "/etc/secret-volume" + - kind: Pod + apiVersion: v1 + metadata: + name: test-db-client-pod + labels: + name: test-db-client + spec: + volumes: + - name: secret-volume + secret: + secretName: test-db-secret + containers: + - name: db-client-container + image: myClientImage + volumeMounts: + - name: secret-volume + readOnly: true + mountPath: "/etc/secret-volume" + EOF + ``` + Note how the specs for the two Pods differ only in one field; this facilitates creating Pods with different capabilities from a common Pod template. + +1. Apply all those objects on the API server by running: + + ```shell + kubectl create -f pod.yaml + ``` Both containers will have the following files present on their filesystems with the values for each container's environment: @@ -448,9 +439,6 @@ for each container's environment: /etc/secret-volume/password ``` -Note how the specs for the two Pods differ only in one field; this facilitates -creating Pods with different capabilities from a common Pod template. - You could further simplify the base Pod specification by using two service accounts: 1. `prod-user` with the `prod-db-secret` From a9db7877a8ec15dc34be208c398e236e34e854ab Mon Sep 17 00:00:00 2001 From: Shannon Kularathna Date: Wed, 26 Jul 2023 21:18:54 +0000 Subject: [PATCH 5/5] Merge description of dotfile volume into the intro sentence. Content is exactly the same --- .../en/docs/concepts/configuration/secret.md | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/content/en/docs/concepts/configuration/secret.md b/content/en/docs/concepts/configuration/secret.md index 7ffe4d731d751..48e3cc4cb6669 100644 --- a/content/en/docs/concepts/configuration/secret.md +++ b/content/en/docs/concepts/configuration/secret.md @@ -69,7 +69,14 @@ help automate node registration. You can make your data "hidden" by defining a key that begins with a dot. This key represents a dotfile or "hidden" file. For example, when the following secret -is mounted into a volume, `secret-volume`: +is mounted into a volume, `secret-volume`, the volume will contain a single file, +called `.secret-file`, and the `dotfile-test-container` will have this file +present at the path `/etc/secret-volume/.secret-file`. + +{{< note >}} +Files beginning with dot characters are hidden from the output of `ls -l`; +you must use `ls -la` to see them when listing directory contents. +{{< /note >}} ```yaml apiVersion: v1 @@ -101,15 +108,6 @@ spec: mountPath: "/etc/secret-volume" ``` -The volume will contain a single file, called `.secret-file`, and -the `dotfile-test-container` will have this file present at the path -`/etc/secret-volume/.secret-file`. - -{{< note >}} -Files beginning with dot characters are hidden from the output of `ls -l`; -you must use `ls -la` to see them when listing directory contents. -{{< /note >}} - ### Use case: Secret visible to one container in a Pod Consider a program that needs to handle HTTP requests, do some complex business