diff --git a/auth/ap.go b/auth/ap.go index fad5af61795..762832cc9ce 100644 --- a/auth/ap.go +++ b/auth/ap.go @@ -4,29 +4,82 @@ import ( "time" "github.com/gravitational/teleport/backend" + "github.com/gravitational/teleport/services" ) // AccessPoint is a interface needed by nodes to control the access // to the node, and provide heartbeats type AccessPoint interface { // GetServers returns a list of registered servers - GetServers() ([]backend.Server, error) + GetServers() ([]services.Server, error) // UpsertServer registers server presence, permanently if ttl is 0 or // for the specified duration with second resolution if it's >= 1 second - UpsertServer(s backend.Server, ttl time.Duration) error + UpsertServer(s services.Server, ttl time.Duration) error // GetUserCAPub returns the user certificate authority public key GetUserCAPub() ([]byte, error) // GetUserKeys returns a list of authorized keys for a given user // in a OpenSSH key authorized_keys format - GetUserKeys(user string) ([]backend.AuthorizedKey, error) + GetUserKeys(user string) ([]services.AuthorizedKey, error) // GetWebSessionsKeys returns a list of generated public keys // associated with user web session - GetWebSessionsKeys(user string) ([]backend.AuthorizedKey, error) + GetWebSessionsKeys(user string) ([]services.AuthorizedKey, error) // GetRemoteCerts returns a list of trusted remote certificates - GetRemoteCerts(ctype, fqdn string) ([]backend.RemoteCert, error) + GetRemoteCerts(ctype, fqdn string) ([]services.RemoteCert, error) +} + +type BackendAccessPoint struct { + caS *services.CAService + presenceS *services.PresenceService + provisioningS *services.ProvisioningService + userS *services.UserService + webS *services.WebService +} + +func NewBackendAccessPoint(bk backend.Backend) *BackendAccessPoint { + ap := BackendAccessPoint{} + ap.caS = services.NewCAService(bk) + ap.presenceS = services.NewPresenceService(bk) + ap.provisioningS = services.NewProvisioningService(bk) + ap.userS = services.NewUserService(bk) + ap.webS = services.NewWebService(bk) + + return &ap +} + +// GetServers returns a list of registered servers +func (ap *BackendAccessPoint) GetServers() ([]services.Server, error) { + return ap.presenceS.GetServers() +} + +// UpsertServer registers server presence, permanently if ttl is 0 or +// for the specified duration with second resolution if it's >= 1 second +func (ap *BackendAccessPoint) UpsertServer(s services.Server, ttl time.Duration) error { + return ap.presenceS.UpsertServer(s, ttl) +} + +// GetUserCAPub returns the user certificate authority public key +func (ap *BackendAccessPoint) GetUserCAPub() ([]byte, error) { + return ap.caS.GetUserCAPub() +} + +// GetUserKeys returns a list of authorized keys for a given user +// in a OpenSSH key authorized_keys format +func (ap *BackendAccessPoint) GetUserKeys(user string) ([]services.AuthorizedKey, error) { + return ap.userS.GetUserKeys(user) +} + +// GetWebSessionsKeys returns a list of generated public keys +// associated with user web session +func (ap *BackendAccessPoint) GetWebSessionsKeys(user string) ([]services.AuthorizedKey, error) { + return ap.webS.GetWebSessionsKeys(user) +} + +// GetRemoteCerts returns a list of trusted remote certificates +func (ap *BackendAccessPoint) GetRemoteCerts(ctype, fqdn string) ([]services.RemoteCert, error) { + return ap.caS.GetRemoteCerts(ctype, fqdn) } diff --git a/auth/auth.go b/auth/auth.go index daa30b3fa3a..b8b5a988b4d 100644 --- a/auth/auth.go +++ b/auth/auth.go @@ -11,10 +11,12 @@ import ( "fmt" "time" + "github.com/gravitational/teleport" "github.com/gravitational/teleport/Godeps/_workspace/src/github.com/gravitational/session" "github.com/gravitational/teleport/Godeps/_workspace/src/github.com/mailgun/lemma/secret" "github.com/gravitational/teleport/Godeps/_workspace/src/golang.org/x/crypto/bcrypt" "github.com/gravitational/teleport/backend" + "github.com/gravitational/teleport/services" ) // Authority implements minimal key-management facility for generating OpenSSH @@ -34,31 +36,47 @@ type Authority interface { type Session struct { SID session.SecureID PID session.PlainID - WS backend.WebSession + WS services.WebSession } -func NewAuthServer(b backend.Backend, a Authority, scrt *secret.Service) *AuthServer { - return &AuthServer{ - b: b, - a: a, - scrt: scrt, - } +func NewAuthServer(bk backend.Backend, a Authority, scrt *secret.Service) *AuthServer { + as := AuthServer{} + + as.bk = bk + as.a = a + as.scrt = scrt + + as.caS = services.NewCAService(as.bk) + as.lockS = services.NewLockService(as.bk) + as.presenceS = services.NewPresenceService(as.bk) + as.provisioningS = services.NewProvisioningService(as.bk) + as.userS = services.NewUserService(as.bk) + as.webS = services.NewWebService(as.bk) + + return &as } // AuthServer implements key signing, generation and ACL functionality // used by teleport type AuthServer struct { - b backend.Backend + bk backend.Backend a Authority scrt *secret.Service + + caS *services.CAService + lockS *services.LockService + presenceS *services.PresenceService + provisioningS *services.ProvisioningService + userS *services.UserService + webS *services.WebService } -func (s *AuthServer) UpsertServer(srv backend.Server, ttl time.Duration) error { - return s.b.UpsertServer(srv, ttl) +func (s *AuthServer) UpsertServer(srv services.Server, ttl time.Duration) error { + return s.presenceS.UpsertServer(srv, ttl) } -func (s *AuthServer) GetServers() ([]backend.Server, error) { - return s.b.GetServers() +func (s *AuthServer) GetServers() ([]services.Server, error) { + return s.presenceS.GetServers() } // UpsertUserKey takes user's public key, generates certificate for it @@ -66,34 +84,34 @@ func (s *AuthServer) GetServers() ([]backend.Server, error) { // by user CA in case of success, error otherwise. The certificate will be // valid for the duration of the ttl passed in. func (s *AuthServer) UpsertUserKey( - user string, key backend.AuthorizedKey, ttl time.Duration) ([]byte, error) { + user string, key services.AuthorizedKey, ttl time.Duration) ([]byte, error) { cert, err := s.GenerateUserCert(key.Value, key.ID, user, ttl) if err != nil { return nil, err } key.Value = cert - if err := s.b.UpsertUserKey(user, key, ttl); err != nil { + if err := s.userS.UpsertUserKey(user, key, ttl); err != nil { return nil, err } return cert, nil } func (s *AuthServer) GetUsers() ([]string, error) { - return s.b.GetUsers() + return s.userS.GetUsers() } func (s *AuthServer) DeleteUser(user string) error { - return s.b.DeleteUser(user) + return s.userS.DeleteUser(user) } -func (s *AuthServer) GetUserKeys(user string) ([]backend.AuthorizedKey, error) { - return s.b.GetUserKeys(user) +func (s *AuthServer) GetUserKeys(user string) ([]services.AuthorizedKey, error) { + return s.userS.GetUserKeys(user) } // DeleteUserKey deletes user key by given ID func (s *AuthServer) DeleteUserKey(user, key string) error { - return s.b.DeleteUserKey(user, key) + return s.userS.DeleteUserKey(user, key) } // GenerateKeyPair generates private and public key pair of OpenSSH certs @@ -101,16 +119,16 @@ func (s *AuthServer) GenerateKeyPair(pass string) ([]byte, []byte, error) { return s.a.GenerateKeyPair(pass) } -func (s *AuthServer) UpsertRemoteCert(cert backend.RemoteCert, ttl time.Duration) error { - return s.b.UpsertRemoteCert(cert, ttl) +func (s *AuthServer) UpsertRemoteCert(cert services.RemoteCert, ttl time.Duration) error { + return s.caS.UpsertRemoteCert(cert, ttl) } -func (s *AuthServer) GetRemoteCerts(ctype string, fqdn string) ([]backend.RemoteCert, error) { - return s.b.GetRemoteCerts(ctype, fqdn) +func (s *AuthServer) GetRemoteCerts(ctype string, fqdn string) ([]services.RemoteCert, error) { + return s.caS.GetRemoteCerts(ctype, fqdn) } func (s *AuthServer) DeleteRemoteCert(ctype string, fqdn, id string) error { - return s.b.DeleteRemoteCert(ctype, fqdn, id) + return s.caS.DeleteRemoteCert(ctype, fqdn, id) } // ResetHostCA generates host certificate authority and updates the backend @@ -119,7 +137,7 @@ func (s *AuthServer) ResetHostCA(pass string) error { if err != nil { return err } - return s.b.UpsertHostCA(backend.CA{Pub: pub, Priv: priv}) + return s.caS.UpsertHostCA(services.CA{Pub: pub, Priv: priv}) } // ResetHostCA generates user certificate authority and updates the backend @@ -128,17 +146,17 @@ func (s *AuthServer) ResetUserCA(pass string) error { if err != nil { return err } - return s.b.UpsertUserCA(backend.CA{Pub: pub, Priv: priv}) + return s.caS.UpsertUserCA(services.CA{Pub: pub, Priv: priv}) } // GetHostCAPub returns a public key for host key signing authority func (s *AuthServer) GetHostCAPub() ([]byte, error) { - return s.b.GetHostCAPub() + return s.caS.GetHostCAPub() } // GetHostCAPub returns a public key for user key signing authority func (s *AuthServer) GetUserCAPub() ([]byte, error) { - return s.b.GetUserCAPub() + return s.caS.GetUserCAPub() } // GenerateHostCert generates host certificate, it takes pkey as a signing @@ -146,7 +164,7 @@ func (s *AuthServer) GetUserCAPub() ([]byte, error) { func (s *AuthServer) GenerateHostCert( key []byte, id, hostname string, ttl time.Duration) ([]byte, error) { - hk, err := s.b.GetHostCA() + hk, err := s.caS.GetHostCA() if err != nil { return nil, err } @@ -158,7 +176,7 @@ func (s *AuthServer) GenerateHostCert( func (s *AuthServer) GenerateUserCert( key []byte, id, username string, ttl time.Duration) ([]byte, error) { - hk, err := s.b.GetUserCA() + hk, err := s.caS.GetUserCA() if err != nil { return nil, err } @@ -173,19 +191,19 @@ func (s *AuthServer) UpsertPassword(user string, password []byte) error { if err != nil { return err } - return s.b.UpsertPasswordHash(user, hash) + return s.webS.UpsertPasswordHash(user, hash) } func (s *AuthServer) CheckPassword(user string, password []byte) error { if err := verifyPassword(password); err != nil { return err } - hash, err := s.b.GetPasswordHash(user) + hash, err := s.webS.GetPasswordHash(user) if err != nil { return err } if err := bcrypt.CompareHashAndPassword(hash, password); err != nil { - return &BadParameterError{Msg: "passwords do not match"} + return &teleport.BadParameterError{Err: "passwords do not match"} } return nil } @@ -209,7 +227,7 @@ func (s *AuthServer) GenerateToken(fqdn string, ttl time.Duration) (string, erro if err != nil { return "", err } - if err := s.b.UpsertToken(string(p.PID), fqdn, ttl); err != nil { + if err := s.provisioningS.UpsertToken(string(p.PID), fqdn, ttl); err != nil { return "", err } return string(p.SID), nil @@ -220,7 +238,7 @@ func (s *AuthServer) ValidateToken(token, fqdn string) error { if err != nil { return err } - out, err := s.b.GetToken(string(pid)) + out, err := s.provisioningS.GetToken(string(pid)) if err != nil { return err } @@ -235,7 +253,7 @@ func (s *AuthServer) DeleteToken(token string) error { if err != nil { return err } - return s.b.DeleteToken(string(pid)) + return s.provisioningS.DeleteToken(string(pid)) } func (s *AuthServer) NewWebSession(user string) (*Session, error) { @@ -247,7 +265,7 @@ func (s *AuthServer) NewWebSession(user string) (*Session, error) { if err != nil { return nil, err } - hk, err := s.b.GetUserCA() + hk, err := s.caS.GetUserCA() if err != nil { return nil, err } @@ -258,13 +276,13 @@ func (s *AuthServer) NewWebSession(user string) (*Session, error) { sess := &Session{ SID: p.SID, PID: p.PID, - WS: backend.WebSession{Priv: priv, Pub: cert}, + WS: services.WebSession{Priv: priv, Pub: cert}, } return sess, nil } func (s *AuthServer) UpsertWebSession(user string, sess *Session, ttl time.Duration) error { - return s.b.UpsertWebSession(user, string(sess.PID), sess.WS, ttl) + return s.webS.UpsertWebSession(user, string(sess.PID), sess.WS, ttl) } func (s *AuthServer) GetWebSession(user string, sid session.SecureID) (*Session, error) { @@ -272,7 +290,7 @@ func (s *AuthServer) GetWebSession(user string, sid session.SecureID) (*Session, if err != nil { return nil, err } - ws, err := s.b.GetWebSession(user, string(pid)) + ws, err := s.webS.GetWebSession(user, string(pid)) if err != nil { return nil, err } @@ -283,8 +301,8 @@ func (s *AuthServer) GetWebSession(user string, sid session.SecureID) (*Session, }, nil } -func (s *AuthServer) GetWebSessionsKeys(user string) ([]backend.AuthorizedKey, error) { - return s.b.GetWebSessionsKeys(user) +func (s *AuthServer) GetWebSessionsKeys(user string) ([]services.AuthorizedKey, error) { + return s.webS.GetWebSessionsKeys(user) } func (s *AuthServer) DeleteWebSession(user string, sid session.SecureID) error { @@ -292,39 +310,39 @@ func (s *AuthServer) DeleteWebSession(user string, sid session.SecureID) error { if err != nil { return err } - return s.b.DeleteWebSession(user, string(pid)) + return s.webS.DeleteWebSession(user, string(pid)) } -func (s *AuthServer) UpsertWebTun(t backend.WebTun, ttl time.Duration) error { - return s.b.UpsertWebTun(t, ttl) +func (s *AuthServer) UpsertWebTun(t services.WebTun, ttl time.Duration) error { + return s.webS.UpsertWebTun(t, ttl) } -func (s *AuthServer) GetWebTun(prefix string) (*backend.WebTun, error) { - return s.b.GetWebTun(prefix) +func (s *AuthServer) GetWebTun(prefix string) (*services.WebTun, error) { + return s.webS.GetWebTun(prefix) } -func (s *AuthServer) GetWebTuns() ([]backend.WebTun, error) { - return s.b.GetWebTuns() +func (s *AuthServer) GetWebTuns() ([]services.WebTun, error) { + return s.webS.GetWebTuns() } func (s *AuthServer) DeleteWebTun(prefix string) error { - return s.b.DeleteWebTun(prefix) + return s.webS.DeleteWebTun(prefix) } // make sure password satisfies our requirements (relaxed), // mostly to avoid putting garbage in func verifyPassword(password []byte) error { if len(password) < MinPasswordLength { - return &BadParameterError{ + return &teleport.BadParameterError{ Param: "password", - Msg: fmt.Sprintf( + Err: fmt.Sprintf( "password is too short, min length is %v", MinPasswordLength), } } if len(password) > MaxPasswordLength { - return &BadParameterError{ + return &teleport.BadParameterError{ Param: "password", - Msg: fmt.Sprintf( + Err: fmt.Sprintf( "password is too long, max length is %v", MaxPasswordLength), } } @@ -336,12 +354,3 @@ const ( MinPasswordLength = 6 MaxPasswordLength = 128 ) - -type BadParameterError struct { - Param string - Msg string -} - -func (p *BadParameterError) Error() string { - return fmt.Sprintf("bad parameter: %v, err: %v", p.Param, p.Msg) -} diff --git a/auth/auth_test.go b/auth/auth_test.go index c567cd8157b..6763dd0ff52 100644 --- a/auth/auth_test.go +++ b/auth/auth_test.go @@ -1,18 +1,25 @@ package auth import ( + "path/filepath" + + "github.com/gravitational/teleport" "github.com/gravitational/teleport/Godeps/_workspace/src/github.com/mailgun/lemma/secret" authority "github.com/gravitational/teleport/auth/native" "github.com/gravitational/teleport/backend" - "github.com/gravitational/teleport/backend/membk" + "github.com/gravitational/teleport/backend/boltbk" + + "github.com/gravitational/log" . "github.com/gravitational/teleport/Godeps/_workspace/src/gopkg.in/check.v1" ) type AuthSuite struct { - bk *membk.MemBackend + bk backend.Backend scrt *secret.Service a *AuthServer + + dir string } var _ = Suite(&AuthSuite{}) @@ -23,10 +30,16 @@ func (s *AuthSuite) SetUpSuite(c *C) { srv, err := secret.New(&secret.Config{KeyBytes: key}) c.Assert(err, IsNil) s.scrt = srv + + log.Init([]*log.LogConfig{&log.LogConfig{Name: "console"}}) } func (s *AuthSuite) SetUpTest(c *C) { - s.bk = membk.New() + s.dir = c.MkDir() + var err error + s.bk, err = boltbk.New(filepath.Join(s.dir, "db")) + c.Assert(err, IsNil) + s.a = NewAuthServer(s.bk, authority.New(), s.scrt) } @@ -34,11 +47,11 @@ func (s *AuthSuite) TestPasswordCRUD(c *C) { pass := []byte("abc123") err := s.a.CheckPassword("user1", pass) - c.Assert(err, FitsTypeOf, &backend.NotFoundError{}) + c.Assert(err, FitsTypeOf, &teleport.NotFoundError{}) c.Assert(s.a.UpsertPassword("user1", pass), IsNil) c.Assert(s.a.CheckPassword("user1", pass), IsNil) - c.Assert(s.a.CheckPassword("user1", []byte("abc123123")), FitsTypeOf, &BadParameterError{}) + c.Assert(s.a.CheckPassword("user1", []byte("abc123123")), FitsTypeOf, &teleport.BadParameterError{}) } func (s *AuthSuite) TestPasswordGarbage(c *C) { @@ -49,7 +62,7 @@ func (s *AuthSuite) TestPasswordGarbage(c *C) { } for _, g := range garbage { err := s.a.CheckPassword("user1", g) - c.Assert(err, FitsTypeOf, &BadParameterError{}) + c.Assert(err, FitsTypeOf, &teleport.BadParameterError{}) } } @@ -61,7 +74,7 @@ func (s *AuthSuite) TestSessions(c *C) { pass := []byte("abc123") ws, err := s.a.SignIn(user, pass) - c.Assert(err, FitsTypeOf, &backend.NotFoundError{}) + c.Assert(err, FitsTypeOf, &teleport.NotFoundError{}) c.Assert(ws, IsNil) c.Assert(s.a.UpsertPassword(user, pass), IsNil) @@ -78,7 +91,7 @@ func (s *AuthSuite) TestSessions(c *C) { c.Assert(err, IsNil) _, err = s.a.GetWebSession(user, ws.SID) - c.Assert(err, FitsTypeOf, &backend.NotFoundError{}) + c.Assert(err, FitsTypeOf, &teleport.NotFoundError{}) } func (s *AuthSuite) TestTokensCRUD(c *C) { @@ -88,9 +101,9 @@ func (s *AuthSuite) TestTokensCRUD(c *C) { c.Assert(s.a.ValidateToken(tok, "a.example.com"), IsNil) c.Assert(s.a.DeleteToken(tok), IsNil) - c.Assert(s.a.DeleteToken(tok), FitsTypeOf, &backend.NotFoundError{}) + c.Assert(s.a.DeleteToken(tok), FitsTypeOf, &teleport.NotFoundError{}) c.Assert(s.a.ValidateToken(tok, "a.example.com"), - FitsTypeOf, &backend.NotFoundError{}) + FitsTypeOf, &teleport.NotFoundError{}) } func (s *AuthSuite) TestBadTokens(c *C) { diff --git a/auth/clt.go b/auth/clt.go index 7969c9dbb2c..12b9d88e53c 100644 --- a/auth/clt.go +++ b/auth/clt.go @@ -10,9 +10,10 @@ import ( "strconv" "time" - "github.com/gravitational/teleport/backend" + "github.com/gravitational/teleport" "github.com/gravitational/teleport/events" "github.com/gravitational/teleport/recorder" + "github.com/gravitational/teleport/services" "github.com/gravitational/teleport/session" "github.com/gravitational/teleport/utils" @@ -63,7 +64,7 @@ func (c *Client) convertResponse( return nil, err } if re.Code() == http.StatusNotFound { - return nil, &backend.NotFoundError{Message: string(re.Bytes())} + return nil, &teleport.NotFoundError{Message: string(re.Bytes())} } if re.Code() < 200 || re.Code() > 299 { return nil, fmt.Errorf("error: %v", string(re.Bytes())) @@ -157,7 +158,7 @@ func (c *Client) UpsertParty(id string, p session.Party, ttl time.Duration) erro return nil } -func (c *Client) UpsertRemoteCert(cert backend.RemoteCert, ttl time.Duration) error { +func (c *Client) UpsertRemoteCert(cert services.RemoteCert, ttl time.Duration) error { out, err := c.PostForm(c.Endpoint("ca", "remote", cert.Type, "hosts", cert.FQDN), url.Values{ "key": []string{string(cert.Value)}, "ttl": []string{ttl.String()}, @@ -173,7 +174,7 @@ func (c *Client) UpsertRemoteCert(cert backend.RemoteCert, ttl time.Duration) er return nil } -func (c *Client) GetRemoteCerts(ctype string, fqdn string) ([]backend.RemoteCert, error) { +func (c *Client) GetRemoteCerts(ctype string, fqdn string) ([]services.RemoteCert, error) { out, err := c.Get(c.Endpoint("ca", "remote", ctype), url.Values{ "fqdn": []string{fqdn}, }) @@ -261,7 +262,7 @@ func (c *Client) GetChunkReader(id string) (recorder.ChunkReadCloser, error) { // UpsertServer is used by SSH servers to reprt their presense // to the auth servers in form of hearbeat expiring after ttl period. -func (c *Client) UpsertServer(s backend.Server, ttl time.Duration) error { +func (c *Client) UpsertServer(s services.Server, ttl time.Duration) error { _, err := c.PostForm(c.Endpoint("servers"), url.Values{ "id": []string{string(s.ID)}, "addr": []string{string(s.Addr)}, @@ -271,7 +272,7 @@ func (c *Client) UpsertServer(s backend.Server, ttl time.Duration) error { } // GetServers returns the list of servers registered in the cluster. -func (c *Client) GetServers() ([]backend.Server, error) { +func (c *Client) GetServers() ([]services.Server, error) { out, err := c.Get(c.Endpoint("servers"), url.Values{}) if err != nil { return nil, err @@ -285,8 +286,8 @@ func (c *Client) GetServers() ([]backend.Server, error) { // UpsertWebTun creates a persistent SSH tunnel to the specified web target // server that is valid for ttl period. -// See backend.WebTun documentation for details -func (c *Client) UpsertWebTun(wt backend.WebTun, ttl time.Duration) error { +// See services.WebTun documentation for details +func (c *Client) UpsertWebTun(wt services.WebTun, ttl time.Duration) error { _, err := c.PostForm(c.Endpoint("tunnels", "web"), url.Values{ "target": []string{string(wt.TargetAddr)}, "proxy": []string{string(wt.ProxyAddr)}, @@ -297,7 +298,7 @@ func (c *Client) UpsertWebTun(wt backend.WebTun, ttl time.Duration) error { } // GetWebTuns returns a list of web tunnels supported by the system -func (c *Client) GetWebTuns() ([]backend.WebTun, error) { +func (c *Client) GetWebTuns() ([]services.WebTun, error) { out, err := c.Get(c.Endpoint("tunnels", "web"), url.Values{}) if err != nil { return nil, err @@ -310,7 +311,7 @@ func (c *Client) GetWebTuns() ([]backend.WebTun, error) { } // GetWebTun retruns the web tunel details by it unique prefix -func (c *Client) GetWebTun(prefix string) (*backend.WebTun, error) { +func (c *Client) GetWebTun(prefix string) (*services.WebTun, error) { out, err := c.Get(c.Endpoint("tunnels", "web", prefix), url.Values{}) if err != nil { return nil, err @@ -382,7 +383,7 @@ func (c *Client) GetWebSession(user string, sid string) (string, error) { // certificate generated, that is stored for the duration of this web // session. These keys are used to access SSH servers via web portal. func (c *Client) GetWebSessionsKeys( - user string) ([]backend.AuthorizedKey, error) { + user string) ([]services.AuthorizedKey, error) { out, err := c.Get(c.Endpoint("users", user, "web", "sessions"), url.Values{}) if err != nil { @@ -425,7 +426,7 @@ func (c *Client) DeleteUser(user string) error { // by user CA in case of success, error otherwise. The certificate will be // valid for the duration of the ttl passed in. func (c *Client) UpsertUserKey(username string, - key backend.AuthorizedKey, ttl time.Duration) ([]byte, error) { + key services.AuthorizedKey, ttl time.Duration) ([]byte, error) { out, err := c.PostForm(c.Endpoint("users", username, "keys"), url.Values{ "key": []string{string(key.Value)}, @@ -445,7 +446,7 @@ func (c *Client) UpsertUserKey(username string, // GetUserKeys returns a list of keys registered for this user. // This list does not include the temporary keys associated with user // web sessions. -func (c *Client) GetUserKeys(user string) ([]backend.AuthorizedKey, error) { +func (c *Client) GetUserKeys(user string) ([]services.AuthorizedKey, error) { out, err := c.Get(c.Endpoint("users", user, "keys"), url.Values{}) if err != nil { return nil, err @@ -625,8 +626,8 @@ type ClientI interface { DeleteSession(id string) error UpsertSession(id string, ttl time.Duration) error UpsertParty(id string, p session.Party, ttl time.Duration) error - UpsertRemoteCert(cert backend.RemoteCert, ttl time.Duration) error - GetRemoteCerts(ctype string, fqdn string) ([]backend.RemoteCert, error) + UpsertRemoteCert(cert services.RemoteCert, ttl time.Duration) error + GetRemoteCerts(ctype string, fqdn string) ([]services.RemoteCert, error) DeleteRemoteCert(ctype string, fqdn, id string) error GenerateToken(fqdn string, ttl time.Duration) (string, error) Log(id lunk.EventID, e lunk.Event) @@ -634,22 +635,22 @@ type ClientI interface { GetEvents(filter events.Filter) ([]lunk.Entry, error) GetChunkWriter(id string) (recorder.ChunkWriteCloser, error) GetChunkReader(id string) (recorder.ChunkReadCloser, error) - UpsertServer(s backend.Server, ttl time.Duration) error - GetServers() ([]backend.Server, error) - UpsertWebTun(wt backend.WebTun, ttl time.Duration) error - GetWebTuns() ([]backend.WebTun, error) - GetWebTun(prefix string) (*backend.WebTun, error) + UpsertServer(s services.Server, ttl time.Duration) error + GetServers() ([]services.Server, error) + UpsertWebTun(wt services.WebTun, ttl time.Duration) error + GetWebTuns() ([]services.WebTun, error) + GetWebTun(prefix string) (*services.WebTun, error) DeleteWebTun(prefix string) error UpsertPassword(user string, password []byte) error CheckPassword(user string, password []byte) error SignIn(user string, password []byte) (string, error) GetWebSession(user string, sid string) (string, error) - GetWebSessionsKeys(user string) ([]backend.AuthorizedKey, error) + GetWebSessionsKeys(user string) ([]services.AuthorizedKey, error) DeleteWebSession(user string, sid string) error GetUsers() ([]string, error) DeleteUser(user string) error - UpsertUserKey(username string, key backend.AuthorizedKey, ttl time.Duration) ([]byte, error) - GetUserKeys(user string) ([]backend.AuthorizedKey, error) + UpsertUserKey(username string, key services.AuthorizedKey, ttl time.Duration) ([]byte, error) + GetUserKeys(user string) ([]services.AuthorizedKey, error) DeleteUserKey(username string, id string) error GetHostCAPub() ([]byte, error) GetUserCAPub() ([]byte, error) diff --git a/auth/init.go b/auth/init.go index 8866f218c6e..de58696bf48 100644 --- a/auth/init.go +++ b/auth/init.go @@ -7,7 +7,9 @@ import ( "path/filepath" "time" + "github.com/gravitational/teleport" "github.com/gravitational/teleport/backend" + "github.com/gravitational/teleport/services" "github.com/gravitational/teleport/sshutils" "github.com/gravitational/teleport/utils" @@ -26,10 +28,12 @@ func Init(b backend.Backend, a Authority, return nil, nil, fmt.Errorf("path can not be empty") } - if err := b.AcquireLock(authDomain, 60*time.Second); err != nil { + lockService := services.NewLockService(b) + err := lockService.AcquireLock(authDomain, 60*time.Second) + if err != nil { return nil, nil, err } - defer b.ReleaseLock(authDomain) + defer lockService.ReleaseLock(authDomain) scrt, err := InitSecret(dataDir) if err != nil { @@ -41,7 +45,7 @@ func Init(b backend.Backend, a Authority, if _, e := asrv.GetHostCAPub(); e != nil { log.Infof("Host CA error: %v", e) - if _, ok := e.(*backend.NotFoundError); ok { + if _, ok := e.(*teleport.NotFoundError); ok { log.Infof("Reseting host CA") if err := asrv.ResetHostCA(""); err != nil { return nil, nil, err @@ -51,7 +55,7 @@ func Init(b backend.Backend, a Authority, if _, e := asrv.GetUserCAPub(); e != nil { log.Infof("User CA error: %v", e) - if _, ok := e.(*backend.NotFoundError); ok { + if _, ok := e.(*teleport.NotFoundError); ok { log.Infof("Reseting host CA") if err := asrv.ResetUserCA(""); err != nil { return nil, nil, err diff --git a/auth/srv.go b/auth/srv.go index 9ae562b8450..3f6a149a8d2 100644 --- a/auth/srv.go +++ b/auth/srv.go @@ -8,9 +8,11 @@ import ( "strconv" "time" + "github.com/gravitational/teleport" "github.com/gravitational/teleport/backend" "github.com/gravitational/teleport/events" "github.com/gravitational/teleport/recorder" + "github.com/gravitational/teleport/services" "github.com/gravitational/teleport/session" "github.com/gravitational/teleport/Godeps/_workspace/src/github.com/codahale/lunk" @@ -125,7 +127,7 @@ func (s *APIServer) upsertServer(w http.ResponseWriter, r *http.Request, p httpr replyErr(w, err) return } - if err := s.s.UpsertServer(backend.Server{ID: id, Addr: addr}, ttl); err != nil { + if err := s.s.UpsertServer(services.Server{ID: id, Addr: addr}, ttl); err != nil { replyErr(w, err) return } @@ -155,7 +157,7 @@ func (s *APIServer) upsertWebTun(w http.ResponseWriter, r *http.Request, p httpr replyErr(w, err) return } - t, err := backend.NewWebTun(prefix, proxyAddr, targetAddr) + t, err := services.NewWebTun(prefix, proxyAddr, targetAddr) if err != nil { replyErr(w, err) return @@ -292,7 +294,7 @@ func (s *APIServer) upsertUserKey(w http.ResponseWriter, r *http.Request, p http replyErr(w, err) return } - cert, err := s.s.UpsertUserKey(p[0].Value, backend.AuthorizedKey{ID: id, Value: []byte(key)}, ttl) + cert, err := s.s.UpsertUserKey(p[0].Value, services.AuthorizedKey{ID: id, Value: []byte(key)}, ttl) if err != nil { replyErr(w, err) return @@ -637,10 +639,10 @@ func (s *APIServer) getChunks(w http.ResponseWriter, r *http.Request, p httprout func replyErr(w http.ResponseWriter, e error) { switch err := e.(type) { - case *backend.NotFoundError: + case *teleport.NotFoundError: reply(w, http.StatusNotFound, message(err.Error())) return - case *backend.MissingParameterError, *BadParameterError, *form.MissingParameterError, *form.BadParameterError: + case *teleport.MissingParameterError, *teleport.BadParameterError, *form.MissingParameterError, *form.BadParameterError: reply(w, http.StatusBadRequest, message(err.Error())) return } @@ -674,7 +676,7 @@ func (s *APIServer) upsertRemoteCert(w http.ResponseWriter, r *http.Request, p h replyErr(w, err) return } - cert := backend.RemoteCert{ID: id, Value: []byte(key), FQDN: fqdn, Type: ctype} + cert := services.RemoteCert{ID: id, Value: []byte(key), FQDN: fqdn, Type: ctype} if err := s.s.UpsertRemoteCert(cert, ttl); err != nil { replyErr(w, err) return @@ -781,7 +783,7 @@ type pubKeyResponse struct { } type pubKeysResponse struct { - PubKeys []backend.AuthorizedKey `json:"pubkeys"` + PubKeys []services.AuthorizedKey `json:"pubkeys"` } type certResponse struct { @@ -789,11 +791,11 @@ type certResponse struct { } type remoteCertResponse struct { - RemoteCert backend.RemoteCert `hson:"remote_cert"` + RemoteCert services.RemoteCert `hson:"remote_cert"` } type remoteCertsResponse struct { - RemoteCerts []backend.RemoteCert `hson:"remote_certs"` + RemoteCerts []services.RemoteCert `hson:"remote_certs"` } type usersResponse struct { @@ -810,19 +812,19 @@ type webSessionResponse struct { } type webSessionsResponse struct { - Keys []backend.AuthorizedKey `json:"keys"` + Keys []services.AuthorizedKey `json:"keys"` } type webTunResponse struct { - Tunnel backend.WebTun `json:"tunnel"` + Tunnel services.WebTun `json:"tunnel"` } type webTunsResponse struct { - Tunnels []backend.WebTun `json:"tunnels"` + Tunnels []services.WebTun `json:"tunnels"` } type serversResponse struct { - Servers []backend.Server `json:"servers"` + Servers []services.Server `json:"servers"` } type tokenResponse struct { diff --git a/auth/srv_test.go b/auth/srv_test.go index 0052ec9413a..9192adf4880 100644 --- a/auth/srv_test.go +++ b/auth/srv_test.go @@ -6,12 +6,13 @@ import ( "testing" "time" + "github.com/gravitational/teleport" authority "github.com/gravitational/teleport/auth/native" - "github.com/gravitational/teleport/backend" "github.com/gravitational/teleport/backend/boltbk" "github.com/gravitational/teleport/events/boltlog" etest "github.com/gravitational/teleport/events/test" rtest "github.com/gravitational/teleport/recorder/test" + "github.com/gravitational/teleport/services" "github.com/gravitational/teleport/recorder" "github.com/gravitational/teleport/recorder/boltrec" @@ -34,6 +35,13 @@ type APISuite struct { rec recorder.Recorder a *AuthServer dir string + + CAS *services.CAService + LockS *services.LockService + PresenceS *services.PresenceService + ProvisioningS *services.ProvisioningService + UserS *services.UserService + WebS *services.WebService } var _ = Suite(&APISuite{}) @@ -65,6 +73,13 @@ func (s *APISuite) SetUpTest(c *C) { clt, err := NewClient(s.srv.URL) c.Assert(err, IsNil) s.clt = clt + + s.CAS = services.NewCAService(s.bk) + s.LockS = services.NewLockService(s.bk) + s.PresenceS = services.NewPresenceService(s.bk) + s.ProvisioningS = services.NewProvisioningService(s.bk) + s.UserS = services.NewUserService(s.bk) + s.WebS = services.NewWebService(s.bk) } func (s *APISuite) TearDownTest(c *C) { @@ -76,12 +91,12 @@ func (s *APISuite) TearDownTest(c *C) { func (s *APISuite) TestHostCACRUD(c *C) { c.Assert(s.clt.ResetHostCA(), IsNil) - hca, err := s.bk.GetHostCA() + hca, err := s.CAS.GetHostCA() c.Assert(err, IsNil) c.Assert(s.clt.ResetHostCA(), IsNil) - hca2, err := s.bk.GetHostCA() + hca2, err := s.CAS.GetHostCA() c.Assert(err, IsNil) c.Assert(hca, Not(DeepEquals), hca2) @@ -94,11 +109,11 @@ func (s *APISuite) TestHostCACRUD(c *C) { func (s *APISuite) TestUserCACRUD(c *C) { c.Assert(s.clt.ResetUserCA(), IsNil) - uca, err := s.bk.GetUserCA() + uca, err := s.CAS.GetUserCA() c.Assert(err, IsNil) c.Assert(s.clt.ResetUserCA(), IsNil) - uca2, err := s.bk.GetUserCA() + uca2, err := s.CAS.GetUserCA() c.Assert(err, IsNil) c.Assert(uca, Not(DeepEquals), uca2) @@ -168,11 +183,11 @@ func (s *APISuite) TestUserKeyCRUD(c *C) { _, pub, err := s.clt.GenerateKeyPair("") c.Assert(err, IsNil) - key := backend.AuthorizedKey{ID: "id", Value: pub} + key := services.AuthorizedKey{ID: "id", Value: pub} cert, err := s.clt.UpsertUserKey("user1", key, 0) c.Assert(err, IsNil) - keys, err := s.bk.GetUserKeys("user1") + keys, err := s.UserS.GetUserKeys("user1") c.Assert(err, IsNil) c.Assert(string(keys[0].Value), DeepEquals, string(cert)) @@ -180,7 +195,7 @@ func (s *APISuite) TestUserKeyCRUD(c *C) { c.Assert(err, IsNil) c.Assert(s.clt.DeleteUserKey("user1", "id"), IsNil) - keys, err = s.bk.GetUserKeys("user1") + keys, err = s.UserS.GetUserKeys("user1") c.Assert(err, IsNil) c.Assert(len(keys), Equals, 0) } @@ -227,7 +242,7 @@ func (s *APISuite) TestWebTuns(c *C) { _, err := s.clt.GetWebTun("p1") c.Assert(err, NotNil) - t := backend.WebTun{ + t := services.WebTun{ Prefix: "p1", TargetAddr: "http://localhost:5000", ProxyAddr: "node1.gravitational.io", @@ -240,7 +255,7 @@ func (s *APISuite) TestWebTuns(c *C) { tuns, err := s.clt.GetWebTuns() c.Assert(err, IsNil) - c.Assert(tuns, DeepEquals, []backend.WebTun{t}) + c.Assert(tuns, DeepEquals, []services.WebTun{t}) c.Assert(s.clt.DeleteWebTun("p1"), IsNil) @@ -253,10 +268,10 @@ func (s *APISuite) TestServers(c *C) { c.Assert(err, IsNil) c.Assert(len(out), Equals, 0) - srv := backend.Server{ID: "id1", Addr: "host:1233"} + srv := services.Server{ID: "id1", Addr: "host:1233"} c.Assert(s.clt.UpsertServer(srv, 0), IsNil) - srv1 := backend.Server{ID: "id2", Addr: "host:1234"} + srv1 := services.Server{ID: "id2", Addr: "host:1234"} c.Assert(s.clt.UpsertServer(srv1, 0), IsNil) out, err = s.clt.GetServers() @@ -287,11 +302,11 @@ func (s *APISuite) TestTokens(c *C) { } func (s *APISuite) TestRemoteCACRUD(c *C) { - key := backend.RemoteCert{ + key := services.RemoteCert{ FQDN: "example.com", ID: "id", Value: []byte("hello1"), - Type: backend.UserCert, + Type: services.UserCert, } err := s.clt.UpsertRemoteCert(key, 0) c.Assert(err, IsNil) @@ -304,7 +319,7 @@ func (s *APISuite) TestRemoteCACRUD(c *C) { c.Assert(err, IsNil) err = s.clt.DeleteRemoteCert(key.Type, key.FQDN, key.ID) - c.Assert(err, FitsTypeOf, &backend.NotFoundError{}) + c.Assert(err, FitsTypeOf, &teleport.NotFoundError{}) } func (s *APISuite) TestSharedSessions(c *C) { diff --git a/auth/tun_test.go b/auth/tun_test.go index 11f341f7bb9..3c152021907 100644 --- a/auth/tun_test.go +++ b/auth/tun_test.go @@ -9,11 +9,11 @@ import ( "path/filepath" authority "github.com/gravitational/teleport/auth/native" - "github.com/gravitational/teleport/backend" - "github.com/gravitational/teleport/backend/membk" + "github.com/gravitational/teleport/backend/boltbk" "github.com/gravitational/teleport/events/boltlog" "github.com/gravitational/teleport/recorder" "github.com/gravitational/teleport/recorder/boltrec" + "github.com/gravitational/teleport/services" "github.com/gravitational/teleport/session" "github.com/gravitational/teleport/sshutils" "github.com/gravitational/teleport/utils" @@ -25,7 +25,7 @@ import ( ) type TunSuite struct { - bk *membk.MemBackend + bk *boltbk.BoltBackend scrt *secret.Service srv *httptest.Server @@ -40,7 +40,6 @@ type TunSuite struct { var _ = Suite(&TunSuite{}) func (s *TunSuite) SetUpSuite(c *C) { - s.dir = c.MkDir() key, err := secret.NewKey() c.Assert(err, IsNil) @@ -49,11 +48,6 @@ func (s *TunSuite) SetUpSuite(c *C) { s.scrt = srv log.Init([]*log.LogConfig{&log.LogConfig{Name: "console"}}) - s.bl, err = boltlog.New(filepath.Join(s.dir, "eventsdb")) - c.Assert(err, IsNil) - - s.rec, err = boltrec.New(s.dir) - c.Assert(err, IsNil) } func (s *TunSuite) TearDownTest(c *C) { @@ -61,7 +55,17 @@ func (s *TunSuite) TearDownTest(c *C) { } func (s *TunSuite) SetUpTest(c *C) { - s.bk = membk.New() + s.dir = c.MkDir() + var err error + s.bk, err = boltbk.New(filepath.Join(s.dir, "db")) + c.Assert(err, IsNil) + + s.bl, err = boltlog.New(filepath.Join(s.dir, "eventsdb")) + c.Assert(err, IsNil) + + s.rec, err = boltrec.New(s.dir) + c.Assert(err, IsNil) + s.a = NewAuthServer(s.bk, authority.New(), s.scrt) s.srv = httptest.NewServer( NewAPIServer(s.a, s.bl, session.New(s.bk), s.rec)) @@ -133,7 +137,7 @@ func (s *TunSuite) TestUnixServerClient(c *C) { c.Assert(err, IsNil) err = clt.UpsertServer( - backend.Server{ID: "a.example.com", Addr: "hello"}, 0) + services.Server{ID: "a.example.com", Addr: "hello"}, 0) c.Assert(err, IsNil) } diff --git a/backend/backend.go b/backend/backend.go index 64ce51ef120..47bb19b24c8 100644 --- a/backend/backend.go +++ b/backend/backend.go @@ -2,8 +2,6 @@ package backend import ( - "fmt" - "net/url" "time" ) @@ -15,201 +13,4 @@ type Backend interface { GetVal(path []string, key string) ([]byte, error) DeleteKey(path []string, key string) error DeleteBucket(path []string, bkt string) error - - // Grab a lock that will be released automatically in ttl time - AcquireLock(token string, ttl time.Duration) error - - // Grab a lock that will be released automatically in ttl time - ReleaseLock(token string) error - - // UpsertUserCA upserts the user certificate authority keys in OpenSSH authorized_keys format - UpsertUserCA(CA) error - - // GetUserCAPub returns the user certificate authority public key - GetUserCAPub() ([]byte, error) - - // Remote Certificate management - UpsertRemoteCert(RemoteCert, time.Duration) error - GetRemoteCerts(ctype string, fqdn string) ([]RemoteCert, error) - DeleteRemoteCert(ctype string, fqdn, id string) error - - // GetCA returns private, public key and certificate for user CA - GetUserCA() (*CA, error) - - // UpsertHostCA upserts host certificate authority keys in OpenSSH authorized_keys format - UpsertHostCA(CA) error - - // GetHostCA returns private, public key and certificate for host CA - GetHostCA() (*CA, error) - - // GetHostCACert returns the host certificate authority certificate - GetHostCAPub() ([]byte, error) - - // GetUserKeys returns a list of authorized keys for a given user - // in a OpenSSH key authorized_keys format - GetUserKeys(user string) ([]AuthorizedKey, error) - - // GetUsers returns a list of users registered in the backend - GetUsers() ([]string, error) - - // DeleteUser deletes a user with all the keys from the backend - DeleteUser(user string) error - - // Upsert Public key in OpenSSH authorized Key format - // user is a user name, keyID is a unique IDentifier for the key - // in case if ttl is 0, the key will be upserted permanently, otherwise - // it will expire in ttl seconds - UpsertUserKey(user string, key AuthorizedKey, ttl time.Duration) error - - // DeleteUserKey deletes user key by given ID - DeleteUserKey(user, key string) error - - // GetServers returns a list of registered servers - GetServers() ([]Server, error) - - // UpsertServer registers server presence, permanently if ttl is 0 or - // for the specified duration with second resolution if it's >= 1 second - UpsertServer(s Server, ttl time.Duration) error - - // UpsertPasswordHash upserts user password hash - UpsertPasswordHash(user string, hash []byte) error - - // GetPasswordHash returns the password hash for a given user - GetPasswordHash(user string) ([]byte, error) - - // UpsertSession - UpsertWebSession(user, sid string, s WebSession, ttl time.Duration) error - - // GetWebSession - GetWebSession(user, sid string) (*WebSession, error) - - // GetWebSessionsKeys - GetWebSessionsKeys(user string) ([]AuthorizedKey, error) - - // DeleteWebSession - DeleteWebSession(user, sid string) error - - UpsertWebTun(WebTun, time.Duration) error - - DeleteWebTun(prefix string) error - - GetWebTun(prefix string) (*WebTun, error) - - GetWebTuns() ([]WebTun, error) - - // Tokens are provisioning tokens for the auth server - UpsertToken(token, fqdn string, ttl time.Duration) error - GetToken(token string) (string, error) - DeleteToken(token string) error -} - -// WebTun is a web tunnel, the SSH tunnel -// created by the SSH server to a remote web server -type WebTun struct { - // Prefix is a domain prefix that will be used - // to serve this tunnel - Prefix string `json:"prefix"` - // ProxyAddr is the address of the SSH server - // that will be acting as a SSH proxy - ProxyAddr string `json:"proxy"` - // TargetAddr is the target http address of the server - TargetAddr string `json:"target"` -} - -func NewWebTun(prefix, proxyAddr, targetAddr string) (*WebTun, error) { - if prefix == "" { - return nil, &MissingParameterError{Param: "prefix"} - } - if targetAddr == "" { - return nil, &MissingParameterError{Param: "target"} - } - if proxyAddr == "" { - return nil, &MissingParameterError{Param: "proxy"} - } - if _, err := url.ParseRequestURI(targetAddr); err != nil { - return nil, &BadParameterError{Param: "target", Err: err.Error()} - } - return &WebTun{Prefix: prefix, ProxyAddr: proxyAddr, TargetAddr: targetAddr}, nil -} - -// WebSession -type WebSession struct { - Pub []byte `json:"pub"` - Priv []byte `json:"priv"` -} - -// CA is a set of private and public keys -type CA struct { - Pub []byte `json:"pub"` - Priv []byte `json:"priv"` -} - -// Server represents a running Teleport server instance -type Server struct { - ID string `json:"id"` - Addr string `json:"addr"` -} - -// AuthorizedKey is a key in form of OpenSSH authorized keys -type AuthorizedKey struct { - ID string `json:"id"` - Value []byte `json:"value"` -} - -type NotFoundError struct { - Message string -} - -func (n *NotFoundError) Error() string { - if n.Message != "" { - return n.Message - } else { - return "Object not found" - } -} - -type AlreadyExistsError struct { - Message string -} - -func (n *AlreadyExistsError) Error() string { - if n.Message != "" { - return n.Message - } else { - return "Object already exists" - } -} - -type MissingParameterError struct { - Param string -} - -func (m *MissingParameterError) Error() string { - return fmt.Sprintf("missing required parameter '%v'", m.Param) -} - -type BadParameterError struct { - Param string - Err string -} - -func (m *BadParameterError) Error() string { - return fmt.Sprintf("bad parameter '%v', %v", m.Param, m.Err) -} - -type RemoteCert struct { - Type string - ID string - FQDN string - Value []byte -} - -const ( - HostCert = "host" - UserCert = "user" -) - -func IsNotFound(e error) bool { - _, ok := e.(*NotFoundError) - return ok } diff --git a/backend/boltbk/boltbk.go b/backend/boltbk/boltbk.go index ac1beae19cf..115bd6aa467 100644 --- a/backend/boltbk/boltbk.go +++ b/backend/boltbk/boltbk.go @@ -8,7 +8,7 @@ import ( "sync" "time" - "github.com/gravitational/teleport/backend" + "github.com/gravitational/teleport" "github.com/gravitational/teleport/Godeps/_workspace/src/github.com/boltdb/bolt" ) @@ -31,10 +31,14 @@ func New(path string) (*BoltBackend, error) { }, nil } +func (b *BoltBackend) Close() error { + return nil +} + func (b *BoltBackend) GetKeys(path []string) ([]string, error) { keys, err := b.getKeys(path) if err != nil { - if isNotFound(err) { + if teleport.IsNotFound(err) { return []string{}, nil } return nil, err @@ -45,7 +49,7 @@ func (b *BoltBackend) GetKeys(path []string) ([]string, error) { } keys, err = b.getKeys(path) if err != nil { - if isNotFound(err) { + if teleport.IsNotFound(err) { return []string{}, nil } return nil, err @@ -80,7 +84,7 @@ func (b *BoltBackend) GetVal(path []string, key string) ([]byte, error) { if err := b.deleteKey(path, key); err != nil { return nil, err } - return nil, &backend.NotFoundError{ + return nil, &teleport.NotFoundError{ Message: fmt.Sprintf("%v: %v not found", path, key)} } return k.Value, nil @@ -94,336 +98,6 @@ func (b *BoltBackend) DeleteBucket(path []string, bucket string) error { return b.deleteBucket(path, bucket) } -func (b *BoltBackend) AcquireLock(token string, ttl time.Duration) error { - b.Lock() - defer b.Unlock() - - expires, ok := b.locks[token] - if ok && expires.After(time.Now()) { - return &backend.AlreadyExistsError{ - Message: fmt.Sprintf("lock %v already locked", token)} - } - b.locks[token] = time.Now().Add(ttl) - return nil -} - -func (b *BoltBackend) ReleaseLock(token string) error { - b.Lock() - defer b.Unlock() - - expires, ok := b.locks[token] - if !ok || expires.Before(time.Now()) { - return &backend.NotFoundError{ - Message: fmt.Sprintf( - "lock %v is deleted or expired", token), - } - } - delete(b.locks, token) - return nil -} - -func (b *BoltBackend) Close() error { - return nil -} - -func (b *BoltBackend) UpsertRemoteCert(cert backend.RemoteCert, ttl time.Duration) error { - return b.upsertKey([]string{"certs", cert.Type, "hosts", cert.FQDN}, cert.ID, cert.Value) -} - -func (b *BoltBackend) GetRemoteCerts(ctype string, fqdn string) ([]backend.RemoteCert, error) { - out := []backend.RemoteCert{} - err := b.db.View(func(tx *bolt.Tx) error { - hosts := []string{} - if fqdn == "" { - bkt, err := GetBucket(tx, []string{"certs", ctype, "hosts"}) - if err != nil { - if isNotFound(err) { - return nil - } - return err - } - c := bkt.Cursor() - for k, _ := c.First(); k != nil; k, _ = c.Next() { - hosts = append(hosts, string(k)) - } - } else { - hosts = []string{fqdn} - } - for _, h := range hosts { - bkt, err := GetBucket(tx, []string{"certs", ctype, "hosts", h}) - if err != nil { - return err - } - c := bkt.Cursor() - for k, v := c.First(); k != nil; k, v = c.Next() { - out = append(out, backend.RemoteCert{ - Type: ctype, - FQDN: h, - ID: string(k), - Value: v, - }) - } - } - return nil - }) - if err != nil { - return nil, err - } - return out, nil -} - -func (b *BoltBackend) DeleteRemoteCert(ctype string, fqdn, id string) error { - return b.deleteKey([]string{"certs", ctype, "hosts", fqdn}, id) -} - -// GetUsers returns a list of users registered in the backend -func (b *BoltBackend) GetUsers() ([]string, error) { - out := []string{} - err := b.db.View(func(tx *bolt.Tx) error { - b := tx.Bucket([]byte("users")) - if b == nil { - return nil - } - c := b.Cursor() - for k, _ := c.First(); k != nil; k, _ = c.Next() { - out = append(out, string(k)) - } - return nil - }) - if err != nil { - return nil, err - } - return out, nil -} - -// DeleteUser deletes a user with all the keys from the backend -func (b *BoltBackend) DeleteUser(user string) error { - return b.deleteBucket([]string{"users"}, user) -} - -func (b *BoltBackend) UpsertUserCA(a backend.CA) error { - return b.upsertJSONKey([]string{"userca"}, "val", a) -} - -func (b *BoltBackend) GetUserCA() (*backend.CA, error) { - var ca *backend.CA - return ca, b.getJSONKey([]string{"userca"}, "val", &ca) -} - -func (b *BoltBackend) GetUserCAPub() ([]byte, error) { - ca, err := b.GetUserCA() - if err != nil { - return nil, err - } - return ca.Pub, nil -} - -func (b *BoltBackend) UpsertHostCA(a backend.CA) error { - return b.upsertJSONKey([]string{"hostca"}, "val", a) -} - -func (b *BoltBackend) GetHostCA() (*backend.CA, error) { - var ca *backend.CA - return ca, b.getJSONKey([]string{"hostca"}, "val", &ca) -} - -func (b *BoltBackend) GetHostCAPub() ([]byte, error) { - ca, err := b.GetHostCA() - if err != nil { - return nil, err - } - return ca.Pub, nil -} - -func (b *BoltBackend) GetUserKeys(user string) ([]backend.AuthorizedKey, error) { - if user == "" { - return nil, &backend.MissingParameterError{Param: "user"} - } - values := []backend.AuthorizedKey{} - err := b.db.View(func(tx *bolt.Tx) error { - bkt, err := GetBucket(tx, []string{"users", user, "keys"}) - if err != nil { - if _, ok := err.(*backend.NotFoundError); ok { - return nil - } - return err - } - c := bkt.Cursor() - for k, v := c.First(); k != nil; k, v = c.Next() { - var key *backend.AuthorizedKey - if err := json.Unmarshal(v, &key); err != nil { - return err - } - values = append(values, *key) - } - return nil - }) - if err != nil { - return nil, err - } - return values, nil -} - -func (b *BoltBackend) UpsertToken(token, fqdn string, ttl time.Duration) error { - return b.upsertKey([]string{"tokens"}, token, []byte(fqdn)) -} - -func (b *BoltBackend) GetToken(token string) (string, error) { - var fqdn []byte - if err := b.getKey([]string{"tokens"}, token, &fqdn); err != nil { - return "", err - } - return string(fqdn), nil -} - -func (b *BoltBackend) DeleteToken(token string) error { - return b.deleteKey([]string{"tokens"}, token) -} - -func (b *BoltBackend) UpsertUserKey(user string, key backend.AuthorizedKey, ttl time.Duration) error { - if user == "" { - return &backend.MissingParameterError{Param: "user"} - } - if key.ID == "" { - return &backend.MissingParameterError{Param: "key.id"} - } - if len(key.Value) == 0 { - return &backend.MissingParameterError{Param: "key.val"} - } - return b.upsertJSONKey([]string{"users", user, "keys"}, key.ID, key) -} - -func (b *BoltBackend) DeleteUserKey(user, keyID string) error { - if user == "" { - return &backend.MissingParameterError{Param: "user"} - } - if keyID == "" { - return &backend.MissingParameterError{Param: "key.id"} - } - return b.deleteKey([]string{"users", user, "keys"}, keyID) -} - -func (b *BoltBackend) UpsertServer(s backend.Server, ttl time.Duration) error { - return b.upsertJSONKey([]string{"servers"}, s.ID, s) -} - -func (b *BoltBackend) GetServers() ([]backend.Server, error) { - values := []backend.Server{} - err := b.db.View(func(tx *bolt.Tx) error { - b := tx.Bucket([]byte("servers")) - if b == nil { - return nil - } - c := b.Cursor() - for k, v := c.First(); k != nil; k, v = c.Next() { - var key *backend.Server - if err := json.Unmarshal(v, &key); err != nil { - return err - } - values = append(values, *key) - } - return nil - }) - if err != nil { - return nil, err - } - return values, nil -} - -func (b *BoltBackend) UpsertPasswordHash(user string, hash []byte) error { - return b.upsertKey([]string{"users", user}, "password-hash", hash) -} - -func (b *BoltBackend) GetPasswordHash(user string) ([]byte, error) { - var hash []byte - err := b.getKey([]string{"users", user}, "password-hash", &hash) - if err != nil { - return nil, err - } - return hash, nil -} - -func (b *BoltBackend) UpsertWebSession(user, sid string, s backend.WebSession, ttl time.Duration) error { - return b.upsertJSONKey([]string{"users", user, "web-sessions"}, sid, s) -} - -func (b *BoltBackend) GetWebSession(user, sid string) (*backend.WebSession, error) { - var ws *backend.WebSession - return ws, b.getJSONKey([]string{"users", user, "web-sessions"}, sid, &ws) -} - -func (b *BoltBackend) GetWebSessionsKeys(user string) ([]backend.AuthorizedKey, error) { - values := []backend.AuthorizedKey{} - err := b.db.View(func(tx *bolt.Tx) error { - bkt, err := GetBucket(tx, []string{"users", user, "web-sessions"}) - if err != nil { - if _, ok := err.(*backend.NotFoundError); ok { - return nil - } - return err - } - c := bkt.Cursor() - for k, v := c.First(); k != nil; k, v = c.Next() { - var ws *backend.WebSession - if err := json.Unmarshal(v, &ws); err != nil { - return err - } - values = append(values, backend.AuthorizedKey{ - ID: string(k), - Value: ws.Pub, - }) - } - return nil - }) - if err != nil { - return nil, err - } - return values, nil -} - -func (b *BoltBackend) DeleteWebSession(user, sid string) error { - return b.deleteKey([]string{"users", user, "web-sessions"}, sid) -} - -func (b *BoltBackend) UpsertWebTun(t backend.WebTun, ttl time.Duration) error { - if t.Prefix == "" { - return &backend.MissingParameterError{Param: "Prefix"} - } - return b.upsertJSONKey([]string{"web-tuns"}, t.Prefix, t) -} - -func (b *BoltBackend) GetWebTun(prefix string) (*backend.WebTun, error) { - var wt *backend.WebTun - return wt, b.getJSONKey([]string{"web-tuns"}, prefix, &wt) -} - -func (b *BoltBackend) DeleteWebTun(prefix string) error { - return b.deleteKey([]string{"web-tuns"}, prefix) -} - -func (b *BoltBackend) GetWebTuns() ([]backend.WebTun, error) { - out := []backend.WebTun{} - err := b.db.View(func(tx *bolt.Tx) error { - bkt, err := GetBucket(tx, []string{"web-tuns"}) - if err != nil { - return err - } - c := bkt.Cursor() - for k, v := c.First(); k != nil; k, v = c.Next() { - var wt *backend.WebTun - if err := json.Unmarshal(v, &wt); err != nil { - return err - } - out = append(out, *wt) - } - return nil - }) - if err != nil { - return nil, err - } - return out, nil -} - func (b *BoltBackend) deleteBucket(buckets []string, bucket string) error { return b.db.Update(func(tx *bolt.Tx) error { bkt, err := GetBucket(tx, buckets) @@ -431,7 +105,7 @@ func (b *BoltBackend) deleteBucket(buckets []string, bucket string) error { return err } if bkt.Bucket([]byte(bucket)) == nil { - return &backend.NotFoundError{ + return &teleport.NotFoundError{ fmt.Sprintf("%v not found", bucket)} } return bkt.DeleteBucket([]byte(bucket)) @@ -445,7 +119,7 @@ func (b *BoltBackend) deleteKey(buckets []string, key string) error { return err } if bkt.Get([]byte(key)) == nil { - return &backend.NotFoundError{} + return &teleport.NotFoundError{} } return bkt.Delete([]byte(key)) }) @@ -483,7 +157,7 @@ func (b *BoltBackend) getJSONKey(buckets []string, key string, val interface{}) } bytes := bkt.Get([]byte(key)) if bytes == nil { - return &backend.NotFoundError{ + return &teleport.NotFoundError{ Message: fmt.Sprintf("%v %v not found", buckets, key), } } @@ -499,7 +173,7 @@ func (b *BoltBackend) getKey(buckets []string, key string, val *[]byte) error { } bytes := bkt.Get([]byte(key)) if bytes == nil { - return &backend.NotFoundError{ + return &teleport.NotFoundError{ Message: fmt.Sprintf("%v %v not found", buckets, key), } } @@ -545,24 +219,19 @@ func UpsertBucket(b *bolt.Tx, buckets []string) (*bolt.Bucket, error) { func GetBucket(b *bolt.Tx, buckets []string) (*bolt.Bucket, error) { bkt := b.Bucket([]byte(buckets[0])) if bkt == nil { - return nil, &backend.NotFoundError{ + return nil, &teleport.NotFoundError{ Message: fmt.Sprintf("bucket %v not found", buckets[0])} } for _, key := range buckets[1:] { bkt = bkt.Bucket([]byte(key)) if bkt == nil { - return nil, &backend.NotFoundError{ + return nil, &teleport.NotFoundError{ Message: fmt.Sprintf("bucket %v not found", key)} } } return bkt, nil } -func isNotFound(err error) bool { - _, ok := err.(*backend.NotFoundError) - return ok -} - type kv struct { Created time.Time `json:"created"` TTL time.Duration `json:"ttl"` diff --git a/backend/boltbk/boltbk_test.go b/backend/boltbk/boltbk_test.go index f0d341bbf8c..ae371b4ac09 100644 --- a/backend/boltbk/boltbk_test.go +++ b/backend/boltbk/boltbk_test.go @@ -34,50 +34,6 @@ func (s *BoltSuite) TearDownTest(c *C) { c.Assert(s.bk.Close(), IsNil) } -func (s *BoltSuite) TestUserKeyCRUD(c *C) { - s.suite.UserKeyCRUD(c) -} - -func (s *BoltSuite) TestUserCACRUD(c *C) { - s.suite.UserCACRUD(c) -} - -func (s *BoltSuite) TestHostCACRUD(c *C) { - s.suite.HostCACRUD(c) -} - -func (s *BoltSuite) TestServerCRUD(c *C) { - s.suite.ServerCRUD(c) -} - -func (s *BoltSuite) TestUsersCRUD(c *C) { - s.suite.UsersCRUD(c) -} - -func (s *BoltSuite) TestPasswordHashCRUD(c *C) { - s.suite.PasswordHashCRUD(c) -} - -func (s *BoltSuite) TestWebSessionCRUD(c *C) { - s.suite.WebSessionCRUD(c) -} - -func (s *BoltSuite) TestWebTunCRUD(c *C) { - s.suite.WebTunCRUD(c) -} - -func (s *BoltSuite) TestLocking(c *C) { - s.suite.Locking(c) -} - -func (s *BoltSuite) TestToken(c *C) { - s.suite.TokenCRUD(c) -} - -func (s *BoltSuite) TestRemoteCert(c *C) { - s.suite.RemoteCertCRUD(c) -} - func (s *BoltSuite) TestBasicCRUD(c *C) { s.suite.BasicCRUD(c) } diff --git a/backend/etcdbk/etcd.go b/backend/etcdbk/etcd.go index 23f3b8231aa..a69d2171692 100644 --- a/backend/etcdbk/etcd.go +++ b/backend/etcdbk/etcd.go @@ -2,12 +2,12 @@ package etcdbk import ( - "encoding/json" "fmt" "sort" "strings" "time" + "github.com/gravitational/teleport" "github.com/gravitational/teleport/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd" "github.com/gravitational/teleport/backend" ) @@ -104,54 +104,6 @@ func (b *bk) DeleteBucket(path []string, key string) error { return convertErr(err) } -func (b *bk) AcquireLock(token string, ttl time.Duration) error { - _, err := b.client.Create( - b.key("locks", token), "lock", uint64(ttl/time.Second)) - return convertErr(err) -} - -func (b *bk) ReleaseLock(token string) error { - _, err := b.client.Delete(b.key("locks", token), false) - return convertErr(err) -} - -func (b *bk) UpsertUserCA(a backend.CA) error { - return b.upsertCA(UserCA, a) -} - -func (b *bk) GetUserCA() (*backend.CA, error) { - return b.getCA(UserCA) -} - -func (b *bk) GetUserCAPub() ([]byte, error) { - ca, err := b.GetUserCA() - if err != nil { - return nil, err - } - return ca.Pub, nil -} - -func (b *bk) UpsertHostCA(a backend.CA) error { - return b.upsertCA(HostCA, a) -} - -func (b *bk) GetHostCA() (*backend.CA, error) { - return b.getCA(HostCA) -} - -func (b *bk) GetHostCAPub() ([]byte, error) { - ca, err := b.GetHostCA() - if err != nil { - return nil, err - } - return ca.Pub, nil -} - -func (b *bk) UpsertRemoteCert(cert backend.RemoteCert, ttl time.Duration) error { - _, err := b.client.Set(b.key("certs", cert.Type, "hosts", cert.FQDN, cert.ID), string(cert.Value), uint64(ttl/time.Second)) - return convertErr(err) -} - func (b *bk) getKeys(key string) ([]string, error) { vals := []string{} re, err := b.client.Get(key, true, false) @@ -170,302 +122,6 @@ func (b *bk) getKeys(key string) ([]string, error) { return vals, nil } -func (b *bk) GetRemoteCerts(ctype, fqdn string) ([]backend.RemoteCert, error) { - certs := []backend.RemoteCert{} - if ctype == "" { - return nil, fmt.Errorf("provide certificate type") - } - var hosts []string - var err error - if fqdn != "" { - hosts = []string{fqdn} - } else { - if hosts, err = b.getKeys(b.key("certs", ctype, "hosts")); err != nil { - return nil, err - } - } - - // for each host, get a list of ids - hs := make(map[string][]string) - for _, h := range hosts { - vals, err := b.getKeys(b.key("certs", ctype, "hosts", h)) - if err != nil { - return nil, err - } - hs[h] = vals - } - - // now, for each id retrieve it's value - for h, ids := range hs { - for _, id := range ids { - re, err := b.client.Get(b.key("certs", ctype, "hosts", h), true, true) - if err != nil { - return nil, convertErr(err) - } - cert := backend.RemoteCert{ - Value: []byte(re.Node.Nodes[0].Value), - Type: ctype, - FQDN: h, - ID: id, - } - certs = append(certs, cert) - } - } - return certs, nil -} - -func (b *bk) DeleteRemoteCert(ctype, fqdn, id string) error { - _, err := b.client.Delete(b.key("certs", ctype, "hosts", fqdn, id), true) - return convertErr(err) -} - -// GetUsers returns a list of users registered in the backend -func (b *bk) GetUsers() ([]string, error) { - values := []string{} - re, err := b.client.Get(b.key("users"), true, false) - if err != nil { - if notFound(err) { - return values, nil - } - return nil, convertErr(err) - } - if !isDir(re.Node) { - return values, nil - } - for _, sn := range re.Node.Nodes { - values = append(values, suffix(sn.Key)) - } - return values, nil -} - -// DeleteUser deletes a user with all the keys from the backend -func (b *bk) DeleteUser(user string) error { - _, err := b.client.Delete(b.key("users", user), true) - return convertErr(err) -} - -func (b *bk) GetUserKeys(user string) ([]backend.AuthorizedKey, error) { - values := []backend.AuthorizedKey{} - re, err := b.client.Get(b.key("users", user, "keys"), true, true) - if err != nil { - if notFound(err) { - return values, nil - } - return nil, convertErr(err) - } - if !isDir(re.Node) { - return values, nil - } - for _, sn := range re.Node.Nodes { - if !isDir(sn) { - values = append(values, backend.AuthorizedKey{ID: suffix(sn.Key), Value: []byte(sn.Value)}) - } - } - return values, nil -} - -func (b *bk) UpsertUserKey(user string, key backend.AuthorizedKey, ttl time.Duration) error { - _, err := b.client.Set(b.key("users", user, "keys", key.ID), string(key.Value), uint64(ttl/time.Second)) - return convertErr(err) -} - -func (b *bk) DeleteUserKey(user, keyID string) error { - _, err := b.client.Delete(b.key("users", user, "keys", keyID), true) - return convertErr(err) -} - -func (b *bk) GetServers() ([]backend.Server, error) { - values := []backend.Server{} - re, err := b.client.Get(b.key("servers"), true, true) - if err != nil { - if notFound(err) { - return values, nil - } - return nil, convertErr(err) - } - if !isDir(re.Node) { - return values, nil - } - for _, sn := range re.Node.Nodes { - if !isDir(sn) { - values = append(values, backend.Server{ID: suffix(sn.Key), Addr: sn.Value}) - } - } - return values, nil -} - -func (b *bk) UpsertServer(s backend.Server, ttl time.Duration) error { - _, err := b.client.Set(b.key("servers", s.ID), string(s.Addr), uint64(ttl/time.Second)) - return convertErr(err) -} - -func (b *bk) UpsertPasswordHash(user string, hash []byte) error { - bytes, err := json.Marshal(hash) - if err != nil { - return err - } - _, err = b.client.Set(b.key("users", user, "web", "pwd"), string(bytes), 0) - return convertErr(err) -} - -func (b *bk) GetPasswordHash(user string) ([]byte, error) { - re, err := b.client.Get(b.key("users", user, "web", "pwd"), false, false) - if err != nil { - return nil, convertErr(err) - } - var hash []byte - if err := json.Unmarshal([]byte(re.Node.Value), &hash); err != nil { - return nil, err - } - return hash, nil -} - -func (b *bk) UpsertWebSession(user, sid string, s backend.WebSession, ttl time.Duration) error { - bytes, err := json.Marshal(s) - if err != nil { - return err - } - _, err = b.client.Set(b.key("users", user, "web", "sessions", sid), string(bytes), uint64(ttl/time.Second)) - return convertErr(err) -} - -func (b *bk) GetWebSession(user, sid string) (*backend.WebSession, error) { - re, err := b.client.Get(b.key("users", user, "web", "sessions", sid), false, false) - if err != nil { - return nil, convertErr(err) - } - var sess *backend.WebSession - if err := json.Unmarshal([]byte(re.Node.Value), &sess); err != nil { - return nil, err - } - return sess, nil -} - -func (b *bk) GetWebSessionsKeys(user string) ([]backend.AuthorizedKey, error) { - values := []backend.AuthorizedKey{} - re, err := b.client.Get(b.key("users", user, "web", "sessions"), true, true) - if err != nil { - if notFound(err) { - return values, nil - } - return nil, convertErr(err) - } - if !isDir(re.Node) { - return values, nil - } - for _, sn := range re.Node.Nodes { - if isDir(sn) { - continue - } - var sess *backend.WebSession - if err := json.Unmarshal([]byte(sn.Value), &sess); err != nil { - return nil, err - } - values = append(values, backend.AuthorizedKey{Value: sess.Pub}) - } - return values, nil -} - -func (b *bk) DeleteWebSession(user, sid string) error { - _, err := b.client.Delete(b.key("users", user, "web", "sessions", sid), true) - return convertErr(err) -} - -func (b *bk) UpsertWebTun(t backend.WebTun, ttl time.Duration) error { - if t.Prefix == "" { - return &backend.MissingParameterError{Param: "Prefix"} - } - bytes, err := json.Marshal(t) - if err != nil { - return err - } - _, err = b.client.Set(b.key("tunnels", "web", t.Prefix), string(bytes), uint64(ttl/time.Second)) - return err -} - -func (b *bk) DeleteWebTun(prefix string) error { - _, err := b.client.Delete(b.key("tunnels", "web", prefix), true) - return convertErr(err) -} - -func (b *bk) GetWebTun(prefix string) (*backend.WebTun, error) { - re, err := b.client.Get(b.key("tunnels", "web", prefix), false, false) - if err != nil { - return nil, convertErr(err) - } - var tun *backend.WebTun - if err := json.Unmarshal([]byte(re.Node.Value), &tun); err != nil { - return nil, err - } - return tun, nil -} - -func (b *bk) GetWebTuns() ([]backend.WebTun, error) { - values := []backend.WebTun{} - re, err := b.client.Get(b.key("tunnels", "web"), true, true) - if err != nil { - if notFound(err) { - return values, nil - } - return nil, convertErr(err) - } - if !isDir(re.Node) { - return values, nil - } - for _, sn := range re.Node.Nodes { - if isDir(sn) { - continue - } - var tun *backend.WebTun - if err := json.Unmarshal([]byte(sn.Value), &tun); err != nil { - return nil, err - } - tun.Prefix = suffix(sn.Key) - values = append(values, *tun) - } - return values, nil -} - -func (b *bk) UpsertToken(token, fqdn string, ttl time.Duration) error { - _, err := b.client.Set( - b.key("tokens", token), fqdn, uint64(ttl/time.Second)) - return convertErr(err) -} - -func (b *bk) GetToken(token string) (string, error) { - re, err := b.client.Get(b.key("tokens", token), false, false) - if err != nil { - return "", convertErr(err) - } - return re.Node.Value, nil -} - -func (b *bk) DeleteToken(token string) error { - _, err := b.client.Delete(b.key("tokens", token), false) - return convertErr(err) -} - -func (b *bk) upsertCA(id string, a backend.CA) error { - out, err := json.Marshal(a) - if err != nil { - return err - } - _, err = b.client.Set(b.key("auth", id, "key"), string(out), 0) - return convertErr(err) -} - -func (b *bk) getCA(id string) (*backend.CA, error) { - re, err := b.client.Get(b.key("auth", id, "key"), false, false) - if err != nil { - return nil, convertErr(err) - } - var ca *backend.CA - if err := json.Unmarshal([]byte(re.Node.Value), &ca); err != nil { - return nil, err - } - return ca, nil -} - func notFound(e error) bool { err, ok := e.(*etcd.EtcdError) return ok && err.ErrorCode == 100 @@ -479,9 +135,9 @@ func convertErr(e error) error { case *etcd.EtcdError: switch err.ErrorCode { case 100: - return &backend.NotFoundError{Message: err.Error()} + return &teleport.NotFoundError{Message: err.Error()} case 105: - return &backend.AlreadyExistsError{Message: err.Error()} + return &teleport.AlreadyExistsError{Message: err.Error()} } } return e @@ -495,8 +151,3 @@ func suffix(key string) string { vals := strings.Split(key, "/") return vals[len(vals)-1] } - -const ( - HostCA = "host" - UserCA = "user" -) diff --git a/backend/etcdbk/etcd_test.go b/backend/etcdbk/etcd_test.go index c0f9d6c7458..f1dedf14738 100644 --- a/backend/etcdbk/etcd_test.go +++ b/backend/etcdbk/etcd_test.go @@ -78,50 +78,6 @@ func (s *EtcdSuite) TestFromString(c *C) { c.Assert(b, NotNil) } -func (s *EtcdSuite) TestUserKeyCRUD(c *C) { - s.suite.UserKeyCRUD(c) -} - -func (s *EtcdSuite) TestUserCACRUD(c *C) { - s.suite.UserCACRUD(c) -} - -func (s *EtcdSuite) TestHostCACRUD(c *C) { - s.suite.HostCACRUD(c) -} - -func (s *EtcdSuite) TestServerCRUD(c *C) { - s.suite.ServerCRUD(c) -} - -func (s *EtcdSuite) TestUsersCRUD(c *C) { - s.suite.UsersCRUD(c) -} - -func (s *EtcdSuite) TestPasswordHashCRUD(c *C) { - s.suite.PasswordHashCRUD(c) -} - -func (s *EtcdSuite) TestWebSessionCRUD(c *C) { - s.suite.WebSessionCRUD(c) -} - -func (s *EtcdSuite) TestWebTunCRUD(c *C) { - s.suite.WebTunCRUD(c) -} - -func (s *EtcdSuite) TestLocking(c *C) { - s.suite.Locking(c) -} - -func (s *EtcdSuite) TestToken(c *C) { - s.suite.TokenCRUD(c) -} - -func (s *EtcdSuite) TestRemoteCert(c *C) { - s.suite.RemoteCertCRUD(c) -} - func (s *EtcdSuite) TestBasicCRUD(c *C) { s.suite.BasicCRUD(c) } diff --git a/backend/membk/mem.go b/backend/membk/mem.go deleted file mode 100644 index 2dee68be774..00000000000 --- a/backend/membk/mem.go +++ /dev/null @@ -1,372 +0,0 @@ -// package membk implements in-memory backend used for tests purposes -package membk - -import ( - "fmt" - "sync" - "time" - - "github.com/gravitational/teleport/backend" -) - -type MemBackend struct { - sync.Mutex - - HostCA *backend.CA - UserCA *backend.CA - - Users map[string]*User - Servers map[string]backend.Server - WebTuns map[string]backend.WebTun - Tokens map[string]string - - Locks map[string]time.Time - RemoteCerts []backend.RemoteCert -} - -type User struct { - Keys map[string]backend.AuthorizedKey - Sessions map[string]backend.WebSession - Hash []byte -} - -func New() *MemBackend { - return &MemBackend{ - Users: make(map[string]*User), - Servers: make(map[string]backend.Server), - WebTuns: make(map[string]backend.WebTun), - Locks: make(map[string]time.Time), - Tokens: make(map[string]string), - } -} - -func (b *MemBackend) GetKeys(path []string) ([]string, error) { - return nil, nil -} - -func (b *MemBackend) UpsertVal(path []string, key string, val []byte, ttl time.Duration) error { - return nil -} - -func (b *MemBackend) GetVal(path []string, key string) ([]byte, error) { - return nil, nil -} - -func (b *MemBackend) DeleteKey(path []string, key string) error { - return nil -} - -func (b *MemBackend) DeleteBucket(path []string, key string) error { - return nil -} - -func (b *MemBackend) AcquireLock(token string, ttl time.Duration) error { - b.Lock() - defer b.Unlock() - - expires, ok := b.Locks[token] - if ok && expires.After(time.Now()) { - return &backend.AlreadyExistsError{ - Message: fmt.Sprintf("lock %v already locked", token)} - } - b.Locks[token] = time.Now().Add(ttl) - return nil -} - -func (b *MemBackend) ReleaseLock(token string) error { - b.Lock() - defer b.Unlock() - - expires, ok := b.Locks[token] - if !ok || expires.Before(time.Now()) { - return &backend.NotFoundError{ - Message: fmt.Sprintf( - "lock %v is deleted or expired", token), - } - } - delete(b.Locks, token) - return nil -} - -func (b *MemBackend) Close() error { - return nil -} - -// Remote Certificate management -func (b *MemBackend) UpsertRemoteCert(crt backend.RemoteCert, ttl time.Duration) error { - for i, c := range b.RemoteCerts { - if c.ID == crt.ID && c.FQDN == crt.FQDN && c.Type == crt.Type { - b.RemoteCerts[i] = crt - return nil - } - } - b.RemoteCerts = append(b.RemoteCerts, crt) - return nil -} - -func (b *MemBackend) GetRemoteCerts(ctype string, fqdn string) ([]backend.RemoteCert, error) { - out := []backend.RemoteCert{} - for _, c := range b.RemoteCerts { - if c.Type != ctype { - continue - } - if fqdn != "" && fqdn != c.FQDN { - continue - } - out = append(out, c) - } - return out, nil -} - -func (b *MemBackend) DeleteRemoteCert(ctype string, fqdn, id string) error { - for i, c := range b.RemoteCerts { - if c.ID == id && c.FQDN == fqdn && c.Type == ctype { - b.RemoteCerts = append(b.RemoteCerts[:i], b.RemoteCerts[i+1:]...) - return nil - } - } - return &backend.NotFoundError{} -} - -// GetUsers returns a list of users registered in the backend -func (b *MemBackend) GetUsers() ([]string, error) { - out := []string{} - for k := range b.Users { - out = append(out, k) - } - return out, nil -} - -// DeleteUser deletes a user with all the keys from the backend -func (b *MemBackend) DeleteUser(user string) error { - _, ok := b.Users[user] - if !ok { - return &backend.NotFoundError{} - } - delete(b.Users, user) - return nil -} - -func (b *MemBackend) UpsertUserCA(a backend.CA) error { - b.UserCA = &a - return nil -} - -func (b *MemBackend) GetUserCA() (*backend.CA, error) { - if b.UserCA == nil { - return nil, &backend.NotFoundError{} - } - return b.UserCA, nil -} - -func (b *MemBackend) GetUserCAPub() ([]byte, error) { - ca, err := b.GetUserCA() - if err != nil { - return nil, err - } - return ca.Pub, nil -} - -func (b *MemBackend) UpsertHostCA(a backend.CA) error { - b.HostCA = &a - return nil -} - -func (b *MemBackend) GetHostCA() (*backend.CA, error) { - if b.HostCA == nil { - return nil, &backend.NotFoundError{} - } - return b.HostCA, nil -} - -func (b *MemBackend) GetHostCAPub() ([]byte, error) { - ca, err := b.GetHostCA() - if err != nil { - return nil, err - } - return ca.Pub, nil -} - -func (b *MemBackend) GetUserKeys(user string) ([]backend.AuthorizedKey, error) { - if user == "" { - return nil, &backend.MissingParameterError{Param: "user"} - } - values := []backend.AuthorizedKey{} - u, ok := b.Users[user] - if !ok || len(u.Keys) == 0 { - return values, nil - } - for _, k := range u.Keys { - values = append(values, k) - } - return values, nil -} - -func (b *MemBackend) UpsertToken(token, fqdn string, ttl time.Duration) error { - b.Tokens[token] = fqdn - return nil -} - -func (b *MemBackend) GetToken(token string) (string, error) { - fqdn, ok := b.Tokens[token] - if !ok { - return "", &backend.NotFoundError{} - } - return fqdn, nil -} - -func (b *MemBackend) DeleteToken(token string) error { - if _, ok := b.Tokens[token]; !ok { - return &backend.NotFoundError{} - } - delete(b.Tokens, token) - return nil -} - -func (b *MemBackend) getUser(user string) *User { - u, ok := b.Users[user] - if ok { - return u - } - u = &User{ - Keys: make(map[string]backend.AuthorizedKey), - Sessions: make(map[string]backend.WebSession), - } - b.Users[user] = u - return u -} - -func (b *MemBackend) UpsertUserKey(user string, key backend.AuthorizedKey, ttl time.Duration) error { - if user == "" { - return &backend.MissingParameterError{Param: "user"} - } - if key.ID == "" { - return &backend.MissingParameterError{Param: "key.id"} - } - if len(key.Value) == 0 { - return &backend.MissingParameterError{Param: "key.val"} - } - b.getUser(user).Keys[key.ID] = key - return nil -} - -func (b *MemBackend) DeleteUserKey(user, keyID string) error { - if user == "" { - return &backend.MissingParameterError{Param: "user"} - } - if keyID == "" { - return &backend.MissingParameterError{Param: "key.id"} - } - u, ok := b.Users[user] - if !ok { - return &backend.NotFoundError{} - } - if _, ok := u.Keys[keyID]; !ok { - return &backend.NotFoundError{} - } - delete(u.Keys, keyID) - return nil -} - -func (b *MemBackend) UpsertServer(s backend.Server, ttl time.Duration) error { - b.Servers[s.ID] = s - return nil -} - -func (b *MemBackend) GetServers() ([]backend.Server, error) { - values := []backend.Server{} - for _, s := range b.Servers { - values = append(values, s) - } - return values, nil -} - -func (b *MemBackend) UpsertPasswordHash(user string, hash []byte) error { - b.getUser(user).Hash = hash - return nil -} - -func (b *MemBackend) GetPasswordHash(user string) ([]byte, error) { - u, ok := b.Users[user] - if !ok { - return nil, &backend.NotFoundError{Message: fmt.Sprintf("user '%v' not found", user)} - } - return u.Hash, nil -} - -func (b *MemBackend) UpsertWebSession(user, sid string, s backend.WebSession, ttl time.Duration) error { - b.getUser(user).Sessions[sid] = s - return nil -} - -func (b *MemBackend) GetWebSession(user, sid string) (*backend.WebSession, error) { - u, ok := b.Users[user] - if !ok { - return nil, &backend.NotFoundError{Message: fmt.Sprintf("user '%v' not found", user)} - } - ws, ok := u.Sessions[sid] - if !ok { - return nil, &backend.NotFoundError{Message: fmt.Sprintf("session '%v' not found for user '%v'", sid, user)} - } - return &ws, nil -} - -func (b *MemBackend) GetWebSessionsKeys(user string) ([]backend.AuthorizedKey, error) { - u, ok := b.Users[user] - if !ok { - return nil, &backend.NotFoundError{Message: fmt.Sprintf("user '%v' not found", user)} - } - out := []backend.AuthorizedKey{} - if len(u.Sessions) == 0 { - return out, nil - } - for _, ws := range u.Sessions { - out = append(out, backend.AuthorizedKey{Value: ws.Pub}) - } - return out, nil -} - -func (b *MemBackend) DeleteWebSession(user, sid string) error { - u, ok := b.Users[user] - if !ok { - return &backend.NotFoundError{Message: fmt.Sprintf("user '%v' not found", user)} - } - if _, ok := u.Sessions[sid]; !ok { - return &backend.NotFoundError{Message: fmt.Sprintf("session '%v' not found for user '%v'", user, sid)} - } - delete(u.Sessions, sid) - return nil -} - -func (b *MemBackend) UpsertWebTun(t backend.WebTun, ttl time.Duration) error { - if t.Prefix == "" { - return &backend.MissingParameterError{Param: "Prefix"} - } - b.WebTuns[t.Prefix] = t - return nil -} - -func (b *MemBackend) GetWebTun(prefix string) (*backend.WebTun, error) { - t, ok := b.WebTuns[prefix] - if !ok { - return nil, &backend.NotFoundError{Message: fmt.Sprintf("web tunnel '%v' not found", prefix)} - } - return &t, nil -} - -func (b *MemBackend) DeleteWebTun(prefix string) error { - _, ok := b.WebTuns[prefix] - if !ok { - return &backend.NotFoundError{Message: fmt.Sprintf("web tunnel '%v' not found", prefix)} - } - delete(b.WebTuns, prefix) - return nil -} - -func (b *MemBackend) GetWebTuns() ([]backend.WebTun, error) { - out := []backend.WebTun{} - for _, t := range b.WebTuns { - out = append(out, t) - } - return out, nil -} diff --git a/backend/membk/mem_test.go b/backend/membk/mem_test.go deleted file mode 100644 index 311e277e3b6..00000000000 --- a/backend/membk/mem_test.go +++ /dev/null @@ -1,74 +0,0 @@ -package membk - -import ( - "testing" - - "github.com/gravitational/teleport/backend/test" - - . "github.com/gravitational/teleport/Godeps/_workspace/src/gopkg.in/check.v1" -) - -func TestMem(t *testing.T) { TestingT(t) } - -type MemSuite struct { - bk *MemBackend - suite test.BackendSuite -} - -var _ = Suite(&MemSuite{}) - -func (s *MemSuite) SetUpTest(c *C) { - // Initiate a backend with a registry - s.bk = New() - - s.suite.ChangesC = make(chan interface{}) - s.suite.B = s.bk -} - -func (s *MemSuite) TearDownTest(c *C) { - c.Assert(s.bk.Close(), IsNil) -} - -func (s *MemSuite) TestUserKeyCRUD(c *C) { - s.suite.UserKeyCRUD(c) -} - -func (s *MemSuite) TestUserCACRUD(c *C) { - s.suite.UserCACRUD(c) -} - -func (s *MemSuite) TestHostCACRUD(c *C) { - s.suite.HostCACRUD(c) -} - -func (s *MemSuite) TestServerCRUD(c *C) { - s.suite.ServerCRUD(c) -} - -func (s *MemSuite) TestUsersCRUD(c *C) { - s.suite.UsersCRUD(c) -} - -func (s *MemSuite) TestPasswordHashCRUD(c *C) { - s.suite.PasswordHashCRUD(c) -} - -func (s *MemSuite) TestWebSessionCRUD(c *C) { - s.suite.WebSessionCRUD(c) -} - -func (s *MemSuite) TestWebTunCRUD(c *C) { - s.suite.WebTunCRUD(c) -} - -func (s *MemSuite) TestLocking(c *C) { - s.suite.Locking(c) -} - -func (s *MemSuite) TestToken(c *C) { - s.suite.TokenCRUD(c) -} - -func (s *MemSuite) TestRemoteCert(c *C) { - s.suite.RemoteCertCRUD(c) -} diff --git a/backend/test/suite.go b/backend/test/suite.go index f8f88b47d55..d7b8c86c61d 100644 --- a/backend/test/suite.go +++ b/backend/test/suite.go @@ -6,6 +6,7 @@ import ( "testing" "time" + "github.com/gravitational/teleport" "github.com/gravitational/teleport/Godeps/_workspace/src/github.com/mailgun/lemma/random" "github.com/gravitational/teleport/backend" @@ -39,258 +40,6 @@ func (s *BackendSuite) expectChanges(c *C, expected ...interface{}) { } } -func (s *BackendSuite) UserKeyCRUD(c *C) { - k := backend.AuthorizedKey{ID: "id1", Value: []byte("val1")} - - c.Assert(s.B.UpsertUserKey("user1", k, 0), IsNil) - - keys, err := s.B.GetUserKeys("user1") - c.Assert(err, IsNil) - c.Assert(keys, DeepEquals, []backend.AuthorizedKey{k}) - - c.Assert(s.B.DeleteUserKey("user1", k.ID), IsNil) - - keys, err = s.B.GetUserKeys("user1") - c.Assert(err, IsNil) - c.Assert(keys, DeepEquals, []backend.AuthorizedKey{}) -} - -func (s *BackendSuite) UsersCRUD(c *C) { - u, err := s.B.GetUsers() - c.Assert(err, IsNil) - c.Assert(len(u), Equals, 0) - - k := backend.AuthorizedKey{ID: "id1", Value: []byte("val1")} - - c.Assert(s.B.UpsertUserKey("user1", k, 0), IsNil) - c.Assert(s.B.UpsertUserKey("user2", k, 0), IsNil) - - u, err = s.B.GetUsers() - c.Assert(err, IsNil) - c.Assert(toSet(u), DeepEquals, map[string]struct{}{"user1": struct{}{}, "user2": struct{}{}}) - - c.Assert(s.B.DeleteUser("user1"), IsNil) - - u, err = s.B.GetUsers() - c.Assert(err, IsNil) - c.Assert(toSet(u), DeepEquals, map[string]struct{}{"user2": struct{}{}}) - - c.Assert(s.B.DeleteUser("user1"), FitsTypeOf, &backend.NotFoundError{}) -} - -func (s *BackendSuite) UserCACRUD(c *C) { - ca := backend.CA{ - Pub: []byte("capub"), - Priv: []byte("capriv"), - } - c.Assert(s.B.UpsertUserCA(ca), IsNil) - - out, err := s.B.GetUserCA() - c.Assert(err, IsNil) - c.Assert(out, DeepEquals, &ca) - - outp, err := s.B.GetUserCAPub() - c.Assert(err, IsNil) - c.Assert(outp, DeepEquals, ca.Pub) -} - -func (s *BackendSuite) HostCACRUD(c *C) { - ca := backend.CA{ - Pub: []byte("capub"), - Priv: []byte("capriv"), - } - c.Assert(s.B.UpsertHostCA(ca), IsNil) - - out, err := s.B.GetHostCA() - c.Assert(err, IsNil) - c.Assert(out, DeepEquals, &ca) - - outp, err := s.B.GetHostCAPub() - c.Assert(err, IsNil) - c.Assert(outp, DeepEquals, ca.Pub) -} - -func (s *BackendSuite) ServerCRUD(c *C) { - out, err := s.B.GetServers() - c.Assert(err, IsNil) - c.Assert(len(out), Equals, 0) - - srv := backend.Server{ID: "srv1", Addr: "localhost:2022"} - c.Assert(s.B.UpsertServer(srv, 0), IsNil) - - out, err = s.B.GetServers() - c.Assert(err, IsNil) - c.Assert(out, DeepEquals, []backend.Server{srv}) -} - -func (s *BackendSuite) PasswordHashCRUD(c *C) { - _, err := s.B.GetPasswordHash("user1") - c.Assert(err, FitsTypeOf, &backend.NotFoundError{}) - - err = s.B.UpsertPasswordHash("user1", []byte("hello123")) - c.Assert(err, IsNil) - - hash, err := s.B.GetPasswordHash("user1") - c.Assert(err, IsNil) - c.Assert(hash, DeepEquals, []byte("hello123")) - - err = s.B.UpsertPasswordHash("user1", []byte("hello321")) - c.Assert(err, IsNil) - - hash, err = s.B.GetPasswordHash("user1") - c.Assert(err, IsNil) - c.Assert(hash, DeepEquals, []byte("hello321")) -} - -func (s *BackendSuite) WebSessionCRUD(c *C) { - _, err := s.B.GetWebSession("user1", "sid1") - c.Assert(err, FitsTypeOf, &backend.NotFoundError{}) - - ws := backend.WebSession{Pub: []byte("pub123"), Priv: []byte("priv123")} - err = s.B.UpsertWebSession("user1", "sid1", ws, 0) - c.Assert(err, IsNil) - - out, err := s.B.GetWebSession("user1", "sid1") - c.Assert(err, IsNil) - c.Assert(out, DeepEquals, &ws) - - ws1 := backend.WebSession{Pub: []byte("pub321"), Priv: []byte("priv321")} - err = s.B.UpsertWebSession("user1", "sid1", ws1, 0) - c.Assert(err, IsNil) - - out2, err := s.B.GetWebSession("user1", "sid1") - c.Assert(err, IsNil) - c.Assert(out2, DeepEquals, &ws1) - - keys, err := s.B.GetWebSessionsKeys("user1") - c.Assert(err, IsNil) - c.Assert(keys[0].Value, DeepEquals, out2.Pub) - - c.Assert(s.B.DeleteWebSession("user1", "sid1"), IsNil) - - _, err = s.B.GetWebSession("user1", "sid1") - c.Assert(err, FitsTypeOf, &backend.NotFoundError{}) -} - -func (s *BackendSuite) WebTunCRUD(c *C) { - _, err := s.B.GetWebTun("p1") - c.Assert(err, FitsTypeOf, &backend.NotFoundError{}) - - t := backend.WebTun{ - Prefix: "p1", - TargetAddr: "http://localhost:5000", - ProxyAddr: "node1.gravitational.io", - } - c.Assert(s.B.UpsertWebTun(t, 0), IsNil) - - out, err := s.B.GetWebTun("p1") - c.Assert(out, DeepEquals, &t) - - tuns, err := s.B.GetWebTuns() - c.Assert(err, IsNil) - c.Assert(tuns, DeepEquals, []backend.WebTun{t}) - - t1 := backend.WebTun{ - Prefix: "p1", - TargetAddr: "http://localhost:5001", - ProxyAddr: "node1.gravitational2.io", - } - c.Assert(s.B.UpsertWebTun(t1, 0), IsNil) - - out, err = s.B.GetWebTun("p1") - c.Assert(out, DeepEquals, &t1) - - c.Assert(s.B.DeleteWebTun("p1"), IsNil) - - _, err = s.B.GetWebTun("p1") - c.Assert(err, FitsTypeOf, &backend.NotFoundError{}) -} - -func (s *BackendSuite) Locking(c *C) { - tok := randomToken() - ttl := 30 * time.Second - - c.Assert(s.B.AcquireLock(tok, ttl), IsNil) - c.Assert(s.B.AcquireLock(tok, ttl), - FitsTypeOf, &backend.AlreadyExistsError{}) - - c.Assert(s.B.ReleaseLock(tok), IsNil) - c.Assert(s.B.ReleaseLock(tok), FitsTypeOf, &backend.NotFoundError{}) - - c.Assert(s.B.AcquireLock(tok, 30*time.Second), IsNil) -} - -func (s *BackendSuite) TokenCRUD(c *C) { - _, err := s.B.GetToken("token") - c.Assert(err, FitsTypeOf, &backend.NotFoundError{}) - - c.Assert(s.B.UpsertToken("token", "a.example.com", 0), IsNil) - - out, err := s.B.GetToken("token") - c.Assert(out, Equals, "a.example.com") - c.Assert(err, IsNil) - - c.Assert(s.B.DeleteToken("token"), IsNil) - - _, err = s.B.GetToken("token") - c.Assert(err, FitsTypeOf, &backend.NotFoundError{}) -} - -func (s *BackendSuite) RemoteCertCRUD(c *C) { - out, err := s.B.GetRemoteCerts(backend.HostCert, "") - c.Assert(err, IsNil) - c.Assert(out, DeepEquals, []backend.RemoteCert{}) - - ca := backend.RemoteCert{ - Type: backend.HostCert, - ID: "c1", - FQDN: "example.com", - Value: []byte("hello"), - } - c.Assert(s.B.UpsertRemoteCert(ca, 0), IsNil) - - out, err = s.B.GetRemoteCerts(backend.HostCert, ca.FQDN) - c.Assert(err, IsNil) - c.Assert(out[0], DeepEquals, ca) - - ca2 := backend.RemoteCert{ - Type: backend.HostCert, - ID: "c2", - FQDN: "example.org", - Value: []byte("hello2"), - } - c.Assert(s.B.UpsertRemoteCert(ca2, 0), IsNil) - - out, err = s.B.GetRemoteCerts(backend.HostCert, ca2.FQDN) - c.Assert(err, IsNil) - c.Assert(out[0], DeepEquals, ca2) - - out, err = s.B.GetRemoteCerts(backend.HostCert, "") - c.Assert(err, IsNil) - c.Assert(len(out), Equals, 2) - - certs := make(map[string]backend.RemoteCert) - for _, c := range out { - certs[c.FQDN+c.ID] = c - } - c.Assert(certs[ca.FQDN+ca.ID], DeepEquals, ca) - c.Assert(certs[ca2.FQDN+ca2.ID], DeepEquals, ca2) - - // Update ca - ca.Value = []byte("hello updated") - c.Assert(s.B.UpsertRemoteCert(ca, 0), IsNil) - - out, err = s.B.GetRemoteCerts(backend.HostCert, ca.FQDN) - c.Assert(err, IsNil) - c.Assert(out[0], DeepEquals, ca) - - err = s.B.DeleteRemoteCert(backend.HostCert, ca.FQDN, ca.ID) - c.Assert(err, IsNil) - - err = s.B.DeleteRemoteCert(backend.HostCert, ca.FQDN, ca.ID) - c.Assert(err, FitsTypeOf, &backend.NotFoundError{}) -} - func (s *BackendSuite) BasicCRUD(c *C) { keys, err := s.B.GetKeys([]string{"keys"}) c.Assert(err, IsNil) @@ -313,7 +62,7 @@ func (s *BackendSuite) BasicCRUD(c *C) { c.Assert(string(out), Equals, "val-updated") c.Assert(s.B.DeleteKey([]string{"a", "b"}, "bkey"), IsNil) - c.Assert(s.B.DeleteKey([]string{"a", "b"}, "bkey"), FitsTypeOf, &backend.NotFoundError{}) + c.Assert(s.B.DeleteKey([]string{"a", "b"}, "bkey"), FitsTypeOf, &teleport.NotFoundError{}) } func (s *BackendSuite) Expiration(c *C) { diff --git a/cp/cp.go b/cp/cp.go index bc9e4ee60cd..0f0d83462eb 100644 --- a/cp/cp.go +++ b/cp/cp.go @@ -12,9 +12,10 @@ import ( "strconv" "time" + "github.com/gravitational/teleport" "github.com/gravitational/teleport/Godeps/_workspace/src/code.google.com/p/go-uuid/uuid" - "github.com/gravitational/teleport/backend" "github.com/gravitational/teleport/events" + "github.com/gravitational/teleport/services" "github.com/gravitational/teleport/sshutils/scp" "github.com/gravitational/teleport/utils" @@ -402,7 +403,7 @@ func (s *CPHandler) sendMessage(w http.ResponseWriter, r *http.Request, p httpro func (s *CPHandler) getSession(w http.ResponseWriter, r *http.Request, p httprouter.Params, c Context) { ses, err := c.GetClient().GetSession(p[0].Value) if err != nil { - if !backend.IsNotFound(err) { + if !teleport.IsNotFound(err) { log.Errorf("failed to retrieve session: %v", err) replyErr(w, http.StatusInternalServerError, err) return @@ -504,7 +505,7 @@ func (s *CPHandler) upsertWebTun(w http.ResponseWriter, r *http.Request, _ httpr roundtrip.ReplyJSON(w, http.StatusBadRequest, message(err.Error())) return } - wt, err := backend.NewWebTun(prefix, proxy, target) + wt, err := services.NewWebTun(prefix, proxy, target) if err != nil { log.Errorf("failed to parse form: %v", err) roundtrip.ReplyJSON(w, http.StatusBadRequest, message(err.Error())) @@ -603,13 +604,13 @@ func (s *CPHandler) postKey(w http.ResponseWriter, r *http.Request, _ httprouter roundtrip.ReplyJSON(w, http.StatusBadRequest, message(err.Error())) return } - cert, err := c.GetClient().UpsertUserKey(c.GetUser(), backend.AuthorizedKey{ID: id, Value: []byte(key)}, 0) + cert, err := c.GetClient().UpsertUserKey(c.GetUser(), services.AuthorizedKey{ID: id, Value: []byte(key)}, 0) if err != nil { log.Errorf("failed to upsert keys: %v", err) roundtrip.ReplyJSON(w, http.StatusBadRequest, message("invalid key format")) return } - roundtrip.ReplyJSON(w, http.StatusOK, backend.AuthorizedKey{ID: key, Value: cert}) + roundtrip.ReplyJSON(w, http.StatusOK, services.AuthorizedKey{ID: key, Value: cert}) } func (s *CPHandler) deleteKey(w http.ResponseWriter, r *http.Request, p httprouter.Params, c Context) { diff --git a/errors.go b/errors.go new file mode 100644 index 00000000000..67a65cf3198 --- /dev/null +++ b/errors.go @@ -0,0 +1,63 @@ +package teleport + +import "fmt" + +type AlreadyAcquiredError struct { + Message string +} + +func (e *AlreadyAcquiredError) Error() string { + if e.Message != "" { + return e.Message + } else { + return "Lock is already aquired" + } + +} + +type NotFoundError struct { + Message string +} + +func (e *NotFoundError) Error() string { + if e.Message != "" { + return e.Message + } else { + return "Object not found" + } + +} + +func IsNotFound(e error) bool { + _, ok := e.(*NotFoundError) + return ok +} + +type AlreadyExistsError struct { + Message string +} + +func (n *AlreadyExistsError) Error() string { + if n.Message != "" { + return n.Message + } else { + return "Object already exists" + } +} + +type MissingParameterError struct { + Param string +} + +func (m *MissingParameterError) Error() string { + return fmt.Sprintf("missing required parameter '%v'", m.Param) +} + +type BadParameterError struct { + Param string + Err string +} + +func (m *BadParameterError) Error() string { + return fmt.Sprintf("bad parameter '%v', %v", m.Param, m.Err) +} diff --git a/events/boltlog/bl.go b/events/boltlog/bl.go index bd0ba8c8b3f..70c5c3037cd 100644 --- a/events/boltlog/bl.go +++ b/events/boltlog/bl.go @@ -6,7 +6,7 @@ import ( "fmt" "time" - "github.com/gravitational/teleport/backend" + "github.com/gravitational/teleport" "github.com/gravitational/teleport/backend/boltbk" "github.com/gravitational/teleport/events" @@ -88,7 +88,7 @@ func (b *BoltLog) GetEvents(f events.Filter) ([]lunk.Entry, error) { bkt, err = boltbk.GetBucket(tx, []string{"events"}) } if err != nil { - if backend.IsNotFound(err) { + if teleport.IsNotFound(err) { return nil } return err diff --git a/recorder/boltrec/brec.go b/recorder/boltrec/brec.go index cf64b2dfabd..2654638cb64 100644 --- a/recorder/boltrec/brec.go +++ b/recorder/boltrec/brec.go @@ -7,7 +7,7 @@ import ( "path/filepath" "sync" - "github.com/gravitational/teleport/backend" + "github.com/gravitational/teleport" "github.com/gravitational/teleport/backend/boltbk" "github.com/gravitational/teleport/recorder" @@ -99,7 +99,7 @@ func (b *boltRW) initWriteIter() error { } bytes := bkt.Get([]byte("val")) if bytes == nil { - return &backend.NotFoundError{ + return &teleport.NotFoundError{ Message: fmt.Sprintf("not found"), } } @@ -110,7 +110,7 @@ func (b *boltRW) initWriteIter() error { if err == nil { return nil } - if !backend.IsNotFound(err) { + if !teleport.IsNotFound(err) { return err } return b.db.Update(func(tx *bolt.Tx) error { @@ -132,7 +132,7 @@ func (b *boltRW) WriteChunks(ch []recorder.Chunk) error { } iterb := ibkt.Get([]byte("val")) if iterb == nil { - return &backend.NotFoundError{fmt.Sprintf("iter not found")} + return &teleport.NotFoundError{fmt.Sprintf("iter not found")} } lastChunk := binary.BigEndian.Uint64(iterb) cbkt, err := boltbk.UpsertBucket(tx, []string{"chunks"}) @@ -166,7 +166,7 @@ func (b *boltRW) ReadChunk(chunk uint64) ([]byte, error) { } bytes := cbkt.Get(bin) if bytes == nil { - return &backend.NotFoundError{fmt.Sprintf("chunk not found")} + return &teleport.NotFoundError{fmt.Sprintf("chunk not found")} } bt = make([]byte, len(bytes)) copy(bt, bytes) @@ -196,7 +196,7 @@ func (r *boltRef) ReadChunks(start int, end int) ([]recorder.Chunk, error) { for i := start; i < end; i++ { out, err := r.rw.ReadChunk(uint64(i)) if err != nil { - if backend.IsNotFound(err) { + if teleport.IsNotFound(err) { return chunks, nil } return nil, err diff --git a/services/ca.go b/services/ca.go index 659dae4b0e1..7807dc10719 100644 --- a/services/ca.go +++ b/services/ca.go @@ -41,8 +41,7 @@ func (s *CAService) UpsertUserCA(ca CA) error { func (s *CAService) GetUserCA() (*CA, error) { val, err := s.backend.GetVal([]string{"ca"}, "userca") if err != nil { - log.Errorf(err.Error()) - return nil, convertErr(err) + return nil, err } var ca CA @@ -59,8 +58,7 @@ func (s *CAService) GetUserCA() (*CA, error) { func (s *CAService) GetUserCAPub() ([]byte, error) { val, err := s.backend.GetVal([]string{"ca"}, "userca") if err != nil { - log.Errorf(err.Error()) - return nil, convertErr(err) + return nil, err } var ca CA @@ -106,7 +104,7 @@ func (s *CAService) GetRemoteCerts(ctype string, "hosts", fqdn}) if err != nil { log.Errorf(err.Error()) - return nil, convertErr(err) + return nil, err } certs := make([]RemoteCert, len(IDs)) for i, id := range IDs { @@ -127,7 +125,7 @@ func (s *CAService) GetRemoteCerts(ctype string, "hosts"}) if err != nil { log.Errorf(err.Error()) - return nil, convertErr(err) + return nil, err } allCerts := make([]RemoteCert, 0) for _, f := range FQDNs { @@ -148,16 +146,12 @@ func (s *CAService) DeleteRemoteCert(ctype, fqdn, id string) error { return trace.Errorf("Unknown certificate type '" + ctype + "'") } - err := convertErr(s.backend.DeleteKey( + err := s.backend.DeleteKey( []string{"certs", ctype, "hosts", fqdn}, id, - )) + ) - if err != nil { - log.Errorf(err.Error()) - return err - } - return nil + return err } // UpsertHostCA upserts host certificate authority keys in OpenSSH authorized_keys format @@ -179,8 +173,7 @@ func (s *CAService) UpsertHostCA(ca CA) error { func (s *CAService) GetHostCA() (*CA, error) { val, err := s.backend.GetVal([]string{"ca"}, "hostca") if err != nil { - log.Errorf(err.Error()) - return nil, convertErr(err) + return nil, err } var ca CA @@ -197,8 +190,7 @@ func (s *CAService) GetHostCA() (*CA, error) { func (s *CAService) GetHostCAPub() ([]byte, error) { val, err := s.backend.GetVal([]string{"ca"}, "hostca") if err != nil { - log.Errorf(err.Error()) - return nil, convertErr(err) + return nil, err } var ca CA diff --git a/services/errors.go b/services/errors.go deleted file mode 100644 index 2d22a8e0ee3..00000000000 --- a/services/errors.go +++ /dev/null @@ -1,40 +0,0 @@ -package services - -import "github.com/gravitational/teleport/backend" - -type AlreadyAcquiredError struct { - Message string -} - -func (e *AlreadyAcquiredError) Error() string { - if e.Message != "" { - return e.Message - } else { - return "Lock is already aquired" - } - -} - -type NotFoundError struct { - Message string -} - -func (e *NotFoundError) Error() string { - if e.Message != "" { - return e.Message - } else { - return "Object not found" - } - -} - -func convertErr(e error) error { - if e == nil { - return nil - } - switch e.(type) { - case *backend.NotFoundError: - return &NotFoundError{} - } - return e -} diff --git a/services/lock.go b/services/lock.go index b5dad885880..99c227df64b 100644 --- a/services/lock.go +++ b/services/lock.go @@ -4,6 +4,7 @@ import ( "time" "github.com/gravitational/log" + "github.com/gravitational/teleport" "github.com/gravitational/teleport/backend" "github.com/gravitational/trace" ) @@ -20,10 +21,10 @@ func NewLockService(backend backend.Backend) *LockService { func (s *LockService) AcquireLock(token string, ttl time.Duration) error { _, err := s.backend.GetVal([]string{"locks"}, token) if err == nil { - return &AlreadyAcquiredError{""} + return &teleport.AlreadyAcquiredError{""} } else { switch err.(type) { - case *backend.NotFoundError: + case *teleport.NotFoundError: default: log.Errorf(err.Error()) return err @@ -43,7 +44,7 @@ func (s *LockService) ReleaseLock(token string) error { err := s.backend.DeleteKey([]string{"locks"}, token) if err != nil { log.Errorf(err.Error()) - return convertErr(err) + return err } return nil } diff --git a/services/provisioning.go b/services/provisioning.go index 07513ac6e26..ec7a99c0155 100644 --- a/services/provisioning.go +++ b/services/provisioning.go @@ -29,15 +29,11 @@ func (s *ProvisioningService) UpsertToken(token, fqdn string, ttl time.Duration) func (s *ProvisioningService) GetToken(token string) (string, error) { fqdn, err := s.backend.GetVal([]string{"tokens"}, token) if err != nil { - log.Errorf(err.Error()) - return "", convertErr(err) + return "", err } return string(fqdn), nil } func (s *ProvisioningService) DeleteToken(token string) error { err := s.backend.DeleteKey([]string{"tokens"}, token) - if err != nil { - log.Errorf(err.Error()) - } - return convertErr(err) + return err } diff --git a/services/services_test.go b/services/services_test.go index 9ae1ff5dc34..48179d1233a 100644 --- a/services/services_test.go +++ b/services/services_test.go @@ -4,9 +4,9 @@ import ( "path/filepath" "testing" - "github.com/gravitational/teleport/backend/boltbk" - + "github.com/gravitational/log" . "github.com/gravitational/teleport/Godeps/_workspace/src/gopkg.in/check.v1" + "github.com/gravitational/teleport/backend/boltbk" ) func TestBolt(t *testing.T) { TestingT(t) } @@ -19,6 +19,10 @@ type BoltSuite struct { var _ = Suite(&BoltSuite{}) +func (s *BoltSuite) SetUpSuite(c *C) { + log.Init([]*log.LogConfig{&log.LogConfig{Name: "console"}}) +} + func (s *BoltSuite) SetUpTest(c *C) { s.dir = c.MkDir() diff --git a/services/test_suite.go b/services/test_suite.go index bd69dfd5a51..d549fa8719c 100644 --- a/services/test_suite.go +++ b/services/test_suite.go @@ -4,6 +4,7 @@ import ( "testing" "time" + "github.com/gravitational/teleport" "github.com/gravitational/teleport/Godeps/_workspace/src/github.com/mailgun/lemma/random" "github.com/gravitational/teleport/backend" @@ -90,7 +91,7 @@ func (s *ServicesTestSuite) UsersCRUD(c *C) { c.Assert(err, IsNil) c.Assert(toSet(u), DeepEquals, map[string]struct{}{"user2": struct{}{}}) - c.Assert(s.UserS.DeleteUser("user1"), FitsTypeOf, &NotFoundError{}) + c.Assert(s.UserS.DeleteUser("user1"), FitsTypeOf, &teleport.NotFoundError{}) } func (s *ServicesTestSuite) UserCACRUD(c *C) { @@ -140,7 +141,7 @@ func (s *ServicesTestSuite) ServerCRUD(c *C) { func (s *ServicesTestSuite) PasswordHashCRUD(c *C) { _, err := s.WebS.GetPasswordHash("user1") - c.Assert(err, FitsTypeOf, &NotFoundError{}) + c.Assert(err, FitsTypeOf, &teleport.NotFoundError{}) err = s.WebS.UpsertPasswordHash("user1", []byte("hello123")) c.Assert(err, IsNil) @@ -159,7 +160,7 @@ func (s *ServicesTestSuite) PasswordHashCRUD(c *C) { func (s *ServicesTestSuite) WebSessionCRUD(c *C) { _, err := s.WebS.GetWebSession("user1", "sid1") - c.Assert(err, FitsTypeOf, &NotFoundError{}) + c.Assert(err, FitsTypeOf, &teleport.NotFoundError{}) ws := WebSession{Pub: []byte("pub123"), Priv: []byte("priv123")} err = s.WebS.UpsertWebSession("user1", "sid1", ws, 0) @@ -184,12 +185,12 @@ func (s *ServicesTestSuite) WebSessionCRUD(c *C) { c.Assert(s.WebS.DeleteWebSession("user1", "sid1"), IsNil) _, err = s.WebS.GetWebSession("user1", "sid1") - c.Assert(err, FitsTypeOf, &NotFoundError{}) + c.Assert(err, FitsTypeOf, &teleport.NotFoundError{}) } func (s *ServicesTestSuite) WebTunCRUD(c *C) { _, err := s.WebS.GetWebTun("p1") - c.Assert(err, FitsTypeOf, &NotFoundError{}) + c.Assert(err, FitsTypeOf, &teleport.NotFoundError{}) t := WebTun{ Prefix: "p1", @@ -218,7 +219,7 @@ func (s *ServicesTestSuite) WebTunCRUD(c *C) { c.Assert(s.WebS.DeleteWebTun("p1"), IsNil) _, err = s.WebS.GetWebTun("p1") - c.Assert(err, FitsTypeOf, &NotFoundError{}) + c.Assert(err, FitsTypeOf, &teleport.NotFoundError{}) } func (s *ServicesTestSuite) Locking(c *C) { @@ -227,17 +228,17 @@ func (s *ServicesTestSuite) Locking(c *C) { c.Assert(s.LockS.AcquireLock(tok, ttl), IsNil) c.Assert(s.LockS.AcquireLock(tok, ttl), - FitsTypeOf, &AlreadyAcquiredError{}) + FitsTypeOf, &teleport.AlreadyAcquiredError{}) c.Assert(s.LockS.ReleaseLock(tok), IsNil) - c.Assert(s.LockS.ReleaseLock(tok), FitsTypeOf, &NotFoundError{}) + c.Assert(s.LockS.ReleaseLock(tok), FitsTypeOf, &teleport.NotFoundError{}) c.Assert(s.LockS.AcquireLock(tok, 30*time.Second), IsNil) } func (s *ServicesTestSuite) TokenCRUD(c *C) { _, err := s.ProvisioningS.GetToken("token") - c.Assert(err, FitsTypeOf, &NotFoundError{}) + c.Assert(err, FitsTypeOf, &teleport.NotFoundError{}) c.Assert(s.ProvisioningS.UpsertToken("token", "a.example.com", 0), IsNil) @@ -248,7 +249,7 @@ func (s *ServicesTestSuite) TokenCRUD(c *C) { c.Assert(s.ProvisioningS.DeleteToken("token"), IsNil) _, err = s.ProvisioningS.GetToken("token") - c.Assert(err, FitsTypeOf, &NotFoundError{}) + c.Assert(err, FitsTypeOf, &teleport.NotFoundError{}) } func (s *ServicesTestSuite) RemoteCertCRUD(c *C) { @@ -303,7 +304,7 @@ func (s *ServicesTestSuite) RemoteCertCRUD(c *C) { c.Assert(err, IsNil) err = s.CAS.DeleteRemoteCert(HostCert, ca.FQDN, ca.ID) - c.Assert(err, FitsTypeOf, &NotFoundError{}) + c.Assert(err, FitsTypeOf, &teleport.NotFoundError{}) } func toSet(vals []string) map[string]struct{} { diff --git a/services/user.go b/services/user.go index a8812e72c91..7977e529236 100644 --- a/services/user.go +++ b/services/user.go @@ -32,8 +32,7 @@ func (s *UserService) UpsertUserKey(user string, key AuthorizedKey, func (s *UserService) GetUserKeys(user string) ([]AuthorizedKey, error) { IDs, err := s.backend.GetKeys([]string{"users", user, "keys"}) if err != nil { - log.Errorf(err.Error()) - return nil, convertErr(err) + return nil, err } keys := make([]AuthorizedKey, len(IDs)) @@ -54,7 +53,6 @@ func (s *UserService) GetUserKeys(user string) ([]AuthorizedKey, error) { func (s *UserService) GetUsers() ([]string, error) { users, err := s.backend.GetKeys([]string{"users"}) if err != nil { - log.Errorf(err.Error()) return nil, trace.Wrap(err) } return users, nil @@ -63,19 +61,13 @@ func (s *UserService) GetUsers() ([]string, error) { // DeleteUser deletes a user with all the keys from the backend func (s *UserService) DeleteUser(user string) error { err := s.backend.DeleteBucket([]string{"users"}, user) - if err != nil { - log.Errorf(err.Error()) - } - return convertErr(err) + return err } // DeleteUserKey deletes user key by given ID func (s *UserService) DeleteUserKey(user, key string) error { err := s.backend.DeleteKey([]string{"users", user, "keys"}, key) - if err != nil { - log.Errorf(err.Error()) - } - return convertErr(err) + return err } type AuthorizedKey struct { diff --git a/services/web.go b/services/web.go index 5a0d70a8c7e..aeda0594aad 100644 --- a/services/web.go +++ b/services/web.go @@ -3,9 +3,11 @@ package services import ( "encoding/json" "fmt" + "net/url" "time" "github.com/gravitational/log" + "github.com/gravitational/teleport" "github.com/gravitational/teleport/backend" "github.com/gravitational/trace" ) @@ -33,8 +35,7 @@ func (s *WebService) UpsertPasswordHash(user string, hash []byte) error { func (s *WebService) GetPasswordHash(user string) ([]byte, error) { hash, err := s.backend.GetVal([]string{"web", "users", user}, "pwd") if err != nil { - log.Errorf(err.Error()) - return nil, convertErr(err) + return nil, err } return hash, err } @@ -66,8 +67,7 @@ func (s *WebService) GetWebSession(user, sid string) (*WebSession, error) { sid, ) if err != nil { - log.Errorf(err.Error()) - return nil, convertErr(err) + return nil, err } var session WebSession @@ -84,8 +84,7 @@ func (s *WebService) GetWebSession(user, sid string) (*WebSession, error) { func (s *WebService) GetWebSessionsKeys(user string) ([]AuthorizedKey, error) { keys, err := s.backend.GetKeys([]string{"web", "users", user, "sessions"}) if err != nil { - log.Errorf(err.Error()) - return nil, convertErr(err) + return nil, err } values := make([]AuthorizedKey, len(keys)) @@ -106,10 +105,7 @@ func (s *WebService) DeleteWebSession(user, sid string) error { []string{"web", "users", user, "sessions"}, sid, ) - if err != nil { - log.Errorf(err.Error()) - } - return convertErr(err) + return err } func (s *WebService) UpsertWebTun(tun WebTun, ttl time.Duration) error { @@ -138,10 +134,7 @@ func (s *WebService) DeleteWebTun(prefix string) error { []string{"web", "tunnels"}, prefix, ) - if err != nil { - log.Errorf(err.Error()) - } - return convertErr(err) + return err } func (s *WebService) GetWebTun(prefix string) (*WebTun, error) { val, err := s.backend.GetVal( @@ -149,8 +142,7 @@ func (s *WebService) GetWebTun(prefix string) (*WebTun, error) { prefix, ) if err != nil { - log.Errorf(err.Error()) - return nil, convertErr(err) + return nil, err } var tun WebTun @@ -165,7 +157,6 @@ func (s *WebService) GetWebTun(prefix string) (*WebTun, error) { func (s *WebService) GetWebTuns() ([]WebTun, error) { keys, err := s.backend.GetKeys([]string{"web", "tunnels"}) if err != nil { - log.Errorf(err.Error()) return nil, err } @@ -198,3 +189,19 @@ type WebTun struct { // TargetAddr is the target http address of the server TargetAddr string `json:"target"` } + +func NewWebTun(prefix, proxyAddr, targetAddr string) (*WebTun, error) { + if prefix == "" { + return nil, &teleport.MissingParameterError{Param: "prefix"} + } + if targetAddr == "" { + return nil, &teleport.MissingParameterError{Param: "target"} + } + if proxyAddr == "" { + return nil, &teleport.MissingParameterError{Param: "proxy"} + } + if _, err := url.ParseRequestURI(targetAddr); err != nil { + return nil, &teleport.BadParameterError{Param: "target", Err: err.Error()} + } + return &WebTun{Prefix: prefix, ProxyAddr: proxyAddr, TargetAddr: targetAddr}, nil +} diff --git a/session/session.go b/session/session.go index eb7ab330bce..f7f3755a9bd 100644 --- a/session/session.go +++ b/session/session.go @@ -3,6 +3,7 @@ package session import ( "time" + "github.com/gravitational/teleport" "github.com/gravitational/teleport/backend" ) @@ -32,7 +33,7 @@ func (s *server) GetSessions() ([]Session, error) { out := []Session{} for _, sid := range keys { se, err := s.GetSession(sid) - if backend.IsNotFound(err) { + if teleport.IsNotFound(err) { continue } out = append(out, *se) @@ -55,7 +56,7 @@ func (s *server) GetSession(id string) (*Session, error) { var p *Party err := s.bk.GetJSONVal([]string{"sessions", id, "parties"}, pk, &p) if err != nil { - if backend.IsNotFound(err) { // key was expired + if teleport.IsNotFound(err) { // key was expired continue } return nil, err diff --git a/session/session_test.go b/session/session_test.go index 81d68a0a93c..bf9cda33a18 100644 --- a/session/session_test.go +++ b/session/session_test.go @@ -5,7 +5,7 @@ import ( "testing" "time" - "github.com/gravitational/teleport/backend" + "github.com/gravitational/teleport" "github.com/gravitational/teleport/backend/boltbk" . "github.com/gravitational/teleport/Godeps/_workspace/src/gopkg.in/check.v1" @@ -104,8 +104,8 @@ func (s *BoltSuite) TestPartiesCRUD(c *C) { // Delete session c.Assert(s.srv.DeleteSession("s1"), IsNil) - c.Assert(s.srv.DeleteSession("s1"), FitsTypeOf, &backend.NotFoundError{}) + c.Assert(s.srv.DeleteSession("s1"), FitsTypeOf, &teleport.NotFoundError{}) _, err = s.srv.GetSession("s1") - c.Assert(err, FitsTypeOf, &backend.NotFoundError{}) + c.Assert(err, FitsTypeOf, &teleport.NotFoundError{}) } diff --git a/srv/srv.go b/srv/srv.go index 157bb3a82b3..28136b4889b 100644 --- a/srv/srv.go +++ b/srv/srv.go @@ -10,9 +10,9 @@ import ( "time" "github.com/gravitational/teleport/auth" - "github.com/gravitational/teleport/backend" "github.com/gravitational/teleport/events" "github.com/gravitational/teleport/recorder" + "github.com/gravitational/teleport/services" rsession "github.com/gravitational/teleport/session" "github.com/gravitational/teleport/sshutils" "github.com/gravitational/teleport/sshutils/scp" @@ -112,7 +112,7 @@ func (s *Server) ID() string { func (s *Server) heartbeatPresence() { for { - srv := backend.Server{ + srv := services.Server{ ID: s.ID(), Addr: s.addr.Addr, } @@ -132,7 +132,7 @@ func (s *Server) getTrustedCAKeys() ([]ssh.PublicKey, error) { } authKeys = append(authKeys, key) - certs, err := s.ap.GetRemoteCerts(backend.UserCert, "") + certs, err := s.ap.GetRemoteCerts(services.UserCert, "") if err != nil { return nil, err } diff --git a/srv/srv_test.go b/srv/srv_test.go index bfca10c22b8..77d1dc69e22 100644 --- a/srv/srv_test.go +++ b/srv/srv_test.go @@ -4,13 +4,14 @@ import ( "bytes" "fmt" "io" + "path/filepath" "strings" "testing" "github.com/gravitational/teleport/auth" authority "github.com/gravitational/teleport/auth/native" - "github.com/gravitational/teleport/backend" - "github.com/gravitational/teleport/backend/membk" + "github.com/gravitational/teleport/backend/boltbk" + "github.com/gravitational/teleport/services" "github.com/gravitational/teleport/sshutils" "github.com/gravitational/teleport/utils" @@ -25,10 +26,11 @@ func TestSrv(t *testing.T) { TestingT(t) } type SrvSuite struct { srv *Server clt *ssh.Client - bk *membk.MemBackend + bk *boltbk.BoltBackend a *auth.AuthServer up *upack scrt *secret.Service + dir string } var _ = Suite(&SrvSuite{}) @@ -42,7 +44,11 @@ func (s *SrvSuite) SetUpSuite(c *C) { } func (s *SrvSuite) SetUpTest(c *C) { - s.bk = membk.New() + s.dir = c.MkDir() + var err error + s.bk, err = boltbk.New(filepath.Join(s.dir, "db")) + c.Assert(err, IsNil) + s.a = auth.NewAuthServer(s.bk, authority.New(), s.scrt) // set up host private key and certificate @@ -61,7 +67,7 @@ func (s *SrvSuite) SetUpTest(c *C) { srv, err := New( utils.NetAddr{Network: "tcp", Addr: "localhost:0"}, []ssh.Signer{signer}, - s.bk, + auth.NewBackendAccessPoint(s.bk), SetShell("/bin/sh"), ) c.Assert(err, IsNil) @@ -248,7 +254,7 @@ func newUpack(user string, a *auth.AuthServer) (*upack, error) { return nil, err } - ucert, err := a.UpsertUserKey(user, backend.AuthorizedKey{ID: user, Value: upub}, 0) + ucert, err := a.UpsertUserKey(user, services.AuthorizedKey{ID: user, Value: upub}, 0) if err != nil { return nil, err } diff --git a/tctl/command/ca.go b/tctl/command/ca.go index cf5087ea95d..e942e402bc0 100644 --- a/tctl/command/ca.go +++ b/tctl/command/ca.go @@ -5,7 +5,7 @@ import ( "time" "github.com/gravitational/teleport/Godeps/_workspace/src/github.com/buger/goterm" - "github.com/gravitational/teleport/backend" + "github.com/gravitational/teleport/services" ) func (cmd *Command) resetHostCA(confirm bool) { @@ -58,7 +58,7 @@ func (cmd *Command) upsertRemoteCert(id, fqdn, certType, path string, ttl time.D cmd.printError(err) return } - cert := backend.RemoteCert{ + cert := services.RemoteCert{ FQDN: fqdn, Type: certType, ID: id, @@ -89,7 +89,7 @@ func (cmd *Command) deleteRemoteCert(id, fqdn, certType string) { cmd.printOK("certificate deleted") } -func remoteCertsView(certs []backend.RemoteCert) string { +func remoteCertsView(certs []services.RemoteCert) string { t := goterm.NewTable(0, 10, 5, ' ', 0) fmt.Fprint(t, "Type\tFQDN\tID\tValue\n") if len(certs) == 0 { diff --git a/tctl/command/cmd_test.go b/tctl/command/cmd_test.go index 5ed1a5a5c71..2543dcbc23d 100644 --- a/tctl/command/cmd_test.go +++ b/tctl/command/cmd_test.go @@ -17,6 +17,7 @@ import ( "github.com/gravitational/teleport/events/boltlog" "github.com/gravitational/teleport/recorder" "github.com/gravitational/teleport/recorder/boltrec" + "github.com/gravitational/teleport/services" "github.com/gravitational/teleport/session" "github.com/gravitational/teleport/utils" @@ -36,12 +37,19 @@ type CmdSuite struct { clt *auth.Client cmd *Command out *bytes.Buffer - bk *boltbk.BoltBackend + bk backend.Backend bl *boltlog.BoltLog scrt *secret.Service rec recorder.Recorder addr utils.NetAddr dir string + + CAS *services.CAService + LockS *services.LockService + PresenceS *services.PresenceService + ProvisioningS *services.ProvisioningService + UserS *services.UserService + WebS *services.WebService } var _ = Suite(&CmdSuite{}) @@ -83,6 +91,13 @@ func (s *CmdSuite) SetUpTest(c *C) { s.out = &bytes.Buffer{} s.cmd = &Command{out: s.out} + + s.CAS = services.NewCAService(s.bk) + s.LockS = services.NewLockService(s.bk) + s.PresenceS = services.NewPresenceService(s.bk) + s.ProvisioningS = services.NewProvisioningService(s.bk) + s.UserS = services.NewUserService(s.bk) + s.WebS = services.NewWebService(s.bk) } func (s *CmdSuite) TearDownTest(c *C) { @@ -108,7 +123,7 @@ func (s *CmdSuite) TestHostCACRUD(c *C) { s.run("host-ca", "reset", "--confirm"), Matches, fmt.Sprintf(".*%v.*", "regenerated")) - hostCA, err := s.bk.GetHostCA() + hostCA, err := s.CAS.GetHostCA() c.Assert(err, IsNil) c.Assert(hostCA, NotNil) @@ -122,7 +137,7 @@ func (s *CmdSuite) TestUserCACRUD(c *C) { s.run("user-ca", "reset", "--confirm"), Matches, fmt.Sprintf(".*%v.*", "regenerated")) - userCA, err := s.bk.GetUserCA() + userCA, err := s.CAS.GetUserCA() c.Assert(err, IsNil) c.Assert(userCA, NotNil) c.Assert(userCA, NotNil) @@ -146,8 +161,8 @@ func (s *CmdSuite) TestUserCRUD(c *C) { out := s.run("user", "upsert-key", "--user", "alex", "--key-id", "key1", "--key", fkey.Name()) c.Assert(out, Matches, fmt.Sprintf(".*%v.*", pub)) - var keys []backend.AuthorizedKey - keys, err = s.bk.GetUserKeys("alex") + var keys []services.AuthorizedKey + keys, err = s.UserS.GetUserKeys("alex") c.Assert(err, IsNil) c.Assert(trim(keys[0].ID), Equals, "key1") c.Assert(trim(string(keys[0].Value)), Equals, trim(out)) @@ -183,8 +198,8 @@ func (s *CmdSuite) TestRemoteCertCRUD(c *C) { out := s.run("remote-ca", "upsert", "--id", "id1", "--type", "user", "--fqdn", "example.com", "--path", fkey.Name()) c.Assert(out, Matches, fmt.Sprintf(".*%v.*", "upserted")) - var remoteCerts []backend.RemoteCert - remoteCerts, err = s.bk.GetRemoteCerts("user", "example.com") + var remoteCerts []services.RemoteCert + remoteCerts, err = s.CAS.GetRemoteCerts("user", "example.com") c.Assert(err, IsNil) c.Assert(trim(string(remoteCerts[0].Value)), Equals, trim(string(pub))) @@ -194,7 +209,7 @@ func (s *CmdSuite) TestRemoteCertCRUD(c *C) { out = s.run("remote-ca", "rm", "--type", "user", "--fqdn", "example.com", "--id", "id1") c.Assert(out, Matches, fmt.Sprintf(".*%v.*", "deleted")) - remoteCerts, err = s.bk.GetRemoteCerts("user", "") + remoteCerts, err = s.CAS.GetRemoteCerts("user", "") c.Assert(len(remoteCerts), Equals, 0) } diff --git a/tctl/command/user.go b/tctl/command/user.go index 3534a961980..ad3db203990 100644 --- a/tctl/command/user.go +++ b/tctl/command/user.go @@ -5,7 +5,7 @@ import ( "time" "github.com/gravitational/teleport/Godeps/_workspace/src/github.com/buger/goterm" - "github.com/gravitational/teleport/backend" + "github.com/gravitational/teleport/services" ) func (cmd *Command) setPass(user, pass string) { @@ -24,7 +24,7 @@ func (cmd *Command) upsertKey(user, keyID, key string, ttl time.Duration) { return } signed, err := cmd.client.UpsertUserKey( - user, backend.AuthorizedKey{ID: keyID, Value: bytes}, ttl) + user, services.AuthorizedKey{ID: keyID, Value: bytes}, ttl) if err != nil { cmd.printError(err) return @@ -72,7 +72,7 @@ func usersView(users []string) string { return t.String() } -func keysView(keys []backend.AuthorizedKey) string { +func keysView(keys []services.AuthorizedKey) string { t := goterm.NewTable(0, 10, 5, ' ', 0) fmt.Fprint(t, "KeyID\tKey\n") if len(keys) == 0 { diff --git a/tun/agent.go b/tun/agent.go index 11e2e09b3b5..80895be8fcf 100644 --- a/tun/agent.go +++ b/tun/agent.go @@ -8,7 +8,7 @@ import ( "time" "github.com/gravitational/teleport/auth" - "github.com/gravitational/teleport/backend" + "github.com/gravitational/teleport/services" "github.com/gravitational/teleport/sshutils" "github.com/gravitational/teleport/utils" @@ -113,7 +113,7 @@ func (a *Agent) checkHostSignature(hostport string, remote net.Addr, key ssh.Pub log.Errorf("error spliting hostport(%v), err: %v", hostport, err) return err } - certs, err := a.clt.GetRemoteCerts(backend.HostCert, hostname) + certs, err := a.clt.GetRemoteCerts(services.HostCert, hostname) if err != nil { log.Errorf("failed to fetch remote certs: %v", err) return err diff --git a/tun/srv.go b/tun/srv.go index 0c2232046b5..09143866e31 100644 --- a/tun/srv.go +++ b/tun/srv.go @@ -8,8 +8,8 @@ import ( "time" "github.com/gravitational/teleport/auth" - "github.com/gravitational/teleport/backend" "github.com/gravitational/teleport/events" + "github.com/gravitational/teleport/services" "github.com/gravitational/teleport/sshutils" "github.com/gravitational/teleport/utils" @@ -273,7 +273,7 @@ func (s *remoteSite) ConnectToServer(server, user string, auth []ssh.AuthMethod) return ssh.NewClient(conn, chans, reqs), nil } -func (s *remoteSite) GetServers() ([]backend.Server, error) { +func (s *remoteSite) GetServers() ([]services.Server, error) { return s.clt.GetServers() }