Skip to content

Conversation

@topperge
Copy link

@topperge topperge commented Nov 12, 2025

Resolves #2026

Description

This PR implements FIPS 140-3 compliant mode for OpenTofu using Go 1.24+'s native FIPS support. When enabled via the GODEBUG=fips140=on environment variable, OpenTofu will use only FIPS-validated cryptographic modules for all operations.

Key Changes

  • FIPS Detection: Uses crypto/fips140.Enabled() to detect when FIPS mode is active
  • GPG Validation Handling: Automatically skips GPG signature validation in FIPS mode (the ProtonMail/go-crypto/openpgp library is not FIPS-compliant) with a logged warning
  • Security Model: In FIPS mode, provider integrity relies on FIPS-validated TLS connections and FIPS-approved checksum verification
  • Documentation: Added comprehensive docs explaining how to enable FIPS mode, implications, and limitations
  • Testing: Updated e2e tests to handle FIPS mode gracefully

What Works in FIPS Mode

  • All TLS connections (provider plugins via mTLS, backend storage, registry access)
  • State encryption (AES-GCM via FIPS-validated modules)
  • Checksum verification (SHA-256 via FIPS-approved algorithms)
  • Random number generation (FIPS-approved DRBG)

Known Limitations

  • GPG signature validation is automatically skipped (library incompatibility)
  • Security relies on FIPS-validated TLS + checksums instead

Files Changed

  • internal/getproviders/package_authentication.go: Skip GPG validation when FIPS is enabled
  • internal/command/meta_providers.go: Comment explaining FIPS compatibility with AutoMTLS
  • internal/command/e2etest/*_test.go: Updated tests to handle FIPS mode
  • docs/fips_support.md: Technical documentation
  • docs/usage/fips.md: User-facing documentation
  • CHANGELOG.md: Feature announcement

Checklist

  • I have read the contribution guide.
  • I have not used an AI coding assistant to create this PR.
  • I have written all code in this PR myself OR I have marked all code I have not written myself (including modified code, e.g. copied from other places and then modified) with a comment indicating where it came from.
  • I (and other contributors to this PR) have not looked at the Terraform source code while implementing this PR.

Go checklist

  • I have run golangci-lint on my change and receive no errors relevant to my code.
  • I have run existing tests to ensure my code doesn't break anything.
  • I have added tests for all relevant use cases of my code, and those tests are passing.
  • I have only exported functions, variables and structs that should be used from other packages.
  • I have added meaningful comments to all exported functions, variables, and structs.

Website/documentation checklist

  • I have locally started the website as described here and checked my changes.

Matt Topper and others added 4 commits November 12, 2025 01:13
This merge brings the FIPS 140-3 compliance feature branch up to date
with the latest upstream/main (523 commits ahead). Key changes:

- Resolved CHANGELOG.md conflict by combining FIPS feature entry with
  upstream changes
- Resolved meta_providers.go import conflict (added context import)
- Fixed crypto/fips package name to crypto/fips140 (correct for Go 1.24+)
- Verified GPG authentication logic works correctly with upstream bug fix
  in SigningSkipped() method

The FIPS feature enables OpenTofu to run in FIPS 140-3 compliant mode
when built with Go 1.24+ and GODEBUG=fips140=on is set at runtime.
GPG signature validation is skipped in FIPS mode as the underlying
OpenPGP library is not FIPS-compliant.

Signed-off-by: Matt Topper <[email protected]>
Extract GPG validation into focused helper functions:
- skipGPGValidation(): Handles FIPS mode and other skip scenarios
- performGPGValidation(): Performs normal GPG verification

This improves code clarity by:
- Separating concerns (FIPS check vs validation logic)
- Making the authentication flow more readable
- Allowing the skip reason to be parameterized for future extensibility

The behavior is unchanged, but the code structure is cleaner and more
maintainable.

Signed-off-by: Matt Topper <[email protected]>
The documentation previously described GPG signature validation as a
'potential limitation' with a phased testing plan. This has been updated
to accurately reflect the implemented behavior:

- docs/fips_support.md: Changed from 'unverified compatibility' to
  'known limitation' with clear explanation of how GPG validation is
  skipped and what security guarantees remain (FIPS TLS + checksums)

- docs/usage/fips.md: Added specific library name (ProtonMail/go-crypto)
  and clarified that integrity relies on both FIPS-validated TLS and
  checksum verification, not just TLS alone

- CHANGELOG.md: Added library name and mentioned checksum verification
  for accuracy

These changes make the documentation consistent with the code and provide
clearer security information for users evaluating FIPS compliance.

Signed-off-by: Matt Topper <[email protected]>
@topperge topperge requested a review from a team as a code owner November 12, 2025 08:26
@github-actions
Copy link

Reminder for the PR assignee: If this is a user-visible change, please update the changelog as part of the PR.

@apparentlymart
Copy link
Contributor

apparentlymart commented Nov 12, 2025

Thanks for working on this, @topperge!

#2026 was labelled as "need-rfc" because we felt that it needed more exploration and decision making before we could move forward with implementation.

Your writeup here does include some answers to questions that such an RFC would presumably cover, but for something security/compliance-sensitive like this I think we should go through the full RFC process so that we have a written record not only of what we decided but why we made those decisions and what we expect the implications of those decisions to be, so that we can make sure to make compatible tradeoffs in future work and so that anyone who might rely on this can know what we're assuming about their requirements and determine whether this does meet their requirements.

In particular (though this is not the only thing that I'd want to explore more in an RFC) I think we need to justify why it's an appropriate tradeoff to implicitly disable the key verification for providers, since having fewer checks when working in a mode that's associated with well-defined security controls seems counter-intuitive.

I note also that what we approved (provisionally, pending RFC) in #2026 was not to support two different usage modes for OpenTofu, but instead to compile OpenTofu in a way that forces this mode on for all users, so that we don't effectively double the number of supported configurations for using OpenTofu. We'd expected that -- assuming we can answer all of the associated design questions in a satisfactory way -- we'd add godebug fips140=on to our go.mod and thus produce OpenTofu releases that are FIPS-compliant by default, rather than only as an opt-in1.

With all of that said: I think we should work through the RFC process on this before considering any specific implementation. Would you be interested in working on such an RFC? The project maintainers could provide some more context on the original issue about what sort of design questions we'd want such an RFC to answer, if that would help quantify the likely work involved in that.

Thanks again!

Footnotes

  1. I must admit that I'm surprised to see GODEBUG working as a runtime-handled environment variable as in your proposed documentation, because from the upstream documentation I'd understood fips140=on as a request to the Go toolchain (at compile time) to link in a specific cryptographic module, and so I wouldn't have expected that cryptographic module to be included at all when that setting wasn't present at compile time.

    Can you share a link to the documentation you referred to that told you that was supported? I'd like to understand more about how it works and what the implications of that strategy are. 🤔

@@ -0,0 +1,33 @@
# Using OpenTofu in FIPS Mode (Experimental)
Copy link
Contributor

Choose a reason for hiding this comment

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

The docs directory in this repository is reserved only for development documentation whose audience is contributors to the OpenTofu codebase.

If we do decide to ship something that requires end-user-configuration (as opposed to being force-enabled for all users) then we'd want to document it somewhere under the website/docs/cli directory so that it would appear in the end-user-oriented documentation on our website.

@apparentlymart
Copy link
Contributor

To try to answer my own question about the runtime handling of GODEBUG I went to dig around in the docs again, and found FIPS 140-3 Compliance which has the following to say about it:

The run-time fips140 GODEBUG option controls whether the Go Cryptographic Module operates in FIPS 140-3 mode. It defaults to off. It can’t be changed after the program has started.

(Emphasis mine)

So indeed it does seem like it's possible to turn this on at runtime despite the fact that the OpenTofu project has not committed to support it.

The GOFIPS140 environment variable is a compile-time setting, but it decides which version of the cryptographic module to use rather than whether the cryptographic module is linked in to the executable at all.

Given all of that, it seems like we (the maintainers on behalf of the project) need to make a decision about whether and how we are going to support running tofu in an environment where GODEBUG is set and specifies a fips140 setting other than off. I'm going to post a comment on the original issue about that, since that's a better place to have this discussion where it's more visible to others who are following the issue.

Thanks again for working on this! I hope we can find a reasonable compromise.

@cam72cam
Copy link
Member

cam72cam commented Dec 3, 2025

Given our decision in #2026, we are closing this PR.

Thank you for your patience @topperge.

@cam72cam cam72cam closed this Dec 3, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants