@percepta/create 3.6.2 → 4.0.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 +37 -6
- package/dist/{git-ops-C2CIjuce.js → git-ops-BD7JNnal.js} +1 -1
- package/dist/{git-ops-C2CIjuce.js.map → git-ops-BD7JNnal.js.map} +1 -1
- package/dist/github-RCIMUq70.js +131 -0
- package/dist/github-RCIMUq70.js.map +1 -0
- package/dist/index.js +68 -125
- package/dist/index.js.map +1 -1
- package/dist/{init-sI9aIrkU.js → init-COp0nGdk.js} +4 -2
- package/dist/{init-sI9aIrkU.js.map → init-COp0nGdk.js.map} +1 -1
- package/dist/manifest-CqIDnbgs.js +58 -0
- package/dist/manifest-CqIDnbgs.js.map +1 -0
- package/dist/register-app-C7ZBpAaZ.js +103 -0
- package/dist/register-app-C7ZBpAaZ.js.map +1 -0
- package/dist/register-os-blueprint-DGjBUZYa.js +90 -0
- package/dist/register-os-blueprint-DGjBUZYa.js.map +1 -0
- package/dist/{status-CKe4aKso.js → status-BXYaQ4a2.js} +3 -3
- package/dist/{status-CKe4aKso.js.map → status-BXYaQ4a2.js.map} +1 -1
- package/dist/{sync-D1vkoofl.js → sync-BayU4w1j.js} +3 -3
- package/dist/{sync-D1vkoofl.js.map → sync-BayU4w1j.js.map} +1 -1
- package/dist/template-versions-CEIP9vhl.js +35 -0
- package/dist/template-versions-CEIP9vhl.js.map +1 -0
- package/dist/{upstream-gUHLWSR1.js → upstream-CZEzLrS4.js} +3 -3
- package/dist/{upstream-gUHLWSR1.js.map → upstream-CZEzLrS4.js.map} +1 -1
- package/dist/validate-dssldJAj.js +14 -0
- package/dist/validate-dssldJAj.js.map +1 -0
- package/package.json +1 -1
- package/template-versions.json +2 -2
- package/templates/infra/os.blueprint.yaml.template +138 -0
- package/templates/library/README.md +5 -2
- package/templates/library/gitignore.template +1 -0
- package/templates/library/package.json.template +17 -13
- package/templates/library/src/index.test.ts +8 -0
- package/templates/library/tsconfig.json +1 -17
- package/templates/library/tsdown.config.ts +3 -0
- package/templates/library/vitest.config.ts +3 -0
- package/templates/monorepo/.dockerignore +1 -0
- package/templates/monorepo/.github/CODEOWNERS +67 -0
- package/templates/monorepo/.github/actions/ci/action.yml +56 -0
- package/templates/monorepo/.github/workflows/build-and-publish.yml +22 -0
- package/templates/monorepo/.github/workflows/pr-build.yml +21 -0
- package/templates/monorepo/.node-version +1 -0
- package/templates/monorepo/README.md +41 -3
- package/templates/monorepo/auth/README.md +6 -3
- package/templates/monorepo/auth/package.json +5 -7
- package/templates/monorepo/auth/src/auth.ts +0 -1
- package/templates/monorepo/auth/src/config/database.ts +1 -1
- package/templates/monorepo/auth/tsconfig.json +1 -10
- package/templates/{webapp → monorepo}/docker-compose.yml +2 -2
- package/templates/monorepo/gitignore.template +1 -0
- package/templates/monorepo/oxfmt.config.ts.template +3 -0
- package/templates/monorepo/oxlint.config.ts.template +3 -0
- package/templates/monorepo/package.json.template +22 -11
- package/templates/monorepo/scripts/setup-local-databases.mjs +183 -0
- package/templates/monorepo/turbo.json +20 -0
- package/templates/webapp/.node-version +0 -1
- package/templates/webapp/AGENTS.md +33 -35
- package/templates/webapp/README.md +34 -38
- package/templates/webapp/agent-skills/database.md +21 -21
- package/templates/webapp/agent-skills/langfuse.md +7 -7
- package/templates/webapp/agent-skills/llm.md +4 -2
- package/templates/webapp/agent-skills/oneshot.md +7 -6
- package/templates/webapp/agent-skills/ryvn.md +12 -16
- package/templates/webapp/deploy/README.md +10 -51
- package/templates/webapp/drizzle.config.ts +2 -23
- package/templates/webapp/env.example.template +8 -14
- package/templates/webapp/globals.d.ts +1 -0
- package/templates/webapp/oxfmt.config.ts.template +5 -0
- package/templates/webapp/package.json.template +18 -33
- package/templates/webapp/scripts/seed.ts +1 -1
- package/templates/webapp/scripts/start.sh +12 -16
- package/templates/webapp/src/app/global-error.tsx +1 -1
- package/templates/webapp/src/config/getEnvConfig.ts +4 -10
- package/templates/webapp/src/config/isDev.ts +0 -2
- package/templates/webapp/src/drizzle/db.ts +6 -21
- package/templates/webapp/src/lib/auth-client.ts +6 -3
- package/templates/webapp/src/startup-checks.ts +28 -7
- package/templates/webapp/tsconfig.json +1 -12
- package/templates/webapp/vitest.config.ts +3 -7
- package/templates/library/eslint.config.js +0 -10
- package/templates/monorepo/auth/scripts/setup-database.ts +0 -11
- package/templates/monorepo/eslint.config.js +0 -10
- package/templates/monorepo/tsconfig.json +0 -16
- package/templates/webapp/.github/workflows/__APP_NAME__-terraform-ryvn-release.yaml +0 -92
- package/templates/webapp/.github/workflows/ci.yml +0 -149
- package/templates/webapp/.prettierrc.mjs +0 -5
- package/templates/webapp/agent-skills/deploy.md +0 -92
- package/templates/webapp/deploy/ryvn/__APP_NAME__-terraform.service.yaml +0 -10
- package/templates/webapp/deploy/ryvn/environments/percepta-test/installations/__APP_NAME__-terraform.env.percepta-test.serviceinstallation.yaml +0 -11
- package/templates/webapp/deploy/ryvn/environments/percepta-test/installations/__APP_NAME__.env.percepta-test.serviceinstallation.yaml +0 -154
- package/templates/webapp/eslint.config.mjs +0 -100
- package/templates/webapp/npmrc.template +0 -4
- package/templates/webapp/terraform/README.md +0 -147
- package/templates/webapp/terraform/deploy.sh +0 -97
- package/templates/webapp/terraform/main.tf +0 -101
- package/templates/webapp/terraform/modules/cloudtrail/main.tf +0 -27
- package/templates/webapp/terraform/modules/cloudtrail/outputs.tf +0 -10
- package/templates/webapp/terraform/modules/cloudtrail/variables.tf +0 -15
- package/templates/webapp/terraform/modules/networking/main.tf +0 -118
- package/templates/webapp/terraform/modules/networking/outputs.tf +0 -38
- package/templates/webapp/terraform/modules/networking/variables.tf +0 -24
- package/templates/webapp/terraform/modules/rds/main.tf +0 -227
- package/templates/webapp/terraform/modules/rds/outputs.tf +0 -73
- package/templates/webapp/terraform/modules/rds/variables.tf +0 -61
- package/templates/webapp/terraform/modules/s3-logging/main.tf +0 -148
- package/templates/webapp/terraform/modules/s3-logging/outputs.tf +0 -10
- package/templates/webapp/terraform/modules/s3-logging/variables.tf +0 -16
- package/templates/webapp/terraform/modules/secrets/main.tf +0 -39
- package/templates/webapp/terraform/modules/secrets/outputs.tf +0 -9
- package/templates/webapp/terraform/modules/secrets/variables.tf +0 -51
- package/templates/webapp/terraform/outputs.tf +0 -102
- package/templates/webapp/terraform/providers.tf +0 -32
- package/templates/webapp/terraform/schema/main.tf +0 -4
- package/templates/webapp/terraform/schema/outputs.tf +0 -9
- package/templates/webapp/terraform/schema/variables.tf +0 -19
- package/templates/webapp/terraform/schema/versions.tf +0 -38
- package/templates/webapp/terraform/terraform.tfvars.example +0 -65
- package/templates/webapp/terraform/variables.tf +0 -129
|
@@ -1,227 +0,0 @@
|
|
|
1
|
-
data "aws_region" "current" {}
|
|
2
|
-
|
|
3
|
-
data "http" "rds_ca" {
|
|
4
|
-
url = "https://truststore.pki.rds.amazonaws.com/${data.aws_region.current.name}/${data.aws_region.current.name}-bundle.pem"
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
data "aws_vpc" "vpc" {
|
|
8
|
-
id = var.vpc_id
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
data "aws_subnet" "subnet" {
|
|
12
|
-
count = length(var.subnet_ids)
|
|
13
|
-
id = var.subnet_ids[count.index]
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
# Check if existing cluster exists
|
|
17
|
-
data "aws_rds_cluster" "existing" {
|
|
18
|
-
count = var.existing_cluster_name != null ? 1 : 0
|
|
19
|
-
cluster_identifier = var.existing_cluster_name
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
resource "random_pet" "name" {
|
|
23
|
-
count = var.create_new_cluster && var.existing_cluster_name == null ? 1 : 0
|
|
24
|
-
length = 2
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
resource "random_password" "master_password" {
|
|
28
|
-
count = var.create_new_cluster && var.existing_cluster_name == null ? 1 : 0
|
|
29
|
-
length = 16
|
|
30
|
-
special = true
|
|
31
|
-
override_special = "_!%^"
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
locals {
|
|
36
|
-
cluster_name = var.existing_cluster_name != null ? var.existing_cluster_name : (var.create_new_cluster ? "${var.name}-${random_pet.name[0].id}" : null)
|
|
37
|
-
|
|
38
|
-
# Use existing cluster details if available, otherwise use new cluster details
|
|
39
|
-
cluster_endpoint = var.existing_cluster_name != null ? data.aws_rds_cluster.existing[0].endpoint : (var.create_new_cluster ? aws_rds_cluster.rds[0].endpoint : null)
|
|
40
|
-
cluster_port = var.existing_cluster_name != null ? data.aws_rds_cluster.existing[0].port : (var.create_new_cluster ? aws_rds_cluster.rds[0].port : null)
|
|
41
|
-
master_username = var.existing_cluster_name != null ? data.aws_rds_cluster.existing[0].master_username : (var.create_new_cluster ? aws_rds_cluster.rds[0].master_username : null)
|
|
42
|
-
master_password = var.existing_cluster_name != null ? null : (var.create_new_cluster ? random_password.master_password[0].result : null)
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
# Security group for new RDS cluster
|
|
46
|
-
resource "aws_security_group" "security_group" {
|
|
47
|
-
count = var.create_new_cluster && var.existing_cluster_name == null ? 1 : 0
|
|
48
|
-
name = "rds-__APP_NAME__-${random_pet.name[0].id}"
|
|
49
|
-
description = "Security group for __APP_NAME_UPPER__ RDS ${random_pet.name[0].id}"
|
|
50
|
-
vpc_id = data.aws_vpc.vpc.id
|
|
51
|
-
|
|
52
|
-
ingress {
|
|
53
|
-
description = "Allow Postgres from VPC"
|
|
54
|
-
from_port = var.port
|
|
55
|
-
to_port = var.port
|
|
56
|
-
protocol = "tcp"
|
|
57
|
-
cidr_blocks = [data.aws_vpc.vpc.cidr_block]
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
egress {
|
|
61
|
-
from_port = 0
|
|
62
|
-
to_port = 0
|
|
63
|
-
protocol = "-1"
|
|
64
|
-
cidr_blocks = ["0.0.0.0/0"]
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
# Subnet group for new RDS cluster
|
|
69
|
-
resource "aws_db_subnet_group" "subnet_group" {
|
|
70
|
-
count = var.create_new_cluster && var.existing_cluster_name == null ? 1 : 0
|
|
71
|
-
name = "rds-__APP_NAME__-${random_pet.name[0].id}"
|
|
72
|
-
description = "Subnet group for __APP_NAME_UPPER__ RDS ${random_pet.name[0].id}"
|
|
73
|
-
subnet_ids = var.subnet_ids
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
# New RDS cluster
|
|
77
|
-
resource "aws_rds_cluster" "rds" {
|
|
78
|
-
count = var.create_new_cluster && var.existing_cluster_name == null ? 1 : 0
|
|
79
|
-
cluster_identifier = local.cluster_name
|
|
80
|
-
engine = "aurora-postgresql"
|
|
81
|
-
engine_mode = "provisioned"
|
|
82
|
-
engine_version = var.engine_version
|
|
83
|
-
vpc_security_group_ids = [aws_security_group.security_group[0].id]
|
|
84
|
-
db_subnet_group_name = aws_db_subnet_group.subnet_group[0].name
|
|
85
|
-
availability_zones = slice(data.aws_subnet.subnet[*].availability_zone, 0, min(3, length(data.aws_subnet.subnet)))
|
|
86
|
-
database_name = "__DB_NAME__"
|
|
87
|
-
port = var.port
|
|
88
|
-
master_username = "__APP_NAME_SNAKE___admin"
|
|
89
|
-
master_password = random_password.master_password[0].result
|
|
90
|
-
storage_encrypted = true
|
|
91
|
-
backup_retention_period = 5
|
|
92
|
-
preferred_backup_window = "07:00-09:00"
|
|
93
|
-
|
|
94
|
-
skip_final_snapshot = true
|
|
95
|
-
enable_http_endpoint = true
|
|
96
|
-
|
|
97
|
-
serverlessv2_scaling_configuration {
|
|
98
|
-
max_capacity = 1.0
|
|
99
|
-
min_capacity = 0.0
|
|
100
|
-
seconds_until_auto_pause = 3600
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
# RDS cluster instance for new cluster
|
|
105
|
-
resource "aws_rds_cluster_instance" "instance" {
|
|
106
|
-
count = var.create_new_cluster && var.existing_cluster_name == null ? 1 : 0
|
|
107
|
-
identifier = "${local.cluster_name}-instance-${count.index}"
|
|
108
|
-
cluster_identifier = aws_rds_cluster.rds[0].id
|
|
109
|
-
instance_class = var.instance_class
|
|
110
|
-
engine = aws_rds_cluster.rds[0].engine
|
|
111
|
-
engine_version = aws_rds_cluster.rds[0].engine_version
|
|
112
|
-
publicly_accessible = false
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
# Store master password in AWS Secrets Manager for new cluster
|
|
116
|
-
resource "aws_secretsmanager_secret" "master_password" {
|
|
117
|
-
count = var.create_new_cluster && var.existing_cluster_name == null ? 1 : 0
|
|
118
|
-
name_prefix = "rds-__APP_NAME__-master-password-${random_pet.name[0].id}-"
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
resource "aws_secretsmanager_secret_version" "master_password" {
|
|
122
|
-
count = var.create_new_cluster && var.existing_cluster_name == null ? 1 : 0
|
|
123
|
-
secret_id = aws_secretsmanager_secret.master_password[0].id
|
|
124
|
-
secret_string = random_password.master_password[0].result
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
################################################################################
|
|
128
|
-
# EDW Readonly User Resources
|
|
129
|
-
################################################################################
|
|
130
|
-
|
|
131
|
-
# Generate secure password for readonly user
|
|
132
|
-
resource "random_password" "readonly_user_password" {
|
|
133
|
-
length = 32
|
|
134
|
-
special = true
|
|
135
|
-
# Use PostgreSQL-safe special characters
|
|
136
|
-
override_special = "!#$%&*()-_=+[]{}<>:?"
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
# Store readonly user credentials in Secrets Manager
|
|
140
|
-
resource "aws_secretsmanager_secret" "readonly_user_credentials" {
|
|
141
|
-
name_prefix = "rds-__APP_NAME__-readonly-${var.name}-${var.environment}-"
|
|
142
|
-
description = "Readonly database credentials for EDW access to __APP_NAME_UPPER__ database"
|
|
143
|
-
|
|
144
|
-
tags = {
|
|
145
|
-
Name = "__APP_NAME__-readonly-credentials"
|
|
146
|
-
Environment = var.environment
|
|
147
|
-
Purpose = "EDW"
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
resource "aws_secretsmanager_secret_version" "readonly_user_credentials" {
|
|
152
|
-
secret_id = aws_secretsmanager_secret.readonly_user_credentials.id
|
|
153
|
-
secret_string = jsonencode({
|
|
154
|
-
username = "__APP_NAME_SNAKE___readonly"
|
|
155
|
-
password = random_password.readonly_user_password.result
|
|
156
|
-
host = local.cluster_endpoint
|
|
157
|
-
port = local.cluster_port
|
|
158
|
-
database = "__DB_NAME__"
|
|
159
|
-
engine = "postgres"
|
|
160
|
-
})
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
# Cross-account IAM role for EDW to assume
|
|
164
|
-
resource "aws_iam_role" "edw_secret_reader_role" {
|
|
165
|
-
count = length(var.edw_allowed_principals) > 0 ? 1 : 0
|
|
166
|
-
name = "__APP_NAME_UPPER__-EDW-SecretReader-${var.name}-${var.environment}"
|
|
167
|
-
|
|
168
|
-
assume_role_policy = jsonencode({
|
|
169
|
-
Version = "2012-10-17"
|
|
170
|
-
Statement = [
|
|
171
|
-
{
|
|
172
|
-
Effect = "Allow"
|
|
173
|
-
Principal = {
|
|
174
|
-
AWS = var.edw_allowed_principals
|
|
175
|
-
}
|
|
176
|
-
Action = "sts:AssumeRole"
|
|
177
|
-
}
|
|
178
|
-
]
|
|
179
|
-
})
|
|
180
|
-
|
|
181
|
-
tags = {
|
|
182
|
-
Name = "__APP_NAME__-edw-secret-reader"
|
|
183
|
-
Environment = var.environment
|
|
184
|
-
Purpose = "EDW"
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
# IAM policy to allow reading the readonly credentials secret
|
|
189
|
-
resource "aws_iam_policy" "edw_secret_reader_policy" {
|
|
190
|
-
count = length(var.edw_allowed_principals) > 0 ? 1 : 0
|
|
191
|
-
name = "__APP_NAME_UPPER__-EDW-SecretReader-Policy-${var.name}-${var.environment}"
|
|
192
|
-
description = "Allows EDW to read __APP_NAME_UPPER__ readonly database credentials from Secrets Manager"
|
|
193
|
-
|
|
194
|
-
policy = jsonencode({
|
|
195
|
-
Version = "2012-10-17"
|
|
196
|
-
Statement = [
|
|
197
|
-
{
|
|
198
|
-
Effect = "Allow"
|
|
199
|
-
Action = [
|
|
200
|
-
"secretsmanager:GetSecretValue",
|
|
201
|
-
"secretsmanager:DescribeSecret"
|
|
202
|
-
]
|
|
203
|
-
Resource = aws_secretsmanager_secret.readonly_user_credentials.arn
|
|
204
|
-
}
|
|
205
|
-
]
|
|
206
|
-
})
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
resource "aws_iam_role_policy_attachment" "edw_secret_reader_attach" {
|
|
210
|
-
count = length(var.edw_allowed_principals) > 0 ? 1 : 0
|
|
211
|
-
role = aws_iam_role.edw_secret_reader_role[0].name
|
|
212
|
-
policy_arn = aws_iam_policy.edw_secret_reader_policy[0].arn
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
# Add ingress rule to security group for EDW VPC CIDR blocks
|
|
216
|
-
resource "aws_security_group_rule" "edw_ingress" {
|
|
217
|
-
count = var.create_new_cluster && var.existing_cluster_name == null && length(var.edw_vpc_cidr_blocks) > 0 ? 1 : 0
|
|
218
|
-
type = "ingress"
|
|
219
|
-
description = "Allow Postgres from EDW VPC via VPC peering"
|
|
220
|
-
from_port = var.port
|
|
221
|
-
to_port = var.port
|
|
222
|
-
protocol = "tcp"
|
|
223
|
-
cidr_blocks = var.edw_vpc_cidr_blocks
|
|
224
|
-
security_group_id = aws_security_group.security_group[0].id
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
output "host" {
|
|
2
|
-
description = "RDS cluster endpoint"
|
|
3
|
-
value = local.cluster_endpoint
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
output "port" {
|
|
7
|
-
description = "RDS cluster port"
|
|
8
|
-
value = local.cluster_port
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
output "database_name" {
|
|
12
|
-
description = "Database name"
|
|
13
|
-
value = "__DB_NAME__"
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
output "username" {
|
|
17
|
-
description = "Database username (master user)"
|
|
18
|
-
value = local.master_username
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
output "password" {
|
|
22
|
-
description = "Database password (master user)"
|
|
23
|
-
value = local.master_password
|
|
24
|
-
sensitive = true
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
output "ssl_cert" {
|
|
28
|
-
description = "RDS CA certificate"
|
|
29
|
-
value = data.http.rds_ca.response_body
|
|
30
|
-
sensitive = true
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
output "connection_url" {
|
|
34
|
-
description = "PostgreSQL connection URL"
|
|
35
|
-
value = "postgresql://${local.master_username}:${local.master_password}@${local.cluster_endpoint}:${local.cluster_port}/__DB_NAME__"
|
|
36
|
-
sensitive = true
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
output "cluster_name" {
|
|
40
|
-
description = "RDS cluster name"
|
|
41
|
-
value = local.cluster_name
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
output "master_username" {
|
|
45
|
-
description = "RDS master username (for new clusters only)"
|
|
46
|
-
value = local.master_username
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
output "master_password" {
|
|
50
|
-
description = "RDS master password (for new clusters only)"
|
|
51
|
-
value = local.master_password
|
|
52
|
-
sensitive = true
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
output "readonly_username" {
|
|
56
|
-
description = "Readonly database username for EDW access"
|
|
57
|
-
value = "__APP_NAME_SNAKE___readonly"
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
output "readonly_user_secret_arn" {
|
|
61
|
-
description = "ARN of the Secrets Manager secret containing readonly user credentials"
|
|
62
|
-
value = aws_secretsmanager_secret.readonly_user_credentials.arn
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
output "readonly_user_secret_name" {
|
|
66
|
-
description = "Name of the Secrets Manager secret containing readonly user credentials"
|
|
67
|
-
value = aws_secretsmanager_secret.readonly_user_credentials.name
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
output "readonly_user_secret_reader_role_arn" {
|
|
71
|
-
description = "ARN of the IAM role that EDW can assume to read the readonly credentials secret"
|
|
72
|
-
value = length(var.edw_allowed_principals) > 0 ? aws_iam_role.edw_secret_reader_role[0].arn : null
|
|
73
|
-
}
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
variable "name" {
|
|
2
|
-
description = "Base name for resources"
|
|
3
|
-
type = string
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
variable "environment" {
|
|
7
|
-
description = "Environment name (e.g. dev, staging, prod)"
|
|
8
|
-
type = string
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
variable "existing_cluster_name" {
|
|
12
|
-
description = "Name of existing RDS cluster to use (optional)"
|
|
13
|
-
type = string
|
|
14
|
-
default = null
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
variable "create_new_cluster" {
|
|
18
|
-
description = "Whether to create a new RDS cluster if existing_cluster_name is not provided"
|
|
19
|
-
type = bool
|
|
20
|
-
default = true
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
variable "vpc_id" {
|
|
24
|
-
description = "VPC ID where resources will be deployed"
|
|
25
|
-
type = string
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
variable "subnet_ids" {
|
|
29
|
-
description = "List of subnet IDs for RDS"
|
|
30
|
-
type = list(string)
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
variable "engine_version" {
|
|
34
|
-
description = "PostgreSQL engine version"
|
|
35
|
-
type = string
|
|
36
|
-
default = "16.8"
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
variable "port" {
|
|
40
|
-
description = "Port for RDS"
|
|
41
|
-
type = number
|
|
42
|
-
default = 5432
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
variable "instance_class" {
|
|
46
|
-
description = "RDS instance class"
|
|
47
|
-
type = string
|
|
48
|
-
default = "db.serverless"
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
variable "edw_allowed_principals" {
|
|
52
|
-
description = "List of IAM principal ARNs allowed to assume the EDW secret reader role"
|
|
53
|
-
type = list(string)
|
|
54
|
-
default = []
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
variable "edw_vpc_cidr_blocks" {
|
|
58
|
-
description = "List of CIDR blocks from EDW VPC to allow database access via VPC peering"
|
|
59
|
-
type = list(string)
|
|
60
|
-
default = []
|
|
61
|
-
}
|
|
@@ -1,148 +0,0 @@
|
|
|
1
|
-
data "aws_caller_identity" "current" {}
|
|
2
|
-
|
|
3
|
-
resource "random_string" "suffix" {
|
|
4
|
-
length = 8
|
|
5
|
-
special = false
|
|
6
|
-
upper = false
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
################################################################################
|
|
10
|
-
# S3 Bucket for Access Logs
|
|
11
|
-
################################################################################
|
|
12
|
-
|
|
13
|
-
resource "aws_s3_bucket" "logs" {
|
|
14
|
-
bucket = "${var.name}-logs-${random_string.suffix.result}"
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
resource "aws_s3_bucket_public_access_block" "logs" {
|
|
18
|
-
bucket = aws_s3_bucket.logs.id
|
|
19
|
-
block_public_acls = true
|
|
20
|
-
block_public_policy = true
|
|
21
|
-
ignore_public_acls = true
|
|
22
|
-
restrict_public_buckets = true
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
resource "aws_s3_bucket_ownership_controls" "logs" {
|
|
26
|
-
bucket = aws_s3_bucket.logs.id
|
|
27
|
-
rule {
|
|
28
|
-
object_ownership = "BucketOwnerPreferred"
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
resource "aws_s3_bucket_versioning" "logs" {
|
|
33
|
-
bucket = aws_s3_bucket.logs.id
|
|
34
|
-
versioning_configuration {
|
|
35
|
-
status = "Enabled"
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
resource "aws_s3_bucket_acl" "logs" {
|
|
40
|
-
depends_on = [aws_s3_bucket_ownership_controls.logs]
|
|
41
|
-
bucket = aws_s3_bucket.logs.id
|
|
42
|
-
acl = "private"
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
resource "aws_s3_bucket_server_side_encryption_configuration" "logs" {
|
|
46
|
-
bucket = aws_s3_bucket.logs.id
|
|
47
|
-
|
|
48
|
-
rule {
|
|
49
|
-
apply_server_side_encryption_by_default {
|
|
50
|
-
sse_algorithm = "AES256"
|
|
51
|
-
}
|
|
52
|
-
bucket_key_enabled = true
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
resource "aws_s3_bucket_lifecycle_configuration" "logs" {
|
|
57
|
-
count = var.s3_expiration_days != null ? 1 : 0
|
|
58
|
-
bucket = aws_s3_bucket.logs.bucket
|
|
59
|
-
|
|
60
|
-
rule {
|
|
61
|
-
id = "expire-objects"
|
|
62
|
-
status = "Enabled"
|
|
63
|
-
filter {
|
|
64
|
-
prefix = ""
|
|
65
|
-
}
|
|
66
|
-
expiration {
|
|
67
|
-
days = var.s3_expiration_days
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
# Bucket policy to allow S3 and CloudTrail services to write logs
|
|
73
|
-
resource "aws_s3_bucket_policy" "logs" {
|
|
74
|
-
bucket = aws_s3_bucket.logs.bucket
|
|
75
|
-
policy = jsonencode({
|
|
76
|
-
Version = "2012-10-17"
|
|
77
|
-
Statement = [
|
|
78
|
-
{
|
|
79
|
-
Sid = "AWSCloudTrailAclCheck"
|
|
80
|
-
Effect = "Allow"
|
|
81
|
-
Principal = {
|
|
82
|
-
Service = "cloudtrail.amazonaws.com"
|
|
83
|
-
}
|
|
84
|
-
Action = "s3:GetBucketAcl"
|
|
85
|
-
Resource = aws_s3_bucket.logs.arn
|
|
86
|
-
Condition = {
|
|
87
|
-
StringEquals = {
|
|
88
|
-
"aws:SourceAccount" = data.aws_caller_identity.current.account_id
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
},
|
|
92
|
-
{
|
|
93
|
-
Sid = "AWSCloudTrailWrite"
|
|
94
|
-
Effect = "Allow"
|
|
95
|
-
Principal = {
|
|
96
|
-
Service = "cloudtrail.amazonaws.com"
|
|
97
|
-
}
|
|
98
|
-
Action = "s3:PutObject"
|
|
99
|
-
Resource = "${aws_s3_bucket.logs.arn}/cloudtrail/*"
|
|
100
|
-
Condition = {
|
|
101
|
-
StringEquals = {
|
|
102
|
-
"s3:x-amz-acl" = "bucket-owner-full-control"
|
|
103
|
-
"aws:SourceAccount" = data.aws_caller_identity.current.account_id
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
},
|
|
107
|
-
{
|
|
108
|
-
Sid = "AllowS3LogDeliveryAcl"
|
|
109
|
-
Effect = "Allow"
|
|
110
|
-
Principal = {
|
|
111
|
-
Service = "s3.amazonaws.com"
|
|
112
|
-
}
|
|
113
|
-
Action = [
|
|
114
|
-
"s3:GetBucketAcl",
|
|
115
|
-
"s3:GetBucketLocation"
|
|
116
|
-
]
|
|
117
|
-
Resource = aws_s3_bucket.logs.arn
|
|
118
|
-
},
|
|
119
|
-
{
|
|
120
|
-
Sid = "AllowS3LogDeliveryPut"
|
|
121
|
-
Effect = "Allow"
|
|
122
|
-
Principal = {
|
|
123
|
-
Service = "s3.amazonaws.com"
|
|
124
|
-
}
|
|
125
|
-
Action = "s3:PutObject"
|
|
126
|
-
Resource = "${aws_s3_bucket.logs.arn}/*"
|
|
127
|
-
Condition = {
|
|
128
|
-
StringEquals = {
|
|
129
|
-
"s3:x-amz-acl" = "bucket-owner-full-control"
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
},
|
|
133
|
-
{
|
|
134
|
-
Sid = "DenyUnEncryptedObjectUploads"
|
|
135
|
-
Effect = "Deny"
|
|
136
|
-
Principal = "*"
|
|
137
|
-
Action = "s3:*"
|
|
138
|
-
Resource = "${aws_s3_bucket.logs.arn}/*"
|
|
139
|
-
Condition = {
|
|
140
|
-
Bool = {
|
|
141
|
-
"aws:SecureTransport" = "false"
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
]
|
|
146
|
-
})
|
|
147
|
-
}
|
|
148
|
-
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
variable "name" {
|
|
2
|
-
description = "Base name for resources"
|
|
3
|
-
type = string
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
variable "environment" {
|
|
7
|
-
description = "Environment name (e.g. dev, staging, prod)"
|
|
8
|
-
type = string
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
variable "s3_expiration_days" {
|
|
12
|
-
description = "Number of days after which S3 objects expire (null to disable expiration)"
|
|
13
|
-
type = number
|
|
14
|
-
default = null
|
|
15
|
-
}
|
|
16
|
-
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
data "aws_region" "current" {}
|
|
2
|
-
|
|
3
|
-
################################################################################
|
|
4
|
-
# Database Credentials Secret
|
|
5
|
-
################################################################################
|
|
6
|
-
|
|
7
|
-
resource "kubernetes_secret" "database_credentials" {
|
|
8
|
-
metadata {
|
|
9
|
-
name = "__APP_NAME__-database-credentials"
|
|
10
|
-
namespace = var.namespace
|
|
11
|
-
}
|
|
12
|
-
type = "Opaque"
|
|
13
|
-
data = {
|
|
14
|
-
host = var.db_host
|
|
15
|
-
port = tostring(var.db_port)
|
|
16
|
-
database = var.db_name
|
|
17
|
-
username = var.db_username
|
|
18
|
-
password = var.db_password
|
|
19
|
-
ssl_cert = var.db_ssl_cert
|
|
20
|
-
database_url = var.db_url
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
# PostgreSQL Secret (Langfuse-style structure)
|
|
25
|
-
resource "kubernetes_secret" "postgresql" {
|
|
26
|
-
metadata {
|
|
27
|
-
name = "__APP_NAME__-postgresql"
|
|
28
|
-
namespace = var.namespace
|
|
29
|
-
}
|
|
30
|
-
type = "Opaque"
|
|
31
|
-
data = {
|
|
32
|
-
postgres-password = var.db_password
|
|
33
|
-
database_url = "postgresql://${var.db_username}:${var.db_password}@${var.db_host}:${var.db_port}/${var.db_name}"
|
|
34
|
-
database_name = var.db_name
|
|
35
|
-
host = var.db_host
|
|
36
|
-
port = tostring(var.db_port)
|
|
37
|
-
username = var.db_username
|
|
38
|
-
}
|
|
39
|
-
}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
output "database_secret_name" {
|
|
2
|
-
description = "Name of the Kubernetes secret containing database credentials"
|
|
3
|
-
value = kubernetes_secret.database_credentials.metadata[0].name
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
output "postgresql_secret_name" {
|
|
7
|
-
description = "Name of the Kubernetes secret containing PostgreSQL credentials (Langfuse-style)"
|
|
8
|
-
value = kubernetes_secret.postgresql.metadata[0].name
|
|
9
|
-
}
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
variable "namespace" {
|
|
2
|
-
description = "Kubernetes namespace for secrets"
|
|
3
|
-
type = string
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
variable "cluster_name" {
|
|
7
|
-
description = "EKS cluster name"
|
|
8
|
-
type = string
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
################################################################################
|
|
12
|
-
# Database Variables
|
|
13
|
-
################################################################################
|
|
14
|
-
|
|
15
|
-
variable "db_host" {
|
|
16
|
-
description = "Database host"
|
|
17
|
-
type = string
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
variable "db_port" {
|
|
21
|
-
description = "Database port"
|
|
22
|
-
type = number
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
variable "db_name" {
|
|
26
|
-
description = "Database name"
|
|
27
|
-
type = string
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
variable "db_username" {
|
|
31
|
-
description = "Database username"
|
|
32
|
-
type = string
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
variable "db_password" {
|
|
36
|
-
description = "Database password"
|
|
37
|
-
type = string
|
|
38
|
-
sensitive = true
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
variable "db_ssl_cert" {
|
|
42
|
-
description = "Database SSL certificate"
|
|
43
|
-
type = string
|
|
44
|
-
sensitive = true
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
variable "db_url" {
|
|
48
|
-
description = "Database connection URL"
|
|
49
|
-
type = string
|
|
50
|
-
sensitive = true
|
|
51
|
-
}
|