Adds WebClientTimeout to config (#7497)

Adds `web_client_timeout` to the Teleport config file and exposes it via
the Cluster Network Settings.

See-Also: #6092
This commit is contained in:
Trent Clarke
2021-07-21 10:40:05 +10:00
committed by GitHub
parent e51bb8b1b4
commit d933fe03ea
8 changed files with 642 additions and 558 deletions
+576 -544
View File
File diff suppressed because it is too large Load Diff
+5
View File
@@ -692,6 +692,11 @@ message ClusterNetworkingConfigSpecV2 {
// ClientIdleTimeoutMessage is the message sent to the user when a connection times out.
string ClientIdleTimeoutMessage = 5 [ (gogoproto.jsontag) = "idle_timeout_message" ];
// WebIdleTimeout sets global cluster default setting for the web UI idle
// timeouts.
int64 WebIdleTimeout = 6
[ (gogoproto.jsontag) = "web_idle_timeout", (gogoproto.casttype) = "Duration" ];
}
// SessionRecordingConfigV2 contains session recording configuration.
+1
View File
@@ -536,6 +536,7 @@ func applyAuthConfig(fc *FileConfig, cfg *service.Config) error {
cfg.Auth.NetworkingConfig, err = types.NewClusterNetworkingConfigFromConfigFile(types.ClusterNetworkingConfigSpecV2{
ClientIdleTimeout: fc.Auth.ClientIdleTimeout,
ClientIdleTimeoutMessage: fc.Auth.ClientIdleTimeoutMessage,
WebIdleTimeout: fc.Auth.WebIdleTimeout,
KeepAliveInterval: fc.Auth.KeepAliveInterval,
KeepAliveCountMax: fc.Auth.KeepAliveCountMax,
SessionControlTimeout: fc.Auth.SessionControlTimeout,
+2
View File
@@ -244,6 +244,7 @@ func TestConfigReading(t *testing.T) {
LicenseFile: "lic.pem",
DisconnectExpiredCert: types.NewBoolOption(true),
ClientIdleTimeout: types.Duration(17 * time.Second),
WebIdleTimeout: types.Duration(19 * time.Second),
},
SSH: SSH{
Service: Service{
@@ -909,6 +910,7 @@ func makeConfigFixture() string {
conf.Auth.ListenAddress = "tcp://auth"
conf.Auth.LicenseFile = "lic.pem"
conf.Auth.ClientIdleTimeout = types.NewDuration(17 * time.Second)
conf.Auth.WebIdleTimeout = types.NewDuration(19 * time.Second)
conf.Auth.DisconnectExpiredCert = types.NewBoolOption(true)
// ssh service:
+4
View File
@@ -523,6 +523,10 @@ type Auth struct {
// MessageOfTheDay is a banner that a user must acknowledge during a `tsh login`.
MessageOfTheDay string `yaml:"message_of_the_day,omitempty"`
// WebIdleTimeout sets global cluster default setting for WebUI client
// idle timeouts
WebIdleTimeout types.Duration `yaml:"web_idle_timeout,omitempty"`
}
// TrustedCluster struct holds configuration values under "trusted_clusters" key
+35 -12
View File
@@ -19,8 +19,10 @@ package config
import (
"bytes"
"testing"
"time"
"github.com/google/go-cmp/cmp"
"github.com/gravitational/teleport/api/types"
"github.com/stretchr/testify/require"
"gopkg.in/yaml.v2"
)
@@ -71,20 +73,22 @@ func TestAuthSection(t *testing.T) {
t.Parallel()
testCases := []struct {
desc string
mutate func(cfgMap)
expectError require.ErrorAssertionFunc
expectEnabled require.BoolAssertionFunc
expectIdleMsg require.ValueAssertionFunc
expectMotd require.ValueAssertionFunc
desc string
mutate func(cfgMap)
expectError require.ErrorAssertionFunc
expectEnabled require.BoolAssertionFunc
expectIdleMsg require.ValueAssertionFunc
expectMotd require.ValueAssertionFunc
expectWebIdleTimeout require.ValueAssertionFunc
}{
{
desc: "Default",
mutate: func(cfg cfgMap) {},
expectError: require.NoError,
expectEnabled: require.True,
expectIdleMsg: require.Empty,
expectMotd: require.Empty,
desc: "Default",
mutate: func(cfg cfgMap) {},
expectError: require.NoError,
expectEnabled: require.True,
expectIdleMsg: require.Empty,
expectMotd: require.Empty,
expectWebIdleTimeout: require.Empty,
}, {
desc: "Enabled",
mutate: func(cfg cfgMap) {
@@ -113,6 +117,21 @@ func TestAuthSection(t *testing.T) {
},
expectError: require.NoError,
expectMotd: requireEqual("Are you pondering what I'm pondering?"),
}, {
desc: "Web idle timeout",
mutate: func(cfg cfgMap) {
cfg["auth_service"].(cfgMap)["web_idle_timeout"] = "10m"
},
expectError: require.NoError,
expectWebIdleTimeout: requireEqual(types.Duration(10 * time.Minute)),
}, {
desc: "Web idle timeout (invalid)",
mutate: func(cfg cfgMap) {
cfg["auth_service"].(cfgMap)["web_idle_timeout"] = "potato"
},
expectError: require.Error,
},
}
@@ -134,6 +153,10 @@ func TestAuthSection(t *testing.T) {
if tt.expectMotd != nil {
tt.expectMotd(t, cfg.Auth.MessageOfTheDay)
}
if tt.expectWebIdleTimeout != nil {
tt.expectWebIdleTimeout(t, cfg.Auth.WebIdleTimeout)
}
})
}
}
+5
View File
@@ -168,6 +168,11 @@ type Config struct {
// ClusterFeatures contains flags for supported/unsupported features.
ClusterFeatures proto.Features
// WebIdleTimeout specifies how long a user WebUI session can be left
// idle before being logged by the server. A zero value means there
// is no idle timeout set.
WebIdleTimeout time.Duration
}
type RewritingHandler struct {
+14 -2
View File
@@ -361,20 +361,32 @@ func (c *SessionContext) getToken() (types.WebToken, error) {
}
// expired returns whether this context has expired.
// The context is considered expired when its bearer token TTL
// is in the past (subject to lingering threshold)
// Session records in the backend are created with a built-in expiry that
// automatically deletes the session record from the back-end database at
// the end of its natural life.
// If a session record still exists in the backend, it is considered still
// alive, regardless of the time. If no such record exists then a record is
// considered expired when its bearer token TTL is in the past (subject to
// lingering threshold)
func (c *SessionContext) expired(ctx context.Context) bool {
_, err := c.parent.readSession(ctx, types.GetWebSessionRequest{
User: c.user,
SessionID: c.session.GetName(),
})
// If looking up the session in the cache or backend succeeds, then
// it by definition must not have expired yet.
if err == nil {
return false
}
// If the session has no expiry time, then also by definition it
// cannot be expired
expiry := c.session.GetBearerTokenExpiryTime()
if expiry.IsZero() {
return false
}
if !trace.IsNotFound(err) {
c.log.WithError(err).Debug("Failed to query web session.")
}