thinkwork-cli 0.1.0 → 0.2.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 (39) hide show
  1. package/README.md +3 -3
  2. package/dist/cli.js +251 -47
  3. package/dist/terraform/examples/greenfield/main.tf +190 -0
  4. package/dist/terraform/examples/greenfield/terraform.tfvars.example +28 -0
  5. package/dist/terraform/modules/_internal/workspace-guard/main.tf +29 -0
  6. package/dist/terraform/modules/app/agentcore-runtime/main.tf +217 -0
  7. package/dist/terraform/modules/app/appsync-subscriptions/main.tf +122 -0
  8. package/dist/terraform/modules/app/appsync-subscriptions/outputs.tf +20 -0
  9. package/dist/terraform/modules/app/appsync-subscriptions/variables.tf +31 -0
  10. package/dist/terraform/modules/app/crons/main.tf +55 -0
  11. package/dist/terraform/modules/app/hindsight-memory/README.md +66 -0
  12. package/dist/terraform/modules/app/hindsight-memory/main.tf +331 -0
  13. package/dist/terraform/modules/app/job-triggers/main.tf +70 -0
  14. package/dist/terraform/modules/app/lambda-api/.build/placeholder.zip +0 -0
  15. package/dist/terraform/modules/app/lambda-api/handlers.tf +311 -0
  16. package/dist/terraform/modules/app/lambda-api/main.tf +245 -0
  17. package/dist/terraform/modules/app/lambda-api/outputs.tf +24 -0
  18. package/dist/terraform/modules/app/lambda-api/variables.tf +153 -0
  19. package/dist/terraform/modules/app/ses-email/main.tf +51 -0
  20. package/dist/terraform/modules/app/static-site/main.tf +176 -0
  21. package/dist/terraform/modules/data/aurora-postgres/README.md +92 -0
  22. package/dist/terraform/modules/data/aurora-postgres/main.tf +185 -0
  23. package/dist/terraform/modules/data/aurora-postgres/outputs.tf +30 -0
  24. package/dist/terraform/modules/data/aurora-postgres/variables.tf +114 -0
  25. package/dist/terraform/modules/data/bedrock-knowledge-base/main.tf +102 -0
  26. package/dist/terraform/modules/data/s3-buckets/main.tf +91 -0
  27. package/dist/terraform/modules/foundation/cognito/main.tf +377 -0
  28. package/dist/terraform/modules/foundation/cognito/outputs.tf +29 -0
  29. package/dist/terraform/modules/foundation/cognito/variables.tf +124 -0
  30. package/dist/terraform/modules/foundation/dns/main.tf +49 -0
  31. package/dist/terraform/modules/foundation/kms/main.tf +49 -0
  32. package/dist/terraform/modules/foundation/vpc/main.tf +137 -0
  33. package/dist/terraform/modules/foundation/vpc/outputs.tf +14 -0
  34. package/dist/terraform/modules/foundation/vpc/variables.tf +40 -0
  35. package/dist/terraform/modules/thinkwork/main.tf +212 -0
  36. package/dist/terraform/modules/thinkwork/outputs.tf +87 -0
  37. package/dist/terraform/modules/thinkwork/variables.tf +241 -0
  38. package/dist/terraform/schema.graphql +199 -0
  39. package/package.json +2 -2
@@ -0,0 +1,114 @@
1
+ variable "stage" {
2
+ description = "Deployment stage (e.g. dev, prod)"
3
+ type = string
4
+ }
5
+
6
+ # ---------------------------------------------------------------------------
7
+ # BYO Aurora
8
+ # ---------------------------------------------------------------------------
9
+
10
+ variable "create_database" {
11
+ description = "Whether to create a new Aurora cluster. Set to false to use an existing cluster."
12
+ type = bool
13
+ default = true
14
+ }
15
+
16
+ variable "existing_db_cluster_arn" {
17
+ description = "ARN of an existing Aurora cluster (required when create_database = false)"
18
+ type = string
19
+ default = null
20
+ }
21
+
22
+ variable "existing_db_secret_arn" {
23
+ description = "ARN of an existing Secrets Manager secret with DB credentials (required when create_database = false)"
24
+ type = string
25
+ default = null
26
+ }
27
+
28
+ variable "existing_db_endpoint" {
29
+ description = "Endpoint of an existing Aurora cluster (required when create_database = false)"
30
+ type = string
31
+ default = null
32
+ }
33
+
34
+ variable "existing_db_security_group_id" {
35
+ description = "Security group ID of an existing Aurora cluster (required when create_database = false)"
36
+ type = string
37
+ default = null
38
+ }
39
+
40
+ # ---------------------------------------------------------------------------
41
+ # Cluster Configuration (only used when create_database = true)
42
+ # ---------------------------------------------------------------------------
43
+
44
+ variable "vpc_id" {
45
+ description = "VPC ID for the database security group"
46
+ type = string
47
+ default = ""
48
+ }
49
+
50
+ variable "subnet_ids" {
51
+ description = "Subnet IDs for the DB subnet group"
52
+ type = list(string)
53
+ default = []
54
+ }
55
+
56
+ variable "db_password" {
57
+ description = "Master password for the Aurora cluster"
58
+ type = string
59
+ sensitive = true
60
+ default = ""
61
+ }
62
+
63
+ variable "database_name" {
64
+ description = "Name of the database to create"
65
+ type = string
66
+ default = "thinkwork"
67
+ }
68
+
69
+ variable "database_engine" {
70
+ description = "Database engine: 'aurora-serverless' (production, serverless v2) or 'rds-postgres' (dev/test, cheaper, single instance)"
71
+ type = string
72
+ default = "aurora-serverless"
73
+
74
+ validation {
75
+ condition = contains(["aurora-serverless", "rds-postgres"], var.database_engine)
76
+ error_message = "database_engine must be 'aurora-serverless' or 'rds-postgres'"
77
+ }
78
+ }
79
+
80
+ variable "engine_version" {
81
+ description = "PostgreSQL engine version"
82
+ type = string
83
+ default = "15.10"
84
+ }
85
+
86
+ variable "min_capacity" {
87
+ description = "Minimum ACU capacity for Aurora serverless v2 (ignored for rds-postgres)"
88
+ type = number
89
+ default = 0.5
90
+ }
91
+
92
+ variable "max_capacity" {
93
+ description = "Maximum ACU capacity for Aurora serverless v2 (ignored for rds-postgres)"
94
+ type = number
95
+ default = 2
96
+ }
97
+
98
+ variable "rds_instance_class" {
99
+ description = "Instance class for rds-postgres engine (ignored for aurora-serverless)"
100
+ type = string
101
+ default = "db.t4g.micro"
102
+ }
103
+
104
+ variable "rds_allocated_storage" {
105
+ description = "Allocated storage in GB for rds-postgres engine (ignored for aurora-serverless)"
106
+ type = number
107
+ default = 20
108
+ }
109
+
110
+ variable "deletion_protection" {
111
+ description = "Enable deletion protection (defaults to true for aurora-serverless, false for rds-postgres)"
112
+ type = bool
113
+ default = null
114
+ }
@@ -0,0 +1,102 @@
1
+ ################################################################################
2
+ # Bedrock Knowledge Base — Data Module
3
+ #
4
+ # Creates the IAM service role that Bedrock Knowledge Bases need to access
5
+ # S3 documents, invoke Titan embeddings, use RDS Data API, and read secrets.
6
+ ################################################################################
7
+
8
+ variable "stage" {
9
+ description = "Deployment stage"
10
+ type = string
11
+ }
12
+
13
+ variable "account_id" {
14
+ description = "AWS account ID"
15
+ type = string
16
+ }
17
+
18
+ variable "region" {
19
+ description = "AWS region"
20
+ type = string
21
+ }
22
+
23
+ variable "bucket_name" {
24
+ description = "S3 bucket name for knowledge base documents"
25
+ type = string
26
+ }
27
+
28
+ data "aws_iam_policy_document" "kb_assume" {
29
+ statement {
30
+ effect = "Allow"
31
+ actions = ["sts:AssumeRole"]
32
+ principals {
33
+ type = "Service"
34
+ identifiers = ["bedrock.amazonaws.com"]
35
+ }
36
+ condition {
37
+ test = "StringEquals"
38
+ variable = "aws:SourceAccount"
39
+ values = [var.account_id]
40
+ }
41
+ }
42
+ }
43
+
44
+ resource "aws_iam_role" "kb_service" {
45
+ name = "thinkwork-${var.stage}-kb-service-role"
46
+ assume_role_policy = data.aws_iam_policy_document.kb_assume.json
47
+ }
48
+
49
+ resource "aws_iam_role_policy" "kb_permissions" {
50
+ name = "knowledge-base-permissions"
51
+ role = aws_iam_role.kb_service.id
52
+
53
+ policy = jsonencode({
54
+ Version = "2012-10-17"
55
+ Statement = [
56
+ {
57
+ Sid = "S3ReadDocs"
58
+ Effect = "Allow"
59
+ Action = [
60
+ "s3:GetObject",
61
+ "s3:ListBucket",
62
+ ]
63
+ Resource = [
64
+ "arn:aws:s3:::${var.bucket_name}",
65
+ "arn:aws:s3:::${var.bucket_name}/*",
66
+ ]
67
+ },
68
+ {
69
+ Sid = "BedrockEmbedding"
70
+ Effect = "Allow"
71
+ Action = ["bedrock:InvokeModel"]
72
+ Resource = "arn:aws:bedrock:${var.region}::foundation-model/amazon.titan-embed-text-v2:0"
73
+ },
74
+ {
75
+ Sid = "RDSDataAPI"
76
+ Effect = "Allow"
77
+ Action = [
78
+ "rds-data:ExecuteStatement",
79
+ "rds-data:BatchExecuteStatement",
80
+ ]
81
+ Resource = "*"
82
+ },
83
+ {
84
+ Sid = "RDSDescribe"
85
+ Effect = "Allow"
86
+ Action = ["rds:DescribeDBClusters"]
87
+ Resource = "*"
88
+ },
89
+ {
90
+ Sid = "SecretsManager"
91
+ Effect = "Allow"
92
+ Action = ["secretsmanager:GetSecretValue"]
93
+ Resource = "*"
94
+ },
95
+ ]
96
+ })
97
+ }
98
+
99
+ output "kb_service_role_arn" {
100
+ description = "IAM role ARN for Bedrock Knowledge Base service"
101
+ value = aws_iam_role.kb_service.arn
102
+ }
@@ -0,0 +1,91 @@
1
+ ################################################################################
2
+ # S3 Buckets — Data Module
3
+ #
4
+ # Creates the primary S3 bucket for skills, artifacts, knowledge base docs,
5
+ # and email inbound storage. HTTPS-only enforcement + SES inbound policy.
6
+ ################################################################################
7
+
8
+ variable "stage" {
9
+ description = "Deployment stage"
10
+ type = string
11
+ }
12
+
13
+ variable "account_id" {
14
+ description = "AWS account ID"
15
+ type = string
16
+ }
17
+
18
+ variable "bucket_name" {
19
+ description = "Name of the S3 bucket"
20
+ type = string
21
+ }
22
+
23
+ resource "aws_s3_bucket" "main" {
24
+ bucket = var.bucket_name
25
+
26
+ tags = {
27
+ Name = "thinkwork-${var.stage}-storage"
28
+ Stage = var.stage
29
+ }
30
+ }
31
+
32
+ resource "aws_s3_bucket_cors_configuration" "main" {
33
+ bucket = aws_s3_bucket.main.id
34
+
35
+ cors_rule {
36
+ allowed_headers = ["*"]
37
+ allowed_methods = ["GET", "PUT", "POST", "HEAD"]
38
+ allowed_origins = ["*"]
39
+ expose_headers = ["ETag"]
40
+ max_age_seconds = 3000
41
+ }
42
+ }
43
+
44
+ resource "aws_s3_bucket_policy" "https_only" {
45
+ bucket = aws_s3_bucket.main.id
46
+
47
+ policy = jsonencode({
48
+ Version = "2012-10-17"
49
+ Statement = [
50
+ {
51
+ Sid = "EnforceHTTPS"
52
+ Effect = "Deny"
53
+ Principal = "*"
54
+ Action = "s3:*"
55
+ Resource = [
56
+ aws_s3_bucket.main.arn,
57
+ "${aws_s3_bucket.main.arn}/*",
58
+ ]
59
+ Condition = {
60
+ Bool = {
61
+ "aws:SecureTransport" = "false"
62
+ }
63
+ }
64
+ },
65
+ {
66
+ Sid = "AllowSESInbound"
67
+ Effect = "Allow"
68
+ Principal = {
69
+ Service = "ses.amazonaws.com"
70
+ }
71
+ Action = "s3:PutObject"
72
+ Resource = "${aws_s3_bucket.main.arn}/*"
73
+ Condition = {
74
+ StringEquals = {
75
+ "AWS:SourceAccount" = var.account_id
76
+ }
77
+ }
78
+ },
79
+ ]
80
+ })
81
+ }
82
+
83
+ output "bucket_name" {
84
+ description = "Name of the S3 bucket"
85
+ value = aws_s3_bucket.main.id
86
+ }
87
+
88
+ output "bucket_arn" {
89
+ description = "ARN of the S3 bucket"
90
+ value = aws_s3_bucket.main.arn
91
+ }
@@ -0,0 +1,377 @@
1
+ ################################################################################
2
+ # Cognito — Foundation Module
3
+ #
4
+ # Creates a Cognito user pool with Google social login, two app clients
5
+ # (web admin + mobile), an identity pool, and user groups.
6
+ # Or accepts an existing pool via BYO variables.
7
+ ################################################################################
8
+
9
+ locals {
10
+ create = var.create_cognito
11
+ create_pre_signup = local.create && var.pre_signup_lambda_zip != ""
12
+
13
+ user_pool_id = local.create ? aws_cognito_user_pool.main[0].id : var.existing_user_pool_id
14
+ user_pool_arn = local.create ? aws_cognito_user_pool.main[0].arn : var.existing_user_pool_arn
15
+ admin_client_id = local.create ? aws_cognito_user_pool_client.admin[0].id : var.existing_admin_client_id
16
+ mobile_client_id = local.create ? aws_cognito_user_pool_client.mobile[0].id : var.existing_mobile_client_id
17
+ identity_pool_id = local.create ? aws_cognito_identity_pool.main[0].id : var.existing_identity_pool_id
18
+ }
19
+
20
+ data "aws_caller_identity" "current" {}
21
+
22
+ ################################################################################
23
+ # Pre Sign-Up Lambda
24
+ ################################################################################
25
+
26
+ resource "aws_iam_role" "pre_signup" {
27
+ count = local.create_pre_signup ? 1 : 0
28
+ name = "thinkwork-${var.stage}-cognito-pre-signup-role"
29
+
30
+ assume_role_policy = jsonencode({
31
+ Version = "2012-10-17"
32
+ Statement = [{
33
+ Effect = "Allow"
34
+ Principal = { Service = "lambda.amazonaws.com" }
35
+ Action = "sts:AssumeRole"
36
+ }]
37
+ })
38
+ }
39
+
40
+ resource "aws_iam_role_policy_attachment" "pre_signup_basic" {
41
+ count = local.create_pre_signup ? 1 : 0
42
+ role = aws_iam_role.pre_signup[0].name
43
+ policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
44
+ }
45
+
46
+ resource "aws_iam_role_policy" "pre_signup_cognito" {
47
+ count = local.create_pre_signup ? 1 : 0
48
+ name = "cognito-access"
49
+ role = aws_iam_role.pre_signup[0].id
50
+
51
+ policy = jsonencode({
52
+ Version = "2012-10-17"
53
+ Statement = [{
54
+ Effect = "Allow"
55
+ Action = [
56
+ "cognito-idp:ListUsers",
57
+ "cognito-idp:AdminLinkProviderForUser",
58
+ "cognito-idp:AdminCreateUser",
59
+ "cognito-idp:AdminSetUserPassword"
60
+ ]
61
+ Resource = aws_cognito_user_pool.main[0].arn
62
+ }]
63
+ })
64
+ }
65
+
66
+ resource "aws_lambda_function" "pre_signup" {
67
+ count = local.create_pre_signup ? 1 : 0
68
+ function_name = "thinkwork-${var.stage}-cognito-pre-signup"
69
+ filename = var.pre_signup_lambda_zip
70
+ handler = "index.handler"
71
+ runtime = "nodejs20.x"
72
+ timeout = 10
73
+ role = aws_iam_role.pre_signup[0].arn
74
+
75
+ source_code_hash = filebase64sha256(var.pre_signup_lambda_zip)
76
+ }
77
+
78
+ resource "aws_lambda_permission" "cognito_pre_signup" {
79
+ count = local.create_pre_signup ? 1 : 0
80
+ statement_id = "AllowCognitoInvoke"
81
+ action = "lambda:InvokeFunction"
82
+ function_name = aws_lambda_function.pre_signup[0].function_name
83
+ principal = "cognito-idp.amazonaws.com"
84
+ source_arn = aws_cognito_user_pool.main[0].arn
85
+ }
86
+
87
+ ################################################################################
88
+ # User Pool
89
+ ################################################################################
90
+
91
+ resource "aws_cognito_user_pool" "main" {
92
+ count = local.create ? 1 : 0
93
+ name = var.user_pool_name != "" ? var.user_pool_name : "thinkwork-${var.stage}-user-pool"
94
+
95
+ username_attributes = ["email"]
96
+ auto_verified_attributes = ["email"]
97
+
98
+ schema {
99
+ name = "email"
100
+ attribute_data_type = "String"
101
+ required = true
102
+ mutable = true
103
+
104
+ string_attribute_constraints {
105
+ min_length = 1
106
+ max_length = 256
107
+ }
108
+ }
109
+
110
+ schema {
111
+ name = "tenant_id"
112
+ attribute_data_type = "String"
113
+ required = false
114
+ mutable = true
115
+
116
+ string_attribute_constraints {
117
+ min_length = 0
118
+ max_length = 36
119
+ }
120
+ }
121
+
122
+ password_policy {
123
+ minimum_length = 8
124
+ require_uppercase = true
125
+ require_lowercase = true
126
+ require_numbers = true
127
+ require_symbols = false
128
+ temporary_password_validity_days = 7
129
+ }
130
+
131
+ account_recovery_setting {
132
+ recovery_mechanism {
133
+ name = "verified_email"
134
+ priority = 1
135
+ }
136
+ }
137
+
138
+ dynamic "lambda_config" {
139
+ for_each = local.create_pre_signup ? [1] : []
140
+ content {
141
+ pre_sign_up = aws_lambda_function.pre_signup[0].arn
142
+ }
143
+ }
144
+
145
+ tags = {
146
+ Name = "thinkwork-${var.stage}-user-pool"
147
+ }
148
+
149
+ lifecycle {
150
+ ignore_changes = [schema]
151
+ }
152
+ }
153
+
154
+ ################################################################################
155
+ # Cognito Domain
156
+ ################################################################################
157
+
158
+ resource "aws_cognito_user_pool_domain" "main" {
159
+ count = local.create ? 1 : 0
160
+ domain = "thinkwork-${var.stage}"
161
+ user_pool_id = aws_cognito_user_pool.main[0].id
162
+ }
163
+
164
+ ################################################################################
165
+ # Google Identity Provider
166
+ ################################################################################
167
+
168
+ resource "aws_cognito_identity_provider" "google" {
169
+ count = local.create && var.google_oauth_client_id != "" ? 1 : 0
170
+ user_pool_id = aws_cognito_user_pool.main[0].id
171
+ provider_name = "Google"
172
+ provider_type = "Google"
173
+
174
+ provider_details = {
175
+ client_id = var.google_oauth_client_id
176
+ client_secret = var.google_oauth_client_secret
177
+ authorize_scopes = "openid email profile"
178
+ attributes_url = "https://people.googleapis.com/v1/people/me?personFields="
179
+ attributes_url_add_attributes = true
180
+ authorize_url = "https://accounts.google.com/o/oauth2/v2/auth"
181
+ oidc_issuer = "https://accounts.google.com"
182
+ token_request_method = "POST"
183
+ token_url = "https://www.googleapis.com/oauth2/v4/token"
184
+ }
185
+
186
+ attribute_mapping = {
187
+ email = "email"
188
+ name = "name"
189
+ username = "sub"
190
+ }
191
+ }
192
+
193
+ locals {
194
+ identity_providers = var.google_oauth_client_id != "" ? ["Google", "COGNITO"] : ["COGNITO"]
195
+ }
196
+
197
+ ################################################################################
198
+ # App Client — Admin (Web)
199
+ ################################################################################
200
+
201
+ resource "aws_cognito_user_pool_client" "admin" {
202
+ count = local.create ? 1 : 0
203
+ name = "ThinkworkAdmin"
204
+ user_pool_id = aws_cognito_user_pool.main[0].id
205
+
206
+ allowed_oauth_flows_user_pool_client = true
207
+ allowed_oauth_flows = ["code"]
208
+ allowed_oauth_scopes = ["openid", "email", "profile"]
209
+
210
+ supported_identity_providers = local.identity_providers
211
+
212
+ callback_urls = var.admin_callback_urls
213
+ logout_urls = var.admin_logout_urls
214
+
215
+ access_token_validity = 1
216
+ id_token_validity = 1
217
+ refresh_token_validity = 30
218
+
219
+ token_validity_units {
220
+ access_token = "hours"
221
+ id_token = "hours"
222
+ refresh_token = "days"
223
+ }
224
+
225
+ read_attributes = [
226
+ "email",
227
+ "email_verified",
228
+ "name",
229
+ "custom:tenant_id",
230
+ ]
231
+
232
+ write_attributes = [
233
+ "email",
234
+ "name",
235
+ "custom:tenant_id",
236
+ ]
237
+
238
+ depends_on = [aws_cognito_identity_provider.google]
239
+ }
240
+
241
+ ################################################################################
242
+ # App Client — Mobile
243
+ ################################################################################
244
+
245
+ resource "aws_cognito_user_pool_client" "mobile" {
246
+ count = local.create ? 1 : 0
247
+ name = "ThinkworkMobile"
248
+ user_pool_id = aws_cognito_user_pool.main[0].id
249
+
250
+ explicit_auth_flows = [
251
+ "ALLOW_USER_PASSWORD_AUTH",
252
+ "ALLOW_USER_SRP_AUTH",
253
+ "ALLOW_REFRESH_TOKEN_AUTH",
254
+ ]
255
+
256
+ allowed_oauth_flows_user_pool_client = true
257
+ allowed_oauth_flows = ["code"]
258
+ allowed_oauth_scopes = ["openid", "email", "profile"]
259
+
260
+ supported_identity_providers = local.identity_providers
261
+
262
+ callback_urls = var.mobile_callback_urls
263
+ logout_urls = var.mobile_logout_urls
264
+
265
+ access_token_validity = 1
266
+ id_token_validity = 1
267
+ refresh_token_validity = 90
268
+
269
+ token_validity_units {
270
+ access_token = "hours"
271
+ id_token = "hours"
272
+ refresh_token = "days"
273
+ }
274
+
275
+ read_attributes = [
276
+ "email",
277
+ "email_verified",
278
+ "name",
279
+ "custom:tenant_id",
280
+ ]
281
+
282
+ write_attributes = [
283
+ "email",
284
+ "name",
285
+ "custom:tenant_id",
286
+ ]
287
+
288
+ depends_on = [aws_cognito_identity_provider.google]
289
+ }
290
+
291
+ ################################################################################
292
+ # Identity Pool
293
+ ################################################################################
294
+
295
+ resource "aws_cognito_identity_pool" "main" {
296
+ count = local.create ? 1 : 0
297
+ identity_pool_name = var.identity_pool_name != "" ? var.identity_pool_name : "thinkwork-${var.stage}-identity-pool"
298
+ allow_unauthenticated_identities = false
299
+
300
+ cognito_identity_providers {
301
+ client_id = aws_cognito_user_pool_client.admin[0].id
302
+ provider_name = "cognito-idp.${var.region}.amazonaws.com/${aws_cognito_user_pool.main[0].id}"
303
+ server_side_token_check = false
304
+ }
305
+
306
+ cognito_identity_providers {
307
+ client_id = aws_cognito_user_pool_client.mobile[0].id
308
+ provider_name = "cognito-idp.${var.region}.amazonaws.com/${aws_cognito_user_pool.main[0].id}"
309
+ server_side_token_check = false
310
+ }
311
+
312
+ tags = {
313
+ Name = "thinkwork-${var.stage}-identity-pool"
314
+ }
315
+ }
316
+
317
+ ################################################################################
318
+ # Identity Pool — Authenticated Role
319
+ ################################################################################
320
+
321
+ resource "aws_iam_role" "authenticated" {
322
+ count = local.create ? 1 : 0
323
+ name = "thinkwork-${var.stage}-cognito-authenticated"
324
+
325
+ assume_role_policy = jsonencode({
326
+ Version = "2012-10-17"
327
+ Statement = [{
328
+ Effect = "Allow"
329
+ Principal = { Federated = "cognito-identity.amazonaws.com" }
330
+ Action = "sts:AssumeRoleWithWebIdentity"
331
+ Condition = {
332
+ StringEquals = {
333
+ "cognito-identity.amazonaws.com:aud" = aws_cognito_identity_pool.main[0].id
334
+ }
335
+ "ForAnyValue:StringLike" = {
336
+ "cognito-identity.amazonaws.com:amr" = "authenticated"
337
+ }
338
+ }
339
+ }]
340
+ })
341
+ }
342
+
343
+ resource "aws_iam_role_policy" "authenticated_appsync" {
344
+ count = local.create ? 1 : 0
345
+ name = "appsync-access"
346
+ role = aws_iam_role.authenticated[0].id
347
+
348
+ policy = jsonencode({
349
+ Version = "2012-10-17"
350
+ Statement = [{
351
+ Effect = "Allow"
352
+ Action = "appsync:GraphQL"
353
+ Resource = "*"
354
+ }]
355
+ })
356
+ }
357
+
358
+ resource "aws_cognito_identity_pool_roles_attachment" "main" {
359
+ count = local.create ? 1 : 0
360
+ identity_pool_id = aws_cognito_identity_pool.main[0].id
361
+
362
+ roles = {
363
+ authenticated = aws_iam_role.authenticated[0].arn
364
+ }
365
+ }
366
+
367
+ ################################################################################
368
+ # User Groups
369
+ ################################################################################
370
+
371
+ resource "aws_cognito_user_group" "groups" {
372
+ for_each = local.create ? toset(["owner", "admin", "member", "viewer"]) : toset([])
373
+
374
+ name = each.key
375
+ user_pool_id = aws_cognito_user_pool.main[0].id
376
+ description = "${title(each.key)} group"
377
+ }