Skip to content

Removed hardcoded secrets#121

Merged
raphael-frank merged 11 commits into
mainfrom
infra/120-remove-hardcode-secrets
Jul 9, 2026
Merged

Removed hardcoded secrets#121
raphael-frank merged 11 commits into
mainfrom
infra/120-remove-hardcode-secrets

Conversation

@f-s-h

@f-s-h f-s-h commented Jul 8, 2026

Copy link
Copy Markdown
Collaborator

Removed hardcoded secrets and created a .env file for local development and github secrets for deployment.

Closes #120

Summary by CodeRabbit

  • New Features
    • Enhanced VM and Kubernetes deployments with deploy-time secret injection for databases, Keycloak, Grafana OAuth, and forward-auth.
    • Added compose environment-file generation and automated Keycloak realm config templating during deploy/start.
  • Bug Fixes
    • Improved database initialization resilience to handle fresh deployments where cross-schema tables may not be ready yet.
  • Security / Hardening
    • Applied stronger Kubernetes runtime hardening (RuntimeDefault seccomp, disabled service account token automount, standardized container security contexts) across monitored and core components.
  • Documentation
    • Expanded README and local environment examples to clarify the single source of truth for secrets and placeholder behavior.

@f-s-h
f-s-h requested a review from raphael-frank July 8, 2026 20:03
@coderabbitai

coderabbitai Bot commented Jul 8, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The PR externalizes deployment secrets across Compose, Helm, CI/CD, and docs, adds shared Kubernetes security-context hardening, and changes py-genai-helper database initialization to retry when tables are not yet available.

Changes

Secret externalization across compose, Helm, CI/CD, and docs

Layer / File(s) Summary
Docker Compose environment sourcing
infra/docker-compose.yml, infra/docker-compose.override.yml
Service database passwords and auth secrets switch to environment variables; Keycloak now renders a realm template at startup, and the Keycloak volume mount points at the template file.
Keycloak realm placeholder substitution
infra/keycloak/realm-config.json, infra/helm/team-devoops/files/realm-config.json, infra/helm/team-devoops/templates/keycloak-realm-configmap.yaml
Keycloak realm password and client-secret literals are replaced with placeholder tokens, and the Helm ConfigMap substitutes those placeholders from chart values.
Helm values defaults removed
infra/helm/team-devoops/values.yaml, services/spring-member/src/main/resources/application.properties, services/spring-organization/src/main/resources/application.properties
Database, Keycloak, and forward-auth secret defaults become explicit placeholders, and the organization/member services are updated to read the new Keycloak secret values.
Ansible and CI/CD secret wiring
infra/ansible/playbook.yml, .github/workflows/cd.yml, README.md, infra/.env.example, services/spring-letter/.env.example
The workflow writes and passes a compose env file, Ansible copies it onto the VM target, Helm upgrade receives secret-backed values, and docs plus the local env examples describe the required variables.

Kubernetes pod security hardening

Layer / File(s) Summary
Shared container security helper
infra/helm/team-devoops/templates/_helpers.tpl
A reusable Helm helper adds container security defaults for privilege escalation, dropped capabilities, and optional runtime user settings.
Workload security contexts
infra/helm/team-devoops/templates/alloy-deployment.yaml, infra/helm/team-devoops/templates/forward-auth.yaml, infra/helm/team-devoops/templates/grafana-deployment.yaml, infra/helm/team-devoops/templates/keycloak-deployment.yaml, infra/helm/team-devoops/templates/keycloak-postgres-statefulset.yaml, infra/helm/team-devoops/templates/loki-deployment.yaml, infra/helm/team-devoops/templates/ollama-deployment.yaml, infra/helm/team-devoops/templates/postgres-statefulset.yaml, infra/helm/team-devoops/templates/prometheus-deployment.yaml, infra/helm/team-devoops/templates/deployment.yaml
Multiple Helm workloads add pod-level seccomp settings, selected service-account token disabling, and container-level security contexts via the shared helper, with workload-specific non-root settings.

py-genai-helper database initialization retry

Layer / File(s) Summary
Retryable DB initialization
services/py-genai-helper/db.py
Report table creation moves into a private helper, and startup now retries table creation until a deadline when the underlying PostgreSQL error indicates missing tables.
Estimated code review effort: 5 (Critical) ~90 minutes

Possibly related PRs

Suggested labels: build

Suggested reviewers: raphael-frank

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning The PR includes unrelated security hardening, resource-limit, and DB retry changes beyond removing hardcoded secrets. Move the Helm securityContext, resource, and DB retry updates to separate PRs unless they are explicitly part of the intended scope.
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is concise and accurately summarizes the main change: removing hardcoded secrets.
Linked Issues check ✅ Passed The changes replace hardcoded credentials with env vars and GitHub secrets across deploy targets and local examples, matching issue #120.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch infra/120-remove-hardcode-secrets

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.

Comment thread infra/helm/team-devoops/values.yaml Fixed
Comment thread infra/helm/team-devoops/values.yaml Fixed
Comment thread infra/helm/team-devoops/values.yaml Fixed
Comment thread infra/helm/team-devoops/values.yaml Fixed
Comment thread infra/helm/team-devoops/values.yaml Fixed
Comment thread infra/helm/team-devoops/values.yaml Fixed
Comment thread infra/helm/team-devoops/values.yaml Fixed
Comment thread infra/helm/team-devoops/values.yaml Fixed
Comment thread infra/helm/team-devoops/values.yaml Fixed
Comment thread infra/helm/team-devoops/values.yaml Fixed

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 7

🧹 Nitpick comments (1)
infra/ansible/playbook.yml (1)

86-93: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win

Suppress Ansible logging for the secret copy task.

Add no_log: true so compose secrets cannot appear in verbose or diff output.

Proposed change
     - name: Write compose .env file
       copy:
         src: "{{ compose_env_file }}"
         dest: "{{ app_dir }}/infra/.env"
         mode: "0600"
         owner: "{{ ansible_user }}"
         group: "{{ ansible_user }}"
+      no_log: true
🤖 Prompt for 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.

In `@infra/ansible/playbook.yml` around lines 86 - 93, The Write compose .env file
task in the playbook should suppress sensitive output so secrets do not leak in
Ansible logs. Update the copy task for the compose env file to use no_log: true,
keeping the existing behavior in place while preventing verbose or diff output
from exposing secrets.
🤖 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/cd.yml:
- Around line 33-64: The compose .env writer in the cd workflow is missing
required secrets, so values in infra/docker-compose.yml can fall back to
defaults. Update the “Write compose .env file” step to include
GRAFANA_OAUTH_CLIENT_SECRET and FORWARD_AUTH_CLIENT_SECRET alongside the
existing secret exports, using the same secret-to-env pattern as the other
variables. Also add a simple validation in that step to fail fast if any
required compose secret is empty before writing /tmp/compose.env.
- Around line 289-300: The Helm deploy step is using --set for secret-backed
password inputs, which can still be type-inferred or mangled before templating;
update the affected entries in the deploy command to use --set-string for the
database and keycloak password flags referenced in the workflow snippet. If any
of these secrets may contain commas or other special characters, prefer passing
them through a temporary values file instead of inline CLI flags.

In `@infra/.env.example`:
- Around line 9-21: Replace the hardcoded sample credentials in
infra/.env.example with non-reusable placeholders, especially
FORWARD_AUTH_COOKIE_SECRET and the password entries. Update the examples to use
blanks or <generate-random> style values and add a brief note that each
developer/environment must supply its own secrets locally. Keep the changes
within the existing environment variable list so the file remains an example
only.

In `@infra/docker-compose.yml`:
- Line 300: The Grafana and Traefik OAuth secret fallbacks are still hardcoded
in the docker-compose configuration, so remove the default values from the
GF_AUTH_GENERIC_OAUTH_CLIENT_SECRET and Traefik forward auth secret references.
Update the compose setup to use required environment interpolation for both
secrets and make sure the workflow writes them into compose.env from GitHub
Secrets, using the existing Grafana and Traefik secret variables as the points
to update.
- Around line 431-433: The realm-config render step in the docker-compose
Keycloak import command is doing raw sed substitution, which can break on
passwords containing /, &, quotes, or backslashes. Update the Keycloak realm
rendering flow to use a JSON-aware templating/rendering approach, or explicitly
escape the secret values before substitution, and make sure the replacement
logic in the existing sed-based import command no longer writes invalid JSON.

In `@infra/helm/team-devoops/templates/keycloak-realm-configmap.yaml`:
- Around line 10-11: The Keycloak realm payload is being rendered in the
ConfigMap via the keycloak-realm-configmap template, which exposes admin/user
passwords and can break JSON when values contain special characters. Move the
rendered realm JSON generation out of the ConfigMap into a Secret, and update
the Keycloak mount/reference to read from that Secret instead. Use the existing
keycloak-realm-config template and the realm-config.json rendering path as the
main locations to adjust, keeping the ConfigMap free of secret material.

In `@infra/helm/team-devoops/values.yaml`:
- Around line 251-252: The forward-auth OIDC client secret still has a hardcoded
default, so it needs to be treated like the cookie secret and injected at deploy
time instead. Update the forward-auth configuration in values.yaml to remove the
default for forwardAuth.clientSecret and wire it from a GitHub Secret alongside
the existing deploy-time secret handling, using the forwardAuth.* settings to
locate the affected config.

---

Nitpick comments:
In `@infra/ansible/playbook.yml`:
- Around line 86-93: The Write compose .env file task in the playbook should
suppress sensitive output so secrets do not leak in Ansible logs. Update the
copy task for the compose env file to use no_log: true, keeping the existing
behavior in place while preventing verbose or diff output from exposing secrets.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 3cdf96bb-d78a-40c5-b7c4-173ec900e679

📥 Commits

Reviewing files that changed from the base of the PR and between 394ec6a and 47570f0.

📒 Files selected for processing (10)
  • .github/workflows/cd.yml
  • README.md
  • infra/.env.example
  • infra/ansible/playbook.yml
  • infra/docker-compose.override.yml
  • infra/docker-compose.yml
  • infra/helm/team-devoops/files/realm-config.json
  • infra/helm/team-devoops/templates/keycloak-realm-configmap.yaml
  • infra/helm/team-devoops/values.yaml
  • infra/keycloak/realm-config.json

Comment thread .github/workflows/cd.yml
Comment on lines +33 to +64
- name: Write compose .env file
env:
POSTGRES_PASSWORD: ${{ secrets.DB_ADMIN_PASSWORD }}
ORGANIZATION_DB_PASSWORD: ${{ secrets.DB_ORGANIZATION_PASSWORD }}
MEMBER_DB_PASSWORD: ${{ secrets.DB_MEMBER_PASSWORD }}
EVENT_DB_PASSWORD: ${{ secrets.DB_EVENT_PASSWORD }}
FEEDBACK_DB_PASSWORD: ${{ secrets.DB_FEEDBACK_PASSWORD }}
FINANCE_DB_PASSWORD: ${{ secrets.DB_FINANCE_PASSWORD }}
LETTER_DB_PASSWORD: ${{ secrets.DB_LETTER_PASSWORD }}
REPORTS_DB_PASSWORD: ${{ secrets.DB_REPORTS_PASSWORD }}
KEYCLOAK_ADMIN_PASSWORD: ${{ secrets.KEYCLOAK_ADMIN_PASSWORD }}
KEYCLOAK_DB_PASSWORD: ${{ secrets.KEYCLOAK_DB_PASSWORD }}
KEYCLOAK_REALM_ADMIN_PASSWORD: ${{ secrets.KEYCLOAK_REALM_ADMIN_PASSWORD }}
KEYCLOAK_REALM_USER_PASSWORD: ${{ secrets.KEYCLOAK_REALM_USER_PASSWORD }}
FORWARD_AUTH_COOKIE_SECRET: ${{ secrets.FORWARD_AUTH_COOKIE_SECRET }}
run: |
cat > /tmp/compose.env << ENVFILE
POSTGRES_PASSWORD=$POSTGRES_PASSWORD
ORGANIZATION_DB_PASSWORD=$ORGANIZATION_DB_PASSWORD
MEMBER_DB_PASSWORD=$MEMBER_DB_PASSWORD
EVENT_DB_PASSWORD=$EVENT_DB_PASSWORD
FEEDBACK_DB_PASSWORD=$FEEDBACK_DB_PASSWORD
FINANCE_DB_PASSWORD=$FINANCE_DB_PASSWORD
LETTER_DB_PASSWORD=$LETTER_DB_PASSWORD
REPORTS_DB_PASSWORD=$REPORTS_DB_PASSWORD
KEYCLOAK_ADMIN_PASSWORD=$KEYCLOAK_ADMIN_PASSWORD
KEYCLOAK_DB_PASSWORD=$KEYCLOAK_DB_PASSWORD
KEYCLOAK_REALM_ADMIN_PASSWORD=$KEYCLOAK_REALM_ADMIN_PASSWORD
KEYCLOAK_REALM_USER_PASSWORD=$KEYCLOAK_REALM_USER_PASSWORD
FORWARD_AUTH_COOKIE_SECRET=$FORWARD_AUTH_COOKIE_SECRET
ENVFILE

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Write and validate all Compose secrets.

This file omits GRAFANA_OAUTH_CLIENT_SECRET and FORWARD_AUTH_CLIENT_SECRET, so Compose falls back to the literal defaults in infra/docker-compose.yml. Add those secrets and fail fast if any required value is empty.

🤖 Prompt for 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.

In @.github/workflows/cd.yml around lines 33 - 64, The compose .env writer in
the cd workflow is missing required secrets, so values in
infra/docker-compose.yml can fall back to defaults. Update the “Write compose
.env file” step to include GRAFANA_OAUTH_CLIENT_SECRET and
FORWARD_AUTH_CLIENT_SECRET alongside the existing secret exports, using the same
secret-to-env pattern as the other variables. Also add a simple validation in
that step to fail fast if any required compose secret is empty before writing
/tmp/compose.env.

Comment thread .github/workflows/cd.yml
Comment on lines +289 to +300
--set database.password="${{ secrets.DB_ADMIN_PASSWORD }}" \
--set database.users.organization.password="${{ secrets.DB_ORGANIZATION_PASSWORD }}" \
--set database.users.member.password="${{ secrets.DB_MEMBER_PASSWORD }}" \
--set database.users.event.password="${{ secrets.DB_EVENT_PASSWORD }}" \
--set database.users.feedback.password="${{ secrets.DB_FEEDBACK_PASSWORD }}" \
--set database.users.finance.password="${{ secrets.DB_FINANCE_PASSWORD }}" \
--set database.users.letter.password="${{ secrets.DB_LETTER_PASSWORD }}" \
--set database.users.reports.password="${{ secrets.DB_REPORTS_PASSWORD }}" \
--set keycloak.adminPassword="${{ secrets.KEYCLOAK_ADMIN_PASSWORD }}" \
--set keycloak.db.password="${{ secrets.KEYCLOAK_DB_PASSWORD }}" \
--set keycloak.users.admin.password="${{ secrets.KEYCLOAK_REALM_ADMIN_PASSWORD }}" \
--set keycloak.users.user.password="${{ secrets.KEYCLOAK_REALM_USER_PASSWORD }}" \

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Inspect Helm secret injection sites and template consumers before switching to --set-string or a values file.
rg -n -C 2 -- '--set .*secrets\.|database\.users\..*password|keycloak\..*password|forwardAuth\..*Secret' .github/workflows infra/helm/team-devoops

Repository: AET-DevOps26/team-devoops

Length of output: 7434


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the exact deploy command and the corresponding Helm value consumers.
sed -n '270,305p' .github/workflows/cd.yml
printf '\n---\n'
sed -n '1,120p' infra/helm/team-devoops/templates/secret-db.yaml
printf '\n---\n'
sed -n '1,80p' infra/helm/team-devoops/templates/keycloak-secret.yaml
printf '\n---\n'
sed -n '1,80p' infra/helm/team-devoops/templates/keycloak-realm-configmap.yaml
printf '\n---\n'
sed -n '1,90p' infra/helm/team-devoops/templates/forward-auth.yaml

Repository: AET-DevOps26/team-devoops

Length of output: 7746


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Check whether these values are documented as plain strings or can be interpreted as numbers/bools.
sed -n '1,40p' infra/helm/team-devoops/values.yaml
printf '\n---\n'
sed -n '176,220p' infra/helm/team-devoops/values.yaml

Repository: AET-DevOps26/team-devoops

Length of output: 3444


🌐 Web query:

Helm --set type coercion --set-string passwords documentation

💡 Result:

In Helm, the --set and --set-string flags serve different purposes regarding type coercion [1][2][3]. --set The --set flag attempts to automatically detect and coerce values into appropriate types (such as integers, floats, booleans, or strings) [4][5][6]. Because of this, it can sometimes behave unexpectedly when a value looks like a number or boolean but should be treated as a string (e.g., a password containing only digits or a Git commit hash) [5][6][7]. --set-string The --set-string flag is designed to force values to be treated as strings, bypassing the automatic type coercion performed by the --set parser [5][6]. It is the recommended approach for values like passwords, image tags, or any other data where you want to ensure the input is interpreted strictly as a string [6]. Important Notes: 1. Syntax Compatibility: Despite its name, --set-string still supports Helm's complex value syntax, allowing you to define arrays and dictionaries (e.g., --set-string list={1,2,3}) [5]. It simply forces the terminal leaf values to be strings rather than native types [5]. 2. Not a Literal Flag: It is important to note that --set-string is not a "literal" flag [5]. It does not prevent all interpretation; for example, it may still be subject to shell expansion or Helm's internal parsing of complex structures [4][5]. If you require a value to be treated absolutely literally, or if you encounter issues where --set-string does not produce the desired result (such as with certain boolean-looking strings), you may need to quote the value or ensure your Helm chart templates handle the input correctly [4][5]. 3. Precedence: When using these flags, the last (right-most) value specified takes precedence if the same key is set multiple times [1]. For security-sensitive data like passwords, using --set-string is a standard practice to prevent Helm from misinterpreting numeric strings as integers or floating-point numbers [6].

Citations:


Use --set-string for the secret-backed Helm inputs here. Helm still type-infers these values before the templates quote them, so a numeric-looking password can change shape; if any secret may contain commas or other special characters, switch to a temporary values file instead. [.github/workflows/cd.yml:289-300]

🤖 Prompt for 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.

In @.github/workflows/cd.yml around lines 289 - 300, The Helm deploy step is
using --set for secret-backed password inputs, which can still be type-inferred
or mangled before templating; update the affected entries in the deploy command
to use --set-string for the database and keycloak password flags referenced in
the workflow snippet. If any of these secrets may contain commas or other
special characters, prefer passing them through a temporary values file instead
of inline CLI flags.

Comment thread infra/.env.example
Comment on lines +9 to +21
POSTGRES_PASSWORD=app_admin_password
ORGANIZATION_DB_PASSWORD=organization_password
MEMBER_DB_PASSWORD=member_password
EVENT_DB_PASSWORD=event_password
FEEDBACK_DB_PASSWORD=feedback_password
FINANCE_DB_PASSWORD=finance_password
LETTER_DB_PASSWORD=letter_password
REPORTS_DB_PASSWORD=reports_password
KEYCLOAK_ADMIN_PASSWORD=admin
KEYCLOAK_DB_PASSWORD=keycloak_password
KEYCLOAK_REALM_ADMIN_PASSWORD=admin123
KEYCLOAK_REALM_USER_PASSWORD=user123
FORWARD_AUTH_COOKIE_SECRET=VdpPltrnS+cc+1hswmya727K69iG7MpMZH/LOLlmox0=

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Replace the example credentials with placeholders.

These are still real-looking secrets, not examples. In particular, the FORWARD_AUTH_COOKIE_SECRET value is a shared session-signing key, so copying this file verbatim would give every environment the same cookie secret. Use blanks or <generate-random> placeholders instead and document how to populate them locally. As per PR objective "Removed hardcoded secrets", .env.example should not ship reusable credentials.

🧰 Tools
🪛 Betterleaks (1.6.0)

[high] 21-21: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

🪛 dotenv-linter (4.0.0)

[warning] 10-10: [UnorderedKey] The ORGANIZATION_DB_PASSWORD key should go before the POSTGRES_PASSWORD key

(UnorderedKey)


[warning] 11-11: [UnorderedKey] The MEMBER_DB_PASSWORD key should go before the ORGANIZATION_DB_PASSWORD key

(UnorderedKey)


[warning] 12-12: [UnorderedKey] The EVENT_DB_PASSWORD key should go before the MEMBER_DB_PASSWORD key

(UnorderedKey)


[warning] 13-13: [UnorderedKey] The FEEDBACK_DB_PASSWORD key should go before the MEMBER_DB_PASSWORD key

(UnorderedKey)


[warning] 14-14: [UnorderedKey] The FINANCE_DB_PASSWORD key should go before the MEMBER_DB_PASSWORD key

(UnorderedKey)


[warning] 15-15: [UnorderedKey] The LETTER_DB_PASSWORD key should go before the MEMBER_DB_PASSWORD key

(UnorderedKey)


[warning] 17-17: [UnorderedKey] The KEYCLOAK_ADMIN_PASSWORD key should go before the LETTER_DB_PASSWORD key

(UnorderedKey)


[warning] 18-18: [UnorderedKey] The KEYCLOAK_DB_PASSWORD key should go before the LETTER_DB_PASSWORD key

(UnorderedKey)


[warning] 19-19: [UnorderedKey] The KEYCLOAK_REALM_ADMIN_PASSWORD key should go before the LETTER_DB_PASSWORD key

(UnorderedKey)


[warning] 20-20: [UnorderedKey] The KEYCLOAK_REALM_USER_PASSWORD key should go before the LETTER_DB_PASSWORD key

(UnorderedKey)


[warning] 21-21: [UnorderedKey] The FORWARD_AUTH_COOKIE_SECRET key should go before the KEYCLOAK_ADMIN_PASSWORD key

(UnorderedKey)

🤖 Prompt for 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.

In `@infra/.env.example` around lines 9 - 21, Replace the hardcoded sample
credentials in infra/.env.example with non-reusable placeholders, especially
FORWARD_AUTH_COOKIE_SECRET and the password entries. Update the examples to use
blanks or <generate-random> style values and add a brief note that each
developer/environment must supply its own secrets locally. Keep the changes
within the existing environment variable list so the file remains an example
only.

Source: Linters/SAST tools

Comment thread infra/docker-compose.yml Outdated
Comment thread infra/docker-compose.yml Outdated
Comment on lines +10 to +11
{{- $rendered := .Files.Get "files/realm-config.json" | replace "__KEYCLOAK_REALM_ADMIN_PASSWORD__" .Values.keycloak.users.admin.password | replace "__KEYCLOAK_REALM_USER_PASSWORD__" .Values.keycloak.users.user.password }}
{{ $rendered | nindent 4 | trim }}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify all consumers of keycloak-realm-config so the volume source can be changed consistently.
rg -n -C 3 'keycloak-realm-config|realm-config\.json|configMap:|secret:' infra/helm/team-devoops

Repository: AET-DevOps26/team-devoops

Length of output: 12356


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== keycloak-realm-configmap.yaml ==\n'
sed -n '1,80p' infra/helm/team-devoops/templates/keycloak-realm-configmap.yaml

printf '\n== keycloak-deployment.yaml (realm-config volume) ==\n'
sed -n '100,125p' infra/helm/team-devoops/templates/keycloak-deployment.yaml

printf '\n== search for Secret-backed realm config ==\n'
rg -n 'keycloak-realm-config|realm-config|kind: Secret|secret:' infra/helm/team-devoops/templates infra/helm/team-devoops/values.yaml

Repository: AET-DevOps26/team-devoops

Length of output: 3692


Move the realm config payload out of the ConfigMap

This template renders the realm user passwords directly into keycloak-realm-config, exposing secret material in a ConfigMap. Store the rendered JSON in a Secret instead and update the Keycloak volume mount; the direct replacements also risk invalid JSON for passwords containing quotes, backslashes, or newlines.

🤖 Prompt for 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.

In `@infra/helm/team-devoops/templates/keycloak-realm-configmap.yaml` around lines
10 - 11, The Keycloak realm payload is being rendered in the ConfigMap via the
keycloak-realm-configmap template, which exposes admin/user passwords and can
break JSON when values contain special characters. Move the rendered realm JSON
generation out of the ConfigMap into a Secret, and update the Keycloak
mount/reference to read from that Secret instead. Use the existing
keycloak-realm-config template and the realm-config.json rendering path as the
main locations to adjust, keeping the ConfigMap free of secret material.

Comment thread infra/helm/team-devoops/values.yaml Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
infra/helm/team-devoops/values.yaml (1)

302-302: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

KEYCLOAK_ADMIN_CLIENT_SECRET is still hardcoded.

Line 302 defaults KEYCLOAK_ADMIN_CLIENT_SECRET to "org-role-sync-secret". The comment on line 298 says to override via --set in CI/prod, but the default value is a real secret string, not a CHANGE_ME placeholder like the other externalized secrets in this PR. If the chart is deployed without the override, this secret ships to production.

🔒 Proposed fix
       KEYCLOAK_ADMIN_CLIENT_ID: "org-role-sync"
-      KEYCLOAK_ADMIN_CLIENT_SECRET: "org-role-sync-secret"
+      KEYCLOAK_ADMIN_CLIENT_SECRET: "CHANGE_ME_KEYCLOAK_ADMIN_CLIENT_SECRET"
       KEYCLOAK_ROLES_CLIENT: "devops-client"
🤖 Prompt for 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.

In `@infra/helm/team-devoops/values.yaml` at line 302, The default for
KEYCLOAK_ADMIN_CLIENT_SECRET in values.yaml is still a real secret string, so
replace it with a non-sensitive placeholder like the other externalized secrets
and keep the actual value supplied only through override mechanisms. Update the
chart values entry near the KEYCLOAK_ADMIN_CLIENT_SECRET setting to use a
CHANGE_ME-style default, and ensure any consuming templates or docs still point
to the override path for CI/prod. Reference the KEYCLOAK_ADMIN_CLIENT_SECRET
value in the team-devoops Helm values so it is easy to locate.
🧹 Nitpick comments (1)
infra/helm/team-devoops/templates/_helpers.tpl (1)

19-39: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win

Drop all capabilities by default in team-devoops.containerSecurityContext
infra/helm/team-devoops/templates/_helpers.tpl:19-39drop: ["NET_RAW"] still leaves other Linux capabilities available. Switch to drop: ["ALL"] and add back only the capabilities each workload needs.

🤖 Prompt for 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.

In `@infra/helm/team-devoops/templates/_helpers.tpl` around lines 19 - 39, The
default container security context in team-devoops.containerSecurityContext only
drops NET_RAW, which still leaves other Linux capabilities enabled. Update the
capabilities block to drop all capabilities by default, then explicitly add back
only the minimum required ones for any workload that needs them, keeping the
existing allowPrivilegeEscalation, runAsNonRoot, and runAsUser behavior intact.
🤖 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 `@infra/helm/team-devoops/values.yaml`:
- Line 249: forwardAuth.clientSecret is still hardcoded in the chart values and
should be externalized like cookieSecret. Update the forwardAuth section in
values.yaml to replace the literal traefik-forward-auth-secret with a
CHANGE_ME-style placeholder or configurable value, keeping the existing
cookieSecret pattern as the reference and ensuring no secret remains embedded in
the default values.

---

Outside diff comments:
In `@infra/helm/team-devoops/values.yaml`:
- Line 302: The default for KEYCLOAK_ADMIN_CLIENT_SECRET in values.yaml is still
a real secret string, so replace it with a non-sensitive placeholder like the
other externalized secrets and keep the actual value supplied only through
override mechanisms. Update the chart values entry near the
KEYCLOAK_ADMIN_CLIENT_SECRET setting to use a CHANGE_ME-style default, and
ensure any consuming templates or docs still point to the override path for
CI/prod. Reference the KEYCLOAK_ADMIN_CLIENT_SECRET value in the team-devoops
Helm values so it is easy to locate.

---

Nitpick comments:
In `@infra/helm/team-devoops/templates/_helpers.tpl`:
- Around line 19-39: The default container security context in
team-devoops.containerSecurityContext only drops NET_RAW, which still leaves
other Linux capabilities enabled. Update the capabilities block to drop all
capabilities by default, then explicitly add back only the minimum required ones
for any workload that needs them, keeping the existing allowPrivilegeEscalation,
runAsNonRoot, and runAsUser behavior intact.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 77539e18-0753-4862-b619-32acff2c8656

📥 Commits

Reviewing files that changed from the base of the PR and between 47570f0 and ed8a19e.

📒 Files selected for processing (13)
  • infra/helm/team-devoops/templates/_helpers.tpl
  • infra/helm/team-devoops/templates/alloy-deployment.yaml
  • infra/helm/team-devoops/templates/deployment.yaml
  • infra/helm/team-devoops/templates/forward-auth.yaml
  • infra/helm/team-devoops/templates/grafana-deployment.yaml
  • infra/helm/team-devoops/templates/keycloak-deployment.yaml
  • infra/helm/team-devoops/templates/keycloak-postgres-statefulset.yaml
  • infra/helm/team-devoops/templates/loki-deployment.yaml
  • infra/helm/team-devoops/templates/ollama-deployment.yaml
  • infra/helm/team-devoops/templates/postgres-statefulset.yaml
  • infra/helm/team-devoops/templates/prometheus-deployment.yaml
  • infra/helm/team-devoops/values.yaml
  • services/spring-letter/.env.example

Comment thread infra/helm/team-devoops/values.yaml Outdated
@f-s-h f-s-h added enhancement New feature or request infra Issue regarding the infrastructure or CICD pipeline labels Jul 9, 2026
@f-s-h f-s-h self-assigned this Jul 9, 2026
raphael-frank and others added 3 commits July 9, 2026 18:14
openssl-rand-base64 secrets routinely contain `/`, which breaks a
`/`-delimited sed s/// (sed has no way to escape the delimiter). With
`set -e` in the entrypoint, that crash-loops the keycloak container
before it ever starts.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
org-role-sync-secret, traefik-forward-auth-secret, and grafana-oauth-secret
were hardcoded in realm-config.json, values.yaml, docker-compose.yml
fallback defaults, and directly in spring-organization's
application.properties -- never actually connected to a GitHub secret in
either deploy target, despite values.yaml comments claiming they would be.
org-role-sync in particular carries Keycloak manage-users, making it the
most sensitive credential left unaddressed.

- realm-config.json (both copies): hardcoded client secrets -> placeholders,
  substituted the same way the two realm passwords already are (Compose sed,
  Helm configmap replace)
- values.yaml: CHANGE_ME placeholders for forwardAuth.clientSecret,
  monitoring.grafana.oauthClientSecret, and the org-role-sync secret in
  organization-service's env; added the same to member-service, which
  previously had no override path at all and silently ran on its Spring
  property's hardcoded fallback in every deploy target
- spring-organization: client-secret now reads from
  KEYCLOAK_ADMIN_CLIENT_SECRET env (was a bare literal, no override
  possible without a rebuild)
- docker-compose.yml/.override.yml: dropped the ${VAR:-hardcoded} fallbacks
  for the two OAuth client secrets so a missing .env value fails loudly
  instead of silently deploying the public default
- cd.yml: 3 new GH secrets threaded through both the VM .env and the Helm
  --set list (KEYCLOAK_ADMIN_CLIENT_SECRET feeds two --set targets, since
  organization-service and member-service both authenticate as the same
  org-role-sync client)
- .env.example: local-dev defaults for the 3 new vars (matching values,
  not real secrets)
- README: documented the 3 new secrets and the org-role-sync client

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…code-secrets

# Conflicts:
#	infra/helm/team-devoops/values.yaml

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
infra/helm/team-devoops/values.yaml (1)

24-54: 🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift

Reject CHANGE_ME_* defaults at render time. These values are written straight into Secrets and Keycloak config; if a deploy misses --set, the chart will roll out known credentials. Add required/fail guards or a schema that blocks placeholder and empty secret values.

🤖 Prompt for 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.

In `@infra/helm/team-devoops/values.yaml` around lines 24 - 54, The placeholder
credentials in the database values are currently allowed through and can be
rendered into Secrets and Keycloak config. Add render-time validation in the
Helm chart, using the values handling around the database secret fields in
values.yaml plus the template/helpers that consume them, so deployment fails if
any password is empty or still set to a CHANGE_ME_* placeholder. Prefer
required/fail checks or a values schema guard that covers the top-level password
and each entry under users.
.github/workflows/cd.yml (1)

295-311: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Avoid inlining secrets in the Helm command In the Helm upgrade step, ${{ secrets.* }} is substituted into the script before Bash runs, so shell metacharacters in a secret can be reinterpreted. helm --set also treats commas and some special characters as syntax. Pass these values via env: and a temp values file, or --set-file, instead.

🤖 Prompt for 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.

In @.github/workflows/cd.yml around lines 295 - 311, The Helm upgrade step is
inlining multiple secret values directly into the command, which can break on
shell metacharacters and Helm --set parsing. Update the CD workflow command to
stop referencing `${{ secrets.* }}` inline and instead pass these values through
`env:` plus a temporary values file or `--set-file`. Focus on the Helm
invocation in the deployment step and keep the existing secret keys and service
settings mapped through safer inputs.
🤖 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 `@infra/docker-compose.yml`:
- Line 40: The Compose secret references are using plain variable expansion,
which can silently default to empty values when env vars are missing. Update the
secret-related entries in the docker-compose file to use required-variable
syntax like ${VAR:?VAR is required}, focusing on the existing
SPRING_DATASOURCE_PASSWORD reference and any similar secret refs in this compose
config.

In `@services/spring-member/src/main/resources/application.properties`:
- Line 22: The Keycloak service-account secret is still configured with a dummy
fallback, so make it a required setting instead of defaulting to
CHANGE_ME_KEYCLOAK_ADMIN_CLIENT_SECRET. Update the property in
application.properties to remove the placeholder default and ensure the related
Helm defaults use a real required value path as well, so missing configuration
fails fast before any Keycloak calls in the service-account setup.

---

Outside diff comments:
In @.github/workflows/cd.yml:
- Around line 295-311: The Helm upgrade step is inlining multiple secret values
directly into the command, which can break on shell metacharacters and Helm
--set parsing. Update the CD workflow command to stop referencing `${{ secrets.*
}}` inline and instead pass these values through `env:` plus a temporary values
file or `--set-file`. Focus on the Helm invocation in the deployment step and
keep the existing secret keys and service settings mapped through safer inputs.

In `@infra/helm/team-devoops/values.yaml`:
- Around line 24-54: The placeholder credentials in the database values are
currently allowed through and can be rendered into Secrets and Keycloak config.
Add render-time validation in the Helm chart, using the values handling around
the database secret fields in values.yaml plus the template/helpers that consume
them, so deployment fails if any password is empty or still set to a CHANGE_ME_*
placeholder. Prefer required/fail checks or a values schema guard that covers
the top-level password and each entry under users.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 5ab32a59-e3c8-46d9-ac9a-f50c9aecbdbb

📥 Commits

Reviewing files that changed from the base of the PR and between ed8a19e and 13c238c.

📒 Files selected for processing (12)
  • .github/workflows/cd.yml
  • README.md
  • infra/.env.example
  • infra/docker-compose.override.yml
  • infra/docker-compose.yml
  • infra/helm/team-devoops/files/realm-config.json
  • infra/helm/team-devoops/templates/deployment.yaml
  • infra/helm/team-devoops/templates/keycloak-realm-configmap.yaml
  • infra/helm/team-devoops/values.yaml
  • infra/keycloak/realm-config.json
  • services/spring-member/src/main/resources/application.properties
  • services/spring-organization/src/main/resources/application.properties
✅ Files skipped from review due to trivial changes (1)
  • README.md
🚧 Files skipped from review as they are similar to previous changes (2)
  • infra/docker-compose.override.yml
  • infra/helm/team-devoops/templates/deployment.yaml

Comment thread infra/docker-compose.yml
- SPRING_DATASOURCE_URL=jdbc:postgresql://app-database:5432/app_db
- SPRING_DATASOURCE_USERNAME=reports_user
- SPRING_DATASOURCE_PASSWORD=reports_password
- SPRING_DATASOURCE_PASSWORD=${REPORTS_DB_PASSWORD}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

git ls-files infra/docker-compose.yml
wc -l infra/docker-compose.yml
sed -n '1,260p' infra/docker-compose.yml
printf '\n--- search ---\n'
rg -n '\$\{[A-Z0-9_]+(:[^}]*)?\}' infra/docker-compose.yml

Repository: AET-DevOps26/team-devoops

Length of output: 12798


🏁 Script executed:

#!/bin/bash
set -euo pipefail

sed -n '1,240p' infra/docker-compose.yml | nl -ba | sed -n '1,240p'
printf '\n--- env refs ---\n'
rg -n '\$\{REPORTS_DB_PASSWORD|\$\{[^}]+\}' infra/docker-compose.yml

Repository: AET-DevOps26/team-devoops

Length of output: 203


Make secret Compose vars required Plain ${VAR} falls back to empty when a deploy env is missing one, which can start services with empty DB credentials or client secrets. Use ${VAR:?VAR is required} for the secret refs in this compose file.

🤖 Prompt for 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.

In `@infra/docker-compose.yml` at line 40, The Compose secret references are using
plain variable expansion, which can silently default to empty values when env
vars are missing. Update the secret-related entries in the docker-compose file
to use required-variable syntax like ${VAR:?VAR is required}, focusing on the
existing SPRING_DATASOURCE_PASSWORD reference and any similar secret refs in
this compose config.

keycloak.realm=devops
keycloak.service-account.client-id=${KEYCLOAK_SERVICE_ACCOUNT_CLIENT_ID:org-role-sync}
keycloak.service-account.client-secret=${KEYCLOAK_SERVICE_ACCOUNT_CLIENT_SECRET:org-role-sync-secret}
keycloak.service-account.client-secret=${KEYCLOAK_SERVICE_ACCOUNT_CLIENT_SECRET:CHANGE_ME_KEYCLOAK_ADMIN_CLIENT_SECRET}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the target file and nearby configuration references
git ls-files services/spring-member/src/main/resources/application.properties
echo '---'
cat -n services/spring-member/src/main/resources/application.properties | sed -n '1,120p'

echo '--- SEARCH keycloak.service-account / CHANGE_ME in repo ---'
rg -n "keycloak\.service-account\.client-secret|CHANGE_ME_KEYCLOAK_ADMIN_CLIENT_SECRET|KEYCLOAK_SERVICE_ACCOUNT_CLIENT_SECRET" .

Repository: AET-DevOps26/team-devoops

Length of output: 2940


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- organization application.properties ---'
cat -n services/spring-organization/src/main/resources/application.properties | sed -n '1,120p'

echo '--- member KeycloakService ---'
cat -n services/spring-member/src/main/java/tum/devoops/memberservice/service/KeycloakService.java | sed -n '1,140p'

echo '--- helm values around relevant env vars ---'
sed -n '300,360p' infra/helm/team-devoops/values.yaml

echo '--- README excerpt around secret docs ---'
sed -n '190,220p' README.md

Repository: AET-DevOps26/team-devoops

Length of output: 15807


Remove the placeholder default for the service-account secret.
application.properties still falls back to CHANGE_ME_KEYCLOAK_ADMIN_CLIENT_SECRET, and the Helm defaults use the same placeholder. Make this a required value so missing config fails fast instead of letting Keycloak calls run with a dummy secret.

🤖 Prompt for 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.

In `@services/spring-member/src/main/resources/application.properties` at line 22,
The Keycloak service-account secret is still configured with a dummy fallback,
so make it a required setting instead of defaulting to
CHANGE_ME_KEYCLOAK_ADMIN_CLIENT_SECRET. Update the property in
application.properties to remove the placeholder default and ensure the related
Helm defaults use a real required value path as well, so missing configuration
fails fast before any Keycloak calls in the service-account setup.

raphael-frank and others added 3 commits July 9, 2026 22:36
The namespace's ResourceQuota was at 6040Mi/6144Mi (98%) and 3560m/4000m
(89%) even at rest -- no room for the old+new pod overlap of a
multi-service rolling deploy, which is what caused ollama's replacement
pod to be flatly rejected ("exceeded quota") during the last cd run,
failing the whole release.

organization/member/event/feedback/finance/letter-service were the one
category in this chart still on the generic untuned default (384Mi/200m)
-- everywhere else has already been trimmed to just above observed peak.
Live `kubectl top` shows ~271-286Mi steady-state per service; their JVM
heap is already capped at 300Mi via JAVA_TOOL_OPTIONS, so 350Mi leaves a
reasonable non-heap margin without idle-vs-peak risk. CPU cut harder
(200m->150m) since it's compressible, not OOM-prone, and live usage is
~2-3m. app-database gets a smaller trim (256Mi->224Mi) given its 146Mi of
observed headroom despite serving 7 services' connection pools.

Frees ~236Mi/330m: quota headroom goes from 104Mi/440m to 340Mi/770m.
Reduces but does not guarantee against the quota-exceeded failure mode
under a full simultaneous rollout -- verified via `helm template` that
totals now sum to 5804Mi/3230m against the 6144Mi/4000m hard limits.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
organization/member/event/feedback/finance/letter-service, py-genai-helper
(image USER "user") and prometheus (image USER "nobody") were all stuck in
CreateContainerConfigError -- "container has runAsNonRoot and image has
non-numeric user, cannot verify user is non-root". The kubelet refuses to
resolve a named USER against the image's /etc/passwd; it only accepts a
numeric UID (or an explicit runAsUser in the pod spec).

Same tradeoff already applied to postgres/ollama/alloy elsewhere in this
chart: the images already run as non-root by default, we just can't
assert it to the kubelet without either this or pinning a numeric
runAsUser. allowPrivilegeEscalation:false and the NET_RAW capability drop
are unaffected.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
On a fresh database, init_db() races against member-service and
organization-service creating member.members / organization.teams,
which its own tables have foreign keys into. Losing that race raised
immediately, crashing the process -- recovery then depended on the
container's restart backoff, which is exponential and can push the
next attempt out far enough to exceed a deploy's overall timeout even
though the underlying dependency clears within a couple of minutes.

Retry the table creation internally instead (2 minute budget, within
the startup probe's ~5.3 minute allowance) so losing the race costs a
slower first boot rather than a container restart.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
services/py-genai-helper/db.py (1)

77-100: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add a retry log in init_db()
The loop can stay silent for up to 2 minutes on cold starts. Add an info log before time.sleep(2) so operators can see the retry cadence and remaining time; this file doesn’t import logging yet, so add that too.

🤖 Prompt for 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.

In `@services/py-genai-helper/db.py` around lines 77 - 100, `init_db()` retries
silently for up to 2 minutes, so add observability to the retry loop by logging
each `ProgrammingError` retry before `time.sleep(2)`, including the retry
cadence and remaining time. Update `db.py` to import and use `logging` (or the
module’s logger) and keep the log inside the `except ProgrammingError as e`
branch, while preserving the existing `UndefinedTable`/deadline behavior around
`_create_report_tables()`.
infra/helm/team-devoops/values.yaml (1)

331-337: 🔒 Security & Privacy | 🔵 Trivial | ⚖️ Poor tradeoff

runAsNonRoot: false removes the non-root guardrail; prefer pinning a numeric runAsUser.

The comment correctly diagnoses why the kubelet can't verify a named image user, but disabling the assertion means the workload would silently start even if a future image change made it run as root, and it breaks Pod Security "restricted" compliance. The documented alternative — an explicit numeric runAsUser (matching each image's adduser UID, e.g. 1000 as already used for py-genai-helper's fsGroup) — keeps the guarantee without the name-resolution failure. Consider applying that instead across these services.

Also applies to: 364-364, 389-389, 406-406, 423-423, 440-440, 458-458, 534-534

🤖 Prompt for 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.

In `@infra/helm/team-devoops/values.yaml` around lines 331 - 337, The
securityContext settings are disabling the non-root check with runAsNonRoot:
false, which removes the guardrail; instead, update the affected service entries
in values.yaml to use an explicit numeric runAsUser that matches each image’s
adduser UID (as already done for py-genai-helper’s fsGroup, e.g. 1000) while
keeping runAsNonRoot enabled. Use the repeated service blocks in the values file
to apply the same numeric UID consistently across all listed services so kubelet
verification and Pod Security restricted compliance are preserved.
🤖 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.

Nitpick comments:
In `@infra/helm/team-devoops/values.yaml`:
- Around line 331-337: The securityContext settings are disabling the non-root
check with runAsNonRoot: false, which removes the guardrail; instead, update the
affected service entries in values.yaml to use an explicit numeric runAsUser
that matches each image’s adduser UID (as already done for py-genai-helper’s
fsGroup, e.g. 1000) while keeping runAsNonRoot enabled. Use the repeated service
blocks in the values file to apply the same numeric UID consistently across all
listed services so kubelet verification and Pod Security restricted compliance
are preserved.

In `@services/py-genai-helper/db.py`:
- Around line 77-100: `init_db()` retries silently for up to 2 minutes, so add
observability to the retry loop by logging each `ProgrammingError` retry before
`time.sleep(2)`, including the retry cadence and remaining time. Update `db.py`
to import and use `logging` (or the module’s logger) and keep the log inside the
`except ProgrammingError as e` branch, while preserving the existing
`UndefinedTable`/deadline behavior around `_create_report_tables()`.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 3110a106-c242-4bb8-bf94-6d5f4aacfde1

📥 Commits

Reviewing files that changed from the base of the PR and between ddb231d and 3a515d4.

📒 Files selected for processing (3)
  • infra/helm/team-devoops/templates/prometheus-deployment.yaml
  • infra/helm/team-devoops/values.yaml
  • services/py-genai-helper/db.py

@raphael-frank raphael-frank left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I moved some remaining secrets into GH secrets and fixed deployment.

@raphael-frank
raphael-frank merged commit ccfe450 into main Jul 9, 2026
29 checks passed
@raphael-frank
raphael-frank deleted the infra/120-remove-hardcode-secrets branch July 9, 2026 22:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request infra Issue regarding the infrastructure or CICD pipeline

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Infra: No hardcoded secrets

3 participants