10.7. Zero Trust Workload Identity Manager の OIDC フェデレーション
Zero Trust Workload Identity Manager は、SPIRE Server を OIDC プロバイダーとして機能させることで、OpenID Connect (OIDC) と統合します。これにより、ワークロードが、検証可能な JSON Web Tokens (SPIFFE Verifiable Identity Documents (JWT-SVIDs)) を、ローカルの SPIRE Agent から要求して受信できるようになります。その後、クラウドプロバイダーなどの外部システムが、SPIRE Server によって公開される OIDC 検出エンドポイントを使用して公開鍵を取得できるようになります。
以下のプロバイダーは、SPIRE OIDC フェデレーションで動作することが検証済みです。
- Azure Entra ID
- Vault
10.7.1. Entra ID OpenID Connect について リンクのコピーリンクがクリップボードにコピーされました!
Entra ID は、ユーザーとアクセス制御を一元管理するクラウドベースのアイデンティティーおよびアクセス管理サービスです。Entra ID は ID プロバイダーとして機能し、ユーザーアイデンティティーを確認して、アプリケーションに ID トークンを発行します。このトークンには重要なユーザー情報が含まれているため、アプリケーションはユーザーの認証情報を管理せずにユーザーの身元を確認できます。
Entra ID OpenID Connect (OIDC) を SPIRE と統合すると、有効期間の短い自動の暗号化アイデンティティーがワークロードに提供されます。SPIRE が発行したアイデンティティーは、静的なシークレットを使用せずにサービスをセキュアに認証するために、Entra ID に送信されます。
10.7.1.1. マネージド OIDC Discovery Provider ルートの外部証明書の設定 リンクのコピーリンクがクリップボードにコピーされました!
マネージドルートは、External Route Certificate 機能を使用して、tls.externalCertificate フィールドを、外部で管理される Transfer Layer Security (TLS) シークレットの名前に設定します。
前提条件
- Zero Trust Workload Identity Manager 0.2.0 以降がインストールされている。
- クラスターに SPIRE Server、SPIRE Agent、SPIFFEE CSI ドライバー、および SPIRE OIDC Discovery Provider オペランドがデプロイされている。
- cert-manager Operator for Red Hat OpenShift がインストールされている。詳細は、cert-manager Operator for Red Hat OpenShift のインストール を参照してください。
-
公に信頼された CA サービスで設定された
ClusterIssuerまたはIssuerが作成されている。たとえば、"Let’s Encrypt ACME" サービスを使用した、Automated Certificate Management Environment (ACME) タイプのIssuerなどです。詳細は、ACME 発行者の設定 を参照してください。
手順
次のコマンドを実行して、参照先のシークレットを読み取る権限をルーターのサービスアカウントに付与するための
Roleを作成します。$ oc create role secret-reader \ --verb=get,list,watch \ --resource=secrets \ --resource-name=$TLS_SECRET_NAME \ -n zero-trust-workload-identity-manager次のコマンドを実行して、ルーターのサービスアカウントを、新しく作成した Role リソースにバインドする
RoleBindingリソースを作成します。$ oc create rolebinding secret-reader-binding \ --role=secret-reader \ --serviceaccount=openshift-ingress:router \ -n zero-trust-workload-identity-manager次のコマンドを実行して、前のステップで生成したた Secret を参照するように
SpireOIDCDIscoveryProviderカスタムリソース (CR) オブジェクトを設定します。$ oc patch SpireOIDCDiscoveryProvider cluster --type=merge -p=' spec: externalSecretRef: ${TLS_SECRET_NAME} '
検証
SpireOIDCDiscoveryProviderCR で、次のコマンドを実行して、ManageRouteReady条件がTrueに設定されているかどうかを確認します。$ oc wait --for=jsonpath='{.status.conditions[?(@.type=="ManagedRouteReady")].status}'=True SpireOIDCDiscoveryProvider/cluster --timeout=120s次のコマンドを実行して、OIDC エンドポイントに HTTPS 経由でセキュアにアクセスできることを確認します。
$ curl https://$JWT_ISSUER_ENDPOINT/.well-known/openid-configuration { "issuer": "https://$JWT_ISSUER_ENDPOINT", "jwks_uri": "https://$JWT_ISSUER_ENDPOINT/keys", "authorization_endpoint": "", "response_types_supported": [ "id_token" ], "subject_types_supported": [], "id_token_signing_alg_values_supported": [ "RS256", "ES256", "ES384" ] }%
10.7.1.2. マネージドルートの無効化 リンクのコピーリンクがクリップボードにコピーされました!
OIDC Discovery Provider サービスの公開動作を完全に制御する必要がある場合は、要件に応じてマネージドルートを無効にできます。
手順
OIDC Discovery Provider を手動で設定するには、次のコマンドを実行して
managedRouteをfalseに設定します。$ oc patch SpireOIDCDiscoveryProvider cluster --type=merge -p=' spec: managedRoute: "false"
10.7.1.3. Microsoft Azure での Entra ID の使用 リンクのコピーリンクがクリップボードにコピーされました!
Entra ID の設定が完了したら、Azure で動作するように Entra ID を設定できます。
前提条件
- 公的に信頼された CA からの TLS 証明書を提供するように、SPIRE OIDC Discovery Provider ルートを設定した。
手順
次のコマンドを実行して、Azure にログインします。
$ az login次のコマンドを実行して、Azure サブスクリプションとテナントの変数を設定します。
$ export SUBSCRIPTION_ID=$(az account list --query "[?isDefault].id" -o tsv)$ export TENANT_ID=$(az account list --query "[?isDefault].tenantId" -o tsv)$ export LOCATION=centralusここでは、以下のようになります。
購読 ID- お客様固有の購読識別子を指定します。
テナント ID- Azure Active Directory インスタンスの ID を指定します。
LOCATION- リソースを作成する Azure リージョン。
次のコマンドを実行して、リソースの変数名を定義します。
$ export NAME=ztwim$ export RESOURCE_GROUP="${NAME}-rg"$ export STORAGE_ACCOUNT="${NAME}storage"$ export STORAGE_CONTAINER="${NAME}storagecontainer"$ export USER_ASSIGNED_IDENTITY_NAME="${NAME}-identity"ここでは、以下のようになります。
名前- すべてのリソースの基本名を指定します。
リソースグループ- リソースグループの名前を指定します。
ストレージアカウント- ストレージアカウントの名前を指定します。
ストレージコンテナー- ストレージコンテナーの名前を指定します。
ユーザー割り当て ID 名- 管理対象アイデンティティーの名前を指定します。
次のコマンドを実行してリソースグループを作成します。
$ az group create \ --name "${RESOURCE_GROUP}" \ --location "${LOCATION}"
10.7.1.4. Azure Blob Storage の設定 リンクのコピーリンクがクリップボードにコピーされました!
コンテンツを保存するために使用する新しいストレージアカウントを作成する必要があります。
手順
次のコマンドを実行して、コンテンツを保存するために使用する新しいストレージアカウントを作成します。
$ az storage account create \ --name ${STORAGE_ACCOUNT} \ --resource-group ${RESOURCE_GROUP} \ --location ${LOCATION} \ --encryption-services blob次のコマンドを実行して、新しく作成したストレージアカウントのストレージ ID を取得します。
$ export STORAGE_ACCOUNT_ID=$(az storage account show -n ${STORAGE_ACCOUNT} -g ${RESOURCE_GROUP} --query id --out tsv)次のコマンドを実行して、新しく作成したストレージアカウント内にストレージコンテナーを作成し、Blob のストレージをサポートするための場所を提供します。
$ az storage container create \ --account-name ${STORAGE_ACCOUNT} \ --name ${STORAGE_CONTAINER} \ --auth-mode login
10.7.1.5. Azure のユーザーマネージド ID の設定 リンクのコピーリンクがクリップボードにコピーされました!
新しいユーザーマネージド ID を作成し、そのユーザーマネージド ID に関連付けられている関連サービスプリンシパルのクライアント ID を取得する必要があります。
手順
次のコマンドを実行して、新しいユーザーマネージド ID を作成し、そのユーザーマネージド ID に関連付けられている関連サービスプリンシパルのクライアント ID を取得します。
$ az identity create \ --name ${USER_ASSIGNED_IDENTITY_NAME} \ --resource-group ${RESOURCE_GROUP}$ export IDENTITY_CLIENT_ID=$(az identity show --resource-group "${RESOURCE_GROUP}" --name "${USER_ASSIGNED_IDENTITY_NAME}" --query 'clientId' -otsv)次のコマンドを実行して、Azure ユーザー割り当てマネージド ID の
CLIENT_IDを取得し、それを環境変数として保存します。$ export IDENTITY_CLIENT_ID=$(az identity show --resource-group "${RESOURCE_GROUP}" --name "${USER_ASSIGNED_IDENTITY_NAME}" --query 'clientId' -otsv)次のコマンドを実行して、ユーザーマネージド ID に関連付けられているサービスプリンシパルにロールを関連付けます。
$ az role assignment create \ --role "Storage Blob Data Contributor" \ --assignee "${IDENTITY_CLIENT_ID}" \ --scope ${STORAGE_ACCOUNT_ID}
10.7.1.6. デモアプリケーションの作成 リンクのコピーリンクがクリップボードにコピーされました!
デモアプリケーションを使用すると、システム全体が動作するかどうかを確認できます。
手順
デモアプリケーションを作成するには、次の手順を実行します。
次のコマンドを実行して、アプリケーション名と namespace を設定します。
$ export APP_NAME=workload-app$ export APP_NAMESPACE=demo以下のコマンドを実行して namespace を作成します。
$ oc create namespace $APP_NAMESPACE次のコマンドを実行して、アプリケーションの Secret を作成します。
$ oc apply -f - << EOF apiVersion: v1 kind: Secret metadata: name: $APP_NAME namespace: $APP_NAMESPACE stringData: AAD_AUTHORITY: https://login.microsoftonline.com/ AZURE_AUDIENCE: "api://AzureADTokenExchange" AZURE_TENANT_ID: "${TENANT_ID}" AZURE_CLIENT_ID: "${IDENTITY_CLIENT_ID}" BLOB_STORE_ACCOUNT: "${STORAGE_ACCOUNT}" BLOB_STORE_CONTAINER: "${STORAGE_CONTAINER}" EOF
10.7.1.7. ワークロードアプリケーションのデプロイ リンクのコピーリンクがクリップボードにコピーされました!
デモアプリケーションを作成したら、デプロイします。
前提条件
- デモアプリケーションが作成およびデプロイ済みである。
手順
アプリケーションをデプロイするには、以下に記載のコマンドブロック全体をコピーし、ターミナルに直接貼り付けます。Enter キーを押します。
$ oc apply -f - << EOF apiVersion: v1 kind: ServiceAccount metadata: name: $APP_NAME namespace: $APP_NAMESPACE --- kind: Deployment apiVersion: apps/v1 metadata: name: $APP_NAME namespace: $APP_NAMESPACE spec: selector: matchLabels: app: $APP_NAME template: metadata: labels: app: $APP_NAME deployment: $APP_NAME spec: serviceAccountName: $APP_NAME containers: - name: $APP_NAME image: "registry.redhat.io/ubi9/python-311:latest" command: - /bin/bash - "-c" - | #!/bin/bash pip install spiffe azure-cli cat << EOF > /opt/app-root/src/get-spiffe-token.py #!/opt/app-root/bin/python from spiffe import JwtSource import argparse parser = argparse.ArgumentParser(description='Retrieve SPIFFE Token.') parser.add_argument("-a", "--audience", help="The audience to include in the token", required=True) args = parser.parse_args() with JwtSource() as source: jwt_svid = source.fetch_svid(audience={args.audience}) print(jwt_svid.token) EOF chmod +x /opt/app-root/src/get-spiffe-token.py while true; do sleep 10; done envFrom: - secretRef: name: $APP_NAME env: - name: SPIFFE_ENDPOINT_SOCKET value: unix:///run/spire/sockets/spire-agent.sock securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL readOnlyRootFilesystem: false runAsNonRoot: true seccompProfile: type: RuntimeDefault ports: - containerPort: 8080 protocol: TCP volumeMounts: - name: spiffe-workload-api mountPath: /run/spire/sockets readOnly: true volumes: - name: spiffe-workload-api csi: driver: csi.spiffe.io readOnly: true EOF
検証
次のコマンドを実行して、
workload-appPod が正常に実行されていることを確認します。$ oc get pods -n $APP_NAMESPACE出力例
NAME READY STATUS RESTARTS AGE workload-app-5f8b9d685b-abcde 1/1 Running 0 60sSPIFFE JWT Token (SVID-JWT) を取得します。
次のコマンドを実行して、Pod 名を動的に取得します。
$ POD_NAME=$(oc get pods -n $APP_NAMESPACE -l app=$APP_NAME -o jsonpath='{.items[0].metadata.name}')次のコマンドを実行して、Pod 内でスクリプトを実行します。
$ oc exec -it $POD_NAME -n $APP_NAMESPACE -- \ /opt/app-root/src/get-spiffe-token.py -a "api://AzureADTokenExchange"
10.7.1.8. SPIFFE アイデンティティーフェデレーションを使用した Azure の設定 リンクのコピーリンクがクリップボードにコピーされました!
SPIFFE アイデンティティーフェデレーションを使用して Azure を設定すると、デモアプリケーションに対するパスワード不要の自動認証を有効にできます。
手順
次のコマンドを実行して、ユーザーマネージド ID と、ワークロードアプリケーションに関連付けられている SPIFFE アイデンティティーの間で、アイデンティティーをフェデレーションします。
$ az identity federated-credential create \ --name ${NAME} \ --identity-name ${USER_ASSIGNED_IDENTITY_NAME} \ --resource-group ${RESOURCE_GROUP} \ --issuer https://$JWT_ISSUER_ENDPOINT \ --subject spiffe://$APP_DOMAIN/ns/$APP_NAMESPACE/sa/$APP_NAME \ --audience api://AzureADTokenExchange
10.7.1.9. アプリケーションワークロードが Azure Blob Storage 内のコンテンツにアクセスできることを確認する リンクのコピーリンクがクリップボードにコピーされました!
アプリケーションワークロードが Azure Blob Storage にアクセスできるかどうかを確認できます。
前提条件
- Azure Blob Storage が作成済みである。
手順
次のコマンドを実行して、SPIFFE Workload API から JWT トークンを取得します。
$ oc rsh -n $APP_NAMESPACE deployment/$APP_NAME次のコマンドを実行して、
TOKENという名前の環境変数を作成してエクスポートします。$ export TOKEN=$(/opt/app-root/src/get-spiffe-token.py --audience=$AZURE_AUDIENCE)次のコマンドを実行して、Pod 内に含まれる Azure CLI にログインします。
$ az login --service-principal \ -t ${AZURE_TENANT_ID} \ -u ${AZURE_CLIENT_ID} \ --federated-token ${TOKEN}次のコマンドを実行して、アプリケーションワークロード Pod で新しいファイルを作成し、そのファイルを Blob Storage にアップロードします。
$ echo “Hello from OpenShift” > openshift-spire-federated-identities.txt次のコマンドを実行して、Azure Blog Storage にファイルをアップロードします。
$ az storage blob upload \ --account-name ${BLOB_STORE_ACCOUNT} \ --container-name ${BLOB_STORE_CONTAINER} \ --name openshift-spire-federated-identities.txt \ --file openshift-spire-federated-identities.txt \ --auth-mode login
検証
次のコマンドを実行して、含まれているファイルをリスト表示し、ファイルが正常にアップロードされたことを確認します。
$ az storage blob list \ --account-name ${BLOB_STORE_ACCOUNT} \ --container-name ${BLOB_STORE_CONTAINER} \ --auth-mode login \ -o table