d324aa0d15
* 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
112 lines
3.8 KiB
Go
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
|
|
}
|