@stacksjs/cloud 0.62.0 → 0.63.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/dist/index.js +170 -137
- package/dist/index.js.map +27 -0
- package/package.json +33 -34
- package/src/cloud/aws-sdk-layer/nodejs/package-lock.json +6 -6
- package/src/cloud/aws-sdk-layer/nodejs/package.json +2 -2
- package/src/cloud/cdn.ts +47 -47
- package/src/cloud/compute.ts +12 -3
- package/src/cloud/deployment.ts +34 -8
- package/src/cloud/docs.ts +2 -1
- package/src/cloud/index.ts +31 -24
- package/src/cloud/queue.ts +2 -4
- package/src/cloud/router-layer/nodejs/package.json +2 -2
- package/src/cloud/security.ts +4 -4
- package/src/cloud/storage.ts +19 -0
- package/src/helpers.ts +10 -4
package/src/cloud/cdn.ts
CHANGED
|
@@ -13,7 +13,6 @@ import {
|
|
|
13
13
|
aws_route53_targets as targets,
|
|
14
14
|
} from 'aws-cdk-lib'
|
|
15
15
|
import type { ApplicationLoadBalancer } from 'aws-cdk-lib/aws-elasticloadbalancingv2'
|
|
16
|
-
import * as kinesis from 'aws-cdk-lib/aws-kinesis'
|
|
17
16
|
import type { Construct } from 'constructs'
|
|
18
17
|
import type { EnvKey } from '../../../../env'
|
|
19
18
|
import type { NestedCloudProps } from '../types'
|
|
@@ -22,6 +21,7 @@ export interface CdnStackProps extends NestedCloudProps {
|
|
|
22
21
|
certificate: acm.Certificate
|
|
23
22
|
logBucket: s3.Bucket
|
|
24
23
|
publicBucket: s3.Bucket
|
|
24
|
+
docsBucket?: s3.Bucket
|
|
25
25
|
firewall: wafv2.CfnWebACL
|
|
26
26
|
originRequestFunction: lambda.Function
|
|
27
27
|
zone: route53.IHostedZone
|
|
@@ -39,7 +39,7 @@ export class CdnStack {
|
|
|
39
39
|
cdnCachePolicy: cloudfront.CachePolicy
|
|
40
40
|
apiCachePolicy: cloudfront.CachePolicy | undefined
|
|
41
41
|
vanityUrl: string
|
|
42
|
-
realtimeLogConfig
|
|
42
|
+
realtimeLogConfig!: cloudfront.RealtimeLogConfig
|
|
43
43
|
props: CdnStackProps
|
|
44
44
|
|
|
45
45
|
constructor(scope: Construct, props: CdnStackProps) {
|
|
@@ -57,12 +57,12 @@ export class CdnStack {
|
|
|
57
57
|
})
|
|
58
58
|
|
|
59
59
|
// Step 1: Create a Kinesis Firehose delivery stream for the logs
|
|
60
|
-
const logStream = new kinesis.Stream(scope, 'StacksCdnRealtimeLogStream', {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
})
|
|
60
|
+
// const logStream = new kinesis.Stream(scope, 'StacksCdnRealtimeLogStream', {
|
|
61
|
+
// streamName: 'StacksCdnRealtimeLogStream',
|
|
62
|
+
// retentionPeriod: Duration.days(1),
|
|
63
|
+
// shardCount: 1,
|
|
64
|
+
// encryption: kinesis.StreamEncryption.UNENCRYPTED,
|
|
65
|
+
// })
|
|
66
66
|
|
|
67
67
|
// Create an IAM role for CloudFront to write logs to Kinesis Firehose
|
|
68
68
|
// new iam.Role(scope, 'LoggingRole', {
|
|
@@ -80,20 +80,20 @@ export class CdnStack {
|
|
|
80
80
|
// })
|
|
81
81
|
|
|
82
82
|
// TODO: make this configurable
|
|
83
|
-
this.realtimeLogConfig = new cloudfront.RealtimeLogConfig(scope, 'StacksRealTimeLogConfig', {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
})
|
|
83
|
+
// this.realtimeLogConfig = new cloudfront.RealtimeLogConfig(scope, 'StacksRealTimeLogConfig', {
|
|
84
|
+
// endPoints: [cloudfront.Endpoint.fromKinesisStream(logStream)],
|
|
85
|
+
// fields: [
|
|
86
|
+
// 'timestamp',
|
|
87
|
+
// 'c-ip',
|
|
88
|
+
// 'cs-method',
|
|
89
|
+
// 'cs-uri-stem',
|
|
90
|
+
// 'cs-uri-query',
|
|
91
|
+
// 'cs-referer',
|
|
92
|
+
// 'cs-user-agent',
|
|
93
|
+
// 'sc-status',
|
|
94
|
+
// ],
|
|
95
|
+
// samplingRate: 100, // Adjust the sampling rate as needed
|
|
96
|
+
// })
|
|
97
97
|
|
|
98
98
|
// the actual CDN distribution
|
|
99
99
|
this.distribution = new cloudfront.Distribution(scope, 'Cdn', {
|
|
@@ -111,7 +111,7 @@ export class CdnStack {
|
|
|
111
111
|
enableIpv6: true,
|
|
112
112
|
|
|
113
113
|
defaultBehavior: {
|
|
114
|
-
origin: new origins.S3Origin(props.publicBucket, {
|
|
114
|
+
origin: new origins.S3Origin(config.app.docMode ? (props.docsBucket as s3.Bucket) : props.publicBucket, {
|
|
115
115
|
originAccessIdentity: this.originAccessIdentity,
|
|
116
116
|
}),
|
|
117
117
|
edgeLambdas: [
|
|
@@ -125,7 +125,7 @@ export class CdnStack {
|
|
|
125
125
|
cachedMethods: this.cachedMethods(),
|
|
126
126
|
viewerProtocolPolicy: cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
|
|
127
127
|
cachePolicy: this.cdnCachePolicy,
|
|
128
|
-
realtimeLogConfig: this.realtimeLogConfig,
|
|
128
|
+
// realtimeLogConfig: this.realtimeLogConfig,
|
|
129
129
|
},
|
|
130
130
|
|
|
131
131
|
additionalBehaviors: this.additionalBehaviors(scope, props),
|
|
@@ -233,22 +233,19 @@ export class CdnStack {
|
|
|
233
233
|
}
|
|
234
234
|
|
|
235
235
|
shouldDeployApi() {
|
|
236
|
-
return config.api?.deploy
|
|
236
|
+
return config.cloud.api?.deploy
|
|
237
237
|
}
|
|
238
238
|
|
|
239
239
|
apiBehaviorOptions(scope: Construct, props: CdnStackProps): Record<string, cloudfront.BehaviorOptions> {
|
|
240
|
-
const hostname = `api.${props.domain}`
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
protocolPolicy: cloudfront.OriginProtocolPolicy.HTTPS_ONLY,
|
|
246
|
-
})
|
|
247
|
-
}
|
|
240
|
+
const hostname = `api.${props.domain}` // TODO: make `api` configurable
|
|
241
|
+
const origin = new origins.HttpOrigin(hostname, {
|
|
242
|
+
originPath: '/',
|
|
243
|
+
protocolPolicy: cloudfront.OriginProtocolPolicy.HTTPS_ONLY,
|
|
244
|
+
})
|
|
248
245
|
|
|
249
246
|
return {
|
|
250
247
|
'/api': {
|
|
251
|
-
origin
|
|
248
|
+
origin,
|
|
252
249
|
compress: true,
|
|
253
250
|
allowedMethods: cloudfront.AllowedMethods.ALLOW_ALL,
|
|
254
251
|
cachedMethods: cloudfront.CachedMethods.CACHE_GET_HEAD_OPTIONS,
|
|
@@ -256,8 +253,9 @@ export class CdnStack {
|
|
|
256
253
|
viewerProtocolPolicy: cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
|
|
257
254
|
realtimeLogConfig: this.realtimeLogConfig,
|
|
258
255
|
},
|
|
256
|
+
|
|
259
257
|
'/api/*': {
|
|
260
|
-
origin
|
|
258
|
+
origin,
|
|
261
259
|
compress: true,
|
|
262
260
|
allowedMethods: cloudfront.AllowedMethods.ALLOW_ALL,
|
|
263
261
|
cachedMethods: cloudfront.CachedMethods.CACHE_GET_HEAD_OPTIONS,
|
|
@@ -268,13 +266,17 @@ export class CdnStack {
|
|
|
268
266
|
}
|
|
269
267
|
}
|
|
270
268
|
|
|
271
|
-
docsBehaviorOptions(
|
|
269
|
+
docsBehaviorOptions(docsBucket?: s3.Bucket): Record<string, cloudfront.BehaviorOptions> {
|
|
270
|
+
if (!docsBucket) return {}
|
|
271
|
+
|
|
272
|
+
const origin = new origins.S3Origin(docsBucket, {
|
|
273
|
+
originAccessIdentity: this.originAccessIdentity,
|
|
274
|
+
originPath: '/',
|
|
275
|
+
})
|
|
276
|
+
|
|
272
277
|
return {
|
|
273
278
|
'/docs': {
|
|
274
|
-
origin
|
|
275
|
-
originAccessIdentity: this.originAccessIdentity,
|
|
276
|
-
originPath: '/docs',
|
|
277
|
-
}),
|
|
279
|
+
origin,
|
|
278
280
|
compress: true,
|
|
279
281
|
allowedMethods: this.allowedMethodsFromString(config.cloud.cdn?.allowedMethods),
|
|
280
282
|
cachedMethods: this.cachedMethodsFromString(config.cloud.cdn?.cachedMethods),
|
|
@@ -282,11 +284,9 @@ export class CdnStack {
|
|
|
282
284
|
cachePolicy: cloudfront.CachePolicy.CACHING_OPTIMIZED,
|
|
283
285
|
realtimeLogConfig: this.realtimeLogConfig,
|
|
284
286
|
},
|
|
287
|
+
|
|
285
288
|
'/docs/*': {
|
|
286
|
-
origin
|
|
287
|
-
originAccessIdentity: this.originAccessIdentity,
|
|
288
|
-
originPath: '/docs',
|
|
289
|
-
}),
|
|
289
|
+
origin,
|
|
290
290
|
compress: true,
|
|
291
291
|
allowedMethods: this.allowedMethodsFromString(config.cloud.cdn?.allowedMethods),
|
|
292
292
|
cachedMethods: this.cachedMethodsFromString(config.cloud.cdn?.cachedMethods),
|
|
@@ -372,7 +372,7 @@ export class CdnStack {
|
|
|
372
372
|
}
|
|
373
373
|
|
|
374
374
|
shouldDeployDocs() {
|
|
375
|
-
return hasFiles(p.projectPath('docs'))
|
|
375
|
+
return hasFiles(p.projectPath('docs')) && !config.app.docMode
|
|
376
376
|
}
|
|
377
377
|
|
|
378
378
|
additionalBehaviors(scope: Construct, props: CdnStackProps): Record<string, cloudfront.BehaviorOptions> {
|
|
@@ -406,9 +406,9 @@ export class CdnStack {
|
|
|
406
406
|
|
|
407
407
|
// if docMode is used, we don't need to add a behavior for the docs
|
|
408
408
|
// because the docs will be the root of the site
|
|
409
|
-
if (this.shouldDeployDocs()
|
|
409
|
+
if (this.shouldDeployDocs()) {
|
|
410
410
|
behaviorOptions = {
|
|
411
|
-
...this.docsBehaviorOptions(props),
|
|
411
|
+
...this.docsBehaviorOptions(props.docsBucket),
|
|
412
412
|
...behaviorOptions,
|
|
413
413
|
}
|
|
414
414
|
}
|
package/src/cloud/compute.ts
CHANGED
|
@@ -49,9 +49,14 @@ export class ComputeStack {
|
|
|
49
49
|
},
|
|
50
50
|
})
|
|
51
51
|
|
|
52
|
+
// const assetImage = new ecr_assets.DockerImageAsset(scope, 'DockerImageAsset', {
|
|
53
|
+
// directory: p.frameworkCloudPath(),
|
|
54
|
+
// })
|
|
55
|
+
|
|
52
56
|
const container = this.taskDefinition.addContainer('WebServerContainer', {
|
|
53
57
|
containerName: `${props.appName}-${props.appEnv}-api`,
|
|
54
|
-
image: ecs.ContainerImage.
|
|
58
|
+
// image: ecs.ContainerImage.fromDockerImageAsset(assetImage),
|
|
59
|
+
image: ecs.ContainerImage.fromAsset(p.frameworkCloudPath()),
|
|
55
60
|
logging: new ecs.AwsLogDriver({
|
|
56
61
|
streamPrefix: `${props.appName}-${props.appEnv}-web-server-logs`,
|
|
57
62
|
logGroup: new LogGroup(scope, 'StacksApiLogs', {
|
|
@@ -217,8 +222,12 @@ export class ComputeStack {
|
|
|
217
222
|
},
|
|
218
223
|
})
|
|
219
224
|
|
|
220
|
-
|
|
221
|
-
|
|
225
|
+
if (service.taskDefinition.executionRole) {
|
|
226
|
+
secrets.grantRead(service.taskDefinition.executionRole)
|
|
227
|
+
container.addEnvironment('SECRETS_ARN', secrets.secretArn)
|
|
228
|
+
} else {
|
|
229
|
+
throw new Error('Service task execution role is undefined.')
|
|
230
|
+
}
|
|
222
231
|
|
|
223
232
|
const apiPrefix = 'api'
|
|
224
233
|
new Output(scope, 'ApiUrl', {
|
package/src/cloud/deployment.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { config } from '@stacksjs/config'
|
|
2
|
-
import {
|
|
2
|
+
import { path as p } from '@stacksjs/path'
|
|
3
|
+
import { hasFiles } from '@stacksjs/storage'
|
|
4
|
+
import { docsSourceHash, websiteSourceHash } from '@stacksjs/utils'
|
|
3
5
|
import type { aws_cloudfront as cloudfront, aws_s3 as s3 } from 'aws-cdk-lib'
|
|
4
6
|
import { AssetHashType, aws_s3_deployment as s3deploy } from 'aws-cdk-lib'
|
|
5
7
|
import type { Construct } from 'constructs'
|
|
@@ -7,6 +9,7 @@ import type { NestedCloudProps } from '../types'
|
|
|
7
9
|
|
|
8
10
|
export interface DeploymentStackProps extends NestedCloudProps {
|
|
9
11
|
publicBucket: s3.Bucket
|
|
12
|
+
docsBucket?: s3.Bucket
|
|
10
13
|
privateBucket: s3.Bucket
|
|
11
14
|
cdn: cloudfront.Distribution
|
|
12
15
|
}
|
|
@@ -14,17 +17,17 @@ export interface DeploymentStackProps extends NestedCloudProps {
|
|
|
14
17
|
export class DeploymentStack {
|
|
15
18
|
privateSource: string
|
|
16
19
|
docsSource: string
|
|
17
|
-
|
|
20
|
+
publicSource: string
|
|
18
21
|
|
|
19
22
|
constructor(scope: Construct, props: DeploymentStackProps) {
|
|
20
23
|
// following paths are relative to where the command is run from
|
|
21
24
|
this.privateSource = '../../private'
|
|
22
25
|
this.docsSource = '../docs/dist/'
|
|
23
|
-
this.
|
|
26
|
+
this.publicSource = config.app.docMode === true ? this.docsSource : '../views/web/dist/'
|
|
24
27
|
|
|
25
28
|
new s3deploy.BucketDeployment(scope, 'Website', {
|
|
26
29
|
sources: [
|
|
27
|
-
s3deploy.Source.asset(this.
|
|
30
|
+
s3deploy.Source.asset(this.publicSource, {
|
|
28
31
|
assetHash: websiteSourceHash(),
|
|
29
32
|
assetHashType: AssetHashType.CUSTOM,
|
|
30
33
|
}),
|
|
@@ -34,9 +37,32 @@ export class DeploymentStack {
|
|
|
34
37
|
distributionPaths: ['/*'],
|
|
35
38
|
})
|
|
36
39
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
40
|
+
if (this.shouldDeployDocs()) {
|
|
41
|
+
// if docs should be deployed, add it to the deployment
|
|
42
|
+
new s3deploy.BucketDeployment(scope, 'Docs', {
|
|
43
|
+
sources: [
|
|
44
|
+
s3deploy.Source.asset(this.docsSource, {
|
|
45
|
+
assetHash: docsSourceHash(),
|
|
46
|
+
assetHashType: AssetHashType.CUSTOM,
|
|
47
|
+
}),
|
|
48
|
+
],
|
|
49
|
+
destinationBucket: props.docsBucket as s3.Bucket,
|
|
50
|
+
distribution: props.cdn,
|
|
51
|
+
distributionPaths: ['/docs/*'],
|
|
52
|
+
})
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (hasFiles(this.privateSource)) {
|
|
56
|
+
new s3deploy.BucketDeployment(scope, 'PrivateFiles', {
|
|
57
|
+
sources: [s3deploy.Source.asset(this.privateSource)],
|
|
58
|
+
destinationBucket: props.privateBucket,
|
|
59
|
+
})
|
|
60
|
+
} else {
|
|
61
|
+
console.error(`The path ${this.privateSource} does not have any files`)
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
shouldDeployDocs() {
|
|
66
|
+
return hasFiles(p.projectPath('docs')) && !config.app.docMode
|
|
41
67
|
}
|
|
42
68
|
}
|
package/src/cloud/docs.ts
CHANGED
|
@@ -16,7 +16,8 @@ export class DocsStack {
|
|
|
16
16
|
|
|
17
17
|
constructor(scope: Construct, props: DocsStackProps) {
|
|
18
18
|
// if docsPrefix is not set, then we know we are in docsMode and the documentation lives at the root of the domain
|
|
19
|
-
const docsPrefix =
|
|
19
|
+
const docsPrefix = 'docs'
|
|
20
|
+
// const docsPrefix = config.app.docMode ? '' : config.docs.base
|
|
20
21
|
|
|
21
22
|
// this edge function ensures pretty docs urls
|
|
22
23
|
// soon to be reused for our Meema features
|
package/src/cloud/index.ts
CHANGED
|
@@ -34,9 +34,9 @@ export class Cloud extends Stack {
|
|
|
34
34
|
permissions: PermissionsStack
|
|
35
35
|
ai: AiStack
|
|
36
36
|
cli: CliStack
|
|
37
|
-
api
|
|
37
|
+
api?: ComputeStack
|
|
38
38
|
cdn!: CdnStack
|
|
39
|
-
queue
|
|
39
|
+
queue?: QueueStack
|
|
40
40
|
deployment!: DeploymentStack
|
|
41
41
|
scope: Construct
|
|
42
42
|
props: CloudOptions
|
|
@@ -92,8 +92,9 @@ export class Cloud extends Stack {
|
|
|
92
92
|
// we use an async init() method here because we need to wait for the
|
|
93
93
|
|
|
94
94
|
async init() {
|
|
95
|
-
|
|
96
|
-
|
|
95
|
+
const props = this.props
|
|
96
|
+
|
|
97
|
+
if (this.shouldDeployApi()) {
|
|
97
98
|
this.api = new ComputeStack(this, {
|
|
98
99
|
...props,
|
|
99
100
|
vpc: this.network.vpc,
|
|
@@ -109,27 +110,33 @@ export class Cloud extends Stack {
|
|
|
109
110
|
})
|
|
110
111
|
|
|
111
112
|
await this.queue.init()
|
|
113
|
+
}
|
|
112
114
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
115
|
+
this.cdn = new CdnStack(this, {
|
|
116
|
+
...props,
|
|
117
|
+
publicBucket: this.storage.publicBucket,
|
|
118
|
+
docsBucket: this.storage.docsBucket,
|
|
119
|
+
logBucket: this.storage.logBucket,
|
|
120
|
+
certificate: this.security.certificate,
|
|
121
|
+
firewall: this.security.firewall,
|
|
122
|
+
originRequestFunction: this.docs.originRequestFunction,
|
|
123
|
+
zone: this.dns.zone,
|
|
124
|
+
cliSetupUrl: this.cli.cliSetupUrl,
|
|
125
|
+
askAiUrl: this.ai.askAiUrl,
|
|
126
|
+
summarizeAiUrl: this.ai.summarizeAiUrl,
|
|
127
|
+
lb: this.api?.lb,
|
|
128
|
+
})
|
|
126
129
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
}
|
|
130
|
+
this.deployment = new DeploymentStack(this, {
|
|
131
|
+
...props,
|
|
132
|
+
publicBucket: this.storage.publicBucket,
|
|
133
|
+
privateBucket: this.storage.privateBucket,
|
|
134
|
+
docsBucket: this.storage.docsBucket,
|
|
135
|
+
cdn: this.cdn.distribution,
|
|
136
|
+
})
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
shouldDeployApi() {
|
|
140
|
+
return config.cloud.api?.deploy
|
|
134
141
|
}
|
|
135
142
|
}
|
package/src/cloud/queue.ts
CHANGED
|
@@ -25,7 +25,7 @@ export class QueueStack {
|
|
|
25
25
|
async init() {
|
|
26
26
|
const jobsDir = path.jobsPath()
|
|
27
27
|
const actionsDir = path.appPath('Actions')
|
|
28
|
-
const ormActionDir = path.
|
|
28
|
+
const ormActionDir = path.builtUserActionsPath('src')
|
|
29
29
|
|
|
30
30
|
const jobFiles = await fs.readdir(jobsDir)
|
|
31
31
|
const actionFiles = await fs.readdir(actionsDir)
|
|
@@ -47,7 +47,7 @@ export class QueueStack {
|
|
|
47
47
|
for (const ormFile of ormActionFiles) {
|
|
48
48
|
if (!ormFile.endsWith('.ts')) continue
|
|
49
49
|
|
|
50
|
-
const ormActionPath = path.
|
|
50
|
+
const ormActionPath = path.builtUserActionsPath(ormFile)
|
|
51
51
|
|
|
52
52
|
// Await the loading of the job module
|
|
53
53
|
const ormAction = await this.loadModule(ormActionPath)
|
|
@@ -60,8 +60,6 @@ export class QueueStack {
|
|
|
60
60
|
|
|
61
61
|
const actionPath = path.appPath(`Actions/${file}`)
|
|
62
62
|
|
|
63
|
-
console.log(actionPath)
|
|
64
|
-
|
|
65
63
|
// Await the loading of the job module
|
|
66
64
|
const action = await this.loadModule(actionPath)
|
|
67
65
|
this.createQueueRule(action, file)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "stacks-router-layer",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.63.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"author": "",
|
|
6
6
|
"license": "MIT",
|
|
@@ -10,6 +10,6 @@
|
|
|
10
10
|
"test": "echo \"Error: no test specified\" && exit 1"
|
|
11
11
|
},
|
|
12
12
|
"dependencies": {
|
|
13
|
-
"@stacksjs/router": "^0.
|
|
13
|
+
"@stacksjs/router": "^0.62.0"
|
|
14
14
|
}
|
|
15
15
|
}
|
package/src/cloud/security.ts
CHANGED
|
@@ -69,9 +69,9 @@ export class SecurityStack {
|
|
|
69
69
|
name: 'CountryRule',
|
|
70
70
|
priority: priorities.length,
|
|
71
71
|
statement: {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
72
|
+
geoMatchStatement: {
|
|
73
|
+
countryCodes: config.security.firewall.countryCodes as string[],
|
|
74
|
+
},
|
|
75
75
|
},
|
|
76
76
|
action: {
|
|
77
77
|
block: {},
|
|
@@ -130,7 +130,7 @@ export class SecurityStack {
|
|
|
130
130
|
searchString: 'true',
|
|
131
131
|
textTransformations: [
|
|
132
132
|
{
|
|
133
|
-
priority:
|
|
133
|
+
priority: 0,
|
|
134
134
|
type: 'NONE',
|
|
135
135
|
},
|
|
136
136
|
],
|
package/src/cloud/storage.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { path as p } from '@stacksjs/path'
|
|
2
|
+
import { hasFiles } from '@stacksjs/storage'
|
|
1
3
|
import type { aws_kms as kms } from 'aws-cdk-lib'
|
|
2
4
|
import { RemovalPolicy, Tags, aws_backup as backup, aws_iam as iam, aws_s3 as s3 } from 'aws-cdk-lib'
|
|
3
5
|
import type { Construct } from 'constructs'
|
|
@@ -10,6 +12,7 @@ export interface StorageStackProps extends NestedCloudProps {
|
|
|
10
12
|
export class StorageStack {
|
|
11
13
|
publicBucket: s3.Bucket
|
|
12
14
|
privateBucket: s3.Bucket
|
|
15
|
+
docsBucket?: s3.Bucket
|
|
13
16
|
logBucket: s3.Bucket
|
|
14
17
|
bucketPrefix: string
|
|
15
18
|
vault: backup.BackupVault
|
|
@@ -29,6 +32,18 @@ export class StorageStack {
|
|
|
29
32
|
|
|
30
33
|
Tags.of(this.publicBucket).add('daily-backup', 'true')
|
|
31
34
|
|
|
35
|
+
if (this.shouldDeployDocs()) {
|
|
36
|
+
this.docsBucket = new s3.Bucket(scope, 'DocsBucket', {
|
|
37
|
+
bucketName: `${this.bucketPrefix}-docs-${props.timestamp}`,
|
|
38
|
+
versioned: true,
|
|
39
|
+
autoDeleteObjects: true,
|
|
40
|
+
removalPolicy: RemovalPolicy.DESTROY,
|
|
41
|
+
encryption: s3.BucketEncryption.S3_MANAGED,
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
Tags.of(this.docsBucket).add('weekly-backup', 'true')
|
|
45
|
+
}
|
|
46
|
+
|
|
32
47
|
this.privateBucket = new s3.Bucket(scope, 'PrivateBucket', {
|
|
33
48
|
bucketName: `${this.bucketPrefix}-private-${props.timestamp}`,
|
|
34
49
|
versioned: true,
|
|
@@ -165,4 +180,8 @@ export class StorageStack {
|
|
|
165
180
|
|
|
166
181
|
return backupRole
|
|
167
182
|
}
|
|
183
|
+
|
|
184
|
+
shouldDeployDocs() {
|
|
185
|
+
return hasFiles(p.projectPath('docs')) || config.app.docMode
|
|
186
|
+
}
|
|
168
187
|
}
|
package/src/helpers.ts
CHANGED
|
@@ -160,7 +160,7 @@ export async function getJumpBoxInstanceId(name?: string) {
|
|
|
160
160
|
],
|
|
161
161
|
})
|
|
162
162
|
|
|
163
|
-
if (data.Reservations?.[0]
|
|
163
|
+
if (data.Reservations?.[0]?.Instances?.[0]) return data.Reservations[0].Instances[0].InstanceId
|
|
164
164
|
|
|
165
165
|
return undefined
|
|
166
166
|
}
|
|
@@ -537,7 +537,7 @@ export async function getJumpBoxSecurityGroupName() {
|
|
|
537
537
|
const ec2 = new EC2({ region: 'us-east-1' })
|
|
538
538
|
const data = await ec2.describeInstances({ InstanceIds: [jumpBoxId] })
|
|
539
539
|
|
|
540
|
-
if (data.Reservations?.[0]
|
|
540
|
+
if (data.Reservations?.[0]?.Instances?.[0]) {
|
|
541
541
|
const instance = data.Reservations[0].Instances[0]
|
|
542
542
|
const securityGroups = instance.SecurityGroups
|
|
543
543
|
|
|
@@ -551,7 +551,7 @@ export async function getSecurityGroupFromInstanceId(instanceId: string) {
|
|
|
551
551
|
const ec2 = new EC2({ region: 'us-east-1' })
|
|
552
552
|
const data = await ec2.describeInstances({ InstanceIds: [instanceId] })
|
|
553
553
|
|
|
554
|
-
if (data.Reservations?.[0]
|
|
554
|
+
if (data.Reservations?.[0]?.Instances?.[0]) {
|
|
555
555
|
const instance = data.Reservations[0].Instances[0]
|
|
556
556
|
const securityGroups = instance.SecurityGroups
|
|
557
557
|
|
|
@@ -606,6 +606,12 @@ export async function getOrCreateTimestamp(): Promise<string> {
|
|
|
606
606
|
}
|
|
607
607
|
}
|
|
608
608
|
|
|
609
|
+
// get the CloudFront distribution ID of the current stack
|
|
610
|
+
export async function getCloudFrontDistributionId(): Promise<string> {
|
|
611
|
+
return ''
|
|
612
|
+
// return await runCommand(`aws cloudfront list-distributions --query "DistributionList.Items[?Origins.Items[0].DomainName=='${config.app.url}'].Id"`)
|
|
613
|
+
}
|
|
614
|
+
|
|
609
615
|
// function isProductionEnv(env: string) {
|
|
610
616
|
// return env === 'production' || env === 'prod'
|
|
611
617
|
// }
|
|
@@ -622,5 +628,5 @@ export async function getOrCreateTimestamp(): Promise<string> {
|
|
|
622
628
|
// catch (error) {
|
|
623
629
|
// console.error('Error fetching buckets', error)
|
|
624
630
|
// return `${prefix}-${timestamp}`
|
|
625
|
-
//
|
|
631
|
+
// }
|
|
626
632
|
// }
|