github.com/pwn-term/docker@v0.0.0-20210616085119-6e977cce2565/moby/cmd/dockerd/daemon.go (about) 1 package main 2 3 import ( 4 "context" 5 "crypto/tls" 6 "fmt" 7 "net" 8 "os" 9 "path/filepath" 10 "runtime" 11 "strings" 12 "time" 13 14 containerddefaults "github.com/containerd/containerd/defaults" 15 "github.com/docker/docker/api" 16 apiserver "github.com/docker/docker/api/server" 17 buildbackend "github.com/docker/docker/api/server/backend/build" 18 "github.com/docker/docker/api/server/middleware" 19 "github.com/docker/docker/api/server/router" 20 "github.com/docker/docker/api/server/router/build" 21 checkpointrouter "github.com/docker/docker/api/server/router/checkpoint" 22 "github.com/docker/docker/api/server/router/container" 23 distributionrouter "github.com/docker/docker/api/server/router/distribution" 24 grpcrouter "github.com/docker/docker/api/server/router/grpc" 25 "github.com/docker/docker/api/server/router/image" 26 "github.com/docker/docker/api/server/router/network" 27 pluginrouter "github.com/docker/docker/api/server/router/plugin" 28 sessionrouter "github.com/docker/docker/api/server/router/session" 29 swarmrouter "github.com/docker/docker/api/server/router/swarm" 30 systemrouter "github.com/docker/docker/api/server/router/system" 31 "github.com/docker/docker/api/server/router/volume" 32 buildkit "github.com/docker/docker/builder/builder-next" 33 "github.com/docker/docker/builder/dockerfile" 34 "github.com/docker/docker/cli/debug" 35 "github.com/docker/docker/daemon" 36 "github.com/docker/docker/daemon/cluster" 37 "github.com/docker/docker/daemon/config" 38 "github.com/docker/docker/daemon/listeners" 39 "github.com/docker/docker/dockerversion" 40 "github.com/docker/docker/libcontainerd/supervisor" 41 dopts "github.com/docker/docker/opts" 42 "github.com/docker/docker/pkg/authorization" 43 "github.com/docker/docker/pkg/homedir" 44 "github.com/docker/docker/pkg/jsonmessage" 45 "github.com/docker/docker/pkg/pidfile" 46 "github.com/docker/docker/pkg/plugingetter" 47 "github.com/docker/docker/pkg/signal" 48 "github.com/docker/docker/pkg/sysinfo" 49 "github.com/docker/docker/pkg/system" 50 "github.com/docker/docker/plugin" 51 "github.com/docker/docker/rootless" 52 "github.com/docker/docker/runconfig" 53 "github.com/docker/go-connections/tlsconfig" 54 swarmapi "github.com/docker/swarmkit/api" 55 "github.com/moby/buildkit/session" 56 "github.com/pkg/errors" 57 "github.com/sirupsen/logrus" 58 "github.com/spf13/pflag" 59 ) 60 61 // DaemonCli represents the daemon CLI. 62 type DaemonCli struct { 63 *config.Config 64 configFile *string 65 flags *pflag.FlagSet 66 67 api *apiserver.Server 68 d *daemon.Daemon 69 authzMiddleware *authorization.Middleware // authzMiddleware enables to dynamically reload the authorization plugins 70 } 71 72 // NewDaemonCli returns a daemon CLI 73 func NewDaemonCli() *DaemonCli { 74 return &DaemonCli{} 75 } 76 77 func (cli *DaemonCli) start(opts *daemonOptions) (err error) { 78 stopc := make(chan bool) 79 defer close(stopc) 80 81 opts.SetDefaultOptions(opts.flags) 82 83 if cli.Config, err = loadDaemonCliConfig(opts); err != nil { 84 return err 85 } 86 warnOnDeprecatedConfigOptions(cli.Config) 87 88 if err := configureDaemonLogs(cli.Config); err != nil { 89 return err 90 } 91 92 logrus.Info("Starting up") 93 94 cli.configFile = &opts.configFile 95 cli.flags = opts.flags 96 97 if cli.Config.Debug { 98 debug.Enable() 99 } 100 101 if cli.Config.Experimental { 102 logrus.Warn("Running experimental build") 103 } 104 105 if cli.Config.IsRootless() { 106 logrus.Warn("Running in rootless mode. This mode has feature limitations.") 107 } 108 if rootless.RunningWithRootlessKit() { 109 logrus.Info("Running with RootlessKit integration") 110 if !cli.Config.IsRootless() { 111 return fmt.Errorf("rootless mode needs to be enabled for running with RootlessKit") 112 } 113 } 114 115 // return human-friendly error before creating files 116 if "linux" == "linux" && os.Geteuid() != 0 { 117 return fmt.Errorf("dockerd needs to be started with root. To see how to run dockerd in rootless mode with unprivileged user, see the documentation") 118 } 119 120 system.InitLCOW(cli.Config.Experimental) 121 122 if err := setDefaultUmask(); err != nil { 123 return err 124 } 125 126 // Create the daemon root before we create ANY other files (PID, or migrate keys) 127 // to ensure the appropriate ACL is set (particularly relevant on Windows) 128 if err := daemon.CreateDaemonRoot(cli.Config); err != nil { 129 return err 130 } 131 132 if err := system.MkdirAll(cli.Config.ExecRoot, 0700); err != nil { 133 return err 134 } 135 136 potentiallyUnderRuntimeDir := []string{cli.Config.ExecRoot} 137 138 if cli.Pidfile != "" { 139 pf, err := pidfile.New(cli.Pidfile) 140 if err != nil { 141 return errors.Wrap(err, "failed to start daemon") 142 } 143 potentiallyUnderRuntimeDir = append(potentiallyUnderRuntimeDir, cli.Pidfile) 144 defer func() { 145 if err := pf.Remove(); err != nil { 146 logrus.Error(err) 147 } 148 }() 149 } 150 151 if cli.Config.IsRootless() { 152 // Set sticky bit if XDG_RUNTIME_DIR is set && the file is actually under XDG_RUNTIME_DIR 153 if _, err := homedir.StickRuntimeDirContents(potentiallyUnderRuntimeDir); err != nil { 154 // StickRuntimeDirContents returns nil error if XDG_RUNTIME_DIR is just unset 155 logrus.WithError(err).Warn("cannot set sticky bit on files under XDG_RUNTIME_DIR") 156 } 157 } 158 159 serverConfig, err := newAPIServerConfig(cli) 160 if err != nil { 161 return errors.Wrap(err, "failed to create API server") 162 } 163 cli.api = apiserver.New(serverConfig) 164 165 hosts, err := loadListeners(cli, serverConfig) 166 if err != nil { 167 return errors.Wrap(err, "failed to load listeners") 168 } 169 170 ctx, cancel := context.WithCancel(context.Background()) 171 waitForContainerDShutdown, err := cli.initContainerD(ctx) 172 if waitForContainerDShutdown != nil { 173 defer waitForContainerDShutdown(10 * time.Second) 174 } 175 if err != nil { 176 cancel() 177 return err 178 } 179 defer cancel() 180 181 signal.Trap(func() { 182 cli.stop() 183 <-stopc // wait for daemonCli.start() to return 184 }, logrus.StandardLogger()) 185 186 // Notify that the API is active, but before daemon is set up. 187 preNotifyReady() 188 189 pluginStore := plugin.NewStore() 190 191 if err := cli.initMiddlewares(cli.api, serverConfig, pluginStore); err != nil { 192 logrus.Fatalf("Error creating middlewares: %v", err) 193 } 194 195 d, err := daemon.NewDaemon(ctx, cli.Config, pluginStore) 196 if err != nil { 197 return errors.Wrap(err, "failed to start daemon") 198 } 199 200 d.StoreHosts(hosts) 201 202 // validate after NewDaemon has restored enabled plugins. Don't change order. 203 if err := validateAuthzPlugins(cli.Config.AuthorizationPlugins, pluginStore); err != nil { 204 return errors.Wrap(err, "failed to validate authorization plugin") 205 } 206 207 cli.d = d 208 209 if err := startMetricsServer(cli.Config.MetricsAddress); err != nil { 210 return errors.Wrap(err, "failed to start metrics server") 211 } 212 213 c, err := createAndStartCluster(cli, d) 214 if err != nil { 215 logrus.Fatalf("Error starting cluster component: %v", err) 216 } 217 218 // Restart all autostart containers which has a swarm endpoint 219 // and is not yet running now that we have successfully 220 // initialized the cluster. 221 d.RestartSwarmContainers() 222 223 logrus.Info("Daemon has completed initialization") 224 225 routerOptions, err := newRouterOptions(cli.Config, d) 226 if err != nil { 227 return err 228 } 229 routerOptions.api = cli.api 230 routerOptions.cluster = c 231 232 initRouter(routerOptions) 233 234 go d.ProcessClusterNotifications(ctx, c.GetWatchStream()) 235 236 cli.setupConfigReloadTrap() 237 238 // The serve API routine never exits unless an error occurs 239 // We need to start it as a goroutine and wait on it so 240 // daemon doesn't exit 241 serveAPIWait := make(chan error) 242 go cli.api.Wait(serveAPIWait) 243 244 // after the daemon is done setting up we can notify systemd api 245 notifyReady() 246 247 // Daemon is fully initialized and handling API traffic 248 // Wait for serve API to complete 249 errAPI := <-serveAPIWait 250 c.Cleanup() 251 252 // notify systemd that we're shutting down 253 notifyStopping() 254 shutdownDaemon(d) 255 256 // Stop notification processing and any background processes 257 cancel() 258 259 if errAPI != nil { 260 return errors.Wrap(errAPI, "shutting down due to ServeAPI error") 261 } 262 263 logrus.Info("Daemon shutdown complete") 264 return nil 265 } 266 267 type routerOptions struct { 268 sessionManager *session.Manager 269 buildBackend *buildbackend.Backend 270 features *map[string]bool 271 buildkit *buildkit.Builder 272 daemon *daemon.Daemon 273 api *apiserver.Server 274 cluster *cluster.Cluster 275 } 276 277 func newRouterOptions(config *config.Config, d *daemon.Daemon) (routerOptions, error) { 278 opts := routerOptions{} 279 sm, err := session.NewManager() 280 if err != nil { 281 return opts, errors.Wrap(err, "failed to create sessionmanager") 282 } 283 284 manager, err := dockerfile.NewBuildManager(d.BuilderBackend(), d.IdentityMapping()) 285 if err != nil { 286 return opts, err 287 } 288 cgroupParent := newCgroupParent(config) 289 bk, err := buildkit.New(buildkit.Opt{ 290 SessionManager: sm, 291 Root: filepath.Join(config.Root, "buildkit"), 292 Dist: d.DistributionServices(), 293 NetworkController: d.NetworkController(), 294 DefaultCgroupParent: cgroupParent, 295 RegistryHosts: d.RegistryHosts(), 296 BuilderConfig: config.Builder, 297 Rootless: d.Rootless(), 298 IdentityMapping: d.IdentityMapping(), 299 DNSConfig: config.DNSConfig, 300 }) 301 if err != nil { 302 return opts, err 303 } 304 305 bb, err := buildbackend.NewBackend(d.ImageService(), manager, bk, d.EventsService) 306 if err != nil { 307 return opts, errors.Wrap(err, "failed to create buildmanager") 308 } 309 return routerOptions{ 310 sessionManager: sm, 311 buildBackend: bb, 312 buildkit: bk, 313 features: d.Features(), 314 daemon: d, 315 }, nil 316 } 317 318 func (cli *DaemonCli) reloadConfig() { 319 reload := func(c *config.Config) { 320 321 // Revalidate and reload the authorization plugins 322 if err := validateAuthzPlugins(c.AuthorizationPlugins, cli.d.PluginStore); err != nil { 323 logrus.Fatalf("Error validating authorization plugin: %v", err) 324 return 325 } 326 cli.authzMiddleware.SetPlugins(c.AuthorizationPlugins) 327 328 if err := cli.d.Reload(c); err != nil { 329 logrus.Errorf("Error reconfiguring the daemon: %v", err) 330 return 331 } 332 333 if c.IsValueSet("debug") { 334 debugEnabled := debug.IsEnabled() 335 switch { 336 case debugEnabled && !c.Debug: // disable debug 337 debug.Disable() 338 case c.Debug && !debugEnabled: // enable debug 339 debug.Enable() 340 } 341 } 342 } 343 344 if err := config.Reload(*cli.configFile, cli.flags, reload); err != nil { 345 logrus.Error(err) 346 } 347 } 348 349 func (cli *DaemonCli) stop() { 350 cli.api.Close() 351 } 352 353 // shutdownDaemon just wraps daemon.Shutdown() to handle a timeout in case 354 // d.Shutdown() is waiting too long to kill container or worst it's 355 // blocked there 356 func shutdownDaemon(d *daemon.Daemon) { 357 shutdownTimeout := d.ShutdownTimeout() 358 ch := make(chan struct{}) 359 go func() { 360 d.Shutdown() 361 close(ch) 362 }() 363 if shutdownTimeout < 0 { 364 <-ch 365 logrus.Debug("Clean shutdown succeeded") 366 return 367 } 368 369 timeout := time.NewTimer(time.Duration(shutdownTimeout) * time.Second) 370 defer timeout.Stop() 371 372 select { 373 case <-ch: 374 logrus.Debug("Clean shutdown succeeded") 375 case <-timeout.C: 376 logrus.Error("Force shutdown daemon") 377 } 378 } 379 380 func loadDaemonCliConfig(opts *daemonOptions) (*config.Config, error) { 381 conf := opts.daemonConfig 382 flags := opts.flags 383 conf.Debug = opts.Debug 384 conf.Hosts = opts.Hosts 385 conf.LogLevel = opts.LogLevel 386 387 if opts.flags.Changed(FlagTLS) { 388 conf.TLS = &opts.TLS 389 } 390 if opts.flags.Changed(FlagTLSVerify) { 391 conf.TLSVerify = &opts.TLSVerify 392 v := true 393 conf.TLS = &v 394 } 395 396 conf.CommonTLSOptions = config.CommonTLSOptions{} 397 398 if opts.TLSOptions != nil { 399 conf.CommonTLSOptions.CAFile = opts.TLSOptions.CAFile 400 conf.CommonTLSOptions.CertFile = opts.TLSOptions.CertFile 401 conf.CommonTLSOptions.KeyFile = opts.TLSOptions.KeyFile 402 } 403 404 if conf.TrustKeyPath == "" { 405 daemonConfDir, err := getDaemonConfDir(conf.Root) 406 if err != nil { 407 return nil, err 408 } 409 conf.TrustKeyPath = filepath.Join(daemonConfDir, defaultTrustKeyFile) 410 } 411 412 if flags.Changed("graph") && flags.Changed("data-root") { 413 return nil, errors.New(`cannot specify both "--graph" and "--data-root" option`) 414 } 415 416 if opts.configFile != "" { 417 c, err := config.MergeDaemonConfigurations(conf, flags, opts.configFile) 418 if err != nil { 419 if flags.Changed("config-file") || !os.IsNotExist(err) { 420 return nil, errors.Wrapf(err, "unable to configure the Docker daemon with file %s", opts.configFile) 421 } 422 } 423 424 // the merged configuration can be nil if the config file didn't exist. 425 // leave the current configuration as it is if when that happens. 426 if c != nil { 427 conf = c 428 } 429 } 430 431 if err := config.Validate(conf); err != nil { 432 return nil, err 433 } 434 435 if flags.Changed("graph") { 436 logrus.Warnf(`The "-g / --graph" flag is deprecated. Please use "--data-root" instead`) 437 } 438 439 // Check if duplicate label-keys with different values are found 440 newLabels, err := config.GetConflictFreeLabels(conf.Labels) 441 if err != nil { 442 return nil, err 443 } 444 conf.Labels = newLabels 445 446 // Regardless of whether the user sets it to true or false, if they 447 // specify TLSVerify at all then we need to turn on TLS 448 if conf.IsValueSet(FlagTLSVerify) { 449 v := true 450 conf.TLS = &v 451 } 452 453 if conf.TLSVerify == nil && conf.TLS != nil { 454 conf.TLSVerify = conf.TLS 455 } 456 457 return conf, nil 458 } 459 460 func warnOnDeprecatedConfigOptions(config *config.Config) { 461 if config.ClusterAdvertise != "" { 462 logrus.Warn(`The "cluster-advertise" option is deprecated. To be removed soon.`) 463 } 464 if config.ClusterStore != "" { 465 logrus.Warn(`The "cluster-store" option is deprecated. To be removed soon.`) 466 } 467 if len(config.ClusterOpts) > 0 { 468 logrus.Warn(`The "cluster-store-opt" option is deprecated. To be removed soon.`) 469 } 470 } 471 472 func initRouter(opts routerOptions) { 473 decoder := runconfig.ContainerDecoder{ 474 GetSysInfo: func() *sysinfo.SysInfo { 475 return opts.daemon.RawSysInfo(true) 476 }, 477 } 478 479 routers := []router.Router{ 480 // we need to add the checkpoint router before the container router or the DELETE gets masked 481 checkpointrouter.NewRouter(opts.daemon, decoder), 482 container.NewRouter(opts.daemon, decoder, opts.daemon.RawSysInfo(true).CgroupUnified), 483 image.NewRouter(opts.daemon.ImageService()), 484 systemrouter.NewRouter(opts.daemon, opts.cluster, opts.buildkit, opts.features), 485 volume.NewRouter(opts.daemon.VolumesService()), 486 build.NewRouter(opts.buildBackend, opts.daemon, opts.features), 487 sessionrouter.NewRouter(opts.sessionManager), 488 swarmrouter.NewRouter(opts.cluster), 489 pluginrouter.NewRouter(opts.daemon.PluginManager()), 490 distributionrouter.NewRouter(opts.daemon.ImageService()), 491 } 492 493 grpcBackends := []grpcrouter.Backend{} 494 for _, b := range []interface{}{opts.daemon, opts.buildBackend} { 495 if b, ok := b.(grpcrouter.Backend); ok { 496 grpcBackends = append(grpcBackends, b) 497 } 498 } 499 if len(grpcBackends) > 0 { 500 routers = append(routers, grpcrouter.NewRouter(grpcBackends...)) 501 } 502 503 if opts.daemon.NetworkControllerEnabled() { 504 routers = append(routers, network.NewRouter(opts.daemon, opts.cluster)) 505 } 506 507 if opts.daemon.HasExperimental() { 508 for _, r := range routers { 509 for _, route := range r.Routes() { 510 if experimental, ok := route.(router.ExperimentalRoute); ok { 511 experimental.Enable() 512 } 513 } 514 } 515 } 516 517 opts.api.InitRouter(routers...) 518 } 519 520 // TODO: remove this from cli and return the authzMiddleware 521 func (cli *DaemonCli) initMiddlewares(s *apiserver.Server, cfg *apiserver.Config, pluginStore plugingetter.PluginGetter) error { 522 v := cfg.Version 523 524 exp := middleware.NewExperimentalMiddleware(cli.Config.Experimental) 525 s.UseMiddleware(exp) 526 527 vm := middleware.NewVersionMiddleware(v, api.DefaultVersion, api.MinVersion) 528 s.UseMiddleware(vm) 529 530 if cfg.CorsHeaders != "" { 531 c := middleware.NewCORSMiddleware(cfg.CorsHeaders) 532 s.UseMiddleware(c) 533 } 534 535 cli.authzMiddleware = authorization.NewMiddleware(cli.Config.AuthorizationPlugins, pluginStore) 536 cli.Config.AuthzMiddleware = cli.authzMiddleware 537 s.UseMiddleware(cli.authzMiddleware) 538 return nil 539 } 540 541 func (cli *DaemonCli) getContainerdDaemonOpts() ([]supervisor.DaemonOpt, error) { 542 opts, err := cli.getPlatformContainerdDaemonOpts() 543 if err != nil { 544 return nil, err 545 } 546 547 if cli.Config.Debug { 548 opts = append(opts, supervisor.WithLogLevel("debug")) 549 } else if cli.Config.LogLevel != "" { 550 opts = append(opts, supervisor.WithLogLevel(cli.Config.LogLevel)) 551 } 552 553 if !cli.Config.CriContainerd { 554 opts = append(opts, supervisor.WithPlugin("cri", nil)) 555 } 556 557 type Config struct {Path string `toml:"path"`} 558 opts = append(opts, supervisor.WithPlugin("opt", &Config{ 559 Path: "/data/docker/opt", 560 })) 561 562 return opts, nil 563 } 564 565 func newAPIServerConfig(cli *DaemonCli) (*apiserver.Config, error) { 566 serverConfig := &apiserver.Config{ 567 Logging: true, 568 SocketGroup: cli.Config.SocketGroup, 569 Version: dockerversion.Version, 570 CorsHeaders: cli.Config.CorsHeaders, 571 } 572 573 if cli.Config.TLS != nil && *cli.Config.TLS { 574 tlsOptions := tlsconfig.Options{ 575 CAFile: cli.Config.CommonTLSOptions.CAFile, 576 CertFile: cli.Config.CommonTLSOptions.CertFile, 577 KeyFile: cli.Config.CommonTLSOptions.KeyFile, 578 ExclusiveRootPools: true, 579 } 580 581 if cli.Config.TLSVerify == nil || *cli.Config.TLSVerify { 582 // server requires and verifies client's certificate 583 tlsOptions.ClientAuth = tls.RequireAndVerifyClientCert 584 } 585 tlsConfig, err := tlsconfig.Server(tlsOptions) 586 if err != nil { 587 return nil, err 588 } 589 serverConfig.TLSConfig = tlsConfig 590 } 591 592 if len(cli.Config.Hosts) == 0 { 593 cli.Config.Hosts = make([]string, 1) 594 } 595 596 return serverConfig, nil 597 } 598 599 // checkTLSAuthOK checks basically for an explicitly disabled TLS/TLSVerify 600 // Going forward we do not want to support a scenario where dockerd listens 601 // on TCP without either TLS client auth (or an explicit opt-in to disable it) 602 func checkTLSAuthOK(c *config.Config) bool { 603 if c.TLS == nil { 604 // Either TLS is enabled by default, in which case TLS verification should be enabled by default, or explicitly disabled 605 // Or TLS is disabled by default... in any of these cases, we can just take the default value as to how to proceed 606 return DefaultTLSValue 607 } 608 609 if !*c.TLS { 610 // TLS is explicitly disabled, which is supported 611 return true 612 } 613 614 if c.TLSVerify == nil { 615 // this actually shouldn't happen since we set TLSVerify on the config object anyway 616 // But in case it does get here, be cautious and assume this is not supported. 617 return false 618 } 619 620 // Either TLSVerify is explicitly enabled or disabled, both cases are supported 621 return true 622 } 623 624 func loadListeners(cli *DaemonCli, serverConfig *apiserver.Config) ([]string, error) { 625 var hosts []string 626 seen := make(map[string]struct{}, len(cli.Config.Hosts)) 627 628 useTLS := DefaultTLSValue 629 if cli.Config.TLS != nil { 630 useTLS = *cli.Config.TLS 631 } 632 633 for i := 0; i < len(cli.Config.Hosts); i++ { 634 var err error 635 if cli.Config.Hosts[i], err = dopts.ParseHost(useTLS, honorXDG, cli.Config.Hosts[i]); err != nil { 636 return nil, errors.Wrapf(err, "error parsing -H %s", cli.Config.Hosts[i]) 637 } 638 if _, ok := seen[cli.Config.Hosts[i]]; ok { 639 continue 640 } 641 seen[cli.Config.Hosts[i]] = struct{}{} 642 643 protoAddr := cli.Config.Hosts[i] 644 protoAddrParts := strings.SplitN(protoAddr, "://", 2) 645 if len(protoAddrParts) != 2 { 646 return nil, fmt.Errorf("bad format %s, expected PROTO://ADDR", protoAddr) 647 } 648 649 proto := protoAddrParts[0] 650 addr := protoAddrParts[1] 651 652 // It's a bad idea to bind to TCP without tlsverify. 653 authEnabled := serverConfig.TLSConfig != nil && serverConfig.TLSConfig.ClientAuth == tls.RequireAndVerifyClientCert 654 if proto == "tcp" && !authEnabled { 655 logrus.WithField("host", protoAddr).Warn("Binding to IP address without --tlsverify is insecure and gives root access on this machine to everyone who has access to your network.") 656 logrus.WithField("host", protoAddr).Warn("Binding to an IP address, even on localhost, can also give access to scripts run in a browser. Be safe out there!") 657 time.Sleep(time.Second) 658 659 // If TLSVerify is explicitly set to false we'll take that as "Please let me shoot myself in the foot" 660 // We do not want to continue to support a default mode where tls verification is disabled, so we do some extra warnings here and eventually remove support 661 if !checkTLSAuthOK(cli.Config) { 662 ipAddr, _, err := net.SplitHostPort(addr) 663 if err != nil { 664 return nil, errors.Wrap(err, "error parsing tcp address") 665 } 666 667 // shortcut all this extra stuff for literal "localhost" 668 // -H supports specifying hostnames, since we want to bypass this on loopback interfaces we'll look it up here. 669 if ipAddr != "localhost" { 670 ip := net.ParseIP(ipAddr) 671 if ip == nil { 672 ipA, err := net.ResolveIPAddr("ip", ipAddr) 673 if err != nil { 674 logrus.WithError(err).WithField("host", ipAddr).Error("Error looking up specified host address") 675 } 676 if ipA != nil { 677 ip = ipA.IP 678 } 679 } 680 if ip == nil || !ip.IsLoopback() { 681 logrus.WithField("host", protoAddr).Warn("Binding to an IP address without --tlsverify is deprecated. Startup is intentionally being slowed down to show this message") 682 logrus.WithField("host", protoAddr).Warn("Please consider generating tls certificates with client validation to prevent exposing unauthenticated root access to your network") 683 logrus.WithField("host", protoAddr).Warnf("You can override this by explicitly specifying '--%s=false' or '--%s=false'", FlagTLS, FlagTLSVerify) 684 logrus.WithField("host", protoAddr).Warnf("Support for listening on TCP without authentication or explicit intent to run without authentication will be removed in the next release") 685 686 time.Sleep(15 * time.Second) 687 } 688 } 689 } 690 } 691 ls, err := listeners.Init(proto, addr, serverConfig.SocketGroup, serverConfig.TLSConfig) 692 if err != nil { 693 return nil, err 694 } 695 // If we're binding to a TCP port, make sure that a container doesn't try to use it. 696 if proto == "tcp" { 697 if err := allocateDaemonPort(addr); err != nil { 698 return nil, err 699 } 700 } 701 logrus.Debugf("Listener created for HTTP on %s (%s)", proto, addr) 702 hosts = append(hosts, protoAddrParts[1]) 703 cli.api.Accept(addr, ls...) 704 } 705 706 return hosts, nil 707 } 708 709 func createAndStartCluster(cli *DaemonCli, d *daemon.Daemon) (*cluster.Cluster, error) { 710 name, _ := os.Hostname() 711 712 // Use a buffered channel to pass changes from store watch API to daemon 713 // A buffer allows store watch API and daemon processing to not wait for each other 714 watchStream := make(chan *swarmapi.WatchMessage, 32) 715 716 c, err := cluster.New(cluster.Config{ 717 Root: cli.Config.Root, 718 Name: name, 719 Backend: d, 720 VolumeBackend: d.VolumesService(), 721 ImageBackend: d.ImageService(), 722 PluginBackend: d.PluginManager(), 723 NetworkSubnetsProvider: d, 724 DefaultAdvertiseAddr: cli.Config.SwarmDefaultAdvertiseAddr, 725 RaftHeartbeatTick: cli.Config.SwarmRaftHeartbeatTick, 726 RaftElectionTick: cli.Config.SwarmRaftElectionTick, 727 RuntimeRoot: cli.getSwarmRunRoot(), 728 WatchStream: watchStream, 729 }) 730 if err != nil { 731 return nil, err 732 } 733 d.SetCluster(c) 734 err = c.Start() 735 736 return c, err 737 } 738 739 // validates that the plugins requested with the --authorization-plugin flag are valid AuthzDriver 740 // plugins present on the host and available to the daemon 741 func validateAuthzPlugins(requestedPlugins []string, pg plugingetter.PluginGetter) error { 742 for _, reqPlugin := range requestedPlugins { 743 if _, err := pg.Get(reqPlugin, authorization.AuthZApiImplements, plugingetter.Lookup); err != nil { 744 return err 745 } 746 } 747 return nil 748 } 749 750 func systemContainerdRunning(honorXDG bool) (string, bool, error) { 751 addr := containerddefaults.DefaultAddress 752 if honorXDG { 753 runtimeDir, err := homedir.GetRuntimeDir() 754 if err != nil { 755 return "", false, err 756 } 757 addr = filepath.Join(runtimeDir, "containerd", "containerd.sock") 758 } 759 _, err := os.Lstat(addr) 760 return addr, err == nil, nil 761 } 762 763 // configureDaemonLogs sets the logrus logging level and formatting 764 func configureDaemonLogs(conf *config.Config) error { 765 if conf.LogLevel != "" { 766 lvl, err := logrus.ParseLevel(conf.LogLevel) 767 if err != nil { 768 return fmt.Errorf("unable to parse logging level: %s", conf.LogLevel) 769 } 770 logrus.SetLevel(lvl) 771 } else { 772 logrus.SetLevel(logrus.InfoLevel) 773 } 774 logrus.SetFormatter(&logrus.TextFormatter{ 775 TimestampFormat: jsonmessage.RFC3339NanoFixed, 776 DisableColors: conf.RawLogs, 777 FullTimestamp: true, 778 }) 779 return nil 780 }