dcl-ops-lib 5.17.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.
- package/README.md +6 -0
- package/StaticWebsite.d.ts +24 -0
- package/StaticWebsite.js +3 -0
- package/acceptAlb.d.ts +4 -0
- package/acceptAlb.js +27 -0
- package/acceptBastion.d.ts +4 -0
- package/acceptBastion.js +27 -0
- package/acceptDb.d.ts +4 -0
- package/acceptDb.js +27 -0
- package/accessTheInternet.d.ts +6 -0
- package/accessTheInternet.js +38 -0
- package/alb.d.ts +14 -0
- package/alb.js +34 -0
- package/buildStatic.d.ts +15 -0
- package/buildStatic.js +169 -0
- package/certificate.d.ts +2 -0
- package/certificate.js +42 -0
- package/cloudflare.d.ts +24 -0
- package/cloudflare.js +72 -0
- package/cloudwatchLogs.d.ts +2 -0
- package/cloudwatchLogs.js +34 -0
- package/createBucketWithUser.d.ts +11 -0
- package/createBucketWithUser.js +59 -0
- package/createFargateTask.d.ts +100 -0
- package/createFargateTask.js +321 -0
- package/createImageFromContext.d.ts +12 -0
- package/createImageFromContext.js +24 -0
- package/domain.d.ts +10 -0
- package/domain.js +49 -0
- package/exposePublicService.d.ts +26 -0
- package/exposePublicService.js +105 -0
- package/getAmi.d.ts +7 -0
- package/getAmi.js +35 -0
- package/getDomainAndSubdomain.d.ts +4 -0
- package/getDomainAndSubdomain.js +22 -0
- package/getImageRegistryAndCredentials.d.ts +6 -0
- package/getImageRegistryAndCredentials.js +33 -0
- package/getSecurityGroup.d.ts +6 -0
- package/getSecurityGroup.js +51 -0
- package/lambda.d.ts +19 -0
- package/lambda.js +149 -0
- package/network.d.ts +3 -0
- package/network.js +17 -0
- package/package.json +37 -0
- package/secrets.d.ts +3 -0
- package/secrets.js +12 -0
- package/setupDatabasePermissions.d.ts +2 -0
- package/setupDatabasePermissions.js +18 -0
- package/stack.d.ts +3 -0
- package/stack.js +22 -0
- package/supra.d.ts +7 -0
- package/supra.js +41 -0
- package/utils.d.ts +1 -0
- package/utils.js +11 -0
- package/values.d.ts +11 -0
- package/values.js +51 -0
- package/vpc.d.ts +3 -0
- package/vpc.js +28 -0
- package/withCache.d.ts +1 -0
- package/withCache.js +14 -0
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.exposePublicService = void 0;
|
|
13
|
+
const aws = require("@pulumi/aws");
|
|
14
|
+
const awsx = require("@pulumi/awsx");
|
|
15
|
+
const domain_1 = require("./domain");
|
|
16
|
+
const alb_1 = require("./alb");
|
|
17
|
+
const certificate_1 = require("./certificate");
|
|
18
|
+
const getDomainAndSubdomain_1 = require("./getDomainAndSubdomain");
|
|
19
|
+
const cloudflare_1 = require("./cloudflare");
|
|
20
|
+
const DEFAULT_HEALTHCHECK_VALUES = {
|
|
21
|
+
path: "/",
|
|
22
|
+
matcher: "200-399",
|
|
23
|
+
interval: 10,
|
|
24
|
+
unhealthyThreshold: 5,
|
|
25
|
+
healthyThreshold: 5,
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* Publicly expose a service on a given domain (with SSL). This will create a
|
|
29
|
+
* Target Group and a Listener for your microservice. Additionally, it will
|
|
30
|
+
* create a Route53 mapping of the DNS that will point to the load balancer.
|
|
31
|
+
*
|
|
32
|
+
* @param name the name of your service.
|
|
33
|
+
* @param domain
|
|
34
|
+
* @param port
|
|
35
|
+
*/
|
|
36
|
+
function exposePublicService(name, domain, port, healthCheck = {}, vpc, extraOptions, deregistrationDelay) {
|
|
37
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
38
|
+
const { alb, listener } = yield (0, alb_1.getAlb)();
|
|
39
|
+
const healthCheckValue = Object.assign({}, DEFAULT_HEALTHCHECK_VALUES, healthCheck);
|
|
40
|
+
const createCFProxy = extraOptions && extraOptions.createCloudflareProxiedSubdomain;
|
|
41
|
+
const onlyCloudflare = (extraOptions && extraOptions.skipInternalDomain) || false;
|
|
42
|
+
const createInternalDomain = !onlyCloudflare;
|
|
43
|
+
const certificate = (0, certificate_1.getCertificateFor)(domain);
|
|
44
|
+
const slug = name;
|
|
45
|
+
const targetVpc = vpc ? vpc : awsx.ec2.Vpc.getDefault();
|
|
46
|
+
const targetDeregistrationDelay = deregistrationDelay ? deregistrationDelay : 300;
|
|
47
|
+
const targetGroup = alb.createTargetGroup(("tg-" + slug).substr(-32) /* last 32 chars */, {
|
|
48
|
+
protocol: "HTTP",
|
|
49
|
+
port,
|
|
50
|
+
healthCheck: healthCheckValue,
|
|
51
|
+
vpc: targetVpc,
|
|
52
|
+
deregistrationDelay: targetDeregistrationDelay
|
|
53
|
+
});
|
|
54
|
+
const domainParts = (0, getDomainAndSubdomain_1.getDomainAndSubdomain)(domain);
|
|
55
|
+
const enabledHostnames = [];
|
|
56
|
+
let record;
|
|
57
|
+
let cloudflareRecord;
|
|
58
|
+
if (createInternalDomain) {
|
|
59
|
+
const hostedZone = yield aws.route53.getZone({ name: domainParts.parentDomain }, { async: true });
|
|
60
|
+
record = new aws.route53.Record(domain, {
|
|
61
|
+
name: domainParts.subdomain,
|
|
62
|
+
zoneId: hostedZone.zoneId,
|
|
63
|
+
type: "A",
|
|
64
|
+
aliases: [
|
|
65
|
+
{
|
|
66
|
+
name: alb.loadBalancer.dnsName,
|
|
67
|
+
zoneId: alb.loadBalancer.zoneId,
|
|
68
|
+
evaluateTargetHealth: false,
|
|
69
|
+
},
|
|
70
|
+
],
|
|
71
|
+
});
|
|
72
|
+
enabledHostnames.push(domain);
|
|
73
|
+
}
|
|
74
|
+
if (createCFProxy) {
|
|
75
|
+
enabledHostnames.push(domainParts.subdomain + "." + domain_1.publicDomain);
|
|
76
|
+
cloudflareRecord = yield (0, cloudflare_1.setRecord)({
|
|
77
|
+
recordName: domainParts.subdomain,
|
|
78
|
+
type: "CNAME",
|
|
79
|
+
value: alb.loadBalancer.dnsName,
|
|
80
|
+
proxied: true,
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
if (enabledHostnames.length) {
|
|
84
|
+
new aws.alb.ListenerRule(`${domain_1.env}-ls-${slug}`, {
|
|
85
|
+
listenerArn: listener.arn,
|
|
86
|
+
conditions: [{ hostHeader: { values: enabledHostnames } }, ...((extraOptions === null || extraOptions === void 0 ? void 0 : extraOptions.targetGroupConditions) || [])],
|
|
87
|
+
actions: [
|
|
88
|
+
{
|
|
89
|
+
type: "forward",
|
|
90
|
+
targetGroupArn: targetGroup.targetGroup.arn,
|
|
91
|
+
},
|
|
92
|
+
],
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
return {
|
|
96
|
+
domain,
|
|
97
|
+
certificate,
|
|
98
|
+
record,
|
|
99
|
+
targetGroup,
|
|
100
|
+
cloudflareRecord,
|
|
101
|
+
};
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
exports.exposePublicService = exposePublicService;
|
|
105
|
+
//# sourceMappingURL=exposePublicService.js.map
|
package/getAmi.d.ts
ADDED
package/getAmi.js
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.getAmi = void 0;
|
|
13
|
+
const aws = require("@pulumi/aws");
|
|
14
|
+
/**
|
|
15
|
+
* @param amiId the ID of the AMI in the Amazon Marketplace
|
|
16
|
+
* @param args.owners the owner of the AMI. Defaults to Amazon owned AMIs
|
|
17
|
+
*/
|
|
18
|
+
function getAmi(amiId, args) {
|
|
19
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
20
|
+
const owners = args && args.owners ? args.owners : ["137112412989"];
|
|
21
|
+
const ami = yield aws.ec2.getAmi({
|
|
22
|
+
filters: [
|
|
23
|
+
{
|
|
24
|
+
name: "name",
|
|
25
|
+
values: [amiId],
|
|
26
|
+
},
|
|
27
|
+
],
|
|
28
|
+
mostRecent: true,
|
|
29
|
+
owners,
|
|
30
|
+
}, { async: true });
|
|
31
|
+
return ami.id;
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
exports.getAmi = getAmi;
|
|
35
|
+
//# sourceMappingURL=getAmi.js.map
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getDomainAndSubdomain = void 0;
|
|
4
|
+
// Split a domain name into its subdomain and parent domain names.
|
|
5
|
+
// e.g. "www.example.com" => "www", "example.com".
|
|
6
|
+
function getDomainAndSubdomain(domain) {
|
|
7
|
+
const parts = domain.split(".");
|
|
8
|
+
if (parts.length < 2) {
|
|
9
|
+
throw new Error(`No TLD found on ${domain}`);
|
|
10
|
+
}
|
|
11
|
+
// No subdomain, e.g. awesome-website.com.
|
|
12
|
+
if (parts.length === 2) {
|
|
13
|
+
return { subdomain: "", parentDomain: domain };
|
|
14
|
+
}
|
|
15
|
+
return {
|
|
16
|
+
subdomain: parts.slice(0, -2).join("."),
|
|
17
|
+
// Trailing "." to canonicalize domain.
|
|
18
|
+
parentDomain: parts.slice(-2).join(".") + ".",
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
exports.getDomainAndSubdomain = getDomainAndSubdomain;
|
|
22
|
+
//# sourceMappingURL=getDomainAndSubdomain.js.map
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.getImageRegistryAndCredentials = void 0;
|
|
13
|
+
const aws = require("@pulumi/aws");
|
|
14
|
+
function getImageRegistryAndCredentials(repo) {
|
|
15
|
+
return repo.registryId.apply((registryId) => __awaiter(this, void 0, void 0, function* () {
|
|
16
|
+
if (!registryId) {
|
|
17
|
+
throw new Error("Expected registry ID to be defined during push");
|
|
18
|
+
}
|
|
19
|
+
const credentials = yield aws.ecr.getCredentials({ registryId: registryId });
|
|
20
|
+
const decodedCredentials = Buffer.from(credentials.authorizationToken, "base64").toString();
|
|
21
|
+
const [username, password] = decodedCredentials.split(":");
|
|
22
|
+
if (!password || !username) {
|
|
23
|
+
throw new Error("Invalid credentials");
|
|
24
|
+
}
|
|
25
|
+
return {
|
|
26
|
+
server: credentials.proxyEndpoint,
|
|
27
|
+
username: username,
|
|
28
|
+
password: password,
|
|
29
|
+
};
|
|
30
|
+
}));
|
|
31
|
+
}
|
|
32
|
+
exports.getImageRegistryAndCredentials = getImageRegistryAndCredentials;
|
|
33
|
+
//# sourceMappingURL=getImageRegistryAndCredentials.js.map
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import * as awsx from "@pulumi/awsx";
|
|
2
|
+
import { Output } from '@pulumi/pulumi';
|
|
3
|
+
export declare function createSecurityGroupFunction(name: string, id: string | Output<string>): {
|
|
4
|
+
getSecurityGroup: () => Promise<awsx.ec2.SecurityGroup | Output<awsx.ec2.SecurityGroup>>;
|
|
5
|
+
getSecurityGroupId: () => Promise<Output<string>>;
|
|
6
|
+
};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.createSecurityGroupFunction = void 0;
|
|
13
|
+
const awsx = require("@pulumi/awsx");
|
|
14
|
+
function createSecurityGroupFunction(name, id) {
|
|
15
|
+
let securityGroupOutput;
|
|
16
|
+
let securityGroupPromise;
|
|
17
|
+
function getSecurityGroup() {
|
|
18
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
19
|
+
if (!securityGroupOutput) {
|
|
20
|
+
if (!securityGroupPromise) {
|
|
21
|
+
securityGroupPromise = new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
|
|
22
|
+
try {
|
|
23
|
+
resolve(awsx.ec2.SecurityGroup.fromExistingId(name, id));
|
|
24
|
+
}
|
|
25
|
+
catch (e) {
|
|
26
|
+
reject(e);
|
|
27
|
+
}
|
|
28
|
+
}));
|
|
29
|
+
return yield securityGroupPromise;
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
return yield securityGroupPromise;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
return securityGroupOutput;
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
function getSecurityGroupId() {
|
|
41
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
42
|
+
return (yield getSecurityGroup()).id;
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
return {
|
|
46
|
+
getSecurityGroup: getSecurityGroup,
|
|
47
|
+
getSecurityGroupId: getSecurityGroupId
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
exports.createSecurityGroupFunction = createSecurityGroupFunction;
|
|
51
|
+
//# sourceMappingURL=getSecurityGroup.js.map
|
package/lambda.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import * as awsx from "@pulumi/awsx";
|
|
2
|
+
import * as aws from "@pulumi/aws";
|
|
3
|
+
import * as pulumi from "@pulumi/pulumi";
|
|
4
|
+
export declare type LambdaOptions = {
|
|
5
|
+
folderName: string;
|
|
6
|
+
extra?: Partial<aws.lambda.FunctionArgs>;
|
|
7
|
+
attachRolePolicyArn?: Record<string, pulumi.Input<string>>;
|
|
8
|
+
};
|
|
9
|
+
export declare function createGateway(options: {
|
|
10
|
+
fullyQualifiedDomainName: string;
|
|
11
|
+
}, fn: (addRoute: (config: LambdaOptions & {
|
|
12
|
+
method: awsx.apigateway.Method;
|
|
13
|
+
path: string;
|
|
14
|
+
extraRoute?: awsx.apigateway.BaseRoute;
|
|
15
|
+
}) => Promise<void>) => Promise<void>): Promise<{
|
|
16
|
+
gateway: awsx.apigateway.API;
|
|
17
|
+
record: aws.route53.Record;
|
|
18
|
+
lambdasDomain: string;
|
|
19
|
+
}>;
|
package/lambda.js
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.createGateway = void 0;
|
|
13
|
+
const awsx = require("@pulumi/awsx");
|
|
14
|
+
const aws = require("@pulumi/aws");
|
|
15
|
+
const pulumi = require("@pulumi/pulumi");
|
|
16
|
+
const path_1 = require("path");
|
|
17
|
+
const domain_1 = require("./domain");
|
|
18
|
+
const cloudflare_1 = require("./cloudflare");
|
|
19
|
+
const getDomainAndSubdomain_1 = require("./getDomainAndSubdomain");
|
|
20
|
+
const certificate_1 = require("./certificate");
|
|
21
|
+
const stack_1 = require("./stack");
|
|
22
|
+
function createLambda(fullyQualifiedDomainName, config) {
|
|
23
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
24
|
+
const { folderName, extra, attachRolePolicyArn } = config;
|
|
25
|
+
const file = require.resolve(folderName);
|
|
26
|
+
const lambdaName = (0, path_1.basename)(folderName);
|
|
27
|
+
if (!lambdaName.match(/^[a-zA-Z0-9-_]+$/)) {
|
|
28
|
+
throw new Error("Invalid(/^[a-zA-Z0-9-_]+$/) folder name: " + folderName);
|
|
29
|
+
}
|
|
30
|
+
const { subdomain } = (0, getDomainAndSubdomain_1.getDomainAndSubdomain)(fullyQualifiedDomainName);
|
|
31
|
+
const rolename = `${subdomain || "ROOTDOMAIN"}-${lambdaName}-role`;
|
|
32
|
+
// Configure IAM so that the AWS Lambda can be run.
|
|
33
|
+
const lambdaApiGatewayRole = new aws.iam.Role((0, stack_1.getStackScopedName)(rolename), {
|
|
34
|
+
assumeRolePolicy: {
|
|
35
|
+
Version: "2012-10-17",
|
|
36
|
+
Statement: [
|
|
37
|
+
{
|
|
38
|
+
Action: "sts:AssumeRole",
|
|
39
|
+
Principal: {
|
|
40
|
+
Service: "lambda.amazonaws.com",
|
|
41
|
+
},
|
|
42
|
+
Effect: "Allow",
|
|
43
|
+
Sid: "",
|
|
44
|
+
},
|
|
45
|
+
],
|
|
46
|
+
},
|
|
47
|
+
});
|
|
48
|
+
// attach AWSLambdaBasicExecutionRole
|
|
49
|
+
// https://docs.aws.amazon.com/lambda/latest/dg/lambda-intro-execution-role.html
|
|
50
|
+
// write cloudwatch logs
|
|
51
|
+
new aws.iam.RolePolicyAttachment((0, stack_1.getStackScopedName)(`${rolename}-AWSLambdaBasicExecutionRole`), {
|
|
52
|
+
role: lambdaApiGatewayRole,
|
|
53
|
+
policyArn: aws.iam.ManagedPolicies.AWSLambdaBasicExecutionRole,
|
|
54
|
+
});
|
|
55
|
+
// upload xray traces
|
|
56
|
+
new aws.iam.RolePolicyAttachment((0, stack_1.getStackScopedName)(`${rolename}-AWSXRayDaemonWriteAccess`), {
|
|
57
|
+
role: lambdaApiGatewayRole,
|
|
58
|
+
policyArn: aws.iam.ManagedPolicies.AWSXRayDaemonWriteAccess,
|
|
59
|
+
});
|
|
60
|
+
if (attachRolePolicyArn) {
|
|
61
|
+
Object.entries(attachRolePolicyArn).forEach(([name, policyArn]) => {
|
|
62
|
+
new aws.iam.RolePolicyAttachment((0, stack_1.getStackScopedName)(`${rolename}-${name}`), {
|
|
63
|
+
role: lambdaApiGatewayRole,
|
|
64
|
+
policyArn,
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
const name = (0, stack_1.getStackScopedName)((subdomain || "ROOTDOMAIN") + "-" + lambdaName);
|
|
69
|
+
const lambda = new aws.lambda.Function(name, Object.assign({ name: name, handler: `${(0, path_1.basename)(file, ".js")}.handler`, timeout: 900, memorySize: 1024, runtime: "nodejs12.x", code: (extra === null || extra === void 0 ? void 0 : extra.code) ||
|
|
70
|
+
new pulumi.asset.AssetArchive({
|
|
71
|
+
[(0, path_1.basename)(file)]: new pulumi.asset.FileAsset(file),
|
|
72
|
+
}), role: (extra === null || extra === void 0 ? void 0 : extra.role) || lambdaApiGatewayRole.arn }, extra));
|
|
73
|
+
return lambda;
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
function createGateway(options, fn) {
|
|
77
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
78
|
+
const routes = [];
|
|
79
|
+
yield fn(function configureApiGatewayLambda(config) {
|
|
80
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
81
|
+
const { method, path, extraRoute } = config;
|
|
82
|
+
const lambda = yield createLambda(options.fullyQualifiedDomainName, config);
|
|
83
|
+
routes.push(Object.assign({ method: method, path, eventHandler: lambda }, extraRoute));
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
if (routes.length == 0) {
|
|
87
|
+
throw new Error("Warning! No routes were configured");
|
|
88
|
+
}
|
|
89
|
+
const stageName = domain_1.env;
|
|
90
|
+
// Create a public HTTP endpoint (using AWS APIGateway)
|
|
91
|
+
const gateway = new awsx.apigateway.API((0, stack_1.getStackScopedName)(options.fullyQualifiedDomainName.replace(/\./g, "-")), {
|
|
92
|
+
routes: routes,
|
|
93
|
+
stageName,
|
|
94
|
+
restApiArgs: {
|
|
95
|
+
name: "rest-api",
|
|
96
|
+
},
|
|
97
|
+
stageArgs: {
|
|
98
|
+
xrayTracingEnabled: true,
|
|
99
|
+
},
|
|
100
|
+
});
|
|
101
|
+
const { record, lambdasDomain } = yield configureApiGatewayDomain(options.fullyQualifiedDomainName, gateway);
|
|
102
|
+
return {
|
|
103
|
+
gateway,
|
|
104
|
+
record,
|
|
105
|
+
lambdasDomain,
|
|
106
|
+
};
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
exports.createGateway = createGateway;
|
|
110
|
+
function configureApiGatewayDomain(fullyQualifiedDomainName, gateway) {
|
|
111
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
112
|
+
const domainParts = (0, getDomainAndSubdomain_1.getDomainAndSubdomain)(fullyQualifiedDomainName);
|
|
113
|
+
const subdomain = domainParts.subdomain || "ROOTDOMAIN";
|
|
114
|
+
// Configure an edge-optimized domain for our API Gateway. This will configure a Cloudfront CDN
|
|
115
|
+
// distribution behind the scenes and serve our API Gateway at a custom domain name over SSL.
|
|
116
|
+
const webDomain = new aws.apigateway.DomainName((0, stack_1.getStackScopedName)(subdomain + "-dn"), {
|
|
117
|
+
certificateArn: (0, certificate_1.getCertificateFor)(fullyQualifiedDomainName),
|
|
118
|
+
domainName: fullyQualifiedDomainName,
|
|
119
|
+
});
|
|
120
|
+
const webDomainMapping = new aws.apigateway.BasePathMapping((0, stack_1.getStackScopedName)(subdomain + "-bpm"), {
|
|
121
|
+
restApi: gateway.restAPI,
|
|
122
|
+
stageName: gateway.stage.stageName,
|
|
123
|
+
domainName: webDomain.id,
|
|
124
|
+
});
|
|
125
|
+
const hostedZone = yield aws.route53.getZone({ name: domainParts.parentDomain }, { async: true });
|
|
126
|
+
const record = new aws.route53.Record((0, stack_1.getStackScopedName)(fullyQualifiedDomainName), {
|
|
127
|
+
name: domainParts.subdomain || "",
|
|
128
|
+
zoneId: hostedZone.zoneId,
|
|
129
|
+
type: "A",
|
|
130
|
+
aliases: [
|
|
131
|
+
{
|
|
132
|
+
evaluateTargetHealth: true,
|
|
133
|
+
name: webDomain.cloudfrontDomainName,
|
|
134
|
+
zoneId: webDomain.cloudfrontZoneId,
|
|
135
|
+
},
|
|
136
|
+
],
|
|
137
|
+
}, { dependsOn: [webDomainMapping] });
|
|
138
|
+
if (domainParts.parentDomain.replace(/\.$/, "") == domain_1.publicDomain) {
|
|
139
|
+
(0, cloudflare_1.setRecord)({
|
|
140
|
+
proxied: true,
|
|
141
|
+
recordName: domainParts.subdomain,
|
|
142
|
+
type: "CNAME",
|
|
143
|
+
value: webDomain.cloudfrontDomainName,
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
return { record, lambdasDomain: fullyQualifiedDomainName };
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
//# sourceMappingURL=lambda.js.map
|
package/network.d.ts
ADDED
package/network.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getInternalSubnetIds = exports.getPrivateSubnetIds = exports.getPublicSubnetIds = void 0;
|
|
4
|
+
const supra_1 = require("./supra");
|
|
5
|
+
function getPublicSubnetIds() {
|
|
6
|
+
return supra_1.supra.getOutputValue('vpcPublicSubnetIds');
|
|
7
|
+
}
|
|
8
|
+
exports.getPublicSubnetIds = getPublicSubnetIds;
|
|
9
|
+
function getPrivateSubnetIds() {
|
|
10
|
+
return supra_1.supra.getOutputValue('vpcPrivateSubnetIds');
|
|
11
|
+
}
|
|
12
|
+
exports.getPrivateSubnetIds = getPrivateSubnetIds;
|
|
13
|
+
function getInternalSubnetIds() {
|
|
14
|
+
return supra_1.supra.getOutputValue('vpcInternalSubnetIds');
|
|
15
|
+
}
|
|
16
|
+
exports.getInternalSubnetIds = getInternalSubnetIds;
|
|
17
|
+
//# sourceMappingURL=network.js.map
|
package/package.json
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "dcl-ops-lib",
|
|
3
|
+
"version": "5.17.0",
|
|
4
|
+
"scripts": {
|
|
5
|
+
"build": "tsc && cp bin/* .",
|
|
6
|
+
"clean": "rm *.d.ts *.js *.js.map"
|
|
7
|
+
},
|
|
8
|
+
"files": [
|
|
9
|
+
"package.json",
|
|
10
|
+
"README.md",
|
|
11
|
+
"*.js",
|
|
12
|
+
"*.d.ts"
|
|
13
|
+
],
|
|
14
|
+
"types": "index.d.ts",
|
|
15
|
+
"main": "index.js",
|
|
16
|
+
"release": {
|
|
17
|
+
"branches": [
|
|
18
|
+
"master"
|
|
19
|
+
],
|
|
20
|
+
"extends": "@semantic-release/gitlab-config"
|
|
21
|
+
},
|
|
22
|
+
"devDependencies": {
|
|
23
|
+
"@semantic-release/gitlab-config": "^8.0.0",
|
|
24
|
+
"@types/mime": "^2.0.3",
|
|
25
|
+
"@types/node": "^14.14.32",
|
|
26
|
+
"semantic-release": "^17.4.1",
|
|
27
|
+
"typescript": "^4.4.3"
|
|
28
|
+
},
|
|
29
|
+
"dependencies": {
|
|
30
|
+
"@pulumi/aws": "^4.21.2",
|
|
31
|
+
"@pulumi/awsx": "^0.31.0",
|
|
32
|
+
"@pulumi/cloudflare": "^3.5.0",
|
|
33
|
+
"@pulumi/docker": "^3.1.0",
|
|
34
|
+
"@pulumi/pulumi": "^3.13.0",
|
|
35
|
+
"mime": "^2.5.2"
|
|
36
|
+
}
|
|
37
|
+
}
|
package/secrets.d.ts
ADDED
package/secrets.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.secretToSSM = void 0;
|
|
4
|
+
const aws = require("@pulumi/aws");
|
|
5
|
+
function secretToSSM(name, secureString) {
|
|
6
|
+
return new aws.ssm.Parameter(name, {
|
|
7
|
+
type: "SecureString",
|
|
8
|
+
value: secureString,
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
exports.secretToSSM = secretToSSM;
|
|
12
|
+
//# sourceMappingURL=secrets.js.map
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.setupDatabasePermissions = void 0;
|
|
4
|
+
function setupDatabasePermissions(databaseName, databaseUsername, databasePassword) {
|
|
5
|
+
// Creating users in terraform+pulumi+aws+postgres is utterly broken.
|
|
6
|
+
// Need to do this manually.
|
|
7
|
+
//
|
|
8
|
+
// CREATE DATABASE databaseName;
|
|
9
|
+
// CREATE ROLE databaseUsername WITH LOGIN PASSWORD 'password';
|
|
10
|
+
// GRANT ALL PRIVILEGES ON DATABASE databaseUsername TO databaseUsername;
|
|
11
|
+
throw new Error(`You need to do the DB setup manually. Sorry about it!
|
|
12
|
+
Please connect to the db through the bastion node and run:
|
|
13
|
+
CREATE DATABASE databaseName;
|
|
14
|
+
CREATE ROLE databaseUsername WITH LOGIN PASSWORD 'password';
|
|
15
|
+
GRANT ALL PRIVILEGES ON DATABASE databaseUsername TO databaseUsername;`);
|
|
16
|
+
}
|
|
17
|
+
exports.setupDatabasePermissions = setupDatabasePermissions;
|
|
18
|
+
//# sourceMappingURL=setupDatabasePermissions.js.map
|
package/stack.d.ts
ADDED
package/stack.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getTeam = exports.getStackScopedName = exports.getStackId = void 0;
|
|
4
|
+
const pulumi = require("@pulumi/pulumi");
|
|
5
|
+
const supraConfig = new pulumi.Config("supra");
|
|
6
|
+
function getStackId() {
|
|
7
|
+
return supraConfig.require("stack-id");
|
|
8
|
+
}
|
|
9
|
+
exports.getStackId = getStackId;
|
|
10
|
+
function getStackScopedName(name) {
|
|
11
|
+
const stackId = getStackId();
|
|
12
|
+
if (stackId) {
|
|
13
|
+
return name + "-" + stackId;
|
|
14
|
+
}
|
|
15
|
+
return name;
|
|
16
|
+
}
|
|
17
|
+
exports.getStackScopedName = getStackScopedName;
|
|
18
|
+
function getTeam() {
|
|
19
|
+
return supraConfig.require("team");
|
|
20
|
+
}
|
|
21
|
+
exports.getTeam = getTeam;
|
|
22
|
+
//# sourceMappingURL=stack.js.map
|
package/supra.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import * as pulumi from "@pulumi/pulumi";
|
|
2
|
+
export declare const supra: pulumi.StackReference;
|
|
3
|
+
export declare function getDbHostAndPort(): pulumi.Output<any>;
|
|
4
|
+
export declare function getDbHost(): pulumi.Output<any>;
|
|
5
|
+
export declare function getDbPort(): pulumi.OutputInstance<number>;
|
|
6
|
+
export declare function getPublicBastionIp(): pulumi.Output<any>;
|
|
7
|
+
export declare function getInternalServiceDiscoveryNamespaceId(): pulumi.Output<any>;
|
package/supra.js
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getInternalServiceDiscoveryNamespaceId = exports.getPublicBastionIp = exports.getDbPort = exports.getDbHost = exports.getDbHostAndPort = exports.supra = void 0;
|
|
4
|
+
const pulumi = require("@pulumi/pulumi");
|
|
5
|
+
const domain_1 = require("./domain");
|
|
6
|
+
exports.supra = new pulumi.StackReference(`supra-${domain_1.env}`, {
|
|
7
|
+
name: `supra-${domain_1.env}`,
|
|
8
|
+
});
|
|
9
|
+
const DEFAULT_DB_PORT = 5432;
|
|
10
|
+
// returns a "db.hostname.com:port" Output<string> for the supra shared database
|
|
11
|
+
function getDbHostAndPort() {
|
|
12
|
+
return exports.supra.requireOutput("db").apply((db) => {
|
|
13
|
+
if (db.endpoint.includes(":")) {
|
|
14
|
+
return db.endpoint;
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
return db.endpoint + ":" + DEFAULT_DB_PORT;
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
exports.getDbHostAndPort = getDbHostAndPort;
|
|
22
|
+
// returns "db.hostname.com" from "db.hostname.com:port" Output<string> for the supra shared database
|
|
23
|
+
function getDbHost() {
|
|
24
|
+
return exports.supra.requireOutput("db").apply((db) => db.endpoint.split(":")[0]);
|
|
25
|
+
}
|
|
26
|
+
exports.getDbHost = getDbHost;
|
|
27
|
+
// returns "port" from "db.hostname.com:port" Output<string> for the supra shared database
|
|
28
|
+
function getDbPort() {
|
|
29
|
+
return exports.supra.requireOutput("db").apply((db) => parseInt(db.endpoint.split(":")[1] || DEFAULT_DB_PORT));
|
|
30
|
+
}
|
|
31
|
+
exports.getDbPort = getDbPort;
|
|
32
|
+
// returns the public IP of the bastion
|
|
33
|
+
function getPublicBastionIp() {
|
|
34
|
+
return exports.supra.requireOutput("bastionValues").apply((bastionValues) => bastionValues.publicIp);
|
|
35
|
+
}
|
|
36
|
+
exports.getPublicBastionIp = getPublicBastionIp;
|
|
37
|
+
function getInternalServiceDiscoveryNamespaceId() {
|
|
38
|
+
return exports.supra.requireOutput("internalSdNamespace").apply(($) => $.id);
|
|
39
|
+
}
|
|
40
|
+
exports.getInternalServiceDiscoveryNamespaceId = getInternalServiceDiscoveryNamespaceId;
|
|
41
|
+
//# sourceMappingURL=supra.js.map
|
package/utils.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function sha256hash(s: string): string;
|
package/utils.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.sha256hash = void 0;
|
|
4
|
+
const crypto = require("crypto");
|
|
5
|
+
function sha256hash(s) {
|
|
6
|
+
const shasum = crypto.createHash("sha256");
|
|
7
|
+
shasum.update(s);
|
|
8
|
+
return shasum.digest("hex").substring(0, 8);
|
|
9
|
+
}
|
|
10
|
+
exports.sha256hash = sha256hash;
|
|
11
|
+
//# sourceMappingURL=utils.js.map
|