Merge pull request #31845 from liggitt/manual-token

Stop recommending people scrape auto-generated service account tokens
This commit is contained in:
Kubernetes Prow Robot 2022-02-24 09:46:31 -08:00 committed by GitHub
commit 9de083393a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 60 additions and 35 deletions

View File

@ -146,14 +146,6 @@ data:
extra: YmFyCg== extra: YmFyCg==
``` ```
When creating a `Pod`, Kubernetes automatically creates a service account Secret
and automatically modifies your Pod to use this Secret. The service account token
Secret contains credentials for accessing the API.
The automatic creation and use of API credentials can be disabled or
overridden if desired. However, if all you need to do is securely access the
API server, this is the recommended workflow.
See the [ServiceAccount](/docs/tasks/configure-pod-container/configure-service-account/) See the [ServiceAccount](/docs/tasks/configure-pod-container/configure-service-account/)
documentation for more information on how service accounts work. documentation for more information on how service accounts work.
You can also check the `automountServiceAccountToken` field and the You can also check the `automountServiceAccountToken` field and the
@ -161,6 +153,19 @@ You can also check the `automountServiceAccountToken` field and the
[`Pod`](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#pod-v1-core) [`Pod`](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#pod-v1-core)
for information on referencing service account from Pods. for information on referencing service account from Pods.
{{< note >}}
Automatic creation of API credentials in secrets to mount into running pods
is no longer used in v1.22 and newer versions. Instead, 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.
Service account token secrets can still be created manually if you need a token that never expires,
However, using the [TokenRequest](/docs/reference/kubernetes-api/authentication-resources/token-request-v1/)
API to obtain a token to access the API is recommended instead.
{{< /note >}}
### Docker config Secrets ### Docker config Secrets
You can use one of the following `type` values to create a Secret to You can use one of the following `type` values to create a Secret to

View File

@ -86,12 +86,36 @@ The output is similar to this:
### Without kubectl proxy ### Without kubectl proxy
Use `kubectl describe secret...` to get the token for the default service account with grep/cut: Use `kubectl apply` and `kubectl describe secret...` to create a token for the default service account with grep/cut:
First, create the Secret, requesting a token for the default ServiceAccount:
```shell
kubectl apply -f - <<EOF
apiVersion: v1
kind: Secret
metadata:
name: default-token
annotations:
kubernetes.io/service-account.name: default
type: kubernetes.io/service-account-token
EOF
```
Next, wait for the token controller to populate the Secret with a token:
```shell
while ! kubectl describe secret default-token | grep -E '^token' >/dev/null; do
echo "waiting for token..." >&2
sleep 1
done
```
Capture and use the generated token:
```shell ```shell
APISERVER=$(kubectl config view --minify | grep server | cut -f 2- -d ":" | tr -d " ") APISERVER=$(kubectl config view --minify | grep server | cut -f 2- -d ":" | tr -d " ")
SECRET_NAME=$(kubectl get secrets | grep ^default | cut -f1 -d ' ') TOKEN=$(kubectl describe secret default-token | grep -E '^token' | cut -f2 -d':' | tr -d " ")
TOKEN=$(kubectl describe secret $SECRET_NAME | grep -E '^token' | cut -f2 -d':' | tr -d " ")
curl $APISERVER/api --header "Authorization: Bearer $TOKEN" --insecure curl $APISERVER/api --header "Authorization: Bearer $TOKEN" --insecure
``` ```
@ -117,8 +141,7 @@ Using `jsonpath`:
```shell ```shell
APISERVER=$(kubectl config view --minify -o jsonpath='{.clusters[0].cluster.server}') APISERVER=$(kubectl config view --minify -o jsonpath='{.clusters[0].cluster.server}')
SECRET_NAME=$(kubectl get serviceaccount default -o jsonpath='{.secrets[0].name}') TOKEN=$(kubectl get secret default-token -o jsonpath='{.data.token}' | base64 --decode)
TOKEN=$(kubectl get secret $SECRET_NAME -o jsonpath='{.data.token}' | base64 --decode)
curl $APISERVER/api --header "Authorization: Bearer $TOKEN" --insecure curl $APISERVER/api --header "Authorization: Bearer $TOKEN" --insecure
``` ```

View File

@ -95,8 +95,25 @@ export CLUSTER_NAME="some_server_name"
# Point to the API server referring the cluster name # Point to the API server referring the cluster name
APISERVER=$(kubectl config view -o jsonpath="{.clusters[?(@.name==\"$CLUSTER_NAME\")].cluster.server}") APISERVER=$(kubectl config view -o jsonpath="{.clusters[?(@.name==\"$CLUSTER_NAME\")].cluster.server}")
# Gets the token value # Create a secret to hold a token for the default service account
TOKEN=$(kubectl get secrets -o jsonpath="{.items[?(@.metadata.annotations['kubernetes\.io/service-account\.name']=='default')].data.token}"|base64 --decode) kubectl apply -f - <<EOF
apiVersion: v1
kind: Secret
metadata:
name: default-token
annotations:
kubernetes.io/service-account.name: default
type: kubernetes.io/service-account-token
EOF
# Wait for the token controller to populate the secret with a token:
while ! kubectl describe secret default-token | grep -E '^token' >/dev/null; do
echo "waiting for token..." >&2
sleep 1
done
# Get the token value
TOKEN=$(kubectl get secret default-token -o jsonpath='{.data.token}' | base64 --decode)
# Explore the API with TOKEN # Explore the API with TOKEN
curl -X GET $APISERVER/api --header "Authorization: Bearer $TOKEN" --insecure curl -X GET $APISERVER/api --header "Authorization: Bearer $TOKEN" --insecure
@ -119,26 +136,6 @@ The output is similar to this:
} }
``` ```
Using `jsonpath` approach:
```shell
APISERVER=$(kubectl config view --minify -o jsonpath='{.clusters[0].cluster.server}')
TOKEN=$(kubectl get secret $(kubectl get serviceaccount default -o jsonpath='{.secrets[0].name}') -o jsonpath='{.data.token}' | base64 --decode )
curl $APISERVER/api --header "Authorization: Bearer $TOKEN" --insecure
{
"kind": "APIVersions",
"versions": [
"v1"
],
"serverAddressByClientCIDRs": [
{
"clientCIDR": "0.0.0.0/0",
"serverAddress": "10.0.1.149:443"
}
]
}
```
The above example uses the `--insecure` flag. This leaves it subject to MITM The above example uses the `--insecure` flag. This leaves it subject to MITM
attacks. When kubectl accesses the cluster it uses a stored root certificate attacks. When kubectl accesses the cluster it uses a stored root certificate
and client certificates to access the server. (These are installed in the and client certificates to access the server. (These are installed in the