Skip to content

Commit

Permalink
feat: give cicd role permissions on eks cluster
Browse files Browse the repository at this point in the history
  • Loading branch information
blacha committed Nov 1, 2023
1 parent b94b816 commit f13e7b5
Show file tree
Hide file tree
Showing 5 changed files with 102 additions and 15 deletions.
25 changes: 12 additions & 13 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,26 +25,25 @@ jobs:
- name: format
run: npm run format -- --fix=false # ensure eslint is not configured to --fix


# - name: Setup kubectl
# uses: azure/setup-kubectl@v3
# with:
# version: 'latest'

# - name: AWS Configure
# uses: aws-actions/[email protected]
# with:
# aws-region: ap-southeast-2
# mask-aws-account-id: true
# role-to-assume: ${{ secrets.AWS_CI_ROLE }}
- name: AWS Configure
uses: aws-actions/[email protected]
with:
aws-region: ap-southeast-2
mask-aws-account-id: true
role-to-assume: ${{ secrets.AWS_CI_ROLE }}

# - name: Login to EKS
# run: |
# aws eks update-kubeconfig --name Workflow --region ap-southeast-2 --role-arn ${{ secrets.AWS_EKS_ROLE }}
- name: Login to EKS
run: |
aws eks update-kubeconfig --name Workflow --region ap-southeast-2
# - name: Check EKS connection
# run: |
# kubectl get nodes
- name: Check EKS connection
run: |
kubectl get nodes
# - name: Install Argo
# run: |
Expand Down
19 changes: 19 additions & 0 deletions infra/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,25 @@ Generally all Kubernetes resources are defined with cdk8s and anything that need

The EKS Cluster base configuration is defined in `./cdk.ts` using [`aws-cdk`](https://aws.amazon.com/cdk/).

### Deployment

To deploy with AWS CDK a few configuration variables need to be set

Due to VPC lookups a AWS account ID needs to be provided

This can be done with either a `export CDK_DEFAULT_ACCOUNT=1234567890` or passed in at run time with `-c aws-account-id=1234567890`

Then a deployment can be made with `cdk`

```
npx cdk diff -c aws-account-id=1234567890 -c ci-role-arn=arn::...
```

#### Context

- `aws-account-id`: Account ID to deploy into
- `ci-role-arn`: AWS Role ARN for the CI user

## Kubernetes resources / CDK8s

The additional components (or Kubernetes resources) running on the EKS cluster are defined in `./cdk8s` using [`cdk8s`](https://cdk8s.io/).
Expand Down
12 changes: 11 additions & 1 deletion infra/cdk.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,23 @@
import { App } from 'aws-cdk-lib';

import { ClusterName } from './constants.js';
import { tryGetContextArn } from './eks/arns.js';
import { LinzEksCluster } from './eks/cluster.js';

const app = new App();

async function main(): Promise<void> {
const accountId = app.node.tryGetContext('aws-account-id') ?? process.env['CDK_DEFAULT_ACCOUNT'];
const ciRoleArn = tryGetContextArn(app.node, 'ci-role-arn');

if (ciRoleArn == null) throw new Error('Missing context: ci-role-arn');
if (accountId == null) {
throw new Error("Missing AWS Account information, set with either '-c aws-account-id' or $CDK_DEFAULT_ACCOUNT");
}

new LinzEksCluster(app, ClusterName, {
env: { region: 'ap-southeast-2', account: process.env['CDK_DEFAULT_ACCOUNT'] },
env: { region: 'ap-southeast-2', account: accountId },
ciRoleArn,
});

app.synth();
Expand Down
50 changes: 50 additions & 0 deletions infra/eks/arns.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { Arn, ArnComponents, ArnFormat } from 'aws-cdk-lib';
import { Node } from 'constructs';

/**
* Validate that a object is a AWS IAM role arn
*
* @param arn arn to validate
* @returns ARN if valid
* @throws {Error} If ARN is not for a AWS IAM Role
*/
export function validateRoleArn(arn: unknown): ArnComponents {
if (typeof arn !== 'string') throw new Error('Failed to parse ARN, is not a string');
if (arn.includes('*')) throw new Error(`ARN cannot include "*" ${arn}`);
try {
const components = Arn.split(arn, ArnFormat.SLASH_RESOURCE_NAME);
if (components.service !== 'iam') throw new Error('ARN is not a iam service');
if (components.resource !== 'role') throw new Error('ARN is not a role');
return components;
} catch (e) {
throw new Error(`Failed to parse ARN: "${arn}"`, { cause: e });
}
}

/**
* Lookup a role ARN from context
*
* @returns arn if its valid, null otherwise
* @throws {Error} If arn is invalid
*/
export function tryGetContextArn(node: Node, context: string): string | null {
const ctx = node.tryGetContext(context);
if (ctx == null) return null;
validateRoleArn(ctx);
return ctx;
}

/**
*
* Lookup a list of role ARNs from context
*
* @throws {Error} If any arn is invalid
* @returns arns if they are valid, null otherwise
*/
export function tryGetContextArns(node: Node, context: string): string[] | null {
const ctx = node.tryGetContext(context);
if (ctx == null) return null;
if (!Array.isArray(ctx)) throw new Error('Failed to parse ARN, is not a string[]');
for (const arn of ctx) validateRoleArn(arn);
return ctx;
}
11 changes: 10 additions & 1 deletion infra/eks/cluster.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@ import { Construct } from 'constructs';

import { CfnOutputKeys } from '../constants.js';

interface EksClusterProps extends StackProps {}
interface EksClusterProps extends StackProps {
/** Optional CI User to grant access to the cluster */
ciRoleArn?: string;
}

export class LinzEksCluster extends Stack {
/* Cluster ID */
Expand Down Expand Up @@ -86,6 +89,12 @@ export class LinzEksCluster extends Stack {
const accountAdminRole = Role.fromRoleName(this, 'AccountAdminRole', 'AccountAdminRole');
this.cluster.awsAuth.addMastersRole(accountAdminRole);

// If defined allow the CI user access to the cluster
if (props.ciRoleArn) {
const ciRole = Role.fromRoleArn(this, 'CiRole', props.ciRoleArn);
this.cluster.awsAuth.addMastersRole(ciRole);
}

// This is the role that the new nodes will start as
this.nodeRole = new Role(this, 'NodeRole', {
assumedBy: new ServicePrincipal(`ec2.${Aws.URL_SUFFIX}`),
Expand Down

0 comments on commit f13e7b5

Please sign in to comment.