nodeenrollment

package module
v0.2.10 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 6, 2024 License: MPL-2.0 Imports: 18 Imported by: 0

README

Node Enrollment

IMPORTANT

This is a repo for an internal HashiCorp library to facilitate sharing its functionality across HashiCorp projects. It is public so that our community versions can successfully import and build it, however it should not be considered to be a supported library outside of HashiCorp.

Documentation

Index

Constants

View Source
const (
	// DefaultNotBeforeClockSkewDuration is the time to subtract from NotBefore to account for
	// some clock skew
	DefaultNotBeforeClockSkewDuration = -5 * time.Minute

	// DefaultNotAfterClockSkewDuration is the time to subtract from NotBefore to account for
	// some clock skew
	DefaultNotAfterClockSkewDuration = 5 * time.Minute

	// DefaultCertificateLifetime is the default duration of a certificate, set
	// to two weeks. Rotations should happen at roughly half this.
	DefaultCertificateLifetime = time.Hour * 24 * 14

	// This is the default time that an server-led activation token is alive
	DefaultMaximumServerLedActivationTokenLifetime = time.Hour * 24 * 14

	// CommonDnsName is a name we can use in the absence of anything more
	// specific. In most cases we actually do not care about common name or DNS
	// SAN verification, and when we do we have an explicit test for it. In all
	// other cases using this allows us to not fail due to name validity checks.
	// Derived loosely from the Wizard in The Wizard of Oz.
	CommonDnsName = "pay-no-attention-to-that-pers-on-behind-the-curt-on"

	// FetchNodeCredsNextProtoV1Prefix is the ALPN NextProto used when a node is
	// trying to fetch credentials
	FetchNodeCredsNextProtoV1Prefix = "v1-nodee-fetch-node-creds-"

	// AuthenticateNodeNextProtoV1Prefix is the ALPN NextProto used when a node
	// is trying to authenticate
	AuthenticateNodeNextProtoV1Prefix = "v1-nodee-authenticate-node-"

	// CertificatePreferenceV1Prefix is the ALPN NextProto used by a node to
	// indicate a certificate preference, since we can't use ServerName
	CertificatePreferenceV1Prefix = "v1-nodee-certificate-preference-"

	// NonceSize is our defined nonce size, in bytes
	NonceSize = 32

	// KeyIdNumWords is the number of words to generate from a hash of the
	// public key to serve as the key ID
	KeyIdNumWords = 8

	// The ID that will always be used for storing root certificate messages
	RootsMessageId = "roots"

	// The default amount of time for a signed fetch request validity period
	DefaultFetchCredentialsLifetime = time.Hour * 24

	// ServerLedActivationTokenPrefix is used to identify an incoming nonce at
	// activation time that should trigger a lookup for a server-generated token
	ServerLedActivationTokenPrefix = "neslat_" // NodeEnrollment Server-Led Activation Token
)

Variables

View Source
var ErrNotAuthorized = errors.New("node is not yet authorized")

ErrNotAuthorized is a common error that we can return to indicate that a node is still awaiting authentication after attempting to fetch credentials

View Source
var ErrNotFound = errors.New("value not found in storage")

ErrNotFound is a common error to use when a value is not found in storage. Depending on the storage implementation it may be a different underlying error, so this ensures we can use errors.Is as a check.

Functions

func ContainsKnownAlpnProto

func ContainsKnownAlpnProto(protos ...string) bool

ContainsKnownAlpnProto performs a simple check to see if one our defined ALPN protos is contained in the given set

func DecryptMessage

func DecryptMessage(ctx context.Context, ct []byte, keySource X25519KeyProducer, result proto.Message, _ ...Option) error

DecryptMessage takes any a value encrypted with EncryptMessage and a valid key source that implements X25519KeyProducer and decrypts the message into the given proto.Message. Internally it uses an `aead` wrapper from go-kms-wrapping v2. No options are currently supported but in the future non-AES-GCM decryption types could be supported by the wrapper and chosen here.

ID should match what was passed into the encryption function. It is also passed as additional authenticated data to the decryption function, if supported.

If decryption fails with the current key, and a prior key is present, use that to try and decrypt the message in the case an older key was used to encrypt the incoming message

func EncryptMessage

func EncryptMessage(ctx context.Context, msg proto.Message, keySource X25519KeyProducer, opt ...Option) ([]byte, error)

EncryptMessage takes any proto.Message and a valid key source that implements X25519KeyProducer. Internally it uses an `aead` wrapper from go-kms-wrapping v2. No options are currently supported but in the future non-AES-GCM encryption types could be supported by the wrapper and chosen here.

The resulting value from the wrapper is marshaled before being returned.

Supported options: WithRandomReader

func IsNil

func IsNil(in any) bool

func KeyIdFromPkix

func KeyIdFromPkix(pkixKey []byte) (string, error)

KeyIdFromPkix derives the library-specific key ID from the PKIX-encoed public key

func SubjectKeyInfoAndKeyIdFromPubKey

func SubjectKeyInfoAndKeyIdFromPubKey(pubKey crypto.PublicKey) ([]byte, string, error)

SubjectKeyInfoAndKeyIdFromPubKey returns the PKIX-encoded public key and the library-specific key ID derived from it

Types

type CleanableStorage added in v0.2.0

type CleanableStorage interface {
	// Cleanup is a cleanup function
	Cleanup(context.Context) error
}

CleanableStorage is an interface that can optionally be implemented by storage implementations to indicate that there is a cleanup function that can be run when storage usage is complete.

type KnownId

type KnownId string
const (
	MissingId KnownId = ""

	// CurrentId is a const for when we are fetching the "current" value for
	// various purposes
	CurrentId KnownId = "current"

	// NextId is a const for when we are fetching the "next" value for various
	// purposes
	NextId KnownId = "next"
)

type MessageWithId

type MessageWithId interface {
	proto.Message
	GetId() string
}

MessageWithId is a proto message that is required to implement a GetId function, which will be immediately satisfied by any message with an `string id = X;` parameter.

type Option

type Option func(*Options) error

Option is a function that takes in an options struct and sets values or returns an error

func WithActivationToken added in v0.1.16

func WithActivationToken(with string) Option

WithActivationToken is used to pass an activation token; typically this will be to pass a server-generated activation token as the nonce for a request

func WithAlpnProtoPrefix

func WithAlpnProtoPrefix(with string) Option

WithAlpnProtoPrefix is used to convey information about which proto is being used to handle a connection

func WithCertificateLifetime

func WithCertificateLifetime(with time.Duration) Option

WithCertificateLifetime allows overriding a default duration for certificate creation. If 0 is passed in, the default will be used; to get an actual zero lifetime (e.g. to only use skew), just specify something short, like a nanosecond.

func WithExpectedPublicKey

func WithExpectedPublicKey(with []byte) Option

WithExpectedPublicKey allows indicating a public key that we expect to be the key signed by a certificate

func WithExtraAlpnProtos added in v0.1.5

func WithExtraAlpnProtos(with []string) Option

WithExtraAlpnProtos is used to allow passing additional ALPN protos in via a ClientHello message, e.g. via the Dial function in the protocol package. This can allow users of the library to perform an extra switch on the desired protocol post-authentication.

func WithLogger added in v0.2.0

func WithLogger(with hclog.Logger) Option

WithLogger allows passing in a logger to use for debugging purposes

func WithMaximumServerLedActivationTokenLifetime added in v0.1.16

func WithMaximumServerLedActivationTokenLifetime(with time.Duration) Option

WithMaximumActivationTokenLifetime allows overriding a default duration for server-led activation token lifetime

func WithNativeConns added in v0.1.18

func WithNativeConns(with bool) Option

WithNativeConns, if set to true, indicates to use the native protocol package conn type to return from the split listener listeners

func WithNonce

func WithNonce(with string) Option

WithNonce is used at various points for encoding nonces in certs or expecting them there

func WithNotAfterClockSkew

func WithNotAfterClockSkew(with time.Duration) Option

WithNotAfterClockSkew allows overriding a default duration for certificate NotAfter clock skew handling

func WithNotBeforeClockSkew

func WithNotBeforeClockSkew(with time.Duration) Option

WithNotBeforeClockSkew allows overriding a default duration for certificate NotBefore clock skew handling

func WithRandomReader

func WithRandomReader(with io.Reader) Option

WithRandomReader allows specifying a reader to use in place of the default (crypto/rand.Reader)

func WithRegistrationWrapper added in v0.2.0

func WithRegistrationWrapper(with wrapping.Wrapper) Option

WithRegistrationWrapper can be used when fetching node credentials to provide registration information. If you want to support more than one, use a pooled wrapper (https://pkg.go.dev/github.com/hashicorp/go-kms-wrapping/v2/extras/multi)

func WithReinitializeRoots added in v0.1.14

func WithReinitializeRoots(with bool) Option

WithReinitializeRoots, if set to true, indicates that the existing roots should be removed entirely before rotation

func WithServerName added in v0.1.2

func WithServerName(with string) Option

WithServerName is used to pass a server name to include in a TLS config

func WithSkipStorage

func WithSkipStorage(with bool) Option

WithSkipStorage allows indicating that the newly generated resource should not be stored in storage, but simply returned in-memory only, useful for tests or cases where the storage implementation wants to manage storage lifecycle (e.g. with transactions)

func WithState

func WithState(with *structpb.Struct) Option

WithState allows passing state in to some registration functions to round trip to NodeInformation storage

func WithStorageWrapper added in v0.2.0

func WithStorageWrapper(with wrapping.Wrapper) Option

WithStorageWrapper will cause the library to wrap any sensitive information (private keys, nonces, etc.) with the given wrapper prior to writing to storage, and to unwrap when reading from storage

func WithTestErrorContains added in v0.2.1

func WithTestErrorContains(with string) Option

WithTestErrorContains is used in some tests to pass expected error values

func WithTlsVerifyOptionsFunc

func WithTlsVerifyOptionsFunc(with func(*x509.CertPool) x509.VerifyOptions) Option

WithTlsVerifyOptionsFunc allows specifying a custom TLS certificate VerifyFunc, useful for testing

func WithWrappingRegistrationFlowApplicationSpecificParams added in v0.2.0

func WithWrappingRegistrationFlowApplicationSpecificParams(with *structpb.Struct) Option

WithWrappingRegistrationFlowApplicationSpecificParams allows passing extra application specific parameters when using the wrapping registration flow

type Options

type Options struct {
	WithCertificateLifetime                               time.Duration
	WithNotBeforeClockSkew                                time.Duration
	WithNotAfterClockSkew                                 time.Duration
	WithRandomReader                                      io.Reader
	WithNonce                                             string
	WithTlsVerifyOptionsFunc                              func(*x509.CertPool) x509.VerifyOptions
	WithStorageWrapper                                    wrapping.Wrapper
	WithRegistrationWrapper                               wrapping.Wrapper
	WithSkipStorage                                       bool
	WithExpectedPublicKey                                 []byte
	WithState                                             *structpb.Struct
	WithWrappingRegistrationFlowApplicationSpecificParams *structpb.Struct
	WithAlpnProtoPrefix                                   string
	WithServerName                                        string
	WithExtraAlpnProtos                                   []string
	WithReinitializeRoots                                 bool
	WithActivationToken                                   string
	WithMaximumServerLedActivationTokenLifetime           time.Duration
	WithNativeConns                                       bool
	WithLogger                                            hclog.Logger
	WithTestErrorContains                                 string
}

Options contains various options. The values are exported since the options are parsed in various other packages.

func GetOpts

func GetOpts(opt ...Option) (*Options, error)

GetOpts iterates the inbound Options and returns a struct and any errors

type Storage

type Storage interface {
	// Store stores the given message
	Store(context.Context, MessageWithId) error

	// Load loads values into the given message. The message must be populated
	// with the ID of the value to load. If not found, the returned error should
	// be ErrNotFound.
	Load(context.Context, MessageWithId) error

	// Remove removes the given message. The ID field of the message must be
	// populated, and only the ID field of the message is considered.
	Remove(context.Context, MessageWithId) error

	// List returns a list of IDs; the type of the message is used to
	// disambiguate what to list, and can be a nil pointer to the type.
	List(context.Context, proto.Message) ([]string, error)
}

Storage is an interface for to store values. The interface operates on proto.Message or MessageWithId (which embeds a proto.Message but requires a GetId() function), which is satisifed by all types in this library and provides some type safety vs. any.

The interface can be used for multiple types of message via a type switch on, allowing various implementations to then read or write the correct data from e.g. separate storage locations.

type X25519KeyProducer added in v0.1.17

type X25519KeyProducer interface {
	X25519EncryptionKey() (string, []byte, error)
	PreviousX25519EncryptionKey() (string, []byte, error)
}

X25519KeyProducer is an interface that can be satisfied by an underlying type that produces an encryption key via X25519, along with a key identifier used for AAD and embedding in the wrapping data. If the ID is empty, it is simply unused for either purpose.

Directories

Path Synopsis
Protocol provides a listener and dial function that can be used to easily integrate this library into other applications.
Protocol provides a listener and dial function that can be used to easily integrate this library into other applications.
storage
util

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL