open-vault/builtin/logical/pki/path_acme_authorizations.go
Steven Clark d324aa0d15
Implement ACME order API (#20127)
* Implement ACME new-order API
 - This is a very rough draft for the new order ACME API

* Add ACME order list API

* Implement ACME Get order API

* Misc order related fixes

 - Filter authorizations in GetOrders for valid
 - Validate notBefore and notAfter dates make sense
 - Add <order>/cert URL path to order response if set to valid

* Return account status within err authorized, if the account key verified
2023-04-14 14:54:48 +00:00

112 lines
3.8 KiB
Go

package pki
import (
"fmt"
"github.com/hashicorp/vault/sdk/framework"
"github.com/hashicorp/vault/sdk/logical"
)
func pathAcmeRootAuthorization(b *backend) *framework.Path {
return patternAcmeAuthorization(b, "acme/authorization/"+framework.MatchAllRegex("auth_id"))
}
func pathAcmeRoleAuthorization(b *backend) *framework.Path {
return patternAcmeAuthorization(b, "roles/"+framework.GenericNameRegex("role")+"/acme/authorization/"+framework.MatchAllRegex("auth_id"))
}
func pathAcmeIssuerAuthorization(b *backend) *framework.Path {
return patternAcmeAuthorization(b, "issuer/"+framework.GenericNameRegex(issuerRefParam)+"/acme/authorization/"+framework.MatchAllRegex("auth_id"))
}
func pathAcmeIssuerAndRoleAuthorization(b *backend) *framework.Path {
return patternAcmeAuthorization(b,
"issuer/"+framework.GenericNameRegex(issuerRefParam)+
"/roles/"+framework.GenericNameRegex("role")+"/acme/authorization/"+framework.MatchAllRegex("auth_id"))
}
func addFieldsForACMEAuthorization(fields map[string]*framework.FieldSchema) map[string]*framework.FieldSchema {
fields["auth_id"] = &framework.FieldSchema{
Type: framework.TypeString,
Description: "ACME authorization identifier value",
Required: true,
}
return fields
}
func patternAcmeAuthorization(b *backend, pattern string) *framework.Path {
fields := map[string]*framework.FieldSchema{}
addFieldsForACMEPath(fields, pattern)
addFieldsForACMERequest(fields)
addFieldsForACMEAuthorization(fields)
return &framework.Path{
Pattern: pattern,
Fields: fields,
Operations: map[logical.Operation]framework.OperationHandler{
logical.UpdateOperation: &framework.PathOperation{
Callback: b.acmeAccountRequiredWrapper(b.acmeAuthorizationHandler),
ForwardPerformanceSecondary: false,
ForwardPerformanceStandby: true,
},
},
HelpSynopsis: "",
HelpDescription: "",
}
}
func (b *backend) acmeAuthorizationHandler(acmeCtx *acmeContext, r *logical.Request, fields *framework.FieldData, userCtx *jwsCtx, data map[string]interface{}, _ *acmeAccount) (*logical.Response, error) {
authId := fields.Get("auth_id").(string)
authz, err := b.acmeState.LoadAuthorization(acmeCtx, userCtx, authId)
if err != nil {
return nil, fmt.Errorf("failed to load authorization: %w", err)
}
var status string
rawStatus, haveStatus := data["status"]
if haveStatus {
var ok bool
status, ok = rawStatus.(string)
if !ok {
return nil, fmt.Errorf("bad type (%T) for value 'status': %w", rawStatus, ErrMalformed)
}
}
if len(data) == 0 {
return b.acmeAuthorizationFetchHandler(acmeCtx, r, fields, userCtx, data, authz)
}
if haveStatus && status == "deactivated" {
return b.acmeAuthorizationDeactivateHandler(acmeCtx, r, fields, userCtx, data, authz)
}
return nil, ErrMalformed
}
func (b *backend) acmeAuthorizationFetchHandler(acmeCtx *acmeContext, r *logical.Request, fields *framework.FieldData, userCtx *jwsCtx, data map[string]interface{}, authz *ACMEAuthorization) (*logical.Response, error) {
return &logical.Response{
Data: authz.NetworkMarshal(),
}, nil
}
func (b *backend) acmeAuthorizationDeactivateHandler(acmeCtx *acmeContext, r *logical.Request, fields *framework.FieldData, userCtx *jwsCtx, data map[string]interface{}, authz *ACMEAuthorization) (*logical.Response, error) {
if authz.Status != ACMEAuthorizationPending && authz.Status != ACMEAuthorizationValid {
return nil, fmt.Errorf("unable to deactivate authorization in '%v' status: %w", authz.Status, ErrMalformed)
}
authz.Status = ACMEAuthorizationDeactivated
for _, challenge := range authz.Challenges {
challenge.Status = ACMEChallengeInvalid
}
if err := b.acmeState.SaveAuthorization(acmeCtx, authz); err != nil {
return nil, fmt.Errorf("error saving deactivated authorization: %w", err)
}
return &logical.Response{
Data: authz.NetworkMarshal(),
}, nil
}