* root: initial rename * web: rename custom element prefix * root: rename external functions with pb_ prefix * root: fix formatting * root: replace domain with goauthentik.io * proxy: update path * root: rename remaining prefixes * flows: rename file extension * root: pbadmin -> akadmin * docs: fix image filenames * lifecycle: ignore migration files * ci: copy default config from current source before loading last tagged * *: new sentry dsn * tests: fix missing python3.9-dev package * root: add additional migrations for service accounts created by outposts * core: mark system-created service accounts with attribute * policies/expression: fix pb_ replacement not working * web: fix last linting errors, add lit-analyse * policies/expressions: fix lint errors * web: fix sidebar display on screens where not all items fit * proxy: attempt to fix proxy pipeline * proxy: use go env GOPATH to get gopath * lib: fix user_default naming inconsistency * docs: add upgrade docs * docs: update screenshots to use authentik * admin: fix create button on empty-state of outpost * web: fix modal submit not refreshing SiteShell and Table * web: fix height of app-card and height of generic icon * web: fix rendering of subtext * admin: fix version check error not being caught * web: fix worker count not being shown * docs: update screenshots * root: new icon * web: fix lint error * admin: fix linting error * root: migrate coverage config to pyproject
		
			
				
	
	
		
			137 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			137 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package server
 | 
						|
 | 
						|
import (
 | 
						|
	"context"
 | 
						|
	"crypto/tls"
 | 
						|
	"net"
 | 
						|
	"net/http"
 | 
						|
	"net/url"
 | 
						|
	"os"
 | 
						|
	"strings"
 | 
						|
 | 
						|
	"github.com/BeryJu/authentik/proxy/pkg/client/crypto"
 | 
						|
	"github.com/BeryJu/authentik/proxy/pkg/models"
 | 
						|
	"github.com/BeryJu/authentik/proxy/pkg/proxy"
 | 
						|
	"github.com/jinzhu/copier"
 | 
						|
	"github.com/justinas/alice"
 | 
						|
	"github.com/oauth2-proxy/oauth2-proxy/pkg/apis/options"
 | 
						|
	"github.com/oauth2-proxy/oauth2-proxy/pkg/middleware"
 | 
						|
	"github.com/oauth2-proxy/oauth2-proxy/pkg/validation"
 | 
						|
	log "github.com/sirupsen/logrus"
 | 
						|
)
 | 
						|
 | 
						|
type providerBundle struct {
 | 
						|
	http.Handler
 | 
						|
 | 
						|
	a     *APIController
 | 
						|
	proxy *proxy.OAuthProxy
 | 
						|
	Host  string
 | 
						|
 | 
						|
	cert *tls.Certificate
 | 
						|
}
 | 
						|
 | 
						|
func (pb *providerBundle) prepareOpts(provider *models.ProxyOutpostConfig) *options.Options {
 | 
						|
	externalHost, err := url.Parse(*provider.ExternalHost)
 | 
						|
	if err != nil {
 | 
						|
		log.WithError(err).Warning("Failed to parse URL, skipping provider")
 | 
						|
		return nil
 | 
						|
	}
 | 
						|
	providerOpts := &options.Options{}
 | 
						|
	copier.Copy(&providerOpts, &pb.a.commonOpts)
 | 
						|
	providerOpts.ClientID = provider.ClientID
 | 
						|
	providerOpts.ClientSecret = provider.ClientSecret
 | 
						|
 | 
						|
	providerOpts.Cookie.Secret = provider.CookieSecret
 | 
						|
	providerOpts.Cookie.Secure = externalHost.Scheme == "https"
 | 
						|
 | 
						|
	providerOpts.SkipOIDCDiscovery = true
 | 
						|
	providerOpts.OIDCIssuerURL = *provider.OidcConfiguration.Issuer
 | 
						|
	providerOpts.LoginURL = *provider.OidcConfiguration.AuthorizationEndpoint
 | 
						|
	providerOpts.RedeemURL = *provider.OidcConfiguration.TokenEndpoint
 | 
						|
	providerOpts.OIDCJwksURL = *provider.OidcConfiguration.JwksURI
 | 
						|
	providerOpts.ProfileURL = *provider.OidcConfiguration.UserinfoEndpoint
 | 
						|
 | 
						|
	if provider.SkipPathRegex != "" {
 | 
						|
		skipRegexes := strings.Split(provider.SkipPathRegex, "\n")
 | 
						|
		providerOpts.SkipAuthRegex = skipRegexes
 | 
						|
	}
 | 
						|
 | 
						|
	providerOpts.UpstreamServers = []options.Upstream{
 | 
						|
		{
 | 
						|
			ID:                    "default",
 | 
						|
			URI:                   *provider.InternalHost,
 | 
						|
			Path:                  "/",
 | 
						|
			InsecureSkipTLSVerify: *&provider.InternalHostSslValidation,
 | 
						|
		},
 | 
						|
	}
 | 
						|
 | 
						|
	if provider.Certificate != nil {
 | 
						|
		pb.a.logger.WithField("provider", provider.ClientID).Debug("Enabling TLS")
 | 
						|
		cert, err := pb.a.client.Crypto.CryptoCertificatekeypairsRead(&crypto.CryptoCertificatekeypairsReadParams{
 | 
						|
			Context: context.Background(),
 | 
						|
			KpUUID:  *provider.Certificate,
 | 
						|
		}, pb.a.auth)
 | 
						|
		if err != nil {
 | 
						|
			pb.a.logger.WithField("provider", provider.ClientID).WithError(err).Warning("Failed to fetch certificate")
 | 
						|
			return providerOpts
 | 
						|
		}
 | 
						|
		x509cert, err := tls.X509KeyPair([]byte(*cert.Payload.CertificateData), []byte(cert.Payload.KeyData))
 | 
						|
		if err != nil {
 | 
						|
			pb.a.logger.WithField("provider", provider.ClientID).WithError(err).Warning("Failed to parse certificate")
 | 
						|
			return providerOpts
 | 
						|
		}
 | 
						|
		pb.cert = &x509cert
 | 
						|
		pb.a.logger.WithField("provider", provider.ClientID).WithField("certificate-key-pair", *cert.Payload.Name).Debug("Loaded certificates")
 | 
						|
	}
 | 
						|
	return providerOpts
 | 
						|
}
 | 
						|
 | 
						|
func (pb *providerBundle) Build(provider *models.ProxyOutpostConfig) {
 | 
						|
	opts := pb.prepareOpts(provider)
 | 
						|
 | 
						|
	chain := alice.New()
 | 
						|
 | 
						|
	if opts.ForceHTTPS {
 | 
						|
		_, httpsPort, err := net.SplitHostPort(opts.HTTPSAddress)
 | 
						|
		if err != nil {
 | 
						|
			log.Fatalf("FATAL: invalid HTTPS address %q: %v", opts.HTTPAddress, err)
 | 
						|
		}
 | 
						|
		chain = chain.Append(middleware.NewRedirectToHTTPS(httpsPort))
 | 
						|
	}
 | 
						|
 | 
						|
	healthCheckPaths := []string{opts.PingPath}
 | 
						|
	healthCheckUserAgents := []string{opts.PingUserAgent}
 | 
						|
	if opts.GCPHealthChecks {
 | 
						|
		healthCheckPaths = append(healthCheckPaths, "/liveness_check", "/readiness_check")
 | 
						|
		healthCheckUserAgents = append(healthCheckUserAgents, "GoogleHC/1.0")
 | 
						|
	}
 | 
						|
 | 
						|
	// To silence logging of health checks, register the health check handler before
 | 
						|
	// the logging handler
 | 
						|
	if opts.Logging.SilencePing {
 | 
						|
		chain = chain.Append(middleware.NewHealthCheck(healthCheckPaths, healthCheckUserAgents), LoggingHandler)
 | 
						|
	} else {
 | 
						|
		chain = chain.Append(LoggingHandler, middleware.NewHealthCheck(healthCheckPaths, healthCheckUserAgents))
 | 
						|
	}
 | 
						|
 | 
						|
	err := validation.Validate(opts)
 | 
						|
	if err != nil {
 | 
						|
		log.Printf("%s", err)
 | 
						|
		os.Exit(1)
 | 
						|
	}
 | 
						|
	oauthproxy, err := proxy.NewOAuthProxy(opts)
 | 
						|
	if err != nil {
 | 
						|
		log.Errorf("ERROR: Failed to initialise OAuth2 Proxy: %v", err)
 | 
						|
		os.Exit(1)
 | 
						|
	}
 | 
						|
 | 
						|
	if *&provider.BasicAuthEnabled {
 | 
						|
		oauthproxy.SetBasicAuth = true
 | 
						|
		oauthproxy.BasicAuthUserAttribute = provider.BasicAuthUserAttribute
 | 
						|
		oauthproxy.BasicAuthPasswordAttribute = provider.BasicAuthPasswordAttribute
 | 
						|
	}
 | 
						|
 | 
						|
	pb.proxy = oauthproxy
 | 
						|
	pb.Handler = chain.Then(oauthproxy)
 | 
						|
}
 |