Skip to content

Commit

Permalink
Automatically calculate public_addr field for dynamic apps (#10941). (
Browse files Browse the repository at this point in the history
#10943) (#11139)

* Autodiscover public_addr for dynamic apps.
  • Loading branch information
Tener authored Mar 15, 2022
1 parent e0dc57f commit 34e472e
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 34 deletions.
34 changes: 2 additions & 32 deletions lib/service/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -4011,7 +4011,8 @@ func getPublicAddr(authClient auth.ReadAppsAccessPoint, a App) (string, error) {
for {
select {
case <-ticker.C:
publicAddr, err := findPublicAddr(authClient, a)
publicAddr, err := app.FindPublicAddr(authClient, a.PublicAddr, a.Name)

if err == nil {
return publicAddr, nil
}
Expand All @@ -4021,37 +4022,6 @@ func getPublicAddr(authClient auth.ReadAppsAccessPoint, a App) (string, error) {
}
}

// findPublicAddr tries to resolve the public address of the proxy of this cluster.
func findPublicAddr(authClient auth.ReadAppsAccessPoint, a App) (string, error) {
// If the application has a public address already set, use it.
if a.PublicAddr != "" {
return a.PublicAddr, nil
}

// Fetch list of proxies, if first has public address set, use it.
servers, err := authClient.GetProxies()
if err != nil {
return "", trace.Wrap(err)
}
if len(servers) == 0 {
return "", trace.BadParameter("cluster has no proxied registered, at least one proxy must be registered for application access")
}
if servers[0].GetPublicAddr() != "" {
addr, err := utils.ParseAddr(servers[0].GetPublicAddr())
if err != nil {
return "", trace.Wrap(err)
}
return fmt.Sprintf("%v.%v", a.Name, addr.Host()), nil
}

// Fall back to cluster name.
cn, err := authClient.GetClusterName()
if err != nil {
return "", trace.Wrap(err)
}
return fmt.Sprintf("%v.%v", a.Name, cn.GetClusterName()), nil
}

// newHTTPFileSystem creates a new HTTP file system for the web handler.
// It uses external configuration to make the decision
func newHTTPFileSystem() (http.FileSystem, error) {
Expand Down
56 changes: 54 additions & 2 deletions lib/srv/app/watcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,13 @@ package app

import (
"context"
"fmt"

"github.com/gravitational/teleport"
"github.com/gravitational/teleport/api/types"
"github.com/gravitational/teleport/lib/auth"
"github.com/gravitational/teleport/lib/services"

"github.com/gravitational/teleport/lib/utils"
"github.com/gravitational/trace"
)

Expand Down Expand Up @@ -82,7 +84,11 @@ func (s *Server) startResourceWatcher(ctx context.Context) (*services.AppWatcher
for {
select {
case apps := <-watcher.AppsC:
s.monitoredApps.setResources(apps)
appsWithAddr := make(types.Apps, 0, len(apps))
for _, app := range apps {
appsWithAddr = append(appsWithAddr, s.guessPublicAddr(app))
}
s.monitoredApps.setResources(appsWithAddr)
select {
case s.reconcileCh <- struct{}{}:
case <-ctx.Done():
Expand All @@ -97,6 +103,52 @@ func (s *Server) startResourceWatcher(ctx context.Context) (*services.AppWatcher
return watcher, nil
}

// guessPublicAddr will guess PublicAddr for given application if it is missing, based on proxy information and app name.
func (s *Server) guessPublicAddr(app types.Application) types.Application {
if app.GetPublicAddr() != "" {
return app
}
appCopy := app.Copy()
pubAddr, err := FindPublicAddr(s.c.AccessPoint, app.GetPublicAddr(), app.GetName())
if err == nil {
appCopy.Spec.PublicAddr = pubAddr
} else {
s.log.WithError(err).Errorf("Unable to find public address for app %q, leaving empty.", app.GetName())
}
return appCopy
}

// FindPublicAddr tries to resolve the public address of the proxy of this cluster.
func FindPublicAddr(authClient auth.ReadAppsAccessPoint, appPublicAddr string, appName string) (string, error) {
// If the application has a public address already set, use it.
if appPublicAddr != "" {
return appPublicAddr, nil
}

// Fetch list of proxies, if first has public address set, use it.
servers, err := authClient.GetProxies()
if err != nil {
return "", trace.Wrap(err)
}
if len(servers) == 0 {
return "", trace.BadParameter("cluster has no proxy registered, at least one proxy must be registered for application access")
}
if servers[0].GetPublicAddr() != "" {
addr, err := utils.ParseAddr(servers[0].GetPublicAddr())
if err != nil {
return "", trace.Wrap(err)
}
return fmt.Sprintf("%v.%v", appName, addr.Host()), nil
}

// Fall back to cluster name.
cn, err := authClient.GetClusterName()
if err != nil {
return "", trace.Wrap(err)
}
return fmt.Sprintf("%v.%v", appName, cn.GetClusterName()), nil
}

func (s *Server) getResources() (resources types.ResourcesWithLabelsMap) {
return s.getApps().AsResources().ToMap()
}
Expand Down

0 comments on commit 34e472e

Please sign in to comment.