From b93624fa1fc8affd010597bcaa1c824466456c63 Mon Sep 17 00:00:00 2001 From: cmeng Date: Thu, 13 Jul 2023 15:19:40 +1200 Subject: [PATCH] fix(chisel): convert seed to private key file EE-5099 (#9149) --- api/chisel/crypto/crypto.go | 61 +++++++++++++++++++ api/chisel/crypto/crypto_test.go | 37 +++++++++++ api/chisel/service.go | 54 ++++++++++------ api/cmd/portainer/main.go | 2 +- api/datastore/datastore_test.go | 2 +- api/datastore/migrate_data.go | 1 + .../migrator/migrate_dbversion100.go | 50 +++++++++++++++ api/datastore/migrator/migrator.go | 13 ++-- .../test_data/output_24_to_latest.json | 4 +- api/filesystem/filesystem.go | 27 ++++++++ api/go.mod | 7 ++- api/go.sum | 26 ++++---- .../endpointedge_status_inspect_test.go | 4 +- api/portainer.go | 2 + 14 files changed, 247 insertions(+), 43 deletions(-) create mode 100644 api/chisel/crypto/crypto.go create mode 100644 api/chisel/crypto/crypto_test.go diff --git a/api/chisel/crypto/crypto.go b/api/chisel/crypto/crypto.go new file mode 100644 index 000000000..1b82940e4 --- /dev/null +++ b/api/chisel/crypto/crypto.go @@ -0,0 +1,61 @@ +package crypto + +import ( + "crypto/ecdsa" + "crypto/elliptic" + "crypto/x509" + "encoding/pem" + "fmt" + "io" + "math/big" + + chshare "github.com/jpillora/chisel/share" +) + +var one = new(big.Int).SetInt64(1) + +// GenerateGo119CompatibleKey This function is basically copied from chshare.GenerateKey. +func GenerateGo119CompatibleKey(seed string) ([]byte, error) { + r := chshare.NewDetermRand([]byte(seed)) + priv, err := ecdsaGenerateKey(elliptic.P256(), r) + if err != nil { + return nil, err + } + b, err := x509.MarshalECPrivateKey(priv) + if err != nil { + return nil, fmt.Errorf("Unable to marshal ECDSA private key: %w", err) + } + return pem.EncodeToMemory(&pem.Block{Type: "EC PRIVATE KEY", Bytes: b}), nil +} + +// This function is copied from Go1.19 +func randFieldElement(c elliptic.Curve, rand io.Reader) (k *big.Int, err error) { + params := c.Params() + // Note that for P-521 this will actually be 63 bits more than the order, as + // division rounds down, but the extra bit is inconsequential. + b := make([]byte, params.N.BitLen()/8+8) + _, err = io.ReadFull(rand, b) + if err != nil { + return + } + + k = new(big.Int).SetBytes(b) + n := new(big.Int).Sub(params.N, one) + k.Mod(k, n) + k.Add(k, one) + return +} + +// This function is copied from Go1.19 +func ecdsaGenerateKey(c elliptic.Curve, rand io.Reader) (*ecdsa.PrivateKey, error) { + k, err := randFieldElement(c, rand) + if err != nil { + return nil, err + } + + priv := new(ecdsa.PrivateKey) + priv.PublicKey.Curve = c + priv.D = k + priv.PublicKey.X, priv.PublicKey.Y = c.ScalarBaseMult(k.Bytes()) + return priv, nil +} diff --git a/api/chisel/crypto/crypto_test.go b/api/chisel/crypto/crypto_test.go new file mode 100644 index 000000000..2dfc28dbd --- /dev/null +++ b/api/chisel/crypto/crypto_test.go @@ -0,0 +1,37 @@ +package crypto + +import ( + "reflect" + "testing" +) + +func TestGenerateGo119CompatibleKey(t *testing.T) { + type args struct { + seed string + } + tests := []struct { + name string + args args + want []byte + wantErr bool + }{ + { + name: "Generate Go 1.19 compatible private key with a given seed", + args: args{seed: "94qh17MCIk8BOkiI"}, + want: []byte("-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIHeohwk0Gy3RHVVViaHz7pz/HOiqA7fkv1FTM3mGgfT3oAoGCCqGSM49\nAwEHoUQDQgAEN7riX06xDsLNPuUmOvYFluNEakcFwZZRVvOcIYk/9VYnanDzW0Km\n8/BUUiKyJDuuGdS4fj9SlQ4iL8yBK01uKg==\n-----END EC PRIVATE KEY-----\n"), + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := GenerateGo119CompatibleKey(tt.args.seed) + if (err != nil) != tt.wantErr { + t.Errorf("GenerateGo119CompatibleKey() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("GenerateGo119CompatibleKey()\ngot: Z %v\nwant: %v", got, tt.want) + } + }) + } +} diff --git a/api/chisel/service.go b/api/chisel/service.go index 2c39a9a5a..a78c4ccf5 100644 --- a/api/chisel/service.go +++ b/api/chisel/service.go @@ -12,8 +12,8 @@ import ( "github.com/portainer/portainer/api/dataservices" "github.com/portainer/portainer/api/http/proxy" - "github.com/dchest/uniuri" chserver "github.com/jpillora/chisel/server" + "github.com/jpillora/chisel/share/ccrypto" "github.com/rs/zerolog/log" ) @@ -36,14 +36,16 @@ type Service struct { shutdownCtx context.Context ProxyManager *proxy.Manager mu sync.Mutex + fileService portainer.FileService } // NewService returns a pointer to a new instance of Service -func NewService(dataStore dataservices.DataStore, shutdownCtx context.Context) *Service { +func NewService(dataStore dataservices.DataStore, shutdownCtx context.Context, fileService portainer.FileService) *Service { return &Service{ tunnelDetailsMap: make(map[portainer.EndpointID]*portainer.TunnelDetails), dataStore: dataStore, shutdownCtx: shutdownCtx, + fileService: fileService, } } @@ -117,14 +119,15 @@ func (service *Service) KeepTunnelAlive(endpointID portainer.EndpointID, ctx con // It starts the tunnel status verification process in the background. // The snapshotter is used in the tunnel status verification process. func (service *Service) StartTunnelServer(addr, port string, snapshotService portainer.SnapshotService) error { - keySeed, err := service.retrievePrivateKeySeed() + privateKeyFile, err := service.retrievePrivateKeyFile() + if err != nil { return err } config := &chserver.Config{ - Reverse: true, - KeySeed: keySeed, + Reverse: true, + PrivateKeyFile: privateKeyFile, } chiselServer, err := chserver.NewServer(config) @@ -160,26 +163,41 @@ func (service *Service) StopTunnelServer() error { return service.chiselServer.Close() } -func (service *Service) retrievePrivateKeySeed() (string, error) { - var serverInfo *portainer.TunnelServerInfo +func (service *Service) retrievePrivateKeyFile() (string, error) { + privateKeyFile := service.fileService.GetDefaultChiselPrivateKeyPath() - serverInfo, err := service.dataStore.TunnelServer().Info() - if service.dataStore.IsErrObjectNotFound(err) { - keySeed := uniuri.NewLen(16) + exist, _ := service.fileService.FileExists(privateKeyFile) + if !exist { + log.Debug(). + Str("private-key", privateKeyFile). + Msg("Chisel private key file does not exist") - serverInfo = &portainer.TunnelServerInfo{ - PrivateKeySeed: keySeed, - } - - err := service.dataStore.TunnelServer().UpdateInfo(serverInfo) + privateKey, err := ccrypto.GenerateKey("") if err != nil { + log.Error(). + Err(err). + Msg("Failed to generate chisel private key") return "", err } - } else if err != nil { - return "", err + + err = service.fileService.StoreChiselPrivateKey(privateKey) + if err != nil { + log.Error(). + Err(err). + Msg("Failed to save Chisel private key to disk") + return "", err + } else { + log.Info(). + Str("private-key", privateKeyFile). + Msg("Generated a new Chisel private key file") + } + } else { + log.Info(). + Str("private-key", privateKeyFile). + Msg("Found Chisel private key file on disk") } - return serverInfo.PrivateKeySeed, nil + return privateKeyFile, nil } func (service *Service) startTunnelVerificationLoop() { diff --git a/api/cmd/portainer/main.go b/api/cmd/portainer/main.go index a5051602c..c8c29b751 100644 --- a/api/cmd/portainer/main.go +++ b/api/cmd/portainer/main.go @@ -429,7 +429,7 @@ func buildServer(flags *portainer.CLIFlags) portainer.Server { log.Fatal().Err(err).Msg("failed initializing key pair") } - reverseTunnelService := chisel.NewService(dataStore, shutdownCtx) + reverseTunnelService := chisel.NewService(dataStore, shutdownCtx, fileService) dockerClientFactory := initDockerClientFactory(digitalSignatureService, reverseTunnelService) kubernetesClientFactory, err := initKubernetesClientFactory(digitalSignatureService, reverseTunnelService, dataStore, instanceID, *flags.AddrHTTPS, settings.UserSessionTimeout) diff --git a/api/datastore/datastore_test.go b/api/datastore/datastore_test.go index c5ee6a905..d26d71240 100644 --- a/api/datastore/datastore_test.go +++ b/api/datastore/datastore_test.go @@ -150,7 +150,7 @@ func (store *Store) CreateEndpoint(t *testing.T, name string, endpointType porta expectedEndpoint = newEndpoint(endpointType, id, name, URL, tls) case portainer.EdgeAgentOnKubernetesEnvironment: - cs := chisel.NewService(store, nil) + cs := chisel.NewService(store, nil, nil) expectedEndpoint = newEndpoint(endpointType, id, name, URL, tls) edgeKey := cs.GenerateEdgeKey(URL, "", int(id)) expectedEndpoint.EdgeKey = edgeKey diff --git a/api/datastore/migrate_data.go b/api/datastore/migrate_data.go index a80f1f152..1279b3834 100644 --- a/api/datastore/migrate_data.go +++ b/api/datastore/migrate_data.go @@ -86,6 +86,7 @@ func (store *Store) newMigratorParameters(version *models.Version) *migrator.Mig AuthorizationService: authorization.NewService(store), EdgeStackService: store.EdgeStackService, EdgeJobService: store.EdgeJobService, + TunnelServerService: store.TunnelServerService, } } diff --git a/api/datastore/migrator/migrate_dbversion100.go b/api/datastore/migrator/migrate_dbversion100.go index c2f3e8184..1c4b7ab68 100644 --- a/api/datastore/migrator/migrate_dbversion100.go +++ b/api/datastore/migrator/migrate_dbversion100.go @@ -3,6 +3,9 @@ package migrator import ( "os" + "github.com/portainer/portainer/api" + "github.com/portainer/portainer/api/chisel/crypto" + "github.com/portainer/portainer/api/dataservices" "github.com/rs/zerolog/log" ) @@ -23,3 +26,50 @@ func (m *Migrator) migrateDockerDesktopExtentionSetting() error { return m.settingsService.UpdateSettings(settings) } + +func (m *Migrator) convertSeedToPrivateKeyForDB100() error { + var serverInfo *portainer.TunnelServerInfo + + serverInfo, err := m.TunnelServerService.Info() + if err != nil { + if dataservices.IsErrObjectNotFound(err) { + log.Info().Msg("ServerInfo object not found") + return nil + } + log.Error(). + Err(err). + Msg("Failed to read ServerInfo from DB") + return err + } + + if serverInfo.PrivateKeySeed != "" { + key, err := crypto.GenerateGo119CompatibleKey(serverInfo.PrivateKeySeed) + if err != nil { + log.Error(). + Err(err). + Msg("Failed to read ServerInfo from DB") + return err + } + + err = m.fileService.StoreChiselPrivateKey(key) + if err != nil { + log.Error(). + Err(err). + Msg("Failed to save Chisel private key to disk") + return err + } + } else { + log.Info().Msg("PrivateKeySeed is blank") + } + + serverInfo.PrivateKeySeed = "" + err = m.TunnelServerService.UpdateInfo(serverInfo) + if err != nil { + log.Error(). + Err(err). + Msg("Failed to clean private key seed in DB") + } else { + log.Info().Msg("Success to migrate private key seed to private key file") + } + return err +} diff --git a/api/datastore/migrator/migrator.go b/api/datastore/migrator/migrator.go index af1d34ed7..be634ef68 100644 --- a/api/datastore/migrator/migrator.go +++ b/api/datastore/migrator/migrator.go @@ -3,6 +3,7 @@ package migrator import ( "errors" + "github.com/Masterminds/semver" portainer "github.com/portainer/portainer/api" "github.com/portainer/portainer/api/database/models" "github.com/portainer/portainer/api/dataservices/dockerhub" @@ -22,11 +23,10 @@ import ( "github.com/portainer/portainer/api/dataservices/stack" "github.com/portainer/portainer/api/dataservices/tag" "github.com/portainer/portainer/api/dataservices/teammembership" + "github.com/portainer/portainer/api/dataservices/tunnelserver" "github.com/portainer/portainer/api/dataservices/user" "github.com/portainer/portainer/api/dataservices/version" "github.com/portainer/portainer/api/internal/authorization" - - "github.com/Masterminds/semver" "github.com/rs/zerolog/log" ) @@ -57,6 +57,7 @@ type ( dockerhubService *dockerhub.Service edgeStackService *edgestack.Service edgeJobService *edgejob.Service + TunnelServerService *tunnelserver.Service } // MigratorParameters represents the required parameters to create a new Migrator instance. @@ -83,6 +84,7 @@ type ( DockerhubService *dockerhub.Service EdgeStackService *edgestack.Service EdgeJobService *edgejob.Service + TunnelServerService *tunnelserver.Service } ) @@ -111,6 +113,7 @@ func NewMigrator(parameters *MigratorParameters) *Migrator { dockerhubService: parameters.DockerhubService, edgeStackService: parameters.EdgeStackService, edgeJobService: parameters.EdgeJobService, + TunnelServerService: parameters.TunnelServerService, } migrator.initMigrations() @@ -209,8 +212,10 @@ func (m *Migrator) initMigrations() { m.addMigrations("2.16.1", m.migrateDBVersionToDB71) m.addMigrations("2.17", m.migrateDBVersionToDB80) m.addMigrations("2.18", m.migrateDBVersionToDB90) - - m.addMigrations("2.19", m.migrateDockerDesktopExtentionSetting) + m.addMigrations("2.19", + m.convertSeedToPrivateKeyForDB100, + m.migrateDockerDesktopExtentionSetting, + ) // Add new migrations below... // One function per migration, each versions migration funcs in the same file. diff --git a/api/datastore/test_data/output_24_to_latest.json b/api/datastore/test_data/output_24_to_latest.json index 80d0b94f7..9d0475f7e 100644 --- a/api/datastore/test_data/output_24_to_latest.json +++ b/api/datastore/test_data/output_24_to_latest.json @@ -879,7 +879,7 @@ } ], "tunnel_server": { - "PrivateKeySeed": "IvX6ZPRuWtLS5zyg" + "PrivateKeySeed": "" }, "users": [ { @@ -944,6 +944,6 @@ } ], "version": { - "VERSION": "{\"SchemaVersion\":\"2.19.0\",\"MigratorCount\":1,\"Edition\":1,\"InstanceID\":\"463d5c47-0ea5-4aca-85b1-405ceefee254\"}" + "VERSION": "{\"SchemaVersion\":\"2.19.0\",\"MigratorCount\":2,\"Edition\":1,\"InstanceID\":\"463d5c47-0ea5-4aca-85b1-405ceefee254\"}" } } \ No newline at end of file diff --git a/api/filesystem/filesystem.go b/api/filesystem/filesystem.go index 08c8454f9..10579cf67 100644 --- a/api/filesystem/filesystem.go +++ b/api/filesystem/filesystem.go @@ -67,6 +67,11 @@ const ( MTLSCertFilename = "mtls-cert.pem" MTLSCACertFilename = "mtls-ca-cert.pem" MTLSKeyFilename = "mtls-key.pem" + + // ChiselPath represents the default chisel path + ChiselPath = "chisel" + // ChiselPrivateKeyFilename represents the chisel private key file name + ChiselPrivateKeyFilename = "private-key.pem" ) // ErrUndefinedTLSFileType represents an error returned on undefined TLS file type @@ -812,6 +817,28 @@ func defaultMTLSCertPathUnderFileStore() (string, string, string) { return certPath, caCertPath, keyPath } +// GetDefaultChiselPrivateKeyPath returns the chisle private key path +func (service *Service) GetDefaultChiselPrivateKeyPath() string { + privateKeyPath := defaultChiselPrivateKeyPathUnderFileStore() + return service.wrapFileStore(privateKeyPath) +} + +func defaultChiselPrivateKeyPathUnderFileStore() string { + return JoinPaths(ChiselPath, ChiselPrivateKeyFilename) +} + +// StoreChiselPrivateKey store the specified chisel private key content on disk. +func (service *Service) StoreChiselPrivateKey(privateKey []byte) error { + err := service.createDirectoryInStore(ChiselPath) + if err != nil && !os.IsExist(err) { + return err + } + + r := bytes.NewReader(privateKey) + privateKeyPath := defaultChiselPrivateKeyPathUnderFileStore() + return service.createFileInStore(privateKeyPath, r) +} + // StoreSSLCertPair stores a ssl certificate pair func (service *Service) StoreSSLCertPair(cert, key []byte) (string, string, error) { certPath, keyPath := defaultCertPathUnderFileStore() diff --git a/api/go.mod b/api/go.mod index f7189b47a..9b7d87e1d 100644 --- a/api/go.mod +++ b/api/go.mod @@ -1,6 +1,6 @@ module github.com/portainer/portainer/api -go 1.19 +go 1.20 require ( github.com/Masterminds/semver v1.5.0 @@ -85,7 +85,7 @@ require ( github.com/emirpasic/gods v1.12.0 // indirect github.com/evanphx/json-patch v4.12.0+incompatible // indirect github.com/felixge/httpsnoop v1.0.1 // indirect - github.com/fsnotify/fsnotify v1.5.1 // indirect + github.com/fsnotify/fsnotify v1.6.0 // indirect github.com/go-asn1-ber/asn1-ber v1.5.1 // indirect github.com/go-git/gcfg v1.5.0 // indirect github.com/go-git/go-billy/v5 v5.1.0 // indirect @@ -160,3 +160,6 @@ require ( sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect sigs.k8s.io/yaml v1.3.0 // indirect ) + +// Remove below line when the "determinstic key" patch for Chisel merged +replace github.com/jpillora/chisel => github.com/portainer/chisel v0.0.0-20230704222304-426f515c6c25 diff --git a/api/go.sum b/api/go.sum index f56c1a191..97dfadcae 100644 --- a/api/go.sum +++ b/api/go.sum @@ -111,9 +111,8 @@ github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8S github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= -github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI= -github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU= +github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= +github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/fvbommel/sortorder v1.0.2 h1:mV4o8B2hKboCdkJm+a7uX/SIpZob4JzUpc5GGnM45eo= github.com/fvbommel/sortorder v1.0.2/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0= github.com/fxamacker/cbor/v2 v2.3.0 h1:aM45YGMctNakddNNAezPxDUpv38j44Abh+hifNuqXik= @@ -205,7 +204,6 @@ github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ= github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= -github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= @@ -230,16 +228,11 @@ github.com/joho/godotenv v1.4.0 h1:3l4+N6zfMWnkbPEXKng2o2/MR5mSwTrBih4ZEkkz1lg= github.com/joho/godotenv v1.4.0/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= -github.com/jpillora/ansi v0.0.0-20170202005112-f496b27cd669/go.mod h1:kOeLNvjNBGSV3uYtFjvb72+fnZCMFJF1XDvRIjdom0g= github.com/jpillora/ansi v1.0.2 h1:+Ei5HCAH0xsrQRCT2PDr4mq9r4Gm4tg+arNdXRkB22s= github.com/jpillora/ansi v1.0.2/go.mod h1:D2tT+6uzJvN1nBVQILYWkIdq7zG+b5gcFN5WI/VyjMY= -github.com/jpillora/backoff v0.0.0-20180909062703-3050d21c67d7/go.mod h1:2iMrUgbbvHEiQClaW2NsSzMyGHqN+rDFqY705q49KG0= -github.com/jpillora/chisel v0.0.0-20190724232113-f3a8df20e389 h1:K3JsoRqX6C4gmTvY4jqtFGCfK8uToj9DMahciJaoWwE= -github.com/jpillora/chisel v0.0.0-20190724232113-f3a8df20e389/go.mod h1:wHQUFFnFySoqdAOzjHkTvb4DsVM1h/73PS9l2vnioRM= -github.com/jpillora/requestlog v0.0.0-20181015073026-df8817be5f82/go.mod h1:w8buj+yNfmLEP0ENlbG/FRnK6bVmuhqXnukYCs9sDvY= +github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/jpillora/requestlog v1.0.0 h1:bg++eJ74T7DYL3DlIpiwknrtfdUA9oP/M4fL+PpqnyA= github.com/jpillora/requestlog v1.0.0/go.mod h1:HTWQb7QfDc2jtHnWe2XEIEeJB7gJPnVdpNn52HXPvy8= -github.com/jpillora/sizestr v0.0.0-20160130011556-e2ea2fa42fb9/go.mod h1:1ffp+CRe0eAwwRb0/BownUAjMBsmTLwgAvRbfj9dRwE= github.com/jpillora/sizestr v1.0.0 h1:4tr0FLxs1Mtq3TnsLDV+GYUWG7Q26a6s+tV5Zfw2ygw= github.com/jpillora/sizestr v1.0.0/go.mod h1:bUhLv4ctkknatr6gR42qPxirmd5+ds1u7mzD+MZ33f0= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= @@ -320,6 +313,8 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/portainer/chisel v0.0.0-20230704222304-426f515c6c25 h1:OfU9WGqE8bYdKB1dH3jgQpM2tP1+l5wGdNLO8Kk7nww= +github.com/portainer/chisel v0.0.0-20230704222304-426f515c6c25/go.mod h1:jhzGKO7NT6pNc/qto8YrNBGnuWZdqswvY6+n4zwE/Zc= github.com/portainer/libcrypto v0.0.0-20220506221303-1f4fb3b30f9a h1:B0z3skIMT+OwVNJPQhKp52X+9OWW6A9n5UWig3lHBJk= github.com/portainer/libcrypto v0.0.0-20220506221303-1f4fb3b30f9a/go.mod h1:n54EEIq+MM0NNtqLeCby8ljL+l275VpolXO0ibHegLE= github.com/portainer/libhttp v0.0.0-20230615144939-a999f666d9a9 h1:Jq8g/pDcFL1Z/DnZgn6DyaWu29y9+RiB5aOJ/Xw4960= @@ -399,7 +394,6 @@ github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9dec go.etcd.io/bbolt v1.3.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ= go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk= -golang.org/x/crypto v0.0.0-20181015023909-0c41d7ab0a0e/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -407,6 +401,7 @@ golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A= golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -421,7 +416,6 @@ golang.org/x/mod v0.9.0 h1:KENHtAZL2y3NLMYZeHY9DW8HW8V+kQyJsY/V9JlKvCs= golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181017193950-04a2e542c03f/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -432,6 +426,7 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210326060303-6b1517762897/go.mod h1:uSPa2vr4CLtc/ILN5odXGNXS6mhrKVzTaCXzk9m6W3k= +golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -443,11 +438,11 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181019160139-8e24a49d80f8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -461,6 +456,8 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -472,15 +469,18 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220906165534-d0df966e6959/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU= golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.6.0 h1:clScbb1cHjoCkyRbWwBEUZ5H/tIFu5TAXIqaZD0Gcjw= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44= diff --git a/api/http/handler/endpointedge/endpointedge_status_inspect_test.go b/api/http/handler/endpointedge/endpointedge_status_inspect_test.go index f43b8a7a1..3c78e80e3 100644 --- a/api/http/handler/endpointedge/endpointedge_status_inspect_test.go +++ b/api/http/handler/endpointedge/endpointedge_status_inspect_test.go @@ -108,10 +108,10 @@ func mustSetupHandler(t *testing.T) *Handler { security.NewRequestBouncer(store, jwtService, apiKeyService), store, fs, - chisel.NewService(store, shutdownCtx), + chisel.NewService(store, shutdownCtx, nil), ) - handler.ReverseTunnelService = chisel.NewService(store, shutdownCtx) + handler.ReverseTunnelService = chisel.NewService(store, shutdownCtx, nil) return handler } diff --git a/api/portainer.go b/api/portainer.go index d2a8cae2d..47eb27217 100644 --- a/api/portainer.go +++ b/api/portainer.go @@ -1420,6 +1420,8 @@ type ( CopySSLCACert(caCertPath string) (string, error) StoreFDOProfileFileFromBytes(fdoProfileIdentifier string, data []byte) (string, error) StoreMTLSCertificates(cert, caCert, key []byte) (string, string, string, error) + GetDefaultChiselPrivateKeyPath() string + StoreChiselPrivateKey(privateKey []byte) error } // GitService represents a service for managing Git