Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions api/types/installers/agentless-installer.sh.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ set -o nounset

. /etc/os-release

PACKAGE_LIST="{{ .TeleportPackage }}"
if [[ "{{ .AutomaticUpgrades }}" == "true" ]]; then
PACKAGE_LIST="${PACKAGE_LIST} {{ .TeleportPackage }}-updater"
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't we need to install only xxx-updater package? I think it will pull teleport package as dependency?

@hugoShaka @fheinecke Am I wrong?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It does 👍
https://apt.releases.development.teleport.dev/ubuntu/dists/bionic/stable/v13/binary-amd64/Packages
image

We can remove it, however I would like to clarify something first:
teleport-ent-updater depends on teleport
teleport and teleport-ent both provide teleport.

So, when we try to install only teleport-ent-updater which package is going to be pulled? Is it teleport or teleport-ent?

Copy link
Copy Markdown
Contributor

@hugoShaka hugoShaka May 3, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, but we don't want the teleport-ent package to be deleted if the user wants to uninstall the updater. IMO it makes sense to mark both as wanted, so teleport-ent won't be auto-removed.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@hugoShaka In your documentation guide we instruct people to just apt install teleport-ent-updater. Is that for scenario when you already have an agent and want to add updater to it?

@fheinecke I think teleport-ent-updater should depend on teleport-ent, not teleport. Can we update that?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is that for scenario when you already have an agent and want to add updater to it?

Yes, the guide explains how to enroll an existing agent into automatic updates

Copy link
Copy Markdown
Contributor

@fheinecke fheinecke May 3, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think teleport-ent-updater should depend on teleport-ent, not teleport. Can we update that?

@r0mant it has been (tested before I went on vacation, see https://github.com/gravitational/teleport.e/pull/1177)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we don't want the teleport-ent package to be deleted if the user wants to uninstall the updater.

I'll keep both packages then 👍

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any condition where {{ .TeleportPackage }} is set to anything but teleport-ent-updater? We don't currently publish separate packages for OSS and this will error if it's set to teleport-updater.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It won't 👍

AutomaticUpgrades comes from:

automaticUpgrades := feats.AutomaticUpgrades && modules.GetModules().BuildType() == modules.BuildEnterprise

So, it will only be true for Enterprise builds
I left a comment so that we can comeback to this and simplify the condition only:

// TODO(marco): remove BuildType check when teleport-upgrade (oss) package is available in apt/yum repos

fi

if [ "$ID" = "debian" ] || [ "$ID" = "ubuntu" ]; then
# old versions of ubuntu require that keys get added by `apt-key add`, without
# adding the key apt shows a key signing error when installing teleport.
Expand All @@ -25,14 +30,14 @@ set -o nounset
echo "deb [signed-by=/usr/share/keyrings/teleport-archive-keyring.asc] https://apt.releases.teleport.dev/${ID?} ${VERSION_CODENAME?} {{ .RepoChannel }}" | sudo tee /etc/apt/sources.list.d/teleport.list >/dev/null
fi
sudo apt-get update
sudo apt-get install -y {{ .TeleportPackage }}
sudo apt-get install -y ${PACKAGE_LIST}
elif [ "$ID" = "amzn" ] || [ "$ID" = "rhel" ]; then
if [ "$ID" = "rhel" ]; then
VERSION_ID=$(echo "$VERSION_ID" | sed 's/\..*//') # convert version numbers like '7.2' to only include the major version
fi
sudo yum-config-manager --add-repo \
"$(rpm --eval "https://yum.releases.teleport.dev/$ID/$VERSION_ID/Teleport/%{_arch}/{{ .RepoChannel }}/teleport.repo")"
sudo yum install -y {{ .TeleportPackage }}
sudo yum install -y ${PACKAGE_LIST}
else
echo "Unsupported distro: $ID"
exit 1
Expand Down
9 changes: 7 additions & 2 deletions api/types/installers/installer.sh.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ on_azure() {

. /etc/os-release

PACKAGE_LIST="{{ .TeleportPackage }} jq"
if [[ "{{ .AutomaticUpgrades }}" == "true" ]]; then
PACKAGE_LIST="${PACKAGE_LIST} {{ .TeleportPackage }}-updater"
fi

# old versions of ubuntu require that keys get added by `apt-key add`, without
# adding the key apt shows a key signing error when installing teleport.
LEGACY_UBUNTU=false
Expand All @@ -41,14 +46,14 @@ on_azure() {
echo "deb [signed-by=/usr/share/keyrings/teleport-archive-keyring.asc] https://apt.releases.teleport.dev/${ID?} ${VERSION_CODENAME?} {{ .RepoChannel }}" | sudo tee /etc/apt/sources.list.d/teleport.list >/dev/null
fi
sudo apt-get update
sudo apt-get install -y {{ .TeleportPackage }} jq
sudo apt-get install -y ${PACKAGE_LIST}
elif [ "$ID" = "amzn" ] || [ "$ID" = "rhel" ]; then
if [ "$ID" = "rhel" ]; then
VERSION_ID=$(echo "$VERSION_ID" | sed 's/\..*//') # convert version numbers like '7.2' to only include the major version
fi
sudo yum-config-manager --add-repo \
"$(rpm --eval "https://yum.releases.teleport.dev/$ID/$VERSION_ID/Teleport/%{_arch}/{{ .RepoChannel }}/teleport.repo")"
sudo yum install -y {{ .TeleportPackage }} jq
sudo yum install -y ${PACKAGE_LIST}
else
echo "Unsupported distro: $ID"
exit 1
Expand Down
3 changes: 3 additions & 0 deletions api/types/installers/installers.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,7 @@ type Template struct {
TeleportPackage string
// RepoChannel is the repo's channel name to install.
RepoChannel string
// AutomaticUpgrades indicates whether Automatic Upgrades are enabled or disabled.
// Its value is either `true` or `false`.
AutomaticUpgrades string
}
12 changes: 8 additions & 4 deletions lib/web/apiserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -1608,11 +1608,15 @@ func (h *Handler) installer(w http.ResponseWriter, r *http.Request, p httprouter
repoChannel = stableCloudChannelRepo
}

// TODO(marco): remove BuildType check when teleport-upgrade (oss) package is available in apt/yum repos.
automaticUpgrades := feats.AutomaticUpgrades && modules.GetModules().BuildType() == modules.BuildEnterprise

tmpl := installers.Template{
PublicProxyAddr: h.PublicProxyAddr(),
MajorVersion: version,
TeleportPackage: teleportPackage,
RepoChannel: repoChannel,
PublicProxyAddr: h.PublicProxyAddr(),
MajorVersion: version,
TeleportPackage: teleportPackage,
RepoChannel: repoChannel,
AutomaticUpgrades: strconv.FormatBool(automaticUpgrades),
}
err = instTmpl.Execute(w, tmpl)
return nil, trace.Wrap(err)
Expand Down
59 changes: 29 additions & 30 deletions lib/web/apiserver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2309,20 +2309,22 @@ func TestPingAutomaticUpgrades(t *testing.T) {

// TestInstallerRepoChannel ensures the returned installer script has the proper repo channel
func TestInstallerRepoChannel(t *testing.T) {
s := newWebSuiteWithConfig(t, webSuiteConfig{
authPreferenceSpec: &types.AuthPreferenceSpecV2{
Type: constants.Local,
SecondFactor: constants.SecondFactorOn,
Webauthn: &types.Webauthn{RPID: "localhost"},
},
})

wc := s.client(t)
t.Run("documented variables are injected", func(t *testing.T) {
s := newWebSuiteWithConfig(t, webSuiteConfig{
authPreferenceSpec: &types.AuthPreferenceSpecV2{
Type: constants.Local,
SecondFactor: constants.SecondFactorOn,
Webauthn: &types.Webauthn{RPID: "localhost"},
},
})
wc := s.client(t)
// Variables documented here: https://goteleport.com/docs/server-access/guides/ec2-discovery/#step-67-optional-customize-the-default-installer-script
err := s.server.Auth().SetInstaller(s.ctx, types.MustNewInstallerV1("custom", `#!/usr/bin/env bash
echo {{ .PublicProxyAddr }}
echo Teleport-{{ .MajorVersion }}
echo Repository Channel: {{ .RepoChannel }}
echo AutomaticUpgrades: {{ .AutomaticUpgrades }}
`))
require.NoError(t, err)

Expand All @@ -2334,21 +2336,15 @@ echo Repository Channel: {{ .RepoChannel }}
// Variables must be injected
require.Contains(t, responseString, "echo Teleport-v")
require.Contains(t, responseString, "echo Repository Channel: stable/v")
require.Contains(t, responseString, "echo AutomaticUpgrades: false")
})
t.Run("cloud with automatic upgrades", func(t *testing.T) {
modules.SetTestModules(t, &modules.TestModules{TestFeatures: modules.Features{
Cloud: true,
AutomaticUpgrades: true,
}})

s := newWebSuiteWithConfig(t, webSuiteConfig{
authPreferenceSpec: &types.AuthPreferenceSpecV2{
Type: constants.Local,
SecondFactor: constants.SecondFactorOn,
Webauthn: &types.Webauthn{RPID: "localhost"},
},
})
wc := s.client(t)
modules.SetTestModules(t, &modules.TestModules{
TestBuildType: modules.BuildEnterprise,
TestFeatures: modules.Features{
Cloud: true,
AutomaticUpgrades: true,
}})

t.Run("default-installer", func(t *testing.T) {
re, err := wc.Get(s.ctx, wc.Endpoint("webapi", "scripts", "installer", "default-installer"), url.Values{})
Expand All @@ -2359,6 +2355,12 @@ echo Repository Channel: {{ .RepoChannel }}
// The repo's channel to use is stable/cloud
require.Contains(t, responseString, "stable/cloud")
require.NotContains(t, responseString, "stable/v")
require.Contains(t, responseString, ""+
" PACKAGE_LIST=\"teleport-ent jq\"\n"+
" if [[ \"true\" == \"true\" ]]; then\n"+
" PACKAGE_LIST=\"${PACKAGE_LIST} teleport-ent-updater\"\n"+
" fi\n",
)
})
t.Run("default-agentless-installer", func(t *testing.T) {
re, err := wc.Get(s.ctx, wc.Endpoint("webapi", "scripts", "installer", "default-agentless-installer"), url.Values{})
Expand All @@ -2369,6 +2371,12 @@ echo Repository Channel: {{ .RepoChannel }}
// The repo's channel to use is stable/cloud
require.Contains(t, responseString, "stable/cloud")
require.NotContains(t, responseString, "stable/v")
require.Contains(t, responseString, ""+
" PACKAGE_LIST=\"teleport-ent\"\n"+
" if [[ \"true\" == \"true\" ]]; then\n"+
" PACKAGE_LIST=\"${PACKAGE_LIST} teleport-ent-updater\"\n"+
" fi\n",
)
})
})
t.Run("cloud without automatic upgrades", func(t *testing.T) {
Expand All @@ -2377,15 +2385,6 @@ echo Repository Channel: {{ .RepoChannel }}
AutomaticUpgrades: false,
}})

s := newWebSuiteWithConfig(t, webSuiteConfig{
authPreferenceSpec: &types.AuthPreferenceSpecV2{
Type: constants.Local,
SecondFactor: constants.SecondFactorOn,
Webauthn: &types.Webauthn{RPID: "localhost"},
},
})
wc := s.client(t)

t.Run("default-installer", func(t *testing.T) {
re, err := wc.Get(s.ctx, wc.Endpoint("webapi", "scripts", "installer", "default-installer"), url.Values{})
require.NoError(t, err)
Expand Down
11 changes: 11 additions & 0 deletions lib/web/join_tokens.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,13 @@ type scriptSettings struct {
joinMethod string
databaseInstallMode bool
stableCloudChannelRepo bool
installUpdater bool
}

// automaticUpgrades returns whether automaticUpgrades should be enabled.
func automaticUpgrades(features proto.Features) bool {
// TODO(marco): remove BuildType check when teleport-updater (oss) package is available in apt/yum repos.
return features.AutomaticUpgrades && modules.GetModules().BuildType() == modules.BuildEnterprise
}

func (h *Handler) createTokenHandle(w http.ResponseWriter, r *http.Request, params httprouter.Params, ctx *SessionContext) (interface{}, error) {
Expand Down Expand Up @@ -209,6 +216,7 @@ func (h *Handler) getNodeJoinScriptHandle(w http.ResponseWriter, r *http.Request
appInstallMode: false,
joinMethod: r.URL.Query().Get("method"),
stableCloudChannelRepo: useStableCloudChannelRepo,
installUpdater: automaticUpgrades(h.ClusterFeatures),
}

script, err := getJoinScript(r.Context(), settings, h.GetProxyClient())
Expand Down Expand Up @@ -253,6 +261,7 @@ func (h *Handler) getAppJoinScriptHandle(w http.ResponseWriter, r *http.Request,
appName: name,
appURI: uri,
stableCloudChannelRepo: useStableCloudChannelRepo,
installUpdater: automaticUpgrades(h.ClusterFeatures),
}

script, err := getJoinScript(r.Context(), settings, h.GetProxyClient())
Expand Down Expand Up @@ -280,6 +289,7 @@ func (h *Handler) getDatabaseJoinScriptHandle(w http.ResponseWriter, r *http.Req
token: params.ByName("token"),
databaseInstallMode: true,
stableCloudChannelRepo: useStableCloudChannelRepo,
installUpdater: automaticUpgrades(h.ClusterFeatures),
}

script, err := getJoinScript(r.Context(), settings, h.GetProxyClient())
Expand Down Expand Up @@ -406,6 +416,7 @@ func getJoinScript(ctx context.Context, settings scriptSettings, m nodeAPIGetter
"caPins": strings.Join(caPins, ","),
"packageName": packageName,
"repoChannel": repoChannel,
"installUpdater": strconv.FormatBool(settings.installUpdater),
"version": version,
"appInstallMode": strconv.FormatBool(settings.appInstallMode),
"appName": settings.appName,
Expand Down
66 changes: 66 additions & 0 deletions lib/web/join_tokens_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -926,6 +926,34 @@ func TestJoinScript(t *testing.T) {
})

t.Run("using repo", func(t *testing.T) {
t.Run("installUpdater set to true, list of packages must include updater package", func(t *testing.T) {
script, err := getJoinScript(context.Background(), scriptSettings{token: validToken, installUpdater: true}, m)
require.NoError(t, err)

require.Contains(t, script, ""+
" PACKAGE_LIST=${TELEPORT_PACKAGE_NAME}\n"+
" # (warning): This expression is constant. Did you forget the $ on a variable?\n"+
" # Disabling the warning above because expression is templated.\n"+
" # shellcheck disable=SC2050\n"+
" if [[ \"true\" == \"true\" ]]; then\n"+
" PACKAGE_LIST=\"${PACKAGE_LIST} ${TELEPORT_PACKAGE_NAME}-updater\"\n"+
" fi\n",
)
})
t.Run("installUpdater set to false, list of packages must not include updater package", func(t *testing.T) {
script, err := getJoinScript(context.Background(), scriptSettings{token: validToken, installUpdater: false}, m)
require.NoError(t, err)

require.Contains(t, script, ""+
" PACKAGE_LIST=${TELEPORT_PACKAGE_NAME}\n"+
" # (warning): This expression is constant. Did you forget the $ on a variable?\n"+
" # Disabling the warning above because expression is templated.\n"+
" # shellcheck disable=SC2050\n"+
" if [[ \"false\" == \"true\" ]]; then\n"+
" PACKAGE_LIST=\"${PACKAGE_LIST} ${TELEPORT_PACKAGE_NAME}-updater\"\n"+
" fi\n",
)
})
t.Run("cloud and automatic upgrades", func(t *testing.T) {
script, err := getJoinScript(context.Background(), scriptSettings{token: validToken, stableCloudChannelRepo: true}, m)
require.NoError(t, err)
Expand All @@ -949,6 +977,44 @@ func TestJoinScript(t *testing.T) {

}

func TestAutomaticUpgrades(t *testing.T) {
t.Run("enterprise and automatic upgrades enabled", func(t *testing.T) {
modules.SetTestModules(t, &modules.TestModules{
TestBuildType: modules.BuildEnterprise,
TestFeatures: modules.Features{
AutomaticUpgrades: true,
},
})

got := automaticUpgrades(*modules.GetModules().Features().ToProto())
require.True(t, got)
})
t.Run("enterprise but automatic upgrades disabled", func(t *testing.T) {
modules.SetTestModules(t, &modules.TestModules{
TestBuildType: modules.BuildEnterprise,
TestFeatures: modules.Features{
AutomaticUpgrades: false,
},
})

got := automaticUpgrades(*modules.GetModules().Features().ToProto())
require.False(t, got)
})

// There's no `teleport-updater` (oss) package yet, so even if automatic upgrades are enabled it must return false.
t.Run("automatic upgrades enabled but build is OSS", func(t *testing.T) {
modules.SetTestModules(t, &modules.TestModules{
TestBuildType: modules.BuildEnterprise,
TestFeatures: modules.Features{
AutomaticUpgrades: false,
},
})

got := automaticUpgrades(*modules.GetModules().Features().ToProto())
require.False(t, got)
})
}

func TestIsSameAzureRuleSet(t *testing.T) {
tests := []struct {
name string
Expand Down
12 changes: 10 additions & 2 deletions lib/web/scripts/node-join/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -851,6 +851,14 @@ install_from_repo() {
REPO_CHANNEL=stable/v"${TELEPORT_VERSION//.*/}"
fi

PACKAGE_LIST=${TELEPORT_PACKAGE_NAME}
# (warning): This expression is constant. Did you forget the $ on a variable?
# Disabling the warning above because expression is templated.
# shellcheck disable=SC2050
if [[ "{{.installUpdater}}" == "true" ]]; then
PACKAGE_LIST="${PACKAGE_LIST} ${TELEPORT_PACKAGE_NAME}-updater"
fi

# Populate $ID, $VERSION_ID, $VERSION_CODENAME and other env vars identifying the OS.
# shellcheck disable=SC1091
. /etc/os-release
Expand All @@ -872,7 +880,7 @@ install_from_repo() {
https://apt.releases.teleport.dev/${ID} ${VERSION_CODENAME} ${REPO_CHANNEL}" > /etc/apt/sources.list.d/teleport.list
fi
apt-get update
apt-get install -y ${TELEPORT_PACKAGE_NAME}
apt-get install -y ${PACKAGE_LIST}
elif [ "$ID" = "amzn" ] || [ "$ID" = "rhel" ] || [ "$ID" = "centos" ] ; then
if [ "$ID" = "rhel" ]; then
VERSION_ID="${VERSION_ID//.*/}" # convert version numbers like '7.2' to only include the major version
Expand All @@ -885,7 +893,7 @@ install_from_repo() {
# See: https://github.com/gravitational/teleport/issues/22581
yum --disablerepo="*" --enablerepo="teleport" clean metadata

yum install -y ${TELEPORT_PACKAGE_NAME}
yum install -y ${PACKAGE_LIST}
else
echo "Unsupported distro: $ID"
exit 1
Expand Down