-
Notifications
You must be signed in to change notification settings - Fork 7
/
oidc-provider.yaml
147 lines (140 loc) · 5.91 KB
/
oidc-provider.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
---
# SPDX-FileCopyrightText: 2020 Bamboo Loans
# SPDX-License-Identifier: MIT
AWSTemplateFormatVersion: '2010-09-09'
Description: 'An example CloudFormation template to configure an EKS cluster with an OpenID Connect provider to use IAM backed service accounts'
Metadata:
Source: https://github.com/bambooengineering/example-eks-oidc-iam-cloudformation
Parameters:
EKSClusterName:
Type: String
Description: Name for EKS Cluster
Resources:
ClusterOIDCURL:
Type: Custom::ClusterOIDCURL
Properties:
ServiceToken: !GetAtt ClusterOIDCURLFunction.Arn
ClusterName: !Ref EKSClusterName
# We need to use the API to get the OpenID Connect URL from the cluster, so a Lambda does that for us here
ClusterOIDCURLFunction:
Type: AWS::Lambda::Function
Properties:
Runtime: python3.7
Handler: index.lambda_handler
MemorySize: 128
Role: !GetAtt ClusterOIDCLambdaExecutionRole.Arn
Timeout: 30
Code:
ZipFile: |
import boto3
import json
import cfnresponse
eks = boto3.client("eks")
def lambda_handler(event, context):
responseData = {}
if event['RequestType'] == 'Delete':
responseData['Reason'] = "Success"
cfnresponse.send(event, context, cfnresponse.SUCCESS, responseData, "")
else:
try:
cluster_name = event['ResourceProperties']['ClusterName']
response = eks.describe_cluster(name=cluster_name)
cluster_oidc_url = response['cluster']['identity']['oidc']['issuer']
# We need the url for the roles without the protocol when creating roles, so remove
# it here to make this easier to use in CF templates.
without_protocol = cluster_oidc_url.replace('https://', '')
responseData['Reason'] = "Success"
responseData['Url'] = without_protocol
cfnresponse.send(event, context, cfnresponse.SUCCESS, responseData, without_protocol)
except Exception as e:
responseData['Reason'] = str(e)
cfnresponse.send(event, context, cfnresponse.FAILED, responseData, "")
ClusterOIDCProvider:
Type: Custom::ClusterOIDCProvider
Properties:
ServiceToken: !GetAtt ClusterOIDCProviderFunction.Arn
ClusterOIDCURL: !Ref ClusterOIDCURL
# This defines the lambda that will run the setup (and teardown) code for the OIDC provider
ClusterOIDCProviderFunction:
Type: AWS::Lambda::Function
Properties:
Runtime: python3.7
Handler: index.lambda_handler
MemorySize: 128
Role: !GetAtt ClusterOIDCLambdaExecutionRole.Arn
Timeout: 30
Code:
ZipFile: |
import boto3
from botocore.exceptions import ClientError
import json
import cfnresponse
iam = boto3.client("iam")
def lambda_handler(event, context):
data = {}
try:
cluster_oidc_url = event['ResourceProperties']['ClusterOIDCURL']
if event['RequestType'] == 'Create':
with_protocol = "https://" + cluster_oidc_url
# This is the ca thumbprint of AWS's issuer
issuer_thumbprint = '9e99a48a9960b14926bb7f3b02e22da2b0ab7280'
resp = iam.create_open_id_connect_provider(Url=with_protocol,ClientIDList=['sts.amazonaws.com'],ThumbprintList=[issuer_thumbprint])
provider_arn = resp['OpenIDConnectProviderArn']
data["Reason"] = "Provider with ARN " + provider_arn + " created"
cfnresponse.send(event, context, cfnresponse.SUCCESS, data, provider_arn)
elif event['RequestType'] == 'Delete':
provider_arn = event["PhysicalResourceId"]
if provider_arn is None:
data["Reason"] = "Provider not present"
cfnresponse.send(event, context, cfnresponse.SUCCESS, data, provider_arn)
else:
resp = iam.delete_open_id_connect_provider(OpenIDConnectProviderArn=provider_arn)
data["Reason"] = "Provider with ARN " + provider_arn + " deleted"
cfnresponse.send(event, context, cfnresponse.SUCCESS, data, provider_arn)
else:
data["Reason"] = "Unknown operation: " + event['RequestType']
cfnresponse.send(event, context, cfnresponse.FAILED, data, "")
except Exception as e:
data["Reason"] = "Cannot " + event['RequestType'] + " Provider" + str(e)
cfnresponse.send(event, context, cfnresponse.FAILED, data, "")
# This the role that gives the stack sufficient permissions to create the OIDC provider. It is only
# used during lifecycle operations of this stack
ClusterOIDCLambdaExecutionRole:
Type: AWS::IAM::Role
Properties:
Path: /
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
Action:
- sts:AssumeRole
Policies:
- PolicyName: root
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- eks:DescribeCluster
Resource: !Sub "arn:aws:eks:${AWS::Region}:${AWS::AccountId}:cluster/${EKSClusterName}"
- Effect: Allow
Action:
- iam:*OpenIDConnectProvider*
Resource: "*"
- Effect: Allow
Action:
- logs:CreateLogGroup
- logs:CreateLogStream
- logs:PutLogEvents
Resource: "*"
Outputs:
ClusterOIDCURL:
Description: The OpenID Connect URL (without protocol)
Value: !Ref ClusterOIDCURL
ClusterOIDCProvider:
Description: The ARN of the OIDCProvider
Value: !Ref ClusterOIDCProvider