mirror of
https://github.com/gravitational/teleport
synced 2024-10-22 10:13:21 +00:00
742 lines
22 KiB
Go
742 lines
22 KiB
Go
package auth
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"fmt"
|
|
"net"
|
|
"net/http"
|
|
"net/url"
|
|
"strconv"
|
|
"time"
|
|
|
|
"github.com/gravitational/teleport"
|
|
"github.com/gravitational/teleport/lib/backend/encryptedbk/encryptor"
|
|
"github.com/gravitational/teleport/lib/events"
|
|
"github.com/gravitational/teleport/lib/recorder"
|
|
"github.com/gravitational/teleport/lib/services"
|
|
"github.com/gravitational/teleport/lib/session"
|
|
"github.com/gravitational/teleport/lib/utils"
|
|
|
|
"github.com/gravitational/teleport/Godeps/_workspace/src/github.com/codahale/lunk"
|
|
"github.com/gravitational/teleport/Godeps/_workspace/src/github.com/gravitational/roundtrip"
|
|
)
|
|
|
|
const CurrentVersion = "v1"
|
|
|
|
// Certificate authority endpoints control user and host CAs.
|
|
// They are central mechanism for authenticating users and hosts within
|
|
// the cluster.
|
|
//
|
|
// Client is HTTP API client that connects to the remote server
|
|
type Client struct {
|
|
roundtrip.Client
|
|
}
|
|
|
|
func NewClientFromNetAddr(
|
|
a utils.NetAddr, params ...roundtrip.ClientParam) (*Client, error) {
|
|
|
|
client := &http.Client{
|
|
Transport: &http.Transport{
|
|
Dial: func(network, address string) (net.Conn, error) {
|
|
return net.Dial(a.Network, a.Addr)
|
|
}}}
|
|
params = append(params, roundtrip.HTTPClient(client))
|
|
u := url.URL{
|
|
Scheme: "http",
|
|
Host: "placeholder",
|
|
Path: a.Path,
|
|
}
|
|
return NewClient(u.String(), params...)
|
|
}
|
|
|
|
func NewClient(addr string, params ...roundtrip.ClientParam) (*Client, error) {
|
|
c, err := roundtrip.NewClient(addr, CurrentVersion, params...)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &Client{*c}, nil
|
|
}
|
|
|
|
func (c *Client) convertResponse(
|
|
re *roundtrip.Response, err error) (*roundtrip.Response, error) {
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if re.Code() == http.StatusNotFound {
|
|
return nil, &teleport.NotFoundError{Message: string(re.Bytes())}
|
|
}
|
|
if re.Code() < 200 || re.Code() > 299 {
|
|
return nil, fmt.Errorf("error: %v", string(re.Bytes()))
|
|
}
|
|
return re, nil
|
|
}
|
|
|
|
// 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 c.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 c.convertResponse(c.Client.Get(u, params))
|
|
}
|
|
|
|
// Delete issues http Delete Request to the server
|
|
func (c *Client) Delete(u string) (*roundtrip.Response, error) {
|
|
return c.convertResponse(c.Client.Delete(u))
|
|
}
|
|
|
|
func (c *Client) GetSessions() ([]session.Session, error) {
|
|
out, err := c.Get(c.Endpoint("sessions"), url.Values{})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var re *sessionsResponse
|
|
if err := json.Unmarshal(out.Bytes(), &re); err != nil {
|
|
return nil, err
|
|
}
|
|
return re.Sessions, nil
|
|
}
|
|
|
|
func (c *Client) GetSession(id string) (*session.Session, error) {
|
|
out, err := c.Get(c.Endpoint("sessions", id), url.Values{})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var re *sessionResponse
|
|
if err := json.Unmarshal(out.Bytes(), &re); err != nil {
|
|
return nil, err
|
|
}
|
|
return &re.Session, nil
|
|
}
|
|
|
|
func (c *Client) DeleteSession(id string) error {
|
|
_, err := c.Delete(c.Endpoint("sessions", id))
|
|
return err
|
|
}
|
|
|
|
func (c *Client) UpsertSession(id string, ttl time.Duration) error {
|
|
out, err := c.PostForm(c.Endpoint("sessions"), url.Values{
|
|
"id": []string{id},
|
|
"ttl": []string{ttl.String()},
|
|
})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
var re *sessionResponse
|
|
if err := json.Unmarshal(out.Bytes(), &re); err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (c *Client) UpsertParty(id string, p session.Party, ttl time.Duration) error {
|
|
a, err := p.LastActive.MarshalText()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
out, err := c.PostForm(c.Endpoint("sessions", id, "parties"), url.Values{
|
|
"id": []string{p.ID},
|
|
"site": []string{p.Site},
|
|
"user": []string{p.User},
|
|
"server_addr": []string{p.ServerAddr},
|
|
"ttl": []string{ttl.String()},
|
|
"last_active": []string{string(a)},
|
|
})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
var re *partyResponse
|
|
if err := json.Unmarshal(out.Bytes(), &re); err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
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()},
|
|
"id": []string{cert.ID},
|
|
})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
var re *remoteCertResponse
|
|
if err := json.Unmarshal(out.Bytes(), &re); err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
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},
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var re *remoteCertsResponse
|
|
if err := json.Unmarshal(out.Bytes(), &re); err != nil {
|
|
return nil, err
|
|
}
|
|
return re.RemoteCerts, nil
|
|
}
|
|
|
|
func (c *Client) DeleteRemoteCert(ctype string, fqdn, id string) error {
|
|
_, err := c.Delete(c.Endpoint("ca", "remote", ctype, "hosts", fqdn, id))
|
|
return err
|
|
}
|
|
|
|
// GenerateToken creates a special provisioning token for the SSH server
|
|
// with the specified fqdn 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 and only to generate the fqdn
|
|
// specified in it.
|
|
func (c *Client) GenerateToken(fqdn string, ttl time.Duration) (string, error) {
|
|
out, err := c.PostForm(c.Endpoint("tokens"), url.Values{
|
|
"fqdn": []string{fqdn},
|
|
"ttl": []string{ttl.String()},
|
|
})
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
var re *tokenResponse
|
|
if err := json.Unmarshal(out.Bytes(), &re); err != nil {
|
|
return "", err
|
|
}
|
|
return re.Token, nil
|
|
}
|
|
|
|
func (c *Client) Log(id lunk.EventID, e lunk.Event) {
|
|
en := lunk.NewEntry(id, e)
|
|
en.Time = time.Now()
|
|
c.LogEntry(en)
|
|
}
|
|
|
|
func (c *Client) LogEntry(en lunk.Entry) error {
|
|
bt, err := json.Marshal(en)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
file := roundtrip.File{
|
|
Name: "event",
|
|
Filename: "event.json",
|
|
Reader: bytes.NewReader(bt),
|
|
}
|
|
_, err = c.PostForm(c.Endpoint("events"), url.Values{}, file)
|
|
return err
|
|
}
|
|
|
|
func (c *Client) GetEvents(filter events.Filter) ([]lunk.Entry, error) {
|
|
vals, err := events.FilterToURL(filter)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
out, err := c.Get(c.Endpoint("events"), vals)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var re *eventsResponse
|
|
if err := json.Unmarshal(out.Bytes(), &re); err != nil {
|
|
return nil, err
|
|
}
|
|
return re.Events, nil
|
|
}
|
|
|
|
func (c *Client) GetChunkWriter(id string) (recorder.ChunkWriteCloser, error) {
|
|
return &chunkRW{c: c, id: id}, nil
|
|
}
|
|
|
|
func (c *Client) GetChunkReader(id string) (recorder.ChunkReadCloser, error) {
|
|
return &chunkRW{c: c, id: id}, nil
|
|
}
|
|
|
|
// 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 services.Server, ttl time.Duration) error {
|
|
_, err := c.PostForm(c.Endpoint("servers"), url.Values{
|
|
"id": []string{string(s.ID)},
|
|
"addr": []string{string(s.Addr)},
|
|
"ttl": []string{ttl.String()},
|
|
})
|
|
return err
|
|
}
|
|
|
|
// GetServers returns the list of servers registered in the cluster.
|
|
func (c *Client) GetServers() ([]services.Server, error) {
|
|
out, err := c.Get(c.Endpoint("servers"), url.Values{})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var re *serversResponse
|
|
if err := json.Unmarshal(out.Bytes(), &re); err != nil {
|
|
return nil, err
|
|
}
|
|
return re.Servers, nil
|
|
}
|
|
|
|
// UpsertWebTun creates a persistent SSH tunnel to the specified web target
|
|
// server that is valid for ttl period.
|
|
// 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)},
|
|
"prefix": []string{string(wt.Prefix)},
|
|
"ttl": []string{ttl.String()},
|
|
})
|
|
return err
|
|
}
|
|
|
|
// GetWebTuns returns a list of web tunnels supported by the system
|
|
func (c *Client) GetWebTuns() ([]services.WebTun, error) {
|
|
out, err := c.Get(c.Endpoint("tunnels", "web"), url.Values{})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var re *webTunsResponse
|
|
if err := json.Unmarshal(out.Bytes(), &re); err != nil {
|
|
return nil, err
|
|
}
|
|
return re.Tunnels, nil
|
|
}
|
|
|
|
// GetWebTun retruns the web tunel details by it unique prefix
|
|
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
|
|
}
|
|
var re *webTunResponse
|
|
if err := json.Unmarshal(out.Bytes(), &re); err != nil {
|
|
return nil, err
|
|
}
|
|
return &re.Tunnel, nil
|
|
}
|
|
|
|
// DeleteWebTun deletes the tunnel by prefix
|
|
func (c *Client) DeleteWebTun(prefix string) error {
|
|
_, err := c.Delete(c.Endpoint("tunnels", "web", prefix))
|
|
return err
|
|
}
|
|
|
|
// 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.PostForm(
|
|
c.Endpoint("users", user, "web", "password"),
|
|
url.Values{"password": []string{string(password)}},
|
|
)
|
|
var re *upsertPasswordResponse
|
|
if err := json.Unmarshal(out.Bytes(), &re); err != nil {
|
|
return "", nil, err
|
|
}
|
|
return re.HotpURL, re.HotpQR, err
|
|
}
|
|
|
|
// CheckPassword checks if the suplied web access password is valid.
|
|
func (c *Client) CheckPassword(user string,
|
|
password []byte, hotpToken string) error {
|
|
_, err := c.PostForm(
|
|
c.Endpoint("users", user, "web", "password", "check"),
|
|
url.Values{
|
|
"password": []string{string(password)},
|
|
"hotpToken": []string{hotpToken},
|
|
})
|
|
return 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) (string, error) {
|
|
out, err := c.PostForm(
|
|
c.Endpoint("users", user, "web", "signin"),
|
|
url.Values{
|
|
"password": []string{string(password)},
|
|
},
|
|
)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
var re *webSessionResponse
|
|
if err := json.Unmarshal(out.Bytes(), &re); err != nil {
|
|
return "", err
|
|
}
|
|
return re.SID, nil
|
|
}
|
|
|
|
// GetWebSession check if a web sesion is valid, returns session id in case if
|
|
// it is valid, or error otherwise.
|
|
func (c *Client) GetWebSession(user string, sid string) (string, error) {
|
|
out, err := c.Get(
|
|
c.Endpoint("users", user, "web", "sessions", sid), url.Values{})
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
var re *webSessionResponse
|
|
if err := json.Unmarshal(out.Bytes(), &re); err != nil {
|
|
return "", err
|
|
}
|
|
return re.SID, nil
|
|
}
|
|
|
|
// GetWebSessionKeys returns the list of temporary keys generated for this
|
|
// user web session. Each web session has a temporary user ssh key and
|
|
// 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) ([]services.AuthorizedKey, error) {
|
|
|
|
out, err := c.Get(c.Endpoint("users", user, "web", "sessions"), url.Values{})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var re *webSessionsResponse
|
|
if err := json.Unmarshal(out.Bytes(), &re); err != nil {
|
|
return nil, err
|
|
}
|
|
return re.Keys, 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 err
|
|
}
|
|
|
|
// GetUsers returns a list of usernames registered in the system
|
|
func (c *Client) GetUsers() ([]string, error) {
|
|
out, err := c.Get(c.Endpoint("users"), url.Values{})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var users *usersResponse
|
|
if err := json.Unmarshal(out.Bytes(), &users); err != nil {
|
|
return nil, err
|
|
}
|
|
return users.Users, nil
|
|
}
|
|
|
|
// DeleteUser deletes a user by username
|
|
func (c *Client) DeleteUser(user string) error {
|
|
_, err := c.Delete(c.Endpoint("users", user))
|
|
return err
|
|
}
|
|
|
|
// UpsertUserKey takes public key of the user, generates certificate for it
|
|
// and adds it to the authorized keys database. It returns certificate signed
|
|
// 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 services.AuthorizedKey, ttl time.Duration) ([]byte, error) {
|
|
|
|
out, err := c.PostForm(c.Endpoint("users", username, "keys"), url.Values{
|
|
"key": []string{string(key.Value)},
|
|
"id": []string{key.ID},
|
|
"ttl": []string{ttl.String()},
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var cert *certResponse
|
|
if err := json.Unmarshal(out.Bytes(), &cert); err != nil {
|
|
return nil, err
|
|
}
|
|
return []byte(cert.Cert), err
|
|
}
|
|
|
|
// 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) ([]services.AuthorizedKey, error) {
|
|
out, err := c.Get(c.Endpoint("users", user, "keys"), url.Values{})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var keys *pubKeysResponse
|
|
if err := json.Unmarshal(out.Bytes(), &keys); err != nil {
|
|
return nil, err
|
|
}
|
|
return keys.PubKeys, nil
|
|
}
|
|
|
|
// DeleteUserKey deletes a key by id for a given user
|
|
func (c *Client) DeleteUserKey(username string, id string) error {
|
|
_, err := c.Delete(c.Endpoint("users", username, "keys", id))
|
|
return err
|
|
}
|
|
|
|
// Returns host certificate authority public key. This public key is used to
|
|
// validate if host certificates were signed by the proper key.
|
|
func (c *Client) GetHostCAPub() ([]byte, error) {
|
|
out, err := c.Get(c.Endpoint("ca", "host", "keys", "pub"), url.Values{})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var pubkey *pubKeyResponse
|
|
if err := json.Unmarshal(out.Bytes(), &pubkey); err != nil {
|
|
return nil, err
|
|
}
|
|
return []byte(pubkey.PubKey), err
|
|
}
|
|
|
|
// Returns user certificate authority public key.
|
|
// This public key is used to check if the users certificate is valid and was
|
|
// signed by this authority.
|
|
func (c *Client) GetUserCAPub() ([]byte, error) {
|
|
out, err := c.Get(c.Endpoint("ca", "user", "keys", "pub"), url.Values{})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var pubkey *pubKeyResponse
|
|
if err := json.Unmarshal(out.Bytes(), &pubkey); err != nil {
|
|
return nil, err
|
|
}
|
|
return []byte(pubkey.PubKey), 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.PostForm(c.Endpoint("keypair"), url.Values{})
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
var kp *keyPairResponse
|
|
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 CA private key and returns the
|
|
// resulting certificate.
|
|
func (c *Client) GenerateHostCert(
|
|
key []byte, id, hostname string, ttl time.Duration) ([]byte, error) {
|
|
|
|
out, err := c.PostForm(c.Endpoint("ca", "host", "certs"), url.Values{
|
|
"key": []string{string(key)},
|
|
"id": []string{id},
|
|
"hostname": []string{hostname},
|
|
"ttl": []string{ttl.String()},
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var cert *certResponse
|
|
if err := json.Unmarshal(out.Bytes(), &cert); err != nil {
|
|
return nil, err
|
|
}
|
|
return []byte(cert.Cert), err
|
|
}
|
|
|
|
// GenerateUserCert takes the public key in the Open SSH ``authorized_keys``
|
|
// plain text format, signs it using User CA signing key and returns the
|
|
// resulting certificate.
|
|
func (c *Client) GenerateUserCert(
|
|
key []byte, id, user string, ttl time.Duration) ([]byte, error) {
|
|
|
|
out, err := c.PostForm(c.Endpoint("ca", "user", "certs"), url.Values{
|
|
"key": []string{string(key)},
|
|
"id": []string{id},
|
|
"user": []string{user},
|
|
"ttl": []string{ttl.String()},
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var cert *certResponse
|
|
if err := json.Unmarshal(out.Bytes(), &cert); err != nil {
|
|
return nil, err
|
|
}
|
|
return []byte(cert.Cert), err
|
|
}
|
|
|
|
// Regenerates host certificate authority private key.
|
|
// Host authority certificate is used to sign SSH hosts public keys,
|
|
// so users and auth servers can authenicate SSH servers
|
|
// when connecting to them.
|
|
|
|
// All host certificate keys will have to be regenerated and all SSH nodes will
|
|
// have to be re-provisioned after calling this method.
|
|
func (c *Client) ResetHostCA() error {
|
|
_, err := c.PostForm(c.Endpoint("ca", "host", "keys"), url.Values{})
|
|
return err
|
|
}
|
|
|
|
// Regenerates user certificate authority private key.
|
|
// User authority certificate is used to sign User SSH public keys,
|
|
// so auth server can check if that is a valid key before even hitting
|
|
// the database.
|
|
//
|
|
// All user certificates will have to be regenerated.
|
|
//
|
|
func (c *Client) ResetUserCA() error {
|
|
_, err := c.PostForm(c.Endpoint("ca", "user", "keys"), url.Values{})
|
|
return err
|
|
}
|
|
|
|
// GetBackendKeys returns IDs of all the backend encrypting keys that
|
|
// this server has
|
|
func (c *Client) GetSealKeys() ([]encryptor.Key, error) {
|
|
out, err := c.Get(c.Endpoint("backend", "keys"), url.Values{})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var res sealKeysResponse
|
|
if err := json.Unmarshal(out.Bytes(), &res); err != nil {
|
|
return nil, err
|
|
}
|
|
return res.Keys, err
|
|
}
|
|
|
|
// GenerateBackendKey generates a new backend encrypting key with the
|
|
// given id and then backend makes a copy of all the data using the
|
|
// generated key for encryption
|
|
func (c *Client) GenerateSealKey(keyName string) (encryptor.Key, error) {
|
|
out, err := c.PostForm(c.Endpoint("backend", "generatekey"), url.Values{
|
|
"name": []string{keyName}})
|
|
if err != nil {
|
|
return encryptor.Key{}, err
|
|
}
|
|
|
|
var res sealKeyResponse
|
|
if err := json.Unmarshal(out.Bytes(), &res); err != nil {
|
|
return encryptor.Key{}, err
|
|
}
|
|
return res.Key, err
|
|
}
|
|
|
|
// DeleteBackendKey deletes the backend encrypting key and all the data
|
|
// encrypted with the key
|
|
func (c *Client) DeleteSealKey(keyID string) error {
|
|
_, err := c.Delete(c.Endpoint("backend", "keys", keyID))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return err
|
|
}
|
|
|
|
// AddBackendKey adds the given encrypting key. If backend works not in
|
|
// readonly mode, backend makes a copy of the data using the key for
|
|
// encryption
|
|
func (c *Client) AddSealKey(key encryptor.Key) error {
|
|
keyJSON, err := json.Marshal(key)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
_, err = c.PostForm(c.Endpoint("backend", "keys"), url.Values{
|
|
"key": []string{string(keyJSON)}})
|
|
return err
|
|
}
|
|
|
|
// GetBackendKeys returns the backend encrypting key.
|
|
func (c *Client) GetSealKey(keyID string) (encryptor.Key, error) {
|
|
out, err := c.Get(c.Endpoint("backend", "keys", keyID), url.Values{})
|
|
if err != nil {
|
|
return encryptor.Key{}, err
|
|
}
|
|
var key sealKeyResponse
|
|
if err := json.Unmarshal(out.Bytes(), &key); err != nil {
|
|
return encryptor.Key{}, err
|
|
}
|
|
return key.Key, nil
|
|
}
|
|
|
|
type chunkRW struct {
|
|
c *Client
|
|
id string
|
|
}
|
|
|
|
func (c *chunkRW) ReadChunks(start int, end int) ([]recorder.Chunk, error) {
|
|
out, err := c.c.Get(c.c.Endpoint("records", c.id, "chunks"), url.Values{
|
|
"start": []string{strconv.Itoa(start)},
|
|
"end": []string{strconv.Itoa(end)},
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var re *chunksResponse
|
|
if err := json.Unmarshal(out.Bytes(), &re); err != nil {
|
|
return nil, err
|
|
}
|
|
return re.Chunks, nil
|
|
}
|
|
|
|
func (c *chunkRW) WriteChunks(chs []recorder.Chunk) error {
|
|
files := make([]roundtrip.File, len(chs))
|
|
|
|
for i, ch := range chs {
|
|
bt, err := json.Marshal(ch)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
files[i] = roundtrip.File{
|
|
Name: "chunk",
|
|
Filename: "chunk.json",
|
|
Reader: bytes.NewReader(bt),
|
|
}
|
|
}
|
|
_, err := c.c.PostForm(
|
|
c.c.Endpoint("records", c.id, "chunks"), url.Values{}, files...)
|
|
return err
|
|
}
|
|
|
|
func (c *chunkRW) Close() error {
|
|
return nil
|
|
}
|
|
|
|
// TOODO(klizhentas) this should be just including appropriate backends
|
|
type ClientI interface {
|
|
GetSessions() ([]session.Session, error)
|
|
GetSession(id string) (*session.Session, error)
|
|
DeleteSession(id string) error
|
|
UpsertSession(id string, ttl time.Duration) error
|
|
UpsertParty(id string, p session.Party, ttl time.Duration) 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)
|
|
LogEntry(en lunk.Entry) error
|
|
GetEvents(filter events.Filter) ([]lunk.Entry, error)
|
|
GetChunkWriter(id string) (recorder.ChunkWriteCloser, error)
|
|
GetChunkReader(id string) (recorder.ChunkReadCloser, 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) (hotpURL string, hotpQR []byte, err error)
|
|
CheckPassword(user string, password []byte, hotpToken string) error
|
|
SignIn(user string, password []byte) (string, error)
|
|
GetWebSession(user string, sid string) (string, error)
|
|
GetWebSessionsKeys(user string) ([]services.AuthorizedKey, error)
|
|
DeleteWebSession(user string, sid string) error
|
|
GetUsers() ([]string, error)
|
|
DeleteUser(user string) 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)
|
|
GenerateKeyPair(pass string) ([]byte, []byte, error)
|
|
GenerateHostCert(key []byte, id, hostname string, ttl time.Duration) ([]byte, error)
|
|
GenerateUserCert(key []byte, id, user string, ttl time.Duration) ([]byte, error)
|
|
ResetHostCA() error
|
|
ResetUserCA() error
|
|
}
|