mirror of
https://github.com/pomerium/pomerium.git
synced 2025-08-06 10:21:05 +02:00
use dependency injection for embedded envoy provider
This commit is contained in:
parent
e09217ece5
commit
5c08990501
14 changed files with 136 additions and 123 deletions
|
@ -21,7 +21,7 @@ func main() {
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
if *versionFlag {
|
if *versionFlag {
|
||||||
fmt.Println("pomerium:", version.FullVersion())
|
fmt.Println("pomerium:", version.FullVersion())
|
||||||
fmt.Println("envoy:", files.FullVersion())
|
fmt.Println("envoy:", files.EmbeddedEnvoyProvider.Version()+"+"+files.EmbeddedEnvoyProvider.Checksum())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,5 +33,5 @@ func main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func run(ctx context.Context) error {
|
func run(ctx context.Context) error {
|
||||||
return pomerium.Run(ctx, *configFile)
|
return pomerium.Run(ctx, *configFile, files.EmbeddedEnvoyProvider)
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,14 +22,16 @@ type MetricsManager struct {
|
||||||
addr string
|
addr string
|
||||||
basicAuth string
|
basicAuth string
|
||||||
handler http.Handler
|
handler http.Handler
|
||||||
|
envoyVersion string
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewMetricsManager creates a new MetricsManager.
|
// NewMetricsManager creates a new MetricsManager.
|
||||||
func NewMetricsManager(ctx context.Context, src Source) *MetricsManager {
|
func NewMetricsManager(ctx context.Context, src Source, envoyVersion string) *MetricsManager {
|
||||||
ctx = log.WithContext(ctx, func(c zerolog.Context) zerolog.Context {
|
ctx = log.WithContext(ctx, func(c zerolog.Context) zerolog.Context {
|
||||||
return c.Str("service", "metrics_manager")
|
return c.Str("service", "metrics_manager")
|
||||||
})
|
})
|
||||||
mgr := &MetricsManager{}
|
mgr := &MetricsManager{}
|
||||||
|
mgr.envoyVersion = envoyVersion
|
||||||
metrics.RegisterInfoMetrics()
|
metrics.RegisterInfoMetrics()
|
||||||
src.OnConfigChange(ctx, mgr.OnConfigChange)
|
src.OnConfigChange(ctx, mgr.OnConfigChange)
|
||||||
mgr.OnConfigChange(ctx, src.GetConfig())
|
mgr.OnConfigChange(ctx, src.GetConfig())
|
||||||
|
@ -73,7 +75,7 @@ func (mgr *MetricsManager) updateInfo(cfg *Config) {
|
||||||
hostname = "__unknown__"
|
hostname = "__unknown__"
|
||||||
}
|
}
|
||||||
|
|
||||||
metrics.SetBuildInfo(serviceName, hostname)
|
metrics.SetBuildInfo(serviceName, hostname, mgr.envoyVersion)
|
||||||
mgr.serviceName = serviceName
|
mgr.serviceName = serviceName
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@ func TestMetricsManager(t *testing.T) {
|
||||||
MetricsAddr: "ADDRESS",
|
MetricsAddr: "ADDRESS",
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
mgr := NewMetricsManager(ctx, src)
|
mgr := NewMetricsManager(ctx, src, "v1.2.3")
|
||||||
srv1 := httptest.NewServer(mgr)
|
srv1 := httptest.NewServer(mgr)
|
||||||
defer srv1.Close()
|
defer srv1.Close()
|
||||||
srv2 := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
srv2 := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
@ -44,7 +44,7 @@ func TestMetricsManagerBasicAuth(t *testing.T) {
|
||||||
MetricsBasicAuth: base64.StdEncoding.EncodeToString([]byte("x:y")),
|
MetricsBasicAuth: base64.StdEncoding.EncodeToString([]byte("x:y")),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
mgr := NewMetricsManager(context.Background(), src)
|
mgr := NewMetricsManager(context.Background(), src, "v1.2.3")
|
||||||
srv1 := httptest.NewServer(mgr)
|
srv1 := httptest.NewServer(mgr)
|
||||||
defer srv1.Close()
|
defer srv1.Close()
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,6 @@ import (
|
||||||
|
|
||||||
"github.com/pomerium/pomerium/config"
|
"github.com/pomerium/pomerium/config"
|
||||||
"github.com/pomerium/pomerium/internal/directory"
|
"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"
|
||||||
"github.com/pomerium/pomerium/internal/identity/manager"
|
"github.com/pomerium/pomerium/internal/identity/manager"
|
||||||
"github.com/pomerium/pomerium/internal/log"
|
"github.com/pomerium/pomerium/internal/log"
|
||||||
|
@ -44,7 +43,7 @@ type DataBroker struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// New creates a new databroker service.
|
// New creates a new databroker service.
|
||||||
func New(cfg *config.Config) (*DataBroker, error) {
|
func New(cfg *config.Config, envoyVersion string) (*DataBroker, error) {
|
||||||
localListener, err := net.Listen("tcp", "127.0.0.1:0")
|
localListener, err := net.Listen("tcp", "127.0.0.1:0")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -54,7 +53,7 @@ func New(cfg *config.Config) (*DataBroker, error) {
|
||||||
|
|
||||||
ui, si := grpcutil.AttachMetadataInterceptors(
|
ui, si := grpcutil.AttachMetadataInterceptors(
|
||||||
metadata.Pairs(
|
metadata.Pairs(
|
||||||
grpcutil.MetadataKeyEnvoyVersion, files.FullVersion(),
|
grpcutil.MetadataKeyEnvoyVersion, envoyVersion,
|
||||||
grpcutil.MetadataKeyPomeriumVersion, version.FullVersion(),
|
grpcutil.MetadataKeyPomeriumVersion, version.FullVersion(),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
|
@ -29,7 +29,7 @@ func TestNew(t *testing.T) {
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
tt.opts.Provider = "google"
|
tt.opts.Provider = "google"
|
||||||
_, err := New(&config.Config{Options: &tt.opts})
|
_, err := New(&config.Config{Options: &tt.opts}, "v1.2.3")
|
||||||
if (err != nil) != tt.wantErr {
|
if (err != nil) != tt.wantErr {
|
||||||
t.Errorf("New() error = %v, wantErr %v", err, tt.wantErr)
|
t.Errorf("New() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
return
|
return
|
||||||
|
|
|
@ -23,7 +23,6 @@ import (
|
||||||
"github.com/pomerium/pomerium/internal/controlplane"
|
"github.com/pomerium/pomerium/internal/controlplane"
|
||||||
"github.com/pomerium/pomerium/internal/databroker"
|
"github.com/pomerium/pomerium/internal/databroker"
|
||||||
"github.com/pomerium/pomerium/internal/envoy"
|
"github.com/pomerium/pomerium/internal/envoy"
|
||||||
"github.com/pomerium/pomerium/internal/envoy/files"
|
|
||||||
"github.com/pomerium/pomerium/internal/log"
|
"github.com/pomerium/pomerium/internal/log"
|
||||||
"github.com/pomerium/pomerium/internal/registry"
|
"github.com/pomerium/pomerium/internal/registry"
|
||||||
"github.com/pomerium/pomerium/internal/urlutil"
|
"github.com/pomerium/pomerium/internal/urlutil"
|
||||||
|
@ -32,9 +31,11 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// Run runs the main pomerium application.
|
// Run runs the main pomerium application.
|
||||||
func Run(ctx context.Context, configFile string) error {
|
func Run(ctx context.Context, configFile string, embeddedEnvoyProvider envoy.EmbeddedEnvoyProvider) error {
|
||||||
|
envoyVersion := embeddedEnvoyProvider.Version() + "+" + embeddedEnvoyProvider.Checksum()
|
||||||
|
|
||||||
log.Info(ctx).
|
log.Info(ctx).
|
||||||
Str("envoy_version", files.FullVersion()).
|
Str("envoy_version", envoyVersion).
|
||||||
Str("version", version.FullVersion()).
|
Str("version", version.FullVersion()).
|
||||||
Msg("cmd/pomerium")
|
Msg("cmd/pomerium")
|
||||||
|
|
||||||
|
@ -60,13 +61,13 @@ func Run(ctx context.Context, configFile string) error {
|
||||||
// override the default http transport so we can use the custom CA in the TLS client config (#1570)
|
// override the default http transport so we can use the custom CA in the TLS client config (#1570)
|
||||||
http.DefaultTransport = config.NewHTTPTransport(src)
|
http.DefaultTransport = config.NewHTTPTransport(src)
|
||||||
|
|
||||||
metricsMgr := config.NewMetricsManager(ctx, src)
|
metricsMgr := config.NewMetricsManager(ctx, src, envoyVersion)
|
||||||
defer metricsMgr.Close()
|
defer metricsMgr.Close()
|
||||||
traceMgr := config.NewTraceManager(ctx, src)
|
traceMgr := config.NewTraceManager(ctx, src)
|
||||||
defer traceMgr.Close()
|
defer traceMgr.Close()
|
||||||
|
|
||||||
// setup the control plane
|
// setup the control plane
|
||||||
controlPlane, err := controlplane.NewServer(src.GetConfig().Options.Services, metricsMgr)
|
controlPlane, err := controlplane.NewServer(src.GetConfig().Options.Services, metricsMgr, envoyVersion)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("error creating control plane: %w", err)
|
return fmt.Errorf("error creating control plane: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -90,7 +91,7 @@ func Run(ctx context.Context, configFile string) error {
|
||||||
log.Info(ctx).Str("port", httpPort).Msg("HTTP server started")
|
log.Info(ctx).Str("port", httpPort).Msg("HTTP server started")
|
||||||
|
|
||||||
// create envoy server
|
// create envoy server
|
||||||
envoyServer, err := envoy.NewServer(ctx, src, grpcPort, httpPort, controlPlane.Builder)
|
envoyServer, err := envoy.NewServer(ctx, src, grpcPort, httpPort, controlPlane.Builder, embeddedEnvoyProvider)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("error creating envoy server: %w", err)
|
return fmt.Errorf("error creating envoy server: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -109,7 +110,7 @@ func Run(ctx context.Context, configFile string) error {
|
||||||
}
|
}
|
||||||
var dataBrokerServer *databroker_service.DataBroker
|
var dataBrokerServer *databroker_service.DataBroker
|
||||||
if config.IsDataBroker(src.GetConfig().Options.Services) {
|
if config.IsDataBroker(src.GetConfig().Options.Services) {
|
||||||
dataBrokerServer, err = setupDataBroker(ctx, src, controlPlane)
|
dataBrokerServer, err = setupDataBroker(ctx, src, controlPlane, envoyVersion)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("setting up databroker: %w", err)
|
return fmt.Errorf("setting up databroker: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -200,8 +201,8 @@ func setupAuthorize(ctx context.Context, src config.Source, controlPlane *contro
|
||||||
return svc, nil
|
return svc, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func setupDataBroker(ctx context.Context, src config.Source, controlPlane *controlplane.Server) (*databroker_service.DataBroker, error) {
|
func setupDataBroker(ctx context.Context, src config.Source, controlPlane *controlplane.Server, envoyVersion string) (*databroker_service.DataBroker, error) {
|
||||||
svc, err := databroker_service.New(src.GetConfig())
|
svc, err := databroker_service.New(src.GetConfig(), envoyVersion)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error creating databroker service: %w", err)
|
return nil, fmt.Errorf("error creating databroker service: %w", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,20 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type mockEmbeddedEnvoyProvider struct{}
|
||||||
|
|
||||||
|
func (mockEmbeddedEnvoyProvider) Checksum() string {
|
||||||
|
return "CHECKSUM"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mockEmbeddedEnvoyProvider) Extract(ctx context.Context) (string, error) {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mockEmbeddedEnvoyProvider) Version() string {
|
||||||
|
return "VERSION"
|
||||||
|
}
|
||||||
|
|
||||||
func Test_run(t *testing.T) {
|
func Test_run(t *testing.T) {
|
||||||
os.Clearenv()
|
os.Clearenv()
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
|
@ -127,7 +141,7 @@ func Test_run(t *testing.T) {
|
||||||
ctx, clearTimeout := context.WithTimeout(context.Background(), 500*time.Millisecond)
|
ctx, clearTimeout := context.WithTimeout(context.Background(), 500*time.Millisecond)
|
||||||
defer clearTimeout()
|
defer clearTimeout()
|
||||||
|
|
||||||
err = Run(ctx, configFile)
|
err = Run(ctx, configFile, mockEmbeddedEnvoyProvider{})
|
||||||
if (err != nil) != tt.wantErr {
|
if (err != nil) != tt.wantErr {
|
||||||
t.Errorf("run() error = %v, wantErr %v", err, tt.wantErr)
|
t.Errorf("run() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,6 @@ import (
|
||||||
"github.com/pomerium/pomerium/config/envoyconfig"
|
"github.com/pomerium/pomerium/config/envoyconfig"
|
||||||
"github.com/pomerium/pomerium/config/envoyconfig/filemgr"
|
"github.com/pomerium/pomerium/config/envoyconfig/filemgr"
|
||||||
"github.com/pomerium/pomerium/internal/controlplane/xdsmgr"
|
"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/httputil/reproxy"
|
||||||
"github.com/pomerium/pomerium/internal/log"
|
"github.com/pomerium/pomerium/internal/log"
|
||||||
"github.com/pomerium/pomerium/internal/telemetry"
|
"github.com/pomerium/pomerium/internal/telemetry"
|
||||||
|
@ -68,7 +67,7 @@ type Server struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewServer creates a new Server. Listener ports are chosen by the OS.
|
// NewServer creates a new Server. Listener ports are chosen by the OS.
|
||||||
func NewServer(name string, metricsMgr *config.MetricsManager) (*Server, error) {
|
func NewServer(name string, metricsMgr *config.MetricsManager, envoyVersion string) (*Server, error) {
|
||||||
srv := &Server{
|
srv := &Server{
|
||||||
metricsMgr: metricsMgr,
|
metricsMgr: metricsMgr,
|
||||||
reproxy: reproxy.New(),
|
reproxy: reproxy.New(),
|
||||||
|
@ -87,7 +86,7 @@ func NewServer(name string, metricsMgr *config.MetricsManager) (*Server, error)
|
||||||
}
|
}
|
||||||
ui, si := grpcutil.AttachMetadataInterceptors(
|
ui, si := grpcutil.AttachMetadataInterceptors(
|
||||||
metadata.Pairs(
|
metadata.Pairs(
|
||||||
grpcutil.MetadataKeyEnvoyVersion, files.FullVersion(),
|
grpcutil.MetadataKeyEnvoyVersion, envoyVersion,
|
||||||
grpcutil.MetadataKeyPomeriumVersion, version.FullVersion(),
|
grpcutil.MetadataKeyPomeriumVersion, version.FullVersion(),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,68 +0,0 @@
|
||||||
package envoy
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"io/fs"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"sync"
|
|
||||||
|
|
||||||
"github.com/natefinch/atomic"
|
|
||||||
|
|
||||||
"github.com/pomerium/pomerium/internal/envoy/files"
|
|
||||||
"github.com/pomerium/pomerium/internal/log"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
embeddedEnvoyPermissions fs.FileMode = 0o700
|
|
||||||
embeddedDirectoryPermissions fs.FileMode = 0o755
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
embeddedFilesBaseDirectory = filepath.Join(os.TempDir(), "pomerium-embedded-files")
|
|
||||||
extractEmbeddedEnvoyOnce sync.Once
|
|
||||||
)
|
|
||||||
|
|
||||||
func extractEmbeddedEnvoy(ctx context.Context) (outPath string, err error) {
|
|
||||||
extractEmbeddedEnvoyOnce.Do(func() {
|
|
||||||
// clean up our base directory before starting
|
|
||||||
err = os.RemoveAll(embeddedFilesBaseDirectory)
|
|
||||||
if err != nil {
|
|
||||||
err = fmt.Errorf("error cleaning embedded file directory: (directory=%s): %w", embeddedFilesBaseDirectory, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// create known directory base to clean at startup
|
|
||||||
err = os.MkdirAll(embeddedFilesBaseDirectory, embeddedDirectoryPermissions)
|
|
||||||
if err != nil {
|
|
||||||
err = fmt.Errorf("error creating embedded file directory: (directory=%s): %w", embeddedFilesBaseDirectory, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// build a random temp directory inside our base directory to guarantee permissions
|
|
||||||
var tmpDir string
|
|
||||||
tmpDir, err = os.MkdirTemp(embeddedFilesBaseDirectory, "envoy-")
|
|
||||||
if err != nil {
|
|
||||||
err = fmt.Errorf("error creating embedded file tmp directory: (directory=%s): %w", embeddedFilesBaseDirectory, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
outPath = filepath.Join(tmpDir, "envoy")
|
|
||||||
|
|
||||||
log.Info(ctx).Str("path", outPath).Msg("extracting envoy binary")
|
|
||||||
err = atomic.WriteFile(outPath, bytes.NewReader(files.Binary()))
|
|
||||||
if err != nil {
|
|
||||||
err = fmt.Errorf("error extracting embedded envoy binary to temporary directory (path=%s): %w", outPath, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
err = os.Chmod(outPath, embeddedEnvoyPermissions)
|
|
||||||
if err != nil {
|
|
||||||
err = fmt.Errorf("error chmoding embedded envoy binary: %w", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return outPath, err
|
|
||||||
}
|
|
|
@ -30,16 +30,15 @@ import (
|
||||||
"github.com/shirou/gopsutil/v3/process"
|
"github.com/shirou/gopsutil/v3/process"
|
||||||
"google.golang.org/protobuf/encoding/protojson"
|
"google.golang.org/protobuf/encoding/protojson"
|
||||||
|
|
||||||
"github.com/pomerium/pomerium/internal/envoy/files"
|
|
||||||
|
|
||||||
"github.com/pomerium/pomerium/config"
|
"github.com/pomerium/pomerium/config"
|
||||||
"github.com/pomerium/pomerium/config/envoyconfig"
|
"github.com/pomerium/pomerium/config/envoyconfig"
|
||||||
"github.com/pomerium/pomerium/internal/log"
|
"github.com/pomerium/pomerium/internal/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
workingDirectoryName = ".pomerium-envoy"
|
workingDirectoryName = ".pomerium-envoy"
|
||||||
configFileName = "envoy-config.yaml"
|
workingDirectoryPermissions = 0o755
|
||||||
|
configFileName = "envoy-config.yaml"
|
||||||
)
|
)
|
||||||
|
|
||||||
type serverOptions struct {
|
type serverOptions struct {
|
||||||
|
@ -47,6 +46,13 @@ type serverOptions struct {
|
||||||
logLevel string
|
logLevel string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// An EmbeddedEnvoyProvider provides an implementation of an embedded envoy.
|
||||||
|
type EmbeddedEnvoyProvider interface {
|
||||||
|
Checksum() string
|
||||||
|
Extract(ctx context.Context) (outPath string, err error)
|
||||||
|
Version() string
|
||||||
|
}
|
||||||
|
|
||||||
// A Server is a pomerium proxy implemented via envoy.
|
// A Server is a pomerium proxy implemented via envoy.
|
||||||
type Server struct {
|
type Server struct {
|
||||||
wd string
|
wd string
|
||||||
|
@ -63,14 +69,19 @@ type Server struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewServer creates a new server with traffic routed by envoy.
|
// NewServer creates a new server with traffic routed by envoy.
|
||||||
func NewServer(ctx context.Context, src config.Source, grpcPort, httpPort string, builder *envoyconfig.Builder) (*Server, error) {
|
func NewServer(ctx context.Context,
|
||||||
|
src config.Source,
|
||||||
|
grpcPort, httpPort string,
|
||||||
|
builder *envoyconfig.Builder,
|
||||||
|
embeddedEnvoyProvider EmbeddedEnvoyProvider,
|
||||||
|
) (*Server, error) {
|
||||||
wd := filepath.Join(os.TempDir(), workingDirectoryName)
|
wd := filepath.Join(os.TempDir(), workingDirectoryName)
|
||||||
err := os.MkdirAll(wd, embeddedEnvoyPermissions)
|
err := os.MkdirAll(wd, workingDirectoryPermissions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error creating temporary working directory for envoy: %w", err)
|
return nil, fmt.Errorf("error creating temporary working directory for envoy: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
envoyPath, err := extractEmbeddedEnvoy(ctx)
|
envoyPath, err := embeddedEnvoyProvider.Extract(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warn(ctx).Err(err).Send()
|
log.Warn(ctx).Err(err).Send()
|
||||||
envoyPath = "envoy"
|
envoyPath = "envoy"
|
||||||
|
@ -82,7 +93,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
|
// Checksum is written at build time, if it's not empty we verify the binary
|
||||||
if files.Checksum() != "" {
|
if embeddedEnvoyProvider.Checksum() != "" {
|
||||||
bs, err := ioutil.ReadFile(fullEnvoyPath)
|
bs, err := ioutil.ReadFile(fullEnvoyPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error reading envoy binary for checksum verification: %w", err)
|
return nil, fmt.Errorf("error reading envoy binary for checksum verification: %w", err)
|
||||||
|
@ -90,8 +101,8 @@ func NewServer(ctx context.Context, src config.Source, grpcPort, httpPort string
|
||||||
h := sha256.New()
|
h := sha256.New()
|
||||||
h.Write(bs)
|
h.Write(bs)
|
||||||
s := hex.EncodeToString(h.Sum(nil))
|
s := hex.EncodeToString(h.Sum(nil))
|
||||||
if files.Checksum() != s {
|
if embeddedEnvoyProvider.Checksum() != s {
|
||||||
return nil, fmt.Errorf("invalid envoy binary, expected %s but got %s", files.Checksum(), s)
|
return nil, fmt.Errorf("invalid envoy binary, expected %s but got %s", embeddedEnvoyProvider.Checksum(), s)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log.Info(ctx).Msg("no checksum defined, envoy binary will not be verified!")
|
log.Info(ctx).Msg("no checksum defined, envoy binary will not be verified!")
|
||||||
|
@ -113,7 +124,7 @@ func NewServer(ctx context.Context, src config.Source, grpcPort, httpPort string
|
||||||
|
|
||||||
log.Info(ctx).
|
log.Info(ctx).
|
||||||
Str("path", envoyPath).
|
Str("path", envoyPath).
|
||||||
Str("checksum", files.Checksum()).
|
Str("checksum", embeddedEnvoyProvider.Checksum()).
|
||||||
Msg("running envoy")
|
Msg("running envoy")
|
||||||
|
|
||||||
return srv, nil
|
return srv, nil
|
||||||
|
|
|
@ -2,26 +2,85 @@
|
||||||
package files
|
package files
|
||||||
|
|
||||||
import (
|
import (
|
||||||
_ "embed" // for embedded files
|
"bytes"
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"io/fs"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/natefinch/atomic"
|
||||||
|
|
||||||
|
"github.com/pomerium/pomerium/internal/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Binary returns the raw envoy binary bytes.
|
const (
|
||||||
func Binary() []byte {
|
embeddedEnvoyPermissions fs.FileMode = 0o700
|
||||||
return rawBinary
|
embeddedDirectoryPermissions fs.FileMode = 0o755
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
embeddedFilesBaseDirectory = filepath.Join(os.TempDir(), "pomerium-embedded-files")
|
||||||
|
|
||||||
|
extractOnce sync.Once
|
||||||
|
extractOutPath string
|
||||||
|
extractErr error
|
||||||
|
)
|
||||||
|
|
||||||
|
type embeddedEnvoyProvider struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Checksum returns the checksum for the embedded envoy binary.
|
func (embeddedEnvoyProvider) Checksum() string {
|
||||||
func Checksum() string {
|
|
||||||
return strings.Fields(rawChecksum)[0]
|
return strings.Fields(rawChecksum)[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
// FullVersion returns the full version string for envoy.
|
func (embeddedEnvoyProvider) Extract(ctx context.Context) (string, error) {
|
||||||
func FullVersion() string {
|
extractOnce.Do(func() {
|
||||||
return Version() + "+" + Checksum()
|
// clean up our base directory before starting
|
||||||
|
extractErr = os.RemoveAll(embeddedFilesBaseDirectory)
|
||||||
|
if extractErr != nil {
|
||||||
|
extractErr = fmt.Errorf("error cleaning embedded file directory: (directory=%s): %w", embeddedFilesBaseDirectory, extractErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// create known directory base to clean at startup
|
||||||
|
extractErr = os.MkdirAll(embeddedFilesBaseDirectory, embeddedDirectoryPermissions)
|
||||||
|
if extractErr != nil {
|
||||||
|
extractErr = fmt.Errorf("error creating embedded file directory: (directory=%s): %w", embeddedFilesBaseDirectory, extractErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// build a random temp directory inside our base directory to guarantee permissions
|
||||||
|
var tmpDir string
|
||||||
|
tmpDir, extractErr = os.MkdirTemp(embeddedFilesBaseDirectory, "envoy-")
|
||||||
|
if extractErr != nil {
|
||||||
|
extractErr = fmt.Errorf("error creating embedded file tmp directory: (directory=%s): %w", embeddedFilesBaseDirectory, extractErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
extractOutPath = filepath.Join(tmpDir, "envoy")
|
||||||
|
|
||||||
|
log.Info(ctx).Str("path", extractOutPath).Msg("extracting envoy binary")
|
||||||
|
extractErr = atomic.WriteFile(extractOutPath, bytes.NewReader(rawBinary))
|
||||||
|
if extractErr != nil {
|
||||||
|
extractErr = fmt.Errorf("error extracting embedded envoy binary to temporary directory (path=%s): %w", extractOutPath, extractErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
extractErr = os.Chmod(extractOutPath, embeddedEnvoyPermissions)
|
||||||
|
if extractErr != nil {
|
||||||
|
extractErr = fmt.Errorf("error chmoding embedded envoy binary: %w", extractErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return extractOutPath, extractErr
|
||||||
}
|
}
|
||||||
|
|
||||||
// Version returns the envoy version.
|
func (embeddedEnvoyProvider) Version() string {
|
||||||
func Version() string {
|
|
||||||
return strings.TrimSpace(rawVersion)
|
return strings.TrimSpace(rawVersion)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EmbeddedEnvoyProvider provides an embedded envoy binary via go:embed.
|
||||||
|
var EmbeddedEnvoyProvider = new(embeddedEnvoyProvider)
|
||||||
|
|
|
@ -133,7 +133,6 @@ func SetDBConfigInfo(ctx context.Context, service, configID string, version uint
|
||||||
); err != nil {
|
); err != nil {
|
||||||
log.Error(ctx).Err(err).Msg("telemetry/metrics: failed to record config error count")
|
log.Error(ctx).Err(err).Msg("telemetry/metrics: failed to record config error count")
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetDBConfigRejected records that a certain databroker config version has been rejected
|
// SetDBConfigRejected records that a certain databroker config version has been rejected
|
||||||
|
@ -176,8 +175,8 @@ func SetConfigInfo(ctx context.Context, service, configName string, checksum uin
|
||||||
|
|
||||||
// SetBuildInfo records the pomerium build info. You must call RegisterInfoMetrics to
|
// SetBuildInfo records the pomerium build info. You must call RegisterInfoMetrics to
|
||||||
// have this exported
|
// have this exported
|
||||||
func SetBuildInfo(service, hostname string) {
|
func SetBuildInfo(service, hostname, envoyVersion string) {
|
||||||
registry.setBuildInfo(service, hostname)
|
registry.setBuildInfo(service, hostname, envoyVersion)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RegisterInfoMetrics registers non-view based metrics registry globally for export
|
// RegisterInfoMetrics registers non-view based metrics registry globally for export
|
||||||
|
|
|
@ -6,7 +6,6 @@ import (
|
||||||
"runtime"
|
"runtime"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/pomerium/pomerium/internal/envoy/files"
|
|
||||||
"github.com/pomerium/pomerium/internal/version"
|
"github.com/pomerium/pomerium/internal/version"
|
||||||
"github.com/pomerium/pomerium/pkg/metrics"
|
"github.com/pomerium/pomerium/pkg/metrics"
|
||||||
|
|
||||||
|
@ -74,13 +73,13 @@ func Test_SetBuildInfo(t *testing.T) {
|
||||||
wantLabels := []metricdata.LabelValue{
|
wantLabels := []metricdata.LabelValue{
|
||||||
{Value: "test_service", Present: true},
|
{Value: "test_service", Present: true},
|
||||||
{Value: version.FullVersion(), Present: true},
|
{Value: version.FullVersion(), Present: true},
|
||||||
{Value: files.FullVersion(), Present: true},
|
{Value: "v1.2.3", Present: true},
|
||||||
{Value: version.GitCommit, Present: true},
|
{Value: version.GitCommit, Present: true},
|
||||||
{Value: runtime.Version(), Present: true},
|
{Value: runtime.Version(), Present: true},
|
||||||
{Value: "test_host", Present: true},
|
{Value: "test_host", Present: true},
|
||||||
}
|
}
|
||||||
|
|
||||||
SetBuildInfo("test_service", "test_host")
|
SetBuildInfo("test_service", "test_host", "v1.2.3")
|
||||||
testMetricRetrieval(registry.registry.Read(), t, wantLabels, int64(1), metrics.BuildInfo)
|
testMetricRetrieval(registry.registry.Read(), t, wantLabels, int64(1), metrics.BuildInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,8 +8,6 @@ import (
|
||||||
"go.opencensus.io/metric"
|
"go.opencensus.io/metric"
|
||||||
"go.opencensus.io/metric/metricdata"
|
"go.opencensus.io/metric/metricdata"
|
||||||
|
|
||||||
"github.com/pomerium/pomerium/internal/envoy/files"
|
|
||||||
|
|
||||||
"github.com/pomerium/pomerium/internal/log"
|
"github.com/pomerium/pomerium/internal/log"
|
||||||
"github.com/pomerium/pomerium/internal/version"
|
"github.com/pomerium/pomerium/internal/version"
|
||||||
"github.com/pomerium/pomerium/pkg/metrics"
|
"github.com/pomerium/pomerium/pkg/metrics"
|
||||||
|
@ -82,14 +80,14 @@ func (r *metricRegistry) init() {
|
||||||
|
|
||||||
// SetBuildInfo records the pomerium build info. You must call RegisterInfoMetrics to
|
// SetBuildInfo records the pomerium build info. You must call RegisterInfoMetrics to
|
||||||
// have this exported
|
// have this exported
|
||||||
func (r *metricRegistry) setBuildInfo(service, hostname string) {
|
func (r *metricRegistry) setBuildInfo(service, hostname, envoyVersion string) {
|
||||||
if registry.buildInfo == nil {
|
if registry.buildInfo == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
m, err := registry.buildInfo.GetEntry(
|
m, err := registry.buildInfo.GetEntry(
|
||||||
metricdata.NewLabelValue(service),
|
metricdata.NewLabelValue(service),
|
||||||
metricdata.NewLabelValue(version.FullVersion()),
|
metricdata.NewLabelValue(version.FullVersion()),
|
||||||
metricdata.NewLabelValue(files.FullVersion()),
|
metricdata.NewLabelValue(envoyVersion),
|
||||||
metricdata.NewLabelValue(version.GitCommit),
|
metricdata.NewLabelValue(version.GitCommit),
|
||||||
metricdata.NewLabelValue((runtime.Version())),
|
metricdata.NewLabelValue((runtime.Version())),
|
||||||
metricdata.NewLabelValue(hostname),
|
metricdata.NewLabelValue(hostname),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue