This commit is contained in:
max furman 2021-05-20 16:02:20 -07:00
parent 5929244fda
commit d8d5d7332b
3 changed files with 102 additions and 56 deletions

View file

@ -32,20 +32,20 @@ func NewHandler(auth *authority.Authority) api.RouterHandler {
// Route traffic and implement the Router interface.
func (h *Handler) Route(r api.Router) {
// Provisioners
r.MethodFunc("GET", "/provisioner/{name}", h.GetProvisioner)
r.MethodFunc("GET", "/provisioners/{name}", h.GetProvisioner)
r.MethodFunc("GET", "/provisioners", h.GetProvisioners)
r.MethodFunc("POST", "/provisioner", h.CreateProvisioner)
r.MethodFunc("PUT", "/provisioner/{name}", h.UpdateProvisioner)
r.MethodFunc("DELETE", "/provisioner/{name}", h.DeleteProvisioner)
r.MethodFunc("POST", "/provisioners", h.CreateProvisioner)
r.MethodFunc("PUT", "/provisioners/{name}", h.UpdateProvisioner)
r.MethodFunc("DELETE", "/provisioners/{name}", h.DeleteProvisioner)
// Admins
r.MethodFunc("GET", "/admin/{id}", h.GetAdmin)
r.MethodFunc("GET", "/admins/{id}", h.GetAdmin)
r.MethodFunc("GET", "/admins", h.GetAdmins)
r.MethodFunc("POST", "/admin", h.CreateAdmin)
r.MethodFunc("PATCH", "/admin/{id}", h.UpdateAdmin)
r.MethodFunc("DELETE", "/admin/{id}", h.DeleteAdmin)
r.MethodFunc("POST", "/admins", h.CreateAdmin)
r.MethodFunc("PATCH", "/admins/{id}", h.UpdateAdmin)
r.MethodFunc("DELETE", "/admins/{id}", h.DeleteAdmin)
// AuthConfig
r.MethodFunc("GET", "/authconfig/{id}", h.GetAuthConfig)
r.MethodFunc("PUT", "/authconfig/{id}", h.UpdateAuthConfig)
r.MethodFunc("GET", "/authconfigs/{id}", h.GetAuthConfig)
r.MethodFunc("PUT", "/authconfigs/{id}", h.UpdateAuthConfig)
}

View file

@ -58,6 +58,20 @@ func WithPassword(pass string) func(*ProvisionerCtx) {
}
}
type unmarshalProvisioner struct {
ID string `json:"-"`
AuthorityID string `json:"-"`
Type string `json:"type"`
Name string `json:"name"`
Claims *Claims `json:"claims"`
Details json.RawMessage `json:"details"`
X509Template string `json:"x509Template"`
X509TemplateData []byte `json:"x509TemplateData"`
SSHTemplate string `json:"sshTemplate"`
SSHTemplateData []byte `json:"sshTemplateData"`
Status status.Type `json:"status"`
}
// Provisioner type.
type Provisioner struct {
ID string `json:"-"`
@ -73,6 +87,38 @@ type Provisioner struct {
Status status.Type `json:"status"`
}
type typ struct {
Type ProvisionerType `json:"type"`
}
// UnmarshalJSON implements the Unmarshal interface.
func (p *Provisioner) UnmarshalJSON(b []byte) error {
var (
err error
up = new(unmarshalProvisioner)
)
if err = json.Unmarshal(b, up); err != nil {
return WrapErrorISE(err, "error unmarshaling provisioner to intermediate type")
}
p.Details, err = UnmarshalProvisionerDetails(up.Details)
if err = json.Unmarshal(b, up); err != nil {
return WrapErrorISE(err, "error unmarshaling provisioner details")
}
p.ID = up.ID
p.AuthorityID = up.AuthorityID
p.Type = up.Type
p.Name = up.Name
p.Claims = up.Claims
p.X509Template = up.X509Template
p.X509TemplateData = up.X509TemplateData
p.SSHTemplate = up.SSHTemplate
p.SSHTemplateData = up.SSHTemplateData
p.Status = up.Status
return nil
}
func (p *Provisioner) GetOptions() *provisioner.Options {
return &provisioner.Options{
X509: &provisioner.X509Options{
@ -415,7 +461,7 @@ type detailsType struct {
Type ProvisionerType
}
func UnmarshalProvisionerDetails(data []byte) (ProvisionerDetails, error) {
func UnmarshalProvisionerDetails(data json.RawMessage) (ProvisionerDetails, error) {
dt := new(detailsType)
if err := json.Unmarshal(data, dt); err != nil {
return nil, WrapErrorISE(err, "error unmarshaling provisioner details")

View file

@ -16,16 +16,16 @@ import (
"github.com/smallstep/certificates/errs"
)
// MgmtClient implements an HTTP client for the CA server.
type MgmtClient struct {
// AdminClient implements an HTTP client for the CA server.
type AdminClient struct {
client *uaClient
endpoint *url.URL
retryFunc RetryFunc
opts []ClientOption
}
// NewMgmtClient creates a new MgmtClient with the given endpoint and options.
func NewMgmtClient(endpoint string, opts ...ClientOption) (*MgmtClient, error) {
// NewAdminClient creates a new AdminClient with the given endpoint and options.
func NewAdminClient(endpoint string, opts ...ClientOption) (*AdminClient, error) {
u, err := parseEndpoint(endpoint)
if err != nil {
return nil, err
@ -40,7 +40,7 @@ func NewMgmtClient(endpoint string, opts ...ClientOption) (*MgmtClient, error) {
return nil, err
}
return &MgmtClient{
return &AdminClient{
client: newClient(tr),
endpoint: u,
retryFunc: o.retryFunc,
@ -48,7 +48,7 @@ func NewMgmtClient(endpoint string, opts ...ClientOption) (*MgmtClient, error) {
}, nil
}
func (c *MgmtClient) retryOnError(r *http.Response) bool {
func (c *AdminClient) retryOnError(r *http.Response) bool {
if c.retryFunc != nil {
if c.retryFunc(r.StatusCode) {
o := new(clientOptions)
@ -67,10 +67,10 @@ func (c *MgmtClient) retryOnError(r *http.Response) bool {
return false
}
// GetAdmin performs the GET /mgmt/admin/{id} request to the CA.
func (c *MgmtClient) GetAdmin(id string) (*mgmt.Admin, error) {
// GetAdmin performs the GET /admin/admin/{id} request to the CA.
func (c *AdminClient) GetAdmin(id string) (*mgmt.Admin, error) {
var retried bool
u := c.endpoint.ResolveReference(&url.URL{Path: path.Join("/mgmt/admin", id)})
u := c.endpoint.ResolveReference(&url.URL{Path: path.Join("/admin/admin", id)})
retry:
resp, err := c.client.Get(u.String())
if err != nil {
@ -81,7 +81,7 @@ retry:
retried = true
goto retry
}
return nil, readMgmtError(resp.Body)
return nil, readAdminError(resp.Body)
}
var adm = new(mgmt.Admin)
if err := readJSON(resp.Body, adm); err != nil {
@ -135,7 +135,7 @@ func WithAdminLimit(limit int) AdminOption {
}
// GetAdmins performs the GET /admin/admins request to the CA.
func (c *MgmtClient) GetAdmins(opts ...AdminOption) (*mgmtAPI.GetAdminsResponse, error) {
func (c *AdminClient) GetAdmins(opts ...AdminOption) (*mgmtAPI.GetAdminsResponse, error) {
var retried bool
o := new(adminOptions)
if err := o.apply(opts); err != nil {
@ -155,7 +155,7 @@ retry:
retried = true
goto retry
}
return nil, readMgmtError(resp.Body)
return nil, readAdminError(resp.Body)
}
var body = new(mgmtAPI.GetAdminsResponse)
if err := readJSON(resp.Body, body); err != nil {
@ -164,14 +164,14 @@ retry:
return body, nil
}
// CreateAdmin performs the POST /admin/admin request to the CA.
func (c *MgmtClient) CreateAdmin(req *mgmtAPI.CreateAdminRequest) (*mgmt.Admin, error) {
// CreateAdmin performs the POST /admin/admins request to the CA.
func (c *AdminClient) CreateAdmin(req *mgmtAPI.CreateAdminRequest) (*mgmt.Admin, error) {
var retried bool
body, err := json.Marshal(req)
if err != nil {
return nil, errs.Wrap(http.StatusInternalServerError, err, "error marshaling request")
}
u := c.endpoint.ResolveReference(&url.URL{Path: "/admin/admin"})
u := c.endpoint.ResolveReference(&url.URL{Path: "/admin/admins"})
retry:
resp, err := c.client.Post(u.String(), "application/json", bytes.NewReader(body))
if err != nil {
@ -182,7 +182,7 @@ retry:
retried = true
goto retry
}
return nil, readMgmtError(resp.Body)
return nil, readAdminError(resp.Body)
}
var adm = new(mgmt.Admin)
if err := readJSON(resp.Body, adm); err != nil {
@ -191,10 +191,10 @@ retry:
return adm, nil
}
// RemoveAdmin performs the DELETE /admin/admin/{id} request to the CA.
func (c *MgmtClient) RemoveAdmin(id string) error {
// RemoveAdmin performs the DELETE /admin/admins/{id} request to the CA.
func (c *AdminClient) RemoveAdmin(id string) error {
var retried bool
u := c.endpoint.ResolveReference(&url.URL{Path: path.Join("/admin/admin", id)})
u := c.endpoint.ResolveReference(&url.URL{Path: path.Join("/admin/admins", id)})
req, err := http.NewRequest("DELETE", u.String(), nil)
if err != nil {
return errors.Wrapf(err, "create DELETE %s request failed", u)
@ -209,19 +209,19 @@ retry:
retried = true
goto retry
}
return readMgmtError(resp.Body)
return readAdminError(resp.Body)
}
return nil
}
// UpdateAdmin performs the PUT /admin/admin/{id} request to the CA.
func (c *MgmtClient) UpdateAdmin(id string, uar *mgmtAPI.UpdateAdminRequest) (*admin.Admin, error) {
// UpdateAdmin performs the PUT /admin/admins/{id} request to the CA.
func (c *AdminClient) UpdateAdmin(id string, uar *mgmtAPI.UpdateAdminRequest) (*admin.Admin, error) {
var retried bool
body, err := json.Marshal(uar)
if err != nil {
return nil, errs.Wrap(http.StatusInternalServerError, err, "error marshaling request")
}
u := c.endpoint.ResolveReference(&url.URL{Path: path.Join("/admin/admin", id)})
u := c.endpoint.ResolveReference(&url.URL{Path: path.Join("/admin/admins", id)})
req, err := http.NewRequest("PATCH", u.String(), bytes.NewReader(body))
if err != nil {
return nil, errors.Wrapf(err, "create PUT %s request failed", u)
@ -236,7 +236,7 @@ retry:
retried = true
goto retry
}
return nil, readMgmtError(resp.Body)
return nil, readAdminError(resp.Body)
}
var adm = new(admin.Admin)
if err := readJSON(resp.Body, adm); err != nil {
@ -245,10 +245,10 @@ retry:
return adm, nil
}
// GetProvisioner performs the GET /admin/provisioner/{name} request to the CA.
func (c *MgmtClient) GetProvisioner(name string) (*mgmt.Provisioner, error) {
// GetProvisioner performs the GET /admin/provisioners/{name} request to the CA.
func (c *AdminClient) GetProvisioner(name string) (*mgmt.Provisioner, error) {
var retried bool
u := c.endpoint.ResolveReference(&url.URL{Path: path.Join("/admin/provisioner", name)})
u := c.endpoint.ResolveReference(&url.URL{Path: path.Join("/admin/provisioners", name)})
retry:
resp, err := c.client.Get(u.String())
if err != nil {
@ -259,7 +259,7 @@ retry:
retried = true
goto retry
}
return nil, readMgmtError(resp.Body)
return nil, readAdminError(resp.Body)
}
var prov = new(mgmt.Provisioner)
if err := readJSON(resp.Body, prov); err != nil {
@ -269,7 +269,7 @@ retry:
}
// GetProvisioners performs the GET /admin/provisioners request to the CA.
func (c *MgmtClient) GetProvisioners() ([]*mgmt.Provisioner, error) {
func (c *AdminClient) GetProvisioners() ([]*mgmt.Provisioner, error) {
var retried bool
u := c.endpoint.ResolveReference(&url.URL{Path: "/admin/provisioners"})
retry:
@ -282,7 +282,7 @@ retry:
retried = true
goto retry
}
return nil, readMgmtError(resp.Body)
return nil, readAdminError(resp.Body)
}
var provs = new([]*mgmt.Provisioner)
if err := readJSON(resp.Body, provs); err != nil {
@ -291,10 +291,10 @@ retry:
return *provs, nil
}
// RemoveProvisioner performs the DELETE /admin/provisioner/{name} request to the CA.
func (c *MgmtClient) RemoveProvisioner(name string) error {
// RemoveProvisioner performs the DELETE /admin/provisioners/{name} request to the CA.
func (c *AdminClient) RemoveProvisioner(name string) error {
var retried bool
u := c.endpoint.ResolveReference(&url.URL{Path: path.Join("/admin/provisioner", name)})
u := c.endpoint.ResolveReference(&url.URL{Path: path.Join("/admin/provisioners", name)})
req, err := http.NewRequest("DELETE", u.String(), nil)
if err != nil {
return errors.Wrapf(err, "create DELETE %s request failed", u)
@ -309,19 +309,19 @@ retry:
retried = true
goto retry
}
return readMgmtError(resp.Body)
return readAdminError(resp.Body)
}
return nil
}
// CreateProvisioner performs the POST /admin/provisioner request to the CA.
func (c *MgmtClient) CreateProvisioner(req *mgmtAPI.CreateProvisionerRequest) (*mgmt.Provisioner, error) {
// CreateProvisioner performs the POST /admin/provisioners request to the CA.
func (c *AdminClient) CreateProvisioner(req *mgmtAPI.CreateProvisionerRequest) (*mgmt.Provisioner, error) {
var retried bool
body, err := json.Marshal(req)
if err != nil {
return nil, errs.Wrap(http.StatusInternalServerError, err, "error marshaling request")
}
u := c.endpoint.ResolveReference(&url.URL{Path: "/admin/provisioner"})
u := c.endpoint.ResolveReference(&url.URL{Path: "/admin/provisioners"})
retry:
resp, err := c.client.Post(u.String(), "application/json", bytes.NewReader(body))
if err != nil {
@ -332,7 +332,7 @@ retry:
retried = true
goto retry
}
return nil, readMgmtError(resp.Body)
return nil, readAdminError(resp.Body)
}
var prov = new(mgmt.Provisioner)
if err := readJSON(resp.Body, prov); err != nil {
@ -341,14 +341,14 @@ retry:
return prov, nil
}
// UpdateProvisioner performs the PUT /admin/provisioner/{id} request to the CA.
func (c *MgmtClient) UpdateProvisioner(id string, upr *mgmtAPI.UpdateProvisionerRequest) (*mgmt.Provisioner, error) {
// UpdateProvisioner performs the PUT /admin/provisioners/{id} request to the CA.
func (c *AdminClient) UpdateProvisioner(id string, upr *mgmtAPI.UpdateProvisionerRequest) (*mgmt.Provisioner, error) {
var retried bool
body, err := json.Marshal(upr)
if err != nil {
return nil, errs.Wrap(http.StatusInternalServerError, err, "error marshaling request")
}
u := c.endpoint.ResolveReference(&url.URL{Path: path.Join("/admin/provisioner", id)})
u := c.endpoint.ResolveReference(&url.URL{Path: path.Join("/admin/provisioners", id)})
req, err := http.NewRequest("PUT", u.String(), bytes.NewReader(body))
if err != nil {
return nil, errors.Wrapf(err, "create PUT %s request failed", u)
@ -363,7 +363,7 @@ retry:
retried = true
goto retry
}
return nil, readMgmtError(resp.Body)
return nil, readAdminError(resp.Body)
}
var prov = new(mgmt.Provisioner)
if err := readJSON(resp.Body, prov); err != nil {
@ -373,7 +373,7 @@ retry:
}
// GetAuthConfig performs the GET /admin/authconfig/{id} request to the CA.
func (c *MgmtClient) GetAuthConfig(id string) (*mgmt.AuthConfig, error) {
func (c *AdminClient) GetAuthConfig(id string) (*mgmt.AuthConfig, error) {
var retried bool
u := c.endpoint.ResolveReference(&url.URL{Path: path.Join("/admin/authconfig", id)})
retry:
@ -386,7 +386,7 @@ retry:
retried = true
goto retry
}
return nil, readMgmtError(resp.Body)
return nil, readAdminError(resp.Body)
}
var ac = new(mgmt.AuthConfig)
if err := readJSON(resp.Body, ac); err != nil {
@ -395,7 +395,7 @@ retry:
return ac, nil
}
func readMgmtError(r io.ReadCloser) error {
func readAdminError(r io.ReadCloser) error {
defer r.Close()
mgmtErr := new(mgmt.Error)
if err := json.NewDecoder(r).Decode(mgmtErr); err != nil {