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.
|
|
|
|
*/
|
2016-02-23 20:03:34 +00:00
|
|
|
|
2015-03-02 20:11:23 +00:00
|
|
|
package auth
|
|
|
|
|
|
|
|
import (
|
2016-04-05 16:58:16 +00:00
|
|
|
"encoding/json"
|
2015-03-02 20:11:23 +00:00
|
|
|
"fmt"
|
|
|
|
"net/http"
|
2016-04-03 05:20:51 +00:00
|
|
|
"net/url"
|
2016-04-27 05:55:06 +00:00
|
|
|
"strconv"
|
2015-03-02 20:11:23 +00:00
|
|
|
"time"
|
|
|
|
|
2015-08-25 17:54:16 +00:00
|
|
|
"github.com/gravitational/teleport"
|
2016-04-25 06:32:44 +00:00
|
|
|
"github.com/gravitational/teleport/lib/events"
|
2016-02-23 20:03:34 +00:00
|
|
|
"github.com/gravitational/teleport/lib/httplib"
|
2015-10-05 17:36:55 +00:00
|
|
|
"github.com/gravitational/teleport/lib/services"
|
2015-10-05 14:33:25 +00:00
|
|
|
"github.com/gravitational/teleport/lib/session"
|
2016-03-02 01:18:06 +00:00
|
|
|
"github.com/gravitational/teleport/lib/utils"
|
2015-07-09 03:57:34 +00:00
|
|
|
|
2016-02-28 21:00:38 +00:00
|
|
|
log "github.com/Sirupsen/logrus"
|
2016-01-21 18:18:59 +00:00
|
|
|
"github.com/gravitational/trace"
|
2016-01-20 15:52:25 +00:00
|
|
|
"github.com/julienschmidt/httprouter"
|
2016-10-14 06:51:16 +00:00
|
|
|
|
|
|
|
"github.com/tstranex/u2f"
|
2015-03-02 20:11:23 +00:00
|
|
|
)
|
|
|
|
|
2016-05-30 08:27:33 +00:00
|
|
|
type APIConfig struct {
|
2016-12-12 00:52:22 +00:00
|
|
|
AuthServer *AuthServer
|
|
|
|
SessionService session.Service
|
|
|
|
AuditLog events.IAuditLog
|
|
|
|
NewChecker NewChecker
|
2016-05-30 08:27:33 +00:00
|
|
|
}
|
|
|
|
|
2016-05-30 18:54:22 +00:00
|
|
|
// APIServer implements http API server for AuthServer interface
|
|
|
|
type APIServer struct {
|
2016-12-12 00:52:22 +00:00
|
|
|
APIConfig
|
2016-05-30 18:54:22 +00:00
|
|
|
httprouter.Router
|
2016-05-30 08:27:33 +00:00
|
|
|
}
|
|
|
|
|
2016-02-23 20:03:34 +00:00
|
|
|
// NewAPIServer returns a new instance of APIServer HTTP handler
|
2016-12-13 22:20:52 +00:00
|
|
|
func NewAPIServer(config *APIConfig) http.Handler {
|
2016-05-30 18:54:22 +00:00
|
|
|
srv := APIServer{
|
2016-12-13 03:26:59 +00:00
|
|
|
APIConfig: *config,
|
2015-03-02 20:11:23 +00:00
|
|
|
}
|
|
|
|
srv.Router = *httprouter.New()
|
|
|
|
|
2016-02-16 17:36:02 +00:00
|
|
|
// Operations on certificate authorities
|
2016-12-12 00:52:22 +00:00
|
|
|
srv.GET("/v1/domain", srv.withAuth(srv.getDomainName))
|
|
|
|
srv.POST("/v1/authorities/:type", srv.withAuth(srv.upsertCertAuthority))
|
|
|
|
srv.DELETE("/v1/authorities/:type/:domain", srv.withAuth(srv.deleteCertAuthority))
|
2016-12-14 23:48:36 +00:00
|
|
|
srv.GET("/v1/authorities/:type/:domain", srv.withAuth(srv.getCertAuthority))
|
2016-12-12 00:52:22 +00:00
|
|
|
srv.GET("/v1/authorities/:type", srv.withAuth(srv.getCertAuthorities))
|
2015-03-02 20:11:23 +00:00
|
|
|
|
|
|
|
// Generating certificates for user and host authorities
|
2016-12-12 00:52:22 +00:00
|
|
|
srv.POST("/v1/ca/host/certs", srv.withAuth(srv.generateHostCert))
|
|
|
|
srv.POST("/v1/ca/user/certs", srv.withAuth(srv.generateUserCert))
|
2015-03-02 20:11:23 +00:00
|
|
|
|
|
|
|
// Operations on users
|
2016-12-12 00:52:22 +00:00
|
|
|
srv.GET("/v1/users", srv.withAuth(srv.getUsers))
|
|
|
|
srv.GET("/v1/users/:user", srv.withAuth(srv.getUser))
|
|
|
|
srv.DELETE("/v1/users/:user", srv.withAuth(srv.deleteUser))
|
2015-03-02 20:11:23 +00:00
|
|
|
|
|
|
|
// Generating keypairs
|
2016-12-12 00:52:22 +00:00
|
|
|
srv.POST("/v1/keypair", srv.withAuth(srv.generateKeyPair))
|
2015-03-19 04:13:56 +00:00
|
|
|
|
|
|
|
// Passwords and sessions
|
2016-12-12 00:52:22 +00:00
|
|
|
srv.POST("/v1/users", srv.withAuth(srv.upsertUser))
|
|
|
|
srv.POST("/v1/users/:user/web/password", srv.withAuth(srv.upsertPassword))
|
|
|
|
srv.POST("/v1/users/:user/web/password/check", srv.withAuth(srv.checkPassword))
|
|
|
|
srv.POST("/v1/users/:user/web/signin", srv.withAuth(srv.signIn))
|
2016-12-15 00:36:55 +00:00
|
|
|
srv.GET("/v1/users/:user/web/signin/preauth", srv.withAuth(srv.preAuthenticatedSignIn))
|
2016-12-12 00:52:22 +00:00
|
|
|
srv.POST("/v1/users/:user/web/sessions", srv.withAuth(srv.createWebSession))
|
|
|
|
srv.GET("/v1/users/:user/web/sessions/:sid", srv.withAuth(srv.getWebSession))
|
|
|
|
srv.DELETE("/v1/users/:user/web/sessions/:sid", srv.withAuth(srv.deleteWebSession))
|
|
|
|
srv.GET("/v1/signuptokens/:token", srv.withAuth(srv.getSignupTokenData))
|
|
|
|
srv.POST("/v1/signuptokens/users", srv.withAuth(srv.createUserWithToken))
|
|
|
|
srv.POST("/v1/signuptokens", srv.withAuth(srv.createSignupToken))
|
2015-03-19 04:13:56 +00:00
|
|
|
|
2015-07-11 00:24:44 +00:00
|
|
|
// Servers and presence heartbeat
|
2016-12-13 22:20:52 +00:00
|
|
|
srv.POST("/v1/namespaces/:namespace/nodes", srv.withAuth(srv.upsertNode))
|
|
|
|
srv.GET("/v1/namespaces/:namespace/nodes", srv.withAuth(srv.getNodes))
|
2016-12-12 00:52:22 +00:00
|
|
|
srv.POST("/v1/authservers", srv.withAuth(srv.upsertAuthServer))
|
|
|
|
srv.GET("/v1/authservers", srv.withAuth(srv.getAuthServers))
|
|
|
|
srv.POST("/v1/proxies", srv.withAuth(srv.upsertProxy))
|
|
|
|
srv.GET("/v1/proxies", srv.withAuth(srv.getProxies))
|
2015-03-02 20:11:23 +00:00
|
|
|
|
2016-03-18 01:42:04 +00:00
|
|
|
// Reverse tunnels
|
2016-12-12 00:52:22 +00:00
|
|
|
srv.POST("/v1/reversetunnels", srv.withAuth(srv.upsertReverseTunnel))
|
|
|
|
srv.GET("/v1/reversetunnels", srv.withAuth(srv.getReverseTunnels))
|
|
|
|
srv.DELETE("/v1/reversetunnels/:domain", srv.withAuth(srv.deleteReverseTunnel))
|
2016-03-18 01:42:04 +00:00
|
|
|
|
2015-05-07 03:10:44 +00:00
|
|
|
// Tokens
|
2016-12-12 00:52:22 +00:00
|
|
|
srv.POST("/v1/tokens", srv.withAuth(srv.generateToken))
|
|
|
|
srv.POST("/v1/tokens/register", srv.withAuth(srv.registerUsingToken))
|
|
|
|
srv.POST("/v1/tokens/register/auth", srv.withAuth(srv.registerNewAuthServer))
|
2016-02-23 20:03:34 +00:00
|
|
|
|
2015-06-30 23:12:18 +00:00
|
|
|
// Sesssions
|
2016-12-13 22:20:52 +00:00
|
|
|
srv.POST("/v1/namespaces/:namespace/sessions", srv.withAuth(srv.createSession))
|
|
|
|
srv.PUT("/v1/namespaces/:namespace/sessions/:id", srv.withAuth(srv.updateSession))
|
|
|
|
srv.GET("/v1/namespaces/:namespace/sessions", srv.withAuth(srv.getSessions))
|
|
|
|
srv.GET("/v1/namespaces/:namespace/sessions/:id", srv.withAuth(srv.getSession))
|
|
|
|
srv.POST("/v1/namespaces/:namespace/sessions/:id/stream", srv.withAuth(srv.postSessionChunk))
|
|
|
|
srv.GET("/v1/namespaces/:namespace/sessions/:id/stream", srv.withAuth(srv.getSessionChunk))
|
|
|
|
srv.GET("/v1/namespaces/:namespace/sessions/:id/events", srv.withAuth(srv.getSessionEvents))
|
2015-06-30 23:12:18 +00:00
|
|
|
|
2016-04-03 05:20:51 +00:00
|
|
|
// OIDC stuff
|
2016-12-12 00:52:22 +00:00
|
|
|
srv.POST("/v1/oidc/connectors", srv.withAuth(srv.upsertOIDCConnector))
|
|
|
|
srv.GET("/v1/oidc/connectors", srv.withAuth(srv.getOIDCConnectors))
|
|
|
|
srv.GET("/v1/oidc/connectors/:id", srv.withAuth(srv.getOIDCConnector))
|
|
|
|
srv.DELETE("/v1/oidc/connectors/:id", srv.withAuth(srv.deleteOIDCConnector))
|
|
|
|
srv.POST("/v1/oidc/requests/create", srv.withAuth(srv.createOIDCAuthRequest))
|
|
|
|
srv.POST("/v1/oidc/requests/validate", srv.withAuth(srv.validateOIDCAuthCallback))
|
2016-04-03 05:20:51 +00:00
|
|
|
|
2016-12-13 03:26:59 +00:00
|
|
|
// Namespaces
|
|
|
|
srv.POST("/v1/namespaces", srv.withAuth(srv.upsertNamespace))
|
|
|
|
srv.GET("/v1/namespaces", srv.withAuth(srv.getNamespaces))
|
|
|
|
srv.GET("/v1/namespaces/:namespace", srv.withAuth(srv.getNamespace))
|
|
|
|
srv.DELETE("/v1/namespaces/:namespace", srv.withAuth(srv.deleteNamespace))
|
|
|
|
|
|
|
|
// Roles
|
|
|
|
srv.POST("/v1/roles", srv.withAuth(srv.upsertRole))
|
|
|
|
srv.GET("/v1/roles", srv.withAuth(srv.getRoles))
|
|
|
|
srv.GET("/v1/roles/:role", srv.withAuth(srv.getRole))
|
|
|
|
srv.DELETE("/v1/roles/:role", srv.withAuth(srv.deleteRole))
|
|
|
|
|
2016-11-09 06:49:59 +00:00
|
|
|
// U2F stuff
|
2016-12-15 00:36:55 +00:00
|
|
|
srv.GET("/v1/u2f/signuptokens/:token", srv.withAuth(srv.getSignupU2FRegisterRequest))
|
|
|
|
srv.POST("/v1/u2f/users", srv.withAuth(srv.createUserWithU2FToken))
|
|
|
|
srv.POST("/v1/u2f/users/:user/sign", srv.withAuth(srv.u2fSignRequest))
|
|
|
|
srv.GET("/v1/u2f/appid", srv.withAuth(srv.getU2FAppID))
|
2016-11-09 06:49:59 +00:00
|
|
|
|
2016-05-17 01:55:56 +00:00
|
|
|
// Provisioning tokens
|
2016-12-12 00:52:22 +00:00
|
|
|
srv.GET("/v1/tokens", srv.withAuth(srv.getTokens))
|
2016-12-14 23:48:36 +00:00
|
|
|
srv.GET("/v1/tokens/:token", srv.withAuth(srv.getToken))
|
2016-12-12 00:52:22 +00:00
|
|
|
srv.DELETE("/v1/tokens/:token", srv.withAuth(srv.deleteToken))
|
2016-05-17 01:55:56 +00:00
|
|
|
|
2016-04-24 22:35:33 +00:00
|
|
|
// Audit logs AKA events
|
2016-12-12 00:52:22 +00:00
|
|
|
srv.POST("/v1/events", srv.withAuth(srv.emitAuditEvent))
|
|
|
|
srv.GET("/v1/events", srv.withAuth(srv.searchEvents))
|
2016-04-24 22:35:33 +00:00
|
|
|
|
2016-12-13 22:20:52 +00:00
|
|
|
return httplib.RewritePaths(&srv.Router,
|
|
|
|
httplib.Rewrite("/v1/nodes", "/v1/namespaces/default/nodes"),
|
|
|
|
httplib.Rewrite("/v1/sessions", "/v1/namespaces/default/sessions"),
|
|
|
|
httplib.Rewrite("/v1/sessions/([^/]+)/(.*)", "/v1/namespaces/default/sessions/$1/$2"),
|
|
|
|
)
|
2015-03-02 20:11:23 +00:00
|
|
|
}
|
|
|
|
|
2016-12-12 00:52:22 +00:00
|
|
|
// HandlerWithAuthFunc is http handler with passed auth context
|
|
|
|
type HandlerWithAuthFunc func(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params) (interface{}, error)
|
|
|
|
|
2016-12-13 03:26:59 +00:00
|
|
|
func (s *APIServer) withAuth(handler HandlerWithAuthFunc) httprouter.Handle {
|
2016-12-12 00:52:22 +00:00
|
|
|
return httplib.MakeHandler(func(w http.ResponseWriter, r *http.Request, p httprouter.Params) (interface{}, error) {
|
|
|
|
// SSH-to-HTTP gateway (tun server) sets HTTP basic auth to SSH cert principal
|
|
|
|
// This allows us to make sure that users can only request new certificates
|
|
|
|
// only for themselves, except admin users
|
|
|
|
caller, _, ok := r.BasicAuth()
|
|
|
|
if !ok {
|
|
|
|
return nil, trace.AccessDenied("missing username or password")
|
|
|
|
}
|
|
|
|
checker, err := s.NewChecker(caller)
|
|
|
|
if err != nil {
|
|
|
|
log.Debugf("failed to create checker: %v for %v", err, caller)
|
|
|
|
return nil, trace.AccessDenied("missing username or password")
|
|
|
|
}
|
|
|
|
auth := &AuthWithRoles{
|
|
|
|
authServer: s.AuthServer,
|
|
|
|
user: caller,
|
|
|
|
checker: checker,
|
|
|
|
sessions: s.SessionService,
|
|
|
|
alog: s.AuditLog,
|
|
|
|
}
|
2016-12-13 03:26:59 +00:00
|
|
|
return handler(auth, w, r, p)
|
2016-12-12 00:52:22 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2016-02-23 20:03:34 +00:00
|
|
|
type upsertServerReq struct {
|
|
|
|
Server services.Server `json:"server"`
|
|
|
|
TTL time.Duration `json:"ttl"`
|
2015-03-19 04:13:56 +00:00
|
|
|
}
|
|
|
|
|
2016-12-13 22:20:52 +00:00
|
|
|
// upsertServer is a common utility function
|
2016-12-13 03:26:59 +00:00
|
|
|
func (s *APIServer) upsertServer(auth ClientI, role teleport.Role, w http.ResponseWriter, r *http.Request, p httprouter.Params) (interface{}, error) {
|
2016-02-23 20:03:34 +00:00
|
|
|
var req upsertServerReq
|
|
|
|
if err := httplib.ReadJSON(r, &req); err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
2016-03-02 19:10:07 +00:00
|
|
|
// if server sent "local" IP address to us, replace the ip/host part with the remote address we see
|
|
|
|
// on the socket, but keep the original port:
|
2016-03-02 01:18:06 +00:00
|
|
|
req.Server.Addr = utils.ReplaceLocalhost(req.Server.Addr, r.RemoteAddr)
|
|
|
|
|
2016-03-12 04:09:40 +00:00
|
|
|
switch role {
|
|
|
|
case teleport.RoleNode:
|
2016-12-13 22:20:52 +00:00
|
|
|
req.Server.Namespace = p.ByName("namespace")
|
2016-12-13 03:26:59 +00:00
|
|
|
if err := auth.UpsertNode(req.Server, req.TTL); err != nil {
|
2016-03-12 04:09:40 +00:00
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
case teleport.RoleAuth:
|
2016-12-13 03:26:59 +00:00
|
|
|
if err := auth.UpsertAuthServer(req.Server, req.TTL); err != nil {
|
2016-03-12 04:09:40 +00:00
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
case teleport.RoleProxy:
|
2016-12-13 03:26:59 +00:00
|
|
|
if err := auth.UpsertProxy(req.Server, req.TTL); err != nil {
|
2016-03-12 04:09:40 +00:00
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
2015-03-19 04:13:56 +00:00
|
|
|
}
|
2016-02-23 20:03:34 +00:00
|
|
|
return message("ok"), nil
|
2015-03-19 04:13:56 +00:00
|
|
|
}
|
|
|
|
|
2016-03-12 04:09:40 +00:00
|
|
|
// upsertNode is called by remote SSH nodes when they ping back into the auth service
|
2016-12-13 03:26:59 +00:00
|
|
|
func (s *APIServer) upsertNode(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params) (interface{}, error) {
|
|
|
|
return s.upsertServer(auth, teleport.RoleNode, w, r, p)
|
2016-03-12 04:09:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// getNodes returns registered SSH nodes
|
2016-12-13 03:26:59 +00:00
|
|
|
func (s *APIServer) getNodes(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params) (interface{}, error) {
|
2016-12-13 22:20:52 +00:00
|
|
|
servers, err := auth.GetNodes(p.ByName("namespace"))
|
2016-03-12 04:09:40 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
return servers, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// upsertProxy is called by remote SSH nodes when they ping back into the auth service
|
2016-12-13 03:26:59 +00:00
|
|
|
func (s *APIServer) upsertProxy(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params) (interface{}, error) {
|
|
|
|
return s.upsertServer(auth, teleport.RoleProxy, w, r, p)
|
2016-03-12 04:09:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// getProxies returns registered proxies
|
2016-12-13 03:26:59 +00:00
|
|
|
func (s *APIServer) getProxies(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params) (interface{}, error) {
|
|
|
|
servers, err := auth.GetProxies()
|
2015-03-19 04:13:56 +00:00
|
|
|
if err != nil {
|
2016-02-23 20:03:34 +00:00
|
|
|
return nil, trace.Wrap(err)
|
2015-03-19 04:13:56 +00:00
|
|
|
}
|
2016-02-23 20:03:34 +00:00
|
|
|
return servers, nil
|
2015-03-19 04:13:56 +00:00
|
|
|
}
|
|
|
|
|
2016-03-12 04:09:40 +00:00
|
|
|
// upsertAuthServer is called by remote Auth servers when they ping back into the auth service
|
2016-12-13 03:26:59 +00:00
|
|
|
func (s *APIServer) upsertAuthServer(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params) (interface{}, error) {
|
|
|
|
return s.upsertServer(auth, teleport.RoleAuth, w, r, p)
|
2016-03-12 04:09:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// getAuthServers returns registered auth servers
|
2016-12-13 03:26:59 +00:00
|
|
|
func (s *APIServer) getAuthServers(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params) (interface{}, error) {
|
|
|
|
servers, err := auth.GetAuthServers()
|
2015-03-19 04:13:56 +00:00
|
|
|
if err != nil {
|
2016-02-23 20:03:34 +00:00
|
|
|
return nil, trace.Wrap(err)
|
2015-03-19 04:13:56 +00:00
|
|
|
}
|
2016-02-23 20:03:34 +00:00
|
|
|
return servers, nil
|
2015-03-19 04:13:56 +00:00
|
|
|
}
|
|
|
|
|
2016-03-18 01:42:04 +00:00
|
|
|
type upsertReverseTunnelReq struct {
|
|
|
|
ReverseTunnel services.ReverseTunnel `json:"reverse_tunnel"`
|
|
|
|
TTL time.Duration `json:"ttl"`
|
|
|
|
}
|
|
|
|
|
|
|
|
// upsertReverseTunnel is called by admin to create a reverse tunnel to remote proxy
|
2016-12-13 03:26:59 +00:00
|
|
|
func (s *APIServer) upsertReverseTunnel(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params) (interface{}, error) {
|
2016-03-18 01:42:04 +00:00
|
|
|
var req upsertReverseTunnelReq
|
|
|
|
if err := httplib.ReadJSON(r, &req); err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
2016-12-13 03:26:59 +00:00
|
|
|
if err := auth.UpsertReverseTunnel(req.ReverseTunnel, req.TTL); err != nil {
|
2016-03-18 01:42:04 +00:00
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
return message("ok"), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// getReverseTunnels returns a list of reverse tunnels
|
2016-12-13 03:26:59 +00:00
|
|
|
func (s *APIServer) getReverseTunnels(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params) (interface{}, error) {
|
|
|
|
reverseTunnels, err := auth.GetReverseTunnels()
|
2016-03-18 01:42:04 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
return reverseTunnels, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// deleteReverseTunnel deletes reverse tunnel
|
2016-12-13 03:26:59 +00:00
|
|
|
func (s *APIServer) deleteReverseTunnel(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params) (interface{}, error) {
|
2016-03-18 01:42:04 +00:00
|
|
|
domainName := p[0].Value
|
2016-12-13 03:26:59 +00:00
|
|
|
err := auth.DeleteReverseTunnel(domainName)
|
2016-03-18 01:42:04 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
return message(fmt.Sprintf("reverse tunnel %v deleted", domainName)), nil
|
|
|
|
}
|
|
|
|
|
2016-05-17 01:55:56 +00:00
|
|
|
// getTokens returns a list of active provisioning tokens. expired (inactive) tokens are not returned
|
2016-12-13 03:26:59 +00:00
|
|
|
func (s *APIServer) getTokens(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params) (interface{}, error) {
|
|
|
|
tokens, err := auth.GetTokens()
|
2016-05-17 03:10:59 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
return tokens, nil
|
2016-05-17 01:55:56 +00:00
|
|
|
}
|
|
|
|
|
2016-12-14 23:48:36 +00:00
|
|
|
// getTokens returns provisioning token by name
|
|
|
|
func (s *APIServer) getToken(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params) (interface{}, error) {
|
|
|
|
token, err := auth.GetToken(p.ByName("token"))
|
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
return token, nil
|
|
|
|
}
|
|
|
|
|
2016-05-17 01:55:56 +00:00
|
|
|
// deleteToken deletes (revokes) a token by its value
|
2016-12-13 03:26:59 +00:00
|
|
|
func (s *APIServer) deleteToken(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params) (interface{}, error) {
|
2016-05-17 01:55:56 +00:00
|
|
|
token := p.ByName("token")
|
2016-12-13 03:26:59 +00:00
|
|
|
if err := auth.DeleteToken(token); err != nil {
|
2016-05-17 03:10:59 +00:00
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
return message(fmt.Sprintf("Token %v deleted", token)), nil
|
2016-05-17 01:55:56 +00:00
|
|
|
}
|
|
|
|
|
2016-12-13 03:26:59 +00:00
|
|
|
func (s *APIServer) deleteWebSession(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params) (interface{}, error) {
|
2015-03-19 04:13:56 +00:00
|
|
|
user, sid := p[0].Value, p[1].Value
|
2016-12-13 03:26:59 +00:00
|
|
|
err := auth.DeleteWebSession(user, sid)
|
2015-03-19 04:13:56 +00:00
|
|
|
if err != nil {
|
2016-02-23 20:03:34 +00:00
|
|
|
return nil, trace.Wrap(err)
|
2015-03-19 04:13:56 +00:00
|
|
|
}
|
2016-02-23 20:03:34 +00:00
|
|
|
return message(fmt.Sprintf("session '%v' for user '%v' deleted", sid, user)), nil
|
2015-03-19 04:13:56 +00:00
|
|
|
}
|
|
|
|
|
2016-12-13 03:26:59 +00:00
|
|
|
func (s *APIServer) getWebSession(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params) (interface{}, error) {
|
2015-03-19 04:13:56 +00:00
|
|
|
user, sid := p[0].Value, p[1].Value
|
2016-12-13 03:26:59 +00:00
|
|
|
sess, err := auth.GetWebSessionInfo(user, sid)
|
2015-03-19 04:13:56 +00:00
|
|
|
if err != nil {
|
2016-02-23 20:03:34 +00:00
|
|
|
return nil, trace.Wrap(err)
|
2015-03-19 04:13:56 +00:00
|
|
|
}
|
2016-02-24 01:26:23 +00:00
|
|
|
return sess, nil
|
2015-03-19 04:13:56 +00:00
|
|
|
}
|
|
|
|
|
2016-02-23 20:03:34 +00:00
|
|
|
type signInReq struct {
|
|
|
|
Password string `json:"password"`
|
|
|
|
}
|
2015-03-19 04:13:56 +00:00
|
|
|
|
2016-12-13 03:26:59 +00:00
|
|
|
func (s *APIServer) signIn(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params) (interface{}, error) {
|
2016-02-23 20:03:34 +00:00
|
|
|
var req *signInReq
|
|
|
|
if err := httplib.ReadJSON(r, &req); err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
2015-03-19 04:13:56 +00:00
|
|
|
}
|
|
|
|
user := p[0].Value
|
2016-12-13 03:26:59 +00:00
|
|
|
sess, err := auth.SignIn(user, []byte(req.Password))
|
2015-03-19 04:13:56 +00:00
|
|
|
if err != nil {
|
2016-02-23 20:03:34 +00:00
|
|
|
return nil, trace.Wrap(err)
|
2015-03-19 04:13:56 +00:00
|
|
|
}
|
2016-02-24 01:26:23 +00:00
|
|
|
return sess, nil
|
2015-03-19 04:13:56 +00:00
|
|
|
}
|
|
|
|
|
2016-12-15 00:36:55 +00:00
|
|
|
func (s *APIServer) preAuthenticatedSignIn(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params) (interface{}, error) {
|
2016-10-16 21:03:43 +00:00
|
|
|
user := p[0].Value
|
2016-12-15 00:36:55 +00:00
|
|
|
sess, err := auth.PreAuthenticatedSignIn(user)
|
2016-10-16 21:03:43 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
return sess, nil
|
|
|
|
}
|
|
|
|
|
2016-12-15 00:36:55 +00:00
|
|
|
func (s *APIServer) u2fSignRequest(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params) (interface{}, error) {
|
2016-10-14 06:51:16 +00:00
|
|
|
var req *signInReq
|
|
|
|
if err := httplib.ReadJSON(r, &req); err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
user := p[0].Value
|
|
|
|
pass := []byte(req.Password)
|
2016-12-15 00:36:55 +00:00
|
|
|
u2fSignReq, err := auth.GetU2FSignRequest(user, pass)
|
2016-10-14 06:51:16 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
return u2fSignReq, nil
|
|
|
|
}
|
|
|
|
|
2016-02-26 22:57:51 +00:00
|
|
|
type createWebSessionReq struct {
|
|
|
|
PrevSessionID string `json:"prev_session_id"`
|
|
|
|
}
|
|
|
|
|
2016-12-13 03:26:59 +00:00
|
|
|
func (s *APIServer) createWebSession(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params) (interface{}, error) {
|
2016-02-26 22:57:51 +00:00
|
|
|
var req *createWebSessionReq
|
|
|
|
if err := httplib.ReadJSON(r, &req); err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
user := p[0].Value
|
2016-04-10 20:29:32 +00:00
|
|
|
if req.PrevSessionID != "" {
|
2016-12-13 03:26:59 +00:00
|
|
|
sess, err := auth.ExtendWebSession(user, req.PrevSessionID)
|
2016-04-10 20:29:32 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
return sess, nil
|
|
|
|
}
|
2016-12-13 03:26:59 +00:00
|
|
|
sess, err := auth.CreateWebSession(user)
|
2016-02-26 22:57:51 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
return sess, nil
|
|
|
|
}
|
|
|
|
|
2016-02-23 20:03:34 +00:00
|
|
|
type upsertPasswordReq struct {
|
|
|
|
Password string `json:"password"`
|
|
|
|
}
|
2015-03-19 04:13:56 +00:00
|
|
|
|
2016-02-23 20:03:34 +00:00
|
|
|
type upsertPasswordResponse struct {
|
|
|
|
HotpURL string `json:"hotp_url"`
|
|
|
|
HotpQR []byte `json:"hotp_qr"`
|
|
|
|
}
|
|
|
|
|
2016-12-13 03:26:59 +00:00
|
|
|
func (s *APIServer) upsertPassword(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params) (interface{}, error) {
|
2016-02-23 20:03:34 +00:00
|
|
|
var req *upsertPasswordReq
|
|
|
|
if err := httplib.ReadJSON(r, &req); err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
2015-03-19 04:13:56 +00:00
|
|
|
}
|
|
|
|
user := p[0].Value
|
2016-12-13 03:26:59 +00:00
|
|
|
hotpURL, hotpQR, err := auth.UpsertPassword(user, []byte(req.Password))
|
2015-10-23 00:45:51 +00:00
|
|
|
if err != nil {
|
2016-02-23 20:03:34 +00:00
|
|
|
return nil, trace.Wrap(err)
|
2015-03-19 04:13:56 +00:00
|
|
|
}
|
2016-02-23 20:03:34 +00:00
|
|
|
return &upsertPasswordResponse{HotpURL: hotpURL, HotpQR: hotpQR}, nil
|
2015-03-19 04:13:56 +00:00
|
|
|
}
|
|
|
|
|
2016-03-31 18:40:22 +00:00
|
|
|
type upsertUserReq struct {
|
|
|
|
User services.User `json:"user"`
|
|
|
|
}
|
|
|
|
|
2016-04-05 16:58:16 +00:00
|
|
|
type upsertUserReqRaw struct {
|
|
|
|
User json.RawMessage `json:"user"`
|
|
|
|
}
|
|
|
|
|
2016-12-13 03:26:59 +00:00
|
|
|
func (s *APIServer) upsertUser(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params) (interface{}, error) {
|
2016-04-05 16:58:16 +00:00
|
|
|
var req *upsertUserReqRaw
|
2016-03-31 18:40:22 +00:00
|
|
|
if err := httplib.ReadJSON(r, &req); err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
2016-12-10 01:31:05 +00:00
|
|
|
user, err := services.GetUserMarshaler().UnmarshalUser(req.User)
|
2016-04-05 16:58:16 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
2016-12-13 03:26:59 +00:00
|
|
|
err = auth.UpsertUser(user)
|
2016-03-31 18:40:22 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
2016-04-05 16:58:16 +00:00
|
|
|
return message(fmt.Sprintf("'%v' user upserted", user.GetName())), nil
|
2016-03-31 18:40:22 +00:00
|
|
|
}
|
|
|
|
|
2016-02-23 20:03:34 +00:00
|
|
|
type checkPasswordReq struct {
|
|
|
|
Password string `json:"password"`
|
|
|
|
HOTPToken string `json:"hotp_token"`
|
|
|
|
}
|
2015-03-19 04:13:56 +00:00
|
|
|
|
2016-12-13 03:26:59 +00:00
|
|
|
func (s *APIServer) checkPassword(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params) (interface{}, error) {
|
2016-02-23 20:03:34 +00:00
|
|
|
var req checkPasswordReq
|
|
|
|
if err := httplib.ReadJSON(r, &req); err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
2015-03-19 04:13:56 +00:00
|
|
|
}
|
|
|
|
user := p[0].Value
|
2016-12-13 03:26:59 +00:00
|
|
|
if err := auth.CheckPassword(user, []byte(req.Password), req.HOTPToken); err != nil {
|
2016-02-23 20:03:34 +00:00
|
|
|
return nil, trace.Wrap(err)
|
2015-03-19 04:13:56 +00:00
|
|
|
}
|
2016-02-23 20:03:34 +00:00
|
|
|
return message(fmt.Sprintf("'%v' user password matches", user)), nil
|
2015-03-19 04:13:56 +00:00
|
|
|
}
|
|
|
|
|
2016-12-13 03:26:59 +00:00
|
|
|
func (s *APIServer) getUser(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params) (interface{}, error) {
|
|
|
|
user, err := auth.GetUser(p[0].Value)
|
2016-04-05 16:58:16 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
return user, nil
|
|
|
|
}
|
|
|
|
|
2016-12-13 03:26:59 +00:00
|
|
|
func (s *APIServer) getUsers(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params) (interface{}, error) {
|
|
|
|
users, err := auth.GetUsers()
|
2015-03-02 20:11:23 +00:00
|
|
|
if err != nil {
|
2016-02-23 20:03:34 +00:00
|
|
|
return nil, trace.Wrap(err)
|
2015-03-02 20:11:23 +00:00
|
|
|
}
|
2016-02-23 20:03:34 +00:00
|
|
|
return users, nil
|
2015-03-02 20:11:23 +00:00
|
|
|
}
|
|
|
|
|
2016-12-13 03:26:59 +00:00
|
|
|
func (s *APIServer) deleteUser(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params) (interface{}, error) {
|
2015-03-02 20:11:23 +00:00
|
|
|
user := p[0].Value
|
2016-12-13 03:26:59 +00:00
|
|
|
if err := auth.DeleteUser(user); err != nil {
|
2016-02-23 20:03:34 +00:00
|
|
|
return nil, trace.Wrap(err)
|
2015-03-02 20:11:23 +00:00
|
|
|
}
|
2016-02-23 20:03:34 +00:00
|
|
|
return message(fmt.Sprintf("user '%v' deleted", user)), nil
|
|
|
|
}
|
2015-03-02 20:11:23 +00:00
|
|
|
|
2016-02-23 20:03:34 +00:00
|
|
|
type generateKeyPairReq struct {
|
|
|
|
Password string `json:"password"`
|
2015-03-02 20:11:23 +00:00
|
|
|
}
|
|
|
|
|
2016-02-23 20:03:34 +00:00
|
|
|
type generateKeyPairResponse struct {
|
|
|
|
PrivKey []byte `json:"privkey"`
|
|
|
|
PubKey string `json:"pubkey"`
|
|
|
|
}
|
2015-03-02 20:11:23 +00:00
|
|
|
|
2016-12-13 03:26:59 +00:00
|
|
|
func (s *APIServer) generateKeyPair(auth ClientI, w http.ResponseWriter, r *http.Request, _ httprouter.Params) (interface{}, error) {
|
2016-02-23 20:03:34 +00:00
|
|
|
var req *generateKeyPairReq
|
|
|
|
if err := httplib.ReadJSON(r, &req); err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
2015-03-02 20:11:23 +00:00
|
|
|
}
|
|
|
|
|
2016-12-13 03:26:59 +00:00
|
|
|
priv, pub, err := auth.GenerateKeyPair(req.Password)
|
2015-03-02 20:11:23 +00:00
|
|
|
if err != nil {
|
2016-02-23 20:03:34 +00:00
|
|
|
return nil, trace.Wrap(err)
|
2015-03-02 20:11:23 +00:00
|
|
|
}
|
2016-02-23 20:03:34 +00:00
|
|
|
return &generateKeyPairResponse{PrivKey: priv, PubKey: string(pub)}, nil
|
|
|
|
}
|
2015-03-02 20:11:23 +00:00
|
|
|
|
2016-02-23 20:03:34 +00:00
|
|
|
type generateHostCertReq struct {
|
2016-05-11 03:27:18 +00:00
|
|
|
Key []byte `json:"key"`
|
|
|
|
Hostname string `json:"hostname"`
|
|
|
|
AuthDomain string `json:"auth_domain"`
|
|
|
|
Roles teleport.Roles `json:"roles"`
|
|
|
|
TTL time.Duration `json:"ttl"`
|
2015-03-02 20:11:23 +00:00
|
|
|
}
|
|
|
|
|
2016-12-13 03:26:59 +00:00
|
|
|
func (s *APIServer) generateHostCert(auth ClientI, w http.ResponseWriter, r *http.Request, _ httprouter.Params) (interface{}, error) {
|
2016-02-23 20:03:34 +00:00
|
|
|
var req *generateHostCertReq
|
|
|
|
if err := httplib.ReadJSON(r, &req); err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
2016-02-19 02:07:43 +00:00
|
|
|
}
|
2016-12-13 03:26:59 +00:00
|
|
|
cert, err := auth.GenerateHostCert(req.Key, req.Hostname, req.AuthDomain, req.Roles, req.TTL)
|
2015-03-02 20:11:23 +00:00
|
|
|
if err != nil {
|
2016-02-23 20:03:34 +00:00
|
|
|
return nil, trace.Wrap(err)
|
2015-03-02 20:11:23 +00:00
|
|
|
}
|
2016-02-23 20:03:34 +00:00
|
|
|
return string(cert), nil
|
2015-03-02 20:11:23 +00:00
|
|
|
}
|
|
|
|
|
2016-02-23 20:03:34 +00:00
|
|
|
type generateUserCertReq struct {
|
|
|
|
Key []byte `json:"key"`
|
|
|
|
User string `json:"user"`
|
|
|
|
TTL time.Duration `json:"ttl"`
|
|
|
|
}
|
|
|
|
|
2016-12-13 03:26:59 +00:00
|
|
|
func (s *APIServer) generateUserCert(auth ClientI, w http.ResponseWriter, r *http.Request, _ httprouter.Params) (interface{}, error) {
|
2016-02-23 20:03:34 +00:00
|
|
|
var req *generateUserCertReq
|
|
|
|
if err := httplib.ReadJSON(r, &req); err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
2015-03-02 20:11:23 +00:00
|
|
|
}
|
2016-12-13 03:26:59 +00:00
|
|
|
cert, err := auth.GenerateUserCert(req.Key, req.User, req.TTL)
|
2015-03-02 20:11:23 +00:00
|
|
|
if err != nil {
|
2016-12-15 00:36:55 +00:00
|
|
|
log.Error(trace.DebugReport(err))
|
2016-02-23 20:03:34 +00:00
|
|
|
return nil, trace.Wrap(err)
|
2015-03-02 20:11:23 +00:00
|
|
|
}
|
2016-02-23 20:03:34 +00:00
|
|
|
return string(cert), nil
|
2015-03-02 20:11:23 +00:00
|
|
|
}
|
|
|
|
|
2016-02-23 20:03:34 +00:00
|
|
|
type generateTokenReq struct {
|
2016-05-10 05:28:44 +00:00
|
|
|
Roles teleport.Roles `json:"roles"`
|
|
|
|
TTL time.Duration `json:"ttl"`
|
2016-02-23 20:03:34 +00:00
|
|
|
}
|
2015-05-07 03:10:44 +00:00
|
|
|
|
2016-12-13 03:26:59 +00:00
|
|
|
func (s *APIServer) generateToken(auth ClientI, w http.ResponseWriter, r *http.Request, _ httprouter.Params) (interface{}, error) {
|
2016-02-23 20:03:34 +00:00
|
|
|
var req *generateTokenReq
|
|
|
|
if err := httplib.ReadJSON(r, &req); err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
2015-05-07 03:10:44 +00:00
|
|
|
}
|
2016-12-13 03:26:59 +00:00
|
|
|
token, err := auth.GenerateToken(req.Roles, req.TTL)
|
2015-05-07 03:10:44 +00:00
|
|
|
if err != nil {
|
2016-02-23 20:03:34 +00:00
|
|
|
return nil, trace.Wrap(err)
|
2015-05-07 03:10:44 +00:00
|
|
|
}
|
2016-02-23 20:03:34 +00:00
|
|
|
return string(token), nil
|
2015-05-07 03:10:44 +00:00
|
|
|
}
|
|
|
|
|
2016-02-23 20:03:34 +00:00
|
|
|
type registerUsingTokenReq struct {
|
2016-03-05 01:48:09 +00:00
|
|
|
HostID string `json:"hostID"`
|
2016-02-23 20:03:34 +00:00
|
|
|
Role teleport.Role `json:"role"`
|
|
|
|
Token string `json:"token"`
|
|
|
|
}
|
2015-11-13 01:32:45 +00:00
|
|
|
|
2016-12-13 03:26:59 +00:00
|
|
|
func (s *APIServer) registerUsingToken(auth ClientI, w http.ResponseWriter, r *http.Request, _ httprouter.Params) (interface{}, error) {
|
2016-02-23 20:03:34 +00:00
|
|
|
var req *registerUsingTokenReq
|
|
|
|
if err := httplib.ReadJSON(r, &req); err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
2015-11-13 01:32:45 +00:00
|
|
|
}
|
2016-12-13 03:26:59 +00:00
|
|
|
keys, err := auth.RegisterUsingToken(req.Token, req.HostID, req.Role)
|
2015-11-13 01:32:45 +00:00
|
|
|
if err != nil {
|
2016-02-23 20:03:34 +00:00
|
|
|
return nil, trace.Wrap(err)
|
2015-11-13 01:32:45 +00:00
|
|
|
}
|
2016-02-23 20:03:34 +00:00
|
|
|
return keys, nil
|
2015-11-13 01:32:45 +00:00
|
|
|
}
|
|
|
|
|
2016-02-23 20:03:34 +00:00
|
|
|
type registerNewAuthServerReq struct {
|
2016-03-10 17:41:01 +00:00
|
|
|
Token string `json:"token"`
|
2016-02-23 20:03:34 +00:00
|
|
|
}
|
2015-11-13 01:32:45 +00:00
|
|
|
|
2016-12-13 03:26:59 +00:00
|
|
|
func (s *APIServer) registerNewAuthServer(auth ClientI, w http.ResponseWriter, r *http.Request, _ httprouter.Params) (interface{}, error) {
|
2016-02-23 20:03:34 +00:00
|
|
|
var req *registerNewAuthServerReq
|
|
|
|
if err := httplib.ReadJSON(r, &req); err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
2015-11-13 01:32:45 +00:00
|
|
|
}
|
2016-12-13 03:26:59 +00:00
|
|
|
err := auth.RegisterNewAuthServer(req.Token)
|
2015-11-13 01:32:45 +00:00
|
|
|
if err != nil {
|
2016-02-23 20:03:34 +00:00
|
|
|
return nil, trace.Wrap(err)
|
2015-11-13 01:32:45 +00:00
|
|
|
}
|
2016-03-10 17:41:01 +00:00
|
|
|
return message("ok"), nil
|
2015-11-13 01:32:45 +00:00
|
|
|
}
|
|
|
|
|
2016-02-23 20:03:34 +00:00
|
|
|
type upsertCertAuthorityReq struct {
|
|
|
|
CA services.CertAuthority `json:"ca"`
|
|
|
|
TTL time.Duration `json:"ttl"`
|
2015-03-02 20:11:23 +00:00
|
|
|
}
|
|
|
|
|
2016-12-13 03:26:59 +00:00
|
|
|
func (s *APIServer) upsertCertAuthority(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params) (interface{}, error) {
|
2016-02-23 20:03:34 +00:00
|
|
|
var req *upsertCertAuthorityReq
|
|
|
|
if err := httplib.ReadJSON(r, &req); err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
2015-06-22 21:05:15 +00:00
|
|
|
}
|
2016-12-13 03:26:59 +00:00
|
|
|
if err := auth.UpsertCertAuthority(req.CA, req.TTL); err != nil {
|
2016-02-23 20:03:34 +00:00
|
|
|
return nil, trace.Wrap(err)
|
2016-02-16 17:36:02 +00:00
|
|
|
}
|
2016-02-23 20:03:34 +00:00
|
|
|
return message("ok"), nil
|
2015-06-22 21:05:15 +00:00
|
|
|
}
|
|
|
|
|
2016-12-13 03:26:59 +00:00
|
|
|
func (s *APIServer) getCertAuthorities(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params) (interface{}, error) {
|
2016-04-03 22:06:50 +00:00
|
|
|
loadKeys, _, err := httplib.ParseBool(r.URL.Query(), "load_keys")
|
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
2016-03-28 19:58:34 +00:00
|
|
|
}
|
2016-12-13 03:26:59 +00:00
|
|
|
certs, err := auth.GetCertAuthorities(services.CertAuthType(p[0].Value), loadKeys)
|
2015-11-18 04:39:19 +00:00
|
|
|
if err != nil {
|
2016-02-23 20:03:34 +00:00
|
|
|
return nil, trace.Wrap(err)
|
2015-11-18 04:39:19 +00:00
|
|
|
}
|
2016-02-23 20:03:34 +00:00
|
|
|
return certs, nil
|
2015-11-18 04:39:19 +00:00
|
|
|
}
|
|
|
|
|
2016-12-14 23:48:36 +00:00
|
|
|
func (s *APIServer) getCertAuthority(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params) (interface{}, error) {
|
|
|
|
loadKeys, _, err := httplib.ParseBool(r.URL.Query(), "load_keys")
|
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
id := services.CertAuthID{
|
|
|
|
Type: services.CertAuthType(p.ByName("type")),
|
|
|
|
DomainName: p.ByName("domain"),
|
|
|
|
}
|
|
|
|
ca, err := auth.GetCertAuthority(id, loadKeys)
|
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
return ca, nil
|
|
|
|
}
|
|
|
|
|
2016-12-13 03:26:59 +00:00
|
|
|
func (s *APIServer) getDomainName(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params) (interface{}, error) {
|
|
|
|
domain, err := auth.GetDomainName()
|
2015-06-22 21:05:15 +00:00
|
|
|
if err != nil {
|
2016-02-23 20:03:34 +00:00
|
|
|
return nil, trace.Wrap(err)
|
2015-06-22 21:05:15 +00:00
|
|
|
}
|
2016-02-23 20:03:34 +00:00
|
|
|
return domain, nil
|
2015-06-22 21:05:15 +00:00
|
|
|
}
|
|
|
|
|
2016-12-08 10:23:51 +00:00
|
|
|
// getU2FAppID returns the U2F AppID in the auth configuration
|
2016-12-15 00:36:55 +00:00
|
|
|
func (s *APIServer) getU2FAppID(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params) (interface{}, error) {
|
|
|
|
appID, err := auth.GetU2FAppID()
|
2016-11-28 08:21:37 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
2016-12-08 10:23:51 +00:00
|
|
|
w.Header().Set("Content-Type", "application/fido.trusted-apps+json")
|
|
|
|
return appID, nil
|
2016-11-28 08:21:37 +00:00
|
|
|
}
|
|
|
|
|
2016-12-13 03:26:59 +00:00
|
|
|
func (s *APIServer) deleteCertAuthority(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params) (interface{}, error) {
|
2016-02-16 17:36:02 +00:00
|
|
|
id := services.CertAuthID{
|
|
|
|
DomainName: p[1].Value,
|
|
|
|
Type: services.CertAuthType(p[0].Value),
|
|
|
|
}
|
2016-12-13 03:26:59 +00:00
|
|
|
if err := auth.DeleteCertAuthority(id); err != nil {
|
2016-02-23 20:03:34 +00:00
|
|
|
return nil, trace.Wrap(err)
|
2015-06-22 21:05:15 +00:00
|
|
|
}
|
2016-02-23 20:03:34 +00:00
|
|
|
return message(fmt.Sprintf("cert '%v' deleted", id)), nil
|
2015-06-22 21:05:15 +00:00
|
|
|
}
|
|
|
|
|
2016-03-01 21:19:43 +00:00
|
|
|
type createSessionReq struct {
|
|
|
|
Session session.Session `json:"session"`
|
2016-02-23 20:03:34 +00:00
|
|
|
}
|
2015-07-03 20:08:26 +00:00
|
|
|
|
2016-12-13 03:26:59 +00:00
|
|
|
func (s *APIServer) createSession(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params) (interface{}, error) {
|
2016-03-01 21:19:43 +00:00
|
|
|
var req *createSessionReq
|
2016-02-23 20:03:34 +00:00
|
|
|
if err := httplib.ReadJSON(r, &req); err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
2015-07-03 20:08:26 +00:00
|
|
|
}
|
2016-12-13 22:20:52 +00:00
|
|
|
req.Session.Namespace = p.ByName("namespace")
|
2016-12-13 03:26:59 +00:00
|
|
|
if err := auth.CreateSession(req.Session); err != nil {
|
2016-02-23 20:03:34 +00:00
|
|
|
return nil, trace.Wrap(err)
|
2015-07-03 20:08:26 +00:00
|
|
|
}
|
2016-03-01 21:19:43 +00:00
|
|
|
return message("ok"), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
type updateSessionReq struct {
|
|
|
|
Update session.UpdateRequest `json:"update"`
|
|
|
|
}
|
|
|
|
|
2016-12-13 03:26:59 +00:00
|
|
|
func (s *APIServer) updateSession(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params) (interface{}, error) {
|
2016-03-01 21:19:43 +00:00
|
|
|
var req *updateSessionReq
|
|
|
|
if err := httplib.ReadJSON(r, &req); err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
2016-12-13 22:20:52 +00:00
|
|
|
req.Update.Namespace = p.ByName("namespace")
|
2016-12-13 03:26:59 +00:00
|
|
|
if err := auth.UpdateSession(req.Update); err != nil {
|
2016-03-01 21:19:43 +00:00
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
return message("ok"), nil
|
2015-07-03 20:08:26 +00:00
|
|
|
}
|
|
|
|
|
2016-12-13 03:26:59 +00:00
|
|
|
func (s *APIServer) getSessions(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params) (interface{}, error) {
|
|
|
|
sessions, err := auth.GetSessions(p.ByName("namespace"))
|
2015-06-30 23:12:18 +00:00
|
|
|
if err != nil {
|
2016-02-23 20:03:34 +00:00
|
|
|
return nil, trace.Wrap(err)
|
2015-06-30 23:12:18 +00:00
|
|
|
}
|
2016-02-23 20:03:34 +00:00
|
|
|
return sessions, nil
|
2015-06-30 23:12:18 +00:00
|
|
|
}
|
|
|
|
|
2016-12-13 03:26:59 +00:00
|
|
|
func (s *APIServer) getSession(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params) (interface{}, error) {
|
2016-12-19 00:58:53 +00:00
|
|
|
sid, err := session.ParseID(p.ByName("id"))
|
2016-03-20 01:16:06 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
2016-12-13 03:26:59 +00:00
|
|
|
se, err := auth.GetSession(p.ByName("namespace"), *sid)
|
2015-06-30 23:12:18 +00:00
|
|
|
if err != nil {
|
2016-02-23 20:03:34 +00:00
|
|
|
return nil, trace.Wrap(err)
|
2015-06-30 23:12:18 +00:00
|
|
|
}
|
2016-02-23 20:03:34 +00:00
|
|
|
return se, nil
|
2015-06-30 23:12:18 +00:00
|
|
|
}
|
|
|
|
|
2016-02-23 20:03:34 +00:00
|
|
|
type getSignupTokenDataResponse struct {
|
|
|
|
User string `json:"user"`
|
|
|
|
QRImg []byte `json:"qrimg"`
|
|
|
|
HotpFirstValues []string `json:"hotp_first_values"`
|
|
|
|
}
|
|
|
|
|
2016-03-06 00:47:03 +00:00
|
|
|
// getSignupTokenData auth API method creates a new sign-up token for adding a new user
|
2016-12-13 03:26:59 +00:00
|
|
|
func (s *APIServer) getSignupTokenData(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params) (interface{}, error) {
|
2016-01-21 22:08:41 +00:00
|
|
|
token := p[0].Value
|
2016-01-21 00:05:23 +00:00
|
|
|
|
2016-12-13 03:26:59 +00:00
|
|
|
user, QRImg, hotpFirstValues, err := auth.GetSignupTokenData(token)
|
2016-01-21 00:05:23 +00:00
|
|
|
if err != nil {
|
2016-02-23 20:03:34 +00:00
|
|
|
return nil, trace.Wrap(err)
|
2016-01-21 00:05:23 +00:00
|
|
|
}
|
|
|
|
|
2016-02-23 20:03:34 +00:00
|
|
|
return &getSignupTokenDataResponse{
|
2016-01-22 19:05:46 +00:00
|
|
|
User: user,
|
|
|
|
QRImg: QRImg,
|
|
|
|
HotpFirstValues: hotpFirstValues,
|
2016-02-23 20:03:34 +00:00
|
|
|
}, nil
|
2016-01-21 00:05:23 +00:00
|
|
|
}
|
|
|
|
|
2016-12-15 00:36:55 +00:00
|
|
|
func (s *APIServer) getSignupU2FRegisterRequest(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params) (interface{}, error) {
|
2016-10-14 06:51:16 +00:00
|
|
|
token := p[0].Value
|
2016-12-15 00:36:55 +00:00
|
|
|
u2fRegReq, err := auth.GetSignupU2FRegisterRequest(token)
|
2016-10-14 06:51:16 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
return u2fRegReq, nil
|
|
|
|
}
|
|
|
|
|
2016-02-23 20:03:34 +00:00
|
|
|
type createSignupTokenReq struct {
|
2016-04-03 05:20:51 +00:00
|
|
|
User services.User `json:"user"`
|
2016-01-21 18:18:59 +00:00
|
|
|
}
|
|
|
|
|
2016-04-05 16:58:16 +00:00
|
|
|
type createSignupTokenReqRaw struct {
|
|
|
|
User json.RawMessage `json:"user"`
|
|
|
|
}
|
|
|
|
|
2016-12-13 03:26:59 +00:00
|
|
|
func (s *APIServer) createSignupToken(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params) (interface{}, error) {
|
2016-04-05 16:58:16 +00:00
|
|
|
var req *createSignupTokenReqRaw
|
2016-02-23 20:03:34 +00:00
|
|
|
if err := httplib.ReadJSON(r, &req); err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
2016-01-21 00:05:23 +00:00
|
|
|
}
|
2016-12-10 01:31:05 +00:00
|
|
|
user, err := services.GetUserMarshaler().UnmarshalUser(req.User)
|
2016-04-05 16:58:16 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
2016-12-13 03:26:59 +00:00
|
|
|
token, err := auth.CreateSignupToken(user)
|
2016-01-21 00:05:23 +00:00
|
|
|
if err != nil {
|
2016-02-23 20:03:34 +00:00
|
|
|
return nil, trace.Wrap(err)
|
2016-01-21 00:05:23 +00:00
|
|
|
}
|
2016-02-23 20:03:34 +00:00
|
|
|
return token, nil
|
2015-05-12 00:04:22 +00:00
|
|
|
}
|
|
|
|
|
2016-02-23 20:03:34 +00:00
|
|
|
type createUserWithTokenReq struct {
|
|
|
|
Token string `json:"token"`
|
|
|
|
Password string `json:"password"`
|
|
|
|
HOTPToken string `json:"hotp_token"`
|
2015-07-11 00:24:44 +00:00
|
|
|
}
|
|
|
|
|
2016-12-13 03:26:59 +00:00
|
|
|
func (s *APIServer) createUserWithToken(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params) (interface{}, error) {
|
2016-02-23 20:03:34 +00:00
|
|
|
var req *createUserWithTokenReq
|
|
|
|
if err := httplib.ReadJSON(r, &req); err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
2016-12-13 03:26:59 +00:00
|
|
|
sess, err := auth.CreateUserWithToken(req.Token, req.Password, req.HOTPToken)
|
2016-02-23 20:03:34 +00:00
|
|
|
if err != nil {
|
2016-12-20 22:01:46 +00:00
|
|
|
log.Error(trace.DebugReport(err))
|
2016-02-23 20:03:34 +00:00
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
2016-02-24 01:26:23 +00:00
|
|
|
return sess, nil
|
2015-12-07 20:05:54 +00:00
|
|
|
}
|
|
|
|
|
2016-12-08 10:23:51 +00:00
|
|
|
type createUserWithU2FTokenReq struct {
|
2016-12-15 00:36:55 +00:00
|
|
|
Token string `json:"token"`
|
|
|
|
Password string `json:"password"`
|
2016-12-08 10:23:51 +00:00
|
|
|
U2FRegisterResponse u2f.RegisterResponse `json:"u2f_register_response"`
|
2016-10-14 06:51:16 +00:00
|
|
|
}
|
|
|
|
|
2016-12-15 00:36:55 +00:00
|
|
|
func (s *APIServer) createUserWithU2FToken(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params) (interface{}, error) {
|
2016-12-08 10:23:51 +00:00
|
|
|
var req *createUserWithU2FTokenReq
|
2016-10-14 06:51:16 +00:00
|
|
|
if err := httplib.ReadJSON(r, &req); err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
|
2016-12-15 00:36:55 +00:00
|
|
|
sess, err := auth.CreateUserWithU2FToken(req.Token, req.Password, req.U2FRegisterResponse)
|
2016-10-14 06:51:16 +00:00
|
|
|
if err != nil {
|
|
|
|
log.Error(err)
|
|
|
|
return nil, trace.Wrap(err)
|
2016-02-23 20:03:34 +00:00
|
|
|
}
|
2016-02-24 01:26:23 +00:00
|
|
|
return sess, nil
|
2015-12-07 20:05:54 +00:00
|
|
|
}
|
|
|
|
|
2016-04-03 05:20:51 +00:00
|
|
|
type upsertOIDCConnectorReq struct {
|
|
|
|
Connector services.OIDCConnector `json:"connector"`
|
|
|
|
TTL time.Duration `json:"ttl"`
|
|
|
|
}
|
|
|
|
|
2016-12-13 03:26:59 +00:00
|
|
|
func (s *APIServer) upsertOIDCConnector(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params) (interface{}, error) {
|
2016-04-03 05:20:51 +00:00
|
|
|
var req *upsertOIDCConnectorReq
|
|
|
|
if err := httplib.ReadJSON(r, &req); err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
2016-12-13 03:26:59 +00:00
|
|
|
err := auth.UpsertOIDCConnector(req.Connector, req.TTL)
|
2016-04-03 05:20:51 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
return message("ok"), nil
|
|
|
|
}
|
|
|
|
|
2016-12-13 03:26:59 +00:00
|
|
|
func (s *APIServer) getOIDCConnector(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params) (interface{}, error) {
|
2016-04-03 22:06:50 +00:00
|
|
|
withSecrets, _, err := httplib.ParseBool(r.URL.Query(), "with_secrets")
|
2016-04-03 05:20:51 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
2016-12-13 03:26:59 +00:00
|
|
|
connector, err := auth.GetOIDCConnector(p[0].Value, withSecrets)
|
2016-04-03 05:20:51 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
return connector, nil
|
|
|
|
}
|
|
|
|
|
2016-12-13 03:26:59 +00:00
|
|
|
func (s *APIServer) deleteOIDCConnector(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params) (interface{}, error) {
|
|
|
|
err := auth.DeleteOIDCConnector(p[0].Value)
|
2016-04-03 05:20:51 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
return message("ok"), nil
|
|
|
|
}
|
|
|
|
|
2016-12-13 03:26:59 +00:00
|
|
|
func (s *APIServer) getOIDCConnectors(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params) (interface{}, error) {
|
2016-04-03 22:06:50 +00:00
|
|
|
withSecrets, _, err := httplib.ParseBool(r.URL.Query(), "with_secrets")
|
2016-04-03 05:20:51 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
2016-12-13 03:26:59 +00:00
|
|
|
connectors, err := auth.GetOIDCConnectors(withSecrets)
|
2016-04-03 05:20:51 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
return connectors, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
type createOIDCAuthRequestReq struct {
|
|
|
|
Req services.OIDCAuthRequest `json:"req"`
|
|
|
|
}
|
|
|
|
|
2016-12-13 03:26:59 +00:00
|
|
|
func (s *APIServer) createOIDCAuthRequest(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params) (interface{}, error) {
|
2016-04-03 05:20:51 +00:00
|
|
|
var req *createOIDCAuthRequestReq
|
|
|
|
if err := httplib.ReadJSON(r, &req); err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
2016-12-13 03:26:59 +00:00
|
|
|
response, err := auth.CreateOIDCAuthRequest(req.Req)
|
2016-04-03 05:20:51 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
return response, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
type validateOIDCAuthCallbackReq struct {
|
2016-04-15 00:50:54 +00:00
|
|
|
Query url.Values `json:"query"`
|
2016-04-03 05:20:51 +00:00
|
|
|
}
|
|
|
|
|
2016-12-13 03:26:59 +00:00
|
|
|
func (s *APIServer) validateOIDCAuthCallback(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params) (interface{}, error) {
|
2016-04-03 05:20:51 +00:00
|
|
|
var req *validateOIDCAuthCallbackReq
|
|
|
|
if err := httplib.ReadJSON(r, &req); err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
2016-12-13 03:26:59 +00:00
|
|
|
response, err := auth.ValidateOIDCAuthCallback(req.Query)
|
2016-04-03 05:20:51 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
return response, nil
|
|
|
|
}
|
|
|
|
|
2016-04-29 09:42:08 +00:00
|
|
|
// HTTP GET /v1/events?query
|
|
|
|
//
|
|
|
|
// Query fields:
|
|
|
|
// 'from' : time filter in RFC3339 format
|
|
|
|
// 'to' : time filter in RFC3339 format
|
|
|
|
// ... : other fields are passed directly to the audit backend
|
2016-12-13 03:26:59 +00:00
|
|
|
func (s *APIServer) searchEvents(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params) (interface{}, error) {
|
2016-04-29 09:42:08 +00:00
|
|
|
var err error
|
|
|
|
to := time.Now().In(time.UTC)
|
|
|
|
from := to.AddDate(0, -1, 0) // one month ago
|
|
|
|
query := r.URL.Query()
|
|
|
|
// parse 'to' and 'from' params:
|
|
|
|
fromStr := query.Get("from")
|
|
|
|
if fromStr != "" {
|
|
|
|
from, err = time.Parse(time.RFC3339, fromStr)
|
|
|
|
if err != nil {
|
|
|
|
return nil, trace.BadParameter("from")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
toStr := query.Get("to")
|
|
|
|
if toStr != "" {
|
|
|
|
to, err = time.Parse(time.RFC3339, toStr)
|
|
|
|
if err != nil {
|
|
|
|
return nil, trace.BadParameter("to")
|
|
|
|
}
|
|
|
|
}
|
2016-05-08 04:17:28 +00:00
|
|
|
// remove 'to' & 'from' fields, passing the rest of the query unmodified
|
|
|
|
// to whatever pluggable search is implemented by the backend
|
2016-04-29 09:42:08 +00:00
|
|
|
query.Del("to")
|
|
|
|
query.Del("from")
|
2016-12-13 03:26:59 +00:00
|
|
|
eventsList, err := auth.SearchEvents(from, to, query.Encode())
|
2016-04-29 09:42:08 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
2016-04-30 05:43:22 +00:00
|
|
|
return eventsList, nil
|
2016-04-29 09:42:08 +00:00
|
|
|
}
|
|
|
|
|
2016-04-24 23:49:03 +00:00
|
|
|
type auditEventReq struct {
|
2016-04-25 06:32:44 +00:00
|
|
|
Type string `json:"type"`
|
|
|
|
Fields events.EventFields `json:"fields"`
|
2016-04-24 23:49:03 +00:00
|
|
|
}
|
|
|
|
|
2016-04-24 22:35:33 +00:00
|
|
|
// HTTP POST /v1/events
|
2016-12-13 03:26:59 +00:00
|
|
|
func (s *APIServer) emitAuditEvent(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params) (interface{}, error) {
|
2016-04-24 23:49:03 +00:00
|
|
|
var req auditEventReq
|
|
|
|
if err := httplib.ReadJSON(r, &req); err != nil {
|
2016-04-24 22:35:33 +00:00
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
2016-12-13 03:26:59 +00:00
|
|
|
if err := auth.EmitAuditEvent(req.Type, req.Fields); err != nil {
|
2016-04-24 22:35:33 +00:00
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
return message("ok"), nil
|
|
|
|
}
|
|
|
|
|
2016-05-05 22:43:29 +00:00
|
|
|
// HTTP POST /v1/sessions/:id/stream
|
2016-12-13 03:26:59 +00:00
|
|
|
func (s *APIServer) postSessionChunk(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params) (interface{}, error) {
|
2016-04-26 00:19:37 +00:00
|
|
|
sid, err := session.ParseID(p.ByName("id"))
|
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
2016-12-13 03:26:59 +00:00
|
|
|
namespace := p.ByName("namespace")
|
|
|
|
if err = auth.PostSessionChunk(namespace, *sid, r.Body); err != nil {
|
2016-04-26 00:19:37 +00:00
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
2016-05-05 22:43:29 +00:00
|
|
|
return message("ok"), nil
|
2016-04-26 00:19:37 +00:00
|
|
|
}
|
|
|
|
|
2016-05-06 06:51:56 +00:00
|
|
|
// HTTP GET /v1/sessions/:id/stream?offset=x&bytes=y
|
|
|
|
// Query parameters:
|
|
|
|
// "offset" : bytes from the beginning
|
|
|
|
// "bytes" : number of bytes to read (it won't return more than 512Kb)
|
2016-12-13 03:26:59 +00:00
|
|
|
func (s *APIServer) getSessionChunk(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params) (interface{}, error) {
|
2016-04-26 00:19:37 +00:00
|
|
|
sid, err := session.ParseID(p.ByName("id"))
|
|
|
|
if err != nil {
|
2016-12-13 03:26:59 +00:00
|
|
|
return nil, trace.BadParameter("missing parameter id")
|
2016-05-06 06:51:56 +00:00
|
|
|
}
|
2016-12-13 03:26:59 +00:00
|
|
|
namespace := p.ByName("namespace")
|
|
|
|
|
2016-05-06 06:51:56 +00:00
|
|
|
// "offset bytes" query param
|
|
|
|
offsetBytes, err := strconv.Atoi(r.URL.Query().Get("offset"))
|
|
|
|
if err != nil || offsetBytes < 0 {
|
|
|
|
offsetBytes = 0
|
2016-04-26 00:19:37 +00:00
|
|
|
}
|
2016-05-06 06:51:56 +00:00
|
|
|
// "max bytes" query param
|
|
|
|
max, err := strconv.Atoi(r.URL.Query().Get("bytes"))
|
2016-04-27 05:55:06 +00:00
|
|
|
if err != nil || offsetBytes < 0 {
|
|
|
|
offsetBytes = 0
|
|
|
|
}
|
2016-12-19 17:48:55 +00:00
|
|
|
log.Debugf("apiserver.GetSessionChunk(%v, %v, offset=%d)", namespace, *sid, offsetBytes)
|
2016-05-06 06:51:56 +00:00
|
|
|
w.Header().Set("Content-Type", "text/plain")
|
|
|
|
|
2016-12-13 03:26:59 +00:00
|
|
|
buffer, err := auth.GetSessionChunk(namespace, *sid, offsetBytes, max)
|
2016-04-26 00:19:37 +00:00
|
|
|
if err != nil {
|
2016-12-13 03:26:59 +00:00
|
|
|
return nil, trace.Wrap(err)
|
2016-04-26 00:19:37 +00:00
|
|
|
}
|
2016-05-06 06:51:56 +00:00
|
|
|
if _, err = w.Write(buffer); err != nil {
|
2016-12-13 03:26:59 +00:00
|
|
|
return nil, trace.Wrap(err)
|
2016-04-26 00:19:37 +00:00
|
|
|
}
|
2016-05-06 06:51:56 +00:00
|
|
|
w.Header().Set("Content-Type", "application/octet-stream")
|
2016-12-13 03:26:59 +00:00
|
|
|
return nil, nil
|
2016-04-26 00:19:37 +00:00
|
|
|
}
|
|
|
|
|
2016-04-30 05:43:22 +00:00
|
|
|
// HTTP GET /v1/sessions/:id/events?maxage=n
|
|
|
|
// Query:
|
|
|
|
// 'after' : cursor value to return events newer than N. Defaults to 0, (return all)
|
2016-12-13 03:26:59 +00:00
|
|
|
func (s *APIServer) getSessionEvents(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params) (interface{}, error) {
|
2016-04-27 05:55:06 +00:00
|
|
|
sid, err := session.ParseID(p.ByName("id"))
|
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
2016-12-13 03:26:59 +00:00
|
|
|
namespace := p.ByName("namespace")
|
2016-04-30 05:43:22 +00:00
|
|
|
afterN, err := strconv.Atoi(r.URL.Query().Get("after"))
|
|
|
|
if err != nil {
|
|
|
|
afterN = 0
|
|
|
|
}
|
2016-05-08 04:17:28 +00:00
|
|
|
log.Debugf("[AUTH] api.getSessionEvents(%v, after=%d)", *sid, afterN)
|
2016-12-13 03:26:59 +00:00
|
|
|
return auth.GetSessionEvents(namespace, *sid, afterN)
|
|
|
|
}
|
|
|
|
|
|
|
|
type upsertNamespaceReq struct {
|
|
|
|
Namespace services.Namespace `json:"namespace"`
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *APIServer) upsertNamespace(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params) (interface{}, error) {
|
|
|
|
var req *upsertNamespaceReq
|
|
|
|
if err := httplib.ReadJSON(r, &req); err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
if err := auth.UpsertNamespace(req.Namespace); err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
return message("ok"), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *APIServer) getNamespaces(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params) (interface{}, error) {
|
|
|
|
namespaces, err := auth.GetNamespaces()
|
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
return namespaces, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *APIServer) getNamespace(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params) (interface{}, error) {
|
|
|
|
name := p.ByName("namespace")
|
|
|
|
namespace, err := auth.GetNamespace(name)
|
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
return namespace, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *APIServer) deleteNamespace(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params) (interface{}, error) {
|
|
|
|
name := p.ByName("namespace")
|
|
|
|
err := auth.DeleteNamespace(name)
|
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
return message("ok"), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
type upsertRoleReq struct {
|
|
|
|
Role services.Role `json:"role"`
|
|
|
|
}
|
|
|
|
|
|
|
|
type upsertRoleReqRaw struct {
|
2016-12-17 03:33:18 +00:00
|
|
|
Role json.RawMessage `json:"role"`
|
2016-12-13 03:26:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (s *APIServer) upsertRole(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params) (interface{}, error) {
|
|
|
|
var req *upsertRoleReqRaw
|
|
|
|
if err := httplib.ReadJSON(r, &req); err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
role, err := services.GetRoleMarshaler().UnmarshalRole(req.Role)
|
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
err = auth.UpsertRole(role)
|
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
2016-12-23 03:06:07 +00:00
|
|
|
return message(fmt.Sprintf("'%v' role upserted", role.GetName())), nil
|
2016-12-13 03:26:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (s *APIServer) getRole(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params) (interface{}, error) {
|
|
|
|
role, err := auth.GetRole(p[0].Value)
|
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
return role, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *APIServer) getRoles(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params) (interface{}, error) {
|
|
|
|
roles, err := auth.GetRoles()
|
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
return roles, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *APIServer) deleteRole(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params) (interface{}, error) {
|
|
|
|
role := p[0].Value
|
|
|
|
if err := auth.DeleteRole(role); err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
return message(fmt.Sprintf("role '%v' deleted", role)), nil
|
2016-04-27 05:55:06 +00:00
|
|
|
}
|
|
|
|
|
2015-03-02 20:11:23 +00:00
|
|
|
func message(msg string) map[string]interface{} {
|
|
|
|
return map[string]interface{}{"message": msg}
|
|
|
|
}
|