Skip to content

Conversation

@AnoshanJ
Copy link
Contributor

@AnoshanJ AnoshanJ commented Feb 2, 2026

Purpose

Describe the problems, issues, or needs driving this feature/fix and include links to related issues in the following format: Resolves issue1, issue2, etc.

Fixes #275

Persist Public-Private keypair used by Agent Manager Service for Token Generation by externalizing JWT signing key management using Kubernetes Secrets with the agent-management-platform helm chart.

  1. Generate keys via Helm Job - The Job generates the RSA key pair and creates or updates a Kubernetes Secret containing the public and private keys.
  2. Mount Secret into the service
  3. Update agent-manager-service/deployment.yaml to mount the JWT signing keys Secret as a volume.
  4. Remove runtime key generation

Goals

Describe the solutions that this feature/fix will introduce to resolve the problems described above

Approach

Describe how you are implementing the solutions. Include an animated GIF or screenshot if the change affects the UI (email [email protected] to review all UI text). Include a link to a Markdown file or Google doc if the feature write-up is too long to paste here.

User stories

Summary of user stories addressed by this change>

Release note

Brief description of the new feature or bug fix as it will appear in the release notes

Documentation

Link(s) to product documentation that addresses the changes of this PR. If no doc impact, enter �N/A� plus brief explanation of why there�s no doc impact

Training

Link to the PR for changes to the training content in https://github.com/wso2/WSO2-Training, if applicable

Certification

Type â��Sentâ�� when you have provided new/updated certification questions, plus four answers for each question (correct answer highlighted in bold), based on this change. Certification questions/answers should be sent to [email protected] and NOT pasted in this PR. If there is no impact on certification exams, type â��N/Aâ�� and explain why.

Marketing

Link to drafts of marketing content that will describe and promote this feature, including product page changes, technical articles, blog posts, videos, etc., if applicable

Automation tests

  • Unit tests

    Code coverage information

  • Integration tests

    Details about the test cases and coverage

Security checks

Samples

Provide high-level details about the samples related to this feature

Related PRs

List any other related PRs

Migrations (if applicable)

Describe migration steps and platforms on which migration has been tested

Test environment

List all JDK versions, operating systems, databases, and browser/versions on which this feature/fix was tested

Learning

Describe the research phase and any blog posts, patterns, libraries, or add-ons you used to solve the problem.

Summary by CodeRabbit

Release Notes

  • New Features
    • Added support for mounting pre-existing JWT signing keys from external sources.
    • Introduced automatic JWT key generation during deployment when keys are not provided externally.
    • Enhanced Helm configuration with flexible JWT key management options and improved deployment initialization flow.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 2, 2026

📝 Walkthrough

Walkthrough

The changes implement persistent JWT signing key management by introducing a Kubernetes Job to generate RSA keypairs and store them as Secrets, updating the agent-manager-service deployment to mount the Secret volume, modifying the entrypoint script to detect and use mounted keys with a fallback for local development, and adding Helm configurations to orchestrate this flow.

Changes

Cohort / File(s) Summary
Entry Point Script
agent-manager-service/entrypoint.sh
Modified to detect JWT keys at /app/keys directory; skips key generation if mounted keys exist, falls back to gen_keys.sh if available, and emits warning only when neither mounted keys nor generation script are present.
Helm Chart Helpers
deployments/helm-charts/.../templates/_helpers.tpl
Added new helper template agent-management-platform.jwtKeysSecretName that resolves secret name from existing value or constructs default name using chart fullname with "-jwt-keys" suffix.
Agent Manager Service Deployment
deployments/helm-charts/.../templates/agent-manager-service/deployment.yaml
Added volumeMount for jwt-keys at /app/keys (readOnly) and corresponding volume sourced from Kubernetes Secret with defaultMode 0440.
JWT Key Generation Infrastructure
deployments/helm-charts/.../templates/jobs/jwt-keys-generation-job.yaml
New Kubernetes Job gated by Helm values; runs on pre-install/pre-upgrade hooks to generate 4096-bit RSA keypair, create public-keys-config.json, and persist all keys in a Kubernetes Secret with metadata annotations.
RBAC & Service Account Setup
deployments/helm-charts/.../templates/rbac.yaml, deployments/helm-charts/.../templates/serviceaccount.yaml
Added Helm hook annotations (helm.sh/hook, helm.sh/hook-weight, helm.sh/hook-delete-policy) to ClusterRole, ClusterRoleBinding, and ServiceAccount to ensure RBAC resources are created before JWT generation Job.
Helm Values Configuration
deployments/helm-charts/.../values.yaml
Added jwtKeysGeneration section (enabled, backoffLimit, resources, security context) and jwtSigning section (existingSecret field for user-provided secrets or auto-generation) after dbMigration block.

Sequence Diagram

sequenceDiagram
    participant Helm as Helm Deployment
    participant Job as JWT Keys Job
    participant Secret as Kubernetes Secret
    participant Pod as Agent Manager Pod
    participant Script as Entrypoint Script
    participant App as Application

    Helm->>Helm: Pre-install/Pre-upgrade Hook
    Helm->>Job: Create JWT Key Generation Job
    Job->>Job: Install OpenSSL, kubectl, curl
    Job->>Secret: Check if JWT Secret exists
    alt Secret Does Not Exist
        Job->>Job: Generate 4096-bit RSA keypair
        Job->>Job: Create public-keys-config.json
        Job->>Secret: Create Secret with keys & config
        Job->>Secret: Annotate with version, key-id, timestamp
    else Secret Already Exists
        Job->>Job: Log and exit successfully
    end
    Helm->>Pod: Deploy Agent Manager with volumeMount
    Pod->>Secret: Mount secret at /app/keys
    Pod->>Script: Start container with entrypoint
    Script->>Script: Detect keys at /app/keys
    alt Keys Found
        Script->>App: Pass mounted keys to application
    else Keys Not Found
        Script->>Script: Attempt gen_keys.sh fallback
        Script->>App: Use generated or mounted keys
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 Keys persist through pod restarts now,
No more lost tokens, take a bow!
Helm Jobs spin, Secrets hold tight,
JWT magic, working just right!

🚥 Pre-merge checks | ✅ 4 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Description check ⚠️ Warning The description is largely incomplete. Most required template sections contain only placeholder text (marked with >) and are not filled out with actual information. Complete the PR description by filling in all major sections: Goals, Approach, User stories, Release notes, Documentation, Security checks, Test environment, and others. Provide substantive details for each section.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main objective of the PR: persisting the public-private keypair used by the Agent Manager Service for token generation.
Linked Issues check ✅ Passed All code changes align with the objectives in #275: keys are generated via a Helm Job, mounted into the service deployment, and entrypoint.sh now detects and uses mounted keys with fallback logic.
Out of Scope Changes check ✅ Passed All changes are directly related to the scope of #275. The PR modifies Helm charts, entrypoint.sh, and RBAC resources exclusively to implement JWT key persistence via Kubernetes Secrets.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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 and usage tips.

@AnoshanJ AnoshanJ requested a review from hanzjk February 2, 2026 09:32
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Fix all issues with AI agents
In `@agent-manager-service/entrypoint.sh`:
- Line 24: Remove the duplicate startup echo by deleting the early echo
"Starting agent-manager-service..." (the first echo invocation) and keep the
later echo that occurs after key handling; specifically remove the initial echo
statement so the single startup message comes only from the post-key-handling
echo.

In
`@deployments/helm-charts/wso2-ai-agent-management-platform/templates/jobs/jwt-keys-generation-job.yaml`:
- Around line 83-86: The conditional check using bash-ism `[[ ... ]]` needs to
be converted to POSIX-compliant tests so the job can run under Alpine's /bin/sh;
locate the if-statement that checks for private.pem, public.pem, and
public-keys-config.json and replace the `[[`/`]]` usage with POSIX `test`/`[`
checks (e.g., use `-f` checks combined with `||`) so the script uses only
/bin/sh-compatible syntax and still exits with the same error message when any
file is missing.
- Around line 68-80: The heredoc used to write public-keys-config.json is
indented, which inserts leading spaces into the JSON and breaks it; modify the
JWT keys generation step in jwt-keys-generation-job.yaml to use an unindented
heredoc (ensure the "cat > public-keys-config.json <<EOF" and the terminating
"EOF" are at column 0) or replace the heredoc with a non-indenting alternative
(e.g., printf/echo) to write the JSON, preserving the KEY_ID and TIMESTAMP
substitutions and the publicKeyPath/public keys structure unchanged.
🧹 Nitpick comments (1)
deployments/helm-charts/wso2-ai-agent-management-platform/templates/jobs/jwt-keys-generation-job.yaml (1)

36-36: Consider pinning a specific Alpine digest for reproducibility.

Using alpine:3.21 is reasonable, but for production workloads, consider pinning to a specific digest to ensure reproducible builds and avoid unexpected changes from tag updates.

@@ -23,13 +23,18 @@ set -e

echo "Starting agent-manager-service..."
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Remove duplicate startup message.

"Starting agent-manager-service..." is printed twice: once at line 24 and again at line 41. Consider removing the first occurrence since the actual startup happens after key handling.

Proposed fix
 echo "Starting agent-manager-service..."
 
-# Check if JWT signing keys exist (mounted from Kubernetes Secret)
+# Check if JWT signing keys exist (mounted from Kubernetes Secret)

Or simply remove line 24:

-echo "Starting agent-manager-service..."
-
 # Check if JWT signing keys exist (mounted from Kubernetes Secret)

Also applies to: 41-41

🤖 Prompt for AI Agents
In `@agent-manager-service/entrypoint.sh` at line 24, Remove the duplicate startup
echo by deleting the early echo "Starting agent-manager-service..." (the first
echo invocation) and keep the later echo that occurs after key handling;
specifically remove the initial echo statement so the single startup message
comes only from the post-key-handling echo.

Comment on lines +68 to +80
cat > public-keys-config.json <<EOF
{
"keys": [
{
"kid": "${KEY_ID}",
"algorithm": "RS256",
"publicKeyPath": "/app/keys/public.pem",
"description": "JWT signing key generated by Helm",
"createdAt": "${TIMESTAMP}"
}
]
}
EOF
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Heredoc indentation will produce malformed JSON.

The heredoc content is indented with leading spaces which will be included in the generated JSON file, making it invalid. The JSON keys will have leading whitespace.

Proposed fix: Use unindented heredoc or remove leading spaces
               # Create public-keys-config.json matching the format expected by gen_keys.sh
-              cat > public-keys-config.json <<EOF
-              {
-                "keys": [
-                  {
-                    "kid": "${KEY_ID}",
-                    "algorithm": "RS256",
-                    "publicKeyPath": "/app/keys/public.pem",
-                    "description": "JWT signing key generated by Helm",
-                    "createdAt": "${TIMESTAMP}"
-                  }
-                ]
-              }
-              EOF
+              cat > public-keys-config.json <<'EOF'
+{
+  "keys": [
+    {
+      "kid": "PLACEHOLDER_KEY_ID",
+      "algorithm": "RS256",
+      "publicKeyPath": "/app/keys/public.pem",
+      "description": "JWT signing key generated by Helm",
+      "createdAt": "PLACEHOLDER_TIMESTAMP"
+    }
+  ]
+}
+EOF
+              # Replace placeholders with actual values
+              sed -i "s/PLACEHOLDER_KEY_ID/${KEY_ID}/g" public-keys-config.json
+              sed -i "s/PLACEHOLDER_TIMESTAMP/${TIMESTAMP}/g" public-keys-config.json

Or use a simpler approach with printf/echo:

               # Create public-keys-config.json matching the format expected by gen_keys.sh
-              cat > public-keys-config.json <<EOF
-              {
-                ...
-              }
-              EOF
+              cat > public-keys-config.json << EOF
+{
+  "keys": [
+    {
+      "kid": "${KEY_ID}",
+      "algorithm": "RS256",
+      "publicKeyPath": "/app/keys/public.pem",
+      "description": "JWT signing key generated by Helm",
+      "createdAt": "${TIMESTAMP}"
+    }
+  ]
+}
+EOF

Note: The EOF marker must be at the start of the line (no leading indentation).

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
cat > public-keys-config.json <<EOF
{
"keys": [
{
"kid": "${KEY_ID}",
"algorithm": "RS256",
"publicKeyPath": "/app/keys/public.pem",
"description": "JWT signing key generated by Helm",
"createdAt": "${TIMESTAMP}"
}
]
}
EOF
cat > public-keys-config.json << EOF
{
"keys": [
{
"kid": "${KEY_ID}",
"algorithm": "RS256",
"publicKeyPath": "/app/keys/public.pem",
"description": "JWT signing key generated by Helm",
"createdAt": "${TIMESTAMP}"
}
]
}
EOF
🤖 Prompt for AI Agents
In
`@deployments/helm-charts/wso2-ai-agent-management-platform/templates/jobs/jwt-keys-generation-job.yaml`
around lines 68 - 80, The heredoc used to write public-keys-config.json is
indented, which inserts leading spaces into the JSON and breaks it; modify the
JWT keys generation step in jwt-keys-generation-job.yaml to use an unindented
heredoc (ensure the "cat > public-keys-config.json <<EOF" and the terminating
"EOF" are at column 0) or replace the heredoc with a non-indenting alternative
(e.g., printf/echo) to write the JSON, preserving the KEY_ID and TIMESTAMP
substitutions and the publicKeyPath/public keys structure unchanged.

Comment on lines +83 to +86
if [[ ! -f private.pem ]] || [[ ! -f public.pem ]] || [[ ! -f public-keys-config.json ]]; then
echo "ERROR: Key generation failed - missing key files"
exit 1
fi
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Critical: Bash syntax [[ ]] not supported in Alpine's /bin/sh.

The script uses [[ ]] test syntax which is a bash-ism, but Alpine's default shell is ash/busybox sh, which doesn't support this syntax. This will cause the job to fail with a syntax error.

Proposed fix: Use POSIX-compliant test syntax
-              if [[ ! -f private.pem ]] || [[ ! -f public.pem ]] || [[ ! -f public-keys-config.json ]]; then
+              if [ ! -f private.pem ] || [ ! -f public.pem ] || [ ! -f public-keys-config.json ]; then
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if [[ ! -f private.pem ]] || [[ ! -f public.pem ]] || [[ ! -f public-keys-config.json ]]; then
echo "ERROR: Key generation failed - missing key files"
exit 1
fi
if [ ! -f private.pem ] || [ ! -f public.pem ] || [ ! -f public-keys-config.json ]; then
echo "ERROR: Key generation failed - missing key files"
exit 1
fi
🤖 Prompt for AI Agents
In
`@deployments/helm-charts/wso2-ai-agent-management-platform/templates/jobs/jwt-keys-generation-job.yaml`
around lines 83 - 86, The conditional check using bash-ism `[[ ... ]]` needs to
be converted to POSIX-compliant tests so the job can run under Alpine's /bin/sh;
locate the if-statement that checks for private.pem, public.pem, and
public-keys-config.json and replace the `[[`/`]]` usage with POSIX `test`/`[`
checks (e.g., use `-f` checks combined with `||`) so the script uses only
/bin/sh-compatible syntax and still exits with the same error message when any
file is missing.

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.

Persist Public-Private keypair used by Agent Manager Service for Token Generation

1 participant