mirror of
https://github.com/oauth2-proxy/oauth2-proxy.git
synced 2025-04-23 12:18:50 +02:00
Add support for systemd.socket
When using sockets to pass data between e.g. nginx and oauth2-proxy it's simpler to use sockets. Systemd can even facilitate this and pass the actual socket directly. This also means that only the socket runs with the same group as nginx while the service runs with DynamicUser. Does not support TLS yet. nginx ``` server { location /oauth2/ { proxy_pass http://unix:/run/oauth2-proxy/oauth2.sock; } ``` oauth2-proxy.socket ``` [Socket] ListenStream=%t/oauth2.sock SocketGroup=www-data SocketMode=0660 ``` Start oauth2-proxy with the parameter `--http-address=fd:3`. Signed-off-by: Josef Johansson <josef@oderland.se>
This commit is contained in:
parent
bc8e7162db
commit
6743a9cc89
@ -10,6 +10,7 @@
|
||||
|
||||
- [#2800](https://github.com/oauth2-proxy/oauth2-proxy/pull/2800) Add some opencontainer labels to docker image (@halkeye)
|
||||
- [#2755](https://github.com/oauth2-proxy/oauth2-proxy/pull/2755) feat: add X-Envoy-External-Address as supported header (@bjencks)
|
||||
- [#1985](https://github.com/oauth2-proxy/oauth2-proxy/pull/1985) Add support for systemd socket (@isodude)
|
||||
|
||||
# V7.7.1
|
||||
|
||||
@ -58,6 +59,7 @@
|
||||
- [#2790](https://github.com/oauth2-proxy/oauth2-proxy/pull/2790) chore(deps): update all golang dependencies (@tuunit)
|
||||
- [#2607](https://github.com/oauth2-proxy/oauth2-proxy/pull/2607) fix(csrf): fix possible infinite loop (@Primexz)
|
||||
|
||||
|
||||
# V7.6.0
|
||||
|
||||
## Release Highlights
|
||||
|
@ -219,7 +219,7 @@ Provider specific options can be found on their respective subpages.
|
||||
|
||||
| Flag / Config Field | Type | Description | Default |
|
||||
| ------------------------------------------------------------------- | -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------ |
|
||||
| flag: `--http-address`<br/>toml: `http_address` | string | `[http://]<addr>:<port>` or `unix://<path>` to listen on for HTTP clients. Square brackets are required for ipv6 address, e.g. `http://[::1]:4180` | `"127.0.0.1:4180"` |
|
||||
| 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"` |
|
||||
| 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"` |
|
||||
| flag: `--metrics-address`<br/>toml: `metrics_address` | string | the address prometheus metrics will be scraped from | `""` |
|
||||
| flag: `--metrics-secure-address`<br/>toml: `metrics_secure_address` | string | the address prometheus metrics will be scraped from if using HTTPS | `""` |
|
||||
|
43
docs/docs/configuration/systemd_socket.md
Normal file
43
docs/docs/configuration/systemd_socket.md
Normal file
@ -0,0 +1,43 @@
|
||||
---
|
||||
id: systemd_socket
|
||||
title: Systemd Socket Activation
|
||||
---
|
||||
|
||||
Pass an existing listener created by systemd.socket to oauth2-proxy.
|
||||
|
||||
To do this create a socket:
|
||||
|
||||
oauth2-proxy.socket
|
||||
```
|
||||
[Socket]
|
||||
ListenStream=%t/oauth2.sock
|
||||
SocketGroup=www-data
|
||||
SocketMode=0660
|
||||
```
|
||||
|
||||
Now it's possible to call this socket from e.g. nginx:
|
||||
```
|
||||
server {
|
||||
location /oauth2/ {
|
||||
proxy_pass http://unix:/run/oauth2-proxy/oauth2.sock;
|
||||
}
|
||||
```
|
||||
|
||||
The oauth2-proxy should have `--http-address=fd:3` as a parameter.
|
||||
Here fd is case insensitive and means file descriptor. The number 3 refers to the first non-stdin/stdout/stderr file descriptor,
|
||||
systemd-socket-activate (which is what systemd.socket uses), listens to what it is told and passes
|
||||
the listener it created onto the process, starting with file descriptor 3.
|
||||
|
||||
```
|
||||
./oauth2-proxy \
|
||||
--http-address="fd:3" \
|
||||
--email-domain="yourcompany.com" \
|
||||
--upstream=http://127.0.0.1:8080/ \
|
||||
--cookie-secret=... \
|
||||
--cookie-secure=true \
|
||||
--provider=... \
|
||||
--client-id=... \
|
||||
--client-secret=...
|
||||
```
|
||||
|
||||
Currently TLS is not supported (but it's doable).
|
@ -29,3 +29,4 @@ title: Installation
|
||||
2. [Select a Provider and Register an OAuth Application with a Provider](configuration/providers/index.md)
|
||||
3. [Configure OAuth2 Proxy using config file, command line options, or environment variables](configuration/overview.md)
|
||||
4. [Configure SSL or Deploy behind an SSL endpoint](configuration/tls.md) (example provided for Nginx)
|
||||
5. [Configure OAuth2 Proxy using systemd.socket](configuration/systemd_socket.md) (example provided for Nginx/Systemd)
|
||||
|
1
go.mod
1
go.mod
@ -11,6 +11,7 @@ require (
|
||||
github.com/bitly/go-simplejson v0.5.1
|
||||
github.com/bsm/redislock v0.9.4
|
||||
github.com/coreos/go-oidc/v3 v3.11.0
|
||||
github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf
|
||||
github.com/fsnotify/fsnotify v1.7.0
|
||||
github.com/ghodss/yaml v1.0.1-0.20220118164431-d8423dcdf344
|
||||
github.com/go-jose/go-jose/v3 v3.0.3
|
||||
|
2
go.sum
2
go.sum
@ -42,6 +42,8 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk
|
||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
github.com/coreos/go-oidc/v3 v3.11.0 h1:Ia3MxdwpSw702YW0xgfmP1GVCMA9aEFWu12XUZ3/OtI=
|
||||
github.com/coreos/go-oidc/v3 v3.11.0/go.mod h1:gE3LgjOgFoHi9a4ce4/tJczr0Ai2/BoDhf0r5lltWI0=
|
||||
github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf h1:iW4rZ826su+pqaw19uhpSCzhj44qo35pNgKFGqzDKkU=
|
||||
github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
||||
|
@ -470,7 +470,7 @@ func legacyServerFlagset() *pflag.FlagSet {
|
||||
flagSet.String("metrics-secure-address", "", "the address /metrics will be served on for HTTPS clients (e.g. \":9100\")")
|
||||
flagSet.String("metrics-tls-cert-file", "", "path to certificate file for secure metrics server")
|
||||
flagSet.String("metrics-tls-key-file", "", "path to private key file for secure metrics server")
|
||||
flagSet.String("http-address", "127.0.0.1:4180", "[http://]<addr>:<port> or unix://<path> to listen on for HTTP clients")
|
||||
flagSet.String("http-address", "127.0.0.1:4180", "[http://]<addr>:<port> or unix://<path> or fd:<int> (case insensitive) to listen on for HTTP clients")
|
||||
flagSet.String("https-address", ":443", "<addr>:<port> to listen on for HTTPS clients")
|
||||
flagSet.String("tls-cert-file", "", "path to certificate file")
|
||||
flagSet.String("tls-key-file", "", "path to private key file")
|
||||
|
@ -7,15 +7,27 @@ import (
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/coreos/go-systemd/activation"
|
||||
"github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/options"
|
||||
"github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/options/util"
|
||||
"github.com/oauth2-proxy/oauth2-proxy/v7/pkg/logger"
|
||||
"golang.org/x/sync/errgroup"
|
||||
)
|
||||
|
||||
// listenFdsStart corresponds to `SD_LISTEN_FDS_START`.
|
||||
// Since the 3 first file descriptors in every linux process is
|
||||
// stdin, stdout and stderr. The first usable file descriptor is 3.
|
||||
// systemd-socket-activate will always assume that the first socket will be
|
||||
// 3 and the rest follow.
|
||||
const (
|
||||
listenFdsStart = 3
|
||||
)
|
||||
|
||||
// Server represents an HTTP or HTTPS server.
|
||||
type Server interface {
|
||||
// Start blocks and runs the server.
|
||||
@ -35,6 +47,9 @@ type Opts struct {
|
||||
|
||||
// TLS is the TLS configuration for the server.
|
||||
TLS *options.TLS
|
||||
|
||||
// Let testing infrastructure circumvent parsing file descriptors
|
||||
fdFiles []*os.File
|
||||
}
|
||||
|
||||
// NewServer creates a new Server from the options given.
|
||||
@ -42,6 +57,11 @@ func NewServer(opts Opts) (Server, error) {
|
||||
s := &server{
|
||||
handler: opts.Handler,
|
||||
}
|
||||
|
||||
if len(opts.fdFiles) > 0 {
|
||||
s.fdFiles = opts.fdFiles
|
||||
}
|
||||
|
||||
if err := s.setupListener(opts); err != nil {
|
||||
return nil, fmt.Errorf("error setting up listener: %v", err)
|
||||
}
|
||||
@ -58,6 +78,30 @@ type server struct {
|
||||
|
||||
listener net.Listener
|
||||
tlsListener net.Listener
|
||||
|
||||
// ensure activation.Files are called once
|
||||
fdFiles []*os.File
|
||||
}
|
||||
|
||||
// convert a string filedescriptor to an actual listener
|
||||
func (s *server) fdToListener(bindAddress string) (net.Listener, error) {
|
||||
fd, err := strconv.Atoi(bindAddress)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("listen failed: fd with name is not implemented yet")
|
||||
}
|
||||
fdIndex := fd - listenFdsStart
|
||||
|
||||
if len(s.fdFiles) == 0 {
|
||||
s.fdFiles = activation.Files(true)
|
||||
}
|
||||
|
||||
l := len(s.fdFiles)
|
||||
|
||||
if fdIndex < 0 || fdIndex >= l || l == 0 {
|
||||
return nil, fmt.Errorf("listen failed: fd outside of range of available file descriptors")
|
||||
}
|
||||
|
||||
return net.FileListener(s.fdFiles[fdIndex])
|
||||
}
|
||||
|
||||
// setupListener sets the server listener if the HTTP server is enabled.
|
||||
@ -69,6 +113,22 @@ func (s *server) setupListener(opts Opts) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Use fd: as a prefix for systemd socket activation, it's generic
|
||||
// enough and short.
|
||||
// The most common usage would be --http-address fd:3.
|
||||
// This causes oauth2-proxy to just assume that the third fd passed
|
||||
// to the program is indeed a net.Listener and starts using it
|
||||
// without setting up a new listener.
|
||||
if strings.HasPrefix(strings.ToLower(opts.BindAddress), "fd:") {
|
||||
listenAddr := opts.BindAddress[3:]
|
||||
listener, err := s.fdToListener(listenAddr)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("listen (%s, %s) failed: %v", "file", listenAddr, err)
|
||||
}
|
||||
s.listener = listener
|
||||
return err
|
||||
}
|
||||
|
||||
networkType := getNetworkScheme(opts.BindAddress)
|
||||
listenAddr := getListenAddress(opts.BindAddress)
|
||||
|
||||
|
@ -5,6 +5,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
|
||||
@ -17,16 +18,17 @@ import (
|
||||
const hello = "Hello World!"
|
||||
|
||||
var _ = Describe("Server", func() {
|
||||
|
||||
handler := http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
||||
rw.Write([]byte(hello))
|
||||
})
|
||||
|
||||
Context("NewServer", func() {
|
||||
type newServerTableInput struct {
|
||||
opts Opts
|
||||
expectedErr error
|
||||
expectHTTPListener bool
|
||||
expectTLSListener bool
|
||||
fdAddr string
|
||||
ipv6 bool
|
||||
}
|
||||
|
||||
@ -34,6 +36,15 @@ var _ = Describe("Server", func() {
|
||||
if in.ipv6 {
|
||||
skipDevContainer()
|
||||
}
|
||||
|
||||
if in.fdAddr != "" {
|
||||
l, err := net.Listen("tcp", in.fdAddr)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
f, err := l.(*net.TCPListener).File()
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
in.opts.fdFiles = []*os.File{f}
|
||||
}
|
||||
|
||||
srv, err := NewServer(in.opts)
|
||||
if in.expectedErr != nil {
|
||||
Expect(err).To(MatchError(ContainSubstring(in.expectedErr.Error())))
|
||||
@ -55,6 +66,46 @@ var _ = Describe("Server", func() {
|
||||
Expect(s.tlsListener.Close()).To(Succeed())
|
||||
}
|
||||
},
|
||||
Entry("with a valid non-lowercase fd IPv4 bind address", &newServerTableInput{
|
||||
opts: Opts{
|
||||
Handler: handler,
|
||||
BindAddress: "Fd:3",
|
||||
},
|
||||
expectedErr: nil,
|
||||
expectHTTPListener: true,
|
||||
expectTLSListener: false,
|
||||
fdAddr: "127.0.0.1:0",
|
||||
}),
|
||||
Entry("with a valid fd IPv4 bind address", &newServerTableInput{
|
||||
opts: Opts{
|
||||
Handler: handler,
|
||||
BindAddress: "fd:3",
|
||||
},
|
||||
expectedErr: nil,
|
||||
expectHTTPListener: true,
|
||||
expectTLSListener: false,
|
||||
fdAddr: "127.0.0.1:0",
|
||||
}),
|
||||
Entry("with a invalid fd named bind address", &newServerTableInput{
|
||||
opts: Opts{
|
||||
Handler: handler,
|
||||
BindAddress: "fd:hello",
|
||||
},
|
||||
expectedErr: fmt.Errorf("error setting up listener: listen (file, %s) failed: listen failed: fd with name is not implemented yet", "hello"),
|
||||
expectHTTPListener: true,
|
||||
expectTLSListener: false,
|
||||
fdAddr: "127.0.0.1:0",
|
||||
}),
|
||||
Entry("with a invalid fd IPv4 bind address", &newServerTableInput{
|
||||
opts: Opts{
|
||||
Handler: handler,
|
||||
BindAddress: "fd:4",
|
||||
},
|
||||
expectedErr: fmt.Errorf("error setting up listener: listen (file, %d) failed: listen failed: fd outside of range of available file descriptors", 4),
|
||||
expectHTTPListener: true,
|
||||
expectTLSListener: false,
|
||||
fdAddr: "127.0.0.1:0",
|
||||
}),
|
||||
Entry("with an ipv4 valid http bind address", &newServerTableInput{
|
||||
opts: Opts{
|
||||
Handler: handler,
|
||||
@ -86,6 +137,21 @@ var _ = Describe("Server", func() {
|
||||
expectHTTPListener: false,
|
||||
expectTLSListener: true,
|
||||
}),
|
||||
Entry("with a both a fd valid http and ipv4 valid https bind address, and valid TLS config", &newServerTableInput{
|
||||
opts: Opts{
|
||||
Handler: handler,
|
||||
BindAddress: "fd:3",
|
||||
SecureBindAddress: "127.0.0.1:0",
|
||||
TLS: &options.TLS{
|
||||
Key: &ipv4KeyDataSource,
|
||||
Cert: &ipv4CertDataSource,
|
||||
},
|
||||
},
|
||||
expectedErr: nil,
|
||||
expectHTTPListener: true,
|
||||
expectTLSListener: true,
|
||||
fdAddr: "127.0.0.1:0",
|
||||
}),
|
||||
Entry("with a both a ipv4 valid http and ipv4 valid https bind address, and valid TLS config", &newServerTableInput{
|
||||
opts: Opts{
|
||||
Handler: handler,
|
||||
@ -300,6 +366,27 @@ var _ = Describe("Server", func() {
|
||||
expectHTTPListener: false,
|
||||
expectTLSListener: true,
|
||||
}),
|
||||
Entry("with valid fd IPv6 bind address", &newServerTableInput{
|
||||
opts: Opts{
|
||||
Handler: handler,
|
||||
BindAddress: "fd:3",
|
||||
},
|
||||
expectedErr: nil,
|
||||
expectHTTPListener: true,
|
||||
expectTLSListener: false,
|
||||
fdAddr: "[::1]:0",
|
||||
ipv6: true,
|
||||
}),
|
||||
Entry("with a invalid fd IPv6 bind address", &newServerTableInput{
|
||||
opts: Opts{
|
||||
Handler: handler,
|
||||
BindAddress: "fd:4",
|
||||
},
|
||||
expectedErr: fmt.Errorf("error setting up listener: listen (file, %d) failed: listen failed: fd outside of range of available file descriptors", 4),
|
||||
expectHTTPListener: true,
|
||||
expectTLSListener: false,
|
||||
fdAddr: "[::1]:0",
|
||||
}),
|
||||
Entry("with an ipv6 valid http bind address", &newServerTableInput{
|
||||
opts: Opts{
|
||||
Handler: handler,
|
||||
@ -334,6 +421,22 @@ var _ = Describe("Server", func() {
|
||||
expectTLSListener: true,
|
||||
ipv6: true,
|
||||
}),
|
||||
Entry("with a both a fd valid http and ipv6 valid https bind address, and valid TLS config", &newServerTableInput{
|
||||
opts: Opts{
|
||||
Handler: handler,
|
||||
BindAddress: "fd:3",
|
||||
SecureBindAddress: "[::1]:0",
|
||||
TLS: &options.TLS{
|
||||
Key: &ipv6KeyDataSource,
|
||||
Cert: &ipv6CertDataSource,
|
||||
},
|
||||
},
|
||||
expectedErr: nil,
|
||||
expectHTTPListener: true,
|
||||
expectTLSListener: true,
|
||||
fdAddr: "[::1]:0",
|
||||
ipv6: true,
|
||||
}),
|
||||
Entry("with a both a ipv6 valid http and ipv6 valid https bind address, and valid TLS config", &newServerTableInput{
|
||||
opts: Opts{
|
||||
Handler: handler,
|
||||
@ -563,6 +666,58 @@ var _ = Describe("Server", func() {
|
||||
|
||||
})
|
||||
|
||||
Context("with an fd ipv4 http server", func() {
|
||||
var listenAddr string
|
||||
|
||||
BeforeEach(func() {
|
||||
l, err := net.Listen("tcp", "127.0.0.1:0")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
f, err := l.(*net.TCPListener).File()
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
srv, err = NewServer(Opts{
|
||||
Handler: handler,
|
||||
BindAddress: "fd:3",
|
||||
fdFiles: []*os.File{f},
|
||||
})
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
listenAddr = fmt.Sprintf("http://%s/", l.Addr().String())
|
||||
})
|
||||
|
||||
It("Starts the server and serves the handler", func() {
|
||||
go func() {
|
||||
defer GinkgoRecover()
|
||||
Expect(srv.Start(ctx)).To(Succeed())
|
||||
}()
|
||||
|
||||
resp, err := httpGet(ctx, listenAddr)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(resp.StatusCode).To(Equal(http.StatusOK))
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(string(body)).To(Equal(hello))
|
||||
})
|
||||
|
||||
It("Stops the server when the context is cancelled", func() {
|
||||
go func() {
|
||||
defer GinkgoRecover()
|
||||
Expect(srv.Start(ctx)).To(Succeed())
|
||||
}()
|
||||
|
||||
_, err := httpGet(ctx, listenAddr)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
cancel()
|
||||
|
||||
Eventually(func() error {
|
||||
_, err := httpGet(ctx, listenAddr)
|
||||
return err
|
||||
}).Should(HaveOccurred())
|
||||
})
|
||||
})
|
||||
|
||||
Context("with an ipv4 http server", func() {
|
||||
var listenAddr string
|
||||
|
||||
@ -682,6 +837,88 @@ var _ = Describe("Server", func() {
|
||||
})
|
||||
})
|
||||
|
||||
Context("with a fd ipv4 http and an ipv4 https server", func() {
|
||||
var listenAddr, secureListenAddr string
|
||||
|
||||
BeforeEach(func() {
|
||||
l, err := net.Listen("tcp", "127.0.0.1:0")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
f, err := l.(*net.TCPListener).File()
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
srv, err = NewServer(Opts{
|
||||
Handler: handler,
|
||||
BindAddress: "fd:3",
|
||||
fdFiles: []*os.File{f},
|
||||
SecureBindAddress: "127.0.0.1:0",
|
||||
TLS: &options.TLS{
|
||||
Key: &ipv4KeyDataSource,
|
||||
Cert: &ipv4CertDataSource,
|
||||
},
|
||||
})
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
s, ok := srv.(*server)
|
||||
Expect(ok).To(BeTrue())
|
||||
|
||||
listenAddr = fmt.Sprintf("http://%s/", l.Addr().String())
|
||||
secureListenAddr = fmt.Sprintf("https://%s/", s.tlsListener.Addr().String())
|
||||
})
|
||||
|
||||
It("Starts the server and serves the handler on http", func() {
|
||||
go func() {
|
||||
defer GinkgoRecover()
|
||||
Expect(srv.Start(ctx)).To(Succeed())
|
||||
}()
|
||||
|
||||
resp, err := httpGet(ctx, listenAddr)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(resp.StatusCode).To(Equal(http.StatusOK))
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(string(body)).To(Equal(hello))
|
||||
})
|
||||
|
||||
It("Starts the server and serves the handler on https", func() {
|
||||
go func() {
|
||||
defer GinkgoRecover()
|
||||
Expect(srv.Start(ctx)).To(Succeed())
|
||||
}()
|
||||
|
||||
resp, err := httpGet(ctx, secureListenAddr)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(resp.StatusCode).To(Equal(http.StatusOK))
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(string(body)).To(Equal(hello))
|
||||
})
|
||||
|
||||
It("Stops both servers when the context is cancelled", func() {
|
||||
go func() {
|
||||
defer GinkgoRecover()
|
||||
Expect(srv.Start(ctx)).To(Succeed())
|
||||
}()
|
||||
|
||||
_, err := httpGet(ctx, listenAddr)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
_, err = httpGet(ctx, secureListenAddr)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
cancel()
|
||||
|
||||
Eventually(func() error {
|
||||
_, err := httpGet(ctx, listenAddr)
|
||||
return err
|
||||
}).Should(HaveOccurred())
|
||||
Eventually(func() error {
|
||||
_, err := httpGet(ctx, secureListenAddr)
|
||||
return err
|
||||
}).Should(HaveOccurred())
|
||||
})
|
||||
})
|
||||
|
||||
Context("with both an ipv4 http and an ipv4 https server", func() {
|
||||
var listenAddr, secureListenAddr string
|
||||
|
||||
@ -880,6 +1117,89 @@ var _ = Describe("Server", func() {
|
||||
})
|
||||
})
|
||||
|
||||
Context("with an fd ipv6 http and an ipv6 https server", func() {
|
||||
var listenAddr, secureListenAddr string
|
||||
|
||||
BeforeEach(func() {
|
||||
skipDevContainer()
|
||||
l, err := net.Listen("tcp", "[::1]:0")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
f, err := l.(*net.TCPListener).File()
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
srv, err = NewServer(Opts{
|
||||
Handler: handler,
|
||||
BindAddress: "fd:3",
|
||||
fdFiles: []*os.File{f},
|
||||
SecureBindAddress: "[::1]:0",
|
||||
TLS: &options.TLS{
|
||||
Key: &ipv6KeyDataSource,
|
||||
Cert: &ipv6CertDataSource,
|
||||
},
|
||||
})
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
s, ok := srv.(*server)
|
||||
Expect(ok).To(BeTrue())
|
||||
|
||||
listenAddr = fmt.Sprintf("http://%s/", l.Addr().String())
|
||||
secureListenAddr = fmt.Sprintf("https://%s/", s.tlsListener.Addr().String())
|
||||
})
|
||||
|
||||
It("Starts the server and serves the handler on http", func() {
|
||||
go func() {
|
||||
defer GinkgoRecover()
|
||||
Expect(srv.Start(ctx)).To(Succeed())
|
||||
}()
|
||||
|
||||
resp, err := httpGet(ctx, listenAddr)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(resp.StatusCode).To(Equal(http.StatusOK))
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(string(body)).To(Equal(hello))
|
||||
})
|
||||
|
||||
It("Starts the server and serves the handler on https", func() {
|
||||
go func() {
|
||||
defer GinkgoRecover()
|
||||
Expect(srv.Start(ctx)).To(Succeed())
|
||||
}()
|
||||
|
||||
resp, err := httpGet(ctx, secureListenAddr)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(resp.StatusCode).To(Equal(http.StatusOK))
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(string(body)).To(Equal(hello))
|
||||
})
|
||||
|
||||
It("Stops both servers when the context is cancelled", func() {
|
||||
go func() {
|
||||
defer GinkgoRecover()
|
||||
Expect(srv.Start(ctx)).To(Succeed())
|
||||
}()
|
||||
|
||||
_, err := httpGet(ctx, listenAddr)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
_, err = httpGet(ctx, secureListenAddr)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
cancel()
|
||||
|
||||
Eventually(func() error {
|
||||
_, err := httpGet(ctx, listenAddr)
|
||||
return err
|
||||
}).Should(HaveOccurred())
|
||||
Eventually(func() error {
|
||||
_, err := httpGet(ctx, secureListenAddr)
|
||||
return err
|
||||
}).Should(HaveOccurred())
|
||||
})
|
||||
})
|
||||
|
||||
Context("with both an ipv6 http and an ipv6 https server", func() {
|
||||
var listenAddr, secureListenAddr string
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user