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"
|
2017-05-27 01:03:19 +00:00
|
|
|
"io/ioutil"
|
2015-03-02 20:11:23 +00:00
|
|
|
"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"
|
2017-04-04 21:46:23 +00:00
|
|
|
"github.com/gravitational/teleport/lib/backend"
|
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
|
|
|
|
2017-04-07 23:51:31 +00:00
|
|
|
"github.com/jonboulle/clockwork"
|
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
|
2017-01-31 04:18:15 +00:00
|
|
|
Authorizer Authorizer
|
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
|
2017-04-07 23:51:31 +00:00
|
|
|
clockwork.Clock
|
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,
|
2017-04-07 23:51:31 +00:00
|
|
|
Clock: clockwork.NewRealClock(),
|
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-29 20:23:58 +00:00
|
|
|
srv.GET("/:version/domain", srv.withAuth(srv.getDomainName))
|
|
|
|
srv.POST("/:version/authorities/:type", srv.withAuth(srv.upsertCertAuthority))
|
|
|
|
srv.DELETE("/:version/authorities/:type/:domain", srv.withAuth(srv.deleteCertAuthority))
|
|
|
|
srv.GET("/:version/authorities/:type/:domain", srv.withAuth(srv.getCertAuthority))
|
|
|
|
srv.GET("/:version/authorities/:type", srv.withAuth(srv.getCertAuthorities))
|
2015-03-02 20:11:23 +00:00
|
|
|
|
|
|
|
// Generating certificates for user and host authorities
|
2016-12-29 20:23:58 +00:00
|
|
|
srv.POST("/:version/ca/host/certs", srv.withAuth(srv.generateHostCert))
|
|
|
|
srv.POST("/:version/ca/user/certs", srv.withAuth(srv.generateUserCert))
|
2015-03-02 20:11:23 +00:00
|
|
|
|
|
|
|
// Operations on users
|
2016-12-29 20:23:58 +00:00
|
|
|
srv.GET("/:version/users", srv.withAuth(srv.getUsers))
|
|
|
|
srv.GET("/:version/users/:user", srv.withAuth(srv.getUser))
|
|
|
|
srv.DELETE("/:version/users/:user", srv.withAuth(srv.deleteUser))
|
2015-03-02 20:11:23 +00:00
|
|
|
|
|
|
|
// Generating keypairs
|
2016-12-29 20:23:58 +00:00
|
|
|
srv.POST("/:version/keypair", srv.withAuth(srv.generateKeyPair))
|
2015-03-19 04:13:56 +00:00
|
|
|
|
|
|
|
// Passwords and sessions
|
2016-12-29 20:23:58 +00:00
|
|
|
srv.POST("/:version/users", srv.withAuth(srv.upsertUser))
|
|
|
|
srv.POST("/:version/users/:user/web/password", srv.withAuth(srv.upsertPassword))
|
|
|
|
srv.POST("/:version/users/:user/web/password/check", srv.withAuth(srv.checkPassword))
|
|
|
|
srv.POST("/:version/users/:user/web/signin", srv.withAuth(srv.signIn))
|
|
|
|
srv.GET("/:version/users/:user/web/signin/preauth", srv.withAuth(srv.preAuthenticatedSignIn))
|
|
|
|
srv.POST("/:version/users/:user/web/sessions", srv.withAuth(srv.createWebSession))
|
|
|
|
srv.GET("/:version/users/:user/web/sessions/:sid", srv.withAuth(srv.getWebSession))
|
|
|
|
srv.DELETE("/:version/users/:user/web/sessions/:sid", srv.withAuth(srv.deleteWebSession))
|
|
|
|
srv.GET("/:version/signuptokens/:token", srv.withAuth(srv.getSignupTokenData))
|
|
|
|
srv.POST("/:version/signuptokens/users", srv.withAuth(srv.createUserWithToken))
|
|
|
|
srv.POST("/:version/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-29 20:23:58 +00:00
|
|
|
srv.POST("/:version/namespaces/:namespace/nodes", srv.withAuth(srv.upsertNode))
|
|
|
|
srv.GET("/:version/namespaces/:namespace/nodes", srv.withAuth(srv.getNodes))
|
|
|
|
srv.POST("/:version/authservers", srv.withAuth(srv.upsertAuthServer))
|
|
|
|
srv.GET("/:version/authservers", srv.withAuth(srv.getAuthServers))
|
|
|
|
srv.POST("/:version/proxies", srv.withAuth(srv.upsertProxy))
|
|
|
|
srv.GET("/:version/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-29 20:23:58 +00:00
|
|
|
srv.POST("/:version/reversetunnels", srv.withAuth(srv.upsertReverseTunnel))
|
|
|
|
srv.GET("/:version/reversetunnels", srv.withAuth(srv.getReverseTunnels))
|
|
|
|
srv.DELETE("/:version/reversetunnels/:domain", srv.withAuth(srv.deleteReverseTunnel))
|
2016-03-18 01:42:04 +00:00
|
|
|
|
2017-03-02 19:50:35 +00:00
|
|
|
// trusted clusters
|
|
|
|
srv.POST("/:version/trustedclusters", srv.withAuth(srv.upsertTrustedCluster))
|
|
|
|
srv.POST("/:version/trustedclusters/validate", srv.withAuth(srv.validateTrustedCluster))
|
|
|
|
srv.GET("/:version/trustedclusters", srv.withAuth(srv.getTrustedClusters))
|
|
|
|
srv.GET("/:version/trustedclusters/:name", srv.withAuth(srv.getTrustedCluster))
|
|
|
|
srv.DELETE("/:version/trustedclusters/:name", srv.withAuth(srv.deleteTrustedCluster))
|
|
|
|
|
2015-05-07 03:10:44 +00:00
|
|
|
// Tokens
|
2016-12-29 20:23:58 +00:00
|
|
|
srv.POST("/:version/tokens", srv.withAuth(srv.generateToken))
|
|
|
|
srv.POST("/:version/tokens/register", srv.withAuth(srv.registerUsingToken))
|
|
|
|
srv.POST("/:version/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-29 20:23:58 +00:00
|
|
|
srv.POST("/:version/namespaces/:namespace/sessions", srv.withAuth(srv.createSession))
|
|
|
|
srv.PUT("/:version/namespaces/:namespace/sessions/:id", srv.withAuth(srv.updateSession))
|
|
|
|
srv.GET("/:version/namespaces/:namespace/sessions", srv.withAuth(srv.getSessions))
|
|
|
|
srv.GET("/:version/namespaces/:namespace/sessions/:id", srv.withAuth(srv.getSession))
|
2017-05-27 01:03:19 +00:00
|
|
|
srv.POST("/:version/namespaces/:namespace/sessions/:id/slice", srv.withAuth(srv.postSessionSlice))
|
2016-12-29 20:23:58 +00:00
|
|
|
srv.POST("/:version/namespaces/:namespace/sessions/:id/stream", srv.withAuth(srv.postSessionChunk))
|
|
|
|
srv.GET("/:version/namespaces/:namespace/sessions/:id/stream", srv.withAuth(srv.getSessionChunk))
|
|
|
|
srv.GET("/:version/namespaces/:namespace/sessions/:id/events", srv.withAuth(srv.getSessionEvents))
|
2015-06-30 23:12:18 +00:00
|
|
|
|
2016-12-13 03:26:59 +00:00
|
|
|
// Namespaces
|
2016-12-29 20:23:58 +00:00
|
|
|
srv.POST("/:version/namespaces", srv.withAuth(srv.upsertNamespace))
|
|
|
|
srv.GET("/:version/namespaces", srv.withAuth(srv.getNamespaces))
|
|
|
|
srv.GET("/:version/namespaces/:namespace", srv.withAuth(srv.getNamespace))
|
|
|
|
srv.DELETE("/:version/namespaces/:namespace", srv.withAuth(srv.deleteNamespace))
|
2016-12-13 03:26:59 +00:00
|
|
|
|
|
|
|
// Roles
|
2016-12-29 20:23:58 +00:00
|
|
|
srv.POST("/:version/roles", srv.withAuth(srv.upsertRole))
|
|
|
|
srv.GET("/:version/roles", srv.withAuth(srv.getRoles))
|
|
|
|
srv.GET("/:version/roles/:role", srv.withAuth(srv.getRole))
|
|
|
|
srv.DELETE("/:version/roles/:role", srv.withAuth(srv.deleteRole))
|
2016-12-13 03:26:59 +00:00
|
|
|
|
2017-07-28 18:37:12 +00:00
|
|
|
// cluster configuration
|
|
|
|
srv.GET("/:version/configuration/name", srv.withAuth(srv.getClusterName))
|
|
|
|
srv.POST("/:version/configuration/name", srv.withAuth(srv.setClusterName))
|
|
|
|
srv.GET("/:version/configuration/static_tokens", srv.withAuth(srv.getStaticTokens))
|
|
|
|
srv.POST("/:version/configuration/static_tokens", srv.withAuth(srv.setStaticTokens))
|
2017-02-14 02:29:27 +00:00
|
|
|
srv.GET("/:version/authentication/preference", srv.withAuth(srv.getClusterAuthPreference))
|
|
|
|
srv.POST("/:version/authentication/preference", srv.withAuth(srv.setClusterAuthPreference))
|
|
|
|
|
|
|
|
// OIDC
|
|
|
|
srv.POST("/:version/oidc/connectors", srv.withAuth(srv.upsertOIDCConnector))
|
|
|
|
srv.GET("/:version/oidc/connectors", srv.withAuth(srv.getOIDCConnectors))
|
|
|
|
srv.GET("/:version/oidc/connectors/:id", srv.withAuth(srv.getOIDCConnector))
|
|
|
|
srv.DELETE("/:version/oidc/connectors/:id", srv.withAuth(srv.deleteOIDCConnector))
|
|
|
|
srv.POST("/:version/oidc/requests/create", srv.withAuth(srv.createOIDCAuthRequest))
|
|
|
|
srv.POST("/:version/oidc/requests/validate", srv.withAuth(srv.validateOIDCAuthCallback))
|
|
|
|
|
2017-05-05 22:53:05 +00:00
|
|
|
// SAML handlers
|
|
|
|
srv.POST("/:version/saml/connectors", srv.withAuth(srv.createSAMLConnector))
|
|
|
|
srv.PUT("/:version/saml/connectors", srv.withAuth(srv.upsertSAMLConnector))
|
|
|
|
srv.GET("/:version/saml/connectors", srv.withAuth(srv.getSAMLConnectors))
|
|
|
|
srv.GET("/:version/saml/connectors/:id", srv.withAuth(srv.getSAMLConnector))
|
|
|
|
srv.DELETE("/:version/saml/connectors/:id", srv.withAuth(srv.deleteSAMLConnector))
|
|
|
|
srv.POST("/:version/saml/requests/create", srv.withAuth(srv.createSAMLAuthRequest))
|
|
|
|
srv.POST("/:version/saml/requests/validate", srv.withAuth(srv.validateSAMLResponse))
|
|
|
|
|
2017-01-17 19:24:17 +00:00
|
|
|
// U2F
|
2016-12-29 20:23:58 +00:00
|
|
|
srv.GET("/:version/u2f/signuptokens/:token", srv.withAuth(srv.getSignupU2FRegisterRequest))
|
|
|
|
srv.POST("/:version/u2f/users", srv.withAuth(srv.createUserWithU2FToken))
|
|
|
|
srv.POST("/:version/u2f/users/:user/sign", srv.withAuth(srv.u2fSignRequest))
|
|
|
|
srv.GET("/:version/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-29 20:23:58 +00:00
|
|
|
srv.GET("/:version/tokens", srv.withAuth(srv.getTokens))
|
|
|
|
srv.GET("/:version/tokens/:token", srv.withAuth(srv.getToken))
|
|
|
|
srv.DELETE("/:version/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-29 20:23:58 +00:00
|
|
|
srv.POST("/:version/events", srv.withAuth(srv.emitAuditEvent))
|
|
|
|
srv.GET("/:version/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
|
2016-12-29 23:46:19 +00:00
|
|
|
type HandlerWithAuthFunc func(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (interface{}, error)
|
2016-12-12 00:52:22 +00:00
|
|
|
|
2016-12-13 03:26:59 +00:00
|
|
|
func (s *APIServer) withAuth(handler HandlerWithAuthFunc) httprouter.Handle {
|
2017-01-29 22:43:08 +00:00
|
|
|
const accessDeniedMsg = "auth API: access denied "
|
2016-12-12 00:52:22 +00:00
|
|
|
return httplib.MakeHandler(func(w http.ResponseWriter, r *http.Request, p httprouter.Params) (interface{}, error) {
|
2017-01-31 04:18:15 +00:00
|
|
|
// SSH-to-HTTP gateway (tun server) expects the auth
|
|
|
|
// context to be set by SSH server
|
2017-01-31 05:43:01 +00:00
|
|
|
authContext, err := s.Authorizer.Authorize(r.Context())
|
2016-12-12 00:52:22 +00:00
|
|
|
if err != nil {
|
2017-07-02 22:26:09 +00:00
|
|
|
// propagate connection problem error so we can differentiate
|
|
|
|
// between connection failed and access denied
|
|
|
|
if trace.IsConnectionProblem(err) {
|
|
|
|
return nil, trace.ConnectionProblem(err, "[07] failed to connect to the database")
|
|
|
|
}
|
2017-01-29 22:43:08 +00:00
|
|
|
log.Warn(accessDeniedMsg + err.Error())
|
2017-01-31 05:43:01 +00:00
|
|
|
return nil, trace.AccessDenied(accessDeniedMsg + "[00]")
|
2016-12-12 00:52:22 +00:00
|
|
|
}
|
|
|
|
auth := &AuthWithRoles{
|
|
|
|
authServer: s.AuthServer,
|
2017-05-19 17:06:48 +00:00
|
|
|
user: authContext.User,
|
2017-01-31 04:18:15 +00:00
|
|
|
checker: authContext.Checker,
|
2016-12-12 00:52:22 +00:00
|
|
|
sessions: s.SessionService,
|
|
|
|
alog: s.AuditLog,
|
|
|
|
}
|
2016-12-29 23:46:19 +00:00
|
|
|
version := p.ByName("version")
|
|
|
|
if version == "" {
|
|
|
|
return nil, trace.BadParameter("missing version")
|
|
|
|
}
|
|
|
|
return handler(auth, w, r, p, version)
|
2016-12-12 00:52:22 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2016-12-29 19:36:57 +00:00
|
|
|
type upsertServerRawReq struct {
|
|
|
|
Server json.RawMessage `json:"server"`
|
2016-02-23 20:03:34 +00:00
|
|
|
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-29 23:46:19 +00:00
|
|
|
func (s *APIServer) upsertServer(auth ClientI, role teleport.Role, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (interface{}, error) {
|
2016-12-29 19:36:57 +00:00
|
|
|
var req upsertServerRawReq
|
2016-02-23 20:03:34 +00:00
|
|
|
if err := httplib.ReadJSON(r, &req); err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
2016-12-29 19:36:57 +00:00
|
|
|
var kind string
|
|
|
|
switch role {
|
|
|
|
case teleport.RoleNode:
|
|
|
|
kind = services.KindNode
|
|
|
|
case teleport.RoleAuth:
|
|
|
|
kind = services.KindAuthServer
|
|
|
|
case teleport.RoleProxy:
|
|
|
|
kind = services.KindProxy
|
|
|
|
}
|
|
|
|
server, err := services.GetServerMarshaler().UnmarshalServer(req.Server, kind)
|
|
|
|
if 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-12-29 19:36:57 +00:00
|
|
|
server.SetAddr(utils.ReplaceLocalhost(server.GetAddr(), r.RemoteAddr))
|
2017-04-07 23:51:31 +00:00
|
|
|
if req.TTL != 0 {
|
|
|
|
server.SetTTL(s, req.TTL)
|
|
|
|
}
|
2016-03-12 04:09:40 +00:00
|
|
|
switch role {
|
|
|
|
case teleport.RoleNode:
|
2017-04-26 20:31:27 +00:00
|
|
|
namespace := p.ByName("namespace")
|
|
|
|
if !services.IsValidNamespace(namespace) {
|
|
|
|
return nil, trace.BadParameter("invalid namespace %q", namespace)
|
|
|
|
}
|
|
|
|
server.SetNamespace(namespace)
|
2017-04-07 23:51:31 +00:00
|
|
|
if err := auth.UpsertNode(server); err != nil {
|
2016-03-12 04:09:40 +00:00
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
case teleport.RoleAuth:
|
2017-04-07 23:51:31 +00:00
|
|
|
if err := auth.UpsertAuthServer(server); err != nil {
|
2016-03-12 04:09:40 +00:00
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
case teleport.RoleProxy:
|
2017-04-07 23:51:31 +00:00
|
|
|
if err := auth.UpsertProxy(server); 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-29 23:46:19 +00:00
|
|
|
func (s *APIServer) upsertNode(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (interface{}, error) {
|
|
|
|
return s.upsertServer(auth, teleport.RoleNode, w, r, p, version)
|
2016-03-12 04:09:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// getNodes returns registered SSH nodes
|
2016-12-29 23:46:19 +00:00
|
|
|
func (s *APIServer) getNodes(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (interface{}, error) {
|
2017-04-26 20:31:27 +00:00
|
|
|
namespace := p.ByName("namespace")
|
|
|
|
if !services.IsValidNamespace(namespace) {
|
|
|
|
return nil, trace.BadParameter("invalid namespace %q", namespace)
|
|
|
|
}
|
|
|
|
servers, err := auth.GetNodes(namespace)
|
2016-03-12 04:09:40 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
2016-12-29 23:46:19 +00:00
|
|
|
return marshalServers(servers, version)
|
2016-03-12 04:09:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// upsertProxy is called by remote SSH nodes when they ping back into the auth service
|
2016-12-29 23:46:19 +00:00
|
|
|
func (s *APIServer) upsertProxy(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (interface{}, error) {
|
|
|
|
return s.upsertServer(auth, teleport.RoleProxy, w, r, p, version)
|
2016-03-12 04:09:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// getProxies returns registered proxies
|
2016-12-29 23:46:19 +00:00
|
|
|
func (s *APIServer) getProxies(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (interface{}, error) {
|
2016-12-13 03:26:59 +00:00
|
|
|
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-12-29 23:46:19 +00:00
|
|
|
return marshalServers(servers, version)
|
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-29 23:46:19 +00:00
|
|
|
func (s *APIServer) upsertAuthServer(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (interface{}, error) {
|
|
|
|
return s.upsertServer(auth, teleport.RoleAuth, w, r, p, version)
|
2016-03-12 04:09:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// getAuthServers returns registered auth servers
|
2016-12-29 23:46:19 +00:00
|
|
|
func (s *APIServer) getAuthServers(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (interface{}, error) {
|
2016-12-13 03:26:59 +00:00
|
|
|
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-12-29 23:46:19 +00:00
|
|
|
return marshalServers(servers, version)
|
2016-12-29 19:36:57 +00:00
|
|
|
}
|
|
|
|
|
2016-12-29 23:46:19 +00:00
|
|
|
func marshalServers(servers []services.Server, version string) (interface{}, error) {
|
2016-12-29 19:36:57 +00:00
|
|
|
items := make([]json.RawMessage, len(servers))
|
|
|
|
for i, server := range servers {
|
2016-12-29 23:46:19 +00:00
|
|
|
data, err := services.GetServerMarshaler().MarshalServer(server, services.WithVersion(version))
|
2016-12-29 19:36:57 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
items[i] = data
|
|
|
|
}
|
|
|
|
return items, nil
|
2015-03-19 04:13:56 +00:00
|
|
|
}
|
|
|
|
|
2016-12-29 19:36:57 +00:00
|
|
|
type upsertReverseTunnelRawReq struct {
|
|
|
|
ReverseTunnel json.RawMessage `json:"reverse_tunnel"`
|
|
|
|
TTL time.Duration `json:"ttl"`
|
2016-03-18 01:42:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// upsertReverseTunnel is called by admin to create a reverse tunnel to remote proxy
|
2016-12-29 23:46:19 +00:00
|
|
|
func (s *APIServer) upsertReverseTunnel(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (interface{}, error) {
|
2016-12-29 19:36:57 +00:00
|
|
|
var req upsertReverseTunnelRawReq
|
2016-03-18 01:42:04 +00:00
|
|
|
if err := httplib.ReadJSON(r, &req); err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
2016-12-29 19:36:57 +00:00
|
|
|
tun, err := services.GetReverseTunnelMarshaler().UnmarshalReverseTunnel(req.ReverseTunnel)
|
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
2017-04-07 23:51:31 +00:00
|
|
|
tun.SetTTL(s, req.TTL)
|
|
|
|
if err := auth.UpsertReverseTunnel(tun); 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-29 23:46:19 +00:00
|
|
|
func (s *APIServer) getReverseTunnels(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (interface{}, error) {
|
2016-12-13 03:26:59 +00:00
|
|
|
reverseTunnels, err := auth.GetReverseTunnels()
|
2016-03-18 01:42:04 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
2016-12-29 19:36:57 +00:00
|
|
|
items := make([]json.RawMessage, len(reverseTunnels))
|
|
|
|
for i, tunnel := range reverseTunnels {
|
2016-12-29 23:46:19 +00:00
|
|
|
data, err := services.GetReverseTunnelMarshaler().MarshalReverseTunnel(tunnel, services.WithVersion(version))
|
2016-12-29 19:36:57 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
items[i] = data
|
|
|
|
}
|
|
|
|
return items, nil
|
2016-03-18 01:42:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// deleteReverseTunnel deletes reverse tunnel
|
2016-12-29 23:46:19 +00:00
|
|
|
func (s *APIServer) deleteReverseTunnel(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (interface{}, error) {
|
2016-12-30 02:57:20 +00:00
|
|
|
domainName := p.ByName("domain")
|
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
|
|
|
|
}
|
|
|
|
|
2017-03-02 19:50:35 +00:00
|
|
|
type upsertTrustedClusterReq struct {
|
|
|
|
TrustedCluster json.RawMessage `json:"trusted_cluster"`
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *APIServer) upsertTrustedCluster(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (interface{}, error) {
|
|
|
|
var req *upsertTrustedClusterReq
|
|
|
|
if err := httplib.ReadJSON(r, &req); err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
trustedCluster, err := services.GetTrustedClusterMarshaler().Unmarshal(req.TrustedCluster)
|
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
err = auth.UpsertTrustedCluster(trustedCluster)
|
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return message("ok"), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *APIServer) validateTrustedCluster(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (interface{}, error) {
|
|
|
|
var validateRequestRaw ValidateTrustedClusterRequestRaw
|
|
|
|
if err := httplib.ReadJSON(r, &validateRequestRaw); err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
validateRequest, err := validateRequestRaw.ToNative()
|
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
validateResponse, err := auth.ValidateTrustedCluster(validateRequest)
|
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
validateResponseRaw, err := validateResponse.ToRaw()
|
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return validateResponseRaw, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *APIServer) getTrustedCluster(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (interface{}, error) {
|
|
|
|
return auth.GetTrustedCluster(p.ByName("name"))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *APIServer) getTrustedClusters(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (interface{}, error) {
|
|
|
|
return auth.GetTrustedClusters()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *APIServer) deleteTrustedCluster(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (interface{}, error) {
|
|
|
|
err := auth.DeleteTrustedCluster(p.ByName("name"))
|
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return message("ok"), 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-29 23:46:19 +00:00
|
|
|
func (s *APIServer) getTokens(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (interface{}, error) {
|
2016-12-13 03:26:59 +00:00
|
|
|
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
|
2016-12-29 23:46:19 +00:00
|
|
|
func (s *APIServer) getToken(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (interface{}, error) {
|
2016-12-14 23:48:36 +00:00
|
|
|
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-29 23:46:19 +00:00
|
|
|
func (s *APIServer) deleteToken(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (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-29 23:46:19 +00:00
|
|
|
func (s *APIServer) deleteWebSession(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (interface{}, error) {
|
2016-12-30 02:57:20 +00:00
|
|
|
user, sid := p.ByName("user"), p.ByName("sid")
|
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
|
|
|
}
|
|
|
|
|
2017-02-11 02:55:51 +00:00
|
|
|
// sessionV1 is a V1 style web session, used in legacy v1 API
|
|
|
|
type sessionV1 struct {
|
|
|
|
// ID is a session ID
|
|
|
|
ID string `json:"id"`
|
|
|
|
// Username is a user this session belongs to
|
|
|
|
Username string `json:"username"`
|
|
|
|
// ExpiresAt is an optional expiry time, if set
|
|
|
|
// that means this web session and all derived web sessions
|
|
|
|
// can not continue after this time, used in OIDC use case
|
|
|
|
// when expiry is set by external identity provider, so user
|
|
|
|
// has to relogin (or later on we'd need to refresh the token)
|
|
|
|
ExpiresAt time.Time `json:"expires_at"`
|
|
|
|
// WS is a private keypair used for signing requests
|
|
|
|
WS services.WebSessionV1 `json:"web"`
|
|
|
|
}
|
|
|
|
|
2016-12-29 23:46:19 +00:00
|
|
|
func (s *APIServer) getWebSession(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (interface{}, error) {
|
2016-12-30 02:57:20 +00:00
|
|
|
user, sid := p.ByName("user"), p.ByName("sid")
|
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
|
|
|
}
|
2017-02-11 02:55:51 +00:00
|
|
|
if version == services.V1 {
|
|
|
|
return &sessionV1{
|
|
|
|
ID: sess.GetName(),
|
|
|
|
Username: sess.GetUser(),
|
|
|
|
ExpiresAt: sess.GetExpiryTime(),
|
|
|
|
WS: *(sess.V1()),
|
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
return rawMessage(services.GetWebSessionMarshaler().MarshalWebSession(sess, services.WithVersion(version)))
|
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-29 23:46:19 +00:00
|
|
|
func (s *APIServer) signIn(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (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
|
|
|
}
|
2017-01-17 19:24:17 +00:00
|
|
|
|
2016-12-30 02:57:20 +00:00
|
|
|
user := p.ByName("user")
|
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
|
|
|
}
|
2017-02-11 02:55:51 +00:00
|
|
|
return rawMessage(services.GetWebSessionMarshaler().MarshalWebSession(sess, services.WithVersion(version)))
|
2015-03-19 04:13:56 +00:00
|
|
|
}
|
|
|
|
|
2016-12-29 23:46:19 +00:00
|
|
|
func (s *APIServer) preAuthenticatedSignIn(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (interface{}, error) {
|
2016-12-30 02:57:20 +00:00
|
|
|
user := p.ByName("user")
|
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)
|
|
|
|
}
|
2017-02-11 02:55:51 +00:00
|
|
|
return rawMessage(services.GetWebSessionMarshaler().MarshalWebSession(sess, services.WithVersion(version)))
|
2016-10-16 21:03:43 +00:00
|
|
|
}
|
|
|
|
|
2016-12-29 23:46:19 +00:00
|
|
|
func (s *APIServer) u2fSignRequest(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (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)
|
|
|
|
}
|
2016-12-30 02:57:20 +00:00
|
|
|
user := p.ByName("user")
|
2016-10-14 06:51:16 +00:00
|
|
|
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-29 23:46:19 +00:00
|
|
|
func (s *APIServer) createWebSession(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (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)
|
|
|
|
}
|
2016-12-30 02:57:20 +00:00
|
|
|
user := p.ByName("user")
|
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)
|
|
|
|
}
|
2017-02-11 02:55:51 +00:00
|
|
|
return rawMessage(services.GetWebSessionMarshaler().MarshalWebSession(sess, services.WithVersion(version)))
|
2016-02-26 22:57:51 +00:00
|
|
|
}
|
|
|
|
|
2016-02-23 20:03:34 +00:00
|
|
|
type upsertPasswordReq struct {
|
|
|
|
Password string `json:"password"`
|
|
|
|
}
|
2015-03-19 04:13:56 +00:00
|
|
|
|
2016-12-29 23:46:19 +00:00
|
|
|
func (s *APIServer) upsertPassword(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (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
|
|
|
}
|
2017-01-17 19:24:17 +00:00
|
|
|
|
2016-12-30 02:57:20 +00:00
|
|
|
user := p.ByName("user")
|
2017-01-17 20:25:39 +00:00
|
|
|
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
|
|
|
}
|
2017-01-17 19:24:17 +00:00
|
|
|
|
2017-01-17 20:25:39 +00:00
|
|
|
return message(fmt.Sprintf("password for for user %q upserted", user)), nil
|
2015-03-19 04:13:56 +00:00
|
|
|
}
|
|
|
|
|
2016-12-29 19:36:57 +00:00
|
|
|
type upsertUserRawReq struct {
|
2016-04-05 16:58:16 +00:00
|
|
|
User json.RawMessage `json:"user"`
|
|
|
|
}
|
|
|
|
|
2016-12-29 23:46:19 +00:00
|
|
|
func (s *APIServer) upsertUser(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (interface{}, error) {
|
2016-12-29 19:36:57 +00:00
|
|
|
var req *upsertUserRawReq
|
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 {
|
2017-01-17 19:24:17 +00:00
|
|
|
Password string `json:"password"`
|
|
|
|
OTPToken string `json:"otp_token"`
|
2016-02-23 20:03:34 +00:00
|
|
|
}
|
2015-03-19 04:13:56 +00:00
|
|
|
|
2016-12-29 23:46:19 +00:00
|
|
|
func (s *APIServer) checkPassword(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (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
|
|
|
}
|
2017-01-17 19:24:17 +00:00
|
|
|
|
2016-12-30 02:57:20 +00:00
|
|
|
user := p.ByName("user")
|
2017-01-17 19:24:17 +00:00
|
|
|
if err := auth.CheckPassword(user, []byte(req.Password), req.OTPToken); err != nil {
|
2016-02-23 20:03:34 +00:00
|
|
|
return nil, trace.Wrap(err)
|
2015-03-19 04:13:56 +00:00
|
|
|
}
|
2017-01-17 19:24:17 +00:00
|
|
|
|
|
|
|
return message(fmt.Sprintf("%q user password matches", user)), nil
|
2015-03-19 04:13:56 +00:00
|
|
|
}
|
|
|
|
|
2016-12-29 23:46:19 +00:00
|
|
|
func (s *APIServer) getUser(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (interface{}, error) {
|
2016-12-30 02:57:20 +00:00
|
|
|
user, err := auth.GetUser(p.ByName("user"))
|
2016-04-05 16:58:16 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
2016-12-30 21:25:35 +00:00
|
|
|
return rawMessage(services.GetUserMarshaler().MarshalUser(user, services.WithVersion(version)))
|
|
|
|
}
|
|
|
|
|
|
|
|
func rawMessage(data []byte, err error) (interface{}, error) {
|
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
m := json.RawMessage(data)
|
|
|
|
return &m, nil
|
2016-04-05 16:58:16 +00:00
|
|
|
}
|
|
|
|
|
2016-12-29 23:46:19 +00:00
|
|
|
func (s *APIServer) getUsers(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (interface{}, error) {
|
2016-12-13 03:26:59 +00:00
|
|
|
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-12-29 23:46:19 +00:00
|
|
|
out := make([]json.RawMessage, len(users))
|
|
|
|
for i, user := range users {
|
|
|
|
data, err := services.GetUserMarshaler().MarshalUser(user, services.WithVersion(version))
|
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
out[i] = data
|
|
|
|
}
|
|
|
|
return out, nil
|
2015-03-02 20:11:23 +00:00
|
|
|
}
|
|
|
|
|
2016-12-29 23:46:19 +00:00
|
|
|
func (s *APIServer) deleteUser(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (interface{}, error) {
|
2016-12-30 02:57:20 +00:00
|
|
|
user := p.ByName("user")
|
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-29 23:46:19 +00:00
|
|
|
func (s *APIServer) generateKeyPair(auth ClientI, w http.ResponseWriter, r *http.Request, _ httprouter.Params, version string) (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 {
|
2017-01-21 02:30:55 +00:00
|
|
|
Key []byte `json:"key"`
|
|
|
|
HostID string `json:"hostname"`
|
|
|
|
NodeName string `json:"node_name"`
|
|
|
|
ClusterName string `json:"auth_domain"`
|
|
|
|
Roles teleport.Roles `json:"roles"`
|
|
|
|
TTL time.Duration `json:"ttl"`
|
2015-03-02 20:11:23 +00:00
|
|
|
}
|
|
|
|
|
2016-12-29 23:46:19 +00:00
|
|
|
func (s *APIServer) generateHostCert(auth ClientI, w http.ResponseWriter, r *http.Request, _ httprouter.Params, version string) (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
|
|
|
}
|
2017-01-21 02:30:55 +00:00
|
|
|
|
|
|
|
cert, err := auth.GenerateHostCert(req.Key, req.HostID, req.NodeName, req.ClusterName, 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
|
|
|
}
|
2017-01-21 02:30:55 +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 {
|
2017-06-20 00:20:21 +00:00
|
|
|
Key []byte `json:"key"`
|
|
|
|
User string `json:"user"`
|
|
|
|
TTL time.Duration `json:"ttl"`
|
|
|
|
Compatibility string `json:"compatibility,omitempty"`
|
2016-02-23 20:03:34 +00:00
|
|
|
}
|
|
|
|
|
2016-12-29 23:46:19 +00:00
|
|
|
func (s *APIServer) generateUserCert(auth ClientI, w http.ResponseWriter, r *http.Request, _ httprouter.Params, version string) (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
|
|
|
}
|
2017-06-20 00:20:21 +00:00
|
|
|
compatibility, err := utils.CheckCompatibilityFlag(req.Compatibility)
|
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
cert, err := auth.GenerateUserCert(req.Key, req.User, req.TTL, compatibility)
|
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 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-29 23:46:19 +00:00
|
|
|
func (s *APIServer) generateToken(auth ClientI, w http.ResponseWriter, r *http.Request, _ httprouter.Params, version string) (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 {
|
2017-01-21 02:30:55 +00:00
|
|
|
HostID string `json:"hostID"`
|
|
|
|
NodeName string `json:"node_name"`
|
|
|
|
Role teleport.Role `json:"role"`
|
|
|
|
Token string `json:"token"`
|
2016-02-23 20:03:34 +00:00
|
|
|
}
|
2015-11-13 01:32:45 +00:00
|
|
|
|
2016-12-29 23:46:19 +00:00
|
|
|
func (s *APIServer) registerUsingToken(auth ClientI, w http.ResponseWriter, r *http.Request, _ httprouter.Params, version string) (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
|
|
|
}
|
2017-01-21 02:30:55 +00:00
|
|
|
|
|
|
|
keys, err := auth.RegisterUsingToken(req.Token, req.HostID, req.NodeName, 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
|
|
|
}
|
2017-01-21 02:30:55 +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-29 23:46:19 +00:00
|
|
|
func (s *APIServer) registerNewAuthServer(auth ClientI, w http.ResponseWriter, r *http.Request, _ httprouter.Params, version string) (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-12-29 19:36:57 +00:00
|
|
|
type upsertCertAuthorityRawReq struct {
|
|
|
|
CA json.RawMessage `json:"ca"`
|
|
|
|
TTL time.Duration `json:"ttl"`
|
2015-03-02 20:11:23 +00:00
|
|
|
}
|
|
|
|
|
2016-12-29 23:46:19 +00:00
|
|
|
func (s *APIServer) upsertCertAuthority(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (interface{}, error) {
|
2016-12-29 19:36:57 +00:00
|
|
|
var req *upsertCertAuthorityRawReq
|
2016-02-23 20:03:34 +00:00
|
|
|
if err := httplib.ReadJSON(r, &req); err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
2015-06-22 21:05:15 +00:00
|
|
|
}
|
2016-12-29 19:36:57 +00:00
|
|
|
ca, err := services.GetCertAuthorityMarshaler().UnmarshalCertAuthority(req.CA)
|
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
2017-04-07 23:51:31 +00:00
|
|
|
if req.TTL != 0 {
|
|
|
|
ca.SetTTL(s, req.TTL)
|
|
|
|
}
|
|
|
|
if err := auth.UpsertCertAuthority(ca); 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-29 23:46:19 +00:00
|
|
|
func (s *APIServer) getCertAuthorities(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (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-30 02:57:20 +00:00
|
|
|
certs, err := auth.GetCertAuthorities(services.CertAuthType(p.ByName("type")), loadKeys)
|
2017-03-02 19:50:35 +00:00
|
|
|
|
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-12-29 19:36:57 +00:00
|
|
|
items := make([]json.RawMessage, len(certs))
|
|
|
|
for i, cert := range certs {
|
2016-12-29 23:46:19 +00:00
|
|
|
data, err := services.GetCertAuthorityMarshaler().MarshalCertAuthority(cert, services.WithVersion(version))
|
2016-12-29 19:36:57 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
items[i] = data
|
|
|
|
}
|
|
|
|
return items, nil
|
2015-11-18 04:39:19 +00:00
|
|
|
}
|
|
|
|
|
2016-12-29 23:46:19 +00:00
|
|
|
func (s *APIServer) getCertAuthority(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (interface{}, error) {
|
2016-12-14 23:48:36 +00:00
|
|
|
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)
|
|
|
|
}
|
2016-12-30 21:25:35 +00:00
|
|
|
return rawMessage(services.GetCertAuthorityMarshaler().MarshalCertAuthority(ca, services.WithVersion(version)))
|
2016-12-14 23:48:36 +00:00
|
|
|
}
|
|
|
|
|
2016-12-29 23:46:19 +00:00
|
|
|
func (s *APIServer) getDomainName(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (interface{}, error) {
|
2016-12-13 03:26:59 +00:00
|
|
|
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-29 23:46:19 +00:00
|
|
|
func (s *APIServer) getU2FAppID(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (interface{}, error) {
|
2017-07-28 18:37:12 +00:00
|
|
|
cap, err := auth.GetAuthPreference()
|
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
universalSecondFactor, err := cap.GetU2F()
|
2016-11-28 08:21:37 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
2017-02-14 02:29:27 +00:00
|
|
|
|
2016-12-08 10:23:51 +00:00
|
|
|
w.Header().Set("Content-Type", "application/fido.trusted-apps+json")
|
2017-07-28 18:37:12 +00:00
|
|
|
return universalSecondFactor.AppID, nil
|
2016-11-28 08:21:37 +00:00
|
|
|
}
|
|
|
|
|
2016-12-29 23:46:19 +00:00
|
|
|
func (s *APIServer) deleteCertAuthority(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (interface{}, error) {
|
2016-02-16 17:36:02 +00:00
|
|
|
id := services.CertAuthID{
|
2016-12-30 02:57:20 +00:00
|
|
|
DomainName: p.ByName("domain"),
|
|
|
|
Type: services.CertAuthType(p.ByName("type")),
|
2016-02-16 17:36:02 +00:00
|
|
|
}
|
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-29 23:46:19 +00:00
|
|
|
func (s *APIServer) createSession(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (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
|
|
|
}
|
2017-04-26 20:31:27 +00:00
|
|
|
namespace := p.ByName("namespace")
|
|
|
|
if !services.IsValidNamespace(namespace) {
|
|
|
|
return nil, trace.BadParameter("invalid namespace %q", namespace)
|
|
|
|
}
|
|
|
|
req.Session.Namespace = 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-29 23:46:19 +00:00
|
|
|
func (s *APIServer) updateSession(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (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)
|
|
|
|
}
|
2017-04-26 20:31:27 +00:00
|
|
|
namespace := p.ByName("namespace")
|
|
|
|
if !services.IsValidNamespace(namespace) {
|
|
|
|
return nil, trace.BadParameter("invalid namespace %q", namespace)
|
|
|
|
}
|
|
|
|
req.Update.Namespace = 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-29 23:46:19 +00:00
|
|
|
func (s *APIServer) getSessions(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (interface{}, error) {
|
2017-04-26 20:31:27 +00:00
|
|
|
namespace := p.ByName("namespace")
|
|
|
|
if !services.IsValidNamespace(namespace) {
|
|
|
|
return nil, trace.BadParameter("invalid namespace %q", namespace)
|
|
|
|
}
|
|
|
|
sessions, err := auth.GetSessions(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-29 23:46:19 +00:00
|
|
|
func (s *APIServer) getSession(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (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)
|
|
|
|
}
|
2017-04-26 20:31:27 +00:00
|
|
|
namespace := p.ByName("namespace")
|
|
|
|
if !services.IsValidNamespace(namespace) {
|
|
|
|
return nil, trace.BadParameter("invalid namespace %q", namespace)
|
|
|
|
}
|
|
|
|
se, err := auth.GetSession(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 {
|
2017-01-17 19:24:17 +00:00
|
|
|
User string `json:"user"`
|
|
|
|
QRImg []byte `json:"qrimg"`
|
2016-02-23 20:03:34 +00:00
|
|
|
}
|
|
|
|
|
2017-01-17 19:24:17 +00:00
|
|
|
// getSignupTokenData returns the signup data for a token.
|
2016-12-29 23:46:19 +00:00
|
|
|
func (s *APIServer) getSignupTokenData(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (interface{}, error) {
|
2016-12-30 02:57:20 +00:00
|
|
|
token := p.ByName("token")
|
2016-01-21 00:05:23 +00:00
|
|
|
|
2017-01-17 19:24:17 +00:00
|
|
|
user, otpQRCode, 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{
|
2017-01-17 19:24:17 +00:00
|
|
|
User: user,
|
|
|
|
QRImg: otpQRCode,
|
2016-02-23 20:03:34 +00:00
|
|
|
}, nil
|
2016-01-21 00:05:23 +00:00
|
|
|
}
|
|
|
|
|
2016-12-29 23:46:19 +00:00
|
|
|
func (s *APIServer) getSignupU2FRegisterRequest(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (interface{}, error) {
|
2016-12-30 02:57:20 +00:00
|
|
|
token := p.ByName("token")
|
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-12-30 02:57:20 +00:00
|
|
|
User services.UserV1 `json:"user"`
|
2016-04-05 16:58:16 +00:00
|
|
|
}
|
|
|
|
|
2016-12-29 23:46:19 +00:00
|
|
|
func (s *APIServer) createSignupToken(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (interface{}, error) {
|
2016-12-30 02:57:20 +00:00
|
|
|
var req *createSignupTokenReq
|
2017-01-17 19:24:17 +00:00
|
|
|
|
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
|
|
|
}
|
2017-01-17 19:24:17 +00:00
|
|
|
|
2016-12-30 02:57:20 +00:00
|
|
|
if err := req.User.Check(); err != nil {
|
2016-12-30 00:17:56 +00:00
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
2017-01-17 19:24:17 +00:00
|
|
|
|
2016-12-30 02:57:20 +00:00
|
|
|
token, err := auth.CreateSignupToken(req.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
|
|
|
}
|
2017-01-17 19:24:17 +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 {
|
2017-01-17 19:24:17 +00:00
|
|
|
Token string `json:"token"`
|
|
|
|
Password string `json:"password"`
|
|
|
|
OTPToken string `json:"otp_token"`
|
2015-07-11 00:24:44 +00:00
|
|
|
}
|
|
|
|
|
2016-12-29 23:46:19 +00:00
|
|
|
func (s *APIServer) createUserWithToken(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (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)
|
|
|
|
}
|
2017-01-17 19:24:17 +00:00
|
|
|
|
2017-07-28 18:37:12 +00:00
|
|
|
cap, err := auth.GetAuthPreference()
|
2017-03-22 02:08:27 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
var webSession services.WebSession
|
|
|
|
|
|
|
|
switch cap.GetSecondFactor() {
|
|
|
|
case teleport.OFF:
|
|
|
|
webSession, err = auth.CreateUserWithoutOTP(req.Token, req.Password)
|
|
|
|
case teleport.OTP, teleport.TOTP, teleport.HOTP:
|
|
|
|
webSession, err = auth.CreateUserWithOTP(req.Token, req.Password, req.OTPToken)
|
|
|
|
}
|
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)
|
|
|
|
}
|
2017-01-17 19:24:17 +00:00
|
|
|
|
2017-03-22 02:08:27 +00:00
|
|
|
return rawMessage(services.GetWebSessionMarshaler().MarshalWebSession(webSession, services.WithVersion(version)))
|
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-29 23:46:19 +00:00
|
|
|
func (s *APIServer) createUserWithU2FToken(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (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
|
|
|
}
|
2017-02-11 02:55:51 +00:00
|
|
|
return rawMessage(services.GetWebSessionMarshaler().MarshalWebSession(sess, services.WithVersion(version)))
|
2015-12-07 20:05:54 +00:00
|
|
|
}
|
|
|
|
|
2016-12-29 19:36:57 +00:00
|
|
|
type upsertOIDCConnectorRawReq struct {
|
|
|
|
Connector json.RawMessage `json:"connector"`
|
|
|
|
TTL time.Duration `json:"ttl"`
|
2016-04-03 05:20:51 +00:00
|
|
|
}
|
|
|
|
|
2016-12-29 23:46:19 +00:00
|
|
|
func (s *APIServer) upsertOIDCConnector(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (interface{}, error) {
|
2016-12-29 19:36:57 +00:00
|
|
|
var req *upsertOIDCConnectorRawReq
|
2016-04-03 05:20:51 +00:00
|
|
|
if err := httplib.ReadJSON(r, &req); err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
2016-12-29 19:36:57 +00:00
|
|
|
connector, err := services.GetOIDCConnectorMarshaler().UnmarshalOIDCConnector(req.Connector)
|
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
2017-04-07 23:51:31 +00:00
|
|
|
if req.TTL != 0 {
|
|
|
|
connector.SetTTL(s, req.TTL)
|
|
|
|
}
|
|
|
|
err = auth.UpsertOIDCConnector(connector)
|
2016-04-03 05:20:51 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
return message("ok"), nil
|
|
|
|
}
|
|
|
|
|
2016-12-29 23:46:19 +00:00
|
|
|
func (s *APIServer) getOIDCConnector(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (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-30 02:57:20 +00:00
|
|
|
connector, err := auth.GetOIDCConnector(p.ByName("id"), withSecrets)
|
2016-04-03 05:20:51 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
2016-12-30 21:25:35 +00:00
|
|
|
return rawMessage(services.GetOIDCConnectorMarshaler().MarshalOIDCConnector(connector, services.WithVersion(version)))
|
2016-04-03 05:20:51 +00:00
|
|
|
}
|
|
|
|
|
2016-12-29 23:46:19 +00:00
|
|
|
func (s *APIServer) deleteOIDCConnector(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (interface{}, error) {
|
2016-12-30 02:57:20 +00:00
|
|
|
err := auth.DeleteOIDCConnector(p.ByName("id"))
|
2016-04-03 05:20:51 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
return message("ok"), nil
|
|
|
|
}
|
|
|
|
|
2016-12-29 23:46:19 +00:00
|
|
|
func (s *APIServer) getOIDCConnectors(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (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)
|
|
|
|
}
|
2016-12-29 19:36:57 +00:00
|
|
|
items := make([]json.RawMessage, len(connectors))
|
|
|
|
for i, connector := range connectors {
|
2016-12-29 23:46:19 +00:00
|
|
|
data, err := services.GetOIDCConnectorMarshaler().MarshalOIDCConnector(connector, services.WithVersion(version))
|
2016-12-29 19:36:57 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
items[i] = data
|
|
|
|
}
|
|
|
|
return items, nil
|
2016-04-03 05:20:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type createOIDCAuthRequestReq struct {
|
|
|
|
Req services.OIDCAuthRequest `json:"req"`
|
|
|
|
}
|
|
|
|
|
2016-12-29 23:46:19 +00:00
|
|
|
func (s *APIServer) createOIDCAuthRequest(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (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-29 20:23:58 +00:00
|
|
|
// oidcAuthRawResponse is returned when auth server validated callback parameters
|
|
|
|
// returned from OIDC provider
|
|
|
|
type oidcAuthRawResponse struct {
|
|
|
|
// Username is authenticated teleport username
|
|
|
|
Username string `json:"username"`
|
|
|
|
// Identity contains validated OIDC identity
|
2017-05-05 22:53:05 +00:00
|
|
|
Identity services.ExternalIdentity `json:"identity"`
|
2016-12-29 20:23:58 +00:00
|
|
|
// Web session will be generated by auth server if requested in OIDCAuthRequest
|
2017-02-11 02:55:51 +00:00
|
|
|
Session json.RawMessage `json:"session,omitempty"`
|
2016-12-29 20:23:58 +00:00
|
|
|
// Cert will be generated by certificate authority
|
|
|
|
Cert []byte `json:"cert,omitempty"`
|
|
|
|
// Req is original oidc auth request
|
|
|
|
Req services.OIDCAuthRequest `json:"req"`
|
|
|
|
// HostSigners is a list of signing host public keys
|
|
|
|
// trusted by proxy, used in console login
|
|
|
|
HostSigners []json.RawMessage `json:"host_signers"`
|
|
|
|
}
|
|
|
|
|
2016-12-29 23:46:19 +00:00
|
|
|
func (s *APIServer) validateOIDCAuthCallback(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (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)
|
|
|
|
}
|
2016-12-29 20:23:58 +00:00
|
|
|
raw := oidcAuthRawResponse{
|
|
|
|
Username: response.Username,
|
|
|
|
Identity: response.Identity,
|
|
|
|
Cert: response.Cert,
|
|
|
|
Req: response.Req,
|
|
|
|
}
|
2017-02-11 02:55:51 +00:00
|
|
|
if response.Session != nil {
|
|
|
|
rawSession, err := services.GetWebSessionMarshaler().MarshalWebSession(response.Session, services.WithVersion(version))
|
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
raw.Session = rawSession
|
2017-05-05 22:53:05 +00:00
|
|
|
}
|
|
|
|
raw.HostSigners = make([]json.RawMessage, len(response.HostSigners))
|
|
|
|
for i, ca := range response.HostSigners {
|
|
|
|
data, err := services.GetCertAuthorityMarshaler().MarshalCertAuthority(ca, services.WithVersion(version))
|
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
raw.HostSigners[i] = data
|
|
|
|
}
|
|
|
|
return &raw, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
type createSAMLConnectorRawReq struct {
|
|
|
|
Connector json.RawMessage `json:"connector"`
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *APIServer) createSAMLConnector(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (interface{}, error) {
|
|
|
|
var req *createSAMLConnectorRawReq
|
|
|
|
if err := httplib.ReadJSON(r, &req); err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
connector, err := services.GetSAMLConnectorMarshaler().UnmarshalSAMLConnector(req.Connector)
|
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
err = auth.CreateSAMLConnector(connector)
|
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
return message("ok"), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
type upsertSAMLConnectorRawReq struct {
|
|
|
|
Connector json.RawMessage `json:"connector"`
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *APIServer) upsertSAMLConnector(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (interface{}, error) {
|
|
|
|
var req *upsertSAMLConnectorRawReq
|
|
|
|
if err := httplib.ReadJSON(r, &req); err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
connector, err := services.GetSAMLConnectorMarshaler().UnmarshalSAMLConnector(req.Connector)
|
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
err = auth.UpsertSAMLConnector(connector)
|
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
return message("ok"), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *APIServer) getSAMLConnector(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (interface{}, error) {
|
|
|
|
withSecrets, _, err := httplib.ParseBool(r.URL.Query(), "with_secrets")
|
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
connector, err := auth.GetSAMLConnector(p.ByName("id"), withSecrets)
|
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
return rawMessage(services.GetSAMLConnectorMarshaler().MarshalSAMLConnector(connector, services.WithVersion(version)))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *APIServer) deleteSAMLConnector(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (interface{}, error) {
|
|
|
|
err := auth.DeleteSAMLConnector(p.ByName("id"))
|
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
return message("ok"), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *APIServer) getSAMLConnectors(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (interface{}, error) {
|
|
|
|
withSecrets, _, err := httplib.ParseBool(r.URL.Query(), "with_secrets")
|
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
connectors, err := auth.GetSAMLConnectors(withSecrets)
|
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
items := make([]json.RawMessage, len(connectors))
|
|
|
|
for i, connector := range connectors {
|
|
|
|
data, err := services.GetSAMLConnectorMarshaler().MarshalSAMLConnector(connector, services.WithVersion(version))
|
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
items[i] = data
|
|
|
|
}
|
|
|
|
return items, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
type createSAMLAuthRequestReq struct {
|
|
|
|
Req services.SAMLAuthRequest `json:"req"`
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *APIServer) createSAMLAuthRequest(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (interface{}, error) {
|
|
|
|
var req *createSAMLAuthRequestReq
|
|
|
|
if err := httplib.ReadJSON(r, &req); err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
response, err := auth.CreateSAMLAuthRequest(req.Req)
|
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
return response, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
type validateSAMLResponseReq struct {
|
|
|
|
Response string `json:"response"`
|
|
|
|
}
|
|
|
|
|
|
|
|
// samlAuthRawResponse is returned when auth server validated callback parameters
|
|
|
|
// returned from SAML provider
|
|
|
|
type samlAuthRawResponse struct {
|
|
|
|
// Username is authenticated teleport username
|
|
|
|
Username string `json:"username"`
|
|
|
|
// Identity contains validated OIDC identity
|
|
|
|
Identity services.ExternalIdentity `json:"identity"`
|
|
|
|
// Web session will be generated by auth server if requested in OIDCAuthRequest
|
|
|
|
Session json.RawMessage `json:"session,omitempty"`
|
|
|
|
// Cert will be generated by certificate authority
|
|
|
|
Cert []byte `json:"cert,omitempty"`
|
|
|
|
// Req is original oidc auth request
|
|
|
|
Req services.SAMLAuthRequest `json:"req"`
|
|
|
|
// HostSigners is a list of signing host public keys
|
|
|
|
// trusted by proxy, used in console login
|
|
|
|
HostSigners []json.RawMessage `json:"host_signers"`
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *APIServer) validateSAMLResponse(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (interface{}, error) {
|
|
|
|
var req *validateSAMLResponseReq
|
|
|
|
if err := httplib.ReadJSON(r, &req); err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
response, err := auth.ValidateSAMLResponse(req.Response)
|
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
raw := samlAuthRawResponse{
|
|
|
|
Username: response.Username,
|
|
|
|
Identity: response.Identity,
|
|
|
|
Cert: response.Cert,
|
|
|
|
Req: response.Req,
|
|
|
|
}
|
|
|
|
if response.Session != nil {
|
|
|
|
rawSession, err := services.GetWebSessionMarshaler().MarshalWebSession(response.Session, services.WithVersion(version))
|
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
raw.Session = rawSession
|
2017-02-11 02:55:51 +00:00
|
|
|
}
|
2016-12-29 20:23:58 +00:00
|
|
|
raw.HostSigners = make([]json.RawMessage, len(response.HostSigners))
|
|
|
|
for i, ca := range response.HostSigners {
|
2016-12-29 23:46:19 +00:00
|
|
|
data, err := services.GetCertAuthorityMarshaler().MarshalCertAuthority(ca, services.WithVersion(version))
|
2016-12-29 20:23:58 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
raw.HostSigners[i] = data
|
|
|
|
}
|
2017-02-11 19:05:09 +00:00
|
|
|
return &raw, nil
|
2016-04-03 05:20:51 +00:00
|
|
|
}
|
|
|
|
|
2016-12-29 20:23:58 +00:00
|
|
|
// HTTP GET /:version/events?query
|
2016-04-29 09:42:08 +00:00
|
|
|
//
|
|
|
|
// 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-29 23:46:19 +00:00
|
|
|
func (s *APIServer) searchEvents(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (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-12-29 20:23:58 +00:00
|
|
|
// HTTP POST /:version/events
|
2016-12-29 23:46:19 +00:00
|
|
|
func (s *APIServer) emitAuditEvent(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (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
|
|
|
|
}
|
|
|
|
|
2017-05-27 01:03:19 +00:00
|
|
|
// HTTP POST /:version/sessions/:id/slice
|
|
|
|
func (s *APIServer) postSessionSlice(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (interface{}, error) {
|
|
|
|
data, err := ioutil.ReadAll(r.Body)
|
|
|
|
if err != nil {
|
2017-05-26 01:56:32 +00:00
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
2017-05-27 01:03:19 +00:00
|
|
|
var slice events.SessionSlice
|
|
|
|
if err := slice.Unmarshal(data); err != nil {
|
|
|
|
return nil, trace.BadParameter("failed to unmarshal %v", err)
|
|
|
|
}
|
|
|
|
if err := auth.PostSessionSlice(slice); err != nil {
|
2017-05-26 01:56:32 +00:00
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
return message("ok"), nil
|
|
|
|
}
|
|
|
|
|
2016-12-29 20:23:58 +00:00
|
|
|
// HTTP POST /:version/sessions/:id/stream
|
2016-12-29 23:46:19 +00:00
|
|
|
func (s *APIServer) postSessionChunk(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (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")
|
2017-04-26 20:31:27 +00:00
|
|
|
if !services.IsValidNamespace(namespace) {
|
|
|
|
return nil, trace.BadParameter("invalid namespace %q", namespace)
|
|
|
|
}
|
2016-12-13 03:26:59 +00:00
|
|
|
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-12-29 20:23:58 +00:00
|
|
|
// HTTP GET /:version/sessions/:id/stream?offset=x&bytes=y
|
2016-05-06 06:51:56 +00:00
|
|
|
// Query parameters:
|
|
|
|
// "offset" : bytes from the beginning
|
|
|
|
// "bytes" : number of bytes to read (it won't return more than 512Kb)
|
2016-12-29 23:46:19 +00:00
|
|
|
func (s *APIServer) getSessionChunk(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (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")
|
2017-04-26 20:31:27 +00:00
|
|
|
if !services.IsValidNamespace(namespace) {
|
|
|
|
return nil, trace.BadParameter("invalid namespace %q", namespace)
|
|
|
|
}
|
2016-12-13 03:26:59 +00:00
|
|
|
|
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-12-29 20:23:58 +00:00
|
|
|
// HTTP GET /:version/sessions/:id/events?maxage=n
|
2016-04-30 05:43:22 +00:00
|
|
|
// Query:
|
|
|
|
// 'after' : cursor value to return events newer than N. Defaults to 0, (return all)
|
2016-12-29 23:46:19 +00:00
|
|
|
func (s *APIServer) getSessionEvents(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (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")
|
2017-04-26 20:31:27 +00:00
|
|
|
if !services.IsValidNamespace(namespace) {
|
|
|
|
return nil, trace.BadParameter("invalid namespace %q", namespace)
|
|
|
|
}
|
2016-04-30 05:43:22 +00:00
|
|
|
afterN, err := strconv.Atoi(r.URL.Query().Get("after"))
|
|
|
|
if err != nil {
|
|
|
|
afterN = 0
|
|
|
|
}
|
2016-12-13 03:26:59 +00:00
|
|
|
return auth.GetSessionEvents(namespace, *sid, afterN)
|
|
|
|
}
|
|
|
|
|
|
|
|
type upsertNamespaceReq struct {
|
|
|
|
Namespace services.Namespace `json:"namespace"`
|
|
|
|
}
|
|
|
|
|
2016-12-29 23:46:19 +00:00
|
|
|
func (s *APIServer) upsertNamespace(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (interface{}, error) {
|
2016-12-13 03:26:59 +00:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2016-12-29 23:46:19 +00:00
|
|
|
func (s *APIServer) getNamespaces(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (interface{}, error) {
|
2016-12-13 03:26:59 +00:00
|
|
|
namespaces, err := auth.GetNamespaces()
|
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
return namespaces, nil
|
|
|
|
}
|
|
|
|
|
2016-12-29 23:46:19 +00:00
|
|
|
func (s *APIServer) getNamespace(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (interface{}, error) {
|
2016-12-13 03:26:59 +00:00
|
|
|
name := p.ByName("namespace")
|
2017-04-26 20:31:27 +00:00
|
|
|
if !services.IsValidNamespace(name) {
|
|
|
|
return nil, trace.BadParameter("invalid namespace %q", name)
|
|
|
|
}
|
|
|
|
|
2016-12-13 03:26:59 +00:00
|
|
|
namespace, err := auth.GetNamespace(name)
|
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
return namespace, nil
|
|
|
|
}
|
|
|
|
|
2016-12-29 23:46:19 +00:00
|
|
|
func (s *APIServer) deleteNamespace(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (interface{}, error) {
|
2016-12-13 03:26:59 +00:00
|
|
|
name := p.ByName("namespace")
|
2017-04-26 20:31:27 +00:00
|
|
|
if !services.IsValidNamespace(name) {
|
|
|
|
return nil, trace.BadParameter("invalid namespace %q", name)
|
|
|
|
}
|
|
|
|
|
2016-12-13 03:26:59 +00:00
|
|
|
err := auth.DeleteNamespace(name)
|
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
return message("ok"), nil
|
|
|
|
}
|
|
|
|
|
2016-12-29 19:36:57 +00:00
|
|
|
type upsertRoleRawReq struct {
|
2016-12-17 03:33:18 +00:00
|
|
|
Role json.RawMessage `json:"role"`
|
2016-12-13 03:26:59 +00:00
|
|
|
}
|
|
|
|
|
2016-12-29 23:46:19 +00:00
|
|
|
func (s *APIServer) upsertRole(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (interface{}, error) {
|
2016-12-29 19:36:57 +00:00
|
|
|
var req *upsertRoleRawReq
|
2016-12-13 03:26:59 +00:00
|
|
|
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)
|
|
|
|
}
|
2017-04-04 21:46:23 +00:00
|
|
|
err = auth.UpsertRole(role, backend.Forever)
|
2016-12-13 03:26:59 +00:00
|
|
|
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
|
|
|
}
|
|
|
|
|
2016-12-29 23:46:19 +00:00
|
|
|
func (s *APIServer) getRole(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (interface{}, error) {
|
2016-12-30 02:57:20 +00:00
|
|
|
role, err := auth.GetRole(p.ByName("role"))
|
2016-12-13 03:26:59 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
2016-12-30 21:25:35 +00:00
|
|
|
return rawMessage(services.GetRoleMarshaler().MarshalRole(role, services.WithVersion(version)))
|
2016-12-13 03:26:59 +00:00
|
|
|
}
|
|
|
|
|
2016-12-29 23:46:19 +00:00
|
|
|
func (s *APIServer) getRoles(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (interface{}, error) {
|
2016-12-13 03:26:59 +00:00
|
|
|
roles, err := auth.GetRoles()
|
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
2016-12-30 02:57:20 +00:00
|
|
|
out := make([]json.RawMessage, len(roles))
|
2016-12-29 19:36:57 +00:00
|
|
|
for i, role := range roles {
|
2016-12-29 23:46:19 +00:00
|
|
|
raw, err := services.GetRoleMarshaler().MarshalRole(role, services.WithVersion(version))
|
2016-12-29 19:36:57 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
2016-12-30 02:57:20 +00:00
|
|
|
out[i] = raw
|
2016-12-29 19:36:57 +00:00
|
|
|
}
|
|
|
|
return out, nil
|
2016-12-13 03:26:59 +00:00
|
|
|
}
|
|
|
|
|
2016-12-29 23:46:19 +00:00
|
|
|
func (s *APIServer) deleteRole(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (interface{}, error) {
|
2016-12-30 02:57:20 +00:00
|
|
|
role := p.ByName("role")
|
2016-12-13 03:26:59 +00:00
|
|
|
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
|
|
|
}
|
|
|
|
|
2017-07-28 18:37:12 +00:00
|
|
|
func (s *APIServer) getClusterName(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (interface{}, error) {
|
|
|
|
cn, err := auth.GetClusterName()
|
2017-02-14 02:29:27 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
|
2017-07-28 18:37:12 +00:00
|
|
|
return rawMessage(services.GetClusterNameMarshaler().Marshal(cn, services.WithVersion(version)))
|
2017-02-14 02:29:27 +00:00
|
|
|
}
|
|
|
|
|
2017-07-28 18:37:12 +00:00
|
|
|
type setClusterNameReq struct {
|
|
|
|
ClusterName json.RawMessage `json:"cluster_name"`
|
2017-02-14 02:29:27 +00:00
|
|
|
}
|
|
|
|
|
2017-07-28 18:37:12 +00:00
|
|
|
func (s *APIServer) setClusterName(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (interface{}, error) {
|
|
|
|
var req *setClusterNameReq
|
2017-02-14 02:29:27 +00:00
|
|
|
|
|
|
|
err := httplib.ReadJSON(r, &req)
|
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
|
2017-07-28 18:37:12 +00:00
|
|
|
cn, err := services.GetClusterNameMarshaler().Unmarshal(req.ClusterName)
|
2017-02-14 02:29:27 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
|
2017-07-28 18:37:12 +00:00
|
|
|
err = auth.SetClusterName(cn)
|
2017-02-14 02:29:27 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
|
2017-07-28 18:37:12 +00:00
|
|
|
return message(fmt.Sprintf("cluster name set: %+v", cn)), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *APIServer) getStaticTokens(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (interface{}, error) {
|
|
|
|
st, err := auth.GetStaticTokens()
|
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return rawMessage(services.GetStaticTokensMarshaler().Marshal(st, services.WithVersion(version)))
|
|
|
|
}
|
|
|
|
|
|
|
|
type setStaticTokensReq struct {
|
|
|
|
StaticTokens json.RawMessage `json:"static_tokens"`
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *APIServer) setStaticTokens(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (interface{}, error) {
|
|
|
|
var req *setStaticTokensReq
|
|
|
|
|
|
|
|
err := httplib.ReadJSON(r, &req)
|
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
st, err := services.GetStaticTokensMarshaler().Unmarshal(req.StaticTokens)
|
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
err = auth.SetStaticTokens(st)
|
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return message(fmt.Sprintf("static tokens set: %+v", st)), nil
|
2017-02-14 02:29:27 +00:00
|
|
|
}
|
|
|
|
|
2017-07-28 18:37:12 +00:00
|
|
|
func (s *APIServer) getClusterAuthPreference(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (interface{}, error) {
|
|
|
|
cap, err := auth.GetAuthPreference()
|
2017-02-14 02:29:27 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
|
2017-07-28 18:37:12 +00:00
|
|
|
return rawMessage(services.GetAuthPreferenceMarshaler().Marshal(cap, services.WithVersion(version)))
|
2017-02-14 02:29:27 +00:00
|
|
|
}
|
|
|
|
|
2017-07-28 18:37:12 +00:00
|
|
|
type setClusterAuthPreferenceReq struct {
|
|
|
|
ClusterAuthPreference json.RawMessage `json:"cluster_auth_prerference"`
|
2017-02-14 02:29:27 +00:00
|
|
|
}
|
|
|
|
|
2017-07-28 18:37:12 +00:00
|
|
|
func (s *APIServer) setClusterAuthPreference(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (interface{}, error) {
|
|
|
|
var req *setClusterAuthPreferenceReq
|
2017-02-14 02:29:27 +00:00
|
|
|
|
|
|
|
err := httplib.ReadJSON(r, &req)
|
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
|
2017-07-28 18:37:12 +00:00
|
|
|
cap, err := services.GetAuthPreferenceMarshaler().Unmarshal(req.ClusterAuthPreference)
|
2017-02-14 02:29:27 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
|
2017-07-28 18:37:12 +00:00
|
|
|
err = auth.SetAuthPreference(cap)
|
2017-02-14 02:29:27 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, trace.Wrap(err)
|
|
|
|
}
|
|
|
|
|
2017-07-28 18:37:12 +00:00
|
|
|
return message(fmt.Sprintf("cluster authenticaton preference set: %+v", cap)), nil
|
2017-02-14 02:29:27 +00:00
|
|
|
}
|
|
|
|
|
2015-03-02 20:11:23 +00:00
|
|
|
func message(msg string) map[string]interface{} {
|
|
|
|
return map[string]interface{}{"message": msg}
|
|
|
|
}
|