docker

package module
v0.9.9 Latest Latest
Warning

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

Go to latest
Published: Feb 28, 2021 License: MIT Imports: 29 Imported by: 2

README

ContainerSSH - Launch Containers on Demand

ContainerSSH Docker Backend Library

Go Report Card LGTM Alerts

This library implements a backend that connects to a Docker socket and launches a new container for each connection, then runs executes a separate command per channel using docker exec. It replaces the legacy dockerrun backend.

⚠⚠⚠ Warning: This is a developer documentation. ⚠⚠⚠
The user documentation for ContainerSSH is located at containerssh.io.

Using this library

This library implements a NetworkConnectionHandler from the sshserver library. This can be embedded into a connection handler.

The network connection handler can be created with the New() method:

var client net.TCPAddr
connectionID := "0123456789ABCDEF"
config := docker.Config{
    //...
}
collector := metrics.New
dr, err := docker.New(
    client,
    connectionID,
    config,
    logger,
)
if err != nil {
    // Handle error
}

The logger parameter is a logger from the ContainerSSH logger library.

The dr variable can then be used to create a container on finished handshake:

ssh, err := dr.OnHandshakeSuccess("provided-connection-username")

Conversely, on disconnect you must call dr.OnDisconnect(). The ssh variable can then be used to create session channels:

var channelID uint64 = 0
extraData := []byte{}
session, err := ssh.OnSessionChannel(channelID, extraData)

Finally, the session can be used to launch programs:

var requestID uint64 = 0
err = session.OnEnvRequest(requestID, "foo", "bar")
// ...
requestID = 1
var stdin io.Reader
var stdout, stderr io.Writer
err = session.OnShell(
    requestID,
    stdin,
    stdout,
    stderr,
    func(exitStatus ExitStatus) {
        // ...
    },
)

Operating modes

This library supports several operating modes:

  • connection creates a container per connection and uses the docker exec mechanism to launch SSH programs inside the container. This mode ignores the CMD of the container image and uses the idleProgram setting to launch inside the container.
  • session creates a container per session and potentially results in multiple containers for a single SSH connection. This mode uses the CMD of the container image or from the configuration.

Documentation

Index

Constants

View Source
const (
	// The ContainerSSH Docker module failed to read from the ContainerSSH agent. This is most likely because the
	// ContainerSSH guest agent is not present in the guest image, but agent support is enabled.
	EFailedAgentRead = "DOCKER_AGENT_READ_FAILED"
	// The ContainerSSH Docker module attempted to close the output (stdout and stderr) for writing but failed to do so.
	EFailedOutputCloseWriting = "DOCKER_CLOSE_OUTPUT_FAILED"
	// The ContainerSSH Docker module attempted to close the input (stdin) for reading but failed to do so.
	EFailedInputCloseWriting = "DOCKER_CLOSE_INPUT_FAILED"
	// The ContainerSSH Docker module detected a configuration error. Please check your configuration.
	EConfigError = "DOCKER_CONFIG_ERROR"
	// The ContainerSSH Docker module is attaching to a container in session mode.
	MContainerAttach = "DOCKER_CONTAINER_ATTACH"
	// The ContainerSSH Docker module has failed to attach to a container in session mode.
	EFailedContainerAttach = "DOCKER_CONTAINER_ATTACH_FAILED"
	// ContainerSSH is creating a container.
	MContainerCreate = "DOCKER_CONTAINER_CREATE"
	// ContainerSSH failed to create a container. This may be a temporary and retried or a permanent error message.
	// Check the log message for details.
	EFailedContainerCreate = "DOCKER_CONTAINER_CREATE_FAILED"
	// ContainerSSH is starting the previously-created container.
	MContainerStart = "DOCKER_CONTAINER_START"
	// Starting the container failed. This message can either be temporary and retried or permanent. Check the log
	// message for details.
	EFailedContainerStart = "DOCKER_CONTAINER_START_FAILED"
	// ContainerSSH is stopping the container.
	MContainerStop = "DOCKER_CONTAINER_STOP"
	// ContainerSSH failed to stop the container. This message can be either temporary and retried or permanent. Check
	// the log message for details.
	EContainerStopFailed = "DOCKER_CONTAINER_STOP_FAILED"
	// The ContainerSSH Docker module os removing the container.
	MContainerRemove = "DOCKER_CONTAINER_REMOVE"
	// The ContainerSSH Docker module could not remove the container. This message may be temporary and retried or
	// permanent. Check the log message for details.
	EFailedContainerRemove = "DOCKER_CONTAINER_REMOVE_FAILED"
	// The ContainerSSH Docker module has successfully removed the container.
	MContainerRemoveSuccessful = "DOCKER_CONTAINER_REMOVE_SUCCESSFUL"
	// The ContainerSSH Docker module is sending a signal to the container.
	MContainerSignal = "DOCKER_CONTAINER_SIGNAL"
	// The ContainerSSH Docker module has failed to send a signal to the container.
	EFailedContainerSignal = "DOCKER_CONTAINER_SIGNAL_FAILED"
	// The ContainerSSH Docker module is shutting down a container.
	EShuttingDown = "DOCKER_CONTAINER_SHUTTING_DOWN"
	// The ContainerSSH Docker module is creating an execution. This may be in connection mode, or it may be the module
	// internally using the exec mechanism to deliver a payload into the container.
	MExec = "DOCKER_EXEC"
	// The ContainerSSH Docker module is attaching to the previously-created execution.
	MExecAttach = "DOCKER_EXEC_ATTACH"
	// The ContainerSSH Docker module could not attach to the previously-created execution.
	EFailedExecAttach = "DOCKER_EXEC_ATTACH_FAILED"
	// The ContainerSSH Docker module is creating an execution.
	MExecCreate = "DOCKER_EXEC_CREATE"
	// The ContainerSSH Docker module has failed to create an execution. This can be temporary and retried or permanent.
	// See the error message for details.
	EFailedExecCreate = "DOCKER_EXEC_CREATE_FAILED"
	// The ContainerSSH Docker module has failed to read the process ID from the ContainerSSH guest agent. This is most
	// likely because the guest image does not contain the guest agent, but guest agent support has been enabled.
	EFailedPIDRead = "DOCKER_EXEC_PID_READ_FAILED"
	// The ContainerSSH Docker module is resizing the console.
	MResizing = "DOCKER_EXEC_RESIZE"
	// The ContainerSSH Docker module failed to resize the console.
	EFailedResize = "DOCKER_EXEC_RESIZE_FAILED"
	// The ContainerSSH Docker module is delivering a signal in container mode.
	MExecSignal = "DOCKER_EXEC_SIGNAL"
	// The ContainerSSH Docker module failed to deliver a signal.
	EFailedExecSignal = "DOCKER_EXEC_SIGNAL_FAILED"
	// The ContainerSSH Docker module failed to deliver a signal because guest agent support is disabled.
	ECannotSendSignalNoAgent = "DOCKER_EXEC_SIGNAL_FAILED_NO_AGENT"
	// The ContainerSSH Docker module successfully delivered the requested signal.
	MExecSignalSuccessful = "DOCKER_EXEC_SIGNAL_SUCCESSFUL"
	// The ContainerSSH Docker module is fetching the exit code from the program.
	MExitCode = "DOCKER_EXIT_CODE"
	// The ContainerSSH Docker module could not fetch the exit code from the program because the container is
	// restarting. This is typically a misconfiguration as ContainerSSH containers should not automatically restart.
	EContainerRestarting = "DOCKER_EXIT_CODE_CONTAINER_RESTARTING"
	// The ContainerSSH Docker module has failed to fetch the exit code of the program.
	EFetchingExitCodeFailed = "DOCKER_EXIT_CODE_FAILED"
	// The ContainerSSH Docker module has received a negative exit code from Docker. This should never happen and is
	// most likely a bug.
	ENegativeExitCode = "DOCKER_EXIT_CODE_NEGATIVE"
	// The ContainerSSH Docker module could not fetch the program exit code because the program is still running.
	// This error may be temporary and retried or permanent.
	EStillRunning = "DOCKER_EXIT_CODE_STILL_RUNNING"
	// The ContainerSSH Docker module is listing the locally present container images to determine if the specified
	// container image needs to be pulled.
	MImageList = "DOCKER_IMAGE_LISTING"
	// The ContainerSSH Docker module failed to list the images present in the local Docker daemon. This is used to
	// determine if the image needs to be pulled. This can be because the Docker daemon is not reachable, the
	// certificate is invalid, or there is something else interfering with listing the images.
	EFailedImageList = "DOCKER_IMAGE_LISTING_FAILED"
	// The ContainerSSH Docker module is pulling the container image.
	MImagePull = "DOCKER_IMAGE_PULL"
	// ContainerSSH failed to pull the specified container image. This can be because of connection issues to the Docker
	// daemon, or because the Docker daemon itself can't pull the image. If you don't intend to have the image pulled
	// you should set the `ImagePullPolicy` to `Never`. See the
	// [Docker documentation](https://containerssh.io/reference/upcoming/docker) for details.
	EFailedImagePull = "DOCKER_IMAGE_PULL_FAILED"
	// The ContainerSSH Docker module is checking if an image pull is needed.
	MImagePullNeeded = "DOCKER_IMAGE_PULL_NEEDED_CHECKING"
	// The ContainerSSH Docker module can't execute the request because the program is already running. This is a client
	// error.
	EProgramAlreadyRunning = "DOCKER_PROGRAM_ALREADY_RUNNING"
	// The ContainerSSH Docker module can't deliver a signal because no PID has been recorded. This is most likely
	// because guest agent support is disabled.
	EFailedSignalNoPID = "DOCKER_SIGNAL_FAILED_NO_PID"
	// The ContainerSSH Docker module failed to stream stdin to the Docker engine.
	EFailedInputStream = "DOCKER_STREAM_INPUT_FAILED"
	// The ContainerSSH Docker module failed to stream stdout and stderr from the Docker engine.
	EFailedOutputStream = "DOCKER_STREAM_OUTPUT_FAILED"
	// The ContainerSSH Docker module is not configured to run the requested subsystem.
	ESubsystemNotSupported = "DOCKER_SUBSYSTEM_NOT_SUPPORTED"
)
View Source
const (
	UserMessageInitializeSSHSession = "Failed to initialize SSH session."
)

Variables

This section is empty.

Functions

func New

func New(
	client net.TCPAddr,
	connectionID string,
	config Config,
	logger log.Logger,
	backendRequestsMetric metrics.SimpleCounter,
	backendFailuresMetric metrics.SimpleCounter,
) (
	sshserver.NetworkConnectionHandler,
	error,
)

New creates a new NetworkConnectionHandler for a specific client.

func NewDockerRun

func NewDockerRun(
	client net.TCPAddr,
	connectionID string,
	legacyConfig DockerRunConfig,
	logger log.Logger,
	backendRequestsMetric metrics.SimpleCounter,
	backendFailuresMetric metrics.SimpleCounter,
) (sshserver.NetworkConnectionHandler, error)

NewDockerRun creates a new NetworkConnectionHandler based on the deprecated "dockerrun" config structure. Deprecated: use New instead

Types

type Config

type Config struct {
	// Connection configures how to connect to dockerd
	Connection ConnectionConfig `json:"connection" yaml:"connection"`
	// Execution drives how the container and the workload is executed
	Execution ExecutionConfig `json:"execution" yaml:"execution"`
	// Timeouts configures the various timeouts when interacting with dockerd.
	Timeouts TimeoutConfig `json:"timeouts" yaml:"timeouts"`
}

Config is the base configuration structure of the DockerRun backend.

func (Config) Validate

func (c Config) Validate() error

Validate validates the provided configuration and returns an error if invalid.

type ConnectionConfig

type ConnectionConfig struct {
	// Host is the docker connect URL
	Host string `json:"host" yaml:"host" default:"unix:///var/run/docker.sock"`
	// CaCert is the CA certificate for Docker connection embedded in the configuration in PEM format.
	CaCert string `json:"cacert" yaml:"cacert"`
	// Cert is the client certificate in PEM format embedded in the configuration.
	Cert string `json:"cert" yaml:"cert"`
	// Key is the client key in PEM format embedded in the configuration.
	Key string `json:"key" yaml:"key"`
}

ConnectionConfig configures how to connect to dockerd.

func (ConnectionConfig) Validate

func (c ConnectionConfig) Validate() error

type DockerRunConfig

type DockerRunConfig struct {
	Host   string                   `json:"host" yaml:"host" comment:"Docker connect URL" default:"unix:///var/run/docker.sock"`
	CaCert string                   `json:"cacert" yaml:"cacert" comment:"CA certificate for Docker connection embedded in the configuration in PEM format."`
	Cert   string                   `json:"cert" yaml:"cert" comment:"Client certificate in PEM format embedded in the configuration."`
	Key    string                   `json:"key" yaml:"key" comment:"Client key in PEM format embedded in the configuration."`
	Config DockerRunContainerConfig `json:"config" yaml:"config" comment:"Config configuration"`
}

DockerRunConfig describes the old ContainerSSH 0.3 configuration format that can still be read and used. Deprecated: Switch to the more generic "docker" backend.

func (DockerRunConfig) Validate added in v0.9.6

func (config DockerRunConfig) Validate() error

Validate validates the docker run config

type DockerRunContainerConfig deprecated

type DockerRunContainerConfig struct {
	LaunchConfig   `json:",inline" yaml:",inline"`
	Subsystems     map[string]string `` /* 133-byte string literal not displayed */
	DisableCommand bool              `json:"disableCommand" yaml:"disableCommand" comment:"Disable command execution passed from SSH"`
	Timeout        time.Duration     `json:"timeout" yaml:"timeout" comment:"Timeout for pod creation" default:"60s"`
}

Deprecated: Switch to the more generic "docker" backend.

func (*DockerRunContainerConfig) UnmarshalJSON added in v0.9.2

func (d *DockerRunContainerConfig) UnmarshalJSON(b []byte) error

func (*DockerRunContainerConfig) UnmarshalYAML added in v0.9.2

func (d *DockerRunContainerConfig) UnmarshalYAML(unmarshal func(interface{}) error) error

func (*DockerRunContainerConfig) Validate added in v0.9.6

func (d *DockerRunContainerConfig) Validate() error

Validate validates the container config

type ExecutionConfig

type ExecutionConfig struct {
	// Launch contains the Docker-specific launch configuration.
	Launch LaunchConfig `json:",inline" yaml:",inline"`
	// Mode influences how commands are executed.
	//
	// - If ExecutionModeConnection is chosen (default) a new container is launched per connection. In this mode
	//   sessions are executed using the "docker exec" functionality and the main container console runs a script that
	//   waits for a termination signal.
	// - If ExecutionModeSession is chosen a new container is launched per session, leading to potentially multiple
	//   containers per connection. In this mode the program is launched directly as the main process of the container.
	//   When configuring this mode you should explicitly configure the "cmd" option to an empty list if you want the
	//   default command in the container to launch.
	Mode ExecutionMode `json:"mode" yaml:"mode" default:"connection"`

	// IdleCommand is the command that runs as the first process in the container in ExecutionModeConnection. Ignored in ExecutionModeSession.
	IdleCommand []string `` /* 191-byte string literal not displayed */
	// ShellCommand is the command used for launching shells when the container is in ExecutionModeConnection. Ignored in ExecutionModeSession.
	ShellCommand []string `json:"shellCommand" yaml:"shellCommand" comment:"Run this command as a default shell." default:"[\"/bin/bash\"]"`
	// AgentPath contains the path to the ContainerSSH Guest Agent.
	AgentPath string `json:"agentPath" yaml:"agentPath" default:"/usr/bin/containerssh-agent"`
	// DisableAgent enables using the ContainerSSH Guest Agent.
	DisableAgent bool `json:"disableAgent" yaml:"disableAgent"`
	// Subsystems contains a map of subsystem names and their corresponding binaries in the container.
	Subsystems map[string]string `` /* 133-byte string literal not displayed */

	// ImagePullPolicy controls when to pull container images.
	ImagePullPolicy ImagePullPolicy `json:"imagePullPolicy" yaml:"imagePullPolicy" comment:"Image pull policy" default:"IfNotPresent"`
	// contains filtered or unexported fields
}

ExecutionConfig contains the configuration of what container to run in Docker.

func (ExecutionConfig) Validate

func (c ExecutionConfig) Validate() error

Validate validates the docker config structure.

type ExecutionMode

type ExecutionMode string

ExecutionMode determines when a container is launched. ExecutionModeConnection launches one container per SSH connection (default), while ExecutionModeSession launches one container per SSH session.

const (
	// ExecutionModeConnection launches one container per SSH connection.
	ExecutionModeConnection ExecutionMode = "connection"
	// ExecutionModeSession launches one container per SSH session (multiple containers per connection).
	ExecutionModeSession ExecutionMode = "session"
)

func (ExecutionMode) Validate

func (e ExecutionMode) Validate() error

Validate validates the execution config.

type ImagePullPolicy

type ImagePullPolicy string

ImagePullPolicy drives how and when images are pulled. The values are closely aligned with the Kubernetes image pull policy.

  • ImagePullPolicyAlways means that the container image will be pulled on every connection.
  • ImagePullPolicyIfNotPresent means the image will be pulled if the image is not present locally, an empty tag, or the "latest" tag was specified.
  • ImagePullPolicyNever means that the image will be never pulled, and if the image is not available locally the connection will fail.
const (
	// ImagePullPolicyAlways means that the container image will be pulled on every connection.
	ImagePullPolicyAlways ImagePullPolicy = "Always"
	// ImagePullPolicyIfNotPresent means the image will be pulled if the image is not present locally, an empty tag, or
	// the "latest" tag was specified.
	ImagePullPolicyIfNotPresent ImagePullPolicy = "IfNotPresent"
	// ImagePullPolicyNever means that the image will be never pulled, and if the image is not available locally the
	// connection will fail.
	ImagePullPolicyNever ImagePullPolicy = "Never"
)

func (ImagePullPolicy) Validate

func (p ImagePullPolicy) Validate() error

Validate checks if the given image pull policy is valid.

type LaunchConfig

type LaunchConfig struct {
	// ContainerConfig contains container-specific configuration options.
	ContainerConfig *container.Config `` /* 129-byte string literal not displayed */
	// HostConfig contains the host-specific configuration options.
	HostConfig *container.HostConfig `json:"host" yaml:"host" comment:"Host configuration"`
	// NetworkConfig contains the network settings.
	NetworkConfig *network.NetworkingConfig `json:"network" yaml:"network" comment:"Network configuration"`
	// Platform contains the platform specification.
	Platform *specs.Platform `json:"platform" yaml:"platform" comment:"Platform specification"`
	// ContainerName is the name of the container to launch. It is recommended to leave this empty, otherwise
	// ContainerSSH may not be able to start the container if a container with the same name already exists.
	ContainerName string `json:"containername" yaml:"containername" comment:"Name for the container to be launched"`
}

LaunchConfig contains the container configuration for the Docker client version 20.

func (*LaunchConfig) UnmarshalJSON

func (l *LaunchConfig) UnmarshalJSON(b []byte) error

UnmarshalJSON implements the special unmarshalling of the LaunchConfig that ignores unknown fields. This is needed because Docker treats removing fields as backwards-compatible. See https://github.com/moby/moby/pull/39158#issuecomment-489704731

func (*LaunchConfig) UnmarshalYAML

func (l *LaunchConfig) UnmarshalYAML(unmarshal func(interface{}) error) error

UnmarshalYAML implements the special unmarshalling of the LaunchConfig that ignores unknown fields. This is needed because Docker treats removing fields as backwards-compatible. See https://github.com/moby/moby/pull/39158#issuecomment-489704731

func (*LaunchConfig) Validate added in v0.9.6

func (l *LaunchConfig) Validate() error

Validate validates the launch configuration.

type TimeoutConfig

type TimeoutConfig struct {
	// ContainerStart is the maximum time starting a container may take.
	ContainerStart time.Duration `json:"containerStart" yaml:"containerStart" default:"60s"`
	// ContainerStop is the maximum time to wait for a container to stop. This should always be set higher than the Docker StopTimeout.
	ContainerStop time.Duration `json:"containerStop" yaml:"containerStop" default:"60s"`
	// CommandStart sets the maximum time starting a command may take.
	CommandStart time.Duration `json:"commandStart" yaml:"commandStart" default:"60s"`
	// Signal sets the maximum time sending a signal may take.
	Signal time.Duration `json:"signal" yaml:"signal" default:"60s"`
	// Signal sets the maximum time setting the window size may take.
	Window time.Duration `json:"window" yaml:"window" default:"60s"`
	// HTTP
	HTTP time.Duration `json:"http" yaml:"http" default:"15s"`
}

TimeoutConfig drives the various timeouts in the Docker backend.

func (*TimeoutConfig) UnmarshalJSON added in v0.9.2

func (t *TimeoutConfig) UnmarshalJSON(b []byte) error

UnmarshalJSON takes a JSON byte array and unmarshalls it into a structure.

func (*TimeoutConfig) UnmarshalYAML added in v0.9.2

func (t *TimeoutConfig) UnmarshalYAML(unmarshal func(interface{}) error) error

UnmarshalYAML takes a YAML byte array and unmarshalls it into a structure.

Jump to

Keyboard shortcuts

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