Skip to content

Commit

Permalink
[v15] Enforce optimistic locking for AuthPreferences, ClusterNetworki…
Browse files Browse the repository at this point in the history
…ngConfig, SessionRecordingConfig (#39785)

* Register cluster configuration service (#38734)

Updates the auth gRPC server to include the new clusterconfigv1
service. The api client was also updated to allow interacting
with the new service(cluster audit config not included yet). Nothing
has yet been converted to use the new service, that will come in a
follow up.

The RPC service proto was also updated to fix a typo that was
reverted in #38736.

* Convert SetClusterNetworkingConfig usages to new Create/Update/Upsert API (#39219)

Migrates callers off the deprecated API and onto the new API so that
ClusterNetworkingConfig can be protected via optimistic locking when
appropriate.

* Convert SetAuthPreferences usages to new Create/Update/Upsert API (#38895)

Migrates callers off the deprecated API and onto the new API so that
AuthPreferences can be protected via optimistic locking when appropriate.

* Convert SetSessionRecordingConfig usages to new Create/Update/Upsert API (#39249)

Migrates callers off the deprecated API and onto the new API so
that SessionRecordingConfig can be protected via optimistic locking
when appropriate.
  • Loading branch information
rosstimothy committed Mar 27, 2024
1 parent 0c7d0c9 commit ee79696
Show file tree
Hide file tree
Showing 50 changed files with 1,850 additions and 1,218 deletions.
223 changes: 192 additions & 31 deletions api/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -2720,71 +2720,185 @@ func (c *Client) SearchSessionEvents(ctx context.Context, fromUTC time.Time, toU
return decodedEvents, response.LastKey, nil
}

// ClusterConfigClient returns an unadorned Cluster Configuration client, using the underlying
// Auth gRPC connection.
func (c *Client) ClusterConfigClient() clusterconfigpb.ClusterConfigServiceClient {
return clusterconfigpb.NewClusterConfigServiceClient(c.conn)
}

// GetClusterNetworkingConfig gets cluster networking configuration.
func (c *Client) GetClusterNetworkingConfig(ctx context.Context) (types.ClusterNetworkingConfig, error) {
resp, err := c.grpc.GetClusterNetworkingConfig(ctx, &emptypb.Empty{})
resp, err := c.ClusterConfigClient().GetClusterNetworkingConfig(ctx, &clusterconfigpb.GetClusterNetworkingConfigRequest{})
if err != nil && trace.IsNotImplemented(err) {
resp, err = c.grpc.GetClusterNetworkingConfig(ctx, &emptypb.Empty{})
}
return resp, trace.Wrap(err)
}

// SetClusterNetworkingConfig sets cluster networking configuration.
// Deprecated: Use UpdateClusterNetworkingConfig or UpsertClusterNetworkingConfig instead.
func (c *Client) SetClusterNetworkingConfig(ctx context.Context, netConfig *types.ClusterNetworkingConfigV2) error {
_, err := c.grpc.SetClusterNetworkingConfig(ctx, netConfig)
return trace.Wrap(err)
}

// setClusterNetworkingConfig sets cluster networking configuration.
func (c *Client) setClusterNetworkingConfig(ctx context.Context, netConfig *types.ClusterNetworkingConfigV2) (types.ClusterNetworkingConfig, error) {
_, err := c.grpc.SetClusterNetworkingConfig(ctx, netConfig)
if err != nil {
return nil, trace.Wrap(err)
}
return resp, nil

cfg, err := c.grpc.GetClusterNetworkingConfig(ctx, &emptypb.Empty{})
return cfg, trace.Wrap(err)
}

// SetClusterNetworkingConfig sets cluster networking configuration.
func (c *Client) SetClusterNetworkingConfig(ctx context.Context, netConfig types.ClusterNetworkingConfig) error {
netConfigV2, ok := netConfig.(*types.ClusterNetworkingConfigV2)
// UpdateClusterNetworkingConfig updates an existing cluster networking configuration.
func (c *Client) UpdateClusterNetworkingConfig(ctx context.Context, cfg types.ClusterNetworkingConfig) (types.ClusterNetworkingConfig, error) {
v2, ok := cfg.(*types.ClusterNetworkingConfigV2)
if !ok {
return trace.BadParameter("invalid type %T", netConfig)
return nil, trace.BadParameter("unsupported cluster networking config type %T", cfg)
}
_, err := c.grpc.SetClusterNetworkingConfig(ctx, netConfigV2)
return trace.Wrap(err)

updated, err := c.ClusterConfigClient().UpdateClusterNetworkingConfig(ctx, &clusterconfigpb.UpdateClusterNetworkingConfigRequest{ClusterNetworkConfig: v2})
// TODO(tross) DELETE IN v18.0.0
if trace.IsNotImplemented(err) {
cnc, err := c.setClusterNetworkingConfig(ctx, v2)
return cnc, trace.Wrap(err)
}

return updated, trace.Wrap(err)
}

// UpsertClusterNetworkingConfig creates a new configuration or overwrites the existing cluster networking configuration.
func (c *Client) UpsertClusterNetworkingConfig(ctx context.Context, cfg types.ClusterNetworkingConfig) (types.ClusterNetworkingConfig, error) {
v2, ok := cfg.(*types.ClusterNetworkingConfigV2)
if !ok {
return nil, trace.BadParameter("unsupported cluster networking config type %T", cfg)
}

updated, err := c.ClusterConfigClient().UpsertClusterNetworkingConfig(ctx, &clusterconfigpb.UpsertClusterNetworkingConfigRequest{ClusterNetworkConfig: v2})
// TODO(tross) DELETE IN v18.0.0
if trace.IsNotImplemented(err) {
cnc, err := c.setClusterNetworkingConfig(ctx, v2)
return cnc, trace.Wrap(err)
}

return updated, trace.Wrap(err)
}

// ResetClusterNetworkingConfig resets cluster networking configuration to defaults.
func (c *Client) ResetClusterNetworkingConfig(ctx context.Context) error {
_, err := c.grpc.ResetClusterNetworkingConfig(ctx, &emptypb.Empty{})
_, err := c.ClusterConfigClient().ResetClusterNetworkingConfig(ctx, &clusterconfigpb.ResetClusterNetworkingConfigRequest{})
if err != nil && trace.IsNotImplemented(err) {
_, err := c.grpc.ResetClusterNetworkingConfig(ctx, &emptypb.Empty{})
return trace.Wrap(err)
}

return trace.Wrap(err)
}

// GetSessionRecordingConfig gets session recording configuration.
func (c *Client) GetSessionRecordingConfig(ctx context.Context) (types.SessionRecordingConfig, error) {
resp, err := c.grpc.GetSessionRecordingConfig(ctx, &emptypb.Empty{})
if err != nil {
return nil, trace.Wrap(err)
resp, err := c.ClusterConfigClient().GetSessionRecordingConfig(ctx, &clusterconfigpb.GetSessionRecordingConfigRequest{})
if err != nil && trace.IsNotImplemented(err) {
resp, err = c.grpc.GetSessionRecordingConfig(ctx, &emptypb.Empty{})
}
return resp, nil

return resp, trace.Wrap(err)
}

// SetSessionRecordingConfig sets session recording configuration.
// Deprecated: Use UpdateSessionRecordingConfig or UpsertSessionRecordingConfig instead.
func (c *Client) SetSessionRecordingConfig(ctx context.Context, recConfig types.SessionRecordingConfig) error {
recConfigV2, ok := recConfig.(*types.SessionRecordingConfigV2)
if !ok {
return trace.BadParameter("invalid type %T", recConfig)
}

_, err := c.grpc.SetSessionRecordingConfig(ctx, recConfigV2)
return trace.Wrap(err)
}

// setSessionRecordingConfig sets session recording configuration.
func (c *Client) setSessionRecordingConfig(ctx context.Context, recConfig types.SessionRecordingConfig) (types.SessionRecordingConfig, error) {
recConfigV2, ok := recConfig.(*types.SessionRecordingConfigV2)
if !ok {
return nil, trace.BadParameter("invalid type %T", recConfig)
}

if _, err := c.grpc.SetSessionRecordingConfig(ctx, recConfigV2); err != nil {
return nil, trace.Wrap(err)
}

cfg, err := c.grpc.GetSessionRecordingConfig(ctx, &emptypb.Empty{})
return cfg, trace.Wrap(err)
}

// ResetSessionRecordingConfig resets session recording configuration to defaults.
func (c *Client) ResetSessionRecordingConfig(ctx context.Context) error {
_, err := c.grpc.ResetSessionRecordingConfig(ctx, &emptypb.Empty{})
_, err := c.ClusterConfigClient().ResetSessionRecordingConfig(ctx, &clusterconfigpb.ResetSessionRecordingConfigRequest{})
if err != nil && trace.IsNotImplemented(err) {
_, err := c.grpc.ResetSessionRecordingConfig(ctx, &emptypb.Empty{})
return trace.Wrap(err)
}

return trace.Wrap(err)
}

// GetAuthPreference gets cluster auth preference.
func (c *Client) GetAuthPreference(ctx context.Context) (types.AuthPreference, error) {
pref, err := c.grpc.GetAuthPreference(ctx, &emptypb.Empty{})
if err != nil {
return nil, trace.Wrap(err)
// UpdateSessionRecordingConfig updates an existing session recording configuration.
func (c *Client) UpdateSessionRecordingConfig(ctx context.Context, cfg types.SessionRecordingConfig) (types.SessionRecordingConfig, error) {
v2, ok := cfg.(*types.SessionRecordingConfigV2)
if !ok {
return nil, trace.BadParameter("unsupported session recording config type %T", cfg)
}

// An old server would send PIVSlot instead of HardwareKey.PIVSlot
// TODO(Joerger): DELETE IN 17.0.0
pref.CheckSetPIVSlot()
updated, err := c.ClusterConfigClient().UpdateSessionRecordingConfig(ctx, &clusterconfigpb.UpdateSessionRecordingConfigRequest{SessionRecordingConfig: v2})
// TODO(tross) DELETE IN v18.0.0
if trace.IsNotImplemented(err) {
cfg, err = c.setSessionRecordingConfig(ctx, v2)
return cfg, trace.Wrap(err)
}
return updated, trace.Wrap(err)
}

// UpsertSessionRecordingConfig creates a new configuration or overwrites the existing session recording configuration.
func (c *Client) UpsertSessionRecordingConfig(ctx context.Context, cfg types.SessionRecordingConfig) (types.SessionRecordingConfig, error) {
v2, ok := cfg.(*types.SessionRecordingConfigV2)
if !ok {
return nil, trace.BadParameter("unsupported session recording config type %T", cfg)
}

updated, err := c.ClusterConfigClient().UpsertSessionRecordingConfig(ctx, &clusterconfigpb.UpsertSessionRecordingConfigRequest{SessionRecordingConfig: v2})
// TODO(tross) DELETE IN v18.0.0
if trace.IsNotImplemented(err) {
cfg, err = c.setSessionRecordingConfig(ctx, v2)
return cfg, trace.Wrap(err)
}
return updated, trace.Wrap(err)
}

// GetAuthPreference gets the active cluster auth preference.
func (c *Client) GetAuthPreference(ctx context.Context) (types.AuthPreference, error) {
pref, err := c.ClusterConfigClient().GetAuthPreference(ctx, &clusterconfigpb.GetAuthPreferenceRequest{})
// TODO(tross) DELETE IN v18.0.0
if err != nil && trace.IsNotImplemented(err) {
pref, err = c.grpc.GetAuthPreference(ctx, &emptypb.Empty{})
if err != nil {
return nil, trace.Wrap(err)
}

return pref, nil
// An old server would send PIVSlot instead of HardwareKey.PIVSlot
// TODO(Joerger): DELETE IN 17.0.0
pref.CheckSetPIVSlot()
}

return pref, trace.Wrap(err)
}

// SetAuthPreference sets cluster auth preference.
// SetAuthPreference sets cluster auth preference via the legacy mechanism.
// Deprecated: Use UpdateAuthPreference or UpsertAuthPreference instead.
// TODO(tross) DELETE IN v18.0.0
func (c *Client) SetAuthPreference(ctx context.Context, authPref types.AuthPreference) error {
authPrefV2, ok := authPref.(*types.AuthPreferenceV2)
if !ok {
Expand All @@ -2799,12 +2913,65 @@ func (c *Client) SetAuthPreference(ctx context.Context, authPref types.AuthPrefe
return trace.Wrap(err)
}

// setAuthPreference sets cluster auth preference via the legacy mechanism.
// TODO(tross) DELETE IN v18.0.0
func (c *Client) setAuthPreference(ctx context.Context, authPref *types.AuthPreferenceV2) (types.AuthPreference, error) {
// An old server would expect PIVSlot instead of HardwareKey.PIVSlot
// TODO(Joerger): DELETE IN 17.0.0
authPref.CheckSetPIVSlot()

_, err := c.grpc.SetAuthPreference(ctx, authPref)
if err != nil {
return nil, trace.Wrap(err)
}

pref, err := c.grpc.GetAuthPreference(ctx, &emptypb.Empty{})
return pref, trace.Wrap(err)
}

// ResetAuthPreference resets cluster auth preference to defaults.
func (c *Client) ResetAuthPreference(ctx context.Context) error {
_, err := c.grpc.ResetAuthPreference(ctx, &emptypb.Empty{})
_, err := c.ClusterConfigClient().ResetAuthPreference(ctx, &clusterconfigpb.ResetAuthPreferenceRequest{})
// TODO(tross) DELETE IN v18.0.0
if err != nil && trace.IsNotImplemented(err) {
_, err := c.grpc.ResetAuthPreference(ctx, &emptypb.Empty{})
return trace.Wrap(err)
}
return trace.Wrap(err)
}

// UpdateAuthPreference updates an existing auth preference.
func (c *Client) UpdateAuthPreference(ctx context.Context, p types.AuthPreference) (types.AuthPreference, error) {
v2, ok := p.(*types.AuthPreferenceV2)
if !ok {
return nil, trace.BadParameter("unsupported auth preference type %T", p)
}

updated, err := c.ClusterConfigClient().UpdateAuthPreference(ctx, &clusterconfigpb.UpdateAuthPreferenceRequest{AuthPreference: v2})
// TODO(tross) DELETE IN v18.0.0
if trace.IsNotImplemented(err) {
pref, err := c.setAuthPreference(ctx, v2)
return pref, trace.Wrap(err)
}
return updated, trace.Wrap(err)
}

// UpsertAuthPreference creates a new preference or overwrites the existing auth preference.
func (c *Client) UpsertAuthPreference(ctx context.Context, p types.AuthPreference) (types.AuthPreference, error) {
v2, ok := p.(*types.AuthPreferenceV2)
if !ok {
return nil, trace.BadParameter("unsupported auth preference type %T", p)
}

updated, err := c.ClusterConfigClient().UpsertAuthPreference(ctx, &clusterconfigpb.UpsertAuthPreferenceRequest{AuthPreference: v2})
// TODO(tross) DELETE IN v18.0.0
if trace.IsNotImplemented(err) {
pref, err := c.setAuthPreference(ctx, v2)
return pref, trace.Wrap(err)
}
return updated, trace.Wrap(err)
}

// GetClusterAuditConfig gets cluster audit configuration.
func (c *Client) GetClusterAuditConfig(ctx context.Context) (types.ClusterAuditConfig, error) {
resp, err := c.grpc.GetClusterAuditConfig(ctx, &emptypb.Empty{})
Expand All @@ -2823,12 +2990,6 @@ func (c *Client) GetClusterAccessGraphConfig(ctx context.Context) (*clusterconfi
return rsp.AccessGraph, nil
}

// ClusterConfigClient returns an unadorned Cluster Configuration client, using the underlying
// Auth gRPC connection.
func (c *Client) ClusterConfigClient() clusterconfigpb.ClusterConfigServiceClient {
return clusterconfigpb.NewClusterConfigServiceClient(c.conn)
}

// GetInstaller gets all installer script resources
func (c *Client) GetInstallers(ctx context.Context) ([]types.Installer, error) {
resp, err := c.grpc.GetInstallers(ctx, &emptypb.Empty{})
Expand Down

0 comments on commit ee79696

Please sign in to comment.