@deployfoundation/foundation-deploy 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/README.md +174 -0
  2. package/agent-image/Dockerfile +254 -0
  3. package/agent-image/bin/aws +36 -0
  4. package/agent-image/bin/gh +193 -0
  5. package/agent-image/bin/git-credential-sky +89 -0
  6. package/agent-image/security-overlay.yml +176 -0
  7. package/cdk.json +6 -0
  8. package/dist/bin/app.js +112 -0
  9. package/dist/bin/foundation-deploy.js +1906 -0
  10. package/dist/bin/release-account.js +154 -0
  11. package/dist/chunk-4aye5cee.js +2416 -0
  12. package/dist/chunk-9ddxyvq2.js +1455 -0
  13. package/dist/chunk-v7tz8g50.js +428 -0
  14. package/dist/src/index.js +88 -0
  15. package/package.json +38 -0
  16. package/pipeline/buildspec.yml +34 -0
  17. package/src/artifacts.ts +318 -0
  18. package/src/deploy/assets/github-app-manifest.yml +29 -0
  19. package/src/deploy/assets/slack-app-manifest.yml +95 -0
  20. package/src/deploy/aws.ts +265 -0
  21. package/src/deploy/cli.ts +212 -0
  22. package/src/deploy/config-sync.ts +93 -0
  23. package/src/deploy/config.ts +29 -0
  24. package/src/deploy/deploy.ts +566 -0
  25. package/src/deploy/endpoint.ts +242 -0
  26. package/src/deploy/github-app-create.ts +154 -0
  27. package/src/deploy/github-app-manifest.ts +53 -0
  28. package/src/deploy/image.ts +80 -0
  29. package/src/deploy/instance.ts +87 -0
  30. package/src/deploy/license-cache.ts +47 -0
  31. package/src/deploy/license.ts +272 -0
  32. package/src/deploy/paths.ts +65 -0
  33. package/src/deploy/post-deploy.ts +97 -0
  34. package/src/deploy/release.ts +282 -0
  35. package/src/deploy/runtime-secret.ts +241 -0
  36. package/src/deploy/setup.ts +393 -0
  37. package/src/deploy/sh.ts +74 -0
  38. package/src/deploy/slack-manifest.ts +112 -0
  39. package/src/deploy/stage-customization.ts +224 -0
  40. package/src/deploy/tracing.ts +243 -0
  41. package/src/deploy-permissions.ts +165 -0
  42. package/src/index.ts +60 -0
  43. package/src/lambda-bundle-context.ts +64 -0
  44. package/src/names.ts +170 -0
  45. package/src/release/kms.ts +86 -0
  46. package/src/release/manifest.ts +265 -0
  47. package/src/stacks/agent-stack.ts +938 -0
  48. package/src/stacks/api-stack.ts +1005 -0
  49. package/src/stacks/ci-stack.ts +96 -0
  50. package/src/stacks/data-stack.ts +446 -0
  51. package/src/stacks/network-stack.ts +282 -0
  52. package/src/stacks/newsletter-stack.ts +572 -0
  53. package/src/stacks/pipeline-stack.ts +242 -0
  54. package/src/stacks/release-account-stack.ts +229 -0
@@ -0,0 +1,154 @@
1
+ #!/usr/bin/env bun
2
+ import {
3
+ DEFAULT_RELEASE_BUCKET
4
+ } from "../chunk-v7tz8g50.js";
5
+ import"../chunk-9ddxyvq2.js";
6
+
7
+ // bin/release-account.ts
8
+ import * as cdk2 from "aws-cdk-lib";
9
+
10
+ // src/stacks/release-account-stack.ts
11
+ import * as cdk from "aws-cdk-lib";
12
+ import * as ecr from "aws-cdk-lib/aws-ecr";
13
+ import * as iam from "aws-cdk-lib/aws-iam";
14
+ import * as kms from "aws-cdk-lib/aws-kms";
15
+ import * as s3 from "aws-cdk-lib/aws-s3";
16
+
17
+ class ReleaseAccountStack extends cdk.Stack {
18
+ bucket;
19
+ repository;
20
+ signingKey;
21
+ releaseRole;
22
+ constructor(scope, id, props) {
23
+ super(scope, id, props);
24
+ const repositoryName = props.repositoryName ?? "foundation/agent";
25
+ const customers = [...props.customerAccountIds];
26
+ const customerPrincipals = customers.map((account) => new iam.AccountPrincipal(account));
27
+ this.bucket = new s3.Bucket(this, "ReleaseBucket", {
28
+ bucketName: props.bucketName,
29
+ versioned: true,
30
+ encryption: s3.BucketEncryption.S3_MANAGED,
31
+ blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,
32
+ enforceSSL: true,
33
+ removalPolicy: cdk.RemovalPolicy.RETAIN
34
+ });
35
+ if (customerPrincipals.length > 0)
36
+ this.bucket.addToResourcePolicy(new iam.PolicyStatement({
37
+ sid: "CustomersReadReleases",
38
+ principals: customerPrincipals,
39
+ actions: ["s3:GetObject", "s3:GetObjectVersion"],
40
+ resources: [this.bucket.arnForObjects("releases/*")]
41
+ }));
42
+ this.repository = new ecr.Repository(this, "AgentRepository", {
43
+ repositoryName,
44
+ imageScanOnPush: true,
45
+ imageTagMutability: ecr.TagMutability.IMMUTABLE,
46
+ encryption: ecr.RepositoryEncryption.AES_256,
47
+ removalPolicy: cdk.RemovalPolicy.RETAIN
48
+ });
49
+ if (customerPrincipals.length > 0)
50
+ this.repository.addToResourcePolicy(new iam.PolicyStatement({
51
+ sid: "CustomersPullAgentImage",
52
+ principals: customerPrincipals,
53
+ actions: [
54
+ "ecr:BatchGetImage",
55
+ "ecr:GetDownloadUrlForLayer",
56
+ "ecr:BatchCheckLayerAvailability",
57
+ "ecr:DescribeImages"
58
+ ]
59
+ }));
60
+ this.signingKey = new kms.Key(this, "ReleaseSigningKey", {
61
+ alias: props.signingKeyAlias ?? "foundation-release",
62
+ description: "Signs Foundation release manifests. Customers verify against it.",
63
+ keySpec: kms.KeySpec.RSA_4096,
64
+ keyUsage: kms.KeyUsage.SIGN_VERIFY,
65
+ removalPolicy: cdk.RemovalPolicy.RETAIN
66
+ });
67
+ if (customerPrincipals.length > 0)
68
+ this.signingKey.addToResourcePolicy(new iam.PolicyStatement({
69
+ sid: "CustomersVerifyManifests",
70
+ principals: customerPrincipals,
71
+ actions: ["kms:Verify", "kms:GetPublicKey", "kms:DescribeKey"],
72
+ resources: ["*"]
73
+ }));
74
+ const provider = iam.OpenIdConnectProvider.fromOpenIdConnectProviderArn(this, "GitHubOidc", `arn:${this.partition}:iam::${this.account}:oidc-provider/token.actions.githubusercontent.com`);
75
+ const [owner, repo] = props.githubRepository.split("/");
76
+ const ids = props.githubRepositoryIds;
77
+ const tagSubjects = [
78
+ `repo:${props.githubRepository}:ref:refs/tags/v*`,
79
+ `repo:${owner}@${ids.owner}/${repo}@${ids.repo}:ref:refs/tags/v*`
80
+ ];
81
+ this.releaseRole = new iam.Role(this, "ReleaseRole", {
82
+ roleName: props.releaseRoleName ?? "FoundationRelease",
83
+ description: `Publishes Foundation releases from tag pushes on ${props.githubRepository}`,
84
+ maxSessionDuration: cdk.Duration.hours(1),
85
+ assumedBy: new iam.WebIdentityPrincipal(provider.openIdConnectProviderArn, {
86
+ StringEquals: { "token.actions.githubusercontent.com:aud": "sts.amazonaws.com" },
87
+ StringLike: { "token.actions.githubusercontent.com:sub": tagSubjects }
88
+ }),
89
+ inlinePolicies: {
90
+ PublishRelease: new iam.PolicyDocument({
91
+ statements: [
92
+ new iam.PolicyStatement({
93
+ sid: "UploadRelease",
94
+ actions: ["s3:PutObject", "s3:GetObject", "s3:ListBucket"],
95
+ resources: [this.bucket.bucketArn, this.bucket.arnForObjects("releases/*")]
96
+ }),
97
+ new iam.PolicyStatement({
98
+ sid: "PushAgentImage",
99
+ actions: [
100
+ "ecr:BatchCheckLayerAvailability",
101
+ "ecr:CompleteLayerUpload",
102
+ "ecr:InitiateLayerUpload",
103
+ "ecr:PutImage",
104
+ "ecr:UploadLayerPart",
105
+ "ecr:BatchGetImage",
106
+ "ecr:DescribeImages"
107
+ ],
108
+ resources: [this.repository.repositoryArn]
109
+ }),
110
+ new iam.PolicyStatement({
111
+ sid: "EcrLogin",
112
+ actions: ["ecr:GetAuthorizationToken"],
113
+ resources: ["*"]
114
+ }),
115
+ new iam.PolicyStatement({
116
+ sid: "SignManifest",
117
+ actions: ["kms:Sign", "kms:GetPublicKey", "kms:DescribeKey"],
118
+ resources: [this.signingKey.keyArn]
119
+ })
120
+ ]
121
+ })
122
+ }
123
+ });
124
+ new cdk.CfnOutput(this, "ReleaseBucketName", { value: this.bucket.bucketName });
125
+ new cdk.CfnOutput(this, "AgentRepositoryUri", { value: this.repository.repositoryUri });
126
+ new cdk.CfnOutput(this, "SigningKeyArn", { value: this.signingKey.keyArn });
127
+ new cdk.CfnOutput(this, "ReleaseRoleArn", { value: this.releaseRole.roleArn });
128
+ new cdk.CfnOutput(this, "CustomerAccountIds", { value: customers.join(",") });
129
+ }
130
+ }
131
+
132
+ // bin/release-account.ts
133
+ var app = new cdk2.App;
134
+ var customerAccountIds = String(app.node.tryGetContext("customerAccountIds") ?? "").split(",").map((id) => id.trim()).filter((id) => id !== "");
135
+ for (const id of customerAccountIds)
136
+ if (!/^\d{12}$/.test(id))
137
+ throw new Error(`customerAccountIds: "${id}" is not a 12-digit AWS account id`);
138
+ new ReleaseAccountStack(app, "FoundationRelease", {
139
+ env: {
140
+ account: process.env.CDK_DEFAULT_ACCOUNT,
141
+ region: process.env.CDK_DEFAULT_REGION ?? "us-east-1"
142
+ },
143
+ bucketName: app.node.tryGetContext("releaseBucket") ?? DEFAULT_RELEASE_BUCKET,
144
+ ...app.node.tryGetContext("agentRepository") === undefined ? {} : { repositoryName: app.node.tryGetContext("agentRepository") },
145
+ customerAccountIds,
146
+ githubRepository: app.node.tryGetContext("githubRepository") ?? "CitrusNest/foundation",
147
+ githubRepositoryIds: {
148
+ owner: Number(app.node.tryGetContext("githubOwnerId") ?? 325214756),
149
+ repo: Number(app.node.tryGetContext("githubRepoId") ?? 1376990599)
150
+ },
151
+ ...app.node.tryGetContext("signingKeyAlias") === undefined ? {} : { signingKeyAlias: app.node.tryGetContext("signingKeyAlias") },
152
+ ...app.node.tryGetContext("releaseRoleName") === undefined ? {} : { releaseRoleName: app.node.tryGetContext("releaseRoleName") }
153
+ });
154
+ app.synth();