diff --git a/lib/autoupdate/agent/installer.go b/lib/autoupdate/agent/installer.go index eded3363c93e3..ae25003e7f639 100644 --- a/lib/autoupdate/agent/installer.go +++ b/lib/autoupdate/agent/installer.go @@ -82,7 +82,7 @@ type LocalInstaller struct { // ReservedFreeInstallDisk is the amount of disk that must remain free in the install directory. ReservedFreeInstallDisk uint64 // TransformService transforms the systemd service during copying. - TransformService func(cfg []byte, pathDir string) []byte + TransformService func(cfg []byte, pathDir string, flags autoupdate.InstallFlags) []byte // ValidateBinary returns true if a file is a linkable binary, or // false if a file should not be linked. ValidateBinary func(ctx context.Context, path string) (bool, error) @@ -417,8 +417,7 @@ func (li *LocalInstaller) Link(ctx context.Context, rev Revision, pathDir string revert, err = li.forceLinks(ctx, filepath.Join(versionDir, "bin"), filepath.Join(versionDir, serviceDir, serviceName), - pathDir, - force, + pathDir, force, rev.Flags, ) if err != nil { return revert, trace.Wrap(err) @@ -431,7 +430,9 @@ func (li *LocalInstaller) Link(ctx context.Context, rev Revision, pathDir string // The revert function restores the previous linking. // See Installer interface for additional specs. func (li *LocalInstaller) LinkSystem(ctx context.Context) (revert func(context.Context) bool, err error) { - revert, err = li.forceLinks(ctx, li.SystemBinDir, li.SystemServiceFile, defaultPathDir, false) + // The system package service file is always removed without flags, so pass + // no flags here to match the behavior. + revert, err = li.forceLinks(ctx, li.SystemBinDir, li.SystemServiceFile, defaultPathDir, false, 0) return revert, trace.Wrap(err) } @@ -446,7 +447,7 @@ func (li *LocalInstaller) TryLink(ctx context.Context, revision Revision, pathDi return trace.Wrap(li.tryLinks(ctx, filepath.Join(versionDir, "bin"), filepath.Join(versionDir, serviceDir, serviceName), - pathDir, + pathDir, revision.Flags, )) } @@ -454,7 +455,9 @@ func (li *LocalInstaller) TryLink(ctx context.Context, revision Revision, pathDi // no installation of Teleport is already linked or partially linked. // See Installer interface for additional specs. func (li *LocalInstaller) TryLinkSystem(ctx context.Context) error { - return trace.Wrap(li.tryLinks(ctx, li.SystemBinDir, li.SystemServiceFile, defaultPathDir)) + // The system package service file is always removed without flags, so pass + // no flags here to match the behavior. + return trace.Wrap(li.tryLinks(ctx, li.SystemBinDir, li.SystemServiceFile, defaultPathDir, 0)) } // Unlink unlinks a version from pathDir and TargetServiceFile. @@ -467,14 +470,16 @@ func (li *LocalInstaller) Unlink(ctx context.Context, rev Revision, pathDir stri return trace.Wrap(li.removeLinks(ctx, filepath.Join(versionDir, "bin"), filepath.Join(versionDir, serviceDir, serviceName), - pathDir, + pathDir, rev.Flags, )) } // UnlinkSystem unlinks the system (package) version from defaultPathDir and TargetServiceFile. // See Installer interface for additional specs. func (li *LocalInstaller) UnlinkSystem(ctx context.Context) error { - return trace.Wrap(li.removeLinks(ctx, li.SystemBinDir, li.SystemServiceFile, defaultPathDir)) + // The system package service file is always linked without flags, so pass + // no flags here to match the behavior. + return trace.Wrap(li.removeLinks(ctx, li.SystemBinDir, li.SystemServiceFile, defaultPathDir, 0)) } // symlink from oldname to newname @@ -495,7 +500,7 @@ type smallFile struct { // If successful, forceLinks may also be reverted after it returns by calling revert. // The revert function returns true if reverting succeeds. // If force is true, non-link files will be overwritten. -func (li *LocalInstaller) forceLinks(ctx context.Context, srcBinDir, srcSvcFile, dstBinDir string, force bool) (revert func(context.Context) bool, err error) { +func (li *LocalInstaller) forceLinks(ctx context.Context, srcBinDir, srcSvcFile, dstBinDir string, force bool, flags autoupdate.InstallFlags) (revert func(context.Context) bool, err error) { // setup revert function var ( revertLinks []symlink @@ -585,7 +590,7 @@ func (li *LocalInstaller) forceLinks(ctx context.Context, srcBinDir, srcSvcFile, // create systemd service file - orig, err := li.forceCopyService(li.TargetServiceFile, srcSvcFile, maxServiceFileSize, dstBinDir) + orig, err := li.forceCopyService(li.TargetServiceFile, srcSvcFile, maxServiceFileSize, dstBinDir, flags) if err != nil && !errors.Is(err, os.ErrExist) { return revert, trace.Wrap(err, "failed to copy service") } @@ -598,12 +603,12 @@ func (li *LocalInstaller) forceLinks(ctx context.Context, srcBinDir, srcSvcFile, // forceCopyService uses forceCopy to copy a systemd service file from src to dst. // The contents of both src and dst must be smaller than n. // See forceCopy for more details. -func (li *LocalInstaller) forceCopyService(dst, src string, n int64, dstBinDir string) (orig *smallFile, err error) { +func (li *LocalInstaller) forceCopyService(dst, src string, n int64, dstBinDir string, flags autoupdate.InstallFlags) (orig *smallFile, err error) { srcData, err := readFileAtMost(src, n) if err != nil { return nil, trace.Wrap(err) } - return forceCopy(dst, li.TransformService(srcData, dstBinDir), n) + return forceCopy(dst, li.TransformService(srcData, dstBinDir, flags), n) } // forceLink attempts to create a symlink, atomically replacing an existing link if already present. @@ -675,7 +680,7 @@ func readFileAtMost(name string, n int64) ([]byte, error) { return data, trace.Wrap(err) } -func (li *LocalInstaller) removeLinks(ctx context.Context, srcBinDir, srcSvcFile, dstBinDir string) error { +func (li *LocalInstaller) removeLinks(ctx context.Context, srcBinDir, srcSvcFile, dstBinDir string, flags autoupdate.InstallFlags) error { removeService := false entries, err := os.ReadDir(srcBinDir) if err != nil { @@ -726,7 +731,7 @@ func (li *LocalInstaller) removeLinks(ctx context.Context, srcBinDir, srcSvcFile if err != nil { return trace.Wrap(err) } - if !bytes.Equal(li.TransformService(srcBytes, dstBinDir), dstBytes) { + if !bytes.Equal(li.TransformService(srcBytes, dstBinDir, flags), dstBytes) { li.Log.WarnContext(ctx, "Removed teleport binary link, but skipping removal of custom teleport.service: the service file does not match the reference file for this version. The file might have been manually edited.") return nil } @@ -740,7 +745,7 @@ func (li *LocalInstaller) removeLinks(ctx context.Context, srcBinDir, srcSvcFile // Existing links that point to files outside binDir or svcDir, as well as existing non-link files, will error. // tryLinks will not attempt to create any links if linking could result in an error. // However, concurrent changes to links may result in an error with partially-complete linking. -func (li *LocalInstaller) tryLinks(ctx context.Context, srcBinDir, srcSvcFile, dstBinDir string) error { +func (li *LocalInstaller) tryLinks(ctx context.Context, srcBinDir, srcSvcFile, dstBinDir string, flags autoupdate.InstallFlags) error { // ensure source directory exists entries, err := os.ReadDir(srcBinDir) if errors.Is(err, os.ErrNotExist) { @@ -798,7 +803,7 @@ func (li *LocalInstaller) tryLinks(ctx context.Context, srcBinDir, srcSvcFile, d } // if any binaries are linked from srcBinDir, always link the service from svcDir - _, err = li.forceCopyService(li.TargetServiceFile, srcSvcFile, maxServiceFileSize, dstBinDir) + _, err = li.forceCopyService(li.TargetServiceFile, srcSvcFile, maxServiceFileSize, dstBinDir, flags) if err != nil && !errors.Is(err, os.ErrExist) { return trace.Wrap(err, "failed to copy service") } diff --git a/lib/autoupdate/agent/installer_test.go b/lib/autoupdate/agent/installer_test.go index 1ab6d0e637d53..80276d90e416d 100644 --- a/lib/autoupdate/agent/installer_test.go +++ b/lib/autoupdate/agent/installer_test.go @@ -425,7 +425,7 @@ func TestLocalInstaller_Link(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { versionsDir := t.TempDir() - versionDir := filepath.Join(versionsDir, version) + versionDir := filepath.Join(versionsDir, version+"_ent") err := os.MkdirAll(versionDir, 0o755) require.NoError(t, err) @@ -459,14 +459,14 @@ func TestLocalInstaller_Link(t *testing.T) { InstallDir: versionsDir, TargetServiceFile: filepath.Join(linkDir, serviceDir, serviceName), Log: slog.Default(), - TransformService: func(b []byte, pathDir string) []byte { - return []byte(fmt.Sprintf("[service=%s][path=%s]", string(b), pathDir)) + TransformService: func(b []byte, pathDir string, flags autoupdate.InstallFlags) []byte { + return []byte(fmt.Sprintf("[service=%s][path=%s][flags=%s]", string(b), pathDir, flags.Strings())) }, ValidateBinary: validator.IsExecutable, Template: autoupdate.DefaultCDNURITemplate, } ctx := context.Background() - revert, err := installer.Link(ctx, NewRevision(version, 0), filepath.Join(linkDir, "bin"), tt.force) + revert, err := installer.Link(ctx, NewRevision(version, autoupdate.FlagEnterprise), filepath.Join(linkDir, "bin"), tt.force) if tt.errMatch != "" { require.Error(t, err) assert.Contains(t, err.Error(), tt.errMatch) @@ -499,7 +499,7 @@ func TestLocalInstaller_Link(t *testing.T) { for _, svc := range tt.resultServices { v, err := os.ReadFile(filepath.Join(linkDir, svc)) require.NoError(t, err) - require.Equal(t, fmt.Sprintf("[service=%s][path=%s]", filepath.Base(svc), filepath.Join(linkDir, "bin")), string(v)) + require.Equal(t, fmt.Sprintf("[service=%s][path=%s][flags=[Enterprise]]", filepath.Base(svc), filepath.Join(linkDir, "bin")), string(v)) } // verify manual revert @@ -680,7 +680,7 @@ func TestLocalInstaller_TryLink(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { versionsDir := t.TempDir() - versionDir := filepath.Join(versionsDir, version) + versionDir := filepath.Join(versionsDir, version+"_ent") err := os.MkdirAll(versionDir, 0o755) require.NoError(t, err) @@ -714,13 +714,13 @@ func TestLocalInstaller_TryLink(t *testing.T) { InstallDir: versionsDir, TargetServiceFile: filepath.Join(linkDir, serviceDir, serviceName), Log: slog.Default(), - TransformService: func(b []byte, pathDir string) []byte { - return []byte(fmt.Sprintf("[service=%s][path=%s]", string(b), pathDir)) + TransformService: func(b []byte, pathDir string, flags autoupdate.InstallFlags) []byte { + return []byte(fmt.Sprintf("[service=%s][path=%s][flags=%s]", string(b), pathDir, flags.Strings())) }, ValidateBinary: validator.IsExecutable, } ctx := context.Background() - err = installer.TryLink(ctx, NewRevision(version, 0), filepath.Join(linkDir, "bin")) + err = installer.TryLink(ctx, NewRevision(version, autoupdate.FlagEnterprise), filepath.Join(linkDir, "bin")) if tt.errMatch != "" { require.Error(t, err) assert.Contains(t, err.Error(), tt.errMatch) @@ -749,7 +749,7 @@ func TestLocalInstaller_TryLink(t *testing.T) { for _, svc := range tt.resultServices { v, err := os.ReadFile(filepath.Join(linkDir, svc)) require.NoError(t, err) - require.Equal(t, fmt.Sprintf("[service=%s][path=%s]", filepath.Base(svc), filepath.Join(linkDir, "bin")), string(v)) + require.Equal(t, fmt.Sprintf("[service=%s][path=%s][flags=[Enterprise]]", filepath.Base(svc), filepath.Join(linkDir, "bin")), string(v)) } }) @@ -851,8 +851,8 @@ func TestLocalInstaller_Remove(t *testing.T) { InstallDir: versionsDir, TargetServiceFile: filepath.Join(linkDir, serviceDir, serviceName), Log: slog.Default(), - TransformService: func(b []byte, pathDir string) []byte { - return []byte(fmt.Sprintf("[service=%s][path=%s]", string(b), pathDir)) + TransformService: func(b []byte, pathDir string, flags autoupdate.InstallFlags) []byte { + return []byte(fmt.Sprintf("[service=%s][path=%s][flags=%s]", string(b), pathDir, flags.Strings())) }, ValidateBinary: validator.IsExecutable, } @@ -864,7 +864,7 @@ func TestLocalInstaller_Remove(t *testing.T) { return } require.NoError(t, err) - _, err = os.Stat(filepath.Join(versionDir, "bin", tt.removeVersion)) + _, err = os.Stat(filepath.Join(versionsDir, tt.removeVersion)) require.ErrorIs(t, err, os.ErrNotExist) }) } @@ -921,8 +921,8 @@ func TestLocalInstaller_IsLinked(t *testing.T) { InstallDir: versionsDir, TargetServiceFile: filepath.Join(linkDir, serviceDir, serviceName), Log: slog.Default(), - TransformService: func(b []byte, pathDir string) []byte { - return []byte(fmt.Sprintf("[service=%s][path=%s]", string(b), pathDir)) + TransformService: func(b []byte, pathDir string, flags autoupdate.InstallFlags) []byte { + return []byte(fmt.Sprintf("[service=%s][path=%s][flags=%s]", string(b), pathDir, flags.Strings())) }, ValidateBinary: validator.IsExecutable, } @@ -981,7 +981,7 @@ func TestLocalInstaller_Unlink(t *testing.T) { {oldname: "bin/teleport", newname: "bin/teleport"}, {oldname: "bin/tsh", newname: "bin/tsh"}, }, - svcCopy: []byte("[service=orig][path=bin]"), + svcCopy: []byte("[service=orig][path=bin][flags=[]]"), }, { name: "different services", @@ -1021,7 +1021,7 @@ func TestLocalInstaller_Unlink(t *testing.T) { links: []symlink{ {oldname: "bin/tsh", newname: "bin/tsh"}, }, - svcCopy: []byte("[service=orig][path=bin]"), + svcCopy: []byte("[service=orig][path=bin][flags=[]]"), remaining: []string{servicePath}, }, { @@ -1031,7 +1031,7 @@ func TestLocalInstaller_Unlink(t *testing.T) { links: []symlink{ {oldname: "bin/teleport", newname: "bin/teleport"}, }, - svcCopy: []byte("[service=orig][path=bin]"), + svcCopy: []byte("[service=orig][path=bin][flags=[]]"), }, { name: "wrong teleport link", @@ -1041,7 +1041,7 @@ func TestLocalInstaller_Unlink(t *testing.T) { {oldname: "other", newname: "bin/teleport"}, {oldname: "bin/tsh", newname: "bin/tsh"}, }, - svcCopy: []byte("[service=orig][path=bin]"), + svcCopy: []byte("[service=orig][path=bin][flags=[]]"), remaining: []string{servicePath, "bin/teleport"}, }, { @@ -1052,7 +1052,7 @@ func TestLocalInstaller_Unlink(t *testing.T) { {oldname: "bin/teleport", newname: "bin/teleport"}, {oldname: "wrong", newname: "bin/tsh"}, }, - svcCopy: []byte("[service=orig][path=bin]"), + svcCopy: []byte("[service=orig][path=bin][flags=[]]"), remaining: []string{"bin/tsh"}, }, } @@ -1107,8 +1107,8 @@ func TestLocalInstaller_Unlink(t *testing.T) { InstallDir: versionsDir, TargetServiceFile: filepath.Join(linkDir, serviceDir, serviceName), Log: slog.Default(), - TransformService: func(b []byte, pathDir string) []byte { - return []byte(fmt.Sprintf("[service=%s][path=%s]", string(b), filepath.Base(pathDir))) + TransformService: func(b []byte, pathDir string, flags autoupdate.InstallFlags) []byte { + return []byte(fmt.Sprintf("[service=%s][path=%s][flags=%s]", string(b), filepath.Base(pathDir), flags.Strings())) }, } ctx := context.Background() diff --git a/lib/autoupdate/agent/setup.go b/lib/autoupdate/agent/setup.go index 2161fbff8be32..732471aba9be1 100644 --- a/lib/autoupdate/agent/setup.go +++ b/lib/autoupdate/agent/setup.go @@ -34,6 +34,7 @@ import ( "github.com/gravitational/trace" "gopkg.in/yaml.v3" + "github.com/gravitational/teleport/lib/autoupdate" "github.com/gravitational/teleport/lib/defaults" libutils "github.com/gravitational/teleport/lib/utils" ) @@ -421,10 +422,14 @@ func writeSystemTemplate(path, t string, values any) error { } // ReplaceTeleportService replaces the default paths in the Teleport service config with namespaced paths. -func (ns *Namespace) ReplaceTeleportService(cfg []byte, pathDir string) []byte { +func (ns *Namespace) ReplaceTeleportService(cfg []byte, pathDir string, flags autoupdate.InstallFlags) []byte { if pathDir == "" { pathDir = ns.defaultPathDir } + var startFlags []string + if flags&autoupdate.FlagFIPS != 0 { + startFlags = append(startFlags, "--fips") + } for _, rep := range []struct { old, new string }{ @@ -440,12 +445,24 @@ func (ns *Namespace) ReplaceTeleportService(cfg []byte, pathDir string) []byte { old: "/run/teleport.pid", new: ns.pidFile, }, + { + old: "/teleport start ", + new: "/teleport start " + joinTerminal(startFlags, " "), + }, } { cfg = bytes.ReplaceAll(cfg, []byte(rep.old), []byte(rep.new)) } return cfg } +func joinTerminal(s []string, sep string) string { + v := strings.Join(s, sep) + if len(v) > 0 { + return v + sep + } + return v +} + func (ns *Namespace) LogWarnings(ctx context.Context, pathDir string) { if ns.name == "" { return diff --git a/lib/autoupdate/agent/setup_test.go b/lib/autoupdate/agent/setup_test.go index 5a32b9e49a1fb..e077d37dd91e7 100644 --- a/lib/autoupdate/agent/setup_test.go +++ b/lib/autoupdate/agent/setup_test.go @@ -30,6 +30,7 @@ import ( "github.com/stretchr/testify/require" "gopkg.in/yaml.v3" + "github.com/gravitational/teleport/lib/autoupdate" "github.com/gravitational/teleport/lib/config" "github.com/gravitational/teleport/lib/utils/testutils/golden" ) @@ -386,3 +387,74 @@ func TestUnversionedTeleportConfig(t *testing.T) { require.NoError(t, err) require.Equal(t, in, out) } + +func TestReplaceTeleportService(t *testing.T) { + t.Parallel() + + const defaultService = ` +[Unit] +Description=Teleport Service +After=network.target + +[Service] +Type=simple +Restart=always +RestartSec=5 +EnvironmentFile=-/etc/default/teleport +ExecStart=/usr/local/bin/teleport start --config /etc/teleport.yaml --pid-file=/run/teleport.pid +# systemd before 239 needs an absolute path +ExecReload=/bin/sh -c "exec pkill -HUP -L -F /run/teleport.pid" +PIDFile=/run/teleport.pid +LimitNOFILE=524288 + +[Install] +WantedBy=multi-user.target +` + + tests := []struct { + name string + in string + + pidFile string + configFile string + pathDir string + flags autoupdate.InstallFlags + }{ + { + name: "default", + in: defaultService, + pidFile: "/var/run/teleport.pid", + configFile: "/etc/teleport.yaml", + pathDir: "/usr/local/bin", + }, + { + name: "custom", + in: defaultService, + pidFile: "/some/path/teleport.pid", + configFile: "/some/path/teleport.yaml", + pathDir: "/some/path/bin", + }, + { + name: "FIPS", + in: defaultService, + pidFile: "/var/run/teleport.pid", + configFile: "/etc/teleport.yaml", + pathDir: "/usr/local/bin", + flags: autoupdate.FlagFIPS, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + ns := &Namespace{ + log: slog.Default(), + configFile: tt.configFile, + pidFile: tt.pidFile, + } + data := ns.ReplaceTeleportService([]byte(tt.in), tt.pathDir, tt.flags) + if golden.ShouldSet() { + golden.Set(t, data) + } + require.Equal(t, string(golden.Get(t)), string(data)) + }) + } +} diff --git a/lib/autoupdate/agent/testdata/TestReplaceTeleportService/FIPS.golden b/lib/autoupdate/agent/testdata/TestReplaceTeleportService/FIPS.golden new file mode 100644 index 0000000000000..787db53a9549d --- /dev/null +++ b/lib/autoupdate/agent/testdata/TestReplaceTeleportService/FIPS.golden @@ -0,0 +1,18 @@ + +[Unit] +Description=Teleport Service +After=network.target + +[Service] +Type=simple +Restart=always +RestartSec=5 +EnvironmentFile=-/etc/default/teleport +ExecStart=/usr/local/bin/teleport start --fips --config /etc/teleport.yaml --pid-file=/var/run/teleport.pid +# systemd before 239 needs an absolute path +ExecReload=/bin/sh -c "exec pkill -HUP -L -F /var/run/teleport.pid" +PIDFile=/var/run/teleport.pid +LimitNOFILE=524288 + +[Install] +WantedBy=multi-user.target diff --git a/lib/autoupdate/agent/testdata/TestReplaceTeleportService/custom.golden b/lib/autoupdate/agent/testdata/TestReplaceTeleportService/custom.golden new file mode 100644 index 0000000000000..c0c056488e286 --- /dev/null +++ b/lib/autoupdate/agent/testdata/TestReplaceTeleportService/custom.golden @@ -0,0 +1,18 @@ + +[Unit] +Description=Teleport Service +After=network.target + +[Service] +Type=simple +Restart=always +RestartSec=5 +EnvironmentFile=-/etc/default/teleport +ExecStart=/some/path/bin/teleport start --config /some/path/teleport.yaml --pid-file=/some/path/teleport.pid +# systemd before 239 needs an absolute path +ExecReload=/bin/sh -c "exec pkill -HUP -L -F /some/path/teleport.pid" +PIDFile=/some/path/teleport.pid +LimitNOFILE=524288 + +[Install] +WantedBy=multi-user.target diff --git a/lib/autoupdate/agent/testdata/TestReplaceTeleportService/default.golden b/lib/autoupdate/agent/testdata/TestReplaceTeleportService/default.golden new file mode 100644 index 0000000000000..282d75dc28a43 --- /dev/null +++ b/lib/autoupdate/agent/testdata/TestReplaceTeleportService/default.golden @@ -0,0 +1,18 @@ + +[Unit] +Description=Teleport Service +After=network.target + +[Service] +Type=simple +Restart=always +RestartSec=5 +EnvironmentFile=-/etc/default/teleport +ExecStart=/usr/local/bin/teleport start --config /etc/teleport.yaml --pid-file=/var/run/teleport.pid +# systemd before 239 needs an absolute path +ExecReload=/bin/sh -c "exec pkill -HUP -L -F /var/run/teleport.pid" +PIDFile=/var/run/teleport.pid +LimitNOFILE=524288 + +[Install] +WantedBy=multi-user.target diff --git a/lib/autoupdate/agent/updater.go b/lib/autoupdate/agent/updater.go index 4c3d9858b43c7..df3874aab3674 100644 --- a/lib/autoupdate/agent/updater.go +++ b/lib/autoupdate/agent/updater.go @@ -337,7 +337,7 @@ type OverrideConfig struct { // ForceVersion to the specified version. ForceVersion string // ForceFlags in installed Teleport. - ForceFlags autoupdate.InstallFlags + ForceFlags []string // AllowOverwrite of installed binaries. AllowOverwrite bool // AllowProxyConflict when proxies in teleport.yaml and update.yaml are mismatched. @@ -394,7 +394,7 @@ func (u *Updater) Install(ctx context.Context, override OverrideConfig) error { } targetVersion := resp.Target.Version targetFlags := resp.Target.Flags - targetFlags |= override.ForceFlags + targetFlags |= autoupdate.NewInstallFlagsFromStrings(override.ForceFlags) if override.ForceVersion != "" { targetVersion = override.ForceVersion } diff --git a/tool/teleport-update/main.go b/tool/teleport-update/main.go index 4a3cdd1b94242..969718d2d2926 100644 --- a/tool/teleport-update/main.go +++ b/tool/teleport-update/main.go @@ -124,11 +124,12 @@ func Run(args []string) int { BoolVar(&ccfg.AllowProxyConflict) enableCmd.Flag("force-version", "Force the provided version instead of using the version provided by the Teleport cluster."). Hidden().Short('f').Envar(updateVersionEnvVar).StringVar(&ccfg.ForceVersion) + enableCmd.Flag("force-flag", "Force the provided version flags instead of using the version flags provided by the Teleport cluster."). + Hidden().StringsVar(&ccfg.ForceFlags) enableCmd.Flag("self-setup", "Use the current teleport-update binary to create systemd service config for managed updates."). Hidden().BoolVar(&ccfg.SelfSetup) enableCmd.Flag("path", "Directory to link the active Teleport installation's binaries into."). Hidden().StringVar(&ccfg.Path) - // TODO(sclevine): add force-fips and force-enterprise as hidden flags disableCmd := app.Command("disable", "Disable agent managed updates. Does not affect the active installation of Teleport.") @@ -145,6 +146,8 @@ func Run(args []string) int { BoolVar(&ccfg.AllowProxyConflict) pinCmd.Flag("force-version", "Force the provided version instead of using the version provided by the Teleport cluster."). Short('f').Envar(updateVersionEnvVar).StringVar(&ccfg.ForceVersion) + pinCmd.Flag("force-flag", "Force the provided version flags instead of using the version flags provided by the Teleport cluster."). + Hidden().StringsVar(&ccfg.ForceFlags) pinCmd.Flag("self-setup", "Use the current teleport-update binary to create systemd service config for managed updates."). Hidden().BoolVar(&ccfg.SelfSetup) pinCmd.Flag("path", "Directory to link the active Teleport installation's binaries into.").