Skip to content

Commit

Permalink
feat: add stack oidc github (#2)
Browse files Browse the repository at this point in the history
  • Loading branch information
FabrizioCafolla authored Jan 20, 2023
1 parent 6569479 commit 16a313a
Show file tree
Hide file tree
Showing 3 changed files with 307 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/stacks/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * from './base';
export * as newrelic from './newrelic';
export * as oidc from './oidc';
39 changes: 39 additions & 0 deletions src/stacks/newrelic/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Duration, SecretValue, RemovalPolicy, CfnOutput } from 'aws-cdk-lib';
import * as cloudwatch from 'aws-cdk-lib/aws-cloudwatch';
import * as iam from 'aws-cdk-lib/aws-iam';
import * as firehose from 'aws-cdk-lib/aws-kinesisfirehose';
import * as s3 from 'aws-cdk-lib/aws-s3';
Expand All @@ -7,6 +8,7 @@ import { Construct } from 'constructs';
import { addBaseTags } from '../../common/utils';
import { BaseStack, BaseStackProps } from '../base';


export const NEW_RELIC_AWS_ACCOUNT_ID = '754728514883';

export enum EndpointType {
Expand Down Expand Up @@ -39,6 +41,7 @@ export class NewRelicStack extends BaseStack {
newRelicFirehoseRole: iam.IRole;
newRelicFirehoseMetrics?: firehose.CfnDeliveryStream;
newRelicFirehoseLogs?: firehose.CfnDeliveryStream;
newRelicCloudwatchLogsStreamRole?: iam.IRole;

constructor(scope: Construct, id: string, props: NewRelicStackProps) {
super(scope, id, props);
Expand All @@ -57,6 +60,7 @@ export class NewRelicStack extends BaseStack {
props.newRelicApiUrlLogs,
props.newRelicLicenseKey,
);
this.newRelicCloudwatchLogsStreamRole = this.createCloudwatchLogsStreamRole();
}

if (props.newRelicApiUrlMetrics) {
Expand All @@ -70,6 +74,41 @@ export class NewRelicStack extends BaseStack {
}
}

createCloudwatchMetricStream(roleArn:string, firehoseArn: string) {
return new cloudwatch.CfnMetricStream(this, 'newrelic-cloudwatch-stream-metrics', {
firehoseArn: firehoseArn,
outputFormat: 'opentelemetry0.7',
roleArn: roleArn,
name: 'newelic-stream-metrics',
});
}

createCloudwatchLogsStreamRole(): iam.IRole {
let role = new iam.Role(
this,
'newrelic-logstream-role', {
roleName: 'NewRelicInfrastructure-CloudwatchStream',
assumedBy: new iam.ServicePrincipal('logs.amazonaws.com'),
},
);

role.addToPolicy(
new iam.PolicyStatement({
actions: [
'firehose:PutRecord',
'firehose:PutRecordBatch',
'kinesis:PutRecords',
'kinesis:PutRecord',
],
resources: ['*'],
}),
);

addBaseTags(role);

return role;
}

createNewRelicRole(newRelicAccountId: string): iam.IRole {
let role = new iam.Role(
this,
Expand Down
267 changes: 267 additions & 0 deletions src/stacks/oidc/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,267 @@
import { CfnOutput } from 'aws-cdk-lib';
import * as iam from 'aws-cdk-lib/aws-iam';
import { Construct } from 'constructs';
import { addBaseTags } from '../../common/utils';
import { BaseStack, BaseStackProps } from '../base';

export enum ProviderUrl {
GITHUB = 'https://token.actions.githubusercontent.com'
}

export enum TokenActions {
ALL,
ALL_BRANCH,
ALL_TAGS,
CUSTOM,
}

export interface GithubOIDCStackStackProps extends BaseStackProps {
readonly githubUser: string;
readonly githubRepository: string;
readonly tokenAction: TokenActions;
readonly cdkDeployRoleManagedPolicies?: iam.ManagedPolicy[];
readonly cdkDeployRolePolicyStatements?: iam.PolicyStatement[];
readonly tokenActionCustom?: string;
}

export class GithubOIDCStack extends BaseStack {
githubUser: string;
githubRepository: string;
tokenAction: TokenActions;
oidcRole: iam.IRole;
cdkBootstrapRole: iam.IRole;
cdkDeployRole: iam.IRole;
cdkDeployRoleManagedPolicies?: iam.ManagedPolicy[];
cdkDeployRolePolicyStatements?: iam.PolicyStatement[];

constructor(scope: Construct, id: string, props: GithubOIDCStackStackProps) {
super(scope, id, props);

this.githubUser = props.githubUser;
this.githubRepository = props.githubRepository;
this.tokenAction = props.tokenAction;

let token = this.createTokenAction(props.tokenAction, props.githubUser, props.githubRepository, props.tokenActionCustom);

this.oidcRole = this.createOidcRole(ProviderUrl.GITHUB, token);
this.cdkBootstrapRole = this.createCdkBootstrapRole();

this.cdkDeployRoleManagedPolicies = props.cdkDeployRoleManagedPolicies;
this.cdkDeployRolePolicyStatements = props.cdkDeployRolePolicyStatements;
this.cdkDeployRole = this.createCdkDeployRole(this.cdkDeployRoleManagedPolicies, this.cdkDeployRolePolicyStatements);
}

createTokenAction(tokenAction: TokenActions, githubUser: string, githubRepository: string, tokenActionCustom?: string): string {
if (tokenAction === TokenActions.ALL) {
return `repo:${githubUser}/*`;
}

if (tokenAction === TokenActions.ALL_BRANCH) {
return `repo:${githubUser}/${githubRepository}:ref:refs/heads/*`;
}

if (tokenAction === TokenActions.ALL_TAGS) {
return `repo:${githubUser}/${githubRepository}:ref:refs/tags/*`;
}

if (tokenAction === TokenActions.CUSTOM) {
return `repo:${githubUser}/${githubRepository}:ref:refs/${tokenActionCustom}`;
}

throw new Error('tokenAction not found');
}


createCdkDeployRole(managed_policies?: iam.IManagedPolicy[], policy_statements?: iam.PolicyStatement[]): iam.IRole {
let basePolicy = new iam.PolicyDocument(
{
statements: [
new iam.PolicyStatement({
resources: [`arn:aws:iam::${this.account}:role/cdk-*`],
actions: [
'sts:AssumeRole',
],
effect: iam.Effect.ALLOW,
}),
new iam.PolicyStatement({
resources: [`arn:aws:iam::${this.account}:role/cdk-*`],
actions: [
'iam:PassRole',
'iam:CreateRole',
'iam:DeleteRole',
'iam:UpdateRole',
'iam:DetachRolePolicy',
'iam:AttachRolePolicy',
'iam:DeleteRolePolicy',
'iam:PutRolePolicy',
'ssm:GetParameters',
],
effect: iam.Effect.ALLOW,
}),
],
},
);
let role = new iam.Role(
this,
'cdk-oidc-deploy-role', {
roleName: 'cdk-oidc-deploy-role',
assumedBy: new iam.ServicePrincipal('cloudformation.amazonaws.com'),
inlinePolicies: {
CDKDeployBasePolicy: basePolicy,
},
},
);

if (policy_statements) {
for (let index = 0; index < policy_statements.length; index++) {
role.addToPolicy(policy_statements[index]);
}
}

if (managed_policies) {
for (let index = 0; index < managed_policies.length; index++) {
role.addManagedPolicy(managed_policies[index]);
}
}


new CfnOutput(this, 'cdk-oidc-deploy-role-output', {
value: role.roleArn,
description: 'Role for cdk deploy role arn',
exportName: 'cdk-oidc-deploy-role',
});

addBaseTags(role);

return role;
}

createCdkBootstrapRole(): iam.IRole {
let policy = new iam.PolicyDocument(
{
statements: [
new iam.PolicyStatement({
resources: [`arn:aws:iam::${this.account}:role/cdk-*`],
actions: [
'sts:AssumeRole',
'iam:*Role*',
],
effect: iam.Effect.ALLOW,
}),
new iam.PolicyStatement({
resources: [`arn:aws:cloudformation:${this.region}:${this.account}:stack/CDKToolkit/*`],
actions: [
'cloudformation:*',
],
effect: iam.Effect.ALLOW,
}),
new iam.PolicyStatement({
resources: ['*'],
actions: [
's3:*',
],
effect: iam.Effect.ALLOW,
}),
new iam.PolicyStatement({
resources: [`arn:aws:ecr:${this.region}:${this.account}:repository/cdk-*`],
actions: [
'ecr:SetRepositoryPolicy',
'ecr:GetLifecyclePolicy',
'ecr:PutImageScanningConfiguration',
'ecr:DescribeRepositories',
'ecr:CreateRepository',
'ecr:DeleteRepository',
],
effect: iam.Effect.ALLOW,
}),
new iam.PolicyStatement({
resources: [`arn:aws:ssm:${this.region}:${this.account}:parameter/cdk-bootstrap/*`],
actions: [
'ssm:GetParameter*',
'ssm:PutParameter*',
'ssm:DeleteParameter*',
],
effect: iam.Effect.ALLOW,
}),
],
},
);

let role = new iam.Role(
this,
'cdk-oidc-bootstrap-role', {
roleName: 'cdk-oidc-bootstrap-role',
assumedBy: new iam.ServicePrincipal('cloudformation.amazonaws.com'),
inlinePolicies: {
CDKBootstrapPolicy: policy,
},
},
);

new CfnOutput(this, 'cdk-oidc-bootstrap-role-output', {
value: role.roleArn,
description: 'Role for cdk bootstrap role arn',
exportName: 'cdk-oidc-bootstrap-role',
});

addBaseTags(role);

return role;
}

createOidcRole(providerUrl: string, token: string): iam.IRole {
let oidcProvider = new iam.OpenIdConnectProvider(
this,
'oidc-provider',
{
url: providerUrl,
clientIds: ['sts.amazonaws.com'],
},
);

let role = new iam.Role(
this,
'oidc-role', {
roleName: 'github-oidc-workflow-role',
assumedBy: new iam.WebIdentityPrincipal(oidcProvider.openIdConnectProviderArn, {
StringLike: {
'token.actions.githubusercontent.com:sub': token,
},
}),
},
);

role.addToPolicy(
new iam.PolicyStatement({
resources: ['*'],
actions: [
'iam:PassRole',
'ssm:GetParameter*',
'cloudformation:*',
's3:*',
'ecr:*',
],
effect: iam.Effect.ALLOW,
}),
);

role.addToPolicy(
new iam.PolicyStatement({
resources: [`arn:aws:iam::${this.account}:role/cdk-*`],
actions: ['sts:AssumeRole'],
effect: iam.Effect.ALLOW,
}),
);

new CfnOutput(this, 'github-oidc-workflow-role-output', {
value: role.roleArn,
description: 'Role for OIDC Github Workflow role arn',
exportName: 'github-oidc-workflow-role',
});

addBaseTags(role);

return role;
}

}

0 comments on commit 16a313a

Please sign in to comment.