LabHub

ブログ

CKA_7_Security

한국어English日本語

この記事は、Udemyの講座 https://www.udemy.com/course/certified-kubernetes-administrator-with-practice-tests および https://kodekloud.com/ の内容を学習しながらまとめたものです。

141 Authentication

Kubernetesには、User Accountを作成する機能はありませんが、serviceaccountを作成する機能はあります。

authentication

ユーザーはkubectlやAPIを使用してKubernetesクラスターにアクセスできます。

authentication

kube-apiserverの起動時に --basic-auth-file=<filename> を指定すると、パスワード認証方式のユーザーを登録できます。ただし、セキュリティが弱く、ユーザーが変更される際にAPIサーバーの再起動が必要になるため、推奨される認証方式ではありません。このように作成されたuser/passwordは、curlコマンドでの認証に使用されます。

authentication

パスワードの代わりにTokenでの認証も可能です。

authentication

146 TLS in Kubernetes

Kubernetes内部では、すべての認証がTLSで動作します。そのため、すべてのコンポーネントには .crt で終わる公開鍵と .key で終わる秘密鍵が存在します。

以下はKubernetesを動作させるサーバーコンポーネントです。

authentication

Kubernetesにアクセスするクライアントも同様にTLS認証を使用します。

authentication

そして、ここで生成されるすべてのCertificateの公開鍵が本物であることを認証するCA(Certificate Authority)が存在する必要があります。

以下のようにETCD用のCAを分離して運用することもできますが、一般的には1つのCAで運用します。この場合、クラスター全体に ca.crtca.key の1ペアが存在します。

authentication

147 TLS in Kubernetes - Certification Creation

Certificate作成ツールとして有名なものにEASYRSA、CFSSL、OPENSSLがありますが、ここではOPENSSLを中心に説明します。

CA(Certificate Authority)のKeyを生成するには、以下のコマンドで行えます。

openssh genrsa -out ca.key 2048 は秘密鍵の作成、openssl req -new -key ca.key -subj "/CN=KUBERNETES-CA" -out ca.csr は署名済み公開鍵の作成、openssl x509 -req -in ca.csr -signkey ca.key -out ca.crt は署名済み公開鍵を秘密鍵で暗号化するコマンドです。

authentication

Admin Userを作成する際、ca.crtとca.keyを使用してadmin.csrを暗号化(CAで証明書を発行)します。

authentication

以降に作成する必要があるほとんどのアカウントも同様のプロセスです。.crtはIDに相当し、.keyはパスワードに相当すると考えてください。

Certificate Signing Requestで署名する際、/CN=kube-admin/O=system:masters を追加してadminアカウントと一般アカウントを区別します。このように作成されたadmin certificateは、curlコマンドの実行時に使用するか、kube-config.yamlに登録して使用します。

authentication

ETCDクラスターはHigh Availabilityで構成されるため、Peer certificationという追加のcertificationも必要です。

authentication

APIサーバーは最も多く使用されるため、名前が多数あります(kubernetes、kubernetes.default、kubernetes.default.svc、kubernetes.default.svc.cluster.local、IPアドレス)。そのため、CAを通じて署名する際にも、すべてのalternative名を明示する必要があります。

authentication

authentication

Kubeletはすべてのノードがそれぞれのcertificateを生成し、保持する必要があります。

authentication

上記で述べたように、1つのクラスターにも数多くのCertificateが存在します。これらすべてのCertificateが正しく設定されているかチェックし管理するのは、非常に困難で退屈な作業です。kubeadm ツールを活用すると、これらの作業を簡単に行えるようになります。

openssl x509 -in <.crt file name> -text -noout コマンドを使用して、Certificateの情報を確認できます。

authentication

kubectl logs etcd-master または docker ps -adocker logs でログを分析して、問題を特定できます。

152 Certificates API

CA(Certificate Authority)は、CAの公開鍵とCAの秘密鍵の2つと言っても過言ではありません。もしこのキーが漏洩した場合、このキーを使って多くのユーザーを作成し、Kubernetesにアクセスするハッキングが発生する可能性があります。そのため、この2つのキーは必ず安全な場所に保管する必要があります。一般的にmaster nodeで作成・管理します。kubeadmは、このCA用キーペアの保管と管理も行います(キーの有効期限管理を含む)。

署名プロセスも簡単です。以下のようにkube-apiserverにユーザーを作成し、base64でエンコードして署名を要求するだけです。

authentication

base64でエンコードする際に -w 0 オプションを使うと1行にまとめることができ、これをrequest部分に貼り付けます。

akshay.yaml
apiVersion: certificates.k8s.io/v1
kind: CertificateSigningRequest
metadata:
  name: akshay
spec:
  signerName: youngju.dev.com/youngju
  usages:
    - digital signature
    - key encipherment
    - server auth
  request: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURSBSRVFVRVNULS0tLS0KTUlJQ1ZqQ0NBVDRDQVFBd0VURVBNQTBHQTFVRUF3d0dZV3R6YUdGNU1JSUJJakFOQmdrcWhraUc5dzBCQVFFRgpBQU9DQVE4QU1JSUJDZ0tDQVFFQXBkakxiamFRNWZMdklvNlBXTFpYaEwwa25wKzZlaUZHd0ZHUFErdmhrNWFBClpyOURYUVJINE9IZ1JESktvUGVxdTRGeDB6TkJUQndKa0ZpZEl4U01rUWNsc0lVT3VncSsyMUNaaHlkd0hFYzgKK1AzQzk2L0JVN3o1T25nWVBsa0ZyZmdBcHhacWo2WVVyTHJpS2V4Q0JHZ0cybzVBN205Q2xzRUhhalQwYlU2SwowWGxCQW9sc2cyM3NMUE1jR1RSdGZ0bGhDUDJoQkZPdHhyRW9SUHFsSUdFdWxEVitpSjZFeVY2SW9NcDhFVmxKCmJvb2MzaW93UE8zOGx4SmwrcWloVGd0OHMwNlYwTHhML0pVejdJQ3FkdFQzcGkvNHJ6VzBFeE16eVNLcllxZjYKZDVNK1RVZDdMMk1vQjF1aTgxQXFJcVpBQWQybExCR0M5dm9vbWpwZWd3SURBUUFCb0FBd0RRWUpLb1pJaHZjTgpBUUVMQlFBRGdnRUJBQXBpdUl4bU9mcEU2NEhTd0VCc1RsbnRScjVyZUNWMStlSzFKSVEyM0UyUXRiL2FrUGZuClNmRmpaRTB0ZmNaVUFHMzVoL214ZTVleEo3ZGNMN3dNT2wxYkVsTXNoTXlydlMyajVKckJhS3ZOaXFXVXo2VTYKbGRydWFlc0dUZDVoTncwVkNUaGpmaXNMcXBWZDI1TWlPcE11SFM0eXFVWUl4dGR1RGQzb01haFVTaXpyY1kzVwpXM0tycTBjSWxaU2p5L2twSzAwdmduclQ2ZlIzaTN4bE1jSkcrVTYzalBnYUhNUHM2MS9YZGhlL0s0dmRyeDllClc2MU1GalRGa0tpY25qYnBCNGZ1Uno3SmRRNW94TS90RFFveEtEYTNGTFNHcklvSGg1YkZlcDFESlZlaHkyeTcKekJFaXZiYWFjaEpGT2xvWHYrZnlVMVpUcS9JUTRLZEdjeU09Ci0tLS0tRU5EIENFUlRJRklDQVRFIFJFUVVFU1QtLS0tLQo=
$ kubectl create -f akshay-csr.yaml
certificatesigningrequest.certificates.k8s.io/akshay created

kubectl get csr コマンドでCSRの署名要求一覧を確認し、kubectl certificate approve <csr-name> で承認します。その後、kubectl get csr jane -o yaml コマンドでCertificate情報を確認できます。

$ kubectl get csr
NAME        AGE   SIGNERNAME                                    REQUESTOR                  REQUESTEDDURATION   CONDITION
akshay      79s   youngju.dev.com/youngju                       kubernetes-admin           <none>              Pending
csr-xjv6n   36m   kubernetes.io/kube-apiserver-client-kubelet   system:node:controlplane   <none>              Approved,Issued

$ kubectl certificate approve akshay
certificatesigningrequest.certificates.k8s.io/akshay approved

$ kubectl certificate deny agent-smith
certificatesigningrequest.certificates.k8s.io/agent-smith denied

$ kubectl delete csr agent-smith
certificatesigningrequest.certificates.k8s.io "agent-smith" deleted

authentication

Certificate関連の操作はController Managerで管理されます。CSR-ApprovingとCSR-Signingの機能です。 そのため、kube-controller-manager.yamlにca.keyとca.crtを登録する必要があります。

authentication

155 KubeConfig

kubectlコマンドを入力するたびにcertificateを指定するのは非常に面倒です。

authentication

ホームディレクトリ配下の .kube/config ファイルに上記の情報を登録しておけば、kubectlコマンド実行時に自動的にこの情報が使用されるため便利です。

configファイルはフォーマットに従って記述する必要があり、Cluster、Context、Userの3つを定義します。

authentication

複数のcontextの中から、.kube/configファイルの current-context にデフォルトのcontextを定義できます。

authentication

kubectl config view でconfigファイルを確認できます。kubectl config use-context <context> でcontextを切り替えます。

各Clusterには複数のnamespaceがあり、contextフィールド内で定義できます。

authentication

159 API Groups

Kubernetes APIは複数のグループに分かれています。その中でもapiとapisは重要なAPIエンドポイントグループを提供します。

authentication

authentication

kubectl proxyを使用すると、権限を持つkube proxyサーバーがAPIサーバーへのリクエストを仲介してくれるため、certificateを指定する必要がありません。

authentication

160 Authorization

Authorizationは、Authenticationが完了した後、どこまでアクセスできるかを決定する権限管理です。

authentication

Node、Attribute-Based、Role-Based、Webhookの4つの方式でAuthorizationを管理できます。

Node Authorizationは、KubeletがAPIサーバーにアクセスする際に使用する権限です。

authentication

Attribute-Based権限管理は、ユーザーが追加されるたびにattributeを変更し、APIサーバーを再起動する必要があるため、管理が困難です。

それに対してRole-Basedは管理が容易です。

authentication

Authorization modeは、kube APIサーバーの起動時に設定できます。Node,RBAC,Webhook のように複数設定することも可能です。Authorization modeが複数設定された場合、指定した順序でAuthorizationが試行されます。

authentication

161 Role Based Access Controls

authorization-mode の確認方法:

$ kubectl describe pod kube-apiserver-controlplane -n kube-system

-- Authorization-mode=Node,RBAC

現在存在するRoleの確認方法:

$ kubectl get roles --all-namespaces

Roleの内容確認方法(configmapのget権限を持つRoleが存在):

$ kubectl describe  role kube-proxy -n kube-system
Name:         kube-proxy
Labels:       <none>
Annotations:  <none>
PolicyRule:
  Resources   Non-Resource URLs  Resource Names  Verbs
  ---------   -----------------  --------------  -----
  configmaps  []                 [kube-proxy]    [get]

Role Bindingの確認:

$  kubectl describe rolebinding kube-proxy -n kube-system
Name:         kube-proxy
Labels:       <none>
Annotations:  <none>
Role:
  Kind:  Role
  Name:  kube-proxy
Subjects:
  Kind   Name                                             Namespace
  ----   ----                                             ---------
  Group  system:bootstrappers:kubeadm:default-node-token

Role-Basedを使用するにはRoleを作成する必要があり、以下のようなファイルで作成できます。

authentication

authentication

role bindingでuserとroleを紐付けます。

authentication

can-iコマンドで権限チェックが可能です。

authentication

アクセス可能なResourceに対して、より細かい権限設定も可能です。

他のユーザーとして操作を行うには --as を使用します。

$ kubectl get pods --as dev-user
Error from server (Forbidden): pods is forbidden: User "dev-user" cannot list resource "pods" in API group "" in the namespace "default"

164 Cluster Roles and Roles Bindings

APIリソースの中にはnamespace内に存在するものがありますが、cluster roleはその外に存在します。これをCluster Scopeと呼びます。一種のスーパー権限を持つroleであるため、使用には注意が必要です。

authentication

このうちCluster AdminやStorage Admin Roleは以下のような権限を持ちます。Roleの作成は ClusterRole kindで行えます。

authentication

作成したRoleとUserをBindingするには、以下のようなbindingが必要です。

authentication

$ kubectl get clusterroles
$ kubectl get clusterrolebindings

167 Service Account

Kubernetesには、2種類のアカウントがあります。UserとServiceです。名前からもわかるように、User Accountは人が使用するアカウントで、Service Accountはマシンやプログラムが使用するアカウントです。

kubectl create serviceaccount <account_name>
kubectl create token <account_name>
kubectl get serviceaccount

Service Accountを作成するとtokenが一緒に生成されます。このトークンは外部アプリケーションがAPIで認証する際に使用され、この情報はKubernetes secretとして保存・管理されます。

authentication

Podを作成する際にdefault Service accountのvolumeが生成されるのも、このtokenを保存するためです。 保存場所は /var/run/secret/kubernetes.io/serviceaccount 配下です。serviceAccountの保存を行いたくない場合は、Podに automountServiceAccountToken をfalseに設定します。

Podに保存されたこのトークンにアクセスするには、kubectl exec -it <pod_name> ls /var/run/secret/kubernetes.io/serviceaccount を使用します。

authentication

default service accountは非常に限定された権限を持っています。そのため、pod-definition.ymlの spec.serviceAccountName にservice accountを指定します。

Kubernetes 1.22バージョンから、有効期限のないトークンの脆弱性改善のためにService Account Token APIが導入されました。このAPIを使用すると有効期限付きのトークンが発行されるため、より安全です。TokenRequestが使用できない場合にのみ、service account token secret Objectを作成することが推奨されています。

authentication

170 Image Security

imageを取得する際、image名の前のユーザーを省略すると 'library' というユーザーがデフォルトで付加されます。 その前にregistryを設定でき、最も有名なpublic registryは docker.iogcr.io です。 public registryにimageをアップロードしてはいけない場合は、private registryを使用できます。

docker login private-registry.io
docker run private-registry.io/apps/internal-app

private registryの場合、usernameとpasswordが必要ですが、これをそのままpod definitionにハードコーディングするとセキュリティ上問題があります。以下のようにsecretを作成して保存し、imagePullSecret セクションにsecret名を記入すれば、Podがprivate registryからimageを取得する際に問題ありません。

authentication

173 Security in docker

Dockerはコンテナを実行しますが、このプロセスを分離(isolate)するためにnamespaceという概念が導入されています。 ホストマシンで確認したコンテナのPIDと、コンテナ内部のPIDは異なります。また、デフォルトでは、明示的に指定しない場合、コンテナ内部でプロセスを実行するユーザーは root になります。

authentication

コンテナ内部の root ユーザーはホストの root ユーザーと同じ権限を持つのでしょうか?答えは「いいえ」です。では、ホストマシンをどこまで利用する権限があるのか気になるかもしれません。実際、Dockerはコンテナを実行するユーザーに制限された権限のみを付与します。さらに多くの権限を付与したい場合は、runコマンドに --cap-add <capability> を追加します。逆にprivilegeを削除するには --cap-drop を使用します。または、すべての権限をコンテナユーザーに付与するには --privileged を付けます。

authentication

174 Security Contexts

Dockerで設定していたcapabilityをコンテナレベルで設定するには、以下のようにします。Podレベルでは設定できません。

authentication

177 Network Policy

Kubernetesでは、クラスター内部のすべてのトラフィックを許可する戦略を取っています。しかし、何らかの理由で特定のポートやIPのみを許可する必要がある場合、Network Policyを設定できます。

authentication

以下のようにDB Podで3306ポートからのIngressのみを許可するNetwork Policyを設定すると、他のポートからのトラフィックは無視されます。

authentication

Network PolicyはSelectorでLabelを利用します。

authentication

Network Policyをサポートするアドオンには、Kube-router、Calico、Romana、Weave-netがあります。Flannelの場合はNetwork Policyをサポートしないため、アドオン選択時に考慮する必要があります。

178 Developing network policies

authentication

ingress内部でruleを複数に分けた場合、ORロジックで動作し、いずれかに該当するものがあればアクセスが許可されます。逆に - を削除して1つのブロックにまとめた場合は AND で動作します。ipBlock を定義して特定のIPがPodにアクセスすることを許可することもできます。

authentication

egress用のnetwork policyもingressと同様に定義できます。

authentication

Network Policyの作成方法は以下の通りです。

Policy Name: internal-policy Policy Type: Egress Egress Allow: payroll Payroll Port: 8080 Egress Allow: mysql MySQL Port: 3306

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: internal-policy
  namespace: default
spec:
  podSelector:
    matchLabels:
      name: internal
  policyTypes:
  - Egress
  - Ingress
  ingress:
    - {}
  egress:
  - to:
    - podSelector:
        matchLabels:
          name: mysql
    ports:
    - protocol: TCP
      port: 3306

  - to:
    - podSelector:
        matchLabels:
          name: payroll
    ports:
    - protocol: TCP
      port: 8080

  - ports:
    - port: 53
      protocol: UDP
    - port: 53
      protocol: TCP

egressを複数作成する場合は以下のようにします。

kind: NetworkPolicy
metadata:
  name: internal-policy
  namespace: default
spec:
  podSelector:
    matchLabels:
      name: internal
  policyTypes:
  - Egress
  egress:
  - to:
    - podSelector:
        matchLabels:
          name: mysql
    ports:
    - protocol: TCP
      port: 3306
  - to:
    - podSelector:
        matchLabels:
          name: payroll
    ports:
    - protocol: TCP
      port: 8080

クイズ

Q1: 「CKA_7_Security」の主なトピックは何ですか? CKA_7_Security

Q2: この記事の重要なポイントは何ですか? CKA_7_Security

Q3: この記事の概念を実践にどう適用できますか? 記事全体で議論されている実践的な例やパターンを参考にしてください。

コメント

まだコメントはありません。

ログインするとコメントできます