Skip to content

28 fr support granular api permissions on a per host basis via allowfrom#75

Merged
wollomatic merged 45 commits into
developfrom
28-fr-support-granular-api-permissions-on-a-per-host-basis-via-allowfrom
Dec 4, 2025
Merged

28 fr support granular api permissions on a per host basis via allowfrom#75
wollomatic merged 45 commits into
developfrom
28-fr-support-granular-api-permissions-on-a-per-host-basis-via-allowfrom

Conversation

@wollomatic
Copy link
Copy Markdown
Owner

This pull request introduces support for per-container allowlists in socket-proxy, allowing more granular control over allowed HTTP methods and bind mount restrictions based on Docker container labels. It refactors the bind mount restriction logic to use allowlists passed per request, updates documentation to reflect these new features, and makes minor improvements to licensing and dependency references.

Per-container allowlist support:

  • Added the ability to specify allowlists for HTTP methods and bind mount restrictions on a per-container basis using Docker labels; this is enabled by the new -proxycontainername parameter. (README.md, cmd/socket-proxy/handlehttprequest.go, [1] [2] [3]
  • Refactored the bind mount restriction functions in cmd/socket-proxy/bindmount.go to accept the allowed bind mounts as a parameter, supporting the new per-container allowlist logic. [1] [2] [3] [4] [5]

Documentation updates:

  • Updated the README.md to document per-container allowlists, new configuration options, and usage notes for compatibility with recent Traefik versions. [1] [2] [3] [4]

Testing and code maintenance:

  • Updated tests in cmd/socket-proxy/bindmount_test.go to use the new function signatures for bind mount validation and restriction checks. [1] [2] [3] [4] [5] [6] [7]

Licensing and dependencies:

  • Updated the LICENSE and README.md to clarify that files under internal/docker and internal/go-connections are licensed under Apache 2.0. [1] [2]
  • Updated the Go base image in Dockerfile from 1.25.1-alpine3.22 to 1.25.3-alpine3.22.

wollomatic and others added 30 commits October 1, 2025 19:47
Bumps golang from 1.25.1-alpine3.22 to 1.25.3-alpine3.22.

---
updated-dependencies:
- dependency-name: golang
  dependency-version: 1.25.3-alpine3.22
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
…3-alpine3.22

Bump golang from 1.25.1-alpine3.22 to 1.25.3-alpine3.22
Updated usage instructions for Traefik due to API version changes.

Signed-off-by: Wolfgang Ellsässer <67168186+wollomatic@users.noreply.github.com>
Added information about allowing requests to /_ping in README.

Signed-off-by: Wolfgang Ellsässer <67168186+wollomatic@users.noreply.github.com>
wollomatic and others added 8 commits November 14, 2025 13:58
Signed-off-by: Wolfgang Ellsässer <67168186+wollomatic@users.noreply.github.com>
Updated usage instructions for Traefik configuration to reflect changes in how Traefik retrieves the Docker API version.

Signed-off-by: Wolfgang Ellsässer <67168186+wollomatic@users.noreply.github.com>
Updated Traefik usage instructions and removed outdated information.

Signed-off-by: Wolfgang Ellsässer <67168186+wollomatic@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Wolfgang Ellsässer <67168186+wollomatic@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Wolfgang Ellsässer <67168186+wollomatic@users.noreply.github.com>
To fix number of retries when querying Docker Engine API for proxy container summary.

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Amanda Wee <amanda@aranel.net>
To fix formatting of SP_PROXYCONTAINERNAME

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Amanda Wee <amanda@aranel.net>
implement per-container allowlists specified by Docker container labels
@wollomatic wollomatic self-assigned this Dec 4, 2025
Copilot AI review requested due to automatic review settings December 4, 2025 19:50
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request introduces per-container allowlist support to socket-proxy, enabling fine-grained control over Docker API access on a per-container basis through Docker labels. The implementation includes a custom Docker client library (extracted from the official Docker SDK), comprehensive allowlist management with event-driven updates, and refactored bind mount restrictions to support the new allowlist architecture.

  • Adds Docker client library under internal/docker and internal/go-connections with API version negotiation and event streaming capabilities
  • Implements AllowListRegistry with thread-safe per-IP allowlist management, automatically updated via Docker events (container start/restart/die)
  • Refactors bind mount restriction functions to accept allowlist parameters, enabling per-container bind mount policies

Reviewed changes

Copilot reviewed 27 out of 27 changed files in this pull request and generated 13 comments.

Show a summary per file
File Description
internal/go-connections/sockets/sockets.go Helper functions for Unix/TCP socket configuration extracted from Docker's go-connections library
internal/docker/client/*.go Custom Docker API client implementation with request handling, ping, events, and container listing
internal/docker/api/**/*.go Docker API type definitions for containers, events, filters, and version comparison
internal/config/config.go Major refactoring introducing AllowListRegistry with per-container allowlist support via Docker labels, event-driven updates, and mutex-protected IP-based lookups
cmd/socket-proxy/main.go Initializes non-default allowlists as a goroutine when proxy container name is provided
cmd/socket-proxy/handlehttprequest.go Refactored to determine appropriate allowlist (default or per-container) based on client IP
cmd/socket-proxy/bindmount.go Updated all bind mount validation functions to accept allowedBindMounts as a parameter
cmd/socket-proxy/bindmount_test.go Updated tests to pass allowedBindMounts directly to validation functions
README.md Documents per-container allowlist feature, Traefik compatibility note, and fixes spelling error
LICENSE Updates Apache 2.0 attribution to include new internal/docker and internal/go-connections files
Dockerfile Updates Go base image from 1.25.1 to 1.25.3

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread internal/docker/client/request.go Outdated
Comment thread internal/config/config.go
Comment thread internal/config/config.go Outdated
Comment thread internal/config/config.go
Comment on lines +278 to +342
func (cfg *Config) UpdateAllowLists() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()

dockerClient, err := client.NewClientWithOpts(
client.WithHost("unix://"+cfg.SocketPath),
client.WithAPIVersionNegotiation(),
)
if err != nil {
slog.Error("failed to create Docker client", "error", err)
return
}
defer dockerClient.Close()

err = cfg.AllowLists.initByIP(ctx, dockerClient)
if err != nil {
slog.Error("failed to initialise non-default allowlists", "error", err)
return
}
slog.Debug("initialised non-default allowlists")

filter := filters.NewArgs()
filter.Add("type", "container")
filter.Add("event", "start")
filter.Add("event", "restart")
filter.Add("event", "die")
eventsChan, errChan := dockerClient.Events(ctx, events.ListOptions{Filters: filter})
slog.Debug("subscribed to Docker event stream to update allowlists")

// print non-default request allowlists
cfg.AllowLists.PrintByIP(cfg.LogJSON)

// handle Docker events to update allowlists
for {
select {
case event, ok := <-eventsChan:
if !ok {
slog.Info("Docker event stream closed")
return
}
slog.Debug("received Docker container event", "action", event.Action, "id", event.Actor.ID[:12])
addedIPs, removedIPs, updateErr := cfg.AllowLists.updateFromEvent(ctx, dockerClient, event)
if updateErr != nil {
slog.Warn("failed to update allowlists from container event", "error", updateErr)
continue
}
for _, ip := range addedIPs {
cfg.AllowLists.mutex.RLock()
allowList, found := cfg.AllowLists.byIP[ip]
cfg.AllowLists.mutex.RUnlock()
if found {
allowList.Print(ip, cfg.LogJSON)
}
}
for _, ip := range removedIPs {
slog.Info("removed allowlist for container", "id", event.Actor.ID[:12], "ip", ip)
}
case err := <-errChan:
if err != nil {
slog.Error("received error from Docker event stream", "error", err)
return
}
}
}
}
Copy link

Copilot AI Dec 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The UpdateAllowLists function runs in an infinite loop (lines 311-341) and is designed to be called as a goroutine. However, there's no mechanism to gracefully shut down this goroutine. Consider accepting a context parameter from the caller (e.g., from main) instead of creating one internally, so the goroutine can be properly cancelled on application shutdown. This would prevent potential resource leaks and allow for cleaner shutdowns.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's keep this suggestion for the next release

Comment thread internal/config/config.go
Comment thread internal/config/config.go
Comment thread internal/config/config.go
Comment thread internal/config/config.go
Comment thread internal/config/config.go
Comment thread internal/docker/client/request.go Outdated
wollomatic and others added 7 commits December 4, 2025 21:15
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Wolfgang Ellsässer <67168186+wollomatic@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Wolfgang Ellsässer <67168186+wollomatic@users.noreply.github.com>
…ssions-on-a-per-host-basis-via-allowfrom' into 28-fr-support-granular-api-permissions-on-a-per-host-basis-via-allowfrom
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Wolfgang Ellsässer <67168186+wollomatic@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Wolfgang Ellsässer <67168186+wollomatic@users.noreply.github.com>
@wollomatic wollomatic merged commit eead766 into develop Dec 4, 2025
4 checks passed
@wollomatic wollomatic deleted the 28-fr-support-granular-api-permissions-on-a-per-host-basis-via-allowfrom branch December 4, 2025 20:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants