AWS CloudFormation の AWS::EKS::Cluster から OIDC プロバイダーの URL を取得するにはどうすればよいですか?
最終更新日: 2020 年 8 月 20 日
AWS::EKS::Cluster から OpenID Connect (OIDC) プロバイダーの URL を取得したいと考えています。その後、AWS CloudFormation を使用して、サービスアカウントの信頼関係のために AWS Identity and Access Management (IAM) ロールの URL を使用したいと考えています。
簡単な説明
AWS::EKS::Cluster では、OIDC プロバイダーの URL を取得するための戻り値が提供されません。既存の Amazon Elastic Kubernetes Service (Amazon EKS) クラスターからクラスター OIDC プロバイダーの URL を取得するには、AWS CloudFormation で AWS Lambda-backed カスタムリソースを使用する必要があります。その後、クラスターからの戻り値を使用して IAM ロールを作成できます。IAM ロールを使用すると、OIDC との信頼関係を確立できます。
注意: 以下の解決方法は Python 3.7 を使用しており、Kubernetes バージョン 1.14 以降に適用できます。
解決方法
次の例では、Amazon EKS クラスターのサービスアカウントを IAM ロールに関連付ける方法を示します。IAM ロールは、Amazon EKS ポッドに対するきめ細かなアクセス許可と、Amazon EKS クラスターのサービスアカウントに対する AWS API への安全なアクセスを提供します。その後、スタックによって Amazon EKS クラスターの OIDC 値に関連付けられた IAM ロールが作成されます。
1. 次の例に基づいて、CustomLambdaEksOidc.template という AWS CloudFormation テンプレートを作成します。
Parameters:
EKSClusterName:
Type: String
Description: Provide the name for EKS Cluster
Resources:
ClusterName:
Type: Custom::ClusterName
Properties:
ServiceToken: !GetAtt LambdaFunction.Arn
cluster_name:
Ref: EKSClusterName
MyIAMRole:
Type: AWS::IAM::Role
DependsOn: ClusterName
Properties:
AssumeRolePolicyDocument: !Sub |
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::${AWS::AccountId}:oidc-provider/${ClusterName.oidc}"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"${ClusterName.oidc}:aud": "system:serviceaccount:default:my-serviceaccount"
}
}
}
]
}
LambdaIAMRole:
Type: 'AWS::IAM::Role'
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
Action:
- 'sts:AssumeRole'
Path: /
Policies:
- PolicyName: root
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- 'eks:DescribeCluster'
Resource: '*'
- Effect: Allow
Action:
- 'logs:CreateLogGroup'
- 'logs:CreateLogStream'
- 'logs:PutLogEvents'
Resource: 'arn:aws:logs:*:*:*'
LambdaFunction:
Type: AWS::Lambda::Function
Properties:
Code:
ZipFile: |
import cfnresponse
import boto3
import json
def lambda_handler(event, context):
print("Received event: " + json.dumps(event, indent=2))
oidc_response = ''
responseData = {}
try:
if event['RequestType'] == 'Delete':
print("Request Type:",event['RequestType'])
print("Delete Request - No Physical resources to delete")
elif event['RequestType'] == 'Create' or event['RequestType'] == 'Update':
print("Request Type:",event['RequestType'])
cluster_name = event['ResourceProperties']['cluster_name']
oidc_response_url = fetchClusterOIDC(cluster_name)
oidc_response=oidc_response_url.split("https://")[1]
responseData['oidc'] = oidc_response
print("Sending response to custom resource for event type " + event['RequestType'])
cfnresponse.send(event, context, cfnresponse.SUCCESS, responseData, "CustomResourcePhysicalID")
return oidc_response
except Exception as e:
print('Failed to process:', e)
responseStatus = 'FAILURE'
responseData = {'Failure': 'Something bad happened.'}
cfnresponse.send(event, context, cfnresponse.FAILED, responseData, "CustomResourcePhysicalID")
def fetchClusterOIDC(cluster_name):
print("Getting Cluster OIDC value for cluster name "+ cluster_name)
oidc = ''
client = boto3.client('eks')
try:
response = client.describe_cluster(
name=cluster_name
)
if response['ResponseMetadata']['HTTPStatusCode'] == 200:
print("Success response recieved for describing cluster "+ cluster_name)
oidc = (response['cluster']['identity']['oidc']['issuer'])
print('OIDC output recieved '+ oidc + ' for Cluster Name ' + cluster_name)
return oidc
except Exception as e:
print('Failed to fetch Cluster OIDC value for cluster name ' + cluster_name, e)
Handler: index.lambda_handler
MemorySize: 1024
Role: !GetAtt LambdaIAMRole.Arn
Runtime: python3.7
Timeout: 300
Outputs:
OIDC:
Description: EKS Cluster OIDC Value
Value:
Fn::GetAtt:
- ClusterName
- oidc
2. CustomLambdaEksOidc.template ファイルを使用して AWS CloudFormation スタックを起動するには、AWS CloudFormation コンソールまたは AWS コマンドラインインターフェイス (AWS CLI) を使用します。
AWS CLI を使用するには、次のコマンドを実行します。
aws cloudformation create-stack --stack-name lambda-eks-oidc --template-body file://CustomLambdaEksOidc.template --parameters ParameterKey=EKSClusterName,ParameterValue=demo-newsblog --capabilities CAPABILITY_NAMED_IAM --region us-east-1
注意: AWS CloudFormation スタックを起動するときは、demo-newsblog を Amazon EKS クラスター名に置き換えます。us-east-1 を AWS リージョンに置き換えます。