2021-05-03 19:48:20 +00:00
|
|
|
package api
|
|
|
|
|
|
|
|
import (
|
2021-05-18 04:07:25 +00:00
|
|
|
"fmt"
|
2021-05-03 19:48:20 +00:00
|
|
|
"net/http"
|
|
|
|
|
|
|
|
"github.com/go-chi/chi"
|
|
|
|
"github.com/smallstep/certificates/api"
|
2021-05-18 04:07:25 +00:00
|
|
|
"github.com/smallstep/certificates/authority/admin"
|
2021-05-12 07:03:40 +00:00
|
|
|
"github.com/smallstep/certificates/authority/mgmt"
|
2021-05-18 23:50:54 +00:00
|
|
|
"github.com/smallstep/certificates/authority/status"
|
2021-05-03 19:48:20 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// CreateAdminRequest represents the body for a CreateAdmin request.
|
|
|
|
type CreateAdminRequest struct {
|
2021-05-18 23:50:54 +00:00
|
|
|
Subject string `json:"subject"`
|
|
|
|
Provisioner string `json:"provisioner"`
|
|
|
|
Type admin.Type `json:"type"`
|
2021-05-03 19:48:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Validate validates a new-admin request body.
|
2021-05-18 04:07:25 +00:00
|
|
|
func (car *CreateAdminRequest) Validate(c *admin.Collection) error {
|
|
|
|
if _, ok := c.LoadBySubProv(car.Subject, car.Provisioner); ok {
|
|
|
|
return mgmt.NewError(mgmt.ErrorBadRequestType,
|
2021-05-18 23:50:54 +00:00
|
|
|
"admin with subject: '%s' and provisioner: '%s' already exists", car.Subject, car.Provisioner)
|
2021-05-18 04:07:25 +00:00
|
|
|
}
|
2021-05-03 19:48:20 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2021-05-18 23:50:54 +00:00
|
|
|
// GetAdminsResponse for returning a list of admins.
|
|
|
|
type GetAdminsResponse struct {
|
|
|
|
Admins []*admin.Admin `json:"admins"`
|
|
|
|
NextCursor string `json:"nextCursor"`
|
|
|
|
}
|
|
|
|
|
2021-05-03 19:48:20 +00:00
|
|
|
// UpdateAdminRequest represents the body for a UpdateAdmin request.
|
|
|
|
type UpdateAdminRequest struct {
|
2021-05-18 23:50:54 +00:00
|
|
|
Type admin.Type `json:"type"`
|
2021-05-03 19:48:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Validate validates a new-admin request body.
|
|
|
|
func (uar *UpdateAdminRequest) Validate() error {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2021-05-12 07:03:40 +00:00
|
|
|
// DeleteResponse is the resource for successful DELETE responses.
|
|
|
|
type DeleteResponse struct {
|
|
|
|
Status string `json:"status"`
|
|
|
|
}
|
|
|
|
|
2021-05-03 19:48:20 +00:00
|
|
|
// GetAdmin returns the requested admin, or an error.
|
|
|
|
func (h *Handler) GetAdmin(w http.ResponseWriter, r *http.Request) {
|
|
|
|
id := chi.URLParam(r, "id")
|
|
|
|
|
2021-05-18 23:50:54 +00:00
|
|
|
adm, ok := h.auth.GetAdminCollection().LoadByID(id)
|
|
|
|
if !ok {
|
|
|
|
api.WriteError(w, mgmt.NewError(mgmt.ErrorNotFoundType,
|
|
|
|
"admin %s not found", id))
|
2021-05-03 19:48:20 +00:00
|
|
|
return
|
|
|
|
}
|
2021-05-18 23:50:54 +00:00
|
|
|
api.JSON(w, adm)
|
2021-05-03 19:48:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// GetAdmins returns all admins associated with the authority.
|
|
|
|
func (h *Handler) GetAdmins(w http.ResponseWriter, r *http.Request) {
|
2021-05-18 23:50:54 +00:00
|
|
|
cursor, limit, err := api.ParseCursor(r)
|
2021-05-03 19:48:20 +00:00
|
|
|
if err != nil {
|
2021-05-18 23:50:54 +00:00
|
|
|
api.WriteError(w, mgmt.WrapError(mgmt.ErrorBadRequestType, err,
|
|
|
|
"error parsing cursor and limit from query params"))
|
2021-05-03 19:48:20 +00:00
|
|
|
return
|
|
|
|
}
|
2021-05-18 23:50:54 +00:00
|
|
|
|
|
|
|
admins, nextCursor := h.auth.GetAdminCollection().Find(cursor, limit)
|
|
|
|
api.JSON(w, &GetAdminsResponse{
|
|
|
|
Admins: admins,
|
|
|
|
NextCursor: nextCursor,
|
|
|
|
})
|
2021-05-03 19:48:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// CreateAdmin creates a new admin.
|
|
|
|
func (h *Handler) CreateAdmin(w http.ResponseWriter, r *http.Request) {
|
2021-05-12 07:03:40 +00:00
|
|
|
ctx := r.Context()
|
|
|
|
|
|
|
|
var body CreateAdminRequest
|
|
|
|
if err := api.ReadJSON(r.Body, &body); err != nil {
|
|
|
|
api.WriteError(w, mgmt.WrapError(mgmt.ErrorBadRequestType, err, "error reading request body"))
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2021-05-18 04:07:25 +00:00
|
|
|
if err := body.Validate(h.auth.GetAdminCollection()); err != nil {
|
|
|
|
api.WriteError(w, err)
|
|
|
|
return
|
|
|
|
}
|
2021-05-12 07:03:40 +00:00
|
|
|
|
2021-05-18 23:50:54 +00:00
|
|
|
p, ok := h.auth.GetProvisionerCollection().LoadByName(body.Provisioner)
|
|
|
|
if !ok {
|
|
|
|
api.WriteError(w, mgmt.NewError(mgmt.ErrorNotFoundType, "provisioner %s not found", body.Provisioner))
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2021-05-12 07:03:40 +00:00
|
|
|
adm := &mgmt.Admin{
|
2021-05-18 23:50:54 +00:00
|
|
|
ProvisionerID: p.GetID(),
|
|
|
|
Subject: body.Subject,
|
|
|
|
Type: body.Type,
|
|
|
|
Status: status.Active,
|
2021-05-12 07:03:40 +00:00
|
|
|
}
|
|
|
|
if err := h.db.CreateAdmin(ctx, adm); err != nil {
|
|
|
|
api.WriteError(w, mgmt.WrapErrorISE(err, "error creating admin"))
|
|
|
|
return
|
|
|
|
}
|
2021-05-18 23:50:54 +00:00
|
|
|
adm.ProvisionerName = p.GetName()
|
|
|
|
adm.ProvisionerType = p.GetType().String()
|
2021-05-12 07:03:40 +00:00
|
|
|
api.JSON(w, adm)
|
2021-05-18 04:07:25 +00:00
|
|
|
if err := h.auth.ReloadAuthConfig(); err != nil {
|
|
|
|
fmt.Printf("err = %+v\n", err)
|
|
|
|
}
|
2021-05-12 07:03:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// DeleteAdmin deletes admin.
|
|
|
|
func (h *Handler) DeleteAdmin(w http.ResponseWriter, r *http.Request) {
|
|
|
|
id := chi.URLParam(r, "id")
|
|
|
|
|
2021-05-18 04:07:25 +00:00
|
|
|
if h.auth.GetAdminCollection().Count() == 1 {
|
|
|
|
api.WriteError(w, mgmt.NewError(mgmt.ErrorBadRequestType, "cannot remove last admin"))
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
ctx := r.Context()
|
2021-05-12 07:03:40 +00:00
|
|
|
adm, err := h.db.GetAdmin(ctx, id)
|
|
|
|
if err != nil {
|
|
|
|
api.WriteError(w, mgmt.WrapErrorISE(err, "error retrieiving admin %s", id))
|
|
|
|
return
|
|
|
|
}
|
2021-05-18 23:50:54 +00:00
|
|
|
adm.Status = status.Deleted
|
2021-05-12 07:03:40 +00:00
|
|
|
if err := h.db.UpdateAdmin(ctx, adm); err != nil {
|
|
|
|
api.WriteError(w, mgmt.WrapErrorISE(err, "error updating admin %s", id))
|
|
|
|
return
|
|
|
|
}
|
|
|
|
api.JSON(w, &DeleteResponse{Status: "ok"})
|
2021-05-18 04:07:25 +00:00
|
|
|
if err := h.auth.ReloadAuthConfig(); err != nil {
|
|
|
|
fmt.Printf("err = %+v\n", err)
|
|
|
|
}
|
2021-05-03 19:48:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// UpdateAdmin updates an existing admin.
|
|
|
|
func (h *Handler) UpdateAdmin(w http.ResponseWriter, r *http.Request) {
|
2021-05-12 07:03:40 +00:00
|
|
|
ctx := r.Context()
|
|
|
|
|
|
|
|
var body UpdateAdminRequest
|
|
|
|
if err := api.ReadJSON(r.Body, &body); err != nil {
|
|
|
|
api.WriteError(w, mgmt.WrapError(mgmt.ErrorBadRequestType, err, "error reading request body"))
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
id := chi.URLParam(r, "id")
|
2021-05-07 00:03:12 +00:00
|
|
|
|
2021-05-18 23:50:54 +00:00
|
|
|
adm, ok := h.auth.GetAdminCollection().LoadByID(id)
|
|
|
|
if !ok {
|
|
|
|
api.WriteError(w, mgmt.NewError(mgmt.ErrorNotFoundType, "admin %s not found", id))
|
|
|
|
return
|
|
|
|
}
|
|
|
|
if adm.Type == body.Type {
|
|
|
|
api.WriteError(w, mgmt.NewError(mgmt.ErrorBadRequestType, "admin %s already has type %s", id, adm.Type))
|
2021-05-12 07:03:40 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2021-05-18 04:07:25 +00:00
|
|
|
adm.Type = body.Type
|
|
|
|
|
2021-05-18 23:50:54 +00:00
|
|
|
if err := h.db.UpdateAdmin(ctx, (*mgmt.Admin)(adm)); err != nil {
|
2021-05-12 07:03:40 +00:00
|
|
|
api.WriteError(w, mgmt.WrapErrorISE(err, "error updating admin %s", id))
|
|
|
|
return
|
|
|
|
}
|
|
|
|
api.JSON(w, adm)
|
2021-05-18 04:07:25 +00:00
|
|
|
if err := h.auth.ReloadAuthConfig(); err != nil {
|
|
|
|
fmt.Printf("err = %+v\n", err)
|
|
|
|
}
|
2021-05-03 19:48:20 +00:00
|
|
|
}
|