|
@@ -68,6 +68,7 @@ func (daemon *Daemon) SystemInfo() (*types.Info, error) {
|
|
Isolation: daemon.defaultIsolation,
|
|
Isolation: daemon.defaultIsolation,
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ daemon.fillAPIInfo(v)
|
|
// Retrieve platform specific info
|
|
// Retrieve platform specific info
|
|
daemon.fillPlatformInfo(v, sysInfo)
|
|
daemon.fillPlatformInfo(v, sysInfo)
|
|
daemon.fillDriverInfo(v)
|
|
daemon.fillDriverInfo(v)
|
|
@@ -171,6 +172,32 @@ func (daemon *Daemon) fillSecurityOptions(v *types.Info, sysInfo *sysinfo.SysInf
|
|
v.SecurityOptions = securityOptions
|
|
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 {
|
|
func hostName() string {
|
|
hostname := ""
|
|
hostname := ""
|
|
if hn, err := os.Hostname(); err != nil {
|
|
if hn, err := os.Hostname(); err != nil {
|