概要
curlコマンドで直接APIに通信する方法は前回試しましたが、「kubectl proxy」を使い
認証を意識していなかったので、今回は認証Tokenを使ったやり方を試してみました。
※前回の記事はここを参照
環境
- 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=$(kubectl create token default)
-
例
tech-0222@MSI:~$ TOKEN=$(kubectl create token default) tech-0222@MSI:~$ echo $TOKEN eyJhbGciOiJSUzI1NiIsImtpZCI6IlZBMUhDRC1GLXhNZjlwa19TWUE5azl3QUlzY0xsMTdQLUlZb3NVOXgwT1UifQ.eyJhdWQiOlsiaHR0cHM6Ly9rdWJlcm5ldGVzLmRlZmF1bHQuc3ZjLmNsdXN0ZXIubG9jYWwiXSwiZXhwIjoxNzIwMzEwNTQ4LCJpYXQiOjE3MjAzMDY5NDgsImlzcyI6Imh0dHBzOi8va3ViZXJuZXRlcy5kZWZhdWx0LnN2Yy5jbHVzdGVyLmxvY2FsIiwia3ViZXJuZXRlcy5pbyI6eyJuYW1lc3BhY2UiOiJkZWZhdWx0Iiwic2VydmljZWFjY291bnQiOnsibmFtZSI6ImRlZmF1bHQiLCJ1aWQiOiI1MmVjZWFhMC04ZDJjLTRlN2YtOGFmYS0yZjZjODcyMmM5Y2EifX0sIm5iZiI6MTcyMDMwNjk0OCwic3ViIjoic3lzdGVtOnNlcnZpY2VhY2NvdW50OmRlZmF1bHQ6ZGVmYXVsdCJ9.ETGmbjvvLkQ3aF4np5WI1hEuTPudCajnjhBcaiVFE_G0ACLZIPZmZh5bPiLY5Jsy7qefpq15eKXKaHOBIkV98S-Tj-MQrpVdIskDI2FGwzhcHauYPmDV17kH9O8fpcR_xPEdi1Dq2O9FTcToNwwfpHpzGCuCdLm5VJ90KDR4_8kGzmu5Aic_NnYALOJ63Snk9uWvinPvsVa5d4uQpGFu_PY7EMkn5WN5NVe5ahMqxBlFozoIMyc8baxUmoqpMpVEouIBu5AZ72I_pV18etkzOwYEGIL_uoliOnwsRDyJTUC2T9uB64KGZtOmRRvRo0qJU_0l76fOP20ZO1ryIe__EA 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)は、SSL警告を無視する
- 「--header」 (-H)は、httpヘッダにリクエストを追加する
- 「-X」 (--request)はHTTPのメソッドを指定する
補足
Tokenの有効期間
コマンド"kubectl create token XXX"で作成できるTokenは有効期間があるTokenです。
defaultの有効期限が気になりますが、設定や公式ドキュメントでは見つけることができませんでした。
ただ、ここの「--duration」で以下文書があるので、サーバ毎に設定するものと思われます。
発行されたトークンの要求された有効期間。設定されていない場合、または 0 に設定されている場合、
有効期間はサーバーによって自動的に決定されます。サーバーは、より長いまたはより短い有効期間を
持つトークンを返す場合があります。
サーバの有効期限を簡単に確認するには、オプション(--duration)を指定せずにログレベルを変えて
コマンド"kubectl create token "を実行すると簡単に確認できます。
以下例だとResponse Body 内の”"expirationSeconds":3600”が該当箇所になり、
有効期限は3600秒(1時間)みたいですね。
- 例
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: {"kind":"TokenRequest","apiVersion":"authentication.k8s.io/v1","metadata":{"name":"default","namespace":"default","creationTimestamp":"2024-07-07T08:27:30Z","managedFields":[{"manager":"kubectl","operation":"Update","apiVersion":"authentication.k8s.io/v1","time":"2024-07-07T08:27:30Z","fieldsType":"FieldsV1","fieldsV1":{"f:spec":{"f:expirationSeconds":{}}},"subresource":"token"}]},"spec":{"audiences":["https://kubernetes.default.svc.cluster.local"],"expirationSeconds":3600,"boundObjectRef":null},"status":{"token":"eyJhbGciOiJSUzI1NiIsImtpZCI6IlZBMUhDRC1GLXhNZjlwa19TWUE5azl3QUlzY0xsMTdQLUlZb3NVOXgwT1UifQ.eyJhdWQiOlsiaHR0cHM6Ly9rdWJlcm5ldGVzLmRlZmF1bHQuc3ZjLmNsdXN0ZXIubG9jYWwiXSwiZXhwIjoxNzIwMzQ0NDUwLCJpYXQiOjE3MjAzNDA4NTAsImlzcyI6Imh0dHBzOi8va3ViZXJuZXRlcy5kZWZhdWx0LnN2Yy5jbHVzdGVyLmxvY2FsIiwia3ViZXJuZXRlcy5pbyI6eyJuYW1lc3BhY2UiOiJkZWZhdWx0Iiwic2VydmljZWFjY291bnQiOnsibmFtZSI6ImRlZmF1bHQiLCJ1aWQiOiI1MmVjZWFhMC04ZDJjLTRlN2YtOGFmYS0yZjZjODcyMmM5Y2EifX0sIm5iZiI6MTcyMDM0MDg1MCwic3ViIjoic3lzdGVtOnNlcnZpY2VhY2NvdW50O [truncated 415 chars] eyJhbGciOiJSUzI1NiIsImtpZCI6IlZBMUhDRC1GLXhNZjlwa19TWUE5azl3QUlzY0xsMTdQLUlZb3NVOXgwT1UifQ.eyJhdWQiOlsiaHR0cHM6Ly9rdWJlcm5ldGVzLmRlZmF1bHQuc3ZjLmNsdXN0ZXIubG9jYWwiXSwiZXhwIjoxNzIwMzQ0NDUwLCJpYXQiOjE3MjAzNDA4NTAsImlzcyI6Imh0dHBzOi8va3ViZXJuZXRlcy5kZWZhdWx0LnN2Yy5jbHVzdGVyLmxvY2FsIiwia3ViZXJuZXRlcy5pbyI6eyJuYW1lc3BhY2UiOiJkZWZhdWx0Iiwic2VydmljZWFjY291bnQiOnsibmFtZSI6ImRlZmF1bHQiLCJ1aWQiOiI1MmVjZWFhMC04ZDJjLTRlN2YtOGFmYS0yZjZjODcyMmM5Y2EifX0sIm5iZiI6MTcyMDM0MDg1MCwic3ViIjoic3lzdGVtOnNlcnZpY2VhY2NvdW50OmRlZmF1bHQ6ZGVmYXVsdCJ9.rN0FjTubF5rynUPDqOUMR82QdohiN1nqD7zcR0iLAzmevCbGqIE2p9Rz9THNkIlTcB5QQav1WbLds0jFB9X78xJBc5cLecDdMxyWv8NwogtYBOZF1sVlDrwbd6rgiYwlyn68zLL0DM0AmpgvfS8LQf2ukVre6DyBNau78IB2_XBC92N0Li97DM6AvUhHpMzCrVYiBtC9kSDxSJvcDdwbMowhmohefQ8jyeH6f5-otyU-M5zXff97Z2RZNukkxGthNJRn8SIY4Zz_jpWWHivqTezDSuJnkQkKrms2xAQOpkybCXn73y_iIPzgGlF8BWYoym1ZvjI1H6xOaXEphPGt5A 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: ZXlKaGJHY2lPaUpTVXpJMU5pSXNJbXRwWkNJNklsWkJNVWhEUkMxR0xYaE5aamx3YTE5VFdVRTVhemwzUVVselkweHNNVGRRTFVsWmIzTlZPWGd3VDFVaWZRLmV5SnBjM01pT2lKcmRXSmxjbTVsZEdWekwzTmxjblpwWTJWaFkyTnZkVzUwSWl3aWEzVmlaWEp1WlhSbGN5NXBieTl6WlhKMmFXTmxZV05qYjNWdWRDOXVZVzFsYzNCaFkyVWlPaUprWldaaGRXeDBJaXdpYTNWaVpYSnVaWFJsY3k1cGJ5OXpaWEoyYVdObFlXTmpiM1Z1ZEM5elpXTnlaWFF1Ym1GdFpTSTZJbVJsWm1GMWJIUXRkRzlyWlc0aUxDSnJkV0psY201bGRHVnpMbWx2TDNObGNuWnBZMlZoWTJOdmRXNTBMM05sY25acFkyVXRZV05qYjNWdWRDNXVZVzFsSWpvaVpHVm1ZWFZzZENJc0ltdDFZbVZ5Ym1WMFpYTXVhVzh2YzJWeWRtbGpaV0ZqWTI5MWJuUXZjMlZ5ZG1salpTMWhZMk52ZFc1MExuVnBaQ0k2SWpVeVpXTmxZV0V3TFRoa01tTXROR1UzWmkwNFlXWmhMVEptTm1NNE56SXlZemxqWVNJc0luTjFZaUk2SW5ONWMzUmxiVHB6WlhKMmFXTmxZV05qYjNWdWREcGtaV1poZFd4ME9tUmxabUYxYkhRaWZRLnhXS0hxS0RfckplSWFvdENVeTFjOUpXaEtiQlNGcXpYY3h6V0tLanY1TE1Za0NVcEFDWThGWF8yb2V4UEdtZDllemFaa1NYZFNpTjhaVVVzY2dUVkg3eWcwZjdDbGRoeHo0TGNfQU9NSmtySmlHSlVDNHRLVkZMWGxlSUpVSVU4eksyUUVpY3hqcFEtaW84N25LOW5rZkRoNC1YUFdRNmNxZ0p2Zjg0bW1iRk9KSVVKSU5nNDAyMEVSWmlaZmpkVGFfNjZQOU45bVY2c1dHYWgtbmRwZEtJSWtRSEJidDZtVmlrWHNiNmN3VWVJbUtXSFl3cHdnU0c2bWFPOGVsSVZhMFc1a2F4Mk9ZeHY4cENleEdvZU92VlpyUlpuRDNSMTllazE0Tl9HelktSDlPSUJWMU83dGJ6TDd2SEZZVHlpRnhGQUNyUk1mZWRBSjBadmx2X2lFQQ==
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 secrets -o jsonpath="{.items[?(@.metadata.annotations['kubernetes\.io/service-account\.name']=='default')].data.token}"|base64 --decode)
tech-0222@MSI:~$
tech-0222@MSI:~$ echo $TOKEN
eyJhbGciOiJSUzI1NiIsImtpZCI6IlZBMUhDRC1GLXhNZjlwa19TWUE5azl3QUlzY0xsMTdQLUlZb3NVOXgwT1UifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZWZhdWx0Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6ImRlZmF1bHQtdG9rZW4iLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoiZGVmYXVsdCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6IjUyZWNlYWEwLThkMmMtNGU3Zi04YWZhLTJmNmM4NzIyYzljYSIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDpkZWZhdWx0OmRlZmF1bHQifQ.xWKHqKD_rJeIaotCUy1c9JWhKbBSFqzXcxzWKKjv5LMYkCUpACY8FX_2oexPGmd9ezaZkSXdSiN8ZUUscgTVH7yg0f7Cldhxz4Lc_AOMJkrJiGJUC4tKVFLXleIJUIU8zK2QEicxjpQ-io87nK9nkfDh4-XPWQ6cqgJvf84mmbFOJIUJINg4020ERZiZfjdTa_66P9N9mV6sWGah-ndpdKIIkQHBbt6mVikXsb6cwUeImKWHYwpwgSG6maO8elIVa0W5kax2OYxv8pCexGoeOvVZrRZnD3R19ek14N_GzY-H9OIBV1O7tbzL7vHFYTyiFxFACrRMfedAJ0Zvlv_iEA
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:~$
#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:~$
ただし、ここでは、この方法は非推奨と書かれているので利用する際には注意がいりますね。