Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cluster Configuration #1430

Merged
merged 2 commits into from
Oct 27, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions integration/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,12 @@ func (i *TeleInstance) CreateEx(trustedSecrets []*InstanceSecrets, tconf *servic
tconf = service.MakeDefaultConfig()
}
tconf.DataDir = dataDir
tconf.Auth.ClusterConfig, err = services.NewClusterConfig(services.ClusterConfigSpecV3{
SessionRecording: services.RecordAtNode,
})
if err != nil {
return trace.Wrap(err)
}
tconf.Auth.ClusterName, err = services.NewClusterName(services.ClusterNameSpecV2{
ClusterName: i.Secrets.SiteName,
})
Expand Down
3 changes: 3 additions & 0 deletions lib/auth/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ type AccessPoint interface {
// server / certificate authority (CA)
GetDomainName() (string, error)

// GetClusterConfig returns cluster level configuration.
GetClusterConfig() (services.ClusterConfig, error)

// GetNamespaces returns a list of namespaces
GetNamespaces() ([]services.Namespace, error)

Expand Down
36 changes: 36 additions & 0 deletions lib/auth/apiserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,8 @@ func NewAPIServer(config *APIConfig) http.Handler {
srv.DELETE("/:version/roles/:role", srv.withAuth(srv.deleteRole))

// cluster configuration
srv.GET("/:version/configuration", srv.withAuth(srv.getClusterConfig))
srv.POST("/:version/configuration", srv.withAuth(srv.setClusterConfig))
srv.GET("/:version/configuration/name", srv.withAuth(srv.getClusterName))
srv.POST("/:version/configuration/name", srv.withAuth(srv.setClusterName))
srv.GET("/:version/configuration/static_tokens", srv.withAuth(srv.getStaticTokens))
Expand Down Expand Up @@ -1694,6 +1696,40 @@ func (s *APIServer) deleteRole(auth ClientI, w http.ResponseWriter, r *http.Requ
return message(fmt.Sprintf("role '%v' deleted", role)), nil
}

func (s *APIServer) getClusterConfig(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (interface{}, error) {
cc, err := auth.GetClusterConfig()
if err != nil {
return nil, trace.Wrap(err)
}

return rawMessage(services.GetClusterConfigMarshaler().Marshal(cc, services.WithVersion(version)))
}

type setClusterConfigReq struct {
ClusterConfig json.RawMessage `json:"cluster_config"`
}

func (s *APIServer) setClusterConfig(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (interface{}, error) {
var req setClusterConfigReq

err := httplib.ReadJSON(r, &req)
if err != nil {
return nil, trace.Wrap(err)
}

cc, err := services.GetClusterConfigMarshaler().Unmarshal(req.ClusterConfig)
if err != nil {
return nil, trace.Wrap(err)
}

err = auth.SetClusterConfig(cc)
if err != nil {
return nil, trace.Wrap(err)
}

return message(fmt.Sprintf("cluster config set: %+v", cc)), nil
}

func (s *APIServer) getClusterName(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (interface{}, error) {
cn, err := auth.GetClusterName()
if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion lib/auth/apiserver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ func (s *APISuite) SetUpTest(c *C) {
s.bk, err = boltbk.New(backend.Params{"path": dir})
c.Assert(err, IsNil)

s.alog, err = events.NewAuditLog(dir)
s.alog, err = events.NewAuditLog(dir, true)
c.Assert(err, IsNil)

s.a = NewAuthServer(&InitConfig{
Expand Down
19 changes: 19 additions & 0 deletions lib/auth/auth_with_roles.go
Original file line number Diff line number Diff line change
Expand Up @@ -790,6 +790,25 @@ func (a *AuthWithRoles) DeleteRole(name string) error {
return a.authServer.DeleteRole(name)
}

// GetClusterConfig gets cluster level configuration.
func (a *AuthWithRoles) GetClusterConfig() (services.ClusterConfig, error) {
if err := a.action(defaults.Namespace, services.KindClusterConfig, services.VerbRead); err != nil {
return nil, trace.Wrap(err)
}
return a.authServer.GetClusterConfig()
}

// SetClusterConfig sets cluster level configuration.
func (a *AuthWithRoles) SetClusterConfig(c services.ClusterConfig) error {
if err := a.action(defaults.Namespace, services.KindClusterConfig, services.VerbCreate); err != nil {
return trace.Wrap(err)
}
if err := a.action(defaults.Namespace, services.KindClusterConfig, services.VerbUpdate); err != nil {
return trace.Wrap(err)
}
return a.authServer.SetClusterConfig(c)
}

// GetClusterName gets the name of the cluster.
func (a *AuthWithRoles) GetClusterName() (services.ClusterName, error) {
if err := a.action(defaults.Namespace, services.KindClusterName, services.VerbRead); err != nil {
Expand Down
30 changes: 30 additions & 0 deletions lib/auth/clt.go
Original file line number Diff line number Diff line change
Expand Up @@ -1471,6 +1471,36 @@ func (c *Client) DeleteRole(name string) error {
return trace.Wrap(err)
}

// GetClusterConfig returns cluster level configuration information.
func (c *Client) GetClusterConfig() (services.ClusterConfig, error) {
out, err := c.Get(c.Endpoint("configuration"), url.Values{})
if err != nil {
return nil, trace.Wrap(err)
}

cc, err := services.GetClusterConfigMarshaler().Unmarshal(out.Bytes())
if err != nil {
return nil, trace.Wrap(err)
}

return cc, err
}

// SetClusterConfig sets cluster level configuration information.
func (c *Client) SetClusterConfig(cc services.ClusterConfig) error {
data, err := services.GetClusterConfigMarshaler().Marshal(cc)
if err != nil {
return trace.Wrap(err)
}

_, err = c.PostJSON(c.Endpoint("configuration"), &setClusterConfigReq{ClusterConfig: data})
if err != nil {
return trace.Wrap(err)
}

return nil
}

func (c *Client) GetClusterName() (services.ClusterName, error) {
out, err := c.Get(c.Endpoint("configuration", "name"), url.Values{})
if err != nil {
Expand Down
9 changes: 9 additions & 0 deletions lib/auth/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,9 @@ type InitConfig struct {
// AuthPreference defines the authentication type (local, oidc) and second
// factor (off, otp, u2f) passed in from a configuration file.
AuthPreference services.AuthPreference

// ClusterConfig holds cluster level configuration.
ClusterConfig services.ClusterConfig
}

// Init instantiates and configures an instance of AuthServer
Expand Down Expand Up @@ -151,6 +154,12 @@ func Init(cfg InitConfig) (*AuthServer, *Identity, error) {
log.Infof("[INIT] Created Reverse Tunnel: %v", tunnel)
}

err = asrv.SetClusterConfig(cfg.ClusterConfig)
if err != nil {
return nil, nil, trace.Wrap(err)
}
log.Infof("[INIT] Updating Cluster Configuration: %v", cfg.ClusterConfig)

// cluster name can only be set once. if it has already been set and we are
// trying to update it to something else, hard fail.
err = asrv.SetClusterName(cfg.ClusterName)
Expand Down
1 change: 1 addition & 0 deletions lib/auth/permissions.go
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ func GetCheckerForBuiltinRole(role teleport.Role) (services.AccessChecker, error
services.NewRule(services.KindUser, services.RO()),
services.NewRule(services.KindRole, services.RO()),
services.NewRule(services.KindClusterAuthPreference, services.RO()),
services.NewRule(services.KindClusterConfig, services.RO()),
services.NewRule(services.KindClusterName, services.RO()),
services.NewRule(services.KindStaticTokens, services.RO()),
services.NewRule(services.KindTunnelConnection, services.RW()),
Expand Down
2 changes: 1 addition & 1 deletion lib/auth/tun_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ func (s *TunSuite) SetUpTest(c *C) {
s.bk, err = dir.New(backend.Params{"path": s.dir})
c.Assert(err, IsNil)

s.alog, err = events.NewAuditLog(s.dir)
s.alog, err = events.NewAuditLog(s.dir, true)
c.Assert(err, IsNil)

s.sessionServer, err = session.New(s.bk)
Expand Down
6 changes: 6 additions & 0 deletions lib/config/configuration.go
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,12 @@ func ApplyFileConfig(fc *FileConfig, cfg *service.Config) error {
log.Warnf(warningMessage)
}
}
// read in and set session recording
clusterConfig, err := fc.Auth.SessionRecording.Parse()
if err != nil {
return trace.Wrap(err)
}
cfg.Auth.ClusterConfig = clusterConfig

// apply "ssh_service" section
if fc.SSH.ListenAddress != "" {
Expand Down
51 changes: 32 additions & 19 deletions lib/config/fileconf.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ var (
"kex_algos": false,
"mac_algos": false,
"connector_name": false,
"session_recording": false,
}
)

Expand Down Expand Up @@ -450,24 +451,9 @@ func (s *Service) Disabled() bool {
type Auth struct {
Service `yaml:",inline"`

// DomainName is the name of the CA who manages this cluster
//DomainName string `yaml:"cluster_name,omitempty"`
// ClusterName is the name of the CA who manages this cluster
ClusterName ClusterName `yaml:"cluster_name,omitempty"`

// TrustedClustersFile is a file path to a file containing public CA keys
// of clusters we trust. One key per line, those starting with '#' are comments
// TODO: THIS SETTING IS DEPRECATED
TrustedClusters []TrustedCluster `yaml:"trusted_clusters,omitempty"`

// FOR INTERNAL USE:
// Authorities : 3rd party certificate authorities (CAs) this auth service trusts.
Authorities []Authority `yaml:"authorities,omitempty"`

// FOR INTERNAL USE:
// ReverseTunnels is a list of SSH tunnels to 3rd party proxy services (used to talk
// to 3rd party auth servers we trust)
ReverseTunnels []ReverseTunnel `yaml:"reverse_tunnels,omitempty"`

// StaticTokens are pre-defined host provisioning tokens supplied via config file for
// environments where paranoid security is not needed
//
Expand All @@ -479,17 +465,34 @@ type Auth struct {
// type, second factor type, specific connector information, etc.
Authentication *AuthenticationConfig `yaml:"authentication,omitempty"`

// SessionRecording determines where the session is recorded: node, proxy, or off.
SessionRecording SessionRecording `yaml:"session_recording"`

// FOR INTERNAL USE:
// Authorities : 3rd party certificate authorities (CAs) this auth service trusts.
Authorities []Authority `yaml:"authorities,omitempty"`

// FOR INTERNAL USE:
// ReverseTunnels is a list of SSH tunnels to 3rd party proxy services (used to talk
// to 3rd party auth servers we trust)
ReverseTunnels []ReverseTunnel `yaml:"reverse_tunnels,omitempty"`

// TrustedClustersFile is a file path to a file containing public CA keys
// of clusters we trust. One key per line, those starting with '#' are comments
// Deprecated: Remove in Teleport 2.4.1.
TrustedClusters []TrustedCluster `yaml:"trusted_clusters,omitempty"`

// OIDCConnectors is a list of trusted OpenID Connect Identity providers
// Deprecated: Use OIDC section in Authentication section instead.
// Deprecated: Remove in Teleport 2.4.1.
OIDCConnectors []OIDCConnector `yaml:"oidc_connectors,omitempty"`

// Configuration for "universal 2nd factor"
// Deprecated: Use U2F section in Authentication section instead.
// Deprecated: Remove in Teleport 2.4.1.
U2F U2F `yaml:"u2f,omitempty"`

// DynamicConfig determines when file configuration is pushed to the backend. Setting
// it here overrides defaults.
// TODO: THIS SETTING IS DEPRECATED
// Deprecated: Remove in Teleport 2.4.1.
DynamicConfig *bool `yaml:"dynamic_config,omitempty"`
}

Expand Down Expand Up @@ -616,6 +619,16 @@ func (u *UniversalSecondFactor) Parse() services.U2F {
}
}

// SessionRecording determines where the session is recorded: node, proxy, or off.
type SessionRecording string

// Parse reads session_recording and creates a services.ClusterConfig.
func (s SessionRecording) Parse() (services.ClusterConfig, error) {
return services.NewClusterConfig(services.ClusterConfigSpecV3{
SessionRecording: services.RecordingType(s),
})
}

// SSH is 'ssh_service' section of the config file
type SSH struct {
Service `yaml:",inline"`
Expand Down
Loading