LoginSignup
9
9

More than 5 years have passed since last update.

Kubernetes API Server の 認可 (Authorization Plugin) によるアクセス制御

Posted at

はじめに

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 の起動時の引数を変更して ABACRBAC 両方を有効にします。この場合はどちらかの Authorization Plugin で認可が下りればアクセスできるようになります。

kubespary で構成した例では kubelet から API Server が起動されるので、manifest を修正します。
API Server を動作させる 2台両方で設定します。

node1,node2で実施
## 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    ## 変更点を後述
/etc/kubernetes/abac-policy.jsonl
{"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}}
kube-apiserver.manifestの修正点
--- /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 クライアント認証をします。
(証明書・秘密鍵は全てのホストが持っている構成です)

ConfigMap作成
# 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
kubeconfig.yaml
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 の修正を行います。

ReplicationController修正
# 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 によって切り替えが可能です。
設定ファイルは以下のようになりました。

/root/.kube/configの確認
# 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 に適用するかを決定します。
ClusterRoleRoleBinding で使用する場合は効果が Namespace 内に限定されます。
クラスタ全体に効果が及ぶのは ClusterRoleClusterRoleBinding で使用する場合のみです。

1種類だけ作って試します。

ABAC のような readonly フラグだけではなく、それぞれの操作を細かく設定できます。
以下の例は Deployment や Service の作成・更新を行うようなユーザを想定しています。kube ユーザと test Namespace の default ServiceAccount をまとめて同じ role に bind します。

user-role.yaml
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: []
user-bind.yaml
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 を切り替えてから設定を投入します。

ClusterRole,RoleBinding作成・確認
# 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 Namespacedefault 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 の設定で許されている操作のみが行えるはずです。

ClusteRole,RoleBindingの削除
# 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)
9
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
9