git.iko.soy/typeable/oauth2-proxy
on master help sign in
feat: add support for setting a unix binding's socket file mode (#3376)

fix: linter issues and set default unix socket permissions to 0660 Signed-off-by: Jan Larwig <jan@larwig.com> Co-authored-by: Tristan <tristan@mangadex.org>

commit9ae0b325a6d75b163c6f1fefb66ca4817c133438 authorJan Larwig <jan@larwig.com> dateThu 19 Mar 2026, 00:08 (7 months ago) parentcdbdb11
6 files changed+113−5
CHANGELOG.md+1 docs/docs/configuration/alpha_config.md+2−2 docs/docs/configuration/overview.md+1−1 pkg/apis/options/server.go+9 pkg/proxyhttp/server.go+50−2 pkg/proxyhttp/server_test.go+50
CHANGELOG.md+1
@@ -17,6 +17,7 @@
1717- [#3365](https://github.com/oauth2-proxy/oauth2-proxy/pull/3365) fix: filter empty strings from allowed groups (@Br1an67)
1818- [#3338](https://github.com/oauth2-proxy/oauth2-proxy/pull/3338) feat: add --config-test flag for validating configuration (@MayorFaj)
1919- [#3347](https://github.com/oauth2-proxy/oauth2-proxy/pull/3347) feat: add same site option for csrf cookies (@jvnoije)
20+- [#3376](https://github.com/oauth2-proxy/oauth2-proxy/pull/3376) feat: allow setting unix socket file mode when declaring listener (@Tristan971 / @tuunit)
2021
2122# V7.14.3
2223
docs/docs/configuration/alpha_config.md+2−2
@@ -584,8 +584,8 @@ Server represents the configuration for an HTTP(S) server
584584
585585| Field | Type | Description |
586586| ----- | ---- | ----------- |
587−| `bindAddress` | _string_ | BindAddress is the address on which to serve traffic.<br/>Leave blank or set to "-" to disable. |
588−| `secureBindAddress` | _string_ | SecureBindAddress is the address on which to serve secure traffic.<br/>Leave blank or set to "-" to disable. |
587+| `bindAddress` | _string_ | BindAddress is the address on which to serve traffic.<br/>Different types of bind addresses are supported:<br/>* `[http://]<addr>:<port>`<br/>* `fd:<int>` (case insensitive)<br/>* `unix://<path>`<br/>Unix sockets are created with default system umask mode, which can be overridden, e.g.: `unix://my-socket,mode=0777`<br/>Square brackets are required for ipv6 address, e.g. `http://[::1]:4180`<br/>Leave blank or set to "-" to disable. |
588+| `secureBindAddress` | _string_ | SecureBindAddress is the address on which to serve secure traffic.<br/>Secure bind addresses need to respond with valid SSL and use the following format:<br/>* `[https://]<addr>:<port>`<br/>Square brackets are required for ipv6 address, e.g. `https://[::1]:4180`<br/>Leave blank or set to "-" to disable. |
589589| `tls` | _[TLS](#tls)_ | TLS contains the information for loading the certificate and key for the<br/>secure traffic and further configuration for the TLS server. |
590590
591591### TLS
docs/docs/configuration/overview.md+1−1
@@ -264,7 +264,7 @@ Provider specific options can be found on their respective subpages.
264264
265265| Flag / Config Field | Type | Description | Default |
266266| ------------------------------------------------------------------- | -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------ |
267−| flag: `--http-address`<br/>toml: `http_address` | string | `[http://]<addr>:<port>` or `unix://<path>` or `fd:<int>` (case insensitive) to listen on for HTTP clients. Square brackets are required for ipv6 address, e.g. `http://[::1]:4180` | `"127.0.0.1:4180"` |
267+| flag: `--http-address`<br/>toml: `http_address` | string | `[http://]<addr>:<port>` or `unix://<path>` or `fd:<int>` (case insensitive) to listen on for HTTP clients. Unix sockets are created with default system umask mode, which can be overridden, e.g. `unix://my-socket,mode=0777`. Square brackets are required for ipv6 address, e.g. `http://[::1]:4180` | `"127.0.0.1:4180"` |
268268| flag: `--https-address`<br/>toml: `https_address` | string | `[https://]<addr>:<port>` to listen on for HTTPS clients. Square brackets are required for ipv6 address, e.g. `https://[::1]:443` | `":443"` |
269269| flag: `--metrics-address`<br/>toml: `metrics_address` | string | the address prometheus metrics will be scraped from | `""` |
270270| flag: `--metrics-secure-address`<br/>toml: `metrics_secure_address` | string | the address prometheus metrics will be scraped from if using HTTPS | `""` |
pkg/apis/options/server.go+9
@@ -3,10 +3,19 @@ package options
33// Server represents the configuration for an HTTP(S) server
44type Server struct {
55 // BindAddress is the address on which to serve traffic.
6+ // Different types of bind addresses are supported:
7+ // * `[http://]<addr>:<port>`
8+ // * `fd:<int>` (case insensitive)
9+ // * `unix://<path>`
10+ // Unix sockets are created with default system umask mode, which can be overridden, e.g.: `unix://my-socket,mode=0777`
11+ // Square brackets are required for ipv6 address, e.g. `http://[::1]:4180`
612 // Leave blank or set to "-" to disable.
713 BindAddress string `yaml:"bindAddress,omitempty"`
814
915 // SecureBindAddress is the address on which to serve secure traffic.
16+ // Secure bind addresses need to respond with valid SSL and use the following format:
17+ // * `[https://]<addr>:<port>`
18+ // Square brackets are required for ipv6 address, e.g. `https://[::1]:4180`
1019 // Leave blank or set to "-" to disable.
1120 SecureBindAddress string `yaml:"secureBindAddress,omitempty"`
1221
pkg/proxyhttp/server.go+50−2
@@ -8,6 +8,7 @@ import (
88 "net"
99 "net/http"
1010 "os"
11+ "strconv"
1112 "strings"
1213 "time"
1314
@@ -95,15 +96,62 @@ func (s *server) setupListener(opts Opts) error {
9596 networkType := getNetworkScheme(opts.BindAddress)
9697 listenAddr := getListenAddress(opts.BindAddress)
9798
98− listener, err := net.Listen(networkType, listenAddr)
99+ listener, err := func() (net.Listener, error) {
100+ if networkType == "unix" {
101+ return setupUnixSocketListener(networkType, listenAddr)
102+ }
103+ return net.Listen(networkType, listenAddr)
104+ }()
105+
99106 if err != nil {
100107 return fmt.Errorf("listen (%s, %s) failed: %w", networkType, listenAddr, err)
101108 }
102− s.listener = listener
103109
110+ s.listener = listener
104111 return nil
105112}
106113
114+func setupUnixSocketListener(networkType string, address string) (net.Listener, error) {
115+ socketOpts := strings.Split(address, ",")
116+ if len(socketOpts) < 2 {
117+ return net.Listen(networkType, address)
118+ }
119+
120+ socketPath := socketOpts[0]
121+ var socketMode os.FileMode
122+ hasSocketMode := false
123+
124+ for _, socketOpt := range socketOpts[1:] {
125+ socketOpt := strings.SplitN(socketOpt, "=", 2)
126+ if len(socketOpt) != 2 {
127+ return nil, fmt.Errorf("unix socket option %s expects a value", socketOpt[0])
128+ }
129+
130+ if socketOpt[0] == "mode" {
131+ mode, err := strconv.ParseUint(socketOpt[1], 8, 32)
132+ if err != nil {
133+ return nil, fmt.Errorf("unix socket file mode has invalid value %s", socketOpt[1])
134+ }
135+ socketMode = os.FileMode(mode)
136+ hasSocketMode = true
137+ }
138+ }
139+
140+ listener, err := net.Listen(networkType, socketPath)
141+ if err != nil {
142+ return nil, err
143+ }
144+
145+ if hasSocketMode {
146+ err = os.Chmod(socketPath, socketMode)
147+ if err != nil {
148+ return nil, fmt.Errorf("cannot set unix socket file mode on %s: %v", socketPath, err)
149+ }
150+ }
151+
152+ return listener, nil
153+}
154+
107155func parseCipherSuites(names []string) ([]uint16, error) {
108156 cipherNameMap := make(map[string]uint16)
109157
pkg/proxyhttp/server_test.go+50
@@ -28,6 +28,8 @@ var _ = Describe("Server", func() {
2828 expectedErr error
2929 expectHTTPListener bool
3030 expectTLSListener bool
31+ expectedSocketMode os.FileMode
32+ socketPath string
3133 fdAddr string
3234 ipv6 bool
3335 }
@@ -57,6 +59,12 @@ var _ = Describe("Server", func() {
5759 s, ok := srv.(*server)
5860 Expect(ok).To(BeTrue())
5961
62+ if in.socketPath != "" {
63+ fileInfo, err := os.Stat(in.socketPath)
64+ Expect(err).ToNot(HaveOccurred())
65+ Expect(fileInfo.Mode().Perm()).To(Equal(in.expectedSocketMode.Perm()))
66+ }
67+
6068 Expect(s.listener != nil).To(Equal(in.expectHTTPListener))
6169 if in.expectHTTPListener {
6270 Expect(s.listener.Close()).To(Succeed())
@@ -648,6 +656,48 @@ var _ = Describe("Server", func() {
648656 expectTLSListener: true,
649657 ipv6: true,
650658 }),
659+ Entry("with a valid unix socket path", &newServerTableInput{
660+ opts: Opts{
661+ Handler: handler,
662+ BindAddress: "unix:///tmp/oauth2-proxy.sock",
663+ },
664+ expectedErr: nil,
665+ expectHTTPListener: true,
666+ expectTLSListener: false,
667+ ipv6: false,
668+ }),
669+ Entry("with a valid unix socket path and a valid socket file mode", &newServerTableInput{
670+ opts: Opts{
671+ Handler: handler,
672+ BindAddress: "unix:///tmp/oauth2-proxy.sock,mode=0777",
673+ },
674+ expectedErr: nil,
675+ expectHTTPListener: true,
676+ expectTLSListener: false,
677+ expectedSocketMode: 0o777,
678+ socketPath: "/tmp/oauth2-proxy.sock",
679+ ipv6: false,
680+ }),
681+ Entry("with a valid unix socket path and a value-less socket file mode argument", &newServerTableInput{
682+ opts: Opts{
683+ Handler: handler,
684+ BindAddress: "unix:///tmp/oauth2-proxy.sock,mode",
685+ },
686+ expectedErr: errors.New("error setting up listener: listen (unix, /tmp/oauth2-proxy.sock,mode) failed: unix socket option mode expects a value"),
687+ expectHTTPListener: false,
688+ expectTLSListener: false,
689+ ipv6: false,
690+ }),
691+ Entry("with a valid unix socket path and an invalid socket file mode value", &newServerTableInput{
692+ opts: Opts{
693+ Handler: handler,
694+ BindAddress: "unix:///tmp/oauth2-proxy.sock,mode=-1",
695+ },
696+ expectedErr: errors.New("error setting up listener: listen (unix, /tmp/oauth2-proxy.sock,mode=-1) failed: unix socket file mode has invalid value -1"),
697+ expectHTTPListener: false,
698+ expectTLSListener: false,
699+ ipv6: false,
700+ }),
651701 )
652702 })
653703