certificates/authority/admin/api/middleware.go
2022-03-24 10:54:45 +01:00

82 lines
2.2 KiB
Go

package api
import (
"context"
"net/http"
"go.step.sm/linkedca"
"github.com/smallstep/certificates/api"
"github.com/smallstep/certificates/authority/admin"
"github.com/smallstep/certificates/authority/admin/db/nosql"
)
type nextHTTP = func(http.ResponseWriter, *http.Request)
// requireAPIEnabled is a middleware that ensures the Administration API
// is enabled before servicing requests.
func (h *Handler) requireAPIEnabled(next nextHTTP) nextHTTP {
return func(w http.ResponseWriter, r *http.Request) {
if !h.auth.IsAdminAPIEnabled() {
api.WriteError(w, admin.NewError(admin.ErrorNotImplementedType,
"administration API not enabled"))
return
}
next(w, r)
}
}
// extractAuthorizeTokenAdmin is a middleware that extracts and caches the bearer token.
func (h *Handler) extractAuthorizeTokenAdmin(next nextHTTP) nextHTTP {
return func(w http.ResponseWriter, r *http.Request) {
tok := r.Header.Get("Authorization")
if tok == "" {
api.WriteError(w, admin.NewError(admin.ErrorUnauthorizedType,
"missing authorization header token"))
return
}
adm, err := h.auth.AuthorizeAdminToken(r, tok)
if err != nil {
api.WriteError(w, err)
return
}
ctx := linkedca.WithAdmin(r.Context(), adm)
next(w, r.WithContext(ctx))
}
}
// checkAction checks if an action is supported in standalone or not
func (h *Handler) checkAction(next nextHTTP, supportedInStandalone bool) nextHTTP {
return func(w http.ResponseWriter, r *http.Request) {
// actions allowed in standalone mode are always supported
if supportedInStandalone {
next(w, r)
return
}
// when not in standalone mode and using a nosql.DB backend,
// actions are not supported
if _, ok := h.adminDB.(*nosql.DB); ok {
api.WriteError(w, admin.NewError(admin.ErrorNotImplementedType,
"operation not supported in standalone mode"))
return
}
// continue to next http handler
next(w, r)
}
}
// adminFromContext searches the context for a *linkedca.Admin.
// Returns the admin or an error.
func adminFromContext(ctx context.Context) (*linkedca.Admin, error) {
val, ok := ctx.Value(admin.AdminContextKey).(*linkedca.Admin)
if !ok || val == nil {
return nil, admin.NewError(admin.ErrorBadRequestType, "admin not in context")
}
return val, nil
}