-
-
Notifications
You must be signed in to change notification settings - Fork 7
/
app-stack.ts
80 lines (67 loc) · 3.66 KB
/
app-stack.ts
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
import * as iam from 'aws-cdk-lib/aws-iam'
import {OpenIdConnectProvider, Policy, PolicyStatement} from 'aws-cdk-lib/aws-iam'
import {CfnOutput, Duration, SecretValue, Stack, StackProps} from 'aws-cdk-lib'
import {Construct} from 'constructs'
import * as lambda from 'aws-cdk-lib/aws-lambda'
import {FunctionUrlAuthType} from 'aws-cdk-lib/aws-lambda'
import * as path from 'path'
import * as secretManager from 'aws-cdk-lib/aws-secretsmanager'
// https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect#example-subject-claims
const GITHUB_ACTIONS_TOKEN_ALLOWED_SUBJECTS: string[] = []
export class AppStack extends Stack {
constructor(scope: Construct, id: string, props?: StackProps) {
super(scope, id, props)
// --- GitHub App Secrets---------------------------------------------------------------------------------------
const githubAppSecret = new secretManager.Secret(this, 'GitHubAppSecret', {
secretName: `${this.stackName}/GitHubApp`, secretObjectValue: {
appId: SecretValue.unsafePlainText('change-me'),
privateKey: SecretValue.unsafePlainText('change-me'),
},
})
// --- API Access Token Function--------------------------------------------------------------------------------
const httpApiAccessTokenFunction = new lambda.Function(this, 'HttpApiFunction', {
runtime: lambda.Runtime.NODEJS_20_X,
handler: 'index.handler',
memorySize: 128,
timeout: Duration.seconds(30),
code: lambda.Code.fromAsset(path.join(__dirname, '../../../../dist')),
environment: {
LOG_LEVEL: 'info',
GITHUB_APP_SECRETS_NAME: githubAppSecret.secretName,
GITHUB_ACTIONS_TOKEN_ALLOWED_SUBJECTS: GITHUB_ACTIONS_TOKEN_ALLOWED_SUBJECTS.join(','),
},
})
githubAppSecret.grantRead(httpApiAccessTokenFunction.role!)
new Policy(this, `${httpApiAccessTokenFunction.node.id}-RolePolicy`, {
statements: [
new PolicyStatement({
actions: ['lambda:GetFunctionUrlConfig'],
resources: [httpApiAccessTokenFunction.functionArn],
})
]
}).attachToRole(httpApiAccessTokenFunction.role!)
// --- add function url
const httpApiFunctionUrl = httpApiAccessTokenFunction.addFunctionUrl({
authType: FunctionUrlAuthType.AWS_IAM,
})
// --- API Access Role------------------------------------------------------------------------------------------
const githubOidcProvider = OpenIdConnectProvider.fromOpenIdConnectProviderArn(
this, 'HttpApiAuthOidcProvider',
`arn:aws:iam::${this.account}:oidc-provider/token.actions.githubusercontent.com`,
)
const httpApiAccessRole = new iam.Role(this, 'HttpApiAccessRole', {
roleName: `${this.stackName}-HttpApiAccess`,
maxSessionDuration: Duration.hours(1), // should set to minimum value for security reasons
assumedBy: new iam.OpenIdConnectPrincipal(githubOidcProvider, {
'StringEquals': {[`${githubOidcProvider.openIdConnectProviderIssuer}:aud`]: 'sts.amazonaws.com'},
'ForAnyValue:StringLike': {[`${githubOidcProvider.openIdConnectProviderIssuer}:sub`]: GITHUB_ACTIONS_TOKEN_ALLOWED_SUBJECTS},
}),
})
httpApiFunctionUrl.grantInvokeUrl(httpApiAccessRole)
// --- Outputs -------------------------------------------------------------------------------------------------
new CfnOutput(this, 'GitHubAppSecretName', {value: githubAppSecret.secretName})
new CfnOutput(this, 'ApiRegion', {value: httpApiFunctionUrl.stack.region})
new CfnOutput(this, 'ApiAccessRoleArn', {value: httpApiAccessRole.roleArn})
new CfnOutput(this, 'ApiUrl', {value: httpApiFunctionUrl.url})
}
}