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

[v15] Enforce optimistic locking for AuthPreferences, ClusterNetworkingConfig, SessionRecordingConfig #39785

Merged
merged 4 commits into from
Mar 27, 2024
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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