Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .coderabbit.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,6 @@ reviews:
tflint:
enabled: true
trivy:
enabled: true
enabled: false
yamllint:
enabled: true
4 changes: 4 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.git
bin/
**/.terraform/
.terraform-docs-cache/
3 changes: 1 addition & 2 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,6 @@ Examples: variable rename/removal, output rename/removal, default value change,
- [ ] Relevant Jira/GitHub issues and related PRs are linked.
- [ ] Tests were added/updated where appropriate.
- [ ] I manually tested the change.
- [ ] `make verify` passes.
- [ ] `make verify-gen` passes.
- [ ] `make pre-push-checks` passes (or each step: `verify`, `verify-gen`, `lint`, `unit-tests`, `license-check`, `docs-lint`).
- [ ] Documentation was added/updated where appropriate (see `make terraform-docs`).
- [ ] Any risk, limitation, or follow-up work is documented.
1 change: 1 addition & 0 deletions .github/workflows/check-commit-format.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ jobs:
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0
persist-credentials: false
- name: Validate Commit Message(s)
env:
PULL_BASE_SHA: ${{ github.event.pull_request.base.sha }}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,7 @@ jobs:
ref: ${{ github.head_ref }}

- name: Install terraform-docs
run: |
set -euo pipefail
TERRAFORM_DOCS_VERSION="$(grep -E '^ARG TERRAFORM_DOCS_VERSION=' Dockerfile | cut -d= -f2)"
curl -sSLo ./terraform-docs.tar.gz "https://terraform-docs.io/dl/v${TERRAFORM_DOCS_VERSION}/terraform-docs-v${TERRAFORM_DOCS_VERSION}-linux-amd64.tar.gz"
tar -xzf terraform-docs.tar.gz terraform-docs
chmod +x terraform-docs
sudo mv terraform-docs /usr/local/bin/terraform-docs
rm -f terraform-docs.tar.gz
terraform-docs version
run: make terraform-docs-bin

# Commits are created via the GitHub Git Database API (not git commit) so GitHub can
# attribute and verify them for the authenticated GitHub App installation.
Expand Down
24 changes: 0 additions & 24 deletions .github/workflows/license-check.yaml

This file was deleted.

24 changes: 0 additions & 24 deletions .github/workflows/test.yml

This file was deleted.

24 changes: 24 additions & 0 deletions .github/workflows/verify-min-terraform.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Validates examples at the minimum Terraform version (root versions.tf required_version).
# The Prow client Dockerfile pins the newest Terraform release; this job guards module minimum compatibility.
name: Verify (minimum Terraform)

on:
pull_request:

jobs:
verify-terraform-1-5-7:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false

- uses: hashicorp/setup-terraform@dfe3c3f87815947d99a8997f908cb6525fc44e9e # v4.0.1
with:
terraform_version: "1.5.7"
terraform_wrapper: false

- name: Validate examples (minimum supported Terraform)
run: make verify
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# terraform-docs.sh pinned binary cache (version from Dockerfile)
# terraform-docs local cache (version from Makefile)
.terraform-docs-cache/

# Local tool binaries (for example Vale installed via make docs-lint)
Expand Down
4 changes: 4 additions & 0 deletions .gitleaks.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,8 @@ description = "Terraform CLI test configs may contain mock tokens/placeholders."
paths = [
# e.g. modules/*/tests/*.tftest.hcl
'''\.tftest''',
# Pinned CLI binaries and Terraform/plugin caches (not source secrets)
'''^bin/''',
'''(?:^|/)\.terraform(?:/|$)''',
'''(?:^|/)\.terraform-docs-cache(?:/|$)''',
]
5 changes: 0 additions & 5 deletions .trivyignore

This file was deleted.

32 changes: 25 additions & 7 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,15 +55,33 @@ Useful skills for this codebase:
- Use **`sensitive`** on variables and outputs where values must not appear in logs or casual `terraform show` output; avoid echoing secrets in `local` values used only for debugging. Passthrough outputs (**`module.*` → root output**) must match submodule sensitivity—see **Security** in [`.cursor/rules/rosa-hcp-terraform.mdc`](.cursor/rules/rosa-hcp-terraform.mdc).
- Do not add logging, outputs, or comments that expose credentials or session tokens.

## Trivy (IaC misconfiguration)
## CI client Dockerfile (Prow)

Repo config: root **`trivy.yaml`** (severity, scanners, skips; includes **`examples/`**). CodeRabbit may run Trivy when enabled in **`.coderabbit.yaml`**. References: [Trivy config file](https://trivy.dev/latest/docs/references/configuration/config-file/), [filtering / ignores](https://trivy.dev/latest/docs/configuration/filtering/).
The root **`Dockerfile`** builds the **OpenShift Prow** client image (`terraform-rhcs-rosa-hcp-clients`). Treat it as a **minimal supply-chain surface**: include **only** what presubmit jobs in [`openshift/release`](https://github.com/openshift/release/tree/master/ci-operator/config/terraform-redhat/terraform-rhcs-rosa-hcp) need today (`make verify`, `make verify-gen`, `make run-example`, and the tools behind `make pre-push-checks`). The image pins the newest Terraform release (`TERRAFORM_VERSION`); module minimum compatibility is enforced separately by GitHub Actions **`verify-min-terraform.yml`** (see **`CONTRIBUTING.md`**).

When **`trivy config`** reports a **misconfiguration** (check IDs like **`AWS-0104`**, **`DS-0002`** — not CVE vulnerability rows from **`trivy fs`** vuln scans):
When changing the Dockerfile:

1. **Prefer fixing** the HCL/Dockerfile (least privilege, encryption, IMDSv2, non-root user, etc.).
2. If an ignore is required, add **`#trivy:ignore:<id>`** on the line **immediately above** the Terraform resource or Dockerfile instruction, with a **short `#` comment** on the same line or the line above explaining why (narrow scope).
3. Use **`.trivyignore`** only when inline suppression is not possible — one ID per line with a **`#` justification** above each.
- **Minimize attack surface** — prefer **`ubi-minimal`** with a **pinned** minor tag (not `:latest`); do not add OS packages, compilers, or CLIs “for convenience” without a job that uses them. The client image runs as **root** so Prow/ci-operator can write to the mounted repo workspace (`make verify`, `make verify-gen`); do not add a non-root `USER` without coordinating `openshift/release` workspace ownership.
- **Pin versions** — base image, AWS CLI, ROSA CLI, Terraform, and Makefile tools; use **`# renovate:`** comments and existing patterns (`hack/install-release-tool.sh` release binaries, not `go install`, unless unavoidable). AWS CLI zips are verified with **`gpg --verify`** against **`hack/aws-cli-public-key.asc`** and the matching **`.sig`** from `awscli.amazonaws.com` ([install guide](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)). ROSA **`rosa-linux.tar.gz`** is verified with **`sha256sum -c`** against **`sha256sum.txt`** from `https://mirror.openshift.com/pub/cgw/rosa/<ROSA_VERSION>/`.
- **Avoid bloat** — the image is tool-heavy (Terraform, AWS CLI, ROSA, lint binaries); do not grow it with extra runtimes, caches, or unrelated utilities. Prefer release tarballs over full language SDKs in the final image.
- **Security scans** — `make security-check` is separate from `make pre-push-checks`; fix findings or document narrow suppressions per the **Gitleaks** and **Checkov** sections below.

## Gitleaks (secret detection)

Repo config: root **`.gitleaks.toml`** (extends default rules; allowlists `*.tftest` harness placeholders and `bin/` / `.terraform/` caches). Install with `make security-check-bin` or `make gitleaks`. `make security-check` runs **`gitleaks detect --no-git`** (current tree only, not git history) before Checkov. References: [Gitleaks README](https://github.com/gitleaks/gitleaks/blob/master/README.md).

When **`make security-check`** reports a Gitleaks finding, treat it as a real secret risk unless the match is a documented mock in test code covered by the allowlist. Do not commit credentials, tokens, or kubeconfigs; rotate anything that was exposed.

## Checkov (Terraform security)

Repo config: root **`checkov.yaml`** (framework, skip paths, **HIGH**/**CRITICAL** hard-fail). Install with `make security-check-bin`. `hack/install-release-tool.sh` verifies each Checkov zip against **`hack/checksums/checkov-<version>.sha256sums`** (upstream releases do not ship checksums — refresh that file when **`CHECKOV_VERSION`** changes). `make security-check` passes **`--skip-download`** so Checkov does not call Prisma Cloud (no `BC_API_KEY` required). **`modules/rosa-cluster-hcp/main.tf`** is skipped because Checkov cannot parse its multiline lifecycle preconditions (Terraform **`make verify`** still validates it). References: [Checkov CLI](https://www.checkov.io/2.Basics/CLI%20Command%20Reference.html).

When **`make security-check`** reports a finding (check IDs like **`CKV_AWS_*`**, **`CKV2_AWS_*`**):

1. **Prefer fixing** the HCL (least privilege, encryption, IMDSv2, etc.).
2. If a skip is required, add **`#checkov:skip=<CKV_ID>:<reason>`** on the line **immediately above** the flagged resource, with a short justification (narrow scope).
3. Use **`skip-check`** entries in **`checkov.yaml`** only when inline suppression is not possible — one ID per entry with a comment explaining why.
4. **Remove stale suppressions** — when code or Checkov no longer reports a check, delete the matching `#checkov:skip` comment or **`checkov.yaml`** `skip-check` entry so drift does not hide new findings.

## Critical Module Guardrails

Expand Down Expand Up @@ -93,4 +111,4 @@ Use mocks for AWS and RHCS resources to verify logic without requiring live cred

When module behavior branches on a **boolean variable** (e.g. **`count = var.x ? 1 : 0`**), prefer **more than one `run` block** (or clearly separated scenarios) so **both** outcomes are covered—typically **`true` / `count = 1`** and **`false` / `count = 0`**—not only the default or “happy” path. That avoids regressions where the positive case passes but the opt-out path breaks.

For exact commands and pass/fail criteria, follow **`CONTRIBUTING.md`**.
Before opening a PR, `make pre-push-checks` must pass locally; see **`CONTRIBUTING.md`** for commands and pass/fail criteria.
12 changes: 7 additions & 5 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,22 @@ This repo is **ROSA HCP** only. The sibling **ROSA Classic** module is [`terrafo
## Before you open a PR

1. **Format** — `terraform fmt -recursive` (or format only dirs you changed).
2. **Validate** — `make verify` (runs `terraform init` + `validate` in each `examples/*` directory). Fix failures in examples you touch or that your change breaks.
2. **Validate** — `make verify` (runs `terraform init` + `validate` in each `examples/*` directory; compatible with the minimum Terraform version in root **`versions.tf`**, currently **>= 1.5.7**). Fix failures in examples you touch or that your change breaks.
3. **Docs** — If you changed variables, outputs, modules, or root wiring: run `make verify-gen` (runs `terraform-docs` via [`scripts/terraform-docs.sh`](scripts/terraform-docs.sh), then [`scripts/verify-gen.sh`](scripts/verify-gen.sh) to ensure README inject blocks are committed).
4. **Module tests** — If a submodule under `modules/<name>/tests/` has `*.tftest.hcl`, run `terraform init -backend=false && terraform test` from `modules/<name>/`, or run `make unit-tests` for all modules with tests.
5. **Documentation lint** — `make docs-lint` runs the pinned [Vale](https://docs.vale.sh/) CLI with Red Hat documentation styles (see [`.vale.ini`](.vale.ini)). Building Vale uses `CGO_ENABLED=1` and requires a C compiler toolchain on the first install.
5. **Documentation lint** — `make docs-lint` runs the pinned [Vale](https://docs.vale.sh/) CLI (release binary from [vale-cli/vale](https://github.com/vale-cli/vale)) with Red Hat documentation styles (see [`.vale.ini`](.vale.ini)).
6. **Provider** — Treat [`terraform-redhat/rhcs`](https://github.com/terraform-redhat/terraform-provider-rhcs) as the source of truth: mirror its schemas in variables and docs. Add `validation` / `precondition` only to echo the provider’s required fields and allowed values (fail fast); do not duplicate or tighten rules the provider already enforces.
7. **Module scope (AWS-only)** — If the change adds or expands **AWS-only** configuration (no `rhcs` surface), confirm it matches **`Module scope (AWS-only vs core HCP)`** in [`.cursor/rules/rosa-hcp-terraform.mdc`](.cursor/rules/rosa-hcp-terraform.mdc). In the PR, **link official Red Hat or cited ROSA HCP documentation** that supports shipping it in-repo, or explain why an exception is justified.

Run the full local verification flow (same steps planned for CI) with:
Run the full local verification flow (same steps as the planned single OpenShift Prow presubmit) with:

```shell
make basic-checks
make pre-push-checks
```

`make basic-checks` runs `verify`, `verify-gen`, `lint`, `unit-tests`, `license-check`, and `docs-lint` in order (fail-fast). Use `make run-checks -- basic --list-steps` or `--dry-run` to inspect the sequence without running it.
`make pre-push-checks` runs `tools` (installs pinned CLI versions from the Makefile), then `verify`, `verify-gen`, `lint`, `unit-tests`, `license-check`, and `docs-lint` in order (fail-fast). Install tools alone with `make tools`. Run individual check targets when debugging one step. OpenShift Prow will use `make pre-push-checks` as the presubmit merge gate after `openshift/release` is updated (client image from the root [`Dockerfile`](Dockerfile) pins the newest Terraform release for integration jobs). GitHub Actions runs **`verify-min-terraform.yml`** on every PR to validate examples at the module minimum in root **`versions.tf`**. Run `make pre-push-checks` locally before opening a PR (use a Terraform version that satisfies **`versions.tf`** locally, or match the versions you need to debug).

**Security (separate from the merge gate):** `make security-check` runs [Gitleaks](https://github.com/gitleaks/gitleaks) secret detection on the **current tree** (`--no-git`; config: [`.gitleaks.toml`](.gitleaks.toml)) and [Checkov](https://www.checkov.io/) Terraform static analysis ([`checkov.yaml`](checkov.yaml); fails on **HIGH** and **CRITICAL**; **`--skip-download`** for offline use, no Prisma Cloud API key). Install both locally with `make security-check-bin` (or `make gitleaks` / `make checkov`). Checkov GitHub release zips have no upstream checksum file; when bumping **`CHECKOV_VERSION`**, add or update **`hack/checksums/checkov-<version>.sha256sums`** (one line per platform zip) and verify with `sha256sum -c` before committing.

## Commit format

Expand Down
56 changes: 42 additions & 14 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,16 +1,44 @@
FROM registry.access.redhat.com/ubi9/ubi:latest
# Pin UBI minor release; avoid :latest for reproducible CI image builds (Prow builds this Dockerfile).
# renovate: datasource=docker depName=registry.access.redhat.com/ubi9/ubi-minimal versioning=regex:^(?<major>\d+)\.(?<minor>\d+)$
FROM registry.access.redhat.com/ubi9/ubi-minimal:9.8
WORKDIR /app
COPY . /app
RUN yum update -y && yum install -y yum-utils shadow-utils unzip tar make && \
yum-config-manager --add-repo https://rpm.releases.hashicorp.com/AmazonLinux/hashicorp.repo && \
yum -y install terraform && \
yum clean all && \
rm -rf /var/cache/yum
RUN curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" && unzip awscliv2.zip && \
./aws/install -i /usr/local/aws-cli -b /usr/local/bin && rm awscliv2.zip && rm -r aws/
RUN curl -sL "https://mirror.openshift.com/pub/cgw/rosa/latest/rosa-linux.tar.gz" -o "rosa.tar.gz" && \
tar xfvz rosa.tar.gz --no-same-owner && mv rosa /usr/local/bin/rosa && rm rosa.tar.gz
ARG TERRAFORM_DOCS_VERSION=0.22.0
RUN curl -sSLo ./terraform-docs.tar.gz https://terraform-docs.io/dl/v${TERRAFORM_DOCS_VERSION}/terraform-docs-v${TERRAFORM_DOCS_VERSION}-$(uname)-amd64.tar.gz && \
tar -xzf terraform-docs.tar.gz terraform-docs && chmod +x terraform-docs && \
mv terraform-docs /usr/local/bin/terraform-docs && rm terraform-docs.tar.gz
# curl-minimal is preinstalled; do not install the curl RPM (conflicts with curl-minimal).
RUN microdnf install -y tar gzip unzip make git which shadow-utils gnupg2 && \
microdnf clean all
# Prow / integration client image: newest Terraform (TERRAFORM_VERSION). Module minimum compatibility is checked in GitHub Actions verify-min-terraform.yml.
# renovate: datasource=github-releases depName=hashicorp/terraform versioning=semver
ARG TERRAFORM_VERSION=1.15.4
RUN curl -fsSL -o /etc/yum.repos.d/hashicorp.repo https://rpm.releases.hashicorp.com/RHEL/hashicorp.repo && \
microdnf install -y "terraform-${TERRAFORM_VERSION}" && \
microdnf clean all && \
terraform version
# renovate: datasource=github-releases depName=aws/aws-cli versioning=semver-coerced
ARG AWS_CLI_VERSION=2.34.53
# PGP verify per https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html
RUN set -euo pipefail; \
aws_zip="awscli-exe-linux-x86_64-${AWS_CLI_VERSION}.zip"; \
curl -fsSL "https://awscli.amazonaws.com/${aws_zip}" -o awscliv2.zip; \
curl -fsSL "https://awscli.amazonaws.com/${aws_zip}.sig" -o awscliv2.sig; \
gpg --import /app/hack/aws-cli-public-key.asc; \
gpg --verify awscliv2.sig awscliv2.zip; \
unzip awscliv2.zip; \
./aws/install -i /usr/local/aws-cli -b /usr/local/bin; \
rm -rf awscliv2.zip awscliv2.sig aws/; \
aws --version
# renovate: datasource=github-releases depName=openshift/rosa versioning=semver
ARG ROSA_VERSION=1.2.62
# SHA256 from mirror sha256sum.txt (https://mirror.openshift.com/pub/cgw/rosa/<version>/)
RUN set -euo pipefail; \
rosa_mirror="https://mirror.openshift.com/pub/cgw/rosa/${ROSA_VERSION}"; \
curl -fsSL "${rosa_mirror}/rosa-linux.tar.gz" -o rosa-linux.tar.gz; \
curl -fsSL "${rosa_mirror}/sha256sum.txt" -o sha256sum.txt; \
grep -F ' rosa-linux.tar.gz' sha256sum.txt | sha256sum -c -; \
tar xzf rosa-linux.tar.gz && mv rosa /usr/local/bin/rosa; \
rm -f rosa-linux.tar.gz sha256sum.txt; \
rosa version
# Tool versions: Makefile (make tools).
RUN make tools
ENV PATH="/app/bin:/usr/local/bin:${PATH}" \
HOME="/app"
# Run as root (default): Prow/ci-operator mounts the repo workspace with root-owned files; non-root USER breaks make verify / verify-gen writes.
Loading