diff --git a/authority/admin/api/handler.go b/authority/admin/api/handler.go index bb871c2a..0ab417e6 100644 --- a/authority/admin/api/handler.go +++ b/authority/admin/api/handler.go @@ -13,7 +13,7 @@ import ( // Handler is the Admin API request handler. type Handler struct { acmeResponder acmeAdminResponderInterface - policyResponder policyAdminResponderInterface + policyResponder PolicyAdminResponder } // Route traffic and implement the Router interface. @@ -24,7 +24,7 @@ func (h *Handler) Route(r api.Router) { } // NewHandler returns a new Authority Config Handler. -func NewHandler(auth adminAuthority, adminDB admin.DB, acmeDB acme.DB, acmeResponder acmeAdminResponderInterface, policyResponder policyAdminResponderInterface) api.RouterHandler { +func NewHandler(auth adminAuthority, adminDB admin.DB, acmeDB acme.DB, acmeResponder acmeAdminResponderInterface, policyResponder PolicyAdminResponder) api.RouterHandler { return &Handler{ acmeResponder: acmeResponder, policyResponder: policyResponder, @@ -36,7 +36,7 @@ var mustAuthority = func(ctx context.Context) adminAuthority { } // Route traffic and implement the Router interface. -func Route(r api.Router, acmeResponder acmeAdminResponderInterface, policyResponder policyAdminResponderInterface) { +func Route(r api.Router, acmeResponder acmeAdminResponderInterface, policyResponder PolicyAdminResponder) { authnz := func(next http.HandlerFunc) http.HandlerFunc { return extractAuthorizeTokenAdmin(requireAPIEnabled(next)) } diff --git a/authority/admin/api/policy.go b/authority/admin/api/policy.go index 6af1104a..9f338c0b 100644 --- a/authority/admin/api/policy.go +++ b/authority/admin/api/policy.go @@ -1,6 +1,7 @@ package api import ( + "context" "errors" "net/http" @@ -14,7 +15,9 @@ import ( "github.com/smallstep/certificates/authority/policy" ) -type policyAdminResponderInterface interface { +// PolicyAdminResponder is the interface responsible for writing ACME admin +// responses. +type PolicyAdminResponder interface { GetAuthorityPolicy(w http.ResponseWriter, r *http.Request) CreateAuthorityPolicy(w http.ResponseWriter, r *http.Request) UpdateAuthorityPolicy(w http.ResponseWriter, r *http.Request) @@ -29,39 +32,24 @@ type policyAdminResponderInterface interface { DeleteACMEAccountPolicy(w http.ResponseWriter, r *http.Request) } -// PolicyAdminResponder is responsible for writing ACME admin responses -type PolicyAdminResponder struct { - auth adminAuthority - adminDB admin.DB - acmeDB acme.DB - isLinkedCA bool -} +// policyAdminResponder is responsible for writing ACME admin responses. +type policyAdminResponder struct{} -// NewACMEAdminResponder returns a new ACMEAdminResponder -func NewPolicyAdminResponder(auth adminAuthority, adminDB admin.DB, acmeDB acme.DB) *PolicyAdminResponder { - - var isLinkedCA bool - if a, ok := adminDB.(interface{ IsLinkedCA() bool }); ok { - isLinkedCA = a.IsLinkedCA() - } - - return &PolicyAdminResponder{ - auth: auth, - adminDB: adminDB, - acmeDB: acmeDB, - isLinkedCA: isLinkedCA, - } +// NewACMEAdminResponder returns a new PolicyAdminResponder. +func NewPolicyAdminResponder() PolicyAdminResponder { + return &policyAdminResponder{} } // GetAuthorityPolicy handles the GET /admin/authority/policy request -func (par *PolicyAdminResponder) GetAuthorityPolicy(w http.ResponseWriter, r *http.Request) { - - if err := par.blockLinkedCA(); err != nil { +func (par *policyAdminResponder) GetAuthorityPolicy(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() + if err := blockLinkedCA(ctx); err != nil { render.Error(w, err) return } - authorityPolicy, err := par.auth.GetAuthorityPolicy(r.Context()) + auth := mustAuthority(ctx) + authorityPolicy, err := 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")) return @@ -76,15 +64,15 @@ 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 { +func (par *policyAdminResponder) CreateAuthorityPolicy(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() + if err := blockLinkedCA(ctx); err != nil { render.Error(w, err) return } - ctx := r.Context() - authorityPolicy, err := par.auth.GetAuthorityPolicy(ctx) + auth := mustAuthority(ctx) + authorityPolicy, err := auth.GetAuthorityPolicy(ctx) if ae, ok := err.(*admin.Error); ok && !ae.IsType(admin.ErrorNotFoundType) { render.Error(w, admin.WrapErrorISE(err, "error retrieving authority policy")) @@ -113,7 +101,7 @@ func (par *PolicyAdminResponder) CreateAuthorityPolicy(w http.ResponseWriter, r adm := linkedca.MustAdminFromContext(ctx) var createdPolicy *linkedca.Policy - if createdPolicy, err = par.auth.CreateAuthorityPolicy(ctx, adm, newPolicy); err != nil { + if createdPolicy, err = auth.CreateAuthorityPolicy(ctx, adm, newPolicy); err != nil { if isBadRequest(err) { render.Error(w, admin.WrapError(admin.ErrorBadRequestType, err, "error storing authority policy")) return @@ -127,15 +115,15 @@ 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 { +func (par *policyAdminResponder) UpdateAuthorityPolicy(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() + if err := blockLinkedCA(ctx); err != nil { render.Error(w, err) return } - ctx := r.Context() - authorityPolicy, err := par.auth.GetAuthorityPolicy(ctx) + auth := mustAuthority(ctx) + authorityPolicy, err := auth.GetAuthorityPolicy(ctx) if ae, ok := err.(*admin.Error); ok && !ae.IsType(admin.ErrorNotFoundType) { render.Error(w, admin.WrapErrorISE(err, "error retrieving authority policy")) @@ -163,7 +151,7 @@ func (par *PolicyAdminResponder) UpdateAuthorityPolicy(w http.ResponseWriter, r adm := linkedca.MustAdminFromContext(ctx) var updatedPolicy *linkedca.Policy - if updatedPolicy, err = par.auth.UpdateAuthorityPolicy(ctx, adm, newPolicy); err != nil { + if updatedPolicy, err = auth.UpdateAuthorityPolicy(ctx, adm, newPolicy); err != nil { if isBadRequest(err) { render.Error(w, admin.WrapError(admin.ErrorBadRequestType, err, "error updating authority policy")) return @@ -177,15 +165,15 @@ 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 { +func (par *policyAdminResponder) DeleteAuthorityPolicy(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() + if err := blockLinkedCA(ctx); err != nil { render.Error(w, err) return } - ctx := r.Context() - authorityPolicy, err := par.auth.GetAuthorityPolicy(ctx) + auth := mustAuthority(ctx) + authorityPolicy, err := auth.GetAuthorityPolicy(ctx) if ae, ok := err.(*admin.Error); ok && !ae.IsType(admin.ErrorNotFoundType) { render.Error(w, admin.WrapErrorISE(ae, "error retrieving authority policy")) @@ -197,7 +185,7 @@ func (par *PolicyAdminResponder) DeleteAuthorityPolicy(w http.ResponseWriter, r return } - if err := par.auth.RemoveAuthorityPolicy(ctx); err != nil { + if err := auth.RemoveAuthorityPolicy(ctx); err != nil { render.Error(w, admin.WrapErrorISE(err, "error deleting authority policy")) return } @@ -206,15 +194,14 @@ 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 { +func (par *policyAdminResponder) GetProvisionerPolicy(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() + if err := blockLinkedCA(ctx); err != nil { render.Error(w, err) return } - prov := linkedca.MustProvisionerFromContext(r.Context()) - + prov := linkedca.MustProvisionerFromContext(ctx) provisionerPolicy := prov.GetPolicy() if provisionerPolicy == nil { render.Error(w, admin.NewError(admin.ErrorNotFoundType, "provisioner policy does not exist")) @@ -225,16 +212,14 @@ 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 { +func (par *policyAdminResponder) CreateProvisionerPolicy(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() + if err := blockLinkedCA(ctx); err != nil { render.Error(w, err) return } - ctx := r.Context() prov := linkedca.MustProvisionerFromContext(ctx) - provisionerPolicy := prov.GetPolicy() if provisionerPolicy != nil { adminErr := admin.NewError(admin.ErrorConflictType, "provisioner %s already has a policy", prov.Name) @@ -256,8 +241,8 @@ func (par *PolicyAdminResponder) CreateProvisionerPolicy(w http.ResponseWriter, } prov.Policy = newPolicy - - if err := par.auth.UpdateProvisioner(ctx, prov); err != nil { + auth := mustAuthority(ctx) + if err := auth.UpdateProvisioner(ctx, prov); err != nil { if isBadRequest(err) { render.Error(w, admin.WrapError(admin.ErrorBadRequestType, err, "error creating provisioner policy")) return @@ -271,16 +256,14 @@ 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 { +func (par *policyAdminResponder) UpdateProvisionerPolicy(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() + if err := blockLinkedCA(ctx); err != nil { render.Error(w, err) return } - ctx := r.Context() prov := linkedca.MustProvisionerFromContext(ctx) - provisionerPolicy := prov.GetPolicy() if provisionerPolicy == nil { render.Error(w, admin.NewError(admin.ErrorNotFoundType, "provisioner policy does not exist")) @@ -301,7 +284,8 @@ func (par *PolicyAdminResponder) UpdateProvisionerPolicy(w http.ResponseWriter, } prov.Policy = newPolicy - if err := par.auth.UpdateProvisioner(ctx, prov); err != nil { + auth := mustAuthority(ctx) + if err := auth.UpdateProvisioner(ctx, prov); err != nil { if isBadRequest(err) { render.Error(w, admin.WrapError(admin.ErrorBadRequestType, err, "error updating provisioner policy")) return @@ -315,16 +299,14 @@ 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 { +func (par *policyAdminResponder) DeleteProvisionerPolicy(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() + if err := blockLinkedCA(ctx); err != nil { render.Error(w, err) return } - ctx := r.Context() prov := linkedca.MustProvisionerFromContext(ctx) - if prov.Policy == nil { render.Error(w, admin.NewError(admin.ErrorNotFoundType, "provisioner policy does not exist")) return @@ -333,7 +315,8 @@ func (par *PolicyAdminResponder) DeleteProvisionerPolicy(w http.ResponseWriter, // remove the policy prov.Policy = nil - if err := par.auth.UpdateProvisioner(ctx, prov); err != nil { + auth := mustAuthority(ctx) + if err := auth.UpdateProvisioner(ctx, prov); err != nil { render.Error(w, admin.WrapErrorISE(err, "error deleting provisioner policy")) return } @@ -341,16 +324,14 @@ func (par *PolicyAdminResponder) DeleteProvisionerPolicy(w http.ResponseWriter, render.JSONStatus(w, DeleteResponse{Status: "ok"}, http.StatusOK) } -func (par *PolicyAdminResponder) GetACMEAccountPolicy(w http.ResponseWriter, r *http.Request) { - - if err := par.blockLinkedCA(); err != nil { +func (par *policyAdminResponder) GetACMEAccountPolicy(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() + if err := blockLinkedCA(ctx); err != nil { render.Error(w, err) return } - ctx := r.Context() eak := linkedca.MustExternalAccountKeyFromContext(ctx) - eakPolicy := eak.GetPolicy() if eakPolicy == nil { render.Error(w, admin.NewError(admin.ErrorNotFoundType, "ACME EAK policy does not exist")) @@ -360,17 +341,15 @@ func (par *PolicyAdminResponder) GetACMEAccountPolicy(w http.ResponseWriter, r * render.ProtoJSONStatus(w, eakPolicy, http.StatusOK) } -func (par *PolicyAdminResponder) CreateACMEAccountPolicy(w http.ResponseWriter, r *http.Request) { - - if err := par.blockLinkedCA(); err != nil { +func (par *policyAdminResponder) CreateACMEAccountPolicy(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() + if err := blockLinkedCA(ctx); err != nil { render.Error(w, err) return } - ctx := r.Context() prov := linkedca.MustProvisionerFromContext(ctx) eak := linkedca.MustExternalAccountKeyFromContext(ctx) - eakPolicy := eak.GetPolicy() if eakPolicy != nil { adminErr := admin.NewError(admin.ErrorConflictType, "ACME EAK %s already has a policy", eak.Id) @@ -394,7 +373,8 @@ func (par *PolicyAdminResponder) CreateACMEAccountPolicy(w http.ResponseWriter, eak.Policy = newPolicy acmeEAK := linkedEAKToCertificates(eak) - if err := par.acmeDB.UpdateExternalAccountKey(ctx, prov.GetId(), acmeEAK); err != nil { + acmeDB := acme.MustDatabaseFromContext(ctx) + if err := acmeDB.UpdateExternalAccountKey(ctx, prov.GetId(), acmeEAK); err != nil { render.Error(w, admin.WrapErrorISE(err, "error creating ACME EAK policy")) return } @@ -402,17 +382,15 @@ func (par *PolicyAdminResponder) CreateACMEAccountPolicy(w http.ResponseWriter, render.ProtoJSONStatus(w, newPolicy, http.StatusCreated) } -func (par *PolicyAdminResponder) UpdateACMEAccountPolicy(w http.ResponseWriter, r *http.Request) { - - if err := par.blockLinkedCA(); err != nil { +func (par *policyAdminResponder) UpdateACMEAccountPolicy(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() + if err := blockLinkedCA(ctx); err != nil { render.Error(w, err) return } - ctx := r.Context() prov := linkedca.MustProvisionerFromContext(ctx) eak := linkedca.MustExternalAccountKeyFromContext(ctx) - eakPolicy := eak.GetPolicy() if eakPolicy == nil { render.Error(w, admin.NewError(admin.ErrorNotFoundType, "ACME EAK policy does not exist")) @@ -434,7 +412,8 @@ func (par *PolicyAdminResponder) UpdateACMEAccountPolicy(w http.ResponseWriter, eak.Policy = newPolicy acmeEAK := linkedEAKToCertificates(eak) - if err := par.acmeDB.UpdateExternalAccountKey(ctx, prov.GetId(), acmeEAK); err != nil { + acmeDB := acme.MustDatabaseFromContext(ctx) + if err := acmeDB.UpdateExternalAccountKey(ctx, prov.GetId(), acmeEAK); err != nil { render.Error(w, admin.WrapErrorISE(err, "error updating ACME EAK policy")) return } @@ -442,17 +421,15 @@ func (par *PolicyAdminResponder) UpdateACMEAccountPolicy(w http.ResponseWriter, render.ProtoJSONStatus(w, newPolicy, http.StatusOK) } -func (par *PolicyAdminResponder) DeleteACMEAccountPolicy(w http.ResponseWriter, r *http.Request) { - - if err := par.blockLinkedCA(); err != nil { +func (par *policyAdminResponder) DeleteACMEAccountPolicy(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() + if err := blockLinkedCA(ctx); err != nil { render.Error(w, err) return } - ctx := r.Context() prov := linkedca.MustProvisionerFromContext(ctx) eak := linkedca.MustExternalAccountKeyFromContext(ctx) - eakPolicy := eak.GetPolicy() if eakPolicy == nil { render.Error(w, admin.NewError(admin.ErrorNotFoundType, "ACME EAK policy does not exist")) @@ -463,7 +440,8 @@ func (par *PolicyAdminResponder) DeleteACMEAccountPolicy(w http.ResponseWriter, eak.Policy = nil acmeEAK := linkedEAKToCertificates(eak) - if err := par.acmeDB.UpdateExternalAccountKey(ctx, prov.GetId(), acmeEAK); err != nil { + acmeDB := acme.MustDatabaseFromContext(ctx) + if err := acmeDB.UpdateExternalAccountKey(ctx, prov.GetId(), acmeEAK); err != nil { render.Error(w, admin.WrapErrorISE(err, "error deleting ACME EAK policy")) return } @@ -472,9 +450,10 @@ func (par *PolicyAdminResponder) DeleteACMEAccountPolicy(w http.ResponseWriter, } // blockLinkedCA blocks all API operations on linked deployments -func (par *PolicyAdminResponder) blockLinkedCA() error { +func blockLinkedCA(ctx context.Context) error { // temporary blocking linked deployments - if par.isLinkedCA { + adminDB := admin.MustFromContext(ctx) + if a, ok := adminDB.(interface{ IsLinkedCA() bool }); ok && a.IsLinkedCA() { return admin.NewError(admin.ErrorNotImplementedType, "policy operations not yet supported in linked deployments") } return nil diff --git a/authority/admin/api/policy_test.go b/authority/admin/api/policy_test.go index 1e70db52..1ec88fb6 100644 --- a/authority/admin/api/policy_test.go +++ b/authority/admin/api/policy_test.go @@ -109,7 +109,8 @@ func TestPolicyAdminResponder_GetAuthorityPolicy(t *testing.T) { err := admin.WrapErrorISE(errors.New("force"), "error retrieving authority policy") err.Message = "error retrieving authority policy: force" return test{ - ctx: ctx, + ctx: ctx, + adminDB: &admin.MockDB{}, auth: &mockAdminAuthority{ MockGetAuthorityPolicy: func(ctx context.Context) (*linkedca.Policy, error) { return nil, admin.NewError(admin.ErrorServerInternalType, "force") @@ -124,7 +125,8 @@ func TestPolicyAdminResponder_GetAuthorityPolicy(t *testing.T) { err := admin.NewError(admin.ErrorNotFoundType, "authority policy does not exist") err.Message = "authority policy does not exist" return test{ - ctx: ctx, + ctx: ctx, + adminDB: &admin.MockDB{}, auth: &mockAdminAuthority{ MockGetAuthorityPolicy: func(ctx context.Context) (*linkedca.Policy, error) { return nil, admin.NewError(admin.ErrorNotFoundType, "not found") @@ -179,7 +181,8 @@ func TestPolicyAdminResponder_GetAuthorityPolicy(t *testing.T) { }, } return test{ - ctx: ctx, + ctx: ctx, + adminDB: &admin.MockDB{}, auth: &mockAdminAuthority{ MockGetAuthorityPolicy: func(ctx context.Context) (*linkedca.Policy, error) { return policy, nil @@ -234,11 +237,12 @@ func TestPolicyAdminResponder_GetAuthorityPolicy(t *testing.T) { for name, prep := range tests { tc := prep(t) t.Run(name, func(t *testing.T) { - - par := NewPolicyAdminResponder(tc.auth, tc.adminDB, nil) + mockMustAuthority(t, tc.auth) + ctx := admin.NewContext(tc.ctx, tc.adminDB) + par := NewPolicyAdminResponder() req := httptest.NewRequest("GET", "/foo", nil) - req = req.WithContext(tc.ctx) + req = req.WithContext(ctx) w := httptest.NewRecorder() par.GetAuthorityPolicy(w, req) @@ -301,7 +305,8 @@ func TestPolicyAdminResponder_CreateAuthorityPolicy(t *testing.T) { err := admin.WrapErrorISE(errors.New("force"), "error retrieving authority policy") err.Message = "error retrieving authority policy: force" return test{ - ctx: ctx, + ctx: ctx, + adminDB: &admin.MockDB{}, auth: &mockAdminAuthority{ MockGetAuthorityPolicy: func(ctx context.Context) (*linkedca.Policy, error) { return nil, admin.NewError(admin.ErrorServerInternalType, "force") @@ -316,7 +321,8 @@ func TestPolicyAdminResponder_CreateAuthorityPolicy(t *testing.T) { err := admin.NewError(admin.ErrorConflictType, "authority already has a policy") err.Message = "authority already has a policy" return test{ - ctx: ctx, + ctx: ctx, + adminDB: &admin.MockDB{}, auth: &mockAdminAuthority{ MockGetAuthorityPolicy: func(ctx context.Context) (*linkedca.Policy, error) { return &linkedca.Policy{}, nil @@ -332,7 +338,8 @@ func TestPolicyAdminResponder_CreateAuthorityPolicy(t *testing.T) { adminErr.Message = "proto: syntax error (line 1:2): invalid value ?" body := []byte("{?}") return test{ - ctx: ctx, + ctx: ctx, + adminDB: &admin.MockDB{}, auth: &mockAdminAuthority{ MockGetAuthorityPolicy: func(ctx context.Context) (*linkedca.Policy, error) { return nil, admin.NewError(admin.ErrorNotFoundType, "not found") @@ -358,7 +365,8 @@ func TestPolicyAdminResponder_CreateAuthorityPolicy(t *testing.T) { } }`) return test{ - ctx: ctx, + ctx: ctx, + adminDB: &admin.MockDB{}, auth: &mockAdminAuthority{ MockGetAuthorityPolicy: func(ctx context.Context) (*linkedca.Policy, error) { return nil, admin.NewError(admin.ErrorNotFoundType, "not found") @@ -509,11 +517,13 @@ func TestPolicyAdminResponder_CreateAuthorityPolicy(t *testing.T) { for name, prep := range tests { tc := prep(t) t.Run(name, func(t *testing.T) { - - par := NewPolicyAdminResponder(tc.auth, tc.adminDB, tc.acmeDB) + mockMustAuthority(t, tc.auth) + ctx := admin.NewContext(tc.ctx, tc.adminDB) + ctx = acme.NewDatabaseContext(ctx, tc.acmeDB) + par := NewPolicyAdminResponder() req := httptest.NewRequest("POST", "/foo", io.NopCloser(bytes.NewBuffer(tc.body))) - req = req.WithContext(tc.ctx) + req = req.WithContext(ctx) w := httptest.NewRecorder() par.CreateAuthorityPolicy(w, req) @@ -586,7 +596,8 @@ func TestPolicyAdminResponder_UpdateAuthorityPolicy(t *testing.T) { err := admin.WrapErrorISE(errors.New("force"), "error retrieving authority policy") err.Message = "error retrieving authority policy: force" return test{ - ctx: ctx, + ctx: ctx, + adminDB: &admin.MockDB{}, auth: &mockAdminAuthority{ MockGetAuthorityPolicy: func(ctx context.Context) (*linkedca.Policy, error) { return nil, admin.NewError(admin.ErrorServerInternalType, "force") @@ -602,7 +613,8 @@ func TestPolicyAdminResponder_UpdateAuthorityPolicy(t *testing.T) { err.Message = "authority policy does not exist" err.Status = http.StatusNotFound return test{ - ctx: ctx, + ctx: ctx, + adminDB: &admin.MockDB{}, auth: &mockAdminAuthority{ MockGetAuthorityPolicy: func(ctx context.Context) (*linkedca.Policy, error) { return nil, nil @@ -625,7 +637,8 @@ func TestPolicyAdminResponder_UpdateAuthorityPolicy(t *testing.T) { adminErr.Message = "proto: syntax error (line 1:2): invalid value ?" body := []byte("{?}") return test{ - ctx: ctx, + ctx: ctx, + adminDB: &admin.MockDB{}, auth: &mockAdminAuthority{ MockGetAuthorityPolicy: func(ctx context.Context) (*linkedca.Policy, error) { return policy, nil @@ -658,7 +671,8 @@ func TestPolicyAdminResponder_UpdateAuthorityPolicy(t *testing.T) { } }`) return test{ - ctx: ctx, + ctx: ctx, + adminDB: &admin.MockDB{}, auth: &mockAdminAuthority{ MockGetAuthorityPolicy: func(ctx context.Context) (*linkedca.Policy, error) { return policy, nil @@ -809,11 +823,13 @@ func TestPolicyAdminResponder_UpdateAuthorityPolicy(t *testing.T) { for name, prep := range tests { tc := prep(t) t.Run(name, func(t *testing.T) { - - par := NewPolicyAdminResponder(tc.auth, tc.adminDB, tc.acmeDB) + mockMustAuthority(t, tc.auth) + ctx := admin.NewContext(tc.ctx, tc.adminDB) + ctx = acme.NewDatabaseContext(ctx, tc.acmeDB) + par := NewPolicyAdminResponder() req := httptest.NewRequest("POST", "/foo", io.NopCloser(bytes.NewBuffer(tc.body))) - req = req.WithContext(tc.ctx) + req = req.WithContext(ctx) w := httptest.NewRecorder() par.UpdateAuthorityPolicy(w, req) @@ -886,7 +902,8 @@ func TestPolicyAdminResponder_DeleteAuthorityPolicy(t *testing.T) { err := admin.WrapErrorISE(errors.New("force"), "error retrieving authority policy") err.Message = "error retrieving authority policy: force" return test{ - ctx: ctx, + ctx: ctx, + adminDB: &admin.MockDB{}, auth: &mockAdminAuthority{ MockGetAuthorityPolicy: func(ctx context.Context) (*linkedca.Policy, error) { return nil, admin.NewError(admin.ErrorServerInternalType, "force") @@ -902,7 +919,8 @@ func TestPolicyAdminResponder_DeleteAuthorityPolicy(t *testing.T) { err.Message = "authority policy does not exist" err.Status = http.StatusNotFound return test{ - ctx: ctx, + ctx: ctx, + adminDB: &admin.MockDB{}, auth: &mockAdminAuthority{ MockGetAuthorityPolicy: func(ctx context.Context) (*linkedca.Policy, error) { return nil, nil @@ -924,7 +942,8 @@ func TestPolicyAdminResponder_DeleteAuthorityPolicy(t *testing.T) { err := admin.NewErrorISE("error deleting authority policy: force") err.Message = "error deleting authority policy: force" return test{ - ctx: ctx, + ctx: ctx, + adminDB: &admin.MockDB{}, auth: &mockAdminAuthority{ MockGetAuthorityPolicy: func(ctx context.Context) (*linkedca.Policy, error) { return policy, nil @@ -947,7 +966,8 @@ func TestPolicyAdminResponder_DeleteAuthorityPolicy(t *testing.T) { } ctx := context.Background() return test{ - ctx: ctx, + ctx: ctx, + adminDB: &admin.MockDB{}, auth: &mockAdminAuthority{ MockGetAuthorityPolicy: func(ctx context.Context) (*linkedca.Policy, error) { return policy, nil @@ -963,11 +983,13 @@ func TestPolicyAdminResponder_DeleteAuthorityPolicy(t *testing.T) { for name, prep := range tests { tc := prep(t) t.Run(name, func(t *testing.T) { - - par := NewPolicyAdminResponder(tc.auth, tc.adminDB, tc.acmeDB) + mockMustAuthority(t, tc.auth) + ctx := admin.NewContext(tc.ctx, tc.adminDB) + ctx = acme.NewDatabaseContext(ctx, tc.acmeDB) + par := NewPolicyAdminResponder() req := httptest.NewRequest("POST", "/foo", io.NopCloser(bytes.NewBuffer(tc.body))) - req = req.WithContext(tc.ctx) + req = req.WithContext(ctx) w := httptest.NewRecorder() par.DeleteAuthorityPolicy(w, req) @@ -1033,6 +1055,7 @@ func TestPolicyAdminResponder_GetProvisionerPolicy(t *testing.T) { err.Message = "provisioner policy does not exist" return test{ ctx: ctx, + adminDB: &admin.MockDB{}, err: err, statusCode: 404, } @@ -1085,7 +1108,8 @@ func TestPolicyAdminResponder_GetProvisionerPolicy(t *testing.T) { } ctx := linkedca.NewContextWithProvisioner(context.Background(), prov) return test{ - ctx: ctx, + ctx: ctx, + adminDB: &admin.MockDB{}, response: &testPolicyResponse{ X509: &testX509Policy{ Allow: &testX509Names{ @@ -1135,11 +1159,13 @@ func TestPolicyAdminResponder_GetProvisionerPolicy(t *testing.T) { for name, prep := range tests { tc := prep(t) t.Run(name, func(t *testing.T) { - - par := NewPolicyAdminResponder(tc.auth, tc.adminDB, tc.acmeDB) + mockMustAuthority(t, tc.auth) + ctx := admin.NewContext(tc.ctx, tc.adminDB) + ctx = acme.NewDatabaseContext(ctx, tc.acmeDB) + par := NewPolicyAdminResponder() req := httptest.NewRequest("GET", "/foo", nil) - req = req.WithContext(tc.ctx) + req = req.WithContext(ctx) w := httptest.NewRecorder() par.GetProvisionerPolicy(w, req) @@ -1214,6 +1240,7 @@ func TestPolicyAdminResponder_CreateProvisionerPolicy(t *testing.T) { err.Message = "provisioner provName already has a policy" return test{ ctx: ctx, + adminDB: &admin.MockDB{}, err: err, statusCode: 409, } @@ -1228,6 +1255,7 @@ func TestPolicyAdminResponder_CreateProvisionerPolicy(t *testing.T) { body := []byte("{?}") return test{ ctx: ctx, + adminDB: &admin.MockDB{}, body: body, err: adminErr, statusCode: 400, @@ -1251,7 +1279,8 @@ func TestPolicyAdminResponder_CreateProvisionerPolicy(t *testing.T) { } }`) return test{ - ctx: ctx, + ctx: ctx, + adminDB: &admin.MockDB{}, auth: &mockAdminAuthority{ MockGetAuthorityPolicy: func(ctx context.Context) (*linkedca.Policy, error) { return nil, admin.NewError(admin.ErrorNotFoundType, "not found") @@ -1283,7 +1312,8 @@ func TestPolicyAdminResponder_CreateProvisionerPolicy(t *testing.T) { body, err := protojson.Marshal(policy) assert.NoError(t, err) return test{ - ctx: ctx, + ctx: ctx, + adminDB: &admin.MockDB{}, auth: &mockAdminAuthority{ MockUpdateProvisioner: func(ctx context.Context, nu *linkedca.Provisioner) error { return &authority.PolicyError{ @@ -1318,7 +1348,8 @@ func TestPolicyAdminResponder_CreateProvisionerPolicy(t *testing.T) { body, err := protojson.Marshal(policy) assert.NoError(t, err) return test{ - ctx: ctx, + ctx: ctx, + adminDB: &admin.MockDB{}, auth: &mockAdminAuthority{ MockUpdateProvisioner: func(ctx context.Context, nu *linkedca.Provisioner) error { return &authority.PolicyError{ @@ -1351,7 +1382,8 @@ func TestPolicyAdminResponder_CreateProvisionerPolicy(t *testing.T) { body, err := protojson.Marshal(policy) assert.NoError(t, err) return test{ - ctx: ctx, + ctx: ctx, + adminDB: &admin.MockDB{}, auth: &mockAdminAuthority{ MockUpdateProvisioner: func(ctx context.Context, nu *linkedca.Provisioner) error { return nil @@ -1372,11 +1404,12 @@ func TestPolicyAdminResponder_CreateProvisionerPolicy(t *testing.T) { for name, prep := range tests { tc := prep(t) t.Run(name, func(t *testing.T) { - - par := NewPolicyAdminResponder(tc.auth, tc.adminDB, nil) + mockMustAuthority(t, tc.auth) + ctx := admin.NewContext(tc.ctx, tc.adminDB) + par := NewPolicyAdminResponder() req := httptest.NewRequest("POST", "/foo", io.NopCloser(bytes.NewBuffer(tc.body))) - req = req.WithContext(tc.ctx) + req = req.WithContext(ctx) w := httptest.NewRecorder() par.CreateProvisionerPolicy(w, req) @@ -1452,6 +1485,7 @@ func TestPolicyAdminResponder_UpdateProvisionerPolicy(t *testing.T) { err.Message = "provisioner policy does not exist" return test{ ctx: ctx, + adminDB: &admin.MockDB{}, err: err, statusCode: 404, } @@ -1474,6 +1508,7 @@ func TestPolicyAdminResponder_UpdateProvisionerPolicy(t *testing.T) { body := []byte("{?}") return test{ ctx: ctx, + adminDB: &admin.MockDB{}, body: body, err: adminErr, statusCode: 400, @@ -1505,7 +1540,8 @@ func TestPolicyAdminResponder_UpdateProvisionerPolicy(t *testing.T) { } }`) return test{ - ctx: ctx, + ctx: ctx, + adminDB: &admin.MockDB{}, auth: &mockAdminAuthority{ MockGetAuthorityPolicy: func(ctx context.Context) (*linkedca.Policy, error) { return nil, admin.NewError(admin.ErrorNotFoundType, "not found") @@ -1538,7 +1574,8 @@ func TestPolicyAdminResponder_UpdateProvisionerPolicy(t *testing.T) { body, err := protojson.Marshal(policy) assert.NoError(t, err) return test{ - ctx: ctx, + ctx: ctx, + adminDB: &admin.MockDB{}, auth: &mockAdminAuthority{ MockUpdateProvisioner: func(ctx context.Context, nu *linkedca.Provisioner) error { return &authority.PolicyError{ @@ -1574,7 +1611,8 @@ func TestPolicyAdminResponder_UpdateProvisionerPolicy(t *testing.T) { body, err := protojson.Marshal(policy) assert.NoError(t, err) return test{ - ctx: ctx, + ctx: ctx, + adminDB: &admin.MockDB{}, auth: &mockAdminAuthority{ MockUpdateProvisioner: func(ctx context.Context, nu *linkedca.Provisioner) error { return &authority.PolicyError{ @@ -1608,7 +1646,8 @@ func TestPolicyAdminResponder_UpdateProvisionerPolicy(t *testing.T) { body, err := protojson.Marshal(policy) assert.NoError(t, err) return test{ - ctx: ctx, + ctx: ctx, + adminDB: &admin.MockDB{}, auth: &mockAdminAuthority{ MockUpdateProvisioner: func(ctx context.Context, nu *linkedca.Provisioner) error { return nil @@ -1629,11 +1668,12 @@ func TestPolicyAdminResponder_UpdateProvisionerPolicy(t *testing.T) { for name, prep := range tests { tc := prep(t) t.Run(name, func(t *testing.T) { - - par := NewPolicyAdminResponder(tc.auth, tc.adminDB, nil) + mockMustAuthority(t, tc.auth) + ctx := admin.NewContext(tc.ctx, tc.adminDB) + par := NewPolicyAdminResponder() req := httptest.NewRequest("POST", "/foo", io.NopCloser(bytes.NewBuffer(tc.body))) - req = req.WithContext(tc.ctx) + req = req.WithContext(ctx) w := httptest.NewRecorder() par.UpdateProvisionerPolicy(w, req) @@ -1710,6 +1750,7 @@ func TestPolicyAdminResponder_DeleteProvisionerPolicy(t *testing.T) { err.Message = "provisioner policy does not exist" return test{ ctx: ctx, + adminDB: &admin.MockDB{}, err: err, statusCode: 404, } @@ -1723,7 +1764,8 @@ func TestPolicyAdminResponder_DeleteProvisionerPolicy(t *testing.T) { err := admin.NewErrorISE("error deleting provisioner policy: force") err.Message = "error deleting provisioner policy: force" return test{ - ctx: ctx, + ctx: ctx, + adminDB: &admin.MockDB{}, auth: &mockAdminAuthority{ MockUpdateProvisioner: func(ctx context.Context, nu *linkedca.Provisioner) error { return errors.New("force") @@ -1740,7 +1782,8 @@ func TestPolicyAdminResponder_DeleteProvisionerPolicy(t *testing.T) { } ctx := linkedca.NewContextWithProvisioner(context.Background(), prov) return test{ - ctx: ctx, + ctx: ctx, + adminDB: &admin.MockDB{}, auth: &mockAdminAuthority{ MockUpdateProvisioner: func(ctx context.Context, nu *linkedca.Provisioner) error { return nil @@ -1753,11 +1796,13 @@ func TestPolicyAdminResponder_DeleteProvisionerPolicy(t *testing.T) { for name, prep := range tests { tc := prep(t) t.Run(name, func(t *testing.T) { - - par := NewPolicyAdminResponder(tc.auth, tc.adminDB, tc.acmeDB) + mockMustAuthority(t, tc.auth) + ctx := admin.NewContext(tc.ctx, tc.adminDB) + ctx = acme.NewDatabaseContext(ctx, tc.acmeDB) + par := NewPolicyAdminResponder() req := httptest.NewRequest("POST", "/foo", io.NopCloser(bytes.NewBuffer(tc.body))) - req = req.WithContext(tc.ctx) + req = req.WithContext(ctx) w := httptest.NewRecorder() par.DeleteProvisionerPolicy(w, req) @@ -1828,6 +1873,7 @@ func TestPolicyAdminResponder_GetACMEAccountPolicy(t *testing.T) { err.Message = "ACME EAK policy does not exist" return test{ ctx: ctx, + adminDB: &admin.MockDB{}, err: err, statusCode: 404, } @@ -1885,7 +1931,8 @@ func TestPolicyAdminResponder_GetACMEAccountPolicy(t *testing.T) { ctx := linkedca.NewContextWithProvisioner(context.Background(), prov) ctx = linkedca.NewContextWithExternalAccountKey(ctx, eak) return test{ - ctx: ctx, + ctx: ctx, + adminDB: &admin.MockDB{}, response: &testPolicyResponse{ X509: &testX509Policy{ Allow: &testX509Names{ @@ -1935,11 +1982,12 @@ func TestPolicyAdminResponder_GetACMEAccountPolicy(t *testing.T) { for name, prep := range tests { tc := prep(t) t.Run(name, func(t *testing.T) { - - par := NewPolicyAdminResponder(nil, tc.adminDB, tc.acmeDB) + ctx := admin.NewContext(tc.ctx, tc.adminDB) + ctx = acme.NewDatabaseContext(ctx, tc.acmeDB) + par := NewPolicyAdminResponder() req := httptest.NewRequest("GET", "/foo", nil) - req = req.WithContext(tc.ctx) + req = req.WithContext(ctx) w := httptest.NewRecorder() par.GetACMEAccountPolicy(w, req) @@ -2018,6 +2066,7 @@ func TestPolicyAdminResponder_CreateACMEAccountPolicy(t *testing.T) { err.Message = "ACME EAK eakID already has a policy" return test{ ctx: ctx, + adminDB: &admin.MockDB{}, err: err, statusCode: 409, } @@ -2036,6 +2085,7 @@ func TestPolicyAdminResponder_CreateACMEAccountPolicy(t *testing.T) { body := []byte("{?}") return test{ ctx: ctx, + adminDB: &admin.MockDB{}, body: body, err: adminErr, statusCode: 400, @@ -2064,6 +2114,7 @@ func TestPolicyAdminResponder_CreateACMEAccountPolicy(t *testing.T) { }`) return test{ ctx: ctx, + adminDB: &admin.MockDB{}, body: body, err: adminErr, statusCode: 400, @@ -2091,7 +2142,8 @@ func TestPolicyAdminResponder_CreateACMEAccountPolicy(t *testing.T) { body, err := protojson.Marshal(policy) assert.NoError(t, err) return test{ - ctx: ctx, + ctx: ctx, + adminDB: &admin.MockDB{}, acmeDB: &acme.MockDB{ MockUpdateExternalAccountKey: func(ctx context.Context, provisionerID string, eak *acme.ExternalAccountKey) error { assert.Equal(t, "provID", provisionerID) @@ -2124,7 +2176,8 @@ func TestPolicyAdminResponder_CreateACMEAccountPolicy(t *testing.T) { body, err := protojson.Marshal(policy) assert.NoError(t, err) return test{ - ctx: ctx, + ctx: ctx, + adminDB: &admin.MockDB{}, acmeDB: &acme.MockDB{ MockUpdateExternalAccountKey: func(ctx context.Context, provisionerID string, eak *acme.ExternalAccountKey) error { assert.Equal(t, "provID", provisionerID) @@ -2147,11 +2200,12 @@ func TestPolicyAdminResponder_CreateACMEAccountPolicy(t *testing.T) { for name, prep := range tests { tc := prep(t) t.Run(name, func(t *testing.T) { - - par := NewPolicyAdminResponder(nil, tc.adminDB, tc.acmeDB) + ctx := admin.NewContext(tc.ctx, tc.adminDB) + ctx = acme.NewDatabaseContext(ctx, tc.acmeDB) + par := NewPolicyAdminResponder() req := httptest.NewRequest("POST", "/foo", io.NopCloser(bytes.NewBuffer(tc.body))) - req = req.WithContext(tc.ctx) + req = req.WithContext(ctx) w := httptest.NewRecorder() par.CreateACMEAccountPolicy(w, req) @@ -2231,6 +2285,7 @@ func TestPolicyAdminResponder_UpdateACMEAccountPolicy(t *testing.T) { err.Message = "ACME EAK policy does not exist" return test{ ctx: ctx, + adminDB: &admin.MockDB{}, err: err, statusCode: 404, } @@ -2257,6 +2312,7 @@ func TestPolicyAdminResponder_UpdateACMEAccountPolicy(t *testing.T) { body := []byte("{?}") return test{ ctx: ctx, + adminDB: &admin.MockDB{}, body: body, err: adminErr, statusCode: 400, @@ -2293,6 +2349,7 @@ func TestPolicyAdminResponder_UpdateACMEAccountPolicy(t *testing.T) { }`) return test{ ctx: ctx, + adminDB: &admin.MockDB{}, body: body, err: adminErr, statusCode: 400, @@ -2321,7 +2378,8 @@ func TestPolicyAdminResponder_UpdateACMEAccountPolicy(t *testing.T) { body, err := protojson.Marshal(policy) assert.NoError(t, err) return test{ - ctx: ctx, + ctx: ctx, + adminDB: &admin.MockDB{}, acmeDB: &acme.MockDB{ MockUpdateExternalAccountKey: func(ctx context.Context, provisionerID string, eak *acme.ExternalAccountKey) error { assert.Equal(t, "provID", provisionerID) @@ -2355,7 +2413,8 @@ func TestPolicyAdminResponder_UpdateACMEAccountPolicy(t *testing.T) { body, err := protojson.Marshal(policy) assert.NoError(t, err) return test{ - ctx: ctx, + ctx: ctx, + adminDB: &admin.MockDB{}, acmeDB: &acme.MockDB{ MockUpdateExternalAccountKey: func(ctx context.Context, provisionerID string, eak *acme.ExternalAccountKey) error { assert.Equal(t, "provID", provisionerID) @@ -2378,11 +2437,12 @@ func TestPolicyAdminResponder_UpdateACMEAccountPolicy(t *testing.T) { for name, prep := range tests { tc := prep(t) t.Run(name, func(t *testing.T) { - - par := NewPolicyAdminResponder(nil, tc.adminDB, tc.acmeDB) + ctx := admin.NewContext(tc.ctx, tc.adminDB) + ctx = acme.NewDatabaseContext(ctx, tc.acmeDB) + par := NewPolicyAdminResponder() req := httptest.NewRequest("POST", "/foo", io.NopCloser(bytes.NewBuffer(tc.body))) - req = req.WithContext(tc.ctx) + req = req.WithContext(ctx) w := httptest.NewRecorder() par.UpdateACMEAccountPolicy(w, req) @@ -2462,6 +2522,7 @@ func TestPolicyAdminResponder_DeleteACMEAccountPolicy(t *testing.T) { err.Message = "ACME EAK policy does not exist" return test{ ctx: ctx, + adminDB: &admin.MockDB{}, err: err, statusCode: 404, } @@ -2487,7 +2548,8 @@ func TestPolicyAdminResponder_DeleteACMEAccountPolicy(t *testing.T) { err := admin.NewErrorISE("error deleting ACME EAK policy: force") err.Message = "error deleting ACME EAK policy: force" return test{ - ctx: ctx, + ctx: ctx, + adminDB: &admin.MockDB{}, acmeDB: &acme.MockDB{ MockUpdateExternalAccountKey: func(ctx context.Context, provisionerID string, eak *acme.ExternalAccountKey) error { assert.Equal(t, "provID", provisionerID) @@ -2518,7 +2580,8 @@ func TestPolicyAdminResponder_DeleteACMEAccountPolicy(t *testing.T) { ctx := linkedca.NewContextWithProvisioner(context.Background(), prov) ctx = linkedca.NewContextWithExternalAccountKey(ctx, eak) return test{ - ctx: ctx, + ctx: ctx, + adminDB: &admin.MockDB{}, acmeDB: &acme.MockDB{ MockUpdateExternalAccountKey: func(ctx context.Context, provisionerID string, eak *acme.ExternalAccountKey) error { assert.Equal(t, "provID", provisionerID) @@ -2533,11 +2596,12 @@ func TestPolicyAdminResponder_DeleteACMEAccountPolicy(t *testing.T) { for name, prep := range tests { tc := prep(t) t.Run(name, func(t *testing.T) { - - par := NewPolicyAdminResponder(nil, tc.adminDB, tc.acmeDB) + ctx := admin.NewContext(tc.ctx, tc.adminDB) + ctx = acme.NewDatabaseContext(ctx, tc.acmeDB) + par := NewPolicyAdminResponder() req := httptest.NewRequest("POST", "/foo", io.NopCloser(bytes.NewBuffer(tc.body))) - req = req.WithContext(tc.ctx) + req = req.WithContext(ctx) w := httptest.NewRecorder() par.DeleteACMEAccountPolicy(w, req) diff --git a/ca/ca.go b/ca/ca.go index 16a5c600..9252fff7 100644 --- a/ca/ca.go +++ b/ca/ca.go @@ -213,7 +213,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() mux.Route("/admin", func(r chi.Router) { adminAPI.Route(r, acmeAdminResponder, policyAdminResponder) })