diff --git a/.gitignore b/.gitignore index 232fb75d..8a2dd1d4 100644 --- a/.gitignore +++ b/.gitignore @@ -49,3 +49,4 @@ package-lock.json .settings/* .env.bak cp.env.bak +.generated.env \ No newline at end of file diff --git a/.local.env b/.local.env index bdfe4e48..afdec487 100644 --- a/.local.env +++ b/.local.env @@ -1,6 +1,6 @@ SENTRIUS_VERSION=1.1.110 SENTRIUS_SSH_VERSION=1.1.19 -SENTRIUS_KEYCLOAK_VERSION=1.1.26 +SENTRIUS_KEYCLOAK_VERSION=1.1.31 SENTRIUS_AGENT_VERSION=1.1.19 SENTRIUS_AI_AGENT_VERSION=1.1.34 LLMPROXY_VERSION=1.0.22 diff --git a/.local.env.bak b/.local.env.bak index d64c46fd..ee39e85f 100644 --- a/.local.env.bak +++ b/.local.env.bak @@ -1,6 +1,6 @@ -SENTRIUS_VERSION=1.1.109 +SENTRIUS_VERSION=1.1.110 SENTRIUS_SSH_VERSION=1.1.19 -SENTRIUS_KEYCLOAK_VERSION=1.1.26 +SENTRIUS_KEYCLOAK_VERSION=1.1.30 SENTRIUS_AGENT_VERSION=1.1.19 SENTRIUS_AI_AGENT_VERSION=1.1.34 LLMPROXY_VERSION=1.0.22 diff --git a/agent-launcher/src/main/resources/application.properties b/agent-launcher/src/main/resources/application.properties index fabcd675..6a83c490 100644 --- a/agent-launcher/src/main/resources/application.properties +++ b/agent-launcher/src/main/resources/application.properties @@ -1,5 +1,5 @@ keystore.file=sso.jceks -keystore.password=keystorepassword +keystore.password=${KEYSTORE_PASSWORD:keystorepassword} keystore.alias=KEYBOX-ENCRYPTION_KEY keystore.algorithm=AES diff --git a/ai-agent/src/main/resources/assessor.properties b/ai-agent/src/main/resources/assessor.properties index e12fc3da..11e0b10d 100644 --- a/ai-agent/src/main/resources/assessor.properties +++ b/ai-agent/src/main/resources/assessor.properties @@ -51,7 +51,7 @@ server.error.whitelabel.enabled=false keycloak.realm=sentrius keycloak.base-url=${KEYCLOAK_BASE_URL:http://localhost:8180} spring.security.oauth2.client.registration.keycloak.client-id=java-agents -spring.security.oauth2.client.registration.keycloak.client-secret=e4WgJovH8MzcAvRnFg3rROAbeDIwiYmx +spring.security.oauth2.client.registration.keycloak.client-secret=${KEYCLOAK_CLIENT_SECRET:} spring.security.oauth2.client.registration.keycloak.authorization-grant-type=client_credentials spring.security.oauth2.client.registration.keycloak.redirect-uri=http://192.168.1.162:8080/login/oauth2/code/keycloak spring.security.oauth2.client.registration.keycloak.scope=openid,profile,email diff --git a/ai-agent/src/main/resources/challenger.properties b/ai-agent/src/main/resources/challenger.properties index 4e194bea..d832496c 100644 --- a/ai-agent/src/main/resources/challenger.properties +++ b/ai-agent/src/main/resources/challenger.properties @@ -46,7 +46,7 @@ server.error.whitelabel.enabled=false keycloak.realm=sentrius keycloak.base-url=${KEYCLOAK_BASE_URL:http://localhost:8180} spring.security.oauth2.client.registration.keycloak.client-id=ai-agents-assessor -spring.security.oauth2.client.registration.keycloak.client-secret=e4WgJovH8MzcAvRnFg3rROAbeDIwiYmy +spring.security.oauth2.client.registration.keycloak.client-secret=${KEYCLOAK_CLIENT_SECRET:} spring.security.oauth2.client.registration.keycloak.authorization-grant-type=client_credentials spring.security.oauth2.client.registration.keycloak.redirect-uri=http://192.168.1.162:8080/login/oauth2/code/keycloak spring.security.oauth2.client.registration.keycloak.scope=openid,profile,email diff --git a/ai-agent/src/main/resources/chat-helper.properties b/ai-agent/src/main/resources/chat-helper.properties index 63bbaa25..54d838be 100644 --- a/ai-agent/src/main/resources/chat-helper.properties +++ b/ai-agent/src/main/resources/chat-helper.properties @@ -52,7 +52,7 @@ keycloak.realm=sentrius keycloak.base-url=${KEYCLOAK_BASE_URL:http://localhost:8180} ## These are programmatically set. spring.security.oauth2.client.registration.keycloak.client-id=java-agents -spring.security.oauth2.client.registration.keycloak.client-secret=e4WgJovH8MzcAvRnFg3rROAbeDIwiYmxsdgd +spring.security.oauth2.client.registration.keycloak.client-secret=${KEYCLOAK_CLIENT_SECRET:} spring.security.oauth2.client.registration.keycloak.authorization-grant-type=client_credentials spring.security.oauth2.client.registration.keycloak.redirect-uri=http://192.168.1.162:8080/login/oauth2/code/keycloak spring.security.oauth2.client.registration.keycloak.scope=openid,profile,email diff --git a/ai-agent/src/main/resources/terminal-helper.properties b/ai-agent/src/main/resources/terminal-helper.properties index e6674ec6..feb93365 100644 --- a/ai-agent/src/main/resources/terminal-helper.properties +++ b/ai-agent/src/main/resources/terminal-helper.properties @@ -51,7 +51,7 @@ server.error.whitelabel.enabled=false keycloak.realm=sentrius keycloak.base-url=${KEYCLOAK_BASE_URL:http://localhost:8180} spring.security.oauth2.client.registration.keycloak.client-id=java-agents -spring.security.oauth2.client.registration.keycloak.client-secret=e4WgJovH8MzcAvRnFg3rROAbeDIwiYmx +spring.security.oauth2.client.registration.keycloak.client-secret=${KEYCLOAK_CLIENT_SECRET:} spring.security.oauth2.client.registration.keycloak.authorization-grant-type=client_credentials spring.security.oauth2.client.registration.keycloak.redirect-uri=http://192.168.1.162:8080/login/oauth2/code/keycloak spring.security.oauth2.client.registration.keycloak.scope=openid,profile,email diff --git a/analytics/src/main/resources/application.properties b/analytics/src/main/resources/application.properties index 9e7afd32..7a7f0792 100644 --- a/analytics/src/main/resources/application.properties +++ b/analytics/src/main/resources/application.properties @@ -1,5 +1,5 @@ keystore.file=sso.jceks -keystore.password=keystorepassword +keystore.password=${KEYSTORE_PASSWORD:keystorepassword} keystore.alias=KEYBOX-ENCRYPTION_KEY keystore.algorithm=AES @@ -16,7 +16,7 @@ spring.flyway.baseline-on-migrate=true spring.datasource.url=jdbc:postgresql://home.guard.local:5432/sentrius spring.datasource.username=postgres -spring.datasource.password=password +spring.datasource.password=${DATABASE_PASSWORD:password} spring.datasource.driver-class-name=org.postgresql.Driver # Connection pool settings @@ -51,7 +51,7 @@ server.error.whitelabel.enabled=false keycloak.realm=sentrius keycloak.base-url=${KEYCLOAK_BASE_URL:http://localhost:8180} spring.security.oauth2.client.registration.keycloak.client-id=sentrius-api -spring.security.oauth2.client.registration.keycloak.client-secret=nGkEukexSWTvDzYjSkDmeUlM0FJ5Jhh0 +spring.security.oauth2.client.registration.keycloak.client-secret=${KEYCLOAK_CLIENT_SECRET:} spring.security.oauth2.client.registration.keycloak.authorization-grant-type=authorization_code spring.security.oauth2.client.registration.keycloak.redirect-uri=http://192.168.1.162:8080/login/oauth2/code/keycloak spring.security.oauth2.client.registration.keycloak.scope=openid,profile,email diff --git a/api/src/main/resources/application.properties b/api/src/main/resources/application.properties index 963639df..27d52ade 100644 --- a/api/src/main/resources/application.properties +++ b/api/src/main/resources/application.properties @@ -1,5 +1,5 @@ keystore.file=sso.jceks -keystore.password=keystorepassword +keystore.password=${KEYSTORE_PASSWORD:keystorepassword} keystore.alias=KEYBOX-ENCRYPTION_KEY keystore.algorithm=AES @@ -22,7 +22,7 @@ spring.thymeleaf.suffix=.html spring.datasource.url=jdbc:postgresql://home.guard.local:5432/sentrius spring.datasource.username=postgres -spring.datasource.password=password +spring.datasource.password=${DATABASE_PASSWORD:password} spring.datasource.driver-class-name=org.postgresql.Driver # Connection pool settings diff --git a/docker/keycloak/Dockerfile b/docker/keycloak/Dockerfile index df8ffdb6..13199433 100644 --- a/docker/keycloak/Dockerfile +++ b/docker/keycloak/Dockerfile @@ -14,10 +14,18 @@ RUN /opt/keycloak/bin/kc.sh build FROM quay.io/keycloak/keycloak:24.0.1 COPY --from=builder /opt/keycloak/ /opt/keycloak/ -COPY ./realms/sentrius-realm.json /opt/keycloak/data/import/sentrius-realm.json +# Copy realm template and processing script +COPY ./realms/sentrius-realm.json.template /opt/keycloak/data/import/sentrius-realm.json.template +COPY ./process-realm-template.sh /opt/keycloak/bin/process-realm-template.sh +COPY ./startup.sh /opt/keycloak/bin/startup.sh -RUN ls -l /opt/keycloak/data/import/sentrius-realm.json +# Make scripts executable and ensure data directory is writable +USER root +RUN chmod +x /opt/keycloak/bin/process-realm-template.sh && \ + chmod +x /opt/keycloak/bin/startup.sh && \ + chown -R keycloak:keycloak /opt/keycloak/data +USER keycloak -ENTRYPOINT ["/opt/keycloak/bin/kc.sh"] -CMD ["start-dev", "--proxy=passthrough", "--import-realm", "--import-realm-overwrite=true", "--health-enabled=true"] +RUN ls -l /opt/keycloak/data/import/sentrius-realm.json.template +ENTRYPOINT ["/opt/keycloak/bin/startup.sh"] \ No newline at end of file diff --git a/docker/keycloak/README.md b/docker/keycloak/README.md new file mode 100644 index 00000000..0408ce3e --- /dev/null +++ b/docker/keycloak/README.md @@ -0,0 +1,30 @@ +# Keycloak Realm Configuration + +This realm configuration file contains client definitions for Sentrius with dynamic secret injection. + +## ๐Ÿ” Dynamic Secret Management + +The Keycloak container now supports dynamic secret injection through environment variables: + +- **SENTRIUS_API_CLIENT_SECRET** - Secret for sentrius-api client +- **SENTRIUS_LAUNCHER_CLIENT_SECRET** - Secret for sentrius-launcher-service client +- **JAVA_AGENTS_CLIENT_SECRET** - Secret for java-agents client +- **AI_AGENT_ASSESSOR_CLIENT_SECRET** - Secret for ai-agent-assessor client + +## How It Works + +1. **Template Processing**: The `sentrius-realm.json.template` file contains environment variable placeholders +2. **Runtime Substitution**: During container startup, the `process-realm-template.sh` script replaces placeholders with actual values +3. **Helm Integration**: The Helm chart generates OAuth2 secrets and passes them as environment variables +4. **Automatic Import**: Keycloak imports the processed realm with the dynamically generated secrets + +## Environment Variable Integration + +The Helm chart automatically: +- Generates random 32-character secrets when none are provided +- Passes these secrets as environment variables to the Keycloak container +- Ensures consistency between Helm-managed OAuth2 secrets and Keycloak realm configuration + +## Fallback Behavior + +If environment variables are not provided, the startup script generates default random secrets to ensure the container can start successfully. \ No newline at end of file diff --git a/docker/keycloak/process-realm-template.sh b/docker/keycloak/process-realm-template.sh new file mode 100644 index 00000000..a88c326d --- /dev/null +++ b/docker/keycloak/process-realm-template.sh @@ -0,0 +1,87 @@ +#!/bin/bash + +# Process realm template with environment variable substitution +# This script replaces environment variable placeholders in the realm template +# with actual values before Keycloak imports the realm + +# Set paths - different for container vs local testing +if [ -f "/opt/keycloak/data/import/sentrius-realm.json.template" ]; then + # Container environment + REALM_TEMPLATE="/opt/keycloak/data/import/sentrius-realm.json.template" + REALM_OUTPUT="/opt/keycloak/data/import/sentrius-realm.json" +elif [ -f "./realms/sentrius-realm.json.template" ]; then + # Local testing environment + REALM_TEMPLATE="./realms/sentrius-realm.json.template" + REALM_OUTPUT="${REALM_OUTPUT:-./sentrius-realm.json}" +else + echo "Error: Realm template not found" + echo " Looked for: /opt/keycloak/data/import/sentrius-realm.json.template" + echo " Looked for: ./realms/sentrius-realm.json.template" + exit 1 +fi + +echo "Processing Keycloak realm template..." +echo " Template: $REALM_TEMPLATE" +echo " Output: $REALM_OUTPUT" + +# Set default values for secrets if not provided +if command -v openssl >/dev/null 2>&1; then + # Use openssl if available + export SENTRIUS_API_CLIENT_SECRET="${SENTRIUS_API_CLIENT_SECRET:-default-api-secret-$(openssl rand -hex 16)}" + export SENTRIUS_LAUNCHER_CLIENT_SECRET="${SENTRIUS_LAUNCHER_CLIENT_SECRET:-default-launcher-secret-$(openssl rand -hex 16)}" + export JAVA_AGENTS_CLIENT_SECRET="${JAVA_AGENTS_CLIENT_SECRET:-default-agents-secret-$(openssl rand -hex 16)}" + export AI_AGENT_ASSESSOR_CLIENT_SECRET="${AI_AGENT_ASSESSOR_CLIENT_SECRET:-default-assessor-secret-$(openssl rand -hex 16)}" +else + # Fallback to simple random generation using date and process ID + RAND_SUFFIX=$(date +%s%N | cut -b1-13)$$ + export SENTRIUS_API_CLIENT_SECRET="${SENTRIUS_API_CLIENT_SECRET:-default-api-secret-${RAND_SUFFIX}}" + export SENTRIUS_LAUNCHER_CLIENT_SECRET="${SENTRIUS_LAUNCHER_CLIENT_SECRET:-default-launcher-secret-${RAND_SUFFIX}a}" + export JAVA_AGENTS_CLIENT_SECRET="${JAVA_AGENTS_CLIENT_SECRET:-default-agents-secret-${RAND_SUFFIX}b}" + export AI_AGENT_ASSESSOR_CLIENT_SECRET="${AI_AGENT_ASSESSOR_CLIENT_SECRET:-default-assessor-secret-${RAND_SUFFIX}c}" +fi + +# Set default values for other placeholders +# set in helm chart +#export ROOT_URL="${ROOT_URL:-http://localhost:8080}" +# set in helm chart +#export REDIRECT_URIS="${REDIRECT_URIS:-http://localhost:8080}" +export GOOGLE_CLIENT_ID="${GOOGLE_CLIENT_ID:-}" +export GOOGLE_CLIENT_SECRET="${GOOGLE_CLIENT_SECRET:-}" + +echo "Substituting environment variables in realm template..." +echo " SENTRIUS_API_CLIENT_SECRET: ${SENTRIUS_API_CLIENT_SECRET:0:8}..." +echo " SENTRIUS_LAUNCHER_CLIENT_SECRET: ${SENTRIUS_LAUNCHER_CLIENT_SECRET:0:8}..." +echo " JAVA_AGENTS_CLIENT_SECRET: ${JAVA_AGENTS_CLIENT_SECRET:0:8}..." +echo " AI_AGENT_ASSESSOR_CLIENT_SECRET: ${AI_AGENT_ASSESSOR_CLIENT_SECRET:0:8}..." + +# Use sed to replace environment variables (since envsubst may not be available) +# Replace ${VAR} with actual values +sed -e "s|\${SENTRIUS_API_CLIENT_SECRET}|${SENTRIUS_API_CLIENT_SECRET}|g" \ + -e "s|\${SENTRIUS_LAUNCHER_CLIENT_SECRET}|${SENTRIUS_LAUNCHER_CLIENT_SECRET}|g" \ + -e "s|\${JAVA_AGENTS_CLIENT_SECRET}|${JAVA_AGENTS_CLIENT_SECRET}|g" \ + -e "s|\${AI_AGENT_ASSESSOR_CLIENT_SECRET}|${AI_AGENT_ASSESSOR_CLIENT_SECRET}|g" \ + -e "s|\${GOOGLE_CLIENT_ID}|${GOOGLE_CLIENT_ID}|g" \ + -e "s|\${GOOGLE_CLIENT_SECRET}|${GOOGLE_CLIENT_SECRET}|g" \ + "$REALM_TEMPLATE" > "$REALM_OUTPUT" + + # these two are set helm chart + # -e "s|\${ROOT_URL}|${ROOT_URL}|g" \ + # -e "s|\${REDIRECT_URIS}|${REDIRECT_URIS}|g" \ + +if [ $? -eq 0 ]; then + echo "Realm template processed successfully: $REALM_OUTPUT" +else + echo "Error: Failed to process realm template" + exit 1 +fi + +# Validate the JSON is valid +if command -v jq >/dev/null 2>&1; then + if ! jq empty < "$REALM_OUTPUT" >/dev/null 2>&1; then + echo "Error: Generated realm JSON is invalid" + exit 1 + fi + echo "Generated realm JSON is valid" +else + echo "Note: jq not available, skipping JSON validation" +fi diff --git a/docker/keycloak/realms/sentrius-realm.json b/docker/keycloak/realms/sentrius-realm.json.template similarity index 98% rename from docker/keycloak/realms/sentrius-realm.json rename to docker/keycloak/realms/sentrius-realm.json.template index f9c27ee6..9bf8da64 100644 --- a/docker/keycloak/realms/sentrius-realm.json +++ b/docker/keycloak/realms/sentrius-realm.json.template @@ -6,7 +6,7 @@ "clientId": "sentrius-api", "enabled": true, "clientAuthenticatorType": "client-secret", - "secret": "nGkEukexSWTvDzYjSkDmeUlM0FJ5Jhh0", + "secret": "${SENTRIUS_API_CLIENT_SECRET}", "rootUrl": "${ROOT_URL}", "baseUrl": "${ROOT_URL}", "serviceAccountsEnabled": true, @@ -40,7 +40,7 @@ "clientId": "sentrius-launcher-service", "enabled": true, "clientAuthenticatorType": "client-secret", - "secret": "nGkEukexSWTSjklj3sddgvDzYjSkDmeUlM0FJ5Jhh0", + "secret": "${SENTRIUS_LAUNCHER_CLIENT_SECRET}", "rootUrl": "${ROOT_URL}", "baseUrl": "${ROOT_URL}", @@ -81,7 +81,7 @@ "enabled": true, "alwaysDisplayInConsole": false, "clientAuthenticatorType": "client-secret", - "secret": "e4WgJovH8MzcAvRnFg3rROAbeDIwiYmx", + "secret": "${JAVA_AGENTS_CLIENT_SECRET}", "redirectUris": [ "${REDIRECT_URIS}/*" ], @@ -168,7 +168,7 @@ "enabled": true, "alwaysDisplayInConsole": false, "clientAuthenticatorType": "client-secret", - "secret": "e4WgJovH8MzcAvRnFg3rROAbeDIwiYmy", + "secret": "${AI_AGENT_ASSESSOR_CLIENT_SECRET}", "redirectUris": [ "${REDIRECT_URIS}/*" ], diff --git a/docker/keycloak/startup.sh b/docker/keycloak/startup.sh new file mode 100644 index 00000000..7dce0e2b --- /dev/null +++ b/docker/keycloak/startup.sh @@ -0,0 +1,8 @@ +#!/bin/bash +echo "Starting Keycloak with dynamic realm processing..." + +# Process the realm template +/opt/keycloak/bin/process-realm-template.sh + +# Start Keycloak with the processed realm +exec /opt/keycloak/bin/kc.sh start-dev --proxy=passthrough --import-realm --import-realm-overwrite=true --health-enabled=true \ No newline at end of file diff --git a/docs/secret-management.md b/docs/secret-management.md new file mode 100644 index 00000000..ef579749 --- /dev/null +++ b/docs/secret-management.md @@ -0,0 +1,92 @@ +# Sentrius Secret Management + +## Overview + +Hardcoded secrets have been removed from the Helm charts and application properties files. The system now supports both dynamic secret generation and external secret management. + +## Dynamic Secret Generation + +When no secrets are provided in values.yaml, the Helm charts will automatically generate random secrets for: + +- OAuth2 client secrets (32 characters) +- Database passwords (32 characters) +- Keystore passwords (24 characters) +- Keycloak admin passwords (24 characters) +- Neo4j authentication strings (16 character passwords) + +## Providing Custom Secrets + +You can override the generated secrets by setting them in your values.yaml: + +```yaml +# Example custom secrets +secrets: + db: + username: "my-db-user" + password: "my-secure-password" + keystorePassword: "my-keystore-password" + +sentrius: + oauth2: + client_secret: "my-oauth2-secret" + +keycloak: + adminPassword: "my-keycloak-admin-password" + clientSecret: "my-keycloak-client-secret" + db: + password: "my-keycloak-db-password" + +neo4j: + env: + NEO4J_AUTH: "neo4j/my-neo4j-password" +``` + +## Environment Variables + +Application properties files now use environment variables with fallback defaults: + +- `KEYCLOAK_CLIENT_SECRET` - OAuth2 client secret for Keycloak +- `DATABASE_PASSWORD` - Database password (defaults to "password") +- `KEYSTORE_PASSWORD` - Keystore password (defaults to "keystorepassword") + +## Keycloak Realm Dynamic Configuration + +The Keycloak Docker container now supports dynamic realm configuration with automatic secret injection: + +### How It Works + +1. **Template Processing**: The Keycloak realm configuration uses a template file (`sentrius-realm.json.template`) with environment variable placeholders +2. **Runtime Substitution**: During container startup, secrets are injected via environment variables: + - `SENTRIUS_API_CLIENT_SECRET` - Secret for sentrius-api client + - `SENTRIUS_LAUNCHER_CLIENT_SECRET` - Secret for sentrius-launcher-service client + - `JAVA_AGENTS_CLIENT_SECRET` - Secret for java-agents client + - `AI_AGENT_ASSESSOR_CLIENT_SECRET` - Secret for ai-agent-assessor client +3. **Helm Integration**: The Helm chart automatically generates these secrets and passes them to the Keycloak container +4. **Fallback Generation**: If no secrets are provided, the container generates secure random defaults + +### Build Integration + +When building the Keycloak container with `./build-images.sh --sentrius-keycloak`, the system: +- Includes the realm template and processing script +- Configures automatic secret substitution during startup +- Ensures consistency between Helm-generated OAuth2 secrets and Keycloak realm configuration + +## Production Deployment + +For production environments, it is recommended to: + +1. Use an external secret management system (HashiCorp Vault, AWS Secrets Manager, etc.) +2. Set all secrets explicitly in your values.yaml file +3. Use Kubernetes secrets or external secret operators +4. Never commit secrets to version control + +## Removed Hardcoded Secrets + +The following hardcoded secrets were removed: + +- `nGkEukexSWTvDzYjSkDmeUlM0FJ5Jhh0` (multiple OAuth2 client secrets) +- `e4WgJovH8MzcAvRnFg3rROAbeDIwiYmx` (agent client secret) +- `KLJMLKSDJGlkj23@#jasdlkjg@#dsagsagdsag` (AI agent client secret) +- `neo4j/testingsecret` (Neo4j authentication) +- Base64 encoded database credentials +- Hardcoded keystore passwords \ No newline at end of file diff --git a/integration-proxy/src/main/resources/application.properties b/integration-proxy/src/main/resources/application.properties index 1a62e904..d174b384 100644 --- a/integration-proxy/src/main/resources/application.properties +++ b/integration-proxy/src/main/resources/application.properties @@ -1,5 +1,5 @@ keystore.file=sso.jceks -keystore.password=keystorepassword +keystore.password=${KEYSTORE_PASSWORD:keystorepassword} keystore.alias=KEYBOX-ENCRYPTION_KEY keystore.algorithm=AES @@ -21,7 +21,7 @@ spring.thymeleaf.suffix=.html spring.datasource.url=jdbc:postgresql://home.guard.local:5432/sentrius spring.datasource.username=postgres -spring.datasource.password=password +spring.datasource.password=${DATABASE_PASSWORD:password} spring.datasource.driver-class-name=org.postgresql.Driver # Connection pool settings @@ -36,7 +36,7 @@ spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect #spring.datasource.url=jdbc:h2:file:~/data/testdb #spring.datasource.driver-class-name=org.h2.Driver #spring.datasource.username=sa -#spring.datasource.password=password +#spring.datasource.password=${DATABASE_PASSWORD:password} #spring.jpa.hibernate.ddl-auto=update diff --git a/ops-scripts/local/deploy-helm.sh b/ops-scripts/local/deploy-helm.sh index 81dbe041..285d7755 100755 --- a/ops-scripts/local/deploy-helm.sh +++ b/ops-scripts/local/deploy-helm.sh @@ -29,6 +29,32 @@ fi # --set sentrius-keycloak.image.pullPolicy="Never" \ # --set sentrius-bad-ssh.image.pullPolicy="Never" \ +# Load any previously generated password from .generated.env +GENERATED_ENV_PATH="${SCRIPT_DIR}/../../.generated.env" +if [[ -f "$GENERATED_ENV_PATH" ]]; then + source "$GENERATED_ENV_PATH" +fi + +# Generate Keycloak DB password if not set and secret doesn't exist +if [[ -z "$KEYCLOAK_DB_PASSWORD" ]]; then + echo "๐Ÿ”Ž Checking if keycloak secret already exists..." + if kubectl get secret "${TENANT}-keycloak-secrets" --namespace "${TENANT}" >/dev/null 2>&1; then + echo "โœ… Found existing keycloak secret; extracting DB password..." + KEYCLOAK_DB_PASSWORD=$(kubectl get secret "${TENANT}-keycloak-secrets" --namespace "${TENANT}" -o jsonpath="{.data.db-password}" | base64 --decode) + + if [[ -z "$KEYCLOAK_DB_PASSWORD" ]]; then + echo "โŒ Secret exists but db-password is empty; exiting for safety" + exit 1 + fi + else + echo "โš ๏ธ No existing secret found; generating new Keycloak DB password..." + KEYCLOAK_DB_PASSWORD=$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 24) + + # Persist it to .generated.env so it doesn't change between runs + echo "KEYCLOAK_DB_PASSWORD=${KEYCLOAK_DB_PASSWORD}" > "$GENERATED_ENV_PATH" + fi +fi + helm upgrade --install sentrius ./sentrius-chart --namespace ${TENANT} \ --set tenant=${TENANT} \ @@ -41,6 +67,7 @@ helm upgrade --install sentrius ./sentrius-chart --namespace ${TENANT} \ --set integrationproxy.image.repository="sentrius-integration-proxy" \ --set integrationproxy.image.pullPolicy="Never" \ --set sentrius.image.repository="sentrius" \ + --set keycloak.db.password="${KEYCLOAK_DB_PASSWORD}" \ --set sentrius.image.pullPolicy="Never" \ --set keycloak.image.pullPolicy="Never" \ --set ssh.image.pullPolicy="Never" \ diff --git a/ops-scripts/local/spindown.sh b/ops-scripts/local/spindown.sh new file mode 100755 index 00000000..b715f5de --- /dev/null +++ b/ops-scripts/local/spindown.sh @@ -0,0 +1,36 @@ +#!/bin/bash + +set -e + +TENANT="dev" +RELEASE="sentrius" + +echo "This will delete the Helm release '$RELEASE' and the entire TENANT '$TENANT'." +read -p "Are you sure? (y/N): " CONFIRM + +if [[ "$CONFIRM" != "y" && "$CONFIRM" != "Y" ]]; then + echo "โŒ Aborted." + exit 1 +fi + +echo "Uninstalling Helm release..." +helm uninstall "$RELEASE" -n "$TENANT" || echo "Helm release not found." + +echo "๐Ÿงน Deleting TENANT '$TENANT'..." +kubectl delete namespace "$TENANT" || echo "namespace not found." +kubectl delete namespace "$TENANT-agents" || echo "namespace not found." + +echo "โณ Waiting for TENANT deletion to complete..." +while kubectl get namespace "$TENANT" &> /dev/null; do + echo " ... still deleting ..." + sleep 2 +done + +while kubectl get namespace "$TENANT-agents" &> /dev/null; do + echo " ... still deleting ..." + sleep 2 +done + +echo "TENANT '$TENANT' deleted." + +echo "Done." diff --git a/provenance-ingestor/src/main/resources/application.properties b/provenance-ingestor/src/main/resources/application.properties index 3f4c0e6c..a052acbe 100644 --- a/provenance-ingestor/src/main/resources/application.properties +++ b/provenance-ingestor/src/main/resources/application.properties @@ -1,5 +1,5 @@ keystore.file=sso.jceks -keystore.password=keystorepassword +keystore.password=${KEYSTORE_PASSWORD:keystorepassword} keystore.alias=KEYBOX-ENCRYPTION_KEY keystore.algorithm=AES @@ -24,7 +24,7 @@ spring.thymeleaf.suffix=.html #spring.datasource.url=jdbc:h2:file:~/data/testdb #spring.datasource.driver-class-name=org.h2.Driver #spring.datasource.username=sa -#spring.datasource.password=password +#spring.datasource.password=${DATABASE_PASSWORD:password} #spring.jpa.hibernate.ddl-auto=update diff --git a/sentrius-chart-launcher/templates/_helpers.tpl b/sentrius-chart-launcher/templates/_helpers.tpl index c67bfde6..4794e8e8 100644 --- a/sentrius-chart-launcher/templates/_helpers.tpl +++ b/sentrius-chart-launcher/templates/_helpers.tpl @@ -17,4 +17,9 @@ app.kubernetes.io/managed-by: {{ .Release.Service }} app.kubernetes.io/name: sentrius-launcher-service app.kubernetes.io/instance: {{ .Release.Name }} app.kubernetes.io/managed-by: {{ .Release.Service }} -{{- end -}} \ No newline at end of file +{{- end -}} +{{- define "keycloak.requireDbPassword" -}} +{{- if not .Values.keycloak.db.password }} + {{- fail "Error: keycloak.db.password must be specified or generated externally." }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/sentrius-chart-launcher/templates/configmap.yaml b/sentrius-chart-launcher/templates/configmap.yaml index 216eb4ef..41c918d2 100644 --- a/sentrius-chart-launcher/templates/configmap.yaml +++ b/sentrius-chart-launcher/templates/configmap.yaml @@ -37,7 +37,7 @@ data: agent.api.url={{ .Values.sentriusDomain }} # Keycloak configuration spring.security.oauth2.client.registration.keycloak.client-id={{ .Values.launcherservice.oauth2.client_id }} - spring.security.oauth2.client.registration.keycloak.client-secret={{ .Values.launcherservice.oauth2.client_secret }} + spring.security.oauth2.client.registration.keycloak.client-secret=${KEYCLOAK_CLIENT_SECRET} spring.security.oauth2.client.registration.keycloak.authorization-grant-type={{ .Values.launcherservice.oauth2.authorization_grant_type }} spring.security.oauth2.client.registration.keycloak.redirect-uri={{ .Values.sentriusDomain }}/login/oauth2/code/keycloak spring.security.oauth2.client.registration.keycloak.scope={{ .Values.launcherservice.oauth2.scope }} @@ -95,7 +95,7 @@ data: # Keycloak configuration spring.security.oauth2.client.registration.keycloak.client-id={{ .Values.launcherservice.oauth2.client_id }} - spring.security.oauth2.client.registration.keycloak.client-secret={{ .Values.launcherservice.oauth2.client_secret }} + spring.security.oauth2.client.registration.keycloak.client-secret=${KEYCLOAK_CLIENT_SECRET} spring.security.oauth2.client.registration.keycloak.authorization-grant-type={{ .Values.launcherservice.oauth2.authorization_grant_type }} spring.security.oauth2.client.registration.keycloak.redirect-uri={{ .Values.sentriusDomain }}/login/oauth2/code/keycloak spring.security.oauth2.client.registration.keycloak.scope={{ .Values.launcherservice.oauth2.scope }} diff --git a/sentrius-chart-launcher/templates/keycloak-secrets.yaml b/sentrius-chart-launcher/templates/keycloak-secrets.yaml new file mode 100644 index 00000000..fb4333ec --- /dev/null +++ b/sentrius-chart-launcher/templates/keycloak-secrets.yaml @@ -0,0 +1,23 @@ +{{- include "keycloak.requireDbPassword" . }} + +apiVersion: v1 +kind: Secret +metadata: + name: {{ .Release.Name }}-keycloak-secrets +type: Opaque +data: + # Keycloak Admin Password + {{- if .Values.keycloak.adminPassword }} + admin-password: {{ .Values.keycloak.adminPassword | b64enc }} + {{- else }} + admin-password: {{ randAlphaNum 24 | b64enc }} + {{- end }} + + # Keycloak Client Secret + {{- if .Values.keycloak.clientSecret }} + client-secret: {{ .Values.keycloak.clientSecret | b64enc }} + {{- else }} + client-secret: {{ randAlphaNum 32 | b64enc }} + {{- end }} + # Keycloak Database Password + db-password: {{ .Values.keycloak.db.password | b64enc }} \ No newline at end of file diff --git a/sentrius-chart-launcher/templates/launcher-deployment.yaml b/sentrius-chart-launcher/templates/launcher-deployment.yaml index f5db0099..610a4795 100644 --- a/sentrius-chart-launcher/templates/launcher-deployment.yaml +++ b/sentrius-chart-launcher/templates/launcher-deployment.yaml @@ -29,6 +29,12 @@ spec: volumeMounts: - name: config-volume mountPath: /config + env: + - name: KEYCLOAK_CLIENT_SECRET + valueFrom: + secretKeyRef: + name: {{ .Release.Name }}-oauth2-secrets + key: launcherservice-client-secret volumes: - name: config-volume configMap: diff --git a/sentrius-chart-launcher/templates/neo4j-secrets.yaml b/sentrius-chart-launcher/templates/neo4j-secrets.yaml new file mode 100644 index 00000000..5309820c --- /dev/null +++ b/sentrius-chart-launcher/templates/neo4j-secrets.yaml @@ -0,0 +1,14 @@ +{{- if .Values.neo4j.enabled }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ .Release.Name }}-neo4j-secrets +type: Opaque +data: + # Neo4j Authentication String (username/password) + {{- if .Values.neo4j.env.NEO4J_AUTH }} + neo4j-auth: {{ .Values.neo4j.env.NEO4J_AUTH | b64enc }} + {{- else }} + neo4j-auth: {{ printf "neo4j/%s" (randAlphaNum 16) | b64enc }} + {{- end }} +{{- end }} \ No newline at end of file diff --git a/sentrius-chart-launcher/templates/oauth2-secrets.yaml b/sentrius-chart-launcher/templates/oauth2-secrets.yaml new file mode 100644 index 00000000..4836d087 --- /dev/null +++ b/sentrius-chart-launcher/templates/oauth2-secrets.yaml @@ -0,0 +1,40 @@ +apiVersion: v1 +kind: Secret +metadata: + name: {{ .Release.Name }}-oauth2-secrets +type: Opaque +data: + # Sentrius OAuth2 Client Secret + {{- if .Values.sentrius.oauth2.client_secret }} + sentrius-client-secret: {{ .Values.sentrius.oauth2.client_secret | b64enc }} + {{- else }} + sentrius-client-secret: {{ randAlphaNum 32 | b64enc }} + {{- end }} + + # LLM Proxy OAuth2 Client Secret + {{- if .Values.llmproxy.oauth2.client_secret }} + llmproxy-client-secret: {{ .Values.llmproxy.oauth2.client_secret | b64enc }} + {{- else }} + llmproxy-client-secret: {{ randAlphaNum 32 | b64enc }} + {{- end }} + + # Sentrius Agent OAuth2 Client Secret + {{- if .Values.sentriusagent.oauth2.client_secret }} + sentriusagent-client-secret: {{ .Values.sentriusagent.oauth2.client_secret | b64enc }} + {{- else }} + sentriusagent-client-secret: {{ randAlphaNum 32 | b64enc }} + {{- end }} + + # Sentrius AI Agent OAuth2 Client Secret + {{- if .Values.sentriusaiagent.oauth2.client_secret }} + sentriusaiagent-client-secret: {{ .Values.sentriusaiagent.oauth2.client_secret | b64enc }} + {{- else }} + sentriusaiagent-client-secret: {{ randAlphaNum 32 | b64enc }} + {{- end }} + + # Launcher Service OAuth2 Client Secret + {{- if .Values.launcherservice.oauth2.client_secret }} + launcherservice-client-secret: {{ .Values.launcherservice.oauth2.client_secret | b64enc }} + {{- else }} + launcherservice-client-secret: {{ randAlphaNum 32 | b64enc }} + {{- end }} \ No newline at end of file diff --git a/sentrius-chart-launcher/values.yaml b/sentrius-chart-launcher/values.yaml index 4a45e039..755e95a0 100644 --- a/sentrius-chart-launcher/values.yaml +++ b/sentrius-chart-launcher/values.yaml @@ -34,7 +34,7 @@ sentrius: resources: {} oauth2: client_id: sentrius-api - client_secret: nGkEukexSWTvDzYjSkDmeUlM0FJ5Jhh0 + client_secret: "" # To be set via environment variable or external secret authorization_grant_type: authorization_code redirect_uri: http://{{ .Values.subdomain }}/login/oauth2/code/keycloak scope: openid,profile,email @@ -60,7 +60,7 @@ llmproxy: resources: {} oauth2: client_id: sentrius-api - client_secret: nGkEukexSWTvDzYjSkDmeUlM0FJ5Jhh0 + client_secret: "" # To be set via environment variable or external secret authorization_grant_type: authorization_code redirect_uri: http://{{ .Values.subdomain }}/login/oauth2/code/keycloak scope: openid,profile,email @@ -84,7 +84,7 @@ sentriusagent: port: 8080 oauth2: client_id: java-agents - client_secret: e4WgJovH8MzcAvRnFg3rROAbeDIwiYmx + client_secret: "" # To be set via environment variable or external secret authorization_grant_type: client_credentials redirect-uri: http://{{ .Values.subdomain }}/login/oauth2/code/keycloak scope: openid,profile,email @@ -112,7 +112,7 @@ sentriusaiagent: port: 8080 oauth2: client_id: java-agents - client_secret: KLJMLKSDJGlkj23@#jasdlkjg@#dsagsagdsag + client_secret: "" # To be set via environment variable or external secret authorization_grant_type: authorization_code redirect-uri: http://{{ .Values.subdomain }}/login/oauth2/code/keycloak scope: openid,profile,email @@ -140,7 +140,7 @@ launcherservice: port: 8080 oauth2: client_id: sentrius-launcher-service - client_secret: nGkEukexSWTSjklj3sddgvDzYjSkDmeUlM0FJ5Jhh0 + client_secret: "" # To be set via environment variable or external secret authorization_grant_type: authorization_code redirect-uri: http://{{ .Values.subdomain }}/login/oauth2/code/keycloak scope: openid,profile,email @@ -185,11 +185,11 @@ keycloak: pullPolicy: IfNotPresent host: keycloak.default.svc.cluster.local adminUser: admin - adminPassword: nGkEukexSWTvDzYjSkDmeUlM0FJ5Jhh0@1 + adminPassword: "" # To be set via environment variable or external secret serviceType: ClusterIP port: 8081 clientId: sentrius-api - clientSecret: nGkEukexSWTvDzYjSkDmeUlM0FJ5Jhh0 + clientSecret: "" # To be set via environment variable or external secret db: image: postgres:15 user: keycloak @@ -314,5 +314,5 @@ neo4j: httpPort: 7474 resources: {} env: - NEO4J_AUTH: neo4j/testingsecret + NEO4J_AUTH: "" # To be set via environment variable (e.g., neo4j/your-secure-password) NEO4J_server_config_strict__validation__enabled: "true" \ No newline at end of file diff --git a/sentrius-chart/templates/_helpers.tpl b/sentrius-chart/templates/_helpers.tpl index c67bfde6..4794e8e8 100644 --- a/sentrius-chart/templates/_helpers.tpl +++ b/sentrius-chart/templates/_helpers.tpl @@ -17,4 +17,9 @@ app.kubernetes.io/managed-by: {{ .Release.Service }} app.kubernetes.io/name: sentrius-launcher-service app.kubernetes.io/instance: {{ .Release.Name }} app.kubernetes.io/managed-by: {{ .Release.Service }} -{{- end -}} \ No newline at end of file +{{- end -}} +{{- define "keycloak.requireDbPassword" -}} +{{- if not .Values.keycloak.db.password }} + {{- fail "Error: keycloak.db.password must be specified or generated externally." }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/sentrius-chart/templates/agent-deployment.yaml b/sentrius-chart/templates/agent-deployment.yaml index d1801064..a33950e2 100644 --- a/sentrius-chart/templates/agent-deployment.yaml +++ b/sentrius-chart/templates/agent-deployment.yaml @@ -43,6 +43,11 @@ spec: secretKeyRef: name: {{ .Release.Name }}-db-secret key: keystore-password + - name: KEYCLOAK_CLIENT_SECRET + valueFrom: + secretKeyRef: + name: {{ .Release.Name }}-oauth2-secrets + key: java-agents-client-secret volumes: - name: config-volume configMap: diff --git a/sentrius-chart/templates/ai-agent-deployment.yaml b/sentrius-chart/templates/ai-agent-deployment.yaml index 87093721..a3717c1a 100644 --- a/sentrius-chart/templates/ai-agent-deployment.yaml +++ b/sentrius-chart/templates/ai-agent-deployment.yaml @@ -27,6 +27,12 @@ spec: volumeMounts: - name: config-volume mountPath: /config + env: + - name: KEYCLOAK_CLIENT_SECRET + valueFrom: + secretKeyRef: + name: {{ .Release.Name }}-oauth2-secrets + key: sentriusaiagent-client-secret volumes: - name: config-volume configMap: diff --git a/sentrius-chart/templates/configmap.yaml b/sentrius-chart/templates/configmap.yaml index f3f72b0d..69f50e38 100644 --- a/sentrius-chart/templates/configmap.yaml +++ b/sentrius-chart/templates/configmap.yaml @@ -44,7 +44,7 @@ data: agent.api.url={{ .Values.sentriusDomain }} # Keycloak configuration spring.security.oauth2.client.registration.keycloak.client-id={{ .Values.sentriusagent.oauth2.client_id }} - spring.security.oauth2.client.registration.keycloak.client-secret={{ .Values.sentriusagent.oauth2.client_secret }} + spring.security.oauth2.client.registration.keycloak.client-secret=${KEYCLOAK_CLIENT_SECRET} spring.security.oauth2.client.registration.keycloak.authorization-grant-type={{ .Values.sentriusagent.oauth2.authorization_grant_type }} spring.security.oauth2.client.registration.keycloak.redirect-uri={{ .Values.sentriusDomain }}/login/oauth2/code/keycloak spring.security.oauth2.client.registration.keycloak.scope={{ .Values.sentriusagent.oauth2.scope }} @@ -74,6 +74,7 @@ data: spring.kafka.properties.max.block.ms=500 spring.kafka.properties.metadata.max.age.ms=10000 spring.kafka.properties.retry.backoff.ms=1000 + bootstrap-servers=sentrius-kafka:9092: ai-agent-application.properties: | spring.main.web-application-type=servlet spring.thymeleaf.enabled=true @@ -96,7 +97,7 @@ data: agent.api.url={{ .Values.sentriusDomain }} # Keycloak configuration spring.security.oauth2.client.registration.keycloak.client-id={{ .Values.sentriusagent.oauth2.client_id }} - spring.security.oauth2.client.registration.keycloak.client-secret={{ .Values.sentriusagent.oauth2.client_secret }} + spring.security.oauth2.client.registration.keycloak.client-secret=${KEYCLOAK_CLIENT_SECRET} spring.security.oauth2.client.registration.keycloak.authorization-grant-type={{ .Values.sentriusagent.oauth2.authorization_grant_type }} spring.security.oauth2.client.registration.keycloak.redirect-uri={{ .Values.sentriusDomain }}/login/oauth2/code/keycloak spring.security.oauth2.client.registration.keycloak.scope={{ .Values.sentriusagent.oauth2.scope }} @@ -131,6 +132,7 @@ data: spring.kafka.properties.max.block.ms=500 spring.kafka.properties.metadata.max.age.ms=10000 spring.kafka.properties.retry.backoff.ms=1000 + bootstrap-servers=sentrius-kafka:9092: analysis-agent-application.properties: | keystore.file=sso.jceks @@ -177,7 +179,7 @@ data: agent.api.url={{ .Values.sentriusDomain }} # Keycloak configuration spring.security.oauth2.client.registration.keycloak.client-id={{ .Values.sentriusagent.oauth2.client_id }} - spring.security.oauth2.client.registration.keycloak.client-secret={{ .Values.sentriusagent.oauth2.client_secret }} + spring.security.oauth2.client.registration.keycloak.client-secret=${KEYCLOAK_CLIENT_SECRET} spring.security.oauth2.client.registration.keycloak.authorization-grant-type={{ .Values.sentriusagent.oauth2.authorization_grant_type }} spring.security.oauth2.client.registration.keycloak.redirect-uri={{ .Values.sentriusDomain }}/login/oauth2/code/keycloak spring.security.oauth2.client.registration.keycloak.scope={{ .Values.sentriusagent.oauth2.scope }} @@ -201,6 +203,7 @@ data: # Reliability spring.kafka.producer.retries=5 spring.kafka.producer.acks=all + bootstrap-servers=sentrius-kafka:9092: # Timeout tuning spring.kafka.producer.request-timeout-ms=10000 @@ -254,7 +257,7 @@ data: management.endpoint.health.show-details=always # Keycloak configuration spring.security.oauth2.client.registration.keycloak.client-id={{ .Values.sentrius.oauth2.client_id }} - spring.security.oauth2.client.registration.keycloak.client-secret={{ .Values.sentrius.oauth2.client_secret }} + spring.security.oauth2.client.registration.keycloak.client-secret=${KEYCLOAK_CLIENT_SECRET} spring.security.oauth2.client.registration.keycloak.authorization-grant-type={{ .Values.sentrius.oauth2.authorization_grant_type }} spring.security.oauth2.client.registration.keycloak.redirect-uri={{ .Values.sentriusDomain }}/login/oauth2/code/keycloak spring.security.oauth2.client.registration.keycloak.scope={{ .Values.sentrius.oauth2.scope }} diff --git a/sentrius-chart/templates/deployment.yaml b/sentrius-chart/templates/deployment.yaml index 022e5a1b..ef82c46f 100644 --- a/sentrius-chart/templates/deployment.yaml +++ b/sentrius-chart/templates/deployment.yaml @@ -42,6 +42,11 @@ spec: - name: config-volume mountPath: /config env: + - name: KEYCLOAK_CLIENT_SECRET + valueFrom: + secretKeyRef: + name: {{ .Release.Name }}-oauth2-secrets + key: sentrius-api-client-secret - name: SPRING_DATASOURCE_USERNAME valueFrom: secretKeyRef: diff --git a/sentrius-chart/templates/ingress.yaml b/sentrius-chart/templates/ingress.yaml index b77aa186..7514ae2e 100644 --- a/sentrius-chart/templates/ingress.yaml +++ b/sentrius-chart/templates/ingress.yaml @@ -5,28 +5,8 @@ metadata: name: managed-cert-ingress-{{ .Values.tenant }} namespace: {{ .Values.tenant }} annotations: - #kubernetes.io/ingress.class: {{ .Values.ingress.class }} - {{- if eq .Values.environment "gke" }} - {{- range $key, $value := .Values.ingress.annotations.gke }} - {{ $key }}: "{{ $value }}" - {{- end }} - {{- else if eq .Values.environment "aws" }} - {{- range $key, $value := .Values.ingress.annotations.aws }} - {{ $key }}: "{{ $value }}" - {{- end }} - {{- else if eq .Values.environment "local" }} - {{- range $key, $value := .Values.ingress.annotations.local }} - {{ $key }}: "{{ $value }}" - {{- end }} - {{- end }} + kubernetes.io/ingress.class: {{ .Values.ingress.class }} spec: - {{- if .Values.ingress.tlsEnabled }} - tls: - - hosts: - - {{ .Values.keycloakSubdomain }} - - {{ .Values.subdomain }} - secretName: wildcard-cert-{{ .Values.tenant }} - {{- end }} rules: - host: {{ .Values.keycloakSubdomain }} http: @@ -38,7 +18,7 @@ spec: name: {{ .Release.Name }}-keycloak port: number: 8081 - - host: {{ .Values.subdomain }} + - host: {{ .Values.tenant }}.sentrius.cloud http: paths: - path: / @@ -48,5 +28,4 @@ spec: name: {{ .Release.Name }}-sentrius port: number: 8080 - -{{- end }} +{{- end }} \ No newline at end of file diff --git a/sentrius-chart/templates/integrationproxy-deployment.yaml b/sentrius-chart/templates/integrationproxy-deployment.yaml index b1e553a1..2b5814a5 100644 --- a/sentrius-chart/templates/integrationproxy-deployment.yaml +++ b/sentrius-chart/templates/integrationproxy-deployment.yaml @@ -58,6 +58,11 @@ spec: secretKeyRef: name: {{ .Release.Name }}-db-secret key: keystore-password + - name: KEYCLOAK_CLIENT_SECRET + valueFrom: + secretKeyRef: + name: {{ .Release.Name }}-oauth2-secrets + key: integrationproxy-client-secret volumes: - name: config-volume diff --git a/sentrius-chart/templates/keycloak-deployment.yaml b/sentrius-chart/templates/keycloak-deployment.yaml index 11d11428..b814cdae 100644 --- a/sentrius-chart/templates/keycloak-deployment.yaml +++ b/sentrius-chart/templates/keycloak-deployment.yaml @@ -17,33 +17,40 @@ spec: app: keycloak release: {{ .Release.Name }} spec: + initContainers: + - name: wait-for-keycloak-db + image: busybox + command: ['sh', '-c', 'until nc -z keycloak-db 5432; do echo waiting for keycloak-db; sleep 2; done;'] containers: - name: keycloak image: "{{ .Values.keycloak.image.repository }}:{{ .Values.keycloak.image.tag }}" imagePullPolicy: "{{ .Values.keycloak.image.pullPolicy }}" ports: - - containerPort: 8081 - {{- if not (eq .Values.environment "gke") }} + - containerPort: {{ .Values.keycloak.port }} readinessProbe: httpGet: path: {{ .Values.healthCheck.keycloak.readinessPath }} - port: {{ .Values.healthCheck.keycloak.port }} - initialDelaySeconds: 5 + port: {{ .Values.keycloak.port }} + initialDelaySeconds: 30 periodSeconds: 10 + timeoutSeconds: 5 livenessProbe: httpGet: path: {{ .Values.healthCheck.keycloak.livenessPath }} - port: {{ .Values.healthCheck.keycloak.port }} - initialDelaySeconds: 5 + port: {{ .Values.keycloak.port }} + initialDelaySeconds: 60 periodSeconds: 10 - {{- end }} + timeoutSeconds: 5 env: - name: KC_HTTP_PORT value: "8081" - name: KEYCLOAK_ADMIN value: {{ .Values.keycloak.adminUser }} - name: KEYCLOAK_ADMIN_PASSWORD - value: {{ .Values.keycloak.adminPassword }} + valueFrom: + secretKeyRef: + name: {{ .Release.Name }}-keycloak-secrets + key: admin-password - name: KC_DB value: postgres - name: KC_DB_URL_HOST @@ -53,7 +60,10 @@ spec: - name: KC_DB_USERNAME value: {{ .Values.keycloak.db.user }} - name: KC_DB_PASSWORD - value: {{ .Values.keycloak.db.password }} + valueFrom: + secretKeyRef: + name: {{ .Release.Name }}-keycloak-secrets + key: db-password - name: KC_HOSTNAME value: {{ .Values.keycloakHostname }} - name: KC_HOSTNAME_STRICT @@ -75,6 +85,27 @@ spec: - name: GOOGLE_CLIENT_ID value: {{ .Values.keycloak.clientId }} - name: GOOGLE_CLIENT_SECRET - value: {{ .Values.keycloak.clientSecret }} - command: [ "/opt/keycloak/bin/kc.sh" ] - args: [ "start-dev", "--proxy=edge", "--import-realm", "--health-enabled=true"] + valueFrom: + secretKeyRef: + name: {{ .Release.Name }}-keycloak-secrets + key: client-secret + - name: SENTRIUS_API_CLIENT_SECRET + valueFrom: + secretKeyRef: + name: {{ .Release.Name }}-oauth2-secrets + key: sentrius-api-client-secret + - name: SENTRIUS_LAUNCHER_CLIENT_SECRET + valueFrom: + secretKeyRef: + name: {{ .Release.Name }}-oauth2-secrets + key: sentrius-launcher-service-client-secret + - name: JAVA_AGENTS_CLIENT_SECRET + valueFrom: + secretKeyRef: + name: {{ .Release.Name }}-oauth2-secrets + key: java-agents-client-secret + - name: AI_AGENT_ASSESSOR_CLIENT_SECRET + valueFrom: + secretKeyRef: + name: {{ .Release.Name }}-oauth2-secrets + key: ai-agent-assessor-client-secret \ No newline at end of file diff --git a/sentrius-chart/templates/keycloak-secrets.yaml b/sentrius-chart/templates/keycloak-secrets.yaml new file mode 100644 index 00000000..fb4333ec --- /dev/null +++ b/sentrius-chart/templates/keycloak-secrets.yaml @@ -0,0 +1,23 @@ +{{- include "keycloak.requireDbPassword" . }} + +apiVersion: v1 +kind: Secret +metadata: + name: {{ .Release.Name }}-keycloak-secrets +type: Opaque +data: + # Keycloak Admin Password + {{- if .Values.keycloak.adminPassword }} + admin-password: {{ .Values.keycloak.adminPassword | b64enc }} + {{- else }} + admin-password: {{ randAlphaNum 24 | b64enc }} + {{- end }} + + # Keycloak Client Secret + {{- if .Values.keycloak.clientSecret }} + client-secret: {{ .Values.keycloak.clientSecret | b64enc }} + {{- else }} + client-secret: {{ randAlphaNum 32 | b64enc }} + {{- end }} + # Keycloak Database Password + db-password: {{ .Values.keycloak.db.password | b64enc }} \ No newline at end of file diff --git a/sentrius-chart/templates/neo4j-deployment.yaml b/sentrius-chart/templates/neo4j-deployment.yaml index fb33a9c0..b4e63418 100644 --- a/sentrius-chart/templates/neo4j-deployment.yaml +++ b/sentrius-chart/templates/neo4j-deployment.yaml @@ -21,7 +21,10 @@ spec: - containerPort: {{ .Values.neo4j.httpPort }} env: - name: NEO4J_AUTH - value: "{{ .Values.neo4j.env.NEO4J_AUTH }}" + valueFrom: + secretKeyRef: + name: {{ .Release.Name }}-neo4j-secrets + key: neo4j-auth - name: NEO4J_server_config_strict__validation__enabled value: {{ .Values.neo4j.env.NEO4J_server_config_strict__validation__enabled | quote }} resources: {{- toYaml .Values.neo4j.resources | nindent 12 }} diff --git a/sentrius-chart/templates/neo4j-secrets.yaml b/sentrius-chart/templates/neo4j-secrets.yaml new file mode 100644 index 00000000..5309820c --- /dev/null +++ b/sentrius-chart/templates/neo4j-secrets.yaml @@ -0,0 +1,14 @@ +{{- if .Values.neo4j.enabled }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ .Release.Name }}-neo4j-secrets +type: Opaque +data: + # Neo4j Authentication String (username/password) + {{- if .Values.neo4j.env.NEO4J_AUTH }} + neo4j-auth: {{ .Values.neo4j.env.NEO4J_AUTH | b64enc }} + {{- else }} + neo4j-auth: {{ printf "neo4j/%s" (randAlphaNum 16) | b64enc }} + {{- end }} +{{- end }} \ No newline at end of file diff --git a/sentrius-chart/templates/oauth2-secrets.yaml b/sentrius-chart/templates/oauth2-secrets.yaml new file mode 100644 index 00000000..f9af42c5 --- /dev/null +++ b/sentrius-chart/templates/oauth2-secrets.yaml @@ -0,0 +1,65 @@ +apiVersion: v1 +kind: Secret +metadata: + name: {{ .Release.Name }}-oauth2-secrets +type: Opaque +data: + # Sentrius OAuth2 Client Secret + {{- if .Values.sentrius.oauth2.client_secret }} + sentrius-client-secret: {{ .Values.sentrius.oauth2.client_secret | b64enc }} + {{- else }} + sentrius-client-secret: {{ randAlphaNum 32 | b64enc }} + {{- end }} + + # Integration Proxy OAuth2 Client Secret + {{- if .Values.integrationproxy.oauth2.client_secret }} + integrationproxy-client-secret: {{ .Values.integrationproxy.oauth2.client_secret | b64enc }} + {{- else }} + integrationproxy-client-secret: {{ randAlphaNum 32 | b64enc }} + {{- end }} + + # Sentrius Agent OAuth2 Client Secret + {{- if .Values.sentriusagent.oauth2.client_secret }} + sentriusagent-client-secret: {{ .Values.sentriusagent.oauth2.client_secret | b64enc }} + {{- else }} + sentriusagent-client-secret: {{ randAlphaNum 32 | b64enc }} + {{- end }} + + # Sentrius AI Agent OAuth2 Client Secret + {{- if .Values.sentriusaiagent.oauth2.client_secret }} + sentriusaiagent-client-secret: {{ .Values.sentriusaiagent.oauth2.client_secret | b64enc }} + {{- else }} + sentriusaiagent-client-secret: {{ randAlphaNum 32 | b64enc }} + {{- end }} + + # Launcher Service OAuth2 Client Secret + {{- if .Values.launcherservice.oauth2.client_secret }} + launcherservice-client-secret: {{ .Values.launcherservice.oauth2.client_secret | b64enc }} + {{- else }} + launcherservice-client-secret: {{ randAlphaNum 32 | b64enc }} + {{- end }} + + # Keycloak Realm Client Secrets - These are used by Keycloak realm configuration + {{- if .Values.keycloak.realm.clients.sentriusApi.client_secret }} + sentrius-api-client-secret: {{ .Values.keycloak.realm.clients.sentriusApi.client_secret | b64enc }} + {{- else }} + sentrius-api-client-secret: {{ randAlphaNum 32 | b64enc }} + {{- end }} + + {{- if .Values.keycloak.realm.clients.sentriusLauncher.client_secret }} + sentrius-launcher-service-client-secret: {{ .Values.keycloak.realm.clients.sentriusLauncher.client_secret | b64enc }} + {{- else }} + sentrius-launcher-service-client-secret: {{ randAlphaNum 32 | b64enc }} + {{- end }} + + {{- if .Values.keycloak.realm.clients.javaAgents.client_secret }} + java-agents-client-secret: {{ .Values.keycloak.realm.clients.javaAgents.client_secret | b64enc }} + {{- else }} + java-agents-client-secret: {{ randAlphaNum 32 | b64enc }} + {{- end }} + + {{- if .Values.keycloak.realm.clients.aiAgentAssessor.client_secret }} + ai-agent-assessor-client-secret: {{ .Values.keycloak.realm.clients.aiAgentAssessor.client_secret | b64enc }} + {{- else }} + ai-agent-assessor-client-secret: {{ randAlphaNum 32 | b64enc }} + {{- end }} \ No newline at end of file diff --git a/sentrius-chart/templates/secret.yaml b/sentrius-chart/templates/secret.yaml index c7d6e17e..86fc4061 100644 --- a/sentrius-chart/templates/secret.yaml +++ b/sentrius-chart/templates/secret.yaml @@ -4,6 +4,18 @@ metadata: name: {{ .Release.Name }}-db-secret type: Opaque data: - db-username: {{ .Values.secrets.db.username }} - db-password: {{ .Values.secrets.db.password }} - keystore-password: {{ .Values.secrets.db.keystorePassword }} + {{- if .Values.secrets.db.username }} + db-username: {{ .Values.secrets.db.username | b64enc }} + {{- else }} + db-username: {{ "admin" | b64enc }} + {{- end }} + {{- if .Values.secrets.db.password }} + db-password: {{ .Values.secrets.db.password | b64enc }} + {{- else }} + db-password: {{ randAlphaNum 32 | b64enc }} + {{- end }} + {{- if .Values.secrets.db.keystorePassword }} + keystore-password: {{ .Values.secrets.db.keystorePassword | b64enc }} + {{- else }} + keystore-password: {{ randAlphaNum 24 | b64enc }} + {{- end }} diff --git a/sentrius-chart/values.yaml b/sentrius-chart/values.yaml index 2310ac1d..76cb3a4d 100644 --- a/sentrius-chart/values.yaml +++ b/sentrius-chart/values.yaml @@ -6,10 +6,10 @@ environment: "gke" # Can be "gke", "aws", "azure", "local" tenant: sentrius-demo subdomain: "{{ .Values.tenant }}.sentrius.cloud" -keycloakSubdomain: keycloak.{{ .Values.subdomain }} -keycloakHostname: "{{ .Values.keycloakSubdomain }}" -keycloakDomain: https://{{ .Values.keycloakSubdomain }} -sentriusDomain: https://{{ .Values.subdomain }} +keycloakSubdomain: "keycloak.{{ .Values.tenant }}.sentrius.cloud" +keycloakHostname: "keycloak.{{ .Values.tenant }}.sentrius.cloud" +keycloakDomain: "https://keycloak.{{ .Values.tenant }}.sentrius.cloud" +sentriusDomain: "https://{{ .Values.tenant }}.sentrius.cloud" launcherFQDN: sentrius-launcher-service.dev.svc.cluster.local @@ -31,7 +31,7 @@ sentrius: resources: {} oauth2: client_id: sentrius-api - client_secret: nGkEukexSWTvDzYjSkDmeUlM0FJ5Jhh0 + client_secret: "" # To be set via environment variable or external secret authorization_grant_type: authorization_code redirect_uri: http://{{ .Values.subdomain }}/login/oauth2/code/keycloak scope: openid,profile,email @@ -57,7 +57,7 @@ integrationproxy: resources: {} oauth2: client_id: sentrius-api - client_secret: nGkEukexSWTvDzYjSkDmeUlM0FJ5Jhh0 + client_secret: "" # To be set via environment variable or external secret authorization_grant_type: authorization_code redirect_uri: http://{{ .Values.subdomain }}/login/oauth2/code/keycloak scope: openid,profile,email @@ -81,7 +81,7 @@ sentriusagent: port: 8080 oauth2: client_id: java-agents - client_secret: e4WgJovH8MzcAvRnFg3rROAbeDIwiYmx + client_secret: "" # To be set via environment variable or external secret authorization_grant_type: client_credentials redirect-uri: http://{{ .Values.subdomain }}/login/oauth2/code/keycloak scope: openid,profile,email @@ -109,7 +109,7 @@ sentriusaiagent: port: 8080 oauth2: client_id: java-agents - client_secret: KLJMLKSDJGlkj23@#jasdlkjg@#dsagsagdsag + client_secret: "" # To be set via environment variable or external secret authorization_grant_type: authorization_code redirect-uri: http://{{ .Values.subdomain }}/login/oauth2/code/keycloak scope: openid,profile,email @@ -137,7 +137,7 @@ launcherservice: port: 8080 oauth2: client_id: sentrius-launcher-service - client_secret: nGkEukexSWTSjklj3sddgvDzYjSkDmeUlM0FJ5Jhh0 + client_secret: "" # To be set via environment variable or external secret authorization_grant_type: authorization_code redirect-uri: http://{{ .Values.subdomain }}/login/oauth2/code/keycloak scope: openid,profile,email @@ -169,12 +169,12 @@ ssh: pullPolicy: IfNotPresent port: 22 -# Secrets +# Secrets - Use external secret management or environment variables secrets: db: - username: YWRtaW4= # admin - password: cGFzc3dvcmQ= # password - keystorePassword: c2VudHJpdXM= # sentrius + username: "" # To be provided via environment variable or external secret + password: "" # To be provided via environment variable or external secret + keystorePassword: "" # To be provided via environment variable or external secret keycloak: image: @@ -182,18 +182,29 @@ keycloak: pullPolicy: IfNotPresent host: keycloak.default.svc.cluster.local adminUser: admin - adminPassword: nGkEukexSWTvDzYjSkDmeUlM0FJ5Jhh0@1 + adminPassword: "" # To be set via environment variable or external secret serviceType: ClusterIP port: 8081 clientId: sentrius-api - clientSecret: nGkEukexSWTvDzYjSkDmeUlM0FJ5Jhh0 + clientSecret: "" # To be set via environment variable or external secret db: image: postgres:15 user: keycloak - password: password + password: "" # To be set via environment variable or external secret database: keycloak storageSize: 10Gi replicas: 1 + # Realm client secrets - used for Keycloak realm template processing + realm: + clients: + sentriusApi: + client_secret: "" # Dynamically generated if not provided + sentriusLauncher: + client_secret: "" # Dynamically generated if not provided + javaAgents: + client_secret: "" # Dynamically generated if not provided + aiAgentAssessor: + client_secret: "" # Dynamically generated if not provided annotations: gke: cloud.google.com/backend-config: '{"default": "sentrius-backend-config"}' @@ -311,5 +322,5 @@ neo4j: httpPort: 7474 resources: {} env: - NEO4J_AUTH: neo4j/testingsecret + NEO4J_AUTH: "" # To be set via environment variable (e.g., neo4j/your-secure-password) NEO4J_server_config_strict__validation__enabled: "true" \ No newline at end of file