diff --git a/tool/tctl/common/edit_command.go b/tool/tctl/common/edit_command.go index 9317db74ce419..5c3b2f9efbdf4 100644 --- a/tool/tctl/common/edit_command.go +++ b/tool/tctl/common/edit_command.go @@ -44,10 +44,11 @@ import ( // EditCommand implements the `tctl edit` command for modifying // Teleport resources. type EditCommand struct { - app *kingpin.Application - cmd *kingpin.CmdClause - config *servicecfg.Config - ref services.Ref + app *kingpin.Application + cmd *kingpin.CmdClause + config *servicecfg.Config + ref services.Ref + confirm bool // Editor is used by tests to inject the editing mechanism // so that different scenarios can be asserted. @@ -61,9 +62,10 @@ func (e *EditCommand) Initialize(app *kingpin.Application, config *servicecfg.Co e.cmd.Arg("resource type/resource name", `Resource to update Type of a resource [for example: rc] Resource name to update - + Example: $ tctl edit rc/remote`).SetValue(&e.ref) + e.cmd.Flag("confirm", "Confirm an unsafe or temporary resource update").Hidden().BoolVar(&e.confirm) } func (e *EditCommand) TryRun(ctx context.Context, cmd string, client *authclient.Client) (bool, error) { @@ -115,6 +117,7 @@ func (e *EditCommand) editResource(ctx context.Context, client *authclient.Clien filename: f.Name(), force: true, withSecrets: true, + confirm: e.confirm, } rc.Initialize(e.app, e.config) diff --git a/tool/tctl/common/resource_command.go b/tool/tctl/common/resource_command.go index 4d4baba819dea..180eff4abaa1d 100644 --- a/tool/tctl/common/resource_command.go +++ b/tool/tctl/common/resource_command.go @@ -715,6 +715,14 @@ func (rc *ResourceCommand) updateAuthPreference(ctx context.Context, client *aut return trace.Wrap(err) } + storedAuthPref, err := client.GetAuthPreference(ctx) + if err != nil { + return trace.Wrap(err) + } + if err := checkUpdateResourceWithOrigin(storedAuthPref, "cluster auth preference", rc.confirm); err != nil { + return trace.Wrap(err) + } + if _, err := client.UpdateAuthPreference(ctx, newAuthPref); err != nil { return trace.Wrap(err) } @@ -751,6 +759,14 @@ func (rc *ResourceCommand) updateClusterNetworkingConfig(ctx context.Context, cl return trace.Wrap(err) } + storedNetConfig, err := client.GetClusterNetworkingConfig(ctx) + if err != nil { + return trace.Wrap(err) + } + if err := checkUpdateResourceWithOrigin(storedNetConfig, "cluster networking configuration", rc.confirm); err != nil { + return trace.Wrap(err) + } + if _, err := client.UpdateClusterNetworkingConfig(ctx, newNetConfig); err != nil { return trace.Wrap(err) } @@ -809,6 +825,14 @@ func (rc *ResourceCommand) updateSessionRecordingConfig(ctx context.Context, cli return trace.Wrap(err) } + storedRecConfig, err := client.GetSessionRecordingConfig(ctx) + if err != nil { + return trace.Wrap(err) + } + if err := checkUpdateResourceWithOrigin(storedRecConfig, "session recording configuration", rc.confirm); err != nil { + return trace.Wrap(err) + } + if _, err := client.UpdateSessionRecordingConfig(ctx, newRecConfig); err != nil { return trace.Wrap(err) } @@ -3165,10 +3189,15 @@ func checkCreateResourceWithOrigin(storedRes types.ResourceWithOrigin, resDesc s if exists := (storedRes.Origin() != types.OriginDefaults); exists && !force { return trace.AlreadyExists("non-default %s already exists", resDesc) } - if managedByStatic := (storedRes.Origin() == types.OriginConfigFile); managedByStatic && !confirm { + return checkUpdateResourceWithOrigin(storedRes, resDesc, confirm) +} + +func checkUpdateResourceWithOrigin(storedRes types.ResourceWithOrigin, resDesc string, confirm bool) error { + managedByStatic := storedRes.Origin() == types.OriginConfigFile + if managedByStatic && !confirm { return trace.BadParameter(`The %s resource is managed by static configuration. We recommend removing configuration from teleport.yaml, restarting the servers and trying this command again. -If you would still like to proceed, re-run the command with both --force and --confirm flags.`, resDesc) +If you would still like to proceed, re-run the command with the --confirm flag.`, resDesc) } return nil }