著者は、 Write for DOnations プログラムの一環として、 Open Sourcing MentalIllnessを選択して寄付を受け取りました。

序章

オープンソースのコンテナオーケストレーションプラットフォームであるKubernetesは、高可用性クラスターの自動化、スケーリング、管理に適したソリューションになりつつあります。 人気が高まっている結果、Kubernetesのセキュリティはますます重要になっています。

Kubernetesに関連する可動部分とさまざまなデプロイシナリオを考慮すると、Kubernetesのセキュリティ保護は複雑になる場合があります。 このため、この記事の目的は、 DigitalOcean Kubernetes(DOKS)クラスターの強固なセキュリティ基盤を提供することです。 このチュートリアルでは、Kubernetesの基本的なセキュリティ対策について説明しており、網羅的なガイドではなく、出発点となることを目的としています。 その他の手順については、Kubernetesの公式ドキュメントをご覧ください。

このガイドでは、DigitalOceanKubernetesクラスターを保護するための基本的な手順を実行します。 TLS / SSL証明書を使用して安全なローカル認証を構成し、ロールベースのアクセス制御(RBAC)を使用してローカルユーザーにアクセス許可を付与し、を使用してKubernetesアプリケーションとデプロイにアクセス許可を付与しますサービスアカウント、およびResourceQuotaおよびLimitRangeアドミッションコントローラーを使用してリソース制限を設定します。

前提条件

このチュートリアルを完了するには、次のものが必要です。

  • 3つの標準ノードがそれぞれ少なくとも2GBRAMおよび1vCPUで構成されたDigitalOceanKubernetes(DOKS)マネージドクラスター。 DOKSクラスターを作成する方法の詳細については、 KubernetesQuickstartガイドをご覧ください。 このチュートリアルでは、DOKSバージョン1.16.2-do.1を使用します。
  • DigitalOceanコントロールパネルからダウンロードされ~/.kube/configとして保存されたクラスター構成ファイルを使用して、DOKSクラスターを管理するように構成されたローカルクライアント。 リモートDOKS管理を構成する方法の詳細については、ガイド DigitalOceanKubernetesClusterに接続する方法をお読みください。 特に、次のものが必要になります。 ローカルマシンにインストールされているkubectlコマンドラインインターフェイス。 kubectlのインストールと構成の詳細については、公式ドキュメントを参照してください。 このチュートリアルでは、kubectlバージョン1.17.0-00を使用します。 公式のDigitalOceanコマンドラインツールであるdoctl。 これをインストールする方法については、doctlGitHubページを参照してください。 このチュートリアルでは、doctlバージョン1.36.0を使用します。

ステップ1—リモートユーザー認証を有効にする

前提条件を完了すると、事前定義されたDigitalOceanベアラートークンを介して認証する1人のKubernetesスーパーユーザーができあがります。 ただし、これらの資格情報を共有することは、このアカウントがクラスターに大規模で破壊的な変更を引き起こす可能性があるため、適切なセキュリティ慣行ではありません。 この可能性を軽減するために、それぞれのローカルクライアントから認証される追加のユーザーを設定できます。

このセクションでは、安全なSSL / TLS証明書を使用して、ローカルクライアントからリモートDOKSクラスターに対して新しいユーザーを認証します。 これは3つのステップのプロセスになります。最初に、ユーザーごとに証明書署名要求(CSR)を作成し、次にkubectlを介してクラスター内でそれらの証明書を直接承認します。 最後に、適切な証明書を使用して各ユーザーにkubeconfigファイルを作成します。 Kubernetesでサポートされている追加の認証方法の詳細については、Kubernetes認証ドキュメントを参照してください。

新規ユーザー向けの証明書署名要求の作成

開始する前に、前提条件の間に構成されたローカルマシンからのDOKSクラスター接続を確認してください。

  1. kubectl cluster-info

構成に応じて、出力は次のようになります。

Output
Kubernetes master is running at https://a6616782-5b7f-4381-9c0f-91d6004217c7.k8s.ondigitalocean.com CoreDNS is running at https://a6616782-5b7f-4381-9c0f-91d6004217c7.k8s.ondigitalocean.com/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.

これは、DOKSクラスターに接続していることを意味します。

次に、クライアントの証明書用のローカルフォルダーを作成します。 このガイドでは、~/certsを使用してすべての証明書を保存します。

  1. mkdir ~/certs

このチュートリアルでは、sammyという新しいユーザーにクラスターへのアクセスを許可します。 これを任意のユーザーに自由に変更してください。 SSLおよびTLSライブラリOpenSSLを使用して、次のコマンドを使用してユーザーの新しい秘密鍵を生成します。

  1. openssl genrsa -out ~/certs/sammy.key 4096

-outフラグは出力ファイルを~/certs/sammy.keyにし、4096はキーを4096ビットに設定します。 OpenSSLの詳細については、 OpenSSLEssentialsガイドを参照してください。

次に、証明書署名要求構成ファイルを作成します。 次のファイルをテキストエディタで開きます(このチュートリアルでは、nanoを使用します)。

  1. nano ~/certs/sammy.csr.cnf

次のコンテンツをsammy.csr.cnfファイルに追加して、サブジェクトに一般名(CN)として目的のユーザー名を指定し、組織(O)としてグループを指定します。

〜/ certs / sammy.csr.cnf
[ req ]
default_bits = 2048
prompt = no
default_md = sha256
distinguished_name = dn
[ dn ]
CN = sammy
O = developers
[ v3_ext ]
authorityKeyIdentifier=keyid,issuer:always
basicConstraints=CA:FALSE
keyUsage=keyEncipherment,dataEncipherment
extendedKeyUsage=serverAuth,clientAuth

証明書署名要求の構成ファイルには、必要なすべての情報、ユーザーID、およびユーザーの適切な使用パラメーターが含まれています。 最後の引数extendedKeyUsage=serverAuth,clientAuthを使用すると、ユーザーは、署名された証明書を使用して、DOKSクラスターでローカルクライアントを認証できます。

次に、sammy証明書署名要求を作成します。

  1. openssl req -config ~/certs/sammy.csr.cnf -new -key ~/certs/sammy.key -nodes -out ~/certs/sammy.csr

-configを使用すると、CSRの構成ファイルを指定でき、-newは、-keyで指定されたキーの新しいCSRを作成していることを通知します。

次のコマンドを実行して、証明書署名要求を確認できます。

  1. openssl req -in ~/certs/sammy.csr -noout -text

ここでは、-inを使用してCSRを渡し、-textを使用して証明書要求をテキストで印刷します。

出力には証明書要求が表示され、その最初は次のようになります。

Output
Certificate Request: Data: Version: 1 (0x0) Subject: CN = sammy, O = developers Subject Public Key Info: Public Key Algorithm: rsaEncryption RSA Public-Key: (4096 bit) ...

同じ手順を繰り返して、追加のユーザーのCSRを作成します。 管理者の~/certsフォルダーにすべての証明書署名要求を保存したら、次の手順に進んでそれらを承認します。

KubernetesAPIを使用した証明書署名要求の管理

kubectlコマンドラインツールを使用して、KubernetesAPIに発行されたTLS証明書を承認または拒否できます。 これにより、要求されたアクセスが特定のユーザーに適切であることを確認できます。 このセクションでは、 sammy の証明書要求を送信し、それを証明します。

CSRをDOKSクラスターに送信するには、次のコマンドを使用します。

cat <<EOF | kubectl apply -f -
apiVersion: certificates.k8s.io/v1beta1
kind: CertificateSigningRequest
metadata:
  name: sammy-authentication
spec:
  groups:
  - system:authenticated
  request: $(cat ~/certs/sammy.csr | base64 | tr -d '\n')
  usages:
  - digital signature
  - key encipherment
  - server auth
  - client auth
EOF

ヒアドキュメントを使用して、このコマンドはcatを使用して証明書要求をkubectl applyに渡します。

証明書のリクエストを詳しく見てみましょう。

  • name: sammy-authenticationは、メタデータ識別子(この場合はsammy-authentication)を作成します。
  • request: $(cat ~/certs/sammy.csr | base64 | tr -d '\n')は、sammy.csr証明書署名要求をBase64としてエンコードされたクラスターに送信します。
  • server authおよびclient authは、証明書の使用目的を指定します。 この場合、目的はユーザー認証です。

出力は次のようになります。

Output
certificatesigningrequest.certificates.k8s.io/sammy-authentication created

次のコマンドを使用して、証明書署名要求のステータスを確認できます。

  1. kubectl get csr

クラスタ構成に応じて、出力は次のようになります。

Output
NAME AGE REQUESTOR CONDITION sammy-authentication 37s your_DO_email Pending

次に、次のコマンドを使用してCSRを承認します。

  1. kubectl certificate approve sammy-authentication

操作を確認するメッセージが表示されます。

Output
certificatesigningrequest.certificates.k8s.io/sammy-authentication approved

注:管理者は、コマンドkubectl certificate deny sammy-authenticationを使用してCSRを拒否することもできます。 TLS証明書の管理の詳細については、Kubernetesの公式ドキュメントをご覧ください。

CSRが承認されたので、次のコマンドを実行して、CSRをローカルマシンにダウンロードできます。

  1. kubectl get csr sammy-authentication -o jsonpath='{.status.certificate}' | base64 --decode > ~/certs/sammy.crt

このコマンドは、kubectlで適切に使用できるようにBase64証明書をデコードしてから、~/certs/sammy.crtとして保存します。

sammy 署名付き証明書が手元にあるので、ユーザーのkubeconfigファイルを作成できるようになりました。

リモートユーザーの構築Kubeconfig

次に、sammyユーザー用の特定のkubeconfigファイルを作成します。 これにより、ユーザーのクラスターへのアクセスをより細かく制御できるようになります。

新しいkubeconfigを構築する最初のステップは、現在のkubeconfigファイルのコピーを作成することです。 このガイドの目的上、新しいkubeconfigファイルはconfig-sammyと呼ばれます。

  1. cp ~/.kube/config ~/.kube/config-sammy

次に、新しいファイルを編集します。

  1. nano ~/.kube/config-sammy

このファイルの最初の8行は、クラスターとのSSL / TLS接続に必要な情報が含まれているため、保持してください。 次に、userパラメータから始めて、テキストを次の強調表示された行に置き換え、ファイルが次のようになるようにします。

config-sammy
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: certificate_data
  name: do-nyc1-do-cluster
contexts:
- context:
    cluster: do-nyc1-do-cluster
    user: sammy
  name: do-nyc1-do-cluster
current-context: do-nyc1-do-cluster
kind: Config
preferences: {}
users:
- name: sammy
  user:
    client-certificate: /home/your_local_user/certs/sammy.crt
    client-key: /home/your_local_user/certs/sammy.key

注: client-certificateclient-keyの両方で、対応する証明書の場所への絶対パスを使用してください。 そうしないと、kubectlでエラーが発生します。

ファイルを保存して終了します。

kubectl cluster-infoを使用して、新しいユーザー接続をテストできます。

  1. kubectl --kubeconfig=/home/your_local_user/.kube/config-sammy cluster-info

次のようなエラーが表示されます。

Output
To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'. Error from server (Forbidden): services is forbidden: User "sammy" cannot list resource "services" in API group "" in the namespace "kube-system"

ユーザーsammyには、クラスター上のリソースを一覧表示する権限がまだないため、このエラーが発生する可能性があります。 ユーザーへの承認の付与については、次のステップで説明します。 今のところ、出力はSSL / TLS接続が成功し、sammy認証クレデンシャルがKubernetesAPIによって受け入れられたことを確認しています。

ステップ2—ロールベースのアクセス制御(RBAC)によるユーザーの承認

ユーザーが認証されると、APIはKubernetesの組み込みのロールベースアクセス制御(RBAC)モデルを使用してその権限を決定します。 RBACは、割り当てられた役割に基づいてユーザー権限を制限する効果的な方法です。 セキュリティの観点から、RBACでは、ユーザーが機密データにアクセスしたり、スーパーユーザーレベルのコマンドを実行したりすることを制限するためのきめ細かい権限を設定できます。 ユーザーロールの詳細については、KubernetesRBACのドキュメントを参照してください。

このステップでは、kubectlを使用して、default名前空間のユーザーsammyに事前定義されたロールeditを割り当てます。 実稼働環境では、カスタムロールやカスタムロールバインディングを使用することをお勧めします。

権限の付与

Kubernetesでは、権限を付与するということは、目的のロールをユーザーに割り当てることを意味します。 次のコマンドを使用して、default名前空間のユーザーsammyedit権限を割り当てます。

  1. kubectl create rolebinding sammy-edit-role --clusterrole=edit --user=sammy --namespace=default

これにより、次のような出力が得られます。

Output
rolebinding.rbac.authorization.k8s.io/sammy-edit-role created

このコマンドをさらに詳しく分析してみましょう。

  • create rolebinding sammy-edit-roleは、この場合はsammy-edit-roleと呼ばれる新しいロールバインディングを作成します。
  • --clusterrole=editは、事前定義されたロールeditをグローバルスコープ(クラスターロール)に割り当てます。
  • --user=sammyは、ロールをバインドするユーザーを指定します。
  • --namespace=defaultは、指定された名前空間(この場合はdefault)内のユーザーロール権限を付与します。

次に、default名前空間にポッドをリストして、ユーザー権限を確認します。 エラーが表示されない場合は、RBAC認証が期待どおりに機能しているかどうかを確認できます。

  1. kubectl --kubeconfig=/home/your_local_user/.kube/config-sammy auth can-i get pods

次の出力が得られます。

Output
yes

sammy にアクセス許可を割り当てたので、次のセクションでそれらのアクセス許可を取り消す練習をすることができます。

権限の取り消し

Kubernetesでの権限の取り消しは、ユーザーロールバインディングを削除することで行われます。

このチュートリアルでは、次のコマンドを実行して、ユーザーsammyからeditロールを削除します。

  1. kubectl delete rolebinding sammy-edit-role

次の出力が得られます。

Output
rolebinding.rbac.authorization.k8s.io "sammy-edit-role" deleted

default名前空間ポッドを一覧表示して、ユーザー権限が期待どおりに取り消されたかどうかを確認します。

  1. kubectl --kubeconfig=/home/localuser/.kube/config-sammy --namespace=default get pods

次のエラーが表示されます。

Output
Error from server (Forbidden): pods is forbidden: User "sammy" cannot list resource "pods" in API group "" in the namespace "default"

これは、承認が取り消されたことを示しています。

セキュリティの観点から、Kubernetes認証モデルにより、クラスタ管理者は必要に応じてオンデマンドでユーザー権限を変更できる柔軟性が得られます。 さらに、役割ベースのアクセス制御は物理ユーザーに限定されません。 次のセクションで学習するように、クラスターサービスへのアクセス許可を付与および削除することもできます。

RBAC承認とカスタムロールの作成方法の詳細については、公式ドキュメントをお読みください。

ステップ3—サービスアカウントを使用したアプリケーションのアクセス許可の管理

前のセクションで述べたように、RBAC認証メカニズムは人間のユーザーを超えて拡張されます。 ポッド内で実行されているアプリケーション、サービス、プロセスなどの人間以外のクラスターユーザーは、Kubernetesがサービスアカウントと呼ぶものを使用してAPIサーバーで認証します。 名前空間内にポッドを作成する場合は、defaultサービスアカウントを使用させるか、任意のサービスアカウントを定義できます。 個々のSAをアプリケーションとプロセスに割り当てる機能により、管理者は必要に応じてアクセス許可を付与または取り消すことができます。 さらに、特定のSAを本番環境に不可欠なアプリケーションに割り当てることは、セキュリティのベストプラクティスと見なされます。 サービスアカウントは認証、つまりRBAC承認チェックに使用されるため、クラスター管理者は、サービスアカウントのアクセス権を変更し、問題のあるプロセスを分離することで、セキュリティの脅威を封じ込めることができます。

サービスアカウントを示すために、このチュートリアルでは、サンプルアプリケーションとして NginxWebサーバーを使用します。

アプリケーションに特定のSAを割り当てる前に、SAを作成する必要があります。 default名前空間にnginx-saという名前の新しいサービスアカウントを作成します。

  1. kubectl create sa nginx-sa

あなたが得るでしょう:

Output
serviceaccount/nginx-sa created

次のコマンドを実行して、サービスアカウントが作成されたことを確認します。

  1. kubectl get sa

これにより、サービスアカウントのリストが表示されます。

Output
NAME SECRETS AGE default 1 22h nginx-sa 1 80s

次に、nginx-saサービスアカウントに役割を割り当てます。 この例では、nginx-sasammyユーザーと同じ権限を付与します。

  1. kubectl create rolebinding nginx-sa-edit \
  2. --clusterrole=edit \
  3. --serviceaccount=default:nginx-sa \
  4. --namespace=default

これを実行すると、次のようになります。

Output
rolebinding.rbac.authorization.k8s.io/nginx-sa-edit created

このコマンドは、[X51X]