はじめに
Authorization Plugin を利用することで、ユーザごとにアクセス可能なリソースを制御することができます。
Authorization Plugin を使うには、誰がリソースにアクセスしているのかを識別する必要があります。
Basic認証やトークン、クライアント証明書などを用いて認証 (Authentication) を行った上で、認証されたユーザや ServiceAccount に対する認可 (Authorization) を行います。
認証・認可が行われるのは secure port に対するアクセスのみで、insecure port に対するアクセスはチェックされません。
認可についての本家ドキュメントは こちら
認証に関しては こちら
テスト環境の Kubernetes クラスタは こちらのように kubespray で作った想定です。
Kubernetes 1.3.0
には RBAC 関連で 正しく動作しないバグ があるので 1.3.4
以降を使用しています。
API Server の設定
ABAC (Attribute-Based Access Control)
と RBAC (Roles-Based Access Control)
を試します。
API Server の起動時の引数を変更して ABAC
と RBAC
両方を有効にします。この場合はどちらかの Authorization Plugin で認可が下りればアクセスできるようになります。
kubespary
で構成した例では kubelet から API Server が起動されるので、manifest を修正します。
API Server を動作させる 2台両方で設定します。
## manifests ディレクトリは watch されているので、先に準備を整える
# vi /etc/kubernetes/abac-policy.jsonl ## 内容は後述
# chmod 600 /etc/kubernetes/abac-policy.jsonl
# cd /etc/kubernetes/manifests
# cp -ip kube-apiserver.manifest /tmp
# vi kube-apiserver.manifest ## 変更点を後述
{"apiVersion": "abac.authorization.kubernetes.io/v1beta1", "kind": "Policy", "spec": {"user": "kube-node", "namespace": "*", "resource": "*", "apiGroup": "*"}}
{"apiVersion": "abac.authorization.kubernetes.io/v1beta1", "kind": "Policy", "spec": {"user": "*", "readonly": true, "nonResourcePath": "*"}}
{"apiVersion": "abac.authorization.kubernetes.io/v1beta1", "kind": "Policy", "spec": {"user": "root", "namespace": "*", "resource": "*", "apiGroup": "*"}}
{"apiVersion": "abac.authorization.kubernetes.io/v1beta1", "kind": "Policy", "spec": {"user": "kube", "namespace": "test", "resource": "services", "apiGroup": "*", "readonly": true}}
{"apiVersion": "abac.authorization.kubernetes.io/v1beta1", "kind": "Policy", "spec": {"user": "kube", "namespace": "test", "resource": "pods", "apiGroup": "*"}}
{"apiVersion": "abac.authorization.kubernetes.io/v1beta1", "kind": "Policy", "spec": {"user": "system:serviceaccount:test:default", "namespace": "test", "resource": "*", "apiGroup": "*", "readonly": true}}
--- /tmp/kube-apiserver.manifest 2016-08-12 00:35:27.311905955 +0900
+++ /etc/kubernetes/manifests/kube-apiserver.manifest 2016-08-12 00:50:44.237718445 +0900
@@ -23,6 +23,9 @@
- --tls-private-key-file=/etc/kubernetes/ssl/apiserver-key.pem
- --token-auth-file=/etc/kubernetes/tokens/known_tokens.csv
- --service-account-key-file=/etc/kubernetes/ssl/apiserver-key.pem
+ - --authorization-mode=ABAC,RBAC
+ - --authorization-policy-file=/etc/kubernetes/abac-policy.jsonl
+ - --authorization-rbac-super-user=root
- --secure-port=443
- --insecure-port=8080
- --v=2
kube-apiserver.manifest
を変更・保存すると自動的に kube-apiserver が再起動されます。
引数が変わっていることを確認しておきます。
# ps -eo args | grep hyperkube\ apiserve[r] | sed "s/ /\n/g"
/hyperkube
apiserver
--advertise-address=192.168.100.1
--etcd-servers=http://127.0.0.1:2379
--insecure-bind-address=127.0.0.1
--apiserver-count=2
--admission-control=NamespaceLifecycle,NamespaceExists,LimitRanger,SecurityContextDeny,ServiceAccount,ResourceQuota
--service-cluster-ip-range=10.233.0.0/18
--client-ca-file=/etc/kubernetes/ssl/ca.pem
--basic-auth-file=/etc/kubernetes/users/known_users.csv
--tls-cert-file=/etc/kubernetes/ssl/apiserver.pem
--tls-private-key-file=/etc/kubernetes/ssl/apiserver-key.pem
--token-auth-file=/etc/kubernetes/tokens/known_tokens.csv
--service-account-key-file=/etc/kubernetes/ssl/apiserver-key.pem
--authorization-mode=ABAC,RBAC
--authorization-policy-file=/etc/kubernetes/abac-policy.jsonl
--authorization-rbac-super-user=root
--secure-port=443
--insecure-port=8080
--v=2
--allow-privileged=true
2>&1
>>
/var/log/kubernetes/kube-apiserver.log
ついでにテスト用の Namespace を作っておきます。
# kubectl create ns test
namespace "test" created
# kubectl get ns
NAME STATUS AGE
default Active 12m
kube-system Active 12m
test Active 2s
kubedns の設定
API Server で認可が有効になったため、このままでは kubedns
から API Server にアクセスできません。
kubedns
は API Server にリクエストして得られた情報をもとに DNS レコードを更新するので、API Server にアクセスできるようにしておく必要があります。
この環境では Replication Controller
としてデプロイされているので、その設定を書き替えます。変更が必要なのは kube2sky
の箇所だけです。
やり方は色々ありますが、ここでは ConfigMap
で kubeconfig.yaml を用意し、ホストの /etc/kubernetes/ssl
にある証明書と秘密鍵を HostPath
でコンテナに見せて TLS クライアント認証をします。
(証明書・秘密鍵は全てのホストが持っている構成です)
# vi kubeconfig.yaml
# kubectl --namespace=kube-system create configmap kubeconfig --from-file=kubeconfig.yaml
configmap "kubeconfig" created
# kubectl --namespace=kube-system get configmap
NAME DATA AGE
kubeconfig 1 7s
apiVersion: v1
kind: Config
clusters:
- name: local
cluster:
certificate-authority: /etc/kubernetes/ssl/ca.pem
server: https://10.233.0.1/
users:
- name: kubedns
user:
client-certificate: /etc/kubernetes/ssl/node.pem
client-key: /etc/kubernetes/ssl/node-key.pem
contexts:
- context:
cluster: local
user: kubedns
name: kubedns-cluster.local
current-context: kubedns-cluster.local
API Server の指定は ClusterIP で行いました。
# kubectl get svc
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes 10.233.0.1 <none> 443/TCP 15m
ConfigMap を作ったら、続いて現在の設定をベースに Replication Controller の修正を行います。
# kubectl --namespace=kube-system get rc kubedns -o yaml > kubedns.yaml
# vi kubedns.yaml
# diff -u <(kubectl --namespace=kube-system get rc kubedns -o yaml) kubedns.yaml
--- /dev/fd/63 2016-08-12 00:56:59.701544080 +0900
+++ kubedns.yaml 2016-08-12 00:56:45.148329156 +0900
@@ -52,6 +52,7 @@
name: etcd-storage
- args:
- --domain=cluster.local
+ - --kubecfg-file=/etc/kubernetes/kubeconfig.yaml
image: gcr.io/google_containers/kube2sky:1.14
imagePullPolicy: IfNotPresent
name: kube2sky
@@ -60,6 +61,12 @@
cpu: 100m
memory: 50Mi
terminationMessagePath: /dev/termination-log
+ volumeMounts:
+ - mountPath: /etc/kubernetes
+ name: kubeconfig
+ - mountPath: /etc/kubernetes/ssl
+ name: etc-kube-ssl
+ readOnly: true
- args:
- -machines=http://localhost:4001
- -addr=0.0.0.0:53
@@ -118,6 +125,12 @@
volumes:
- emptyDir: {}
name: etcd-storage
+ - configMap:
+ name: kubeconfig
+ name: kubeconfig
+ - hostPath:
+ path: /etc/kubernetes/ssl
+ name: etc-kube-ssl
status:
fullyLabeledReplicas: 1
observedGeneration: 1
設定を作ったら Replication Controller を更新します。
Pod を作り直させるために、一度削除します。
削除してしばらく待つと自動的に Replication Controller が Pod を作り直します。
# kubectl replace -f kubedns.yaml
replicationcontroller "kubedns" replaced
# kubectl --namespace=kube-system get pod -l k8s-app=kubedns
NAME READY STATUS RESTARTS AGE
kubedns-gy54j 4/4 Running 0 17m
# kubectl --namespace=kube-system delete pod kubedns-gy54j
pod "kubedns-gy54j" deleted
# kubectl --namespace=kube-system get pod -l k8s-app=kubedns
NAME READY STATUS RESTARTS AGE
kubedns-ys89d 4/4 Running 0 44s
Pod が動いたら適当な Service を作って名前が引けるか確認しておきます。
名前登録されることを確認したいだけなので、Endpoint は存在しなくて問題ありません。
# kubectl expose svc kubernetes --name=hoge --port=1111 --selector="foo=bar"
service "hoge" exposed
# kubectl get svc
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
hoge 10.233.62.169 <none> 1111/TCP 4s
kubernetes 10.233.0.1 <none> 443/TCP 21m
# dig +short hoge.default.svc.cluster.local.
10.233.62.169
無事に名前が引けたら余計な Service は削除しておきます。
# kubectl delete svc hoge
service "hoge" deleted
ABAC
ABAC policy 設定の説明
どのようにアクセス可否が設定されたかを確認する前に、API Server の設定 で記述した abac-policy.jsonl
の設定について説明します。
以下は kube-node ユーザに全ての Namespace 及びリソースへのアクセスを許可するものです。
{"apiVersion": "abac.authorization.kubernetes.io/v1beta1", "kind": "Policy", "spec": {"user": "kube-node", "namespace": "*", "resource": "*", "apiGroup": "*"}}
この環境で kubelet の認証設定は /etc/kubernetes/node-kubeconfig.yaml
を参照するようになっています。
apiVersion: v1
kind: Config
clusters:
- name: local
cluster:
certificate-authority: /etc/kubernetes/ssl/ca.pem
users:
- name: kubelet
user:
client-certificate: /etc/kubernetes/ssl/node.pem
client-key: /etc/kubernetes/ssl/node-key.pem
contexts:
- context:
cluster: local
user: kubelet
name: kubelet-cluster.local
current-context: kubelet-cluster.local
この証明書の CN が kube-node です。これにより kubelet は API Server へアクセスできます。
# openssl x509 -in /etc/kubernetes/ssl/node.pem -subject -noout
subject= /CN=kube-node
kube-proxy も同じ node-kubeconfig.yaml
を参照しています。
(Master として kubespray
で構成したホストは localhost の insecure port を参照しますが、Master の機能を持たないよう kubespray
で構成したホストは Master にしたホストの secure port を参照します。)
kubedns も設定は若干異なりますが、同じ証明書を使ってクライアント認証しています。
以下は nonResourcePath へのアクセスを全てのユーザに許可するものです。
kubectl を叩く際にバージョン情報のリクエストなどに用いられます。
{"apiVersion": "abac.authorization.kubernetes.io/v1beta1", "kind": "Policy", "spec": {"user": "*", "readonly": true, "nonResourcePath": "*"}}
以下は root ユーザに全ての Namespace 及びリソースへのアクセスを許可するものです。
この環境では後述する RBAC のスーパーユーザとしても root ユーザを使用します。
{"apiVersion": "abac.authorization.kubernetes.io/v1beta1", "kind": "Policy", "spec": {"user": "root", "namespace": "*", "resource": "*", "apiGroup": "*"}}
以下は kube ユーザに限定的なアクセスを許可するものです。
test Namespace において Service の読み取りと Pod の読み書きを可能にしています。
{"apiVersion": "abac.authorization.kubernetes.io/v1beta1", "kind": "Policy", "spec": {"user": "kube", "namespace": "test", "resource": "services", "apiGroup": "*", "readonly": true}}
{"apiVersion": "abac.authorization.kubernetes.io/v1beta1", "kind": "Policy", "spec": {"user": "kube", "namespace": "test", "resource": "pods", "apiGroup": "*"}}
以下は test Namespace の default という ServiceAccount に test Namespace の全てのリソースへ読み取りアクセスを許可するものです。
ServiceAccount の設定を書く場合は system:serviceaccount:<namespace>:<serviceaccountname>
という形式のユーザ名にします。
{"apiVersion": "abac.authorization.kubernetes.io/v1beta1", "kind": "Policy", "spec": {"user": "system:serviceaccount:test:default", "namespace": "test", "resource": "*", "apiGroup": "*", "readonly": true}}
default という ServiceAccount は test Namespace を作成した際に自動的に作られたものです。
# kubectl --namespace=test get sa
NAME SECRETS AGE
default 1 15m
# kubectl --namespace=test get secret
NAME TYPE DATA AGE
default-token-a9aii kubernetes.io/service-account-token 3 15m
ABAC 動作テスト
設定した通りに制御されるか確認します。
kubectl の認証設定をします。
ここで注意が必要なのは、insecure port へのアクセスは認証・認可が必要ない (常にアクセス許可される) ということです。
Authorization Plugin の動作テストをするには、kubectl でのアクセスを secure port の方に向ける必要があります。
(kubectl のデフォルトは http://locahost:8080/ 宛てになっています)
## 認証ありにしたい場合は secure port に向ける
# kubectl config set-cluster kubespray-secure --server=https://kubernetes.default.svc.cluster.local/ --certificate-authority=/root/.kube/ca.pem
# cp /etc/kubernetes/ssl/ca.pem /root/.kube/
## root ユーザに関する設定
# kubectl config set-credentials root --username=root --password=changeme
# kubectl config set-context kubespray-root --cluster=kubespray-secure --user=root
## kube ユーザに関する設定
# kubectl config set-credentials kube --username=kube --password=changeme
# kubectl config set-context kubespray-kube --cluster=kubespray-secure --user=kube
## insecure port にアクセスするための設定
# kubectl config set-cluster kubespray-insecure --server=http://localhost:8080/
# kubectl config set-context insecure --cluster=kubespray-insecure --user=""
## test Namespace の default ServiceAccount に関する設定
# yum install -y jq
# kubectl config set-credentials test-default-sa \
--token=$(kubectl --namespace=test get secret \
$(kubectl --namespace=test get sa default -o json | \
jq -r .secrets[0].name) -o json | jq -r .data.token | base64 -d)
# kubectl config set-context kubespray-test-default-sa --cluster=kubespray-secure --user=test-default-sa
4つの context を設定しました。これらは use-context によって切り替えが可能です。
設定ファイルは以下のようになりました。
# kubectl config view
apiVersion: v1
clusters:
- cluster:
server: http://localhost:8080/
name: kubespray-insecure
- cluster:
certificate-authority: ca.pem
server: https://kubernetes.default.svc.cluster.local/
name: kubespray-secure
contexts:
- context:
cluster: kubespray-insecure
user: ""
name: insecure
- context:
cluster: kubespray-secure
user: kube
name: kubespray-kube
- context:
cluster: kubespray-secure
user: root
name: kubespray-root
- context:
cluster: kubespray-secure
user: test-default-sa
name: kubespray-test-default-sa
current-context: ""
kind: Config
preferences: {}
users:
- name: kube
user:
password: changeme
username: kube
- name: root
user:
password: changeme
username: root
- name: test-default-sa
user:
token: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJ0ZXN0Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6ImRlZmF1bHQtdG9rZW4tYTlhaWkiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoiZGVmYXVsdCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6IjgxNzY2MGJhLTVmZGItMTFlNi05NzJlLTAwMGMyOTJlZWMzNyIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDp0ZXN0OmRlZmF1bHQifQ.5N_TDpepXRL3yf_vslVoU0b76VcE2FqXToGbIBIZH-o5Fxqn-yuzXQ16JRdZaAKpFQHX1vG8xnHqRsrt3xrM228zuF6h6vZjephsLqPYNdy3dHhc62ZhhiI_RWzcb6uMYlAxT4YwfGWL-DikSuZtH5YJiASreo17Uf4Xy2_6WeRPzweLG4GHDHvdmTV5Llz-nRqcIC6CaYvDpxoShTx4DdbG9PkH7txnhHGGxZj-7qC_vThaN0APrJrWTeRPyu2oFy78vioAbB5mPHo9XNZ7hjWKtzUwzy26wFDgzdCUyzRmRaGKnTe1DQLQRoR5iw5byfaaM8tsHGtbPWsk8Dw3mA
まずは root ユーザとしてアクセスしてみます。
# kubectl config use-context kubespray-root
# kubectl config current-context
kubespray-root
# kubectl get secret --all-namespaces
NAMESPACE NAME TYPE DATA AGE
default default-token-vxtr6 kubernetes.io/service-account-token 3 31m
kube-system default-token-gh3tp kubernetes.io/service-account-token 3 31m
test default-token-a9aii kubernetes.io/service-account-token 3 18m
全てを試すのは面倒なので secret だけですが、全ての Namespace にアクセスできました。同様に Service や Pod も問題なくアクセスできます。
kube ユーザの場合はどうでしょうか。切り替えてアクセスしてみます。
# kubectl config use-context kubespray-kube
# kubectl config current-context
kubespray-kube
## kube-system Namespace にはアクセスできない
# kubectl --namespace=kube-system get pod
the server does not allow access to the requested resource (get pods)
## test Namespace ならリソースの種類によってはアクセスできる (オブジェクトは未作成なので無い)
# kubectl --namespace=test get pod
# kubectl --namespace=test get svc
# kubectl --namespace=test get secret
the server does not allow access to the requested resource (get secrets)
## test Namespace で Pod を作れるが Service は作れない
# kubectl --namespace=test run test -l foo=bar --image=nginx:alpine --restart=Never
pod "test" created
# kubectl --namespace=test get pod
NAME READY STATUS RESTARTS AGE
test 1/1 Running 0 11s
# kubectl --namespace=test expose pod test --port=80 --target-port=80
Error from server: the server does not allow access to the requested resource (post services)
test Namespace の default という ServiceAccount も試します。
# kubectl config use-context kubespray-test-default-sa
# kubectl config current-context
kubespray-test-default-sa
## kube-system Namespace にはアクセスできない
# kubectl --namespace=kube-system get pod
the server does not allow access to the requested resource (get pods)
## test Namespace ならアクセスできるが、readonly で Pod を作れない
# kubectl --namespace=test get pod
NAME READY STATUS RESTARTS AGE
test 1/1 Running 0 1m
# kubectl --namespace=test get svc
# kubectl --namespace=test get secret
NAME TYPE DATA AGE
default-token-a9aii kubernetes.io/service-account-token 3 20m
# kubectl --namespace=test run test2 -l foo=baz --image=nginx:alpine --restart=Never
Error from server: the server does not allow access to the requested resource (post pods)
insecure port を使って制限されないことを確認するついでに、作成した Pod を削除します。
# kubectl config use-context insecure
# kubectl config current-context
insecure
# kubectl --namespace=test delete pod test
pod "test" deleted
RBAC
RBAC では ABAC より細かい制御が可能です。
RBAC はまだアルファ版なので、本番運用するには注意が必要かもしれません。
RBAC 設定作成
RBAC の設定には以下のものがあります。
- RBAC のスーパーユーザ
- 特定の Namespace にのみ効果が及ぶ
Role
,RoleBinding
- クラスタ全体に効果が及ぶ
ClusterRole
,ClusterRoleBinding
Role
, ClusterRole
で権限セットを定義し、RoleBidnnig
, ClusterRoleBinding
でどのユーザまたは ServiceAccount に適用するかを決定します。
ClusterRole
を RoleBinding
で使用する場合は効果が Namespace 内に限定されます。
クラスタ全体に効果が及ぶのは ClusterRole
を ClusterRoleBinding
で使用する場合のみです。
1種類だけ作って試します。
ABAC のような readonly フラグだけではなく、それぞれの操作を細かく設定できます。
以下の例は Deployment や Service の作成・更新を行うようなユーザを想定しています。kube
ユーザと test Namespace の default
ServiceAccount をまとめて同じ role に bind します。
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1alpha1
metadata:
# "namespace" omitted since ClusterRoles are not namespaced.
#namespace: default
name: normal-user
rules:
- apiGroups: [""] # The API group "" indicates the default API Group.
resources: ["pods"]
verbs: ["get", "list", "create", "update", "watch", "delete", "deletecollection"]
nonResourceURLs: []
- apiGroups: [""] # The API group "" indicates the default API Group.
resources: ["endpoints", "events", "services"]
verbs: ["get", "list", "create", "update", "delete", "watch" ]
nonResourceURLs: [""]
- apiGroups: ["extensions"] # The API group "" indicates the default API Group.
resources: ["replicasets", "deployments"]
verbs: ["get", "list", "create", "update", "watch", "delete", "deletecollection", "patch"]
nonResourceURLs: []
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1alpha1
metadata:
name: test-normal-users
namespace: test
subjects:
- kind: ServiceAccount
name: default
namespace: test
- kind: User
name: kube
roleRef:
kind: ClusterRole
name: normal-user
apiVersion: rbac.authorization.k8s.io/v1alpha1
RBAC の設定を変更するには RBAC のスーパーユーザ (ここでは root) になる必要があるので context を切り替えてから設定を投入します。
# kubectl config use-context kubespray-root
# kubectl config current-context
kubespray-root
# kubectl create -f user-role.yaml
clusterrole "normal-user" created
# kubectl create -f user-bind.yaml
rolebinding "test-normal-users" created
# kubectl get clusterroles
NAME AGE
normal-user 6s
# kubectl --namespace=test get rolebindings
NAME AGE
test-normal-users 23s
RBAC 動作テスト
作成したオブジェクトのテストをします。
まずは kube
ユーザが normal-user
ロールの権限を持つことを確認します。
# kubectl config use-context kubespray-kube
# kubectl config current-context
kubespray-kube
## test Namespace で bind しているので kube-system Namespace にはアクセスできない
# kubectl --namespace=kube-system get pod
the server does not allow access to the requested resource (get pods)
## test Namespace なら Deployment, ReplicaSet, Pod が作れる
# kubectl --namespace=test run test -l foo=bar --image=nginx:1.10.1-alpine
deployment "test" created
# kubectl --namespace=test get deployment
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
test 1 1 1 0 8s
# kubectl --namespace=test get rs
NAME DESIRED CURRENT AGE
test-2066847110 1 1 9s
# kubectl --namespace=test get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE
test-2066847110-wk5ze 1/1 Running 0 28s 10.233.120.3 node3
## Service も作れる
# kubectl --namespace=test expose deployment/test --port=80 --target-port=80
service "test" exposed
# kubectl --namespace=test get svc
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
test 10.233.32.165 <none> 80/TCP 6s
# kubectl --namespace=test get ep
NAME ENDPOINTS AGE
test 10.233.120.3:80 12s
## test Namespace でも serviceaccount や secret にはアクセスできない
# kubectl --namespace=test get sa
the server does not allow access to the requested resource (get serviceaccounts)
# kubectl --namespace=test get secret
the server does not allow access to the requested resource (get secrets)
続いて test Namespace
の default
ServiceAccount も確認します。
# kubectl config use-context kubespray-test-default-sa
# kubectl config current-context
kubespray-test-default-sa
## test Namespace で bind しているので kube-system Namespace にはアクセスできない
# kubectl --namespace=kube-system get pod
the server does not allow access to the requested resource (get pods)
## test Namespace のリソースを読み取れる
# kubectl --namespace=test get deployment
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
test 1 1 1 1 1m
# kubectl --namespace=test get rs
NAME DESIRED CURRENT AGE
test-2066847110 1 1 1m
# kubectl --namespace=test get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE
test-2066847110-wk5ze 1/1 Running 0 1m 10.233.120.3 node3
## test Namespace なら Deployment, ReplicaSet, Pod の変更ができる
# kubectl --namespace=test scale --replicas=2 deployment/test
deployment "test" scaled
# kubectl --namespace=test get deployment
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
test 2 2 2 1 2m
# kubectl --namespace=test get rs
NAME DESIRED CURRENT AGE
test-2066847110 2 2 2m
# kubectl --namespace=test get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE
test-2066847110-bcenk 1/1 Running 0 21s 10.233.82.3 node1
test-2066847110-wk5ze 1/1 Running 0 3m 10.233.120.3 node3
# kubectl --namespace=test get svc
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
test 10.233.32.165 <none> 80/TCP 2m
# kubectl --namespace=test get ep
NAME ENDPOINTS AGE
test 10.233.120.3:80,10.233.82.3:80 2m
## test Namespace で serviceaccount や secret にアクセスできる
# kubectl --namespace=test get sa
NAME SECRETS AGE
default 1 28m
# kubectl --namespace=test get secret
NAME TYPE DATA AGE
default-token-a9aii kubernetes.io/service-account-token 3 28m
## serviceaccount の作成はできない
# kubectl --namespace=test create sa hoge
Error from server: the server does not allow access to the requested resource (post serviceaccounts)
Secret へアクセス可能なことを不審に思った方もいるかもしれません。
kube
ユーザが ServiceAccount
, Secret
にアクセスできないのに、同じ ClusterRole
である test Namespace の default
ServiceAccount は何故アクセスできてしまうのでしょうか?
API Server の設定 でも触れたように、ABAC
及び RBAC
が両方設定されている場合には、どちらか一方で認可されればアクセス可能になります。
test Namespace の default
ServiceAccount は ABAC
のポリシーファイルに以下のように設定されています。これにより test Namespace の全てのリソースへの readonly なアクセスは許されているのです。
{"apiVersion": "abac.authorization.kubernetes.io/v1beta1", "kind": "Policy", "spec": {"user": "system:serviceaccount:test:default", "namespace": "test", "resource": "*", "apiGroup": "*", "readonly": true}}
最後に role を削除してもう一度確認してみます。
ABAC
の設定で許されている操作のみが行えるはずです。
# kubectl config use-context kubespray-root
# kubectl config current-context
kubespray-root
# kubectl delete -f user-role.yaml
clusterrole "normal-user" deleted
# kubectl delete -f user-bind.yaml
rolebinding "test-normal-users" deleted
## 何も表示されないことを確認
# kubectl get clusterroles
# kubectl --namespace=test get rolebindings
## kube ユーザの確認
# kubectl config use-context kubespray-kube
# kubectl config current-context
kubespray-kube
# kubectl --namespace=test get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE
test-2066847110-bcenk 1/1 Running 0 2m 10.233.82.3 node1
test-2066847110-wk5ze 1/1 Running 0 5m 10.233.120.3 node3
# kubectl --namespace=test get deployment
the server does not allow access to the requested resource (get deployments.extensions)
# kubectl --namespace=test get rs
the server does not allow access to the requested resource (get replicasets.extensions)
## default ServiceAccount の確認
# kubectl config use-context kubespray-test-default-sa
# kubectl config current-context
kubespray-test-default-sa
# kubectl --namespace=test get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE
test-2066847110-bcenk 1/1 Running 0 3m 10.233.82.3 node1
test-2066847110-wk5ze 1/1 Running 0 5m 10.233.120.3 node3
# kubectl --namespace=test get deployment
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
test 2 2 2 2 6m
# kubectl --namespace=test get secret
NAME TYPE DATA AGE
default-token-a9aii kubernetes.io/service-account-token 3 31m
# kubectl --namespace=test run hoge -l foo=baz --image=nginx:alpine --restart=Never
Error from server: the server does not allow access to the requested resource (post pods)