diff --git a/charts/mcp-stack/Chart.yaml b/charts/mcp-stack/Chart.yaml index 27702fc0..8c47878e 100644 --- a/charts/mcp-stack/Chart.yaml +++ b/charts/mcp-stack/Chart.yaml @@ -22,7 +22,7 @@ type: application # * appVersion - upstream application version; shown in UIs but not # used for upgrade logic. # -------------------------------------------------------------------- -version: 0.5.0 +version: 0.5.1 appVersion: "0.5.0" # Icon shown by registries / dashboards (must be an http(s) URL). diff --git a/charts/mcp-stack/templates/NOTES.txt b/charts/mcp-stack/templates/NOTES.txt index e1f51c61..0c05cebf 100644 --- a/charts/mcp-stack/templates/NOTES.txt +++ b/charts/mcp-stack/templates/NOTES.txt @@ -20,6 +20,7 @@ {{- $pgadminSvc := printf "%s-pgadmin" $fullName }} {{- $gwSecret := printf "%s-gateway-secret" $fullName }} +{{- $adminSecret := printf "%s-admin-secret" $fullName }} {{- $pgSecret := include "mcp-stack.postgresSecretName" . }} {{- /* ─── Secret look-ups (only used when $showSecrets=true) */}} @@ -28,9 +29,11 @@ {{- $pgPass := "" }} {{- if $showSecrets }} {{- with (lookup "v1" "Secret" $ns $gwSecret) }} - {{- $basicAuthPass = index .data "BASIC_AUTH_PASSWORD" | b64dec }} {{- $jwtKey = index .data "JWT_SECRET_KEY" | b64dec }} {{- end }} + {{- with (lookup "v1" "Secret" $ns $gwSecret) }} + {{- $basicAuthPass = index .data "BASIC_AUTH_PASSWORD" | b64dec }} + {{- end }} {{- with (lookup "v1" "Secret" $ns $pgSecret) }} {{- $pgPass = index .data "POSTGRES_PASSWORD" | b64dec }} {{- end }} diff --git a/charts/mcp-stack/templates/configmap-postgres.yaml b/charts/mcp-stack/templates/configmap-postgres.yaml index 18bd6231..805dcaf6 100644 --- a/charts/mcp-stack/templates/configmap-postgres.yaml +++ b/charts/mcp-stack/templates/configmap-postgres.yaml @@ -1,6 +1,27 @@ +{{/* ------------------------------------------------------------------- + CONFIGMAP - Gateway Plain-Text Configuration + ------------------------------------------------------------------- + - Renders a ConfigMap named postgres-config + - Each key/value becomes an environment variable. + - Use ONLY for non-secret data ( db host, port and related) + ------------------------------------------------------------------- */}} + +{{- if .Values.postgres.enabled }} apiVersion: v1 kind: ConfigMap metadata: name: postgres-config data: - POSTGRES_DB: {{ .Values.postgres.credentials.database }} + POSTGRES_DB: {{ .Values.postgres.database | quote }} + POSTGRES_PORT: {{ .Values.postgres.service.port | quote }} + POSTGRES_HOST: {{ printf "%s-postgres" (include "mcp-stack.fullname" .) }} +{{- else if eq .Values.postgres.enabled false }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: postgres-config +data: + POSTGRES_DB: {{ default "mcpgateway" .Values.postgres.db | quote }} + POSTGRES_PORT: {{ .Values.postgres.port | quote}} + POSTGRES_HOST: {{ .Values.postgres.host | quote }} +{{- end }} diff --git a/charts/mcp-stack/templates/deployment-mcpgateway.yaml b/charts/mcp-stack/templates/deployment-mcpgateway.yaml index 0b6b8e79..eca906c9 100644 --- a/charts/mcp-stack/templates/deployment-mcpgateway.yaml +++ b/charts/mcp-stack/templates/deployment-mcpgateway.yaml @@ -27,11 +27,17 @@ spec: labels: app: {{ include "mcp-stack.fullname" . }}-mcpgateway - spec: + spec: + {{- if .Values.global.imagePullSecrets }} + imagePullSecrets: + {{- range .Values.global.imagePullSecrets }} + - name: {{ . }} + {{- end }} + {{- end }} containers: - name: mcp-context-forge image: "{{ .Values.mcpContextForge.image.repository }}:{{ .Values.mcpContextForge.image.tag }}" - imagePullPolicy: {{ .Values.mcpContextForge.image.pullPolicy }} + imagePullPolicy: {{ .Values.mcpContextForge.image.pullPolicy | quote }} # Gateway's internal port ports: @@ -45,27 +51,38 @@ spec: env: # ---------- POSTGRES ---------- - name: POSTGRES_HOST - value: {{ printf "%s-postgres" (include "mcp-stack.fullname" .) }} + valueFrom: + configMapKeyRef: + key: POSTGRES_HOST + name: postgres-config - name: POSTGRES_PORT - value: "{{ .Values.mcpContextForge.env.postgres.port }}" + valueFrom: + configMapKeyRef: + key: POSTGRES_PORT + name: postgres-config - name: POSTGRES_DB - value: "{{ .Values.mcpContextForge.env.postgres.db }}" + valueFrom: + configMapKeyRef: + key: POSTGRES_DB + name: postgres-config - name: POSTGRES_USER valueFrom: secretKeyRef: - name: {{ include "mcp-stack.postgresSecretName" . | trim }} - key: POSTGRES_USER + name: {{ if .Values.pgSecretMounts }}{{ .Values.pgSecretMounts.name }}{{ else }}{{ include "mcp-stack.postgresSecretName" . | trim }}{{ end }} + key: {{ if .Values.pgSecretMounts }}{{ .Values.pgSecretMounts.userNameKey }}{{ else }}POSTGRES_USER{{ end }} - name: POSTGRES_PASSWORD valueFrom: secretKeyRef: - name: {{ include "mcp-stack.postgresSecretName" . | trim }} - key: POSTGRES_PASSWORD + name: {{ if .Values.pgSecretMounts }}{{ .Values.pgSecretMounts.name }}{{ else }}{{ include "mcp-stack.postgresSecretName" . | trim }}{{ end }} + key: {{ if .Values.pgSecretMounts }}{{ .Values.pgSecretMounts.passwordKeyKey }}{{ else }}POSTGRES_PASSWORD{{ end }} # ---------- REDIS ---------- - name: REDIS_HOST - value: {{ printf "%s-redis" (include "mcp-stack.fullname" .) }} + value: {{ if .Values.redis.host }}{{ .Values.redis.host }}{{ else }}{{ printf "%s-redis" (include "mcp-stack.fullname" .) }}{{ end }} - name: REDIS_PORT - value: "{{ .Values.mcpContextForge.env.redis.port }}" + value: "{{ .Values.redis.port }}" + + # ---------- DERIVED URLS ---------- # These MUST be placed *after* the concrete vars above so the @@ -80,8 +97,13 @@ spec: # BULK ENV-VARS - pulled from ConfigMap + Secret ################################################################ envFrom: + {{- if .Values.mcpContextForge.secret.create }} - secretRef: name: {{ include "mcp-stack.fullname" . }}-gateway-secret + {{- else }} + - secretRef: + name: {{ if .Values.mcpContextForge.mcpGatewaySecret }}{{ .Values.mcpContextForge.mcpGatewaySecret.name }}{{ end }} + {{- end }} - configMapRef: name: {{ include "mcp-stack.fullname" . }}-gateway-config diff --git a/charts/mcp-stack/templates/job-migration.yaml b/charts/mcp-stack/templates/job-migration.yaml index 0f510bb3..1b7dfdcb 100644 --- a/charts/mcp-stack/templates/job-migration.yaml +++ b/charts/mcp-stack/templates/job-migration.yaml @@ -40,22 +40,30 @@ spec: env: # ---------- POSTGRES ---------- - name: POSTGRES_HOST - value: {{ printf "%s-postgres" (include "mcp-stack.fullname" .) }} + valueFrom: + configMapKeyRef: + key: POSTGRES_HOST + name: postgres-config - name: POSTGRES_PORT - value: "{{ .Values.mcpContextForge.env.postgres.port }}" + valueFrom: + configMapKeyRef: + key: POSTGRES_PORT + name: postgres-config - name: POSTGRES_DB - value: "{{ .Values.mcpContextForge.env.postgres.db }}" + valueFrom: + configMapKeyRef: + key: POSTGRES_DB + name: postgres-config - name: POSTGRES_USER valueFrom: secretKeyRef: - name: {{ include "mcp-stack.postgresSecretName" . | trim }} - key: POSTGRES_USER + name: {{ if .Values.pgSecretMounts }}{{ .Values.pgSecretMounts.name }}{{ else }}{{ include "mcp-stack.postgresSecretName" . | trim }}{{ end }} + key: {{ if .Values.pgSecretMounts }}{{ .Values.pgSecretMounts.userNameKey }}{{ else }}POSTGRES_USER{{ end }} - name: POSTGRES_PASSWORD valueFrom: secretKeyRef: - name: {{ include "mcp-stack.postgresSecretName" . | trim }} - key: POSTGRES_PASSWORD - + name: {{ if .Values.pgSecretMounts }}{{ .Values.pgSecretMounts.name }}{{ else }}{{ include "mcp-stack.postgresSecretName" . | trim }}{{ end }} + key: {{ if .Values.pgSecretMounts }}{{ .Values.pgSecretMounts.passwordKeyKey }}{{ else }}POSTGRES_PASSWORD{{ end }} # ---------- DERIVED URLS ---------- - name: DATABASE_URL value: >- @@ -71,6 +79,8 @@ spec: {{- if .Values.global.imagePullSecrets }} imagePullSecrets: - {{- toYaml .Values.global.imagePullSecrets | nindent 8 }} + {{- range .Values.global.imagePullSecrets }} + - name: {{ . }} + {{- end }} {{- end }} {{- end }} diff --git a/charts/mcp-stack/templates/secret-gateway.yaml b/charts/mcp-stack/templates/secret-gateway.yaml index 28b7e05f..3b9f2606 100644 --- a/charts/mcp-stack/templates/secret-gateway.yaml +++ b/charts/mcp-stack/templates/secret-gateway.yaml @@ -7,8 +7,7 @@ Kubernetes will base64-encode them on creation. - Put ONLY sensitive credentials or tokens here. ------------------------------------------------------------------- */}} - -{{- if .Values.mcpContextForge.secret }} +{{- if .Values.mcpContextForge.secret.create }} apiVersion: v1 kind: Secret metadata: @@ -17,9 +16,13 @@ metadata: {{- include "mcp-stack.labels" . | nindent 4 }} app.kubernetes.io/component: gateway type: Opaque -stringData: -{{- /* Iterate over every key in mcpContextForge.secret */}} -{{- range $key, $val := .Values.mcpContextForge.secret }} - {{ $key }}: {{ $val | quote }} -{{- end }} +data: + BASIC_AUTH_USER: {{ default "admin" .Values.mcpContextForge.secret.data.BASIC_AUTH_USER | b64enc }} + BASIC_AUTH_PASSWORD: {{- if or .Values.mcpContextForge.secret.regeneratePassword (not .Values.mcpContextForge.secret.data.BASIC_AUTH_PASSWORD) }} + {{ randAlphaNum 32 | b64enc }} + {{- else }} + {{ .Values.mcpContextForge.secret.data.BASIC_AUTH_PASSWORD | b64enc }} + {{- end }} + JWT_SECRET_KEY: {{ .Values.mcpContextForge.secret.data.JWT_SECRET_KEY | b64enc }} + AUTH_ENCRYPTION_SECRET: {{ .Values.mcpContextForge.secret.data.AUTH_ENCRYPTION_SECRET | b64enc }} {{- end }} diff --git a/charts/mcp-stack/templates/secret-postgres.yaml b/charts/mcp-stack/templates/secret-postgres.yaml index 62969e63..f0a2ae4a 100644 --- a/charts/mcp-stack/templates/secret-postgres.yaml +++ b/charts/mcp-stack/templates/secret-postgres.yaml @@ -1,5 +1,5 @@ # templates/secret-postgres.yaml -{{- if and .Values.postgres.enabled (not .Values.postgres.existingSecret) }} +{{- if and .Values.postgres.enabled (not .Values.postgres.pgSecretMounts) }} apiVersion: v1 kind: Secret metadata: @@ -7,7 +7,16 @@ metadata: type: Opaque stringData: # add the keys the Postgres image needs - POSTGRES_USER: {{ .Values.postgres.credentials.user | quote }} + POSTGRES_USER: {{ .Values.postgres.credentials.user | quote }} POSTGRES_PASSWORD: {{ .Values.postgres.credentials.password | quote }} - POSTGRES_DB: {{ .Values.postgres.credentials.database | quote }} +{{- else if and .Values.postgres.generatePostgresqlPasswordSecret.enabled (not .Values.postgres.enabled ) }} +apiVersion: v1 +kind: Secret +metadata: + name: "{{ include "mcp-stack.postgresSecretName" . | trim }}" +type: Opaque +stringData: + # add the keys the Postgres image needs + POSTGRES_USER: {{ .Values.postgres.generatePostgresqlPasswordSecret.postgresqlUsername | quote }} + POSTGRES_PASSWORD: {{ .Values.postgres.generatePostgresqlPasswordSecret.postgresqlPassword | quote }} {{- end }} diff --git a/charts/mcp-stack/values.schema.json b/charts/mcp-stack/values.schema.json index 9e79ef37..d133fa4f 100644 --- a/charts/mcp-stack/values.schema.json +++ b/charts/mcp-stack/values.schema.json @@ -203,47 +203,12 @@ "type": "string", "description": "Host binding address", "default": "0.0.0.0" - }, - "postgres": { - "type": "object", - "description": "PostgreSQL connection configuration", - "properties": { - "port": { - "type": "integer", - "minimum": 1, - "maximum": 65535, - "default": 5432 - }, - "db": { - "type": "string", - "default": "postgresdb" - }, - "userKey": { - "type": "string", - "default": "POSTGRES_USER" - }, - "passwordKey": { - "type": "string", - "default": "POSTGRES_PASSWORD" - } - }, - "additionalProperties": false - }, - "redis": { - "type": "object", - "description": "Redis connection configuration", - "properties": { - "port": { - "type": "integer", - "minimum": 1, - "maximum": 65535, - "default": 6379 - } - }, - "additionalProperties": false } }, - "additionalProperties": false + "additionalProperties": false}, + "mcpGatewaySecret": { + "type": "object", + "description": "External Secret configuration" }, "config": { "type": "object", @@ -526,6 +491,22 @@ "description": "File lock path", "default": "gateway_healthcheck_init.lock" }, + "AUTH_REQUIRED": { + "type": "string", + "enum": ["true", "false"], + "description": "Require authentication", + "default": "true" + }, + "JWT_ALGORITHM": { + "type": "string", + "description": "JWT algorithm", + "default": "HS256" + }, + "TOKEN_EXPIRY": { + "type": "string", + "description": "Token expiry in minutes", + "default": "10080" + }, "DEV_MODE": { "type": "string", "enum": ["true", "false"], @@ -561,27 +542,11 @@ "description": "Basic auth password", "default": "changeme" }, - "AUTH_REQUIRED": { - "type": "string", - "enum": ["true", "false"], - "description": "Require authentication", - "default": "true" - }, "JWT_SECRET_KEY": { "type": "string", "description": "JWT secret key", "default": "my-test-key" }, - "JWT_ALGORITHM": { - "type": "string", - "description": "JWT algorithm", - "default": "HS256" - }, - "TOKEN_EXPIRY": { - "type": "string", - "description": "Token expiry in minutes", - "default": "10080" - }, "AUTH_ENCRYPTION_SECRET": { "type": "string", "description": "Auth encryption secret", @@ -759,6 +724,31 @@ }, "additionalProperties": false }, + "pgSecretMounts": { + "type": "object", + "description": "External Secret configuration" + }, + "host": { + "type": "string", + "description": "PostgreSQL External Host configuration", + "default": "postgres" }, + + "port": { + "type": ["integer", "null"], + "minimum": 1, + "maximum": 65535, + "default": null, + "description": "PostgreSQL port, leave null to let user set it manually for their external postgreSQL" + }, + "db": { + "type": "string", + "default": "postgresdb" + }, + "database": { + "type": "string", + "default": "postgresdb", + "description": "PostgreSQL DB name for the default installation" + }, "persistence": { "type": "object", "description": "PostgreSQL persistence configuration", @@ -791,11 +781,25 @@ }, "additionalProperties": false }, - "existingSecret": { - "type": "string", - "description": "Existing secret name", - "default": "" - }, + "generatePostgresqlPasswordSecret": { + "type": "object", + "description": "PostgreSQL secret configuration", + "properties": { + "enabled": { + "type": "boolean", + "description": "Create Secret of the externally deployed postgres", + "default": false + }, + "postgresqlPassword": { + "type": "string", + "description": "Create Secret of the externally deployed postgres for password" + }, + "postgresqlUsername": { + "type": "string", + "description": "Create Secret of the externally deployed postgre for username" + }}, + "additionalProperties": false + }, "credentials": { "type": "object", "description": "PostgreSQL credentials", @@ -892,6 +896,16 @@ }, "additionalProperties": false }, + "port": { + "type": "integer", + "minimum": 1, + "maximum": 65535, + "default": 6379 + }, + "host": { + "type": "string", + "default": "redis" + }, "resources": { "$ref": "#/$defs/resources", "description": "Resource limits and requests" diff --git a/charts/mcp-stack/values.yaml b/charts/mcp-stack/values.yaml index 98955371..9d4f7973 100644 --- a/charts/mcp-stack/values.yaml +++ b/charts/mcp-stack/values.yaml @@ -95,20 +95,6 @@ mcpContextForge: #################################################################### env: host: 0.0.0.0 # bind address inside the container - - postgres: - # host is auto-generated as -mcp-stack-postgres - # host: postgres # uncomment to override the generated name - port: 5432 - db: postgresdb - userKey: POSTGRES_USER # key in the secret that stores the username - passwordKey: POSTGRES_PASSWORD - - redis: - # host is auto-generated as -mcp-stack-redis - # host: redis # uncomment to override the generated name - port: 6379 - #################################################################### # PLAIN-TEXT (NON-SECRET) SETTINGS # Rendered into a ConfigMap; readable by anyone with GET access. @@ -195,6 +181,12 @@ mcpContextForge: UNHEALTHY_THRESHOLD: "3" # failed checks before peer marked unhealthy FILELOCK_NAME: gateway_healthcheck_init.lock # lock file used at start-up + + # ─ Admin & auth ─ + AUTH_REQUIRED: "true" # enforce authentication globally (true/false) + JWT_ALGORITHM: HS256 # signing algorithm for JWT tokens + TOKEN_EXPIRY: "10080" # JWT validity (minutes); 10080 = 7 days + # ─ Development toggles ─ DEV_MODE: "false" # enable dev-mode features RELOAD: "false" # auto-reload code on changes @@ -207,35 +199,38 @@ mcpContextForge: # so their placeholders resolve at runtime. Override them if needed. #################################################################### secret: - # ─ Admin & auth ─ - BASIC_AUTH_USER: admin # username for basic-auth login - BASIC_AUTH_PASSWORD: changeme # password for basic-auth (CHANGE IN PROD!) - AUTH_REQUIRED: "true" # enforce authentication globally (true/false) - JWT_SECRET_KEY: my-test-key # secret key used to sign JWT tokens - JWT_ALGORITHM: HS256 # signing algorithm for JWT tokens - TOKEN_EXPIRY: "10080" # JWT validity (minutes); 10080 = 7 days - AUTH_ENCRYPTION_SECRET: my-test-salt # passphrase to derive AES key for secure storage - # (derived URLs are defined in deployment-mcp.yaml) - - # ─ Optional database / redis overrides ─ - # DATABASE_URL: "postgresql://admin:s3cr3t@db.acme.com:5432/prod" # override the auto-generated URL - # REDIS_URL: "redis://cache.acme.com:6379/0" # override the auto-generated URL - - #################################################################### - # Names of ConfigMap / Secret are resolved by templates; leave as-is. + # create: true if want to create the secret, recommended only for personal/quick installs + create: false + regeneatePassword: false # set to true to generate a new password each time + data: + BASIC_AUTH_USER: admin # username for basic-auth login + BASIC_AUTH_PASSWORD: "" # Password for basic authentication. + # - If left empty and `regeneratePassword: true`, a random password will be generated at install and on every upgrade. + # - If left empty and `regeneratePassword: false`, the same password will be retained across upgrades. + # - If a value is provided, it will be used as-is regardless of `regeneratePassword`. + JWT_SECRET_KEY: my-test-key # secret key used to sign JWT tokens + AUTH_ENCRYPTION_SECRET: my-test-salt # passphrase to derive AES key for secure storage + ################################################################### + # mcpSecret , sameple key value with description as follows + # JWT_SECRET_KEY: my-test-key # secret key used to sign JWT tokens and + # AUTH_ENCRYPTION_SECRET: my-test-salt # passphrase to derive AES key for secure storage + # BASIC_AUTH_USER: admin # username for basic-auth login + # BASIC_AUTH_PASSWORD: changeme # password for basic-auth (CHANGE IN PROD!) + # Secrets must be manually created in the namespace and will be mounted to the MCP gateway deployment + # Define key as BASIC_AUTH_USER,BASIC_AUTH_PASSWORD, JWT_SECRET_KEY and AUTH_ENCRYPTION_SECRET #################################################################### - envFrom: - - secretRef: - name: mcp-gateway-secret - - configMapRef: - name: mcp-gateway-config + mcpGatewaySecret: + # name: mcp-cf-gateway-secret + # secretName: mcp-cf-gateway-secret + # readOnly: true + # optional: false ######################################################################## # DATABASE MIGRATION (Alembic) # Runs as a Job before mcpgateway deployment ######################################################################## migration: - enabled: true # Set to false to skip migrations + enabled: false # Set to false to skip migrations # Job configuration restartPolicy: Never # Job should not restart on failure @@ -270,7 +265,7 @@ postgres: enabled: true image: - repository: postgres + repository: postgres ## docker.io/bitnami/postgresql:17.5.0 #More compatible with RHOCP tag: "17" pullPolicy: IfNotPresent @@ -278,6 +273,8 @@ postgres: type: ClusterIP port: 5432 + database: mcpgateway + # PersistentVolumeClaim for data durability persistence: enabled: true @@ -285,9 +282,6 @@ postgres: accessModes: [ReadWriteMany] size: 5Gi - # Leave blank to autogenerate -mcp-stack-postgres-secret. - existingSecret: "" - credentials: # used only when existingSecret is blank database: postgresdb user: admin @@ -321,6 +315,34 @@ postgres: timeoutSeconds: 3 successThreshold: 1 failureThreshold: 5 + + # set this PostgreSQL hostname/port and db when using an external PostgreSQL database,(Postgres enabled should be false in that case) + # set this PostgreSQL hostname when using an external PostgreSQL database + host: "" + # set this PostgreSQL port when using an external PostgreSQL database + port: + # set this PostgreSQL database when using an external PostgreSQL database + db: "" + + ################################################################### + # Postgres server secret mounts, if providing externally managed Postgres. + # Secrets must be manually created in the namespace. + # Define key POSTGRES_USER and POSTGRES_PASSWORD + #################################################################### + pgSecretMounts: + # name: postgres-secret + # secretName: postgres-secret + # userNameKey: POSTGRES_USER + # passwordKey: POSTGRES_PASSWORD + # readOnly: true + # optional: false + +# Whether to generate a secret resource for the PostgreSQL password. Useful if +# global.postgresqlSecretName is managed outside of this helm chart and want to automate creating credentials.But its less secure to use in production + generatePostgresqlPasswordSecret: + enabled: false + postgresqlPassword: "" #Change with External PostgreSQL password , ideally not recommended to have this in values.yaml (prod) + postgresqlUsername: "" #Change with External PostgreSQL username ######################################################################## # REDIS CACHE @@ -336,7 +358,11 @@ redis: service: type: ClusterIP port: 6379 - + + # set this Redis hostname/port using an external Redis (Redis enabled should be false in that case) + host: "" + port: 6379 + # ─── Resource limits & requests ─── resources: limits: