config: generate fallback cert only as last resort

Currently Pomerium will generate a self-signed wildcard certificate for
use as a fallback certificate.

As far as I can tell, if any other certificate is configured the
self-signed wildcard will never be presented, except in the case that a
TLS connection is made without the SNI (server name indication)
extension. Given that all modern browsers support SNI, in practice I
think this self-signed certificate will never be presented to end users.

However, this self-signed certificate will show up in network scans, and
may be reported as a problem in certain vulnerability scanning tools.

Let's avoid generating this self-signed certificate if Pomerium has any
other certificate configured. This should prevent false positive reports
from vulnerability scans.
This commit is contained in:
Kenneth Jenkins 2024-08-29 12:22:59 -07:00
parent ef08c32c82
commit b9443f552e
2 changed files with 46 additions and 29 deletions

View file

@ -173,30 +173,11 @@ func (cfg *Config) GetTLSClientConfig() (*tls.Config, error) {
}, nil
}
// GenerateCatchAllCertificate generates a catch-all certificate. If no derived CA is defined a
// self-signed certificate will be generated.
func (cfg *Config) GenerateCatchAllCertificate() (*tls.Certificate, error) {
if cfg.Options.DeriveInternalDomainCert != nil {
sharedKey, err := cfg.Options.GetSharedKey()
if err != nil {
return nil, fmt.Errorf("failed to generate cert, invalid shared key: %w", err)
}
ca, err := derivecert.NewCA(sharedKey)
if err != nil {
return nil, fmt.Errorf("failed to generate cert, invalid derived CA: %w", err)
}
pem, err := ca.NewServerCert([]string{"*"})
if err != nil {
return nil, fmt.Errorf("failed to generate cert, error creating server certificate: %w", err)
}
cert, err := pem.TLS()
if err != nil {
return nil, fmt.Errorf("failed to generate cert, error converting generated certificate into TLS certificate: %w", err)
}
return &cert, nil
// GenerateDerivedCertificate generates a wildcard certificate from a CA
// derived from the shared secret.
func (cfg *Config) GenerateDerivedCertificate() (*tls.Certificate, error) {
if cfg.Options.DeriveInternalDomainCert == nil {
return nil, nil
}
sharedKey, err := cfg.Options.GetSharedKey()
@ -204,7 +185,30 @@ func (cfg *Config) GenerateCatchAllCertificate() (*tls.Certificate, error) {
return nil, fmt.Errorf("failed to generate cert, invalid shared key: %w", err)
}
// finally fall back to a generated, self-signed certificate
ca, err := derivecert.NewCA(sharedKey)
if err != nil {
return nil, fmt.Errorf("failed to generate cert, invalid derived CA: %w", err)
}
pem, err := ca.NewServerCert([]string{"*"})
if err != nil {
return nil, fmt.Errorf("failed to generate cert, error creating server certificate: %w", err)
}
cert, err := pem.TLS()
if err != nil {
return nil, fmt.Errorf("failed to generate cert, error converting generated certificate into TLS certificate: %w", err)
}
return &cert, nil
}
// GenerateFallbackCertificate generates a self-signed certificate derived from
// the shared secret.
func (cfg *Config) GenerateFallbackCertificate() (*tls.Certificate, error) {
sharedKey, err := cfg.Options.GetSharedKey()
if err != nil {
return nil, fmt.Errorf("failed to generate cert, invalid shared key: %w", err)
}
return cryptutil.GenerateCertificate(sharedKey, "*")
}

View file

@ -104,12 +104,25 @@ func getAllCertificates(cfg *config.Config) ([]tls.Certificate, error) {
return nil, fmt.Errorf("error collecting all certificates: %w", err)
}
wc, err := cfg.GenerateCatchAllCertificate()
if err != nil {
return nil, fmt.Errorf("error getting wildcard certificate: %w", err)
if cfg.Options.DeriveInternalDomainCert != nil {
wc, err := cfg.GenerateDerivedCertificate()
if err != nil {
return nil, fmt.Errorf("error generating wildcard certificate: %w", err)
}
allCertificates = append(allCertificates, *wc)
}
return append(allCertificates, *wc), nil
// Generate a fallback certificate only as a last resort, if no other
// certificates are configured.
if len(allCertificates) == 0 {
wc, err := cfg.GenerateFallbackCertificate()
if err != nil {
return nil, fmt.Errorf("error generating wildcard certificate: %w", err)
}
allCertificates = append(allCertificates, *wc)
}
return allCertificates, nil
}
func (b *Builder) buildTLSSocket(ctx context.Context, cfg *config.Config, certs []tls.Certificate) (*envoy_config_core_v3.TransportSocket, error) {