vault/builtin/logical/pki/path_acme_authorizations.go
Vault Automation 7f9a3efe21
VAULT-39462 PKI observations (#9576) (#9747)
* VAULT-39462 PKI observations first draft?

* acme account

* acme account 2

* license

* belt and braces

* EST, and some tests

* more stuff

* SCEP

* key tests etc

* WIP reorganize code into an observe sub-package with interfaces

* make fmt

* fmt

* fmt

* empty file hehe

* copyright headers

* Update builtin/logical/pki/backend_cmpv2_ent_test.go



* Update builtin/logical/pki/backend_cmpv2_ent_test.go



* Update builtin/logical/pki/path_ocsp.go



* Update builtin/logical/pki/path_acme_order.go



* Update builtin/logical/pki/path_acme_order.go



* extra info

* add stored to cieps

* make fmt

---------

Co-authored-by: Violet Hynes <violet.hynes@hashicorp.com>
Co-authored-by: Steven Clark <steven.clark@hashicorp.com>
2025-09-30 12:34:07 -04:00

107 lines
3.6 KiB
Go

// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package pki
import (
"fmt"
"github.com/hashicorp/vault/builtin/logical/pki/observe"
"github.com/hashicorp/vault/sdk/framework"
"github.com/hashicorp/vault/sdk/logical"
)
func pathAcmeAuthorization(b *backend, baseUrl string, opts acmeWrapperOpts) *framework.Path {
return patternAcmeAuthorization(b, baseUrl+"/authorization/"+framework.MatchAllRegex("auth_id"), opts)
}
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, opts acmeWrapperOpts) *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(opts, b.acmeAuthorizationHandler),
ForwardPerformanceSecondary: false,
ForwardPerformanceStandby: true,
},
},
HelpSynopsis: pathAcmeHelpSync,
HelpDescription: pathAcmeHelpDesc,
}
}
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.GetAcmeState().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)
}
}
b.pkiObserver.RecordPKIObservation(acmeCtx, r, observe.ObservationTypePKIAcmeAuthorization,
observe.NewAdditionalPKIMetadata("auth_id", authId),
observe.NewAdditionalPKIMetadata("status", status),
)
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(acmeCtx),
}, 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.GetAcmeState().SaveAuthorization(acmeCtx, authz); err != nil {
return nil, fmt.Errorf("error saving deactivated authorization: %w", err)
}
return &logical.Response{
Data: authz.NetworkMarshal(acmeCtx),
}, nil
}