From b72430f4ea5600b7d036cf639cd5cbaecbde520d Mon Sep 17 00:00:00 2001 From: Herman Slatman Date: Thu, 21 Apr 2022 16:18:55 +0200 Subject: [PATCH] Block all APIs when using linked deployment mode --- authority/admin/api/acme.go | 38 ++++++------- authority/admin/api/middleware.go | 2 +- authority/admin/api/policy.go | 89 ++++++++++++++++++++++++++++--- ca/ca.go | 2 +- 4 files changed, 99 insertions(+), 32 deletions(-) diff --git a/authority/admin/api/acme.go b/authority/admin/api/acme.go index fe667181..cd4b1e17 100644 --- a/authority/admin/api/acme.go +++ b/authority/admin/api/acme.go @@ -129,29 +129,21 @@ func linkedEAKToCertificates(k *linkedca.EABKey) *acme.ExternalAccountKey { BoundAt: k.BoundAt.AsTime(), } - if k.Policy == nil { - return eak - } - - eak.Policy = &acme.Policy{} - - if k.Policy.X509 == nil { - return eak - } - - eak.Policy.X509 = acme.X509Policy{ - Allowed: acme.PolicyNames{}, - Denied: acme.PolicyNames{}, - } - - if k.Policy.X509.Allow != nil { - eak.Policy.X509.Allowed.DNSNames = k.Policy.X509.Allow.Dns - eak.Policy.X509.Allowed.IPRanges = k.Policy.X509.Allow.Ips - } - - if k.Policy.X509.Deny != nil { - eak.Policy.X509.Denied.DNSNames = k.Policy.X509.Deny.Dns - eak.Policy.X509.Denied.IPRanges = k.Policy.X509.Deny.Ips + if policy := k.GetPolicy(); policy != nil { + eak.Policy = &acme.Policy{} + if x509 := policy.GetX509(); x509 != nil { + eak.Policy.X509 = acme.X509Policy{} + if allow := x509.GetAllow(); allow != nil { + eak.Policy.X509.Allowed = acme.PolicyNames{} + eak.Policy.X509.Allowed.DNSNames = allow.Dns + eak.Policy.X509.Allowed.IPRanges = allow.Ips + } + if deny := x509.GetDeny(); deny != nil { + eak.Policy.X509.Denied = acme.PolicyNames{} + eak.Policy.X509.Denied.DNSNames = deny.Dns + eak.Policy.X509.Denied.IPRanges = deny.Ips + } + } } return eak diff --git a/authority/admin/api/middleware.go b/authority/admin/api/middleware.go index 45f46753..af3dac5d 100644 --- a/authority/admin/api/middleware.go +++ b/authority/admin/api/middleware.go @@ -103,7 +103,7 @@ func (h *Handler) checkAction(next http.HandlerFunc, supportedInStandalone bool) } // loadExternalAccountKey is a middleware that searches for an ACME -// External Account Key by accountID, keyID or reference and stores it in the context. +// External Account Key by reference or keyID and stores it in the context. func (h *Handler) loadExternalAccountKey(next http.HandlerFunc) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { ctx := r.Context() diff --git a/authority/admin/api/policy.go b/authority/admin/api/policy.go index 34b7bf96..f316ba93 100644 --- a/authority/admin/api/policy.go +++ b/authority/admin/api/policy.go @@ -31,23 +31,30 @@ type policyAdminResponderInterface interface { // PolicyAdminResponder is responsible for writing ACME admin responses type PolicyAdminResponder struct { - auth adminAuthority - adminDB admin.DB - acmeDB acme.DB + auth adminAuthority + adminDB admin.DB + acmeDB acme.DB + deploymentType string } // NewACMEAdminResponder returns a new ACMEAdminResponder -func NewPolicyAdminResponder(auth adminAuthority, adminDB admin.DB, acmeDB acme.DB) *PolicyAdminResponder { +func NewPolicyAdminResponder(auth adminAuthority, adminDB admin.DB, acmeDB acme.DB, deploymentType string) *PolicyAdminResponder { return &PolicyAdminResponder{ - auth: auth, - adminDB: adminDB, - acmeDB: acmeDB, + auth: auth, + adminDB: adminDB, + acmeDB: acmeDB, + deploymentType: deploymentType, } } // GetAuthorityPolicy handles the GET /admin/authority/policy request func (par *PolicyAdminResponder) GetAuthorityPolicy(w http.ResponseWriter, r *http.Request) { + if err := par.blockLinkedCA(); err != nil { + render.Error(w, err) + return + } + policy, err := par.auth.GetAuthorityPolicy(r.Context()) if ae, ok := err.(*admin.Error); ok && !ae.IsType(admin.ErrorNotFoundType) { render.Error(w, admin.WrapErrorISE(ae, "error retrieving authority policy")) @@ -65,6 +72,11 @@ func (par *PolicyAdminResponder) GetAuthorityPolicy(w http.ResponseWriter, r *ht // CreateAuthorityPolicy handles the POST /admin/authority/policy request func (par *PolicyAdminResponder) CreateAuthorityPolicy(w http.ResponseWriter, r *http.Request) { + if err := par.blockLinkedCA(); err != nil { + render.Error(w, err) + return + } + ctx := r.Context() policy, err := par.auth.GetAuthorityPolicy(ctx) @@ -111,6 +123,11 @@ func (par *PolicyAdminResponder) CreateAuthorityPolicy(w http.ResponseWriter, r // UpdateAuthorityPolicy handles the PUT /admin/authority/policy request func (par *PolicyAdminResponder) UpdateAuthorityPolicy(w http.ResponseWriter, r *http.Request) { + if err := par.blockLinkedCA(); err != nil { + render.Error(w, err) + return + } + ctx := r.Context() policy, err := par.auth.GetAuthorityPolicy(ctx) @@ -153,6 +170,11 @@ func (par *PolicyAdminResponder) UpdateAuthorityPolicy(w http.ResponseWriter, r // DeleteAuthorityPolicy handles the DELETE /admin/authority/policy request func (par *PolicyAdminResponder) DeleteAuthorityPolicy(w http.ResponseWriter, r *http.Request) { + if err := par.blockLinkedCA(); err != nil { + render.Error(w, err) + return + } + ctx := r.Context() policy, err := par.auth.GetAuthorityPolicy(ctx) @@ -177,6 +199,11 @@ func (par *PolicyAdminResponder) DeleteAuthorityPolicy(w http.ResponseWriter, r // GetProvisionerPolicy handles the GET /admin/provisioners/{name}/policy request func (par *PolicyAdminResponder) GetProvisionerPolicy(w http.ResponseWriter, r *http.Request) { + if err := par.blockLinkedCA(); err != nil { + render.Error(w, err) + return + } + prov := linkedca.ProvisionerFromContext(r.Context()) policy := prov.GetPolicy() @@ -191,6 +218,11 @@ func (par *PolicyAdminResponder) GetProvisionerPolicy(w http.ResponseWriter, r * // CreateProvisionerPolicy handles the POST /admin/provisioners/{name}/policy request func (par *PolicyAdminResponder) CreateProvisionerPolicy(w http.ResponseWriter, r *http.Request) { + if err := par.blockLinkedCA(); err != nil { + render.Error(w, err) + return + } + ctx := r.Context() prov := linkedca.ProvisionerFromContext(ctx) @@ -231,6 +263,11 @@ func (par *PolicyAdminResponder) CreateProvisionerPolicy(w http.ResponseWriter, // UpdateProvisionerPolicy handles the PUT /admin/provisioners/{name}/policy request func (par *PolicyAdminResponder) UpdateProvisionerPolicy(w http.ResponseWriter, r *http.Request) { + if err := par.blockLinkedCA(); err != nil { + render.Error(w, err) + return + } + ctx := r.Context() prov := linkedca.ProvisionerFromContext(ctx) @@ -266,6 +303,11 @@ func (par *PolicyAdminResponder) UpdateProvisionerPolicy(w http.ResponseWriter, // DeleteProvisionerPolicy handles the DELETE /admin/provisioners/{name}/policy request func (par *PolicyAdminResponder) DeleteProvisionerPolicy(w http.ResponseWriter, r *http.Request) { + if err := par.blockLinkedCA(); err != nil { + render.Error(w, err) + return + } + ctx := r.Context() prov := linkedca.ProvisionerFromContext(ctx) @@ -286,6 +328,12 @@ func (par *PolicyAdminResponder) DeleteProvisionerPolicy(w http.ResponseWriter, } func (par *PolicyAdminResponder) GetACMEAccountPolicy(w http.ResponseWriter, r *http.Request) { + + if err := par.blockLinkedCA(); err != nil { + render.Error(w, err) + return + } + ctx := r.Context() eak := linkedca.ExternalAccountKeyFromContext(ctx) @@ -299,6 +347,12 @@ func (par *PolicyAdminResponder) GetACMEAccountPolicy(w http.ResponseWriter, r * } func (par *PolicyAdminResponder) CreateACMEAccountPolicy(w http.ResponseWriter, r *http.Request) { + + if err := par.blockLinkedCA(); err != nil { + render.Error(w, err) + return + } + ctx := r.Context() prov := linkedca.ProvisionerFromContext(ctx) eak := linkedca.ExternalAccountKeyFromContext(ctx) @@ -330,6 +384,12 @@ func (par *PolicyAdminResponder) CreateACMEAccountPolicy(w http.ResponseWriter, } func (par *PolicyAdminResponder) UpdateACMEAccountPolicy(w http.ResponseWriter, r *http.Request) { + + if err := par.blockLinkedCA(); err != nil { + render.Error(w, err) + return + } + ctx := r.Context() prov := linkedca.ProvisionerFromContext(ctx) eak := linkedca.ExternalAccountKeyFromContext(ctx) @@ -359,6 +419,12 @@ func (par *PolicyAdminResponder) UpdateACMEAccountPolicy(w http.ResponseWriter, } func (par *PolicyAdminResponder) DeleteACMEAccountPolicy(w http.ResponseWriter, r *http.Request) { + + if err := par.blockLinkedCA(); err != nil { + render.Error(w, err) + return + } + ctx := r.Context() prov := linkedca.ProvisionerFromContext(ctx) eak := linkedca.ExternalAccountKeyFromContext(ctx) @@ -381,6 +447,15 @@ func (par *PolicyAdminResponder) DeleteACMEAccountPolicy(w http.ResponseWriter, render.JSONStatus(w, DeleteResponse{Status: "ok"}, http.StatusOK) } +// blockLinkedCA blocks all API operations on linked deployments +func (par *PolicyAdminResponder) blockLinkedCA() error { + // temporary blocking linked deployments based on string comparison (preventing import cycle) + if par.deploymentType == "linked" { + return admin.NewError(admin.ErrorNotImplementedType, "policy operations not yet supported in linked deployments") + } + return nil +} + // applyConditionalDefaults applies default settings in case they're not provided // in the request body. func applyConditionalDefaults(p *linkedca.Policy) { diff --git a/ca/ca.go b/ca/ca.go index e63750b5..3c60f9e5 100644 --- a/ca/ca.go +++ b/ca/ca.go @@ -219,7 +219,7 @@ func (ca *CA) Init(cfg *config.Config) (*CA, error) { adminDB := auth.GetAdminDatabase() if adminDB != nil { acmeAdminResponder := adminAPI.NewACMEAdminResponder() - policyAdminResponder := adminAPI.NewPolicyAdminResponder(auth, adminDB, acmeDB) + policyAdminResponder := adminAPI.NewPolicyAdminResponder(auth, adminDB, acmeDB, cfg.AuthorityConfig.DeploymentType) adminHandler := adminAPI.NewHandler(auth, adminDB, acmeDB, acmeAdminResponder, policyAdminResponder) mux.Route("/admin", func(r chi.Router) { adminHandler.Route(r)