mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Add warning if REST API is accessible through an insecure connection
The remote API allows full privilege escalation and is equivalent to having root access on the host. Because of this, the API should never be accessible through an insecure connection (TCP without TLS, or TCP without TLS verification). Although a warning is already logged on startup if the daemon uses an insecure configuration, this warning is not very visible (unless someone decides to read the logs). This patch attempts to make insecure configuration more visible by sending back warnings through the API (which will be printed when using `docker info`). Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
parent
2629fe9326
commit
547b993e07
2 changed files with 51 additions and 0 deletions
|
@ -68,6 +68,7 @@ func (daemon *Daemon) SystemInfo() (*types.Info, error) {
|
|||
Isolation: daemon.defaultIsolation,
|
||||
}
|
||||
|
||||
daemon.fillAPIInfo(v)
|
||||
// Retrieve platform specific info
|
||||
daemon.fillPlatformInfo(v, sysInfo)
|
||||
daemon.fillDriverInfo(v)
|
||||
|
@ -171,6 +172,32 @@ func (daemon *Daemon) fillSecurityOptions(v *types.Info, sysInfo *sysinfo.SysInf
|
|||
v.SecurityOptions = securityOptions
|
||||
}
|
||||
|
||||
func (daemon *Daemon) fillAPIInfo(v *types.Info) {
|
||||
const warn string = `
|
||||
Access to the remote API is equivalent to root access on the host. Refer
|
||||
to the 'Docker daemon attack surface' section in the documentation for
|
||||
more information: https://docs.docker.com/engine/security/security/#docker-daemon-attack-surface`
|
||||
|
||||
cfg := daemon.configStore
|
||||
for _, host := range cfg.Hosts {
|
||||
// cnf.Hosts is normalized during startup, so should always have a scheme/proto
|
||||
h := strings.SplitN(host, "://", 2)
|
||||
proto := h[0]
|
||||
addr := h[1]
|
||||
if proto != "tcp" {
|
||||
continue
|
||||
}
|
||||
if !cfg.TLS {
|
||||
v.Warnings = append(v.Warnings, fmt.Sprintf("WARNING: API is accessible on http://%s without encryption.%s", addr, warn))
|
||||
continue
|
||||
}
|
||||
if !cfg.TLSVerify {
|
||||
v.Warnings = append(v.Warnings, fmt.Sprintf("WARNING: API is accessible on https://%s without TLS client verification.%s", addr, warn))
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func hostName() string {
|
||||
hostname := ""
|
||||
if hn, err := os.Hostname(); err != nil {
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/docker/internal/test/daemon"
|
||||
"github.com/docker/docker/internal/test/request"
|
||||
"gotest.tools/assert"
|
||||
is "gotest.tools/assert/cmp"
|
||||
|
@ -40,3 +41,26 @@ func TestInfoAPI(t *testing.T) {
|
|||
assert.Check(t, is.Contains(out, linePrefix))
|
||||
}
|
||||
}
|
||||
|
||||
func TestInfoAPIWarnings(t *testing.T) {
|
||||
d := daemon.New(t)
|
||||
|
||||
client, err := d.NewClient()
|
||||
assert.NilError(t, err)
|
||||
|
||||
d.StartWithBusybox(t, "--iptables=false", "-H=0.0.0.0:23756", "-H=unix://"+d.Sock())
|
||||
defer d.Stop(t)
|
||||
|
||||
info, err := client.Info(context.Background())
|
||||
assert.NilError(t, err)
|
||||
|
||||
stringsToCheck := []string{
|
||||
"Access to the remote API is equivalent to root access",
|
||||
"http://0.0.0.0:23756",
|
||||
}
|
||||
|
||||
out := fmt.Sprintf("%+v", info)
|
||||
for _, linePrefix := range stringsToCheck {
|
||||
assert.Check(t, is.Contains(out, linePrefix))
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue