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
16 changes: 12 additions & 4 deletions integration/autoupdate/tools/updater/modules.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"context"
"crypto"
"fmt"
"os"
"time"

"github.com/gravitational/trace"
Expand All @@ -35,8 +36,12 @@ import (
"github.com/gravitational/teleport/lib/tlsca"
)

// TestPassword is password generated during the test to login in test cluster.
const TestPassword = "UPDATER_TEST_PASSWORD"
const (
// TestPassword is env var used for setting password generated during the test to login in test cluster.
TestPassword = "UPDATER_TEST_PASSWORD"
// TestBuild is env var for setting test build type during the test.
TestBuild = "UPDATER_TEST_BUILD"
)

var (
version = teleport.Version
Expand All @@ -54,17 +59,20 @@ func (p *TestModules) GetSuggestedAccessLists(context.Context, *tlsca.Identity,

// BuildType returns build type (OSS or Enterprise)
func (p *TestModules) BuildType() string {
if build := os.Getenv(TestBuild); build != "" {
return build
}
return "CLI"
}

// IsEnterpriseBuild returns false for [TestModules].
func (p *TestModules) IsEnterpriseBuild() bool {
return false
return os.Getenv(TestBuild) == modules.BuildEnterprise
}

// IsOSSBuild returns false for [TestModules].
func (p *TestModules) IsOSSBuild() bool {
return false
return os.Getenv(TestBuild) == modules.BuildOSS
}

// LicenseExpiry returns the expiry date of the enterprise license, if applicable.
Expand Down
49 changes: 49 additions & 0 deletions integration/autoupdate/tools/updater_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,10 @@ import (
"github.com/stretchr/testify/require"

"github.com/gravitational/teleport/api/types"
"github.com/gravitational/teleport/integration/autoupdate/tools/updater"
"github.com/gravitational/teleport/lib/autoupdate"
"github.com/gravitational/teleport/lib/autoupdate/tools"
"github.com/gravitational/teleport/lib/modules"
)

var (
Expand Down Expand Up @@ -216,3 +219,49 @@ func TestUpdateInterruptSignal(t *testing.T) {
}
assert.Contains(t, output.String(), "Update progress:")
}

// TestUpdateForOSSBuild verifies the update logic for AGPL editions of Teleport requires
// base URL environment variable.
func TestUpdateForOSSBuild(t *testing.T) {
t.Setenv(types.HomeEnvVar, t.TempDir())
ctx := context.Background()

// Enable OSS build.
t.Setenv(updater.TestBuild, modules.BuildOSS)

// Fetch compiled test binary with updater logic and install to $TELEPORT_HOME.
updater := tools.NewUpdater(
toolsDir,
testVersions[0],
tools.WithBaseURL(baseURL),
)
err := updater.Update(ctx, testVersions[0])
require.NoError(t, err)

// Verify that requested update is ignored by OSS build and version wasn't updated.
cmd := exec.CommandContext(ctx, filepath.Join(toolsDir, "tsh"), "version")
cmd.Env = append(
os.Environ(),
fmt.Sprintf("%s=%s", teleportToolsVersion, testVersions[1]),
)
out, err := cmd.Output()
require.NoError(t, err)

matches := pattern.FindStringSubmatch(string(out))
require.Len(t, matches, 2)
require.Equal(t, testVersions[0], matches[1])

// Next update is set with the base URL env variable, must download new version.
t.Setenv(autoupdate.BaseURLEnvVar, baseURL)
cmd = exec.CommandContext(ctx, filepath.Join(toolsDir, "tsh"), "version")
cmd.Env = append(
os.Environ(),
fmt.Sprintf("%s=%s", teleportToolsVersion, testVersions[1]),
)
out, err = cmd.Output()
require.NoError(t, err)

matches = pattern.FindStringSubmatch(string(out))
require.Len(t, matches, 2)
require.Equal(t, testVersions[1], matches[1])
}
11 changes: 11 additions & 0 deletions lib/autoupdate/tools/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ import (
stacksignal "github.com/gravitational/teleport/lib/utils/signal"
)

// warnMessageOSSBuild is warning exposed to the user that build type without base url is disabled.
const warnMessageOSSBuild = "Client tools updates are disabled because the server is licensed under AGPL " +
"but Teleport-distributed binaries are licensed under Community Edition. To use Community Edition " +
"builds or custom binaries, set the 'TELEPORT_CDN_BASE_URL' environment variable."

// Variables might to be overridden during compilation time for integration tests.
var (
// version is the current version of the Teleport.
Expand Down Expand Up @@ -86,6 +91,7 @@ func CheckAndUpdateRemote(ctx context.Context, proxy string, insecure bool, reEx
slog.WarnContext(ctx, "Client tools update is disabled", "error", err)
return nil
}

// Overrides default base URL for custom CDN for downloading updates.
if envBaseURL := os.Getenv(autoupdate.BaseURLEnvVar); envBaseURL != "" {
baseURL = envBaseURL
Expand All @@ -110,6 +116,11 @@ func updateAndReExec(ctx context.Context, updater *Updater, toolsVersion string,
// is required if the user passed in the TELEPORT_TOOLS_VERSION
// explicitly.
err := updater.UpdateWithLock(ctxUpdate, toolsVersion)
if err != nil && errors.Is(err, errNoBaseURL) {
// If base URL wasn't defined we have to cancel update and re-execution with warning.
slog.WarnContext(ctx, warnMessageOSSBuild)
return nil
}
if err != nil && !errors.Is(err, context.Canceled) {
return trace.Wrap(err)
}
Expand Down
7 changes: 2 additions & 5 deletions lib/autoupdate/tools/updater.go
Original file line number Diff line number Diff line change
Expand Up @@ -409,11 +409,6 @@ func (u *Updater) downloadHash(ctx context.Context, url string) ([]byte, error)
// downloadArchive downloads the archive package by `url` and writes content to the writer interface,
// return calculated sha256 hash sum of the content.
func (u *Updater) downloadArchive(ctx context.Context, url string, f io.Writer) ([]byte, error) {
// Display a progress bar before initiating the update request to inform the user that
// an update is in progress, allowing them the option to cancel before actual response
// which might be delayed with slow internet connection or complete isolation to CDN.
pw, finish := newProgressWriter(10)
defer finish()
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
if err != nil {
return nil, trace.Wrap(err)
Expand All @@ -429,6 +424,8 @@ func (u *Updater) downloadArchive(ctx context.Context, url string, f io.Writer)
if resp.StatusCode != http.StatusOK {
return nil, trace.BadParameter("bad status when downloading archive: %v", resp.StatusCode)
}
pw, finish := newProgressWriter(10)
defer finish()

if resp.ContentLength != -1 {
if err := checkFreeSpace(u.toolsDir, uint64(resp.ContentLength)); err != nil {
Expand Down
7 changes: 7 additions & 0 deletions lib/autoupdate/tools/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ import (
"github.com/gravitational/teleport/lib/utils"
)

var errNoBaseURL = errors.New("baseURL is not defined")

// Dir returns the path to client tools in $TELEPORT_HOME/bin.
func Dir() (string, error) {
home := os.Getenv(types.HomeEnvVar)
Expand Down Expand Up @@ -128,6 +130,11 @@ type packageURL struct {

// teleportPackageURLs returns the URL for the Teleport archive to download.
func teleportPackageURLs(uriTmpl string, baseURL, version string) ([]packageURL, error) {
envBaseURL := os.Getenv(autoupdate.BaseURLEnvVar)
if modules.GetModules().BuildType() == modules.BuildOSS && envBaseURL == "" {
return nil, errNoBaseURL
}

var flags autoupdate.InstallFlags
m := modules.GetModules()
if m.IsBoringBinary() {
Expand Down