Skip to content
Draft
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
1 change: 1 addition & 0 deletions BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ go_config(
export_stdlib = "//go/config:export_stdlib",
gc_goopts = "//go/config:gc_goopts",
gc_linkopts = "//go/config:gc_linkopts",
gofips140 = "//go/config:gofips140",
gotags = "//go/config:tags",
linkmode = "//go/config:linkmode",
msan = "//go/config:msan",
Expand Down
2 changes: 2 additions & 0 deletions docs/go/core/rules.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
[config_setting]: https://docs.bazel.build/versions/master/be/general.html#config_setting
[data dependencies]: https://bazel.build/concepts/dependencies#data-dependencies
[goarch]: /go/modes.rst#goarch
[gofips140]: /go/modes.rst#gofips140
[goos]: /go/modes.rst#goos
[mode attributes]: /go/modes.rst#mode-attributes
[nogo]: /go/nogo.rst#nogo
Expand Down Expand Up @@ -58,6 +59,7 @@ sufficient to match the capabilities of the normal go tools.
- [config_setting]
- [data dependencies]
- [goarch]
- [gofips140]
- [goos]
- [mode attributes]
- [nogo]
Expand Down
24 changes: 14 additions & 10 deletions docs/go/core/rules.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
[config_setting]: https://docs.bazel.build/versions/master/be/general.html#config_setting
[data dependencies]: https://bazel.build/concepts/dependencies#data-dependencies
[goarch]: /go/modes.rst#goarch
[gofips140]: /go/modes.rst#gofips140
[goos]: /go/modes.rst#goos
[mode attributes]: /go/modes.rst#mode-attributes
[nogo]: /go/nogo.rst#nogo
Expand Down Expand Up @@ -60,6 +61,7 @@ sufficient to match the capabilities of the normal go tools.
- [config_setting]
- [data dependencies]
- [goarch]
- [gofips140]
- [goos]
- [mode attributes]
- [nogo]
Expand Down Expand Up @@ -124,8 +126,8 @@ Rules

<pre>
go_binary(<a href="#go_binary-name">name</a>, <a href="#go_binary-basename">basename</a>, <a href="#go_binary-cdeps">cdeps</a>, <a href="#go_binary-cgo">cgo</a>, <a href="#go_binary-clinkopts">clinkopts</a>, <a href="#go_binary-copts">copts</a>, <a href="#go_binary-cppopts">cppopts</a>, <a href="#go_binary-cxxopts">cxxopts</a>, <a href="#go_binary-data">data</a>, <a href="#go_binary-deps">deps</a>, <a href="#go_binary-embed">embed</a>,
<a href="#go_binary-embedsrcs">embedsrcs</a>, <a href="#go_binary-env">env</a>, <a href="#go_binary-gc_goopts">gc_goopts</a>, <a href="#go_binary-gc_linkopts">gc_linkopts</a>, <a href="#go_binary-goarch">goarch</a>, <a href="#go_binary-goos">goos</a>, <a href="#go_binary-gotags">gotags</a>, <a href="#go_binary-importpath">importpath</a>, <a href="#go_binary-linkmode">linkmode</a>, <a href="#go_binary-msan">msan</a>,
<a href="#go_binary-out">out</a>, <a href="#go_binary-pgoprofile">pgoprofile</a>, <a href="#go_binary-pure">pure</a>, <a href="#go_binary-race">race</a>, <a href="#go_binary-srcs">srcs</a>, <a href="#go_binary-static">static</a>, <a href="#go_binary-x_defs">x_defs</a>)
<a href="#go_binary-embedsrcs">embedsrcs</a>, <a href="#go_binary-env">env</a>, <a href="#go_binary-gc_goopts">gc_goopts</a>, <a href="#go_binary-gc_linkopts">gc_linkopts</a>, <a href="#go_binary-goarch">goarch</a>, <a href="#go_binary-gofips140">gofips140</a>, <a href="#go_binary-goos">goos</a>, <a href="#go_binary-gotags">gotags</a>, <a href="#go_binary-importpath">importpath</a>,
<a href="#go_binary-linkmode">linkmode</a>, <a href="#go_binary-msan">msan</a>, <a href="#go_binary-out">out</a>, <a href="#go_binary-pgoprofile">pgoprofile</a>, <a href="#go_binary-pure">pure</a>, <a href="#go_binary-race">race</a>, <a href="#go_binary-srcs">srcs</a>, <a href="#go_binary-static">static</a>, <a href="#go_binary-x_defs">x_defs</a>)
</pre>

This builds an executable from a set of source files,
Expand All @@ -136,7 +138,7 @@ This builds an executable from a set of source files,
<ul>
<li>[GoArchive]</li>
</ul>


### **Attributes**

Expand All @@ -159,6 +161,7 @@ This builds an executable from a set of source files,
| <a id="go_binary-gc_goopts"></a>gc_goopts | List of flags to add to the Go compilation command when using the gc compiler. Subject to ["Make variable"] substitution and [Bourne shell tokenization]. | List of strings | optional | [] |
| <a id="go_binary-gc_linkopts"></a>gc_linkopts | List of flags to add to the Go link command when using the gc compiler. Subject to ["Make variable"] substitution and [Bourne shell tokenization]. | List of strings | optional | [] |
| <a id="go_binary-goarch"></a>goarch | Forces a binary to be cross-compiled for a specific architecture. It's usually better to control this on the command line with <code>--platforms</code>.<br><br> This disables cgo by default, since a cross-compiling C/C++ toolchain is rarely available. To force cgo, set <code>pure</code> = <code>off</code>.<br><br> See [Cross compilation] for more information. | String | optional | "auto" |
| <a id="go_binary-gofips140"></a>gofips140 | Controls the GOFIPS140 environment variable. May be any string value. Common values include <code>"off"</code> (default), <code>"latest"</code>, and specific versions like <code>"v1.0.0"</code>. See [mode attributes], specifically [gofips140]. | String | optional | "off" |
| <a id="go_binary-goos"></a>goos | Forces a binary to be cross-compiled for a specific operating system. It's usually better to control this on the command line with <code>--platforms</code>.<br><br> This disables cgo by default, since a cross-compiling C/C++ toolchain is rarely available. To force cgo, set <code>pure</code> = <code>off</code>.<br><br> See [Cross compilation] for more information. | String | optional | "auto" |
| <a id="go_binary-gotags"></a>gotags | Enables a list of build tags when evaluating [build constraints]. Useful for conditional compilation. | List of strings | optional | [] |
| <a id="go_binary-importpath"></a>importpath | The import path of this binary. Binaries can't actually be imported, but this may be used by [go_path] and other tools to report the location of source files. This may be inferred from embedded libraries. | String | optional | "" |
Expand Down Expand Up @@ -191,7 +194,7 @@ This wraps an executable built by `go_binary` to cross compile it
<ul>
<li>[GoArchive]</li>
</ul>


### **Attributes**

Expand Down Expand Up @@ -226,7 +229,7 @@ This builds a Go library from a set of source files that are all part of
<li>[GoInfo]</li>
<li>[GoArchive]</li>
</ul>


### **Attributes**

Expand Down Expand Up @@ -269,7 +272,7 @@ go_path(<a href="#go_path-name">name</a>, <a href="#go_path-data">data</a>, <a h
`go_path` can depend on one or more Go targets (i.e., [go_library], [go_binary], or [go_test]).
It will include packages from those targets, as well as their transitive dependencies.
Packages will be in subdirectories named after their `importpath` or `importmap` attributes under a `src/` directory.


### **Attributes**

Expand Down Expand Up @@ -339,7 +342,7 @@ This declares a set of source files and related dependencies that can be embedde
<ul>
<li>[GoInfo]</li>
</ul>


### **Attributes**

Expand All @@ -363,8 +366,8 @@ This declares a set of source files and related dependencies that can be embedde

<pre>
go_test(<a href="#go_test-name">name</a>, <a href="#go_test-cdeps">cdeps</a>, <a href="#go_test-cgo">cgo</a>, <a href="#go_test-clinkopts">clinkopts</a>, <a href="#go_test-copts">copts</a>, <a href="#go_test-cppopts">cppopts</a>, <a href="#go_test-cxxopts">cxxopts</a>, <a href="#go_test-data">data</a>, <a href="#go_test-deps">deps</a>, <a href="#go_test-embed">embed</a>, <a href="#go_test-embedsrcs">embedsrcs</a>, <a href="#go_test-env">env</a>,
<a href="#go_test-env_inherit">env_inherit</a>, <a href="#go_test-gc_goopts">gc_goopts</a>, <a href="#go_test-gc_linkopts">gc_linkopts</a>, <a href="#go_test-goarch">goarch</a>, <a href="#go_test-goos">goos</a>, <a href="#go_test-gotags">gotags</a>, <a href="#go_test-importpath">importpath</a>, <a href="#go_test-linkmode">linkmode</a>, <a href="#go_test-msan">msan</a>, <a href="#go_test-pure">pure</a>,
<a href="#go_test-race">race</a>, <a href="#go_test-rundir">rundir</a>, <a href="#go_test-srcs">srcs</a>, <a href="#go_test-static">static</a>, <a href="#go_test-x_defs">x_defs</a>)
<a href="#go_test-env_inherit">env_inherit</a>, <a href="#go_test-gc_goopts">gc_goopts</a>, <a href="#go_test-gc_linkopts">gc_linkopts</a>, <a href="#go_test-goarch">goarch</a>, <a href="#go_test-gofips140">gofips140</a>, <a href="#go_test-goos">goos</a>, <a href="#go_test-gotags">gotags</a>, <a href="#go_test-importpath">importpath</a>, <a href="#go_test-linkmode">linkmode</a>,
<a href="#go_test-msan">msan</a>, <a href="#go_test-pure">pure</a>, <a href="#go_test-race">race</a>, <a href="#go_test-rundir">rundir</a>, <a href="#go_test-srcs">srcs</a>, <a href="#go_test-static">static</a>, <a href="#go_test-x_defs">x_defs</a>)
</pre>

This builds a set of tests that can be run with `bazel test`.<br><br>
Expand Down Expand Up @@ -396,7 +399,7 @@ This builds a set of tests that can be run with `bazel test`.<br><br>
the name based on the last component of the path. For example, a test
in `//foo/bar` is named `bar_test`, and uses internal and external
sources.


### **Attributes**

Expand All @@ -419,6 +422,7 @@ This builds a set of tests that can be run with `bazel test`.<br><br>
| <a id="go_test-gc_goopts"></a>gc_goopts | List of flags to add to the Go compilation command when using the gc compiler. Subject to ["Make variable"] substitution and [Bourne shell tokenization]. | List of strings | optional | [] |
| <a id="go_test-gc_linkopts"></a>gc_linkopts | List of flags to add to the Go link command when using the gc compiler. Subject to ["Make variable"] substitution and [Bourne shell tokenization]. | List of strings | optional | [] |
| <a id="go_test-goarch"></a>goarch | Forces a binary to be cross-compiled for a specific architecture. It's usually better to control this on the command line with <code>--platforms</code>.<br><br> This disables cgo by default, since a cross-compiling C/C++ toolchain is rarely available. To force cgo, set <code>pure</code> = <code>off</code>.<br><br> See [Cross compilation] for more information. | String | optional | "auto" |
| <a id="go_test-gofips140"></a>gofips140 | Controls the GOFIPS140 environment variable. May be any string value. Common values include <code>"off"</code> (default), <code>"latest"</code>, and specific versions like <code>"v1.0.0"</code>. See [mode attributes], specifically [gofips140]. | String | optional | "off" |
| <a id="go_test-goos"></a>goos | Forces a binary to be cross-compiled for a specific operating system. It's usually better to control this on the command line with <code>--platforms</code>.<br><br> This disables cgo by default, since a cross-compiling C/C++ toolchain is rarely available. To force cgo, set <code>pure</code> = <code>off</code>.<br><br> See [Cross compilation] for more information. | String | optional | "auto" |
| <a id="go_test-gotags"></a>gotags | Enables a list of build tags when evaluating [build constraints]. Useful for conditional compilation. | List of strings | optional | [] |
| <a id="go_test-importpath"></a>importpath | The import path of this test. Tests can't actually be imported, but this may be used by [go_path] and other tools to report the location of source files. This may be inferred from embedded libraries. | String | optional | "" |
Expand Down
6 changes: 6 additions & 0 deletions go/config/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@ bool_flag(
visibility = ["//visibility:public"],
)

string_flag(
name = "gofips140",
build_setting_default = "off",
visibility = ["//visibility:public"],
)

bool_flag(
name = "debug",
build_setting_default = False,
Expand Down
1 change: 1 addition & 0 deletions go/core.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ Core Go rules
.. _config_setting: https://docs.bazel.build/versions/master/be/general.html#config_setting
.. _data dependencies: https://bazel.build/concepts/dependencies#data-dependencies
.. _goarch: modes.rst#goarch
.. _gofips140: modes.rst#gofips140
.. _goos: modes.rst#goos
.. _mode attributes: modes.rst#mode-attributes
.. _nogo: nogo.rst#nogo
Expand Down
7 changes: 7 additions & 0 deletions go/modes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,13 @@ or using `Bazel configuration transitions`_.
| ``CGO_ENABLED=0``). Packages that contain cgo code may still be built, but |
| the cgo code will be filtered out, and the ``cgo`` build tag will be false. |
+------------------------+---------------------+-------------------------------+
| :param:`gofips140` | :type:`string` | :value:`"off"` |
+------------------------+---------------------+-------------------------------+
| Controls the ``GOFIPS140`` environment variable used by Go 1.24+ to select |
| the version of the Go Cryptographic Module. Can be set to ``"off"`` |
| (default), ``"latest"``, or a specific version like ``"v1.0.0"``. |
| See the `Go 1.24 FIPS 140-3 documentation`_ for more details. |
+------------------------+---------------------+-------------------------------+
| :param:`debug` | :type:`bool` | :value:`false` |
+------------------------+---------------------+-------------------------------+
| Includes debugging information in compiled packages (using the ``-N`` and |
Expand Down
7 changes: 7 additions & 0 deletions go/private/context.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,7 @@ default_go_config_info = GoConfigInfo(
race = False,
msan = False,
pure = False,
gofips140 = "off",
strip = False,
debug = False,
linkmode = LINKMODE_NORMAL,
Expand Down Expand Up @@ -541,6 +542,7 @@ def go_context(
"GOROOT": goroot,
"GOROOT_FINAL": "GOROOT",
"CGO_ENABLED": "0" if mode.pure else "1",
"GOFIPS140": mode.gofips140,

# If we use --action_env=GOPATH, or in other cases where environment
# variables are passed through to this builder, the SDK build will try
Expand Down Expand Up @@ -988,6 +990,7 @@ def _go_config_impl(ctx):
race = race,
msan = msan,
pure = ctx.attr.pure[BuildSettingInfo].value,
gofips140 = ctx.attr.gofips140[BuildSettingInfo].value,
strip = ctx.attr.strip,
debug = ctx.attr.debug[BuildSettingInfo].value,
linkmode = ctx.attr.linkmode[BuildSettingInfo].value,
Expand Down Expand Up @@ -1024,6 +1027,10 @@ go_config = rule(
mandatory = True,
providers = [BuildSettingInfo],
),
"gofips140": attr.label(
mandatory = True,
providers = [BuildSettingInfo],
),
"strip": attr.bool(mandatory = True),
"debug": attr.label(
mandatory = True,
Expand Down
2 changes: 2 additions & 0 deletions go/private/mode.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ def mode_string(mode):
result.append("msan")
if mode.pure:
result.append("pure")
if mode.gofips140 != "off":
result.append("gofips140=" + mode.gofips140)
if mode.debug:
result.append("debug")
if mode.strip:
Expand Down
7 changes: 7 additions & 0 deletions go/private/rules/binary.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,13 @@ def _go_binary_kwargs(go_cc_aspects = []):
[pure].
""",
),
"gofips140": attr.string(
default = "off",
doc = """Controls the GOFIPS140 environment variable. May be any string value.
Common values include `"off"` (default), `"latest"`, and specific versions like `"v1.0.0"`.
See [mode attributes], specifically [gofips140].
""",
),
"static": attr.string(
default = "auto",
doc = """Controls whether a binary is statically linked. May be one of `on`,
Expand Down
7 changes: 7 additions & 0 deletions go/private/rules/test.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,13 @@ _go_test_kwargs = {
[pure].
""",
),
"gofips140": attr.string(
default = "off",
doc = """Controls the GOFIPS140 environment variable. May be any string value.
Common values include `"off"` (default), `"latest"`, and specific versions like `"v1.0.0"`.
See [mode attributes], specifically [gofips140].
""",
),
"static": attr.string(
default = "auto",
doc = """Controls whether a binary is statically linked. May be one of `on`,
Expand Down
7 changes: 7 additions & 0 deletions go/private/rules/transition.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ TRANSITIONED_GO_SETTING_KEYS = [
"//go/config:msan",
"//go/config:race",
"//go/config:pure",
"//go/config:gofips140",
"//go/config:linkmode",
"//go/config:tags",
"//go/config:pgoprofile",
Expand Down Expand Up @@ -109,6 +110,10 @@ def _go_transition_impl(settings, attr):
if tags:
settings["//go/config:tags"] = _deduped_and_sorted(tags)

gofips140 = getattr(attr, "gofips140", "off")
Copy link
Member

Choose a reason for hiding this comment

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

Doesn't this mean that it's impossible to disable fips for a binary if it is enabled globally?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This option just determines what gets built into the crypto module (see: https://go.dev/doc/security/fips140#the-gofips140-environment-variable). Essentially:

  • "off": Use the fips140 crypto from the standard library tree in use, but does not enable FIPS mode at runtime by default. You would need the GODEBUG runtime option to enable fips140 (e.g. GODEBUG=fips140=on or GODEBUG=fips140=only)
  • "latest": Same as off, but enables FIPS mode without needing the runtime flag.
  • "vX.Y.Z": Uses a specific Go crypto module, and enabled FIPS mode by default.

if gofips140 != "off":
settings["//go/config:gofips140"] = gofips140

linkmode = getattr(attr, "linkmode", "auto")
if linkmode != "auto":
if linkmode not in LINKMODES:
Expand Down Expand Up @@ -198,6 +203,7 @@ _common_reset_transition_dict = dict({
"//go/config:msan": False,
"//go/config:race": False,
"//go/config:pure": False,
"//go/config:gofips140": "off",
"//go/config:debug": False,
"//go/config:linkmode": LINKMODE_NORMAL,
"//go/config:tags": [],
Expand All @@ -214,6 +220,7 @@ _stdlib_keep_keys = sorted([
"//go/config:msan",
"//go/config:race",
"//go/config:pure",
"//go/config:gofips140",
"//go/config:linkmode",
"//go/config:tags",
"//go/config:pgoprofile",
Expand Down
5 changes: 5 additions & 0 deletions tests/core/go_binary/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,11 @@ go_bazel_test(
embedsrcs = ["pgo.pprof"],
)

go_bazel_test(
name = "gofips140_test",
srcs = ["gofips140_test.go"],
)

# Tests using .syso files in go_binary both transitively and directly.
go_binary(
name = "meaning",
Expand Down
87 changes: 87 additions & 0 deletions tests/core/go_binary/gofips140_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
// Copyright 2025 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package gofips140_test

import (
"bytes"
"testing"

"github.com/bazelbuild/rules_go/go/tools/bazel_testing"
)

func TestMain(m *testing.M) {
bazel_testing.TestMain(m, bazel_testing.Args{
Main: `
-- BUILD.bazel --
load("@io_bazel_rules_go//go:def.bzl", "go_binary")

go_binary(
name = "gofips140_off",
srcs = ["gofips140.go"],
gofips140 = "off",
)

go_binary(
name = "gofips140_latest",
srcs = ["gofips140.go"],
gofips140 = "latest",
)

go_binary(
name = "gofips140_version",
srcs = ["gofips140.go"],
gofips140 = "v1.0.0",
)

-- gofips140.go --
package main

import (
"crypto/fips140"
"fmt"
)

func main() {
fmt.Printf("%t", fips140.Enabled())
}
`,
})
}

// TestGOFIPS140Attribute checks that the gofips140 attribute on go_binary
// controls the GOFIPS140 environment variable.
func TestGOFIPS140Attribute(t *testing.T) {
tests := []struct {
target string
want string
}{
{"//:gofips140_off", "false"},
{"//:gofips140_latest", "true"},
{"//:gofips140_version", "true"},
}

for _, tt := range tests {
t.Run(tt.target, func(t *testing.T) {
out, err := bazel_testing.BazelOutput("run", tt.target)
if err != nil {
t.Fatalf("running %s: %v", tt.target, err)
}
got := string(bytes.TrimSpace(out))
if got != tt.want {
t.Fatalf("got %q; want %q", got, tt.want)
}
})
}
}
Loading