EKSクラスターへのアクセスは普通はIAMで行うが、それ以外のやり方で行うとしたら以下がありそう。
- ユーザーの証明書を発行する
- ServiceAccountを作ってそのトークンをダウンロードして使う
できるのかを確認しようとしたメモ。
コンポーネント | バージョン | 備考 |
---|---|---|
Kubernetes | 1.18 | |
eksプラットフォームバージョン | eks.3 |
証明書
証明書でアクセスできるかを確認する。
CertificateSigningRequestをリソースを作ってあげると署名されて返ってくる。
秘密鍵を作成する。
$ openssl genrsa -out jane.key 2048 Generating RSA private key, 2048 bit long modulus ..........+++ ...............................................................................................................+++ e is 65537 (0x10001)
CSRを作成する。
$ openssl req -new -key jane.key -out jane.csr You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) []: State or Province Name (full name) []: Locality Name (eg, city) []: Organization Name (eg, company) []: Organizational Unit Name (eg, section) []: Common Name (eg, fully qualified host name) []:jane Email Address []: Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []:
# Linux # cat jane.csr | base64 -w 0 # CSR=$(cat jane.csr | base64 -w 0) # Mac cat jane.csr | base64 CSR=$(cat jane.csr | base64)
yamlを作成する。EKSの1.18のクラスターの場合はapiVersion: certificates.k8s.io/v1
ではなくcertificates.k8s.io/v1beta1
とする必要があった。
# 1.19以上? cat <<EOF > csr.yaml apiVersion: certificates.k8s.io/v1 kind: CertificateSigningRequest metadata: name: jane spec: groups: - system:authenticated request: ${CSR} signerName: kubernetes.io/kube-apiserver-client usages: - client auth EOF # 1.18以下? cat <<EOF > csr.yaml apiVersion: certificates.k8s.io/v1beta1 kind: CertificateSigningRequest metadata: name: jane spec: groups: - system:authenticated request: ${CSR} signerName: kubernetes.io/kube-apiserver-client usages: - client auth EOF
CSRリソースを作成する。
$ k apply -f csr.yaml certificatesigningrequest.certificates.k8s.io/jane created
状態を確認する。
$ k get csr NAME AGE SIGNERNAME REQUESTOR CONDITION csr-47rlp 13m kubernetes.io/kubelet-serving system:node:ip-192-168-35-64.ap-northeast-1.compute.internal Approved,Issued csr-fvndx 13m kubernetes.io/kubelet-serving system:node:ip-192-168-10-143.ap-northeast-1.compute.internal Approved,Issued jane 7s kubernetes.io/kube-apiserver-client kubernetes-admin Pending
Pending
になるので、approveする。
$ k certificate approve jane certificatesigningrequest.certificates.k8s.io/jane approved
確認する。
$ k get csr NAME AGE SIGNERNAME REQUESTOR CONDITION csr-47rlp 15m kubernetes.io/kubelet-serving system:node:ip-192-168-35-64.ap-northeast-1.compute.internal Approved,Issued csr-fvndx 15m kubernetes.io/kubelet-serving system:node:ip-192-168-10-143.ap-northeast-1.compute.internal Approved,Issued jane 87s kubernetes.io/kube-apiserver-client kubernetes-admin Approved,Issued
statusに証明書が入ってくるので、取り出す。
k get csr jane -o json | jq -r '.status.certificate' | base64 --decode k get csr jane -o json | jq -r '.status.certificate' | base64 --decode > jane.crt
証明書を確認する。
$ openssl x509 -text -in jane.crt -noout Certificate: Data: Version: 3 (0x2) Serial Number: 09:35:1d:11:fd:1e:68:04:fd:35:a0:00:c7:c3:07:6b:6e:69:54:bd Signature Algorithm: sha256WithRSAEncryption Issuer: CN=kubernetes Validity Not Before: Dec 28 00:38:00 2020 GMT Not After : Dec 28 00:38:00 2021 GMT Subject: CN=jane Subject Public Key Info: Public Key Algorithm: rsaEncryption Public-Key: (2048 bit) Modulus: 00:c5:fa:83:17:03:3a:7b:e3:c0:98:14:ae:d7:c2: 46:3b:cb:d4:9d:8e:6e:ac:3b:49:99:9e:5a:99:9b: eb:f0:5d:3b:7c:6f:97:f0:86:f5:9b:6b:bf:94:9c: 21:64:2f:74:56:f4:a0:58:81:52:ec:80:4c:33:74: 49:e4:da:6d:03:a8:3a:7b:8f:17:19:dd:32:2d:cc: f2:1f:ef:e0:38:31:57:93:92:bd:fe:6b:79:99:f8: ff:07:10:f3:8a:de:ec:d5:91:08:50:86:59:87:0e: f4:40:be:85:48:fb:70:b1:3c:e6:b5:0e:3c:93:77: 8f:9f:5c:2c:08:7a:59:03:d4:8d:fa:dc:e4:69:be: 15:b1:d8:7c:c6:fe:86:40:f8:04:6b:1d:a7:64:33: 8e:70:79:9d:35:16:20:3d:08:7a:d5:86:22:4d:d9: d8:4a:dc:f5:9a:62:5d:f1:83:31:1d:d5:fe:50:dc: 56:35:58:cb:7a:f2:8a:09:0e:a0:b3:48:8e:54:14: 30:b0:7c:13:54:1f:3e:b0:73:32:02:6e:9f:6a:87: 05:96:93:f2:7f:6c:3f:1e:df:96:8d:f5:25:72:47: 9f:21:43:b5:89:9d:78:08:5c:96:4b:65:ab:75:b8: ca:46:96:af:7a:0e:57:8b:16:a2:06:e1:42:24:eb: 70:a1 Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Extended Key Usage: TLS Web Client Authentication X509v3 Basic Constraints: critical CA:FALSE X509v3 Subject Key Identifier: 35:F4:D3:88:1C:57:AF:1D:EE:EE:F5:E0:34:2C:D2:3F:23:1E:6E:A0 Signature Algorithm: sha256WithRSAEncryption b6:7b:2a:8a:d0:95:07:d7:93:6f:33:d7:dd:c0:e8:05:a5:af: 1c:e3:38:d9:17:4a:33:c7:77:1a:f8:11:a1:f2:1e:36:cb:7c: 4e:13:3a:a6:33:ed:60:b3:aa:b0:8d:ef:a6:45:7c:8a:c3:fe: 23:c4:fe:8c:99:c4:93:b8:55:53:a0:4e:cc:d0:0a:70:59:cc: e2:3e:99:a5:30:58:b9:08:e7:d0:e4:a5:b6:9a:7f:a0:66:75: c4:ef:fc:77:90:84:7e:19:f4:e6:53:aa:0e:e2:ec:e7:94:9c: be:2d:66:94:11:c3:55:5e:78:c5:55:65:d0:de:31:cf:13:17: 12:f0:50:d8:fe:24:41:56:38:7a:7c:70:59:2d:da:49:24:84: aa:fc:0c:fd:79:a1:af:d9:9a:f8:3c:60:54:7d:56:bd:6a:16: 5c:ed:7f:38:86:0a:8b:b1:54:85:eb:a4:e5:f6:5a:3b:39:4d: 08:74:b9:3b:bd:b8:08:1f:c7:1d:6b:de:03:82:f0:c0:1d:57: fa:d1:0d:4c:10:ea:ed:61:36:93:ed:81:b4:4f:7f:79:23:b1: d3:ad:03:05:2d:a9:8a:15:94:f0:a1:f9:7b:c2:79:a2:40:8b: 7e:a1:b9:f8:c3:8c:33:82:46:a2:eb:46:2b:76:11:31:ba:c8: cb:ec:a7:46
kubeconfigにクレデンシャルをセットする。
# ファイルを参照する場合 # k config set-credentials jane --client-key=jane.key --client-certificate=jane.crt # 秘密鍵と証明書を埋め込む場合 k config set-credentials jane --client-key=jane.key --client-certificate=jane.crt --embed-certs
クラスターを確認する。
$ k config get-clusters NAME mycluster.ap-northeast-1.eksctl.io myeksdcluster.sotoiwa.dev
コンテキストを作成する。
$ k config set-context jane --cluster=mycluster.ap-northeast-1.eksctl.io --user=jane Context "jane" created.
コンテキストを切り替える前に、ユーザーjane
にview
のClusterRoleをバインドしておく。
$ k create clusterrolebinding jane --clusterrole=view --user=jane clusterrolebinding.rbac.authorization.k8s.io/jane created
現在のコンテキストに設定する。
$ k config use-context jane Switched to context "jane".
kubectlを実行する。
$ k get pod -n kube-system error: You must be logged in to the server (Unauthorized) $ k get node error: You must be logged in to the server (Unauthorized)
ダメだった。できないのか、どこか手順を間違えたのか?
ca証明書をファイルにする。
k config view --raw -o json | jq -r '.clusters[] | select( .name == "mycluster.ap-northeast-1.eksctl.io" ) | .cluster."certificate-authority-data"' | base64 --decode > ca.crt
curlでクライアント証明書を渡さずにアクセスすると、anonymousとしてアクセスできている。
$ curl https://26BA04AD024EF5657DA104B8C1F00FEF.gr7.ap-northeast-1.eks.amazonaws.com --cacert ca.crt { "kind": "Status", "apiVersion": "v1", "metadata": { }, "status": "Failure", "message": "forbidden: User \"system:anonymous\" cannot get path \"/\"", "reason": "Forbidden", "details": { }, "code": 403 }
クライアント証明書を渡してアクセスすると、Unauthorizedになる。
$ curl https://26BA04AD024EF5657DA104B8C1F00FEF.gr7.ap-northeast-1.eks.amazonaws.com --cacert ca.crt --cert jane.crt --key jane.key { "kind": "Status", "apiVersion": "v1", "metadata": { }, "status": "Failure", "message": "Unauthorized", "reason": "Unauthorized", "code": 401 }
ServiceAccountのトークン
ServiceAccountのトークンでアクセスできるのかを確認する。
kube-system
Namespaceにbatch-user
ServiceAccountを作成する。
$ k -n kube-system create sa batch-user serviceaccount/batch-user created
view
のClusterRoleをバインドする。
$ k create clusterrolebinding batch-user --clusterrole=view --serviceaccount=kube-system:batch-user clusterrolebinding.rbac.authorization.k8s.io/batch-user created
Secretの名前を取得する。
SECRET=$(k -n kube-system get sa batch-user -o json | jq -r '.secrets[].name')
トークンを取得する。
TOKEN=$(k -n kube-system get secret $SECRET -o json | jq -r '.data.token' | base64 --decode)
kubeconfigにクレデンシャルをセットする。
kubectl config set-credentials batch-user --token=${TOKEN}
クラスターを確認する。
k config get-clusters
コンテキストを作成する。
$ k config set-context batch-user --cluster=prometheus-operator.ap-northeast-1.eksctl.io --user=batch-user Context "batch-user" created.
現在のコンテキストに設定する。
$ k config use-context batch-user Switched to context "batch-user".
kubectlを実行する。
$ k get pod -n kube-system NAME READY STATUS RESTARTS AGE aws-load-balancer-controller-6c4d8d8f64-m5qgs 1/1 Running 0 26d aws-node-d9vxl 1/1 Running 0 25d aws-node-skmks 1/1 Running 0 26d aws-node-vzc8c 1/1 Running 0 26d coredns-86f7d88d77-fdshl 1/1 Running 0 26d coredns-86f7d88d77-rqblg 1/1 Running 0 26d external-dns-7855554c94-cct6v 1/1 Running 0 26d kube-proxy-4wcxp 1/1 Running 0 26d kube-proxy-9skkb 1/1 Running 0 25d kube-proxy-nnhkg 1/1 Running 0 26d metrics-server-5f956b6d5f-plb5j 1/1 Running 0 26d $ k get node Error from server (Forbidden): nodes is forbidden: User "system:serviceaccount:kube-system:batch-user" cannot list resource "nodes" in API group "" at the cluster scope
こちらはできた。
EKSベストプラクティスに、EKSではwebhook token authenticationとservice account tokensがサポートされているという記載があったので、ServiceAccountのトークンはいけるが、証明書はダメなものと思われる。
The Kubernetes project supports a variety of different strategies to authenticate requests to the kube-apiserver service, e.g. Bearer Tokens, X.509 certificates, OIDC, etc. EKS currently has native support for webhook token authentication and service account tokens.