forked from TrueCloudLab/certificates
wip
This commit is contained in:
parent
638766c615
commit
9bf9bf142d
8 changed files with 121 additions and 58 deletions
|
@ -32,7 +32,7 @@ import (
|
|||
// Authority implements the Certificate Authority internal interface.
|
||||
type Authority struct {
|
||||
config *config.Config
|
||||
mgmtDB mgmt.DB
|
||||
adminDB mgmt.DB
|
||||
keyManager kms.KeyManager
|
||||
provisioners *provisioner.Collection
|
||||
admins *admin.Collection
|
||||
|
@ -130,7 +130,7 @@ func NewEmbedded(opts ...Option) (*Authority, error) {
|
|||
}
|
||||
|
||||
func (a *Authority) ReloadAuthConfig() error {
|
||||
mgmtAuthConfig, err := a.mgmtDB.GetAuthConfig(context.Background(), mgmt.DefaultAuthorityID)
|
||||
mgmtAuthConfig, err := a.adminDB.GetAuthConfig(context.Background(), mgmt.DefaultAuthorityID)
|
||||
if err != nil {
|
||||
return mgmt.WrapErrorISE(err, "error getting authConfig from db")
|
||||
}
|
||||
|
@ -204,14 +204,14 @@ func (a *Authority) init() error {
|
|||
// Pull AuthConfig from DB.
|
||||
if true {
|
||||
// Check if AuthConfig already exists
|
||||
a.mgmtDB, err = authMgmtNosql.New(a.db.(nosql.DB), mgmt.DefaultAuthorityID)
|
||||
a.adminDB, err = authMgmtNosql.New(a.db.(nosql.DB), mgmt.DefaultAuthorityID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
mgmtAuthConfig, err := a.mgmtDB.GetAuthConfig(context.Background(), mgmt.DefaultAuthorityID)
|
||||
mgmtAuthConfig, err := a.adminDB.GetAuthConfig(context.Background(), mgmt.DefaultAuthorityID)
|
||||
if err != nil {
|
||||
if k, ok := err.(*mgmt.Error); ok && k.IsType(mgmt.ErrorNotFoundType) {
|
||||
mgmtAuthConfig, err = mgmt.CreateAuthority(context.Background(), a.mgmtDB, mgmt.WithDefaultAuthorityID)
|
||||
mgmtAuthConfig, err = mgmt.CreateAuthority(context.Background(), a.adminDB, mgmt.WithDefaultAuthorityID)
|
||||
if err != nil {
|
||||
return mgmt.WrapErrorISE(err, "error creating authConfig")
|
||||
}
|
||||
|
@ -465,9 +465,9 @@ func (a *Authority) GetDatabase() db.AuthDB {
|
|||
return a.db
|
||||
}
|
||||
|
||||
// GetMgmtDatabase returns the mgmt database, if one exists.
|
||||
func (a *Authority) GetMgmtDatabase() mgmt.DB {
|
||||
return a.mgmtDB
|
||||
// GetAdminDatabase returns the mgmt database, if one exists.
|
||||
func (a *Authority) GetAdminDatabase() mgmt.DB {
|
||||
return a.adminDB
|
||||
}
|
||||
|
||||
// GetAdminCollection returns the admin collection.
|
||||
|
|
37
authority/config.go
Normal file
37
authority/config.go
Normal file
|
@ -0,0 +1,37 @@
|
|||
package authority
|
||||
|
||||
import "github.com/smallstep/certificates/authority/config"
|
||||
|
||||
// Config is an alias to support older APIs.
|
||||
type Config = config.Config
|
||||
|
||||
// AuthConfig is an alias to support older APIs.
|
||||
type AuthConfig = config.AuthConfig
|
||||
|
||||
// ASN1DN is an alias to support older APIs.
|
||||
type ASN1DN = config.ASN1DN
|
||||
|
||||
// TLS
|
||||
|
||||
// TLSOptions is an alias to support older APIs.
|
||||
type TLSOptions = config.TLSOptions
|
||||
|
||||
// SSH
|
||||
|
||||
// SSHConfig is an alias to support older APIs.
|
||||
type SSHConfig = config.SSHConfig
|
||||
|
||||
// Bastion is an alias to support older APIs.
|
||||
type Bastion = config.Bastion
|
||||
|
||||
// HostTag is an alias to support older APIs.
|
||||
type HostTag = config.HostTag
|
||||
|
||||
// Host is an alias to support older APIs.
|
||||
type Host = config.Host
|
||||
|
||||
// SSHPublicKey is an alias to support older APIs.
|
||||
type SSHPublicKey = config.SSHPublicKey
|
||||
|
||||
// SSHKeys is an alias to support older APIs.
|
||||
type SSHKeys = config.SSHKeys
|
|
@ -25,8 +25,8 @@ type Handler struct {
|
|||
}
|
||||
|
||||
// NewHandler returns a new Authority Config Handler.
|
||||
func NewHandler(db mgmt.DB, auth *authority.Authority) api.RouterHandler {
|
||||
return &Handler{db, auth}
|
||||
func NewHandler(auth *authority.Authority) api.RouterHandler {
|
||||
return &Handler{auth.GetAdminDatabase(), auth}
|
||||
}
|
||||
|
||||
// Route traffic and implement the Router interface.
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
"github.com/smallstep/certificates/authority/mgmt"
|
||||
"github.com/smallstep/certificates/authority/provisioner"
|
||||
"github.com/smallstep/certificates/authority/status"
|
||||
"github.com/smallstep/certificates/errs"
|
||||
)
|
||||
|
||||
// CreateProvisionerRequest represents the body for a CreateProvisioner request.
|
||||
|
@ -31,6 +32,12 @@ func (cpr *CreateProvisionerRequest) Validate(c *provisioner.Collection) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// GetProvisionersResponse is the type for GET /admin/provisioners responses.
|
||||
type GetProvisionersResponse struct {
|
||||
Provisioners provisioner.List `json:"provisioners"`
|
||||
NextCursor string `json:"nextCursor"`
|
||||
}
|
||||
|
||||
// UpdateProvisionerRequest represents the body for a UpdateProvisioner request.
|
||||
type UpdateProvisionerRequest struct {
|
||||
Type string `json:"type"`
|
||||
|
@ -72,14 +79,22 @@ func (h *Handler) GetProvisioner(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
// GetProvisioners returns all provisioners associated with the authority.
|
||||
func (h *Handler) GetProvisioners(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
|
||||
provs, err := h.db.GetProvisioners(ctx)
|
||||
cursor, limit, err := api.ParseCursor(r)
|
||||
if err != nil {
|
||||
api.WriteError(w, err)
|
||||
api.WriteError(w, mgmt.WrapError(mgmt.ErrorBadRequestType, err,
|
||||
"error parsing cursor / limt query params"))
|
||||
return
|
||||
}
|
||||
api.JSON(w, provs)
|
||||
|
||||
p, next, err := h.auth.GetProvisioners(cursor, limit)
|
||||
if err != nil {
|
||||
api.WriteError(w, errs.InternalServerErr(err))
|
||||
return
|
||||
}
|
||||
api.JSON(w, &GetProvisionersResponse{
|
||||
Provisioners: p,
|
||||
NextCursor: next,
|
||||
})
|
||||
}
|
||||
|
||||
// CreateProvisioner creates a new prov.
|
||||
|
|
|
@ -60,17 +60,17 @@ func WithPassword(pass string) func(*ProvisionerCtx) {
|
|||
|
||||
// Provisioner type.
|
||||
type Provisioner struct {
|
||||
ID string `json:"-"`
|
||||
AuthorityID string `json:"-"`
|
||||
Type string `json:"type"`
|
||||
Name string `json:"name"`
|
||||
Claims *Claims `json:"claims"`
|
||||
Details interface{} `json:"details"`
|
||||
X509Template string `json:"x509Template"`
|
||||
X509TemplateData []byte `json:"x509TemplateData"`
|
||||
SSHTemplate string `json:"sshTemplate"`
|
||||
SSHTemplateData []byte `json:"sshTemplateData"`
|
||||
Status status.Type `json:"status"`
|
||||
ID string `json:"-"`
|
||||
AuthorityID string `json:"-"`
|
||||
Type string `json:"type"`
|
||||
Name string `json:"name"`
|
||||
Claims *Claims `json:"claims"`
|
||||
Details ProvisionerDetails `json:"details"`
|
||||
X509Template string `json:"x509Template"`
|
||||
X509TemplateData []byte `json:"x509TemplateData"`
|
||||
SSHTemplate string `json:"sshTemplate"`
|
||||
SSHTemplateData []byte `json:"sshTemplateData"`
|
||||
Status status.Type `json:"status"`
|
||||
}
|
||||
|
||||
func (p *Provisioner) GetOptions() *provisioner.Options {
|
||||
|
@ -111,6 +111,8 @@ func CreateProvisioner(ctx context.Context, db DB, typ, name string, opts ...Pro
|
|||
return p, nil
|
||||
}
|
||||
|
||||
// ProvisionerDetails is the interface implemented by all provisioner details
|
||||
// attributes.
|
||||
type ProvisionerDetails interface {
|
||||
isProvisionerDetails()
|
||||
}
|
||||
|
@ -118,8 +120,8 @@ type ProvisionerDetails interface {
|
|||
// ProvisionerDetailsJWK represents the values required by a JWK provisioner.
|
||||
type ProvisionerDetailsJWK struct {
|
||||
Type ProvisionerType `json:"type"`
|
||||
PubKey []byte `json:"pubKey"`
|
||||
EncPrivKey string `json:"privKey"`
|
||||
PublicKey []byte `json:"publicKey"`
|
||||
PrivateKey string `json:"PrivateKey"`
|
||||
}
|
||||
|
||||
// ProvisionerDetailsOIDC represents the values required by a OIDC provisioner.
|
||||
|
@ -232,8 +234,8 @@ func createJWKDetails(pc *ProvisionerCtx) (*ProvisionerDetailsJWK, error) {
|
|||
|
||||
return &ProvisionerDetailsJWK{
|
||||
Type: ProvisionerTypeJWK,
|
||||
PubKey: jwkPubBytes,
|
||||
EncPrivKey: jwePrivStr,
|
||||
PublicKey: jwkPubBytes,
|
||||
PrivateKey: jwePrivStr,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -248,7 +250,7 @@ func (p *Provisioner) ToCertificates() (provisioner.Interface, error) {
|
|||
switch details := p.Details.(type) {
|
||||
case *ProvisionerDetailsJWK:
|
||||
jwk := new(jose.JSONWebKey)
|
||||
if err := json.Unmarshal(details.PubKey, &jwk); err != nil {
|
||||
if err := json.Unmarshal(details.PublicKey, &jwk); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &provisioner.JWK{
|
||||
|
@ -256,7 +258,7 @@ func (p *Provisioner) ToCertificates() (provisioner.Interface, error) {
|
|||
Type: p.Type,
|
||||
Name: p.Name,
|
||||
Key: jwk,
|
||||
EncryptedKey: details.EncPrivKey,
|
||||
EncryptedKey: details.PrivateKey,
|
||||
Claims: claims,
|
||||
Options: p.GetOptions(),
|
||||
}, nil
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/smallstep/certificates/authority/config"
|
||||
"github.com/smallstep/certificates/authority/mgmt"
|
||||
"github.com/smallstep/certificates/authority/provisioner"
|
||||
"github.com/smallstep/certificates/cas"
|
||||
casapi "github.com/smallstep/certificates/cas/apiv1"
|
||||
|
@ -187,6 +188,14 @@ func WithX509FederatedBundle(pemCerts []byte) Option {
|
|||
}
|
||||
}
|
||||
|
||||
// WithAdminDB is an option to set the database backing the admin APIs.
|
||||
func WithAdminDB(db mgmt.DB) Option {
|
||||
return func(a *Authority) error {
|
||||
a.adminDB = db
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func readCertificateBundle(pemCerts []byte) ([]*x509.Certificate, error) {
|
||||
var block *pem.Block
|
||||
var certs []*x509.Certificate
|
||||
|
|
10
ca/ca.go
10
ca/ca.go
|
@ -171,11 +171,11 @@ func (ca *CA) Init(config *config.Config) (*CA, error) {
|
|||
acmeHandler.Route(r)
|
||||
})
|
||||
|
||||
// MGMT Router
|
||||
mgmtDB := auth.GetMgmtDatabase()
|
||||
if mgmtDB != nil {
|
||||
mgmtHandler := mgmtAPI.NewHandler(mgmtDB, auth)
|
||||
mux.Route("/mgmt", func(r chi.Router) {
|
||||
// Admin API Router
|
||||
adminDB := auth.GetAdminDatabase()
|
||||
if adminDB != nil {
|
||||
mgmtHandler := mgmtAPI.NewHandler(auth)
|
||||
mux.Route("/admin", func(r chi.Router) {
|
||||
mgmtHandler.Route(r)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -134,7 +134,7 @@ func WithAdminLimit(limit int) AdminOption {
|
|||
}
|
||||
}
|
||||
|
||||
// GetAdmins performs the GET /mgmt/admins request to the CA.
|
||||
// GetAdmins performs the GET /admin/admins request to the CA.
|
||||
func (c *MgmtClient) GetAdmins(opts ...AdminOption) (*mgmtAPI.GetAdminsResponse, error) {
|
||||
var retried bool
|
||||
o := new(adminOptions)
|
||||
|
@ -142,7 +142,7 @@ func (c *MgmtClient) GetAdmins(opts ...AdminOption) (*mgmtAPI.GetAdminsResponse,
|
|||
return nil, err
|
||||
}
|
||||
u := c.endpoint.ResolveReference(&url.URL{
|
||||
Path: "/mgmt/admins",
|
||||
Path: "/admin/admins",
|
||||
RawQuery: o.rawQuery(),
|
||||
})
|
||||
retry:
|
||||
|
@ -164,14 +164,14 @@ retry:
|
|||
return body, nil
|
||||
}
|
||||
|
||||
// CreateAdmin performs the POST /mgmt/admin request to the CA.
|
||||
// CreateAdmin performs the POST /admin/admin request to the CA.
|
||||
func (c *MgmtClient) 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: "/mgmt/admin"})
|
||||
u := c.endpoint.ResolveReference(&url.URL{Path: "/admin/admin"})
|
||||
retry:
|
||||
resp, err := c.client.Post(u.String(), "application/json", bytes.NewReader(body))
|
||||
if err != nil {
|
||||
|
@ -191,10 +191,10 @@ retry:
|
|||
return adm, nil
|
||||
}
|
||||
|
||||
// RemoveAdmin performs the DELETE /mgmt/admin/{id} request to the CA.
|
||||
// RemoveAdmin performs the DELETE /admin/admin/{id} request to the CA.
|
||||
func (c *MgmtClient) RemoveAdmin(id string) 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)})
|
||||
req, err := http.NewRequest("DELETE", u.String(), nil)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "create DELETE %s request failed", u)
|
||||
|
@ -214,14 +214,14 @@ retry:
|
|||
return nil
|
||||
}
|
||||
|
||||
// UpdateAdmin performs the PUT /mgmt/admin/{id} request to the CA.
|
||||
// UpdateAdmin performs the PUT /admin/admin/{id} request to the CA.
|
||||
func (c *MgmtClient) 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("/mgmt/admin", id)})
|
||||
u := c.endpoint.ResolveReference(&url.URL{Path: path.Join("/admin/admin", 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)
|
||||
|
@ -245,10 +245,10 @@ retry:
|
|||
return adm, nil
|
||||
}
|
||||
|
||||
// GetProvisioner performs the GET /mgmt/provisioner/{id} request to the CA.
|
||||
func (c *MgmtClient) GetProvisioner(id string) (*mgmt.Provisioner, error) {
|
||||
// GetProvisioner performs the GET /admin/provisioner/{name} request to the CA.
|
||||
func (c *MgmtClient) GetProvisioner(name string) (*mgmt.Provisioner, error) {
|
||||
var retried bool
|
||||
u := c.endpoint.ResolveReference(&url.URL{Path: path.Join("/mgmt/provisioner", id)})
|
||||
u := c.endpoint.ResolveReference(&url.URL{Path: path.Join("/admin/provisioner", name)})
|
||||
retry:
|
||||
resp, err := c.client.Get(u.String())
|
||||
if err != nil {
|
||||
|
@ -268,10 +268,10 @@ retry:
|
|||
return prov, nil
|
||||
}
|
||||
|
||||
// GetProvisioners performs the GET /mgmt/provisioners request to the CA.
|
||||
// GetProvisioners performs the GET /admin/provisioners request to the CA.
|
||||
func (c *MgmtClient) GetProvisioners() ([]*mgmt.Provisioner, error) {
|
||||
var retried bool
|
||||
u := c.endpoint.ResolveReference(&url.URL{Path: "/mgmt/provisioners"})
|
||||
u := c.endpoint.ResolveReference(&url.URL{Path: "/admin/provisioners"})
|
||||
retry:
|
||||
resp, err := c.client.Get(u.String())
|
||||
if err != nil {
|
||||
|
@ -291,10 +291,10 @@ retry:
|
|||
return *provs, nil
|
||||
}
|
||||
|
||||
// RemoveProvisioner performs the DELETE /mgmt/provisioner/{name} request to the CA.
|
||||
// RemoveProvisioner performs the DELETE /admin/provisioner/{name} request to the CA.
|
||||
func (c *MgmtClient) RemoveProvisioner(name string) error {
|
||||
var retried bool
|
||||
u := c.endpoint.ResolveReference(&url.URL{Path: path.Join("/mgmt/provisioner", name)})
|
||||
u := c.endpoint.ResolveReference(&url.URL{Path: path.Join("/admin/provisioner", name)})
|
||||
req, err := http.NewRequest("DELETE", u.String(), nil)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "create DELETE %s request failed", u)
|
||||
|
@ -314,14 +314,14 @@ retry:
|
|||
return nil
|
||||
}
|
||||
|
||||
// CreateProvisioner performs the POST /mgmt/provisioner request to the CA.
|
||||
// CreateProvisioner performs the POST /admin/provisioner request to the CA.
|
||||
func (c *MgmtClient) 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: "/mgmt/provisioner"})
|
||||
u := c.endpoint.ResolveReference(&url.URL{Path: "/admin/provisioner"})
|
||||
retry:
|
||||
resp, err := c.client.Post(u.String(), "application/json", bytes.NewReader(body))
|
||||
if err != nil {
|
||||
|
@ -341,14 +341,14 @@ retry:
|
|||
return prov, nil
|
||||
}
|
||||
|
||||
// UpdateProvisioner performs the PUT /mgmt/provisioner/{id} request to the CA.
|
||||
// UpdateProvisioner performs the PUT /admin/provisioner/{id} request to the CA.
|
||||
func (c *MgmtClient) 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("/mgmt/provisioner", id)})
|
||||
u := c.endpoint.ResolveReference(&url.URL{Path: path.Join("/admin/provisioner", 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)
|
||||
|
@ -372,10 +372,10 @@ retry:
|
|||
return prov, nil
|
||||
}
|
||||
|
||||
// GetAuthConfig performs the GET /mgmt/authconfig/{id} request to the CA.
|
||||
// GetAuthConfig performs the GET /admin/authconfig/{id} request to the CA.
|
||||
func (c *MgmtClient) GetAuthConfig(id string) (*mgmt.AuthConfig, error) {
|
||||
var retried bool
|
||||
u := c.endpoint.ResolveReference(&url.URL{Path: path.Join("/mgmt/authconfig", id)})
|
||||
u := c.endpoint.ResolveReference(&url.URL{Path: path.Join("/admin/authconfig", id)})
|
||||
retry:
|
||||
resp, err := c.client.Get(u.String())
|
||||
if err != nil {
|
||||
|
|
Loading…
Reference in a new issue