Repository: elastic/fleet-server
Pull request #4820: Add version metadata to version command
Author: login: michel-laterman
Labels: name: enhancement
description: New feature or request
name: Team:Elastic-Agent-Control-Plane
description: Label for the Agent Control Plane team
name: backport-8.19
description: Automated backport to the 8.19 branch
Created: 2025-04-16T19:38:46Z | Merged: 2025-04-24T18:46:16Z

## What is the problem this PR solves?

We are not able to determine if a fleet-server binary is a FIPS distribution or not.

## How does this PR solve the problem?

Add build commit, build time, and FIPS distribution indicator to the output of the version command. Add FIPS distribution indicator to initial log line.

## How to test this PR locally

Run: `./fleet-server -v`

Example output:

```
./bin/fleet-server -v
fleet-server version 9.1.0 [5500121e built 2025-04-16 19:28:02 +0000 UTC] (FIPS-distribution: false)
```

## Design Checklist

- ~~I have ensured my design is stateless and will work when multiple fleet-server instances are behind a load balancer.~~
- ~~I have or intend to scale test my changes, ensuring it will work reliably with 100K+ agents connected.~~
- ~~I have included fail safe mechanisms to limit the load on fleet-server: rate limiting, circuit breakers, caching, load shedding, etc.~~

## Checklist

- [x] I have commented my code, particularly in hard-to-understand areas
- ~~I have made corresponding changes to the documentation~~
- ~~I have made corresponding change to the default configuration files~~
- ~~I have added tests that prove my fix is effective or that my feature works~~
- [x] I have added an entry in `./changelog/fragments` using the [changelog tool](https://github.com/elastic/fleet-server#changelog)


Diff:
diff --git a/changelog/fragments/1744831791-Add-version-metadata-to-version-command-output.yaml b/changelog/fragments/1744831791-Add-version-metadata-to-version-command-output.yaml
new file mode 100644
index 0000000000..4d9f6f6051
--- /dev/null
+++ b/changelog/fragments/1744831791-Add-version-metadata-to-version-command-output.yaml
@@ -0,0 +1,34 @@
+# Kind can be one of:
+# - breaking-change: a change to previously-documented behavior
+# - deprecation: functionality that is being removed in a later release
+# - bug-fix: fixes a problem in a previous version
+# - enhancement: extends functionality but does not break or fix existing behavior
+# - feature: new functionality
+# - known-issue: problems that we are aware of in a given version
+# - security: impacts on the security of a product or a user’s deployment.
+# - upgrade: important information for someone upgrading from a prior version
+# - other: does not fit into any of the other categories
+kind: enhancement
+
+# Change summary; a 80ish characters long description of the change.
+summary: Add version metadata to version command output
+
+# Long description; in case the summary is not enough to describe the change
+# this field accommodate a description without length limits.
+# NOTE: This field will be rendered only for breaking-change and known-issue kinds at the moment.
+description: |
+  Add commit, buildtime, and FIPS distribution indicators to output of version command.
+  Add fips-distribution attribute to initial startup log.
+
+# Affected component; usually one of "elastic-agent", "fleet-server", "filebeat", "metricbeat", "auditbeat", "all", etc.
+component: fleet-server
+
+# PR URL; optional; the PR number that added the changeset.
+# If not present is automatically filled by the tooling finding the PR where this changelog fragment has been added.
+# NOTE: the tooling supports backports, so it's able to fill the original PR number instead of the backport PR number.
+# Please provide it if you are adding a fragment for a different PR.
+pr: https://github.com/elastic/fleet-server/pull/4820
+
+# Issue URL; optional; the GitHub issue related to this changeset (either closes or is part of).
+# If not present is automatically filled by the tooling with the issue linked to the PR number.
+#issue: https://github.com/owner/repo/1234
diff --git a/cmd/fleet/main.go b/cmd/fleet/main.go
index b083463d47..bcf8281f5b 100644
--- a/cmd/fleet/main.go
+++ b/cmd/fleet/main.go
@@ -49,6 +49,7 @@ func initLogger(cfg *config.Config, version, commit string) (*logger.Logger, err
 	log.Info().
 		Str("version", version).
 		Str("commit", commit).
+		Bool("fips-distribution", build.FIPSDistribution).
 		Int("pid", os.Getpid()).
 		Int("ppid", os.Getppid()).
 		Str("exe", os.Args[0]).
@@ -140,7 +141,7 @@ func NewCommand(bi build.Info) *cobra.Command {
 		Use:     build.ServiceName,
 		Short:   "Fleet Server controls a fleet of Elastic Agents",
 		RunE:    getRunCommand(bi),
-		Version: bi.Version,
+		Version: bi.FullVersion(),
 	}
 	cmd.Flags().StringP("config", "c", "fleet-server.yml", "Configuration for Fleet Server")
 	cmd.Flags().Bool(kAgentMode, false, "Running under execution of the Elastic Agent")
diff --git a/internal/pkg/build/build.go b/internal/pkg/build/build.go
index b0d387950d..207e2db191 100644
--- a/internal/pkg/build/build.go
+++ b/internal/pkg/build/build.go
@@ -5,7 +5,10 @@
 // Package build contains build inforamtion that can be exposed during runtime.
 package build
 
-import "time"
+import (
+	"fmt"
+	"time"
+)
 
 const ServiceName = "fleet-server"
 
@@ -15,6 +18,10 @@ type Info struct {
 	BuildTime       time.Time
 }
 
+func (i Info) FullVersion() string {
+	return fmt.Sprintf("%s [%s built %s] (FIPS-distribution: %v)", i.Version, i.Commit, i.BuildTime, FIPSDistribution)
+}
+
 // Time parses the given string using RFC3339, or returns an empty time.Time.
 func Time(stime string) time.Time {
 	t, err := time.Parse(time.RFC3339, stime)
diff --git a/internal/pkg/build/fips.go b/internal/pkg/build/fips.go
new file mode 100644
index 0000000000..6fd8955c82
--- /dev/null
+++ b/internal/pkg/build/fips.go
@@ -0,0 +1,9 @@
+// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+// or more contributor license agreements. Licensed under the Elastic License;
+// you may not use this file except in compliance with the Elastic License.
+
+//go:build requirefips
+
+package build
+
+const FIPSDistribution = true
diff --git a/internal/pkg/build/nofips.go b/internal/pkg/build/nofips.go
new file mode 100644
index 0000000000..4032922a62
--- /dev/null
+++ b/internal/pkg/build/nofips.go
@@ -0,0 +1,9 @@
+// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+// or more contributor license agreements. Licensed under the Elastic License;
+// you may not use this file except in compliance with the Elastic License.
+
+//go:build !requirefips
+
+package build
+
+const FIPSDistribution = false


Reviews:
user: login: ycombinator
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-18T17:30:25Z
user: login: michel-laterman
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-21T18:01:59Z
user: login: ycombinator
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-04-24T15:26:26Z

Review comments:
diff_hunk: @@ -0,0 +1,34 @@
+# Kind can be one of:
path: changelog/fragments/1744831791-Add-version-metadata-to-version-command-output.yaml
user: login: ycombinator
body: Are we adding CHANGELOGs for FIPS work? See discussion in https://github.com/elastic/elastic-agent/pull/7862#discussion_r2045574930
created_at: 2025-04-18T17:30:25Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,34 @@
+# Kind can be one of:
path: changelog/fragments/1744831791-Add-version-metadata-to-version-command-output.yaml
user: login: michel-laterman
body: Normally no, but this adds the commit hash and buildtime to the version command as well
created_at: 2025-04-21T18:01:59Z
author_association: CONTRIBUTOR

PR comments:
user: login: elastic-sonarqube[bot]
created_at: 2025-04-16T20:06:59Z
body: ## [![Quality Gate passed](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v104/checks/QualityGateBadge/passed-16px.png 'Quality Gate passed')](https://sonar.elastic.dev/dashboard?id=elastic_fleet-server_AYpL8BsVaV3I-igkX4hx&pullRequest=4820) **Quality Gate passed**  
Issues  
[![](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v104/common/passed-16px.png '')](https://sonar.elastic.dev/project/issues?id=elastic_fleet-server_AYpL8BsVaV3I-igkX4hx&pullRequest=4820&resolved=false) [0 New issues](https://sonar.elastic.dev/project/issues?id=elastic_fleet-server_AYpL8BsVaV3I-igkX4hx&pullRequest=4820&resolved=false)  
[![](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v104/common/fixed-16px.png '')](https://sonar.elastic.dev/project/issues?id=elastic_fleet-server_AYpL8BsVaV3I-igkX4hx&fixedInPullRequest=4820) [0 Fixed issues](https://sonar.elastic.dev/project/issues?id=elastic_fleet-server_AYpL8BsVaV3I-igkX4hx&fixedInPullRequest=4820)  
[![](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v104/common/accepted-16px.png '')](https://sonar.elastic.dev/project/issues?id=elastic_fleet-server_AYpL8BsVaV3I-igkX4hx&pullRequest=4820&issueStatuses=ACCEPTED) [0 Accepted issues](https://sonar.elastic.dev/project/issues?id=elastic_fleet-server_AYpL8BsVaV3I-igkX4hx&pullRequest=4820&issueStatuses=ACCEPTED)

Measures  
[![](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v104/common/passed-16px.png '')](https://sonar.elastic.dev/security_hotspots?id=elastic_fleet-server_AYpL8BsVaV3I-igkX4hx&pullRequest=4820) [0 Security Hotspots](https://sonar.elastic.dev/security_hotspots?id=elastic_fleet-server_AYpL8BsVaV3I-igkX4hx&pullRequest=4820)  
[![](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v104/common/passed-16px.png '')](https://sonar.elastic.dev/component_measures?id=elastic_fleet-server_AYpL8BsVaV3I-igkX4hx&pullRequest=4820&metric=new_coverage&view=list) [100.0% Coverage on New Code](https://sonar.elastic.dev/component_measures?id=elastic_fleet-server_AYpL8BsVaV3I-igkX4hx&pullRequest=4820&metric=new_coverage&view=list)  
[![](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v104/common/passed-16px.png '')](https://sonar.elastic.dev/component_measures?id=elastic_fleet-server_AYpL8BsVaV3I-igkX4hx&pullRequest=4820&metric=new_duplicated_lines_density&view=list) [0.0% Duplication on New Code](https://sonar.elastic.dev/component_measures?id=elastic_fleet-server_AYpL8BsVaV3I-igkX4hx&pullRequest=4820&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarQube](https://sonar.elastic.dev/dashboard?id=elastic_fleet-server_AYpL8BsVaV3I-igkX4hx&pullRequest=4820)


author_association: NONE