Skip to content

Commit

Permalink
[v16] Client tools autoupdates (#48645)
Browse files Browse the repository at this point in the history
* Expose client tools auto update for find endpoint (#46785)

* Expose client tools auto update for find endpoint

* Group auto update settings in find response
Log error instead returning error
Add tests auto update settings in find endpoint
Add check for not implemented error

* Add more test cases

* Client AutoUpdate proto structure changes (#47532)

* Update client autoupdate proto structure

* Replace with reserved

* Fix unit tests

* Add more info in proto

* Rename proto to be aligned RFD namings

* Replace enum type for ToolsMode to string

* Add packaging utility for client tools auto updates (#47060)

* Add packaging utility for client tools auto updates

* Add error handling for close functions

* Move archive to existing utils package

* Move archive helpers to integration/helper
CR changes

* CR changes

* CR changes

* CR changes
Replace creating directory with extract path as argument

* CR changes

* Validate full size before un-archive
Extract files to extractDir with ignore dir structure

* Change compressing with relative paths
Add test for cleanup and fix skip logic

* CR changes

* CR changes

* Fix linter

* Client tools auto update (#47466)

* Add client tools auto update

* Replace fork for posix platform for re-exec
Move integration tests to client tools specific dir
Use context cancellation with SIGTERM, SIGINT
Remove cancelable tee reader with context replacement
Renaming

* Fix syscall path execution
Fix archive cleanup if hash is not valid
Limit the archive write bytes

* Cover the case with single package for darwin platform after v17

* Move updater logic to tools package

* Move context out from the library
Base URL renaming

* Add more context in comments

* Changes in find endpoint

* Replace test http server with `httptest`
Replace hash for bytes matching
Proper temp file close for archive download

* Add more context to comments

* Move feature flag to main package to be reused

* Constant rename

* Replace build tag with lib/modules to identify enterprise build

* Replace fips tag with modules flag

* 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)

* Connect: Make sure tsh auto-updates are turned off (#49180)

* Add dir for code shared between Node.js processes

* Connect: Make sure tsh auto-updates are turned off

* Pass TELEPORT_TOOLS_VERSION=off to tsh vnet-daemon

* Disable client tools auto update disabled if there are no home dir (#49159)

Move updater to general tools package

* Move client auto update helper to lib package (#49247)

---------

Co-authored-by: Rafał Cieślak <[email protected]>
  • Loading branch information
vapopov and ravicious authored Dec 4, 2024
1 parent 9b8c6ed commit e15e3c7
Show file tree
Hide file tree
Showing 57 changed files with 4,831 additions and 1,181 deletions.
10 changes: 10 additions & 0 deletions api/client/webclient/webclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,8 @@ type PingResponse struct {
ServerVersion string `json:"server_version"`
// MinClientVersion is the minimum client version required by the server.
MinClientVersion string `json:"min_client_version"`
// AutoUpdateSettings contains the auto update settings.
AutoUpdate AutoUpdateSettings `json:"auto_update"`
// ClusterName contains the name of the Teleport cluster.
ClusterName string `json:"cluster_name"`

Expand Down Expand Up @@ -328,6 +330,14 @@ type ProxySettings struct {
TLSRoutingEnabled bool `json:"tls_routing_enabled"`
}

// AutoUpdateSettings contains information about the auto update requirements.
type AutoUpdateSettings struct {
// ToolsVersion defines the version of {tsh, tctl} for client auto update.
ToolsVersion string `json:"tools_version"`
// ToolsAutoUpdate indicates if the requesting tools client should be updated.
ToolsAutoUpdate bool `json:"tools_auto_update"`
}

// KubeProxySettings is kubernetes proxy settings
type KubeProxySettings struct {
// Enabled is true when kubernetes proxy is enabled
Expand Down
258 changes: 199 additions & 59 deletions api/gen/proto/go/teleport/autoupdate/v1/autoupdate.pb.go

Large diffs are not rendered by default.

23 changes: 19 additions & 4 deletions api/proto/teleport/autoupdate/v1/autoupdate.proto
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,15 @@ message AutoUpdateConfig {

// AutoUpdateConfigSpec encodes the parameters of the autoupdate config object.
message AutoUpdateConfigSpec {
// ToolsAutoupdate encodes the feature flag to enable/disable tools autoupdates.
bool tools_autoupdate = 1;
reserved 1;
reserved "tools_autoupdate"; // ToolsAutoupdate is replaced by tools.mode.
AutoUpdateConfigSpecTools tools = 2;
}

// AutoUpdateConfigSpecTools encodes the parameters for client tools auto updates.
message AutoUpdateConfigSpecTools {
// Mode defines state of the client tools auto update.
string mode = 1;
}

// AutoUpdateVersion is a resource singleton with version required for
Expand All @@ -50,6 +57,14 @@ message AutoUpdateVersion {

// AutoUpdateVersionSpec encodes the parameters of the autoupdate versions.
message AutoUpdateVersionSpec {
// ToolsVersion is the semantic version required for tools autoupdates.
string tools_version = 1;
reserved 1;
reserved "tools_version"; // ToolsVersion is replaced by tools.target_version.
AutoUpdateVersionSpecTools tools = 2;
}

// AutoUpdateVersionSpecTools encodes the parameters for client tools auto updates.
message AutoUpdateVersionSpecTools {
// TargetVersion specifies the semantic version required for tools to establish a connection with the cluster.
// Client tools after connection to the cluster going to be updated to this version automatically.
string target_version = 1;
}
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 @@ -6928,6 +6928,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 @@ -6959,6 +6966,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 @@ -6990,6 +7004,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 @@ -7021,6 +7042,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 @@ -7052,6 +7080,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 @@ -7083,6 +7118,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
12 changes: 12 additions & 0 deletions api/types/autoupdate/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,13 @@ import (
"github.com/gravitational/teleport/api/types"
)

const (
// ToolsUpdateModeEnabled enables client tools automatic updates.
ToolsUpdateModeEnabled = "enabled"
// ToolsUpdateModeDisabled disables client tools automatic updates.
ToolsUpdateModeDisabled = "disabled"
)

// NewAutoUpdateConfig creates a new auto update configuration resource.
func NewAutoUpdateConfig(spec *autoupdate.AutoUpdateConfigSpec) (*autoupdate.AutoUpdateConfig, error) {
config := &autoupdate.AutoUpdateConfig{
Expand Down Expand Up @@ -58,6 +65,11 @@ func ValidateAutoUpdateConfig(c *autoupdate.AutoUpdateConfig) error {
if c.Spec == nil {
return trace.BadParameter("Spec is nil")
}
if c.Spec.Tools != nil {
if c.Spec.Tools.Mode != ToolsUpdateModeDisabled && c.Spec.Tools.Mode != ToolsUpdateModeEnabled {
return trace.BadParameter("ToolsMode is not valid")
}
}

return nil
}
27 changes: 23 additions & 4 deletions api/types/autoupdate/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,9 @@ func TestNewAutoUpdateConfig(t *testing.T) {
{
name: "success tools autoupdate disabled",
spec: &autoupdate.AutoUpdateConfigSpec{
ToolsAutoupdate: false,
Tools: &autoupdate.AutoUpdateConfigSpecTools{
Mode: ToolsUpdateModeDisabled,
},
},
assertErr: func(t *testing.T, err error, a ...any) {
require.NoError(t, err)
Expand All @@ -53,14 +55,18 @@ func TestNewAutoUpdateConfig(t *testing.T) {
Name: types.MetaNameAutoUpdateConfig,
},
Spec: &autoupdate.AutoUpdateConfigSpec{
ToolsAutoupdate: false,
Tools: &autoupdate.AutoUpdateConfigSpecTools{
Mode: ToolsUpdateModeDisabled,
},
},
},
},
{
name: "success tools autoupdate enabled",
spec: &autoupdate.AutoUpdateConfigSpec{
ToolsAutoupdate: true,
Tools: &autoupdate.AutoUpdateConfigSpecTools{
Mode: ToolsUpdateModeEnabled,
},
},
assertErr: func(t *testing.T, err error, a ...any) {
require.NoError(t, err)
Expand All @@ -72,7 +78,9 @@ func TestNewAutoUpdateConfig(t *testing.T) {
Name: types.MetaNameAutoUpdateConfig,
},
Spec: &autoupdate.AutoUpdateConfigSpec{
ToolsAutoupdate: true,
Tools: &autoupdate.AutoUpdateConfigSpecTools{
Mode: ToolsUpdateModeEnabled,
},
},
},
},
Expand All @@ -83,6 +91,17 @@ func TestNewAutoUpdateConfig(t *testing.T) {
require.ErrorContains(t, err, "Spec is nil")
},
},
{
name: "invalid tools mode",
spec: &autoupdate.AutoUpdateConfigSpec{
Tools: &autoupdate.AutoUpdateConfigSpecTools{
Mode: "invalid-mode",
},
},
assertErr: func(t *testing.T, err error, a ...any) {
require.ErrorContains(t, err, "ToolsMode is not valid")
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
Expand Down
12 changes: 7 additions & 5 deletions api/types/autoupdate/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,13 @@ func ValidateAutoUpdateVersion(v *autoupdate.AutoUpdateVersion) error {
return trace.BadParameter("Spec is nil")
}

if v.Spec.ToolsVersion == "" {
return trace.BadParameter("ToolsVersion is unset")
}
if _, err := semver.NewVersion(v.Spec.ToolsVersion); err != nil {
return trace.BadParameter("ToolsVersion is not a valid semantic version")
if v.Spec.Tools != nil {
if v.Spec.Tools.TargetVersion == "" {
return trace.BadParameter("TargetVersion is unset")
}
if _, err := semver.NewVersion(v.Spec.Tools.TargetVersion); err != nil {
return trace.BadParameter("TargetVersion is not a valid semantic version")
}
}

return nil
Expand Down
20 changes: 14 additions & 6 deletions api/types/autoupdate/version_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,9 @@ func TestNewAutoUpdateVersion(t *testing.T) {
{
name: "success tools autoupdate version",
spec: &autoupdate.AutoUpdateVersionSpec{
ToolsVersion: "1.2.3-dev",
Tools: &autoupdate.AutoUpdateVersionSpecTools{
TargetVersion: "1.2.3-dev",
},
},
assertErr: func(t *testing.T, err error, a ...any) {
require.NoError(t, err)
Expand All @@ -53,26 +55,32 @@ func TestNewAutoUpdateVersion(t *testing.T) {
Name: types.MetaNameAutoUpdateVersion,
},
Spec: &autoupdate.AutoUpdateVersionSpec{
ToolsVersion: "1.2.3-dev",
Tools: &autoupdate.AutoUpdateVersionSpecTools{
TargetVersion: "1.2.3-dev",
},
},
},
},
{
name: "invalid empty tools version",
spec: &autoupdate.AutoUpdateVersionSpec{
ToolsVersion: "",
Tools: &autoupdate.AutoUpdateVersionSpecTools{
TargetVersion: "",
},
},
assertErr: func(t *testing.T, err error, a ...any) {
require.ErrorContains(t, err, "ToolsVersion is unset")
require.ErrorContains(t, err, "TargetVersion is unset")
},
},
{
name: "invalid semantic tools version",
spec: &autoupdate.AutoUpdateVersionSpec{
ToolsVersion: "17-0-0",
Tools: &autoupdate.AutoUpdateVersionSpecTools{
TargetVersion: "17-0-0",
},
},
assertErr: func(t *testing.T, err error, a ...any) {
require.ErrorContains(t, err, "ToolsVersion is not a valid semantic version")
require.ErrorContains(t, err, "TargetVersion is not a valid semantic version")
},
},
{
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 @@ -2302,3 +2302,27 @@ func (m *UserTaskUpdate) TrimToMaxSize(_ int) AuditEvent {
func (m *UserTaskDelete) TrimToMaxSize(_ int) AuditEvent {
return m
}

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
}
Loading

0 comments on commit e15e3c7

Please sign in to comment.