mirror of
https://github.com/gravitational/teleport
synced 2024-10-22 10:13:21 +00:00
1208 lines
38 KiB
Go
1208 lines
38 KiB
Go
/*
|
|
Copyright 2015 Gravitational, Inc.
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
*/
|
|
|
|
package auth
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"io/ioutil"
|
|
"net"
|
|
"net/http"
|
|
"net/url"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/Sirupsen/logrus"
|
|
"github.com/gravitational/roundtrip"
|
|
|
|
"github.com/gravitational/teleport"
|
|
"github.com/gravitational/teleport/lib/events"
|
|
"github.com/gravitational/teleport/lib/httplib"
|
|
"github.com/gravitational/teleport/lib/services"
|
|
"github.com/gravitational/teleport/lib/session"
|
|
"github.com/gravitational/trace"
|
|
|
|
"github.com/tstranex/u2f"
|
|
)
|
|
|
|
// CurrentVersion is a current API version
|
|
const CurrentVersion = "v1"
|
|
|
|
type Dialer func(network, addr string) (net.Conn, error)
|
|
|
|
// Client is HTTP Auth API client. It works by connecting to auth servers
|
|
// via HTTP.
|
|
//
|
|
// When Teleport servers connect to auth API, they usually establish an SSH
|
|
// tunnel first, and then do HTTP-over-SSH. This client is wrapped by auth.TunClient
|
|
// in lib/auth/tun.go
|
|
type Client struct {
|
|
roundtrip.Client
|
|
transport *http.Transport
|
|
}
|
|
|
|
// NewAuthClient returns a new instance of the client which talks to
|
|
// an Auth server API (aka "site API") via HTTP-over-SSH
|
|
func NewClient(addr string, dialer Dialer, params ...roundtrip.ClientParam) (*Client, error) {
|
|
if dialer == nil {
|
|
dialer = net.Dial
|
|
}
|
|
transport := &http.Transport{Dial: dialer}
|
|
params = append(params, roundtrip.HTTPClient(&http.Client{
|
|
Transport: transport,
|
|
}))
|
|
|
|
c, err := roundtrip.NewClient(addr, CurrentVersion, params...)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &Client{
|
|
Client: *c,
|
|
transport: transport,
|
|
}, nil
|
|
}
|
|
|
|
func (c *Client) GetTransport() *http.Transport {
|
|
return c.transport
|
|
}
|
|
|
|
// PostJSON is a generic method that issues http POST request to the server
|
|
func (c *Client) PostJSON(
|
|
endpoint string, val interface{}) (*roundtrip.Response, error) {
|
|
return httplib.ConvertResponse(c.Client.PostJSON(endpoint, val))
|
|
}
|
|
|
|
// PutJSON is a generic method that issues http PUT request to the server
|
|
func (c *Client) PutJSON(
|
|
endpoint string, val interface{}) (*roundtrip.Response, error) {
|
|
return httplib.ConvertResponse(c.Client.PutJSON(endpoint, val))
|
|
}
|
|
|
|
// PostForm is a generic method that issues http POST request to the server
|
|
func (c *Client) PostForm(
|
|
endpoint string,
|
|
vals url.Values,
|
|
files ...roundtrip.File) (*roundtrip.Response, error) {
|
|
|
|
return httplib.ConvertResponse(c.Client.PostForm(endpoint, vals, files...))
|
|
}
|
|
|
|
// Get issues http GET request to the server
|
|
func (c *Client) Get(u string, params url.Values) (*roundtrip.Response, error) {
|
|
return httplib.ConvertResponse(c.Client.Get(u, params))
|
|
}
|
|
|
|
// Delete issues http Delete Request to the server
|
|
func (c *Client) Delete(u string) (*roundtrip.Response, error) {
|
|
return httplib.ConvertResponse(c.Client.Delete(u))
|
|
}
|
|
|
|
// GetSessions returns a list of active sessions in the cluster
|
|
// as reported by auth server
|
|
func (c *Client) GetSessions(namespace string) ([]session.Session, error) {
|
|
if namespace == "" {
|
|
return nil, trace.BadParameter("missing namespace parameter")
|
|
}
|
|
out, err := c.Get(c.Endpoint("namespaces", namespace, "sessions"), url.Values{})
|
|
if err != nil {
|
|
return nil, trace.Wrap(err)
|
|
}
|
|
var sessions []session.Session
|
|
if err := json.Unmarshal(out.Bytes(), &sessions); err != nil {
|
|
return nil, err
|
|
}
|
|
return sessions, nil
|
|
}
|
|
|
|
// GetSession returns a session by ID
|
|
func (c *Client) GetSession(namespace string, id session.ID) (*session.Session, error) {
|
|
if namespace == "" {
|
|
return nil, trace.BadParameter("missing parameter namespace")
|
|
}
|
|
// saving extra round-trip
|
|
if err := id.Check(); err != nil {
|
|
return nil, trace.Wrap(err)
|
|
}
|
|
out, err := c.Get(c.Endpoint("namespaces", namespace, "sessions", string(id)), url.Values{})
|
|
if err != nil {
|
|
return nil, trace.Wrap(err)
|
|
}
|
|
var sess *session.Session
|
|
if err := json.Unmarshal(out.Bytes(), &sess); err != nil {
|
|
return nil, trace.Wrap(err)
|
|
}
|
|
return sess, nil
|
|
}
|
|
|
|
// DeleteSession deletes a session by ID
|
|
func (c *Client) DeleteSession(namespace, id string) error {
|
|
if namespace == "" {
|
|
return trace.BadParameter("missing namespace parameter")
|
|
}
|
|
_, err := c.Delete(c.Endpoint("namespaces", namespace, "sessions", id))
|
|
return trace.Wrap(err)
|
|
}
|
|
|
|
// CreateSession creates new session
|
|
func (c *Client) CreateSession(sess session.Session) error {
|
|
if sess.Namespace == "" {
|
|
return trace.BadParameter("missing parameter namespace")
|
|
}
|
|
_, err := c.PostJSON(c.Endpoint("namespaces", sess.Namespace, "sessions"), createSessionReq{Session: sess})
|
|
return trace.Wrap(err)
|
|
}
|
|
|
|
// UpdateSession updates existing session
|
|
func (c *Client) UpdateSession(req session.UpdateRequest) error {
|
|
if err := req.Check(); err != nil {
|
|
return trace.Wrap(err)
|
|
}
|
|
_, err := c.PutJSON(c.Endpoint("namespaces", req.Namespace, "sessions", string(req.ID)), updateSessionReq{Update: req})
|
|
return trace.Wrap(err)
|
|
}
|
|
|
|
// GetDomainName returns local auth domain of the current auth server
|
|
func (c *Client) GetDomainName() (string, error) {
|
|
out, err := c.Get(c.Endpoint("domain"), url.Values{})
|
|
if err != nil {
|
|
return "", trace.Wrap(err)
|
|
}
|
|
var domain string
|
|
if err := json.Unmarshal(out.Bytes(), &domain); err != nil {
|
|
return "", trace.Wrap(err)
|
|
}
|
|
return domain, nil
|
|
}
|
|
|
|
func (c *Client) Close() error {
|
|
return nil
|
|
}
|
|
|
|
// UpsertCertAuthority updates or inserts new cert authority
|
|
func (c *Client) UpsertCertAuthority(ca services.CertAuthority, ttl time.Duration) error {
|
|
if err := ca.Check(); err != nil {
|
|
return trace.Wrap(err)
|
|
}
|
|
_, err := c.PostJSON(c.Endpoint("authorities", string(ca.Type)),
|
|
upsertCertAuthorityReq{CA: ca, TTL: ttl})
|
|
return trace.Wrap(err)
|
|
}
|
|
|
|
// GetCertAuthorities returns a list of certificate authorities
|
|
func (c *Client) GetCertAuthorities(caType services.CertAuthType, loadKeys bool) ([]*services.CertAuthority, error) {
|
|
if err := caType.Check(); err != nil {
|
|
return nil, trace.Wrap(err)
|
|
}
|
|
out, err := c.Get(c.Endpoint("authorities", string(caType)), url.Values{
|
|
"load_keys": []string{fmt.Sprintf("%t", loadKeys)},
|
|
})
|
|
if err != nil {
|
|
return nil, trace.Wrap(err)
|
|
}
|
|
var re []*services.CertAuthority
|
|
if err := json.Unmarshal(out.Bytes(), &re); err != nil {
|
|
return nil, err
|
|
}
|
|
return re, nil
|
|
}
|
|
|
|
// GetCertAuthority returns certificate authority by given id. Parameter loadSigningKeys
|
|
// controls if signing keys are loaded
|
|
func (c *Client) GetCertAuthority(id services.CertAuthID, loadSigningKeys bool) (*services.CertAuthority, error) {
|
|
if err := id.Check(); err != nil {
|
|
return nil, trace.Wrap(err)
|
|
}
|
|
out, err := c.Get(c.Endpoint("authorities", string(id.Type), id.DomainName), url.Values{
|
|
"load_keys": []string{fmt.Sprintf("%t", loadSigningKeys)},
|
|
})
|
|
if err != nil {
|
|
return nil, trace.Wrap(err)
|
|
}
|
|
var re services.CertAuthority
|
|
if err := json.Unmarshal(out.Bytes(), &re); err != nil {
|
|
return nil, err
|
|
}
|
|
return &re, nil
|
|
}
|
|
|
|
// DeleteCertAuthority deletes cert authority by ID
|
|
func (c *Client) DeleteCertAuthority(id services.CertAuthID) error {
|
|
if err := id.Check(); err != nil {
|
|
return trace.Wrap(err)
|
|
}
|
|
_, err := c.Delete(c.Endpoint("authorities", string(id.Type), id.DomainName))
|
|
return trace.Wrap(err)
|
|
}
|
|
|
|
// GenerateToken creates a special provisioning token for a new SSH server
|
|
// that is valid for ttl period seconds.
|
|
//
|
|
// This token is used by SSH server to authenticate with Auth server
|
|
// and get signed certificate and private key from the auth server.
|
|
//
|
|
// The token can be used only once.
|
|
func (c *Client) GenerateToken(roles teleport.Roles, ttl time.Duration) (string, error) {
|
|
out, err := c.PostJSON(c.Endpoint("tokens"), generateTokenReq{
|
|
Roles: roles,
|
|
TTL: ttl,
|
|
})
|
|
if err != nil {
|
|
return "", trace.Wrap(err)
|
|
}
|
|
var token string
|
|
if err := json.Unmarshal(out.Bytes(), &token); err != nil {
|
|
return "", trace.Wrap(err)
|
|
}
|
|
return token, nil
|
|
}
|
|
|
|
// RegisterUsingToken calls the auth service API to register a new node via registration token
|
|
// which has been previously issued via GenerateToken
|
|
func (c *Client) RegisterUsingToken(token, hostID string, role teleport.Role) (*PackedKeys, error) {
|
|
out, err := c.PostJSON(c.Endpoint("tokens", "register"),
|
|
registerUsingTokenReq{
|
|
HostID: hostID,
|
|
Token: token,
|
|
Role: role,
|
|
})
|
|
if err != nil {
|
|
return nil, trace.Wrap(err)
|
|
}
|
|
var keys PackedKeys
|
|
if err := json.Unmarshal(out.Bytes(), &keys); err != nil {
|
|
return nil, trace.Wrap(err)
|
|
}
|
|
return &keys, nil
|
|
}
|
|
|
|
// GetTokens returns a list of active invitation tokens for nodes and users
|
|
func (c *Client) GetTokens() (tokens []services.ProvisionToken, err error) {
|
|
out, err := c.Get(c.Endpoint("tokens"), url.Values{})
|
|
if err != nil {
|
|
return nil, trace.Wrap(err)
|
|
}
|
|
if err := json.Unmarshal(out.Bytes(), &tokens); err != nil {
|
|
return nil, trace.Wrap(err)
|
|
}
|
|
return tokens, nil
|
|
}
|
|
|
|
// GetToken returns provisioning token
|
|
func (c *Client) GetToken(token string) (*services.ProvisionToken, error) {
|
|
out, err := c.Get(c.Endpoint("tokens", token), url.Values{})
|
|
if err != nil {
|
|
return nil, trace.Wrap(err)
|
|
}
|
|
var tok services.ProvisionToken
|
|
if err := json.Unmarshal(out.Bytes(), &tok); err != nil {
|
|
return nil, trace.Wrap(err)
|
|
}
|
|
return &tok, nil
|
|
}
|
|
|
|
// DeleteToken deletes a given provisioning token on the auth server (CA). It
|
|
// could be a user token or a machine token
|
|
func (c *Client) DeleteToken(token string) error {
|
|
_, err := c.Delete(c.Endpoint("tokens", token))
|
|
return trace.Wrap(err)
|
|
}
|
|
|
|
// RegisterNewAuthServer is used to register new auth server with token
|
|
func (c *Client) RegisterNewAuthServer(token string) error {
|
|
_, err := c.PostJSON(c.Endpoint("tokens", "register", "auth"), registerNewAuthServerReq{
|
|
Token: token,
|
|
})
|
|
return trace.Wrap(err)
|
|
}
|
|
|
|
// UpsertNode is used by SSH servers to reprt their presense
|
|
// to the auth servers in form of hearbeat expiring after ttl period.
|
|
func (c *Client) UpsertNode(s services.Server, ttl time.Duration) error {
|
|
if s.Namespace == "" {
|
|
return trace.BadParameter("missing node namespace")
|
|
}
|
|
args := upsertServerReq{
|
|
Server: s,
|
|
TTL: ttl,
|
|
}
|
|
_, err := c.PostJSON(c.Endpoint("namespaces", s.Namespace, "nodes"), args)
|
|
return trace.Wrap(err)
|
|
}
|
|
|
|
// GetNodes returns the list of servers registered in the cluster.
|
|
func (c *Client) GetNodes(namespace string) ([]services.Server, error) {
|
|
if namespace == "" {
|
|
return nil, trace.BadParameter("missing parameter namespace")
|
|
}
|
|
out, err := c.Get(c.Endpoint("namespaces", namespace, "nodes"), url.Values{})
|
|
if err != nil {
|
|
return nil, trace.Wrap(err)
|
|
}
|
|
var re []services.Server
|
|
if err := json.Unmarshal(out.Bytes(), &re); err != nil {
|
|
return nil, trace.Wrap(err)
|
|
}
|
|
return re, nil
|
|
}
|
|
|
|
// UpsertReverseTunnel is used by admins to create a new reverse tunnel
|
|
// to the remote proxy to bypass firewall restrictions
|
|
func (c *Client) UpsertReverseTunnel(tunnel services.ReverseTunnel, ttl time.Duration) error {
|
|
args := upsertReverseTunnelReq{
|
|
ReverseTunnel: tunnel,
|
|
TTL: ttl,
|
|
}
|
|
_, err := c.PostJSON(c.Endpoint("reversetunnels"), args)
|
|
return trace.Wrap(err)
|
|
}
|
|
|
|
// GetReverseTunnels returns the list of created reverse tunnels
|
|
func (c *Client) GetReverseTunnels() ([]services.ReverseTunnel, error) {
|
|
out, err := c.Get(c.Endpoint("reversetunnels"), url.Values{})
|
|
if err != nil {
|
|
return nil, trace.Wrap(err)
|
|
}
|
|
var tunnels []services.ReverseTunnel
|
|
if err := json.Unmarshal(out.Bytes(), &tunnels); err != nil {
|
|
return nil, trace.Wrap(err)
|
|
}
|
|
return tunnels, nil
|
|
}
|
|
|
|
// DeleteReverseTunnel deletes reverse tunnel by domain name
|
|
func (c *Client) DeleteReverseTunnel(domainName string) error {
|
|
// this is to avoid confusing error in case if domain emtpy for example
|
|
// HTTP route will fail producing generic not found error
|
|
// instead we catch the error here
|
|
if strings.TrimSpace(domainName) == "" {
|
|
return trace.BadParameter("empty domain name")
|
|
}
|
|
_, err := c.Delete(c.Endpoint("reversetunnels", domainName))
|
|
return trace.Wrap(err)
|
|
}
|
|
|
|
// UpsertAuthServer is used by auth servers to report their presense
|
|
// to other auth servers in form of hearbeat expiring after ttl period.
|
|
func (c *Client) UpsertAuthServer(s services.Server, ttl time.Duration) error {
|
|
args := upsertServerReq{
|
|
Server: s,
|
|
TTL: ttl,
|
|
}
|
|
_, err := c.PostJSON(c.Endpoint("authservers"), args)
|
|
return trace.Wrap(err)
|
|
}
|
|
|
|
// GetAuthServers returns the list of auth servers registered in the cluster.
|
|
func (c *Client) GetAuthServers() ([]services.Server, error) {
|
|
out, err := c.Get(c.Endpoint("authservers"), url.Values{})
|
|
if err != nil {
|
|
return nil, trace.Wrap(err)
|
|
}
|
|
var re []services.Server
|
|
if err := json.Unmarshal(out.Bytes(), &re); err != nil {
|
|
return nil, trace.Wrap(err)
|
|
}
|
|
return re, nil
|
|
}
|
|
|
|
// UpsertProxy is used by proxies to report their presense
|
|
// to other auth servers in form of hearbeat expiring after ttl period.
|
|
func (c *Client) UpsertProxy(s services.Server, ttl time.Duration) error {
|
|
args := upsertServerReq{
|
|
Server: s,
|
|
TTL: ttl,
|
|
}
|
|
_, err := c.PostJSON(c.Endpoint("proxies"), args)
|
|
return trace.Wrap(err)
|
|
}
|
|
|
|
// GetProxies returns the list of auth servers registered in the cluster.
|
|
func (c *Client) GetProxies() ([]services.Server, error) {
|
|
out, err := c.Get(c.Endpoint("proxies"), url.Values{})
|
|
if err != nil {
|
|
return nil, trace.Wrap(err)
|
|
}
|
|
var re []services.Server
|
|
if err := json.Unmarshal(out.Bytes(), &re); err != nil {
|
|
return nil, trace.Wrap(err)
|
|
}
|
|
return re, nil
|
|
}
|
|
|
|
// GetU2FAppID returns U2F settings, like App ID and Facets
|
|
func (c *Client) GetU2FAppID() (string, error) {
|
|
out, err := c.Get(c.Endpoint("u2f", "appID"), url.Values{})
|
|
if err != nil {
|
|
return "", trace.Wrap(err)
|
|
}
|
|
var appid string
|
|
if err := json.Unmarshal(out.Bytes(), &appid); err != nil {
|
|
return "", trace.Wrap(err)
|
|
}
|
|
return appid, nil
|
|
}
|
|
|
|
// UpsertPassword updates web access password for the user
|
|
func (c *Client) UpsertPassword(user string,
|
|
password []byte) (hotpURL string, hotpQR []byte, err error) {
|
|
out, err := c.PostJSON(
|
|
c.Endpoint("users", user, "web", "password"),
|
|
upsertPasswordReq{
|
|
Password: string(password),
|
|
})
|
|
if err != nil {
|
|
return "", nil, trace.Wrap(err)
|
|
}
|
|
var re *upsertPasswordResponse
|
|
if err := json.Unmarshal(out.Bytes(), &re); err != nil {
|
|
return "", nil, err
|
|
}
|
|
return re.HotpURL, re.HotpQR, err
|
|
}
|
|
|
|
// UpsertUser user updates or inserts user entry
|
|
func (c *Client) UpsertUser(user services.User) error {
|
|
_, err := c.PostJSON(c.Endpoint("users"), upsertUserReq{User: user})
|
|
return trace.Wrap(err)
|
|
}
|
|
|
|
// CheckPassword checks if the suplied web access password is valid.
|
|
func (c *Client) CheckPassword(user string, password []byte, hotpToken string) error {
|
|
_, err := c.PostJSON(
|
|
c.Endpoint("users", user, "web", "password", "check"),
|
|
checkPasswordReq{
|
|
Password: string(password),
|
|
HOTPToken: hotpToken,
|
|
})
|
|
return trace.Wrap(err)
|
|
}
|
|
|
|
// SignIn checks if the web access password is valid, and if it is valid
|
|
// returns a secure web session id.
|
|
func (c *Client) SignIn(user string, password []byte) (*Session, error) {
|
|
out, err := c.PostJSON(
|
|
c.Endpoint("users", user, "web", "signin"),
|
|
signInReq{
|
|
Password: string(password),
|
|
},
|
|
)
|
|
if err != nil {
|
|
return nil, trace.Wrap(err)
|
|
}
|
|
var sess *Session
|
|
if err := json.Unmarshal(out.Bytes(), &sess); err != nil {
|
|
return nil, err
|
|
}
|
|
return sess, nil
|
|
}
|
|
|
|
// PreAuthenticatedSignIn is for 2-way authentication methods like U2F where the password is
|
|
// already checked before issueing the second factor challenge
|
|
func (c *Client) PreAuthenticatedSignIn(user string) (*Session, error) {
|
|
out, err := c.Get(
|
|
c.Endpoint("users", user, "web", "signin", "preauth"),
|
|
url.Values{},
|
|
)
|
|
if err != nil {
|
|
return nil, trace.Wrap(err)
|
|
}
|
|
var sess *Session
|
|
if err := json.Unmarshal(out.Bytes(), &sess); err != nil {
|
|
return nil, err
|
|
}
|
|
return sess, nil
|
|
}
|
|
|
|
// GetU2FSignRequest generates request for user trying to authenticate with U2F token
|
|
func (c *Client) GetU2FSignRequest(user string, password []byte) (*u2f.SignRequest, error) {
|
|
out, err := c.PostJSON(
|
|
c.Endpoint("u2f", "users", user, "sign"),
|
|
signInReq{
|
|
Password: string(password),
|
|
},
|
|
)
|
|
if err != nil {
|
|
return nil, trace.Wrap(err)
|
|
}
|
|
var signRequest *u2f.SignRequest
|
|
if err := json.Unmarshal(out.Bytes(), &signRequest); err != nil {
|
|
return nil, err
|
|
}
|
|
return signRequest, nil
|
|
}
|
|
|
|
// ExtendWebSession creates a new web session for a user based on another
|
|
// valid web session
|
|
func (c *Client) ExtendWebSession(user string, prevSessionID string) (*Session, error) {
|
|
out, err := c.PostJSON(
|
|
c.Endpoint("users", user, "web", "sessions"),
|
|
createWebSessionReq{
|
|
PrevSessionID: prevSessionID,
|
|
},
|
|
)
|
|
if err != nil {
|
|
return nil, trace.Wrap(err)
|
|
}
|
|
var sess *Session
|
|
if err := json.Unmarshal(out.Bytes(), &sess); err != nil {
|
|
return nil, err
|
|
}
|
|
return sess, nil
|
|
}
|
|
|
|
// CreateWebSession creates a new web session for a user
|
|
func (c *Client) CreateWebSession(user string) (*Session, error) {
|
|
out, err := c.PostJSON(
|
|
c.Endpoint("users", user, "web", "sessions"),
|
|
createWebSessionReq{},
|
|
)
|
|
if err != nil {
|
|
return nil, trace.Wrap(err)
|
|
}
|
|
var sess *Session
|
|
if err := json.Unmarshal(out.Bytes(), &sess); err != nil {
|
|
return nil, err
|
|
}
|
|
return sess, nil
|
|
}
|
|
|
|
// GetWebSessionInfo checks if a web sesion is valid, returns session id in case if
|
|
// it is valid, or error otherwise.
|
|
func (c *Client) GetWebSessionInfo(user string, sid string) (*Session, error) {
|
|
out, err := c.Get(
|
|
c.Endpoint("users", user, "web", "sessions", sid), url.Values{})
|
|
if err != nil {
|
|
return nil, trace.Wrap(err)
|
|
}
|
|
var sess *Session
|
|
if err := json.Unmarshal(out.Bytes(), &sess); err != nil {
|
|
return nil, trace.Wrap(err)
|
|
}
|
|
return sess, nil
|
|
}
|
|
|
|
// DeleteWebSession deletes a web session for this user by id
|
|
func (c *Client) DeleteWebSession(user string, sid string) error {
|
|
_, err := c.Delete(c.Endpoint("users", user, "web", "sessions", sid))
|
|
return trace.Wrap(err)
|
|
}
|
|
|
|
// GetUser returns a list of usernames registered in the system
|
|
func (c *Client) GetUser(name string) (services.User, error) {
|
|
if name == "" {
|
|
return nil, trace.BadParameter("missing username")
|
|
}
|
|
out, err := c.Get(c.Endpoint("users", name), url.Values{})
|
|
if err != nil {
|
|
return nil, trace.Wrap(err)
|
|
}
|
|
user, err := services.GetUserMarshaler().UnmarshalUser(out.Bytes())
|
|
if err != nil {
|
|
return nil, trace.Wrap(err)
|
|
}
|
|
return user, nil
|
|
}
|
|
|
|
// GetUsers returns a list of usernames registered in the system
|
|
func (c *Client) GetUsers() ([]services.User, error) {
|
|
out, err := c.Get(c.Endpoint("users"), url.Values{})
|
|
if err != nil {
|
|
return nil, trace.Wrap(err)
|
|
}
|
|
var items []json.RawMessage
|
|
if err := json.Unmarshal(out.Bytes(), &items); err != nil {
|
|
return nil, trace.Wrap(err)
|
|
}
|
|
users := make([]services.User, len(items))
|
|
for i, userBytes := range items {
|
|
user, err := services.GetUserMarshaler().UnmarshalUser(userBytes)
|
|
if err != nil {
|
|
return nil, trace.Wrap(err)
|
|
}
|
|
users[i] = user
|
|
}
|
|
return users, nil
|
|
}
|
|
|
|
// DeleteUser deletes a user by username
|
|
func (c *Client) DeleteUser(user string) error {
|
|
_, err := c.Delete(c.Endpoint("users", user))
|
|
return trace.Wrap(err)
|
|
}
|
|
|
|
// GenerateKeyPair generates SSH private/public key pair optionally protected
|
|
// by password. If the pass parameter is an empty string, the key pair
|
|
// is not password-protected.
|
|
func (c *Client) GenerateKeyPair(pass string) ([]byte, []byte, error) {
|
|
out, err := c.PostJSON(c.Endpoint("keypair"), generateKeyPairReq{Password: pass})
|
|
if err != nil {
|
|
return nil, nil, trace.Wrap(err)
|
|
}
|
|
var kp *generateKeyPairResponse
|
|
if err := json.Unmarshal(out.Bytes(), &kp); err != nil {
|
|
return nil, nil, err
|
|
}
|
|
return kp.PrivKey, []byte(kp.PubKey), err
|
|
}
|
|
|
|
// GenerateHostCert takes the public key in the Open SSH ``authorized_keys``
|
|
// plain text format, signs it using Host Certificate Authority private key and returns the
|
|
// resulting certificate.
|
|
func (c *Client) GenerateHostCert(
|
|
key []byte, hostname, authDomain string, roles teleport.Roles, ttl time.Duration) ([]byte, error) {
|
|
|
|
out, err := c.PostJSON(c.Endpoint("ca", "host", "certs"),
|
|
generateHostCertReq{
|
|
Key: key,
|
|
Hostname: hostname,
|
|
AuthDomain: authDomain,
|
|
Roles: roles,
|
|
TTL: ttl,
|
|
})
|
|
if err != nil {
|
|
return nil, trace.Wrap(err)
|
|
}
|
|
var cert string
|
|
if err := json.Unmarshal(out.Bytes(), &cert); err != nil {
|
|
return nil, err
|
|
}
|
|
return []byte(cert), nil
|
|
}
|
|
|
|
// GenerateUserCert takes the public key in the Open SSH ``authorized_keys``
|
|
// plain text format, signs it using User Certificate Authority signing key and returns the
|
|
// resulting certificate.
|
|
func (c *Client) GenerateUserCert(
|
|
key []byte, user string, ttl time.Duration) ([]byte, error) {
|
|
|
|
out, err := c.PostJSON(c.Endpoint("ca", "user", "certs"),
|
|
generateUserCertReq{
|
|
Key: key,
|
|
User: user,
|
|
TTL: ttl,
|
|
})
|
|
if err != nil {
|
|
return nil, trace.Wrap(err)
|
|
}
|
|
var cert string
|
|
if err := json.Unmarshal(out.Bytes(), &cert); err != nil {
|
|
return nil, trace.Wrap(err)
|
|
}
|
|
return []byte(cert), nil
|
|
}
|
|
|
|
// CreateSignupToken creates one time token for creating account for the user
|
|
// For each token it creates username and hotp generator
|
|
func (c *Client) CreateSignupToken(user services.User) (string, error) {
|
|
if err := user.Check(); err != nil {
|
|
return "", trace.Wrap(err)
|
|
}
|
|
out, err := c.PostJSON(c.Endpoint("signuptokens"), createSignupTokenReq{
|
|
User: user,
|
|
})
|
|
if err != nil {
|
|
return "", trace.Wrap(err)
|
|
}
|
|
var token string
|
|
if err := json.Unmarshal(out.Bytes(), &token); err != nil {
|
|
return "", trace.Wrap(err)
|
|
}
|
|
return token, nil
|
|
}
|
|
|
|
// GetSignupTokenData returns token data for a valid token
|
|
func (c *Client) GetSignupTokenData(token string) (user string,
|
|
QRImg []byte, hotpFirstValues []string, e error) {
|
|
|
|
out, err := c.Get(c.Endpoint("signuptokens", token), url.Values{})
|
|
if err != nil {
|
|
return "", nil, nil, err
|
|
}
|
|
var tokenData getSignupTokenDataResponse
|
|
if err := json.Unmarshal(out.Bytes(), &tokenData); err != nil {
|
|
return "", nil, nil, err
|
|
}
|
|
return tokenData.User, tokenData.QRImg, tokenData.HotpFirstValues, nil
|
|
}
|
|
|
|
// GetSignupU2FRegisterRequest generates sign request for user trying to sign up with invite tokenx
|
|
func (c *Client) GetSignupU2FRegisterRequest(token string) (u2fRegisterRequest *u2f.RegisterRequest, e error) {
|
|
out, err := c.Get(c.Endpoint("u2f", "signuptokens", token), url.Values{})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var u2fRegReq u2f.RegisterRequest
|
|
if err := json.Unmarshal(out.Bytes(), &u2fRegReq); err != nil {
|
|
return nil, err
|
|
}
|
|
return &u2fRegReq, nil
|
|
}
|
|
|
|
// CreateUserWithToken creates account with provided token and password.
|
|
// Account username and hotp generator are taken from token data.
|
|
// Deletes token after account creation.
|
|
func (c *Client) CreateUserWithToken(token, password, hotpToken string) (*Session, error) {
|
|
out, err := c.PostJSON(c.Endpoint("signuptokens", "users"), createUserWithTokenReq{
|
|
Token: token,
|
|
Password: password,
|
|
HOTPToken: hotpToken,
|
|
})
|
|
if err != nil {
|
|
return nil, trace.Wrap(err)
|
|
}
|
|
var sess *Session
|
|
if err := json.Unmarshal(out.Bytes(), &sess); err != nil {
|
|
return nil, trace.Wrap(err)
|
|
}
|
|
return sess, nil
|
|
}
|
|
|
|
// CreateUserWithU2FToken creates user account with provided token and U2F sign response
|
|
func (c *Client) CreateUserWithU2FToken(token string, password string, u2fRegisterResponse u2f.RegisterResponse) (*Session, error) {
|
|
out, err := c.PostJSON(c.Endpoint("u2f", "users"), createUserWithU2FTokenReq{
|
|
Token: token,
|
|
Password: password,
|
|
U2FRegisterResponse: u2fRegisterResponse,
|
|
})
|
|
if err != nil {
|
|
return nil, trace.Wrap(err)
|
|
}
|
|
var sess *Session
|
|
if err := json.Unmarshal(out.Bytes(), &sess); err != nil {
|
|
return nil, trace.Wrap(err)
|
|
}
|
|
return sess, nil
|
|
}
|
|
|
|
// UpsertOIDCConnector updates or creates OIDC connector
|
|
func (c *Client) UpsertOIDCConnector(connector services.OIDCConnector, ttl time.Duration) error {
|
|
_, err := c.PostJSON(c.Endpoint("oidc", "connectors"), upsertOIDCConnectorReq{
|
|
Connector: connector,
|
|
TTL: ttl,
|
|
})
|
|
if err != nil {
|
|
return trace.Wrap(err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// GetOIDCConnector returns OIDC connector information by id
|
|
func (c *Client) GetOIDCConnector(id string, withSecrets bool) (*services.OIDCConnector, error) {
|
|
if id == "" {
|
|
return nil, trace.BadParameter("missing connector id")
|
|
}
|
|
out, err := c.Get(c.Endpoint("oidc", "connectors", id),
|
|
url.Values{"with_secrets": []string{fmt.Sprintf("%t", withSecrets)}})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var conn *services.OIDCConnector
|
|
if err := json.Unmarshal(out.Bytes(), &conn); err != nil {
|
|
return nil, trace.Wrap(err)
|
|
}
|
|
return conn, nil
|
|
}
|
|
|
|
// GetOIDCConnector gets OIDC connectors list
|
|
func (c *Client) GetOIDCConnectors(withSecrets bool) ([]services.OIDCConnector, error) {
|
|
out, err := c.Get(c.Endpoint("oidc", "connectors"),
|
|
url.Values{"with_secrets": []string{fmt.Sprintf("%t", withSecrets)}})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var connectors []services.OIDCConnector
|
|
if err := json.Unmarshal(out.Bytes(), &connectors); err != nil {
|
|
return nil, trace.Wrap(err)
|
|
}
|
|
return connectors, nil
|
|
}
|
|
|
|
// DeleteOIDCConnector deletes OIDC connector by ID
|
|
func (c *Client) DeleteOIDCConnector(connectorID string) error {
|
|
if connectorID == "" {
|
|
return trace.BadParameter("missing connector id")
|
|
}
|
|
_, err := c.Delete(c.Endpoint("oidc", "connectors", connectorID))
|
|
return trace.Wrap(err)
|
|
}
|
|
|
|
// CreateOIDCAuthRequest creates OIDCAuthRequest
|
|
func (c *Client) CreateOIDCAuthRequest(req services.OIDCAuthRequest) (*services.OIDCAuthRequest, error) {
|
|
out, err := c.PostJSON(c.Endpoint("oidc", "requests", "create"), createOIDCAuthRequestReq{
|
|
Req: req,
|
|
})
|
|
if err != nil {
|
|
return nil, trace.Wrap(err)
|
|
}
|
|
var response *services.OIDCAuthRequest
|
|
if err := json.Unmarshal(out.Bytes(), &response); err != nil {
|
|
return nil, trace.Wrap(err)
|
|
}
|
|
return response, nil
|
|
}
|
|
|
|
// ValidateOIDCAuthCallback validates OIDC auth callback returned from redirect
|
|
func (c *Client) ValidateOIDCAuthCallback(q url.Values) (*OIDCAuthResponse, error) {
|
|
out, err := c.PostJSON(c.Endpoint("oidc", "requests", "validate"), validateOIDCAuthCallbackReq{
|
|
Query: q,
|
|
})
|
|
if err != nil {
|
|
return nil, trace.Wrap(err)
|
|
}
|
|
var response *OIDCAuthResponse
|
|
if err := json.Unmarshal(out.Bytes(), &response); err != nil {
|
|
return nil, trace.Wrap(err)
|
|
}
|
|
return response, nil
|
|
}
|
|
|
|
// EmitAuditEvent sends an auditable event to the auth server (part of evets.IAuditLog interface)
|
|
func (c *Client) EmitAuditEvent(eventType string, fields events.EventFields) error {
|
|
_, err := c.PostJSON(c.Endpoint("events"), &auditEventReq{
|
|
Type: eventType,
|
|
Fields: fields,
|
|
})
|
|
if err != nil {
|
|
return trace.Wrap(err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// PostSessionChunk allows clients to submit session stream chunks to the audit log
|
|
// (part of evets.IAuditLog interface)
|
|
//
|
|
// The data is POSTed to HTTP server as a simple binary body (no encodings of any
|
|
// kind are needed)
|
|
func (c *Client) PostSessionChunk(namespace string, sid session.ID, reader io.Reader) error {
|
|
if namespace == "" {
|
|
return trace.BadParameter("missing parameter namespace")
|
|
}
|
|
r, err := http.NewRequest("POST", c.Endpoint("namespaces", namespace, "sessions", string(sid), "stream"), reader)
|
|
if err != nil {
|
|
return trace.Wrap(err)
|
|
}
|
|
r.Header.Set("Content-Type", "application/octet-stream")
|
|
c.Client.SetAuthHeader(r.Header)
|
|
re, err := c.Client.HTTPClient().Do(r)
|
|
if err != nil {
|
|
return trace.Wrap(err)
|
|
}
|
|
// we **must** consume response by reading all of its body, otherwise the http
|
|
// client will allocate a new connection for subsequent requests
|
|
defer re.Body.Close()
|
|
responseBytes, _ := ioutil.ReadAll(re.Body)
|
|
return trace.ReadError(re.StatusCode, responseBytes)
|
|
}
|
|
|
|
// GetSessionChunk allows clients to receive a byte array (chunk) from a recorded
|
|
// session stream, starting from 'offset', up to 'max' in length. The upper bound
|
|
// of 'max' is set to events.MaxChunkBytes
|
|
func (c *Client) GetSessionChunk(namespace string, sid session.ID, offsetBytes, maxBytes int) ([]byte, error) {
|
|
if namespace == "" {
|
|
return nil, trace.BadParameter("missing parameter namespace")
|
|
}
|
|
response, err := c.Get(c.Endpoint("namespaces", namespace, "sessions", string(sid), "stream"), url.Values{
|
|
"offset": []string{strconv.Itoa(offsetBytes)},
|
|
"bytes": []string{strconv.Itoa(maxBytes)},
|
|
})
|
|
if err != nil {
|
|
logrus.Error(err)
|
|
return nil, trace.Wrap(err)
|
|
}
|
|
return response.Bytes(), nil
|
|
}
|
|
|
|
// Returns events that happen during a session sorted by time
|
|
// (oldest first).
|
|
//
|
|
// afterN allows to filter by "newer than N" value where N is the cursor ID
|
|
// of previously returned bunch (good for polling for latest)
|
|
//
|
|
// This function is usually used in conjunction with GetSessionReader to
|
|
// replay recorded session streams.
|
|
func (c *Client) GetSessionEvents(namespace string, sid session.ID, afterN int) (retval []events.EventFields, err error) {
|
|
if namespace == "" {
|
|
return nil, trace.BadParameter("missing parameter namespace")
|
|
}
|
|
query := make(url.Values)
|
|
if afterN > 0 {
|
|
query.Set("after", strconv.Itoa(afterN))
|
|
}
|
|
response, err := c.Get(c.Endpoint("namespaces", namespace, "sessions", string(sid), "events"), query)
|
|
if err != nil {
|
|
return nil, trace.Wrap(err)
|
|
}
|
|
retval = make([]events.EventFields, 0)
|
|
if err := json.Unmarshal(response.Bytes(), &retval); err != nil {
|
|
return nil, trace.Wrap(err)
|
|
}
|
|
return retval, nil
|
|
}
|
|
|
|
// SearchEvents returns events that fit the criteria
|
|
func (c *Client) SearchEvents(from, to time.Time, query string) ([]events.EventFields, error) {
|
|
q, err := url.ParseQuery(query)
|
|
if err != nil {
|
|
return nil, trace.BadParameter("query")
|
|
}
|
|
q.Set("from", from.Format(time.RFC3339))
|
|
q.Set("to", to.Format(time.RFC3339))
|
|
response, err := c.Get(c.Endpoint("events"), q)
|
|
if err != nil {
|
|
return nil, trace.Wrap(err)
|
|
}
|
|
retval := make([]events.EventFields, 0)
|
|
if err := json.Unmarshal(response.Bytes(), &retval); err != nil {
|
|
return nil, trace.Wrap(err)
|
|
}
|
|
return retval, nil
|
|
}
|
|
|
|
// GetNamespaces returns a list of namespaces
|
|
func (c *Client) GetNamespaces() ([]services.Namespace, error) {
|
|
out, err := c.Get(c.Endpoint("namespaces"), url.Values{})
|
|
if err != nil {
|
|
return nil, trace.Wrap(err)
|
|
}
|
|
var re []services.Namespace
|
|
if err := json.Unmarshal(out.Bytes(), &re); err != nil {
|
|
return nil, trace.Wrap(err)
|
|
}
|
|
return re, nil
|
|
}
|
|
|
|
// GetNamespace returns namespace by name
|
|
func (c *Client) GetNamespace(name string) (*services.Namespace, error) {
|
|
if name == "" {
|
|
return nil, trace.BadParameter("missing namespace name")
|
|
}
|
|
out, err := c.Get(c.Endpoint("namespaces", name), url.Values{})
|
|
if err != nil {
|
|
return nil, trace.Wrap(err)
|
|
}
|
|
var ns services.Namespace
|
|
if err := json.Unmarshal(out.Bytes(), &ns); err != nil {
|
|
return nil, trace.Wrap(err)
|
|
}
|
|
return &ns, nil
|
|
}
|
|
|
|
// UpsertNamespace upserts namespace
|
|
func (c *Client) UpsertNamespace(ns services.Namespace) error {
|
|
_, err := c.PostJSON(c.Endpoint("namespaces"), upsertNamespaceReq{Namespace: ns})
|
|
return trace.Wrap(err)
|
|
}
|
|
|
|
// DeleteNamespace deletes namespace by name
|
|
func (c *Client) DeleteNamespace(name string) error {
|
|
_, err := c.Delete(c.Endpoint("namespaces", name))
|
|
return trace.Wrap(err)
|
|
}
|
|
|
|
// GetRoles returns a list of roles
|
|
func (c *Client) GetRoles() ([]services.Role, error) {
|
|
out, err := c.Get(c.Endpoint("roles"), url.Values{})
|
|
if err != nil {
|
|
return nil, trace.Wrap(err)
|
|
}
|
|
var items []json.RawMessage
|
|
if err := json.Unmarshal(out.Bytes(), &items); err != nil {
|
|
return nil, trace.Wrap(err)
|
|
}
|
|
roles := make([]services.Role, len(items))
|
|
for i, roleBytes := range items {
|
|
role, err := services.GetRoleMarshaler().UnmarshalRole(roleBytes)
|
|
if err != nil {
|
|
return nil, trace.Wrap(err)
|
|
}
|
|
roles[i] = role
|
|
}
|
|
return roles, nil
|
|
}
|
|
|
|
// UpsertRole creates or updates role
|
|
func (c *Client) UpsertRole(role services.Role) error {
|
|
_, err := c.PostJSON(c.Endpoint("roles"), upsertRoleReq{Role: role})
|
|
return trace.Wrap(err)
|
|
}
|
|
|
|
// GetRole returns role by name
|
|
func (c *Client) GetRole(name string) (services.Role, error) {
|
|
if name == "" {
|
|
return nil, trace.BadParameter("missing name")
|
|
}
|
|
out, err := c.Get(c.Endpoint("roles", name), url.Values{})
|
|
if err != nil {
|
|
return nil, trace.Wrap(err)
|
|
}
|
|
role, err := services.GetRoleMarshaler().UnmarshalRole(out.Bytes())
|
|
if err != nil {
|
|
return nil, trace.Wrap(err)
|
|
}
|
|
return role, nil
|
|
}
|
|
|
|
// DeleteRole deletes role by name
|
|
func (c *Client) DeleteRole(name string) error {
|
|
_, err := c.Delete(c.Endpoint("roles", name))
|
|
return trace.Wrap(err)
|
|
}
|
|
|
|
// WebService implements features used by Web UI clients
|
|
type WebService interface {
|
|
// GetWebSessionInfo checks if a web sesion is valid, returns session id in case if
|
|
// it is valid, or error otherwise.
|
|
GetWebSessionInfo(user string, sid string) (*Session, error)
|
|
// ExtendWebSession creates a new web session for a user based on another
|
|
// valid web session
|
|
ExtendWebSession(user string, prevSessionID string) (*Session, error)
|
|
// CreateWebSession creates a new web session for a user
|
|
CreateWebSession(user string) (*Session, error)
|
|
// DeleteWebSession deletes a web session for this user by id
|
|
DeleteWebSession(user string, sid string) error
|
|
}
|
|
|
|
// IdentityService manages identities and userse
|
|
type IdentityService interface {
|
|
// UpsertPassword updates web access password for the user
|
|
UpsertPassword(user string, password []byte) (hotpURL string, hotpQR []byte, err error)
|
|
|
|
// UpsertOIDCConnector updates or creates OIDC connector
|
|
UpsertOIDCConnector(connector services.OIDCConnector, ttl time.Duration) error
|
|
|
|
// GetOIDCConnector returns OIDC connector information by id
|
|
GetOIDCConnector(id string, withSecrets bool) (*services.OIDCConnector, error)
|
|
|
|
// GetOIDCConnector gets OIDC connectors list
|
|
GetOIDCConnectors(withSecrets bool) ([]services.OIDCConnector, error)
|
|
|
|
// DeleteOIDCConnector deletes OIDC connector by ID
|
|
DeleteOIDCConnector(connectorID string) error
|
|
|
|
// CreateOIDCAuthRequest creates OIDCAuthRequest
|
|
CreateOIDCAuthRequest(req services.OIDCAuthRequest) (*services.OIDCAuthRequest, error)
|
|
|
|
// ValidateOIDCAuthCallback validates OIDC auth callback returned from redirect
|
|
ValidateOIDCAuthCallback(q url.Values) (*OIDCAuthResponse, error)
|
|
|
|
// GetU2FSignRequest generates request for user trying to authenticate with U2F token
|
|
GetU2FSignRequest(user string, password []byte) (*u2f.SignRequest, error)
|
|
|
|
// GetSignupU2FRegisterRequest generates sign request for user trying to sign up with invite token
|
|
GetSignupU2FRegisterRequest(token string) (*u2f.RegisterRequest, error)
|
|
|
|
// CreateUserWithU2FToken creates user account with provided token and U2F sign response
|
|
CreateUserWithU2FToken(token string, password string, u2fRegisterResponse u2f.RegisterResponse) (*Session, error)
|
|
|
|
// PreAuthenticatedSignIn is used get web session for a user that is already authenticated
|
|
PreAuthenticatedSignIn(user string) (*Session, error)
|
|
|
|
// GetU2FAppID returns U2F settings, like App ID and Facets
|
|
GetU2FAppID() (string, error)
|
|
|
|
// GetUser returns a list of usernames registered in the system
|
|
GetUser(name string) (services.User, error)
|
|
|
|
// UpsertUser user updates or inserts user entry
|
|
UpsertUser(user services.User) error
|
|
|
|
// DeleteUser deletes a user by username
|
|
DeleteUser(user string) error
|
|
|
|
// GetUsers returns a list of usernames registered in the system
|
|
GetUsers() ([]services.User, error)
|
|
|
|
// CheckPassword checks if the suplied web access password is valid.
|
|
CheckPassword(user string, password []byte, hotpToken string) error
|
|
|
|
// SignIn checks if the web access password is valid, and if it is valid
|
|
// returns a secure web session id.
|
|
SignIn(user string, password []byte) (*Session, error)
|
|
|
|
// CreateUserWithToken creates account with provided token and password.
|
|
// Account username and hotp generator are taken from token data.
|
|
// Deletes token after account creation.
|
|
CreateUserWithToken(token, password, hotpToken string) (*Session, error)
|
|
|
|
// GenerateToken creates a special provisioning token for a new SSH server
|
|
// that is valid for ttl period seconds.
|
|
//
|
|
// This token is used by SSH server to authenticate with Auth server
|
|
// and get signed certificate and private key from the auth server.
|
|
//
|
|
// The token can be used only once.
|
|
GenerateToken(roles teleport.Roles, ttl time.Duration) (string, error)
|
|
|
|
// GenerateKeyPair generates SSH private/public key pair optionally protected
|
|
// by password. If the pass parameter is an empty string, the key pair
|
|
// is not password-protected.
|
|
GenerateKeyPair(pass string) ([]byte, []byte, error)
|
|
|
|
// GenerateHostCert takes the public key in the Open SSH ``authorized_keys``
|
|
// plain text format, signs it using Host Certificate Authority private key and returns the
|
|
// resulting certificate.
|
|
GenerateHostCert(key []byte, hostname, authDomain string, roles teleport.Roles, ttl time.Duration) ([]byte, error)
|
|
|
|
// GenerateUserCert takes the public key in the Open SSH ``authorized_keys``
|
|
// plain text format, signs it using User Certificate Authority signing key and returns the
|
|
// resulting certificate.
|
|
GenerateUserCert(key []byte, user string, ttl time.Duration) ([]byte, error)
|
|
|
|
// GetSignupTokenData returns token data for a valid token
|
|
GetSignupTokenData(token string) (user string, QRImg []byte, hotpFirstValues []string, e error)
|
|
|
|
// CreateSignupToken creates one time token for creating account for the user
|
|
// For each token it creates username and hotp generator
|
|
CreateSignupToken(user services.User) (string, error)
|
|
}
|
|
|
|
// ProvisioningService is a service in control
|
|
// of adding new nodes, auth servers and proxies to the cluster
|
|
type ProvisioningService interface {
|
|
// GetTokens returns a list of active invitation tokens for nodes and users
|
|
GetTokens() (tokens []services.ProvisionToken, err error)
|
|
|
|
// GetToken returns provisioning token
|
|
GetToken(token string) (*services.ProvisionToken, error)
|
|
|
|
// DeleteToken deletes a given provisioning token on the auth server (CA). It
|
|
// could be a user token or a machine token
|
|
DeleteToken(token string) error
|
|
// RegisterUsingToken calls the auth service API to register a new node via registration token
|
|
// which has been previously issued via GenerateToken
|
|
RegisterUsingToken(token, hostID string, role teleport.Role) (*PackedKeys, error)
|
|
|
|
// RegisterNewAuthServer is used to register new auth server with token
|
|
RegisterNewAuthServer(token string) error
|
|
}
|
|
|
|
// ClientI is a client to Auth service
|
|
type ClientI interface {
|
|
IdentityService
|
|
ProvisioningService
|
|
services.Trust
|
|
events.IAuditLog
|
|
services.Presence
|
|
services.Access
|
|
WebService
|
|
session.Service
|
|
|
|
GetDomainName() (string, error)
|
|
}
|