Turn AuditConfig into a standalone resource (#6997)

This commit is contained in:
Andrej Tokarčík 2021-06-14 22:49:22 +02:00 committed by GitHub
parent feebcd97c0
commit 3d22eaac0e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
40 changed files with 2604 additions and 1396 deletions

View file

@ -1438,3 +1438,27 @@ func (c *Client) ResetAuthPreference(ctx context.Context) error {
_, err := c.grpc.ResetAuthPreference(ctx, &empty.Empty{})
return trail.FromGRPC(err)
}
// GetClusterAuditConfig gets cluster audit configuration.
func (c *Client) GetClusterAuditConfig(ctx context.Context) (types.ClusterAuditConfig, error) {
resp, err := c.grpc.GetClusterAuditConfig(ctx, &empty.Empty{}, c.callOpts...)
if err != nil {
return nil, trail.FromGRPC(err)
}
return resp, nil
}
// SetClusterAuditConfig sets cluster audit configuration.
func (c *Client) SetClusterAuditConfig(ctx context.Context, auditConfig types.ClusterAuditConfig) error {
auditConfigV2, ok := auditConfig.(*types.ClusterAuditConfigV2)
if !ok {
return trace.BadParameter("invalid type %T", auditConfig)
}
_, err := c.grpc.SetClusterAuditConfig(ctx, auditConfigV2, c.callOpts...)
return trail.FromGRPC(err)
}
// DeleteClusterAuditConfig not implemented: can only be called locally.
func (c *Client) DeleteClusterAuditConfig(ctx context.Context) error {
return trace.NotImplemented(notImplementedMessage)
}

File diff suppressed because it is too large Load diff

View file

@ -84,6 +84,9 @@ message Event {
// AuthPreference is cluster auth preference.
types.AuthPreferenceV2 AuthPreference = 22
[ (gogoproto.jsontag) = "auth_preference,omitempty" ];
// ClusterAuditConfig is a resource for cluster audit configuration.
types.ClusterAuditConfigV2 ClusterAuditConfig = 23
[ (gogoproto.jsontag) = "cluster_audit_config,omitempty" ];
}
}
@ -1099,6 +1102,11 @@ service AuthService {
// DeleteToken deletes an existing token in a backend described by the given request.
rpc DeleteToken(types.ResourceRequest) returns (google.protobuf.Empty);
// GetClusterAuditConfig gets cluster audit configuration.
rpc GetClusterAuditConfig(google.protobuf.Empty) returns (types.ClusterAuditConfigV2);
// SetClusterAuditConfig sets cluster audit configuration.
rpc SetClusterAuditConfig(types.ClusterAuditConfigV2) returns (google.protobuf.Empty);
// GetClusterNetworkingConfig gets cluster networking configuration.
rpc GetClusterNetworkingConfig(google.protobuf.Empty) returns (types.ClusterNetworkingConfigV2);
// SetClusterNetworkingConfig sets cluster networking configuration.

View file

@ -166,6 +166,9 @@ func eventFromGRPC(in proto.Event) (*types.Event, error) {
} else if r := in.GetDatabaseServer(); r != nil {
out.Resource = r
return &out, nil
} else if r := in.GetClusterAuditConfig(); r != nil {
out.Resource = r
return &out, nil
} else if r := in.GetClusterNetworkingConfig(); r != nil {
out.Resource = r
return &out, nil

261
api/types/audit.go Normal file
View file

@ -0,0 +1,261 @@
/*
Copyright 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 types
import (
"time"
"github.com/gravitational/teleport/api/defaults"
"github.com/gravitational/trace"
)
// ClusterAuditConfig defines cluster-wide audit log configuration. This is
// a configuration resource, never create more than one instance of it.
type ClusterAuditConfig interface {
Resource
// Type gets the audit backend type.
Type() string
// SetType sets the audit backend type.
SetType(string)
// Region gets a cloud provider region.
Region() string
// SetRegion sets a cloud provider region.
SetRegion(string)
// ShouldUploadSessions returns whether audit config
// instructs server to upload sessions.
ShouldUploadSessions() bool
// AuditSessionsURI gets the audit sessions URI.
AuditSessionsURI() string
// SetAuditSessionsURI sets the audit sessions URI.
SetAuditSessionsURI(string)
// AuditEventsURIs gets the audit events URIs.
AuditEventsURIs() []string
// SetAuditEventsURIs sets the audit events URIs.
SetAuditEventsURIs([]string)
// EnableContinuousBackups is used to enable (or disable) PITR (Point-In-Time Recovery).
EnableContinuousBackups() bool
// EnableAutoScaling is used to enable (or disable) auto scaling policy.
EnableAutoScaling() bool
// ReadMaxCapacity is the maximum provisioned read capacity.
ReadMaxCapacity() int64
// ReadMinCapacity is the minimum provisioned read capacity.
ReadMinCapacity() int64
// ReadTargetValue is the ratio of consumed read to provisioned capacity.
ReadTargetValue() float64
// WriteMaxCapacity is the maximum provisioned write capacity.
WriteMaxCapacity() int64
// WriteMinCapacity is the minimum provisioned write capacity.
WriteMinCapacity() int64
// WriteTargetValue is the ratio of consumed write to provisioned capacity.
WriteTargetValue() float64
}
// NewClusterAuditConfig is a convenience method to to create ClusterAuditConfigV2.
func NewClusterAuditConfig(spec ClusterAuditConfigSpecV2) (ClusterAuditConfig, error) {
auditConfig := &ClusterAuditConfigV2{
Kind: KindClusterAuditConfig,
Version: V2,
Metadata: Metadata{
Name: MetaNameClusterAuditConfig,
Namespace: defaults.Namespace,
},
Spec: spec,
}
if err := auditConfig.CheckAndSetDefaults(); err != nil {
return nil, trace.Wrap(err)
}
return auditConfig, nil
}
// DefaultClusterAuditConfig returns the default audit log configuration.
func DefaultClusterAuditConfig() ClusterAuditConfig {
config, _ := NewClusterAuditConfig(ClusterAuditConfigSpecV2{})
return config
}
// GetVersion returns resource version.
func (c *ClusterAuditConfigV2) GetVersion() string {
return c.Version
}
// GetName returns the name of the resource.
func (c *ClusterAuditConfigV2) GetName() string {
return c.Metadata.Name
}
// SetName sets the name of the resource.
func (c *ClusterAuditConfigV2) SetName(e string) {
c.Metadata.Name = e
}
// SetExpiry sets expiry time for the object.
func (c *ClusterAuditConfigV2) SetExpiry(expires time.Time) {
c.Metadata.SetExpiry(expires)
}
// Expiry returns object expiry setting.
func (c *ClusterAuditConfigV2) Expiry() time.Time {
return c.Metadata.Expiry()
}
// SetTTL sets Expires header using the provided clock.
// Use SetExpiry instead.
// DELETE IN 7.0.0
func (c *ClusterAuditConfigV2) SetTTL(clock Clock, ttl time.Duration) {
c.Metadata.SetTTL(clock, ttl)
}
// GetMetadata returns object metadata.
func (c *ClusterAuditConfigV2) GetMetadata() Metadata {
return c.Metadata
}
// GetResourceID returns resource ID.
func (c *ClusterAuditConfigV2) GetResourceID() int64 {
return c.Metadata.ID
}
// SetResourceID sets resource ID.
func (c *ClusterAuditConfigV2) SetResourceID(id int64) {
c.Metadata.ID = id
}
// GetKind returns resource kind.
func (c *ClusterAuditConfigV2) GetKind() string {
return c.Kind
}
// GetSubKind returns resource subkind.
func (c *ClusterAuditConfigV2) GetSubKind() string {
return c.SubKind
}
// SetSubKind sets resource subkind.
func (c *ClusterAuditConfigV2) SetSubKind(sk string) {
c.SubKind = sk
}
// Type gets the audit backend type.
func (c *ClusterAuditConfigV2) Type() string {
return c.Spec.Type
}
// SetType sets the audit backend type.
func (c *ClusterAuditConfigV2) SetType(backendType string) {
c.Spec.Type = backendType
}
// Region gets a cloud provider region.
func (c *ClusterAuditConfigV2) Region() string {
return c.Spec.Region
}
// SetRegion sets a cloud provider region.
func (c *ClusterAuditConfigV2) SetRegion(region string) {
c.Spec.Region = region
}
// ShouldUploadSessions returns whether audit config
// instructs server to upload sessions.
func (c *ClusterAuditConfigV2) ShouldUploadSessions() bool {
return c.Spec.AuditSessionsURI != ""
}
// AuditSessionsURI gets the audit sessions URI.
func (c *ClusterAuditConfigV2) AuditSessionsURI() string {
return c.Spec.AuditSessionsURI
}
// SetAuditSessionsURI sets the audit sessions URI.
func (c *ClusterAuditConfigV2) SetAuditSessionsURI(uri string) {
c.Spec.AuditSessionsURI = uri
}
// AuditEventsURIs gets the audit events URIs.
func (c *ClusterAuditConfigV2) AuditEventsURIs() []string {
return c.Spec.AuditEventsURI
}
// SetAuditEventsURIs sets the audit events URIs.
func (c *ClusterAuditConfigV2) SetAuditEventsURIs(uris []string) {
c.Spec.AuditEventsURI = uris
}
// EnableContinuousBackups is used to enable (or disable) PITR (Point-In-Time Recovery).
func (c *ClusterAuditConfigV2) EnableContinuousBackups() bool {
return c.Spec.EnableContinuousBackups
}
// EnableAutoScaling is used to enable (or disable) auto scaling policy.
func (c *ClusterAuditConfigV2) EnableAutoScaling() bool {
return c.Spec.EnableAutoScaling
}
// ReadMaxCapacity is the maximum provisioned read capacity.
func (c *ClusterAuditConfigV2) ReadMaxCapacity() int64 {
return c.Spec.ReadMaxCapacity
}
// ReadMinCapacity is the minimum provisioned read capacity.
func (c *ClusterAuditConfigV2) ReadMinCapacity() int64 {
return c.Spec.ReadMinCapacity
}
// ReadTargetValue is the ratio of consumed read to provisioned capacity.
func (c *ClusterAuditConfigV2) ReadTargetValue() float64 {
return c.Spec.ReadTargetValue
}
// WriteMaxCapacity is the maximum provisioned write capacity.
func (c *ClusterAuditConfigV2) WriteMaxCapacity() int64 {
return c.Spec.WriteMaxCapacity
}
// WriteMinCapacity is the minimum provisioned write capacity.
func (c *ClusterAuditConfigV2) WriteMinCapacity() int64 {
return c.Spec.WriteMinCapacity
}
// WriteTargetValue is the ratio of consumed write to provisioned capacity.
func (c *ClusterAuditConfigV2) WriteTargetValue() float64 {
return c.Spec.WriteTargetValue
}
// setStaticFields sets static resource header and metadata fields.
func (c *ClusterAuditConfigV2) setStaticFields() {
c.Kind = KindClusterAuditConfig
c.Version = V2
c.Metadata.Name = MetaNameClusterAuditConfig
}
// CheckAndSetDefaults verifies the constraints for ClusterAuditConfig.
func (c *ClusterAuditConfigV2) CheckAndSetDefaults() error {
c.setStaticFields()
if err := c.Metadata.CheckAndSetDefaults(); err != nil {
return trace.Wrap(err)
}
return nil
}

View file

@ -37,11 +37,13 @@ type ClusterConfig interface {
// SetClusterID sets the cluster ID
SetClusterID(string)
// GetAuditConfig returns audit settings
GetAuditConfig() AuditConfig
// HasAuditConfig returns true if audit configuration is set.
// DELETE IN 8.0.0
HasAuditConfig() bool
// SetAuditConfig sets audit config
SetAuditConfig(AuditConfig)
// SetAuditConfig sets audit configuration.
// DELETE IN 8.0.0
SetAuditConfig(ClusterAuditConfig) error
// HasNetworkingFields returns true if embedded networking configuration is set.
// DELETE IN 8.0.0
@ -166,16 +168,6 @@ func (c *ClusterConfigV3) SetClusterID(id string) {
c.Spec.ClusterID = id
}
// GetAuditConfig returns audit settings
func (c *ClusterConfigV3) GetAuditConfig() AuditConfig {
return c.Spec.Audit
}
// SetAuditConfig sets audit config
func (c *ClusterConfigV3) SetAuditConfig(cfg AuditConfig) {
c.Spec.Audit = cfg
}
// CheckAndSetDefaults checks validity of all parameters and sets defaults.
func (c *ClusterConfigV3) CheckAndSetDefaults() error {
// make sure we have defaults for all metadata fields
@ -189,6 +181,23 @@ func (c *ClusterConfigV3) CheckAndSetDefaults() error {
return nil
}
// HasAuditConfig returns true if audit configuration is set.
// DELETE IN 8.0.0
func (c *ClusterConfigV3) HasAuditConfig() bool {
return c.Spec.Audit != nil
}
// SetAuditConfig sets audit configuration.
// DELETE IN 8.0.0
func (c *ClusterConfigV3) SetAuditConfig(auditConfig ClusterAuditConfig) error {
auditConfigV2, ok := auditConfig.(*ClusterAuditConfigV2)
if !ok {
return trace.BadParameter("unexpected type %T", auditConfig)
}
c.Spec.Audit = &auditConfigV2.Spec
return nil
}
// HasNetworkingFields returns true if embedded networking configuration is set.
// DELETE IN 8.0.0
func (c *ClusterConfigV3) HasNetworkingFields() bool {
@ -251,9 +260,10 @@ func (c *ClusterConfigV3) SetAuthFields(authPref AuthPreference) error {
return nil
}
// ClearLegacyFields clears embedded legacy fields.
// ClearLegacyFields clears legacy fields.
// DELETE IN 8.0.0
func (c *ClusterConfigV3) ClearLegacyFields() {
c.Spec.Audit = nil
c.Spec.ClusterNetworkingConfigSpecV2 = nil
c.Spec.LegacySessionRecordingConfigSpec = nil
c.Spec.LegacyClusterConfigAuthFields = nil

View file

@ -155,6 +155,13 @@ const (
// MetaNameClusterConfig is the exact name of the cluster config singleton resource.
MetaNameClusterConfig = "cluster-config"
// KindClusterAuditConfig is the resource that holds cluster audit configuration.
KindClusterAuditConfig = "cluster_audit_config"
// MetaNameClusterAuditConfig is the exact name of the singleton resource holding
// cluster audit configuration.
MetaNameClusterAuditConfig = "cluster-audit-config"
// KindClusterNetworkingConfig is the resource that holds cluster networking configuration.
KindClusterNetworkingConfig = "cluster_networking_config"

View file

@ -77,7 +77,7 @@ func DefaultClusterNetworkingConfig() ClusterNetworkingConfig {
// newClusterNetworkingConfigWithLabels is a convenience method to create
// ClusterNetworkingConfigV2 with a specific map of labels.
func newClusterNetworkingConfigWithLabels(spec ClusterNetworkingConfigSpecV2, labels map[string]string) (ClusterNetworkingConfig, error) {
netConfig := ClusterNetworkingConfigV2{
netConfig := &ClusterNetworkingConfigV2{
Kind: KindClusterNetworkingConfig,
Version: V2,
Metadata: Metadata{
@ -91,7 +91,7 @@ func newClusterNetworkingConfigWithLabels(spec ClusterNetworkingConfigSpecV2, la
if err := netConfig.CheckAndSetDefaults(); err != nil {
return nil, trace.Wrap(err)
}
return &netConfig, nil
return netConfig, nil
}
// GetVersion returns resource version.

View file

@ -42,10 +42,6 @@ type SessionRecordingConfig interface {
// SetProxyChecksHostKeys sets if the proxy will check host keys.
SetProxyChecksHostKeys(bool)
// CheckAndSetDefaults sets and default values and then
// verifies the constraints for SessionRecordingConfig.
CheckAndSetDefaults() error
}
// NewSessionRecordingConfigFromConfigFile is a convenience method to create
@ -67,7 +63,7 @@ func DefaultSessionRecordingConfig() SessionRecordingConfig {
// newSessionRecordingConfigWithLabels is a convenience method to create
// SessionRecordingConfigV2 with a specific map of labels.
func newSessionRecordingConfigWithLabels(spec SessionRecordingConfigSpecV2, labels map[string]string) (SessionRecordingConfig, error) {
recConfig := SessionRecordingConfigV2{
recConfig := &SessionRecordingConfigV2{
Kind: KindSessionRecordingConfig,
Version: V2,
Metadata: Metadata{
@ -81,7 +77,7 @@ func newSessionRecordingConfigWithLabels(spec SessionRecordingConfigSpecV2, labe
if err := recConfig.CheckAndSetDefaults(); err != nil {
return nil, trace.Wrap(err)
}
return &recConfig, nil
return recConfig, nil
}
// GetVersion returns resource version.

File diff suppressed because it is too large Load diff

View file

@ -518,7 +518,8 @@ message ClusterConfigSpecV3 {
string ClusterID = 2 [ (gogoproto.jsontag) = "cluster_id" ];
// Audit is a section with audit config
AuditConfig Audit = 4 [ (gogoproto.nullable) = false, (gogoproto.jsontag) = "audit" ];
ClusterAuditConfigSpecV2 Audit = 4
[ (gogoproto.nullable) = true, (gogoproto.jsontag) = "audit,omitempty" ];
// DELETE IN 8.0.0
ClusterNetworkingConfigSpecV2 NetworkingConfig = 11
@ -533,8 +534,27 @@ message ClusterConfigSpecV3 {
[ (gogoproto.nullable) = true, (gogoproto.jsontag) = "", (gogoproto.embed) = true ];
}
// AuditConfig represents audit log settings in the cluster
message AuditConfig {
// ClusterAuditConfigV2 represents audit log settings in the cluster.
message ClusterAuditConfigV2 {
// Kind is a resource kind
string Kind = 1 [ (gogoproto.jsontag) = "kind" ];
// SubKind is an optional resource sub kind, used in some resources
string SubKind = 2 [ (gogoproto.jsontag) = "sub_kind,omitempty" ];
// Version is a resource version
string Version = 3 [ (gogoproto.jsontag) = "version" ];
// Metadata is resource metadata
Metadata Metadata = 4 [ (gogoproto.nullable) = false, (gogoproto.jsontag) = "metadata" ];
// Spec is a ClusterAuditConfig specification
ClusterAuditConfigSpecV2 Spec = 5
[ (gogoproto.nullable) = false, (gogoproto.jsontag) = "spec" ];
}
// ClusterAuditConfigSpecV2 is the actual data we care about
// for ClusterAuditConfig.
message ClusterAuditConfigSpecV2 {
reserved 5;
reserved "audit_table_name";
// Type is audit backend type
string Type = 1 [ (gogoproto.jsontag) = "type,omitempty" ];
// Region is a region setting for audit sessions used by cloud providers
@ -548,14 +568,9 @@ message AuditConfig {
(gogoproto.jsontag) = "audit_events_uri,omitempty",
(gogoproto.customtype) = "github.com/gravitational/teleport/api/types/wrappers.Strings"
];
// AuditTableName is a DB table name used for audits
// Deprecated in favor of AuditEventsURI
// DELETE IN (3.1.0)
string AuditTableName = 5 [ (gogoproto.jsontag) = "audit_table_name,omitempty" ];
// EnableContinuousBackups is used to enable (or disable) PITR (Point-In-Time Recovery).
bool EnableContinuousBackups = 6 [ (gogoproto.jsontag) = "continuous_backups,omitempty" ];
// EnableAutoScaling is used to enable (or disable) auto scaling policy.
bool EnableAutoScaling = 7 [ (gogoproto.jsontag) = "auto_scaling,omitempty" ];
// ReadMaxCapacity is the maximum provisioned read capacity.
@ -695,7 +710,7 @@ message AuthPreferenceSpecV2 {
BoolValue DisconnectExpiredCert = 6 [
(gogoproto.nullable) = true,
(gogoproto.jsontag) = "disconnect_expired_cert,omitempty",
(gogoproto.casttype) = "BoolOption"
(gogoproto.customtype) = "BoolOption"
];
// AllowLocalAuth is true if local authentication is enabled.

View file

@ -256,8 +256,8 @@ func testAuditOn(t *testing.T, suite *integrationTestSuite) {
for _, tt := range tests {
t.Run(tt.comment, func(t *testing.T) {
makeConfig := func() (*testing.T, []string, []*InstanceSecrets, *service.Config) {
clusterConfig, err := types.NewClusterConfig(types.ClusterConfigSpecV3{
Audit: types.AuditConfig{AuditSessionsURI: tt.auditSessionsURI},
auditConfig, err := types.NewClusterAuditConfig(types.ClusterAuditConfigSpecV2{
AuditSessionsURI: tt.auditSessionsURI,
})
require.NoError(t, err)
@ -268,7 +268,7 @@ func testAuditOn(t *testing.T, suite *integrationTestSuite) {
tconf := suite.defaultServiceConfig()
tconf.Auth.Enabled = true
tconf.Auth.ClusterConfig = clusterConfig
tconf.Auth.AuditConfig = auditConfig
tconf.Auth.SessionRecordingConfig = recConfig
tconf.Proxy.Enabled = true
tconf.Proxy.DisableWebService = true

View file

@ -74,6 +74,9 @@ type ReadAccessPoint interface {
// GetClusterConfig returns cluster level configuration.
GetClusterConfig(opts ...services.MarshalOption) (types.ClusterConfig, error)
// GetClusterAuditConfig returns cluster audit configuration.
GetClusterAuditConfig(ctx context.Context, opts ...services.MarshalOption) (types.ClusterAuditConfig, error)
// GetClusterNetworkingConfig returns cluster networking configuration.
GetClusterNetworkingConfig(ctx context.Context, opts ...services.MarshalOption) (types.ClusterNetworkingConfig, error)
@ -180,6 +183,9 @@ type AccessCache interface {
// GetClusterConfig returns cluster level configuration.
GetClusterConfig(opts ...services.MarshalOption) (types.ClusterConfig, error)
// GetClusterAuditConfig returns cluster audit configuration.
GetClusterAuditConfig(ctx context.Context, opts ...services.MarshalOption) (types.ClusterAuditConfig, error)
// GetClusterNetworkingConfig returns cluster networking configuration.
GetClusterNetworkingConfig(ctx context.Context, opts ...services.MarshalOption) (types.ClusterNetworkingConfig, error)

View file

@ -379,11 +379,31 @@ func (a *Server) SetAuditLog(auditLog events.IAuditLog) {
a.IAuditLog = auditLog
}
// GetAuthPreference gets AuthPreference from the backend.
func (a *Server) GetAuthPreference() (types.AuthPreference, error) {
return a.GetCache().GetAuthPreference()
}
// GetClusterConfig gets ClusterConfig from the backend.
func (a *Server) GetClusterConfig(opts ...services.MarshalOption) (types.ClusterConfig, error) {
return a.GetCache().GetClusterConfig(opts...)
}
// GetClusterAuditConfig gets ClusterAuditConfig from the backend.
func (a *Server) GetClusterAuditConfig(ctx context.Context, opts ...services.MarshalOption) (types.ClusterAuditConfig, error) {
return a.GetCache().GetClusterAuditConfig(ctx, opts...)
}
// GetClusterNetworkingConfig gets ClusterNetworkingConfig from the backend.
func (a *Server) GetClusterNetworkingConfig(ctx context.Context, opts ...services.MarshalOption) (types.ClusterNetworkingConfig, error) {
return a.GetCache().GetClusterNetworkingConfig(ctx, opts...)
}
// GetSessionRecordingConfig gets SessionRecordingConfig from the backend.
func (a *Server) GetSessionRecordingConfig(ctx context.Context, opts ...services.MarshalOption) (types.SessionRecordingConfig, error) {
return a.GetCache().GetSessionRecordingConfig(ctx, opts...)
}
// GetClusterName returns the domain name that identifies this authority server.
// Also known as "cluster name"
func (a *Server) GetClusterName(opts ...services.MarshalOption) (types.ClusterName, error) {

View file

@ -77,9 +77,11 @@ type AuthSuite struct {
var _ = Suite(&AuthSuite{})
func (s *AuthSuite) SetUpTest(c *C) {
ctx := context.Background()
var err error
s.dataDir = c.MkDir()
s.bk, err = lite.NewWithConfig(context.TODO(), lite.Config{Path: s.dataDir})
s.bk, err = lite.NewWithConfig(ctx, lite.Config{Path: s.dataDir})
c.Assert(err, IsNil)
clusterName, err := types.NewClusterName(types.ClusterNameSpecV2{
@ -116,10 +118,13 @@ func (s *AuthSuite) SetUpTest(c *C) {
err = s.a.SetAuthPreference(authPreference)
c.Assert(err, IsNil)
err = s.a.SetClusterNetworkingConfig(context.TODO(), types.DefaultClusterNetworkingConfig())
err = s.a.SetClusterAuditConfig(ctx, types.DefaultClusterAuditConfig())
c.Assert(err, IsNil)
err = s.a.SetSessionRecordingConfig(context.TODO(), types.DefaultSessionRecordingConfig())
err = s.a.SetClusterNetworkingConfig(ctx, types.DefaultClusterNetworkingConfig())
c.Assert(err, IsNil)
err = s.a.SetSessionRecordingConfig(ctx, types.DefaultSessionRecordingConfig())
c.Assert(err, IsNil)
err = s.a.SetClusterConfig(services.DefaultClusterConfig())

View file

@ -2260,6 +2260,30 @@ func (a *ServerWithRoles) DeleteAuthPreference(context.Context) error {
return trace.NotImplemented(notImplementedMessage)
}
// GetClusterAuditConfig gets cluster audit configuration.
func (a *ServerWithRoles) GetClusterAuditConfig(ctx context.Context, opts ...services.MarshalOption) (types.ClusterAuditConfig, error) {
if err := a.action(apidefaults.Namespace, types.KindClusterAuditConfig, types.VerbRead); err != nil {
return nil, trace.Wrap(err)
}
return a.authServer.GetClusterAuditConfig(ctx, opts...)
}
// SetClusterAuditConfig sets cluster audit configuration.
func (a *ServerWithRoles) SetClusterAuditConfig(ctx context.Context, auditConfig types.ClusterAuditConfig) error {
if err := a.action(apidefaults.Namespace, types.KindClusterAuditConfig, types.VerbCreate); err != nil {
return trace.Wrap(err)
}
if err := a.action(apidefaults.Namespace, types.KindClusterAuditConfig, types.VerbUpdate); err != nil {
return trace.Wrap(err)
}
return a.authServer.SetClusterAuditConfig(ctx, auditConfig)
}
// DeleteClusterAuditConfig not implemented: can only be called locally.
func (a *ServerWithRoles) DeleteClusterAuditConfig(ctx context.Context) error {
return trace.NotImplemented(notImplementedMessage)
}
// GetClusterNetworkingConfig gets cluster networking configuration.
func (a *ServerWithRoles) GetClusterNetworkingConfig(ctx context.Context, opts ...services.MarshalOption) (types.ClusterNetworkingConfig, error) {
if err := a.action(apidefaults.Namespace, types.KindClusterNetworkingConfig, types.VerbRead); err != nil {

View file

@ -1644,6 +1644,11 @@ func (c *Client) DeleteAuthPreference(context.Context) error {
return trace.NotImplemented(notImplementedMessage)
}
// GetClusterAuditConfig gets cluster audit configuration.
func (c *Client) GetClusterAuditConfig(ctx context.Context, opts ...services.MarshalOption) (types.ClusterAuditConfig, error) {
return c.APIClient.GetClusterAuditConfig(ctx)
}
// GetClusterNetworkingConfig gets cluster networking configuration.
func (c *Client) GetClusterNetworkingConfig(ctx context.Context, opts ...services.MarshalOption) (types.ClusterNetworkingConfig, error) {
return c.APIClient.GetClusterNetworkingConfig(ctx)

View file

@ -399,6 +399,10 @@ func eventToGRPC(ctx context.Context, in types.Event) (*proto.Event, error) {
out.Resource = &proto.Event_DatabaseServer{
DatabaseServer: r,
}
case *types.ClusterAuditConfigV2:
out.Resource = &proto.Event_ClusterAuditConfig{
ClusterAuditConfig: r,
}
case *types.ClusterNetworkingConfigV2:
out.Resource = &proto.Event_ClusterNetworkingConfig{
ClusterNetworkingConfig: r,
@ -2483,6 +2487,35 @@ func (g *GRPCServer) DeleteAllNodes(ctx context.Context, req *types.ResourcesInN
return &empty.Empty{}, nil
}
// GetClusterAuditConfig gets cluster audit configuration.
func (g *GRPCServer) GetClusterAuditConfig(ctx context.Context, _ *empty.Empty) (*types.ClusterAuditConfigV2, error) {
auth, err := g.authenticate(ctx)
if err != nil {
return nil, trace.Wrap(err)
}
auditConfig, err := auth.ServerWithRoles.GetClusterAuditConfig(ctx)
if err != nil {
return nil, trace.Wrap(err)
}
auditConfigV2, ok := auditConfig.(*types.ClusterAuditConfigV2)
if !ok {
return nil, trace.BadParameter("unexpected type %T", auditConfig)
}
return auditConfigV2, nil
}
// SetClusterAuditConfig sets cluster audit configuration.
func (g *GRPCServer) SetClusterAuditConfig(ctx context.Context, auditConfig *types.ClusterAuditConfigV2) (*empty.Empty, error) {
auth, err := g.authenticate(ctx)
if err != nil {
return nil, trace.Wrap(err)
}
if err = auth.ServerWithRoles.SetClusterAuditConfig(ctx, auditConfig); err != nil {
return nil, trace.Wrap(err)
}
return &empty.Empty{}, nil
}
// GetClusterNetworkingConfig gets cluster networking configuration.
func (g *GRPCServer) GetClusterNetworkingConfig(ctx context.Context, _ *empty.Empty) (*types.ClusterNetworkingConfigV2, error) {
auth, err := g.authenticate(ctx)

View file

@ -235,6 +235,11 @@ func NewTestAuthServer(cfg TestAuthServerConfig) (*TestAuthServer, error) {
return nil, trace.Wrap(err)
}
err = srv.AuthServer.SetClusterAuditConfig(ctx, types.DefaultClusterAuditConfig())
if err != nil {
return nil, trace.Wrap(err)
}
err = srv.AuthServer.SetClusterNetworkingConfig(ctx, types.DefaultClusterNetworkingConfig())
if err != nil {
return nil, trace.Wrap(err)

View file

@ -139,6 +139,9 @@ type InitConfig struct {
// ClusterConfig holds cluster level configuration.
ClusterConfig types.ClusterConfig
// ClusterAuditConfig holds cluster audit configuration.
ClusterAuditConfig types.ClusterAuditConfig
// ClusterNetworkingConfig holds cluster networking configuration.
ClusterNetworkingConfig types.ClusterNetworkingConfig
@ -241,6 +244,11 @@ func Init(cfg InitConfig, opts ...ServerOption) (*Server, error) {
log.Infof("Created reverse tunnel: %v.", tunnel)
}
err = asrv.SetClusterAuditConfig(ctx, cfg.ClusterAuditConfig)
if err != nil {
return nil, trace.Wrap(err)
}
err = initSetClusterNetworkingConfig(ctx, asrv, cfg.ClusterNetworkingConfig)
if err != nil {
return nil, trace.Wrap(err)

View file

@ -847,6 +847,7 @@ func setupConfig(t *testing.T) InitConfig {
Backend: bk,
Authority: testauthority.New(),
ClusterConfig: services.DefaultClusterConfig(),
ClusterAuditConfig: types.DefaultClusterAuditConfig(),
ClusterNetworkingConfig: types.DefaultClusterNetworkingConfig(),
SessionRecordingConfig: types.DefaultSessionRecordingConfig(),
ClusterName: clusterName,

View file

@ -262,6 +262,7 @@ func (a *authorizer) authorizeRemoteBuiltinRole(r RemoteBuiltinRole) (*Context,
types.NewRule(types.KindReverseTunnel, services.RO()),
types.NewRule(types.KindTunnelConnection, services.RO()),
types.NewRule(types.KindClusterConfig, services.RO()),
types.NewRule(types.KindClusterAuditConfig, services.RO()),
types.NewRule(types.KindClusterNetworkingConfig, services.RO()),
types.NewRule(types.KindSessionRecordingConfig, services.RO()),
types.NewRule(types.KindKubeService, services.RO()),
@ -330,6 +331,7 @@ func GetCheckerForBuiltinRole(clusterName string, recConfig types.SessionRecordi
types.NewRule(types.KindReverseTunnel, services.RW()),
types.NewRule(types.KindTunnelConnection, services.RO()),
types.NewRule(types.KindClusterConfig, services.RO()),
types.NewRule(types.KindClusterAuditConfig, services.RO()),
types.NewRule(types.KindClusterNetworkingConfig, services.RO()),
types.NewRule(types.KindSessionRecordingConfig, services.RO()),
types.NewRule(types.KindClusterAuthPreference, services.RO()),
@ -354,6 +356,7 @@ func GetCheckerForBuiltinRole(clusterName string, recConfig types.SessionRecordi
types.NewRule(types.KindReverseTunnel, services.RW()),
types.NewRule(types.KindTunnelConnection, services.RO()),
types.NewRule(types.KindClusterConfig, services.RO()),
types.NewRule(types.KindClusterAuditConfig, services.RO()),
types.NewRule(types.KindClusterNetworkingConfig, services.RO()),
types.NewRule(types.KindSessionRecordingConfig, services.RO()),
types.NewRule(types.KindClusterAuthPreference, services.RO()),
@ -381,6 +384,7 @@ func GetCheckerForBuiltinRole(clusterName string, recConfig types.SessionRecordi
types.NewRule(types.KindReverseTunnel, services.RW()),
types.NewRule(types.KindTunnelConnection, services.RO()),
types.NewRule(types.KindClusterConfig, services.RO()),
types.NewRule(types.KindClusterAuditConfig, services.RO()),
types.NewRule(types.KindClusterNetworkingConfig, services.RO()),
types.NewRule(types.KindSessionRecordingConfig, services.RO()),
types.NewRule(types.KindClusterAuthPreference, services.RO()),
@ -418,6 +422,7 @@ func GetCheckerForBuiltinRole(clusterName string, recConfig types.SessionRecordi
types.NewRule(types.KindRole, services.RO()),
types.NewRule(types.KindClusterAuthPreference, services.RO()),
types.NewRule(types.KindClusterConfig, services.RO()),
types.NewRule(types.KindClusterAuditConfig, services.RO()),
types.NewRule(types.KindClusterNetworkingConfig, services.RO()),
types.NewRule(types.KindSessionRecordingConfig, services.RO()),
types.NewRule(types.KindClusterName, services.RO()),
@ -478,6 +483,7 @@ func GetCheckerForBuiltinRole(clusterName string, recConfig types.SessionRecordi
types.NewRule(types.KindRole, services.RO()),
types.NewRule(types.KindClusterAuthPreference, services.RO()),
types.NewRule(types.KindClusterConfig, services.RO()),
types.NewRule(types.KindClusterAuditConfig, services.RO()),
types.NewRule(types.KindClusterNetworkingConfig, services.RO()),
types.NewRule(types.KindSessionRecordingConfig, services.RO()),
types.NewRule(types.KindClusterName, services.RO()),
@ -559,6 +565,7 @@ func GetCheckerForBuiltinRole(clusterName string, recConfig types.SessionRecordi
types.NewRule(types.KindEvent, services.RW()),
types.NewRule(types.KindCertAuthority, services.ReadNoSecrets()),
types.NewRule(types.KindClusterConfig, services.RO()),
types.NewRule(types.KindClusterAuditConfig, services.RO()),
types.NewRule(types.KindClusterNetworkingConfig, services.RO()),
types.NewRule(types.KindSessionRecordingConfig, services.RO()),
types.NewRule(types.KindClusterAuthPreference, services.RO()),

View file

@ -3034,7 +3034,7 @@ func (s *TLSSuite) TestEvents(c *check.C) {
suite.Events(c)
}
// TestEventsClusterConifg test cluster configuration
// TestEventsClusterConfig test cluster configuration
func (s *TLSSuite) TestEventsClusterConfig(c *check.C) {
clt, err := s.server.NewClient(TestBuiltin(types.RoleAdmin))
c.Assert(err, check.IsNil)
@ -3120,17 +3120,15 @@ func (s *TLSSuite) TestEventsClusterConfig(c *check.C) {
},
})
// update cluster config
clusterConfig, err := types.NewClusterConfig(types.ClusterConfigSpecV3{
Audit: types.AuditConfig{
AuditEventsURI: []string{"dynamodb://audit_table_name", "file:///home/log"},
},
// update audit config
auditConfig, err := types.NewClusterAuditConfig(types.ClusterAuditConfigSpecV2{
AuditEventsURI: []string{"dynamodb://audit_table_name", "file:///home/log"},
})
c.Assert(err, check.IsNil)
err = s.server.Auth().SetClusterConfig(clusterConfig)
err = s.server.Auth().SetClusterAuditConfig(ctx, auditConfig)
c.Assert(err, check.IsNil)
clusterConfig, err = s.server.Auth().GetClusterConfig()
clusterConfig, err := s.server.Auth().GetClusterConfig()
c.Assert(err, check.IsNil)
suite.ExpectResource(c, w, 3*time.Second, clusterConfig)

View file

@ -108,6 +108,7 @@ func newTestAuthServer(ctx context.Context, t *testing.T, name ...string) *Serve
a, err := NewServer(authConfig)
require.NoError(t, err)
t.Cleanup(func() { a.Close() })
require.NoError(t, a.SetClusterAuditConfig(ctx, types.DefaultClusterAuditConfig()))
require.NoError(t, a.SetClusterNetworkingConfig(ctx, types.DefaultClusterNetworkingConfig()))
require.NoError(t, a.SetSessionRecordingConfig(ctx, types.DefaultSessionRecordingConfig()))
require.NoError(t, a.SetAuthPreference(types.DefaultAuthPreference()))

View file

@ -189,7 +189,7 @@ type Config struct {
Type string `yaml:"type,omitempty"`
// Params is a generic key/value property bag which allows arbitrary
// falues to be passed to backend
// values to be passed to backend
Params Params `yaml:",inline"`
}

18
lib/cache/cache.go vendored
View file

@ -47,6 +47,7 @@ func ForAuth(cfg Config) Config {
{Kind: types.KindCertAuthority, LoadSecrets: true},
{Kind: types.KindClusterName},
{Kind: types.KindClusterConfig},
{Kind: types.KindClusterAuditConfig},
{Kind: types.KindClusterNetworkingConfig},
{Kind: types.KindClusterAuthPreference},
{Kind: types.KindSessionRecordingConfig},
@ -80,6 +81,7 @@ func ForProxy(cfg Config) Config {
{Kind: types.KindCertAuthority, LoadSecrets: false},
{Kind: types.KindClusterName},
{Kind: types.KindClusterConfig},
{Kind: types.KindClusterAuditConfig},
{Kind: types.KindClusterNetworkingConfig},
{Kind: types.KindClusterAuthPreference},
{Kind: types.KindSessionRecordingConfig},
@ -110,6 +112,7 @@ func ForRemoteProxy(cfg Config) Config {
{Kind: types.KindCertAuthority, LoadSecrets: false},
{Kind: types.KindClusterName},
{Kind: types.KindClusterConfig},
{Kind: types.KindClusterAuditConfig},
{Kind: types.KindClusterNetworkingConfig},
{Kind: types.KindClusterAuthPreference},
{Kind: types.KindSessionRecordingConfig},
@ -139,6 +142,7 @@ func ForOldRemoteProxy(cfg Config) Config {
{Kind: types.KindCertAuthority, LoadSecrets: false},
{Kind: types.KindClusterName},
{Kind: types.KindClusterConfig},
{Kind: types.KindClusterAuditConfig},
{Kind: types.KindClusterNetworkingConfig},
{Kind: types.KindClusterAuthPreference},
{Kind: types.KindSessionRecordingConfig},
@ -165,6 +169,7 @@ func ForNode(cfg Config) Config {
{Kind: types.KindCertAuthority, LoadSecrets: false},
{Kind: types.KindClusterName},
{Kind: types.KindClusterConfig},
{Kind: types.KindClusterAuditConfig},
{Kind: types.KindClusterNetworkingConfig},
{Kind: types.KindClusterAuthPreference},
{Kind: types.KindSessionRecordingConfig},
@ -186,6 +191,7 @@ func ForKubernetes(cfg Config) Config {
{Kind: types.KindCertAuthority, LoadSecrets: false},
{Kind: types.KindClusterName},
{Kind: types.KindClusterConfig},
{Kind: types.KindClusterAuditConfig},
{Kind: types.KindClusterNetworkingConfig},
{Kind: types.KindClusterAuthPreference},
{Kind: types.KindSessionRecordingConfig},
@ -205,6 +211,7 @@ func ForApps(cfg Config) Config {
{Kind: types.KindCertAuthority, LoadSecrets: false},
{Kind: types.KindClusterName},
{Kind: types.KindClusterConfig},
{Kind: types.KindClusterAuditConfig},
{Kind: types.KindClusterNetworkingConfig},
{Kind: types.KindClusterAuthPreference},
{Kind: types.KindSessionRecordingConfig},
@ -225,6 +232,7 @@ func ForDatabases(cfg Config) Config {
{Kind: types.KindCertAuthority, LoadSecrets: false},
{Kind: types.KindClusterName},
{Kind: types.KindClusterConfig},
{Kind: types.KindClusterAuditConfig},
{Kind: types.KindClusterNetworkingConfig},
{Kind: types.KindClusterAuthPreference},
{Kind: types.KindSessionRecordingConfig},
@ -1040,6 +1048,16 @@ func (c *Cache) GetClusterConfig(opts ...services.MarshalOption) (types.ClusterC
return rg.clusterConfig.GetClusterConfig(opts...)
}
// GetClusterAuditConfig gets ClusterAuditConfig from the backend.
func (c *Cache) GetClusterAuditConfig(ctx context.Context, opts ...services.MarshalOption) (types.ClusterAuditConfig, error) {
rg, err := c.read()
if err != nil {
return nil, trace.Wrap(err)
}
defer rg.Release()
return rg.clusterConfig.GetClusterAuditConfig(ctx, opts...)
}
// GetClusterNetworkingConfig gets ClusterNetworkingConfig from the backend.
func (c *Cache) GetClusterNetworkingConfig(ctx context.Context, opts ...services.MarshalOption) (types.ClusterNetworkingConfig, error) {
rg, err := c.read()

View file

@ -842,11 +842,12 @@ func (s *CacheSuite) TestTokens(c *check.C) {
// TestClusterConfig tests cluster configuration
func (s *CacheSuite) TestClusterConfig(c *check.C) {
ctx := context.Background()
p := s.newPackForAuth(c)
defer p.Close()
// DELETE IN 8.0.0
err := p.clusterConfigS.SetClusterNetworkingConfig(context.TODO(), types.DefaultClusterNetworkingConfig())
err := p.clusterConfigS.SetClusterNetworkingConfig(ctx, types.DefaultClusterNetworkingConfig())
c.Assert(err, check.IsNil)
select {
@ -867,8 +868,7 @@ func (s *CacheSuite) TestClusterConfig(c *check.C) {
c.Fatalf("timeout waiting for event")
}
// DELETE IN 8.0.0
err = p.clusterConfigS.SetSessionRecordingConfig(context.TODO(), types.DefaultSessionRecordingConfig())
err = p.clusterConfigS.SetSessionRecordingConfig(ctx, types.DefaultSessionRecordingConfig())
c.Assert(err, check.IsNil)
select {
@ -878,17 +878,25 @@ func (s *CacheSuite) TestClusterConfig(c *check.C) {
c.Fatalf("timeout waiting for event")
}
// update cluster config
clusterConfig, err := types.NewClusterConfig(types.ClusterConfigSpecV3{
Audit: types.AuditConfig{
AuditEventsURI: []string{"dynamodb://audit_table_name", "file:///home/log"},
},
// DELETE IN 8.0.0
auditConfig, err := types.NewClusterAuditConfig(types.ClusterAuditConfigSpecV2{
AuditEventsURI: []string{"dynamodb://audit_table_name", "file:///home/log"},
})
c.Assert(err, check.IsNil)
err = p.clusterConfigS.SetClusterConfig(clusterConfig)
err = p.clusterConfigS.SetClusterAuditConfig(ctx, auditConfig)
c.Assert(err, check.IsNil)
clusterConfig, err = p.clusterConfigS.GetClusterConfig()
select {
case event := <-p.eventsC:
c.Assert(event.Type, check.Equals, EventProcessed)
case <-time.After(time.Second):
c.Fatalf("timeout waiting for event")
}
err = p.clusterConfigS.SetClusterConfig(services.DefaultClusterConfig())
c.Assert(err, check.IsNil)
clusterConfig, err := p.clusterConfigS.GetClusterConfig()
c.Assert(err, check.IsNil)
select {

View file

@ -73,6 +73,11 @@ func setupCollections(c *Cache, watches []types.WatchKind) (map[resourceKind]col
return nil, trace.BadParameter("missing parameter ClusterConfig")
}
collections[resourceKind] = &clusterConfig{watch: watch, Cache: c}
case types.KindClusterAuditConfig:
if c.ClusterConfig == nil {
return nil, trace.BadParameter("missing parameter ClusterConfig")
}
collections[resourceKind] = &clusterAuditConfig{watch: watch, Cache: c}
case types.KindClusterNetworkingConfig:
if c.ClusterConfig == nil {
return nil, trace.BadParameter("missing parameter ClusterConfig")
@ -1761,6 +1766,76 @@ func (c *authPreference) watchKind() types.WatchKind {
return c.watch
}
type clusterAuditConfig struct {
*Cache
watch types.WatchKind
}
func (c *clusterAuditConfig) erase(ctx context.Context) error {
if err := c.clusterConfigCache.DeleteClusterAuditConfig(ctx); err != nil {
if !trace.IsNotFound(err) {
return trace.Wrap(err)
}
}
return nil
}
func (c *clusterAuditConfig) fetch(ctx context.Context) (apply func(ctx context.Context) error, err error) {
var noConfig bool
resource, err := c.ClusterConfig.GetClusterAuditConfig(ctx)
if err != nil {
if !trace.IsNotFound(err) {
return nil, trace.Wrap(err)
}
noConfig = true
}
return func(ctx context.Context) error {
// either zero or one instance exists, so we either erase or
// update, but not both.
if noConfig {
if err := c.erase(ctx); err != nil {
return trace.Wrap(err)
}
return nil
}
c.setTTL(resource)
if err := c.clusterConfigCache.SetClusterAuditConfig(ctx, resource); err != nil {
return trace.Wrap(err)
}
return nil
}, nil
}
func (c *clusterAuditConfig) processEvent(ctx context.Context, event types.Event) error {
switch event.Type {
case types.OpDelete:
err := c.clusterConfigCache.DeleteClusterAuditConfig(ctx)
if err != nil {
if !trace.IsNotFound(err) {
c.Warningf("Failed to delete resource %v.", err)
return trace.Wrap(err)
}
}
case types.OpPut:
resource, ok := event.Resource.(types.ClusterAuditConfig)
if !ok {
return trace.BadParameter("unexpected type %T", event.Resource)
}
c.setTTL(resource)
if err := c.clusterConfigCache.SetClusterAuditConfig(ctx, resource); err != nil {
return trace.Wrap(err)
}
default:
c.Warningf("Skipping unsupported event type %v.", event.Type)
}
return nil
}
func (c *clusterAuditConfig) watchKind() types.WatchKind {
return c.watch
}
type clusterNetworkingConfig struct {
*Cache
watch types.WatchKind

View file

@ -502,16 +502,13 @@ func applyAuthConfig(fc *FileConfig, cfg *service.Config) error {
log.Warnf(warningMessage)
}
auditConfig, err := services.AuditConfigFromObject(fc.Storage.Params)
// Set cluster audit configuration from file configuration.
auditConfigSpec, err := services.ClusterAuditConfigSpecFromObject(fc.Storage.Params)
if err != nil {
return trace.Wrap(err)
}
auditConfig.Type = fc.Storage.Type
// Set cluster-wide configuration from file configuration.
cfg.Auth.ClusterConfig, err = types.NewClusterConfig(types.ClusterConfigSpecV3{
Audit: *auditConfig,
})
auditConfigSpec.Type = fc.Storage.Type
cfg.Auth.AuditConfig, err = types.NewClusterAuditConfig(*auditConfigSpec)
if err != nil {
return trace.Wrap(err)
}

View file

@ -495,6 +495,9 @@ type AuthConfig struct {
// ClusterConfig stores cluster level configuration.
ClusterConfig types.ClusterConfig
// AuditConfig stores cluster audit configuration.
AuditConfig types.ClusterAuditConfig
// NetworkingConfig stores cluster networking configuration.
NetworkingConfig types.ClusterNetworkingConfig
@ -854,6 +857,7 @@ func ApplyDefaults(cfg *Config) {
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()

View file

@ -867,8 +867,8 @@ func adminCreds() (*int, *int, error) {
// initUploadHandler initializes upload handler based on the config settings,
// currently the only upload handler supported is S3
// the call can return trace.NotFound if no upload handler is setup
func initUploadHandler(auditConfig types.AuditConfig, dataDir string) (events.MultipartHandler, error) {
if auditConfig.AuditSessionsURI == "" {
func initUploadHandler(auditConfig types.ClusterAuditConfig, dataDir string) (events.MultipartHandler, error) {
if !auditConfig.ShouldUploadSessions() {
recordsDir := filepath.Join(dataDir, events.RecordsDir)
if err := os.MkdirAll(recordsDir, teleport.SharedDirMode); err != nil {
return nil, trace.ConvertSystemError(err)
@ -888,7 +888,7 @@ func initUploadHandler(auditConfig types.AuditConfig, dataDir string) (events.Mu
}
return wrapper, nil
}
uri, err := utils.ParseSessionsURI(auditConfig.AuditSessionsURI)
uri, err := utils.ParseSessionsURI(auditConfig.AuditSessionsURI())
if err != nil {
return nil, trace.Wrap(err)
}
@ -906,7 +906,7 @@ func initUploadHandler(auditConfig types.AuditConfig, dataDir string) (events.Mu
return handler, nil
case teleport.SchemeS3:
config := s3sessions.Config{}
if err := config.SetFromURL(uri, auditConfig.Region); err != nil {
if err := config.SetFromURL(uri, auditConfig.Region()); err != nil {
return nil, trace.Wrap(err)
}
handler, err := s3sessions.NewHandler(config)
@ -934,22 +934,10 @@ func initUploadHandler(auditConfig types.AuditConfig, dataDir string) (events.Mu
// initExternalLog initializes external storage, if the storage is not
// setup, returns (nil, nil).
func initExternalLog(ctx context.Context, auditConfig types.AuditConfig, log logrus.FieldLogger, backend backend.Backend) (events.IAuditLog, error) {
//
// DELETE IN: 5.0
// We could probably just remove AuditTableName now (its been deprecated for a while), but
// its probably more polite to delete it on a major release transition.
//
if auditConfig.AuditTableName != "" {
log.Warningf("Please note that 'audit_table_name' is deprecated and will be removed in several releases. Use audit_events_uri: '%v://%v' instead.", dynamo.GetName(), auditConfig.AuditTableName)
if len(auditConfig.AuditEventsURI) != 0 {
return nil, trace.BadParameter("Detected configuration specifying 'audit_table_name' and 'audit_events_uri' at the same time. Please migrate your config to use 'audit_events_uri' only.")
}
auditConfig.AuditEventsURI = []string{fmt.Sprintf("%v://%v", dynamo.GetName(), auditConfig.AuditTableName)}
}
func initExternalLog(ctx context.Context, auditConfig types.ClusterAuditConfig, log logrus.FieldLogger, backend backend.Backend) (events.IAuditLog, error) {
var hasNonFileLog bool
var loggers []events.IAuditLog
for _, eventsURI := range auditConfig.AuditEventsURI {
for _, eventsURI := range auditConfig.AuditEventsURIs() {
uri, err := utils.ParseSessionsURI(eventsURI)
if err != nil {
return nil, trace.Wrap(err)
@ -971,15 +959,15 @@ func initExternalLog(ctx context.Context, auditConfig types.AuditConfig, log log
hasNonFileLog = true
cfg := dynamoevents.Config{
Tablename: uri.Host,
Region: auditConfig.Region,
EnableContinuousBackups: auditConfig.EnableContinuousBackups,
EnableAutoScaling: auditConfig.EnableAutoScaling,
ReadMinCapacity: auditConfig.ReadMinCapacity,
ReadMaxCapacity: auditConfig.ReadMaxCapacity,
ReadTargetValue: auditConfig.ReadTargetValue,
WriteMinCapacity: auditConfig.WriteMinCapacity,
WriteMaxCapacity: auditConfig.WriteMaxCapacity,
WriteTargetValue: auditConfig.WriteTargetValue,
Region: auditConfig.Region(),
EnableContinuousBackups: auditConfig.EnableContinuousBackups(),
EnableAutoScaling: auditConfig.EnableAutoScaling(),
ReadMinCapacity: auditConfig.ReadMinCapacity(),
ReadMaxCapacity: auditConfig.ReadMaxCapacity(),
ReadTargetValue: auditConfig.ReadTargetValue(),
WriteMinCapacity: auditConfig.WriteMinCapacity(),
WriteMaxCapacity: auditConfig.WriteMaxCapacity(),
WriteTargetValue: auditConfig.WriteTargetValue(),
}
err = cfg.SetFromURL(uri)
if err != nil {
@ -1022,7 +1010,7 @@ func initExternalLog(ctx context.Context, auditConfig types.AuditConfig, log log
return nil, nil
}
if !services.ShouldUploadSessions(auditConfig) && hasNonFileLog {
if !auditConfig.ShouldUploadSessions() && hasNonFileLog {
// if audit events are being exported, session recordings should
// be exported as well.
return nil, trace.BadParameter("please specify audit_sessions_uri when using external audit backends")
@ -1075,7 +1063,7 @@ func (process *TeleportProcess) initAuthService() error {
process.log.Warn(warningMessage)
}
auditConfig := cfg.Auth.ClusterConfig.GetAuditConfig()
auditConfig := cfg.Auth.AuditConfig
uploadHandler, err = initUploadHandler(
auditConfig, filepath.Join(cfg.DataDir, teleport.LogsDir))
if err != nil {
@ -1164,6 +1152,7 @@ func (process *TeleportProcess) initAuthService() error {
Authority: cfg.Keygen,
ClusterConfiguration: cfg.ClusterConfiguration,
ClusterConfig: cfg.Auth.ClusterConfig,
ClusterAuditConfig: cfg.Auth.AuditConfig,
ClusterNetworkingConfig: cfg.Auth.NetworkingConfig,
SessionRecordingConfig: cfg.Auth.SessionRecordingConfig,
ClusterName: cfg.Auth.ClusterName,

View file

@ -276,9 +276,11 @@ func (s *ServiceTestSuite) TestInitExternalLog(c *check.C) {
cmt := check.Commentf("tt[%v]: %+v", i, tt)
loggers, err := initExternalLog(context.Background(), types.AuditConfig{
auditConfig, err := types.NewClusterAuditConfig(types.ClusterAuditConfigSpecV2{
AuditEventsURI: tt.events,
}, t.Log, backend)
})
c.Assert(err, check.IsNil, cmt)
loggers, err := initExternalLog(context.Background(), auditConfig, t.Log, backend)
if tt.isErr {
c.Assert(err, check.NotNil, cmt)

90
lib/services/audit.go Normal file
View file

@ -0,0 +1,90 @@
/*
Copyright 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 services
import (
"github.com/gravitational/teleport/api/types"
"github.com/gravitational/teleport/lib/utils"
"github.com/gravitational/trace"
)
// ClusterAuditConfigSpecFromObject returns audit config spec from object.
func ClusterAuditConfigSpecFromObject(in interface{}) (*types.ClusterAuditConfigSpecV2, error) {
var cfg types.ClusterAuditConfigSpecV2
if in == nil {
return &cfg, nil
}
if err := utils.ObjectToStruct(in, &cfg); err != nil {
return nil, trace.Wrap(err)
}
return &cfg, nil
}
// UnmarshalClusterAuditConfig unmarshals the ClusterAuditConfig resource from JSON.
func UnmarshalClusterAuditConfig(bytes []byte, opts ...MarshalOption) (types.ClusterAuditConfig, error) {
var auditConfig types.ClusterAuditConfigV2
if len(bytes) == 0 {
return nil, trace.BadParameter("missing resource data")
}
cfg, err := CollectOptions(opts)
if err != nil {
return nil, trace.Wrap(err)
}
if err := utils.FastUnmarshal(bytes, &auditConfig); err != nil {
return nil, trace.BadParameter(err.Error())
}
if err := auditConfig.CheckAndSetDefaults(); err != nil {
return nil, trace.Wrap(err)
}
if cfg.ID != 0 {
auditConfig.SetResourceID(cfg.ID)
}
if !cfg.Expires.IsZero() {
auditConfig.SetExpiry(cfg.Expires)
}
return &auditConfig, nil
}
// MarshalClusterAuditConfig marshals the ClusterAuditConfig resource to JSON.
func MarshalClusterAuditConfig(auditConfig types.ClusterAuditConfig, opts ...MarshalOption) ([]byte, error) {
if err := auditConfig.CheckAndSetDefaults(); err != nil {
return nil, trace.Wrap(err)
}
cfg, err := CollectOptions(opts)
if err != nil {
return nil, trace.Wrap(err)
}
switch auditConfig := auditConfig.(type) {
case *types.ClusterAuditConfigV2:
if !cfg.PreserveResourceID {
// avoid modifying the original object
// to prevent unexpected data races
copy := *auditConfig
copy.SetResourceID(0)
auditConfig = &copy
}
return utils.FastMarshal(auditConfig)
default:
return nil, trace.BadParameter("unrecognized cluster audit config version %T", auditConfig)
}
}

View file

@ -113,11 +113,6 @@ func UnmarshalAuthPreference(bytes []byte, opts ...MarshalOption) (types.AuthPre
return nil, trace.Wrap(err)
}
err = authPreference.CheckAndSetDefaults()
if err != nil {
return nil, trace.Wrap(err)
}
if cfg.ID != 0 {
authPreference.SetResourceID(cfg.ID)
}

View file

@ -38,24 +38,6 @@ func DefaultClusterConfig() types.ClusterConfig {
}
}
// AuditConfigFromObject returns audit config from interface object
func AuditConfigFromObject(in interface{}) (*types.AuditConfig, error) {
var cfg types.AuditConfig
if in == nil {
return &cfg, nil
}
if err := utils.ObjectToStruct(in, &cfg); err != nil {
return nil, trace.Wrap(err)
}
return &cfg, nil
}
// ShouldUploadSessions returns whether audit config
// instructs server to upload sessions
func ShouldUploadSessions(a types.AuditConfig) bool {
return a.AuditSessionsURI != ""
}
// UnmarshalClusterConfig unmarshals the ClusterConfig resource from JSON.
func UnmarshalClusterConfig(bytes []byte, opts ...MarshalOption) (types.ClusterConfig, error) {
var clusterConfig types.ClusterConfigV3

View file

@ -64,6 +64,13 @@ type ClusterConfiguration interface {
// DeleteClusterConfig deletes cluster config resource
DeleteClusterConfig() error
// GetClusterAuditConfig gets ClusterAuditConfig from the backend.
GetClusterAuditConfig(context.Context, ...MarshalOption) (types.ClusterAuditConfig, error)
// SetClusterAuditConfig sets ClusterAuditConfig from the backend.
SetClusterAuditConfig(context.Context, types.ClusterAuditConfig) error
// DeleteClusterAuditConfig deletes ClusterAuditConfig from the backend.
DeleteClusterAuditConfig(ctx context.Context) error
// GetClusterNetworkingConfig gets ClusterNetworkingConfig from the backend.
GetClusterNetworkingConfig(context.Context, ...MarshalOption) (types.ClusterNetworkingConfig, error)
// SetClusterNetworkingConfig sets ClusterNetworkingConfig from the backend.

View file

@ -233,6 +233,17 @@ func (s *ClusterConfigurationService) GetClusterConfig(opts ...services.MarshalO
return nil, trace.Wrap(err)
}
// To ensure backward compatibility, extend the fetched ClusterConfig
// resource with the values that are now stored in ClusterAuditConfig.
// DELETE IN 8.0.0
auditConfig, err := s.GetClusterAuditConfig(context.TODO())
if err != nil {
return nil, trace.Wrap(err)
}
if err := clusterConfig.SetAuditConfig(auditConfig); err != nil {
return nil, trace.Wrap(err)
}
// To ensure backward compatibility, extend the fetched ClusterConfig
// resource with the values that are now stored in ClusterNetworkingConfig.
// DELETE IN 8.0.0
@ -283,6 +294,9 @@ func (s *ClusterConfigurationService) DeleteClusterConfig() error {
// SetClusterConfig sets services.ClusterConfig on the backend.
func (s *ClusterConfigurationService) SetClusterConfig(c types.ClusterConfig) error {
if c.HasAuditConfig() {
return trace.BadParameter("cluster config has legacy audit config, call SetClusterAuditConfig to set these fields")
}
if c.HasNetworkingFields() {
return trace.BadParameter("cluster config has legacy networking fields, call SetClusterNetworkingConfig to set these fields")
}
@ -312,6 +326,50 @@ func (s *ClusterConfigurationService) SetClusterConfig(c types.ClusterConfig) er
return nil
}
// GetClusterAuditConfig gets cluster audit config from the backend.
func (s *ClusterConfigurationService) GetClusterAuditConfig(ctx context.Context, opts ...services.MarshalOption) (types.ClusterAuditConfig, error) {
item, err := s.Get(ctx, backend.Key(clusterConfigPrefix, auditPrefix))
if err != nil {
if trace.IsNotFound(err) {
return nil, trace.NotFound("cluster audit config not found")
}
return nil, trace.Wrap(err)
}
return services.UnmarshalClusterAuditConfig(item.Value, append(opts, services.WithResourceID(item.ID), services.WithExpires(item.Expires))...)
}
// SetClusterAuditConfig sets the cluster audit config on the backend.
func (s *ClusterConfigurationService) SetClusterAuditConfig(ctx context.Context, auditConfig types.ClusterAuditConfig) error {
value, err := services.MarshalClusterAuditConfig(auditConfig)
if err != nil {
return trace.Wrap(err)
}
item := backend.Item{
Key: backend.Key(clusterConfigPrefix, auditPrefix),
Value: value,
ID: auditConfig.GetResourceID(),
}
_, err = s.Put(ctx, item)
if err != nil {
return trace.Wrap(err)
}
return nil
}
// DeleteClusterAuditConfig deletes ClusterAuditConfig from the backend.
func (s *ClusterConfigurationService) DeleteClusterAuditConfig(ctx context.Context) error {
err := s.Delete(ctx, backend.Key(clusterConfigPrefix, auditPrefix))
if err != nil {
if trace.IsNotFound(err) {
return trace.NotFound("cluster audit config not found")
}
return trace.Wrap(err)
}
return nil
}
// GetClusterNetworkingConfig gets cluster networking config from the backend.
func (s *ClusterConfigurationService) GetClusterNetworkingConfig(ctx context.Context, opts ...services.MarshalOption) (types.ClusterNetworkingConfig, error) {
item, err := s.Get(ctx, backend.Key(clusterConfigPrefix, networkingPrefix))
@ -418,6 +476,7 @@ const (
authPrefix = "authentication"
preferencePrefix = "preference"
generalPrefix = "general"
auditPrefix = "audit"
networkingPrefix = "networking"
sessionRecordingPrefix = "session_recording"
)

View file

@ -114,96 +114,87 @@ func (s *ClusterConfigurationSuite) TestSessionRecording(c *check.C) {
}
func (s *ClusterConfigurationSuite) TestAuditConfig(c *check.C) {
// default is to record at the node
clusterConfig, err := types.NewClusterConfig(types.ClusterConfigSpecV3{})
c.Assert(err, check.IsNil)
cfg := clusterConfig.GetAuditConfig()
c.Assert(cfg, check.DeepEquals, types.AuditConfig{})
// update sessions to be recorded at the proxy and check again
in := types.AuditConfig{
Region: "us-west-1",
Type: "dynamodb",
AuditSessionsURI: "file:///home/log",
AuditTableName: "audit_table_name",
AuditEventsURI: []string{"dynamodb://audit_table_name", "file:///home/log"},
}
clusterConfig.SetAuditConfig(in)
out := clusterConfig.GetAuditConfig()
fixtures.DeepCompare(c, out, in)
config := `
testCases := []struct {
spec types.ClusterAuditConfigSpecV2
config string
}{
{
spec: types.ClusterAuditConfigSpecV2{
Region: "us-west-1",
Type: "dynamodb",
AuditSessionsURI: "file:///home/log",
AuditEventsURI: []string{"dynamodb://audit_table_name", "file:///home/log"},
},
config: `
region: 'us-west-1'
type: 'dynamodb'
audit_sessions_uri: file:///home/log
audit_table_name: audit_table_name
audit_events_uri: ['dynamodb://audit_table_name', 'file:///home/log']
`
var data map[string]interface{}
err = yaml.Unmarshal([]byte(config), &data)
c.Assert(err, check.IsNil)
out2, err := services.AuditConfigFromObject(data)
c.Assert(err, check.IsNil)
fixtures.DeepCompare(c, *out2, in)
config = `
`,
},
{
spec: types.ClusterAuditConfigSpecV2{
Region: "us-west-1",
Type: "dir",
AuditSessionsURI: "file:///home/log",
AuditEventsURI: []string{"dynamodb://audit_table_name"},
},
config: `
region: 'us-west-1'
type: 'dir'
audit_sessions_uri: file:///home/log
audit_events_uri: 'dynamodb://audit_table_name'
`
data = nil
err = yaml.Unmarshal([]byte(config), &data)
c.Assert(err, check.IsNil)
`,
},
}
out2, err = services.AuditConfigFromObject(data)
c.Assert(err, check.IsNil)
fixtures.DeepCompare(c, *out2, types.AuditConfig{
for _, tc := range testCases {
in, err := types.NewClusterAuditConfig(tc.spec)
c.Assert(err, check.IsNil)
var data map[string]interface{}
err = yaml.Unmarshal([]byte(tc.config), &data)
c.Assert(err, check.IsNil)
configSpec, err := services.ClusterAuditConfigSpecFromObject(data)
c.Assert(err, check.IsNil)
out, err := types.NewClusterAuditConfig(*configSpec)
c.Assert(err, check.IsNil)
fixtures.DeepCompare(c, out, in)
}
}
func (s *ClusterConfigurationSuite) TestAuditConfigMarshal(c *check.C) {
// single audit_events uri value
auditConfig, err := types.NewClusterAuditConfig(types.ClusterAuditConfigSpecV2{
Region: "us-west-1",
Type: "dir",
Type: "dynamodb",
AuditSessionsURI: "file:///home/log",
AuditEventsURI: []string{"dynamodb://audit_table_name"},
})
}
func (s *ClusterConfigurationSuite) TestClusterConfigMarshal(c *check.C) {
// signle audit_events uri value
clusterConfig, err := types.NewClusterConfig(types.ClusterConfigSpecV3{
Audit: types.AuditConfig{
Region: "us-west-1",
Type: "dynamodb",
AuditSessionsURI: "file:///home/log",
AuditTableName: "audit_table_name",
AuditEventsURI: []string{"dynamodb://audit_table_name"},
},
})
c.Assert(err, check.IsNil)
data, err := services.MarshalClusterConfig(clusterConfig)
data, err := services.MarshalClusterAuditConfig(auditConfig)
c.Assert(err, check.IsNil)
out, err := services.UnmarshalClusterConfig(data)
out, err := services.UnmarshalClusterAuditConfig(data)
c.Assert(err, check.IsNil)
fixtures.DeepCompare(c, clusterConfig, out)
fixtures.DeepCompare(c, auditConfig, out)
// multiple events uri values
clusterConfig, err = types.NewClusterConfig(types.ClusterConfigSpecV3{
Audit: types.AuditConfig{
Region: "us-west-1",
Type: "dynamodb",
AuditSessionsURI: "file:///home/log",
AuditTableName: "audit_table_name",
AuditEventsURI: []string{"dynamodb://audit_table_name", "file:///home/test/log"},
},
auditConfig, err = types.NewClusterAuditConfig(types.ClusterAuditConfigSpecV2{
Region: "us-west-1",
Type: "dynamodb",
AuditSessionsURI: "file:///home/log",
AuditEventsURI: []string{"dynamodb://audit_table_name", "file:///home/test/log"},
})
c.Assert(err, check.IsNil)
data, err = services.MarshalClusterConfig(clusterConfig)
data, err = services.MarshalClusterAuditConfig(auditConfig)
c.Assert(err, check.IsNil)
out, err = services.UnmarshalClusterConfig(data)
out, err = services.UnmarshalClusterAuditConfig(data)
c.Assert(err, check.IsNil)
fixtures.DeepCompare(c, clusterConfig, out)
fixtures.DeepCompare(c, auditConfig, out)
}

View file

@ -68,6 +68,8 @@ func (e *EventsService) NewWatcher(ctx context.Context, watch types.Watch) (type
parser = newStaticTokensParser()
case types.KindClusterConfig:
parser = newClusterConfigParser(e.getClusterConfig)
case types.KindClusterAuditConfig:
parser = newClusterAuditConfigParser()
case types.KindClusterNetworkingConfig:
parser = newClusterNetworkingConfigParser()
case types.KindClusterAuthPreference:
@ -364,6 +366,7 @@ func (p *staticTokensParser) parse(event backend.Event) (types.Resource, error)
func newClusterConfigParser(getClusterConfig getClusterConfigFunc) *clusterConfigParser {
prefixes := [][]byte{
backend.Key(clusterConfigPrefix, generalPrefix),
backend.Key(clusterConfigPrefix, auditPrefix),
backend.Key(clusterConfigPrefix, networkingPrefix),
backend.Key(clusterConfigPrefix, sessionRecordingPrefix),
backend.Key(authPrefix, preferencePrefix, generalPrefix),
@ -406,6 +409,40 @@ func (p *clusterConfigParser) parse(event backend.Event) (types.Resource, error)
}
}
func newClusterAuditConfigParser() *clusterAuditConfigParser {
return &clusterAuditConfigParser{
baseParser: newBaseParser(backend.Key(clusterConfigPrefix, auditPrefix)),
}
}
type clusterAuditConfigParser struct {
baseParser
}
func (p *clusterAuditConfigParser) parse(event backend.Event) (types.Resource, error) {
switch event.Type {
case types.OpDelete:
h, err := resourceHeader(event, types.KindClusterAuditConfig, types.V2, 0)
if err != nil {
return nil, trace.Wrap(err)
}
h.SetName(types.MetaNameClusterAuditConfig)
return h, nil
case types.OpPut:
clusterAuditConfig, err := services.UnmarshalClusterAuditConfig(
event.Item.Value,
services.WithResourceID(event.Item.ID),
services.WithExpires(event.Item.Expires),
)
if err != nil {
return nil, trace.Wrap(err)
}
return clusterAuditConfig, nil
default:
return nil, trace.BadParameter("event %v is not supported", event.Type)
}
}
func newClusterNetworkingConfigParser() *clusterNetworkingConfigParser {
return &clusterNetworkingConfigParser{
baseParser: newBaseParser(backend.Key(clusterConfigPrefix, networkingPrefix)),

View file

@ -1141,6 +1141,16 @@ func CollectOptions(opts ...Option) Options {
// ClusterConfig tests cluster configuration
func (s *ServicesTestSuite) ClusterConfig(c *check.C, opts ...Option) {
auditConfig, err := types.NewClusterAuditConfig(types.ClusterAuditConfigSpecV2{
Region: "us-west-1",
Type: "dynamodb",
AuditSessionsURI: "file:///home/log",
AuditEventsURI: []string{"dynamodb://audit_table_name", "file:///home/log"},
})
c.Assert(err, check.IsNil)
err = s.ConfigS.SetClusterAuditConfig(context.TODO(), auditConfig)
c.Assert(err, check.IsNil)
// DELETE IN 8.0.0
netConfig, err := types.NewClusterNetworkingConfigFromConfigFile(types.ClusterNetworkingConfigSpecV2{
ClientIdleTimeout: types.NewDuration(17 * time.Second),
@ -1167,13 +1177,6 @@ func (s *ServicesTestSuite) ClusterConfig(c *check.C, opts ...Option) {
config, err := types.NewClusterConfig(types.ClusterConfigSpecV3{
ClusterID: "27",
Audit: types.AuditConfig{
Region: "us-west-1",
Type: "dynamodb",
AuditSessionsURI: "file:///home/log",
AuditTableName: "audit_table_name",
AuditEventsURI: []string{"dynamodb://audit_table_name", "file:///home/log"},
},
})
c.Assert(err, check.IsNil)
@ -1183,6 +1186,7 @@ func (s *ServicesTestSuite) ClusterConfig(c *check.C, opts ...Option) {
gotConfig, err := s.ConfigS.GetClusterConfig()
c.Assert(err, check.IsNil)
config.SetResourceID(gotConfig.GetResourceID())
config.SetAuditConfig(auditConfig)
config.SetNetworkingFields(netConfig)
config.SetSessionRecordingFields(recConfig)
config.SetAuthFields(authPref)
@ -1764,7 +1768,11 @@ func (s *ServicesTestSuite) EventsClusterConfig(c *check.C) {
},
crud: func(context.Context) types.Resource {
// DELETE IN 8.0.0
err := s.ConfigS.SetClusterNetworkingConfig(context.TODO(), types.DefaultClusterNetworkingConfig())
err := s.ConfigS.SetClusterAuditConfig(context.TODO(), types.DefaultClusterAuditConfig())
c.Assert(err, check.IsNil)
// DELETE IN 8.0.0
err = s.ConfigS.SetClusterNetworkingConfig(context.TODO(), types.DefaultClusterNetworkingConfig())
c.Assert(err, check.IsNil)
// DELETE IN 8.0.0
@ -1823,6 +1831,31 @@ func (s *ServicesTestSuite) EventsClusterConfig(c *check.C) {
return out
},
},
{
name: "Cluster audit configuration",
kind: types.WatchKind{
Kind: types.KindClusterAuditConfig,
},
crud: func(ctx context.Context) types.Resource {
auditConfig, err := types.NewClusterAuditConfig(types.ClusterAuditConfigSpecV2{
Region: "us-west-1",
Type: "dynamodb",
AuditSessionsURI: "file:///home/log",
AuditEventsURI: []string{"dynamodb://audit_table_name", "file:///home/test/log"},
})
c.Assert(err, check.IsNil)
err = s.ConfigS.SetClusterAuditConfig(ctx, auditConfig)
c.Assert(err, check.IsNil)
out, err := s.ConfigS.GetClusterAuditConfig(ctx)
c.Assert(err, check.IsNil)
err = s.ConfigS.DeleteClusterAuditConfig(ctx)
c.Assert(err, check.IsNil)
return out
},
},
{
name: "Cluster networking configuration",
kind: types.WatchKind{