diff --git a/.github/workflows/charts-lint.yaml b/.github/workflows/charts-lint.yaml new file mode 100644 index 000000000..d3930845d --- /dev/null +++ b/.github/workflows/charts-lint.yaml @@ -0,0 +1,51 @@ +name: Lint and Test Charts + +on: + pull_request: + branches: + - main + paths: + - '.github/workflows/charts-lint.yaml' + - 'charts/**' + +jobs: + lint-test: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Set up Helm + uses: azure/setup-helm@v4.2.0 + with: + version: v3.14.4 + + - uses: actions/setup-python@v4 + with: + python-version: '3.x' + check-latest: true + + - name: Set up chart-testing + uses: helm/chart-testing-action@v2.6.1 + + - name: Run chart-testing (list-changed) + id: list-changed + run: | + changed=$(ct list-changed --target-branch ${{ github.event.repository.default_branch }}) + if [[ -n "$changed" ]]; then + echo "changed=true" >> "$GITHUB_OUTPUT" + fi + + - name: Run chart-testing (lint) + if: steps.list-changed.outputs.changed == 'true' + run: ct lint --target-branch ${{ github.event.repository.default_branch }} + + - name: Create kind cluster + if: steps.list-changed.outputs.changed == 'true' + uses: helm/kind-action@v1.10.0 + + - name: Run chart-testing (install) + if: steps.list-changed.outputs.changed == 'true' + run: ct install --target-branch ${{ github.event.repository.default_branch }} diff --git a/.github/workflows/charts-readme-docs.yaml b/.github/workflows/charts-readme-docs.yaml new file mode 100644 index 000000000..7112ca394 --- /dev/null +++ b/.github/workflows/charts-readme-docs.yaml @@ -0,0 +1,39 @@ +name: "Charts: Update README" + +on: + pull_request: + branches: + - main + paths: + - '.github/workflows/charts-readme-docs.yaml' + - 'charts/**' + +env: + HELM_DOCS_VERSION: 1.11.2 + +jobs: + chart-readme: + name: Update README + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + ref: ${{ github.event.pull_request.head.ref }} + + - name: install helm-docs + run: | + cd /tmp + wget https://github.com/norwoodj/helm-docs/releases/download/v${{env.HELM_DOCS_VERSION}}/helm-docs_Linux_x86_64.tar.gz + tar -xvf helm-docs_Linux_x86_64.tar.gz + sudo mv helm-docs /usr/local/sbin + + - name: run helm-docs + run: | + helm-docs -t README.md.gotmpl -o README.md + + - name: Commit changes + uses: stefanzweifel/git-auto-commit-action@v4 + id: auto-commit + with: + branch: ${{ github.event.pull_request.head.ref }} diff --git a/.github/workflows/charts-release-ghpages.yaml b/.github/workflows/charts-release-ghpages.yaml new file mode 100644 index 000000000..7f24fdad2 --- /dev/null +++ b/.github/workflows/charts-release-ghpages.yaml @@ -0,0 +1,54 @@ +name: "Charts: Release to GHCR OCI" + +on: + workflow_dispatch: {} + push: + branches: + - main + paths: + - '.github/workflows/charts-release-ghpages.yaml' + - 'charts/**' + +env: + CHARTS_SRC_DIR: "charts" + TARGET_REGISTRY: ghcr.io + +jobs: + release-charts: + name: Release Charts + runs-on: ubuntu-latest + permissions: write-all + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Configure Git + run: | + git config user.name "$GITHUB_ACTOR" + git config user.email "$GITHUB_ACTOR@users.noreply.github.com" + + - name: Login to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ${{ env.TARGET_REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Install Helm + uses: azure/setup-helm@v3 + + - name: Run chart-releaser + uses: helm/chart-releaser-action@v1.5.0 + with: + charts_dir: ${{ env.CHARTS_SRC_DIR }} + env: + CR_TOKEN: "${{ secrets.GITHUB_TOKEN }}" + + - name: Publish Helm Chart to GHCR + run: | + helm package charts/kube-guardian + helm push kube-guardian-*.tgz oci://${{ env.TARGET_REGISTRY }}/${{ github.repository_owner }}/charts + env: + GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" diff --git a/charts/kube-guardian/.helmignore b/charts/kube-guardian/.helmignore new file mode 100644 index 000000000..0e8a0eb36 --- /dev/null +++ b/charts/kube-guardian/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/charts/kube-guardian/Chart.yaml b/charts/kube-guardian/Chart.yaml new file mode 100644 index 000000000..93ad0e5da --- /dev/null +++ b/charts/kube-guardian/Chart.yaml @@ -0,0 +1,36 @@ +apiVersion: v2 +name: kube-guardian +description: A Helm chart for Kubernetes +home: https://xentra.ai/ + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: 0.0.8 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. Versions are not expected to +# follow Semantic Versioning. They should reflect the version the application is using. +# It is recommended to use it with quotes. +appVersion: "1.16.0" +kubeVersion: ">= 1.18.0-0" + +keywords: + - BPF + - eBPF + - Kubernetes + - Networking + - Security + - Observability + - Troubleshooting + +sources: + - https://github.com/xentra-ai/charts + +maintainers: + # Mahesh Rayas + - name: maheshrayas + email: mahesh.rayas@xentra-ai.com + # Michael Fornaro + - name: xunholy + email: michael.fornaro@xentra-ai.com diff --git a/charts/kube-guardian/README.md b/charts/kube-guardian/README.md new file mode 100644 index 000000000..e27101d0d --- /dev/null +++ b/charts/kube-guardian/README.md @@ -0,0 +1,175 @@ +# Xentra Helm Chart + +This chart bootstraps the [Xentra]() controlplane onto a [Kubernetes](http://kubernetes.io) cluster using the [Helm](https://helm.sh) package manager. + +![Version: 0.0.8](https://img.shields.io/badge/Version-0.0.8-informational?style=flat-square) + +## Overview + +This Helm chart deploys: + +- A Xentra control plane configured to your specifications +- Additional features and components (optional) + +## Prerequisites + +- Kubernetes 1.19+ +- Helm 3.0+ + +**Note:** *If you're using cilium ensure the following setting is set otherwise PodIPs are not correctly aggregated when determining traffic origin and desgination: `bpf.masquerade: false`* + +## Install the Chart + +To install the chart with the release name `my-release`: + +Add the chart repo + +```bash +helm repo add xentra https://xentra-ai.github.io/charts +``` + +You can then run `helm search repo xentra` to search the charts. + +Install chart using Helm v3.0+ + +```bash +helm install kube-guardian xentra/kube-guardian --namespace kube-guardian --create-namespace +``` + +If you want to use the OCI variant of the helm chart, you can use the following command: + +```bash +helm template kube-guardian oci://ghcr.io/xentra-ai/charts/kube-guardian --namespace kube-guardian --create-namespace +``` + +**Note:** *If you have the [Pod Securty Admission](https://kubernetes.io/docs/concepts/security/pod-security-admission/) enabled for your cluster you will need to add the following annotation to the namespace that the chart is deployed* + +Example: + +```yaml +apiVersion: v1 +kind: Namespace +metadata: + labels: + pod-security.kubernetes.io/enforce: privileged + pod-security.kubernetes.io/warn: privileged + name: kube-guardian +``` + +## Directory Structure + +The following shows the directory structure of the Helm chart. + +```bash +charts/xentra/ +├── .helmignore # Contains patterns to ignore when packaging Helm charts. +├── Chart.yaml # Information about your chart +├── values.yaml # The default values for your templates +├── charts/ # Charts that this chart depends on +└── templates/ # The template files + └── tests/ # The test files +``` + +## Configuration + +The following table lists the configurable parameters of the Xentra chart and their default values. + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| broker.affinity | object | `{}` | | +| broker.autoscaling.enabled | bool | `false` | | +| broker.autoscaling.maxReplicas | int | `100` | | +| broker.autoscaling.minReplicas | int | `1` | | +| broker.autoscaling.targetCPUUtilizationPercentage | int | `80` | | +| broker.container.port | int | `9090` | | +| broker.fullnameOverride | string | `""` | | +| broker.image.pullPolicy | string | `"Always"` | | +| broker.image.repository | string | `"ghcr.io/xentra-ai/images/guardian-broker"` | | +| broker.image.sha | string | `""` | | +| broker.image.tag | string | `"latest"` | | +| broker.imagePullSecrets | list | `[]` | | +| broker.nameOverride | string | `""` | | +| broker.nodeSelector | object | `{"kubernetes.io/arch":"amd64"}` | Node labels for the kube-guardian broker pod assignment | +| broker.podAnnotations | object | `{}` | | +| broker.podSecurityContext | object | `{}` | | +| broker.priorityClassName | string | `""` | | +| broker.replicaCount | int | `1` | Number of broker replicas to deploy | +| broker.resources | object | `{}` | | +| broker.securityContext | object | `{}` | | +| broker.service.name | string | `"broker"` | | +| broker.service.port | int | `9090` | | +| broker.service.type | string | `"ClusterIP"` | | +| broker.serviceAccount.annotations | object | `{}` | | +| broker.serviceAccount.automountServiceAccountToken | bool | `false` | | +| broker.serviceAccount.create | bool | `true` | | +| broker.serviceAccount.name | string | `""` | | +| broker.tolerations | list | `[]` | Tolerations for the kube-guardian broker pod assignment | +| controller.affinity | object | `{}` | | +| controller.autoscaling.enabled | bool | `false` | | +| controller.autoscaling.maxReplicas | int | `100` | | +| controller.autoscaling.minReplicas | int | `1` | | +| controller.autoscaling.targetCPUUtilizationPercentage | int | `80` | | +| controller.fullnameOverride | string | `""` | | +| controller.image.pullPolicy | string | `"Always"` | | +| controller.image.repository | string | `"ghcr.io/xentra-ai/images/guardian-controller"` | | +| controller.image.sha | string | `""` | Overrides the image tag. | +| controller.image.tag | string | `"edge"` | | +| controller.imagePullSecrets | list | `[]` | | +| controller.nameOverride | string | `""` | | +| controller.nodeSelector | object | `{"kubernetes.io/os":"linux"}` | Node labels for the kube-guardian controller pod assignment | +| controller.podAnnotations | object | `{}` | | +| controller.podSecurityContext | object | `{}` | | +| controller.priorityClassName | string | `""` | Priority class to be used for the kube-guardian controller pods | +| controller.resources | object | `{}` | | +| controller.securityContext | object | `{}` | | +| controller.service.port | int | `80` | | +| controller.service.type | string | `"ClusterIP"` | | +| controller.serviceAccount.annotations | object | `{}` | Annotations to add to the service account | +| controller.serviceAccount.automountServiceAccountToken | bool | `false` | Automount API credentials for a service account | +| controller.serviceAccount.create | bool | `true` | Specifies whether a service account should be created | +| controller.serviceAccount.name | string | `""` | The name of the service account to use. If not set and create is true, a name is generated using the fullname template | +| controller.tolerations | list | `[{"effect":"NoSchedule","key":"node-role.kubernetes.io/control-plane","operator":"Exists"}]` | Tolerations for the kube-guardian controller pod assignment | +| database.affinity | object | `{}` | | +| database.autoscaling.enabled | bool | `false` | | +| database.autoscaling.maxReplicas | int | `100` | | +| database.autoscaling.minReplicas | int | `1` | | +| database.autoscaling.targetCPUUtilizationPercentage | int | `80` | | +| database.container.port | int | `5432` | | +| database.fullnameOverride | string | `""` | | +| database.image.pullPolicy | string | `"Always"` | | +| database.image.repository | string | `"postgres"` | | +| database.image.sha | string | `""` | | +| database.image.tag | string | `"latest"` | | +| database.imagePullSecrets | list | `[]` | | +| database.name | string | `"guardian-db"` | | +| database.nameOverride | string | `""` | | +| database.nodeSelector | object | `{}` | Node labels for the kube-guardian database pod assignment | +| database.persistence.enabled | bool | `false` | | +| database.persistence.existingClaim | string | `""` | | +| database.podAnnotations | object | `{}` | | +| database.podSecurityContext | object | `{}` | | +| database.priorityClassName | string | `""` | Priority class to be used for the kube-guardian database pods | +| database.resources | object | `{}` | | +| database.securityContext | object | `{}` | | +| database.service.name | string | `"guardian-db"` | | +| database.service.port | int | `80` | | +| database.service.type | string | `"ClusterIP"` | | +| database.serviceAccount.annotations | object | `{}` | | +| database.serviceAccount.automountServiceAccountToken | bool | `false` | | +| database.serviceAccount.create | bool | `true` | | +| database.serviceAccount.name | string | `""` | | +| database.tolerations | list | `[]` | Tolerations for the kube-guardian database pod assignment | +| global.annotations | object | `{"foo":"bar"}` | Annotations to apply to all resources | +| global.labels | object | `{}` | Labels to apply to all resources | +| global.priorityClassName | string | `""` | Priority class to be used for the kube-guardian pods | +| namespace.annotations | object | `{}` | Annotations to add to the namespace | +| namespace.labels | object | `{}` | Labels to add to the namespace | +| namespace.name | string | `""` | | + +## Uninstalling the Chart + +To uninstall/delete the my-release deployment: + +```bash +helm uninstall my-release +``` diff --git a/charts/kube-guardian/README.md.gotmpl b/charts/kube-guardian/README.md.gotmpl new file mode 100644 index 000000000..2216a2451 --- /dev/null +++ b/charts/kube-guardian/README.md.gotmpl @@ -0,0 +1,85 @@ +# Xentra Helm Chart + +This chart bootstraps the [Xentra]() controlplane onto a [Kubernetes](http://kubernetes.io) cluster using the [Helm](https://helm.sh) package manager. + +{{ template "chart.versionBadge" . }} + +## Overview + +This Helm chart deploys: + +- A Xentra control plane configured to your specifications +- Additional features and components (optional) + +## Prerequisites + +- Kubernetes 1.19+ +- Helm 3.0+ + +**Note:** *If you're using cilium ensure the following setting is set otherwise PodIPs are not correctly aggregated when determining traffic origin and desgination: `bpf.masquerade: false`* + +## Install the Chart + +To install the chart with the release name `my-release`: + +Add the chart repo + +```bash +helm repo add xentra https://xentra-ai.github.io/charts +``` + +You can then run `helm search repo xentra` to search the charts. + +Install chart using Helm v3.0+ + +```bash +helm install kube-guardian xentra/kube-guardian --namespace kube-guardian --create-namespace +``` + +If you want to use the OCI variant of the helm chart, you can use the following command: + +```bash +helm template kube-guardian oci://ghcr.io/xentra-ai/charts/kube-guardian --namespace kube-guardian --create-namespace +``` + +**Note:** *If you have the [Pod Securty Admission](https://kubernetes.io/docs/concepts/security/pod-security-admission/) enabled for your cluster you will need to add the following annotation to the namespace that the chart is deployed* + +Example: + +```yaml +apiVersion: v1 +kind: Namespace +metadata: + labels: + pod-security.kubernetes.io/enforce: privileged + pod-security.kubernetes.io/warn: privileged + name: kube-guardian +``` + +## Directory Structure + +The following shows the directory structure of the Helm chart. + +```bash +charts/xentra/ +├── .helmignore # Contains patterns to ignore when packaging Helm charts. +├── Chart.yaml # Information about your chart +├── values.yaml # The default values for your templates +├── charts/ # Charts that this chart depends on +└── templates/ # The template files + └── tests/ # The test files +``` + +## Configuration + +The following table lists the configurable parameters of the Xentra chart and their default values. + +{{ template "chart.valuesTable" . }} + +## Uninstalling the Chart + +To uninstall/delete the my-release deployment: + +```bash +helm uninstall my-release +``` diff --git a/charts/kube-guardian/charts/.gitkeep b/charts/kube-guardian/charts/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/charts/kube-guardian/crds /.gitkeep b/charts/kube-guardian/crds /.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/charts/kube-guardian/templates/NOTES.txt b/charts/kube-guardian/templates/NOTES.txt new file mode 100644 index 000000000..e69de29bb diff --git a/charts/kube-guardian/templates/_helpers.tpl b/charts/kube-guardian/templates/_helpers.tpl new file mode 100644 index 000000000..033030855 --- /dev/null +++ b/charts/kube-guardian/templates/_helpers.tpl @@ -0,0 +1,71 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "kube-guardian.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "kube-guardian.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 }} + +{{/* +This gets around an problem within helm discussed here +https://github.com/helm/helm/issues/5358 +*/}} +{{- define "kube-guardian.namespace" -}} + {{ .Values.namespace.name | default .Release.Namespace }} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "kube-guardian.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "kube-guardian.labels" -}} +helm.sh/chart: {{ include "kube-guardian.chart" . }} +{{ include "kube-guardian.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- if .Values.global.labels}} +{{ toYaml .Values.global.labels }} +{{- end }} +{{- end }} + +{{/* +Common Annotations +*/}} +{{- define "kube-guardian.annotations" -}} +{{- if .Values.global.annotations -}} + {{- toYaml .Values.global.annotations | nindent 2 }} +{{- end }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "kube-guardian.selectorLabels" -}} +app.kubernetes.io/name: {{ include "kube-guardian.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} diff --git a/charts/kube-guardian/templates/broker/deployment.yaml b/charts/kube-guardian/templates/broker/deployment.yaml new file mode 100644 index 000000000..137098f65 --- /dev/null +++ b/charts/kube-guardian/templates/broker/deployment.yaml @@ -0,0 +1,68 @@ +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "kube-guardian.name" . }}-broker + labels: + {{- include "kube-guardian.labels" . | nindent 4 }} + annotations: + {{- include "kube-guardian.annotations" . | nindent 4 }} +spec: + {{- if not .Values.broker.autoscaling.enabled }} + replicas: {{ .Values.broker.replicaCount }} + {{- end }} + selector: + matchLabels: + app: {{ .Values.broker.service.name }} + app.kubernetes.io/name: {{ .Values.broker.service.name }} + template: + metadata: + {{- with .Values.broker.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + app: {{ .Values.broker.service.name }} + app.kubernetes.io/name: {{ .Values.broker.service.name }} + spec: + automountServiceAccountToken: true + {{- with .Values.broker.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ default "broker" .Values.broker.serviceAccount.name }} + securityContext: + {{- toYaml .Values.broker.podSecurityContext | nindent 8 }} + containers: + - name: broker + securityContext: + {{- toYaml .Values.broker.securityContext | nindent 12 }} + {{- if .Values.broker.image.sha }} + image: "{{ .Values.broker.image.repository }}@{{ .Values.broker.image.sha }}" + {{- else }} + image: "{{ .Values.broker.image.repository }}:{{ .Values.broker.image.tag }}" + {{- end }} + imagePullPolicy: {{ .Values.broker.image.pullPolicy }} + ports: + - name: http + containerPort: {{ .Values.broker.container.port }} + protocol: TCP + env: + - name: DATABASE_URL + value: "postgres://rust@{{ .Values.database.name }}.{{ include "kube-guardian.namespace" . }}.svc.cluster.local:{{ .Values.database.container.port }}/kube" + {{- with .Values.broker.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.broker.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.broker.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.broker.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/charts/kube-guardian/templates/broker/service.yaml b/charts/kube-guardian/templates/broker/service.yaml new file mode 100644 index 000000000..9d03a8808 --- /dev/null +++ b/charts/kube-guardian/templates/broker/service.yaml @@ -0,0 +1,18 @@ +--- +apiVersion: v1 +kind: Service +metadata: + name: {{ .Values.broker.service.name }} + labels: + {{- include "kube-guardian.labels" . | nindent 4 }} + annotations: + {{- include "kube-guardian.annotations" . | nindent 4 }} +spec: + type: {{ .Values.broker.service.type }} + ports: + - port: {{ .Values.broker.service.port }} + targetPort: http + protocol: TCP + name: http + selector: + app.kubernetes.io/name: {{ .Values.broker.service.name }} diff --git a/charts/kube-guardian/templates/broker/serviceaccount.yaml b/charts/kube-guardian/templates/broker/serviceaccount.yaml new file mode 100644 index 000000000..9979a5e5a --- /dev/null +++ b/charts/kube-guardian/templates/broker/serviceaccount.yaml @@ -0,0 +1,14 @@ +{{- if .Values.broker.serviceAccount.create -}} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ default "broker" .Values.broker.serviceAccount.name }} + labels: + {{- include "kube-guardian.labels" . | nindent 4 }} + {{- with .Values.broker.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +automountServiceAccountToken: {{ .Values.broker.serviceAccount.automountServiceAccountToken }} +{{- end }} diff --git a/charts/kube-guardian/templates/clusterrole.yaml b/charts/kube-guardian/templates/clusterrole.yaml new file mode 100644 index 000000000..b9433032a --- /dev/null +++ b/charts/kube-guardian/templates/clusterrole.yaml @@ -0,0 +1,14 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ include "kube-guardian.name" . }}-viewer + labels: + {{- include "kube-guardian.labels" . | nindent 4 }} + {{- include "kube-guardian.annotations" . | nindent 2 }} +rules: +- apiGroups: ["*"] + resources: ["namespaces", "pods", "services"] + verbs: + - get + - watch + - list diff --git a/charts/kube-guardian/templates/clusterrolebinding.yaml b/charts/kube-guardian/templates/clusterrolebinding.yaml new file mode 100644 index 000000000..7f0f4c3a2 --- /dev/null +++ b/charts/kube-guardian/templates/clusterrolebinding.yaml @@ -0,0 +1,12 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ include "kube-guardian.fullname" . }} +subjects: +- kind: ServiceAccount + name: {{ default "controller" .Values.controller.serviceAccount.name }} + namespace: {{ include "kube-guardian.namespace" . }} +roleRef: + kind: ClusterRole + name: {{ include "kube-guardian.name" . }}-viewer + apiGroup: rbac.authorization.k8s.io diff --git a/charts/kube-guardian/templates/controller/daemonset.yaml b/charts/kube-guardian/templates/controller/daemonset.yaml new file mode 100644 index 000000000..6976c1631 --- /dev/null +++ b/charts/kube-guardian/templates/controller/daemonset.yaml @@ -0,0 +1,105 @@ +--- +apiVersion: apps/v1 +kind: DaemonSet +metadata: + name: {{ include "kube-guardian.name" . }}-controller + labels: + {{- include "kube-guardian.labels" . | nindent 4 }} + annotations: + {{- include "kube-guardian.annotations" . | nindent 4 }} +spec: + selector: + matchLabels: + app.kubernetes.io/name: kube-guardian + template: + metadata: + labels: + app.kubernetes.io/name: kube-guardian + spec: + automountServiceAccountToken: true + hostNetwork: true + {{- if .Values.controller.imagePullSecrets }} + imagePullSecrets: + {{ toYaml .Values.controller.imagePullSecrets | indent 8 }} + {{- end }} + initContainers: + - name: wait-for-api + image: busybox + command: ["sh", "-c", "until wget -qO- http://{{ .Values.broker.service.name }}.{{ include "kube-guardian.namespace" . }}.svc.cluster.local:{{ .Values.broker.container.port }}/health; do sleep 5; done"] + containers: + - name: controller + {{- if .Values.controller.image.sha }} + image: "{{ .Values.controller.image.repository }}@{{ .Values.controller.image.sha }}" + {{- else }} + image: "{{ .Values.controller.image.repository }}:{{ .Values.controller.image.tag }}" + {{- end }} + args: + - "cilium" + imagePullPolicy: {{ .Values.controller.image.pullPolicy }} + securityContext: + privileged: true + readOnlyRootFilesystem: true + capabilities: + add: + - CAP_BPF + env: + - name: RUST_LOG + value: DEBUG + - name: CURRENT_NODE + valueFrom: + fieldRef: + fieldPath: spec.nodeName + - name: API_ENDPOINT + value: "http://{{ .Values.broker.service.name }}.{{ include "kube-guardian.namespace" . }}.svc.cluster.local:{{ .Values.broker.container.port }}" + volumeMounts: + - name: bpffs + mountPath: /sys/fs/bpf + readOnly: true + - name: run-containerd-bundle + mountPath: /run/containerd/io.containerd.runtime.v2.task + readOnly: true + - name: containerd-sock + mountPath: /run/containerd/containerd.sock + readOnly: true + - mountPath: /proc + name: hostproc + readOnly: true + - mountPath: /sys/fs/cgroup + name: cgroup + readOnly: true + {{- with .Values.broker.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + serviceAccountName: {{ default "controller" .Values.controller.serviceAccount.name }} + dnsPolicy: ClusterFirstWithHostNet + {{- with .Values.controller.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.controller.priorityClassName }} + priorityClassName: {{ .Values.controller.priorityClassName | quote }} + {{- end }} + volumes: + - name: bpffs + hostPath: + path: /sys/fs/bpf + type: Directory + - name: run-containerd-bundle + hostPath: + path: /run/containerd/io.containerd.runtime.v2.task + - name: containerd-sock + hostPath: + path: /run/containerd/containerd.sock + - hostPath: + path: /proc + type: Directory + name: hostproc + - hostPath: + path: /sys/fs/cgroup + type: Directory + name: cgroup + nodeSelector: + {{- if .Values.controller.nodeSelector }} + {{- toYaml .Values.controller.nodeSelector | nindent 8 }} + {{- end }} diff --git a/charts/kube-guardian/templates/controller/serviceaccount.yaml b/charts/kube-guardian/templates/controller/serviceaccount.yaml new file mode 100644 index 000000000..623143cd4 --- /dev/null +++ b/charts/kube-guardian/templates/controller/serviceaccount.yaml @@ -0,0 +1,14 @@ +{{- if .Values.controller.serviceAccount.create -}} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ default "controller" .Values.controller.serviceAccount.name }} + labels: + {{- include "kube-guardian.labels" . | nindent 4 }} + {{- with .Values.controller.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +automountServiceAccountToken: {{ .Values.controller.serviceAccount.automountServiceAccountToken }} +{{- end }} diff --git a/charts/kube-guardian/templates/database/deployment.yaml b/charts/kube-guardian/templates/database/deployment.yaml new file mode 100644 index 000000000..9163d469d --- /dev/null +++ b/charts/kube-guardian/templates/database/deployment.yaml @@ -0,0 +1,43 @@ + +--- +# TODO This resource should be a statefulset +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .Values.database.name }} + annotations: + {{- include "kube-guardian.annotations" . | nindent 4 }} +spec: + replicas: 1 + selector: + matchLabels: + app: postgresdb + template: + metadata: + labels: + app: postgresdb + spec: + automountServiceAccountToken: true + containers: + - name: postgresdb + image: postgres + ports: + - containerPort: 5432 + env: + - name: POSTGRES_USER + value: rust + - name: POSTGRES_HOST_AUTH_METHOD + value: trust + - name: POSTGRES_DB + value: kube + volumeMounts: + - mountPath: /var/lib/postgres/data + name: db-data + volumes: + - name: db-data + {{- if .Values.database.persistence.enabled }} + persistentVolumeClaim: + claimName: {{ .Values.database.persistence.existingClaim }} + {{- else }} + emptyDir: {} + {{- end -}} diff --git a/charts/kube-guardian/templates/database/service.yaml b/charts/kube-guardian/templates/database/service.yaml new file mode 100644 index 000000000..4c2f0e7d0 --- /dev/null +++ b/charts/kube-guardian/templates/database/service.yaml @@ -0,0 +1,18 @@ +--- +apiVersion: v1 +kind: Service +metadata: + name: {{ .Values.database.service.name }} + labels: + app: postgresdb + annotations: + {{- include "kube-guardian.annotations" . | nindent 4 }} +spec: + type: {{ .Values.database.service.type }} + ports: + - port: 5432 + # targetPort: postgresdb + protocol: TCP + name: http + selector: + app: postgresdb diff --git a/charts/kube-guardian/templates/database/serviceaccount.yaml b/charts/kube-guardian/templates/database/serviceaccount.yaml new file mode 100644 index 000000000..0202a21f1 --- /dev/null +++ b/charts/kube-guardian/templates/database/serviceaccount.yaml @@ -0,0 +1,14 @@ +{{- if .Values.database.serviceAccount.create -}} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ default "database" .Values.database.serviceAccount.name }} + labels: + {{- include "kube-guardian.labels" . | nindent 4 }} + {{- with .Values.database.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +automountServiceAccountToken: {{ .Values.database.serviceAccount.automountServiceAccountToken }} +{{- end }} diff --git a/charts/kube-guardian/templates/tests/test-connection.yaml b/charts/kube-guardian/templates/tests/test-connection.yaml new file mode 100644 index 000000000..1ac8cd254 --- /dev/null +++ b/charts/kube-guardian/templates/tests/test-connection.yaml @@ -0,0 +1,19 @@ +{{/* +TODO: Ignore this file for now. It's not used yet. + +apiVersion: v1 +kind: Pod +metadata: + name: "{{ include "kube-guardian.fullname" . }}-test-connection" + labels: + {{- include "kube-guardian.labels" . | nindent 4 }} + annotations: + "helm.sh/hook": test +spec: + containers: + - name: wget + image: busybox + command: ['wget'] + args: ['{{ include "kube-guardian.fullname" . }}:{{ .Values.service.port }}'] + restartPolicy: Never +*/}} diff --git a/charts/kube-guardian/values.yaml b/charts/kube-guardian/values.yaml new file mode 100644 index 000000000..5ea34376e --- /dev/null +++ b/charts/kube-guardian/values.yaml @@ -0,0 +1,249 @@ +# Default values for kube-guardian. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. +global: + # -- Labels to apply to all resources + labels: {} + # -- Annotations to apply to all resources + annotations: + "foo": "bar" + + # -- Priority class to be used for the kube-guardian pods + priorityClassName: "" + +namespace: + name: "" + # -- Labels to add to the namespace + labels: {} + # -- Annotations to add to the namespace + annotations: {} + +controller: + image: + repository: ghcr.io/xentra-ai/images/guardian-controller + pullPolicy: Always + tag: "edge" + # -- Overrides the image tag. + sha: "" + + imagePullSecrets: [] + nameOverride: "" + fullnameOverride: "" + + serviceAccount: + # -- Specifies whether a service account should be created + create: true + # -- Annotations to add to the service account + annotations: {} + # -- The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + # -- Automount API credentials for a service account + automountServiceAccountToken: false + + podAnnotations: {} + + podSecurityContext: {} + # fsGroup: 2000 + + securityContext: {} + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + + service: + type: ClusterIP + port: 80 + + resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + + autoscaling: + enabled: false + minReplicas: 1 + maxReplicas: 100 + targetCPUUtilizationPercentage: 80 + # targetMemoryUtilizationPercentage: 80 + + # -- Node labels for the kube-guardian controller pod assignment + nodeSelector: + kubernetes.io/os: linux + + # -- Tolerations for the kube-guardian controller pod assignment + tolerations: + - key: "node-role.kubernetes.io/control-plane" + operator: "Exists" + effect: "NoSchedule" + + affinity: {} + + # -- Priority class to be used for the kube-guardian controller pods + priorityClassName: "" + +broker: + # -- Number of broker replicas to deploy + replicaCount: 1 + image: + repository: ghcr.io/xentra-ai/images/guardian-broker + pullPolicy: Always + tag: "latest" + # Overrides the image tag. + sha: "" + + container: + port: 9090 + + imagePullSecrets: [] + nameOverride: "" + fullnameOverride: "" + + serviceAccount: + # Specifies whether a service account should be created + create: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + # Automount API credentials for a service account + automountServiceAccountToken: false + + podAnnotations: {} + + podSecurityContext: {} + # fsGroup: 2000 + + securityContext: {} + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + + service: + name: "broker" + type: ClusterIP + port: 9090 + + resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + + autoscaling: + enabled: false + minReplicas: 1 + maxReplicas: 100 + targetCPUUtilizationPercentage: 80 + # targetMemoryUtilizationPercentage: 80 + + # -- Node labels for the kube-guardian broker pod assignment + nodeSelector: + kubernetes.io/arch: amd64 + + # -- Tolerations for the kube-guardian broker pod assignment + tolerations: [] + + affinity: {} + + # Optional priority class to be used for the kube-guardian broker pods + priorityClassName: "" + +database: + name: guardian-db + image: + repository: postgres + pullPolicy: Always + tag: "latest" + # Overrides the image tag. + sha: "" + + persistence: + enabled: false + existingClaim: "" + + container: + port: 5432 + + imagePullSecrets: [] + nameOverride: "" + fullnameOverride: "" + + serviceAccount: + # Specifies whether a service account should be created + create: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + # Automount API credentials for a service account + automountServiceAccountToken: false + + podAnnotations: {} + + podSecurityContext: {} + # fsGroup: 2000 + + securityContext: {} + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + + service: + name: "guardian-db" + type: ClusterIP + port: 80 + + resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + + autoscaling: + enabled: false + minReplicas: 1 + maxReplicas: 100 + targetCPUUtilizationPercentage: 80 + # targetMemoryUtilizationPercentage: 80 + + # -- Node labels for the kube-guardian database pod assignment + nodeSelector: {} + + # -- Tolerations for the kube-guardian database pod assignment + tolerations: [] + + affinity: {} + + # -- Priority class to be used for the kube-guardian database pods + priorityClassName: ""