Skip to content

Commit 10a7763

Browse files
committed
feat(keycloak): add placeholder env files for Keycloak and adjust permissions in agent config
1 parent 10e6e13 commit 10a7763

3 files changed

Lines changed: 61 additions & 74 deletions

File tree

README.md

Lines changed: 39 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -8,78 +8,6 @@ Currently using [OpenBao](https://openbao.org) and [OpenTofu](https://opentofu.o
88
99
---
1010

11-
## Repository Layout
12-
13-
```
14-
project-armory/
15-
├── vault/ # OpenTofu module — deploys Vault via podman compose
16-
│ ├── versions.tf
17-
│ ├── variables.tf
18-
│ ├── main.tf # TLS generation, config rendering, container lifecycle
19-
│ ├── outputs.tf
20-
│ ├── example.tfvars
21-
│ └── templates/
22-
│ ├── vault.hcl.tpl # Vault server config (raft storage, TLS listener, audit)
23-
│ └── compose.yml.tpl
24-
├── vault-config/ # OpenTofu module — configures Vault (PKI, secrets engines, auth)
25-
│ ├── versions.tf
26-
│ ├── variables.tf
27-
│ ├── pki.tf # Three-tier PKI hierarchy (root, internal, external CAs)
28-
│ ├── auth.tf # AppRole + userpass auth methods (userpass toggleable)
29-
│ ├── policies.tf # ACL policies: operator, kv_admin, kv_reader_keycloak, keycloak_db, app_db
30-
│ ├── audit.tf # Audit device note (OpenBao 2.x: declared in vault.hcl, not API)
31-
│ ├── kv.tf # KV v2 mount + Keycloak admin bootstrap secret
32-
│ ├── database.tf # Database secrets engine: Postgres connection, static + dynamic roles
33-
│ ├── oidc.tf # OIDC auth method backed by Keycloak (toggled by oidc_enabled)
34-
│ ├── outputs.tf
35-
│ └── example.tfvars
36-
├── services/
37-
│ ├── webserver/ # OpenTofu module — nginx + Vault Agent sidecar
38-
│ │ ├── main.tf # Vault policy, AppRole, dir scaffolding, compose deploy
39-
│ │ ├── templates/
40-
│ │ │ ├── agent.hcl.tpl # Vault Agent: AppRole + pkiCert
41-
│ │ │ ├── nginx.conf.tpl
42-
│ │ │ └── compose.yml.tpl
43-
│ │ └── ...
44-
│ ├── postgres/ # OpenTofu module — PostgreSQL container
45-
│ │ ├── main.tf # Dir scaffolding, config rendering, podman compose deploy
46-
│ │ ├── templates/
47-
│ │ │ ├── compose.yml.tpl # pg_isready healthcheck, armory-net
48-
│ │ │ └── init.sql.tpl # Creates databases, vault_mgmt role, template roles
49-
│ │ └── ...
50-
│ ├── keycloak/ # OpenTofu module — Keycloak + Vault Agent sidecar
51-
│ │ ├── main.tf # Vault policy, AppRole (PKI + DB + KV policies), compose deploy
52-
│ │ ├── templates/
53-
│ │ │ ├── agent.hcl.tpl # Vault Agent: pkiCert + DB static-creds + KV admin
54-
│ │ │ └── compose.yml.tpl # vault-agent + keycloak services
55-
│ │ └── ...
56-
│ └── agent/ # OpenTofu module + Python service — agentic layer
57-
│ ├── main.tf # AppRole secret_id issuance, credential files on disk
58-
│ ├── example.tfvars
59-
│ ├── tests/
60-
│ │ └── config.tftest.hcl # Module-level unit tests (mocked providers)
61-
│ └── agent/ # Python FastAPI service
62-
│ ├── api.py # FastAPI endpoint — Keycloak JWT validation, task dispatch
63-
│ ├── agent.py # Task runner — per-task Vault auth, request_id, audit trail
64-
│ ├── vault_client.py # Vault AppRole auth + dynamic DB credential helpers
65-
│ ├── oidc.py # Keycloak JWKS validation (authlib, TTL cache, azp check)
66-
│ ├── tools.py # Tool implementations (SELECT-only DB query)
67-
│ └── requirements.txt
68-
├── tests/ # End-to-end integration test suite
69-
│ ├── conftest.py # Session fixtures: full lifecycle management
70-
│ ├── test_tls.py
71-
│ ├── test_pki.py
72-
│ ├── test_auth.py
73-
│ ├── test_webserver.py
74-
│ ├── test_agent.py # Agent AppRole policy + credential lifecycle tests
75-
│ └── requirements.txt
76-
└── docs/
77-
├── ADR/ # Architecture Decision Records (ADR-001 through ADR-020)
78-
└── pki_workflows.md # Cryptographic material custody reference
79-
```
80-
81-
---
82-
8311
## Requirements
8412

8513
| Tool | Minimum version | Notes |
@@ -152,6 +80,9 @@ Configures PKI hierarchy, AppRole auth, userpass operator account, KV v2 engine
15280
> Vault immediately sets the initial credential. Roles are added in a re-apply after
15381
> Postgres is up (Phase 5b).
15482
83+
**Note:**
84+
After completing Phase 5 (Postgres deployment), you must re-apply the vault-config module with `database_roles_enabled=true` to enable Vault to create the database roles. See Phase 5b below for the exact command.
85+
15586
---
15687

15788
### Phase 4 — Deploy the webserver (optional demo)
@@ -200,6 +131,40 @@ tofu apply -var database_roles_enabled=true -auto-approve
200131

201132
This creates the Keycloak static role and the app dynamic role. Vault connects to Postgres immediately — the container must be healthy before running this step.
202133

134+
**Summary of steps:**
135+
1. Deploy Postgres (Phase 5)
136+
2. Re-apply vault-config with:
137+
```bash
138+
cd vault-config/
139+
export TF_VAR_vault_token=<ROOT_TOKEN>
140+
tofu apply -var database_roles_enabled=true -var agent_enabled=true -auto-approve
141+
```
142+
This enables Vault to create the required database roles.
143+
**Validation:** Confirm Vault issued database credentials
144+
145+
podman exec armory-vault bao list database/roles
146+
podman exec armory-vault bao read database/creds/keycloak
147+
podman exec armory-vault bao read database/creds/app
148+
**Note:** You must export the Vault root token (or a token with the correct database policy) before running these commands, or you will get 403 errors.
149+
150+
```bash
151+
export VAULT_TOKEN=<ROOT_TOKEN>
152+
153+
# List dynamic database roles (should show 'app')
154+
podman exec -e VAULT_TOKEN=$VAULT_TOKEN armory-vault bao list database/roles
155+
156+
# List static database roles (should show 'keycloak')
157+
podman exec -e VAULT_TOKEN=$VAULT_TOKEN armory-vault bao list database/static-roles
158+
159+
# Read credentials for the Keycloak static role (should show rotation info and username)
160+
podman exec -e VAULT_TOKEN=$VAULT_TOKEN armory-vault bao read database/static-roles/keycloak
161+
162+
# Read credentials for the app dynamic role (should return a username and password)
163+
podman exec -e VAULT_TOKEN=$VAULT_TOKEN armory-vault bao read database/creds/app
164+
```
165+
166+
If these commands return valid output for both roles, Phase 5b was successful and Vault is managing both dynamic and static database roles as intended.
167+
203168
---
204169

205170
### Phase 6 — Deploy Keycloak
@@ -259,6 +224,8 @@ export TF_VAR_vault_token=<ROOT_TOKEN>
259224
tofu apply -var agent_enabled=true -var database_roles_enabled=true
260225
```
261226

227+
This command ensures both the agent AppRole and the database roles are enabled in Vault. Both variables must be set to `true` when deploying the agentic layer.
228+
262229
**Step 2:** Issue credentials and scaffold host directories:
263230

264231
```bash

services/keycloak/main.tf

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,24 @@ resource "local_sensitive_file" "wrapped_secret_id" {
109109
content = vault_approle_auth_backend_role_secret_id.keycloak.wrapping_token
110110
}
111111

112+
# Placeholder env files must exist before podman-compose up — podman-compose
113+
# validates env_file paths before starting any container, including the
114+
# vault-agent that writes the real credentials. Vault-agent overwrites these;
115+
# the vault-agent healthcheck (test -s) blocks keycloak until they are non-empty.
116+
resource "local_file" "keycloak_env_placeholder" {
117+
depends_on = [null_resource.create_dirs]
118+
filename = "${local.dirs.secrets}/keycloak.env"
119+
file_permission = "0666"
120+
content = ""
121+
}
122+
123+
resource "local_file" "keycloak_admin_env_placeholder" {
124+
depends_on = [null_resource.create_dirs]
125+
filename = "${local.dirs.secrets}/keycloak-admin.env"
126+
file_permission = "0666"
127+
content = ""
128+
}
129+
112130
resource "local_file" "compose" {
113131
depends_on = [null_resource.create_dirs]
114132
filename = "${var.deploy_dir}/compose.yml"
@@ -139,6 +157,8 @@ resource "null_resource" "deploy" {
139157
depends_on = [
140158
local_file.agent_config,
141159
local_file.compose,
160+
local_file.keycloak_env_placeholder,
161+
local_file.keycloak_admin_env_placeholder,
142162
local_sensitive_file.role_id,
143163
local_sensitive_file.wrapped_secret_id,
144164
]

services/keycloak/templates/agent.hcl.tpl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ KC_DB_PASSWORD={{ .Data.password }}
4949
{{- end }}
5050
EOT
5151
destination = "/vault/secrets/keycloak.env"
52-
perms = "0640"
52+
perms = "0644"
5353
}
5454

5555
# ---------------------------------------------------------------------------
@@ -64,5 +64,5 @@ KC_BOOTSTRAP_ADMIN_PASSWORD={{ .Data.data.password }}
6464
{{- end }}
6565
EOT
6666
destination = "/vault/secrets/keycloak-admin.env"
67-
perms = "0640"
67+
perms = "0644"
6868
}

0 commit comments

Comments
 (0)