vault/sdk/helper/nonce/nonce.go
Alexander Scheel b1f0d4e495
Add nonce service to sdk/helpers, use in PKI (#20688)
* Build a better nonce service

Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com>

* Add internal nonce service for testing

Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com>

* Add benchmarks for nonce service

Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com>

* Add statistics around how long tidy took

Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com>

* Replace ACME nonces with shared nonce service

Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com>

* Add an initialize method to nonce services

Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com>

* Use the new initialize helper on nonce service in PKI

Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com>

* Add additional tests for nonces

Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com>

* Format sdk/helper/nonce

Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com>

* Use default 90s nonce expiry in PKI

Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com>

* Remove parallel test case as covered by benchmark

Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com>

* Add additional commentary to encrypted nonce implementation

Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com>

* Add nonce to test_packages

Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com>

---------

Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com>
2023-05-23 19:44:05 +00:00

71 lines
2.4 KiB
Go

// Nonce is a class for generating and validating nonces loosely based off
// the design of Let's Encrypt's Boulder nonce service here:
//
// https://github.com/letsencrypt/boulder/blob/main/nonce/nonce.go
package nonce
import (
"time"
)
// NonceService is an interface for issuing and redeeming nonces, with
// a hook to periodically free resources when no redemptions have happened
// recently.
//
// Notably, nonces are not guaranteed to be stored or persisted; nonces
// from one startup will not necessarily be valid from another.
type NonceService interface {
// Before using a nonce service, it must be initialized. Failure to
// initialize might result in panics or other unexpected results.
Initialize() error
// Get a nonce; returns three values:
//
// 1. The nonce itself, a base64-url-no-padding opaque value.
// 2. A time at which the nonce will expire, based on the validity
// period specified at construction. By default, the service issues
// short-lived nonces.
// 3. An error if one occurred during generation of the nonce.
Get() (string, time.Time, error)
// Redeem the given nonce, returning whether or not it was accepted. A
// nonce given twice will be rejected if the service is a strict nonce
// service, but potentially accepted if the nonce service is loose
// (i.e., temporal revocation only).
Redeem(string) bool
// A hook to tidy the memory usage of the underlying implementation; is
// implementation dependent. Some implementations may not return status
// information.
Tidy() *NonceStatus
// If true, this is a strict only-once redemption service implementation,
// else a nonce could be accepted more than once within some safety
// window.
IsStrict() bool
// Whether or not this service is usable across nodes.
IsCrossNode() bool
}
func NewNonceService() NonceService {
// By default, we create an encrypted nonce service that is strict but not
// cross node, using a default window of 90 seconds (equal to the default
// context request timeout window).
return NewNonceServiceWithValidity(90 * time.Second)
}
func NewNonceServiceWithValidity(validity time.Duration) NonceService {
return newEncryptedNonceService(validity)
}
// Status information about the number of nonces in this service, perhaps
// local to this node. Presumably, the delta roughly correlates to present
// memory usage.
type NonceStatus struct {
Issued uint64
Outstanding uint64
Message string
}