Skip to content

Remove default credentials from gateway and use file config interpolation for encryption key #2853

Merged
renuka-fernando merged 3 commits into
wso2:mainfrom
thivindu:config-interpolation
Jul 24, 2026
Merged

Remove default credentials from gateway and use file config interpolation for encryption key #2853
renuka-fernando merged 3 commits into
wso2:mainfrom
thivindu:config-interpolation

Conversation

@thivindu

@thivindu thivindu commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Purpose

Two related fixes that stop shipping guessable/hardcoded secrets and move them to provisioned, interpolated sources:

  1. Gateway - removes the hardcoded admin:admin basic-auth credential from the gateway-controller REST/management API. The credential is now provisioned by setup.sh and injected via config interpolation, with fail-closed startup validation.
  2. Platform API - switches the at-rest encryption_key from an environment variable to a mounted file ({{ file }} interpolation), generated by setup.sh and mounted by the composes.

Neither service ships a usable default secret anymore; both fail closed if the secret is absent.


Fix 1 — Remove hardcoded admin:admin from the gateway-controller

Problem

gateway/configs/config.toml shipped a functional admin/admin basic-auth user, and every example/curl embedded Authorization: Basic YWRtaW46YWRtaW4=. A default credential present in every install is effectively no authentication.

Change

  • configs/config.toml / config-template.toml: the admin user is now interpolated, with no shipped default and password_hashed = true:
    username = '{{ env "APIP_GW_CONTROLLER_AUTH_BASIC_ADMIN_USERNAME" "" }}'
    password = '{{ env "APIP_GW_CONTROLLER_AUTH_BASIC_ADMIN_PASSWORD_HASH" "" }}'
  • scripts/setup.sh: prompts for (or reads ADMIN_USERNAME/ADMIN_PASSWORD from the env for CI), bcrypt-hashes the password, writes APIP_GW_CONTROLLER_AUTH_BASIC_ADMIN_USERNAME + APIP_GW_CONTROLLER_AUTH_BASIC_ADMIN_PASSWORD_HASH into api-platform.env, and prints the plaintext once.
  • Fail-closed validation (pkg/config/config.go validateAuthConfig): basic auth enabled with an empty username/password now refuses to start rather than silently degrading to the no-auth passthrough. common/authenticators/authn.go logs a one-time warning when it does run with no authenticators.
  • Example/perf scripts (examples/seed.py, cleanup.py, curls, perf/…) now read ADMIN_USERNAME/ADMIN_PASSWORD from the environment.

Fix 2 — Platform API: read the encryption key from a file, not an env var (closes #2835)

Problem

platform_api.security.encryption_key used {{ env "APIP_CP_ENCRYPTION_KEY" }}, forcing operators to generate and paste the key into an environment variable.

Change

  • platform-api/config/config.toml:
    encryption_key = '{{ file "/etc/platform-api/keys/encryption.key" }}'
  • (/etc/platform-api is already on the platform-api {{ file }} allowlist; {{ file }} trims the trailing newline, so openssl rand -hex 32 > file works directly.)
  • All three deployment paths that mount the shipped config now generate + mount the key file:
    • portals/ai-workspace/setup.sh & portals/developer-portal/scripts/setup.sh — write resources/keys/encryption.key (dropped the env-var write).
    • distribution/all-in-one/docker-compose.yaml — the keygen init container also writes /keys/encryption.key (owned by uid 10001, chmod 0600); dropped the APIP_CP_ENCRYPTION_KEY env line.
    • portals/developer-portal/docker-compose.platform-api.yaml — added the previously-missing resources/keys mount.

@coderabbitai

coderabbitai Bot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Gateway Basic Auth is now provisioned through setup.sh, stored as a bcrypt hash, and validated at startup. Platform API encryption keys are generated and mounted as files. Documentation, workflows, examples, samples, and runtime configurations now use the updated credential and key-management flows.

Changes

Gateway security and key provisioning

Layer / File(s) Summary
Gateway admin credential provisioning and validation
.agents/skills/*, .github/workflows/perf-gateway.yml, gateway/configs/*, gateway/scripts/setup.sh, gateway/gateway-controller/*, event-gateway/*, gateway/perf/*
Gateway Basic Auth credentials are supplied through environment variables, hashed during setup, persisted in api-platform.env, and rejected when configured credentials are empty.
Platform API file-based encryption keys
distribution/all-in-one/*, platform-api/config/*, portals/*, docs/ai-workspace/*, *.github/workflows/*
Platform API encryption keys are generated under resources/keys, mounted into services, and loaded with {{ file }} interpolation instead of the primary environment variable path.
Authenticated API examples and sample scripts
docs/ai-gateway/*, docs/gateway/*, samples/*
Management API examples and sample scripts derive Basic Auth from ADMIN_USERNAME and ADMIN_PASSWORD rather than hardcoded encoded credentials.
Runtime defaults and resource alignment
common/authenticators/authn.go, gateway/docker-compose.yaml
No-auth middleware logs its effective authentication behavior, and gateway service resource allocations are increased.

Estimated code review effort: 4 (Complex) | ~45 minutes

Possibly related PRs

Suggested reviewers: ashera96, malinthaprasan, tharindu1st

🚥 Pre-merge checks | ✅ 2 | ❌ 3

❌ Failed checks (3 warnings)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning The gateway default-credential work and related docs/scripts go beyond linked issue #2835, which only requested file interpolation for the encryption key. Either add linked issues for the gateway credential changes or split them into a separate PR focused solely on #2835.
Docstring Coverage ⚠️ Warning Docstring coverage is 46.15% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ⚠️ Warning The description covers the purpose and implementation broadly, but most required template sections—goals, approach, tests, security, samples, and environment—are missing. Add the missing template sections with concise details for goals, approach, user stories, docs, automation tests, security checks, samples, related PRs, and test environment.
✅ Passed checks (2 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Issue #2835's file-based encryption key requirement is implemented via config, setup scripts, and compose mounts.
Title check ✅ Passed The title accurately summarizes the two main changes: removing default gateway credentials and switching encryption key handling to file interpolation.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 16

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/ai-workspace-pr-check.yml:
- Around line 59-61: Remove the fixed admin/admin credential from the workflow
setup described by the surrounding comments. Update the adjacent setup
invocation to generate a unique password per run, pass that value through the
job environment or Cypress configuration, and revise the documentation so it no
longer advertises reusable credentials.

In `@common/authenticators/authn.go`:
- Around line 82-83: Update the no-auth configuration branch in the
authenticator initialization flow around the warning log to require an explicit
development/test opt-out before permitting unauthenticated admin access. If that
opt-out is absent, fail startup instead of continuing; preserve the warning only
for the explicitly permitted opt-out path and ensure authentication remains fail
closed by default.

In `@distribution/all-in-one/docker-compose.yaml`:
- Around line 106-117: Update the initialization flow around the existing
jwt_private.pem, jwt_public.pem, and encryption.key checks so each missing
artifact is generated independently without overwriting an existing JWT keypair.
Preserve existing JWT files when present, generate only absent files, and always
apply the required ownership and 0600 modes afterward to the generated or
existing private/encryption keys.

In `@docs/ai-gateway/mcp/quick-start-guide.md`:
- Around line 58-61: Add a trailing backslash to the curl command in the
quick-start example so the following heredoc and --data-binary argument remain
part of the same command.

In `@docs/ai-workspace/features/secrets-management.md`:
- Around line 350-351: Update the preceding encryption-key configuration
guidance to make the setup-provisioned mounted file at
resources/keys/encryption.key the Docker Compose default. Reframe
APIP_CP_ENCRYPTION_KEY as an alternative configuration path rather than a
required, never-auto-generated variable, and ensure the instructions match what
the shipped Compose config reads.

In `@event-gateway/docker-compose.test.postgres.yaml`:
- Around line 60-61: Remove the hardcoded values from
APIP_GW_CONTROLLER_AUTH_BASIC_ADMIN_USERNAME and
APIP_GW_CONTROLLER_AUTH_BASIC_ADMIN_PASSWORD_HASH in the test Compose
configuration. Require both credentials to come from externally supplied or
generated environment values, configured so startup fails when either is absent.

In `@event-gateway/docker-compose.test.sqlserver.yaml`:
- Around line 80-81: Remove the hardcoded admin username and bcrypt password
hash from the test SQL Server compose configuration, and require both values
through environment-variable substitution without functional defaults. Update
the relevant APIP_GW_CONTROLLER_AUTH_BASIC_ADMIN_USERNAME and
APIP_GW_CONTROLLER_AUTH_BASIC_ADMIN_PASSWORD_HASH entries while preserving the
existing variable names expected by the gateway.

In `@gateway/distribution/README.md`:
- Around line 45-47: Update the startup-failure statement in
gateway/distribution/README.md lines 45-47 to state that the controller refuses
to start without credentials only when Basic Auth is enabled; apply the same
qualification to the corresponding statement in gateway/README.md lines 47-49,
keeping both READMEs consistent.

In `@gateway/gateway-controller/pkg/config/config.go`:
- Around line 1894-1904: Update the Basic Auth validation in
gateway/gateway-controller/pkg/config/config.go around the enabled-auth check to
return a startup error when len(c.Controller.Auth.Basic.Users) is zero, while
preserving validation of empty usernames or passwords for configured users. Add
or update the corresponding validator test in
gateway/gateway-controller/pkg/config/validator_test.go to assert that enabled
Basic Auth with no users is rejected.

In `@platform-api/config/config-template.toml`:
- Around line 39-41: Correct the encryption-key setup guidance near the
`encryption_key` configuration: either change the empty `encryption_key` value
to use the documented `file` interpolation token for
`/etc/platform-api/keys/encryption.key`, or revise the preceding instructions to
tell users to replace the empty value manually. Ensure the template instructions
match the actual configuration behavior.

In `@portals/ai-workspace/distribution/README.md`:
- Line 44: Add resources/keys/encryption.key to the setup-output table in the
README, alongside the other generated and persisted secrets, and describe it as
the Platform API encryption key that must be retained.

In `@portals/ai-workspace/setup.sh`:
- Around line 130-135: Update the encryption key setup in setup.sh to avoid
world-readable permissions: replace the 644 mode on "$KEYS_DIR/encryption.key"
with a restrictive service-readable ownership and mode, such as 640 with the
appropriate group or 600 when the container UID owns the file. Preserve
readability by the Platform API service.
- Around line 130-134: The provisioning block that writes encryption.key must
preserve an existing key across setup reruns. Update the openssl generation
around KEYS_DIR/encryption.key to create the file only when absent, while
retaining the existing key; allow replacement only through the explicit
force/rotation path documented in the workspace README.

In `@samples/ai-app-claude-code/setup.sh`:
- Around line 73-76: Remove all admin/admin credential fallbacks and references.
In samples/ai-app-claude-code/setup.sh lines 73-76, require or use
explicit/generated credentials and recompute AUTH_HEADER after they are
available; also remove its Basic Auth fallback at line 14. Update
docs/gateway/kubernetes/gateway-operator.md lines 712-723 and
docs/gateway/kubernetes/kubernetes-standalone.md lines 206-217 to describe
provisioned credentials instead of chart-default admin/admin values. In
samples/ai-agent-with-mcp/configure-gateway.sh line 25,
samples/ai-app-claude-code/teardown.sh line 12,
samples/ai-gw-llm-proxy/inject-mock.sh line 27, and
samples/ai-gw-mcp-claude-desktop/inject-mock.sh line 26, require or source
explicit/generated credentials rather than silently defaulting.

In `@samples/llm-cost-control-and-privacy-control/setup.sh`:
- Line 14: Strip carriage returns and newlines from the base64 output used to
build AUTH_HEADER, ensuring long credentials remain on one line. Apply this
change at the AUTH_HEADER assignments in
samples/llm-cost-control-and-privacy-control/setup.sh (14-14),
samples/llm-cost-control-and-privacy-control/teardown.sh (12-12),
samples/prompt-decorator-policy/setup.sh (14-14), and
samples/prompt-decorator-policy/teardown.sh (12-12).
- Around line 151-154: Remove all known default administrative credentials and
require securely supplied credentials throughout the affected setup, teardown,
workflow, documentation, and skill instructions. In
samples/llm-cost-control-and-privacy-control/setup.sh lines 151-154 and
samples/prompt-decorator-policy/setup.sh lines 80-83, eliminate admin/admin
fallbacks; in both setup.sh line 14 sites and teardown.sh line 12 sites, require
and reuse credential variables for authentication and cleanup. Replace
perf-admin in .github/workflows/perf-gateway.yml lines 13-16 with a masked
secret or per-run credential, update .agents/skills/gateway-debug/SKILL.md lines
120-128 and 383 to describe variable-based authentication, and remove documented
admin/admin defaults from both README sites.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 491fc384-c122-496a-a8ed-38dd24fa5d4e

📥 Commits

Reviewing files that changed from the base of the PR and between 1e85434 and b390e4c.

📒 Files selected for processing (66)
  • .agents/skills/gateway-debug/SKILL.md
  • .agents/skills/gateway-integration-tests/SKILL.md
  • .github/workflows/ai-workspace-pr-check.yml
  • .github/workflows/perf-gateway.yml
  • common/authenticators/authn.go
  • distribution/all-in-one/docker-compose.yaml
  • docs/ai-gateway/llm/guardrails/aws-bedrock-guardrail.md
  • docs/ai-gateway/llm/guardrails/azure-content-safety.md
  • docs/ai-gateway/llm/guardrails/content-length.md
  • docs/ai-gateway/llm/guardrails/json-schema.md
  • docs/ai-gateway/llm/guardrails/pii-masking-regex.md
  • docs/ai-gateway/llm/guardrails/regex.md
  • docs/ai-gateway/llm/guardrails/semantic-prompt-guard.md
  • docs/ai-gateway/llm/guardrails/sentence-count.md
  • docs/ai-gateway/llm/guardrails/url.md
  • docs/ai-gateway/llm/guardrails/word-count.md
  • docs/ai-gateway/llm/llm-templates.md
  • docs/ai-gateway/llm/load-balancing/model-round-robin.md
  • docs/ai-gateway/llm/load-balancing/model-weighted-round-robin.md
  • docs/ai-gateway/llm/prompt-management/prompt-decorator.md
  • docs/ai-gateway/llm/prompt-management/prompt-template.md
  • docs/ai-gateway/llm/quick-start-guide.md
  • docs/ai-gateway/llm/semantic-caching.md
  • docs/ai-gateway/mcp/quick-start-guide.md
  • docs/ai-workspace/configuration.md
  • docs/ai-workspace/features/secrets-management.md
  • docs/gateway/bottom-up-api-deployment-guide.md
  • docs/gateway/kubernetes/gateway-operator.md
  • docs/gateway/kubernetes/kubernetes-standalone.md
  • docs/gateway/quick-start-guide.md
  • event-gateway/docker-compose.test.postgres.yaml
  • event-gateway/docker-compose.test.sqlserver.yaml
  • gateway/README.md
  • gateway/configs/config-template.toml
  • gateway/configs/config.toml
  • gateway/distribution/README.md
  • gateway/docker-compose.yaml
  • gateway/gateway-controller/README.md
  • gateway/gateway-controller/authentication.md
  • gateway/gateway-controller/pkg/config/config.go
  • gateway/gateway-controller/pkg/config/interpolate_test.go
  • gateway/gateway-controller/pkg/config/validator_test.go
  • gateway/perf/create_apis_and_capture_stats.sh
  • gateway/scripts/setup.sh
  • platform-api/README.md
  • platform-api/config/config-template.toml
  • platform-api/config/config.toml
  • platform-api/config/config_test.go
  • portals/ai-workspace/README.md
  • portals/ai-workspace/distribution/README.md
  • portals/ai-workspace/production/README.md
  • portals/ai-workspace/setup.sh
  • portals/developer-portal/distribution/README.md
  • portals/developer-portal/docker-compose.platform-api.yaml
  • portals/developer-portal/scripts/setup.sh
  • samples/ai-agent-with-mcp/configure-gateway.sh
  • samples/ai-app-claude-code/setup.sh
  • samples/ai-app-claude-code/teardown.sh
  • samples/ai-gw-llm-proxy/inject-mock.sh
  • samples/ai-gw-mcp-claude-desktop/inject-mock.sh
  • samples/llm-cost-control-and-privacy-control/README.md
  • samples/llm-cost-control-and-privacy-control/setup.sh
  • samples/llm-cost-control-and-privacy-control/teardown.sh
  • samples/prompt-decorator-policy/README.md
  • samples/prompt-decorator-policy/setup.sh
  • samples/prompt-decorator-policy/teardown.sh

Comment thread .github/workflows/ai-workspace-pr-check.yml
Comment thread common/authenticators/authn.go
Comment thread distribution/all-in-one/docker-compose.yaml Outdated
Comment thread docs/ai-gateway/mcp/quick-start-guide.md
Comment thread docs/ai-workspace/features/secrets-management.md Outdated
Comment thread portals/ai-workspace/setup.sh Outdated
Comment thread portals/ai-workspace/setup.sh Outdated
Comment thread samples/ai-app-claude-code/setup.sh
Comment thread samples/llm-cost-control-and-privacy-control/setup.sh Outdated
Comment thread samples/llm-cost-control-and-privacy-control/setup.sh
@renuka-fernando
renuka-fernando merged commit f29ebf5 into wso2:main Jul 24, 2026
19 of 20 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Task]: Use file config interpolation for encryption key

2 participants