diff --git a/DSL/CronManager/script/delete_secrets_from_vault.sh b/DSL/CronManager/script/delete_secrets_from_vault.sh index 3b405927..0e457e41 100644 --- a/DSL/CronManager/script/delete_secrets_from_vault.sh +++ b/DSL/CronManager/script/delete_secrets_from_vault.sh @@ -6,9 +6,18 @@ set -e # Exit on any error # Configuration -# Use vaultAgentUrl which points to vault-agent-cron proxy -# The agent automatically injects the authentication token -VAULT_ADDR="${vaultAgentUrl:-http://vault-agent-cron:8203}" +# Resolve Vault Agent URL: +# 1. Use vaultAgentUrl env var if set (from container env or CronManager request) +# 2. Auto-detect Kubernetes via KUBERNETES_SERVICE_HOST (injected by kubelet, cannot be disabled) +# 3. Auto-detect Kubernetes via service account token (mounted by default in every pod) +# 4. Fallback to Docker Compose hostname +if [ -n "$vaultAgentUrl" ]; then + VAULT_ADDR="$vaultAgentUrl" +elif [ -n "$KUBERNETES_SERVICE_HOST" ] || [ -f "/var/run/secrets/kubernetes.io/serviceaccount/token" ]; then + VAULT_ADDR="http://localhost:8203" +else + VAULT_ADDR="http://vault-agent-cron:8203" +fi # Logging function log() { @@ -169,4 +178,4 @@ delete_llm_secrets # Delete embedding secrets delete_embedding_secrets -log "=== Vault secrets deletion completed ===" +log "=== Vault secrets deletion completed ===" \ No newline at end of file diff --git a/DSL/CronManager/script/store_secrets_in_vault.sh b/DSL/CronManager/script/store_secrets_in_vault.sh index 60784eed..d977f1ef 100644 --- a/DSL/CronManager/script/store_secrets_in_vault.sh +++ b/DSL/CronManager/script/store_secrets_in_vault.sh @@ -6,9 +6,20 @@ set -e # Exit on any error # Configuration -# Use vaultAgentUrl which points to vault-agent-cron proxy -# The agent automatically injects the authentication token -VAULT_ADDR="${vaultAgentUrl:-http://vault-agent-cron:8203}" +# Resolve Vault Agent URL: +# 1. Use vaultAgentUrl env var if set (from container env or CronManager request) +# 2. Auto-detect Kubernetes via KUBERNETES_SERVICE_HOST (injected by kubelet, cannot be disabled) +# 3. Auto-detect Kubernetes via service account token (mounted by default in every pod) +# 4. Fallback to Docker Compose hostname +if [ -n "$vaultAgentUrl" ]; then + VAULT_ADDR="$vaultAgentUrl" +elif [ -n "$KUBERNETES_SERVICE_HOST" ] || [ -f "/var/run/secrets/kubernetes.io/serviceaccount/token" ]; then + VAULT_ADDR="http://localhost:8203" +else + VAULT_ADDR="http://vault-agent-cron:8203" +fi + +echo "DEBUG: VAULT_ADDR=$VAULT_ADDR vaultAgentUrl=$vaultAgentUrl KUBERNETES_SERVICE_HOST=$KUBERNETES_SERVICE_HOST" # Decryption Configuration PRIVATE_KEY_CACHE="" diff --git a/kubernetes/Chart.yaml b/kubernetes/Chart.yaml index eb9a316a..ef6d5a2c 100644 --- a/kubernetes/Chart.yaml +++ b/kubernetes/Chart.yaml @@ -113,4 +113,7 @@ dependencies: version: 0.1.0 repository: "file://./charts/Notifications-Node" condition: Notifications-Node.enabled - + - name: OpenSearch + version: 0.1.0 + repository: "file://./charts/OpenSearch" + condition: OpenSearch.enabled \ No newline at end of file diff --git a/kubernetes/LANGFUSE_SETUP.md b/kubernetes/LANGFUSE_SETUP.md index 6c0f11bd..c54d91af 100644 --- a/kubernetes/LANGFUSE_SETUP.md +++ b/kubernetes/LANGFUSE_SETUP.md @@ -51,9 +51,12 @@ kubectl cp store-langfuse-secrets.sh rag-module/vault-0:/tmp/store-langfuse-secr kubectl exec -n your-namespace vault-0 -- sh -c \ "LANGFUSE_INIT_PROJECT_PUBLIC_KEY=pk-lf-YOUR_KEY \ LANGFUSE_INIT_PROJECT_SECRET_KEY=sk-lf-YOUR_KEY \ + LANGFUSE_HOST=http://langfuse-web:3005 \ sh /tmp/store-langfuse-secrets.sh" ``` Replace `pk-lf-YOUR_KEY` and `sk-lf-YOUR_KEY` with the actual keys from step 3. -The script stores them at `secret/data/langfuse/config` in Vault, where the LLM Orchestration Service reads them. +> **Note:** In Kubernetes, the Langfuse-Web service port is `3005` (mapped to container port 3000), so `LANGFUSE_HOST` must be set explicitly. In Docker Compose, the default (`http://langfuse-web:3000`) is used automatically. + +The script stores them at `secret/data/langfuse/config` in Vault, where the LLM Orchestration Service reads them. \ No newline at end of file diff --git a/kubernetes/charts/CronManager/templates/deployment-byk-cronmanager.yaml b/kubernetes/charts/CronManager/templates/deployment-byk-cronmanager.yaml index 15dc9615..bdf53252 100644 --- a/kubernetes/charts/CronManager/templates/deployment-byk-cronmanager.yaml +++ b/kubernetes/charts/CronManager/templates/deployment-byk-cronmanager.yaml @@ -36,6 +36,14 @@ spec: mountPath: /app/scripts - name: vector-indexer mountPath: /app/src/vector_indexer + - name: tool-classifier + mountPath: /app/src/tool_classifier + - name: intent-data-enrichment + mountPath: /app/src/intent_data_enrichment + - name: api-tool-indexer + mountPath: /app/src/api_tool_indexer + - name: src-utils + mountPath: /app/src/utils command: - sh - -c @@ -45,12 +53,20 @@ spec: mkdir -p /app/src/vector_indexer && mkdir -p /app/scripts && mkdir -p /DSL && - mkdir -p /app/src/utils + mkdir -p /app/src/utils && + mkdir -p /app/src/tool_classifier && + mkdir -p /app/src/intent_data_enrichment && + mkdir -p /app/src/api_tool_indexer cp -r /tmp/rag/DSL/CronManager/DSL/* /DSL/ && cp -r /tmp/rag/DSL/CronManager/script/* /app/scripts/ && cp -r /tmp/rag/src/vector_indexer/* /app/src/vector_indexer/ && - cp -r /tmp/rag/src/utils/decrypt_vault_secrets.py /app/src/utils/ && + cp -r /tmp/rag/src/tool_classifier/* /app/src/tool_classifier/ && + cp -r /tmp/rag/src/intent_data_enrichment/* /app/src/intent_data_enrichment/ && + cp -r /tmp/rag/src/api_tool_indexer/* /app/src/api_tool_indexer/ && + cp /tmp/rag/src/utils/decrypt_vault_secrets.py /app/src/utils/ && + cp /tmp/rag/src/__init__.py /app/src/__init__.py && + cp /tmp/rag/grafana-configs/loki_logger.py /app/src/vector_indexer/loki_logger.py && # Set execute permissions on all shell scripts chmod +x /app/scripts/*.sh && @@ -91,7 +107,7 @@ spec: value: {{ .Values.cronmanager.environment.pythonPath | quote }} {{- if .Values.vaultAgent.enabled }} # Vault Agent proxy URL (localhost sidecar) - - name: VAULT_AGENT_URL + - name: vaultAgentUrl value: "http://localhost:8203" {{- end }} - name: RAG_MODULE_RUUTER_PRIVATE @@ -112,6 +128,14 @@ spec: mountPath: /app/scripts - name: vector-indexer mountPath: /app/src/vector_indexer + - name: tool-classifier + mountPath: /app/src/tool_classifier + - name: intent-data-enrichment + mountPath: /app/src/intent_data_enrichment + - name: api-tool-indexer + mountPath: /app/src/api_tool_indexer + - name: src-utils + mountPath: /app/src/utils - name: datasets mountPath: /app/datasets @@ -122,8 +146,16 @@ spec: emptyDir: {} - name: vector-indexer emptyDir: {} + - name: tool-classifier + emptyDir: {} + - name: intent-data-enrichment + emptyDir: {} + - name: api-tool-indexer + emptyDir: {} - name: datasets emptyDir: {} + - name: src-utils + emptyDir: {} - name: cronmanager-data persistentVolumeClaim: claimName: "{{ .Values.release_name }}-data" diff --git a/kubernetes/charts/CronManager/values.yaml b/kubernetes/charts/CronManager/values.yaml index df8013cf..4db03e3e 100644 --- a/kubernetes/charts/CronManager/values.yaml +++ b/kubernetes/charts/CronManager/values.yaml @@ -11,7 +11,7 @@ cronmanager: environment: containerPort: "8080" - pythonPath: "/app:/app/src/vector_indexer" + pythonPath: "/app:/app/src:/app/src/vector_indexer:/app/src/intent_data_enrichment:/app/src/api_tool_indexer" VAULT_ADDR: "http://vault:8200" service: diff --git a/kubernetes/charts/GUI/templates/configmap-vite-config.yaml b/kubernetes/charts/GUI/templates/configmap-vite-config.yaml index 7110554b..fe4e29cc 100644 --- a/kubernetes/charts/GUI/templates/configmap-vite-config.yaml +++ b/kubernetes/charts/GUI/templates/configmap-vite-config.yaml @@ -45,6 +45,21 @@ data: 'Content-Security-Policy': process.env.REACT_APP_CSP, }), }, + proxy: { + '/vault-agent-gui': { + target: 'http://localhost:8202', + changeOrigin: true, + rewrite: (path) => path.replace(/^\/vault-agent-gui/, ''), + }, + '/sse': { + target: 'http://notifications-node:4040', + changeOrigin: true, + }, + '/channels': { + target: 'http://notifications-node:4040', + changeOrigin: true, + }, + }, }, resolve: { alias: { @@ -53,4 +68,4 @@ data: }, }, }); -{{- end }} +{{- end }} \ No newline at end of file diff --git a/kubernetes/charts/GUI/values.yaml b/kubernetes/charts/GUI/values.yaml index 03257659..50c1ac9a 100644 --- a/kubernetes/charts/GUI/values.yaml +++ b/kubernetes/charts/GUI/values.yaml @@ -14,10 +14,10 @@ gui: #service URLs services: - ruuterPublic: "http:///ruuter-public" - ruuterPrivate: "http:///ruuter-private" - authenticationLayer: "http://" - notificationNode: "http://notifications-node:4040" + ruuterPublic: "http://localhost:8086" + ruuterPrivate: "http://localhost:8088" + authenticationLayer: "http://localhost:3004" + notificationNode: "http://localhost:3003" datasetGenerator: "http://dataset-gen-service:8000" # Content Security Policy - Updated for browser access @@ -33,7 +33,7 @@ gui: # Ingress host ingress: - host: "" # Update with actual domain + host: "localhost" # Update with actual domain resources: limits: @@ -52,20 +52,4 @@ gui: # Vault Agent sidecar configuration vaultAgent: - enabled: true - - - # ingress: - # enabled: true - # className: nginx - # annotations: - # nginx.ingress.kubernetes.io/rewrite-target: / - # nginx.ingress.kubernetes.io/proxy-read-timeout: "3600" - # nginx.ingress.kubernetes.io/proxy-send-timeout: "3600" - # nginx.ingress.kubernetes.io/proxy-body-size: "50m" - # hosts: - # - host: rag.local - # paths: - # - path: / - # pathType: Prefix - # tls: [] \ No newline at end of file + enabled: true \ No newline at end of file diff --git a/kubernetes/charts/LLM-Orchestration-Service/templates/deployment-byk-llm-orchestration.yaml b/kubernetes/charts/LLM-Orchestration-Service/templates/deployment-byk-llm-orchestration.yaml index 3e0feacb..fdfca98b 100644 --- a/kubernetes/charts/LLM-Orchestration-Service/templates/deployment-byk-llm-orchestration.yaml +++ b/kubernetes/charts/LLM-Orchestration-Service/templates/deployment-byk-llm-orchestration.yaml @@ -21,6 +21,7 @@ spec: initContainers: - name: volume-init image: "{{ .Values.initContainer.image.repository }}:{{ .Values.initContainer.image.tag }}" + imagePullPolicy: {{ .Values.initContainer.image.pullPolicy }} command: - sh - -c @@ -146,6 +147,11 @@ spec: - name: logs-volume mountPath: {{ .Values.volumes.logs.mountPath }} {{- end }} + {{- if .Values.vaultAgent.enabled }} + - name: vault-agent-llm-token + mountPath: /agent/llm-token + readOnly: true + {{- end }} resources: requests: diff --git a/kubernetes/charts/LLM-Orchestration-Service/values.yaml b/kubernetes/charts/LLM-Orchestration-Service/values.yaml index 7e457d22..6db9bcfe 100644 --- a/kubernetes/charts/LLM-Orchestration-Service/values.yaml +++ b/kubernetes/charts/LLM-Orchestration-Service/values.yaml @@ -50,6 +50,7 @@ initContainer: image: repository: "ghcr.io/buerokratt/llm-orchestration-service" # Update with actual llm-orchestration image repository tag: "latest" + pullPolicy: "IfNotPresent" # InitContainer will prepare the runtime volumes prepareVolumes: true @@ -73,9 +74,22 @@ healthcheck: # Additional readiness checks readinessPath: "/ready" +# Environment variables injected into the LLM container +# Redis defaults match the in-cluster Redis service (see Redis chart) +env: + REDIS_HOST: "redis" + REDIS_PORT: "6379" + REDIS_AUTH: "myredissecret" + REDIS_SESSION_DB: "0" + VAULT_AGENT_PROXY: "true" + TOOL_CLASSIFIER_ENABLED: "true" + SERVICE_WORKFLOW_ENABLED: "true" + API_TOOL_CALLING_WORKFLOW_ENABLED: "true" + CONTEXT_WORKFLOW_ENABLED: "true" + MULTI_INTENT_ENABLED: "true" + # Vault Agent sidecar configuration # WHY: LLM Orchestration needs read access to encrypted LLM API keys # Security: Agent enforces policy - read-only access to LLM secrets vaultAgent: - enabled: true - + enabled: true \ No newline at end of file diff --git a/kubernetes/charts/Langfuse-Web/templates/deployment-byk-langfuse-web.yaml b/kubernetes/charts/Langfuse-Web/templates/deployment-byk-langfuse-web.yaml index 18d14804..f7e3e054 100644 --- a/kubernetes/charts/Langfuse-Web/templates/deployment-byk-langfuse-web.yaml +++ b/kubernetes/charts/Langfuse-Web/templates/deployment-byk-langfuse-web.yaml @@ -50,6 +50,10 @@ spec: - name: http containerPort: {{ .Values.service.targetPort }} protocol: TCP + {{- if .Values.envFrom }} + envFrom: + {{- toYaml .Values.envFrom | nindent 12 }} + {{- end }} env: {{- range $key, $value := .Values.env }} - name: {{ $key }} diff --git a/kubernetes/charts/Langfuse-Web/values.yaml b/kubernetes/charts/Langfuse-Web/values.yaml index 6dfaf1cf..ce4da5b7 100644 --- a/kubernetes/charts/Langfuse-Web/values.yaml +++ b/kubernetes/charts/Langfuse-Web/values.yaml @@ -17,6 +17,7 @@ service: # Environment variables env: # Non-sensitive configuration + HOSTNAME: "0.0.0.0" NEXTAUTH_URL: "http://localhost:3000" TELEMETRY_ENABLED: "true" LANGFUSE_ENABLE_EXPERIMENTAL_FEATURES: "true" @@ -53,9 +54,9 @@ env: REDIS_HOST: "redis" REDIS_PORT: "6379" REDIS_TLS_ENABLED: "false" - REDIS_TLS_CA: "" - REDIS_TLS_CERT: "" - REDIS_TLS_KEY: "" + REDIS_TLS_CA: "/certs/ca.crt" + REDIS_TLS_CERT: "/certs/redis.crt" + REDIS_TLS_KEY: "/certs/redis.key" # Email configuration EMAIL_FROM_ADDRESS: "" @@ -90,7 +91,7 @@ resources: pullPolicy: IfNotPresent healthcheck: - enabled: true + enabled: false initialDelaySeconds: 60 periodSeconds: 30 timeoutSeconds: 10 diff --git a/kubernetes/charts/Langfuse-Worker/values.yaml b/kubernetes/charts/Langfuse-Worker/values.yaml index 0a7343eb..b02bfe4a 100644 --- a/kubernetes/charts/Langfuse-Worker/values.yaml +++ b/kubernetes/charts/Langfuse-Worker/values.yaml @@ -16,6 +16,7 @@ service: # Environment variables env: # Non-sensitive configuration + HOSTNAME: "0.0.0.0" NEXTAUTH_URL: "http://localhost:3000" TELEMETRY_ENABLED: "true" LANGFUSE_ENABLE_EXPERIMENTAL_FEATURES: "true" @@ -52,9 +53,9 @@ env: REDIS_HOST: "redis" REDIS_PORT: "6379" REDIS_TLS_ENABLED: "false" - REDIS_TLS_CA: "" - REDIS_TLS_CERT: "" - REDIS_TLS_KEY: "" + REDIS_TLS_CA: "/certs/ca.crt" + REDIS_TLS_CERT: "/certs/redis.crt" + REDIS_TLS_KEY: "/certs/redis.key" # Email configuration EMAIL_FROM_ADDRESS: "" @@ -77,7 +78,7 @@ resources: pullPolicy: IfNotPresent healthcheck: - enabled: true + enabled: false initialDelaySeconds: 60 periodSeconds: 30 timeoutSeconds: 10 diff --git a/kubernetes/charts/Loki/templates/deployment-loki.yaml b/kubernetes/charts/Loki/templates/deployment-loki.yaml index 7967b8a3..9bf85dd3 100644 --- a/kubernetes/charts/Loki/templates/deployment-loki.yaml +++ b/kubernetes/charts/Loki/templates/deployment-loki.yaml @@ -25,6 +25,7 @@ spec: volumeMounts: - name: config mountPath: /etc/loki/local-config.yaml + subPath: loki.yaml {{- if .Values.persistence.enabled }} - name: storage mountPath: /loki diff --git a/kubernetes/charts/Notifications-Node/Chart.yaml b/kubernetes/charts/Notifications-Node/Chart.yaml new file mode 100644 index 00000000..a7756889 --- /dev/null +++ b/kubernetes/charts/Notifications-Node/Chart.yaml @@ -0,0 +1,6 @@ +apiVersion: v2 +name: Notifications-Node +description: A Helm chart for Notifications server +type: application +version: 0.1.0 +appVersion: "1.0" \ No newline at end of file diff --git a/kubernetes/charts/Notifications-Node/templates/deployment-byk-notifications.yaml b/kubernetes/charts/Notifications-Node/templates/deployment-byk-notifications.yaml new file mode 100644 index 00000000..81141337 --- /dev/null +++ b/kubernetes/charts/Notifications-Node/templates/deployment-byk-notifications.yaml @@ -0,0 +1,69 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .Values.release_name }} + labels: + app: {{ .Values.release_name }} +spec: + replicas: {{ .Values.replicas }} + selector: + matchLabels: + app: {{ .Values.release_name }} + template: + metadata: + labels: + app: {{ .Values.release_name }} + spec: + containers: + - name: {{ .Values.release_name }} + image: "{{ .Values.notifications.image.repository }}:{{ .Values.notifications.image.tag }}" + imagePullPolicy: {{ .Values.notifications.image.pullPolicy }} + ports: + - containerPort: {{ .Values.notifications.port }} + protocol: TCP + env: + # Node.js application configuration + - name: NODE_ENV + value: {{ .Values.notifications.nodeEnv | quote }} + - name: PORT + value: {{ .Values.notifications.port | quote }} + - name: REFRESH_INTERVAL + value: {{ .Values.notifications.refreshInterval | quote }} + + # OpenSearch configuration + {{- if .Values.notifications.opensearch.enabled }} + - name: OPENSEARCH_PROTOCOL + value: {{ .Values.notifications.opensearch.protocol | quote }} + - name: OPENSEARCH_HOST + value: {{ .Values.notifications.opensearch.host | quote }} + - name: OPENSEARCH_PORT + value: {{ .Values.notifications.opensearch.port | quote }} + - name: OPENSEARCH_USERNAME + valueFrom: + secretKeyRef: + name: notifications-env-secret + key: OPENSEARCH_USERNAME + - name: OPENSEARCH_PASSWORD + valueFrom: + secretKeyRef: + name: notifications-env-secret + key: OPENSEARCH_PASSWORD + {{- end }} + + # CORS configuration + - name: CORS_WHITELIST_ORIGINS + value: {{ .Values.notifications.cors.whitelistOrigins | quote }} + + # BYK Stack integration + - name: RUUTER_URL + value: {{ .Values.notifications.services.ruuterUrl | quote }} + + resources: + limits: + cpu: {{ .Values.notifications.resources.limits.cpu }} + memory: {{ .Values.notifications.resources.limits.memory }} + requests: + cpu: {{ .Values.notifications.resources.requests.cpu }} + memory: {{ .Values.notifications.resources.requests.memory }} + + restartPolicy: Always \ No newline at end of file diff --git a/kubernetes/charts/Notifications-Node/templates/secret-byk-notifications.yaml b/kubernetes/charts/Notifications-Node/templates/secret-byk-notifications.yaml new file mode 100644 index 00000000..5119a1c7 --- /dev/null +++ b/kubernetes/charts/Notifications-Node/templates/secret-byk-notifications.yaml @@ -0,0 +1,13 @@ +{{- if .Values.notifications.opensearch.enabled }} +apiVersion: v1 +kind: Secret +metadata: + name: notifications-env-secret + labels: + app: {{ .Values.release_name }} + +type: Opaque +data: + OPENSEARCH_USERNAME: {{ .Values.notifications.opensearch.username | b64enc }} + OPENSEARCH_PASSWORD: {{ .Values.notifications.opensearch.password | b64enc }} +{{- end }} \ No newline at end of file diff --git a/kubernetes/charts/Notifications-Node/templates/service-byk-notifications.yaml b/kubernetes/charts/Notifications-Node/templates/service-byk-notifications.yaml new file mode 100644 index 00000000..fbd8da49 --- /dev/null +++ b/kubernetes/charts/Notifications-Node/templates/service-byk-notifications.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ .Values.release_name }} + labels: + app: {{ .Values.release_name }} +spec: + type: {{ .Values.notifications.service.type }} + ports: + - port: {{ .Values.notifications.service.port }} + targetPort: {{ .Values.notifications.service.targetPort }} + protocol: TCP + name: http + selector: + app: {{ .Values.release_name }} + \ No newline at end of file diff --git a/kubernetes/charts/Notifications-Node/values.yaml b/kubernetes/charts/Notifications-Node/values.yaml new file mode 100644 index 00000000..9ad67631 --- /dev/null +++ b/kubernetes/charts/Notifications-Node/values.yaml @@ -0,0 +1,52 @@ +replicas: 1 + +podAnnotations: {} +podSecurityContext: {} +securityContext: {} + +release_name: "notifications-node" + +notifications: + image: + repository: public.ecr.aws/e7g9l0j0/rag-module/notification-server + tag: latest + pullPolicy: IfNotPresent + + # Node.js application configuration + port: 4040 + refreshInterval: 1000 + nodeEnv: production + + # OpenSearch configuration + opensearch: + enabled: true + protocol: http + host: opensearch-node + port: 9200 + username: admin + password: admin + + # CORS configuration for frontend access + cors: + whitelistOrigins: "http://gui:3001,http://gui:3002,http://gui:3003,http://authentication-layer:3004,http://ruuter-public:8086,http://ruuter-private:8088" + + # BYK Stack integration + services: + ruuterUrl: "http://ruuter-public:8086" + + resources: + limits: + cpu: 500m + memory: 512Mi + requests: + cpu: 100m + memory: 128Mi + + service: + type: ClusterIP + port: 4040 + targetPort: 4040 + + # Security configuration + security: + csrfEnabled: true \ No newline at end of file diff --git a/kubernetes/charts/OpenSearch/Chart.yaml b/kubernetes/charts/OpenSearch/Chart.yaml new file mode 100644 index 00000000..58322f7c --- /dev/null +++ b/kubernetes/charts/OpenSearch/Chart.yaml @@ -0,0 +1,6 @@ +apiVersion: v2 +name: OpenSearch +description: A Helm chart for OpenSearch search and analytics engine +type: application +version: 0.1.0 +appVersion: "2.11.1" \ No newline at end of file diff --git a/kubernetes/charts/OpenSearch/templates/deployment-byk-opensearch.yaml b/kubernetes/charts/OpenSearch/templates/deployment-byk-opensearch.yaml new file mode 100644 index 00000000..48239ee6 --- /dev/null +++ b/kubernetes/charts/OpenSearch/templates/deployment-byk-opensearch.yaml @@ -0,0 +1,77 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .Values.release_name }} + labels: + app: {{ .Values.release_name }} +spec: + replicas: {{ .Values.replicas }} + selector: + matchLabels: + app: {{ .Values.release_name }} + template: + metadata: + labels: + app: {{ .Values.release_name }} + spec: + containers: + - name: {{ .Values.release_name }} + image: "{{ .Values.opensearch.image.repository }}:{{ .Values.opensearch.image.tag }}" + imagePullPolicy: {{ .Values.opensearch.image.pullPolicy }} + securityContext: + capabilities: + add: ["IPC_LOCK", "SYS_RESOURCE"] + ports: + - containerPort: {{ .Values.opensearch.ports.api }} + name: api + protocol: TCP + - containerPort: {{ .Values.opensearch.ports.performance }} + name: performance + protocol: TCP + env: + # Cluster configuration + - name: node.name + value: {{ .Values.opensearch.cluster.nodeName | quote }} + - name: cluster.name + value: {{ .Values.opensearch.cluster.name | quote }} + - name: discovery.type + value: {{ .Values.opensearch.cluster.discoveryType | quote }} + - name: discovery.seed_hosts + value: {{ .Values.opensearch.cluster.seed_hosts | quote }} + + # Java memory configuration + - name: OPENSEARCH_JAVA_OPTS + value: {{ .Values.opensearch.javaOpts | quote }} + + # Performance configuration + - name: bootstrap.memory_lock + value: {{ .Values.opensearch.bootstrapMemoryLock | quote }} + + # Security configuration + {{- if not .Values.opensearch.security.enabled }} + - name: plugins.security.disabled + value: "true" + {{- end }} + + {{- if .Values.opensearch.persistence.enabled }} + volumeMounts: + - name: opensearch-data + mountPath: {{ .Values.opensearch.persistence.mountPath }} + {{- end }} + + resources: + limits: + cpu: {{ .Values.opensearch.resources.limits.cpu }} + memory: {{ .Values.opensearch.resources.limits.memory }} + requests: + cpu: {{ .Values.opensearch.resources.requests.cpu }} + memory: {{ .Values.opensearch.resources.requests.memory }} + + {{- if .Values.opensearch.persistence.enabled }} + volumes: + - name: opensearch-data + persistentVolumeClaim: + claimName: {{ .Values.release_name }}-data-pvc + {{- end }} + + restartPolicy: Always \ No newline at end of file diff --git a/kubernetes/charts/OpenSearch/templates/ingress.yaml b/kubernetes/charts/OpenSearch/templates/ingress.yaml new file mode 100644 index 00000000..201079f1 --- /dev/null +++ b/kubernetes/charts/OpenSearch/templates/ingress.yaml @@ -0,0 +1,43 @@ +{{- if .Values.opensearch.ingress.enabled -}} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ .Values.release_name }}-ingress + labels: + app: {{ .Values.release_name }} + {{- with .Values.opensearch.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if .Values.opensearch.ingress.className }} + ingressClassName: {{ .Values.opensearch.ingress.className }} + {{- end }} + {{- if .Values.opensearch.ingress.tls }} + tls: + {{- range .Values.opensearch.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} + {{- end }} + rules: + {{- range .Values.opensearch.ingress.hosts }} + - host: {{ .host | quote }} + http: + paths: + {{- range .paths }} + - path: {{ .path }} + {{- if .pathType }} + pathType: {{ .pathType }} + {{- end }} + backend: + service: + name: {{ $.Values.release_name }} + port: + number: {{ $.Values.opensearch.service.apiPort }} + {{- end }} + {{- end }} +{{- end }} \ No newline at end of file diff --git a/kubernetes/charts/OpenSearch/templates/pvc-opensearch.yaml b/kubernetes/charts/OpenSearch/templates/pvc-opensearch.yaml new file mode 100644 index 00000000..09417ffc --- /dev/null +++ b/kubernetes/charts/OpenSearch/templates/pvc-opensearch.yaml @@ -0,0 +1,22 @@ +{{- if .Values.opensearch.persistence.enabled }} +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: {{ .Values.release_name }}-data-pvc + namespace: {{ .Release.Namespace }} + labels: + app: {{ .Values.release_name }} +spec: + accessModes: + - {{ .Values.opensearch.persistence.accessMode }} + resources: + requests: + storage: {{ .Values.opensearch.persistence.size }} + {{- if .Values.opensearch.persistence.storageClass }} + {{- if (eq "-" .Values.opensearch.persistence.storageClass) }} + storageClassName: "" + {{- else }} + storageClassName: {{ .Values.opensearch.persistence.storageClass | quote }} + {{- end }} + {{- end }} +{{- end }} \ No newline at end of file diff --git a/kubernetes/charts/OpenSearch/templates/service-byk-opensearch.yaml b/kubernetes/charts/OpenSearch/templates/service-byk-opensearch.yaml new file mode 100644 index 00000000..cf40517d --- /dev/null +++ b/kubernetes/charts/OpenSearch/templates/service-byk-opensearch.yaml @@ -0,0 +1,19 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ .Values.release_name }} + labels: + app: {{ .Values.release_name }} +spec: + type: {{ .Values.opensearch.service.type }} + ports: + - port: {{ .Values.opensearch.service.api }} + targetPort: {{ .Values.opensearch.ports.api }} + protocol: TCP + name: api + - port: {{ .Values.opensearch.service.performance }} + targetPort: {{ .Values.opensearch.ports.performance }} + protocol: TCP + name: performance + selector: + app: {{ .Values.release_name }} \ No newline at end of file diff --git a/kubernetes/charts/OpenSearch/values.yaml b/kubernetes/charts/OpenSearch/values.yaml new file mode 100644 index 00000000..185806c7 --- /dev/null +++ b/kubernetes/charts/OpenSearch/values.yaml @@ -0,0 +1,80 @@ +replicas: 1 + +podAnnotations: {} +podSecurityContext: {} +securityContext: {} + +release_name: "opensearch-node" +dashboards_release_name: "opensearch-dashboards" + +opensearch: + image: + repository: opensearchproject/opensearch + tag: "2.11.1" + pullPolicy: IfNotPresent + + + cluster: + name: "opensearch-cluster" + nodeName: "opensearch-node" + discoveryType: "single-node" + seed_hosts: "opensearch" + + # Java memory configuration + javaOpts: "-Xms512m -Xmx512m" + + # Security configuration + security: + enabled: false + + # Performance settings + bootstrapMemoryLock: false + + # Ports configuration for pod + ports: + api: 9200 + performance: 9600 + + # Persistent storage configuration + persistence: + enabled: true + size: 10Gi + storageClass: "" + accessMode: ReadWriteOnce + mountPath: /usr/share/opensearch/data + + resources: + limits: + cpu: 1000m + memory: 2Gi + requests: + cpu: 200m + memory: 1Gi + + # Service configuration + service: + type: ClusterIP + api: 9200 + performance: 9600 + + # Ingress configuration + ingress: + enabled: false + className: nginx + annotations: + nginx.ingress.kubernetes.io/rewrite-target: / + hosts: + - host: opensearch.global-classifier.local + paths: + - path: / + pathType: Prefix + tls: [] + + # Ulimits (required for OpenSearch memory locking) + ulimits: + memlock: + soft: -1 + hard: -1 + nofile: + soft: 65536 + hard: 65536 \ No newline at end of file diff --git a/kubernetes/charts/Ruuter-Private/templates/configmap-byk-ruuter-private.yaml b/kubernetes/charts/Ruuter-Private/templates/configmap-byk-ruuter-private.yaml index 6f84c283..6b158fb9 100644 --- a/kubernetes/charts/Ruuter-Private/templates/configmap-byk-ruuter-private.yaml +++ b/kubernetes/charts/Ruuter-Private/templates/configmap-byk-ruuter-private.yaml @@ -7,12 +7,13 @@ metadata: data: constants.ini: | [DSL] - RAG_SEARCH_RUUTER_PUBLIC=http://ruuter-public:8086/rag-search - RAG_SEARCH_RUUTER_PRIVATE=http://ruuter-private:8088/rag-search - RAG_SEARCH_DMAPPER=http://data-mapper:3000 + RAG_SEARCH_RUUTER_PUBLIC=http://ruuter-public:8086 + RAG_SEARCH_RUUTER_PRIVATE=http://ruuter-private:8088 + RAG_SEARCH_DMAPPER=http://data-mapper:3001 RAG_SEARCH_RESQL=http://resql:8082/rag-search RAG_SEARCH_PROJECT_LAYER=rag-search RAG_SEARCH_TIM=http://tim:8085 RAG_SEARCH_CRON_MANAGER=http://cron-manager:9010 RAG_SEARCH_LLM_ORCHESTRATOR=http://llm-orchestration-service:8100/orchestrate - DOMAIN=localhost \ No newline at end of file + DOMAIN=localhost + DB_PASSWORD=dbadmin \ No newline at end of file diff --git a/kubernetes/charts/Ruuter-Private/values.yaml b/kubernetes/charts/Ruuter-Private/values.yaml index 3a48ac17..f3d5a644 100644 --- a/kubernetes/charts/Ruuter-Private/values.yaml +++ b/kubernetes/charts/Ruuter-Private/values.yaml @@ -6,7 +6,7 @@ images: scope: registry: "ghcr.io" repository: "buerokratt/ruuter" - tag: "v2.2.1" + tag: "v2.2.8" service: type: ClusterIP @@ -15,7 +15,7 @@ service: env: - APPLICATION_CORS_ALLOWEDORIGINS: "http://gui:3001,http://ruuter-private:8088,http://ruuter-public:8086,http://authentication-layer:3004,http://notifications-node:4040,http://dataset-gen-service:8000,http://localhost:3001" + APPLICATION_CORS_ALLOWEDORIGINS: "https://ec2-34-253-140-113.eu-west-1.compute.amazonaws.com:32017,http://gui:3001,http://ruuter-private:8088,http://ruuter-public:8086,http://authentication-layer:3004,http://notifications-node:4040,http://dataset-gen-service:8000,http://localhost:3001" APPLICATION_HTTPCODESALLOWLIST: "200,201,202,400,401,403,500" APPLICATION_INTERNALREQUESTS_ALLOWEDIPS: "127.0.0.1" APPLICATION_LOGGING_DISPLAYREQUESTCONTENT: "true" @@ -42,9 +42,9 @@ resources: ingress: - enabled: false - host: "rag.local" #change this to domain - corsAllowOrigin: "http://localhost:3001,http://localhost:3003,http://localhost:8088,http://localhost:3002,http://localhost:3004,http://localhost:8000" + enabled: true + host: "ec2-34-253-140-113.eu-west-1.compute.amazonaws.com" #change this to domain + corsAllowOrigin: "https://ec2-34-253-140-113.eu-west-1.compute.amazonaws.com:32017,http://localhost:3001,http://localhost:3003,http://localhost:8088,http://localhost:3002,http://localhost:3004,http://localhost:8000" ssl: enabled: false certIssuerName: "letsencrypt-prod" @@ -55,4 +55,3 @@ pullPolicy: IfNotPresent podAnnotations: dsl-checksum: "initial" - diff --git a/kubernetes/charts/Ruuter-Public/templates/configmap-byk-ruuter-public.yaml b/kubernetes/charts/Ruuter-Public/templates/configmap-byk-ruuter-public.yaml index a6a56c0c..67b08aae 100644 --- a/kubernetes/charts/Ruuter-Public/templates/configmap-byk-ruuter-public.yaml +++ b/kubernetes/charts/Ruuter-Public/templates/configmap-byk-ruuter-public.yaml @@ -7,12 +7,13 @@ metadata: data: constants.ini: | [DSL] - RAG_SEARCH_RUUTER_PUBLIC=http://ruuter-public:8086/rag-search - RAG_SEARCH_RUUTER_PRIVATE=http://ruuter-private:8088/rag-search - RAG_SEARCH_DMAPPER=http://data-mapper:3000 + RAG_SEARCH_RUUTER_PUBLIC=http://ruuter-public:8086 + RAG_SEARCH_RUUTER_PRIVATE=http://ruuter-private:8088 + RAG_SEARCH_DMAPPER=http://data-mapper:3001 RAG_SEARCH_RESQL=http://resql:8082/rag-search RAG_SEARCH_PROJECT_LAYER=rag-search RAG_SEARCH_TIM=http://tim:8085 RAG_SEARCH_CRON_MANAGER=http://cron-manager:9010 RAG_SEARCH_LLM_ORCHESTRATOR=http://llm-orchestration-service:8100/orchestrate - DOMAIN=localhost \ No newline at end of file + DOMAIN=localhost + DB_PASSWORD=dbadmin \ No newline at end of file diff --git a/kubernetes/charts/Ruuter-Public/values.yaml b/kubernetes/charts/Ruuter-Public/values.yaml index 320d43f6..22f27d89 100644 --- a/kubernetes/charts/Ruuter-Public/values.yaml +++ b/kubernetes/charts/Ruuter-Public/values.yaml @@ -6,7 +6,7 @@ images: scope: registry: "ghcr.io" repository: "buerokratt/ruuter" - tag: v2.2.1 + tag: "v2.2.8" service: type: ClusterIP @@ -14,7 +14,7 @@ service: targetPort: 8086 env: - APPLICATION_CORS_ALLOWEDORIGINS: "http://localhost:8086,http://localhost:3001,http://localhost:3003,http://localhost:3004,http://localhost:8080,http://localhost:8000,http://localhost:8090" + APPLICATION_CORS_ALLOWEDORIGINS: "https://ec2-34-253-140-113.eu-west-1.compute.amazonaws.com:32017,http://localhost:8086,http://localhost:3001,http://localhost:3003,http://localhost:3004,http://localhost:8080,http://localhost:8000,http://localhost:8090" APPLICATION_HTTPCODESALLOWLIST: "200,201,202,204,400,401,403,500" APPLICATION_INTERNALREQUESTS_ALLOWEDIPS: "127.0.0.1" APPLICATION_LOGGING_DISPLAYREQUESTCONTENT: "true" @@ -40,8 +40,8 @@ resources: ingress: enabled: true - host: "rag.local" # Change this to domain - corsAllowOrigin: "http://localhost:8086,http://localhost:3001,http://localhost:3003,http://localhost:3004,http://localhost:8080,http://localhost:8000,http://localhost:8090" + host: "ec2-34-253-140-113.eu-west-1.compute.amazonaws.com" # EC2 domain + corsAllowOrigin: "https://ec2-34-253-140-113.eu-west-1.compute.amazonaws.com:32017,http://localhost:8086,http://localhost:3001,http://localhost:3003,http://localhost:3004,http://localhost:8080,http://localhost:8000,http://localhost:8090" ssl: enabled: false # Set to true for production with proper certificates certIssuerName: "letsencrypt-prod" @@ -51,4 +51,4 @@ ingress: pullPolicy: IfNotPresent podAnnotations: - dsl-checksum: "94b84bb5ff4d" + dsl-checksum: "ac610bf9ecc0" \ No newline at end of file diff --git a/kubernetes/charts/Vault-Agent-Cron/templates/configmap.yaml b/kubernetes/charts/Vault-Agent-Cron/templates/configmap.yaml index 37a7af6e..4bebfa76 100644 --- a/kubernetes/charts/Vault-Agent-Cron/templates/configmap.yaml +++ b/kubernetes/charts/Vault-Agent-Cron/templates/configmap.yaml @@ -10,7 +10,9 @@ metadata: component: vault-agent data: cron-agent.hcl: | - + # Vault Agent Configuration for CronManager Service + # This agent provides CronManager with access to encryption keys and write access to secrets + vault { address = "http://vault:8200" retry { @@ -29,7 +31,7 @@ data: } } - # Write token to shared volume for agent to use + # Write token to file for CronManager service to use sink "file" { config = { path = "{{ .Values.agent.tokenPath }}/token" @@ -38,12 +40,12 @@ data: } } - # Caching configuration for CronManager + # Caching configuration cache { - default_lease_duration = "{{ .Values.agent.tokenTTL }}" + default_lease_duration = "{{ .Values.agent.tokenTTL }}" # Medium TTL for CronManager } - # API proxy listener - CronManager connects to localhost:{{ .Values.agent.port }} + # API proxy listener for CronManager service listener "tcp" { address = "0.0.0.0:{{ .Values.agent.port }}" tls_disable = true @@ -52,7 +54,5 @@ data: # API proxy configuration api_proxy { use_auto_auth_token = true - enforce_consistency = "always" - when_inconsistent = "forward" } -{{- end }} +{{- end }} \ No newline at end of file diff --git a/kubernetes/charts/Vault-Agent-GUI/templates/configmap.yaml b/kubernetes/charts/Vault-Agent-GUI/templates/configmap.yaml index 72ce877b..11e36dd8 100644 --- a/kubernetes/charts/Vault-Agent-GUI/templates/configmap.yaml +++ b/kubernetes/charts/Vault-Agent-GUI/templates/configmap.yaml @@ -10,7 +10,8 @@ metadata: data: gui-agent.hcl: | # Vault Agent Configuration for GUI Service - + # This agent provides GUI with access to public encryption key only + vault { address = "http://vault:8200" retry { @@ -29,7 +30,7 @@ data: } } - # Write token to shared volume for agent to use + # Write token to file for GUI service to use sink "file" { config = { path = "{{ .Values.agent.tokenPath }}/token" @@ -38,12 +39,12 @@ data: } } - # Caching configuration for GUI + # Caching configuration cache { - default_lease_duration = "{{ .Values.agent.tokenTTL }}" + default_lease_duration = "{{ .Values.agent.tokenTTL }}" # Short-lived tokens for GUI } - # API proxy listener - GUI connects to localhost:{{ .Values.agent.port }} + # API proxy listener for GUI service listener "tcp" { address = "0.0.0.0:{{ .Values.agent.port }}" tls_disable = true @@ -52,7 +53,5 @@ data: # API proxy configuration api_proxy { use_auto_auth_token = true - enforce_consistency = "always" - when_inconsistent = "forward" } -{{- end }} +{{- end }} \ No newline at end of file diff --git a/kubernetes/charts/Vault-Agent-LLM/templates/configmap.yaml b/kubernetes/charts/Vault-Agent-LLM/templates/configmap.yaml index 08c38ea2..1af16338 100644 --- a/kubernetes/charts/Vault-Agent-LLM/templates/configmap.yaml +++ b/kubernetes/charts/Vault-Agent-LLM/templates/configmap.yaml @@ -7,15 +7,13 @@ metadata: component: vault-agent data: agent.hcl: | - # Vault Agent Configuration for LLM Orchestration Service - vault { address = "http://vault:8200" retry { num_retries = 5 } } - + auto_auth { method "approle" { mount_path = "auth/approle" @@ -25,8 +23,7 @@ data: remove_secret_id_file_after_reading = false } } - - # Write token to shared volume for agent to use + sink "file" { config = { path = "/agent/llm-token/token" @@ -34,19 +31,16 @@ data: } } } - - # Caching configuration for LLM (longer TTL) + cache { - default_lease_duration = "1h" + default_lease_duration = "1h" # Longer TTL for LLM service } - + listener "tcp" { - address = "0.0.0.0:8201" + address = "0.0.0.0:8201" # Listen on all interfaces tls_disable = true } - + api_proxy { use_auto_auth_token = true - enforce_consistency = "always" - when_inconsistent = "forward" - } + } \ No newline at end of file diff --git a/kubernetes/charts/Vault-Agent-LLM/templates/deployment.yaml b/kubernetes/charts/Vault-Agent-LLM/templates/deployment.yaml deleted file mode 100644 index 943597a0..00000000 --- a/kubernetes/charts/Vault-Agent-LLM/templates/deployment.yaml +++ /dev/null @@ -1,107 +0,0 @@ -# DEPRECATED: This standalone deployment is no longer used -# WHY: Vault Agent now runs as a SIDECAR in LLM-Orchestration-Service pod -# This ensures LLM cannot bypass the agent and access Vault directly -# Keeping this file for any future reference -{{- if .Values.deployment.standalone }} -apiVersion: apps/v1 -kind: Deployment -metadata: - name: {{ .Values.release_name }} - labels: - app: {{ .Values.release_name }} - component: vault-agent-llm -spec: - replicas: {{ .Values.deployment.replicas }} - selector: - matchLabels: - app: {{ .Values.release_name }} - component: vault-agent-llm - template: - metadata: - labels: - app: {{ .Values.release_name }} - component: vault-agent-llm - spec: - {{- if .Values.affinity.enabled }} - affinity: - podAffinity: - requiredDuringSchedulingIgnoredDuringExecution: - - labelSelector: - matchExpressions: - - key: app - operator: In - values: - - {{ .Values.vault.serviceName }} - topologyKey: kubernetes.io/hostname - {{- end }} - volumes: - {{- if .Values.volumes.agentCredentials.enabled }} - - name: vault-agent-creds - persistentVolumeClaim: - claimName: vault-agent-creds - {{- end }} - {{- if .Values.volumes.agentToken.enabled }} - - name: vault-agent-token - persistentVolumeClaim: - claimName: vault-agent-token - {{- end }} - {{- if .Values.volumes.agentConfig.enabled }} - - name: vault-agent-config - configMap: - name: {{ .Values.release_name }}-config - defaultMode: 0644 - {{- end }} - containers: - - name: vault-agent - image: "{{ .Values.images.vault.registry }}/{{ .Values.images.vault.repository }}:{{ .Values.images.vault.tag }}" - imagePullPolicy: {{ .Values.pullPolicy }} - command: - - vault - - agent - - -config=/agent/config/agent.hcl - - -log-level=info - env: - - name: VAULT_ADDR - value: {{ .Values.vault.addr | quote }} - - name: VAULT_SKIP_VERIFY - value: "true" - volumeMounts: - {{- if .Values.volumes.agentCredentials.enabled }} - - name: vault-agent-creds - mountPath: {{ .Values.volumes.agentCredentials.mountPath }} - readOnly: true - {{- end }} - {{- if .Values.volumes.agentToken.enabled }} - - name: vault-agent-token - mountPath: {{ .Values.volumes.agentToken.mountPath }} - {{- end }} - {{- if .Values.volumes.agentConfig.enabled }} - - name: vault-agent-config - mountPath: {{ .Values.volumes.agentConfig.mountPath }} - readOnly: true - {{- end }} - {{- if .Values.probes.livenessProbe.enabled }} - livenessProbe: - httpGet: - path: {{ .Values.probes.livenessProbe.httpGet.path }} - port: {{ .Values.probes.livenessProbe.httpGet.port }} - initialDelaySeconds: {{ .Values.probes.livenessProbe.initialDelaySeconds }} - periodSeconds: {{ .Values.probes.livenessProbe.periodSeconds }} - {{- end }} - {{- if .Values.probes.readinessProbe.enabled }} - readinessProbe: - httpGet: - path: {{ .Values.probes.readinessProbe.httpGet.path }} - port: {{ .Values.probes.readinessProbe.httpGet.port }} - initialDelaySeconds: {{ .Values.probes.readinessProbe.initialDelaySeconds }} - periodSeconds: {{ .Values.probes.readinessProbe.periodSeconds }} - {{- end }} - {{- if .Values.resources }} - resources: -{{ toYaml .Values.resources | indent 10 }} - {{- end }} - securityContext: - capabilities: - add: - - IPC_LOCK -{{- end }} \ No newline at end of file diff --git a/kubernetes/charts/Vault-Init/templates/configmap.yaml b/kubernetes/charts/Vault-Init/templates/configmap.yaml index 9cc2b12a..f8c02f64 100644 --- a/kubernetes/charts/Vault-Init/templates/configmap.yaml +++ b/kubernetes/charts/Vault-Init/templates/configmap.yaml @@ -9,13 +9,95 @@ data: {{ .Values.initScript.filename }}: | #!/bin/sh set -e - + VAULT_ADDR="${VAULT_ADDR:-http://vault:8200}" UNSEAL_KEYS_FILE="/vault/data/unseal-keys.json" INIT_FLAG="/vault/data/.initialized" - + echo "=== Vault Initialization Script ===" - + + # --------------------------------------------------------------------------- + # Helpers (used by the SUBSEQUENT DEPLOYMENT branch) + # --------------------------------------------------------------------------- + + # Ensure a role_id file exists on disk; fetch from Vault if missing. + # Usage: ensure_role_id + ensure_role_id() { + role="$1"; rid_file="$2" + if [ -f "$rid_file" ] && [ -s "$rid_file" ]; then + return 0 + fi + echo "Fetching role_id for $role..." + rid=$(wget -q -O- \ + --header="X-Vault-Token: $ROOT_TOKEN" \ + "$VAULT_ADDR/v1/auth/approle/role/$role/role-id" | \ + grep -o '"role_id":"[^"]*"' | cut -d':' -f2 | tr -d '"') + echo "$rid" > "$rid_file" + chmod 640 "$rid_file" + } + + # Return 0 if the on-disk role_id + secret_id still authenticate, 1 otherwise. + # Usage: validate_secret_id + validate_secret_id() { + rid_file="$1"; sid_file="$2" + [ -f "$rid_file" ] && [ -f "$sid_file" ] || return 1 + rid=$(cat "$rid_file"); sid=$(cat "$sid_file") + [ -n "$rid" ] && [ -n "$sid" ] || return 1 + # wget returns non-zero on HTTP 400 (invalid creds); also confirm a token came back. + resp=$(wget -q -O- \ + --post-data="{\"role_id\":\"$rid\",\"secret_id\":\"$sid\"}" \ + --header='Content-Type: application/json' \ + "$VAULT_ADDR/v1/auth/approle/login" 2>/dev/null) || return 1 + echo "$resp" | grep -q '"client_token"' || return 1 + return 0 + } + + # Mint a fresh secret_id for a role and write it to disk. + # Usage: mint_secret_id + mint_secret_id() { + role="$1"; sid_file="$2" + sid=$(wget -q -O- --post-data='' \ + --header="X-Vault-Token: $ROOT_TOKEN" \ + "$VAULT_ADDR/v1/auth/approle/role/$role/secret-id" | \ + grep -o '"secret_id":"[^"]*"' | cut -d':' -f2 | tr -d '"') + echo "$sid" > "$sid_file" + chmod 640 "$sid_file" + } + + # Reuse the existing secret_id if it still authenticates; otherwise mint a new one. + # Usage: reconcile_secret_id + reconcile_secret_id() { + role="$1"; rid_file="$2"; sid_file="$3" + ensure_role_id "$role" "$rid_file" + if validate_secret_id "$rid_file" "$sid_file"; then + echo "$role: existing secret_id still valid - reusing" + else + echo "$role: secret_id invalid or missing - minting a new one" + mint_secret_id "$role" "$sid_file" + fi + } + + # Create or update an AppRole that issues a PERIODIC token (no max_ttl): the + # agent renews it forever and never re-runs approle/login in steady state. + # secret_id_ttl=0 + secret_id_num_uses=0 keep the secret_id valid across + # restarts. Idempotent: does not invalidate existing secret_ids, safe per run. + # Usage: upsert_approle + upsert_approle() { + role="$1"; policy="$2"; period="$3" + wget -q -O- --post-data='{"token_policies":["'"$policy"'"],"token_period":"'"$period"'","token_num_uses":0,"secret_id_ttl":"0","secret_id_num_uses":0,"bind_secret_id":true}' \ + --header="X-Vault-Token: $ROOT_TOKEN" \ + --header='Content-Type: application/json' \ + "$VAULT_ADDR/v1/auth/approle/role/$role" >/dev/null + } + + # Apply the current AppRole definitions for all three services. + ensure_approles() { + echo "Ensuring AppRole configs (periodic tokens)..." + upsert_approle "gui-service" "gui-policy" "20m" + upsert_approle "cron-manager-service" "cron-manager-policy" "30m" + upsert_approle "llm-orchestration-service" "llm-orchestration-policy" "1h" + } + # Wait for Vault to be ready echo "Waiting for Vault..." for i in $(seq 1 30); do @@ -26,7 +108,7 @@ data: echo "Waiting... ($i/30)" sleep 2 done - + # Check if this is first time if [ ! -f "$INIT_FLAG" ]; then echo "=== FIRST TIME DEPLOYMENT ===" @@ -115,6 +197,8 @@ data: path "secret/data/embeddings/connections/*" { capabilities = ["read", "list"] } path "secret/metadata/embeddings/connections/*" { capabilities = ["read", "list"] } path "secret/data/encryption/*" { capabilities = ["deny"] } + path "secret/data/langfuse/*" { capabilities = ["read"] } + path "secret/metadata/langfuse/*" { capabilities = ["read", "list"] } path "auth/token/lookup-self" { capabilities = ["read"] }' LLM_POLICY_JSON=$(echo "$LLM_POLICY" | jq -Rs '{"policy":.}') @@ -123,27 +207,9 @@ data: --header='Content-Type: application/json' \ "$VAULT_ADDR/v1/sys/policies/acl/llm-orchestration-policy" >/dev/null - # Create GUI AppRole - echo "Creating gui-service AppRole..." - wget -q -O- --post-data='{"token_policies":["gui-policy"],"token_no_default_policy":true,"token_ttl":"15m","token_max_ttl":"1h","secret_id_ttl":"24h","secret_id_num_uses":0,"bind_secret_id":true}' \ - --header="X-Vault-Token: $ROOT_TOKEN" \ - --header='Content-Type: application/json' \ - "$VAULT_ADDR/v1/auth/approle/role/gui-service" >/dev/null - - # Create CronManager AppRole - echo "Creating cron-manager-service AppRole..." - wget -q -O- --post-data='{"token_policies":["cron-manager-policy"],"token_no_default_policy":true,"token_ttl":"30m","token_max_ttl":"8h","secret_id_ttl":"24h","secret_id_num_uses":0,"bind_secret_id":true}' \ - --header="X-Vault-Token: $ROOT_TOKEN" \ - --header='Content-Type: application/json' \ - "$VAULT_ADDR/v1/auth/approle/role/cron-manager-service" >/dev/null - - # Create LLM Orchestration AppRole - echo "Creating llm-orchestration-service AppRole..." - wget -q -O- --post-data='{"token_policies":["llm-orchestration-policy"],"token_no_default_policy":true,"token_ttl":"1h","token_max_ttl":"24h","secret_id_ttl":"24h","secret_id_num_uses":0,"bind_secret_id":true}' \ - --header="X-Vault-Token: $ROOT_TOKEN" \ - --header='Content-Type: application/json' \ - "$VAULT_ADDR/v1/auth/approle/role/llm-orchestration-service" >/dev/null - + # Create the three AppRoles (periodic tokens - see upsert_approle). + ensure_approles + # Ensure credentials directory exists mkdir -p /agent/credentials @@ -248,8 +314,7 @@ data: # Mark as initialized touch "$INIT_FLAG" echo "=== First time setup complete ===" - - + else echo "=== SUBSEQUENT DEPLOYMENT ===" @@ -285,65 +350,22 @@ data: # Get root token ROOT_TOKEN=$(grep -o '"root_token":"[^"]*"' "$UNSEAL_KEYS_FILE" | cut -d':' -f2 | tr -d '"') export VAULT_TOKEN="$ROOT_TOKEN" - + + # Re-apply AppRole definitions so config changes (e.g. periodic tokens) + # take effect on redeploy without re-initializing Vault. Idempotent and + # does not invalidate existing secret_ids. + ensure_approles + # Ensure credentials directory exists mkdir -p /agent/credentials - # Always regenerate all secret_ids on restart - echo "Regenerating GUI secret_id..." - GUI_SECRET_ID=$(wget -q -O- --post-data='' \ - --header="X-Vault-Token: $ROOT_TOKEN" \ - "$VAULT_ADDR/v1/auth/approle/role/gui-service/secret-id" | \ - grep -o '"secret_id":"[^"]*"' | cut -d':' -f2 | tr -d '"') - echo "$GUI_SECRET_ID" > /agent/credentials/gui_secret_id - - echo "Regenerating CronManager secret_id..." - CRON_SECRET_ID=$(wget -q -O- --post-data='' \ - --header="X-Vault-Token: $ROOT_TOKEN" \ - "$VAULT_ADDR/v1/auth/approle/role/cron-manager-service/secret-id" | \ - grep -o '"secret_id":"[^"]*"' | cut -d':' -f2 | tr -d '"') - echo "$CRON_SECRET_ID" > /agent/credentials/cron_secret_id - - echo "Regenerating LLM secret_id..." - LLM_SECRET_ID=$(wget -q -O- --post-data='' \ - --header="X-Vault-Token: $ROOT_TOKEN" \ - "$VAULT_ADDR/v1/auth/approle/role/llm-orchestration-service/secret-id" | \ - grep -o '"secret_id":"[^"]*"' | cut -d':' -f2 | tr -d '"') - echo "$LLM_SECRET_ID" > /agent/credentials/llm_secret_id - - # Set permissions - chmod 640 /agent/credentials/*_secret_id - - # Ensure role_ids exist - if [ ! -f /agent/credentials/gui_role_id ]; then - echo "Copying GUI role_id..." - GUI_ROLE_ID=$(wget -q -O- \ - --header="X-Vault-Token: $ROOT_TOKEN" \ - "$VAULT_ADDR/v1/auth/approle/role/gui-service/role-id" | \ - grep -o '"role_id":"[^"]*"' | cut -d':' -f2 | tr -d '"') - echo "$GUI_ROLE_ID" > /agent/credentials/gui_role_id - chmod 640 /agent/credentials/gui_role_id - fi - - if [ ! -f /agent/credentials/cron_role_id ]; then - echo "Copying CronManager role_id..." - CRON_ROLE_ID=$(wget -q -O- \ - --header="X-Vault-Token: $ROOT_TOKEN" \ - "$VAULT_ADDR/v1/auth/approle/role/cron-manager-service/role-id" | \ - grep -o '"role_id":"[^"]*"' | cut -d':' -f2 | tr -d '"') - echo "$CRON_ROLE_ID" > /agent/credentials/cron_role_id - chmod 640 /agent/credentials/cron_role_id - fi - - if [ ! -f /agent/credentials/llm_role_id ]; then - echo "Copying LLM role_id..." - LLM_ROLE_ID=$(wget -q -O- \ - --header="X-Vault-Token: $ROOT_TOKEN" \ - "$VAULT_ADDR/v1/auth/approle/role/llm-orchestration-service/role-id" | \ - grep -o '"role_id":"[^"]*"' | cut -d':' -f2 | tr -d '"') - echo "$LLM_ROLE_ID" > /agent/credentials/llm_role_id - chmod 640 /agent/credentials/llm_role_id - fi + # Reconcile secret_ids: reuse the existing one if it still authenticates, + # mint a new one only if invalid or missing - keeps one stable secret_id + # across restarts instead of rotating every boot. reconcile_secret_id also + # ensures the role_id file exists first (validation needs both). + reconcile_secret_id "gui-service" /agent/credentials/gui_role_id /agent/credentials/gui_secret_id + reconcile_secret_id "cron-manager-service" /agent/credentials/cron_role_id /agent/credentials/cron_secret_id + reconcile_secret_id "llm-orchestration-service" /agent/credentials/llm_role_id /agent/credentials/llm_secret_id fi - + echo "=== Vault init complete ===" \ No newline at end of file diff --git a/kubernetes/charts/Vault-Init/templates/job.yaml b/kubernetes/charts/Vault-Init/templates/job.yaml index 4c1f9811..52758783 100644 --- a/kubernetes/charts/Vault-Init/templates/job.yaml +++ b/kubernetes/charts/Vault-Init/templates/job.yaml @@ -14,6 +14,9 @@ spec: component: vault-init spec: restartPolicy: {{ .Values.job.restartPolicy }} + # Run as root to allow chown of PVC directories (mirrors docker-compose user: "0") + securityContext: + runAsUser: 0 {{- if .Values.affinity.enabled }} affinity: podAffinity: diff --git a/kubernetes/charts/Vault/templates/configmap.yaml b/kubernetes/charts/Vault/templates/configmap.yaml index 1e32fd90..cea5b77c 100644 --- a/kubernetes/charts/Vault/templates/configmap.yaml +++ b/kubernetes/charts/Vault/templates/configmap.yaml @@ -9,24 +9,29 @@ metadata: data: vault.hcl: | # HashiCorp Vault Server Configuration - # Production-ready configuration for LLM Orchestration Service - - # Storage backend - Raft for high availability + # Single-node Raft for the RAG-Module services + + # Storage backend - Raft storage "raft" { path = "/vault/file" node_id = "vault-node-1" - - # Retry join configuration for clustering (single node for now) - retry_join { - leader_api_addr = "http://vault:8200" - } + + # NOTE: No retry_join for a single node. A lone node self-bootstraps. + # A retry_join pointing at itself causes repeated + # "failed to get raft challenge ... Vault is sealed" errors and a + # messy double Raft init on every boot. Add retry_join back only when + # you actually have peer nodes to join. } - - # HTTP listener configuration + + # HTTP API listener. + # Vault automatically uses the next port up (8201) as its internal + # cluster port, so do NOT define a separate listener on 8201 — that + # collides with the cluster listener ("bind: address already in use") + # and degrades the login/request-forwarding path the agents rely on. listener "tcp" { - address = "0.0.0.0:8200" - tls_disable = true - + address = "0.0.0.0:8200" + tls_disable = true + # Enable CORS for web UI access cors_enabled = true cors_allowed_origins = [ @@ -34,33 +39,24 @@ data: "http://vault:8200" ] } - - # Cluster listener for HA (required even for single node) - listener "tcp" { - address = "0.0.0.0:8201" - cluster_addr = "http://0.0.0.0:8201" - tls_disable = true - } - - # API and cluster addresses + + # API and cluster addresses. + # cluster_addr tells Vault where its internal cluster port (8201) is + # reachable; Vault binds that port itself — no listener block needed. api_addr = "http://vault:8200" cluster_addr = "http://vault:8201" - + # Security and performance settings disable_mlock = false disable_cache = false ui = false - + # Default lease and maximum lease durations default_lease_ttl = "168h" # 7 days max_lease_ttl = "720h" # 30 days - + # Logging configuration - log_level = "INFO" + log_level = "INFO" log_format = "json" - - # Development settings (remove in production) - # Note: In production, you should not use dev mode - # and should properly initialize and unseal the vault {{- end }} \ No newline at end of file diff --git a/src/api_tool_indexer/constants.py b/src/api_tool_indexer/constants.py index 1bdd7b6d..43701a64 100644 --- a/src/api_tool_indexer/constants.py +++ b/src/api_tool_indexer/constants.py @@ -23,7 +23,7 @@ class ApiToolIndexerConstants: # LLM / Embedding API DEFAULT_API_BASE_URL = "http://llm-orchestration-service:8100" DEFAULT_ENVIRONMENT = "production" - DEFAULT_CONNECTION_ID = "gpt-4o-mini" + DEFAULT_CONNECTION_ID = "" # Retry Configuration MAX_RETRIES = 3