Skip to content

Commit

Permalink
[v17] Client tools autoupdates (#48635)
Browse files Browse the repository at this point in the history
* Client auto updates integration for {tctl,tsh} (#47815)

* Client auto updates integration for tctl/tsh

* Add version validation
Fix recursive version check for darwin platform
Fix cleanup for multi-package support

* Fix identifying tools removal from home directory

* Replace ToolsMode with ToolsAutoUpdate

* Reuse insecure flag for tests

* Fix CheckRemote with login

* Fix windows administrative access requirement
Update must be able to be canceled, re-execute with latest version or last updated
Show progress bar before request is made

* Fix update cancellation for login action
Address review comments

* Add signal handler with stack context cancellation

* Use copy instead of hard link for windows
Fix progress bar if we can't receive size of package

* Replace with list in order to support manual cancel

* Download archive package to temp directory

* Decrease timeout for client tools proxy call

* Add audit logs for auto update resources (#48218)
  • Loading branch information
vapopov authored Nov 11, 2024
1 parent 11d0ffe commit 200eb57
Show file tree
Hide file tree
Showing 33 changed files with 2,384 additions and 1,254 deletions.
4 changes: 2 additions & 2 deletions api/client/webclient/webclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -334,8 +334,8 @@ type ProxySettings struct {
type AutoUpdateSettings struct {
// ToolsVersion defines the version of {tsh, tctl} for client auto update.
ToolsVersion string `json:"tools_version"`
// ToolsMode defines mode client auto update feature `enabled|disabled`.
ToolsMode string `json:"tools_mode"`
// ToolsAutoUpdate indicates if the requesting tools client should be updated.
ToolsAutoUpdate bool `json:"tools_auto_update"`
}

// KubeProxySettings is kubernetes proxy settings
Expand Down
42 changes: 42 additions & 0 deletions api/proto/teleport/legacy/types/events/events.proto
Original file line number Diff line number Diff line change
Expand Up @@ -6977,6 +6977,13 @@ message AutoUpdateConfigCreate {
(gogoproto.embed) = true,
(gogoproto.jsontag) = ""
];

// Status indicates whether the creation was successful.
Status Status = 5 [
(gogoproto.nullable) = false,
(gogoproto.embed) = true,
(gogoproto.jsontag) = ""
];
}

// AutoUpdateConfigUpdate is emitted when an auto update config is updated.
Expand Down Expand Up @@ -7008,6 +7015,13 @@ message AutoUpdateConfigUpdate {
(gogoproto.embed) = true,
(gogoproto.jsontag) = ""
];

// ResourceMetadata is a common resource event metadata
ResourceMetadata Resource = 5 [
(gogoproto.nullable) = false,
(gogoproto.embed) = true,
(gogoproto.jsontag) = ""
];
}

// AutoUpdateConfigDelete is emitted when an auto update config is deleted.
Expand Down Expand Up @@ -7039,6 +7053,13 @@ message AutoUpdateConfigDelete {
(gogoproto.embed) = true,
(gogoproto.jsontag) = ""
];

// Status indicates whether the deletion was successful.
Status Status = 5 [
(gogoproto.nullable) = false,
(gogoproto.embed) = true,
(gogoproto.jsontag) = ""
];
}

// AutoUpdateVersionCreate is emitted when an auto update version is created.
Expand Down Expand Up @@ -7070,6 +7091,13 @@ message AutoUpdateVersionCreate {
(gogoproto.embed) = true,
(gogoproto.jsontag) = ""
];

// Status indicates whether the creation was successful.
Status Status = 5 [
(gogoproto.nullable) = false,
(gogoproto.embed) = true,
(gogoproto.jsontag) = ""
];
}

// AutoUpdateVersionUpdate is emitted when an auto update version is updated.
Expand Down Expand Up @@ -7101,6 +7129,13 @@ message AutoUpdateVersionUpdate {
(gogoproto.embed) = true,
(gogoproto.jsontag) = ""
];

// ResourceMetadata is a common resource event metadata
ResourceMetadata Resource = 5 [
(gogoproto.nullable) = false,
(gogoproto.embed) = true,
(gogoproto.jsontag) = ""
];
}

// AutoUpdateVersionDelete is emitted when an auto update version is deleted.
Expand Down Expand Up @@ -7132,6 +7167,13 @@ message AutoUpdateVersionDelete {
(gogoproto.embed) = true,
(gogoproto.jsontag) = ""
];

// Status indicates whether the deletion was successful.
Status Status = 5 [
(gogoproto.nullable) = false,
(gogoproto.embed) = true,
(gogoproto.jsontag) = ""
];
}

// StaticHostUserCreate is emitted when a static host user is created.
Expand Down
24 changes: 24 additions & 0 deletions api/types/events/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -2328,3 +2328,27 @@ func (m *SFTPSummary) TrimToMaxSize(maxSize int) AuditEvent {

return out
}

func (m *AutoUpdateConfigCreate) TrimToMaxSize(_ int) AuditEvent {
return m
}

func (m *AutoUpdateConfigUpdate) TrimToMaxSize(_ int) AuditEvent {
return m
}

func (m *AutoUpdateConfigDelete) TrimToMaxSize(_ int) AuditEvent {
return m
}

func (m *AutoUpdateVersionCreate) TrimToMaxSize(_ int) AuditEvent {
return m
}

func (m *AutoUpdateVersionUpdate) TrimToMaxSize(_ int) AuditEvent {
return m
}

func (m *AutoUpdateVersionDelete) TrimToMaxSize(_ int) AuditEvent {
return m
}
2,401 changes: 1,342 additions & 1,059 deletions api/types/events/events.pb.go

Large diffs are not rendered by default.

25 changes: 25 additions & 0 deletions api/types/events/oneof.go
Original file line number Diff line number Diff line change
Expand Up @@ -765,6 +765,31 @@ func ToOneOf(in AuditEvent) (*OneOf, error) {
out.Event = &OneOf_SFTPSummary{
SFTPSummary: e,
}
case *AutoUpdateConfigCreate:
out.Event = &OneOf_AutoUpdateConfigCreate{
AutoUpdateConfigCreate: e,
}
case *AutoUpdateConfigUpdate:
out.Event = &OneOf_AutoUpdateConfigUpdate{
AutoUpdateConfigUpdate: e,
}
case *AutoUpdateConfigDelete:
out.Event = &OneOf_AutoUpdateConfigDelete{
AutoUpdateConfigDelete: e,
}

case *AutoUpdateVersionCreate:
out.Event = &OneOf_AutoUpdateVersionCreate{
AutoUpdateVersionCreate: e,
}
case *AutoUpdateVersionUpdate:
out.Event = &OneOf_AutoUpdateVersionUpdate{
AutoUpdateVersionUpdate: e,
}
case *AutoUpdateVersionDelete:
out.Event = &OneOf_AutoUpdateVersionDelete{
AutoUpdateVersionDelete: e,
}
default:
slog.ErrorContext(context.Background(), "Attempted to convert dynamic event of unknown type into protobuf event.", "event_type", in.GetType())
unknown := &Unknown{}
Expand Down
17 changes: 9 additions & 8 deletions integration/autoupdate/tools/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ import (

"github.com/gravitational/trace"

"github.com/gravitational/teleport/integration/helpers"
"github.com/gravitational/teleport/api/constants"
"github.com/gravitational/teleport/integration/helpers/archive"
)

const (
Expand Down Expand Up @@ -133,25 +134,25 @@ func buildAndArchiveApps(ctx context.Context, path string, toolsDir string, vers
for _, app := range []string{"tsh", "tctl"} {
output := filepath.Join(versionPath, app)
switch runtime.GOOS {
case "windows":
case constants.WindowsOS:
output = filepath.Join(versionPath, app+".exe")
case "darwin":
case constants.DarwinOS:
output = filepath.Join(versionPath, app+".app", "Contents", "MacOS", app)
}
if err := buildBinary(output, toolsDir, version, baseURL); err != nil {
return trace.Wrap(err)
}
}
switch runtime.GOOS {
case "darwin":
case constants.DarwinOS:
archivePath := filepath.Join(path, fmt.Sprintf("teleport-%s.pkg", version))
return trace.Wrap(helpers.CompressDirToPkgFile(ctx, versionPath, archivePath, "com.example.pkgtest"))
case "windows":
return trace.Wrap(archive.CompressDirToPkgFile(ctx, versionPath, archivePath, "com.example.pkgtest"))
case constants.WindowsOS:
archivePath := filepath.Join(path, fmt.Sprintf("teleport-v%s-windows-amd64-bin.zip", version))
return trace.Wrap(helpers.CompressDirToZipFile(ctx, versionPath, archivePath))
return trace.Wrap(archive.CompressDirToZipFile(ctx, versionPath, archivePath))
default:
archivePath := filepath.Join(path, fmt.Sprintf("teleport-v%s-linux-%s-bin.tar.gz", version, runtime.GOARCH))
return trace.Wrap(helpers.CompressDirToTarGzFile(ctx, versionPath, archivePath))
return trace.Wrap(archive.CompressDirToTarGzFile(ctx, versionPath, archivePath))
}
}

Expand Down
21 changes: 6 additions & 15 deletions integration/autoupdate/tools/updater/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,9 @@ import (
"log"
"os"
"os/signal"
"runtime"
"syscall"
"time"

"github.com/gravitational/teleport/api/constants"
"github.com/gravitational/teleport/lib/autoupdate/tools"
)

Expand All @@ -40,17 +38,20 @@ var (
)

func main() {
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
defer cancel()
ctx, _ = signal.NotifyContext(ctx, syscall.SIGINT, syscall.SIGTERM)

updater := tools.NewUpdater(
clientTools(),
tools.DefaultClientTools(),
toolsDir,
version,
tools.WithBaseURL(baseURL),
)
toolsVersion, reExec := updater.CheckLocal()
toolsVersion, reExec, err := updater.CheckLocal()
if err != nil {
log.Fatal(err)
}
if reExec {
// Download and update the version of client tools required by the cluster.
// This is required if the user passed in the TELEPORT_TOOLS_VERSION explicitly.
Expand All @@ -76,13 +77,3 @@ func main() {
fmt.Printf("Teleport v%v git\n", version)
}
}

// clientTools list of the client tools needs to be updated.
func clientTools() []string {
switch runtime.GOOS {
case constants.WindowsOS:
return []string{"tsh.exe", "tctl.exe"}
default:
return []string{"tsh", "tctl"}
}
}
17 changes: 3 additions & 14 deletions integration/autoupdate/tools/updater_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,13 @@ import (
"os/exec"
"path/filepath"
"regexp"
"runtime"
"strings"
"testing"
"time"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/gravitational/teleport/api/constants"
"github.com/gravitational/teleport/lib/autoupdate/tools"
)

Expand All @@ -51,7 +49,7 @@ func TestUpdate(t *testing.T) {

// Fetch compiled test binary with updater logic and install to $TELEPORT_HOME.
updater := tools.NewUpdater(
clientTools(),
tools.DefaultClientTools(),
toolsDir,
testVersions[0],
tools.WithBaseURL(baseURL),
Expand Down Expand Up @@ -93,7 +91,7 @@ func TestParallelUpdate(t *testing.T) {

// Initial fetch the updater binary un-archive and replace.
updater := tools.NewUpdater(
clientTools(),
tools.DefaultClientTools(),
toolsDir,
testVersions[0],
tools.WithBaseURL(baseURL),
Expand Down Expand Up @@ -167,7 +165,7 @@ func TestUpdateInterruptSignal(t *testing.T) {

// Initial fetch the updater binary un-archive and replace.
updater := tools.NewUpdater(
clientTools(),
tools.DefaultClientTools(),
toolsDir,
testVersions[0],
tools.WithBaseURL(baseURL),
Expand Down Expand Up @@ -220,12 +218,3 @@ func TestUpdateInterruptSignal(t *testing.T) {
}
assert.Contains(t, output.String(), "Update progress:")
}

func clientTools() []string {
switch runtime.GOOS {
case constants.WindowsOS:
return []string{"tsh.exe", "tctl.exe"}
default:
return []string{"tsh", "tctl"}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package helpers
package archive

import (
"archive/tar"
Expand Down
3 changes: 3 additions & 0 deletions integrations/event-handler/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -1133,7 +1133,10 @@ github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLe
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20240525223248-4bfdf5a9a2af h1:kmjWCqn2qkEml422C2Rrd27c3VGxi6a/6HNq8QmHRKM=
github.com/google/pprof v0.0.0-20240525223248-4bfdf5a9a2af/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo=
github.com/google/renameio v0.1.0 h1:GOZbcHa3HfsPKPlmyPyN2KEohoMXOhdMbHrvbpl2QaA=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/renameio/v2 v2.0.0 h1:UifI23ZTGY8Tt29JbYFiuyIU3eX+RNFtUwefq9qAhxg=
github.com/google/renameio/v2 v2.0.0/go.mod h1:BtmJXm5YlszgC+TD4HOEEUFgkJP3nLxehU6hfe7jRt4=
github.com/google/s2a-go v0.1.8 h1:zZDs9gcbt9ZPLV0ndSyQk6Kacx2g/X+SKYovpnz3SMM=
github.com/google/s2a-go v0.1.8/go.mod h1:6iNWHTpQ+nfNRN5E00MSdfDwVesa8hhS32PhPO8deJA=
github.com/google/safetext v0.0.0-20240104143208-7a7d9b3d812f h1:o2yGZLlsOj5H5uvtQNEdi6DeA0GbUP3lm0gWW5RvY0s=
Expand Down
1 change: 1 addition & 0 deletions integrations/terraform/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ require (
github.com/google/go-tspi v0.3.0 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/pprof v0.0.0-20240525223248-4bfdf5a9a2af // indirect
github.com/google/renameio/v2 v2.0.0 // indirect
github.com/google/s2a-go v0.1.8 // indirect
github.com/google/safetext v0.0.0-20240104143208-7a7d9b3d812f // indirect
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
Expand Down
1 change: 0 additions & 1 deletion integrations/terraform/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -1260,7 +1260,6 @@ github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLe
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20240525223248-4bfdf5a9a2af h1:kmjWCqn2qkEml422C2Rrd27c3VGxi6a/6HNq8QmHRKM=
github.com/google/pprof v0.0.0-20240525223248-4bfdf5a9a2af/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo=
github.com/google/renameio v0.1.0 h1:GOZbcHa3HfsPKPlmyPyN2KEohoMXOhdMbHrvbpl2QaA=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/renameio/v2 v2.0.0 h1:UifI23ZTGY8Tt29JbYFiuyIU3eX+RNFtUwefq9qAhxg=
github.com/google/renameio/v2 v2.0.0/go.mod h1:BtmJXm5YlszgC+TD4HOEEUFgkJP3nLxehU6hfe7jRt4=
Expand Down
Loading

0 comments on commit 200eb57

Please sign in to comment.