diff --git a/.github/workflows/build-dev-chart.yml b/.github/workflows/build-dev-chart.yml new file mode 100644 index 0000000..1dcd29e --- /dev/null +++ b/.github/workflows/build-dev-chart.yml @@ -0,0 +1,81 @@ +name: Build and Push Development Helm Chart +# Publishes a Helm chart to GHCR when the chart itself changes or on workflow_dispatch. + +on: + push: + branches: [ main ] + paths: + - 'deployments/helm/**' + - '.github/workflows/build-dev-chart.yml' + workflow_dispatch: + inputs: + version: + description: 'Chart version to publish (leave empty for 0.0.0-dev.)' + required: false + type: string + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +permissions: + contents: read + packages: write + +env: + REGISTRY: ghcr.io + CHART_NAME: argus + CHART_DIR: deployments/helm/argus + VALUES_EXAMPLE: deployments/helm/values-example.yaml + +jobs: + publish-dev-chart: + name: Package & Push Dev Helm Chart + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up Helm + uses: azure/setup-helm@v4 + with: + version: v3.16.2 + + - name: Convert repository owner to lowercase + id: repo_owner + run: echo "owner=$(echo '${{ github.repository_owner }}' | tr '[:upper:]' '[:lower:]')" >> "$GITHUB_OUTPUT" + + - name: Lint chart + run: helm lint ${{ env.CHART_DIR }} -f ${{ env.VALUES_EXAMPLE }} + + - name: Log in to GHCR (Helm) + run: echo "${{ secrets.GITHUB_TOKEN }}" | helm registry login ${{ env.REGISTRY }} --username ${{ github.actor }} --password-stdin + + - name: Determine version and package chart + id: package + run: | + CHART_VER="${{ github.event.inputs.version }}" + if [ -z "$CHART_VER" ]; then + CHART_VER="0.0.0-dev.${{ github.run_number }}" + fi + echo "version=${CHART_VER}" >> "$GITHUB_OUTPUT" + + helm package ${{ env.CHART_DIR }} \ + --version "${CHART_VER}" \ + --destination . + + - name: Push chart to GHCR + run: | + helm push ${{ env.CHART_NAME }}-${{ steps.package.outputs.version }}.tgz \ + oci://${{ env.REGISTRY }}/${{ steps.repo_owner.outputs.owner }}/charts + + - name: Summary + run: | + { + echo "## Helm Chart Published" + echo "" + echo "- Chart: \`oci://${{ env.REGISTRY }}/${{ steps.repo_owner.outputs.owner }}/charts/${{ env.CHART_NAME }}\`" + echo "- Version: ${{ steps.package.outputs.version }}" + echo "- Pull command:" + echo " \`helm pull oci://${{ env.REGISTRY }}/${{ steps.repo_owner.outputs.owner }}/charts/${{ env.CHART_NAME }} --version ${{ steps.package.outputs.version }}\`" + } >> "$GITHUB_STEP_SUMMARY" diff --git a/.github/workflows/helm-ci.yml b/.github/workflows/helm-ci.yml new file mode 100644 index 0000000..f6197b8 --- /dev/null +++ b/.github/workflows/helm-ci.yml @@ -0,0 +1,35 @@ +name: Helm Chart CI +# Validates the Helm chart on PRs: lint + render. Never publishes — packaging and +# pushing to GHCR is handled by build-dev-chart.yml (dev) and release-chart.yml (release). + +on: + pull_request: + branches: [ main ] + paths: + - 'deployments/helm/**' + - '.github/workflows/helm-ci.yml' + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + helm-validate: + name: Lint & template chart + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Set up Helm + uses: azure/setup-helm@v4 + with: + version: v3.16.2 + + - name: Lint chart + run: helm lint deployments/helm/argus -f deployments/helm/values-example.yaml + + - name: Render templates (default values + explicit test password) + run: helm template argus deployments/helm/argus --set auth.password=ci-test-password + + - name: Render templates (example values) + run: helm template argus deployments/helm/argus -f deployments/helm/values-example.yaml diff --git a/.gitignore b/.gitignore index d0aa5e7..e7dae41 100644 --- a/.gitignore +++ b/.gitignore @@ -40,3 +40,7 @@ coverage.html # Editor/IDE # .idea/ # .vscode/ + +# Helm packages +*.tgz +.cr-release-packages/ diff --git a/README.md b/README.md index bfa47df..056f1a2 100644 --- a/README.md +++ b/README.md @@ -147,16 +147,26 @@ Argus exports standard Prometheus metrics at `/metrics`: ## Deployment & Helm Chart -Argus includes an official Helm chart located at [`deployments/helm/argus`](deployments/helm/argus). +Argus provides an official Helm chart published as an **OCI Artifact** to GitHub Container Registry (`ghcr.io/lsflk/charts/argus`), as well as local chart source at [`deployments/helm/argus`](deployments/helm/argus). +### Install via OCI Artifact (Recommended) +```bash +helm upgrade --install argus oci://ghcr.io/lsflk/charts/argus \ + --version 0.1.0 \ + -n nsw-infra-staging \ + --create-namespace \ + -f custom-values.yaml +``` + +### Standalone Deployment from Source ```bash -# Standalone Helm chart deployment: helm upgrade --install argus ./deployments/helm/argus \ -n nsw-infra-staging \ + --create-namespace \ -f ./deployments/helm/argus/values.yaml ``` -For full Helm configuration details and GitOps umbrella chart integration, see [deployments/helm/argus/README.md](deployments/helm/argus/README.md). +For full Helm configuration parameters, GitOps umbrella chart integration, and OCI release details, see [deployments/helm/argus/README.md](deployments/helm/argus/README.md). ## Configuration diff --git a/deployments/helm/argus/.helmignore b/deployments/helm/argus/.helmignore new file mode 100644 index 0000000..39d96b8 --- /dev/null +++ b/deployments/helm/argus/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when packaging a Helm chart. +# See https://helm.sh/docs/chart_template_guide/helm_ignore_file/ +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.bak +*.swp +*.orig +*~ +# Various IDEs +.project +.idea/ +.vscode/ +# Helm packaging artifacts +*.tgz +.cr-release-packages/ diff --git a/deployments/helm/argus/Chart.yaml b/deployments/helm/argus/Chart.yaml index 7589b45..123b3a9 100644 --- a/deployments/helm/argus/Chart.yaml +++ b/deployments/helm/argus/Chart.yaml @@ -4,3 +4,10 @@ description: Secure, Tamper-Proof cryptographic Audit Log Service type: application version: 0.1.0 appVersion: "1.0.0" +home: https://github.com/LSFLK/argus +sources: + - https://github.com/LSFLK/argus +annotations: + org.opencontainers.image.source: https://github.com/LSFLK/argus + org.opencontainers.image.description: Secure, Tamper-Proof cryptographic Audit Log Service Helm Chart + org.opencontainers.image.licenses: Apache-2.0 diff --git a/deployments/helm/argus/README.md b/deployments/helm/argus/README.md index 7895e7c..3209da4 100644 --- a/deployments/helm/argus/README.md +++ b/deployments/helm/argus/README.md @@ -5,7 +5,7 @@ This Helm chart deploys **Argus**, the secure cryptographic Audit Logging servic ## Prerequisites - Kubernetes 1.20+ -- Helm 3.0+ +- Helm 3.8.0+ (with native OCI support) - (Optional) External Secrets Operator (ESO) & HashiCorp Vault integration for managing secrets. ## Chart Details @@ -16,11 +16,32 @@ This chart provisions: - Audit enums **ConfigMap** (`enums.yaml`) - Credentials **Secret** (or **ExternalSecret** when ESO is enabled) +--- + ## Installation & Deployment -### Standalone Deployment +### 1. Install via OCI Artifact (Recommended) + +Argus Helm charts are published as OCI artifacts to the GitHub Container Registry (`ghcr.io`). + +```bash +# Install directly from OCI registry +helm upgrade --install argus oci://ghcr.io/lsflk/charts/argus \ + --version 0.1.0 \ + --namespace nsw-infra-staging \ + --create-namespace \ + --values ./custom-values.yaml +``` + +To pull the packaged chart locally: + +```bash +helm pull oci://ghcr.io/lsflk/charts/argus --version 0.1.0 +``` -To deploy Argus independently: +### 2. Standalone Deployment from Source + +To deploy Argus from the local repository directory: ```bash helm upgrade --install argus ./deployments/helm/argus \ @@ -29,9 +50,18 @@ helm upgrade --install argus ./deployments/helm/argus \ --values ./deployments/helm/argus/values.yaml ``` -### Parent Chart (GitOps Umbrella) Integration +### 3. Parent Chart (GitOps Umbrella) Integration + +When referencing Argus as a dependency in your umbrella chart (`Chart.yaml`): + +```yaml +dependencies: + - name: argus + version: "0.1.0" + repository: "oci://ghcr.io/lsflk/charts" +``` -When deployed via `nsw-gitops` under `infra-umbrella`, toggle the Argus component in your environment values file (e.g., `envs/staging/infra-values.yaml`): +In your environment values file (e.g., `envs/staging/infra-values.yaml`): ```yaml argus: @@ -44,6 +74,33 @@ argus: S3_COMPLIANCE_BUCKET: "nsw-audit-compliance-logs-staging" ``` +--- + +## Publishing to OCI Registry + +### Automated (CI/CD) + +The Helm chart automation mirrors the `nsw-srilanka` and `nsw-agency` setup: +- **Dev Chart (`.github/workflows/build-dev-chart.yml`)**: On pushes to `main` with chart changes (or manual dispatch), packages and publishes a dev chart (`0.0.0-dev.`) to `oci://ghcr.io/lsflk/charts`. +- **Chart CI (`.github/workflows/helm-ci.yml`)**: Lints the chart and verifies template rendering on pull requests. + +### Manual Packaging and Push + +To manually package and push to OCI registry: + +```bash +# 1. Package the chart +helm package deployments/helm/argus -d .cr-release-packages/ + +# 2. Login to GHCR (requires PAT with write:packages) +echo "$CR_PAT" | helm registry login ghcr.io -u --password-stdin + +# 3. Push OCI artifact +helm push .cr-release-packages/argus-0.1.0.tgz oci://ghcr.io/lsflk/charts +``` + +--- + ## Configuration Parameters | Parameter | Description | Default | diff --git a/deployments/helm/values-example.yaml b/deployments/helm/values-example.yaml new file mode 100644 index 0000000..149cc4d --- /dev/null +++ b/deployments/helm/values-example.yaml @@ -0,0 +1,59 @@ +# Example override values for the Argus Helm chart. +# helm install argus ./deployments/helm/argus -f ./deployments/helm/values-example.yaml + +replicaCount: 2 + +image: + repository: ghcr.io/opennsw/argus + tag: "1.0.0" + pullPolicy: IfNotPresent + +service: + type: ClusterIP + port: 3001 + name: argus-service + +resources: + limits: + cpu: 500m + memory: 512Mi + requests: + cpu: 100m + memory: 256Mi + +securityContext: + runAsUser: 10001 + runAsNonRoot: true + readOnlyRootFilesystem: false + allowPrivilegeEscalation: false + +env: + ENVIRONMENT: production + DB_TYPE: postgres + DB_HOST: nsw-db + DB_PORT: 5432 + DB_NAME: audit_db + DB_SSLMODE: disable + REQUIRE_SIGNATURES: "true" + AUDIT_ENUMS_CONFIG: "/app/configs/enums.yaml" + + # AWS S3 Compliance Settings (Object Lock) + S3_COMPLIANCE_BUCKET: "nsw-audit-compliance-logs-staging" + S3_REGION: "us-east-1" + S3_PREFIX: "audit-logs" + S3_RETENTION_DAYS: "2555" + S3_OBJECT_LOCK_MODE: "COMPLIANCE" + S3_USE_PATH_STYLE: "false" + S3_ENDPOINT: "" + +auth: + username: "postgres" + password: "example-db-password" + existingSecret: "" + externalSecrets: + enabled: false + secretStoreName: "nsw-vault-backend" + secretStoreKind: "ClusterSecretStore" + refreshInterval: "1h" + remoteDbKey: "nsw/staging/db" + remoteAwsKey: "nsw/staging/aws"