diff --git a/.github/workflows/publish-helm-chart.yml b/.github/workflows/publish-helm-chart.yml new file mode 100644 index 0000000..95c0707 --- /dev/null +++ b/.github/workflows/publish-helm-chart.yml @@ -0,0 +1,37 @@ +name: publish-helm-chart + +on: + push: + branches: ['master'] + tags: + - '*' + paths: + - 'helm/**' + +concurrency: ${{ github.ref }} + +jobs: + build-and-push-helm-chart: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + steps: + - uses: actions/checkout@v4 + - name: Install Helm + uses: azure/setup-helm@v4.2.0 + - name: Package and upload chart + shell: bash + env: + REGISTRY: "ghcr.io" + REPOSITORY: "${{ github.repository }}" + TOKEN: "${{ secrets.GITHUB_TOKEN }}" + USER: "${{ github.repository_owner }}" + run: | + rm -rf dist + mkdir dist + helm package helm/ -d dist/ + echo "${TOKEN}" | helm registry login "${REGISTRY}/${REPOSITORY,,}" -u "${USER}" --password-stdin + for file in dist/*; do + helm push "$file" "oci://${REGISTRY}/${REPOSITORY,,}/charts" + done diff --git a/helm/.helmignore b/helm/.helmignore new file mode 100644 index 0000000..0e8a0eb --- /dev/null +++ b/helm/.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/helm/Chart.yaml b/helm/Chart.yaml new file mode 100644 index 0000000..ce076c4 --- /dev/null +++ b/helm/Chart.yaml @@ -0,0 +1,5 @@ +apiVersion: v1 +appVersion: "1.0" +description: Deploy self-registering SDM gateway +name: strongdm-gateway +version: 1.0.0 diff --git a/helm/templates/admin-token-secret.yaml b/helm/templates/admin-token-secret.yaml new file mode 100644 index 0000000..3b47076 --- /dev/null +++ b/helm/templates/admin-token-secret.yaml @@ -0,0 +1,6 @@ +apiVersion: v1 +kind: Secret +metadata: + name: {{ .Chart.Name }}-admin-token +stringData: + token: {{ .Values.sdm.admin.token }} diff --git a/helm/templates/eip-attach-configmap.yaml b/helm/templates/eip-attach-configmap.yaml new file mode 100644 index 0000000..23ed11b --- /dev/null +++ b/helm/templates/eip-attach-configmap.yaml @@ -0,0 +1,25 @@ +# configmap for eip-attach init container +{{- if .Values.sdm.gateway.eip.enabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: eip-attach-script + labels: + app: eip-attach-script +data: + eip-attach.sh: |- + #!/bin/bash + METADATA_TOKEN=$(curl -s -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600") + AZ=$(curl -s -H "X-aws-ec2-metadata-token: $METADATA_TOKEN" http://169.254.169.254/latest/dynamic/instance-identity/document | jq -r .availabilityZone) + INSTANCE_ID=$(curl -s -H "X-aws-ec2-metadata-token: $METADATA_TOKEN" http://169.254.169.254/latest/meta-data/instance-id) + INTERFACE_ID=$(curl -s -H "X-aws-ec2-metadata-token: $METADATA_TOKEN" "http://169.254.169.254/latest/meta-data/network/interfaces/macs/$( /config/public-ipv4 +{{- end }} diff --git a/helm/templates/gateway-deployment.yaml b/helm/templates/gateway-deployment.yaml new file mode 100644 index 0000000..07a37b8 --- /dev/null +++ b/helm/templates/gateway-deployment.yaml @@ -0,0 +1,137 @@ +{{- if .Values.sdm.gateway.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .Chart.Name }} + labels: + app: sdm-gateway +spec: + replicas: {{ .Values.sdm.gateway.replicas }} + selector: + matchLabels: + app: sdm-gateway +{{- if .Values.sdm.gateway.strategy }} + strategy: +{{ toYaml .Values.sdm.gateway.strategy | indent 4 }} +{{- end }} + template: + metadata: + annotations: + cluster-autoscaler.kubernetes.io/safe-to-evict: "false" +{{- if .Values.sdm.gateway.podAnnotations }} +{{ toYaml .Values.sdm.gateway.podAnnotations | indent 8 }} +{{- end }} + labels: + app: sdm-gateway + spec: +{{- if .Values.sdm.gateway.affinity }} + affinity: +{{ toYaml .Values.sdm.gateway.affinity | indent 8 }} +{{- end }} + hostNetwork: {{ .Values.sdm.gateway.hostNetwork }} +{{- if .Values.sdm.gateway.nodeSelector }} + nodeSelector: +{{ toYaml .Values.sdm.gateway.nodeSelector | indent 8 }} +{{- end }} +{{- if or .Values.sdm.gateway.eip.enabled .Values.sdm.gateway.initContainers }} + initContainers: +{{- if .Values.sdm.gateway.eip.enabled }} + - name: eip-attach + image: {{ .Values.sdm.gateway.eip.image }} + imagePullPolicy: IfNotPresent + command: + - /bin/bash + - /usr/local/bin/eip-attach.sh + volumeMounts: + - name: eip-attach-script + mountPath: /usr/local/bin/eip-attach.sh + subPath: eip-attach.sh + - name: config-dir + mountPath: /config +{{- end }} +{{- if .Values.sdm.gateway.initContainers }} +{{ toYaml .Values.sdm.gateway.initContainers | indent 8 }} +{{- end }} +{{- end }} + containers: + - name: sdm-gateway + image: {{ .Values.sdm.gateway.image }} + imagePullPolicy: Always +{{- if .Values.sdm.gateway.eip.enabled }} + command: + - /bin/bash + - -c + - >- + source /config/public-ipv4 && + /docker-entrypoint.sh +{{- end }} + env: + - name: SDM_ORCHESTRATOR_PROBES + value: ":9090" + - name: SDM_ADMIN_TOKEN + valueFrom: + secretKeyRef: + name: {{ .Chart.Name }}-admin-token + key: token + - name: SDM_RELAY_PORT + value: "{{ .Values.sdm.gateway.port }}" + - name: SDM_RELAY_TOKEN_FILE + value: /config/token.txt + - name: SDM_RELAY_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + livenessProbe: + httpGet: + path: /liveness + port: 9090 + initialDelaySeconds: 5 + periodSeconds: 10 + ports: + - name: proxy + containerPort: {{ .Values.sdm.gateway.port }} + resources: {{ toYaml .Values.sdm.gateway.resources | nindent 10 }} + volumeMounts: + - name: config-dir + mountPath: /config +{{- if .Values.sdm.logExporter.enabled }} + - name: log-dir + mountPath: /home/sdmuser/logs +{{- end }} +{{- if .Values.sdm.logExporter.enabled }} + - name: log-exporter + image: {{ .Values.sdm.logExporter.image }} + imagePullPolicy: Always + env: + - name: LOG_EXPORT_CONTAINER_INPUT + value: file-json + - name: LOG_FILE_PATH + value: '/var/log/sdm/*.log' + - name: LOG_EXPORT_CONTAINER_OUTPUT + value: sumologic + - name: SUMOLOGIC_ENDPOINT + value: {{ .Values.sdm.logExporter.sumoLogic.endpoint }} + - name: SUMOLOGIC_SOURCE_CATEGORY + value: {{ .Values.sdm.logExporter.sumoLogic.sourceCategory }} + resources: {{ toYaml .Values.sdm.logExporter.resources | nindent 10 }} + volumeMounts: + - name: log-dir + mountPath: /var/log/sdm +{{- end }} +{{- if .Values.sdm.gateway.tolerations }} + tolerations: +{{ toYaml .Values.sdm.gateway.tolerations | indent 8 }} +{{- end }} + volumes: + - name: config-dir + emptyDir: {} +{{- if .Values.sdm.logExporter.enabled }} + - name: log-dir + emptyDir: {} +{{- end }} +{{- if .Values.sdm.gateway.eip.enabled }} + - name: eip-attach-script + configMap: + name: eip-attach-script +{{- end }} +{{- end }} diff --git a/helm/values.yaml b/helm/values.yaml new file mode 100644 index 0000000..553dd2d --- /dev/null +++ b/helm/values.yaml @@ -0,0 +1,48 @@ +# Default values for sdm-gateway + +sdm: + admin: + # This value should be a base64-encoded SDM admin token with at least "relay:create" permissions + token: CHANGEME + gateway: + enabled: true + image: applause/strongdm-gateway:1.2.2 + port: 5000 + replicas: 3 + eip: + enabled: true + image: amazon/aws-cli:2.15.62 + tag: ec2_instance + value: dev_gateway + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: subnet + operator: In + values: + - public + hostNetwork: true + nodeSelector: + sdm: "true" + resources: + requests: + cpu: 500m + memory: 64Mi + limits: + cpu: 3 + memory: 1Gi + # the number of pods is equal to number of nodes and we can't fit two pods on same node + strategy: + rollingUpdate: + maxSurge: 0 + logExporter: + enabled: true + image: applause/strongdm-log-export:1.0.43.2 + sumoLogic: + # This value is the endpoint URL from sumologic + endpoint: ENDPOINT + # This value is the category in sumologic for this data + sourceCategory: CATEGORY + resources: {}