From af3cf7dae958d99cdf80c6f37119eaa8380730d3 Mon Sep 17 00:00:00 2001 From: max furman Date: Thu, 6 May 2021 17:03:12 -0700 Subject: [PATCH] first steps --- authority/authority.go | 37 ++++++---- authority/config/config.go | 11 ++- authority/mgmt/api/admin.go | 98 ++++++++++++++------------- authority/mgmt/api/authConfig.go | 89 ++++++++++++------------ authority/mgmt/api/handler.go | 10 ++- authority/mgmt/api/provisioner.go | 84 ++++++++++++----------- authority/mgmt/authConfig.go | 24 +------ authority/mgmt/config.go | 26 +++++++ authority/mgmt/db.go | 6 +- authority/mgmt/db/nosql/admin.go | 3 +- authority/mgmt/db/nosql/authConfig.go | 44 ++++++------ authority/mgmt/errors.go | 5 ++ authority/mgmt/provisioner.go | 15 ++-- ca/ca.go | 12 ++++ ca/mgmtClient.go | 8 +-- 15 files changed, 259 insertions(+), 213 deletions(-) diff --git a/authority/authority.go b/authority/authority.go index 53a3ee72..016b838a 100644 --- a/authority/authority.go +++ b/authority/authority.go @@ -31,7 +31,7 @@ import ( // Authority implements the Certificate Authority internal interface. type Authority struct { config *config.Config - mgmtDB *mgmt.DB + mgmtDB mgmt.DB keyManager kms.KeyManager provisioners *provisioner.Collection db db.AuthDB @@ -146,20 +146,26 @@ func (a *Authority) init() error { // Pull AuthConfig from DB. if true { - if len(a.config.AuthConfig.AuthorityID)_== 0 { - mgmtDB, err := authMgmtNosql.New(a.db.(nosql.DB), mgmt.DefaultAuthorityID) - if err != nil { - return err - } - mgmtAuthConfig, err := mgmt.CreateAuthority(context.Background, mgmtDB, WithDefaultAuthorityID) - if err != nil { - return err - } - a.config.AuthConfig, err := mgmtAuthConfig.ToCertificates() - if err != nil { - return err + // Check if AuthConfig already exists + a.mgmtDB, err = authMgmtNosql.New(a.db.(nosql.DB), mgmt.DefaultAuthorityID) + if err != nil { + return err + } + mgmtAuthConfig, err := a.mgmtDB.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) + if err != nil { + return mgmt.WrapErrorISE(err, "error creating authConfig") + } + } else { + return mgmt.WrapErrorISE(err, "error getting authConfig from db") } } + a.config.AuthorityConfig, err = mgmtAuthConfig.ToCertificates() + if err != nil { + return err + } } // Initialize key manager if it has not been set in the options. @@ -394,6 +400,11 @@ 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 +} + // Shutdown safely shuts down any clients, databases, etc. held by the Authority. func (a *Authority) Shutdown() error { if err := a.keyManager.Close(); err != nil { diff --git a/authority/config/config.go b/authority/config/config.go index 852641c2..66b8bbe0 100644 --- a/authority/config/config.go +++ b/authority/config/config.go @@ -32,9 +32,14 @@ var ( MaxVersion: 1.2, Renegotiation: false, } - DefaultBackdate = time.Minute + // DefaultBackdate length of time to backdate certificates to avoid + // clock skew validation issues. + DefaultBackdate = time.Minute + // DefaultDisableRenewal disables renewals per provisioner. DefaultDisableRenewal = false - DefaultEnableSSHCA = false + // DefaultEnableSSHCA enable SSH CA features per provisioner or globally + // for all provisioners. + DefaultEnableSSHCA = false // GlobalProvisionerClaims default claims for the Authority. Can be overriden // by provisioner specific claims. GlobalProvisionerClaims = provisioner.Claims{ @@ -153,7 +158,7 @@ func LoadConfiguration(filename string) (*Config, error) { return nil, errors.Wrapf(err, "error parsing %s", filename) } - c.init() + c.Init() return &c, nil } diff --git a/authority/mgmt/api/admin.go b/authority/mgmt/api/admin.go index 6f6aaa93..f544b631 100644 --- a/authority/mgmt/api/admin.go +++ b/authority/mgmt/api/admin.go @@ -58,55 +58,59 @@ func (h *Handler) GetAdmins(w http.ResponseWriter, r *http.Request) { // CreateAdmin creates a new admin. func (h *Handler) CreateAdmin(w http.ResponseWriter, r *http.Request) { - ctx := r.Context() - - var body CreateAdminRequest - if err := ReadJSON(r.Body, &body); err != nil { - api.WriteError(w, err) - return - } - if err := body.Validate(); err != nil { - api.WriteError(w, err) - } - - adm := &config.Admin{ - Name: body.Name, - Provisioner: body.Provisioner, - IsSuperAdmin: body.IsSuperAdmin, - } - if err := h.db.CreateAdmin(ctx, adm); err != nil { - api.WriteError(w, err) - return - } - api.JSONStatus(w, adm, http.StatusCreated) + /* + ctx := r.Context() + + var body CreateAdminRequest + if err := ReadJSON(r.Body, &body); err != nil { + api.WriteError(w, err) + return + } + if err := body.Validate(); err != nil { + api.WriteError(w, err) + } + + adm := &config.Admin{ + Name: body.Name, + Provisioner: body.Provisioner, + IsSuperAdmin: body.IsSuperAdmin, + } + if err := h.db.CreateAdmin(ctx, adm); err != nil { + api.WriteError(w, err) + return + } + api.JSONStatus(w, adm, http.StatusCreated) + */ } // UpdateAdmin updates an existing admin. func (h *Handler) UpdateAdmin(w http.ResponseWriter, r *http.Request) { - ctx := r.Context() - id := chi.URLParam(r, "id") - - var body UpdateAdminRequest - if err := ReadJSON(r.Body, &body); err != nil { - api.WriteError(w, err) - return - } - if err := body.Validate(); err != nil { - api.WriteError(w, err) - return - } - if adm, err := h.db.GetAdmin(ctx, id); err != nil { - api.WriteError(w, err) - return - } - - adm.Name = body.Name - adm.Provisioner = body.Provisioner - adm.IsSuperAdmin = body.IsSuperAdmin - - if err := h.db.UpdateAdmin(ctx, adm); err != nil { - api.WriteError(w, err) - return - } - api.JSON(w, adm) + /* + ctx := r.Context() + id := chi.URLParam(r, "id") + + var body UpdateAdminRequest + if err := ReadJSON(r.Body, &body); err != nil { + api.WriteError(w, err) + return + } + if err := body.Validate(); err != nil { + api.WriteError(w, err) + return + } + if adm, err := h.db.GetAdmin(ctx, id); err != nil { + api.WriteError(w, err) + return + } + + adm.Name = body.Name + adm.Provisioner = body.Provisioner + adm.IsSuperAdmin = body.IsSuperAdmin + + if err := h.db.UpdateAdmin(ctx, adm); err != nil { + api.WriteError(w, err) + return + } + api.JSON(w, adm) + */ } diff --git a/authority/mgmt/api/authConfig.go b/authority/mgmt/api/authConfig.go index fb23f8e8..283a4b66 100644 --- a/authority/mgmt/api/authConfig.go +++ b/authority/mgmt/api/authConfig.go @@ -5,16 +5,15 @@ import ( "github.com/go-chi/chi" "github.com/smallstep/certificates/api" - "github.com/smallstep/certificates/authority" "github.com/smallstep/certificates/authority/config" + "github.com/smallstep/certificates/authority/mgmt" ) // CreateAuthConfigRequest represents the body for a CreateAuthConfig request. type CreateAuthConfigRequest struct { - ASN1DN *authority.ASN1DN `json:"asn1dn,omitempty"` - Claims *config.Claims `json:"claims,omitempty"` - DisableIssuedAtCheck bool `json:"disableIssuedAtCheck,omitempty"` - Backdate string `json:"backdate,omitempty"` + ASN1DN *config.ASN1DN `json:"asn1dn,omitempty"` + Claims *mgmt.Claims `json:"claims,omitempty"` + Backdate string `json:"backdate,omitempty"` } // Validate validates a CreateAuthConfig request body. @@ -24,10 +23,9 @@ func (car *CreateAuthConfigRequest) Validate() error { // UpdateAuthConfigRequest represents the body for a UpdateAuthConfig request. type UpdateAuthConfigRequest struct { - ASN1DN *authority.ASN1DN `json:"asn1dn"` - Claims *config.Claims `json:"claims"` - DisableIssuedAtCheck bool `json:"disableIssuedAtCheck,omitempty"` - Backdate string `json:"backdate,omitempty"` + ASN1DN *config.ASN1DN `json:"asn1dn"` + Claims *mgmt.Claims `json:"claims"` + Backdate string `json:"backdate,omitempty"` } // Validate validates a new-admin request body. @@ -53,7 +51,7 @@ func (h *Handler) CreateAuthConfig(w http.ResponseWriter, r *http.Request) { ctx := r.Context() var body CreateAuthConfigRequest - if err := ReadJSON(r.Body, &body); err != nil { + if err := api.ReadJSON(r.Body, &body); err != nil { api.WriteError(w, err) return } @@ -61,10 +59,9 @@ func (h *Handler) CreateAuthConfig(w http.ResponseWriter, r *http.Request) { api.WriteError(w, err) } - ac := config.AuthConfig{ - Status: config.StatusActive, - DisableIssuedAtCheck: body.DisableIssuedAtCheck, - Backdate: "1m", + ac := &mgmt.AuthConfig{ + Status: mgmt.StatusActive, + Backdate: "1m", } if body.ASN1DN != nil { ac.ASN1DN = body.ASN1DN @@ -84,38 +81,40 @@ func (h *Handler) CreateAuthConfig(w http.ResponseWriter, r *http.Request) { // UpdateAuthConfig updates an existing AuthConfig. func (h *Handler) UpdateAuthConfig(w http.ResponseWriter, r *http.Request) { - ctx := r.Context() - id := chi.URLParam(r, "id") + /* + ctx := r.Context() + id := chi.URLParam(r, "id") - var body UpdateAuthConfigRequest - if err := ReadJSON(r.Body, &body); err != nil { - api.WriteError(w, err) - return - } - if err := body.Validate(); err != nil { - api.WriteError(w, err) - return - } - if ac, err := h.db.GetAuthConfig(ctx, id); err != nil { - api.WriteError(w, err) - return - } + var body UpdateAuthConfigRequest + if err := api.ReadJSON(r.Body, &body); err != nil { + api.WriteError(w, err) + return + } + if err := body.Validate(); err != nil { + api.WriteError(w, err) + return + } + ac, err := h.db.GetAuthConfig(ctx, id) + if err != nil { + api.WriteError(w, err) + return + } - ac.DisableIssuedAtCheck = body.DisableIssuedAtCheck - ac.Status = body.Status - if body.ASN1DN != nil { - ac.ASN1DN = body.ASN1DN - } - if body.Claims != nil { - ac.Claims = body.Claims - } - if body.Backdate != "" { - ac.Backdate = body.Backdate - } + ac.Status = body.Status + if body.ASN1DN != nil { + ac.ASN1DN = body.ASN1DN + } + if body.Claims != nil { + ac.Claims = body.Claims + } + if body.Backdate != "" { + ac.Backdate = body.Backdate + } - if err := h.db.UpdateAuthConfig(ctx, ac); err != nil { - api.WriteError(w, err) - return - } - api.JSON(w, ac) + if err := h.db.UpdateAuthConfig(ctx, ac); err != nil { + api.WriteError(w, err) + return + } + api.JSON(w, ac) + */ } diff --git a/authority/mgmt/api/handler.go b/authority/mgmt/api/handler.go index f30544c5..0e512a39 100644 --- a/authority/mgmt/api/handler.go +++ b/authority/mgmt/api/handler.go @@ -4,7 +4,7 @@ import ( "time" "github.com/smallstep/certificates/api" - "github.com/smallstep/certificates/authority/config" + "github.com/smallstep/certificates/authority/mgmt" ) // Clock that returns time in UTC rounded to seconds. @@ -19,14 +19,12 @@ var clock Clock // Handler is the ACME API request handler. type Handler struct { - db config.DB + db mgmt.DB } // NewHandler returns a new Authority Config Handler. -func NewHandler(db config.DB) api.RouterHandler { - return &Handler{ - db: ops.DB, - } +func NewHandler(db mgmt.DB) api.RouterHandler { + return &Handler{db} } // Route traffic and implement the Router interface. diff --git a/authority/mgmt/api/provisioner.go b/authority/mgmt/api/provisioner.go index 76bbe7cf..43293221 100644 --- a/authority/mgmt/api/provisioner.go +++ b/authority/mgmt/api/provisioner.go @@ -5,17 +5,17 @@ import ( "github.com/go-chi/chi" "github.com/smallstep/certificates/api" - "github.com/smallstep/certificates/authority/config" + "github.com/smallstep/certificates/authority/mgmt" ) // CreateProvisionerRequest represents the body for a CreateProvisioner request. type CreateProvisionerRequest struct { - Type string `json:"type"` - Name string `json:"name"` - Claims *config.Claims `json:"claims"` - Details interface{} `json:"details"` - X509Template string `json:"x509Template"` - SSHTemplate string `json:"sshTemplate"` + Type string `json:"type"` + Name string `json:"name"` + Claims *mgmt.Claims `json:"claims"` + Details interface{} `json:"details"` + X509Template string `json:"x509Template"` + SSHTemplate string `json:"sshTemplate"` } // Validate validates a new-provisioner request body. @@ -25,10 +25,10 @@ func (car *CreateProvisionerRequest) Validate() error { // UpdateProvisionerRequest represents the body for a UpdateProvisioner request. type UpdateProvisionerRequest struct { - Claims *config.Claims `json:"claims"` - Details interface{} `json:"details"` - X509Template string `json:"x509Template"` - SSHTemplate string `json:"sshTemplate"` + Claims *mgmt.Claims `json:"claims"` + Details interface{} `json:"details"` + X509Template string `json:"x509Template"` + SSHTemplate string `json:"sshTemplate"` } // Validate validates a new-provisioner request body. @@ -66,7 +66,7 @@ func (h *Handler) CreateProvisioner(w http.ResponseWriter, r *http.Request) { ctx := r.Context() var body CreateProvisionerRequest - if err := ReadJSON(r.Body, &body); err != nil { + if err := api.ReadJSON(r.Body, &body); err != nil { api.WriteError(w, err) return } @@ -74,7 +74,7 @@ func (h *Handler) CreateProvisioner(w http.ResponseWriter, r *http.Request) { api.WriteError(w, err) } - prov := &config.Provisioner{ + prov := &mgmt.Provisioner{ Type: body.Type, Name: body.Name, Claims: body.Claims, @@ -91,32 +91,34 @@ func (h *Handler) CreateProvisioner(w http.ResponseWriter, r *http.Request) { // UpdateProvisioner updates an existing prov. func (h *Handler) UpdateProvisioner(w http.ResponseWriter, r *http.Request) { - ctx := r.Context() - id := chi.URLParam(r, "id") - - var body UpdateProvisionerRequest - if err := ReadJSON(r.Body, &body); err != nil { - api.WriteError(w, err) - return - } - if err := body.Validate(); err != nil { - api.WriteError(w, err) - return - } - if prov, err := h.db.GetProvisioner(ctx, id); err != nil { - api.WriteError(w, err) - return - } - - prov.Claims = body.Claims - prov.Details = body.Provisioner - prov.X509Template = body.X509Template - prov.SSHTemplate = body.SSHTemplate - prov.Status = body.Status - - if err := h.db.UpdateProvisioner(ctx, prov); err != nil { - api.WriteError(w, err) - return - } - api.JSON(w, prov) + /* + ctx := r.Context() + id := chi.URLParam(r, "id") + + var body UpdateProvisionerRequest + if err := ReadJSON(r.Body, &body); err != nil { + api.WriteError(w, err) + return + } + if err := body.Validate(); err != nil { + api.WriteError(w, err) + return + } + if prov, err := h.db.GetProvisioner(ctx, id); err != nil { + api.WriteError(w, err) + return + } + + prov.Claims = body.Claims + prov.Details = body.Provisioner + prov.X509Template = body.X509Template + prov.SSHTemplate = body.SSHTemplate + prov.Status = body.Status + + if err := h.db.UpdateProvisioner(ctx, prov); err != nil { + api.WriteError(w, err) + return + } + api.JSON(w, prov) + */ } diff --git a/authority/mgmt/authConfig.go b/authority/mgmt/authConfig.go index 595b2ed0..734bca50 100644 --- a/authority/mgmt/authConfig.go +++ b/authority/mgmt/authConfig.go @@ -19,28 +19,8 @@ type AuthConfig struct { func NewDefaultAuthConfig() *AuthConfig { return &AuthConfig{ - Claims: &Claims{ - X509: &X509Claims{ - Durations: &Durations{ - Min: config.GlobalProvisionerClaims.MinTLSDur.String(), - Max: config.GlobalProvisionerClaims.MaxTLSDur.String(), - Default: config.GlobalProvisionerClaims.DefaultTLSDur.String(), - }, - }, - SSH: &SSHClaims{ - UserDurations: &Durations{ - Min: config.GlobalProvisionerClaims.MinUserSSHDur.String(), - Max: config.GlobalProvisionerClaims.MaxUserSSHDur.String(), - Default: config.GlobalProvisionerClaims.DefaultUserSSHDur.String(), - }, - HostDurations: &Durations{ - Min: config.GlobalProvisionerClaims.MinHostSSHDur.String(), - Max: config.GlobalProvisionerClaims.MaxHostSSHDur.String(), - Default: config.GlobalProvisionerClaims.DefaultHostSSHDur.String(), - }, - }, - DisableRenewal: config.DefaultDisableRenewal, - }, + Claims: NewDefaultClaims(), + ASN1DN: &config.ASN1DN{}, Backdate: config.DefaultBackdate.String(), Status: StatusActive, } diff --git a/authority/mgmt/config.go b/authority/mgmt/config.go index db70e6e5..0cd25aad 100644 --- a/authority/mgmt/config.go +++ b/authority/mgmt/config.go @@ -4,6 +4,7 @@ import ( "context" "github.com/pkg/errors" + "github.com/smallstep/certificates/authority/config" ) const ( @@ -50,6 +51,31 @@ type Durations struct { Default string `json:"default"` } +func NewDefaultClaims() *Claims { + return &Claims{ + X509: &X509Claims{ + Durations: &Durations{ + Min: config.GlobalProvisionerClaims.MinTLSDur.String(), + Max: config.GlobalProvisionerClaims.MaxTLSDur.String(), + Default: config.GlobalProvisionerClaims.DefaultTLSDur.String(), + }, + }, + SSH: &SSHClaims{ + UserDurations: &Durations{ + Min: config.GlobalProvisionerClaims.MinUserSSHDur.String(), + Max: config.GlobalProvisionerClaims.MaxUserSSHDur.String(), + Default: config.GlobalProvisionerClaims.DefaultUserSSHDur.String(), + }, + HostDurations: &Durations{ + Min: config.GlobalProvisionerClaims.MinHostSSHDur.String(), + Max: config.GlobalProvisionerClaims.MaxHostSSHDur.String(), + Default: config.GlobalProvisionerClaims.DefaultHostSSHDur.String(), + }, + }, + DisableRenewal: config.DefaultDisableRenewal, + } +} + type AuthorityOption func(*AuthConfig) error func WithDefaultAuthorityID(ac *AuthConfig) error { diff --git a/authority/mgmt/db.go b/authority/mgmt/db.go index 99228a4d..9cfab3e5 100644 --- a/authority/mgmt/db.go +++ b/authority/mgmt/db.go @@ -18,7 +18,7 @@ type DB interface { UpdateProvisioner(ctx context.Context, prov *Provisioner) error CreateAdmin(ctx context.Context, admin *Admin) error - GetAdmin(ctx context.Context, id string) error + GetAdmin(ctx context.Context, id string) (*Admin, error) GetAdmins(ctx context.Context) ([]*Admin, error) UpdateAdmin(ctx context.Context, admin *Admin) error @@ -116,7 +116,7 @@ func (m *MockDB) GetAdmins(ctx context.Context) ([]*Admin, error) { // UpdateAdmin mock func (m *MockDB) UpdateAdmin(ctx context.Context, adm *Admin) error { - if m.UpdateAdmin != nil { + if m.MockUpdateAdmin != nil { return m.MockUpdateAdmin(ctx, adm) } return m.MockError @@ -142,7 +142,7 @@ func (m *MockDB) GetAuthConfig(ctx context.Context, id string) (*AuthConfig, err // UpdateAuthConfig mock func (m *MockDB) UpdateAuthConfig(ctx context.Context, adm *AuthConfig) error { - if m.UpdateAuthConfig != nil { + if m.MockUpdateAuthConfig != nil { return m.MockUpdateAuthConfig(ctx, adm) } return m.MockError diff --git a/authority/mgmt/db/nosql/admin.go b/authority/mgmt/db/nosql/admin.go index cba8c59d..564ac1c7 100644 --- a/authority/mgmt/db/nosql/admin.go +++ b/authority/mgmt/db/nosql/admin.go @@ -6,7 +6,6 @@ import ( "time" "github.com/pkg/errors" - "github.com/smallstep/certificates/acme" "github.com/smallstep/certificates/authority/mgmt" "github.com/smallstep/nosql" ) @@ -109,7 +108,7 @@ func unmarshalAdmin(data []byte, id string) (*mgmt.Admin, error) { // GetAdmins retrieves and unmarshals all active (not deleted) admins // from the database. // TODO should we be paginating? -func (db *DB) GetAdmins(ctx context.Context, az *acme.Authorization) ([]*mgmt.Admin, error) { +func (db *DB) GetAdmins(ctx context.Context) ([]*mgmt.Admin, error) { dbEntries, err := db.db.List(authorityAdminsTable) if err != nil { return nil, errors.Wrap(err, "error loading admins") diff --git a/authority/mgmt/db/nosql/authConfig.go b/authority/mgmt/db/nosql/authConfig.go index 6fe1266b..fe189ce3 100644 --- a/authority/mgmt/db/nosql/authConfig.go +++ b/authority/mgmt/db/nosql/authConfig.go @@ -12,13 +12,12 @@ import ( ) type dbAuthConfig struct { - ID string `json:"id"` - ASN1DN *config.ASN1DN `json:"asn1dn"` - Claims *mgmt.Claims `json:"claims"` - DisableIssuedAtCheck bool `json:"disableIssuedAtCheck,omitempty"` - Backdate string `json:"backdate,omitempty"` - CreatedAt time.Time `json:"createdAt"` - DeletedAt time.Time `json:"deletedAt"` + ID string `json:"id"` + ASN1DN *config.ASN1DN `json:"asn1dn"` + Claims *mgmt.Claims `json:"claims"` + Backdate string `json:"backdate,omitempty"` + CreatedAt time.Time `json:"createdAt"` + DeletedAt time.Time `json:"deletedAt"` } func (dbp *dbAuthConfig) clone() *dbAuthConfig { @@ -63,30 +62,30 @@ func (db *DB) GetAuthConfig(ctx context.Context, id string) (*mgmt.AuthConfig, e } return &mgmt.AuthConfig{ - ID: dba.ID, - Provisioners: provs, - ASN1DN: dba.ASN1DN, - Backdate: dba.Backdate, - Claims: dba.Claims, - DisableIssuedAtCheck: dba.DisableIssuedAtCheck, + ID: dba.ID, + Provisioners: provs, + ASN1DN: dba.ASN1DN, + Backdate: dba.Backdate, + Claims: dba.Claims, }, nil } // CreateAuthConfig stores a new provisioner to the database. func (db *DB) CreateAuthConfig(ctx context.Context, ac *mgmt.AuthConfig) error { var err error - ac.ID, err = randID() - if err != nil { - return errors.Wrap(err, "error generating random id for provisioner") + if ac.ID == "" { + ac.ID, err = randID() + if err != nil { + return errors.Wrap(err, "error generating random id for provisioner") + } } dba := &dbAuthConfig{ - ID: ac.ID, - ASN1DN: ac.ASN1DN, - Claims: ac.Claims, - DisableIssuedAtCheck: ac.DisableIssuedAtCheck, - Backdate: ac.Backdate, - CreatedAt: clock.Now(), + ID: ac.ID, + ASN1DN: ac.ASN1DN, + Claims: ac.Claims, + Backdate: ac.Backdate, + CreatedAt: clock.Now(), } return db.save(ctx, dba.ID, dba, nil, "authConfig", authorityConfigsTable) @@ -106,7 +105,6 @@ func (db *DB) UpdateAuthConfig(ctx context.Context, ac *mgmt.AuthConfig) error { nu.DeletedAt = clock.Now() } nu.Claims = ac.Claims - nu.DisableIssuedAtCheck = ac.DisableIssuedAtCheck nu.Backdate = ac.Backdate return db.save(ctx, old.ID, nu, old, "authConfig", authorityProvisionersTable) diff --git a/authority/mgmt/errors.go b/authority/mgmt/errors.go index f8b6fd65..ae18619c 100644 --- a/authority/mgmt/errors.go +++ b/authority/mgmt/errors.go @@ -87,6 +87,11 @@ type Error struct { Status int `json:"-"` } +// IsType returns true if the error type matches the input type. +func (e *Error) IsType(pt ProblemType) bool { + return pt.String() == e.Type +} + // NewError creates a new Error type. func NewError(pt ProblemType, msg string, args ...interface{}) *Error { return newError(pt, errors.Errorf(msg, args...)) diff --git a/authority/mgmt/provisioner.go b/authority/mgmt/provisioner.go index 2cb21403..427846fa 100644 --- a/authority/mgmt/provisioner.go +++ b/authority/mgmt/provisioner.go @@ -20,6 +20,16 @@ type ProvisionerCtx struct { Password string } +func NewProvisionerCtx(opts ...ProvisionerOption) *ProvisionerCtx { + pc := &ProvisionerCtx{ + Claims: NewDefaultClaims(), + } + for _, o := range opts { + o(pc) + } + return pc +} + func WithJWK(jwk *jose.JSONWebKey, jwe *jose.JSONWebEncryption) func(*ProvisionerCtx) { return func(ctx *ProvisionerCtx) { ctx.JWK = jwk @@ -62,10 +72,7 @@ func (p *Provisioner) GetOptions() *provisioner.Options { } func CreateProvisioner(ctx context.Context, db DB, typ, name string, opts ...ProvisionerOption) (*Provisioner, error) { - pc := new(ProvisionerCtx) - for _, o := range opts { - o(pc) - } + pc := NewProvisionerCtx(opts...) details, err := createJWKDetails(pc) if err != nil { diff --git a/ca/ca.go b/ca/ca.go index d9bcdd5e..ec10f74c 100644 --- a/ca/ca.go +++ b/ca/ca.go @@ -18,6 +18,7 @@ import ( "github.com/smallstep/certificates/authority" "github.com/smallstep/certificates/authority/config" "github.com/smallstep/certificates/authority/mgmt" + mgmtAPI "github.com/smallstep/certificates/authority/mgmt/api" "github.com/smallstep/certificates/db" "github.com/smallstep/certificates/logging" "github.com/smallstep/certificates/monitoring" @@ -143,6 +144,7 @@ func (ca *CA) Init(config *config.Config) (*CA, error) { dns = fmt.Sprintf("%s:%s", dns, port) } + // ACME Router prefix := "acme" var acmeDB acme.DB if config.DB == nil { @@ -169,6 +171,16 @@ func (ca *CA) Init(config *config.Config) (*CA, error) { acmeHandler.Route(r) }) + // MGMT Router + + mgmtDB := auth.GetMgmtDatabase() + if mgmtDB != nil { + mgmtHandler := mgmtAPI.NewHandler(mgmtDB) + mux.Route("/mgmt", func(r chi.Router) { + mgmtHandler.Route(r) + }) + } + // helpful routine for logging all routes // /* walkFunc := func(method string, route string, handler http.Handler, middlewares ...func(http.Handler) http.Handler) error { diff --git a/ca/mgmtClient.go b/ca/mgmtClient.go index 1172218f..ac494d90 100644 --- a/ca/mgmtClient.go +++ b/ca/mgmtClient.go @@ -60,10 +60,10 @@ func (c *MgmtClient) retryOnError(r *http.Response) bool { return false } -// GetAdmin performs the GET /config/admin/{id} request to the CA. +// GetAdmin performs the GET /mgmt/admin/{id} request to the CA. func (c *MgmtClient) GetAdmin(id string) (*mgmt.Admin, error) { var retried bool - u := c.endpoint.ResolveReference(&url.URL{Path: path.Join("/config/admin", id)}) + u := c.endpoint.ResolveReference(&url.URL{Path: path.Join("/mgmt/admin", id)}) retry: resp, err := c.client.Get(u.String()) if err != nil { @@ -83,10 +83,10 @@ retry: return adm, nil } -// GetAdmins performs the GET /config/admins request to the CA. +// GetAdmins performs the GET /mgmt/admins request to the CA. func (c *MgmtClient) GetAdmins() ([]*mgmt.Admin, error) { var retried bool - u := c.endpoint.ResolveReference(&url.URL{Path: "/config/admins"}) + u := c.endpoint.ResolveReference(&url.URL{Path: "/mgmt/admins"}) retry: resp, err := c.client.Get(u.String()) if err != nil {