LoginSignup
0
0

More than 1 year has passed since last update.

OPA Gatekeeperを使って特定のIAMユーザだけ特定のNamespaceでのリソース作成を禁止する

Last updated at Posted at 2022-09-28

1つのEKSクラスタを複数のIAMユーザで使いまわしている時に、Admin的なユーザ以外にはkube-systemでリソースを作成して欲しくないケースがある。(レアケースだとは思うが。。。)
RBACで出来なくもなさそうだが、特定のNamespaceだけ除外する、というのがあまりキレイに出来ないので、OPA Gatekeeperを使って実装した時のメモ。

今回は以下の条件で作成した。

  • kube-systemでのPodの作成を抑止する
  • IAMユーザのARNをConstraint側で渡せるようにする
  • NamespaceもConstraint側で記載するようにし、Template側で縛らないようにする

OPA Gatekeeperのインストール

こちらより最新版のOPA Gatekeeperのバージョンを確認し、インストールする。

export OPA_GK_VERSION=3.9
kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper/release-${OPA_GK_VERSION}/deploy/gatekeeper.yaml 

Podがあがっていることを確認する。

$ kubectl get pod -n gatekeeper-system
NAME                                             READY   STATUS    RESTARTS   AGE
gatekeeper-audit-779ffb6c54-hshsd                1/1     Running   0          21s
gatekeeper-controller-manager-7b4c8d7b97-57d77   1/1     Running   0          21s
gatekeeper-controller-manager-7b4c8d7b97-pmqmv   1/1     Running   0          21s
gatekeeper-controller-manager-7b4c8d7b97-zkqn9   1/1     Running   0          20s

ConstraintTemplateの作成

OPA Gatekeeperで与える制約の元となるテンプレートを作成する。
作成したテンプレートは以下となる。

apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
  name: k8sdenyarn
spec:
  crd:
    spec:
      names:
        kind: K8sDenyArn
      validation:
        openAPIV3Schema:
          type: object
          properties:
            denyArns:
              type: array
              items:
                type: string
  targets:
    - target: admission.k8s.gatekeeper.sh
      rego: |
        package k8sdenyarn

        violation[{"msg": msg}] {
          denyArns := input.parameters.denyArns[_]
          namespace := input.review.namespace
          operation := input.review.operation
          userInfo := input.review.userInfo

          userInfo.extra.arn[_] == denyArns
          operation == "CREATE"
          msg := sprintf("denied namespace: %v operation: %v arn: %v", [namespace, operation, userInfo.extra.arn])
        }

以下解説する。

      names:
        kind: K8sDenyArn
      validation:
        openAPIV3Schema:
          type: object
          properties:
            denyArns:
              type: array
              items:
                type: string

上記の箇所ではカスタムリソースを生成するとともに、パラメータとしてdenyArnsというものを用意した。これにより、ARNを可変値として渡せるようにし、K8sDenyArnリソース作成時に決まるものとした。

          denyArns := input.parameters.denyArns[_]

上記箇所でK8sDenyArnリソース作成時に設定したARNを取得している。

          operation := input.review.operation

上記箇所でPodに対するオペレーション(CREATE, UPDATE等)を取得している。なお、input.reviewがどのような値を持っているかはこちらの公式の説明を確認するとよい。

          userInfo := input.review.userInfo

上記箇所でユーザ情報を取得している。
この中身はEKSで実行した場合は以下となっていた。

{
  "extra": {
    "accessKeyId": [
      "xxxxxxx"
    ],
    "arn": [
      "arn:aws:iam::xxxx:user/username"
    ],
    "canonicalArn": [
      "arn:aws:iam::xxxx:user/username"
    ],
    "sessionName": [
      ""
    ]
  },
  "groups": [
    "system:masters",
    "system:authenticated"
  ],
  "uid": "aws-iam-authenticator:xxxx:xxxx",
  "username": "kubernetes-admin"
}

見て分かるようにextraのところにAWSに関連する情報が含まれているため、これを利用してリソース作成を抑制する。

          userInfo.extra.arn[_] == denyArns
          operation == "CREATE"

上記箇所はエラーとする条件を記載している。violation内の評価式は全てがTrueだとリソース操作を抑止するため、ここでは

  • 指定したARNがリソース作成時のパラメータに含まれているか
  • リソース操作がCREATEになっているか

をチェックして、条件が一致する場合は抑止するようにしている。

Constraintの作成

次にContraintとなる、先程定義したkind: K8sDenyArnを作成する。

apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sDenyArn
metadata:
  name: deny-arn
spec:
  match:
    kinds:
      - apiGroups: [""]
        kinds: ["Pod"]
    namespaces:
      - "kube-system"
  parameters:
    denyArns:
    - "arn:aws:iam::xxxxx:user/username"

namespaceはparametersで渡すことも出来るのだが、matchで絞った方が早いのでmatch部分に書くようにした。

動作確認

それぞれのリソースを適用した状態で、実際にPodを作成してみる。
最初に、kube-systemとdefaultにそれぞれ作成してみる。

$ kubectl run nginx --image nginx -n kube-system
Error from server (Forbidden): admission webhook "validation.gatekeeper.sh" denied the request: [deny-arn] denied namespace: kube-system operation: CREATE arn: ["arn:aws:iam::xxxx:user/username"]
$ kubectl run nginx --image nginx -n default
pod/nginx created

kube-systemのみ失敗した。
次に、K8sDenyArnのARNを変更して実行する。

$ kubectl run nginx --image nginx -n kube-system
pod/nginx created
$ kubectl run nginx --image nginx -n default
pod/nginx created

どちらも成功した。ARNによる制御が上手く行っていることが確認できた。

0
0
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
0
0