mirror of
https://github.com/gravitational/teleport
synced 2024-10-21 17:53:28 +00:00
604 lines
17 KiB
Go
604 lines
17 KiB
Go
/*
|
|
Copyright 2015 Gravitational, Inc.
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
*/
|
|
|
|
package auth
|
|
|
|
import (
|
|
"encoding/base32"
|
|
"fmt"
|
|
"net/url"
|
|
"path/filepath"
|
|
"time"
|
|
|
|
"github.com/gravitational/teleport"
|
|
authority "github.com/gravitational/teleport/lib/auth/testauthority"
|
|
"github.com/gravitational/teleport/lib/backend"
|
|
"github.com/gravitational/teleport/lib/backend/dir"
|
|
"github.com/gravitational/teleport/lib/defaults"
|
|
"github.com/gravitational/teleport/lib/events"
|
|
"github.com/gravitational/teleport/lib/services"
|
|
"github.com/gravitational/teleport/lib/services/local"
|
|
"github.com/gravitational/teleport/lib/services/suite"
|
|
"github.com/gravitational/teleport/lib/session"
|
|
"github.com/gravitational/teleport/lib/sshutils"
|
|
"github.com/gravitational/teleport/lib/utils"
|
|
|
|
"github.com/pquerna/otp/totp"
|
|
"golang.org/x/crypto/ssh"
|
|
. "gopkg.in/check.v1"
|
|
)
|
|
|
|
var _ = fmt.Printf // for testing
|
|
|
|
type TunSuite struct {
|
|
bk backend.Backend
|
|
|
|
tsrv *AuthTunnel
|
|
a *AuthServer
|
|
signer ssh.Signer
|
|
dir string
|
|
alog events.IAuditLog
|
|
conf *APIConfig
|
|
sessionServer session.Service
|
|
}
|
|
|
|
var _ = Suite(&TunSuite{})
|
|
|
|
func (s *TunSuite) SetUpSuite(c *C) {
|
|
utils.InitLoggerForTests()
|
|
}
|
|
|
|
func (s *TunSuite) SetUpTest(c *C) {
|
|
s.dir = c.MkDir()
|
|
|
|
var err error
|
|
s.bk, err = dir.New(backend.Params{"path": s.dir})
|
|
c.Assert(err, IsNil)
|
|
|
|
s.alog, err = events.NewAuditLog(s.dir)
|
|
c.Assert(err, IsNil)
|
|
|
|
s.sessionServer, err = session.New(s.bk)
|
|
c.Assert(err, IsNil)
|
|
|
|
access := local.NewAccessService(s.bk)
|
|
identity := local.NewIdentityService(s.bk)
|
|
|
|
s.a = NewAuthServer(&InitConfig{
|
|
Backend: s.bk,
|
|
Authority: authority.New(),
|
|
DomainName: "localhost",
|
|
Access: access,
|
|
Identity: identity,
|
|
})
|
|
|
|
// set up host private key and certificate
|
|
c.Assert(s.a.UpsertCertAuthority(
|
|
suite.NewTestCA(services.HostCA, "localhost")), IsNil)
|
|
|
|
hpriv, hpub, err := s.a.GenerateKeyPair("")
|
|
c.Assert(err, IsNil)
|
|
hcert, err := s.a.GenerateHostCert(hpub, "00000000-0000-0000-0000-000000000000", "localhost", "localhost", teleport.Roles{teleport.RoleNode}, 0)
|
|
c.Assert(err, IsNil)
|
|
|
|
authorizer, err := NewAuthorizer(s.a.Access, s.a.Identity, s.a.Trust)
|
|
c.Assert(err, IsNil)
|
|
|
|
signer, err := sshutils.NewSigner(hpriv, hcert)
|
|
c.Assert(err, IsNil)
|
|
s.signer = signer
|
|
s.conf = &APIConfig{
|
|
AuthServer: s.a,
|
|
Authorizer: authorizer,
|
|
SessionService: s.sessionServer,
|
|
AuditLog: s.alog,
|
|
}
|
|
|
|
tsrv, err := NewTunnel(utils.NetAddr{AddrNetwork: "tcp", Addr: "127.0.0.1:0"}, signer, s.conf)
|
|
c.Assert(err, IsNil)
|
|
c.Assert(tsrv.Start(), IsNil)
|
|
s.tsrv = tsrv
|
|
}
|
|
|
|
func (s *TunSuite) TestUnixServerClient(c *C) {
|
|
authorizer, err := NewAuthorizer(s.a.Access, s.a.Identity, s.a.Trust)
|
|
c.Assert(err, IsNil)
|
|
|
|
tsrv, err := NewTunnel(
|
|
utils.NetAddr{AddrNetwork: "tcp", Addr: "127.0.0.1:0"},
|
|
s.signer,
|
|
&APIConfig{
|
|
AuthServer: s.a,
|
|
Authorizer: authorizer,
|
|
SessionService: s.sessionServer,
|
|
AuditLog: s.alog,
|
|
},
|
|
)
|
|
|
|
c.Assert(err, IsNil)
|
|
c.Assert(tsrv.Start(), IsNil)
|
|
s.tsrv = tsrv
|
|
|
|
userName := "test"
|
|
pass := []byte("pwd123")
|
|
rawSecret := "def456"
|
|
otpSecret := base32.StdEncoding.EncodeToString([]byte(rawSecret))
|
|
|
|
user, role := createUserAndRole(s.a, userName, []string{userName})
|
|
role.SetResource(services.KindNode, services.RW())
|
|
err = s.a.UpsertRole(role, backend.Forever)
|
|
c.Assert(err, IsNil)
|
|
|
|
err = s.a.UpsertPassword(user.GetName(), pass)
|
|
c.Assert(err, IsNil)
|
|
|
|
err = s.a.UpsertTOTP(user.GetName(), otpSecret)
|
|
c.Assert(err, IsNil)
|
|
|
|
otpURL, _, err := s.a.GetOTPData(userName)
|
|
c.Assert(err, IsNil)
|
|
|
|
// make sure label in url is correct
|
|
u, err := url.Parse(otpURL)
|
|
c.Assert(err, IsNil)
|
|
c.Assert(u.Path, Equals, "/test")
|
|
|
|
// create a valid otp token
|
|
validToken, err := totp.GenerateCode(otpSecret, time.Now())
|
|
c.Assert(err, IsNil)
|
|
|
|
authMethod, err := NewWebPasswordAuth(user.GetName(), pass, validToken)
|
|
c.Assert(err, IsNil)
|
|
|
|
clt, err := NewTunClient("test",
|
|
[]utils.NetAddr{{AddrNetwork: "tcp", Addr: tsrv.Addr()}},
|
|
"test", authMethod)
|
|
c.Assert(err, IsNil)
|
|
|
|
err = clt.UpsertNode(newServer(services.KindNode, "a.example.com", "hello", "hello", defaults.Namespace))
|
|
c.Assert(err, IsNil)
|
|
}
|
|
|
|
func (s *TunSuite) TestSessions(c *C) {
|
|
c.Assert(s.a.UpsertCertAuthority(
|
|
suite.NewTestCA(services.UserCA, "localhost")), IsNil)
|
|
|
|
user := "ws-test"
|
|
pass := []byte("ws-abc123")
|
|
rawSecret := "def456"
|
|
otpSecret := base32.StdEncoding.EncodeToString([]byte(rawSecret))
|
|
|
|
createUserAndRole(s.a, user, []string{user})
|
|
|
|
err := s.a.UpsertPassword(user, pass)
|
|
c.Assert(err, IsNil)
|
|
|
|
err = s.a.UpsertTOTP(user, otpSecret)
|
|
c.Assert(err, IsNil)
|
|
|
|
otpURL, _, err := s.a.GetOTPData(user)
|
|
c.Assert(err, IsNil)
|
|
|
|
// make sure label in url is correct
|
|
u, err := url.Parse(otpURL)
|
|
c.Assert(err, IsNil)
|
|
c.Assert(u.Path, Equals, "/ws-test")
|
|
|
|
// create a valid otp token
|
|
validToken, err := totp.GenerateCode(otpSecret, time.Now())
|
|
c.Assert(err, IsNil)
|
|
|
|
authMethod, err := NewWebPasswordAuth(user, pass, validToken)
|
|
c.Assert(err, IsNil)
|
|
|
|
clt, err := NewTunClient("test",
|
|
[]utils.NetAddr{{AddrNetwork: "tcp", Addr: s.tsrv.Addr()}}, user, authMethod)
|
|
c.Assert(err, IsNil)
|
|
defer clt.Close()
|
|
|
|
ws, err := clt.SignIn(user, pass)
|
|
c.Assert(err, IsNil)
|
|
c.Assert(ws, Not(Equals), "")
|
|
|
|
// Resume session via sesison id
|
|
authMethod, err = NewWebSessionAuth(user, []byte(ws.GetName()))
|
|
c.Assert(err, IsNil)
|
|
|
|
cltw, err := NewTunClient("test",
|
|
[]utils.NetAddr{{AddrNetwork: "tcp", Addr: s.tsrv.Addr()}}, user, authMethod)
|
|
c.Assert(err, IsNil)
|
|
defer cltw.Close()
|
|
|
|
out, err := cltw.GetWebSessionInfo(user, ws.GetName())
|
|
c.Assert(err, IsNil)
|
|
c.Assert(out, DeepEquals, ws)
|
|
|
|
err = cltw.DeleteWebSession(user, ws.GetName())
|
|
c.Assert(err, IsNil)
|
|
|
|
_, err = clt.GetWebSessionInfo(user, ws.GetName())
|
|
c.Assert(err, NotNil)
|
|
}
|
|
|
|
// TestWebCreatingNewUserInvalidClientValidToken tries to connect to the auth server
|
|
// using an invalid singup token but then tries to pull back signup token data
|
|
// using a valid token. This should fail.
|
|
func (s *TunSuite) TestWebCreatingNewUserInvalidClientValidToken(c *C) {
|
|
c.Assert(s.a.UpsertCertAuthority(
|
|
suite.NewTestCA(services.UserCA, "localhost")), IsNil)
|
|
|
|
user := "foobar"
|
|
mappings := []string{"admin", "db"}
|
|
|
|
token, err := s.a.CreateSignupToken(services.UserV1{Name: user, AllowedLogins: mappings})
|
|
c.Assert(err, IsNil)
|
|
|
|
authMethod, err := NewSignupTokenAuth("invalid_signup_token")
|
|
c.Assert(err, IsNil)
|
|
|
|
clt, err := NewTunClient("test",
|
|
[]utils.NetAddr{{AddrNetwork: "tcp", Addr: s.tsrv.Addr()}}, user, authMethod)
|
|
c.Assert(err, IsNil)
|
|
defer clt.Close()
|
|
|
|
_, _, err = clt.GetSignupTokenData(token)
|
|
c.Assert(err, NotNil)
|
|
}
|
|
|
|
// TestWebCreatingNewUserValidClientInvalidToken connects to the auth server using a
|
|
// valid signup token but then tries to get invalid token data back. This should fail.
|
|
func (s *TunSuite) TestWebCreatingNewUserValidClientInvalidToken(c *C) {
|
|
c.Assert(s.a.UpsertCertAuthority(
|
|
suite.NewTestCA(services.UserCA, "localhost")), IsNil)
|
|
|
|
user := "foobar"
|
|
mappings := []string{"admin", "db"}
|
|
|
|
token, err := s.a.CreateSignupToken(services.UserV1{Name: user, AllowedLogins: mappings})
|
|
c.Assert(err, IsNil)
|
|
|
|
authMethod, err := NewSignupTokenAuth(token)
|
|
c.Assert(err, IsNil)
|
|
|
|
clt, err := NewTunClient("test",
|
|
[]utils.NetAddr{{AddrNetwork: "tcp", Addr: s.tsrv.Addr()}}, user, authMethod)
|
|
c.Assert(err, IsNil)
|
|
defer clt.Close()
|
|
|
|
_, _, err = clt.GetSignupTokenData("invalid_signup_token")
|
|
c.Assert(err, NotNil)
|
|
|
|
// no permissions to do this
|
|
_, err = clt.GetUsers()
|
|
c.Assert(err, NotNil)
|
|
}
|
|
|
|
// TestWebCreatingNewUserValidClientValidToken connects to the auth server using a
|
|
// valid signup token and then tries to get a valid token back. Then try and login
|
|
// as the new user. This should all succeed.
|
|
func (s *TunSuite) TestWebCreatingNewUserValidClientValidToken(c *C) {
|
|
ap, err := services.NewAuthPreference(services.AuthPreferenceSpecV2{
|
|
Type: "local",
|
|
SecondFactor: "otp",
|
|
})
|
|
c.Assert(err, IsNil)
|
|
err = s.a.SetClusterAuthPreference(ap)
|
|
c.Assert(err, IsNil)
|
|
|
|
c.Assert(s.a.UpsertCertAuthority(
|
|
suite.NewTestCA(services.UserCA, "localhost")), IsNil)
|
|
|
|
user := "foobar"
|
|
password := "bazqux"
|
|
mappings := []string{"admin", "db"}
|
|
|
|
token, err := s.a.CreateSignupToken(services.UserV1{Name: user, AllowedLogins: mappings})
|
|
c.Assert(err, IsNil)
|
|
|
|
authMethod, err := NewSignupTokenAuth(token)
|
|
c.Assert(err, IsNil)
|
|
|
|
clt, err := NewTunClient("test",
|
|
[]utils.NetAddr{{AddrNetwork: "tcp", Addr: s.tsrv.Addr()}}, user, authMethod)
|
|
c.Assert(err, IsNil)
|
|
defer clt.Close()
|
|
|
|
// check that the usernames are the same
|
|
userInToken, _, err := clt.GetSignupTokenData(token)
|
|
c.Assert(err, IsNil)
|
|
c.Assert(user, Equals, userInToken)
|
|
|
|
// get otp token
|
|
tokenData, err := s.a.Identity.GetSignupToken(token)
|
|
validToken, err := totp.GenerateCode(tokenData.OTPKey, time.Now())
|
|
c.Assert(err, IsNil)
|
|
|
|
// create a user
|
|
_, err = clt.CreateUserWithOTP(token, password, validToken)
|
|
c.Assert(err, IsNil)
|
|
|
|
// delete token so we can re-use it without messing with clocks
|
|
err = s.a.Identity.DeleteUsedTOTPToken(user)
|
|
c.Assert(err, IsNil)
|
|
|
|
// now login as the fresh new user
|
|
authMethod, err = NewWebPasswordAuth(user, []byte(password), validToken)
|
|
c.Assert(err, IsNil)
|
|
|
|
clt, err = NewTunClient("test",
|
|
[]utils.NetAddr{{AddrNetwork: "tcp", Addr: s.tsrv.Addr()}}, user, authMethod)
|
|
c.Assert(err, IsNil)
|
|
defer clt.Close()
|
|
|
|
ws, err := clt.SignIn(user, []byte(password))
|
|
c.Assert(err, IsNil)
|
|
c.Assert(ws, Not(Equals), "")
|
|
}
|
|
|
|
// TestWebCreatingNewUserValidClientValidTokenReuseToken connects to teh auth server
|
|
// using a valid signup token and then uses a valid token to create a user. Then
|
|
// try to create another user. This should fail.
|
|
func (s *TunSuite) TestWebCreatingNewUserValidClientValidTokenReuseToken(c *C) {
|
|
ap, err := services.NewAuthPreference(services.AuthPreferenceSpecV2{
|
|
Type: "local",
|
|
SecondFactor: "otp",
|
|
})
|
|
c.Assert(err, IsNil)
|
|
err = s.a.SetClusterAuthPreference(ap)
|
|
c.Assert(err, IsNil)
|
|
|
|
c.Assert(s.a.UpsertCertAuthority(
|
|
suite.NewTestCA(services.UserCA, "localhost")), IsNil)
|
|
|
|
user := "foobar"
|
|
mappings := []string{"admin", "db"}
|
|
|
|
token, err := s.a.CreateSignupToken(services.UserV1{Name: user, AllowedLogins: mappings})
|
|
c.Assert(err, IsNil)
|
|
|
|
authMethod, err := NewSignupTokenAuth(token)
|
|
c.Assert(err, IsNil)
|
|
|
|
clt, err := NewTunClient("test",
|
|
[]utils.NetAddr{{AddrNetwork: "tcp", Addr: s.tsrv.Addr()}}, user, authMethod)
|
|
c.Assert(err, IsNil)
|
|
defer clt.Close()
|
|
|
|
validPassword := "valid_password"
|
|
tokenData, err := s.a.Identity.GetSignupToken(token)
|
|
validToken, err := totp.GenerateCode(tokenData.OTPKey, time.Now())
|
|
c.Assert(err, IsNil)
|
|
|
|
// first time we should be able to create a user
|
|
_, err = clt.CreateUserWithOTP(token, validPassword, validToken)
|
|
c.Assert(err, IsNil)
|
|
|
|
// second time it should fail
|
|
_, err = clt.CreateUserWithOTP(token, validPassword, validToken)
|
|
c.Assert(err, NotNil)
|
|
|
|
// signup token should be gone now
|
|
_, err = s.a.Identity.GetSignupToken(token)
|
|
c.Assert(err, NotNil)
|
|
|
|
// try and connect again this should fail as well
|
|
clt, err = NewTunClient("test",
|
|
[]utils.NetAddr{{AddrNetwork: "tcp", Addr: s.tsrv.Addr()}}, user, authMethod)
|
|
c.Assert(err, IsNil)
|
|
|
|
_, _, err = clt.GetSignupTokenData(token)
|
|
c.Assert(err, NotNil)
|
|
}
|
|
|
|
func (s *TunSuite) TestPermissions(c *C) {
|
|
c.Assert(s.a.UpsertCertAuthority(
|
|
suite.NewTestCA(services.UserCA, "localhost")), IsNil)
|
|
|
|
userName := "ws-test2"
|
|
pass := []byte("ws-abc1234")
|
|
rawSecret := "def456"
|
|
otpSecret := base32.StdEncoding.EncodeToString([]byte(rawSecret))
|
|
|
|
user, _ := createUserAndRole(s.a, userName, []string{userName})
|
|
|
|
err := s.a.UpsertPassword(user.GetName(), pass)
|
|
c.Assert(err, IsNil)
|
|
|
|
err = s.a.UpsertTOTP(user.GetName(), otpSecret)
|
|
c.Assert(err, IsNil)
|
|
|
|
otpURL, _, err := s.a.GetOTPData(userName)
|
|
c.Assert(err, IsNil)
|
|
|
|
// make sure label in url is correct
|
|
u, err := url.Parse(otpURL)
|
|
c.Assert(err, IsNil)
|
|
c.Assert(u.Path, Equals, "/ws-test2")
|
|
|
|
// create a valid otp token
|
|
validToken, err := totp.GenerateCode(otpSecret, time.Now())
|
|
c.Assert(err, IsNil)
|
|
|
|
authMethod, err := NewWebPasswordAuth(user.GetName(), pass, validToken)
|
|
c.Assert(err, IsNil)
|
|
|
|
clt, err := NewTunClient("test",
|
|
[]utils.NetAddr{{AddrNetwork: "tcp", Addr: s.tsrv.Addr()}}, user.GetName(), authMethod)
|
|
c.Assert(err, IsNil)
|
|
defer clt.Close()
|
|
|
|
ws, err := clt.SignIn(user.GetName(), pass)
|
|
c.Assert(err, IsNil)
|
|
c.Assert(ws, Not(Equals), "")
|
|
|
|
// Requesting forbidden for User action
|
|
server := newServer(services.KindNode, "name", "host", "host", defaults.Namespace)
|
|
err = clt.UpsertNode(server)
|
|
c.Assert(err, NotNil)
|
|
|
|
// Requesting forbidden for User action
|
|
err = clt.DeleteUser(user.GetName())
|
|
c.Assert(err, NotNil)
|
|
|
|
// Resume session via sesison id
|
|
authMethod, err = NewWebSessionAuth(user.GetName(), []byte(ws.GetName()))
|
|
c.Assert(err, IsNil)
|
|
|
|
cltw, err := NewTunClient("test",
|
|
[]utils.NetAddr{{AddrNetwork: "tcp", Addr: s.tsrv.Addr()}}, user.GetName(), authMethod)
|
|
c.Assert(err, IsNil)
|
|
defer cltw.Close()
|
|
|
|
// Requesting forbidden for Web action
|
|
err = cltw.DeleteUser(user.GetName())
|
|
c.Assert(err, NotNil)
|
|
|
|
out, err := cltw.GetWebSessionInfo(user.GetName(), ws.GetName())
|
|
c.Assert(err, IsNil)
|
|
c.Assert(out, DeepEquals, ws)
|
|
|
|
err = cltw.DeleteWebSession(user.GetName(), ws.GetName())
|
|
c.Assert(err, IsNil)
|
|
|
|
_, err = clt.GetWebSessionInfo(user.GetName(), ws.GetName())
|
|
c.Assert(err, NotNil)
|
|
}
|
|
|
|
func (s *TunSuite) TestSessionsBadPassword(c *C) {
|
|
c.Assert(s.a.UpsertCertAuthority(
|
|
suite.NewTestCA(services.UserCA, "localhost")), IsNil)
|
|
|
|
user := "system-test"
|
|
pass := []byte("system-abc123")
|
|
rawSecret := "def456"
|
|
otpSecret := base32.StdEncoding.EncodeToString([]byte(rawSecret))
|
|
|
|
err := s.a.UpsertPassword(user, pass)
|
|
c.Assert(err, IsNil)
|
|
|
|
err = s.a.UpsertTOTP(user, otpSecret)
|
|
c.Assert(err, IsNil)
|
|
|
|
otpURL, _, err := s.a.GetOTPData(user)
|
|
c.Assert(err, IsNil)
|
|
|
|
// make sure label in url is correct
|
|
u, err := url.Parse(otpURL)
|
|
c.Assert(err, IsNil)
|
|
c.Assert(u.Path, Equals, "/system-test")
|
|
|
|
// create a valid otp token
|
|
validToken, err := totp.GenerateCode(otpSecret, time.Now())
|
|
c.Assert(err, IsNil)
|
|
|
|
authMethod, err := NewWebPasswordAuth(user, pass, validToken)
|
|
c.Assert(err, IsNil)
|
|
|
|
clt, err := NewTunClient("test",
|
|
[]utils.NetAddr{{AddrNetwork: "tcp", Addr: s.tsrv.Addr()}}, user, authMethod)
|
|
c.Assert(err, IsNil)
|
|
defer clt.Close()
|
|
|
|
ws, err := clt.SignIn(user, []byte("different-pass"))
|
|
c.Assert(err, NotNil)
|
|
c.Assert(ws, IsNil)
|
|
|
|
ws, err = clt.SignIn("not-exists", pass)
|
|
c.Assert(err, NotNil)
|
|
c.Assert(ws, IsNil)
|
|
}
|
|
|
|
func (s *TunSuite) TestFailover(c *C) {
|
|
node := newServer(
|
|
services.KindNode,
|
|
"node1",
|
|
"node.example.com:12345",
|
|
"node.example.com",
|
|
defaults.Namespace,
|
|
)
|
|
c.Assert(s.a.UpsertNode(node), IsNil)
|
|
|
|
ports, err := utils.GetFreeTCPPorts(1)
|
|
c.Assert(err, IsNil)
|
|
|
|
clt, err := NewTunClient("test",
|
|
[]utils.NetAddr{
|
|
{AddrNetwork: "tcp", Addr: fmt.Sprintf("127.0.0.1:%v", ports.Pop())},
|
|
{AddrNetwork: "tcp", Addr: s.tsrv.Addr()},
|
|
}, "localhost", []ssh.AuthMethod{ssh.PublicKeys(s.signer)})
|
|
c.Assert(err, IsNil)
|
|
defer clt.Close()
|
|
|
|
nodes, err := clt.GetNodes(defaults.Namespace)
|
|
c.Assert(err, IsNil)
|
|
c.Assert(nodes, DeepEquals, []services.Server{node})
|
|
}
|
|
|
|
func (s *TunSuite) TestSync(c *C) {
|
|
authServer := newServer(
|
|
services.KindAuthServer,
|
|
"node1",
|
|
"node.example.com:12345",
|
|
"node.example.com",
|
|
defaults.Namespace,
|
|
)
|
|
c.Assert(s.a.UpsertAuthServer(authServer), IsNil)
|
|
|
|
storage := utils.NewFileAddrStorage(filepath.Join(c.MkDir(), "addr.json"))
|
|
|
|
// authAddr is 'statically' configured CA address:
|
|
authAddr := s.tsrv.Addr()
|
|
|
|
clt, err := NewTunClient("test",
|
|
[]utils.NetAddr{
|
|
{AddrNetwork: "tcp", Addr: authAddr},
|
|
}, "localhost", []ssh.AuthMethod{ssh.PublicKeys(s.signer)},
|
|
TunClientStorage(storage),
|
|
)
|
|
c.Assert(err, IsNil)
|
|
defer clt.Close()
|
|
|
|
err = clt.fetchAndSync()
|
|
c.Assert(err, IsNil)
|
|
|
|
allServers := []utils.NetAddr{
|
|
{Addr: authAddr, AddrNetwork: "tcp", Path: ""},
|
|
{Addr: "node.example.com:12345", AddrNetwork: "tcp"},
|
|
}
|
|
discoveredServers := []utils.NetAddr{
|
|
{Addr: "node.example.com:12345", AddrNetwork: "tcp"},
|
|
}
|
|
c.Assert(clt.getAuthServers(), DeepEquals, allServers)
|
|
|
|
syncedServers, err := storage.GetAddresses()
|
|
c.Assert(err, IsNil)
|
|
c.Assert(syncedServers, DeepEquals, discoveredServers)
|
|
|
|
// test sorting
|
|
unsorted := []utils.NetAddr{
|
|
{Addr: "2", AddrNetwork: "udp"},
|
|
{Addr: "1", AddrNetwork: "tcp"},
|
|
{Addr: "4", AddrNetwork: "smtp"},
|
|
{Addr: "3", AddrNetwork: "http"},
|
|
}
|
|
clt.setAuthServers(unsorted)
|
|
sorted := clt.getAuthServers()
|
|
c.Assert(sorted[0].Addr, Equals, authAddr) // the statically set CA addr is always 1st
|
|
c.Assert(sorted[1].Addr, Equals, "1")
|
|
c.Assert(sorted[2].Addr, Equals, "2")
|
|
c.Assert(sorted[3].Addr, Equals, "3")
|
|
}
|