From ff74b902eeb420a55bb53d03d569bf3769d52bcc Mon Sep 17 00:00:00 2001 From: hugoShaka Date: Thu, 20 Feb 2025 17:45:22 -0500 Subject: [PATCH] Use install.sh in discovery's default installer --- lib/auth/grpcserver.go | 24 +++++++++++- lib/auth/grpcserver_test.go | 35 ++++++++++++++++- lib/srv/server/installer/autodiscover.go | 2 + lib/srv/server/installer/defaultinstallers.go | 39 +++++++++++++++++-- 4 files changed, 92 insertions(+), 8 deletions(-) diff --git a/lib/auth/grpcserver.go b/lib/auth/grpcserver.go index b761765240a10..f257faf56642b 100644 --- a/lib/auth/grpcserver.go +++ b/lib/auth/grpcserver.go @@ -4526,7 +4526,15 @@ func (g *GRPCServer) GetInstaller(ctx context.Context, req *types.ResourceReques if trace.IsNotFound(err) { switch req.Name { case installers.InstallerScriptName: - return installer.DefaultInstaller, nil + _, err = auth.authServer.GetAutoUpdateAgentRollout(ctx) + switch { + case trace.IsNotFound(err): + return installer.LegacyDefaultInstaller, nil + case err != nil: + return nil, trace.Wrap(err, "failed to get query autoupdate state to build installer") + default: + return installer.NewDefaultInstaller, nil + } case installers.InstallerScriptNameAgentless: return installers.DefaultAgentlessInstaller, nil } @@ -4551,8 +4559,20 @@ func (g *GRPCServer) GetInstallers(ctx context.Context, _ *emptypb.Empty) (*type return nil, trace.Wrap(err) } var installersV1 []*types.InstallerV1 + + var defaultInstaller *types.InstallerV1 + _, err = auth.authServer.GetAutoUpdateAgentRollout(ctx) + switch { + case trace.IsNotFound(err): + defaultInstaller = installer.LegacyDefaultInstaller + case err != nil: + return nil, trace.Wrap(err, "failed to get query autoupdate state to build installer") + default: + defaultInstaller = installer.NewDefaultInstaller + } + defaultInstallers := map[string]*types.InstallerV1{ - types.DefaultInstallerScriptName: installer.DefaultInstaller, + types.DefaultInstallerScriptName: defaultInstaller, installers.InstallerScriptNameAgentless: installers.DefaultAgentlessInstaller, } diff --git a/lib/auth/grpcserver_test.go b/lib/auth/grpcserver_test.go index a651958a15fd1..a76661fb9da26 100644 --- a/lib/auth/grpcserver_test.go +++ b/lib/auth/grpcserver_test.go @@ -47,12 +47,14 @@ import ( otlpresourcev1 "go.opentelemetry.io/proto/otlp/resource/v1" otlptracev1 "go.opentelemetry.io/proto/otlp/trace/v1" "google.golang.org/protobuf/testing/protocmp" + "google.golang.org/protobuf/types/known/durationpb" "google.golang.org/protobuf/types/known/emptypb" "github.com/gravitational/teleport" "github.com/gravitational/teleport/api/client/proto" "github.com/gravitational/teleport/api/constants" apidefaults "github.com/gravitational/teleport/api/defaults" + autoupdatev1pb "github.com/gravitational/teleport/api/gen/proto/go/teleport/autoupdate/v1" clusterconfigpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/clusterconfig/v1" mfav1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/mfa/v1" "github.com/gravitational/teleport/api/internalutils/stream" @@ -61,6 +63,7 @@ import ( "github.com/gravitational/teleport/api/observability/tracing" "github.com/gravitational/teleport/api/trail" "github.com/gravitational/teleport/api/types" + "github.com/gravitational/teleport/api/types/autoupdate" "github.com/gravitational/teleport/api/types/installers" "github.com/gravitational/teleport/api/utils" "github.com/gravitational/teleport/api/utils/keys" @@ -4611,12 +4614,21 @@ func TestGRPCServer_GetInstallers(t *testing.T) { tests := []struct { name string inputInstallers map[string]string + hasAgentRollout bool expectedInstallers map[string]string }{ { name: "default installers only", expectedInstallers: map[string]string{ - types.DefaultInstallerScriptName: installer.DefaultInstaller.GetScript(), + types.DefaultInstallerScriptName: installer.LegacyDefaultInstaller.GetScript(), + installers.InstallerScriptNameAgentless: installers.DefaultAgentlessInstaller.GetScript(), + }, + }, + { + name: "new default installers", + hasAgentRollout: true, + expectedInstallers: map[string]string{ + types.DefaultInstallerScriptName: installer.NewDefaultInstaller.GetScript(), installers.InstallerScriptNameAgentless: installers.DefaultAgentlessInstaller.GetScript(), }, }, @@ -4627,7 +4639,7 @@ func TestGRPCServer_GetInstallers(t *testing.T) { }, expectedInstallers: map[string]string{ "my-custom-installer": "echo test", - types.DefaultInstallerScriptName: installer.DefaultInstaller.GetScript(), + types.DefaultInstallerScriptName: installer.LegacyDefaultInstaller.GetScript(), installers.InstallerScriptNameAgentless: installers.DefaultAgentlessInstaller.GetScript(), }, }, @@ -4649,6 +4661,25 @@ func TestGRPCServer_GetInstallers(t *testing.T) { require.NoError(t, err) }) + if tc.hasAgentRollout { + rollout, err := autoupdate.NewAutoUpdateAgentRollout( + &autoupdatev1pb.AutoUpdateAgentRolloutSpec{ + StartVersion: "1.2.3", + TargetVersion: "1.2.4", + Schedule: autoupdate.AgentsScheduleImmediate, + AutoupdateMode: autoupdate.AgentsUpdateModeEnabled, + Strategy: autoupdate.AgentsStrategyTimeBased, + MaintenanceWindowDuration: durationpb.New(1 * time.Hour), + }) + require.NoError(t, err) + _, err = grpc.AuthServer.CreateAutoUpdateAgentRollout(ctx, rollout) + require.NoError(t, err) + + t.Cleanup(func() { + assert.NoError(t, grpc.AuthServer.DeleteAutoUpdateAgentRollout(ctx)) + }) + } + for name, script := range tc.inputInstallers { installer, err := types.NewInstallerV1(name, script) require.NoError(t, err) diff --git a/lib/srv/server/installer/autodiscover.go b/lib/srv/server/installer/autodiscover.go index 744acbd737ec4..aa79d796391eb 100644 --- a/lib/srv/server/installer/autodiscover.go +++ b/lib/srv/server/installer/autodiscover.go @@ -226,6 +226,8 @@ func (ani *AutoDiscoverNodeInstaller) Install(ctx context.Context) error { ani.Logger.InfoContext(ctx, "Detected cloud provider", "cloud", imdsClient.GetType()) // Check if teleport is already installed and install it, if it's absent. + // In the new autoupdate install flow, teleport-update should have already + // taken care of installing teleport. if _, err := os.Stat(ani.binariesLocation.Teleport); err != nil { ani.Logger.InfoContext(ctx, "Installing teleport") if err := ani.installTeleportFromRepo(ctx); err != nil { diff --git a/lib/srv/server/installer/defaultinstallers.go b/lib/srv/server/installer/defaultinstallers.go index f9bb4dbf77b9f..a690ccffd668b 100644 --- a/lib/srv/server/installer/defaultinstallers.go +++ b/lib/srv/server/installer/defaultinstallers.go @@ -26,11 +26,40 @@ import ( "github.com/gravitational/teleport/lib/web/scripts/oneoff" ) -// DefaultInstaller represents the default installer script provided by teleport. -var DefaultInstaller = oneoffScriptToDefaultInstaller() +// Depending on your cluster setup we have 2 installers: +// - LegacyDefaultInstaller which uses oneoff.sh to download teleport and run "teleport install". +// Teleport install does package-based installations. +// - -func oneoffScriptToDefaultInstaller() *types.InstallerV1 { - argsList := []string{ +// LegacyDefaultInstaller represents the default installer script provided by teleport. +var ( + // LegacyDefaultInstaller uses oneoff.sh to download the Teleport tarball and run `teleport install`. + // The Teleport install command handles both Teleport installation and agent configuration. + LegacyDefaultInstaller = oneoffScriptToDefaultInstaller() + + // NewDefaultInstaller installs Teleport by calling the standard "/scripts/install.sh" route on the proxy. + // After successfully installing Teleport, it will invoke the same `teleport install` + // command as the LegacyDefaultInstaller which will only take care of configuring Teleport. + NewDefaultInstaller = types.MustNewInstallerV1(installers.InstallerScriptName, execGenericInstallScript+configureTeleport) + + execGenericInstallScript = `#!/bin/bash +set -euo pipefail + +INSTALL_SCRIPT_URL="https://{{.PublicProxyAddr}}/scripts/install.sh" + +echo "Offloading the installation part to the generic Teleport install script hosted at: $INSTALL_SCRIPT_URL" + +curl "$INSTALL_SCRIPT_URL" | sudo bash +` + configureTeleport = `#!/bin/bash +set -euo pipefail + +echo "Configuring the Teleport agent" + +set +x +sudo teleport ` + strings.Join(argsList, " ") + + argsList = []string{ "install", "autodiscover-node", "--public-proxy-addr={{.PublicProxyAddr}}", "--teleport-package={{.TeleportPackage}}", @@ -38,7 +67,9 @@ func oneoffScriptToDefaultInstaller() *types.InstallerV1 { "--auto-upgrade={{.AutomaticUpgrades}}", "--azure-client-id={{.AzureClientID}}", } +) +func oneoffScriptToDefaultInstaller() *types.InstallerV1 { script, err := oneoff.BuildScript(oneoff.OneOffScriptParams{ EntrypointArgs: strings.Join(argsList, " "), SuccessMessage: "Teleport is installed and running.",