@swovohq/fuel 0.2.2-alpha.9 → 0.2.2-alpha.90
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 +108 -4
- package/dist/bin/fuel.js +76 -30
- package/dist/bin/fuel.js.map +1 -1
- package/dist/commands/config-verify.d.ts.map +1 -1
- package/dist/commands/config-verify.js +14 -6
- package/dist/commands/config-verify.js.map +1 -1
- package/dist/commands/create-app.d.ts.map +1 -1
- package/dist/commands/create-app.js +36 -4
- package/dist/commands/create-app.js.map +1 -1
- package/dist/commands/infra-deploy.d.ts +15 -1
- package/dist/commands/infra-deploy.d.ts.map +1 -1
- package/dist/commands/infra-deploy.js +144 -15
- package/dist/commands/infra-deploy.js.map +1 -1
- package/dist/commands/infra-destroy.js +3 -3
- package/dist/commands/infra-destroy.js.map +1 -1
- package/dist/commands/infra-init.d.ts +91 -0
- package/dist/commands/infra-init.d.ts.map +1 -1
- package/dist/commands/infra-init.js +510 -80
- package/dist/commands/infra-init.js.map +1 -1
- package/dist/commands/infra-pull.d.ts +8 -0
- package/dist/commands/infra-pull.d.ts.map +1 -0
- package/dist/commands/infra-pull.js +80 -0
- package/dist/commands/infra-pull.js.map +1 -0
- package/dist/engines/convention.d.ts +2 -2
- package/dist/engines/convention.d.ts.map +1 -1
- package/dist/engines/convention.js +6 -4
- package/dist/engines/convention.js.map +1 -1
- package/dist/engines/dependencies.d.ts +2 -0
- package/dist/engines/dependencies.d.ts.map +1 -1
- package/dist/engines/dependencies.js.map +1 -1
- package/dist/infra/azure-defaults.d.ts +49 -0
- package/dist/infra/azure-defaults.d.ts.map +1 -0
- package/dist/infra/azure-defaults.js +52 -0
- package/dist/infra/azure-defaults.js.map +1 -0
- package/dist/infra/azure-keyvault-client.d.ts +4 -0
- package/dist/infra/azure-keyvault-client.d.ts.map +1 -0
- package/dist/infra/azure-keyvault-client.js +57 -0
- package/dist/infra/azure-keyvault-client.js.map +1 -0
- package/dist/infra/azure-rbac.d.ts +11 -0
- package/dist/infra/azure-rbac.d.ts.map +1 -0
- package/dist/infra/azure-rbac.js +47 -0
- package/dist/infra/azure-rbac.js.map +1 -0
- package/dist/infra/azure-state-storage.d.ts +20 -0
- package/dist/infra/azure-state-storage.d.ts.map +1 -0
- package/dist/infra/azure-state-storage.js +229 -0
- package/dist/infra/azure-state-storage.js.map +1 -0
- package/dist/infra/credentials.d.ts +2 -2
- package/dist/infra/credentials.d.ts.map +1 -1
- package/dist/infra/credentials.js +8 -4
- package/dist/infra/credentials.js.map +1 -1
- package/dist/infra/deployment-detect.d.ts +9 -0
- package/dist/infra/deployment-detect.d.ts.map +1 -0
- package/dist/infra/deployment-detect.js +53 -0
- package/dist/infra/deployment-detect.js.map +1 -0
- package/dist/infra/git-client.d.ts.map +1 -1
- package/dist/infra/git-client.js +6 -10
- package/dist/infra/git-client.js.map +1 -1
- package/dist/infra/github-client.d.ts +7 -0
- package/dist/infra/github-client.d.ts.map +1 -1
- package/dist/infra/github-client.js +44 -4
- package/dist/infra/github-client.js.map +1 -1
- package/dist/infra/github-token-link.d.ts +4 -0
- package/dist/infra/github-token-link.d.ts.map +1 -0
- package/dist/infra/github-token-link.js +28 -0
- package/dist/infra/github-token-link.js.map +1 -0
- package/dist/infra/orchestrator.d.ts +4 -1
- package/dist/infra/orchestrator.d.ts.map +1 -1
- package/dist/infra/orchestrator.js +209 -59
- package/dist/infra/orchestrator.js.map +1 -1
- package/dist/infra/preflight.d.ts.map +1 -1
- package/dist/infra/preflight.js +17 -9
- package/dist/infra/preflight.js.map +1 -1
- package/dist/infra/remote-secret.d.ts +14 -0
- package/dist/infra/remote-secret.d.ts.map +1 -0
- package/dist/infra/remote-secret.js +42 -0
- package/dist/infra/remote-secret.js.map +1 -0
- package/dist/infra/template-engine.d.ts +14 -5
- package/dist/infra/template-engine.d.ts.map +1 -1
- package/dist/infra/template-engine.js +145 -39
- package/dist/infra/template-engine.js.map +1 -1
- package/dist/infra/tofu-runner.d.ts +4 -3
- package/dist/infra/tofu-runner.d.ts.map +1 -1
- package/dist/infra/tofu-runner.js +36 -27
- package/dist/infra/tofu-runner.js.map +1 -1
- package/dist/infra/types.d.ts +240 -16
- package/dist/infra/types.d.ts.map +1 -1
- package/dist/infra/types.js +207 -18
- package/dist/infra/types.js.map +1 -1
- package/dist/infra-templates/TODO-azure-prod.md +119 -0
- package/dist/infra-templates/modules/azure-container-app/main.tf +124 -0
- package/dist/infra-templates/modules/azure-container-app/outputs.tf +24 -0
- package/dist/infra-templates/modules/azure-container-app/variables.tf +80 -0
- package/dist/infra-templates/modules/azure-container-apps-environment/main.tf +18 -0
- package/dist/infra-templates/modules/azure-container-apps-environment/outputs.tf +14 -0
- package/dist/infra-templates/modules/azure-container-apps-environment/variables.tf +24 -0
- package/dist/infra-templates/modules/azure-container-registry/main.tf +10 -0
- package/dist/infra-templates/modules/azure-container-registry/outputs.tf +14 -0
- package/dist/infra-templates/modules/azure-container-registry/variables.tf +20 -0
- package/dist/infra-templates/modules/azure-front-door/main.tf +80 -0
- package/dist/infra-templates/modules/azure-front-door/outputs.tf +20 -0
- package/dist/infra-templates/modules/azure-front-door/variables.tf +26 -0
- package/dist/infra-templates/modules/azure-github-oidc/main.tf +48 -0
- package/dist/infra-templates/modules/azure-github-oidc/outputs.tf +9 -0
- package/dist/infra-templates/modules/azure-github-oidc/variables.tf +69 -0
- package/dist/infra-templates/modules/azure-key-vault/main.tf +21 -0
- package/dist/infra-templates/modules/azure-key-vault/outputs.tf +11 -0
- package/dist/infra-templates/modules/azure-key-vault/variables.tf +43 -0
- package/dist/infra-templates/modules/azure-monitor/main.tf +29 -0
- package/dist/infra-templates/modules/azure-monitor/outputs.tf +17 -0
- package/dist/infra-templates/modules/azure-monitor/variables.tf +32 -0
- package/dist/infra-templates/modules/azure-network/main.tf +134 -0
- package/dist/infra-templates/modules/azure-network/outputs.tf +44 -0
- package/dist/infra-templates/modules/azure-network/variables.tf +56 -0
- package/dist/infra-templates/modules/azure-postgresql-flexible/main.tf +34 -0
- package/dist/infra-templates/modules/azure-postgresql-flexible/outputs.tf +20 -0
- package/dist/infra-templates/modules/azure-postgresql-flexible/variables.tf +54 -0
- package/dist/infra-templates/modules/azure-redis-cache/main.tf +32 -0
- package/dist/infra-templates/modules/azure-redis-cache/outputs.tf +15 -0
- package/dist/infra-templates/modules/azure-redis-cache/variables.tf +30 -0
- package/dist/infra-templates/modules/azure-resource-group/main.tf +5 -0
- package/dist/infra-templates/modules/azure-resource-group/outputs.tf +11 -0
- package/dist/infra-templates/modules/azure-resource-group/variables.tf +16 -0
- package/dist/infra-templates/modules/azure-sql-database/main.tf +63 -0
- package/dist/infra-templates/modules/azure-sql-database/outputs.tf +20 -0
- package/dist/infra-templates/modules/azure-sql-database/variables.tf +78 -0
- package/dist/infra-templates/modules/azure-storage-account/main.tf +13 -0
- package/dist/infra-templates/modules/azure-storage-account/outputs.tf +16 -0
- package/dist/infra-templates/modules/azure-storage-account/variables.tf +38 -0
- package/dist/infra-templates/modules/cloud-watch/event-bridge.tf +15 -0
- package/dist/infra-templates/modules/cloud-watch/lambda.tf +84 -0
- package/dist/infra-templates/modules/cloud-watch/lambda_function.zip +0 -0
- package/dist/infra-templates/modules/cloud-watch/lambda_function_deploy.zip +0 -0
- package/dist/infra-templates/modules/cloud-watch/main.tf +156 -0
- package/dist/infra-templates/modules/cloud-watch/sns.tf +3 -0
- package/dist/infra-templates/modules/cloud-watch/variables.tf +38 -0
- package/dist/infra-templates/modules/ecs-core/alb.tf +126 -0
- package/dist/infra-templates/modules/ecs-core/cloudwatch.tf +48 -0
- package/dist/infra-templates/modules/ecs-core/iam.tf +95 -0
- package/dist/infra-templates/modules/ecs-core/main.tf +12 -0
- package/dist/infra-templates/modules/ecs-core/outputs.tf +44 -0
- package/dist/infra-templates/modules/ecs-core/secrets.tf +9 -0
- package/dist/infra-templates/modules/ecs-core/security_groups.tf +73 -0
- package/dist/infra-templates/modules/ecs-core/variables.tf +96 -0
- package/dist/infra-templates/modules/ecs-service/ecs_autoscaling.tf +51 -0
- package/dist/infra-templates/modules/ecs-service/ecs_service.tf +39 -0
- package/dist/infra-templates/modules/ecs-service/ecs_task_definition.tf +56 -0
- package/dist/infra-templates/modules/ecs-service/variables.tf +170 -0
- package/dist/infra-templates/modules/elastic-container-registry/main.tf +32 -0
- package/dist/infra-templates/modules/elastic-container-registry/outputs.tf +9 -0
- package/dist/infra-templates/modules/elastic-container-registry/variables.tf +25 -0
- package/dist/infra-templates/modules/github-oidc-role/main.tf +46 -0
- package/dist/infra-templates/modules/github-oidc-role/outputs.tf +4 -0
- package/dist/infra-templates/modules/github-oidc-role/variables.tf +11 -0
- package/dist/infra-templates/modules/guardduty/main.tf +8 -0
- package/dist/infra-templates/modules/iam/main.tf +205 -0
- package/dist/infra-templates/modules/iam/outputs.tf +3 -0
- package/dist/infra-templates/modules/iam/variables.tf +4 -0
- package/dist/infra-templates/modules/random-key/main.tf +11 -0
- package/dist/infra-templates/modules/random-key/outputs.tf +4 -0
- package/dist/infra-templates/modules/random-key/variables.tf +10 -0
- package/dist/infra-templates/modules/redis/main.tf +47 -0
- package/dist/infra-templates/modules/redis/outputs.tf +8 -0
- package/dist/infra-templates/modules/redis/variables.tf +20 -0
- package/dist/infra-templates/modules/relational-database-service/main.tf +44 -0
- package/dist/infra-templates/modules/relational-database-service/outputs.tf +13 -0
- package/dist/infra-templates/modules/relational-database-service/security-group.tf +15 -0
- package/dist/infra-templates/modules/relational-database-service/variables.tf +50 -0
- package/dist/infra-templates/modules/secret/main.tf +14 -0
- package/dist/infra-templates/modules/secret/outputs.tf +3 -0
- package/dist/infra-templates/modules/secret/variables.tf +8 -0
- package/dist/infra-templates/modules/simple-storage-service/main.tf +28 -0
- package/dist/infra-templates/modules/simple-storage-service/variables.tf +4 -0
- package/dist/infra-templates/modules/vpc/data.tf +2 -0
- package/dist/infra-templates/modules/vpc/main.tf +76 -0
- package/dist/infra-templates/modules/vpc/outputs.tf +23 -0
- package/dist/infra-templates/modules/vpc/variables.tf +5 -0
- package/dist/infra-templates/package.json +6 -0
- package/dist/infra-templates/templates/azure/MANUAL_DEPLOY.md +168 -0
- package/dist/infra-templates/templates/azure/backend.tf +8 -0
- package/dist/infra-templates/templates/azure/data.tf +21 -0
- package/dist/infra-templates/templates/azure/default.tfvars +0 -0
- package/dist/infra-templates/templates/azure/locals.tf +116 -0
- package/dist/infra-templates/templates/azure/main.tf +421 -0
- package/dist/infra-templates/templates/azure/outputs.tf +40 -0
- package/dist/infra-templates/templates/azure/providers.tf +65 -0
- package/dist/infra-templates/templates/azure/variables.tf +69 -0
- package/dist/infra-templates/templates/azure/workflows/build_and_deploy.yml +155 -0
- package/dist/infra-templates/templates/azure/workflows/tests.yml +63 -0
- package/dist/infra-templates/templates/ecs/README.md +225 -0
- package/dist/infra-templates/templates/ecs/backend.tf +7 -0
- package/dist/infra-templates/templates/ecs/data.tf +6 -0
- package/dist/infra-templates/templates/ecs/default.tfvars +1 -0
- package/dist/infra-templates/templates/ecs/locals.tf +97 -0
- package/dist/infra-templates/templates/ecs/main.tf +185 -0
- package/dist/infra-templates/templates/ecs/outputs.tf +42 -0
- package/dist/infra-templates/templates/ecs/providers.tf +21 -0
- package/dist/infra-templates/templates/ecs/variables.tf +105 -0
- package/dist/infra-templates/templates/ecs/workflows/build_and_deploy.yml +188 -0
- package/dist/infra-templates/templates/ecs/workflows/tests.yml +65 -0
- package/package.json +10 -2
- package/schema/fuel.schema.json +570 -91
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
variable "project_name" {
|
|
2
|
+
description = "Project name used as prefix for resource names"
|
|
3
|
+
type = string
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
variable "github_organization" {
|
|
7
|
+
description = "GitHub organization name for the OIDC trust subject"
|
|
8
|
+
type = string
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
variable "github_repo_name" {
|
|
12
|
+
description = "GitHub repository name for the OIDC trust subject"
|
|
13
|
+
type = string
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
variable "branches" {
|
|
17
|
+
description = "Branches allowed to assume the Azure AD application via OIDC. One federated credential is created per branch."
|
|
18
|
+
type = list(string)
|
|
19
|
+
default = ["main"]
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
variable "role_assignment_scope" {
|
|
23
|
+
description = "Scope for the Contributor role assignment, typically the resource group ID"
|
|
24
|
+
type = string
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
variable "existing_client_id" {
|
|
28
|
+
description = <<-EOT
|
|
29
|
+
Client ID of an app registration + service principal + federated identity credential(s)
|
|
30
|
+
already created out-of-band by a tenant admin. Set this when the deploying SP lacks the
|
|
31
|
+
Entra ID "Application Administrator" role (creating an app registration requires it,
|
|
32
|
+
regardless of subscription-level RBAC) — the module then looks up and reuses that identity
|
|
33
|
+
instead of creating a new one. The Contributor role assignment is still managed by this
|
|
34
|
+
module either way, since that only needs "User Access Administrator" on the subscription.
|
|
35
|
+
EOT
|
|
36
|
+
type = string
|
|
37
|
+
default = null
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
variable "existing_principal_id" {
|
|
41
|
+
description = <<-EOT
|
|
42
|
+
Object ID (principal ID) of the service principal identified by existing_client_id, when
|
|
43
|
+
that's already known. Set this to skip looking it up via Microsoft Graph entirely — the
|
|
44
|
+
lookup (data.azuread_service_principal.existing) needs Directory.Read.All or
|
|
45
|
+
Application.Read.All on the deploying SP, which many tenant admins won't grant just to
|
|
46
|
+
resolve one known object. Whoever created the app out-of-band can get this by running
|
|
47
|
+
`az ad sp show --id <existing_client_id> --query id -o tsv`.
|
|
48
|
+
EOT
|
|
49
|
+
type = string
|
|
50
|
+
default = null
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
variable "manage_role_assignment" {
|
|
54
|
+
description = <<-EOT
|
|
55
|
+
Whether Terraform should create/manage the Contributor role assignment for this identity.
|
|
56
|
+
Set to false when it was already granted out-of-band alongside existing_client_id (e.g. a
|
|
57
|
+
tenant admin's onboarding runbook already ran `az role assignment create ... --role
|
|
58
|
+
Contributor`) — otherwise Terraform tries to create it again on every apply and fails with
|
|
59
|
+
RoleAssignmentExists.
|
|
60
|
+
EOT
|
|
61
|
+
type = bool
|
|
62
|
+
default = true
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
variable "enabled" {
|
|
66
|
+
description = "Set to false to skip this module entirely (no app, no SP, no role assignment). Use to unblock testing while waiting on a tenant admin for Application Administrator or an existing_client_id."
|
|
67
|
+
type = bool
|
|
68
|
+
default = true
|
|
69
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Application Key Vault (RBAC-based), used by apps to read secrets at runtime.
|
|
2
|
+
# Distinct from the bootstrap vault created by the CLI via SDK.
|
|
3
|
+
resource "azurerm_key_vault" "this" {
|
|
4
|
+
name = var.name
|
|
5
|
+
resource_group_name = var.resource_group_name
|
|
6
|
+
location = var.location
|
|
7
|
+
tenant_id = var.tenant_id
|
|
8
|
+
sku_name = var.sku_name
|
|
9
|
+
|
|
10
|
+
rbac_authorization_enabled = true
|
|
11
|
+
purge_protection_enabled = false
|
|
12
|
+
soft_delete_retention_days = 7
|
|
13
|
+
|
|
14
|
+
public_network_access_enabled = length(var.ip_rules) > 0 ? true : var.public_network_access_enabled
|
|
15
|
+
|
|
16
|
+
network_acls {
|
|
17
|
+
bypass = "AzureServices"
|
|
18
|
+
default_action = var.network_acls_default_action
|
|
19
|
+
ip_rules = var.ip_rules
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
variable "name" {
|
|
2
|
+
type = string
|
|
3
|
+
description = "Key Vault name"
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
variable "resource_group_name" {
|
|
7
|
+
type = string
|
|
8
|
+
description = "Resource group where the Key Vault is created"
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
variable "location" {
|
|
12
|
+
type = string
|
|
13
|
+
description = "Azure region"
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
variable "tenant_id" {
|
|
17
|
+
type = string
|
|
18
|
+
description = "Azure AD tenant ID"
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
variable "sku_name" {
|
|
22
|
+
type = string
|
|
23
|
+
description = "Key Vault SKU"
|
|
24
|
+
default = "standard"
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
variable "public_network_access_enabled" {
|
|
28
|
+
type = bool
|
|
29
|
+
description = "Allow access from the public internet. Defaults to false: this vault isn't read by anything at runtime today (no VNet/private-endpoint consumer wired up yet), so there's no reason to expose it publicly."
|
|
30
|
+
default = false
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
variable "network_acls_default_action" {
|
|
34
|
+
type = string
|
|
35
|
+
description = "Default action for requests not matched by an IP/VNet rule. Defaults to \"Deny\" — flip to \"Allow\" (or add a private endpoint) only once something outside the vault's own resource group needs to read from it."
|
|
36
|
+
default = "Deny"
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
variable "ip_rules" {
|
|
40
|
+
type = list(string)
|
|
41
|
+
description = "Public IPs/CIDRs allowed through the firewall (e.g. the operator machine running `tofu apply`, which needs data-plane access to write secrets). Forces public_network_access_enabled on when non-empty, since Azure ignores network_acls entirely while public access is off."
|
|
42
|
+
default = []
|
|
43
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
resource "azurerm_log_analytics_workspace" "this" {
|
|
2
|
+
name = "${var.project_name}-law"
|
|
3
|
+
resource_group_name = var.resource_group_name
|
|
4
|
+
location = var.location
|
|
5
|
+
sku = "PerGB2018"
|
|
6
|
+
retention_in_days = var.retention_days
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
resource "azurerm_application_insights" "this" {
|
|
10
|
+
name = "${var.project_name}-appi"
|
|
11
|
+
resource_group_name = var.resource_group_name
|
|
12
|
+
location = var.location
|
|
13
|
+
application_type = "web"
|
|
14
|
+
workspace_id = azurerm_log_analytics_workspace.this.id
|
|
15
|
+
daily_data_cap_in_gb = var.daily_data_cap_gb
|
|
16
|
+
retention_in_days = var.retention_days
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
resource "azurerm_portal_dashboard" "this" {
|
|
20
|
+
count = var.dashboard_count
|
|
21
|
+
name = "${var.project_name}-dashboard-${count.index + 1}"
|
|
22
|
+
resource_group_name = var.resource_group_name
|
|
23
|
+
location = var.location
|
|
24
|
+
|
|
25
|
+
dashboard_properties = jsonencode({
|
|
26
|
+
lenses = {}
|
|
27
|
+
metadata = {}
|
|
28
|
+
})
|
|
29
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
output "log_analytics_workspace_id" {
|
|
2
|
+
value = azurerm_log_analytics_workspace.this.id
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
output "instrumentation_key" {
|
|
6
|
+
value = azurerm_application_insights.this.instrumentation_key
|
|
7
|
+
sensitive = true
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
output "connection_string" {
|
|
11
|
+
value = azurerm_application_insights.this.connection_string
|
|
12
|
+
sensitive = true
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
output "app_insights_id" {
|
|
16
|
+
value = azurerm_application_insights.this.id
|
|
17
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
variable "project_name" {
|
|
2
|
+
type = string
|
|
3
|
+
description = "Project name, used to derive resource names"
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
variable "resource_group_name" {
|
|
7
|
+
type = string
|
|
8
|
+
description = "Resource group where the monitoring resources are created"
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
variable "location" {
|
|
12
|
+
type = string
|
|
13
|
+
description = "Azure region"
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
variable "daily_data_cap_gb" {
|
|
17
|
+
type = number
|
|
18
|
+
description = "Daily data ingestion cap in GB for Application Insights"
|
|
19
|
+
default = 1
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
variable "retention_days" {
|
|
23
|
+
type = number
|
|
24
|
+
description = "Data retention in days"
|
|
25
|
+
default = 90
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
variable "dashboard_count" {
|
|
29
|
+
type = number
|
|
30
|
+
description = "Number of portal dashboards to create"
|
|
31
|
+
default = 0
|
|
32
|
+
}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
# Keeps every database/cache reachable only from inside this VNet. Container Apps
|
|
2
|
+
# ingress stays public (Front Door needs a public origin) — this only closes off
|
|
3
|
+
# the data-plane services that have no reason to be reachable from the internet.
|
|
4
|
+
resource "azurerm_virtual_network" "this" {
|
|
5
|
+
name = "${var.project_name}-vnet"
|
|
6
|
+
resource_group_name = var.resource_group_name
|
|
7
|
+
location = var.location
|
|
8
|
+
address_space = var.address_space
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
resource "azurerm_subnet" "container_apps_infra" {
|
|
12
|
+
name = "${var.project_name}-cae-subnet"
|
|
13
|
+
resource_group_name = var.resource_group_name
|
|
14
|
+
virtual_network_name = azurerm_virtual_network.this.name
|
|
15
|
+
address_prefixes = var.container_apps_subnet_prefix
|
|
16
|
+
|
|
17
|
+
delegation {
|
|
18
|
+
name = "container-apps-environment"
|
|
19
|
+
service_delegation {
|
|
20
|
+
name = "Microsoft.App/environments"
|
|
21
|
+
actions = ["Microsoft.Network/virtualNetworks/subnets/join/action"]
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
# A subnet has no reliable outbound internet path of its own once placed in a custom
|
|
27
|
+
# VNet — Azure's "default outbound access" is being retired for newly created resources.
|
|
28
|
+
# Without this, every Container App revision hangs pulling its image (any image, from
|
|
29
|
+
# any registry) until the platform gives up ("Operation expired"). This is Microsoft's
|
|
30
|
+
# own recommended pattern for Container Apps in a BYO VNet.
|
|
31
|
+
resource "azurerm_public_ip" "container_apps_nat" {
|
|
32
|
+
name = "${var.project_name}-cae-nat-ip"
|
|
33
|
+
resource_group_name = var.resource_group_name
|
|
34
|
+
location = var.location
|
|
35
|
+
allocation_method = "Static"
|
|
36
|
+
sku = "Standard"
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
resource "azurerm_nat_gateway" "container_apps" {
|
|
40
|
+
name = "${var.project_name}-cae-nat"
|
|
41
|
+
resource_group_name = var.resource_group_name
|
|
42
|
+
location = var.location
|
|
43
|
+
sku_name = "Standard"
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
resource "azurerm_nat_gateway_public_ip_association" "container_apps" {
|
|
47
|
+
nat_gateway_id = azurerm_nat_gateway.container_apps.id
|
|
48
|
+
public_ip_address_id = azurerm_public_ip.container_apps_nat.id
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
resource "azurerm_subnet_nat_gateway_association" "container_apps" {
|
|
52
|
+
subnet_id = azurerm_subnet.container_apps_infra.id
|
|
53
|
+
nat_gateway_id = azurerm_nat_gateway.container_apps.id
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
# Postgres Flexible Server's private-access model is VNet integration (delegated_subnet_id
|
|
57
|
+
# + private_dns_zone_id directly on the server resource) rather than a standard Private
|
|
58
|
+
# Endpoint — it needs its own subnet delegated specifically to the Postgres RP.
|
|
59
|
+
resource "azurerm_subnet" "postgres" {
|
|
60
|
+
count = var.postgres_needed ? 1 : 0
|
|
61
|
+
|
|
62
|
+
name = "${var.project_name}-postgres-subnet"
|
|
63
|
+
resource_group_name = var.resource_group_name
|
|
64
|
+
virtual_network_name = azurerm_virtual_network.this.name
|
|
65
|
+
address_prefixes = var.postgres_subnet_prefix
|
|
66
|
+
|
|
67
|
+
delegation {
|
|
68
|
+
name = "postgres-flexible-server"
|
|
69
|
+
service_delegation {
|
|
70
|
+
name = "Microsoft.DBforPostgreSQL/flexibleServers"
|
|
71
|
+
actions = ["Microsoft.Network/virtualNetworks/subnets/join/action"]
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
# Azure SQL and Azure Managed Redis use standard Private Link — a plain (non-delegated)
|
|
77
|
+
# subnet with network policies disabled, shared across both.
|
|
78
|
+
resource "azurerm_subnet" "private_endpoints" {
|
|
79
|
+
count = (var.mssql_needed || var.redis_needed) ? 1 : 0
|
|
80
|
+
|
|
81
|
+
name = "${var.project_name}-pe-subnet"
|
|
82
|
+
resource_group_name = var.resource_group_name
|
|
83
|
+
virtual_network_name = azurerm_virtual_network.this.name
|
|
84
|
+
address_prefixes = var.private_endpoints_subnet_prefix
|
|
85
|
+
private_endpoint_network_policies = "Disabled"
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
resource "azurerm_private_dns_zone" "postgres" {
|
|
89
|
+
count = var.postgres_needed ? 1 : 0
|
|
90
|
+
|
|
91
|
+
name = "privatelink.postgres.database.azure.com"
|
|
92
|
+
resource_group_name = var.resource_group_name
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
resource "azurerm_private_dns_zone_virtual_network_link" "postgres" {
|
|
96
|
+
count = var.postgres_needed ? 1 : 0
|
|
97
|
+
|
|
98
|
+
name = "${var.project_name}-postgres-link"
|
|
99
|
+
resource_group_name = var.resource_group_name
|
|
100
|
+
private_dns_zone_name = azurerm_private_dns_zone.postgres[0].name
|
|
101
|
+
virtual_network_id = azurerm_virtual_network.this.id
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
resource "azurerm_private_dns_zone" "mssql" {
|
|
105
|
+
count = var.mssql_needed ? 1 : 0
|
|
106
|
+
|
|
107
|
+
name = "privatelink.database.windows.net"
|
|
108
|
+
resource_group_name = var.resource_group_name
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
resource "azurerm_private_dns_zone_virtual_network_link" "mssql" {
|
|
112
|
+
count = var.mssql_needed ? 1 : 0
|
|
113
|
+
|
|
114
|
+
name = "${var.project_name}-mssql-link"
|
|
115
|
+
resource_group_name = var.resource_group_name
|
|
116
|
+
private_dns_zone_name = azurerm_private_dns_zone.mssql[0].name
|
|
117
|
+
virtual_network_id = azurerm_virtual_network.this.id
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
resource "azurerm_private_dns_zone" "redis" {
|
|
121
|
+
count = var.redis_needed ? 1 : 0
|
|
122
|
+
|
|
123
|
+
name = "privatelink.redis.azure.net"
|
|
124
|
+
resource_group_name = var.resource_group_name
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
resource "azurerm_private_dns_zone_virtual_network_link" "redis" {
|
|
128
|
+
count = var.redis_needed ? 1 : 0
|
|
129
|
+
|
|
130
|
+
name = "${var.project_name}-redis-link"
|
|
131
|
+
resource_group_name = var.resource_group_name
|
|
132
|
+
private_dns_zone_name = azurerm_private_dns_zone.redis[0].name
|
|
133
|
+
virtual_network_id = azurerm_virtual_network.this.id
|
|
134
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
output "vnet_id" {
|
|
2
|
+
value = azurerm_virtual_network.this.id
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
output "container_apps_subnet_id" {
|
|
6
|
+
value = azurerm_subnet.container_apps_infra.id
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
# Static outbound IP for the Container Apps environment — useful for allowlisting this
|
|
10
|
+
# project's apps against third-party APIs/firewalls that require a fixed source IP.
|
|
11
|
+
output "container_apps_outbound_ip" {
|
|
12
|
+
value = azurerm_public_ip.container_apps_nat.ip_address
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
output "postgres_subnet_id" {
|
|
16
|
+
value = try(azurerm_subnet.postgres[0].id, null)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
output "private_endpoints_subnet_id" {
|
|
20
|
+
value = try(azurerm_subnet.private_endpoints[0].id, null)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
output "postgres_dns_zone_id" {
|
|
24
|
+
value = try(azurerm_private_dns_zone.postgres[0].id, null)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
output "mssql_dns_zone_id" {
|
|
28
|
+
value = try(azurerm_private_dns_zone.mssql[0].id, null)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
output "redis_dns_zone_id" {
|
|
32
|
+
value = try(azurerm_private_dns_zone.redis[0].id, null)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
# So callers can `depends_on = [module.network]` and be sure the VNet links (not just the
|
|
36
|
+
# zones) exist before creating a resource that needs private DNS resolution to work.
|
|
37
|
+
# Only includes links for zones actually created (postgres_needed/mssql_needed/redis_needed).
|
|
38
|
+
output "ready" {
|
|
39
|
+
value = compact([
|
|
40
|
+
try(azurerm_private_dns_zone_virtual_network_link.postgres[0].id, null),
|
|
41
|
+
try(azurerm_private_dns_zone_virtual_network_link.mssql[0].id, null),
|
|
42
|
+
try(azurerm_private_dns_zone_virtual_network_link.redis[0].id, null),
|
|
43
|
+
])
|
|
44
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
variable "project_name" {
|
|
2
|
+
type = string
|
|
3
|
+
description = "Used as a naming prefix for the VNet, subnets, and private DNS zones"
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
variable "resource_group_name" {
|
|
7
|
+
type = string
|
|
8
|
+
description = "Resource group where networking resources are created"
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
variable "location" {
|
|
12
|
+
type = string
|
|
13
|
+
description = "Azure region"
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
variable "address_space" {
|
|
17
|
+
type = list(string)
|
|
18
|
+
description = "VNet address space"
|
|
19
|
+
default = ["10.20.0.0/16"]
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
variable "container_apps_subnet_prefix" {
|
|
23
|
+
type = list(string)
|
|
24
|
+
description = "Subnet for the Container Apps environment's infrastructure. /23 minimum (Consumption-only environments require /23; a /27 workload-profile environment would fit too)."
|
|
25
|
+
default = ["10.20.0.0/23"]
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
variable "postgres_subnet_prefix" {
|
|
29
|
+
type = list(string)
|
|
30
|
+
description = "Subnet delegated to Microsoft.DBforPostgreSQL/flexibleServers. Shared by every Postgres flexible server in this project (Azure minimum is /28; sized larger for headroom)."
|
|
31
|
+
default = ["10.20.2.0/26"]
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
variable "private_endpoints_subnet_prefix" {
|
|
35
|
+
type = list(string)
|
|
36
|
+
description = "Subnet for standard Private Link endpoints (Azure SQL, Azure Managed Redis)."
|
|
37
|
+
default = ["10.20.3.0/26"]
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
variable "postgres_needed" {
|
|
41
|
+
type = bool
|
|
42
|
+
description = "Whether any app in this project uses the Postgres engine. Skips the delegated subnet + private DNS zone when false."
|
|
43
|
+
default = true
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
variable "mssql_needed" {
|
|
47
|
+
type = bool
|
|
48
|
+
description = "Whether any app in this project uses the mssql engine. Skips its private DNS zone when false."
|
|
49
|
+
default = true
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
variable "redis_needed" {
|
|
53
|
+
type = bool
|
|
54
|
+
description = "Whether any app in this project has Redis enabled. Skips its private DNS zone when false."
|
|
55
|
+
default = true
|
|
56
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
resource "random_password" "this" {
|
|
2
|
+
length = 24
|
|
3
|
+
special = true
|
|
4
|
+
override_special = "!#$%&*()-_=+[]{}<>:?"
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
locals {
|
|
8
|
+
effective_password = var.admin_password != "" ? var.admin_password : random_password.this.result
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
resource "azurerm_postgresql_flexible_server" "this" {
|
|
12
|
+
name = var.server_name
|
|
13
|
+
resource_group_name = var.resource_group_name
|
|
14
|
+
location = var.location
|
|
15
|
+
administrator_login = var.admin_username
|
|
16
|
+
administrator_password = local.effective_password
|
|
17
|
+
sku_name = var.sku_name
|
|
18
|
+
storage_mb = var.storage_mb
|
|
19
|
+
version = "16"
|
|
20
|
+
# zone intentionally not specified — let Azure choose.
|
|
21
|
+
|
|
22
|
+
# VNet-integrated instead of public: reachable only from the delegated subnet's VNet
|
|
23
|
+
# (the Container Apps environment lives there too), no public endpoint at all.
|
|
24
|
+
delegated_subnet_id = var.delegated_subnet_id
|
|
25
|
+
private_dns_zone_id = var.private_dns_zone_id
|
|
26
|
+
public_network_access_enabled = false
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
resource "azurerm_postgresql_flexible_server_database" "this" {
|
|
30
|
+
server_id = azurerm_postgresql_flexible_server.this.id
|
|
31
|
+
name = var.database_name
|
|
32
|
+
collation = "en_US.utf8"
|
|
33
|
+
charset = "UTF8"
|
|
34
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
output "fqdn" {
|
|
2
|
+
value = azurerm_postgresql_flexible_server.this.fqdn
|
|
3
|
+
description = "Fully qualified domain name of the PostgreSQL Flexible Server"
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
output "database_name" {
|
|
7
|
+
value = azurerm_postgresql_flexible_server_database.this.name
|
|
8
|
+
description = "Name of the PostgreSQL database"
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
output "admin_username" {
|
|
12
|
+
value = var.admin_username
|
|
13
|
+
description = "Administrator username for the PostgreSQL Flexible Server"
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
output "admin_password" {
|
|
17
|
+
value = local.effective_password
|
|
18
|
+
sensitive = true
|
|
19
|
+
description = "Effective administrator password for the PostgreSQL Flexible Server"
|
|
20
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
variable "server_name" {
|
|
2
|
+
description = "Name of the PostgreSQL Flexible Server. Must be globally unique."
|
|
3
|
+
type = string
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
variable "database_name" {
|
|
7
|
+
description = "Name of the PostgreSQL database"
|
|
8
|
+
type = string
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
variable "resource_group_name" {
|
|
12
|
+
description = "Name of the resource group where the server will be created"
|
|
13
|
+
type = string
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
variable "location" {
|
|
17
|
+
description = "Azure region where the server will be created"
|
|
18
|
+
type = string
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
variable "admin_username" {
|
|
22
|
+
description = "Administrator login for the PostgreSQL Flexible Server"
|
|
23
|
+
type = string
|
|
24
|
+
default = "pgadmin"
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
variable "admin_password" {
|
|
28
|
+
description = "Administrator password for the PostgreSQL Flexible Server. Leave empty to auto-generate."
|
|
29
|
+
type = string
|
|
30
|
+
default = ""
|
|
31
|
+
sensitive = true
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
variable "sku_name" {
|
|
35
|
+
description = "SKU name for the PostgreSQL Flexible Server"
|
|
36
|
+
type = string
|
|
37
|
+
default = "GP_Standard_D4s_v3"
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
variable "storage_mb" {
|
|
41
|
+
description = "Max storage allowed for the PostgreSQL Flexible Server, in MB"
|
|
42
|
+
type = number
|
|
43
|
+
default = 32768
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
variable "delegated_subnet_id" {
|
|
47
|
+
description = "Subnet delegated to Microsoft.DBforPostgreSQL/flexibleServers. Postgres Flexible Server's private-access model wires this directly on the server, not via a separate private endpoint."
|
|
48
|
+
type = string
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
variable "private_dns_zone_id" {
|
|
52
|
+
description = "Private DNS zone (privatelink.postgres.database.azure.com) linked to the same VNet as delegated_subnet_id."
|
|
53
|
+
type = string
|
|
54
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
resource "azurerm_managed_redis" "this" {
|
|
2
|
+
name = var.name
|
|
3
|
+
resource_group_name = var.resource_group_name
|
|
4
|
+
location = var.location
|
|
5
|
+
sku_name = var.sku_name
|
|
6
|
+
public_network_access = "Disabled"
|
|
7
|
+
|
|
8
|
+
default_database {
|
|
9
|
+
client_protocol = "Encrypted"
|
|
10
|
+
clustering_policy = "EnterpriseCluster"
|
|
11
|
+
eviction_policy = "VolatileLRU"
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
resource "azurerm_private_endpoint" "this" {
|
|
16
|
+
name = "${var.name}-pe"
|
|
17
|
+
resource_group_name = var.resource_group_name
|
|
18
|
+
location = var.location
|
|
19
|
+
subnet_id = var.private_endpoint_subnet_id
|
|
20
|
+
|
|
21
|
+
private_service_connection {
|
|
22
|
+
name = "${var.name}-psc"
|
|
23
|
+
private_connection_resource_id = azurerm_managed_redis.this.id
|
|
24
|
+
subresource_names = ["redisEnterprise"]
|
|
25
|
+
is_manual_connection = false
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
private_dns_zone_group {
|
|
29
|
+
name = "default"
|
|
30
|
+
private_dns_zone_ids = [var.private_dns_zone_id]
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
output "hostname" {
|
|
2
|
+
value = azurerm_managed_redis.this.hostname
|
|
3
|
+
description = "Hostname of the Azure Managed Redis instance"
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
output "ssl_port" {
|
|
7
|
+
value = azurerm_managed_redis.this.default_database[0].port
|
|
8
|
+
description = "TLS port of the Azure Managed Redis instance"
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
output "primary_access_key" {
|
|
12
|
+
value = azurerm_managed_redis.this.default_database[0].primary_access_key
|
|
13
|
+
sensitive = true
|
|
14
|
+
description = "Primary access key for the Azure Managed Redis default database"
|
|
15
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
variable "name" {
|
|
2
|
+
description = "Name of the Redis Enterprise cluster"
|
|
3
|
+
type = string
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
variable "resource_group_name" {
|
|
7
|
+
description = "Name of the resource group where the Redis Enterprise cluster will be created"
|
|
8
|
+
type = string
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
variable "location" {
|
|
12
|
+
description = "Azure region where the Redis Enterprise cluster will be created"
|
|
13
|
+
type = string
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
variable "sku_name" {
|
|
17
|
+
description = "SKU name for the Redis Enterprise cluster (Azure Managed Redis 'Balanced' tier, e.g. Balanced_B0, Balanced_B1, Balanced_B5)"
|
|
18
|
+
type = string
|
|
19
|
+
default = "Balanced_B0"
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
variable "private_endpoint_subnet_id" {
|
|
23
|
+
description = "Subnet for the Private Link endpoint (non-delegated, network policies disabled)"
|
|
24
|
+
type = string
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
variable "private_dns_zone_id" {
|
|
28
|
+
description = "Private DNS zone (privatelink.redis.azure.net) linked to the same VNet as private_endpoint_subnet_id"
|
|
29
|
+
type = string
|
|
30
|
+
}
|