From 65dbdfb41b1fce4b41c19b280c5831765c583f15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Busso?= Date: Tue, 19 Jan 2021 13:22:19 +1300 Subject: [PATCH] Proxy --- api/cmd/portainer/main.go | 53 ++++++++++++++++++--------------- api/exec/compose_wrapper.go | 21 ++++++------- api/http/server.go | 59 +++++++++++++++++++------------------ 3 files changed, 68 insertions(+), 65 deletions(-) diff --git a/api/cmd/portainer/main.go b/api/cmd/portainer/main.go index 8f4032a58..60d584fdc 100644 --- a/api/cmd/portainer/main.go +++ b/api/cmd/portainer/main.go @@ -18,9 +18,10 @@ import ( "github.com/portainer/portainer/api/http" "github.com/portainer/portainer/api/http/client" "github.com/portainer/portainer/api/http/proxy" + "github.com/portainer/portainer/api/http/proxy/factory/kubernetes" "github.com/portainer/portainer/api/internal/snapshot" "github.com/portainer/portainer/api/jwt" - "github.com/portainer/portainer/api/kubernetes" + k8s "github.com/portainer/portainer/api/kubernetes" kubecli "github.com/portainer/portainer/api/kubernetes/cli" "github.com/portainer/portainer/api/ldap" "github.com/portainer/portainer/api/libcompose" @@ -132,7 +133,7 @@ func initKubernetesClientFactory(signatureService portainer.DigitalSignatureServ func initSnapshotService(snapshotInterval string, dataStore portainer.DataStore, dockerClientFactory *docker.ClientFactory, kubernetesClientFactory *kubecli.ClientFactory) (portainer.SnapshotService, error) { dockerSnapshotter := docker.NewSnapshotter(dockerClientFactory) - kubernetesSnapshotter := kubernetes.NewSnapshotter(kubernetesClientFactory) + kubernetesSnapshotter := k8s.NewSnapshotter(kubernetesClientFactory) snapshotService, err := snapshot.NewService(snapshotInterval, dataStore, dockerSnapshotter, kubernetesSnapshotter) if err != nil { @@ -386,8 +387,10 @@ func main() { if err != nil { log.Fatal(err) } + kubernetesTokenCacheManager := kubernetes.NewTokenCacheManager() + proxyManager := proxy.NewManager(dataStore, digitalSignatureService, reverseTunnelService, dockerClientFactory, kubernetesClientFactory, kubernetesTokenCacheManager) - composeStackManager := initComposeStackManager(*flags.Assets, *flags.Data, reverseTunnelService) + composeStackManager := initComposeStackManager(*flags.Assets, *flags.Data, reverseTunnelService, *proxyManager) kubernetesDeployer := initKubernetesDeployer(*flags.Assets) @@ -454,27 +457,29 @@ func main() { } var server portainer.Server = &http.Server{ - ReverseTunnelService: reverseTunnelService, - Status: applicationStatus, - BindAddress: *flags.Addr, - AssetsPath: *flags.Assets, - DataStore: dataStore, - SwarmStackManager: swarmStackManager, - ComposeStackManager: composeStackManager, - KubernetesDeployer: kubernetesDeployer, - CryptoService: cryptoService, - JWTService: jwtService, - FileService: fileService, - LDAPService: ldapService, - OAuthService: oauthService, - GitService: gitService, - SignatureService: digitalSignatureService, - SnapshotService: snapshotService, - SSL: *flags.SSL, - SSLCert: *flags.SSLCert, - SSLKey: *flags.SSLKey, - DockerClientFactory: dockerClientFactory, - KubernetesClientFactory: kubernetesClientFactory, + ReverseTunnelService: reverseTunnelService, + Status: applicationStatus, + BindAddress: *flags.Addr, + AssetsPath: *flags.Assets, + DataStore: dataStore, + SwarmStackManager: swarmStackManager, + ComposeStackManager: composeStackManager, + KubernetesDeployer: kubernetesDeployer, + CryptoService: cryptoService, + JWTService: jwtService, + FileService: fileService, + LDAPService: ldapService, + OAuthService: oauthService, + GitService: gitService, + ProxyManager: *proxyManager, + KubernetesTokenCacheManager: kubernetesTokenCacheManager, + SignatureService: digitalSignatureService, + SnapshotService: snapshotService, + SSL: *flags.SSL, + SSLCert: *flags.SSLCert, + SSLKey: *flags.SSLKey, + DockerClientFactory: dockerClientFactory, + KubernetesClientFactory: kubernetesClientFactory, } log.Printf("Starting Portainer %s on %s", portainer.APIVersion, *flags.Addr) diff --git a/api/exec/compose_wrapper.go b/api/exec/compose_wrapper.go index fe0de2107..04b1286f3 100644 --- a/api/exec/compose_wrapper.go +++ b/api/exec/compose_wrapper.go @@ -55,29 +55,28 @@ func (w *ComposeWrapper) command(command []string, stack *portainer.Stack, endpo if err != nil { return nil, err } - log.Printf("Endpoint: %v\n", endpoint) + if endpoint != nil { - log.Println("Endpoint Exists, need a Proxy Server...") + if endpoint.URL != "" { proxy, err := w.proxyManager.CreateAndRegisterEndpointProxy(endpoint) - log.Println("Endpoint has an URL, we create a proxy") + listener, err := net.Listen("tcp", ":0") if err != nil { return nil, err } - + log.Printf("Proxy Server: %v", proxy) server := http.Server{ Handler: proxy, } shutdownChan := make(chan error, 1) - log.Println("Let's start a Proxy Server...") + port := listener.Addr().(*net.TCPAddr).Port go func() { - log.Println("Starting Proxy Server...") - + log.Printf("Starting Proxy server on %s...\n", fmt.Sprintf("http://localhost:%d", port)) // details are the same as for the `server.ListenAndServe()` section above err := server.Serve(listener) - log.Printf("Proxy Server exited with '%v` error\n", err) + log.Printf("Proxy Server exited with '%v' error\n", err) if err != http.ErrServerClosed { log.Printf("Put '%v' error returned by Proxy Server to shutdown channel\n", err) @@ -87,14 +86,12 @@ func (w *ComposeWrapper) command(command []string, stack *portainer.Stack, endpo defer server.Close() - port := listener.Addr().(*net.TCPAddr).Port - log.Println("Add proxy server to options", fmt.Sprintf("http://locahost:%d", port)) - options = append(options, "-H", fmt.Sprintf("http://locahost:%d", port)) + options = append(options, "-H", fmt.Sprintf("http://localhost:%d", port)) } } - options = addTLSConnectionOptions(options, endpoint) + // options = addTLSConnectionOptions(options, endpoint) args := append(options, command...) diff --git a/api/http/server.go b/api/http/server.go index 8f83529f1..74e626625 100644 --- a/api/http/server.go +++ b/api/http/server.go @@ -39,39 +39,41 @@ import ( "github.com/portainer/portainer/api/http/proxy" "github.com/portainer/portainer/api/http/proxy/factory/kubernetes" "github.com/portainer/portainer/api/http/security" + "github.com/portainer/portainer/api/kubernetes/cli" ) // Server implements the portainer.Server interface type Server struct { - BindAddress string - AssetsPath string - Status *portainer.Status - ReverseTunnelService portainer.ReverseTunnelService - ComposeStackManager portainer.ComposeStackManager - CryptoService portainer.CryptoService - SignatureService portainer.DigitalSignatureService - SnapshotService portainer.SnapshotService - FileService portainer.FileService - DataStore portainer.DataStore - GitService portainer.GitService - JWTService portainer.JWTService - LDAPService portainer.LDAPService - OAuthService portainer.OAuthService - SwarmStackManager portainer.SwarmStackManager - Handler *handler.Handler - SSL bool - SSLCert string - SSLKey string - DockerClientFactory *docker.ClientFactory - KubernetesClientFactory *cli.ClientFactory - KubernetesDeployer portainer.KubernetesDeployer + BindAddress string + AssetsPath string + Status *portainer.Status + ReverseTunnelService portainer.ReverseTunnelService + ComposeStackManager portainer.ComposeStackManager + CryptoService portainer.CryptoService + SignatureService portainer.DigitalSignatureService + SnapshotService portainer.SnapshotService + FileService portainer.FileService + DataStore portainer.DataStore + GitService portainer.GitService + JWTService portainer.JWTService + LDAPService portainer.LDAPService + OAuthService portainer.OAuthService + SwarmStackManager portainer.SwarmStackManager + ProxyManager proxy.Manager + KubernetesTokenCacheManager *kubernetes.TokenCacheManager + Handler *handler.Handler + SSL bool + SSLCert string + SSLKey string + DockerClientFactory *docker.ClientFactory + KubernetesClientFactory *cli.ClientFactory + KubernetesDeployer portainer.KubernetesDeployer } // Start starts the HTTP server func (server *Server) Start() error { - kubernetesTokenCacheManager := kubernetes.NewTokenCacheManager() - proxyManager := proxy.NewManager(server.DataStore, server.SignatureService, server.ReverseTunnelService, server.DockerClientFactory, server.KubernetesClientFactory, kubernetesTokenCacheManager) + kubernetesTokenCacheManager := server.KubernetesTokenCacheManager requestBouncer := security.NewRequestBouncer(server.DataStore, server.JWTService) @@ -82,7 +84,7 @@ func (server *Server) Start() error { authHandler.CryptoService = server.CryptoService authHandler.JWTService = server.JWTService authHandler.LDAPService = server.LDAPService - authHandler.ProxyManager = proxyManager + authHandler.ProxyManager = &server.ProxyManager authHandler.KubernetesTokenCacheManager = kubernetesTokenCacheManager authHandler.OAuthService = server.OAuthService @@ -116,9 +118,8 @@ func (server *Server) Start() error { var endpointHandler = endpoints.NewHandler(requestBouncer) endpointHandler.DataStore = server.DataStore endpointHandler.FileService = server.FileService - endpointHandler.ProxyManager = proxyManager + endpointHandler.ProxyManager = &server.ProxyManager endpointHandler.SnapshotService = server.SnapshotService - endpointHandler.ProxyManager = proxyManager endpointHandler.ReverseTunnelService = server.ReverseTunnelService var endpointEdgeHandler = endpointedge.NewHandler(requestBouncer) @@ -131,7 +132,7 @@ func (server *Server) Start() error { var endpointProxyHandler = endpointproxy.NewHandler(requestBouncer) endpointProxyHandler.DataStore = server.DataStore - endpointProxyHandler.ProxyManager = proxyManager + endpointProxyHandler.ProxyManager = &server.ProxyManager endpointProxyHandler.ReverseTunnelService = server.ReverseTunnelService var fileHandler = file.NewHandler(filepath.Join(server.AssetsPath, "public")) @@ -141,7 +142,7 @@ func (server *Server) Start() error { var registryHandler = registries.NewHandler(requestBouncer) registryHandler.DataStore = server.DataStore registryHandler.FileService = server.FileService - registryHandler.ProxyManager = proxyManager + registryHandler.ProxyManager = &server.ProxyManager var resourceControlHandler = resourcecontrols.NewHandler(requestBouncer) resourceControlHandler.DataStore = server.DataStore