TUN-5551: Show whether the binary was built for FIPS compliance
This is shown in 3 ways: - the version output with `cloudflared version` and alike commands - the build_info prometheus metric - a logging message
This commit is contained in:
parent
01ad2785ee
commit
a39d95d5f7
1
Makefile
1
Makefile
|
@ -25,6 +25,7 @@ ifeq ($(FIPS), true)
|
||||||
LINK_FLAGS := -linkmode=external -extldflags=-static $(LINK_FLAGS)
|
LINK_FLAGS := -linkmode=external -extldflags=-static $(LINK_FLAGS)
|
||||||
# Prevent linking with libc regardless of CGO enabled or not.
|
# Prevent linking with libc regardless of CGO enabled or not.
|
||||||
GO_BUILD_TAGS := $(GO_BUILD_TAGS) osusergo netgo fips
|
GO_BUILD_TAGS := $(GO_BUILD_TAGS) osusergo netgo fips
|
||||||
|
VERSION_FLAGS := $(VERSION_FLAGS) -X "main.BuildType=FIPS"
|
||||||
endif
|
endif
|
||||||
|
|
||||||
LDFLAGS := -ldflags='$(VERSION_FLAGS) $(LINK_FLAGS)'
|
LDFLAGS := -ldflags='$(VERSION_FLAGS) $(LINK_FLAGS)'
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package buildinfo
|
package cliutil
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
@ -11,23 +11,39 @@ type BuildInfo struct {
|
||||||
GoOS string `json:"go_os"`
|
GoOS string `json:"go_os"`
|
||||||
GoVersion string `json:"go_version"`
|
GoVersion string `json:"go_version"`
|
||||||
GoArch string `json:"go_arch"`
|
GoArch string `json:"go_arch"`
|
||||||
|
BuildType string `json:"build_type"`
|
||||||
CloudflaredVersion string `json:"cloudflared_version"`
|
CloudflaredVersion string `json:"cloudflared_version"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetBuildInfo(cloudflaredVersion string) *BuildInfo {
|
func GetBuildInfo(buildType, version string) *BuildInfo {
|
||||||
return &BuildInfo{
|
return &BuildInfo{
|
||||||
GoOS: runtime.GOOS,
|
GoOS: runtime.GOOS,
|
||||||
GoVersion: runtime.Version(),
|
GoVersion: runtime.Version(),
|
||||||
GoArch: runtime.GOARCH,
|
GoArch: runtime.GOARCH,
|
||||||
CloudflaredVersion: cloudflaredVersion,
|
BuildType: buildType,
|
||||||
|
CloudflaredVersion: version,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bi *BuildInfo) Log(log *zerolog.Logger) {
|
func (bi *BuildInfo) Log(log *zerolog.Logger) {
|
||||||
log.Info().Msgf("Version %s", bi.CloudflaredVersion)
|
log.Info().Msgf("Version %s", bi.CloudflaredVersion)
|
||||||
|
if bi.BuildType != "" {
|
||||||
|
log.Info().Msgf("Built%s", bi.GetBuildTypeMsg())
|
||||||
|
}
|
||||||
log.Info().Msgf("GOOS: %s, GOVersion: %s, GoArch: %s", bi.GoOS, bi.GoVersion, bi.GoArch)
|
log.Info().Msgf("GOOS: %s, GOVersion: %s, GoArch: %s", bi.GoOS, bi.GoVersion, bi.GoArch)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bi *BuildInfo) OSArch() string {
|
func (bi *BuildInfo) OSArch() string {
|
||||||
return fmt.Sprintf("%s_%s", bi.GoOS, bi.GoArch)
|
return fmt.Sprintf("%s_%s", bi.GoOS, bi.GoArch)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (bi *BuildInfo) Version() string {
|
||||||
|
return bi.CloudflaredVersion
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bi *BuildInfo) GetBuildTypeMsg() string {
|
||||||
|
if bi.BuildType == "" {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return fmt.Sprintf(" with %s", bi.BuildType)
|
||||||
|
}
|
|
@ -31,6 +31,7 @@ const (
|
||||||
var (
|
var (
|
||||||
Version = "DEV"
|
Version = "DEV"
|
||||||
BuildTime = "unknown"
|
BuildTime = "unknown"
|
||||||
|
BuildType = ""
|
||||||
// Mostly network errors that we don't want reported back to Sentry, this is done by substring match.
|
// Mostly network errors that we don't want reported back to Sentry, this is done by substring match.
|
||||||
ignoredErrors = []string{
|
ignoredErrors = []string{
|
||||||
"connection reset by peer",
|
"connection reset by peer",
|
||||||
|
@ -46,9 +47,10 @@ var (
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
rand.Seed(time.Now().UnixNano())
|
rand.Seed(time.Now().UnixNano())
|
||||||
metrics.RegisterBuildInfo(BuildTime, Version)
|
metrics.RegisterBuildInfo(BuildType, BuildTime, Version)
|
||||||
raven.SetRelease(Version)
|
raven.SetRelease(Version)
|
||||||
maxprocs.Set()
|
maxprocs.Set()
|
||||||
|
bInfo := cliutil.GetBuildInfo(BuildType, Version)
|
||||||
|
|
||||||
// Graceful shutdown channel used by the app. When closed, app must terminate gracefully.
|
// Graceful shutdown channel used by the app. When closed, app must terminate gracefully.
|
||||||
// Windows service manager closes this channel when it receives stop command.
|
// Windows service manager closes this channel when it receives stop command.
|
||||||
|
@ -71,7 +73,7 @@ func main() {
|
||||||
Terms (https://www.cloudflare.com/terms/) and Privacy Policy (https://www.cloudflare.com/privacypolicy/).`,
|
Terms (https://www.cloudflare.com/terms/) and Privacy Policy (https://www.cloudflare.com/privacypolicy/).`,
|
||||||
time.Now().Year(),
|
time.Now().Year(),
|
||||||
)
|
)
|
||||||
app.Version = fmt.Sprintf("%s (built %s)", Version, BuildTime)
|
app.Version = fmt.Sprintf("%s (built %s%s)", Version, BuildTime, bInfo.GetBuildTypeMsg())
|
||||||
app.Description = `cloudflared connects your machine or user identity to Cloudflare's global network.
|
app.Description = `cloudflared connects your machine or user identity to Cloudflare's global network.
|
||||||
You can use it to authenticate a session to reach an API behind Access, route web traffic to this machine,
|
You can use it to authenticate a session to reach an API behind Access, route web traffic to this machine,
|
||||||
and configure access control.
|
and configure access control.
|
||||||
|
@ -81,7 +83,7 @@ func main() {
|
||||||
app.Action = action(graceShutdownC)
|
app.Action = action(graceShutdownC)
|
||||||
app.Commands = commands(cli.ShowVersion)
|
app.Commands = commands(cli.ShowVersion)
|
||||||
|
|
||||||
tunnel.Init(Version, graceShutdownC) // we need this to support the tunnel sub command...
|
tunnel.Init(bInfo, graceShutdownC) // we need this to support the tunnel sub command...
|
||||||
access.Init(graceShutdownC)
|
access.Init(graceShutdownC)
|
||||||
updater.Init(Version)
|
updater.Init(Version)
|
||||||
runApp(app, graceShutdownC)
|
runApp(app, graceShutdownC)
|
||||||
|
|
|
@ -22,7 +22,6 @@ import (
|
||||||
"github.com/urfave/cli/v2/altsrc"
|
"github.com/urfave/cli/v2/altsrc"
|
||||||
|
|
||||||
"github.com/cloudflare/cloudflared/cfapi"
|
"github.com/cloudflare/cloudflared/cfapi"
|
||||||
"github.com/cloudflare/cloudflared/cmd/cloudflared/buildinfo"
|
|
||||||
"github.com/cloudflare/cloudflared/cmd/cloudflared/cliutil"
|
"github.com/cloudflare/cloudflared/cmd/cloudflared/cliutil"
|
||||||
"github.com/cloudflare/cloudflared/cmd/cloudflared/proxydns"
|
"github.com/cloudflare/cloudflared/cmd/cloudflared/proxydns"
|
||||||
"github.com/cloudflare/cloudflared/cmd/cloudflared/ui"
|
"github.com/cloudflare/cloudflared/cmd/cloudflared/ui"
|
||||||
|
@ -86,7 +85,7 @@ const (
|
||||||
|
|
||||||
var (
|
var (
|
||||||
graceShutdownC chan struct{}
|
graceShutdownC chan struct{}
|
||||||
version string
|
buildInfo *cliutil.BuildInfo
|
||||||
|
|
||||||
routeFailMsg = fmt.Sprintf("failed to provision routing, please create it manually via Cloudflare dashboard or UI; "+
|
routeFailMsg = fmt.Sprintf("failed to provision routing, please create it manually via Cloudflare dashboard or UI; "+
|
||||||
"most likely you already have a conflicting record there. You can also rerun this command with --%s to overwrite "+
|
"most likely you already have a conflicting record there. You can also rerun this command with --%s to overwrite "+
|
||||||
|
@ -175,8 +174,8 @@ func TunnelCommand(c *cli.Context) error {
|
||||||
return runClassicTunnel(sc)
|
return runClassicTunnel(sc)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Init(ver string, gracefulShutdown chan struct{}) {
|
func Init(info *cliutil.BuildInfo, gracefulShutdown chan struct{}) {
|
||||||
version, graceShutdownC = ver, gracefulShutdown
|
buildInfo, graceShutdownC = info, gracefulShutdown
|
||||||
}
|
}
|
||||||
|
|
||||||
// runAdhocNamedTunnel create, route and run a named tunnel in one command
|
// runAdhocNamedTunnel create, route and run a named tunnel in one command
|
||||||
|
@ -209,7 +208,7 @@ func runAdhocNamedTunnel(sc *subcommandContext, name, credentialsOutputPath stri
|
||||||
|
|
||||||
// runClassicTunnel creates a "classic" non-named tunnel
|
// runClassicTunnel creates a "classic" non-named tunnel
|
||||||
func runClassicTunnel(sc *subcommandContext) error {
|
func runClassicTunnel(sc *subcommandContext) error {
|
||||||
return StartServer(sc.c, version, nil, sc.log, sc.isUIEnabled)
|
return StartServer(sc.c, buildInfo, nil, sc.log, sc.isUIEnabled)
|
||||||
}
|
}
|
||||||
|
|
||||||
func routeFromFlag(c *cli.Context) (route cfapi.HostnameRoute, ok bool) {
|
func routeFromFlag(c *cli.Context) (route cfapi.HostnameRoute, ok bool) {
|
||||||
|
@ -224,7 +223,7 @@ func routeFromFlag(c *cli.Context) (route cfapi.HostnameRoute, ok bool) {
|
||||||
|
|
||||||
func StartServer(
|
func StartServer(
|
||||||
c *cli.Context,
|
c *cli.Context,
|
||||||
version string,
|
info *cliutil.BuildInfo,
|
||||||
namedTunnel *connection.NamedTunnelConfig,
|
namedTunnel *connection.NamedTunnelConfig,
|
||||||
log *zerolog.Logger,
|
log *zerolog.Logger,
|
||||||
isUIEnabled bool,
|
isUIEnabled bool,
|
||||||
|
@ -271,8 +270,7 @@ func StartServer(
|
||||||
defer trace.Stop()
|
defer trace.Stop()
|
||||||
}
|
}
|
||||||
|
|
||||||
buildInfo := buildinfo.GetBuildInfo(version)
|
info.Log(log)
|
||||||
buildInfo.Log(log)
|
|
||||||
logClientOptions(c, log)
|
logClientOptions(c, log)
|
||||||
|
|
||||||
// this context drives the server, when it's cancelled tunnel and all other components (origins, dns, etc...) should stop
|
// this context drives the server, when it's cancelled tunnel and all other components (origins, dns, etc...) should stop
|
||||||
|
@ -336,7 +334,7 @@ func StartServer(
|
||||||
observer.SendURL(quickTunnelURL)
|
observer.SendURL(quickTunnelURL)
|
||||||
}
|
}
|
||||||
|
|
||||||
tunnelConfig, ingressRules, err := prepareTunnelConfig(c, buildInfo, version, log, logTransport, observer, namedTunnel)
|
tunnelConfig, ingressRules, err := prepareTunnelConfig(c, info, log, logTransport, observer, namedTunnel)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Err(err).Msg("Couldn't start tunnel")
|
log.Err(err).Msg("Couldn't start tunnel")
|
||||||
return err
|
return err
|
||||||
|
@ -377,7 +375,7 @@ func StartServer(
|
||||||
|
|
||||||
if isUIEnabled {
|
if isUIEnabled {
|
||||||
tunnelUI := ui.NewUIModel(
|
tunnelUI := ui.NewUIModel(
|
||||||
version,
|
info.Version(),
|
||||||
hostname,
|
hostname,
|
||||||
metricsListener.Addr().String(),
|
metricsListener.Addr().String(),
|
||||||
&ingressRules,
|
&ingressRules,
|
||||||
|
|
|
@ -16,7 +16,8 @@ import (
|
||||||
"github.com/urfave/cli/v2"
|
"github.com/urfave/cli/v2"
|
||||||
"golang.org/x/crypto/ssh/terminal"
|
"golang.org/x/crypto/ssh/terminal"
|
||||||
|
|
||||||
"github.com/cloudflare/cloudflared/cmd/cloudflared/buildinfo"
|
"github.com/cloudflare/cloudflared/cmd/cloudflared/cliutil"
|
||||||
|
|
||||||
"github.com/cloudflare/cloudflared/config"
|
"github.com/cloudflare/cloudflared/config"
|
||||||
"github.com/cloudflare/cloudflared/connection"
|
"github.com/cloudflare/cloudflared/connection"
|
||||||
"github.com/cloudflare/cloudflared/edgediscovery"
|
"github.com/cloudflare/cloudflared/edgediscovery"
|
||||||
|
@ -148,8 +149,7 @@ func getOriginCert(originCertPath string, log *zerolog.Logger) ([]byte, error) {
|
||||||
|
|
||||||
func prepareTunnelConfig(
|
func prepareTunnelConfig(
|
||||||
c *cli.Context,
|
c *cli.Context,
|
||||||
buildInfo *buildinfo.BuildInfo,
|
info *cliutil.BuildInfo,
|
||||||
version string,
|
|
||||||
log, logTransport *zerolog.Logger,
|
log, logTransport *zerolog.Logger,
|
||||||
observer *connection.Observer,
|
observer *connection.Observer,
|
||||||
namedTunnel *connection.NamedTunnelConfig,
|
namedTunnel *connection.NamedTunnelConfig,
|
||||||
|
@ -193,8 +193,8 @@ func prepareTunnelConfig(
|
||||||
namedTunnel.Client = tunnelpogs.ClientInfo{
|
namedTunnel.Client = tunnelpogs.ClientInfo{
|
||||||
ClientID: clientUUID[:],
|
ClientID: clientUUID[:],
|
||||||
Features: dedup(features),
|
Features: dedup(features),
|
||||||
Version: version,
|
Version: info.Version(),
|
||||||
Arch: buildInfo.OSArch(),
|
Arch: info.OSArch(),
|
||||||
}
|
}
|
||||||
ingressRules, err = ingress.ParseIngress(cfg)
|
ingressRules, err = ingress.ParseIngress(cfg)
|
||||||
if err != nil && err != ingress.ErrNoIngressRules {
|
if err != nil && err != ingress.ErrNoIngressRules {
|
||||||
|
@ -281,7 +281,7 @@ func prepareTunnelConfig(
|
||||||
|
|
||||||
return &origin.TunnelConfig{
|
return &origin.TunnelConfig{
|
||||||
ConnectionConfig: connectionConfig,
|
ConnectionConfig: connectionConfig,
|
||||||
OSArch: buildInfo.OSArch(),
|
OSArch: info.OSArch(),
|
||||||
ClientID: clientID,
|
ClientID: clientID,
|
||||||
EdgeAddrs: c.StringSlice("edge"),
|
EdgeAddrs: c.StringSlice("edge"),
|
||||||
Region: c.String("region"),
|
Region: c.String("region"),
|
||||||
|
@ -293,7 +293,7 @@ func prepareTunnelConfig(
|
||||||
Log: log,
|
Log: log,
|
||||||
LogTransport: logTransport,
|
LogTransport: logTransport,
|
||||||
Observer: observer,
|
Observer: observer,
|
||||||
ReportedVersion: version,
|
ReportedVersion: info.Version(),
|
||||||
// Note TUN-3758 , we use Int because UInt is not supported with altsrc
|
// Note TUN-3758 , we use Int because UInt is not supported with altsrc
|
||||||
Retries: uint(c.Int("retries")),
|
Retries: uint(c.Int("retries")),
|
||||||
RunFromTerminal: isRunningFromTerminal(),
|
RunFromTerminal: isRunningFromTerminal(),
|
||||||
|
|
|
@ -76,7 +76,7 @@ func RunQuickTunnel(sc *subcommandContext) error {
|
||||||
|
|
||||||
return StartServer(
|
return StartServer(
|
||||||
sc.c,
|
sc.c,
|
||||||
version,
|
buildInfo,
|
||||||
&connection.NamedTunnelConfig{Credentials: credentials, QuickTunnelUrl: data.Result.Hostname},
|
&connection.NamedTunnelConfig{Credentials: credentials, QuickTunnelUrl: data.Result.Hostname},
|
||||||
sc.log,
|
sc.log,
|
||||||
sc.isUIEnabled,
|
sc.isUIEnabled,
|
||||||
|
|
|
@ -76,7 +76,7 @@ func (sc *subcommandContext) client() (cfapi.Client, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
userAgent := fmt.Sprintf("cloudflared/%s", version)
|
userAgent := fmt.Sprintf("cloudflared/%s", buildInfo.Version())
|
||||||
client, err := cfapi.NewRESTClient(
|
client, err := cfapi.NewRESTClient(
|
||||||
sc.c.String("api-url"),
|
sc.c.String("api-url"),
|
||||||
credential.cert.AccountID,
|
credential.cert.AccountID,
|
||||||
|
@ -303,7 +303,7 @@ func (sc *subcommandContext) run(tunnelID uuid.UUID) error {
|
||||||
|
|
||||||
return StartServer(
|
return StartServer(
|
||||||
sc.c,
|
sc.c,
|
||||||
version,
|
buildInfo,
|
||||||
&connection.NamedTunnelConfig{Credentials: credentials},
|
&connection.NamedTunnelConfig{Credentials: credentials},
|
||||||
sc.log,
|
sc.log,
|
||||||
sc.isUIEnabled,
|
sc.isUIEnabled,
|
||||||
|
|
|
@ -83,15 +83,15 @@ func ServeMetrics(
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func RegisterBuildInfo(buildTime string, version string) {
|
func RegisterBuildInfo(buildType, buildTime, version string) {
|
||||||
buildInfo := prometheus.NewGaugeVec(
|
buildInfo := prometheus.NewGaugeVec(
|
||||||
prometheus.GaugeOpts{
|
prometheus.GaugeOpts{
|
||||||
// Don't namespace build_info, since we want it to be consistent across all Cloudflare services
|
// Don't namespace build_info, since we want it to be consistent across all Cloudflare services
|
||||||
Name: "build_info",
|
Name: "build_info",
|
||||||
Help: "Build and version information",
|
Help: "Build and version information",
|
||||||
},
|
},
|
||||||
[]string{"goversion", "revision", "version"},
|
[]string{"goversion", "type", "revision", "version"},
|
||||||
)
|
)
|
||||||
prometheus.MustRegister(buildInfo)
|
prometheus.MustRegister(buildInfo)
|
||||||
buildInfo.WithLabelValues(runtime.Version(), buildTime, version).Set(1)
|
buildInfo.WithLabelValues(runtime.Version(), buildType, buildTime, version).Set(1)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue