diff --git a/charts/akto-ai-guardrails/Chart.yaml b/charts/akto-ai-guardrails/Chart.yaml new file mode 100644 index 00000000..6855e674 --- /dev/null +++ b/charts/akto-ai-guardrails/Chart.yaml @@ -0,0 +1,19 @@ +apiVersion: v2 +name: akto-ai-guardrails +description: Helm chart for installing Akto AI Guardrails services +type: application +version: 0.1.0 +appVersion: "1.12.1" +home: https://www.akto.io +icon: https://akto-setup.s3.amazonaws.com/templates/128x128.png +sources: + - https://github.com/akto-api-security/helm-charts/tree/master/charts/akto-ai-guardrails +keywords: + - akto + - ai + - guardrails + - security + - llm +maintainers: + - name: Ankush Jain + email: ankush@akto.io diff --git a/charts/akto-ai-guardrails/README.md b/charts/akto-ai-guardrails/README.md new file mode 100644 index 00000000..bcbe86ba --- /dev/null +++ b/charts/akto-ai-guardrails/README.md @@ -0,0 +1,332 @@ +# Akto AI Guardrails Helm Chart + +This Helm chart deploys the Akto AI Guardrails services on Kubernetes. + +## Overview + +The Akto AI Guardrails solution consists of three microservices: + +1. **Agent Guard Executor** (Python Service): ML model service for AI guardrail execution +2. **Agent Guard Engine** (Go Service): Orchestration service that coordinates requests +3. **Guardrails Service**: Main service that integrates with Akto's backend services + +## Architecture + +``` +┌─────────────────────┐ +│ Guardrails Service │ +│ (Port 8080) │ +└──────────┬──────────┘ + │ + ▼ +┌─────────────────────┐ +│ Agent Guard Engine │ +│ (Port 8091) │ +└──────────┬──────────┘ + │ + ▼ +┌─────────────────────┐ +│ Agent Guard Executor│ +│ (Port 8092) │ +└─────────────────────┘ +``` + +## Prerequisites + +- Kubernetes 1.19+ +- Helm 3.0+ +- PV provisioner support (for model cache persistence) +- 8GB+ available memory (recommended) +- 4+ CPU cores (recommended) + +## Installation + +### Quick Start + +```bash +# Add the Akto Helm repository (if available) +helm repo add akto https://charts.akto.io +helm repo update + +# Install with default values +helm install akto-ai-guardrails akto/akto-ai-guardrails +``` + +### Install from local chart + +```bash +# From the helm-charts directory +helm install akto-ai-guardrails ./charts/akto-ai-guardrails +``` + +### Custom Installation + +Create a custom values file with your configuration: + +```bash +# Create custom-values.yaml +cat < custom-values.yaml +# Configure required backend services +guardrailsService: + env: + aktoApiBaseUrl: "https://your-akto-api.example.com" + databaseAbstractorServiceUrl: "https://your-database-abstractor.example.com" + databaseAbstractorServiceToken: "your-jwt-token-here" + threatBackendUrl: "https://your-threat-backend.example.com" + threatBackendToken: "your-jwt-token-here" + +# Adjust resources based on your cluster +agentGuardExecutor: + resources: + requests: + memory: 4Gi + cpu: 2 + limits: + memory: 8Gi + cpu: 4 + +# Configure persistence +agentGuardExecutor: + persistence: + size: 30Gi + storageClass: "fast-ssd" +EOF + +# Install with custom values +helm install akto-ai-guardrails ./charts/akto-ai-guardrails -f custom-values.yaml + +# IMPORTANT: Add custom-values.yaml to .gitignore to avoid committing secrets +echo "custom-values.yaml" >> .gitignore +``` + +## Configuration + +### Required Environment Variables + +The following environment variables **must be configured** before deployment: + +| Variable | Description | Required | +|----------|-------------|----------| +| `guardrailsService.env.aktoApiBaseUrl` | Base URL for Akto API | Yes | +| `guardrailsService.env.databaseAbstractorServiceUrl` | URL for database abstractor service | Yes | +| `guardrailsService.env.databaseAbstractorServiceToken` | JWT authentication token for database abstractor | Yes | +| `guardrailsService.env.threatBackendUrl` | URL for threat backend service | Yes | +| `guardrailsService.env.threatBackendToken` | JWT authentication token for threat backend | Yes | + +**Note**: These values are empty by default in `values.yaml` for security reasons. You must provide them via: +- A custom values file (recommended for development) +- Helm `--set` flags +- Kubernetes secrets (recommended for production) + +### Key Parameters + +| Parameter | Description | Default | +|-----------|-------------|---------| +| `agentGuardExecutor.enabled` | Enable the Python executor service | `true` | +| `agentGuardExecutor.replicas` | Number of executor replicas | `1` | +| `agentGuardExecutor.persistence.enabled` | Enable persistent volume for model cache | `true` | +| `agentGuardExecutor.persistence.size` | Size of model cache PVC | `20Gi` | +| `agentGuardEngine.enabled` | Enable the Go engine service | `true` | +| `agentGuardEngine.replicas` | Number of engine replicas | `1` | +| `guardrailsService.enabled` | Enable the guardrails service | `true` | +| `guardrailsService.env.databaseAbstractorServiceUrl` | Database abstractor URL | `""` | +| `guardrailsService.env.threatBackendUrl` | Threat backend URL | `""` | + +### Resource Configuration + +The default resource allocations are: + +**Agent Guard Executor (Python)**: +- Requests: 2 CPU, 2Gi memory +- Limits: 4 CPU, 6Gi memory + +**Agent Guard Engine (Go)**: +- Requests: 500m CPU, 1Gi memory +- Limits: 2 CPU, 2Gi memory + +**Guardrails Service**: +- Requests: 500m CPU, 1Gi memory +- Limits: 2 CPU, 2Gi memory + +## Service Dependencies + +The services are deployed in order with proper health checks: + +1. **Agent Guard Executor** starts first and downloads ML models +2. **Agent Guard Engine** starts after executor is ready +3. **Guardrails Service** can be accessed once all services are healthy + +## Persistent Storage + +The Agent Guard Executor requires persistent storage to cache ML models. This prevents re-downloading models on pod restarts. + +### Storage Classes + +Specify a storage class in your values: + +```yaml +agentGuardExecutor: + persistence: + storageClass: "gp3" # AWS + # storageClass: "standard-rwo" # GCP + # storageClass: "managed-premium" # Azure +``` + +## Service Access + +### Internal Service DNS + +Services are accessible within the cluster at: + +- `akto-ai-guardrails-executor:8092` - Executor service +- `akto-ai-guardrails-engine:8091` - Engine service +- `akto-ai-guardrails-service:8080` - Guardrails service + +### External Access + +To expose services externally, modify the service type: + +```yaml +guardrailsService: + service: + type: LoadBalancer # or NodePort +``` + +## Health Checks + +All services include: +- **Liveness probes**: Restart unhealthy pods +- **Readiness probes**: Route traffic only to ready pods + +The Python executor has longer initial delays to account for model loading time. + +## Upgrading + +```bash +# Upgrade to a new version +helm upgrade akto-ai-guardrails ./charts/akto-ai-guardrails -f custom-values.yaml + +# Rollback if needed +helm rollback akto-ai-guardrails +``` + +## Uninstalling + +```bash +# Remove the chart +helm uninstall akto-ai-guardrails + +# Note: PVCs are not deleted automatically. Delete manually if needed: +kubectl delete pvc akto-ai-guardrails-model-cache +``` + +## Troubleshooting + +### Pod Not Starting + +Check pod status: +```bash +kubectl get pods -l app.kubernetes.io/name=akto-ai-guardrails +kubectl describe pod +kubectl logs +``` + +### Model Download Issues + +The executor pod may take 5-10 minutes on first start to download ML models. Monitor logs: + +```bash +kubectl logs -f deployment/akto-ai-guardrails-executor +``` + +### Resource Constraints + +If pods are OOMKilled or CPU throttled, increase resource limits: + +```yaml +agentGuardExecutor: + resources: + limits: + memory: 8Gi # Increase from default 6Gi + cpu: 6 # Increase from default 4 +``` + +### Service Connectivity + +Test service connectivity: + +```bash +# From within the cluster +kubectl run -it --rm debug --image=curlimages/curl --restart=Never -- sh +curl http://akto-ai-guardrails-executor:8092/health +curl http://akto-ai-guardrails-engine:8091/health +curl http://akto-ai-guardrails-service:8080/health +``` + +## Security + +### Pod Security + +The chart includes security contexts: +- Non-root user execution +- Dropped capabilities +- Read-only root filesystem where possible + +### Secrets Management + +**IMPORTANT**: Never commit JWT tokens to version control. Use one of the following methods: + +#### Method 1: Custom Values File (Development/Testing) + +```bash +# Create a custom values file (add to .gitignore) +cat < custom-values.yaml +guardrailsService: + env: + aktoApiBaseUrl: "https://akto-mcp-proxy-nginx.billing-53a.workers.dev" + databaseAbstractorServiceUrl: "https://cyborg.akto.io" + databaseAbstractorServiceToken: "your-jwt-token-here" + threatBackendUrl: "https://tbs.akto.io" + threatBackendToken: "your-jwt-token-here" +EOF + +# Install with custom values +helm install akto-ai-guardrails ./charts/akto-ai-guardrails -f custom-values.yaml -n akto-ai + +# Add to .gitignore +echo "custom-values.yaml" >> .gitignore +``` + +#### Method 2: Helm --set Flags (CI/CD) + +```bash +helm install akto-ai-guardrails ./charts/akto-ai-guardrails -n akto-ai \ + --set guardrailsService.env.aktoApiBaseUrl="https://akto-mcp-proxy-nginx.billing-53a.workers.dev" \ + --set guardrailsService.env.databaseAbstractorServiceUrl="https://cyborg.akto.io" \ + --set guardrailsService.env.databaseAbstractorServiceToken="your-jwt-token" \ + --set guardrailsService.env.threatBackendUrl="https://tbs.akto.io" \ + --set guardrailsService.env.threatBackendToken="your-jwt-token" +``` + +#### Method 3: Kubernetes Secrets (Production - Recommended) + +```bash +# Create secret with tokens +kubectl create secret generic guardrails-secrets -n akto-ai \ + --from-literal=database-abstractor-token='your-jwt-token' \ + --from-literal=threat-backend-token='your-jwt-token' + +# Note: Using secrets requires modifying the deployment template to reference the secret +# This is the most secure approach for production environments +``` + +## Support + +For issues and questions: +- GitHub: https://github.com/akto-api-security/helm-charts +- Documentation: https://www.akto.io/docs +- Email: support@akto.io + +## License + +Copyright © 2024 Akto diff --git a/charts/akto-ai-guardrails/minikube-values.yaml b/charts/akto-ai-guardrails/minikube-values.yaml new file mode 100644 index 00000000..42c3680a --- /dev/null +++ b/charts/akto-ai-guardrails/minikube-values.yaml @@ -0,0 +1,31 @@ +# Minikube-friendly resource configuration +agentGuardEngine: + resources: + requests: + cpu: 100m + memory: 256Mi + limits: + cpu: 500m + memory: 512Mi + +agentGuardExecutor: + resources: + requests: + cpu: 200m + memory: 512Mi + limits: + cpu: 1 + memory: 1Gi + + # Disable persistence for minikube + persistence: + enabled: false + +guardrailsService: + resources: + requests: + cpu: 100m + memory: 256Mi + limits: + cpu: 500m + memory: 512Mi diff --git a/charts/akto-ai-guardrails/templates/_helpers.tpl b/charts/akto-ai-guardrails/templates/_helpers.tpl new file mode 100644 index 00000000..6b89a563 --- /dev/null +++ b/charts/akto-ai-guardrails/templates/_helpers.tpl @@ -0,0 +1,108 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "akto-ai-guardrails.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +*/}} +{{- define "akto-ai-guardrails.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "akto-ai-guardrails.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "akto-ai-guardrails.labels" -}} +helm.sh/chart: {{ include "akto-ai-guardrails.chart" . }} +{{ include "akto-ai-guardrails.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "akto-ai-guardrails.selectorLabels" -}} +app.kubernetes.io/name: {{ include "akto-ai-guardrails.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "akto-ai-guardrails.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "akto-ai-guardrails.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} + +{{/* +Agent Guard Engine labels +*/}} +{{- define "akto-ai-guardrails.agentGuardEngine.labels" -}} +{{ include "akto-ai-guardrails.labels" . }} +app.kubernetes.io/component: agent-guard-engine +{{- end }} + +{{/* +Agent Guard Engine selector labels +*/}} +{{- define "akto-ai-guardrails.agentGuardEngine.selectorLabels" -}} +{{ include "akto-ai-guardrails.selectorLabels" . }} +app.kubernetes.io/component: agent-guard-engine +{{- end }} + +{{/* +Agent Guard Executor labels +*/}} +{{- define "akto-ai-guardrails.agentGuardExecutor.labels" -}} +{{ include "akto-ai-guardrails.labels" . }} +app.kubernetes.io/component: agent-guard-executor +{{- end }} + +{{/* +Agent Guard Executor selector labels +*/}} +{{- define "akto-ai-guardrails.agentGuardExecutor.selectorLabels" -}} +{{ include "akto-ai-guardrails.selectorLabels" . }} +app.kubernetes.io/component: agent-guard-executor +{{- end }} + +{{/* +Guardrails Service labels +*/}} +{{- define "akto-ai-guardrails.guardrailsService.labels" -}} +{{ include "akto-ai-guardrails.labels" . }} +app.kubernetes.io/component: guardrails-service +{{- end }} + +{{/* +Guardrails Service selector labels +*/}} +{{- define "akto-ai-guardrails.guardrailsService.selectorLabels" -}} +{{ include "akto-ai-guardrails.selectorLabels" . }} +app.kubernetes.io/component: guardrails-service +{{- end }} diff --git a/charts/akto-ai-guardrails/templates/deployment.yaml b/charts/akto-ai-guardrails/templates/deployment.yaml new file mode 100644 index 00000000..4fa822ae --- /dev/null +++ b/charts/akto-ai-guardrails/templates/deployment.yaml @@ -0,0 +1,260 @@ +{{- if .Values.agentGuardExecutor.enabled }} +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "akto-ai-guardrails.fullname" . }}-executor + labels: + {{- include "akto-ai-guardrails.agentGuardExecutor.labels" . | nindent 4 }} +spec: + replicas: {{ .Values.agentGuardExecutor.replicas }} + selector: + matchLabels: + {{- include "akto-ai-guardrails.agentGuardExecutor.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + {{- include "akto-ai-guardrails.agentGuardExecutor.selectorLabels" . | nindent 8 }} + spec: + {{- with .Values.global.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "akto-ai-guardrails.serviceAccountName" . }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + containers: + - name: agent-guard-executor + securityContext: + {{- toYaml .Values.securityContext | nindent 10 }} + image: "{{ .Values.agentGuardExecutor.image.repository }}:{{ .Values.agentGuardExecutor.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.agentGuardExecutor.image.pullPolicy }} + ports: + - name: http + containerPort: {{ .Values.agentGuardExecutor.service.targetPort }} + protocol: TCP + env: + - name: PYTHONUNBUFFERED + value: {{ quote .Values.agentGuardExecutor.env.pythonUnbuffered }} + - name: PORT + value: {{ quote .Values.agentGuardExecutor.env.port }} + - name: HF_HOME + value: {{ quote .Values.agentGuardExecutor.env.hfHome }} + - name: KUBERNETES_CLUSTER_DOMAIN + value: {{ quote .Values.kubernetesClusterDomain }} + {{- if .Values.agentGuardExecutor.livenessProbe.enabled }} + livenessProbe: + httpGet: + path: {{ .Values.agentGuardExecutor.livenessProbe.httpGet.path }} + port: {{ .Values.agentGuardExecutor.livenessProbe.httpGet.port }} + initialDelaySeconds: {{ .Values.agentGuardExecutor.livenessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.agentGuardExecutor.livenessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.agentGuardExecutor.livenessProbe.timeoutSeconds }} + failureThreshold: {{ .Values.agentGuardExecutor.livenessProbe.failureThreshold }} + {{- end }} + {{- if .Values.agentGuardExecutor.readinessProbe.enabled }} + readinessProbe: + httpGet: + path: {{ .Values.agentGuardExecutor.readinessProbe.httpGet.path }} + port: {{ .Values.agentGuardExecutor.readinessProbe.httpGet.port }} + initialDelaySeconds: {{ .Values.agentGuardExecutor.readinessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.agentGuardExecutor.readinessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.agentGuardExecutor.readinessProbe.timeoutSeconds }} + failureThreshold: {{ .Values.agentGuardExecutor.readinessProbe.failureThreshold }} + {{- end }} + resources: + {{- toYaml .Values.agentGuardExecutor.resources | nindent 10 }} + {{- if .Values.agentGuardExecutor.persistence.enabled }} + volumeMounts: + - name: model-cache + mountPath: {{ .Values.agentGuardExecutor.persistence.mountPath }} + {{- end }} + {{- if .Values.agentGuardExecutor.persistence.enabled }} + volumes: + - name: model-cache + persistentVolumeClaim: + claimName: {{ include "akto-ai-guardrails.fullname" . }}-model-cache + {{- end }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} +{{- end }} +--- +{{- if .Values.agentGuardEngine.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "akto-ai-guardrails.fullname" . }}-engine + labels: + {{- include "akto-ai-guardrails.agentGuardEngine.labels" . | nindent 4 }} +spec: + replicas: {{ .Values.agentGuardEngine.replicas }} + selector: + matchLabels: + {{- include "akto-ai-guardrails.agentGuardEngine.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + {{- include "akto-ai-guardrails.agentGuardEngine.selectorLabels" . | nindent 8 }} + spec: + {{- with .Values.global.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "akto-ai-guardrails.serviceAccountName" . }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + containers: + - name: agent-guard-engine + securityContext: + {{- toYaml .Values.securityContext | nindent 10 }} + image: "{{ .Values.agentGuardEngine.image.repository }}:{{ .Values.agentGuardEngine.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.agentGuardEngine.image.pullPolicy }} + ports: + - name: http + containerPort: {{ .Values.agentGuardEngine.service.targetPort }} + protocol: TCP + env: + - name: GIN_MODE + value: {{ quote .Values.agentGuardEngine.env.ginMode }} + - name: PORT + value: {{ quote .Values.agentGuardEngine.env.port }} + - name: PYTHON_SERVICE_URL + value: {{ quote .Values.agentGuardEngine.env.pythonServiceUrl }} + - name: KUBERNETES_CLUSTER_DOMAIN + value: {{ quote .Values.kubernetesClusterDomain }} + {{- if .Values.agentGuardEngine.livenessProbe.enabled }} + livenessProbe: + httpGet: + path: {{ .Values.agentGuardEngine.livenessProbe.httpGet.path }} + port: {{ .Values.agentGuardEngine.livenessProbe.httpGet.port }} + initialDelaySeconds: {{ .Values.agentGuardEngine.livenessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.agentGuardEngine.livenessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.agentGuardEngine.livenessProbe.timeoutSeconds }} + failureThreshold: {{ .Values.agentGuardEngine.livenessProbe.failureThreshold }} + {{- end }} + {{- if .Values.agentGuardEngine.readinessProbe.enabled }} + readinessProbe: + httpGet: + path: {{ .Values.agentGuardEngine.readinessProbe.httpGet.path }} + port: {{ .Values.agentGuardEngine.readinessProbe.httpGet.port }} + initialDelaySeconds: {{ .Values.agentGuardEngine.readinessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.agentGuardEngine.readinessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.agentGuardEngine.readinessProbe.timeoutSeconds }} + failureThreshold: {{ .Values.agentGuardEngine.readinessProbe.failureThreshold }} + {{- end }} + resources: + {{- toYaml .Values.agentGuardEngine.resources | nindent 10 }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} +{{- end }} +--- +{{- if .Values.guardrailsService.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "akto-ai-guardrails.fullname" . }}-service + labels: + {{- include "akto-ai-guardrails.guardrailsService.labels" . | nindent 4 }} +spec: + replicas: {{ .Values.guardrailsService.replicas }} + selector: + matchLabels: + {{- include "akto-ai-guardrails.guardrailsService.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + {{- include "akto-ai-guardrails.guardrailsService.selectorLabels" . | nindent 8 }} + spec: + {{- with .Values.global.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "akto-ai-guardrails.serviceAccountName" . }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + containers: + - name: guardrails-service + securityContext: + {{- toYaml .Values.securityContext | nindent 10 }} + image: "{{ .Values.guardrailsService.image.repository }}:{{ .Values.guardrailsService.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.guardrailsService.image.pullPolicy }} + ports: + - name: http + containerPort: {{ .Values.guardrailsService.service.targetPort }} + protocol: TCP + env: + - name: SERVER_PORT + value: {{ quote .Values.guardrailsService.env.serverPort }} + - name: AKTO_API_BASE_URL + value: {{ quote .Values.guardrailsService.env.aktoApiBaseUrl }} + - name: DATABASE_ABSTRACTOR_SERVICE_URL + value: {{ quote .Values.guardrailsService.env.databaseAbstractorServiceUrl }} + - name: DATABASE_ABSTRACTOR_SERVICE_TOKEN + value: {{ quote .Values.guardrailsService.env.databaseAbstractorServiceToken }} + - name: AGENT_GUARD_ENGINE_URL + value: {{ quote .Values.guardrailsService.env.agentGuardEngineUrl }} + - name: THREAT_BACKEND_URL + value: {{ quote .Values.guardrailsService.env.threatBackendUrl }} + - name: THREAT_BACKEND_TOKEN + value: {{ quote .Values.guardrailsService.env.threatBackendToken }} + - name: LOG_LEVEL + value: {{ quote .Values.guardrailsService.env.logLevel }} + - name: GIN_MODE + value: {{ quote .Values.guardrailsService.env.ginMode }} + - name: KUBERNETES_CLUSTER_DOMAIN + value: {{ quote .Values.kubernetesClusterDomain }} + {{- if .Values.guardrailsService.livenessProbe.enabled }} + livenessProbe: + httpGet: + path: {{ .Values.guardrailsService.livenessProbe.httpGet.path }} + port: {{ .Values.guardrailsService.livenessProbe.httpGet.port }} + initialDelaySeconds: {{ .Values.guardrailsService.livenessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.guardrailsService.livenessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.guardrailsService.livenessProbe.timeoutSeconds }} + failureThreshold: {{ .Values.guardrailsService.livenessProbe.failureThreshold }} + {{- end }} + {{- if .Values.guardrailsService.readinessProbe.enabled }} + readinessProbe: + httpGet: + path: {{ .Values.guardrailsService.readinessProbe.httpGet.path }} + port: {{ .Values.guardrailsService.readinessProbe.httpGet.port }} + initialDelaySeconds: {{ .Values.guardrailsService.readinessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.guardrailsService.readinessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.guardrailsService.readinessProbe.timeoutSeconds }} + failureThreshold: {{ .Values.guardrailsService.readinessProbe.failureThreshold }} + {{- end }} + resources: + {{- toYaml .Values.guardrailsService.resources | nindent 10 }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} +{{- end }} diff --git a/charts/akto-ai-guardrails/templates/pvc.yaml b/charts/akto-ai-guardrails/templates/pvc.yaml new file mode 100644 index 00000000..18f7ebe2 --- /dev/null +++ b/charts/akto-ai-guardrails/templates/pvc.yaml @@ -0,0 +1,23 @@ +{{- if and .Values.agentGuardExecutor.enabled .Values.agentGuardExecutor.persistence.enabled }} +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: {{ include "akto-ai-guardrails.fullname" . }}-model-cache + labels: + {{- include "akto-ai-guardrails.agentGuardExecutor.labels" . | nindent 4 }} +spec: + accessModes: + - {{ .Values.agentGuardExecutor.persistence.accessMode }} + {{- if .Values.agentGuardExecutor.persistence.storageClass }} + {{- if (eq "-" .Values.agentGuardExecutor.persistence.storageClass) }} + storageClassName: "" + {{- else }} + storageClassName: {{ .Values.agentGuardExecutor.persistence.storageClass | quote }} + {{- end }} + {{- else if .Values.global.storageClass }} + storageClassName: {{ .Values.global.storageClass | quote }} + {{- end }} + resources: + requests: + storage: {{ .Values.agentGuardExecutor.persistence.size }} +{{- end }} diff --git a/charts/akto-ai-guardrails/templates/service.yaml b/charts/akto-ai-guardrails/templates/service.yaml new file mode 100644 index 00000000..821566e1 --- /dev/null +++ b/charts/akto-ai-guardrails/templates/service.yaml @@ -0,0 +1,54 @@ +{{- if .Values.agentGuardExecutor.enabled }} +--- +apiVersion: v1 +kind: Service +metadata: + name: {{ include "akto-ai-guardrails.fullname" . }}-executor + labels: + {{- include "akto-ai-guardrails.agentGuardExecutor.labels" . | nindent 4 }} +spec: + type: {{ .Values.agentGuardExecutor.service.type }} + ports: + - port: {{ .Values.agentGuardExecutor.service.port }} + targetPort: {{ .Values.agentGuardExecutor.service.targetPort }} + protocol: TCP + name: http + selector: + {{- include "akto-ai-guardrails.agentGuardExecutor.selectorLabels" . | nindent 4 }} +{{- end }} +--- +{{- if .Values.agentGuardEngine.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "akto-ai-guardrails.fullname" . }}-engine + labels: + {{- include "akto-ai-guardrails.agentGuardEngine.labels" . | nindent 4 }} +spec: + type: {{ .Values.agentGuardEngine.service.type }} + ports: + - port: {{ .Values.agentGuardEngine.service.port }} + targetPort: {{ .Values.agentGuardEngine.service.targetPort }} + protocol: TCP + name: http + selector: + {{- include "akto-ai-guardrails.agentGuardEngine.selectorLabels" . | nindent 4 }} +{{- end }} +--- +{{- if .Values.guardrailsService.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "akto-ai-guardrails.fullname" . }}-service + labels: + {{- include "akto-ai-guardrails.guardrailsService.labels" . | nindent 4 }} +spec: + type: {{ .Values.guardrailsService.service.type }} + ports: + - port: {{ .Values.guardrailsService.service.port }} + targetPort: {{ .Values.guardrailsService.service.targetPort }} + protocol: TCP + name: http + selector: + {{- include "akto-ai-guardrails.guardrailsService.selectorLabels" . | nindent 4 }} +{{- end }} diff --git a/charts/akto-ai-guardrails/templates/serviceaccount.yaml b/charts/akto-ai-guardrails/templates/serviceaccount.yaml new file mode 100644 index 00000000..327b7adc --- /dev/null +++ b/charts/akto-ai-guardrails/templates/serviceaccount.yaml @@ -0,0 +1,12 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "akto-ai-guardrails.serviceAccountName" . }} + labels: + {{- include "akto-ai-guardrails.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/charts/akto-ai-guardrails/values.yaml b/charts/akto-ai-guardrails/values.yaml new file mode 100644 index 00000000..279d67db --- /dev/null +++ b/charts/akto-ai-guardrails/values.yaml @@ -0,0 +1,182 @@ +kubernetesClusterDomain: cluster.local + +# Global settings +global: + imagePullSecrets: [] + storageClass: "" + +# Agent Guard Engine (Go Service) +agentGuardEngine: + enabled: true + replicas: 1 + image: + repository: public.ecr.aws/aktosecurity/akto-agent-guard-engine + tag: 1.12.1_local + pullPolicy: IfNotPresent + + service: + type: ClusterIP + port: 8091 + targetPort: 8091 + + env: + ginMode: release + port: "8091" + pythonServiceUrl: http://akto-ai-guardrails-executor:8092 + + resources: + requests: + cpu: 500m + memory: 1Gi + limits: + cpu: 2 + memory: 2Gi + + livenessProbe: + enabled: true + httpGet: + path: /health + port: 8091 + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 3 + + readinessProbe: + enabled: true + httpGet: + path: /health + port: 8091 + initialDelaySeconds: 10 + periodSeconds: 5 + timeoutSeconds: 3 + failureThreshold: 3 + +# Agent Guard Executor (Python Service) +agentGuardExecutor: + enabled: true + replicas: 1 + image: + repository: public.ecr.aws/aktosecurity/akto-agent-guard-executor + tag: 1.12.1_local + pullPolicy: IfNotPresent + + service: + type: ClusterIP + port: 8092 + targetPort: 8092 + + env: + pythonUnbuffered: "1" + port: "8092" + hfHome: /app/.cache/huggingface + + resources: + requests: + cpu: 2 + memory: 2Gi + limits: + cpu: 4 + memory: 6Gi + + # Persistent volume for model cache + persistence: + enabled: true + storageClass: "" + accessMode: ReadWriteOnce + size: 20Gi + mountPath: /app/.cache/huggingface + + livenessProbe: + enabled: true + httpGet: + path: /health + port: 8092 + initialDelaySeconds: 60 + periodSeconds: 15 + timeoutSeconds: 10 + failureThreshold: 10 + + readinessProbe: + enabled: true + httpGet: + path: /health + port: 8092 + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 5 + +# Guardrails Service +guardrailsService: + enabled: true + replicas: 1 + image: + repository: public.ecr.aws/aktosecurity/akto-guardrails-service + tag: 1.12.1_local + pullPolicy: IfNotPresent + + service: + type: ClusterIP + port: 8080 + targetPort: 8080 + + env: + serverPort: "8080" + # These should be provided via values or secrets + aktoApiBaseUrl: "https://akto-mcp-proxy-nginx.billing-53a.workers.dev" + databaseAbstractorServiceUrl: "https://cyborg.akto.io" + databaseAbstractorServiceToken: "" + agentGuardEngineUrl: "http://akto-ai-guardrails-engine.akto-ai.svc.cluster.local:8091" + threatBackendUrl: "https://tbs.akto.io" + threatBackendToken: "" + logLevel: info + ginMode: release + + resources: + requests: + cpu: 500m + memory: 1Gi + limits: + cpu: 2 + memory: 2Gi + + livenessProbe: + enabled: true + httpGet: + path: /health + port: 8080 + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 3 + + readinessProbe: + enabled: true + httpGet: + path: /health + port: 8080 + initialDelaySeconds: 10 + periodSeconds: 5 + timeoutSeconds: 3 + failureThreshold: 3 + +# Service Account +serviceAccount: + create: true + annotations: {} + name: "" + +# Pod Security +podSecurityContext: {} + +securityContext: {} + +# Node selector +nodeSelector: {} + +# Tolerations +tolerations: [] + +# Affinity +affinity: {} diff --git a/charts/akto-setup-dashboard/Chart.yaml b/charts/akto-setup-dashboard/Chart.yaml index c29504d5..9ab62bc6 100644 --- a/charts/akto-setup-dashboard/Chart.yaml +++ b/charts/akto-setup-dashboard/Chart.yaml @@ -2,8 +2,8 @@ apiVersion: v2 name: akto-dashboard description: Helm chart for installing Akto type: application -version: 0.1.5 -appVersion: "0.1.5" +version: 0.1.6 +appVersion: "0.1.6" home: https://www.akto.io icon: https://akto-setup.s3.amazonaws.com/templates/128x128.png sources: diff --git a/charts/akto-setup-dashboard/templates/deployment.yaml b/charts/akto-setup-dashboard/templates/deployment.yaml index 04e057e3..50847927 100644 --- a/charts/akto-setup-dashboard/templates/deployment.yaml +++ b/charts/akto-setup-dashboard/templates/deployment.yaml @@ -2,10 +2,12 @@ apiVersion: apps/v1 kind: Deployment metadata: name: {{ include "akto.fullname" . }}-dashboard + {{- if .Values.keel.enabled }} annotations: keel.sh/policy: force keel.sh/trigger: poll keel.sh/pollSchedule: "@every 60m" + {{- end }} labels: {{- include "akto.labels" . | nindent 4 }} spec: @@ -76,10 +78,12 @@ apiVersion: apps/v1 kind: Deployment metadata: name: {{ include "akto.fullname" . }}-testing + {{- if .Values.keel.enabled }} annotations: keel.sh/policy: force keel.sh/trigger: poll keel.sh/pollSchedule: "@every 60m" + {{- end }} labels: {{- include "akto.labels" . | nindent 4 }} spec: @@ -138,6 +142,7 @@ spec: name: akto-api-security-testing resources: {{- toYaml .Values.testing.aktoApiSecurityTesting.resources | nindent 10 }} restartPolicy: Always +{{- if .Values.keel.enabled }} --- apiVersion: apps/v1 kind: Deployment @@ -207,4 +212,5 @@ spec: ports: - containerPort: 9300 resources: {{- toYaml .Values.keel.keel.resources | nindent 10 }} - serviceAccountName: {{ include "akto.fullname" . }}-keel \ No newline at end of file + serviceAccountName: {{ include "akto.fullname" . }}-keel +{{- end }} \ No newline at end of file diff --git a/charts/akto-setup-dashboard/templates/keel-rbac-binding.yaml b/charts/akto-setup-dashboard/templates/keel-rbac-binding.yaml index 297ed81c..25ca48b9 100644 --- a/charts/akto-setup-dashboard/templates/keel-rbac-binding.yaml +++ b/charts/akto-setup-dashboard/templates/keel-rbac-binding.yaml @@ -1,3 +1,4 @@ +{{- if .Values.keel.enabled }} apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: @@ -11,4 +12,5 @@ roleRef: subjects: - kind: ServiceAccount name: '{{ include "akto.fullname" . }}-keel' - namespace: '{{ .Release.Namespace }}' \ No newline at end of file + namespace: '{{ .Release.Namespace }}' +{{- end }} \ No newline at end of file diff --git a/charts/akto-setup-dashboard/templates/keel-rbac.yaml b/charts/akto-setup-dashboard/templates/keel-rbac.yaml index 79a88b18..b5a5d016 100644 --- a/charts/akto-setup-dashboard/templates/keel-rbac.yaml +++ b/charts/akto-setup-dashboard/templates/keel-rbac.yaml @@ -1,3 +1,4 @@ +{{- if .Values.keel.enabled }} apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: @@ -49,3 +50,4 @@ rules: - get - create - update +{{- end }} diff --git a/charts/akto-setup-dashboard/templates/keel.yaml b/charts/akto-setup-dashboard/templates/keel.yaml index 8b2d67ef..5550a6d3 100644 --- a/charts/akto-setup-dashboard/templates/keel.yaml +++ b/charts/akto-setup-dashboard/templates/keel.yaml @@ -1,3 +1,4 @@ +{{- if .Values.keel.enabled }} apiVersion: v1 kind: Service metadata: @@ -12,3 +13,4 @@ spec: {{- include "akto.selectorLabels" . | nindent 4 }} ports: {{- .Values.keel.ports | toYaml | nindent 2 -}} +{{- end }} diff --git a/charts/akto-setup-dashboard/templates/serviceaccount.yaml b/charts/akto-setup-dashboard/templates/serviceaccount.yaml index 208ca254..0c2502c5 100644 --- a/charts/akto-setup-dashboard/templates/serviceaccount.yaml +++ b/charts/akto-setup-dashboard/templates/serviceaccount.yaml @@ -1,3 +1,4 @@ +{{- if .Values.keel.enabled }} apiVersion: v1 kind: ServiceAccount metadata: @@ -6,4 +7,5 @@ metadata: app: {{ include "akto.fullname" . }}-keel {{- include "akto.labels" . | nindent 4 }} annotations: - {{- toYaml .Values.keel.serviceAccount.annotations | nindent 4 }} \ No newline at end of file + {{- toYaml .Values.keel.serviceAccount.annotations | nindent 4 }} +{{- end }} \ No newline at end of file diff --git a/charts/akto-setup-dashboard/values.yaml b/charts/akto-setup-dashboard/values.yaml index 3558ee99..9e228357 100644 --- a/charts/akto-setup-dashboard/values.yaml +++ b/charts/akto-setup-dashboard/values.yaml @@ -60,6 +60,7 @@ testing: replicas: 1 keel: + enabled: false keel: env: awsAccessKeyId: ""