2015-10-31 18:56:49 +00:00
|
|
|
/*
|
|
|
|
Copyright 2015 Gravitational, Inc.
|
|
|
|
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
you may not use this file except in compliance with the License.
|
|
|
|
You may obtain a copy of the License at
|
|
|
|
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
See the License for the specific language governing permissions and
|
|
|
|
limitations under the License.
|
|
|
|
*/
|
2015-03-02 20:11:23 +00:00
|
|
|
// package auth implements certificate signing authority and access control server
|
|
|
|
// Authority server is composed of several parts:
|
|
|
|
//
|
|
|
|
// * Authority server itself that implements signing and acl logic
|
|
|
|
// * HTTP server wrapper for authority server
|
|
|
|
// * HTTP client wrapper
|
|
|
|
//
|
|
|
|
package auth
|
|
|
|
|
|
|
|
import (
|
2016-02-13 23:36:22 +00:00
|
|
|
"fmt"
|
2016-02-24 01:26:23 +00:00
|
|
|
|
2016-02-13 23:36:22 +00:00
|
|
|
"os"
|
2015-03-02 20:11:23 +00:00
|
|
|
"time"
|
|
|
|
|
2016-02-23 01:12:59 +00:00
|
|
|
"github.com/gravitational/configure/cstrings"
|
2016-02-18 22:55:39 +00:00
|
|
|
"github.com/gravitational/teleport"
|
2015-10-05 14:33:25 +00:00
|
|
|
"github.com/gravitational/teleport/lib/backend/encryptedbk"
|
2015-11-13 01:32:45 +00:00
|
|
|
"github.com/gravitational/teleport/lib/backend/encryptedbk/encryptor"
|
2015-10-05 17:36:55 +00:00
|
|
|
"github.com/gravitational/teleport/lib/services"
|
2016-02-13 23:36:22 +00:00
|
|
|
"github.com/gravitational/teleport/lib/utils"
|
|
|
|
|
|
|
|
log "github.com/Sirupsen/logrus"
|
2016-02-18 22:55:39 +00:00
|
|
|
"github.com/gravitational/trace"
|
2016-02-24 01:26:23 +00:00
|
|
|
"github.com/jonboulle/clockwork"
|
2015-03-02 20:11:23 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// Authority implements minimal key-management facility for generating OpenSSH
|
|
|
|
//compatible public/private key pairs and OpenSSH certificates
|
|
|
|
type Authority interface {
|
2016-02-16 17:36:02 +00:00
|
|
|
// GenerateKeyPair generates new keypair
|
2015-03-19 04:13:56 +00:00
|
|
|
GenerateKeyPair(passphrase string) (privKey []byte, pubKey []byte, err error)
|
2016-02-16 17:36:02 +00:00
|
|
|
|
|
|
|
// GetNewKeyPairFromPool returns new keypair from pre-generated in memory pool
|
2016-01-29 22:44:43 +00:00
|
|
|
GetNewKeyPairFromPool() (privKey []byte, pubKey []byte, err error)
|
2015-03-02 20:11:23 +00:00
|
|
|
|
2015-05-12 00:04:22 +00:00
|
|
|
// GenerateHostCert generates host certificate, it takes pkey as a signing
|
|
|
|
// private key (host certificate authority)
|
2016-03-05 00:27:52 +00:00
|
|
|
GenerateHostCert(pkey, key []byte, hostID, authDomain string, role teleport.Role, ttl time.Duration) ([]byte, error)
|
2015-03-02 20:11:23 +00:00
|
|
|
|
2015-05-12 00:04:22 +00:00
|
|
|
// GenerateHostCert generates user certificate, it takes pkey as a signing
|
|
|
|
// private key (user certificate authority)
|
2016-02-19 02:07:43 +00:00
|
|
|
GenerateUserCert(pkey, key []byte, username string, ttl time.Duration) ([]byte, error)
|
2015-03-02 20:11:23 +00:00
|
|
|
}
|
|
|
|
|
2016-02-24 01:26:23 +00:00
|
|
|
// Session is a web session context, stores temporary key-value pair and session id
|
2015-03-19 04:13:56 +00:00
|
|
|
type Session struct {
|
2016-02-24 01:26:23 +00:00
|
|
|
// ID is a session ID
|
|
|
|
ID string `json:"id"`
|
|
|
|
// User is a user this session belongs to
|
2016-02-25 19:30:59 +00:00
|
|
|
User services.User `json:"user"`
|
2016-02-24 01:26:23 +00:00
|
|
|
// WS is a private keypair used for signing requests
|
|
|
|
WS services.WebSession `json:"web"`
|
|
|
|
}
|
|
|
|
|
|
|
|
// AuthServerOption allows setting options as functional arguments to AuthServer
|
|
|
|
type AuthServerOption func(*AuthServer)
|
|
|
|
|
|
|
|
// AuthClock allows setting clock for auth server (used in tests)
|
|
|
|
func AuthClock(clock clockwork.Clock) AuthServerOption {
|
|
|
|
return func(a *AuthServer) {
|
|
|
|
a.clock = clock
|
|
|
|
}
|
2015-03-19 04:13:56 +00:00
|
|
|
}
|
|
|
|
|
2016-02-24 01:26:23 +00:00
|
|
|
// NewAuthServer returns a new AuthServer instance
|
2016-03-05 00:27:52 +00:00
|
|
|
func NewAuthServer(bk *encryptedbk.ReplicatedBackend, a Authority, domainName string, opts ...AuthServerOption) *AuthServer {
|
2015-08-25 17:54:16 +00:00
|
|
|
as := AuthServer{}
|
|
|
|
|
2016-02-24 01:26:23 +00:00
|
|
|
for _, o := range opts {
|
|
|
|
o(&as)
|
|
|
|
}
|
|
|
|
|
|
|
|
if as.clock == nil {
|
|
|
|
as.clock = clockwork.NewRealClock()
|
|
|
|
}
|
|
|
|
|
2015-08-25 17:54:16 +00:00
|
|
|
as.bk = bk
|
2015-08-27 14:39:33 +00:00
|
|
|
as.Authority = a
|
2015-08-25 17:54:16 +00:00
|
|
|
|
2015-08-27 14:39:33 +00:00
|
|
|
as.CAService = services.NewCAService(as.bk)
|
|
|
|
as.LockService = services.NewLockService(as.bk)
|
|
|
|
as.PresenceService = services.NewPresenceService(as.bk)
|
|
|
|
as.ProvisioningService = services.NewProvisioningService(as.bk)
|
|
|
|
as.WebService = services.NewWebService(as.bk)
|
2015-09-12 01:19:20 +00:00
|
|
|
as.BkKeysService = services.NewBkKeysService(as.bk)
|
2015-08-25 17:54:16 +00:00
|
|
|
|
2016-03-05 00:27:52 +00:00
|
|
|
as.DomainName = domainName
|
2015-08-25 17:54:16 +00:00
|
|
|
return &as
|
2015-03-02 20:11:23 +00:00
|
|
|
}
|
|
|
|
|
2015-05-12 00:04:22 +00:00
|
|
|
// AuthServer implements key signing, generation and ACL functionality
|
|
|
|
// used by teleport
|
2015-03-02 20:11:23 +00:00
|
|
|
type AuthServer struct {
|
2016-02-24 01:26:23 +00:00
|
|
|
clock clockwork.Clock
|
|
|
|
bk *encryptedbk.ReplicatedBackend
|
2015-08-27 14:39:33 +00:00
|
|
|
Authority
|
2016-03-05 00:27:52 +00:00
|
|
|
DomainName string
|
2015-08-25 17:54:16 +00:00
|
|
|
|
2015-08-27 14:39:33 +00:00
|
|
|
*services.CAService
|
|
|
|
*services.LockService
|
|
|
|
*services.PresenceService
|
|
|
|
*services.ProvisioningService
|
|
|
|
*services.WebService
|
2015-09-12 01:19:20 +00:00
|
|
|
*services.BkKeysService
|
2015-03-02 20:11:23 +00:00
|
|
|
}
|
|
|
|
|
2016-02-16 17:36:02 +00:00
|
|
|
// GetLocalDomain returns domain name that identifies this authority server
|
|
|
|
func (a *AuthServer) GetLocalDomain() (string, error) {
|
2016-03-05 00:27:52 +00:00
|
|
|
return a.DomainName, nil
|
2015-03-02 20:11:23 +00:00
|
|
|
}
|
|
|
|
|
2015-05-12 00:04:22 +00:00
|
|
|
// GenerateHostCert generates host certificate, it takes pkey as a signing
|
|
|
|
// private key (host certificate authority)
|
2016-03-05 00:27:52 +00:00
|
|
|
func (s *AuthServer) GenerateHostCert(key []byte, hostID, authDomain string, role teleport.Role, ttl time.Duration) ([]byte, error) {
|
2016-02-16 17:36:02 +00:00
|
|
|
ca, err := s.CAService.GetCertAuthority(services.CertAuthID{
|
|
|
|
Type: services.HostCA,
|
2016-03-05 00:27:52 +00:00
|
|
|
DomainName: s.DomainName,
|
2016-02-16 17:36:02 +00:00
|
|
|
}, true)
|
2015-03-02 20:11:23 +00:00
|
|
|
if err != nil {
|
2016-02-16 17:36:02 +00:00
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
privateKey, err := ca.FirstSigningKey()
|
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
2015-03-02 20:11:23 +00:00
|
|
|
}
|
2016-03-05 00:27:52 +00:00
|
|
|
return s.Authority.GenerateHostCert(privateKey, key, hostID, authDomain, role, ttl)
|
2015-03-02 20:11:23 +00:00
|
|
|
}
|
|
|
|
|
2016-02-16 17:36:02 +00:00
|
|
|
// GenerateUserCert generates user certificate, it takes pkey as a signing
|
2015-05-12 00:04:22 +00:00
|
|
|
// private key (user certificate authority)
|
|
|
|
func (s *AuthServer) GenerateUserCert(
|
2016-02-19 02:07:43 +00:00
|
|
|
key []byte, username string, ttl time.Duration) ([]byte, error) {
|
2015-05-12 00:04:22 +00:00
|
|
|
|
2016-02-16 17:36:02 +00:00
|
|
|
ca, err := s.CAService.GetCertAuthority(services.CertAuthID{
|
|
|
|
Type: services.UserCA,
|
2016-03-05 00:27:52 +00:00
|
|
|
DomainName: s.DomainName,
|
2016-02-16 17:36:02 +00:00
|
|
|
}, true)
|
2015-03-02 20:11:23 +00:00
|
|
|
if err != nil {
|
2016-02-16 17:36:02 +00:00
|
|
|
return nil, trace.Wrap(err)
|
2015-03-02 20:11:23 +00:00
|
|
|
}
|
2016-02-16 17:36:02 +00:00
|
|
|
privateKey, err := ca.FirstSigningKey()
|
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
2016-02-19 02:07:43 +00:00
|
|
|
return s.Authority.GenerateUserCert(privateKey, key, username, ttl)
|
2015-03-19 04:13:56 +00:00
|
|
|
}
|
|
|
|
|
2016-02-24 01:26:23 +00:00
|
|
|
func (s *AuthServer) SignIn(user string, password []byte) (*Session, error) {
|
2015-10-23 20:34:09 +00:00
|
|
|
if err := s.CheckPasswordWOToken(user, password); err != nil {
|
2016-02-24 01:26:23 +00:00
|
|
|
return nil, trace.Wrap(err)
|
2015-03-19 04:13:56 +00:00
|
|
|
}
|
|
|
|
sess, err := s.NewWebSession(user)
|
|
|
|
if err != nil {
|
2016-02-24 01:26:23 +00:00
|
|
|
return nil, trace.Wrap(err)
|
2015-03-19 04:13:56 +00:00
|
|
|
}
|
2015-10-27 23:30:16 +00:00
|
|
|
if err := s.UpsertWebSession(user, sess, WebSessionTTL); err != nil {
|
2016-02-24 01:26:23 +00:00
|
|
|
return nil, trace.Wrap(err)
|
2015-03-19 04:13:56 +00:00
|
|
|
}
|
2016-02-24 01:26:23 +00:00
|
|
|
sess.WS.Priv = nil
|
|
|
|
return sess, nil
|
2015-03-19 04:13:56 +00:00
|
|
|
}
|
|
|
|
|
2016-02-26 22:57:51 +00:00
|
|
|
// CreateWebSession creates a new web session for a user based on a valid previous sessionID,
|
|
|
|
// method is used to renew the web session for a user
|
|
|
|
func (s *AuthServer) CreateWebSession(user string, prevSessionID string) (*Session, error) {
|
|
|
|
_, err := s.GetWebSession(user, prevSessionID)
|
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
sess, err := s.NewWebSession(user)
|
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
if err := s.UpsertWebSession(user, sess, WebSessionTTL); err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
sess.WS.Priv = nil
|
|
|
|
return sess, nil
|
|
|
|
}
|
|
|
|
|
2016-02-19 02:07:43 +00:00
|
|
|
func (s *AuthServer) GenerateToken(nodeName string, role teleport.Role, ttl time.Duration) (string, error) {
|
2016-02-23 01:12:59 +00:00
|
|
|
if !cstrings.IsValidDomainName(nodeName) {
|
2016-02-18 22:55:39 +00:00
|
|
|
return "", trace.Wrap(teleport.BadParameter("nodeName",
|
|
|
|
fmt.Sprintf("'%v' is not a valid dns name", nodeName)))
|
|
|
|
}
|
2016-02-19 02:07:43 +00:00
|
|
|
if err := role.Check(); err != nil {
|
|
|
|
return "", trace.Wrap(err)
|
|
|
|
}
|
2016-02-26 22:57:51 +00:00
|
|
|
token, err := utils.CryptoRandomHex(TokenLenBytes)
|
2016-02-18 02:32:11 +00:00
|
|
|
if err != nil {
|
|
|
|
return "", trace.Wrap(err)
|
2015-05-07 03:10:44 +00:00
|
|
|
}
|
2016-02-19 02:07:43 +00:00
|
|
|
outputToken, err := services.JoinTokenRole(token, string(role))
|
2016-01-26 00:16:58 +00:00
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
2016-02-19 02:07:43 +00:00
|
|
|
if err := s.ProvisioningService.UpsertToken(token, nodeName, string(role), ttl); err != nil {
|
2015-05-07 03:10:44 +00:00
|
|
|
return "", err
|
|
|
|
}
|
2016-01-26 00:16:58 +00:00
|
|
|
return outputToken, nil
|
2015-05-07 03:10:44 +00:00
|
|
|
}
|
|
|
|
|
2015-11-20 21:15:48 +00:00
|
|
|
func (s *AuthServer) ValidateToken(token, domainName string) (role string, e error) {
|
2016-01-26 00:16:58 +00:00
|
|
|
token, _, err := services.SplitTokenRole(token)
|
|
|
|
if err != nil {
|
|
|
|
return "", trace.Wrap(err)
|
|
|
|
}
|
2016-02-13 20:03:01 +00:00
|
|
|
tok, err := s.ProvisioningService.GetToken(token)
|
2015-05-07 03:10:44 +00:00
|
|
|
if err != nil {
|
2015-11-16 05:21:34 +00:00
|
|
|
return "", trace.Wrap(err)
|
2015-11-13 01:32:45 +00:00
|
|
|
}
|
2015-11-20 21:15:48 +00:00
|
|
|
if tok.DomainName != domainName {
|
|
|
|
return "", trace.Errorf("domainName does not match")
|
2015-11-13 01:32:45 +00:00
|
|
|
}
|
|
|
|
return tok.Role, nil
|
|
|
|
}
|
|
|
|
|
2016-02-19 02:07:43 +00:00
|
|
|
func (s *AuthServer) RegisterUsingToken(outputToken, nodename string, role teleport.Role) (keys PackedKeys, e error) {
|
2016-02-11 20:23:37 +00:00
|
|
|
log.Infof("[AUTH] Node `%v` is trying to join", nodename)
|
2016-02-19 02:07:43 +00:00
|
|
|
if err := role.Check(); err != nil {
|
|
|
|
return PackedKeys{}, trace.Wrap(err)
|
|
|
|
}
|
2016-01-26 00:16:58 +00:00
|
|
|
token, _, err := services.SplitTokenRole(outputToken)
|
|
|
|
if err != nil {
|
|
|
|
return PackedKeys{}, trace.Wrap(err)
|
|
|
|
}
|
2016-02-11 20:23:37 +00:00
|
|
|
tok, err := s.ProvisioningService.GetToken(token)
|
2015-11-13 01:32:45 +00:00
|
|
|
if err != nil {
|
2016-02-11 20:23:37 +00:00
|
|
|
log.Warningf("[AUTH] Node `%v` cannot join: token error. %v", nodename, err)
|
2015-11-16 05:21:34 +00:00
|
|
|
return PackedKeys{}, trace.Wrap(err)
|
2015-11-13 01:32:45 +00:00
|
|
|
}
|
2016-02-11 20:23:37 +00:00
|
|
|
if tok.DomainName != nodename {
|
2016-02-19 02:07:43 +00:00
|
|
|
return PackedKeys{}, trace.Wrap(
|
|
|
|
teleport.BadParameter("domainName", "domainName does not match"))
|
2015-11-13 01:32:45 +00:00
|
|
|
}
|
|
|
|
|
2016-02-19 02:07:43 +00:00
|
|
|
if tok.Role != string(role) {
|
|
|
|
return PackedKeys{}, trace.Wrap(
|
|
|
|
teleport.BadParameter("token.Role", "role does not match"))
|
2015-11-13 01:32:45 +00:00
|
|
|
}
|
|
|
|
k, pub, err := s.GenerateKeyPair("")
|
|
|
|
if err != nil {
|
|
|
|
return PackedKeys{}, trace.Wrap(err)
|
|
|
|
}
|
2016-02-19 02:07:43 +00:00
|
|
|
// we always append authority's domain to resulting node name,
|
|
|
|
// that's how we make sure that nodes are uniquely identified/found
|
|
|
|
// in cases when we have multiple environments/organizations
|
2016-03-05 00:27:52 +00:00
|
|
|
fqdn := fmt.Sprintf("%s.%s", nodename, s.DomainName)
|
|
|
|
c, err := s.GenerateHostCert(pub, fqdn, s.DomainName, role, 0)
|
2015-11-13 01:32:45 +00:00
|
|
|
if err != nil {
|
2016-02-11 20:23:37 +00:00
|
|
|
log.Warningf("[AUTH] Node `%v` cannot join: cert generation error. %v", nodename, err)
|
2015-11-13 01:32:45 +00:00
|
|
|
return PackedKeys{}, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
keys = PackedKeys{
|
|
|
|
Key: k,
|
|
|
|
Cert: c,
|
|
|
|
}
|
|
|
|
|
2016-01-26 00:16:58 +00:00
|
|
|
if err := s.DeleteToken(outputToken); err != nil {
|
2015-11-13 01:32:45 +00:00
|
|
|
return PackedKeys{}, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
|
2016-02-13 23:36:22 +00:00
|
|
|
utils.Consolef(os.Stdout, "[AUTH] Node `%v` joined the cluster", nodename)
|
2015-11-13 01:32:45 +00:00
|
|
|
return keys, nil
|
|
|
|
}
|
|
|
|
|
2016-01-26 00:16:58 +00:00
|
|
|
func (s *AuthServer) RegisterNewAuthServer(domainName, outputToken string,
|
2015-11-13 01:32:45 +00:00
|
|
|
publicSealKey encryptor.Key) (masterKey encryptor.Key, e error) {
|
2016-01-26 00:16:58 +00:00
|
|
|
|
|
|
|
token, _, err := services.SplitTokenRole(outputToken)
|
|
|
|
if err != nil {
|
|
|
|
return encryptor.Key{}, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
|
2016-02-18 02:32:11 +00:00
|
|
|
tok, err := s.ProvisioningService.GetToken(token)
|
2015-11-13 01:32:45 +00:00
|
|
|
if err != nil {
|
2015-11-16 05:21:34 +00:00
|
|
|
return encryptor.Key{}, trace.Wrap(err)
|
2015-05-07 03:10:44 +00:00
|
|
|
}
|
2015-11-20 21:15:48 +00:00
|
|
|
if tok.DomainName != domainName {
|
2016-02-19 02:07:43 +00:00
|
|
|
return encryptor.Key{}, trace.Wrap(
|
|
|
|
teleport.AccessDenied("domainName does not match"))
|
2015-11-13 01:32:45 +00:00
|
|
|
}
|
|
|
|
|
2016-02-19 02:07:43 +00:00
|
|
|
if tok.Role != string(teleport.RoleAuth) {
|
|
|
|
return encryptor.Key{}, trace.Wrap(
|
|
|
|
teleport.AccessDenied("role does not match"))
|
2015-11-13 01:32:45 +00:00
|
|
|
}
|
|
|
|
|
2016-01-26 00:16:58 +00:00
|
|
|
if err := s.DeleteToken(outputToken); err != nil {
|
2015-11-13 01:32:45 +00:00
|
|
|
return encryptor.Key{}, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := s.BkKeysService.AddSealKey(publicSealKey); err != nil {
|
|
|
|
return encryptor.Key{}, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
localKey, err := s.BkKeysService.GetSignKey()
|
|
|
|
if err != nil {
|
|
|
|
return encryptor.Key{}, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return localKey.Public(), nil
|
2015-05-07 03:10:44 +00:00
|
|
|
}
|
|
|
|
|
2016-01-26 00:16:58 +00:00
|
|
|
func (s *AuthServer) DeleteToken(outputToken string) error {
|
|
|
|
token, _, err := services.SplitTokenRole(outputToken)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2016-02-13 20:03:01 +00:00
|
|
|
return s.ProvisioningService.DeleteToken(token)
|
2015-05-07 03:10:44 +00:00
|
|
|
}
|
|
|
|
|
2016-02-25 19:30:59 +00:00
|
|
|
func (s *AuthServer) NewWebSession(userName string) (*Session, error) {
|
2016-02-26 22:57:51 +00:00
|
|
|
token, err := utils.CryptoRandomHex(WebSessionTokenLenBytes)
|
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
bearerToken, err := utils.CryptoRandomHex(WebSessionTokenLenBytes)
|
2015-03-19 04:13:56 +00:00
|
|
|
if err != nil {
|
2016-02-18 02:32:11 +00:00
|
|
|
return nil, trace.Wrap(err)
|
2015-03-19 04:13:56 +00:00
|
|
|
}
|
2016-01-29 22:44:43 +00:00
|
|
|
priv, pub, err := s.GetNewKeyPairFromPool()
|
2015-03-19 04:13:56 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2016-02-16 17:36:02 +00:00
|
|
|
ca, err := s.CAService.GetCertAuthority(services.CertAuthID{
|
|
|
|
Type: services.UserCA,
|
2016-03-05 00:27:52 +00:00
|
|
|
DomainName: s.DomainName,
|
2016-02-16 17:36:02 +00:00
|
|
|
}, true)
|
2015-03-19 04:13:56 +00:00
|
|
|
if err != nil {
|
2016-02-16 17:36:02 +00:00
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
privateKey, err := ca.FirstSigningKey()
|
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
2015-03-19 04:13:56 +00:00
|
|
|
}
|
2016-02-25 19:30:59 +00:00
|
|
|
cert, err := s.Authority.GenerateUserCert(privateKey, pub, userName, WebSessionTTL)
|
2015-03-19 04:13:56 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2016-02-25 19:30:59 +00:00
|
|
|
user, err := s.GetUser(userName)
|
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
2015-03-19 04:13:56 +00:00
|
|
|
sess := &Session{
|
2016-02-24 01:26:23 +00:00
|
|
|
ID: token,
|
2016-02-25 19:30:59 +00:00
|
|
|
User: *user,
|
2016-02-26 22:57:51 +00:00
|
|
|
WS: services.WebSession{
|
|
|
|
Priv: priv,
|
|
|
|
Pub: cert,
|
|
|
|
Expires: s.clock.Now().UTC().Add(WebSessionTTL),
|
|
|
|
BearerToken: bearerToken,
|
|
|
|
},
|
2015-03-19 04:13:56 +00:00
|
|
|
}
|
|
|
|
return sess, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *AuthServer) UpsertWebSession(user string, sess *Session, ttl time.Duration) error {
|
2016-02-18 02:32:11 +00:00
|
|
|
return s.WebService.UpsertWebSession(user, sess.ID, sess.WS, ttl)
|
2015-03-19 04:13:56 +00:00
|
|
|
}
|
|
|
|
|
2016-02-25 19:30:59 +00:00
|
|
|
func (s *AuthServer) GetWebSession(userName string, id string) (*Session, error) {
|
|
|
|
ws, err := s.WebService.GetWebSession(userName, id)
|
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
user, err := s.GetUser(userName)
|
2015-03-19 04:13:56 +00:00
|
|
|
if err != nil {
|
2016-02-18 02:32:11 +00:00
|
|
|
return nil, trace.Wrap(err)
|
2015-03-19 04:13:56 +00:00
|
|
|
}
|
|
|
|
return &Session{
|
2016-02-24 01:26:23 +00:00
|
|
|
ID: id,
|
2016-02-25 19:30:59 +00:00
|
|
|
User: *user,
|
2016-02-24 01:26:23 +00:00
|
|
|
WS: *ws,
|
2015-03-19 04:13:56 +00:00
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
2016-02-25 19:30:59 +00:00
|
|
|
func (s *AuthServer) GetWebSessionInfo(userName string, id string) (*Session, error) {
|
|
|
|
sess, err := s.WebService.GetWebSession(userName, id)
|
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
user, err := s.GetUser(userName)
|
2016-02-21 22:39:32 +00:00
|
|
|
if err != nil {
|
2016-02-24 01:26:23 +00:00
|
|
|
return nil, trace.Wrap(err)
|
2016-02-21 22:39:32 +00:00
|
|
|
}
|
2016-02-24 01:26:23 +00:00
|
|
|
sess.Priv = nil
|
|
|
|
return &Session{
|
|
|
|
ID: id,
|
2016-02-25 19:30:59 +00:00
|
|
|
User: *user,
|
2016-02-24 01:26:23 +00:00
|
|
|
WS: *sess,
|
|
|
|
}, nil
|
2016-02-21 22:39:32 +00:00
|
|
|
}
|
|
|
|
|
2016-02-18 02:32:11 +00:00
|
|
|
func (s *AuthServer) DeleteWebSession(user string, id string) error {
|
|
|
|
return trace.Wrap(s.WebService.DeleteWebSession(user, id))
|
2015-03-19 04:13:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
const (
|
2016-02-26 22:57:51 +00:00
|
|
|
// WebSessionTTL specifies standard web session time to live
|
|
|
|
WebSessionTTL = 10 * time.Minute
|
|
|
|
// TokenLenBytes is len in bytes of the invite token
|
|
|
|
TokenLenBytes = 16
|
|
|
|
// WebSessionTokenLenBytes specifies len in bytes of the
|
|
|
|
// web session random token
|
2016-02-18 02:32:11 +00:00
|
|
|
WebSessionTokenLenBytes = 32
|
2015-03-19 04:13:56 +00:00
|
|
|
)
|