Skip to content

Commit 3d15ef3

Browse files
committed
Stop recommending people scrape auto-generated service account tokens
1 parent 1b1917c commit 3d15ef3

File tree

3 files changed

+60
-35
lines changed

3 files changed

+60
-35
lines changed

content/en/docs/concepts/configuration/secret.md

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -146,21 +146,26 @@ data:
146146
extra: YmFyCg==
147147
```
148148
149-
When creating a `Pod`, Kubernetes automatically creates a service account Secret
150-
and automatically modifies your Pod to use this Secret. The service account token
151-
Secret contains credentials for accessing the API.
152-
153-
The automatic creation and use of API credentials can be disabled or
154-
overridden if desired. However, if all you need to do is securely access the
155-
API server, this is the recommended workflow.
156-
157149
See the [ServiceAccount](/docs/tasks/configure-pod-container/configure-service-account/)
158150
documentation for more information on how service accounts work.
159151
You can also check the `automountServiceAccountToken` field and the
160152
`serviceAccountName` field of the
161153
[`Pod`](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#pod-v1-core)
162154
for information on referencing service account from Pods.
163155

156+
{{< note >}}
157+
Automatic creation of API credentials in secrets to mount into running pods
158+
is no longer used in v1.22 and newer versions. Instead, API credentials are
159+
obtained directly by using the [TokenRequest](/docs/reference/kubernetes-api/authentication-resources/token-request-v1/) API,
160+
and are mounted into Pods using a [projected volume](/docs/reference/access-authn-authz/service-accounts-admin/#bound-service-account-token-volume).
161+
The tokens obtained using this method have bounded lifetimes, and are automatically
162+
invalidated when the Pod they are mounted into is deleted.
163+
164+
Service account token secrets can still be created manually if you need a token that never expires,
165+
However, using the [TokenRequest](/docs/reference/kubernetes-api/authentication-resources/token-request-v1/)
166+
API to obtain a token to access the API is recommended instead.
167+
{{< /note >}}
168+
164169
### Docker config Secrets
165170

166171
You can use one of the following `type` values to create a Secret to

content/en/docs/tasks/access-application-cluster/access-cluster.md

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -86,12 +86,36 @@ The output is similar to this:
8686

8787
### Without kubectl proxy
8888

89-
Use `kubectl describe secret...` to get the token for the default service account with grep/cut:
89+
Use `kubectl apply` and `kubectl describe secret...` to create a token for the default service account with grep/cut:
90+
91+
First, create the Secret, requesting a token for the default ServiceAccount:
92+
93+
```shell
94+
kubectl apply -f - <<EOF
95+
apiVersion: v1
96+
kind: Secret
97+
metadata:
98+
name: default-token
99+
annotations:
100+
kubernetes.io/service-account.name: default
101+
type: kubernetes.io/service-account-token
102+
EOF
103+
```
104+
105+
Next, wait for the token controller to populate the Secret with a token:
106+
107+
```shell
108+
while ! kubectl describe secret default-token | grep -E '^token' >/dev/null; do
109+
echo "waiting for token..." >&2
110+
sleep 1
111+
done
112+
```
113+
114+
Capture and use the generated token:
90115

91116
```shell
92117
APISERVER=$(kubectl config view --minify | grep server | cut -f 2- -d ":" | tr -d " ")
93-
SECRET_NAME=$(kubectl get secrets | grep ^default | cut -f1 -d ' ')
94-
TOKEN=$(kubectl describe secret $SECRET_NAME | grep -E '^token' | cut -f2 -d':' | tr -d " ")
118+
TOKEN=$(kubectl describe secret default-token | grep -E '^token' | cut -f2 -d':' | tr -d " ")
95119

96120
curl $APISERVER/api --header "Authorization: Bearer $TOKEN" --insecure
97121
```
@@ -117,8 +141,7 @@ Using `jsonpath`:
117141

118142
```shell
119143
APISERVER=$(kubectl config view --minify -o jsonpath='{.clusters[0].cluster.server}')
120-
SECRET_NAME=$(kubectl get serviceaccount default -o jsonpath='{.secrets[0].name}')
121-
TOKEN=$(kubectl get secret $SECRET_NAME -o jsonpath='{.data.token}' | base64 --decode)
144+
TOKEN=$(kubectl get secret default-token -o jsonpath='{.data.token}' | base64 --decode)
122145

123146
curl $APISERVER/api --header "Authorization: Bearer $TOKEN" --insecure
124147
```

content/en/docs/tasks/administer-cluster/access-cluster-api.md

Lines changed: 19 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,25 @@ export CLUSTER_NAME="some_server_name"
9595
# Point to the API server referring the cluster name
9696
APISERVER=$(kubectl config view -o jsonpath="{.clusters[?(@.name==\"$CLUSTER_NAME\")].cluster.server}")
9797

98-
# Gets the token value
99-
TOKEN=$(kubectl get secrets -o jsonpath="{.items[?(@.metadata.annotations['kubernetes\.io/service-account\.name']=='default')].data.token}"|base64 --decode)
98+
# Create a secret to hold a token for the default service account
99+
kubectl apply -f - <<EOF
100+
apiVersion: v1
101+
kind: Secret
102+
metadata:
103+
name: default-token
104+
annotations:
105+
kubernetes.io/service-account.name: default
106+
type: kubernetes.io/service-account-token
107+
EOF
108+
109+
# Wait for the token controller to populate the secret with a token:
110+
while ! kubectl describe secret default-token | grep -E '^token' >/dev/null; do
111+
echo "waiting for token..." >&2
112+
sleep 1
113+
done
114+
115+
# Get the token value
116+
TOKEN=$(kubectl get secret default-token -o jsonpath='{.data.token}' | base64 --decode)
100117

101118
# Explore the API with TOKEN
102119
curl -X GET $APISERVER/api --header "Authorization: Bearer $TOKEN" --insecure
@@ -119,26 +136,6 @@ The output is similar to this:
119136
}
120137
```
121138

122-
Using `jsonpath` approach:
123-
124-
```shell
125-
APISERVER=$(kubectl config view --minify -o jsonpath='{.clusters[0].cluster.server}')
126-
TOKEN=$(kubectl get secret $(kubectl get serviceaccount default -o jsonpath='{.secrets[0].name}') -o jsonpath='{.data.token}' | base64 --decode )
127-
curl $APISERVER/api --header "Authorization: Bearer $TOKEN" --insecure
128-
{
129-
"kind": "APIVersions",
130-
"versions": [
131-
"v1"
132-
],
133-
"serverAddressByClientCIDRs": [
134-
{
135-
"clientCIDR": "0.0.0.0/0",
136-
"serverAddress": "10.0.1.149:443"
137-
}
138-
]
139-
}
140-
```
141-
142139
The above example uses the `--insecure` flag. This leaves it subject to MITM
143140
attacks. When kubectl accesses the cluster it uses a stored root certificate
144141
and client certificates to access the server. (These are installed in the

0 commit comments

Comments
 (0)