1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00

Validate hostname starting from 1.24 API.

In order to keep a little bit of "sanity" on the API side, validate
hostname only starting from v1.24 API version.

Signed-off-by: Vincent Demeester <vincent@sbr.pm>
This commit is contained in:
Vincent Demeester 2016-07-06 09:13:59 +02:00
parent ad44f49470
commit 6daf3d2a78
No known key found for this signature in database
GPG key ID: 083CC6FD6EB699A3
13 changed files with 44 additions and 32 deletions

View file

@ -32,17 +32,17 @@ type copyBackend interface {
// stateBackend includes functions to implement to provide container state lifecycle functionality. // stateBackend includes functions to implement to provide container state lifecycle functionality.
type stateBackend interface { type stateBackend interface {
ContainerCreate(types.ContainerCreateConfig) (types.ContainerCreateResponse, error) ContainerCreate(config types.ContainerCreateConfig, validateHostname bool) (types.ContainerCreateResponse, error)
ContainerKill(name string, sig uint64) error ContainerKill(name string, sig uint64) error
ContainerPause(name string) error ContainerPause(name string) error
ContainerRename(oldName, newName string) error ContainerRename(oldName, newName string) error
ContainerResize(name string, height, width int) error ContainerResize(name string, height, width int) error
ContainerRestart(name string, seconds int) error ContainerRestart(name string, seconds int) error
ContainerRm(name string, config *types.ContainerRmConfig) error ContainerRm(name string, config *types.ContainerRmConfig) error
ContainerStart(name string, hostConfig *container.HostConfig) error ContainerStart(name string, hostConfig *container.HostConfig, validateHostname bool) error
ContainerStop(name string, seconds int) error ContainerStop(name string, seconds int) error
ContainerUnpause(name string) error ContainerUnpause(name string) error
ContainerUpdate(name string, hostConfig *container.HostConfig) ([]string, error) ContainerUpdate(name string, hostConfig *container.HostConfig, validateHostname bool) ([]string, error)
ContainerWait(name string, timeout time.Duration) (int, error) ContainerWait(name string, timeout time.Duration) (int, error)
} }

View file

@ -132,10 +132,10 @@ func (s *containerRouter) postContainersStart(ctx context.Context, w http.Respon
// including r.TransferEncoding // including r.TransferEncoding
// allow a nil body for backwards compatibility // allow a nil body for backwards compatibility
version := httputils.VersionFromContext(ctx)
var hostConfig *container.HostConfig var hostConfig *container.HostConfig
// A non-nil json object is at least 7 characters. // A non-nil json object is at least 7 characters.
if r.ContentLength > 7 || r.ContentLength == -1 { if r.ContentLength > 7 || r.ContentLength == -1 {
version := httputils.VersionFromContext(ctx)
if versions.GreaterThanOrEqualTo(version, "1.24") { if versions.GreaterThanOrEqualTo(version, "1.24") {
return validationError{fmt.Errorf("starting container with HostConfig was deprecated since v1.10 and removed in v1.12")} return validationError{fmt.Errorf("starting container with HostConfig was deprecated since v1.10 and removed in v1.12")}
} }
@ -151,7 +151,8 @@ func (s *containerRouter) postContainersStart(ctx context.Context, w http.Respon
hostConfig = c hostConfig = c
} }
if err := s.backend.ContainerStart(vars["name"], hostConfig); err != nil { validateHostname := versions.GreaterThanOrEqualTo(version, "1.24")
if err := s.backend.ContainerStart(vars["name"], hostConfig, validateHostname); err != nil {
return err return err
} }
w.WriteHeader(http.StatusNoContent) w.WriteHeader(http.StatusNoContent)
@ -311,6 +312,7 @@ func (s *containerRouter) postContainerUpdate(ctx context.Context, w http.Respon
return err return err
} }
version := httputils.VersionFromContext(ctx)
var updateConfig container.UpdateConfig var updateConfig container.UpdateConfig
decoder := json.NewDecoder(r.Body) decoder := json.NewDecoder(r.Body)
@ -324,7 +326,8 @@ func (s *containerRouter) postContainerUpdate(ctx context.Context, w http.Respon
} }
name := vars["name"] name := vars["name"]
warnings, err := s.backend.ContainerUpdate(name, hostConfig) validateHostname := versions.GreaterThanOrEqualTo(version, "1.24")
warnings, err := s.backend.ContainerUpdate(name, hostConfig, validateHostname)
if err != nil { if err != nil {
return err return err
} }
@ -351,13 +354,14 @@ func (s *containerRouter) postContainersCreate(ctx context.Context, w http.Respo
version := httputils.VersionFromContext(ctx) version := httputils.VersionFromContext(ctx)
adjustCPUShares := versions.LessThan(version, "1.19") adjustCPUShares := versions.LessThan(version, "1.19")
validateHostname := versions.GreaterThanOrEqualTo(version, "1.24")
ccr, err := s.backend.ContainerCreate(types.ContainerCreateConfig{ ccr, err := s.backend.ContainerCreate(types.ContainerCreateConfig{
Name: name, Name: name,
Config: config, Config: config,
HostConfig: hostConfig, HostConfig: hostConfig,
NetworkingConfig: networkingConfig, NetworkingConfig: networkingConfig,
AdjustCPUShares: adjustCPUShares, AdjustCPUShares: adjustCPUShares,
}) }, validateHostname)
if err != nil { if err != nil {
return err return err
} }

View file

@ -116,7 +116,7 @@ type Backend interface {
// ContainerAttachRaw attaches to container. // ContainerAttachRaw attaches to container.
ContainerAttachRaw(cID string, stdin io.ReadCloser, stdout, stderr io.Writer, stream bool) error ContainerAttachRaw(cID string, stdin io.ReadCloser, stdout, stderr io.Writer, stream bool) error
// ContainerCreate creates a new Docker container and returns potential warnings // ContainerCreate creates a new Docker container and returns potential warnings
ContainerCreate(types.ContainerCreateConfig) (types.ContainerCreateResponse, error) ContainerCreate(config types.ContainerCreateConfig, validateHostname bool) (types.ContainerCreateResponse, error)
// ContainerRm removes a container specified by `id`. // ContainerRm removes a container specified by `id`.
ContainerRm(name string, config *types.ContainerRmConfig) error ContainerRm(name string, config *types.ContainerRmConfig) error
// Commit creates a new Docker image from an existing Docker container. // Commit creates a new Docker image from an existing Docker container.
@ -124,7 +124,7 @@ type Backend interface {
// ContainerKill stops the container execution abruptly. // ContainerKill stops the container execution abruptly.
ContainerKill(containerID string, sig uint64) error ContainerKill(containerID string, sig uint64) error
// ContainerStart starts a new container // ContainerStart starts a new container
ContainerStart(containerID string, hostConfig *container.HostConfig) error ContainerStart(containerID string, hostConfig *container.HostConfig, validateHostname bool) error
// ContainerWait stops processing until the given container is stopped. // ContainerWait stops processing until the given container is stopped.
ContainerWait(containerID string, timeout time.Duration) (int, error) ContainerWait(containerID string, timeout time.Duration) (int, error)
// ContainerUpdateCmdOnBuild updates container.Path and container.Args // ContainerUpdateCmdOnBuild updates container.Path and container.Args

View file

@ -181,7 +181,7 @@ func (b *Builder) runContextCommand(args []string, allowRemote bool, allowLocalD
return nil return nil
} }
container, err := b.docker.ContainerCreate(types.ContainerCreateConfig{Config: b.runConfig}) container, err := b.docker.ContainerCreate(types.ContainerCreateConfig{Config: b.runConfig}, true)
if err != nil { if err != nil {
return err return err
} }
@ -508,7 +508,7 @@ func (b *Builder) create() (string, error) {
c, err := b.docker.ContainerCreate(types.ContainerCreateConfig{ c, err := b.docker.ContainerCreate(types.ContainerCreateConfig{
Config: b.runConfig, Config: b.runConfig,
HostConfig: hostConfig, HostConfig: hostConfig,
}) }, true)
if err != nil { if err != nil {
return "", err return "", err
} }
@ -552,7 +552,7 @@ func (b *Builder) run(cID string) (err error) {
} }
}() }()
if err := b.docker.ContainerStart(cID, nil); err != nil { if err := b.docker.ContainerStart(cID, nil, true); err != nil {
return err return err
} }

View file

@ -18,8 +18,8 @@ type Backend interface {
DeleteManagedNetwork(name string) error DeleteManagedNetwork(name string) error
SetupIngress(req clustertypes.NetworkCreateRequest, nodeIP string) error SetupIngress(req clustertypes.NetworkCreateRequest, nodeIP string) error
PullImage(ctx context.Context, image, tag string, metaHeaders map[string][]string, authConfig *types.AuthConfig, outStream io.Writer) error PullImage(ctx context.Context, image, tag string, metaHeaders map[string][]string, authConfig *types.AuthConfig, outStream io.Writer) error
CreateManagedContainer(types.ContainerCreateConfig) (types.ContainerCreateResponse, error) CreateManagedContainer(config types.ContainerCreateConfig, validateHostname bool) (types.ContainerCreateResponse, error)
ContainerStart(name string, hostConfig *container.HostConfig) error ContainerStart(name string, hostConfig *container.HostConfig, validateHostname bool) error
ContainerStop(name string, seconds int) error ContainerStop(name string, seconds int) error
ConnectContainerToNetwork(containerName, networkName string, endpointConfig *network.EndpointSettings) error ConnectContainerToNetwork(containerName, networkName string, endpointConfig *network.EndpointSettings) error
UpdateContainerServiceConfig(containerName string, serviceConfig *clustertypes.ServiceConfig) error UpdateContainerServiceConfig(containerName string, serviceConfig *clustertypes.ServiceConfig) error

View file

@ -9,8 +9,10 @@ import (
"syscall" "syscall"
"github.com/Sirupsen/logrus" "github.com/Sirupsen/logrus"
"github.com/docker/docker/api/server/httputils"
executorpkg "github.com/docker/docker/daemon/cluster/executor" executorpkg "github.com/docker/docker/daemon/cluster/executor"
"github.com/docker/engine-api/types" "github.com/docker/engine-api/types"
"github.com/docker/engine-api/types/versions"
"github.com/docker/libnetwork" "github.com/docker/libnetwork"
"github.com/docker/swarmkit/api" "github.com/docker/swarmkit/api"
"github.com/docker/swarmkit/log" "github.com/docker/swarmkit/log"
@ -115,13 +117,16 @@ func (c *containerAdapter) removeNetworks(ctx context.Context) error {
func (c *containerAdapter) create(ctx context.Context, backend executorpkg.Backend) error { func (c *containerAdapter) create(ctx context.Context, backend executorpkg.Backend) error {
var cr types.ContainerCreateResponse var cr types.ContainerCreateResponse
var err error var err error
version := httputils.VersionFromContext(ctx)
validateHostname := versions.GreaterThanOrEqualTo(version, "1.24")
if cr, err = backend.CreateManagedContainer(types.ContainerCreateConfig{ if cr, err = backend.CreateManagedContainer(types.ContainerCreateConfig{
Name: c.container.name(), Name: c.container.name(),
Config: c.container.config(), Config: c.container.config(),
HostConfig: c.container.hostConfig(), HostConfig: c.container.hostConfig(),
// Use the first network in container create // Use the first network in container create
NetworkingConfig: c.container.createNetworkingConfig(), NetworkingConfig: c.container.createNetworkingConfig(),
}); err != nil { }, validateHostname); err != nil {
return err return err
} }
@ -145,7 +150,9 @@ func (c *containerAdapter) create(ctx context.Context, backend executorpkg.Backe
} }
func (c *containerAdapter) start(ctx context.Context) error { func (c *containerAdapter) start(ctx context.Context) error {
return c.backend.ContainerStart(c.container.name(), nil) version := httputils.VersionFromContext(ctx)
validateHostname := versions.GreaterThanOrEqualTo(version, "1.24")
return c.backend.ContainerStart(c.container.name(), nil, validateHostname)
} }
func (c *containerAdapter) inspect(ctx context.Context) (types.ContainerJSON, error) { func (c *containerAdapter) inspect(ctx context.Context) (types.ContainerJSON, error) {

View file

@ -203,7 +203,7 @@ func (daemon *Daemon) setHostConfig(container *container.Container, hostConfig *
// verifyContainerSettings performs validation of the hostconfig and config // verifyContainerSettings performs validation of the hostconfig and config
// structures. // structures.
func (daemon *Daemon) verifyContainerSettings(hostConfig *containertypes.HostConfig, config *containertypes.Config, update bool) ([]string, error) { func (daemon *Daemon) verifyContainerSettings(hostConfig *containertypes.HostConfig, config *containertypes.Config, update bool, validateHostname bool) ([]string, error) {
// First perform verification of settings common across all platforms. // First perform verification of settings common across all platforms.
if config != nil { if config != nil {
@ -222,10 +222,10 @@ func (daemon *Daemon) verifyContainerSettings(hostConfig *containertypes.HostCon
} }
// Validate if the given hostname is RFC 1123 (https://tools.ietf.org/html/rfc1123) compliant. // Validate if the given hostname is RFC 1123 (https://tools.ietf.org/html/rfc1123) compliant.
if len(config.Hostname) > 0 { if validateHostname && len(config.Hostname) > 0 {
// RFC1123 specifies that 63 bytes is the maximium length // RFC1123 specifies that 63 bytes is the maximium length
// Windows has the limitation of 63 bytes in length // Windows has the limitation of 63 bytes in length
// Linux hostname is limited to HOST_NAME_MAX=64, not not including the terminating null byte. // Linux hostname is limited to HOST_NAME_MAX=64, not including the terminating null byte.
// We limit the length to 63 bytes here to match RFC1035 and RFC1123. // We limit the length to 63 bytes here to match RFC1035 and RFC1123.
matched, _ := regexp.MatchString("^(([[:alnum:]]|[[:alnum:]][[:alnum:]\\-]*[[:alnum:]])\\.)*([[:alnum:]]|[[:alnum:]][[:alnum:]\\-]*[[:alnum:]])$", config.Hostname) matched, _ := regexp.MatchString("^(([[:alnum:]]|[[:alnum:]][[:alnum:]\\-]*[[:alnum:]])\\.)*([[:alnum:]]|[[:alnum:]][[:alnum:]\\-]*[[:alnum:]])$", config.Hostname)
if len(config.Hostname) > 63 || !matched { if len(config.Hostname) > 63 || !matched {

View file

@ -20,21 +20,21 @@ import (
) )
// CreateManagedContainer creates a container that is managed by a Service // CreateManagedContainer creates a container that is managed by a Service
func (daemon *Daemon) CreateManagedContainer(params types.ContainerCreateConfig) (types.ContainerCreateResponse, error) { func (daemon *Daemon) CreateManagedContainer(params types.ContainerCreateConfig, validateHostname bool) (types.ContainerCreateResponse, error) {
return daemon.containerCreate(params, true) return daemon.containerCreate(params, true, validateHostname)
} }
// ContainerCreate creates a regular container // ContainerCreate creates a regular container
func (daemon *Daemon) ContainerCreate(params types.ContainerCreateConfig) (types.ContainerCreateResponse, error) { func (daemon *Daemon) ContainerCreate(params types.ContainerCreateConfig, validateHostname bool) (types.ContainerCreateResponse, error) {
return daemon.containerCreate(params, false) return daemon.containerCreate(params, false, validateHostname)
} }
func (daemon *Daemon) containerCreate(params types.ContainerCreateConfig, managed bool) (types.ContainerCreateResponse, error) { func (daemon *Daemon) containerCreate(params types.ContainerCreateConfig, managed bool, validateHostname bool) (types.ContainerCreateResponse, error) {
if params.Config == nil { if params.Config == nil {
return types.ContainerCreateResponse{}, fmt.Errorf("Config cannot be empty in order to create a container") return types.ContainerCreateResponse{}, fmt.Errorf("Config cannot be empty in order to create a container")
} }
warnings, err := daemon.verifyContainerSettings(params.HostConfig, params.Config, false) warnings, err := daemon.verifyContainerSettings(params.HostConfig, params.Config, false, validateHostname)
if err != nil { if err != nil {
return types.ContainerCreateResponse{Warnings: warnings}, err return types.ContainerCreateResponse{Warnings: warnings}, err
} }

View file

@ -18,7 +18,7 @@ import (
) )
// ContainerStart starts a container. // ContainerStart starts a container.
func (daemon *Daemon) ContainerStart(name string, hostConfig *containertypes.HostConfig) error { func (daemon *Daemon) ContainerStart(name string, hostConfig *containertypes.HostConfig, validateHostname bool) error {
container, err := daemon.GetContainer(name) container, err := daemon.GetContainer(name)
if err != nil { if err != nil {
return err return err
@ -68,7 +68,7 @@ func (daemon *Daemon) ContainerStart(name string, hostConfig *containertypes.Hos
// check if hostConfig is in line with the current system settings. // check if hostConfig is in line with the current system settings.
// It may happen cgroups are umounted or the like. // It may happen cgroups are umounted or the like.
if _, err = daemon.verifyContainerSettings(container.HostConfig, nil, false); err != nil { if _, err = daemon.verifyContainerSettings(container.HostConfig, nil, false, validateHostname); err != nil {
return err return err
} }
// Adapt for old containers in case we have updates in this function and // Adapt for old containers in case we have updates in this function and

View file

@ -7,10 +7,10 @@ import (
) )
// ContainerUpdate updates configuration of the container // ContainerUpdate updates configuration of the container
func (daemon *Daemon) ContainerUpdate(name string, hostConfig *container.HostConfig) ([]string, error) { func (daemon *Daemon) ContainerUpdate(name string, hostConfig *container.HostConfig, validateHostname bool) ([]string, error) {
var warnings []string var warnings []string
warnings, err := daemon.verifyContainerSettings(hostConfig, nil, true) warnings, err := daemon.verifyContainerSettings(hostConfig, nil, true, validateHostname)
if err != nil { if err != nil {
return warnings, err return warnings, err
} }

View file

@ -133,9 +133,10 @@ This section lists each version from latest to oldest. Each listing includes a
* `POST /containers/{name:.*}/copy` is now removed and errors out starting from this API version. * `POST /containers/{name:.*}/copy` is now removed and errors out starting from this API version.
* API errors are now returned as JSON instead of plain text. * API errors are now returned as JSON instead of plain text.
* `POST /containers/create` and `POST /containers/(id)/start` allow you to configure kernel parameters (sysctls) for use in the container. * `POST /containers/create` and `POST /containers/(id)/start` allow you to configure kernel parameters (sysctls) for use in the container.
* `POST /v1.23/containers/<container ID>/exec` and `POST /v1.23/exec/<exec ID>/start` * `POST /containers/<container ID>/exec` and `POST /exec/<exec ID>/start`
no longer expects a "Container" field to be present. This property was not used no longer expects a "Container" field to be present. This property was not used
and is no longer sent by the docker client. and is no longer sent by the docker client.
* `POST /containers/create/` now validates the hostname (should be a valid RFC 1123 hostname).
### v1.23 API changes ### v1.23 API changes

View file

@ -361,7 +361,7 @@ Create a container
**JSON parameters**: **JSON parameters**:
- **Hostname** - A string value containing the hostname to use for the - **Hostname** - A string value containing the hostname to use for the
container. container. This must be a valid RFC 1123 hostname.
- **Domainname** - A string value containing the domain name to use - **Domainname** - A string value containing the domain name to use
for the container. for the container.
- **User** - A string value specifying the user inside the container. - **User** - A string value specifying the user inside the container.

View file

@ -362,7 +362,7 @@ Create a container
**JSON parameters**: **JSON parameters**:
- **Hostname** - A string value containing the hostname to use for the - **Hostname** - A string value containing the hostname to use for the
container. container. This must be a valid RFC 1123 hostname.
- **Domainname** - A string value containing the domain name to use - **Domainname** - A string value containing the domain name to use
for the container. for the container.
- **User** - A string value specifying the user inside the container. - **User** - A string value specifying the user inside the container.