Skip to content

feat(ENG-13677): Terraform credential helper - #400

Merged
tigh-latte merged 17 commits into
masterfrom
tigh/terraform-credential-provider
Sep 8, 2026
Merged

feat(ENG-13677): Terraform credential helper#400
tigh-latte merged 17 commits into
masterfrom
tigh/terraform-credential-provider

Conversation

@tigh-latte

@tigh-latte tigh-latte commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Description

Adds a Terraform credentials helper for Cloudsmith registries so
terraform init can authenticate against a Cloudsmith Terraform registry with
no token on disk, reusing the existing Cloudsmith CLI credential chain
(--api-key/CLOUDSMITH_API_KEY, credentials.ini, the OS keyring, or OIDC).

Terraform discovers credentials helpers as executables named
terraform-credentials-<name> and only searches its plugin directories (never
$PATH). This PR ships the helper, a launcher/wrapper that satisfies that
discovery contract, an installer that wires up ~/.terraformrc, and the
repository-scoped token format the registry expects.

What's included

Command (cloudsmith credential-helper terraform)

  • Implements Terraform's credentials-helper protocol for the get verb.
    Accepts Terraform's [verb] <hostname> calling convention (verb defaults to
    get; hostname falls back to stdin) so the launcher can forward args
    verbatim.
  • Returns {"token": "..."} for a Cloudsmith host and {} for any other host
    (exit 0) so Terraform falls back to its own credential sources.
    store/forget and unknown verbs return an actionable error and a non-zero
    exit. Missing credentials for a Cloudsmith host produce a clean refusal, never
    a traceback.
  • Registered on the credential-helper group.

Installer (credential-helper install/uninstall/list terraform)

  • Writes the launcher into Terraform's plugin dir (~/.terraform.d/plugins by
    default; --bin-dir overrides) and manages the credentials_helper "cloudsmith" block in ~/.terraformrc via a regex block editor (no HCL
    parser); refuses if a different helper block already exists.
  • Bakes the resolved --org, -P/--profile, and --repo into the terraformrc
    args list so terraform init needs no environment variables. Computes the
    terraformrc change before writing the launcher so a conflict leaves no orphan.

Repository-scoped, custom-domain-aware token format

  • Terraform never tells a credentials helper which repository is requested, so
    -r/--repo/--repository (or CLOUDSMITH_REPO) is required on get, and
    can also be passed to install to bake it into the terraformrc args.
  • Tokens are scoped per repository:
    • Standard *.cloudsmith.io/*.cloudsmith.com hosts → {org}/{repo}/{token}
      (the organisation is required here).
    • Custom domains (already bound to a single organisation) → {repo}/{token}
      (the org is used only to resolve the domain, never emitted in the token).
  • Added is_standard_cloudsmith_domain() to credential_helpers/common.py to
    distinguish standard hosts from custom domains (is_cloudsmith_domain was
    refactored to reuse it; behaviour unchanged).

Type of Change

  • New feature

Testing

  • Unit tests for the runtime (get/store/forget, token / empty-object /
    refusal outcomes, org-required-on-standard-domain, org-omitted-on-custom-
    domain), the CLI shim, the wrapper delegation, the terraformrc block
    helpers, and the installer (launcher + terraformrc, --org/-P/--repo
    baking, conflict handling).
  • is_standard_cloudsmith_domain unit coverage (apex/subdomain/scheme/casing
    matches, plus custom-domain and lookalike non-matches).
  • A live integration test (@pytest.mark.integration) that runs a real
    terraform init in an isolated HOME and asserts it does not fail for
    authentication reasons; skips cleanly when terraform, the wrapper, or the
    PYTEST_CLOUDSMITH_* vars are absent.
env -u CLOUDSMITH_PROFILE -u CLOUDSMITH_ORG -u CLOUDSMITH_WORKSPACE \
    -u CLOUDSMITH_KEYRING_BACKEND HOME=$(mktemp -d) \
    pytest -m "not integration"

Additional Notes

Copilot AI lite review requested due to automatic review settings August 31, 2026 08:54
@tigh-latte
tigh-latte requested a review from a team as a code owner August 31, 2026 08:54

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a Terraform credentials helper integration to Cloudsmith CLI so terraform init can authenticate against Cloudsmith Terraform registries via the existing CLI credential chain (env/config/keyring/OIDC), plus installer logic to wire Terraform’s plugin dir and ~/.terraformrc.

Changes:

  • Introduces Terraform helper runtime + terraformrc block editor + installer that writes a terraform-credentials-cloudsmith launcher into Terraform’s plugin directory and manages a credentials_helper "cloudsmith" block.
  • Adds CLI wiring for cloudsmith credential-helper terraform and extends credential-helper install to support Terraform-specific baked args (org/profile/repo) and next-steps guidance.
  • Adds unit + integration tests and refactors domain detection by introducing is_standard_cloudsmith_domain().

Reviewed changes

Copilot reviewed 14 out of 14 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
cloudsmith_cli/credential_helpers/terraform/terraformrc.py Text-based add/update/remove of the credentials_helper "cloudsmith" terraformrc block.
cloudsmith_cli/credential_helpers/terraform/runtime.py Implements Terraform credentials-helper protocol behavior and scoped token formatting.
cloudsmith_cli/credential_helpers/terraform/installer.py Installs/removes the launcher into Terraform plugin dir and updates terraformrc.
cloudsmith_cli/credential_helpers/terraform/init.py Exposes Terraform helper runtime functions at package level.
cloudsmith_cli/credential_helpers/common.py Adds is_standard_cloudsmith_domain() and reuses it in is_cloudsmith_domain().
cloudsmith_cli/cli/commands/credential_helper/terraform.py Click command shim for Terraform helper (parses verb/hostname, prints JSON).
cloudsmith_cli/cli/commands/credential_helper/manage.py Registers Terraform installer; adds Terraform repo bake + next-steps output.
cloudsmith_cli/cli/commands/credential_helper/init.py Registers the terraform subcommand under credential-helper.
cloudsmith_cli/cli/tests/test_startup_imports.py Adds import-safety tests for Terraform helper (and wrapper).
cloudsmith_cli/cli/tests/test_credential_helper_terraform.py Adds runtime/CLI/wrapper behavior tests for Terraform helper.
cloudsmith_cli/cli/tests/test_credential_helper_terraform_installer.py Adds terraformrc + installer + CLI install/uninstall tests.
cloudsmith_cli/cli/tests/commands/test_credential_helper.py Adds unit coverage for is_standard_cloudsmith_domain().
cloudsmith_cli/cli/tests/commands/test_credential_helper_terraform_integration.py Adds live terraform init integration test exercising helper auth path.
CHANGELOG.md Documents the new Terraform credentials helper feature.
Suppressed comments (1)

cloudsmith_cli/cli/tests/test_startup_imports.py:76

  • This test imports cloudsmith_cli.credential_helpers.terraform.wrapper, but there is no wrapper.py under cloudsmith_cli/credential_helpers/terraform/ in this PR (only __init__.py, runtime.py, installer.py, terraformrc.py). This will fail at import time and break the suite.

Either add the missing wrapper module (and its packaging entry point if it’s meant to be an installed executable), or adjust/remove the wrapper-related tests if the launcher written by TerraformInstaller is the only wrapper being shipped.


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread cloudsmith_cli/credential_helpers/terraform/runtime.py
Comment thread cloudsmith_cli/credential_helpers/terraform/terraformrc.py Outdated
Comment thread cloudsmith_cli/cli/tests/test_credential_helper_terraform.py
Comment thread cloudsmith_cli/credential_helpers/terraform/installer.py
Comment thread cloudsmith_cli/credential_helpers/terraform/installer.py Outdated
Comment thread cloudsmith_cli/credential_helpers/terraform/installer.py Outdated
Comment thread cloudsmith_cli/cli/commands/credential_helper/manage.py
Comment thread cloudsmith_cli/cli/commands/credential_helper/terraform.py
@tigh-latte
tigh-latte force-pushed the tigh/terraform-credential-provider branch from 176f131 to 6766bbf Compare September 7, 2026 11:36
@tigh-latte

Copy link
Copy Markdown
Contributor Author

@BartoszBlizniak this is ready for another look now

@BartoszBlizniak BartoszBlizniak left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two of the three earlier threads (--config-file/--credentials-file baking and draining stdin on store) are fixed correctly, thanks. The plugin-dir restriction needs another pass, see inline.

Comment thread cloudsmith_cli/credential_helpers/terraform/installer.py Outdated
Comment thread cloudsmith_cli/cli/tests/test_credential_helper_terraform_installer.py Outdated
Fix misunderstand and incorrect implementation of mirror dir being used as plugin
install dir.
@tigh-latte
tigh-latte force-pushed the tigh/terraform-credential-provider branch from 39ff0a6 to 5ed9aae Compare September 8, 2026 09:49
@tigh-latte
tigh-latte merged commit aee00f6 into master Sep 8, 2026
22 checks passed
@tigh-latte
tigh-latte deleted the tigh/terraform-credential-provider branch September 8, 2026 11:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

4 participants