概要 #
curlコマンドで直接APIに通信する方法は前回試しましたが、「kubectl proxy」を使い 認証を意識していなかったので、今回は認証Tokenを使ったやり方を試してみました。※前回のKubernetes APIをkubectlではなくcurlで呼び出す記事を参照
環境 #
- minikube version: v1.32.0
- Kubernetes v1.28.3
- Ubuntu 22.04.4 LTS(WSL)
やってみたこと #
kubeconfigから全てのCluster名を確認 #
-
コマンド
kubectl config view -o jsonpath='{"Cluster name\tServer\n"}{range .clusters[*]}{.name}{"\t"}{.cluster.server}{"\n"}{end}' -
例
tech-0222@MSI:~$ kubectl config view -o jsonpath='{"Cluster name\tServer\n"}{range .clusters[*]}{.name}{"\t"}{.cluster.server}{"\n"}{end}' Cluster name Server test https://127.0.0.1:32784 tech-0222@MSI:~$
呼び出ししたいCluster名を変数にセット #
-
コマンド
export CLUSTER_NAME="some_server_name" -
例
export CLUSTER_NAME="test" -
結果
tech-0222@MSI:~$ export CLUSTER_NAME="test" tech-0222@MSI:~$ tech-0222@MSI:~$ echo $CLUSTER_NAME test tech-0222@MSI:~$
ClusterのアクセスURLを変数に設定 #
-
コマンド
APISERVER=$(kubectl config view -o jsonpath="{.clusters[?(@.name==\"$CLUSTER_NAME\")].cluster.server}") -
例
tech-0222@MSI:~$ APISERVER=$(kubectl config view -o jsonpath="{.clusters[?(@.name==\"$CLUSTER_NAME\")].cluster.server}") tech-0222@MSI:~$ echo $APISERVER https://127.0.0.1:32784 tech-0222@MSI:~$defaultのServiceAccountからTokenを作成 #
Tokenは認証情報です。以下の出力例では値を掲載しません。取得確認には値を表示せず、変数が空でないことだけを確認します。
-
コマンド
TOKEN=$(kubectl create token default) -
例
tech-0222@MSI:~$ TOKEN=$(kubectl create token default) tech-0222@MSI:~$ test -n "$TOKEN" && echo "Token取得済み" Token取得済み tech-0222@MSI:~$curl でAPIを呼び出してみる #
リクエストに対して以下例のようにレスポンスが返ってくれば Tokenによる認証を行いAPIが実行できています。
-
コマンド
curl -X GET $APISERVER/api --header "Authorization: Bearer $TOKEN" --insecure -
例
tech-0222@MSI:~$ curl -X GET $APISERVER/api --header "Authorization: Bearer $TOKEN" --insecure { "kind": "APIVersions", "versions": [ "v1" ], "serverAddressByClientCIDRs": [ { "clientCIDR": "0.0.0.0/0", "serverAddress": "192.168.67.2:8443" } ] }tech-0222@MSI:~$ちなみに、API実行のcurl オプションの意味は以下です。
-
「–insecure」 (-k)は、TLS証明書の検証をスキップする
-
「–header」 (-H)は、httpヘッダにリクエストを追加する
-
「-X」 (–request)はHTTPのメソッドを指定する
補足 #
Tokenの有効期間 #
kubectl create tokenで発行するTokenには有効期間があります。--durationを省略した場合の期間は、APIサーバーが決めます。
公式リファレンスには、--durationについて次の説明があります。
発行されたトークンの要求された有効期間。設定されていない場合、または 0 に設定されている場合、有効期間はサーバーによって自動的に決定されます。サーバーは、より長いまたはより短い有効期間を 持つトークンを返す場合があります。
以下では--v=8でTokenRequestの内容を確認します。実際の失効時刻を示す出力とは区別してください。
以下のResponse Bodyでは、spec.expirationSecondsが3600秒です。これは要求された有効期間であり、実際の失効時刻はTokenのexpなどで確認します。
--v=8のデバッグ出力とコマンドの標準出力にはTokenが含まれます。ログを保存・共有する場合は、Tokenを伏せてください。
-
例
tech-0222@MSI:~$ kubectl create token default --v=8 I0707 17:27:30.419698 1833212 loader.go:395] Config loaded from file: /home/tech-0222/.kube/config I0707 17:27:30.420420 1833212 cert_rotation.go:137] Starting client certificate rotation controller I0707 17:27:30.420661 1833212 request.go:1212] Request Body: {"kind":"TokenRequest","apiVersion":"authentication.k8s.io/v1","metadata":{"creationTimestamp":null},"spec":{"audiences":null,"expirationSeconds":null,"boundObjectRef":null},"status":{"token":"","expirationTimestamp":null}} I0707 17:27:30.420755 1833212 round_trippers.go:463] POST https://127.0.0.1:32784/api/v1/namespaces/default/serviceaccounts/default/token I0707 17:27:30.420779 1833212 round_trippers.go:469] Request Headers: I0707 17:27:30.420787 1833212 round_trippers.go:473] Accept: application/json, */* I0707 17:27:30.420829 1833212 round_trippers.go:473] Content-Type: application/json I0707 17:27:30.420845 1833212 round_trippers.go:473] User-Agent: kubectl/v1.28.2 (linux/amd64) kubernetes/89a4ea3 I0707 17:27:30.429270 1833212 round_trippers.go:574] Response Status: 201 Created in 8 milliseconds I0707 17:27:30.429293 1833212 round_trippers.go:577] Response Headers: I0707 17:27:30.429298 1833212 round_trippers.go:580] X-Kubernetes-Pf-Prioritylevel-Uid: e9925eb0-9df8-4d18-8eb2-c2944fbabe8d I0707 17:27:30.429310 1833212 round_trippers.go:580] Content-Length: 1439 I0707 17:27:30.429319 1833212 round_trippers.go:580] Date: Sun, 07 Jul 2024 08:27:30 GMT I0707 17:27:30.429323 1833212 round_trippers.go:580] Audit-Id: 3383d33e-e93f-44c5-bf71-8c87996ba6a6 I0707 17:27:30.429326 1833212 round_trippers.go:580] Cache-Control: no-cache, private I0707 17:27:30.429330 1833212 round_trippers.go:580] Content-Type: application/json I0707 17:27:30.429334 1833212 round_trippers.go:580] X-Kubernetes-Pf-Flowschema-Uid: f54fb6b1-342b-4e6e-875a-ba24f54cf8f2 I0707 17:27:30.429373 1833212 request.go:1212] Response Body(Tokenを伏せた抜粋): {"spec":{"expirationSeconds":3600},"status":{"token":"<非掲載>"}} <Tokenの値は非掲載> tech-0222@MSI:~$Tokenの永続化 #
特別なアノテーションを使用して新しい Secret を作成することでTokenを永続化できるみたいです。※ServiceAccount の長期 API トークンを手動で作成する
- 実行例
- デフォルトであるServiceAccountのdefaultのTokenでSecretを作成
tech-0222@MSI:~$
tech-0222@MSI:~$ kubectl get secrets
No resources found in default namespace.
tech-0222@MSI:~$
tech-0222@MSI:~$ 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
secret/default-token created
tech-0222@MSI:~$ kubectl get secrets
NAME TYPE DATA AGE
default-token kubernetes.io/service-account-token 3 4s
tech-0222@MSI:~$
tech-0222@MSI:~$ kubectl get secrets -o yaml
apiVersion: v1
items:
- apiVersion: v1
data:
ca.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURCakNDQWU2Z0F3SUJBZ0lCQVRBTkJna3Foa2lHOXcwQkFRc0ZBREFWTVJNd0VRWURWUVFERXdwdGFXNXAKYTNWaVpVTkJNQjRYRFRJME1ERXdNekF4TXpjeE0xb1hEVE0wTURFd01UQXhNemN4TTFvd0ZURVRNQkVHQTFVRQpBeE1LYldsdWFXdDFZbVZEUVRDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBT1NvCmZnSjNRSitUNG1jd3ZQMnFPT3VMc2ZweUpBenYrQmNRNUFiRWZvL3BXS3dOMkt3Y1pBUm5kOUY1b3kwcEp4a0gKMDJNbHEycm1nTVNqN1A2cktab0lmZW5VS3NxbXg5dmtGRlVZa1RscFlmRHpCWUt1alhEM1phdTVyL2YyUmwyTQpDMWRzdTlyWXlRTWY2STd1Rm1iWEFuc1VlcGt5U0ptMWczTXVGbDE2QytUTzhyKzNvZ3VBVzZkN2piVlk5S2RECk9icnBySjBEallRS2JRdmNlWFloNXZoZlBwTVpObjdWclpZTDZDTXF1c29UYmJ1eUFqanlXRHdxYW54ZzRvZmgKbTVWRUZMRDRsRWZlNm43TnZHVm0rcy9uZlN6OXpsRjBNVFNpUEhPbCtzdVNpcTFWMTQxbytybGYrMk52UXJnNgpwNkxjZnFhNllqeUR6aDlLTTFjQ0F3RUFBYU5oTUY4d0RnWURWUjBQQVFIL0JBUURBZ0trTUIwR0ExVWRKUVFXCk1CUUdDQ3NHQVFVRkJ3TUNCZ2dyQmdFRkJRY0RBVEFQQmdOVkhSTUJBZjhFQlRBREFRSC9NQjBHQTFVZERnUVcKQkJUa0xCWmlNREpKSXl0aGV5V2NUWVk3YVN3VUtqQU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFUY2lnMkVKSwpoMTQxaEwyYU0vaXlVdkxWNjJPMjIwN2JzZm01ajNOWk01YXN4VUxxMGJGN09mNEVma2ozTU1Fa005VkVUM0R0Cml0ZW1qeXdHV1EyQlZsZGRJUmU3czUvUng0SlpkK1h5Z2YyeC9QL1drdFhpc3FqZEMraXlwVFFJek5Ib2NnTUwKSCtTR1d5ZjhTTWZXb0J1aXpBYTdENmJqTXVCV25xL1dvUDhoTC9MUHVJdUtwTU1mMjNscXdFMnRUM1R4ZmdJMQpPWGdST29DbDR0dmhnSXZUdDQxSi9ScGt0Skk2QXYwem8yZ1BjZnVEMTFzOEhhL0dMdm05MEd4OFkrTmYyZklBCmg3eUlUR3Y5VGp0bnozdVVhYzVkakEyOUl5V09wcGdiVVlab0NaUmU3elkxaWF2b0haL2xvNU43YW8wSmM5SnQKN2h5QndWL3JlNFgzeFE9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
namespace: ZGVmYXVsdA==
token: <Tokenの値は非掲載>
kind: Secret
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"v1","kind":"Secret","metadata":{"annotations":{"kubernetes.io/service-account.name":"default"},"name":"default-token","namespace":"default"},"type":"kubernetes.io/service-account-token"}
kubernetes.io/service-account.name: default
kubernetes.io/service-account.uid: 52eceaa0-8d2c-4e7f-8afa-2f6c8722c9ca
creationTimestamp: "2024-07-07T08:41:41Z"
name: default-token
namespace: default
resourceVersion: "20292"
uid: 6be44e73-b3bd-4c11-8333-2f6fb2076c15
type: kubernetes.io/service-account-token
kind: List
metadata:
resourceVersion: ""
tech-0222@MSI:~$
- 作成したSecretでのAPIアクセス例
#作成したSecretのTokenをデコードして変数にセット
tech-0222@MSI:~$ TOKEN=$(kubectl get secret default-token -o jsonpath='{.data.token}' | base64 --decode)
tech-0222@MSI:~$
tech-0222@MSI:~$ test -n "$TOKEN" && echo "Token取得済み"
Token取得済み
tech-0222@MSI:~$
# API実行
tech-0222@MSI:~$ curl -X GET $APISERVER/api --header "Authorization: Bearer $TOKEN" --insecure
{
"kind": "APIVersions",
"versions": [
"v1"
],
"serverAddressByClientCIDRs": [
{
"clientCIDR": "0.0.0.0/0",
"serverAddress": "192.168.67.2:8443"
}
]
}tech-0222@MSI:~$
#Secret削除後、同じTokenでのAPIアクセスを確認
#
tech-0222@MSI:~$ kubectl delete secrets default-token
secret "default-token" deleted
tech-0222@MSI:~$
tech-0222@MSI:~$ curl -X GET $APISERVER/api --header "Authorization: Bearer $TOKEN" --insecure
{
"kind": "Status",
"apiVersion": "v1",
"metadata": {},
"status": "Failure",
"message": "Unauthorized",
"reason": "Unauthorized",
"code": 401
}tech-0222@MSI:~$
この環境ではSecretの削除後、同じTokenでのAPIアクセスは401 Unauthorizedになりました。
Kubernetes公式ドキュメントは、TokenRequest APIが使えない場合に限って長期TokenのSecretを作成するよう案内しています。