Report FirewallBackend in "docker info".
It's currently "iptables" or "iptables+firewalld" on Linux, and
omitted on Windows.
Signed-off-by: Rob Murray <rob.murray@docker.com>
| ... | ... |
@@ -106,6 +106,10 @@ func (s *systemRouter) getInfo(ctx context.Context, w http.ResponseWriter, r *ht |
| 106 | 106 |
info.RegistryConfig.AllowNondistributableArtifactsCIDRs = []*registry.NetIPNet{}
|
| 107 | 107 |
info.RegistryConfig.AllowNondistributableArtifactsHostnames = []string{}
|
| 108 | 108 |
} |
| 109 |
+ if versions.LessThan(version, "1.49") {
|
|
| 110 |
+ // FirewallBackend field introduced in API v1.49. |
|
| 111 |
+ info.FirewallBackend = nil |
|
| 112 |
+ } |
|
| 109 | 113 |
|
| 110 | 114 |
// TODO(thaJeztah): Expected commits are deprecated, and should no longer be set in API 1.49. |
| 111 | 115 |
info.ContainerdCommit.Expected = info.ContainerdCommit.ID //nolint:staticcheck // ignore SA1019: field is deprecated, but still used on API < v1.49. |
| ... | ... |
@@ -6856,6 +6856,8 @@ definitions: |
| 6856 | 6856 |
description: "The network pool size" |
| 6857 | 6857 |
type: "integer" |
| 6858 | 6858 |
example: "24" |
| 6859 |
+ FirewallBackend: |
|
| 6860 |
+ $ref: "#/definitions/FirewallInfo" |
|
| 6859 | 6861 |
Warnings: |
| 6860 | 6862 |
description: | |
| 6861 | 6863 |
List of warnings / informational messages about missing features, or |
| ... | ... |
@@ -6939,6 +6941,37 @@ definitions: |
| 6939 | 6939 |
default: "plugins.moby" |
| 6940 | 6940 |
example: "plugins.moby" |
| 6941 | 6941 |
|
| 6942 |
+ FirewallInfo: |
|
| 6943 |
+ description: | |
|
| 6944 |
+ Information about the daemon's firewalling configuration. |
|
| 6945 |
+ |
|
| 6946 |
+ This field is currently only used on Linux, and omitted on other platforms. |
|
| 6947 |
+ type: "object" |
|
| 6948 |
+ x-nullable: true |
|
| 6949 |
+ properties: |
|
| 6950 |
+ Driver: |
|
| 6951 |
+ description: | |
|
| 6952 |
+ The name of the firewall backend driver. |
|
| 6953 |
+ type: "string" |
|
| 6954 |
+ example: "nftables" |
|
| 6955 |
+ Info: |
|
| 6956 |
+ description: | |
|
| 6957 |
+ Information about the firewall backend, provided as |
|
| 6958 |
+ "label" / "value" pairs. |
|
| 6959 |
+ |
|
| 6960 |
+ <p><br /></p> |
|
| 6961 |
+ |
|
| 6962 |
+ > **Note**: The information returned in this field, including the |
|
| 6963 |
+ > formatting of values and labels, should not be considered stable, |
|
| 6964 |
+ > and may change without notice. |
|
| 6965 |
+ type: "array" |
|
| 6966 |
+ items: |
|
| 6967 |
+ type: "array" |
|
| 6968 |
+ items: |
|
| 6969 |
+ type: "string" |
|
| 6970 |
+ example: |
|
| 6971 |
+ - ["ReloadedAt", "2025-01-01T00:00:00Z"] |
|
| 6972 |
+ |
|
| 6942 | 6973 |
# PluginsInfo is a temp struct holding Plugins name |
| 6943 | 6974 |
# registered with docker daemon. It is used by Info struct |
| 6944 | 6975 |
PluginsInfo: |
| ... | ... |
@@ -73,6 +73,7 @@ type Info struct {
|
| 73 | 73 |
SecurityOptions []string |
| 74 | 74 |
ProductLicense string `json:",omitempty"` |
| 75 | 75 |
DefaultAddressPools []NetworkAddressPool `json:",omitempty"` |
| 76 |
+ FirewallBackend *FirewallInfo `json:"FirewallBackend,omitempty"` |
|
| 76 | 77 |
CDISpecDirs []string |
| 77 | 78 |
|
| 78 | 79 |
Containerd *ContainerdInfo `json:",omitempty"` |
| ... | ... |
@@ -151,3 +152,11 @@ type NetworkAddressPool struct {
|
| 151 | 151 |
Base string |
| 152 | 152 |
Size int |
| 153 | 153 |
} |
| 154 |
+ |
|
| 155 |
+// FirewallInfo describes the firewall backend. |
|
| 156 |
+type FirewallInfo struct {
|
|
| 157 |
+ // Driver is the name of the firewall backend driver. |
|
| 158 |
+ Driver string `json:"Driver"` |
|
| 159 |
+ // Info is a list of label/value pairs, containing information related to the firewall. |
|
| 160 |
+ Info [][2]string `json:"Info,omitempty"` |
|
| 161 |
+} |
| ... | ... |
@@ -93,6 +93,7 @@ func (daemon *Daemon) SystemInfo(ctx context.Context) (*system.Info, error) {
|
| 93 | 93 |
daemon.fillSecurityOptions(v, sysInfo, &cfg.Config) |
| 94 | 94 |
daemon.fillLicense(v) |
| 95 | 95 |
daemon.fillDefaultAddressPools(ctx, v, &cfg.Config) |
| 96 |
+ daemon.fillFirewallInfo(v) |
|
| 96 | 97 |
|
| 97 | 98 |
return v, nil |
| 98 | 99 |
} |
| ... | ... |
@@ -284,6 +285,13 @@ func (daemon *Daemon) fillDefaultAddressPools(ctx context.Context, v *system.Inf |
| 284 | 284 |
} |
| 285 | 285 |
} |
| 286 | 286 |
|
| 287 |
+func (daemon *Daemon) fillFirewallInfo(v *system.Info) {
|
|
| 288 |
+ if daemon.netController == nil {
|
|
| 289 |
+ return |
|
| 290 |
+ } |
|
| 291 |
+ v.FirewallBackend = daemon.netController.FirewallBackend() |
|
| 292 |
+} |
|
| 293 |
+ |
|
| 287 | 294 |
func hostName(ctx context.Context) string {
|
| 288 | 295 |
ctx, span := tracing.StartSpan(ctx, "hostName") |
| 289 | 296 |
defer span.End() |
| ... | ... |
@@ -21,6 +21,8 @@ keywords: "API, Docker, rcli, REST, documentation" |
| 21 | 21 |
encoded OCI Platform type) allowing to specify a platform of the multi-platform |
| 22 | 22 |
image to inspect. |
| 23 | 23 |
This option is mutually exclusive with the `manifests` option. |
| 24 |
+* `GET /info` now returns a `FirewallBackend` containing information about |
|
| 25 |
+ the daemon's firewalling configuration. |
|
| 24 | 26 |
|
| 25 | 27 |
## v1.48 API changes |
| 26 | 28 |
|
| 27 | 29 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,37 @@ |
| 0 |
+package networking |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "testing" |
|
| 4 |
+ |
|
| 5 |
+ "github.com/docker/docker/client" |
|
| 6 |
+ "github.com/docker/docker/internal/testutils/networking" |
|
| 7 |
+ "github.com/docker/docker/testutil/request" |
|
| 8 |
+ "gotest.tools/v3/assert" |
|
| 9 |
+ is "gotest.tools/v3/assert/cmp" |
|
| 10 |
+) |
|
| 11 |
+ |
|
| 12 |
+func TestInfoFirewallBackend(t *testing.T) {
|
|
| 13 |
+ ctx := setupTest(t) |
|
| 14 |
+ c := testEnv.APIClient() |
|
| 15 |
+ |
|
| 16 |
+ expDriver := "iptables" |
|
| 17 |
+ if !testEnv.IsRootless() && networking.FirewalldRunning() {
|
|
| 18 |
+ expDriver = "iptables+firewalld" |
|
| 19 |
+ } |
|
| 20 |
+ info, err := c.Info(ctx) |
|
| 21 |
+ assert.NilError(t, err) |
|
| 22 |
+ assert.Assert(t, info.FirewallBackend != nil, "expected firewall backend in info response") |
|
| 23 |
+ t.Log("FirewallBackend: Driver:", info.FirewallBackend.Driver)
|
|
| 24 |
+ for _, kv := range info.FirewallBackend.Info {
|
|
| 25 |
+ t.Logf("FirewallBackend: %s: %s", kv[0], kv[1])
|
|
| 26 |
+ } |
|
| 27 |
+ assert.Check(t, is.Equal(info.FirewallBackend.Driver, expDriver)) |
|
| 28 |
+ |
|
| 29 |
+ // Check FirewallBackend is omitted for API <= 1.48. |
|
| 30 |
+ t.Run("api 1.48", func(t *testing.T) {
|
|
| 31 |
+ c148 := request.NewAPIClient(t, client.WithVersion("1.48"))
|
|
| 32 |
+ info148, err := c148.Info(ctx) |
|
| 33 |
+ assert.NilError(t, err) |
|
| 34 |
+ assert.Check(t, is.Nil(info148.FirewallBackend)) |
|
| 35 |
+ }) |
|
| 36 |
+} |
| ... | ... |
@@ -6,12 +6,25 @@ import ( |
| 6 | 6 |
"sync" |
| 7 | 7 |
|
| 8 | 8 |
"github.com/containerd/log" |
| 9 |
+ "github.com/docker/docker/api/types/system" |
|
| 9 | 10 |
"github.com/docker/docker/libnetwork/iptables" |
| 10 | 11 |
"github.com/docker/docker/libnetwork/netlabel" |
| 11 | 12 |
"github.com/docker/docker/libnetwork/options" |
| 12 | 13 |
"github.com/docker/docker/libnetwork/osl" |
| 13 | 14 |
) |
| 14 | 15 |
|
| 16 |
+// FirewallBackend returns the name of the firewall backend for "docker info". |
|
| 17 |
+func (c *Controller) FirewallBackend() *system.FirewallInfo {
|
|
| 18 |
+ usingFirewalld, err := iptables.UsingFirewalld() |
|
| 19 |
+ if err != nil {
|
|
| 20 |
+ return nil |
|
| 21 |
+ } |
|
| 22 |
+ if usingFirewalld {
|
|
| 23 |
+ return &system.FirewallInfo{Driver: "iptables+firewalld"}
|
|
| 24 |
+ } |
|
| 25 |
+ return &system.FirewallInfo{Driver: "iptables"}
|
|
| 26 |
+} |
|
| 27 |
+ |
|
| 15 | 28 |
// enabledIptablesVersions returns the iptables versions that are enabled |
| 16 | 29 |
// for the controller. |
| 17 | 30 |
func (c *Controller) enabledIptablesVersions() []iptables.IPVersion {
|
| ... | ... |
@@ -2,6 +2,13 @@ |
| 2 | 2 |
|
| 3 | 3 |
package libnetwork |
| 4 | 4 |
|
| 5 |
+import "github.com/docker/docker/api/types/system" |
|
| 6 |
+ |
|
| 7 |
+// FirewallBackend returns the name of the firewall backend for "docker info". |
|
| 8 |
+func (c *Controller) FirewallBackend() *system.FirewallInfo {
|
|
| 9 |
+ return nil |
|
| 10 |
+} |
|
| 11 |
+ |
|
| 5 | 12 |
// enabledIptablesVersions is a no-op on non-Linux systems. |
| 6 | 13 |
func (c *Controller) enabledIptablesVersions() []any {
|
| 7 | 14 |
return nil |
| ... | ... |
@@ -8,6 +8,7 @@ import ( |
| 8 | 8 |
"strings" |
| 9 | 9 |
|
| 10 | 10 |
"github.com/containerd/log" |
| 11 |
+ "github.com/docker/docker/pkg/rootless" |
|
| 11 | 12 |
dbus "github.com/godbus/dbus/v5" |
| 12 | 13 |
"github.com/pkg/errors" |
| 13 | 14 |
) |
| ... | ... |
@@ -40,7 +41,10 @@ var ( |
| 40 | 40 |
// passthrough interface. The error return is non-nil if the status cannot be |
| 41 | 41 |
// determined because the initialisation function has not been called. |
| 42 | 42 |
func UsingFirewalld() (bool, error) {
|
| 43 |
- if !firewalldInitCalled {
|
|
| 43 |
+ // If called before startup has completed, the firewall backend is unknown. |
|
| 44 |
+ // But, if running rootless, the init function is not called because |
|
| 45 |
+ // firewalld will be running in the host's netns, not in rootlesskit's. |
|
| 46 |
+ if !firewalldInitCalled && !rootless.RunningWithRootlessKit() {
|
|
| 44 | 47 |
return false, fmt.Errorf("iptables.firewalld is not initialised")
|
| 45 | 48 |
} |
| 46 | 49 |
return firewalldRunning, nil |
| ... | ... |
@@ -982,6 +982,13 @@ func (d *Daemon) Info(t testing.TB) system.Info {
|
| 982 | 982 |
return info |
| 983 | 983 |
} |
| 984 | 984 |
|
| 985 |
+func (d *Daemon) FirewallBackendDriver(t testing.TB) string {
|
|
| 986 |
+ t.Helper() |
|
| 987 |
+ info := d.Info(t) |
|
| 988 |
+ assert.Assert(t, info.FirewallBackend != nil, "no firewall backend reported") |
|
| 989 |
+ return info.FirewallBackend.Driver |
|
| 990 |
+} |
|
| 991 |
+ |
|
| 985 | 992 |
// TamperWithContainerConfig modifies the on-disk config of a container. |
| 986 | 993 |
func (d *Daemon) TamperWithContainerConfig(t testing.TB, containerID string, tamper func(*container.Container)) {
|
| 987 | 994 |
t.Helper() |