diff --git a/.gitignore b/.gitignore index 8268cd13d..4b2a7be5b 100644 --- a/.gitignore +++ b/.gitignore @@ -89,3 +89,4 @@ docs/.vuepress/dist/ .service-accounts /bazel-* +internal/envoy/files/ diff --git a/Makefile b/Makefile index 4498dfa07..a99959fbc 100644 --- a/Makefile +++ b/Makefile @@ -24,8 +24,7 @@ CTIMEVAR=-X $(PKG)/internal/version.GitCommit=$(GITCOMMIT) \ -X $(PKG)/internal/version.Version=$(VERSION) \ -X $(PKG)/internal/version.BuildMeta=$(BUILDMETA) \ -X $(PKG)/internal/version.ProjectName=$(NAME) \ - -X $(PKG)/internal/version.ProjectURL=$(PKG) \ - -X $(PKG)/internal/envoy.Checksum=$$(cat ./bin/envoy.sha256 | tr -d '\n') + -X $(PKG)/internal/version.ProjectURL=$(PKG) GO ?= "go" GO_LDFLAGS=-ldflags "-s -w $(CTIMEVAR)" @@ -49,6 +48,7 @@ generate-mocks: ## Generate mocks .PHONY: build-lint deps-lint: ## Install lint dependencies @echo "==> $@" + ./scripts/get-envoy.bash @$(GO) install github.com/client9/misspell/cmd/misspell@${MISSPELL_VERSION} @$(GO) install github.com/golangci/golangci-lint/cmd/golangci-lint@${GOLANGCI_VERSION} diff --git a/cmd/pomerium-cli/version.go b/cmd/pomerium-cli/version.go index 1abe2d37b..d498911db 100644 --- a/cmd/pomerium-cli/version.go +++ b/cmd/pomerium-cli/version.go @@ -17,6 +17,6 @@ var versionCmd = &cobra.Command{ Short: "version", Long: `Print the cli version.`, Run: func(cmd *cobra.Command, args []string) { - fmt.Println(version.FullVersion()) + fmt.Println("pomerium:", version.FullVersion()) }, } diff --git a/cmd/pomerium/main.go b/cmd/pomerium/main.go index 97bbf7d95..32e823307 100644 --- a/cmd/pomerium/main.go +++ b/cmd/pomerium/main.go @@ -7,6 +7,7 @@ import ( "fmt" "github.com/pomerium/pomerium/internal/cmd/pomerium" + "github.com/pomerium/pomerium/internal/envoy/files" "github.com/pomerium/pomerium/internal/log" "github.com/pomerium/pomerium/internal/version" ) @@ -17,6 +18,13 @@ var ( ) func main() { + flag.Parse() + if *versionFlag { + fmt.Println("pomerium:", version.FullVersion()) + fmt.Println("envoy:", files.FullVersion()) + return + } + ctx := context.Background() if err := run(ctx); !errors.Is(err, context.Canceled) { log.Fatal().Err(err).Msg("cmd/pomerium") @@ -25,10 +33,5 @@ func main() { } func run(ctx context.Context) error { - flag.Parse() - if *versionFlag { - fmt.Println(version.FullVersion()) - return nil - } return pomerium.Run(ctx, *configFile) } diff --git a/databroker/cache.go b/databroker/cache.go index 883eff7eb..6d22deb2f 100644 --- a/databroker/cache.go +++ b/databroker/cache.go @@ -15,6 +15,7 @@ import ( "github.com/pomerium/pomerium/config" "github.com/pomerium/pomerium/internal/directory" + "github.com/pomerium/pomerium/internal/envoy/files" "github.com/pomerium/pomerium/internal/identity" "github.com/pomerium/pomerium/internal/identity/manager" "github.com/pomerium/pomerium/internal/log" @@ -52,7 +53,10 @@ func New(cfg *config.Config) (*DataBroker, error) { sharedKey, _ := cfg.Options.GetSharedKey() ui, si := grpcutil.AttachMetadataInterceptors( - metadata.Pairs(grpcutil.MetadataKeyPomeriumVersion, version.FullVersion()), + metadata.Pairs( + grpcutil.MetadataKeyEnvoyVersion, files.FullVersion(), + grpcutil.MetadataKeyPomeriumVersion, version.FullVersion(), + ), ) // No metrics handler because we have one in the control plane. Add one diff --git a/internal/cmd/pomerium/pomerium.go b/internal/cmd/pomerium/pomerium.go index 36776c002..0b804d451 100644 --- a/internal/cmd/pomerium/pomerium.go +++ b/internal/cmd/pomerium/pomerium.go @@ -23,6 +23,7 @@ import ( "github.com/pomerium/pomerium/internal/controlplane" "github.com/pomerium/pomerium/internal/databroker" "github.com/pomerium/pomerium/internal/envoy" + "github.com/pomerium/pomerium/internal/envoy/files" "github.com/pomerium/pomerium/internal/log" "github.com/pomerium/pomerium/internal/registry" "github.com/pomerium/pomerium/internal/urlutil" @@ -32,7 +33,10 @@ import ( // Run runs the main pomerium application. func Run(ctx context.Context, configFile string) error { - log.Info(ctx).Str("version", version.FullVersion()).Msg("cmd/pomerium") + log.Info(ctx). + Str("envoy_version", files.FullVersion()). + Str("version", version.FullVersion()). + Msg("cmd/pomerium") var src config.Source diff --git a/internal/controlplane/server.go b/internal/controlplane/server.go index 2514fa7a3..d3bc04fc4 100644 --- a/internal/controlplane/server.go +++ b/internal/controlplane/server.go @@ -20,6 +20,7 @@ import ( "github.com/pomerium/pomerium/config/envoyconfig" "github.com/pomerium/pomerium/config/envoyconfig/filemgr" "github.com/pomerium/pomerium/internal/controlplane/xdsmgr" + "github.com/pomerium/pomerium/internal/envoy/files" "github.com/pomerium/pomerium/internal/httputil/reproxy" "github.com/pomerium/pomerium/internal/log" "github.com/pomerium/pomerium/internal/telemetry" @@ -85,7 +86,10 @@ func NewServer(name string, metricsMgr *config.MetricsManager) (*Server, error) return nil, err } ui, si := grpcutil.AttachMetadataInterceptors( - metadata.Pairs(grpcutil.MetadataKeyPomeriumVersion, version.FullVersion()), + metadata.Pairs( + grpcutil.MetadataKeyEnvoyVersion, files.FullVersion(), + grpcutil.MetadataKeyPomeriumVersion, version.FullVersion(), + ), ) srv.GRPCServer = grpc.NewServer( grpc.StatsHandler(telemetry.NewGRPCServerStatsHandler(name)), diff --git a/internal/envoy/embed.go b/internal/envoy/embed.go index 07e05eef4..b085dd210 100644 --- a/internal/envoy/embed.go +++ b/internal/envoy/embed.go @@ -13,8 +13,10 @@ import ( "github.com/pomerium/pomerium/internal/log" ) -const embeddedEnvoyPermissions fs.FileMode = 0o700 -const embeddedDirectoryPermissions fs.FileMode = 0o755 +const ( + embeddedEnvoyPermissions fs.FileMode = 0o700 + embeddedDirectoryPermissions fs.FileMode = 0o755 +) var embeddedFilesBaseDirectory = filepath.Join(os.TempDir(), "pomerium-embedded-files") diff --git a/internal/envoy/envoy.go b/internal/envoy/envoy.go index d924f7875..adebe505a 100644 --- a/internal/envoy/envoy.go +++ b/internal/envoy/envoy.go @@ -30,6 +30,8 @@ import ( "github.com/shirou/gopsutil/v3/process" "google.golang.org/protobuf/encoding/protojson" + "github.com/pomerium/pomerium/internal/envoy/files" + "github.com/pomerium/pomerium/config" "github.com/pomerium/pomerium/config/envoyconfig" "github.com/pomerium/pomerium/internal/log" @@ -40,9 +42,6 @@ const ( configFileName = "envoy-config.yaml" ) -// Checksum is the embedded envoy binary checksum. This value is populated by `make build`. -var Checksum string - type serverOptions struct { services string logLevel string @@ -83,7 +82,7 @@ func NewServer(ctx context.Context, src config.Source, grpcPort, httpPort string } // Checksum is written at build time, if it's not empty we verify the binary - if Checksum != "" { + if files.Checksum() != "" { bs, err := ioutil.ReadFile(fullEnvoyPath) if err != nil { return nil, fmt.Errorf("error reading envoy binary for checksum verification: %w", err) @@ -91,8 +90,8 @@ func NewServer(ctx context.Context, src config.Source, grpcPort, httpPort string h := sha256.New() h.Write(bs) s := hex.EncodeToString(h.Sum(nil)) - if Checksum != s { - return nil, fmt.Errorf("invalid envoy binary, expected %s but got %s", Checksum, s) + if files.Checksum() != s { + return nil, fmt.Errorf("invalid envoy binary, expected %s but got %s", files.Checksum(), s) } } else { log.Info(ctx).Msg("no checksum defined, envoy binary will not be verified!") @@ -114,7 +113,7 @@ func NewServer(ctx context.Context, src config.Source, grpcPort, httpPort string log.Info(ctx). Str("path", envoyPath). - Str("checksum", Checksum). + Str("checksum", files.Checksum()). Msg("running envoy") return srv, nil diff --git a/internal/envoy/files/files.go b/internal/envoy/files/files.go new file mode 100644 index 000000000..b89c18fc5 --- /dev/null +++ b/internal/envoy/files/files.go @@ -0,0 +1,28 @@ +// Package files contains files for use with envoy. +package files + +import ( + _ "embed" // for embedded files + "strings" +) + +//go:embed envoy.sha256 +var rawChecksum string + +//go:embed envoy.version +var rawVersion string + +// Checksum returns the checksum for the embedded envoy binary. +func Checksum() string { + return strings.Fields(rawChecksum)[0] +} + +// FullVersion returns the full version string for envoy. +func FullVersion() string { + return Version() + "+" + Checksum() +} + +// Version returns the envoy version. +func Version() string { + return strings.TrimSpace(rawVersion) +} diff --git a/internal/telemetry/metrics/info_test.go b/internal/telemetry/metrics/info_test.go index be5ff12ff..b39b92ff1 100644 --- a/internal/telemetry/metrics/info_test.go +++ b/internal/telemetry/metrics/info_test.go @@ -6,6 +6,7 @@ import ( "runtime" "testing" + "github.com/pomerium/pomerium/internal/envoy/files" "github.com/pomerium/pomerium/internal/version" "github.com/pomerium/pomerium/pkg/metrics" @@ -63,6 +64,7 @@ func Test_SetDBConfigInfo(t *testing.T) { }) } } + func Test_SetBuildInfo(t *testing.T) { registry = newMetricRegistry() @@ -72,6 +74,7 @@ func Test_SetBuildInfo(t *testing.T) { wantLabels := []metricdata.LabelValue{ {Value: "test_service", Present: true}, {Value: version.FullVersion(), Present: true}, + {Value: files.FullVersion(), Present: true}, {Value: version.GitCommit, Present: true}, {Value: runtime.Version(), Present: true}, {Value: "test_host", Present: true}, diff --git a/internal/telemetry/metrics/registry.go b/internal/telemetry/metrics/registry.go index 7aa0cbc8b..ce1c1e603 100644 --- a/internal/telemetry/metrics/registry.go +++ b/internal/telemetry/metrics/registry.go @@ -8,6 +8,8 @@ import ( "go.opencensus.io/metric" "go.opencensus.io/metric/metricdata" + "github.com/pomerium/pomerium/internal/envoy/files" + "github.com/pomerium/pomerium/internal/log" "github.com/pomerium/pomerium/internal/version" "github.com/pomerium/pomerium/pkg/metrics" @@ -45,6 +47,7 @@ func (r *metricRegistry) init() { metric.WithLabelKeys( metrics.ServiceLabel, metrics.VersionLabel, + metrics.EnvoyVersionLabel, metrics.RevisionLabel, metrics.GoVersionLabel, metrics.HostLabel, @@ -86,6 +89,7 @@ func (r *metricRegistry) setBuildInfo(service, hostname string) { m, err := registry.buildInfo.GetEntry( metricdata.NewLabelValue(service), metricdata.NewLabelValue(version.FullVersion()), + metricdata.NewLabelValue(files.FullVersion()), metricdata.NewLabelValue(version.GitCommit), metricdata.NewLabelValue((runtime.Version())), metricdata.NewLabelValue(hostname), diff --git a/pkg/grpcutil/version.go b/pkg/grpcutil/version.go index 1adc65c08..9da403a04 100644 --- a/pkg/grpcutil/version.go +++ b/pkg/grpcutil/version.go @@ -7,6 +7,9 @@ import ( "google.golang.org/grpc/metadata" ) +// MetadataKeyEnvoyVersion is the gRPC metadata key used for the envoy version. +const MetadataKeyEnvoyVersion = "x-envoy-version" + // MetadataKeyPomeriumVersion is the gRPC metadata key used for the pomerium version. const MetadataKeyPomeriumVersion = "x-pomerium-version" diff --git a/pkg/metrics/constants.go b/pkg/metrics/constants.go index 17ab6f63e..ecc651ee8 100644 --- a/pkg/metrics/constants.go +++ b/pkg/metrics/constants.go @@ -36,6 +36,7 @@ const ( ServiceLabel = "service" ConfigLabel = "config" VersionLabel = "version" + EnvoyVersionLabel = "envoy_version" RevisionLabel = "revision" GoVersionLabel = "goversion" HostLabel = "host" diff --git a/scripts/get-envoy.bash b/scripts/get-envoy.bash index d593c8ea7..5e727f24b 100755 --- a/scripts/get-envoy.bash +++ b/scripts/get-envoy.bash @@ -4,8 +4,9 @@ set -euo pipefail PATH="$PATH:$(go env GOPATH)/bin" export PATH +_project_root="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)/.." _envoy_version=1.17.3 -_dir="${DIR:-"$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)/../bin"}" +_dir="${DIR:-"$_project_root/bin"}" _target="${TARGET:-"$(go env GOOS)-$(go env GOARCH)"}" # until m1 macs are supported, fallback to x86 and use rosetta @@ -13,35 +14,33 @@ if [ "$_target" == "darwin-arm64" ]; then _target="darwin-amd64" fi -is_command() { - command -v "$1" >/dev/null -} +_url="https://github.com/pomerium/envoy-binaries/releases/download/v${_envoy_version}/envoy-${_target}" -hash_sha256() { - TARGET=${1:-/dev/stdin} - if is_command gsha256sum; then - hash=$(gsha256sum "$TARGET") || return 1 - echo "$hash" | cut -d ' ' -f 1 - elif is_command sha256sum; then - hash=$(sha256sum "$TARGET") || return 1 - echo "$hash" | cut -d ' ' -f 1 - elif is_command shasum; then - hash=$(shasum -a 256 "$TARGET" 2>/dev/null) || return 1 - echo "$hash" | cut -d ' ' -f 1 - elif is_command openssl; then - hash=$(openssl -dst openssl dgst -sha256 "$TARGET") || return 1 - echo "$hash" | cut -d ' ' -f a - else - echo "hash_sha256 unable to find command to compute sha-256 hash" - return 1 - fi -} +# create the directory if it doesn't exist +mkdir -p "$_dir" -if [ -f "$_dir/envoy" ]; then - exit 0 +# download the shasum of the binary +curl \ + --compressed \ + --silent \ + --location \ + --output "$_dir/envoy-$_target.sha256" \ + "$_url.sha256" + +# if the shasum doesn't match (or the binary doesn't exist), re-download +if ! (cd "$_dir" && shasum -c "envoy-$_target.sha256" >/dev/null 2>&1) ; then + curl \ + --compressed \ + --silent \ + --location \ + --output "$_dir/envoy-$_target" \ + "$_url" fi -mkdir -p "$_dir" -curl -L --compressed -o "$_dir/envoy" "https://github.com/pomerium/envoy-binaries/releases/download/v${_envoy_version}/envoy-${_target}" +# save the bare name +cp -f "$_dir/envoy-$_target" "$_dir/envoy" +cp -f "$_dir/envoy-$_target.sha256" "$_dir/envoy.sha256" -hash_sha256 "$_dir/envoy" >"$_dir/envoy.sha256" +# save to the embedded files in the envoy package +cp -f "$_dir/envoy-$_target.sha256" "$_project_root/internal/envoy/files/envoy.sha256" +echo "$_envoy_version" > "$_project_root/internal/envoy/files/envoy.version"