protocol

package
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

Documentation

Overview

Protocol provides a listener and dial function that can be used to easily integrate this library into other applications. An application can wrap its incoming listener with an InterceptingListener from this package, which will handle the connection iff the incoming TLS NextProto value is one known by this library, and it can have its dial function use this package for dialing. Either a connection will be returned or a (possibly temporary) error; on the application side, it merely needs to check the negotiated protocol in the returned tls.Conn to see if it matches the defined authentication proto (a fetch connection will _always_ return a (temporary) error). If so, the node is successfully authenticated.

Using this package is optional but encouraged when possible to avoid having to instrument logic directly within an app.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Dial

func Dial(
	ctx context.Context,
	storage nodeenrollment.Storage,
	addr string,
	opt ...nodeenrollment.Option,
) (net.Conn, error)

Dial returns a function suitable for dialing a connection to an InterceptingListener. It takes in storage, an address, and options.

Supported options: WithRandomReader, WithStorageWrapper (passed through to LoadNodeCredentials and NodeCredentials.Store), WithNotBeforeClockSkew/WithNotAfterClockSkew (these are used as NotBefore/NotAfter lifetimes for the generated cert used for client side TLS), WithExtraAlpnProtos (passed through to the client side TLS configuration), WithActivationToken/WithRegistrationWrapper/WithWrappingRegistrationFlowApplicationSpecificParams (passed through to CreateFetchNodeCredentialsRequest), WithLogger

Types

type ClientInfo added in v0.1.5

type ClientInfo struct {
	// contains filtered or unexported fields
}

ClientInfo allows us to pass information back from the TLS handshake

type Conn added in v0.1.5

type Conn struct {
	*tls.Conn
	// contains filtered or unexported fields
}

Conn embeds a *tls.Conn and allows us to add extra bits into it

func NewConn added in v0.1.7

func NewConn(base *tls.Conn, opt ...nodeenrollment.Option) (*Conn, error)

NewConn constructs a conn from a base TLS connection and possibly client next protos.

Supported options: WithExtraAlpnProtos (used to set clientNextProtos), WithState (storing client state information)

func (*Conn) ClientNextProtos added in v0.1.5

func (c *Conn) ClientNextProtos() []string

ClientNextProtos returns the value of NextProtos originally presented by the client at connection time

func (*Conn) ClientState added in v0.1.19

func (c *Conn) ClientState() *structpb.Struct

ClientState returns the value of the state embedded into the original client request, which may be nil

type FetchCredsFn

FetchCredsFn is a function that is used when a node requests fetching its initial credentials. It returns a response or an error. This is called during TLS negotiation for the given ALPN proto.

Note that options do not carry across gRPC; in practice this means they do not carry across multiple nodes. Only options meant for local use (WithRandomReader, WithStorageWrapper, WithLogger) etc. should be used, via the direct functions.

type GenerateServerCertificatesFn

GenerateServerCertificatesFn is a function that is used when a node is connecting by the upstream node to fetch a certificate to present to the node. It returns a response or an error. This is called during TLS negotiation for the given ALPN proto.

Note that options do not carry across gRPC; in practice this means they do not carry across multiple nodes. Only options meant for local use (WithRandomReader, WithStorageWrapper, WithLogger) etc. should be used, via the direct functions.

type InterceptingListener

type InterceptingListener struct {
	// contains filtered or unexported fields
}

InterceptingListener is a listener that transparently handles fetch and auth flows if the right ALPN protos are found, and passes through otherwise

func NewInterceptingListener

func NewInterceptingListener(
	config *InterceptingListenerConfiguration,
) (*InterceptingListener, error)

New creates a new listener based on the passed in listener (which should not be a TLS listener) and the given base TLS configuration. This function will substitute its own TLS configuration to handle the protos specific to nodeenrollment. Any connection coming in that is not using those protos will simply be passed through.

The context value is not used here, but simply passed through to other library functions. To stop the listener, close it normally.

func (*InterceptingListener) Accept

func (l *InterceptingListener) Accept() (conn net.Conn, retErr error)

Accept accepts the next connection.

If the TLS protos is one of our known credential fetching/auth protos, we'll handle it. Otherwise we pass through.

You should check the resulting connection before trusting it. You can do that by seeing if the negotiated protocol was the auth protocol handled by this library:

if strings.HasPrefix(
	returnedConn.(*protocol.Conn).Conn.ConnectionState().NegotiatedProtocol,
	nodeenrollment.AuthenticateNodeNextProtoV1Prefix
) {
	// Authenticated by this library
} else {
	// Not authenticated by this library
}

There is also some special behavior around the errors that this function returns. For compatibility with listeners passed into gRPC servers, most errors satisfy a Temporary interface so that returning an error does not cause the gRPC server to shut down the listener, which should really only happen for system-level errors rather than connection-specific errors. For gRPC this should likely just work, but if you need to check if this is a true error in your own code, you can do this:

if tempErr, ok := err.(interface {
  Temporary() bool
}); ok && tempErr.Temporary() {

If it's temporary, continue on and accept the next connection.

What's returned is a protocol.Conn; it contains an embedded *tls.Conn as the Conn variable, if needed.

Supported options: WithLogger

func (*InterceptingListener) Addr

func (l *InterceptingListener) Addr() net.Addr

Addr satisfies the net.Listener interface and simply returns the base listener's address

func (*InterceptingListener) Close

func (l *InterceptingListener) Close() error

Close satisfies the net.Listener interface and closes the base listener

type InterceptingListenerConfiguration

type InterceptingListenerConfiguration struct {
	// The context that will be used to call any functions once a connection is
	// accepted. Required.
	Context context.Context

	// The storage that will be used for any storage needs for connections.
	// Required.
	Storage nodeenrollment.Storage

	// The base listener to accept connections from and possibly intercept.
	// Required.
	BaseListener net.Listener

	// The TLS configuration to use if the incoming connection is not one
	// handled by this library. If nil, any connection not handled by this
	// library will result in a TLS error.
	BaseTlsConfiguration *tls.Config

	// The function to use for the FetchCredentials operation. If nil, the
	// default will be used, which is suitable for a server.
	FetchCredsFunc FetchCredsFn

	// The function to use for the GenerateServerCertificates operation. If nil,
	// the default will be used, which is suitable for a server.
	GenerateServerCertificatesFunc GenerateServerCertificatesFn

	// If provided, options to pass into various storage functions, e.g.
	// WithRandomReader, WithStorageWrapper, WithLogger, etc.
	Options []nodeenrollment.Option
}

InterceptingListenerConfiguration contains config information for InterceptingListener

Jump to

Keyboard shortcuts

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