mirror of
https://github.com/gravitational/teleport
synced 2024-10-19 16:53:57 +00:00
Use fake clock consistently in units tests. (#5263)
Use fake clock consistently in units tests.
This commit is contained in:
parent
a9829381e8
commit
6684c37103
|
@ -90,7 +90,7 @@ type CertAuthority interface {
|
|||
// GetTLSKeyPairs returns first PEM encoded TLS cert
|
||||
GetTLSKeyPairs() []TLSKeyPair
|
||||
// JWTSigner returns the active JWT key used to sign tokens.
|
||||
JWTSigner() (*jwt.Key, error)
|
||||
JWTSigner(jwt.Config) (*jwt.Key, error)
|
||||
// GetJWTKeyPairs gets all JWT key pairs.
|
||||
GetJWTKeyPairs() []JWTKeyPair
|
||||
// SetJWTKeyPairs sets all JWT key pairs.
|
||||
|
@ -221,7 +221,7 @@ func (ca *CertAuthorityV2) GetTLSKeyPairs() []TLSKeyPair {
|
|||
}
|
||||
|
||||
// JWTSigner returns the active JWT key used to sign tokens.
|
||||
func (ca *CertAuthorityV2) JWTSigner() (*jwt.Key, error) {
|
||||
func (ca *CertAuthorityV2) JWTSigner(config jwt.Config) (*jwt.Key, error) {
|
||||
if len(ca.Spec.JWTKeyPairs) == 0 {
|
||||
return nil, trace.BadParameter("no JWT keypairs found")
|
||||
}
|
||||
|
@ -229,11 +229,10 @@ func (ca *CertAuthorityV2) JWTSigner() (*jwt.Key, error) {
|
|||
if err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
key, err := jwt.New(&jwt.Config{
|
||||
Algorithm: defaults.ApplicationTokenAlgorithm,
|
||||
ClusterName: ca.Spec.ClusterName,
|
||||
PrivateKey: privateKey,
|
||||
})
|
||||
config.Algorithm = defaults.ApplicationTokenAlgorithm
|
||||
config.ClusterName = ca.Spec.ClusterName
|
||||
config.PrivateKey = privateKey
|
||||
key, err := jwt.New(&config)
|
||||
if err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
|
|
2
go.mod
2
go.mod
|
@ -44,7 +44,7 @@ require (
|
|||
github.com/hashicorp/golang-lru v0.5.4
|
||||
github.com/iovisor/gobpf v0.0.1
|
||||
github.com/johannesboyne/gofakes3 v0.0.0-20191228161223-9aee1c78a252
|
||||
github.com/jonboulle/clockwork v0.2.1
|
||||
github.com/jonboulle/clockwork v0.2.2
|
||||
github.com/json-iterator/go v1.1.10
|
||||
github.com/julienschmidt/httprouter v1.2.0
|
||||
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0
|
||||
|
|
4
go.sum
4
go.sum
|
@ -355,8 +355,8 @@ github.com/johannesboyne/gofakes3 v0.0.0-20191228161223-9aee1c78a252/go.mod h1:c
|
|||
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
||||
github.com/jonboulle/clockwork v0.2.0 h1:J2SLSdy7HgElq8ekSl2Mxh6vrRNFxqbXGenYH2I02Vs=
|
||||
github.com/jonboulle/clockwork v0.2.0/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8=
|
||||
github.com/jonboulle/clockwork v0.2.1 h1:S/EaQvW6FpWMYAvYvY+OBDvpaM+izu0oiwo5y0MH7U0=
|
||||
github.com/jonboulle/clockwork v0.2.1/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8=
|
||||
github.com/jonboulle/clockwork v0.2.2 h1:UOGuzwb1PwsrDAObMuhUnj0p5ULPj8V/xJ7Kx9qUBdQ=
|
||||
github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8=
|
||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68=
|
||||
|
|
|
@ -49,12 +49,12 @@ import (
|
|||
"github.com/gravitational/teleport/lib/tlsca"
|
||||
"github.com/gravitational/teleport/lib/utils"
|
||||
"github.com/gravitational/teleport/lib/wrappers"
|
||||
"github.com/pborman/uuid"
|
||||
|
||||
"github.com/coreos/go-oidc/oauth2"
|
||||
"github.com/coreos/go-oidc/oidc"
|
||||
"github.com/gravitational/trace"
|
||||
"github.com/jonboulle/clockwork"
|
||||
"github.com/pborman/uuid"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
saml2 "github.com/russellhaering/gosaml2"
|
||||
"github.com/tstranex/u2f"
|
||||
|
@ -1842,6 +1842,13 @@ func (a *Server) GetAppSession(ctx context.Context, req services.GetAppSessionRe
|
|||
return a.GetCache().GetAppSession(ctx, req)
|
||||
}
|
||||
|
||||
// WithClock is a functional server option that sets the server's clock
|
||||
func WithClock(clock clockwork.Clock) func(*Server) {
|
||||
return func(s *Server) {
|
||||
s.clock = clock
|
||||
}
|
||||
}
|
||||
|
||||
// authKeepAliver is a keep aliver using auth server directly
|
||||
type authKeepAliver struct {
|
||||
sync.RWMutex
|
||||
|
|
|
@ -67,7 +67,7 @@ func (cfg *TestAuthServerConfig) CheckAndSetDefaults() error {
|
|||
return trace.BadParameter("missing parameter Dir")
|
||||
}
|
||||
if cfg.Clock == nil {
|
||||
cfg.Clock = clockwork.NewFakeClockAt(time.Now())
|
||||
cfg.Clock = clockwork.NewFakeClock()
|
||||
}
|
||||
if len(cfg.CipherSuites) == 0 {
|
||||
cfg.CipherSuites = utils.DefaultCipherSuites()
|
||||
|
@ -160,13 +160,13 @@ func NewTestAuthServer(cfg TestAuthServerConfig) (*TestAuthServer, error) {
|
|||
|
||||
srv.AuthServer, err = NewServer(&InitConfig{
|
||||
Backend: srv.Backend,
|
||||
Authority: authority.New(),
|
||||
Authority: authority.NewWithClock(cfg.Clock),
|
||||
Access: access,
|
||||
Identity: identity,
|
||||
AuditLog: srv.AuditLog,
|
||||
SkipPeriodicOperations: true,
|
||||
Emitter: localLog,
|
||||
})
|
||||
}, WithClock(cfg.Clock))
|
||||
if err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
|
@ -214,13 +214,25 @@ func NewTestAuthServer(cfg TestAuthServerConfig) (*TestAuthServer, error) {
|
|||
}
|
||||
|
||||
// Setup certificate and signing authorities.
|
||||
if err = srv.AuthServer.UpsertCertAuthority(suite.NewTestCA(services.HostCA, srv.ClusterName)); err != nil {
|
||||
if err = srv.AuthServer.UpsertCertAuthority(suite.NewTestCAWithConfig(suite.TestCAConfig{
|
||||
Type: services.HostCA,
|
||||
ClusterName: srv.ClusterName,
|
||||
Clock: cfg.Clock,
|
||||
})); err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
if err = srv.AuthServer.UpsertCertAuthority(suite.NewTestCA(services.UserCA, srv.ClusterName)); err != nil {
|
||||
if err = srv.AuthServer.UpsertCertAuthority(suite.NewTestCAWithConfig(suite.TestCAConfig{
|
||||
Type: services.UserCA,
|
||||
ClusterName: srv.ClusterName,
|
||||
Clock: cfg.Clock,
|
||||
})); err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
if err = srv.AuthServer.UpsertCertAuthority(suite.NewTestCA(services.JWTSigner, srv.ClusterName)); err != nil {
|
||||
if err = srv.AuthServer.UpsertCertAuthority(suite.NewTestCAWithConfig(suite.TestCAConfig{
|
||||
Type: services.JWTSigner,
|
||||
ClusterName: srv.ClusterName,
|
||||
Clock: cfg.Clock,
|
||||
})); err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
|
||||
|
@ -381,6 +393,7 @@ func (a *TestAuthServer) NewRemoteClient(identity TestIdentity, addr net.Addr, p
|
|||
tlsConfig.Certificates = []tls.Certificate{*cert}
|
||||
tlsConfig.RootCAs = pool
|
||||
tlsConfig.ServerName = EncodeClusterName(a.ClusterName)
|
||||
tlsConfig.Time = a.AuthServer.clock.Now
|
||||
addrs := []string{addr.String()}
|
||||
return NewClient(client.Config{Addrs: addrs, TLS: tlsConfig})
|
||||
}
|
||||
|
@ -461,6 +474,7 @@ func NewTestTLSServer(cfg TestTLSServerConfig) (*TestTLSServer, error) {
|
|||
if err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
tlsConfig.Time = cfg.AuthServer.Clock().Now
|
||||
|
||||
accessPoint, err := NewAdminAuthServer(srv.AuthServer.AuthServer, srv.AuthServer.SessionServer, srv.AuthServer.AuditLog)
|
||||
if err != nil {
|
||||
|
@ -549,6 +563,7 @@ func (t *TestTLSServer) NewClientFromWebSession(sess services.WebSession) (*Clie
|
|||
return nil, trace.Wrap(err, "failed to parse TLS cert and key")
|
||||
}
|
||||
tlsConfig.Certificates = []tls.Certificate{tlsCert}
|
||||
tlsConfig.Time = t.AuthServer.AuthServer.clock.Now
|
||||
addrs := []string{t.Addr().String()}
|
||||
return NewClient(client.Config{Addrs: addrs, TLS: tlsConfig})
|
||||
}
|
||||
|
@ -579,6 +594,7 @@ func (t *TestTLSServer) ClientTLSConfig(identity TestIdentity) (*tls.Config, err
|
|||
// server should apply Nop builtin role
|
||||
tlsConfig.Certificates = nil
|
||||
}
|
||||
tlsConfig.Time = t.AuthServer.AuthServer.clock.Now
|
||||
return tlsConfig, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@ import (
|
|||
"github.com/gravitational/teleport/lib/utils"
|
||||
|
||||
"github.com/gravitational/trace"
|
||||
"github.com/jonboulle/clockwork"
|
||||
)
|
||||
|
||||
// LocalRegister is used to generate host keys when a node or proxy is running
|
||||
|
@ -91,6 +92,16 @@ type RegisterParams struct {
|
|||
CAPath string
|
||||
// GetHostCredentials is a client that can fetch host credentials.
|
||||
GetHostCredentials HostCredentials
|
||||
// Clock specifies the time provider. Will be used to override the time anchor
|
||||
// for TLS certificate verification.
|
||||
// Defaults to real clock if unspecified
|
||||
Clock clockwork.Clock
|
||||
}
|
||||
|
||||
func (r *RegisterParams) setDefaults() {
|
||||
if r.Clock == nil {
|
||||
r.Clock = clockwork.NewRealClock()
|
||||
}
|
||||
}
|
||||
|
||||
// CredGetter is an interface for a client that can be used to get host
|
||||
|
@ -103,6 +114,7 @@ type HostCredentials func(context.Context, string, bool, RegisterUsingTokenReque
|
|||
// tokens to prove a valid auth server was used to issue the joining request
|
||||
// as well as a method for the node to validate the auth server.
|
||||
func Register(params RegisterParams) (*Identity, error) {
|
||||
params.setDefaults()
|
||||
// Read in the token. The token can either be passed in or come from a file
|
||||
// on disk.
|
||||
token, err := utils.ReadToken(params.Token)
|
||||
|
@ -219,6 +231,7 @@ func registerThroughAuth(token string, params RegisterParams) (*Identity, error)
|
|||
// Server it is connecting to.
|
||||
func insecureRegisterClient(params RegisterParams) (*Client, error) {
|
||||
tlsConfig := utils.TLSConfig(params.CipherSuites)
|
||||
tlsConfig.Time = params.Clock.Now
|
||||
|
||||
cert, err := readCA(params)
|
||||
if err != nil && !trace.IsNotFound(err) {
|
||||
|
@ -275,6 +288,7 @@ func pinRegisterClient(params RegisterParams) (*Client, error) {
|
|||
// an attacker were to MITM this connection the CA pin will not match below.
|
||||
tlsConfig := utils.TLSConfig(params.CipherSuites)
|
||||
tlsConfig.InsecureSkipVerify = true
|
||||
tlsConfig.Time = params.Clock.Now
|
||||
authClient, err := NewClient(client.Config{Addrs: utils.NetAddrsToStrings(params.Servers), TLS: tlsConfig})
|
||||
if err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
|
@ -305,6 +319,7 @@ func pinRegisterClient(params RegisterParams) (*Client, error) {
|
|||
// Create another client, but this time with the CA provided to validate
|
||||
// that the Auth Server was issued a certificate by the same CA.
|
||||
tlsConfig = utils.TLSConfig(params.CipherSuites)
|
||||
tlsConfig.Time = params.Clock.Now
|
||||
certPool := x509.NewCertPool()
|
||||
certPool.AddCert(tlsCA)
|
||||
tlsConfig.RootCAs = certPool
|
||||
|
|
|
@ -497,10 +497,15 @@ func startNewRotation(req rotationReq, ca services.CertAuthority) error {
|
|||
sshPublicKey = ssh.MarshalAuthorizedKey(signer.PublicKey())
|
||||
sshPrivateKey = req.privateKey
|
||||
|
||||
tlsPrivateKey, tlsPublicKey, err = tlsca.GenerateSelfSignedCAWithPrivateKey(rsaKey.(*rsa.PrivateKey), pkix.Name{
|
||||
CommonName: ca.GetClusterName(),
|
||||
Organization: []string{ca.GetClusterName()},
|
||||
}, nil, defaults.CATTL)
|
||||
tlsPrivateKey, tlsPublicKey, err = tlsca.GenerateSelfSignedCAWithConfig(tlsca.GenerateCAConfig{
|
||||
PrivateKey: rsaKey.(*rsa.PrivateKey),
|
||||
Entity: pkix.Name{
|
||||
CommonName: ca.GetClusterName(),
|
||||
Organization: []string{ca.GetClusterName()},
|
||||
},
|
||||
TTL: defaults.CATTL,
|
||||
Clock: req.clock,
|
||||
})
|
||||
if err != nil {
|
||||
return trace.Wrap(err)
|
||||
}
|
||||
|
|
|
@ -107,7 +107,7 @@ func (s *Server) generateAppToken(username string, roles []string, uri string, e
|
|||
}
|
||||
|
||||
// Extract the JWT signing key and sign the claims.
|
||||
privateKey, err := ca.JWTSigner()
|
||||
privateKey, err := ca.JWTSigner(jwt.Config{Clock: s.clock})
|
||||
if err != nil {
|
||||
return "", trace.Wrap(err)
|
||||
}
|
||||
|
|
|
@ -19,7 +19,6 @@ package testauthority
|
|||
import (
|
||||
"crypto/rand"
|
||||
random "math/rand"
|
||||
"time"
|
||||
|
||||
"github.com/gravitational/teleport"
|
||||
"github.com/gravitational/teleport/lib/auth/native"
|
||||
|
@ -29,14 +28,22 @@ import (
|
|||
"github.com/gravitational/teleport/lib/wrappers"
|
||||
|
||||
"github.com/gravitational/trace"
|
||||
"github.com/jonboulle/clockwork"
|
||||
"golang.org/x/crypto/ssh"
|
||||
)
|
||||
|
||||
type Keygen struct {
|
||||
clock clockwork.Clock
|
||||
}
|
||||
|
||||
// New creates a new key generator with defaults
|
||||
func New() *Keygen {
|
||||
return &Keygen{}
|
||||
return &Keygen{clock: clockwork.NewRealClock()}
|
||||
}
|
||||
|
||||
// NewWithClock creates a new key generator with the specified configuration
|
||||
func NewWithClock(clock clockwork.Clock) *Keygen {
|
||||
return &Keygen{clock: clock}
|
||||
}
|
||||
|
||||
func (n *Keygen) Close() {
|
||||
|
@ -57,7 +64,7 @@ func (n *Keygen) GenerateHostCert(c services.HostCertParams) ([]byte, error) {
|
|||
}
|
||||
validBefore := uint64(ssh.CertTimeInfinity)
|
||||
if c.TTL != 0 {
|
||||
b := time.Now().Add(c.TTL)
|
||||
b := n.clock.Now().Add(c.TTL)
|
||||
validBefore = uint64(b.Unix())
|
||||
}
|
||||
principals := native.BuildPrincipals(c.HostID, c.NodeName, c.ClusterName, c.Roles)
|
||||
|
@ -89,7 +96,7 @@ func (n *Keygen) GenerateUserCert(c services.UserCertParams) ([]byte, error) {
|
|||
}
|
||||
validBefore := uint64(ssh.CertTimeInfinity)
|
||||
if c.TTL != 0 {
|
||||
b := time.Now().Add(c.TTL)
|
||||
b := n.clock.Now().Add(c.TTL)
|
||||
validBefore = uint64(b.Unix())
|
||||
}
|
||||
cert := &ssh.Certificate{
|
||||
|
|
|
@ -57,6 +57,7 @@ import (
|
|||
type TLSSuite struct {
|
||||
dataDir string
|
||||
server *TestTLSServer
|
||||
clock clockwork.FakeClock
|
||||
}
|
||||
|
||||
var _ = check.Suite(&TLSSuite{})
|
||||
|
@ -69,9 +70,11 @@ func (s *TLSSuite) SetUpSuite(c *check.C) {
|
|||
|
||||
func (s *TLSSuite) SetUpTest(c *check.C) {
|
||||
s.dataDir = c.MkDir()
|
||||
s.clock = clockwork.NewFakeClock()
|
||||
|
||||
testAuthServer, err := NewTestAuthServer(TestAuthServerConfig{
|
||||
Dir: s.dataDir,
|
||||
Dir: s.dataDir,
|
||||
Clock: s.clock,
|
||||
})
|
||||
c.Assert(err, check.IsNil)
|
||||
s.server, err = testAuthServer.NewTestTLSServer()
|
||||
|
@ -90,6 +93,7 @@ func (s *TLSSuite) TestRemoteBuiltinRole(c *check.C) {
|
|||
remoteServer, err := NewTestAuthServer(TestAuthServerConfig{
|
||||
Dir: c.MkDir(),
|
||||
ClusterName: "remote",
|
||||
Clock: s.clock,
|
||||
})
|
||||
c.Assert(err, check.IsNil)
|
||||
|
||||
|
@ -131,6 +135,7 @@ func (s *TLSSuite) TestAcceptedUsage(c *check.C) {
|
|||
Dir: c.MkDir(),
|
||||
ClusterName: "remote",
|
||||
AcceptedUsage: []string{"usage:k8s"},
|
||||
Clock: s.clock,
|
||||
})
|
||||
c.Assert(err, check.IsNil)
|
||||
|
||||
|
@ -188,6 +193,7 @@ func (s *TLSSuite) TestRemoteRotation(c *check.C) {
|
|||
remoteServer, err := NewTestAuthServer(TestAuthServerConfig{
|
||||
Dir: c.MkDir(),
|
||||
ClusterName: "remote",
|
||||
Clock: s.clock,
|
||||
})
|
||||
c.Assert(err, check.IsNil)
|
||||
|
||||
|
@ -287,6 +293,7 @@ func (s *TLSSuite) TestLocalProxyPermissions(c *check.C) {
|
|||
remoteServer, err := NewTestAuthServer(TestAuthServerConfig{
|
||||
Dir: c.MkDir(),
|
||||
ClusterName: "remote",
|
||||
Clock: s.clock,
|
||||
})
|
||||
c.Assert(err, check.IsNil)
|
||||
|
||||
|
@ -322,9 +329,6 @@ func (s *TLSSuite) TestLocalProxyPermissions(c *check.C) {
|
|||
func (s *TLSSuite) TestAutoRotation(c *check.C) {
|
||||
var ok bool
|
||||
|
||||
clock := clockwork.NewFakeClockAt(time.Now().Add(-2 * time.Hour))
|
||||
s.server.Auth().SetClock(clock)
|
||||
|
||||
// create proxy client
|
||||
proxy, err := s.server.NewClient(TestBuiltin(teleport.RoleProxy))
|
||||
c.Assert(err, check.IsNil)
|
||||
|
@ -345,7 +349,7 @@ func (s *TLSSuite) TestAutoRotation(c *check.C) {
|
|||
c.Assert(err, check.IsNil)
|
||||
|
||||
// advance rotation by clock
|
||||
clock.Advance(gracePeriod/3 + time.Minute)
|
||||
s.clock.Advance(gracePeriod/3 + time.Minute)
|
||||
err = s.server.Auth().autoRotateCertAuthorities()
|
||||
c.Assert(err, check.IsNil)
|
||||
|
||||
|
@ -365,7 +369,7 @@ func (s *TLSSuite) TestAutoRotation(c *check.C) {
|
|||
c.Assert(err, check.IsNil)
|
||||
|
||||
// advance rotation by clock
|
||||
clock.Advance((gracePeriod*2)/3 + time.Minute)
|
||||
s.clock.Advance((gracePeriod*2)/3 + time.Minute)
|
||||
err = s.server.Auth().autoRotateCertAuthorities()
|
||||
c.Assert(err, check.IsNil)
|
||||
|
||||
|
@ -388,7 +392,7 @@ func (s *TLSSuite) TestAutoRotation(c *check.C) {
|
|||
c.Assert(err, check.IsNil)
|
||||
|
||||
// complete rotation - advance rotation by clock
|
||||
clock.Advance(gracePeriod/3 + time.Minute)
|
||||
s.clock.Advance(gracePeriod/3 + time.Minute)
|
||||
err = s.server.Auth().autoRotateCertAuthorities()
|
||||
c.Assert(err, check.IsNil)
|
||||
ca, err = s.server.Auth().GetCertAuthority(services.CertAuthID{
|
||||
|
@ -418,9 +422,6 @@ func (s *TLSSuite) TestAutoRotation(c *check.C) {
|
|||
func (s *TLSSuite) TestAutoFallback(c *check.C) {
|
||||
var ok bool
|
||||
|
||||
clock := clockwork.NewFakeClockAt(time.Now().Add(-2 * time.Hour))
|
||||
s.server.Auth().SetClock(clock)
|
||||
|
||||
// create proxy client just for test purposes
|
||||
proxy, err := s.server.NewClient(TestBuiltin(teleport.RoleProxy))
|
||||
c.Assert(err, check.IsNil)
|
||||
|
@ -441,7 +442,7 @@ func (s *TLSSuite) TestAutoFallback(c *check.C) {
|
|||
c.Assert(err, check.IsNil)
|
||||
|
||||
// advance rotation by clock
|
||||
clock.Advance(gracePeriod/3 + time.Minute)
|
||||
s.clock.Advance(gracePeriod/3 + time.Minute)
|
||||
err = s.server.Auth().autoRotateCertAuthorities()
|
||||
c.Assert(err, check.IsNil)
|
||||
|
||||
|
@ -670,9 +671,6 @@ func (s *TLSSuite) TestRollback(c *check.C) {
|
|||
// TestAppTokenRotation checks that JWT tokens can be rotated and tokens can or
|
||||
// can not be validated at the appropriate phase.
|
||||
func (s *TLSSuite) TestAppTokenRotation(c *check.C) {
|
||||
clock := clockwork.NewFakeClockAt(time.Now())
|
||||
s.server.Auth().SetClock(clock)
|
||||
|
||||
client, err := s.server.NewClient(TestBuiltin(teleport.RoleApp))
|
||||
c.Assert(err, check.IsNil)
|
||||
|
||||
|
@ -683,7 +681,7 @@ func (s *TLSSuite) TestAppTokenRotation(c *check.C) {
|
|||
Username: "foo",
|
||||
Roles: []string{"bar", "baz"},
|
||||
URI: "http://localhost:8080",
|
||||
Expires: clock.Now().Add(1 * time.Minute),
|
||||
Expires: s.clock.Now().Add(1 * time.Minute),
|
||||
})
|
||||
c.Assert(err, check.IsNil)
|
||||
|
||||
|
@ -696,7 +694,7 @@ func (s *TLSSuite) TestAppTokenRotation(c *check.C) {
|
|||
c.Assert(oldCA.GetJWTKeyPairs(), check.HasLen, 1)
|
||||
|
||||
// Verify that the JWT token validates with the JWT authority.
|
||||
_, err = s.verifyJWT(clock, s.server.ClusterName(), oldCA.GetJWTKeyPairs(), oldJWT)
|
||||
_, err = s.verifyJWT(s.clock, s.server.ClusterName(), oldCA.GetJWTKeyPairs(), oldJWT)
|
||||
c.Assert(err, check.IsNil)
|
||||
|
||||
// Start rotation and move to initial phase. A new CA will be added (for
|
||||
|
@ -720,7 +718,7 @@ func (s *TLSSuite) TestAppTokenRotation(c *check.C) {
|
|||
c.Assert(oldCA.GetJWTKeyPairs(), check.HasLen, 2)
|
||||
|
||||
// Verify that the JWT token validates with the JWT authority.
|
||||
_, err = s.verifyJWT(clock, s.server.ClusterName(), oldCA.GetJWTKeyPairs(), oldJWT)
|
||||
_, err = s.verifyJWT(s.clock, s.server.ClusterName(), oldCA.GetJWTKeyPairs(), oldJWT)
|
||||
c.Assert(err, check.IsNil)
|
||||
|
||||
// Move rotation into the update client phase. In this phase, requests will
|
||||
|
@ -739,7 +737,7 @@ func (s *TLSSuite) TestAppTokenRotation(c *check.C) {
|
|||
Username: "foo",
|
||||
Roles: []string{"bar", "baz"},
|
||||
URI: "http://localhost:8080",
|
||||
Expires: clock.Now().Add(1 * time.Minute),
|
||||
Expires: s.clock.Now().Add(1 * time.Minute),
|
||||
})
|
||||
c.Assert(err, check.IsNil)
|
||||
|
||||
|
@ -753,9 +751,9 @@ func (s *TLSSuite) TestAppTokenRotation(c *check.C) {
|
|||
c.Assert(newCA.GetRotation().Phase, check.Equals, services.RotationPhaseUpdateClients)
|
||||
|
||||
// Both JWT should now validate.
|
||||
_, err = s.verifyJWT(clock, s.server.ClusterName(), newCA.GetJWTKeyPairs(), oldJWT)
|
||||
_, err = s.verifyJWT(s.clock, s.server.ClusterName(), newCA.GetJWTKeyPairs(), oldJWT)
|
||||
c.Assert(err, check.IsNil)
|
||||
_, err = s.verifyJWT(clock, s.server.ClusterName(), newCA.GetJWTKeyPairs(), newJWT)
|
||||
_, err = s.verifyJWT(s.clock, s.server.ClusterName(), newCA.GetJWTKeyPairs(), newJWT)
|
||||
c.Assert(err, check.IsNil)
|
||||
|
||||
// Move rotation into update servers phase.
|
||||
|
@ -777,9 +775,9 @@ func (s *TLSSuite) TestAppTokenRotation(c *check.C) {
|
|||
c.Assert(newCA.GetRotation().Phase, check.Equals, services.RotationPhaseUpdateServers)
|
||||
|
||||
// Both JWT should continue to validate.
|
||||
_, err = s.verifyJWT(clock, s.server.ClusterName(), newCA.GetJWTKeyPairs(), oldJWT)
|
||||
_, err = s.verifyJWT(s.clock, s.server.ClusterName(), newCA.GetJWTKeyPairs(), oldJWT)
|
||||
c.Assert(err, check.IsNil)
|
||||
_, err = s.verifyJWT(clock, s.server.ClusterName(), newCA.GetJWTKeyPairs(), newJWT)
|
||||
_, err = s.verifyJWT(s.clock, s.server.ClusterName(), newCA.GetJWTKeyPairs(), newJWT)
|
||||
c.Assert(err, check.IsNil)
|
||||
|
||||
// Complete rotation. The old CA will be removed.
|
||||
|
@ -801,9 +799,9 @@ func (s *TLSSuite) TestAppTokenRotation(c *check.C) {
|
|||
c.Assert(newCA.GetRotation().Phase, check.Equals, services.RotationPhaseStandby)
|
||||
|
||||
// Old token should no longer validate.
|
||||
_, err = s.verifyJWT(clock, s.server.ClusterName(), newCA.GetJWTKeyPairs(), oldJWT)
|
||||
_, err = s.verifyJWT(s.clock, s.server.ClusterName(), newCA.GetJWTKeyPairs(), oldJWT)
|
||||
c.Assert(err, check.NotNil)
|
||||
_, err = s.verifyJWT(clock, s.server.ClusterName(), newCA.GetJWTKeyPairs(), newJWT)
|
||||
_, err = s.verifyJWT(s.clock, s.server.ClusterName(), newCA.GetJWTKeyPairs(), newJWT)
|
||||
c.Assert(err, check.IsNil)
|
||||
}
|
||||
|
||||
|
@ -813,6 +811,7 @@ func (s *TLSSuite) TestRemoteUser(c *check.C) {
|
|||
remoteServer, err := NewTestAuthServer(TestAuthServerConfig{
|
||||
Dir: c.MkDir(),
|
||||
ClusterName: "remote",
|
||||
Clock: s.clock,
|
||||
})
|
||||
c.Assert(err, check.IsNil)
|
||||
|
||||
|
@ -924,6 +923,7 @@ func (s *TLSSuite) TestTunnelConnectionsCRUD(c *check.C) {
|
|||
|
||||
suite := &suite.ServicesTestSuite{
|
||||
PresenceS: clt,
|
||||
Clock: clockwork.NewFakeClock(),
|
||||
}
|
||||
suite.TunnelConnectionsCRUD(c)
|
||||
}
|
||||
|
@ -1178,7 +1178,7 @@ func (s *TLSSuite) TestValidatePostSessionSlice(c *check.C) {
|
|||
Namespace: defaults.Namespace,
|
||||
SessionID: string(sess.ID),
|
||||
Chunks: []*events.SessionChunk{
|
||||
&events.SessionChunk{
|
||||
{
|
||||
Time: time.Now().UTC().UnixNano(),
|
||||
EventIndex: 0,
|
||||
EventType: events.SessionStartEvent,
|
||||
|
@ -1244,13 +1244,13 @@ func (s *TLSSuite) TestSharedSessions(c *check.C) {
|
|||
Namespace: defaults.Namespace,
|
||||
SessionID: string(sess.ID),
|
||||
Chunks: []*events.SessionChunk{
|
||||
&events.SessionChunk{
|
||||
{
|
||||
Time: time.Now().UTC().UnixNano(),
|
||||
EventIndex: 0,
|
||||
EventType: events.SessionStartEvent,
|
||||
Data: marshal(events.EventFields{events.EventLogin: "bob", "val": "one"}),
|
||||
},
|
||||
&events.SessionChunk{
|
||||
{
|
||||
Time: time.Now().UTC().UnixNano(),
|
||||
EventIndex: 1,
|
||||
EventType: events.SessionEndEvent,
|
||||
|
@ -1276,13 +1276,13 @@ func (s *TLSSuite) TestSharedSessions(c *check.C) {
|
|||
Namespace: defaults.Namespace,
|
||||
SessionID: string(anotherSessionID),
|
||||
Chunks: []*events.SessionChunk{
|
||||
&events.SessionChunk{
|
||||
{
|
||||
Time: time.Now().UTC().UnixNano(),
|
||||
EventIndex: 0,
|
||||
EventType: events.SessionStartEvent,
|
||||
Data: marshal(events.EventFields{events.EventLogin: "alice", "val": "three"}),
|
||||
},
|
||||
&events.SessionChunk{
|
||||
{
|
||||
Time: time.Now().UTC().UnixNano(),
|
||||
EventIndex: 1,
|
||||
EventType: events.SessionEndEvent,
|
||||
|
@ -2008,9 +2008,6 @@ func (s *TLSSuite) TestGenerateCerts(c *check.C) {
|
|||
// TestGenerateAppToken checks the identity of the caller and makes sure only
|
||||
// certain roles can request JWT tokens.
|
||||
func (s *TLSSuite) TestGenerateAppToken(c *check.C) {
|
||||
clock := clockwork.NewFakeClockAt(time.Now())
|
||||
s.server.Auth().SetClock(clock)
|
||||
|
||||
authClient, err := s.server.NewClient(TestBuiltin(teleport.RoleAdmin))
|
||||
c.Assert(err, check.IsNil)
|
||||
|
||||
|
@ -2020,7 +2017,7 @@ func (s *TLSSuite) TestGenerateAppToken(c *check.C) {
|
|||
}, true)
|
||||
c.Assert(err, check.IsNil)
|
||||
|
||||
key, err := ca.JWTSigner()
|
||||
key, err := ca.JWTSigner(jwt.Config{Clock: s.clock})
|
||||
c.Assert(err, check.IsNil)
|
||||
|
||||
var tests = []struct {
|
||||
|
@ -2054,7 +2051,7 @@ func (s *TLSSuite) TestGenerateAppToken(c *check.C) {
|
|||
Username: "foo@example.com",
|
||||
Roles: []string{"bar", "baz"},
|
||||
URI: "http://localhost:8080",
|
||||
Expires: clock.Now().Add(1 * time.Minute),
|
||||
Expires: s.clock.Now().Add(1 * time.Minute),
|
||||
})
|
||||
c.Assert(err != nil, check.Equals, tt.outError, tt.inComment)
|
||||
if !tt.outError {
|
||||
|
@ -2195,7 +2192,7 @@ func (s *TLSSuite) TestAuthenticateWebUserOTP(c *check.C) {
|
|||
c.Assert(err, check.IsNil)
|
||||
|
||||
// create a valid otp token
|
||||
validToken, err := totp.GenerateCode(otpSecret, s.server.Clock().Now())
|
||||
validToken, err := totp.GenerateCode(otpSecret, s.clock.Now())
|
||||
c.Assert(err, check.IsNil)
|
||||
|
||||
proxy, err := s.server.NewClient(TestBuiltin(teleport.RoleProxy))
|
||||
|
@ -2496,6 +2493,7 @@ func (s *TLSSuite) TestRegisterCAPin(c *check.C) {
|
|||
PublicSSHKey: pub,
|
||||
PublicTLSKey: pubTLS,
|
||||
CAPin: caPin,
|
||||
Clock: s.clock,
|
||||
})
|
||||
c.Assert(err, check.IsNil)
|
||||
|
||||
|
@ -2513,6 +2511,7 @@ func (s *TLSSuite) TestRegisterCAPin(c *check.C) {
|
|||
PublicSSHKey: pub,
|
||||
PublicTLSKey: pubTLS,
|
||||
CAPin: "sha256:123",
|
||||
Clock: s.clock,
|
||||
})
|
||||
c.Assert(err, check.NotNil)
|
||||
}
|
||||
|
@ -2551,6 +2550,7 @@ func (s *TLSSuite) TestRegisterCAPath(c *check.C) {
|
|||
PrivateKey: priv,
|
||||
PublicSSHKey: pub,
|
||||
PublicTLSKey: pubTLS,
|
||||
Clock: s.clock,
|
||||
})
|
||||
c.Assert(err, check.IsNil)
|
||||
|
||||
|
@ -2582,6 +2582,7 @@ func (s *TLSSuite) TestRegisterCAPath(c *check.C) {
|
|||
PublicSSHKey: pub,
|
||||
PublicTLSKey: pubTLS,
|
||||
CAPath: caPath,
|
||||
Clock: s.clock,
|
||||
})
|
||||
c.Assert(err, check.IsNil)
|
||||
}
|
||||
|
|
|
@ -226,10 +226,11 @@ func (c *Connector) Close() error {
|
|||
// TeleportProcess structure holds the state of the Teleport daemon, controlling
|
||||
// execution and configuration of the teleport services: ssh, auth and proxy.
|
||||
type TeleportProcess struct {
|
||||
clockwork.Clock
|
||||
Clock clockwork.Clock
|
||||
sync.Mutex
|
||||
Supervisor
|
||||
Config *Config
|
||||
|
||||
// localAuth has local auth server listed in case if this process
|
||||
// has started with auth server role enabled
|
||||
localAuth *auth.Server
|
||||
|
@ -1314,7 +1315,7 @@ func (process *TeleportProcess) initAuthService() error {
|
|||
} else {
|
||||
srv.Spec.Rotation = state.Spec.Rotation
|
||||
}
|
||||
srv.SetTTL(process, defaults.ServerAnnounceTTL)
|
||||
srv.SetTTL(process.Clock, defaults.ServerAnnounceTTL)
|
||||
return &srv, nil
|
||||
},
|
||||
KeepAlivePeriod: defaults.ServerKeepAliveTTL,
|
||||
|
|
|
@ -88,7 +88,7 @@ func (f *processState) update(event Event) {
|
|||
s, ok := f.states[component]
|
||||
if !ok {
|
||||
// Register a new component.
|
||||
s = &componentState{recoveryTime: f.process.Now(), state: stateStarting}
|
||||
s = &componentState{recoveryTime: f.process.Clock.Now(), state: stateStarting}
|
||||
f.states[component] = s
|
||||
}
|
||||
|
||||
|
@ -109,10 +109,10 @@ func (f *processState) update(event Event) {
|
|||
f.process.log.Debugf("Teleport component %q has started.", component)
|
||||
case stateDegraded:
|
||||
s.state = stateRecovering
|
||||
s.recoveryTime = f.process.Now()
|
||||
s.recoveryTime = f.process.Clock.Now()
|
||||
f.process.log.Infof("Teleport component %q is recovering from a degraded state.", component)
|
||||
case stateRecovering:
|
||||
if f.process.Now().Sub(s.recoveryTime) > defaults.HeartbeatCheckPeriod*2 {
|
||||
if f.process.Clock.Now().Sub(s.recoveryTime) > defaults.HeartbeatCheckPeriod*2 {
|
||||
s.state = stateOK
|
||||
f.process.log.Infof("Teleport component %q has recovered from a degraded state.", component)
|
||||
}
|
||||
|
|
|
@ -141,7 +141,7 @@ type UserCertParams struct {
|
|||
ActiveRequests RequestIDs
|
||||
}
|
||||
|
||||
// Check checks the user cert parameters
|
||||
// Check checks the user certificate parameters
|
||||
func (c UserCertParams) Check() error {
|
||||
if len(c.PrivateCASigningKey) == 0 || c.CASigningAlg == "" {
|
||||
return trace.BadParameter("PrivateCASigningKey and CASigningAlg are required")
|
||||
|
|
|
@ -47,7 +47,7 @@ func (s *ServicesSuite) SetUpSuite(c *check.C) {
|
|||
func (s *ServicesSuite) SetUpTest(c *check.C) {
|
||||
var err error
|
||||
|
||||
clock := clockwork.NewFakeClockAt(time.Now())
|
||||
clock := clockwork.NewFakeClock()
|
||||
|
||||
s.bk, err = lite.NewWithConfig(context.TODO(), lite.Config{
|
||||
Path: c.MkDir(),
|
||||
|
|
|
@ -53,11 +53,31 @@ var _ = fmt.Printf
|
|||
// NewTestCA returns new test authority with a test key as a public and
|
||||
// signing key
|
||||
func NewTestCA(caType services.CertAuthType, clusterName string, privateKeys ...[]byte) *services.CertAuthorityV2 {
|
||||
return NewTestCAWithConfig(TestCAConfig{
|
||||
Type: caType,
|
||||
ClusterName: clusterName,
|
||||
PrivateKeys: privateKeys,
|
||||
Clock: clockwork.NewRealClock(),
|
||||
})
|
||||
}
|
||||
|
||||
// TestCAConfig defines the configuration for generating
|
||||
// a test certificate authority
|
||||
type TestCAConfig struct {
|
||||
Type services.CertAuthType
|
||||
ClusterName string
|
||||
PrivateKeys [][]byte
|
||||
Clock clockwork.Clock
|
||||
}
|
||||
|
||||
// NewTestCAWithConfig generates a new certificate authority with the specified
|
||||
// configuration
|
||||
func NewTestCAWithConfig(config TestCAConfig) *services.CertAuthorityV2 {
|
||||
// privateKeys is to specify another RSA private key
|
||||
if len(privateKeys) == 0 {
|
||||
privateKeys = [][]byte{fixtures.PEMBytes["rsa"]}
|
||||
if len(config.PrivateKeys) == 0 {
|
||||
config.PrivateKeys = [][]byte{fixtures.PEMBytes["rsa"]}
|
||||
}
|
||||
keyBytes := privateKeys[0]
|
||||
keyBytes := config.PrivateKeys[0]
|
||||
rsaKey, err := ssh.ParseRawPrivateKey(keyBytes)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
|
@ -68,10 +88,15 @@ func NewTestCA(caType services.CertAuthType, clusterName string, privateKeys ...
|
|||
panic(err)
|
||||
}
|
||||
|
||||
key, cert, err := tlsca.GenerateSelfSignedCAWithPrivateKey(rsaKey.(*rsa.PrivateKey), pkix.Name{
|
||||
CommonName: clusterName,
|
||||
Organization: []string{clusterName},
|
||||
}, nil, defaults.CATTL)
|
||||
key, cert, err := tlsca.GenerateSelfSignedCAWithConfig(tlsca.GenerateCAConfig{
|
||||
PrivateKey: rsaKey.(*rsa.PrivateKey),
|
||||
Entity: pkix.Name{
|
||||
CommonName: config.ClusterName,
|
||||
Organization: []string{config.ClusterName},
|
||||
},
|
||||
TTL: defaults.CATTL,
|
||||
Clock: config.Clock,
|
||||
})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
@ -83,15 +108,15 @@ func NewTestCA(caType services.CertAuthType, clusterName string, privateKeys ...
|
|||
|
||||
return &services.CertAuthorityV2{
|
||||
Kind: services.KindCertAuthority,
|
||||
SubKind: string(caType),
|
||||
SubKind: string(config.Type),
|
||||
Version: services.V2,
|
||||
Metadata: services.Metadata{
|
||||
Name: clusterName,
|
||||
Name: config.ClusterName,
|
||||
Namespace: defaults.Namespace,
|
||||
},
|
||||
Spec: services.CertAuthoritySpecV2{
|
||||
Type: caType,
|
||||
ClusterName: clusterName,
|
||||
Type: config.Type,
|
||||
ClusterName: config.ClusterName,
|
||||
CheckingKeys: [][]byte{ssh.MarshalAuthorizedKey(signer.PublicKey())},
|
||||
SigningKeys: [][]byte{keyBytes},
|
||||
TLSKeyPairs: []services.TLSKeyPair{{Cert: cert, Key: key}},
|
||||
|
@ -528,7 +553,7 @@ func (s *ServicesTestSuite) WebSessionCRUD(c *check.C) {
|
|||
_, err := s.WebS.GetWebSession("user1", "sid1")
|
||||
c.Assert(trace.IsNotFound(err), check.Equals, true, check.Commentf("%#v", err))
|
||||
|
||||
dt := time.Date(2015, 6, 5, 4, 3, 2, 1, time.UTC).UTC()
|
||||
dt := s.Clock.Now().Add(1 * time.Minute)
|
||||
ws := services.NewWebSession("sid1", services.KindWebSession, services.KindWebSession,
|
||||
services.WebSessionSpecV2{
|
||||
Pub: []byte("pub123"),
|
||||
|
@ -575,7 +600,7 @@ func (s *ServicesTestSuite) TokenCRUD(c *check.C) {
|
|||
c.Assert(token.GetRoles().Include(teleport.RoleAuth), check.Equals, true)
|
||||
c.Assert(token.GetRoles().Include(teleport.RoleNode), check.Equals, true)
|
||||
c.Assert(token.GetRoles().Include(teleport.RoleProxy), check.Equals, false)
|
||||
diff := time.Now().UTC().Add(defaults.ProvisioningTokenTTL).Second() - token.Expiry().Second()
|
||||
diff := s.Clock.Now().UTC().Add(defaults.ProvisioningTokenTTL).Second() - token.Expiry().Second()
|
||||
if diff > 1 {
|
||||
c.Fatalf("expected diff to be within one second, got %v instead", diff)
|
||||
}
|
||||
|
@ -823,7 +848,7 @@ func (s *ServicesTestSuite) TunnelConnectionsCRUD(c *check.C) {
|
|||
c.Assert(err, check.IsNil)
|
||||
c.Assert(len(out), check.Equals, 0)
|
||||
|
||||
dt := time.Date(2015, 6, 5, 4, 3, 2, 1, time.UTC).UTC()
|
||||
dt := s.Clock.Now()
|
||||
conn, err := services.NewTunnelConnection("conn1", services.TunnelConnectionSpecV2{
|
||||
ClusterName: clusterName,
|
||||
ProxyName: "p1",
|
||||
|
|
|
@ -46,7 +46,7 @@ import (
|
|||
)
|
||||
|
||||
type Suite struct {
|
||||
clock clockwork.Clock
|
||||
clock clockwork.FakeClock
|
||||
dataDir string
|
||||
authServer *auth.TestAuthServer
|
||||
tlsServer *auth.TestTLSServer
|
||||
|
@ -74,7 +74,7 @@ func TestApp(t *testing.T) { check.TestingT(t) }
|
|||
func (s *Suite) SetUpSuite(c *check.C) {
|
||||
utils.InitLoggerForTests(testing.Verbose())
|
||||
|
||||
s.clock = clockwork.NewFakeClockAt(time.Now())
|
||||
s.clock = clockwork.NewFakeClock()
|
||||
s.dataDir = c.MkDir()
|
||||
|
||||
var err error
|
||||
|
@ -82,6 +82,7 @@ func (s *Suite) SetUpSuite(c *check.C) {
|
|||
s.authServer, err = auth.NewTestAuthServer(auth.TestAuthServerConfig{
|
||||
ClusterName: "root.example.com",
|
||||
Dir: s.dataDir,
|
||||
Clock: s.clock,
|
||||
})
|
||||
c.Assert(err, check.IsNil)
|
||||
s.tlsServer, err = s.authServer.NewTestTLSServer()
|
||||
|
@ -116,10 +117,13 @@ func (s *Suite) SetUpTest(c *check.C) {
|
|||
// Create a in-memory HTTP server that will respond with a UUID. This value
|
||||
// will be checked in the client later to ensure a connection was made.
|
||||
s.message = uuid.New()
|
||||
s.testhttp = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
s.testhttp = httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Fprintln(w, s.message)
|
||||
s.closeFunc()
|
||||
}))
|
||||
s.testhttp.Config.TLSConfig = &tls.Config{Time: s.clock.Now}
|
||||
s.testhttp.Start()
|
||||
|
||||
// Extract the hostport that the in-memory HTTP server is running on.
|
||||
u, err := url.Parse(s.testhttp.URL)
|
||||
|
@ -147,7 +151,7 @@ func (s *Suite) SetUpTest(c *check.C) {
|
|||
Spec: services.ServerSpecV2{
|
||||
Version: teleport.Version,
|
||||
Apps: []*services.App{
|
||||
&services.App{
|
||||
{
|
||||
Name: "foo",
|
||||
URI: s.testhttp.URL,
|
||||
PublicAddr: "foo.example.com",
|
||||
|
@ -166,6 +170,7 @@ func (s *Suite) SetUpTest(c *check.C) {
|
|||
c.Assert(err, check.IsNil)
|
||||
tlsConfig, err := serverIdentity.TLSConfig(nil)
|
||||
c.Assert(err, check.IsNil)
|
||||
tlsConfig.Time = s.clock.Now
|
||||
|
||||
// Generate certificate for user.
|
||||
privateKey, publicKey, err := s.tlsServer.Auth().GenerateKeyPair("")
|
||||
|
@ -286,6 +291,8 @@ func (s *Suite) TestHandleConnection(c *check.C) {
|
|||
RootCAs: s.hostCertPool,
|
||||
// Certificates is the user's application specific certificate.
|
||||
Certificates: []tls.Certificate{s.clientCertificate},
|
||||
// Time defines the time anchor for certificate validation
|
||||
Time: s.clock.Now,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
|
@ -29,8 +29,10 @@ import (
|
|||
"github.com/gravitational/teleport/lib/services"
|
||||
"github.com/gravitational/teleport/lib/sshutils"
|
||||
"github.com/gravitational/teleport/lib/utils"
|
||||
|
||||
"github.com/gravitational/trace"
|
||||
|
||||
"github.com/jonboulle/clockwork"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
|
@ -54,6 +56,11 @@ type AuthHandlers struct {
|
|||
// FIPS mode means Teleport started in a FedRAMP/FIPS 140-2 compliant
|
||||
// configuration.
|
||||
FIPS bool
|
||||
|
||||
// Clock specifies the time provider. Will be used to override the time anchor
|
||||
// for TLS certificate verification.
|
||||
// Defaults to real clock if unspecified
|
||||
Clock clockwork.Clock
|
||||
}
|
||||
|
||||
// CreateIdentityContext returns an IdentityContext populated with information
|
||||
|
@ -198,9 +205,14 @@ func (h *AuthHandlers) UserKeyAuth(conn ssh.ConnMetadata, key ssh.PublicKey) (*s
|
|||
// Check that the user certificate uses supported public key algorithms, was
|
||||
// issued by Teleport, and check the certificate metadata (principals,
|
||||
// timestamp, etc). Fallback to keys is not supported.
|
||||
clock := time.Now
|
||||
if h.Clock != nil {
|
||||
clock = h.Clock.Now
|
||||
}
|
||||
certChecker := utils.CertChecker{
|
||||
CertChecker: ssh.CertChecker{
|
||||
IsUserAuthority: h.IsUserAuthority,
|
||||
Clock: clock,
|
||||
},
|
||||
FIPS: h.FIPS,
|
||||
}
|
||||
|
|
|
@ -299,6 +299,7 @@ func New(c ServerConfig) (*Server, error) {
|
|||
AccessPoint: c.AuthClient,
|
||||
FIPS: c.FIPS,
|
||||
Emitter: c.Emitter,
|
||||
Clock: c.Clock,
|
||||
}
|
||||
|
||||
// Common term handlers.
|
||||
|
|
|
@ -297,6 +297,15 @@ func (s *Server) HandleConnection(conn net.Conn) {
|
|||
// RotationGetter returns rotation state
|
||||
type RotationGetter func(role teleport.Role) (*services.Rotation, error)
|
||||
|
||||
// SetClock is a functional server option to override the internal
|
||||
// clock
|
||||
func SetClock(clock clockwork.Clock) ServerOption {
|
||||
return func(s *Server) error {
|
||||
s.clock = clock
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// SetRotationGetter sets rotation state getter
|
||||
func SetRotationGetter(getter RotationGetter) ServerOption {
|
||||
return func(s *Server) error {
|
||||
|
@ -542,6 +551,7 @@ func New(addr utils.NetAddr,
|
|||
AccessPoint: s.authService,
|
||||
FIPS: s.fips,
|
||||
Emitter: s.StreamEmitter,
|
||||
Clock: s.clock,
|
||||
}
|
||||
|
||||
// common term handlers
|
||||
|
|
|
@ -52,6 +52,7 @@ import (
|
|||
|
||||
"github.com/gravitational/trace"
|
||||
|
||||
"github.com/jonboulle/clockwork"
|
||||
"github.com/pborman/uuid"
|
||||
"github.com/sirupsen/logrus"
|
||||
. "gopkg.in/check.v1"
|
||||
|
@ -76,6 +77,7 @@ type SrvSuite struct {
|
|||
nodeID string
|
||||
adminClient *auth.Client
|
||||
testServer *auth.TestAuthServer
|
||||
clock clockwork.FakeClock
|
||||
}
|
||||
|
||||
// teleportTestUser is additional user used for tests
|
||||
|
@ -112,9 +114,12 @@ func (s *SrvSuite) SetUpTest(c *C) {
|
|||
c.Assert(err, IsNil)
|
||||
s.user = u.Username
|
||||
|
||||
s.clock = clockwork.NewFakeClock()
|
||||
|
||||
authServer, err := auth.NewTestAuthServer(auth.TestAuthServerConfig{
|
||||
ClusterName: "localhost",
|
||||
Dir: c.MkDir(),
|
||||
Clock: s.clock,
|
||||
})
|
||||
c.Assert(err, IsNil)
|
||||
s.server, err = authServer.NewTestTLSServer()
|
||||
|
@ -184,6 +189,7 @@ func (s *SrvSuite) SetUpTest(c *C) {
|
|||
},
|
||||
),
|
||||
SetBPF(&bpf.NOP{}),
|
||||
SetClock(s.clock),
|
||||
)
|
||||
c.Assert(err, IsNil)
|
||||
s.srv = srv
|
||||
|
@ -215,7 +221,6 @@ func (s *SrvSuite) SetUpTest(c *C) {
|
|||
c.Assert(err, IsNil)
|
||||
c.Assert(agent.ForwardToAgent(client, keyring), IsNil)
|
||||
s.clt = client
|
||||
|
||||
}
|
||||
|
||||
func (s *SrvSuite) TearDownTest(c *C) {
|
||||
|
@ -736,6 +741,7 @@ func (s *SrvSuite) TestProxyReverseTunnel(c *C) {
|
|||
SetNamespace(defaults.Namespace),
|
||||
SetPAMConfig(&pam.Config{Enabled: false}),
|
||||
SetBPF(&bpf.NOP{}),
|
||||
SetClock(s.clock),
|
||||
)
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(proxy.Start(), IsNil)
|
||||
|
@ -813,9 +819,9 @@ func (s *SrvSuite) TestProxyReverseTunnel(c *C) {
|
|||
SetPAMConfig(&pam.Config{Enabled: false}),
|
||||
SetBPF(&bpf.NOP{}),
|
||||
SetEmitter(s.nodeClient),
|
||||
SetClock(s.clock),
|
||||
)
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(srv2.Start(), IsNil)
|
||||
c.Assert(srv2.heartbeat.ForceSend(time.Second), IsNil)
|
||||
defer srv2.Close()
|
||||
|
@ -903,6 +909,7 @@ func (s *SrvSuite) TestProxyRoundRobin(c *C) {
|
|||
SetNamespace(defaults.Namespace),
|
||||
SetPAMConfig(&pam.Config{Enabled: false}),
|
||||
SetBPF(&bpf.NOP{}),
|
||||
SetClock(s.clock),
|
||||
)
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(proxy.Start(), IsNil)
|
||||
|
@ -1008,6 +1015,7 @@ func (s *SrvSuite) TestProxyDirectAccess(c *C) {
|
|||
SetNamespace(defaults.Namespace),
|
||||
SetPAMConfig(&pam.Config{Enabled: false}),
|
||||
SetBPF(&bpf.NOP{}),
|
||||
SetClock(s.clock),
|
||||
)
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(proxy.Start(), IsNil)
|
||||
|
@ -1087,12 +1095,12 @@ func (s *SrvSuite) TestLimiter(c *C) {
|
|||
limiter.Config{
|
||||
MaxConnections: 2,
|
||||
Rates: []limiter.Rate{
|
||||
limiter.Rate{
|
||||
{
|
||||
Period: 10 * time.Second,
|
||||
Average: 1,
|
||||
Burst: 3,
|
||||
},
|
||||
limiter.Rate{
|
||||
{
|
||||
Period: 40 * time.Millisecond,
|
||||
Average: 10,
|
||||
Burst: 30,
|
||||
|
@ -1118,6 +1126,7 @@ func (s *SrvSuite) TestLimiter(c *C) {
|
|||
SetNamespace(defaults.Namespace),
|
||||
SetPAMConfig(&pam.Config{Enabled: false}),
|
||||
SetBPF(&bpf.NOP{}),
|
||||
SetClock(s.clock),
|
||||
)
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(srv.Start(), IsNil)
|
||||
|
|
|
@ -30,6 +30,7 @@ import (
|
|||
|
||||
"github.com/gravitational/teleport"
|
||||
"github.com/gravitational/trace"
|
||||
"github.com/jonboulle/clockwork"
|
||||
)
|
||||
|
||||
// ClusterName returns cluster name from organization
|
||||
|
@ -42,8 +43,39 @@ func ClusterName(subject pkix.Name) (string, error) {
|
|||
|
||||
// GenerateSelfSignedCA generates self-signed certificate authority used for internal inter-node communications
|
||||
func GenerateSelfSignedCAWithPrivateKey(priv *rsa.PrivateKey, entity pkix.Name, dnsNames []string, ttl time.Duration) ([]byte, []byte, error) {
|
||||
notBefore := time.Now()
|
||||
notAfter := notBefore.Add(ttl)
|
||||
return GenerateSelfSignedCAWithConfig(GenerateCAConfig{
|
||||
PrivateKey: priv,
|
||||
Entity: entity,
|
||||
DNSNames: dnsNames,
|
||||
TTL: ttl,
|
||||
Clock: clockwork.NewRealClock(),
|
||||
})
|
||||
}
|
||||
|
||||
// GenerateCAConfig defines the configuration for generating
|
||||
// self-signed CA certificates
|
||||
type GenerateCAConfig struct {
|
||||
PrivateKey *rsa.PrivateKey
|
||||
Entity pkix.Name
|
||||
DNSNames []string
|
||||
TTL time.Duration
|
||||
Clock clockwork.Clock
|
||||
}
|
||||
|
||||
// setDefaults imposes defaults on this configuration
|
||||
func (r *GenerateCAConfig) setDefaults() {
|
||||
if r.Clock == nil {
|
||||
r.Clock = clockwork.NewRealClock()
|
||||
}
|
||||
}
|
||||
|
||||
// GenerateSelfSignedCAWithConfig generates a new CA certificate from the specified
|
||||
// configuration.
|
||||
// Returns PEM-encoded private key/certificate payloads upon success
|
||||
func GenerateSelfSignedCAWithConfig(config GenerateCAConfig) (keyPEM []byte, certPEM []byte, err error) {
|
||||
config.setDefaults()
|
||||
notBefore := config.Clock.Now()
|
||||
notAfter := notBefore.Add(config.TTL)
|
||||
|
||||
serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
|
||||
serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
|
||||
|
@ -52,27 +84,27 @@ func GenerateSelfSignedCAWithPrivateKey(priv *rsa.PrivateKey, entity pkix.Name,
|
|||
}
|
||||
// this is important, otherwise go will accept certificate authorities
|
||||
// signed by the same private key and having the same subject (happens in tests)
|
||||
entity.SerialNumber = serialNumber.String()
|
||||
config.Entity.SerialNumber = serialNumber.String()
|
||||
|
||||
template := x509.Certificate{
|
||||
SerialNumber: serialNumber,
|
||||
Issuer: entity,
|
||||
Subject: entity,
|
||||
Issuer: config.Entity,
|
||||
Subject: config.Entity,
|
||||
NotBefore: notBefore,
|
||||
NotAfter: notAfter,
|
||||
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
|
||||
BasicConstraintsValid: true,
|
||||
IsCA: true,
|
||||
DNSNames: dnsNames,
|
||||
DNSNames: config.DNSNames,
|
||||
}
|
||||
|
||||
derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv)
|
||||
derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &config.PrivateKey.PublicKey, config.PrivateKey)
|
||||
if err != nil {
|
||||
return nil, nil, trace.Wrap(err)
|
||||
}
|
||||
|
||||
keyPEM := pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(priv)})
|
||||
certPEM := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
|
||||
keyPEM = pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(config.PrivateKey)})
|
||||
certPEM = pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
|
||||
|
||||
return keyPEM, certPEM, nil
|
||||
}
|
||||
|
|
|
@ -92,6 +92,14 @@ func SetSessionStreamPollPeriod(period time.Duration) HandlerOption {
|
|||
}
|
||||
}
|
||||
|
||||
// SetClock sets the clock on a handler
|
||||
func SetClock(clock clockwork.Clock) HandlerOption {
|
||||
return func(h *Handler) error {
|
||||
h.clock = clock
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// Config represents web handler configuration parameters
|
||||
type Config struct {
|
||||
// Proxy is a reverse tunnel proxy that handles connections
|
||||
|
@ -171,15 +179,10 @@ func (h *RewritingHandler) Close() error {
|
|||
// NewHandler returns a new instance of web proxy handler
|
||||
func NewHandler(cfg Config, opts ...HandlerOption) (*RewritingHandler, error) {
|
||||
const apiPrefix = "/" + teleport.WebAPIVersion
|
||||
lauth, err := newSessionCache(cfg.ProxyClient, []utils.NetAddr{cfg.AuthServers}, cfg.CipherSuites)
|
||||
if err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
|
||||
h := &Handler{
|
||||
cfg: cfg,
|
||||
auth: lauth,
|
||||
log: newPackageLogger(),
|
||||
cfg: cfg,
|
||||
log: newPackageLogger(),
|
||||
clock: clockwork.NewRealClock(),
|
||||
}
|
||||
|
||||
for _, o := range opts {
|
||||
|
@ -188,6 +191,17 @@ func NewHandler(cfg Config, opts ...HandlerOption) (*RewritingHandler, error) {
|
|||
}
|
||||
}
|
||||
|
||||
auth, err := newSessionCache(&sessionCache{
|
||||
proxyClient: cfg.ProxyClient,
|
||||
authServers: []utils.NetAddr{cfg.AuthServers},
|
||||
cipherSuites: cfg.CipherSuites,
|
||||
clock: h.clock,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
h.auth = auth
|
||||
|
||||
_, sshPort, err := net.SplitHostPort(cfg.ProxySSHAddr.String())
|
||||
if err != nil {
|
||||
h.log.WithError(err).Warnf("Invalid SSH proxy address %q, will use default port %v.",
|
||||
|
@ -196,10 +210,6 @@ func NewHandler(cfg Config, opts ...HandlerOption) (*RewritingHandler, error) {
|
|||
}
|
||||
h.sshPort = sshPort
|
||||
|
||||
if h.clock == nil {
|
||||
h.clock = clockwork.NewRealClock()
|
||||
}
|
||||
|
||||
// ping endpoint is used to check if the server is up. the /webapi/ping
|
||||
// endpoint returns the default authentication method and configuration that
|
||||
// the server supports. the /webapi/ping/:connector endpoint can be used to
|
||||
|
@ -1190,7 +1200,7 @@ func NewSessionResponse(ctx *SessionContext) (*CreateSessionResponse, error) {
|
|||
return &CreateSessionResponse{
|
||||
Type: roundtrip.AuthBearer,
|
||||
Token: webSession.GetBearerToken(),
|
||||
ExpiresIn: int(time.Until(webSession.GetBearerTokenExpiryTime()) / time.Second),
|
||||
ExpiresIn: int(webSession.GetBearerTokenExpiryTime().Sub(ctx.parent.clock.Now()) / time.Second),
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -99,12 +99,10 @@ type WebSuite struct {
|
|||
mockU2F *mocku2f.Key
|
||||
server *auth.TestTLSServer
|
||||
proxyClient *auth.Client
|
||||
clock clockwork.Clock
|
||||
clock clockwork.FakeClock
|
||||
}
|
||||
|
||||
var _ = Suite(&WebSuite{
|
||||
clock: clockwork.NewFakeClock(),
|
||||
})
|
||||
var _ = Suite(&WebSuite{})
|
||||
|
||||
// TestMain will re-execute Teleport to run a command if "exec" is passed to
|
||||
// it as an argument. Otherwise it will run tests as normal.
|
||||
|
@ -144,11 +142,12 @@ func (s *WebSuite) SetUpTest(c *C) {
|
|||
u, err := user.Current()
|
||||
c.Assert(err, IsNil)
|
||||
s.user = u.Username
|
||||
s.clock = clockwork.NewFakeClock()
|
||||
|
||||
authServer, err := auth.NewTestAuthServer(auth.TestAuthServerConfig{
|
||||
ClusterName: "localhost",
|
||||
Dir: c.MkDir(),
|
||||
Clock: clockwork.NewFakeClockAt(time.Date(2017, 05, 10, 18, 53, 0, 0, time.UTC)),
|
||||
Clock: s.clock,
|
||||
})
|
||||
c.Assert(err, IsNil)
|
||||
s.server, err = authServer.NewTestTLSServer()
|
||||
|
@ -191,6 +190,7 @@ func (s *WebSuite) SetUpTest(c *C) {
|
|||
regular.SetEmitter(nodeClient),
|
||||
regular.SetPAMConfig(&pam.Config{Enabled: false}),
|
||||
regular.SetBPF(&bpf.NOP{}),
|
||||
regular.SetClock(s.clock),
|
||||
)
|
||||
c.Assert(err, IsNil)
|
||||
s.node = node
|
||||
|
@ -243,6 +243,7 @@ func (s *WebSuite) SetUpTest(c *C) {
|
|||
regular.SetEmitter(s.proxyClient),
|
||||
regular.SetNamespace(defaults.Namespace),
|
||||
regular.SetBPF(&bpf.NOP{}),
|
||||
regular.SetClock(s.clock),
|
||||
)
|
||||
c.Assert(err, IsNil)
|
||||
|
||||
|
@ -256,7 +257,7 @@ func (s *WebSuite) SetUpTest(c *C) {
|
|||
Context: context.Background(),
|
||||
HostUUID: proxyID,
|
||||
Emitter: s.proxyClient,
|
||||
}, SetSessionStreamPollPeriod(200*time.Millisecond))
|
||||
}, SetSessionStreamPollPeriod(200*time.Millisecond), SetClock(s.clock))
|
||||
c.Assert(err, IsNil)
|
||||
|
||||
s.webServer = httptest.NewUnstartedServer(handler)
|
||||
|
@ -314,9 +315,7 @@ func (s *WebSuite) authPackFromResponse(c *C, re *roundtrip.Response) *authPack
|
|||
jar.SetCookies(s.url(), re.Cookies())
|
||||
|
||||
session, err := sess.response()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
c.Assert(err, IsNil)
|
||||
if session.ExpiresIn < 0 {
|
||||
c.Errorf("expected expiry time to be in the future but got %v", session.ExpiresIn)
|
||||
}
|
||||
|
@ -346,7 +345,7 @@ func (s *WebSuite) authPack(c *C, user string) *authPack {
|
|||
s.createUser(c, user, login, pass, otpSecret)
|
||||
|
||||
// create a valid otp token
|
||||
validToken, err := totp.GenerateCode(otpSecret, time.Now())
|
||||
validToken, err := totp.GenerateCode(otpSecret, s.clock.Now())
|
||||
c.Assert(err, IsNil)
|
||||
|
||||
clt := s.client()
|
||||
|
@ -590,10 +589,10 @@ func (s *WebSuite) TestCSRF(c *C) {
|
|||
|
||||
func (s *WebSuite) TestPasswordChange(c *C) {
|
||||
pack := s.authPack(c, "foo")
|
||||
fakeClock := clockwork.NewFakeClock()
|
||||
s.server.AuthServer.AuthServer.SetClock(fakeClock)
|
||||
|
||||
validToken, err := totp.GenerateCode(pack.otpSecret, fakeClock.Now())
|
||||
// invalidate the token
|
||||
s.clock.Advance(1 * time.Minute)
|
||||
validToken, err := totp.GenerateCode(pack.otpSecret, s.clock.Now())
|
||||
c.Assert(err, IsNil)
|
||||
|
||||
req := changePasswordReq{
|
||||
|
@ -1345,7 +1344,9 @@ func (s *WebSuite) TestChangePasswordWithTokenOTP(c *C) {
|
|||
secrets, err := s.server.Auth().RotateResetPasswordTokenSecrets(context.TODO(), token.GetName())
|
||||
c.Assert(err, IsNil)
|
||||
|
||||
secondFactorToken, err := totp.GenerateCode(secrets.GetOTPKey(), time.Now())
|
||||
// Advance the clock to invalidate the TOTP token
|
||||
s.clock.Advance(1 * time.Minute)
|
||||
secondFactorToken, err := totp.GenerateCode(secrets.GetOTPKey(), s.clock.Now())
|
||||
c.Assert(err, IsNil)
|
||||
|
||||
data, err := json.Marshal(auth.ChangePasswordWithTokenRequest{
|
||||
|
@ -1815,7 +1816,7 @@ func (s *WebSuite) TestCreateAppSession(c *C) {
|
|||
Spec: services.ServerSpecV2{
|
||||
Version: teleport.Version,
|
||||
Apps: []*services.App{
|
||||
&services.App{
|
||||
{
|
||||
Name: "panel",
|
||||
PublicAddr: "panel.example.com",
|
||||
URI: "http://127.0.0.1:8080",
|
||||
|
@ -1902,11 +1903,6 @@ func (s *WebSuite) TestCreateAppSession(c *C) {
|
|||
}
|
||||
}
|
||||
|
||||
// TestAppRouting verifies requests get routed correctly: either to the Web UI
|
||||
// or an application.
|
||||
func (s *WebSuite) TestRouting(c *C) {
|
||||
}
|
||||
|
||||
type authProviderMock struct {
|
||||
server services.ServerV2
|
||||
}
|
||||
|
|
|
@ -314,23 +314,27 @@ func (c *SessionContext) Close() error {
|
|||
}
|
||||
|
||||
// newSessionCache returns new instance of the session cache
|
||||
func newSessionCache(proxyClient auth.ClientI, servers []utils.NetAddr, cipherSuites []uint16) (*sessionCache, error) {
|
||||
clusterName, err := proxyClient.GetClusterName()
|
||||
func newSessionCache(config *sessionCache) (*sessionCache, error) {
|
||||
clusterName, err := config.proxyClient.GetClusterName()
|
||||
if err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
m, err := ttlmap.New(1024, ttlmap.CallOnExpire(closeContext))
|
||||
if config.clock == nil {
|
||||
config.clock = clockwork.NewRealClock()
|
||||
}
|
||||
m, err := ttlmap.New(1024, ttlmap.CallOnExpire(closeContext), ttlmap.Clock(config.clock))
|
||||
if err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
cache := &sessionCache{
|
||||
clusterName: clusterName.GetClusterName(),
|
||||
proxyClient: proxyClient,
|
||||
proxyClient: config.proxyClient,
|
||||
contexts: m,
|
||||
authServers: servers,
|
||||
authServers: config.authServers,
|
||||
closer: utils.NewCloseBroadcaster(),
|
||||
cipherSuites: cipherSuites,
|
||||
cipherSuites: config.cipherSuites,
|
||||
log: newPackageLogger(),
|
||||
clock: config.clock,
|
||||
}
|
||||
// periodically close expired and unused sessions
|
||||
go cache.expireSessions()
|
||||
|
@ -347,6 +351,7 @@ type sessionCache struct {
|
|||
authServers []utils.NetAddr
|
||||
closer *utils.CloseBroadcaster
|
||||
clusterName string
|
||||
clock clockwork.Clock
|
||||
|
||||
// cipherSuites is the list of supported TLS cipher suites.
|
||||
cipherSuites []uint16
|
||||
|
@ -576,6 +581,7 @@ func (s *sessionCache) ValidateSession(user, sid string) (*SessionContext, error
|
|||
tlsConfig.Certificates = []tls.Certificate{tlsCert}
|
||||
tlsConfig.RootCAs = certPool
|
||||
tlsConfig.ServerName = auth.EncodeClusterName(s.clusterName)
|
||||
tlsConfig.Time = s.clock.Now
|
||||
|
||||
userClient, err := auth.NewClient(apiclient.Config{
|
||||
Addrs: utils.NetAddrsToStrings(s.authServers),
|
||||
|
@ -597,7 +603,7 @@ func (s *sessionCache) ValidateSession(user, sid string) (*SessionContext, error
|
|||
}),
|
||||
}
|
||||
|
||||
ttl := utils.ToTTL(clockwork.NewRealClock(), sess.GetBearerTokenExpiryTime())
|
||||
ttl := utils.ToTTL(s.clock, sess.GetBearerTokenExpiryTime())
|
||||
out, err := s.insertContext(user, sid, c, ttl)
|
||||
if err != nil {
|
||||
// this means that someone has just inserted the context, so
|
||||
|
|
2
vendor/github.com/jonboulle/clockwork/clockwork.go
generated
vendored
2
vendor/github.com/jonboulle/clockwork/clockwork.go
generated
vendored
|
@ -152,7 +152,7 @@ func (fc *fakeClock) NewTicker(d time.Duration) Ticker {
|
|||
clock: fc,
|
||||
period: d,
|
||||
}
|
||||
go ft.tick()
|
||||
ft.runTickThread()
|
||||
return ft
|
||||
}
|
||||
|
||||
|
|
58
vendor/github.com/jonboulle/clockwork/ticker.go
generated
vendored
58
vendor/github.com/jonboulle/clockwork/ticker.go
generated
vendored
|
@ -34,33 +34,39 @@ func (ft *fakeTicker) Stop() {
|
|||
ft.stop <- true
|
||||
}
|
||||
|
||||
// tick sends the tick time to the ticker channel after every period.
|
||||
// Tick events are discarded if the underlying ticker channel does
|
||||
// not have enough capacity.
|
||||
func (ft *fakeTicker) tick() {
|
||||
tick := ft.clock.Now()
|
||||
for {
|
||||
tick = tick.Add(ft.period)
|
||||
remaining := tick.Sub(ft.clock.Now())
|
||||
if remaining <= 0 {
|
||||
// The tick should have already happened. This can happen when
|
||||
// Advance() is called on the fake clock with a duration larger
|
||||
// than this ticker's period.
|
||||
// runTickThread initializes a background goroutine to send the tick time to the ticker channel
|
||||
// after every period. Tick events are discarded if the underlying ticker channel does not have
|
||||
// enough capacity.
|
||||
func (ft *fakeTicker) runTickThread() {
|
||||
nextTick := ft.clock.Now().Add(ft.period)
|
||||
next := ft.clock.After(ft.period)
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case ft.c <- tick:
|
||||
default:
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
select {
|
||||
case <-ft.stop:
|
||||
return
|
||||
case <-ft.clock.After(remaining):
|
||||
select {
|
||||
case ft.c <- tick:
|
||||
default:
|
||||
case <-ft.stop:
|
||||
return
|
||||
case <-next:
|
||||
// We send the time that the tick was supposed to occur at.
|
||||
tick := nextTick
|
||||
// Before sending the tick, we'll compute the next tick time and star the clock.After call.
|
||||
now := ft.clock.Now()
|
||||
// First, figure out how many periods there have been between "now" and the time we were
|
||||
// supposed to have trigged, then advance over all of those.
|
||||
skipTicks := (now.Sub(tick) + ft.period - 1) / ft.period
|
||||
nextTick = nextTick.Add(skipTicks * ft.period)
|
||||
// Now, keep advancing until we are past now. This should happen at most once.
|
||||
for !nextTick.After(now) {
|
||||
nextTick = nextTick.Add(ft.period)
|
||||
}
|
||||
// Figure out how long between now and the next scheduled tick, then wait that long.
|
||||
remaining := nextTick.Sub(now)
|
||||
next = ft.clock.After(remaining)
|
||||
// Finally, we can actually send the tick.
|
||||
select {
|
||||
case ft.c <- tick:
|
||||
default:
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
|
2
vendor/modules.txt
vendored
2
vendor/modules.txt
vendored
|
@ -274,7 +274,7 @@ github.com/johannesboyne/gofakes3
|
|||
github.com/johannesboyne/gofakes3/backend/s3mem
|
||||
github.com/johannesboyne/gofakes3/internal/goskipiter
|
||||
github.com/johannesboyne/gofakes3/internal/s3io
|
||||
# github.com/jonboulle/clockwork v0.2.1
|
||||
# github.com/jonboulle/clockwork v0.2.2
|
||||
## explicit
|
||||
github.com/jonboulle/clockwork
|
||||
# github.com/json-iterator/go v1.1.10
|
||||
|
|
Loading…
Reference in a new issue