diff --git a/Makefile b/Makefile index 5b7029f2..2877c8d9 100644 --- a/Makefile +++ b/Makefile @@ -25,6 +25,7 @@ ifeq ($(FIPS), true) LINK_FLAGS := -linkmode=external -extldflags=-static $(LINK_FLAGS) # Prevent linking with libc regardless of CGO enabled or not. GO_BUILD_TAGS := $(GO_BUILD_TAGS) osusergo netgo fips + VERSION_FLAGS := $(VERSION_FLAGS) -X "main.BuildType=FIPS" endif LDFLAGS := -ldflags='$(VERSION_FLAGS) $(LINK_FLAGS)' diff --git a/cmd/cloudflared/buildinfo/build_info.go b/cmd/cloudflared/cliutil/build_info.go similarity index 59% rename from cmd/cloudflared/buildinfo/build_info.go rename to cmd/cloudflared/cliutil/build_info.go index 069d3fd8..4d73701e 100644 --- a/cmd/cloudflared/buildinfo/build_info.go +++ b/cmd/cloudflared/cliutil/build_info.go @@ -1,4 +1,4 @@ -package buildinfo +package cliutil import ( "fmt" @@ -11,23 +11,39 @@ type BuildInfo struct { GoOS string `json:"go_os"` GoVersion string `json:"go_version"` GoArch string `json:"go_arch"` + BuildType string `json:"build_type"` CloudflaredVersion string `json:"cloudflared_version"` } -func GetBuildInfo(cloudflaredVersion string) *BuildInfo { +func GetBuildInfo(buildType, version string) *BuildInfo { return &BuildInfo{ GoOS: runtime.GOOS, GoVersion: runtime.Version(), GoArch: runtime.GOARCH, - CloudflaredVersion: cloudflaredVersion, + BuildType: buildType, + CloudflaredVersion: version, } } func (bi *BuildInfo) Log(log *zerolog.Logger) { 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) } func (bi *BuildInfo) OSArch() string { 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) +} diff --git a/cmd/cloudflared/main.go b/cmd/cloudflared/main.go index 8ebf90af..8732ad34 100644 --- a/cmd/cloudflared/main.go +++ b/cmd/cloudflared/main.go @@ -31,6 +31,7 @@ const ( var ( Version = "DEV" BuildTime = "unknown" + BuildType = "" // Mostly network errors that we don't want reported back to Sentry, this is done by substring match. ignoredErrors = []string{ "connection reset by peer", @@ -46,9 +47,10 @@ var ( func main() { rand.Seed(time.Now().UnixNano()) - metrics.RegisterBuildInfo(BuildTime, Version) + metrics.RegisterBuildInfo(BuildType, BuildTime, Version) raven.SetRelease(Version) maxprocs.Set() + bInfo := cliutil.GetBuildInfo(BuildType, Version) // Graceful shutdown channel used by the app. When closed, app must terminate gracefully. // 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/).`, 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. You can use it to authenticate a session to reach an API behind Access, route web traffic to this machine, and configure access control. @@ -81,7 +83,7 @@ func main() { app.Action = action(graceShutdownC) 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) updater.Init(Version) runApp(app, graceShutdownC) diff --git a/cmd/cloudflared/tunnel/cmd.go b/cmd/cloudflared/tunnel/cmd.go index 0eb3ac75..1f9df38b 100644 --- a/cmd/cloudflared/tunnel/cmd.go +++ b/cmd/cloudflared/tunnel/cmd.go @@ -22,7 +22,6 @@ import ( "github.com/urfave/cli/v2/altsrc" "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/proxydns" "github.com/cloudflare/cloudflared/cmd/cloudflared/ui" @@ -86,7 +85,7 @@ const ( var ( graceShutdownC chan struct{} - version string + buildInfo *cliutil.BuildInfo 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 "+ @@ -175,8 +174,8 @@ func TunnelCommand(c *cli.Context) error { return runClassicTunnel(sc) } -func Init(ver string, gracefulShutdown chan struct{}) { - version, graceShutdownC = ver, gracefulShutdown +func Init(info *cliutil.BuildInfo, gracefulShutdown chan struct{}) { + buildInfo, graceShutdownC = info, gracefulShutdown } // 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 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) { @@ -224,7 +223,7 @@ func routeFromFlag(c *cli.Context) (route cfapi.HostnameRoute, ok bool) { func StartServer( c *cli.Context, - version string, + info *cliutil.BuildInfo, namedTunnel *connection.NamedTunnelConfig, log *zerolog.Logger, isUIEnabled bool, @@ -271,8 +270,7 @@ func StartServer( defer trace.Stop() } - buildInfo := buildinfo.GetBuildInfo(version) - buildInfo.Log(log) + info.Log(log) logClientOptions(c, log) // 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) } - tunnelConfig, ingressRules, err := prepareTunnelConfig(c, buildInfo, version, log, logTransport, observer, namedTunnel) + tunnelConfig, ingressRules, err := prepareTunnelConfig(c, info, log, logTransport, observer, namedTunnel) if err != nil { log.Err(err).Msg("Couldn't start tunnel") return err @@ -377,7 +375,7 @@ func StartServer( if isUIEnabled { tunnelUI := ui.NewUIModel( - version, + info.Version(), hostname, metricsListener.Addr().String(), &ingressRules, diff --git a/cmd/cloudflared/tunnel/configuration.go b/cmd/cloudflared/tunnel/configuration.go index 25eaf2a6..0d29cc7d 100644 --- a/cmd/cloudflared/tunnel/configuration.go +++ b/cmd/cloudflared/tunnel/configuration.go @@ -16,7 +16,8 @@ import ( "github.com/urfave/cli/v2" "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/connection" "github.com/cloudflare/cloudflared/edgediscovery" @@ -148,8 +149,7 @@ func getOriginCert(originCertPath string, log *zerolog.Logger) ([]byte, error) { func prepareTunnelConfig( c *cli.Context, - buildInfo *buildinfo.BuildInfo, - version string, + info *cliutil.BuildInfo, log, logTransport *zerolog.Logger, observer *connection.Observer, namedTunnel *connection.NamedTunnelConfig, @@ -193,8 +193,8 @@ func prepareTunnelConfig( namedTunnel.Client = tunnelpogs.ClientInfo{ ClientID: clientUUID[:], Features: dedup(features), - Version: version, - Arch: buildInfo.OSArch(), + Version: info.Version(), + Arch: info.OSArch(), } ingressRules, err = ingress.ParseIngress(cfg) if err != nil && err != ingress.ErrNoIngressRules { @@ -281,7 +281,7 @@ func prepareTunnelConfig( return &origin.TunnelConfig{ ConnectionConfig: connectionConfig, - OSArch: buildInfo.OSArch(), + OSArch: info.OSArch(), ClientID: clientID, EdgeAddrs: c.StringSlice("edge"), Region: c.String("region"), @@ -293,7 +293,7 @@ func prepareTunnelConfig( Log: log, LogTransport: logTransport, Observer: observer, - ReportedVersion: version, + ReportedVersion: info.Version(), // Note TUN-3758 , we use Int because UInt is not supported with altsrc Retries: uint(c.Int("retries")), RunFromTerminal: isRunningFromTerminal(), diff --git a/cmd/cloudflared/tunnel/quick_tunnel.go b/cmd/cloudflared/tunnel/quick_tunnel.go index 16255bc2..08b5ff78 100644 --- a/cmd/cloudflared/tunnel/quick_tunnel.go +++ b/cmd/cloudflared/tunnel/quick_tunnel.go @@ -76,7 +76,7 @@ func RunQuickTunnel(sc *subcommandContext) error { return StartServer( sc.c, - version, + buildInfo, &connection.NamedTunnelConfig{Credentials: credentials, QuickTunnelUrl: data.Result.Hostname}, sc.log, sc.isUIEnabled, diff --git a/cmd/cloudflared/tunnel/subcommand_context.go b/cmd/cloudflared/tunnel/subcommand_context.go index 2a20aaaa..cb5b15be 100644 --- a/cmd/cloudflared/tunnel/subcommand_context.go +++ b/cmd/cloudflared/tunnel/subcommand_context.go @@ -76,7 +76,7 @@ func (sc *subcommandContext) client() (cfapi.Client, error) { if err != nil { return nil, err } - userAgent := fmt.Sprintf("cloudflared/%s", version) + userAgent := fmt.Sprintf("cloudflared/%s", buildInfo.Version()) client, err := cfapi.NewRESTClient( sc.c.String("api-url"), credential.cert.AccountID, @@ -303,7 +303,7 @@ func (sc *subcommandContext) run(tunnelID uuid.UUID) error { return StartServer( sc.c, - version, + buildInfo, &connection.NamedTunnelConfig{Credentials: credentials}, sc.log, sc.isUIEnabled, diff --git a/metrics/metrics.go b/metrics/metrics.go index 1f2b5156..3210e840 100644 --- a/metrics/metrics.go +++ b/metrics/metrics.go @@ -83,15 +83,15 @@ func ServeMetrics( return err } -func RegisterBuildInfo(buildTime string, version string) { +func RegisterBuildInfo(buildType, buildTime, version string) { buildInfo := prometheus.NewGaugeVec( prometheus.GaugeOpts{ // Don't namespace build_info, since we want it to be consistent across all Cloudflare services Name: "build_info", Help: "Build and version information", }, - []string{"goversion", "revision", "version"}, + []string{"goversion", "type", "revision", "version"}, ) prometheus.MustRegister(buildInfo) - buildInfo.WithLabelValues(runtime.Version(), buildTime, version).Set(1) + buildInfo.WithLabelValues(runtime.Version(), buildType, buildTime, version).Set(1) }