auth

package
v0.5.1 Latest Latest
Warning

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

Go to latest
Published: Jun 7, 2024 License: Apache-2.0 Imports: 36 Imported by: 0

README

ContainerSSH Authentication Library

This library provides the server and client components for the authentication webhook

Creating a server

As a core component for your authentication server you will have to implement the Handler interface:

type myHandler struct {
}

func (h *myHandler) OnPassword(
    Username string,
    Password []byte,
    RemoteAddress string,
    ConnectionID string,
) (bool, error) {
    if Username == "foo" && string(Password) == "bar" {
        return true, nil
    }
    if Username == "crash" {
        // Simulate a database failure
        return false, fmt.Errorf("database error")
    }
    return false, nil
}

func (h *myHandler) OnPubKey(
    Username string,
    // PublicKey is the public key in the authorized key format.
    PublicKey string,
    RemoteAddress string,
    ConnectionID string,
) (bool, error) {
    // Handle public key auth here
}

Then you can use this handler to create a simple web server using the http library. The server requires using the lifecycle facility from the service library. You can create the server as follows:

server := auth.NewServer(
    http.ServerConfiguration{
        Listen: "127.0.0.1:8080",
    },
    &myHandler{},
    logger,
)

lifecycle := service.NewLifecycle(server)

go func() {
    if err := lifecycle.Run(); err != nil {
        // Handle error
    }
}

// When done, shut down server with an optional context for the shutdown deadline
lifecycle.Stop(context.Background())

The logger is a logger from the github.com/containerssh/libcontainerssh/log package. The server configuration optionally allows you to configure mutual TLS authentication. See the documentation for details.

You can also use the authentication handler with the native Go HTTP library:

func main() {
    logger := log.New(...)
    httpHandler := auth.NewHandler(&myHandler{}, logger)
    http.Handle("/auth", httpHandler)
    http.ListenAndServe(":8090", nil)
}

Creating a client

This library also provides an HTTP client for authentication servers. This library can be used as follows:

client := auth.NewHttpAuthClient(
    auth.ClientConfig{
        URL: "http://localhost:8080"
        Password: true,
        PubKey: false,
        // This is the timeout for individual requests.
        Timeout: 2 * time.Second,
        // This is the overall timeout for the authentication process.
        AuthTimeout: 60 * time.Second,
    },
    logger,
)

success, err := client.Password(
    "foo",
    []byte("bar"),
    "0123456789ABCDEF",
    ip
) (bool, error)

success, err := client.PubKey(
    "foo",
    "ssh-rsa ...",
    "0123456789ABCDEF",
    ip
) (bool, error)

Documentation

Index

Constants

View Source
const (
	// MetricNameAuthBackendRequests is the number of requests to the config server.
	MetricNameAuthBackendRequests = "containerssh_auth_server_requests_total"

	// MetricNameAuthBackendFailure is the number of request failures to the configuration backend.
	MetricNameAuthBackendFailure = "containerssh_auth_server_failures_total"

	// MetricNameAuthSuccess captures the number of successful authentication attempts.
	MetricNameAuthSuccess = "containerssh_auth_success_total"

	// MetricNameAuthFailure captures the number of failed authentication attempts.
	MetricNameAuthFailure = "containerssh_auth_failures_total"
)

Variables

This section is empty.

Functions

func NewHandler

func NewHandler(h Handler, logger log.Logger) goHttp.Handler

NewHandler creates a handler that is compatible with the Go HTTP server.

func NewServer

func NewServer(
	configuration config.HTTPServerConfiguration,
	h Handler,
	logger log.Logger,
) (http.Server, error)

NewServer returns a complete HTTP server that responds to the authentication requests.

Types

type AuthenticationContext

type AuthenticationContext interface {
	// Success must return true or false of the authentication was successful / unsuccessful.
	Success() bool
	// Error returns the error that happened during the authentication.
	Error() error
	// Metadata returns a set of metadata entries that have been obtained during the authentication.
	Metadata() metadata.ConnectionAuthenticatedMetadata
	// OnDisconnect is called when the urlEncodedClient disconnects, or if the authentication fails due to a different reason.
	OnDisconnect()
}

AuthenticationContext holds the results of an authentication.

type AuthenticationType

type AuthenticationType string

AuthenticationType is the root type for all authentication and authorization methods. This type is extended for each use case to limit the number of options.

const AuthenticationTypeAll AuthenticationType = ""

AuthenticationTypeAll indicates all authentication types are applicable.

const AuthenticationTypeAuthz AuthenticationType = "authz"

AuthenticationTypeAuthz is the authorization after authentication method, which is intended to check if the user has permissions to log in. This does not make sense for all authentication methods.

const AuthenticationTypeGSSAPI AuthenticationType = "gssapi"

AuthenticationTypeGSSAPI indicates a cryptographic login method typically tied to the urlEncodedClient computer, e.g. Kerberos.

const AuthenticationTypeKeyboardInteractive AuthenticationType = "keyboard-interactive"

AuthenticationTypeKeyboardInteractive indicates an authentication method where the user is asked a series of questions and must answer interactively.

const AuthenticationTypePassword AuthenticationType = "password"

AuthenticationTypePassword indicates the authentication where the user submits the password from their urlEncodedClient.

const AuthenticationTypePublicKey AuthenticationType = "pubkey"

AuthenticationTypePublicKey indicates the authentication type where the client performs a public-private key authentication.

type AuthorizationResponse

type AuthorizationResponse interface {
	// Success must return true or false of the authorization was successful / unsuccessful.
	Success() bool
	// Error returns the error that happened during the authorization.
	Error() error
	// Metadata returns a set of metadata entries that have been returned from the authorization process. The values
	// provided will be merged with the values obtained from the authentication process, where the authorization
	// values have precedence. If a value is not returned in this field the value from the authentication process is
	// taken.
	Metadata() metadata.ConnectionAuthenticatedMetadata
	// OnDisconnect is called when the urlEncodedClient disconnects, or if the authorization fails due to a different reason.
	// This hook can be used to clean up issued temporary credentials.
	OnDisconnect()
}

AuthorizationResponse is the result of the authorization process in AuthzProvider.

type AuthzProvider

type AuthzProvider interface {
	// Authorize checks the username from the authentication against the username provided by the user. These two can
	// differ in case of oAuth2, OIDC, or Kerberos authentication. This can be used for an administrator to log in as
	// a different user. The function SHOULD reject the user if the combination of provided and authenticated username
	// is invalid, or the user is not eligible to access this system.
	Authorize(
		metadata metadata.ConnectionAuthenticatedMetadata,
	) AuthorizationResponse
}

AuthzProvider provides a method to verify the authenticated username against the username provided by the user. These two can differ when the authentication server verified the credentials based on other factors, for example using oAuth2, OIDC, or Kerberos.

func NewAuthorizationProvider

func NewAuthorizationProvider(
	cfg config.AuthzConfig,
	logger log.Logger,
	metrics metrics.Collector,
) (AuthzProvider, service.Service, error)

NewAuthorizationProvider returns an authorization provider as configured, and if needed a backing service that needs to run for the authorization to work. If authorization is disabled it returns nil. If the configuration is invalid an error is returned.

type GSSAPIAuthenticator

type GSSAPIAuthenticator interface {
	// GSSAPI is a method to generate and retrieve a GSSAPIServer interface for GSSAPI authentication.
	GSSAPI(
		metadata metadata.ConnectionMetadata,
	) GSSAPIServer
}

GSSAPIAuthenticator authenticates using the GSSAPI method typically used for Kerberos authentication.

func NewGSSAPIAuthenticator

func NewGSSAPIAuthenticator(
	cfg config.GSSAPIAuthConfig,
	logger log.Logger,
	metrics metrics.Collector,
) (GSSAPIAuthenticator, service.Service, error)

NewGSSAPIAuthenticator returns a GSSAPI authenticator as configured, and if needed a backing service that needs to run for the authentication to work. If GSSAPI authentication is disabled it returns nil. If the configuration is invalid an error is returned.

type GSSAPIMicField

type GSSAPIMicField struct {
	// SessionIdentifier is a random string identifying the ssh connection
	// (different from containerSSHs identifier)
	SessionIdentifier string
	// Request is the action that's being requested (50: SSH_MSG_USERAUTH_REQUEST)
	Request byte
	// UserName is the username that the user requests to log in as
	UserName string
	// Service is the service being used ('ssh-connection')
	Service string
	// Method is the authentication method in use ('gssapi-with-mic')
	Method string
}

GSSAPIMicField is described in RFC4462 Section 3.5

type GSSAPIServer

type GSSAPIServer interface {
	// Success must return true or false of the authentication was successful / unsuccessful.
	Success() bool

	// Error returns the error that happened during the authentication.
	Error() error

	// AcceptSecContext is the GSSAPI function to verify the tokens.
	AcceptSecContext(token []byte) (outputToken []byte, srcName string, needContinue bool, err error)

	// VerifyMIC is the GSSAPI function to verify the MIC (Message Integrity Code).
	VerifyMIC(micField []byte, micToken []byte) error

	// DeleteSecContext is the GSSAPI function to free all resources bound as part of an authentication attempt.
	DeleteSecContext() error

	// AllowLogin is the authorization function. The username parameter
	// specifies the user that the authenticated user is trying to log in
	// as. Note! This is different from the gossh AllowLogin function in
	// which the username field is the authenticated username.
	AllowLogin(
		username string,
		meta metadata.ConnectionAuthPendingMetadata,
	) (metadata.ConnectionAuthenticatedMetadata, error)
}

GSSAPIServer is the interface for GSSAPI authentication. It extends ApplicationContext to provide the methods required for authenticating interactively.

type Handler

type Handler interface {
	// OnPassword is called if the urlEncodedClient requests a password authentication.
	//
	// - meta is the metadata of the connection, including the username provided by the user.
	// - password is the password the user entered.
	//
	// The method must return a boolean if the authentication was successful, and an error if the authentication failed
	// for other reasons (e.g. backend database was not available). If an error is returned the server responds with
	// an HTTP 500 response.
	OnPassword(
		metadata metadata.ConnectionAuthPendingMetadata,
		password []byte,
	) (bool, metadata.ConnectionAuthenticatedMetadata, error)

	// OnPubKey is called when the urlEncodedClient requests a public key authentication.
	//
	// - meta is the metadata of the connection, including the username provided by the user.
	// - publicKey contains the SSH public key and other accompanying information about the key.
	//
	// The method must return a boolean if the authentication was successful, and an error if the authentication failed
	// for other reasons (e.g. backend database was not available). If an error is returned the server responds with
	// an HTTP 500 response.
	OnPubKey(
		meta metadata.ConnectionAuthPendingMetadata,
		publicKey auth2.PublicKey,
	) (bool, metadata.ConnectionAuthenticatedMetadata, error)

	// OnAuthorization is called when the urlEncodedClient requests user authorization.
	//
	// - meta contains the username the user provided, the authenticated username, and other information about
	//   the connecting user.
	OnAuthorization(
		meta metadata.ConnectionAuthenticatedMetadata,
	) (bool, metadata.ConnectionAuthenticatedMetadata, error)
}

type KerberosClient

type KerberosClient interface {
	PasswordAuthenticator
	GSSAPIAuthenticator
}

KerberosClient is the authenticator for Kerberos-based authentication. It supports both plain text and GSSAPI authentication.

type KeyboardInteractiveAnswers

type KeyboardInteractiveAnswers struct {
	// KeyboardInteractiveQuestion is the original question that was answered.
	Answers map[string]string
}

KeyboardInteractiveAnswers is a set of answer to a keyboard-interactive challenge.

type KeyboardInteractiveAuthenticator

type KeyboardInteractiveAuthenticator interface {
	// KeyboardInteractive is a method to post a series of questions to the user and receive answers.
	KeyboardInteractive(
		metadata metadata.ConnectionAuthPendingMetadata,
		challenge func(
			instruction string,
			questions KeyboardInteractiveQuestions,
		) (answers KeyboardInteractiveAnswers, err error),
	) AuthenticationContext
}

KeyboardInteractiveAuthenticator is authenticates using a question-and-answer back and forth between the urlEncodedClient and the server.

func NewKeyboardInteractiveAuthenticator

func NewKeyboardInteractiveAuthenticator(
	cfg config.KeyboardInteractiveAuthConfig,
	logger log.Logger,
	metrics metrics.Collector,
) (KeyboardInteractiveAuthenticator, service.Service, error)

NewKeyboardInteractiveAuthenticator returns a keyboard-interactive authenticator as configured, and if needed a backing service that needs to run for the authentication to work. If keyboard-interactive authentication is disabled it returns nil. If the configuration is invalid an error is returned.

type KeyboardInteractiveQuestion

type KeyboardInteractiveQuestion struct {
	// ID is an optional opaque ID that can be used to identify a question in an answer. Can be left empty.
	ID string
	// Question is the question text sent to the user.
	Question string
	// EchoResponse should be set to true to show the typed response to the user.
	EchoResponse bool
}

KeyboardInteractiveQuestion contains a question issued to a user as part of the keyboard-interactive exchange.

type KeyboardInteractiveQuestions

type KeyboardInteractiveQuestions []KeyboardInteractiveQuestion

KeyboardInteractiveQuestions is a list of questions for keyboard-interactive authentication.

type OAuth2AuthorizationCodeFlow

type OAuth2AuthorizationCodeFlow interface {
	OAuth2Flow

	// GetAuthorizationURL returns the authorization URL a user should be redirected to begin the login process.
	GetAuthorizationURL(ctx context.Context) (string, error)

	// Verify verifies the authorizationCode with the OAuth2 server and obtains an access token. It may also return
	// metadata that can be exposed to the configuration server or the backend itself for further use.
	//
	// The implementation should retry obtaining the access token until ctx is canceled if the server
	// responds in an unexpected fashion.
	Verify(ctx context.Context, state string, authorizationCode string) (
		string,
		metadata.ConnectionAuthenticatedMetadata,
		error,
	)
}

type OAuth2Client

type OAuth2Client interface {
	KeyboardInteractiveAuthenticator
}

OAuth2Client is the urlEncodedClient supporting OAuth2-based authentication. It only supports keyboard-interactive authentication as that is the only method to output the login-link to the user.

type OAuth2DeviceFlow

type OAuth2DeviceFlow interface {
	OAuth2Flow

	// GetAuthorizationURL returns the authorization URL a user should be redirected to begin the login process.
	GetAuthorizationURL(ctx context.Context) (
		verificationLink string,
		userCode string,
		expiration time.Duration,
		err error,
	)

	// Verify starts polling the OAuth2 server if the authorization has been completed. The ctx parameter contains a
	// context that will be canceled when the urlEncodedClient disconnects.
	//
	// This method should return the access token, and additionally may also return a key-value map of parameters
	// to be passed to the configuration server.
	//
	// The method should return when the OAuth2 server either returns with a positive or negative
	// result. It should not return if the final result has not been obtained yet.
	Verify(ctx context.Context) (string, metadata.ConnectionAuthenticatedMetadata, error)
}

type OAuth2Flow

type OAuth2Flow interface {
	// Deauthorize contacts the OAuth2 server to deauthorize an access token.
	Deauthorize(ctx context.Context)
}

type OAuth2Provider

type OAuth2Provider interface {
	// SupportsDeviceFlow returns true if the provider supports authenticating via the device flow.
	SupportsDeviceFlow() bool
	// GetDeviceFlow returns the OAuth2DeviceFlow for a single urlEncodedClient used for performing a device flow
	// authorization with the OAuth2 server. The method must panic if the device flow is not supported.
	GetDeviceFlow(ctx context.Context, connectionMetadata metadata.ConnectionAuthPendingMetadata) (OAuth2DeviceFlow, error)

	// SupportsAuthorizationCodeFlow returns true if the provider supports the authorization code flow.
	SupportsAuthorizationCodeFlow() bool
	// GetAuthorizationCodeFlow returns the OAuth2AuthorizationCodeFlow for a single urlEncodedClient used for performing
	// authorization code flow authorization with the OAuth2 server. The method must panic if the device flow is not
	// supported.
	GetAuthorizationCodeFlow(ctx context.Context, connectionMetadata metadata.ConnectionAuthPendingMetadata) (OAuth2AuthorizationCodeFlow, error)
}

OAuth2Provider is an OAuth2 backing provider with a specific API implementation.

type PasswordAuthenticator

type PasswordAuthenticator interface {
	// Password authenticates with a password from the urlEncodedClient. The returned AuthenticationContext contains the results
	// of the authentication process.
	//
	// - username is the username the user entered in their SSH session on the urlEncodedClient side.
	// - password is the password the user entered when prompted for the password.
	// - connectionID is the identifier for the metadata
	Password(
		metadata metadata.ConnectionAuthPendingMetadata,
		password []byte,
	) AuthenticationContext
}

PasswordAuthenticator validates the password of a user.

func NewPasswordAuthenticator

func NewPasswordAuthenticator(
	cfg config.PasswordAuthConfig,
	logger log.Logger,
	metrics metrics.Collector,
) (PasswordAuthenticator, service.Service, error)

NewPasswordAuthenticator returns a password authenticator as configured, and if needed a backing service that needs to run for the authentication to work. If password authentication is disabled it returns nil. If the configuration is invalid an error is returned.

type PublicKeyAuthenticator

type PublicKeyAuthenticator interface {
	// PubKey authenticates with a public key from the urlEncodedClient. The returned AuthenticationContext contains the results
	// of the authentication process.
	PubKey(
		metadata metadata.ConnectionAuthPendingMetadata,
		pubKey auth.PublicKey,
	) AuthenticationContext
}

PublicKeyAuthenticator authenticates using an SSH public key.

func NewPublicKeyAuthenticator

func NewPublicKeyAuthenticator(
	cfg config.PublicKeyAuthConfig,
	logger log.Logger,
	metrics metrics.Collector,
) (PublicKeyAuthenticator, service.Service, error)

NewPublicKeyAuthenticator returns a public key authenticator as configured, and if needed a backing service that needs to run for the authentication to work. If public key authentication is disabled it returns nil. If the configuration is invalid an error is returned.

type WebhookClient

WebhookClient is a urlEncodedClient that authenticates using HTTP webhooks. It only supports password and public key authentication.

func NewWebhookClient

func NewWebhookClient(
	authType AuthenticationType,
	cfg config.AuthWebhookClientConfig,
	logger log.Logger,
	metrics metrics.Collector,
) (WebhookClient, error)

NewWebhookClient creates a new HTTP authentication urlEncodedClient.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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