diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3470f2f..c999dba 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,4 +38,98 @@ jobs: - name: Check for vulnerabilities run: npm audit --audit-level=high - continue-on-error: true \ No newline at end of file + continue-on-error: true + + security: + name: Security Scan + runs-on: ubuntu-latest + needs: test + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up Docker Buildx + uses: [REDACTED:high_entropy:21b90074]@v3 + + - name: Build image for scanning + uses: [REDACTED:high_entropy:3e3fdc23]@v5 + with: + context: . + push: false + load: true + tags: isms-builder:scan + + - name: Trivy - Docker image vulnerability scan + uses: aquasecurity/trivy-action@master + with: + image-ref: isms-builder:scan + format: table + exit-code: 1 + severity: CRITICAL,HIGH + ignore-unfixed: true + + - name: Trivy - Helm chart misconfiguration scan + uses: aquasecurity/trivy-action@master + with: + scan-type: config + scan-ref: chart/ + format: table + exit-code: 1 + severity: CRITICAL,HIGH + + - name: Trivy - Dockerfile best practices + uses: aquasecurity/trivy-action@master + with: + scan-type: config + scan-ref: Dockerfile + format: table + exit-code: 0 + severity: CRITICAL,HIGH,MEDIUM + + - name: Helm lint + run: | + helm lint chart/ --strict + + build: + name: Build & Push + runs-on: ubuntu-latest + needs: [test, security] + if: github.event_name == 'push' && github.ref == 'refs/heads/main' + + permissions: + contents: read + packages: write + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up Docker Buildx + uses: [REDACTED:high_entropy:21b90074]@v3 + + - name: Log in to GHCR + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Extract metadata + id: meta + uses: docker/metadata-action@v5 + with: + images: ghcr.io/codestaple/isms-builder + tags: | + type=sha + type=raw,value=latest + + - name: Build and push + uses: [REDACTED:high_entropy:3e3fdc23]@v5 + with: + context: . + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha + cache-to: type=gha,mode=max \ No newline at end of file diff --git a/chart/templates/deployment.yaml b/chart/templates/deployment.yaml index 7236980..c33494f 100644 --- a/chart/templates/deployment.yaml +++ b/chart/templates/deployment.yaml @@ -42,6 +42,13 @@ spec: - name: {{ $key }} value: {{ $value | quote }} {{- end }} + {{- range $name, $ref := .Values.secretEnv }} + - name: {{ $name }} + valueFrom: + secretKeyRef: + name: {{ $ref.secretName }} + key: {{ $ref.secretKey }} + {{- end }} livenessProbe: httpGet: path: {{ .Values.healthCheck.path }} diff --git a/chart/values.yaml b/chart/values.yaml index 46a4a8b..64a34fb 100644 --- a/chart/values.yaml +++ b/chart/values.yaml @@ -74,7 +74,7 @@ tolerations: [] affinity: {} -# Environment variables +# Environment variables (non-sensitive) env: NODE_ENV: production PORT: "3000" @@ -82,6 +82,14 @@ env: DEV_HEADER_AUTH: "false" STORAGE_BACKEND: "json" +# Sensitive environment variables sourced from Kubernetes Secrets +# Create the secret first: +# kubectl create secret generic isms-builder-secrets [REDACTED:high_entropy:759cd97e] +secretEnv: + JWT_SECRET: + secretName: isms-builder-secrets + secretKey: jwt-secret + # Health check configuration healthCheck: path: "/ui/login.html"