├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── Dockerfile ├── LICENSE ├── README.md ├── app ├── app.py └── templates │ └── aws-auth.yaml.jinja ├── events └── example-event.json └── iam ├── lambda-role-permission.json └── lambda-trust-policy.json /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | ## Code of Conduct 2 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 3 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 4 | opensource-codeofconduct@amazon.com with any additional questions or comments. 5 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing Guidelines 2 | 3 | Thank you for your interest in contributing to our project. Whether it's a bug report, new feature, correction, or additional 4 | documentation, we greatly value feedback and contributions from our community. 5 | 6 | Please read through this document before submitting any issues or pull requests to ensure we have all the necessary 7 | information to effectively respond to your bug report or contribution. 8 | 9 | 10 | ## Reporting Bugs/Feature Requests 11 | 12 | We welcome you to use the GitHub issue tracker to report bugs or suggest features. 13 | 14 | When filing an issue, please check existing open, or recently closed, issues to make sure somebody else hasn't already 15 | reported the issue. Please try to include as much information as you can. Details like these are incredibly useful: 16 | 17 | * A reproducible test case or series of steps 18 | * The version of our code being used 19 | * Any modifications you've made relevant to the bug 20 | * Anything unusual about your environment or deployment 21 | 22 | 23 | ## Contributing via Pull Requests 24 | Contributions via pull requests are much appreciated. Before sending us a pull request, please ensure that: 25 | 26 | 1. You are working against the latest source on the *main* branch. 27 | 2. You check existing open, and recently merged, pull requests to make sure someone else hasn't addressed the problem already. 28 | 3. You open an issue to discuss any significant work - we would hate for your time to be wasted. 29 | 30 | To send us a pull request, please: 31 | 32 | 1. Fork the repository. 33 | 2. Modify the source; please focus on the specific change you are contributing. If you also reformat all the code, it will be hard for us to focus on your change. 34 | 3. Ensure local tests pass. 35 | 4. Commit to your fork using clear commit messages. 36 | 5. Send us a pull request, answering any default questions in the pull request interface. 37 | 6. Pay attention to any automated CI failures reported in the pull request, and stay involved in the conversation. 38 | 39 | GitHub provides additional document on [forking a repository](https://help.github.com/articles/fork-a-repo/) and 40 | [creating a pull request](https://help.github.com/articles/creating-a-pull-request/). 41 | 42 | 43 | ## Finding contributions to work on 44 | Looking at the existing issues is a great way to find something to contribute on. As our projects, by default, use the default GitHub issue labels (enhancement/bug/duplicate/help wanted/invalid/question/wontfix), looking at any 'help wanted' issues is a great place to start. 45 | 46 | 47 | ## Code of Conduct 48 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 49 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 50 | opensource-codeofconduct@amazon.com with any additional questions or comments. 51 | 52 | 53 | ## Security issue notifications 54 | If you discover a potential security issue in this project we ask that you notify AWS/Amazon Security via our [vulnerability reporting page](http://aws.amazon.com/security/vulnerability-reporting/). Please do **not** create a public github issue. 55 | 56 | 57 | ## Licensing 58 | 59 | See the [LICENSE](LICENSE) file for our project's licensing. We will ask you to confirm the licensing of your contribution. 60 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # Permission is hereby granted, free of charge, to any person obtaining a copy of this 3 | # software and associated documentation files (the "Software"), to deal in the Software 4 | # without restriction, including without limitation the rights to use, copy, modify, 5 | # merge, publish, distribute, sublicense, and/or sell copies of the Software, and to 6 | # permit persons to whom the Software is furnished to do so. 7 | # 8 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 9 | # INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 10 | # PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 11 | # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 12 | # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 13 | # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 14 | 15 | ARG DIGEST="sha256:027ffb620da90fc79e1b62843b846400ac50b9bc8d87c53d7ba6d6b92b6f2b1d" 16 | ARG DISTRO_VERSION="3.13" 17 | ARG FUNCTION_DIR="/app" 18 | ARG GLIBC_VER="2.31-r0" 19 | ARG RUNTIME_VERSION="3.9.4" 20 | ARG USER="ekscontainer" 21 | 22 | FROM python:${RUNTIME_VERSION}-alpine${DISTRO_VERSION}@${DIGEST} AS compiler 23 | 24 | RUN apk update && \ 25 | apk upgrade && \ 26 | apk add --no-cache \ 27 | libstdc++ \ 28 | binutils \ 29 | curl 30 | 31 | FROM compiler AS builder 32 | ARG FUNCTION_DIR 33 | WORKDIR ${FUNCTION_DIR} 34 | 35 | RUN apk add --no-cache \ 36 | build-base \ 37 | libtool \ 38 | autoconf \ 39 | automake \ 40 | libexecinfo-dev \ 41 | make \ 42 | cmake \ 43 | libcurl 44 | 45 | RUN python3 -m pip install --target ${FUNCTION_DIR} \ 46 | awslambdaric \ 47 | boto3 \ 48 | jinja2 \ 49 | pylint 50 | 51 | COPY app/ ${FUNCTION_DIR} 52 | 53 | FROM compiler 54 | ARG FUNCTION_DIR 55 | ARG GLIBC_VER 56 | ARG USER 57 | WORKDIR $FUNCTION_DIR 58 | 59 | RUN curl -sL https://alpine-pkgs.sgerrand.com/sgerrand.rsa.pub -o /etc/apk/keys/sgerrand.rsa.pub && \ 60 | curl -sLO https://github.com/sgerrand/alpine-pkg-glibc/releases/download/${GLIBC_VER}/glibc-${GLIBC_VER}.apk && \ 61 | curl -sLO https://github.com/sgerrand/alpine-pkg-glibc/releases/download/${GLIBC_VER}/glibc-bin-${GLIBC_VER}.apk && \ 62 | curl -sLO https://github.com/sgerrand/alpine-pkg-glibc/releases/download/${GLIBC_VER}/glibc-i18n-${GLIBC_VER}.apk && \ 63 | apk add --no-cache \ 64 | glibc-${GLIBC_VER}.apk \ 65 | glibc-bin-${GLIBC_VER}.apk \ 66 | glibc-i18n-${GLIBC_VER}.apk && \ 67 | /usr/glibc-compat/bin/localedef -i en_US -f UTF-8 en_US.UTF-8 && \ 68 | curl -sL https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip -o awscliv2.zip && \ 69 | unzip awscliv2.zip && \ 70 | aws/install && \ 71 | curl -sL "https://github.com/weaveworks/eksctl/releases/latest/download/eksctl_$(uname -s)_amd64.tar.gz" | tar xz -C /tmp && \ 72 | mv /tmp/eksctl /usr/local/bin && \ 73 | curl -sLO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl && \ 74 | mv ./kubectl /usr/local/bin/kubectl && \ 75 | chmod a+x /usr/local/bin/kubectl && \ 76 | adduser -D ${USER} && \ 77 | rm -rf \ 78 | awscliv2.zip \ 79 | aws \ 80 | /usr/local/aws-cli/v2/*/dist/aws_completer \ 81 | /usr/local/aws-cli/v2/*/dist/awscli/data/ac.index \ 82 | /usr/local/aws-cli/v2/*/dist/awscli/examples \ 83 | glibc-*.apk && \ 84 | apk --no-cache del && \ 85 | rm -rf /var/cache/apk/* 86 | 87 | COPY --from=builder ${FUNCTION_DIR} ${FUNCTION_DIR} 88 | 89 | CMD [ "app.handler" ] 90 | ENTRYPOINT ["/usr/local/bin/python", "-m", "awslambdaric"] -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | this software and associated documentation files (the "Software"), to deal in 5 | the Software without restriction, including without limitation the rights to 6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 7 | the Software, and to permit persons to whom the Software is furnished to do so. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 10 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 11 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 12 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 13 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 14 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 15 | 16 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | *This sample, non-production-ready template describes managing EKS with Lambda functions. 2 | (c) 2021 Amazon Web Services, Inc. or its 3 | affiliates. All Rights Reserved. This AWS Content is provided subject to the 4 | terms of the AWS Customer Agreement available at 5 | http://aws.amazon.com/agreement or other written agreement between Customer 6 | and either Amazon Web Services, Inc. or Amazon Web Services 7 | EMEA SARL or both.* 8 | 9 | # Simplifying Kubernetes configurations using AWS Lambda 10 | 11 | Creating a serverless model for updating Elastic Kubernetes Clusters (EKS) 12 | 13 | This repository enables users to call Kubernetes APIs to create and manage resources through a unified control plane. Users will interact with Kubernetes API using Python and the the config map is created by Jinja2. This provides a solution that simplifies the user experience by enabling users to manage a Kubernetes cluster without installing multiple tools on their local developer machine. Additionally, this solution will remove the complexities of additional Domain-specific language knowledge and reduce the dependencies and packages installed on the user’s local machine. 14 | 15 | ## Repository Layout: 16 | 17 | ```bash 18 | . 19 | ├── Dockerfile 20 | ├── LICENSE 21 | ├── README.md 22 | ├── app 23 | │   ├── app.py 24 | │   └── templates 25 | │   └── aws-auth.yaml.jinja 26 | ├── events 27 | │   └── example-event.json 28 | └── iam 29 | ├── lambda-role-permission.json 30 | └── lambda-trust-policy.json 31 | 32 | 4 directories, 8 files 33 | 34 | ``` 35 | 36 | ## Requirements: 37 | 38 | * Permission to deploy a Docker image to AWS Elastic Container Repository (ECR) and trigger Lambda functions within a given AWS environment. See sample policy below: 39 | 40 | ```json 41 | { 42 | "Version": "2012-10-17", 43 | "Statement": [ 44 | { 45 | "Sid": "AccountPermissions", 46 | "Effect": "Allow", 47 | "Action": [ 48 | "ecr:GetAuthorizationToken", 49 | "ecr:PutRegistryPolicy", 50 | "ecr:PutReplicationConfiguration", 51 | "lambda:ListFunctions", 52 | "lambda:ListEventSourceMappings", 53 | "lambda:GetAccountSettings", 54 | "lambda:ListLayers", 55 | "lambda:ListLayerVersions", 56 | "lambda:ListCodeSigningConfigs" 57 | ], 58 | "Resource": "*" 59 | }, 60 | { 61 | "Sid": "ECRSpecific", 62 | "Effect": "Allow", 63 | "Action": [ 64 | "ecr:PutLifecyclePolicy", 65 | "ecr:PutImageTagMutability", 66 | "ecr:GetDownloadUrlForLayer", 67 | "ecr:ListTagsForResource", 68 | "ecr:UploadLayerPart", 69 | "ecr:BatchDeleteImage", 70 | "ecr:ListImages", 71 | "ecr:PutImage", 72 | "ecr:UntagResource", 73 | "ecr:BatchGetImage", 74 | "ecr:CompleteLayerUpload", 75 | "ecr:DescribeImages", 76 | "ecr:TagResource", 77 | "ecr:DescribeRepositories", 78 | "ecr:StartLifecyclePolicyPreview", 79 | "ecr:InitiateLayerUpload", 80 | "ecr:DeleteRepositoryPolicy", 81 | "ecr:BatchCheckLayerAvailability", 82 | "ecr:ReplicateImage", 83 | "ecr:GetRepositoryPolicy", 84 | "ecr:GetLifecyclePolicy" 85 | ], 86 | "Resource": "arn:aws:ecr:*::repository/*" 87 | }, 88 | { 89 | "Sid": "LambdaLayerSpecific", 90 | "Effect": "Allow", 91 | "Action": [ 92 | "lambda:GetLayerVersion", 93 | "lambda:GetLayerVersionPolicy", 94 | "lambda:GetProvisionedConcurrencyConfig", 95 | "lambda:DeleteLayerVersion", 96 | "lambda:GetEventSourceMapping", 97 | "lambda:ListFunctionsByCodeSigningConfig", 98 | "lambda:GetCodeSigningConfig" 99 | ], 100 | "Resource": [ 101 | "arn:aws:lambda:*::function:*:*", 102 | "arn:aws:lambda:*::event-source-mapping:*", 103 | "arn:aws:lambda:*::layer:*:*" 104 | ] 105 | }, 106 | { 107 | "Sid": "LambdaSpecific", 108 | "Effect": "Allow", 109 | "Action": [ 110 | "lambda:InvokeFunction", 111 | "lambda:ListVersionsByFunction", 112 | "lambda:GetFunction", 113 | "lambda:ListAliases", 114 | "lambda:PublishLayerVersion", 115 | "lambda:UpdateFunctionConfiguration", 116 | "lambda:GetFunctionConfiguration", 117 | "lambda:GetFunctionCodeSigningConfig", 118 | "lambda:UpdateFunctionCode", 119 | "lambda:ListFunctionEventInvokeConfigs", 120 | "lambda:ListProvisionedConcurrencyConfigs", 121 | "lambda:GetFunctionConcurrency", 122 | "lambda:ListTags", 123 | "lambda:GetFunctionEventInvokeConfig", 124 | "lambda:DeleteFunction", 125 | "lambda:PublishVersion", 126 | "lambda:GetAlias", 127 | "lambda:GetPolicy" 128 | ], 129 | "Resource": [ 130 | "arn:aws:lambda:*::layer:*", 131 | "arn:aws:lambda:*::function:*" 132 | ] 133 | } 134 | ] 135 | } 136 | ``` 137 | 138 | #### Additional Lambda Role Permissions 139 | The Lambda role needs the following permissions: 140 | 1. Create CloudWatch Logs 141 | 2. The following permissions below 142 | 143 | ```json 144 | { 145 | "Version": "2012-10-17", 146 | "Statement": [ 147 | { 148 | "Sid": "EKSSpecific", 149 | "Effect": "Allow", 150 | "Action": [ 151 | "eks:DisassociateIdentityProviderConfig", 152 | "eks:UpdateClusterConfig", 153 | "eks:AssociateIdentityProviderConfig" 154 | ], 155 | "Resource": [ 156 | "arn:aws:eks:*::identityproviderconfig/*/*/*/*", 157 | "arn:aws:eks:*::cluster/*" 158 | ] 159 | } 160 | ] 161 | } 162 | ``` 163 | 164 | ## Implementation Steps: 165 | 166 | 1a. Create Lambda role 167 | ```bash 168 | aws iam create-role \ 169 | --role-name \ 170 | --assume-role-policy-document file://iam/lambda-trust-policy.json 171 | ``` 172 | 1b. Create IAM policy 173 | ```bash 174 | aws iam create-policy \ 175 | --policy-name -policy \ 176 | --policy-document file://iam/lambda-role-permission.json 177 | ``` 178 | add basic lambda execution role: 179 | ```bash 180 | aws iam attach-role-policy \ 181 | --role-name \ 182 | --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole 183 | ``` 184 | 2. Create AWS ECR 185 | ```bash 186 | aws ecr create-repository \ 187 | --repository-name 188 | ``` 189 | and authorization to push Docker images to ECR: 190 | ```bash 191 | aws ecr get-login-password \ 192 | --region | docker login \ 193 | --username AWS \ 194 | --password-stdin .dkr.ecr..amazonaws.com 195 | ``` 196 | 3a. Create Elastic Kubernetes Cluster: 197 | ```bash 198 | eksctl create cluster \ 199 | --name demo-eks-cluster \ 200 | --version 1.20 \ 201 | --nodegroup-name demo-managed-node-group \ 202 | --node-type t3.medium \ 203 | --nodes 2 \ 204 | --region \ 205 | --enable-ssm 206 | ``` 207 | 3b. Add Lambda role to EKS configmap 208 | ```bash 209 | kubectl edit -n kube-system configmap/aws-auth 210 | ``` 211 | 3c. Add the following 212 | ```bash 213 | - userarn: 214 | username: admin 215 | groups: 216 | - system:masters 217 | ``` 218 | 219 | 4. Create and push Docker image to repository: 220 | 221 | ```bash 222 | docker build -t blog-example:1.0 .; 223 | docker tag blog-example:1.0 .dkr.ecr..amazonaws.com/:latest; 224 | docker push :latest 225 | ``` 226 | 227 | 5. Create Lambda container function: 228 | ```bash 229 | aws lambda create-function \ 230 | --function-name \ 231 | --package-type Image \ 232 | --code ImageUri=:latest \ 233 | --role 234 | ``` 235 | 236 | 6. Run API command via Lambda: 237 | 238 | ```bash 239 | aws lambda invoke \ 240 | --function-name \ 241 | --invocation-type Event \ 242 | --payload fileb://events/event.json \ 243 | response.json 244 | ``` 245 | 246 | API Layout is as such 247 | 248 | ```json 249 | { 250 | "RequestType" : "Create", 251 | "ResourceProperties" : { 252 | "ClusterName": "", 253 | "RoleMappings": [ 254 | { 255 | "arn": "", 256 | "username": "system:node:{{EC2PrivateDNSName}}", 257 | "groups": [ 258 | "system:bootstrappers", 259 | "system:nodes" 260 | ] 261 | } 262 | ... 263 | ] 264 | } 265 | } 266 | ``` 267 | 268 | # Additional Information 269 | 270 | 1. Allowed API "RequestTypes": Create, Update, Delete 271 | 2. To verify run the following command: `kubectl edit configmap -n kube-system aws-auth` 272 | 273 | ## Security: 274 | 275 | See [CONTRIBUTING](CONTRIBUTING.md#security-issue-notifications) for more information. 276 | 277 | ## License: 278 | 279 | This library is licensed under the MIT-0 License. See the LICENSE file. 280 | 281 | -------------------------------------------------------------------------------- /app/app.py: -------------------------------------------------------------------------------- 1 | """ 2 | Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this 4 | software and associated documentation files (the "Software"), to deal in the Software 5 | without restriction, including without limitation the rights to use, copy, modify, 6 | merge, publish, distribute, sublicense, and/or sell copies of the Software, and to 7 | permit persons to whom the Software is furnished to do so. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 10 | INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 11 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 12 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 13 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 14 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 15 | """ 16 | 17 | import json 18 | import logging 19 | import os 20 | import subprocess 21 | import jinja2 22 | from jinja2 import select_autoescape 23 | import sys 24 | 25 | 26 | # Logger 27 | logger = logging.getLogger() 28 | logger.setLevel(logging.INFO) 29 | 30 | # Jinja configs 31 | templateLoader = jinja2.FileSystemLoader(searchpath="./") 32 | templateEnv = jinja2.Environment(autoescape=select_autoescape(default_for_string=True, default=True), 33 | loader=templateLoader, 34 | trim_blocks=True) 35 | 36 | 37 | def get_stdout(output): 38 | """ 39 | Validates command output returncode and returns stdout 40 | :param output: the output of a subprocess 41 | :return the stdout of the subprocess output 42 | """ 43 | logger.info(output) 44 | if output.returncode == 0: 45 | command_output = output.stdout 46 | else: 47 | raise Exception(f'Command failed for - stderr: {output.stderr} - ' 48 | f'returncode: {output.returncode}') 49 | 50 | return command_output 51 | 52 | 53 | def create_kubeconfig(cluster_name): 54 | """ 55 | Updates the kubernetes context on the `kubeconfig` file. 56 | :param cluster_name: the name of the EKS cluster 57 | """ 58 | logger.info('Create kube config file.') 59 | configure_cli = f'aws eks update-kubeconfig --name {cluster_name}' 60 | output = subprocess.run( 61 | f'{configure_cli}', 62 | encoding='utf-8', 63 | capture_output=True, 64 | shell=True, 65 | check=False 66 | ) 67 | if output.returncode != 0: 68 | raise RuntimeError(f'Failed to create kube config file {output.stderr}.') 69 | 70 | logger.info('Successfully created kubeconfig file.') 71 | 72 | 73 | def update_identity_mappings(event, action): 74 | """ 75 | Uses the `action` parameter to run an `kubectl apply` or 76 | `kubectl delete` command. 77 | :param event: the CFN event 78 | :param action: `apply` to create/update the config map, or `delete` to delete it 79 | """ 80 | 81 | template_file = "templates/aws-auth.yaml.jinja" 82 | template = templateEnv.get_template(template_file) 83 | aws_auth = template.render(roleMappings=event["ResourceProperties"]["RoleMappings"]) 84 | command_base = 'cat <_aws-auth. 138 | :param event: the CFN event 139 | :return: the CFN resource id 140 | """ 141 | cluster_name = event["ResourceProperties"]['ClusterName'] 142 | resource_id = cluster_name + "_aws-auth" 143 | 144 | return resource_id 145 | 146 | 147 | def handler(event, _): 148 | """ 149 | Entry point for the lambda. 150 | :param event: the CFN event 151 | :param context: the lambda context 152 | """ 153 | 154 | kube_config_path = '/tmp/kubeconfig' 155 | os.environ['KUBECONFIG'] = kube_config_path 156 | 157 | cluster_name = event["ResourceProperties"]['ClusterName'] 158 | 159 | try: 160 | create_kubeconfig(cluster_name) 161 | if event['RequestType'] == 'Create' or event['RequestType'] == 'Update': 162 | create(event) 163 | elif event['RequestType'] == 'Delete': 164 | delete(event) 165 | except Exception: 166 | logger.error('Signaling failure') 167 | sys.exit(1) 168 | else: 169 | sys.exit(0) 170 | 171 | 172 | def create(event): 173 | """ 174 | Handles the `create` event. 175 | :param event: the CFN event 176 | :param context: the lambda context 177 | """ 178 | logger.info(f"Creating identity mapping... event: {event}") 179 | update_identity_mappings(event=event, action="apply") 180 | 181 | def delete(event): 182 | """ 183 | Handles the `delete` event. 184 | :param event: the CFN event 185 | :param context: the lambda context 186 | """ 187 | logger.info(f"Deleting identity mapping... event: {event}") 188 | update_identity_mappings(event=event, action="delete") 189 | -------------------------------------------------------------------------------- /app/templates/aws-auth.yaml.jinja: -------------------------------------------------------------------------------- 1 | kind: ConfigMap 2 | apiVersion: v1 3 | metadata: 4 | name: aws-auth 5 | data: 6 | mapRoles: | 7 | {% for role in roleMappings %} 8 | - rolearn: {{ role.arn }} 9 | username: {{ role.username }} 10 | groups: 11 | {% for group in role.groups %} 12 | - {{ group }} 13 | {% endfor %} 14 | 15 | {% endfor %} 16 | 17 | -------------------------------------------------------------------------------- /events/example-event.json: -------------------------------------------------------------------------------- 1 | { 2 | "RequestType" : "Create", 3 | "LogicalResourceId" : "EKSIdentityMapping", 4 | "ResourceProperties" : { 5 | "ClusterName": "", 6 | "RoleMappings": [ 7 | { 8 | "arn": "", 9 | "username": "system:node:{{EC2PrivateDNSName}}", 10 | "groups": [ 11 | "system:bootstrappers", 12 | "system:nodes" 13 | ] 14 | } 15 | ] 16 | } 17 | } -------------------------------------------------------------------------------- /iam/lambda-role-permission.json: -------------------------------------------------------------------------------- 1 | { 2 | "Version": "2012-10-17", 3 | "Statement": [ 4 | { 5 | "Sid": "AccountPermissions", 6 | "Effect": "Allow", 7 | "Action": [ 8 | "ecr:GetAuthorizationToken", 9 | "ecr:PutRegistryPolicy", 10 | "ecr:PutReplicationConfiguration", 11 | "lambda:ListFunctions", 12 | "lambda:ListEventSourceMappings", 13 | "lambda:GetAccountSettings", 14 | "lambda:ListLayers", 15 | "lambda:ListLayerVersions", 16 | "lambda:ListCodeSigningConfigs" 17 | ], 18 | "Resource": "*" 19 | }, 20 | { 21 | "Sid": "ECRSpecific", 22 | "Effect": "Allow", 23 | "Action": [ 24 | "ecr:PutLifecyclePolicy", 25 | "ecr:PutImageTagMutability", 26 | "ecr:GetDownloadUrlForLayer", 27 | "ecr:ListTagsForResource", 28 | "ecr:UploadLayerPart", 29 | "ecr:BatchDeleteImage", 30 | "ecr:ListImages", 31 | "ecr:PutImage", 32 | "ecr:UntagResource", 33 | "ecr:BatchGetImage", 34 | "ecr:CompleteLayerUpload", 35 | "ecr:DescribeImages", 36 | "ecr:TagResource", 37 | "ecr:DescribeRepositories", 38 | "ecr:StartLifecyclePolicyPreview", 39 | "ecr:InitiateLayerUpload", 40 | "ecr:DeleteRepositoryPolicy", 41 | "ecr:BatchCheckLayerAvailability", 42 | "ecr:ReplicateImage", 43 | "ecr:GetRepositoryPolicy", 44 | "ecr:GetLifecyclePolicy" 45 | ], 46 | "Resource": "arn:aws:ecr:*::repository/*" 47 | }, 48 | { 49 | "Sid": "LambdaLayerSpecific", 50 | "Effect": "Allow", 51 | "Action": [ 52 | "lambda:GetLayerVersion", 53 | "lambda:GetLayerVersionPolicy", 54 | "lambda:GetProvisionedConcurrencyConfig", 55 | "lambda:DeleteLayerVersion", 56 | "lambda:GetEventSourceMapping", 57 | "lambda:ListFunctionsByCodeSigningConfig", 58 | "lambda:GetCodeSigningConfig" 59 | ], 60 | "Resource": [ 61 | "arn:aws:lambda:*::function:*:*", 62 | "arn:aws:lambda:*::event-source-mapping:*", 63 | "arn:aws:lambda:*::layer:*:*" 64 | ] 65 | }, 66 | { 67 | "Sid": "LambdaSpecific", 68 | "Effect": "Allow", 69 | "Action": [ 70 | "lambda:InvokeFunction", 71 | "lambda:ListVersionsByFunction", 72 | "lambda:GetFunction", 73 | "lambda:ListAliases", 74 | "lambda:PublishLayerVersion", 75 | "lambda:UpdateFunctionConfiguration", 76 | "lambda:GetFunctionConfiguration", 77 | "lambda:GetFunctionCodeSigningConfig", 78 | "lambda:UpdateFunctionCode", 79 | "lambda:ListFunctionEventInvokeConfigs", 80 | "lambda:ListProvisionedConcurrencyConfigs", 81 | "lambda:GetFunctionConcurrency", 82 | "lambda:ListTags", 83 | "lambda:GetFunctionEventInvokeConfig", 84 | "lambda:DeleteFunction", 85 | "lambda:PublishVersion", 86 | "lambda:GetAlias", 87 | "lambda:GetPolicy" 88 | ], 89 | "Resource": [ 90 | "arn:aws:lambda:*::layer:*", 91 | "arn:aws:lambda:*::function:*" 92 | ] 93 | } 94 | ] 95 | } -------------------------------------------------------------------------------- /iam/lambda-trust-policy.json: -------------------------------------------------------------------------------- 1 | { 2 | "Version": "2012-10-17", 3 | "Statement": [ 4 | { 5 | "Effect": "Allow", 6 | "Principal": { 7 | "Service": "lambda.amazonaws.com" 8 | }, 9 | "Action": "sts:AssumeRole" 10 | } 11 | ] 12 | } --------------------------------------------------------------------------------