teleport/lib/service/cfg.go
Trent Clarke 52fb813390
Adds per-node ability to disable ssh TCP forwarding (#6989)
Prior to this change, TCP forwarding over SSH could only be disallowed
by user-based rules, rather than by individual target nodes.

This change adds:
  * the`port_forwarding` key to the yaml SSH config block, with a boolean value
  * Plumbing to pipe the resulting config value through to the SSH server
  * A predicate check in the SSH server to [dis]allow port forwarding based on the setting.

This change also:
    * adds a common way for integration tests to await the establishment of an SSH session
    * refactors several integration tests to use this new method rather than manually waiting
    * adds some marshaling code to move errors from spawned goroutines back into the 
      main test routine in verifySessionJoin()

See-Also: Issue #6783
2021-06-16 20:17:26 -05:00

920 lines
30 KiB
Go

/*
Copyright 2015-2021 Gravitational, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package service
import (
"fmt"
"io"
"net"
"net/http"
"net/url"
"os"
"path/filepath"
"strconv"
"strings"
"time"
"golang.org/x/crypto/ssh"
"golang.org/x/net/http/httpguts"
"k8s.io/apimachinery/pkg/util/validation"
"github.com/gravitational/teleport/api/types"
apiutils "github.com/gravitational/teleport/api/utils"
"github.com/gravitational/teleport/lib/auth"
"github.com/gravitational/teleport/lib/backend"
"github.com/gravitational/teleport/lib/backend/lite"
"github.com/gravitational/teleport/lib/backend/memory"
"github.com/gravitational/teleport/lib/bpf"
"github.com/gravitational/teleport/lib/defaults"
"github.com/gravitational/teleport/lib/events"
"github.com/gravitational/teleport/lib/limiter"
"github.com/gravitational/teleport/lib/pam"
"github.com/gravitational/teleport/lib/plugin"
"github.com/gravitational/teleport/lib/services"
"github.com/gravitational/teleport/lib/srv/app"
"github.com/gravitational/teleport/lib/sshca"
"github.com/gravitational/teleport/lib/tlsca"
"github.com/gravitational/teleport/lib/utils"
"github.com/ghodss/yaml"
"github.com/gravitational/trace"
"github.com/jonboulle/clockwork"
)
// Config structure is used to initialize _all_ services Teleport can run.
// Some settings are global (like DataDir) while others are grouped into
// sections, like AuthConfig
type Config struct {
// DataDir provides directory where teleport stores it's permanent state
// (in case of auth server backed by BoltDB) or local state, e.g. keys
DataDir string
// Hostname is a node host name
Hostname string
// Token is used to register this Teleport instance with the auth server
Token string
// AuthServers is a list of auth servers, proxies and peer auth servers to
// connect to. Yes, this is not just auth servers, the field name is
// misleading.
AuthServers []utils.NetAddr
// Identities is an optional list of pre-generated key pairs
// for teleport roles, this is helpful when server is preconfigured
Identities []*auth.Identity
// AdvertiseIP is used to "publish" an alternative IP address or hostname this node
// can be reached on, if running behind NAT
AdvertiseIP string
// CachePolicy sets caching policy for nodes and proxies
// in case if they loose connection to auth servers
CachePolicy CachePolicy
// Auth service configuration. Manages cluster state and configuration.
Auth AuthConfig
// Proxy service configuration. Manages incoming and outbound
// connections to the cluster.
Proxy ProxyConfig
// SSH service configuration. Manages SSH servers running within the cluster.
SSH SSHConfig
// App service configuration. Manages applications running within the cluster.
Apps AppsConfig
// Databases defines database proxy service configuration.
Databases DatabasesConfig
// Keygen points to a key generator implementation
Keygen sshca.Authority
// HostUUID is a unique UUID of this host (it will be known via this UUID within
// a teleport cluster). It's automatically generated on 1st start
HostUUID string
// Console writer to speak to a user
Console io.Writer
// ReverseTunnels is a list of reverse tunnels to create on the
// first cluster start
ReverseTunnels []types.ReverseTunnel
// OIDCConnectors is a list of trusted OpenID Connect identity providers
OIDCConnectors []types.OIDCConnector
// PidFile is a full path of the PID file for teleport daemon
PIDFile string
// Trust is a service that manages users and credentials
Trust services.Trust
// Presence service is a discovery and hearbeat tracker
Presence services.Presence
// Events is events service
Events types.Events
// Provisioner is a service that keeps track of provisioning tokens
Provisioner services.Provisioner
// Trust is a service that manages users and credentials
Identity services.Identity
// Access is a service that controls access
Access services.Access
// ClusterConfiguration is a service that provides cluster configuration
ClusterConfiguration services.ClusterConfiguration
// CipherSuites is a list of TLS ciphersuites that Teleport supports. If
// omitted, a Teleport selected list of defaults will be used.
CipherSuites []uint16
// Ciphers is a list of SSH ciphers that the server supports. If omitted,
// the defaults will be used.
Ciphers []string
// KEXAlgorithms is a list of SSH key exchange (KEX) algorithms that the
// server supports. If omitted, the defaults will be used.
KEXAlgorithms []string
// MACAlgorithms is a list of SSH message authentication codes (MAC) that
// the server supports. If omitted the defaults will be used.
MACAlgorithms []string
// CASignatureAlgorithm is an SSH Certificate Authority (CA) signature
// algorithm that the server uses for signing user and host certificates.
// If omitted, the default will be used.
CASignatureAlgorithm *string
// DiagnosticAddr is an address for diagnostic and healthz endpoint service
DiagnosticAddr utils.NetAddr
// Debug sets debugging mode, results in diagnostic address
// endpoint extended with additional /debug handlers
Debug bool
// UploadEventsC is a channel for upload events
// used in tests
UploadEventsC chan events.UploadEvent `json:"-"`
// FileDescriptors is an optional list of file descriptors for the process
// to inherit and use for listeners, used for in-process updates.
FileDescriptors []FileDescriptor
// PollingPeriod is set to override default internal polling periods
// of sync agents, used to speed up integration tests.
PollingPeriod time.Duration
// ClientTimeout is set to override default client timeouts
// used by internal clients, used to speed up integration tests.
ClientTimeout time.Duration
// ShutdownTimeout is set to override default shutdown timeout.
ShutdownTimeout time.Duration
// CAPin is the SKPI hash of the CA used to verify the Auth Server.
CAPin string
// Clock is used to control time in tests.
Clock clockwork.Clock
// FIPS means FedRAMP/FIPS 140-2 compliant configuration was requested.
FIPS bool
// BPFConfig holds configuration for the BPF service.
BPFConfig *bpf.Config
// Kube is a Kubernetes API gateway using Teleport client identities.
Kube KubeConfig
// Log optionally specifies the logger
Log utils.Logger
// PluginRegistry allows adding enterprise logic to Teleport services
PluginRegistry plugin.Registry
}
// ApplyToken assigns a given token to all internal services but only if token
// is not an empty string.
//
// returns:
// true, nil if the token has been modified
// false, nil if the token has not been modified
// false, err if there was an error
func (cfg *Config) ApplyToken(token string) (bool, error) {
if token != "" {
var err error
cfg.Token, err = utils.ReadToken(token)
if err != nil {
return false, trace.Wrap(err)
}
return true, nil
}
return false, nil
}
// RoleConfig is a config for particular Teleport role
func (cfg *Config) RoleConfig() RoleConfig {
return RoleConfig{
DataDir: cfg.DataDir,
HostUUID: cfg.HostUUID,
HostName: cfg.Hostname,
AuthServers: cfg.AuthServers,
Auth: cfg.Auth,
Console: cfg.Console,
}
}
// DebugDumpToYAML is useful for debugging: it dumps the Config structure into
// a string
func (cfg *Config) DebugDumpToYAML() string {
shallow := *cfg
// do not copy sensitive data to stdout
shallow.Identities = nil
shallow.Auth.Authorities = nil
out, err := yaml.Marshal(shallow)
if err != nil {
return err.Error()
}
return string(out)
}
// CachePolicy sets caching policy for proxies and nodes
type CachePolicy struct {
// Type sets the cache type
Type string
// Enabled enables or disables caching
Enabled bool
// TTL sets maximum TTL for the cached values
// without explicit TTL set
TTL time.Duration
// NeverExpires means that cache values without TTL
// set by the auth server won't expire
NeverExpires bool
// RecentTTL is the recently accessed items cache TTL
RecentTTL *time.Duration
}
// GetRecentTTL either returns TTL that was set,
// or default recent TTL value
func (c *CachePolicy) GetRecentTTL() time.Duration {
if c.RecentTTL == nil {
return defaults.RecentCacheTTL
}
return *c.RecentTTL
}
// CheckAndSetDefaults checks and sets default values
func (c *CachePolicy) CheckAndSetDefaults() error {
switch c.Type {
case "", lite.GetName():
c.Type = lite.GetName()
case memory.GetName():
default:
return trace.BadParameter("unsupported cache type %q, supported values are %q and %q",
c.Type, lite.GetName(), memory.GetName())
}
return nil
}
// String returns human-friendly representation of the policy
func (c CachePolicy) String() string {
if !c.Enabled {
return "no cache policy"
}
recentCachePolicy := ""
if c.GetRecentTTL() == 0 {
recentCachePolicy = "will not cache frequently accessed items"
} else {
recentCachePolicy = fmt.Sprintf("will cache frequently accessed items for %v", c.GetRecentTTL())
}
if c.NeverExpires {
return fmt.Sprintf("%v cache that will not expire in case if connection to database is lost, %v", c.Type, recentCachePolicy)
}
if c.TTL == 0 {
return fmt.Sprintf("%v cache that will expire after connection to database is lost after %v, %v", c.Type, defaults.CacheTTL, recentCachePolicy)
}
return fmt.Sprintf("%v cache that will expire after connection to database is lost after %v, %v", c.Type, c.TTL, recentCachePolicy)
}
// ProxyConfig specifies configuration for proxy service
type ProxyConfig struct {
// Enabled turns proxy role on or off for this process
Enabled bool
//DisableTLS is enabled if we don't want self-signed certs
DisableTLS bool
// DisableWebInterface allows to turn off serving the Web UI interface
DisableWebInterface bool
// DisableWebService turnes off serving web service completely, including web UI
DisableWebService bool
// DisableReverseTunnel disables reverse tunnel on the proxy
DisableReverseTunnel bool
// DisableDatabaseProxy disables database access proxy listener
DisableDatabaseProxy bool
// ReverseTunnelListenAddr is address where reverse tunnel dialers connect to
ReverseTunnelListenAddr utils.NetAddr
// EnableProxyProtocol enables proxy protocol support
EnableProxyProtocol bool
// WebAddr is address for web portal of the proxy
WebAddr utils.NetAddr
// SSHAddr is address of ssh proxy
SSHAddr utils.NetAddr
// MySQLAddr is address of MySQL proxy.
MySQLAddr utils.NetAddr
Limiter limiter.Config
// PublicAddrs is a list of the public addresses the proxy advertises
// for the HTTP endpoint. The hosts in in PublicAddr are included in the
// list of host principals on the TLS and SSH certificate.
PublicAddrs []utils.NetAddr
// SSHPublicAddrs is a list of the public addresses the proxy advertises
// for the SSH endpoint. The hosts in in PublicAddr are included in the
// list of host principals on the TLS and SSH certificate.
SSHPublicAddrs []utils.NetAddr
// TunnelPublicAddrs is a list of the public addresses the proxy advertises
// for the tunnel endpoint. The hosts in PublicAddr are included in the
// list of host principals on the TLS and SSH certificate.
TunnelPublicAddrs []utils.NetAddr
// PostgresPublicAddrs is a list of the public addresses the proxy
// advertises for Postgres clients.
PostgresPublicAddrs []utils.NetAddr
// MySQLPublicAddrs is a list of the public addresses the proxy
// advertises for MySQL clients.
MySQLPublicAddrs []utils.NetAddr
// Kube specifies kubernetes proxy configuration
Kube KubeProxyConfig
// KeyPairs are the key and certificate pairs that the proxy will load.
KeyPairs []KeyPairPath
// ACME is ACME protocol support config
ACME ACME
}
// ACME configures ACME automatic certificate renewal
type ACME struct {
// Enabled enables or disables ACME support
Enabled bool
// Email receives notifications from ACME server
Email string
// URI is ACME server URI
URI string
}
// KeyPairPath are paths to a key and certificate file.
type KeyPairPath struct {
// PrivateKey is the path to a PEM encoded private key.
PrivateKey string
// Certificate is the path to a PEM encoded certificate.
Certificate string
}
// KubeAddr returns the address for the Kubernetes endpoint on this proxy that
// can be reached by clients.
func (c ProxyConfig) KubeAddr() (string, error) {
if !c.Kube.Enabled {
return "", trace.NotFound("kubernetes support not enabled on this proxy")
}
if len(c.Kube.PublicAddrs) > 0 {
return fmt.Sprintf("https://%s", c.Kube.PublicAddrs[0].Addr), nil
}
host := "<proxyhost>"
// Try to guess the hostname from the HTTP public_addr.
if len(c.PublicAddrs) > 0 {
host = c.PublicAddrs[0].Host()
}
u := url.URL{
Scheme: "https",
Host: net.JoinHostPort(host, strconv.Itoa(c.Kube.ListenAddr.Port(defaults.KubeListenPort))),
}
return u.String(), nil
}
// KubeProxyConfig specifies configuration for proxy service
type KubeProxyConfig struct {
// Enabled turns kubernetes proxy role on or off for this process
Enabled bool
// ListenAddr is the address to listen on for incoming kubernetes requests.
ListenAddr utils.NetAddr
// ClusterOverride causes all traffic to go to a specific remote
// cluster, used only in tests
ClusterOverride string
// PublicAddrs is a list of the public addresses the Teleport Kube proxy can be accessed by,
// it also affects the host principals and routing logic
PublicAddrs []utils.NetAddr
// KubeconfigPath is a path to kubeconfig
KubeconfigPath string
// LegacyKubeProxy specifies that this proxy was configured using the
// legacy kubernetes section.
LegacyKubeProxy bool
}
// AuthConfig is a configuration of the auth server
type AuthConfig struct {
// Enabled turns auth role on or off for this process
Enabled bool
// EnableProxyProtocol enables proxy protocol support
EnableProxyProtocol bool
// SSHAddr is the listening address of SSH tunnel to HTTP service
SSHAddr utils.NetAddr
// Authorities is a set of trusted certificate authorities
// that will be added by this auth server on the first start
Authorities []types.CertAuthority
// Resources is a set of previously backed up resources
// used to bootstrap backend state on the first start.
Resources []types.Resource
// Roles is a set of roles to pre-provision for this cluster
Roles []types.Role
// ClusterName is a name that identifies this authority and all
// host nodes in the cluster that will share this authority domain name
// as a base name, e.g. if authority domain name is example.com,
// all nodes in the cluster will have UUIDs in the form: <uuid>.example.com
ClusterName types.ClusterName
// StaticTokens are pre-defined host provisioning tokens supplied via config file for
// environments where paranoid security is not needed
StaticTokens types.StaticTokens
// StorageConfig contains configuration settings for the storage backend.
StorageConfig backend.Config
Limiter limiter.Config
// NoAudit, when set to true, disables session recording and event audit
NoAudit bool
// Preference defines the authentication preference (type and second factor) for
// the auth server.
Preference types.AuthPreference
// ClusterConfig stores cluster level configuration.
ClusterConfig types.ClusterConfig
// AuditConfig stores cluster audit configuration.
AuditConfig types.ClusterAuditConfig
// NetworkingConfig stores cluster networking configuration.
NetworkingConfig types.ClusterNetworkingConfig
// SessionRecordingConfig stores session recording configuration.
SessionRecordingConfig types.SessionRecordingConfig
// LicenseFile is a full path to the license file
LicenseFile string
// PublicAddrs affects the SSH host principals and DNS names added to the SSH and TLS certs.
PublicAddrs []utils.NetAddr
}
// SSHConfig configures SSH server node role
type SSHConfig struct {
Enabled bool
Addr utils.NetAddr
Namespace string
Shell string
Limiter limiter.Config
Labels map[string]string
CmdLabels services.CommandLabels
PermitUserEnvironment bool
// PAM holds PAM configuration for Teleport.
PAM *pam.Config
// PublicAddrs affects the SSH host principals and DNS names added to the SSH and TLS certs.
PublicAddrs []utils.NetAddr
// BPF holds BPF configuration for Teleport.
BPF *bpf.Config
// ProxyReverseTunnelFallbackAddr optionall specifies the address of the proxy if reverse tunnel
// discovered proxy fails.
// This configuration is not exposed directly but can be set from environment via
// defaults.ProxyFallbackAddrEnvar.
//
// See github.com/gravitational/teleport/issues/4141 for details.
ProxyReverseTunnelFallbackAddr *utils.NetAddr
// AllowTCPForwarding indicates that TCP port forwarding is allowed on this node
AllowTCPForwarding bool
}
// KubeConfig specifies configuration for kubernetes service
type KubeConfig struct {
// Enabled turns kubernetes service role on or off for this process
Enabled bool
// ListenAddr is the address to listen on for incoming kubernetes requests.
// Optional.
ListenAddr *utils.NetAddr
// PublicAddrs is a list of the public addresses the Teleport kubernetes
// service can be reached by the proxy service.
PublicAddrs []utils.NetAddr
// KubeClusterName is the name of a kubernetes cluster this proxy is running
// in. If empty, defaults to the Teleport cluster name.
KubeClusterName string
// KubeconfigPath is a path to kubeconfig
KubeconfigPath string
// Labels are used for RBAC on clusters.
StaticLabels map[string]string
DynamicLabels services.CommandLabels
// Limiter limits the connection and request rates.
Limiter limiter.Config
}
// DatabasesConfig configures the database proxy service.
type DatabasesConfig struct {
// Enabled enables the database proxy service.
Enabled bool
// Databases is a list of databases proxied by this service.
Databases []Database
}
// Database represents a single database that's being proxied.
type Database struct {
// Name is the database name, used to refer to in CLI.
Name string
// Description is a free-form database description.
Description string
// Protocol is the database type, e.g. postgres or mysql.
Protocol string
// URI is the database endpoint to connect to.
URI string
// StaticLabels is a map of database static labels.
StaticLabels map[string]string
// DynamicLabels is a list of database dynamic labels.
DynamicLabels services.CommandLabels
// CACert is an optional database CA certificate.
CACert []byte
// AWS contains AWS specific settings for RDS/Aurora/Redshift databases.
AWS DatabaseAWS
// GCP contains GCP specific settings for Cloud SQL databases.
GCP DatabaseGCP
}
// DatabaseAWS contains AWS specific settings for RDS/Aurora databases.
type DatabaseAWS struct {
// Region is the cloud region database is running in when using AWS RDS.
Region string
// Redshift contains Redshift specific settings.
Redshift DatabaseAWSRedshift
}
// DatabaseAWSRedshift contains AWS Redshift specific settings.
type DatabaseAWSRedshift struct {
// ClusterID is the Redshift cluster identifier.
ClusterID string
}
// DatabaseGCP contains GCP specific settings for Cloud SQL databases.
type DatabaseGCP struct {
// ProjectID is the GCP project ID where the database is deployed.
ProjectID string
// InstanceID is the Cloud SQL instance ID.
InstanceID string
}
// Check validates the database proxy configuration.
func (d *Database) Check() error {
if d.Name == "" {
return trace.BadParameter("empty database name")
}
// Unlike application access proxy, database proxy name doesn't necessarily
// need to be a valid subdomain but use the same validation logic for the
// simplicity and consistency.
if errs := validation.IsDNS1035Label(d.Name); len(errs) > 0 {
return trace.BadParameter("invalid database %q name: %v", d.Name, errs)
}
if !apiutils.SliceContainsStr(defaults.DatabaseProtocols, d.Protocol) {
return trace.BadParameter("unsupported database %q protocol %q, supported are: %v",
d.Name, d.Protocol, defaults.DatabaseProtocols)
}
if _, _, err := net.SplitHostPort(d.URI); err != nil {
return trace.BadParameter("invalid database %q address %q: %v",
d.Name, d.URI, err)
}
if len(d.CACert) != 0 {
if _, err := tlsca.ParseCertificatePEM(d.CACert); err != nil {
return trace.BadParameter("provided database %q CA doesn't appear to be a valid x509 certificate: %v",
d.Name, err)
}
}
// Validate Redshift specific configuration.
if d.AWS.Redshift.ClusterID != "" {
if d.AWS.Region == "" {
return trace.BadParameter("missing AWS region for Redshift database %q", d.Name)
}
}
// Validate Cloud SQL specific configuration.
switch {
case d.GCP.ProjectID != "" && d.GCP.InstanceID == "":
return trace.BadParameter("missing Cloud SQL instance ID for database %q", d.Name)
case d.GCP.ProjectID == "" && d.GCP.InstanceID != "":
return trace.BadParameter("missing Cloud SQL project ID for database %q", d.Name)
case d.GCP.ProjectID != "" && d.GCP.InstanceID != "":
// Only Postgres Cloud SQL instances currently support IAM authentication.
// It's a relatively new feature so we'll be able to enable it once it
// expands to MySQL as well:
// https://cloud.google.com/sql/docs/postgres/authentication
if d.Protocol != defaults.ProtocolPostgres {
return trace.BadParameter("Cloud SQL IAM authentication is currently supported only for PostgreSQL databases, can't use database %q with protocol %q", d.Name, d.Protocol)
}
// TODO(r0mant): See if we can download it automatically similar to RDS:
// https://cloud.google.com/sql/docs/postgres/instance-info#rest-v1beta4
if len(d.CACert) == 0 {
return trace.BadParameter("missing Cloud SQL instance root certificate for database %q", d.Name)
}
}
return nil
}
// AppsConfig configures application proxy service.
type AppsConfig struct {
// Enabled enables application proxying service.
Enabled bool
// DebugApp enabled a header dumping debugging application.
DebugApp bool
// Apps is the list of applications that are being proxied.
Apps []App
}
// App is the specific application that will be proxied by the application
// service. This needs to exist because if the "config" package tries to
// directly create a services.App it will get into circular imports.
type App struct {
// Name of the application.
Name string
// Description is the app description.
Description string
// URI is the internal address of the application.
URI string
// Public address of the application. This is the address users will access
// the application at.
PublicAddr string
// StaticLabels is a map of static labels to apply to this application.
StaticLabels map[string]string
// DynamicLabels is a list of dynamic labels to apply to this application.
DynamicLabels services.CommandLabels
// InsecureSkipVerify is used to skip validating the server's certificate.
InsecureSkipVerify bool
// Rewrite defines a block that is used to rewrite requests and responses.
Rewrite *Rewrite
}
// Check validates an application.
func (a App) Check() error {
if a.Name == "" {
return trace.BadParameter("missing application name")
}
if a.URI == "" {
return trace.BadParameter("missing application %q URI", a.Name)
}
// Check if the application name is a valid subdomain. Don't allow names that
// are invalid subdomains because for trusted clusters the name is used to
// construct the domain that the application will be available at.
if errs := validation.IsDNS1035Label(a.Name); len(errs) > 0 {
return trace.BadParameter("application name %q must be a valid DNS subdomain: https://goteleport.com/teleport/docs/application-access/#application-name", a.Name)
}
// Parse and validate URL.
if _, err := url.Parse(a.URI); err != nil {
return trace.BadParameter("application %q URI invalid: %v", a.Name, err)
}
// If a port was specified or an IP address was provided for the public
// address, return an error.
if a.PublicAddr != "" {
if _, _, err := net.SplitHostPort(a.PublicAddr); err == nil {
return trace.BadParameter("application %q public_addr %q can not contain a port, applications will be available on the same port as the web proxy", a.Name, a.PublicAddr)
}
if net.ParseIP(a.PublicAddr) != nil {
return trace.BadParameter("application %q public_addr %q can not be an IP address, Teleport Application Access uses DNS names for routing", a.Name, a.PublicAddr)
}
}
// Make sure there are no reserved headers in the rewrite configuration.
// They wouldn't be rewritten even if we allowed them here but catch it
// early and let the user know.
if a.Rewrite != nil {
for _, h := range a.Rewrite.Headers {
if app.IsReservedHeader(h.Name) {
return trace.BadParameter("invalid application %q header rewrite configuration: header %q is reserved and can't be rewritten",
a.Name, http.CanonicalHeaderKey(h.Name))
}
}
}
return nil
}
// Rewrite is a list of rewriting rules to apply to requests and responses.
type Rewrite struct {
// Redirect is a list of hosts that should be rewritten to the public address.
Redirect []string
// Headers is a list of extra headers to inject in the request.
Headers []Header
}
// Header represents a single http header passed over to the proxied application.
type Header struct {
// Name is the http header name.
Name string
// Value is the http header value.
Value string
}
// ParseHeader parses the provided string as a http header.
func ParseHeader(header string) (*Header, error) {
parts := strings.SplitN(header, ":", 2)
if len(parts) != 2 {
return nil, trace.BadParameter("failed to parse %q as http header", header)
}
name := strings.TrimSpace(parts[0])
value := strings.TrimSpace(parts[1])
if !httpguts.ValidHeaderFieldName(name) {
return nil, trace.BadParameter("invalid http header name: %q", header)
}
if !httpguts.ValidHeaderFieldValue(value) {
return nil, trace.BadParameter("invalid http header value: %q", header)
}
return &Header{
Name: name,
Value: value,
}, nil
}
// ParseHeaders parses the provided list as http headers.
func ParseHeaders(headers []string) (headersOut []Header, err error) {
for _, header := range headers {
h, err := ParseHeader(header)
if err != nil {
return nil, trace.Wrap(err)
}
headersOut = append(headersOut, *h)
}
return headersOut, nil
}
// MakeDefaultConfig creates a new Config structure and populates it with defaults
func MakeDefaultConfig() (config *Config) {
config = &Config{}
ApplyDefaults(config)
return config
}
// ApplyDefaults applies default values to the existing config structure
func ApplyDefaults(cfg *Config) {
// Get defaults for Cipher, Kex algorithms, and MAC algorithms from
// golang.org/x/crypto/ssh default config.
var sc ssh.Config
sc.SetDefaults()
if cfg.Log == nil {
cfg.Log = utils.NewLogger()
}
// Remove insecure and (borderline insecure) cryptographic primitives from
// default configuration. These can still be added back in file configuration by
// users, but not supported by default by Teleport. See #1856 for more
// details.
kex := utils.RemoveFromSlice(sc.KeyExchanges,
defaults.DiffieHellmanGroup1SHA1,
defaults.DiffieHellmanGroup14SHA1)
macs := utils.RemoveFromSlice(sc.MACs,
defaults.HMACSHA1,
defaults.HMACSHA196)
hostname, err := os.Hostname()
if err != nil {
hostname = "localhost"
cfg.Log.Errorf("Failed to determine hostname: %v.", err)
}
// Global defaults.
cfg.Hostname = hostname
cfg.DataDir = defaults.DataDir
cfg.Console = os.Stdout
cfg.CipherSuites = utils.DefaultCipherSuites()
cfg.Ciphers = sc.Ciphers
cfg.KEXAlgorithms = kex
cfg.MACAlgorithms = macs
// Auth service defaults.
cfg.Auth.Enabled = true
cfg.Auth.SSHAddr = *defaults.AuthListenAddr()
cfg.Auth.StorageConfig.Type = lite.GetName()
cfg.Auth.StorageConfig.Params = backend.Params{defaults.BackendPath: filepath.Join(cfg.DataDir, defaults.BackendDir)}
cfg.Auth.StaticTokens = services.DefaultStaticTokens()
cfg.Auth.ClusterConfig = services.DefaultClusterConfig()
cfg.Auth.AuditConfig = types.DefaultClusterAuditConfig()
cfg.Auth.NetworkingConfig = types.DefaultClusterNetworkingConfig()
cfg.Auth.SessionRecordingConfig = types.DefaultSessionRecordingConfig()
cfg.Auth.Preference = types.DefaultAuthPreference()
defaults.ConfigureLimiter(&cfg.Auth.Limiter)
cfg.Auth.LicenseFile = filepath.Join(cfg.DataDir, defaults.LicenseFile)
// Proxy service defaults.
cfg.Proxy.Enabled = true
cfg.Proxy.SSHAddr = *defaults.ProxyListenAddr()
cfg.Proxy.WebAddr = *defaults.ProxyWebListenAddr()
cfg.Proxy.ReverseTunnelListenAddr = *defaults.ReverseTunnelListenAddr()
defaults.ConfigureLimiter(&cfg.Proxy.Limiter)
// Kubernetes proxy service defaults.
cfg.Proxy.Kube.Enabled = false
cfg.Proxy.Kube.ListenAddr = *defaults.KubeProxyListenAddr()
// SSH service defaults.
cfg.SSH.Enabled = true
cfg.SSH.Shell = defaults.DefaultShell
defaults.ConfigureLimiter(&cfg.SSH.Limiter)
cfg.SSH.PAM = &pam.Config{Enabled: false}
cfg.SSH.BPF = &bpf.Config{Enabled: false}
cfg.SSH.AllowTCPForwarding = true
// Kubernetes service defaults.
cfg.Kube.Enabled = false
defaults.ConfigureLimiter(&cfg.Kube.Limiter)
// Apps service defaults. It's disabled by default.
cfg.Apps.Enabled = false
// Databases proxy service is disabled by default.
cfg.Databases.Enabled = false
}
// ApplyFIPSDefaults updates default configuration to be FedRAMP/FIPS 140-2
// compliant.
func ApplyFIPSDefaults(cfg *Config) {
cfg.FIPS = true
// Update TLS and SSH cryptographic primitives.
cfg.CipherSuites = defaults.FIPSCipherSuites
cfg.Ciphers = defaults.FIPSCiphers
cfg.KEXAlgorithms = defaults.FIPSKEXAlgorithms
cfg.MACAlgorithms = defaults.FIPSMACAlgorithms
// Only SSO based authentication is supported in FIPS mode. The SSO
// provider is where any FedRAMP/FIPS 140-2 compliance (like password
// complexity) should be enforced.
cfg.Auth.Preference.SetAllowLocalAuth(false)
// Update cluster configuration to record sessions at node, this way the
// entire cluster is FedRAMP/FIPS 140-2 compliant.
cfg.Auth.SessionRecordingConfig.SetMode(types.RecordAtNode)
}