• v3.7.4 936cf8846a

    feat: serve local terraform repos as a provider registry (#102)
    ci/woodpecker/tag/docker Pipeline was successful

    unkinben released this 2026-07-03 18:55:35 +10:00 | 20 commits to master since this release

    Why

    Local terraform repos already served the Terraform network mirror protocol, but consuming that requires every user to add a provider_installation { network_mirror } block to ~/.terraformrc. A source = "artifactapi.k8s.../ns/type" address instead triggers the provider registry protocol (service discovery at /.well-known/terraform.json + GPG-signed SHA256SUMS), which returned 404 — hence "does not offer a provider registry."

    Local repos are meant to be the real thing, so this makes a terraform local repo a first-class provider registry: terraform init installs from a bare source address with no client config.

    What

    • Serve /.well-known/terraform.json service discovery and the providers.v1 endpoints under /terraform/v1/providers: versions, download/{os}/{arch}, sha256sums, sha256sums.sig.
    • Map the Terraform namespace segment to the artifactapi repo name; locate the provider by type. download_url points back at the existing /api/v1/local/... path.
    • Generate SHA256SUMS per version and sign it with a GPG key loaded from TF_SIGNING_KEY_PATH (optional TF_SIGNING_KEY_PASSPHRASE); advertise the public key + key id in the download response. No key → registry stays disabled (endpoints 404), so behaviour is unchanged until the signing secret is present.
    • New internal/tfsign (key load + detached signing, via x/crypto/openpgp) and internal/api/terraform (registry handler). Export ParseProviderZip for reuse.
    • TF_PROVIDER_PROTOCOLS (default 5.0,6.0) sets the advertised plugin protocols.
    • README section documenting usage.

    Consumer

    terraform {
      required_providers {
        artifactapi = {
          source  = "artifactapi.k8s.syd1.au.unkin.net/terraform-unkin/artifactapi"
          version = "0.1.2"
        }
      }
    }
    

    Tests

    • internal/tfsign: sign + verify round-trip, disabled/missing-key paths.
    • internal/api/terraform: dockerised full flow (discovery → versions → download → sha256sums → sig), verifying the signature against the advertised public key.

    Follow-ups (separate PRs)

    • argocd-apps: mount the signing K8s secret into the api deployment + set TF_SIGNING_KEY_PATH. The / HTTPRoute already routes /.well-known and /terraform to the API, so no gateway change is needed.
    • Image/version bump once tagged.

    Note

    Anchored the terraform/ gitignore to the repo root (/terraform/) so it stops matching internal/*/terraform/. This surfaced internal/provider/terraform/terraform_extra_test.go, which had been silently untracked — now committed.

    Reviewed-on: #102
    Co-authored-by: Ben Vincent ben@unkin.net
    Co-committed-by: Ben Vincent ben@unkin.net

    Downloads