1
0
mirror of https://github.com/oauth2-proxy/oauth2-proxy.git synced 2024-11-24 08:52:25 +02:00

Add description on ipv6 address (#1635)

* add docs on ipv6

* add tests for ipv6 address

* add tests for ipv6 address

* remove Print function for debugging

* Updated changelog
This commit is contained in:
t-katsumura 2022-05-23 18:17:29 +09:00 committed by GitHub
parent 743c344fdc
commit c6a98369a0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 486 additions and 67 deletions

View File

@ -41,6 +41,7 @@ If you are using an architecture specific tag (ex: v7.2.1-arm64) you should move
- [#1594](https://github.com/oauth2-proxy/oauth2-proxy/pull/1594) Release ARMv8 docker images (@braunsonm) - [#1594](https://github.com/oauth2-proxy/oauth2-proxy/pull/1594) Release ARMv8 docker images (@braunsonm)
- [#1649](https://github.com/oauth2-proxy/oauth2-proxy/pull/1649) Return a 400 instead of a 500 when a request contains an invalid redirect target (@niksko) - [#1649](https://github.com/oauth2-proxy/oauth2-proxy/pull/1649) Return a 400 instead of a 500 when a request contains an invalid redirect target (@niksko)
- [#1638](https://github.com/oauth2-proxy/oauth2-proxy/pull/1638) Implement configurable upstream timeout (@jacksgt) - [#1638](https://github.com/oauth2-proxy/oauth2-proxy/pull/1638) Implement configurable upstream timeout (@jacksgt)
- [#1635](https://github.com/oauth2-proxy/oauth2-proxy/pull/1635) Added description and unit tests for ipv6 address (@t-katsumura)
# V7.2.1 # V7.2.1

View File

@ -119,8 +119,8 @@ An example [oauth2-proxy.cfg](https://github.com/oauth2-proxy/oauth2-proxy/blob/
| `--google-service-account-json` | string | the path to the service account json credentials | | | `--google-service-account-json` | string | the path to the service account json credentials | |
| `--htpasswd-file` | string | additionally authenticate against a htpasswd file. Entries must be created with `htpasswd -B` for bcrypt encryption | | | `--htpasswd-file` | string | additionally authenticate against a htpasswd file. Entries must be created with `htpasswd -B` for bcrypt encryption | |
| `--htpasswd-user-group` | string \| list | the groups to be set on sessions for htpasswd users | | | `--htpasswd-user-group` | string \| list | the groups to be set on sessions for htpasswd users | |
| `--http-address` | string | `[http://]<addr>:<port>` or `unix://<path>` to listen on for HTTP clients | `"127.0.0.1:4180"` | | `--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"` |
| `--https-address` | string | `<addr>:<port>` to listen on for HTTPS clients | `":443"` | | `--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"` |
| `--logging-compress` | bool | Should rotated log files be compressed using gzip | false | | `--logging-compress` | bool | Should rotated log files be compressed using gzip | false |
| `--logging-filename` | string | File to log requests to, empty for `stdout` | `""` (stdout) | | `--logging-filename` | string | File to log requests to, empty for `stdout` | `""` (stdout) |
| `--logging-local-time` | bool | Use local time in log files and backup filenames instead of UTC | true (local time) | | `--logging-local-time` | bool | Use local time in log files and backup filenames instead of UTC | true (local time) |

View File

@ -15,8 +15,9 @@ import (
. "github.com/onsi/gomega" . "github.com/onsi/gomega"
) )
var certData []byte var ipv4CertData, ipv6CertData []byte
var certDataSource, keyDataSource options.SecretSource var ipv4CertDataSource, ipv4KeyDataSource options.SecretSource
var ipv6CertDataSource, ipv6KeyDataSource options.SecretSource
var client *http.Client var client *http.Client
func TestHTTPSuite(t *testing.T) { func TestHTTPSuite(t *testing.T) {
@ -28,28 +29,46 @@ func TestHTTPSuite(t *testing.T) {
} }
var _ = BeforeSuite(func() { var _ = BeforeSuite(func() {
By("Generating a self-signed cert for TLS tests", func() { By("Generating a ipv4 self-signed cert for TLS tests", func() {
certBytes, keyBytes, err := util.GenerateCert() certBytes, keyBytes, err := util.GenerateCert("127.0.0.1")
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
certData = certBytes ipv4CertData = certBytes
certOut := new(bytes.Buffer) certOut := new(bytes.Buffer)
Expect(pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: certBytes})).To(Succeed()) Expect(pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: certBytes})).To(Succeed())
certDataSource.Value = certOut.Bytes() ipv4CertDataSource.Value = certOut.Bytes()
keyOut := new(bytes.Buffer) keyOut := new(bytes.Buffer)
Expect(pem.Encode(keyOut, &pem.Block{Type: "PRIVATE KEY", Bytes: keyBytes})).To(Succeed()) Expect(pem.Encode(keyOut, &pem.Block{Type: "PRIVATE KEY", Bytes: keyBytes})).To(Succeed())
keyDataSource.Value = keyOut.Bytes() ipv4KeyDataSource.Value = keyOut.Bytes()
})
By("Generating a ipv6 self-signed cert for TLS tests", func() {
certBytes, keyBytes, err := util.GenerateCert("::1")
Expect(err).ToNot(HaveOccurred())
ipv6CertData = certBytes
certOut := new(bytes.Buffer)
Expect(pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: certBytes})).To(Succeed())
ipv6CertDataSource.Value = certOut.Bytes()
keyOut := new(bytes.Buffer)
Expect(pem.Encode(keyOut, &pem.Block{Type: "PRIVATE KEY", Bytes: keyBytes})).To(Succeed())
ipv6KeyDataSource.Value = keyOut.Bytes()
}) })
By("Setting up a http client", func() { By("Setting up a http client", func() {
cert, err := tls.X509KeyPair(certDataSource.Value, keyDataSource.Value) ipv4cert, err := tls.X509KeyPair(ipv4CertDataSource.Value, ipv4KeyDataSource.Value)
Expect(err).ToNot(HaveOccurred())
ipv6cert, err := tls.X509KeyPair(ipv6CertDataSource.Value, ipv6KeyDataSource.Value)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
certificate, err := x509.ParseCertificate(cert.Certificate[0]) ipv4certificate, err := x509.ParseCertificate(ipv4cert.Certificate[0])
Expect(err).ToNot(HaveOccurred())
ipv6certificate, err := x509.ParseCertificate(ipv6cert.Certificate[0])
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
certpool := x509.NewCertPool() certpool := x509.NewCertPool()
certpool.AddCert(certificate) certpool.AddCert(ipv4certificate)
certpool.AddCert(ipv6certificate)
transport := http.DefaultTransport.(*http.Transport).Clone() transport := http.DefaultTransport.(*http.Transport).Clone()
transport.TLSClientConfig.RootCAs = certpool transport.TLSClientConfig.RootCAs = certpool

View File

@ -50,7 +50,7 @@ var _ = Describe("Server", func() {
Expect(s.tlsListener.Close()).To(Succeed()) Expect(s.tlsListener.Close()).To(Succeed())
} }
}, },
Entry("with a valid http bind address", &newServerTableInput{ Entry("with an ipv4 valid http bind address", &newServerTableInput{
opts: Opts{ opts: Opts{
Handler: handler, Handler: handler,
BindAddress: "127.0.0.1:0", BindAddress: "127.0.0.1:0",
@ -59,7 +59,7 @@ var _ = Describe("Server", func() {
expectHTTPListener: true, expectHTTPListener: true,
expectTLSListener: false, expectTLSListener: false,
}), }),
Entry("with a valid https bind address, with no TLS config", &newServerTableInput{ Entry("with an ipv4 valid https bind address, with no TLS config", &newServerTableInput{
opts: Opts{ opts: Opts{
Handler: handler, Handler: handler,
SecureBindAddress: "127.0.0.1:0", SecureBindAddress: "127.0.0.1:0",
@ -68,27 +68,27 @@ var _ = Describe("Server", func() {
expectHTTPListener: false, expectHTTPListener: false,
expectTLSListener: false, expectTLSListener: false,
}), }),
Entry("with a valid https bind address, and valid TLS config", &newServerTableInput{ Entry("with an ipv4 valid https bind address, and valid TLS config", &newServerTableInput{
opts: Opts{ opts: Opts{
Handler: handler, Handler: handler,
SecureBindAddress: "127.0.0.1:0", SecureBindAddress: "127.0.0.1:0",
TLS: &options.TLS{ TLS: &options.TLS{
Key: &keyDataSource, Key: &ipv4KeyDataSource,
Cert: &certDataSource, Cert: &ipv4CertDataSource,
}, },
}, },
expectedErr: nil, expectedErr: nil,
expectHTTPListener: false, expectHTTPListener: false,
expectTLSListener: true, expectTLSListener: true,
}), }),
Entry("with a both a valid http and valid https bind address, and valid TLS config", &newServerTableInput{ Entry("with a both a ipv4 valid http and ipv4 valid https bind address, and valid TLS config", &newServerTableInput{
opts: Opts{ opts: Opts{
Handler: handler, Handler: handler,
BindAddress: "127.0.0.1:0", BindAddress: "127.0.0.1:0",
SecureBindAddress: "127.0.0.1:0", SecureBindAddress: "127.0.0.1:0",
TLS: &options.TLS{ TLS: &options.TLS{
Key: &keyDataSource, Key: &ipv4KeyDataSource,
Cert: &certDataSource, Cert: &ipv4CertDataSource,
}, },
}, },
expectedErr: nil, expectedErr: nil,
@ -113,7 +113,7 @@ var _ = Describe("Server", func() {
expectHTTPListener: false, expectHTTPListener: false,
expectTLSListener: false, expectTLSListener: false,
}), }),
Entry("with an invalid bind address scheme", &newServerTableInput{ Entry("with an ipv4 invalid bind address scheme", &newServerTableInput{
opts: Opts{ opts: Opts{
Handler: handler, Handler: handler,
BindAddress: "invalid://127.0.0.1:0", BindAddress: "invalid://127.0.0.1:0",
@ -122,20 +122,20 @@ var _ = Describe("Server", func() {
expectHTTPListener: false, expectHTTPListener: false,
expectTLSListener: false, expectTLSListener: false,
}), }),
Entry("with an invalid secure bind address scheme", &newServerTableInput{ Entry("with an ipv4 invalid secure bind address scheme", &newServerTableInput{
opts: Opts{ opts: Opts{
Handler: handler, Handler: handler,
SecureBindAddress: "invalid://127.0.0.1:0", SecureBindAddress: "invalid://127.0.0.1:0",
TLS: &options.TLS{ TLS: &options.TLS{
Key: &keyDataSource, Key: &ipv4KeyDataSource,
Cert: &certDataSource, Cert: &ipv4CertDataSource,
}, },
}, },
expectedErr: nil, expectedErr: nil,
expectHTTPListener: false, expectHTTPListener: false,
expectTLSListener: true, expectTLSListener: true,
}), }),
Entry("with an invalid bind address port", &newServerTableInput{ Entry("with an ipv4 invalid bind address port", &newServerTableInput{
opts: Opts{ opts: Opts{
Handler: handler, Handler: handler,
BindAddress: "127.0.0.1:a", BindAddress: "127.0.0.1:a",
@ -144,20 +144,20 @@ var _ = Describe("Server", func() {
expectHTTPListener: false, expectHTTPListener: false,
expectTLSListener: false, expectTLSListener: false,
}), }),
Entry("with an invalid secure bind address port", &newServerTableInput{ Entry("with an ipv4 invalid secure bind address port", &newServerTableInput{
opts: Opts{ opts: Opts{
Handler: handler, Handler: handler,
SecureBindAddress: "127.0.0.1:a", SecureBindAddress: "127.0.0.1:a",
TLS: &options.TLS{ TLS: &options.TLS{
Key: &keyDataSource, Key: &ipv4KeyDataSource,
Cert: &certDataSource, Cert: &ipv4CertDataSource,
}, },
}, },
expectedErr: errors.New("error setting up TLS listener: listen (127.0.0.1:a) failed: listen tcp: "), expectedErr: errors.New("error setting up TLS listener: listen (127.0.0.1:a) failed: listen tcp: "),
expectHTTPListener: false, expectHTTPListener: false,
expectTLSListener: false, expectTLSListener: false,
}), }),
Entry("with an invalid TLS key", &newServerTableInput{ Entry("with an ipv4 invalid TLS key", &newServerTableInput{
opts: Opts{ opts: Opts{
Handler: handler, Handler: handler,
SecureBindAddress: "127.0.0.1:0", SecureBindAddress: "127.0.0.1:0",
@ -165,19 +165,19 @@ var _ = Describe("Server", func() {
Key: &options.SecretSource{ Key: &options.SecretSource{
Value: []byte("invalid"), Value: []byte("invalid"),
}, },
Cert: &certDataSource, Cert: &ipv4CertDataSource,
}, },
}, },
expectedErr: errors.New("error setting up TLS listener: could not load certificate: could not parse certificate data: tls: failed to find any PEM data in key input"), expectedErr: errors.New("error setting up TLS listener: could not load certificate: could not parse certificate data: tls: failed to find any PEM data in key input"),
expectHTTPListener: false, expectHTTPListener: false,
expectTLSListener: false, expectTLSListener: false,
}), }),
Entry("with an invalid TLS cert", &newServerTableInput{ Entry("with an ipv4 invalid TLS cert", &newServerTableInput{
opts: Opts{ opts: Opts{
Handler: handler, Handler: handler,
SecureBindAddress: "127.0.0.1:0", SecureBindAddress: "127.0.0.1:0",
TLS: &options.TLS{ TLS: &options.TLS{
Key: &keyDataSource, Key: &ipv4KeyDataSource,
Cert: &options.SecretSource{ Cert: &options.SecretSource{
Value: []byte("invalid"), Value: []byte("invalid"),
}, },
@ -187,31 +187,31 @@ var _ = Describe("Server", func() {
expectHTTPListener: false, expectHTTPListener: false,
expectTLSListener: false, expectTLSListener: false,
}), }),
Entry("with no TLS key", &newServerTableInput{ Entry("with an ipv4 address, with no TLS key", &newServerTableInput{
opts: Opts{ opts: Opts{
Handler: handler, Handler: handler,
SecureBindAddress: "127.0.0.1:0", SecureBindAddress: "127.0.0.1:0",
TLS: &options.TLS{ TLS: &options.TLS{
Cert: &certDataSource, Cert: &ipv4CertDataSource,
}, },
}, },
expectedErr: errors.New("error setting up TLS listener: could not load certificate: could not load key data: no configuration provided"), expectedErr: errors.New("error setting up TLS listener: could not load certificate: could not load key data: no configuration provided"),
expectHTTPListener: false, expectHTTPListener: false,
expectTLSListener: false, expectTLSListener: false,
}), }),
Entry("with no TLS cert", &newServerTableInput{ Entry("with an ipv4 address, with no TLS cert", &newServerTableInput{
opts: Opts{ opts: Opts{
Handler: handler, Handler: handler,
SecureBindAddress: "127.0.0.1:0", SecureBindAddress: "127.0.0.1:0",
TLS: &options.TLS{ TLS: &options.TLS{
Key: &keyDataSource, Key: &ipv4KeyDataSource,
}, },
}, },
expectedErr: errors.New("error setting up TLS listener: could not load certificate: could not load cert data: no configuration provided"), expectedErr: errors.New("error setting up TLS listener: could not load certificate: could not load cert data: no configuration provided"),
expectHTTPListener: false, expectHTTPListener: false,
expectTLSListener: false, expectTLSListener: false,
}), }),
Entry("when the bind address is prefixed with the http scheme", &newServerTableInput{ Entry("when the ipv4 bind address is prefixed with the http scheme", &newServerTableInput{
opts: Opts{ opts: Opts{
Handler: handler, Handler: handler,
BindAddress: "http://127.0.0.1:0", BindAddress: "http://127.0.0.1:0",
@ -220,26 +220,26 @@ var _ = Describe("Server", func() {
expectHTTPListener: true, expectHTTPListener: true,
expectTLSListener: false, expectTLSListener: false,
}), }),
Entry("when the secure bind address is prefixed with the https scheme", &newServerTableInput{ Entry("when the ipv4 secure bind address is prefixed with the https scheme", &newServerTableInput{
opts: Opts{ opts: Opts{
Handler: handler, Handler: handler,
SecureBindAddress: "https://127.0.0.1:0", SecureBindAddress: "https://127.0.0.1:0",
TLS: &options.TLS{ TLS: &options.TLS{
Key: &keyDataSource, Key: &ipv4KeyDataSource,
Cert: &certDataSource, Cert: &ipv4CertDataSource,
}, },
}, },
expectedErr: nil, expectedErr: nil,
expectHTTPListener: false, expectHTTPListener: false,
expectTLSListener: true, expectTLSListener: true,
}), }),
Entry("with a valid https bind address, and valid TLS config with MinVersion", &newServerTableInput{ Entry("with an ipv4 valid https bind address, and valid TLS config with MinVersion", &newServerTableInput{
opts: Opts{ opts: Opts{
Handler: handler, Handler: handler,
SecureBindAddress: "127.0.0.1:0", SecureBindAddress: "127.0.0.1:0",
TLS: &options.TLS{ TLS: &options.TLS{
Key: &keyDataSource, Key: &ipv4KeyDataSource,
Cert: &certDataSource, Cert: &ipv4CertDataSource,
MinVersion: "TLS1.3", MinVersion: "TLS1.3",
}, },
}, },
@ -247,13 +247,206 @@ var _ = Describe("Server", func() {
expectHTTPListener: false, expectHTTPListener: false,
expectTLSListener: true, expectTLSListener: true,
}), }),
Entry("with a valid https bind address, and invalid TLS config with unknown MinVersion", &newServerTableInput{ Entry("with an ipv4 valid https bind address, and invalid TLS config with unknown MinVersion", &newServerTableInput{
opts: Opts{ opts: Opts{
Handler: handler, Handler: handler,
SecureBindAddress: "127.0.0.1:0", SecureBindAddress: "127.0.0.1:0",
TLS: &options.TLS{ TLS: &options.TLS{
Key: &keyDataSource, Key: &ipv4KeyDataSource,
Cert: &certDataSource, Cert: &ipv4CertDataSource,
MinVersion: "TLS1.42",
},
},
expectedErr: errors.New("error setting up TLS listener: unknown TLS MinVersion config provided"),
expectHTTPListener: false,
expectTLSListener: true,
}),
Entry("with an ipv6 valid http bind address", &newServerTableInput{
opts: Opts{
Handler: handler,
BindAddress: "[::1]:0",
},
expectedErr: nil,
expectHTTPListener: true,
expectTLSListener: false,
}),
Entry("with an ipv6 valid https bind address, with no TLS config", &newServerTableInput{
opts: Opts{
Handler: handler,
SecureBindAddress: "[::1]:0",
},
expectedErr: errors.New("error setting up TLS listener: no TLS config provided"),
expectHTTPListener: false,
expectTLSListener: false,
}),
Entry("with an ipv6 valid https bind address, and valid TLS config", &newServerTableInput{
opts: Opts{
Handler: handler,
SecureBindAddress: "[::1]:0",
TLS: &options.TLS{
Key: &ipv6KeyDataSource,
Cert: &ipv6CertDataSource,
},
},
expectedErr: nil,
expectHTTPListener: false,
expectTLSListener: true,
}),
Entry("with a both a ipv6 valid http and ipv6 valid https bind address, and valid TLS config", &newServerTableInput{
opts: Opts{
Handler: handler,
BindAddress: "[::1]:0",
SecureBindAddress: "[::1]:0",
TLS: &options.TLS{
Key: &ipv6KeyDataSource,
Cert: &ipv6CertDataSource,
},
},
expectedErr: nil,
expectHTTPListener: true,
expectTLSListener: true,
}),
Entry("with an ipv6 invalid bind address scheme", &newServerTableInput{
opts: Opts{
Handler: handler,
BindAddress: "invalid://[::1]:0",
},
expectedErr: errors.New("error setting up listener: listen (invalid, [::1]:0) failed: listen invalid: unknown network invalid"),
expectHTTPListener: false,
expectTLSListener: false,
}),
Entry("with an ipv6 invalid secure bind address scheme", &newServerTableInput{
opts: Opts{
Handler: handler,
SecureBindAddress: "invalid://[::1]:0",
TLS: &options.TLS{
Key: &ipv6KeyDataSource,
Cert: &ipv6CertDataSource,
},
},
expectedErr: nil,
expectHTTPListener: false,
expectTLSListener: true,
}),
Entry("with an ipv6 invalid bind address port", &newServerTableInput{
opts: Opts{
Handler: handler,
BindAddress: "[::1]:a",
},
expectedErr: errors.New("error setting up listener: listen (tcp, [::1]:a) failed: listen tcp: "),
expectHTTPListener: false,
expectTLSListener: false,
}),
Entry("with an ipv6 invalid secure bind address port", &newServerTableInput{
opts: Opts{
Handler: handler,
SecureBindAddress: "[::1]:a",
TLS: &options.TLS{
Key: &ipv6KeyDataSource,
Cert: &ipv6CertDataSource,
},
},
expectedErr: errors.New("error setting up TLS listener: listen ([::1]:a) failed: listen tcp: "),
expectHTTPListener: false,
expectTLSListener: false,
}),
Entry("with an ipv6 invalid TLS key", &newServerTableInput{
opts: Opts{
Handler: handler,
SecureBindAddress: "[::1]:0",
TLS: &options.TLS{
Key: &options.SecretSource{
Value: []byte("invalid"),
},
Cert: &ipv6CertDataSource,
},
},
expectedErr: errors.New("error setting up TLS listener: could not load certificate: could not parse certificate data: tls: failed to find any PEM data in key input"),
expectHTTPListener: false,
expectTLSListener: false,
}),
Entry("with an ipv6 invalid TLS cert", &newServerTableInput{
opts: Opts{
Handler: handler,
SecureBindAddress: "[::1]:0",
TLS: &options.TLS{
Key: &ipv6KeyDataSource,
Cert: &options.SecretSource{
Value: []byte("invalid"),
},
},
},
expectedErr: errors.New("error setting up TLS listener: could not load certificate: could not parse certificate data: tls: failed to find any PEM data in certificate input"),
expectHTTPListener: false,
expectTLSListener: false,
}),
Entry("with an ipv6 address, with no TLS key", &newServerTableInput{
opts: Opts{
Handler: handler,
SecureBindAddress: "[::1]:0",
TLS: &options.TLS{
Cert: &ipv6CertDataSource,
},
},
expectedErr: errors.New("error setting up TLS listener: could not load certificate: could not load key data: no configuration provided"),
expectHTTPListener: false,
expectTLSListener: false,
}),
Entry("with an ipv6 address, with no TLS cert", &newServerTableInput{
opts: Opts{
Handler: handler,
SecureBindAddress: "[::1]:0",
TLS: &options.TLS{
Key: &ipv6KeyDataSource,
},
},
expectedErr: errors.New("error setting up TLS listener: could not load certificate: could not load cert data: no configuration provided"),
expectHTTPListener: false,
expectTLSListener: false,
}),
Entry("when the ipv6 bind address is prefixed with the http scheme", &newServerTableInput{
opts: Opts{
Handler: handler,
BindAddress: "http://[::1]:0",
},
expectedErr: nil,
expectHTTPListener: true,
expectTLSListener: false,
}),
Entry("when the ipv6 secure bind address is prefixed with the https scheme", &newServerTableInput{
opts: Opts{
Handler: handler,
SecureBindAddress: "https://[::1]:0",
TLS: &options.TLS{
Key: &ipv6KeyDataSource,
Cert: &ipv6CertDataSource,
},
},
expectedErr: nil,
expectHTTPListener: false,
expectTLSListener: true,
}),
Entry("with an ipv6 valid https bind address, and valid TLS config with MinVersion", &newServerTableInput{
opts: Opts{
Handler: handler,
SecureBindAddress: "[::1]:0",
TLS: &options.TLS{
Key: &ipv6KeyDataSource,
Cert: &ipv6CertDataSource,
MinVersion: "TLS1.3",
},
},
expectedErr: nil,
expectHTTPListener: false,
expectTLSListener: true,
}),
Entry("with an ipv6 valid https bind address, and invalid TLS config with unknown MinVersion", &newServerTableInput{
opts: Opts{
Handler: handler,
SecureBindAddress: "[::1]:0",
TLS: &options.TLS{
Key: &ipv6KeyDataSource,
Cert: &ipv6CertDataSource,
MinVersion: "TLS1.42", MinVersion: "TLS1.42",
}, },
}, },
@ -277,7 +470,7 @@ var _ = Describe("Server", func() {
cancel() cancel()
}) })
Context("with an http server", func() { Context("with an ipv4 http server", func() {
var listenAddr string var listenAddr string
BeforeEach(func() { BeforeEach(func() {
@ -327,7 +520,7 @@ var _ = Describe("Server", func() {
}) })
}) })
Context("with an https server", func() { Context("with an ipv4 https server", func() {
var secureListenAddr string var secureListenAddr string
BeforeEach(func() { BeforeEach(func() {
@ -336,8 +529,8 @@ var _ = Describe("Server", func() {
Handler: handler, Handler: handler,
SecureBindAddress: "127.0.0.1:0", SecureBindAddress: "127.0.0.1:0",
TLS: &options.TLS{ TLS: &options.TLS{
Key: &keyDataSource, Key: &ipv4KeyDataSource,
Cert: &certDataSource, Cert: &ipv4CertDataSource,
}, },
}) })
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
@ -392,11 +585,11 @@ var _ = Describe("Server", func() {
Expect(resp.TLS.VerifiedChains).Should(HaveLen(1)) Expect(resp.TLS.VerifiedChains).Should(HaveLen(1))
Expect(resp.TLS.VerifiedChains[0]).Should(HaveLen(1)) Expect(resp.TLS.VerifiedChains[0]).Should(HaveLen(1))
Expect(resp.TLS.VerifiedChains[0][0].Raw).Should(Equal(certData)) Expect(resp.TLS.VerifiedChains[0][0].Raw).Should(Equal(ipv4CertData))
}) })
}) })
Context("with both an http and an https server", func() { Context("with both an ipv4 http and an ipv4 https server", func() {
var listenAddr, secureListenAddr string var listenAddr, secureListenAddr string
BeforeEach(func() { BeforeEach(func() {
@ -406,8 +599,204 @@ var _ = Describe("Server", func() {
BindAddress: "127.0.0.1:0", BindAddress: "127.0.0.1:0",
SecureBindAddress: "127.0.0.1:0", SecureBindAddress: "127.0.0.1:0",
TLS: &options.TLS{ TLS: &options.TLS{
Key: &keyDataSource, Key: &ipv4KeyDataSource,
Cert: &certDataSource, Cert: &ipv4CertDataSource,
},
})
Expect(err).ToNot(HaveOccurred())
s, ok := srv.(*server)
Expect(ok).To(BeTrue())
listenAddr = fmt.Sprintf("http://%s/", s.listener.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 := client.Get(listenAddr)
Expect(err).ToNot(HaveOccurred())
Expect(resp.StatusCode).To(Equal(http.StatusOK))
body, err := ioutil.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 := client.Get(secureListenAddr)
Expect(err).ToNot(HaveOccurred())
Expect(resp.StatusCode).To(Equal(http.StatusOK))
body, err := ioutil.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 := client.Get(listenAddr)
Expect(err).ToNot(HaveOccurred())
_, err = client.Get(secureListenAddr)
Expect(err).ToNot(HaveOccurred())
cancel()
Eventually(func() error {
_, err := client.Get(listenAddr)
return err
}).Should(HaveOccurred())
Eventually(func() error {
_, err := client.Get(secureListenAddr)
return err
}).Should(HaveOccurred())
})
})
Context("with an ipv6 http server", func() {
var listenAddr string
BeforeEach(func() {
var err error
srv, err = NewServer(Opts{
Handler: handler,
BindAddress: "[::1]:0",
})
Expect(err).ToNot(HaveOccurred())
s, ok := srv.(*server)
Expect(ok).To(BeTrue())
listenAddr = fmt.Sprintf("http://%s/", s.listener.Addr().String())
})
It("Starts the server and serves the handler", func() {
go func() {
defer GinkgoRecover()
Expect(srv.Start(ctx)).To(Succeed())
}()
resp, err := client.Get(listenAddr)
Expect(err).ToNot(HaveOccurred())
Expect(resp.StatusCode).To(Equal(http.StatusOK))
body, err := ioutil.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 := client.Get(listenAddr)
Expect(err).ToNot(HaveOccurred())
cancel()
Eventually(func() error {
_, err := client.Get(listenAddr)
return err
}).Should(HaveOccurred())
})
})
Context("with an ipv6 https server", func() {
var secureListenAddr string
BeforeEach(func() {
var err error
srv, err = NewServer(Opts{
Handler: handler,
SecureBindAddress: "[::1]:0",
TLS: &options.TLS{
Key: &ipv6KeyDataSource,
Cert: &ipv6CertDataSource,
},
})
Expect(err).ToNot(HaveOccurred())
s, ok := srv.(*server)
Expect(ok).To(BeTrue())
secureListenAddr = fmt.Sprintf("https://%s/", s.tlsListener.Addr().String())
})
It("Starts the server and serves the handler", func() {
go func() {
defer GinkgoRecover()
Expect(srv.Start(ctx)).To(Succeed())
}()
resp, err := client.Get(secureListenAddr)
Expect(err).ToNot(HaveOccurred())
Expect(resp.StatusCode).To(Equal(http.StatusOK))
body, err := ioutil.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 := client.Get(secureListenAddr)
Expect(err).ToNot(HaveOccurred())
cancel()
Eventually(func() error {
_, err := client.Get(secureListenAddr)
return err
}).Should(HaveOccurred())
})
It("Serves the certificate provided", func() {
go func() {
defer GinkgoRecover()
Expect(srv.Start(ctx)).To(Succeed())
}()
resp, err := client.Get(secureListenAddr)
Expect(err).ToNot(HaveOccurred())
Expect(resp.StatusCode).To(Equal(http.StatusOK))
Expect(resp.TLS.VerifiedChains).Should(HaveLen(1))
Expect(resp.TLS.VerifiedChains[0]).Should(HaveLen(1))
Expect(resp.TLS.VerifiedChains[0][0].Raw).Should(Equal(ipv6CertData))
})
})
Context("with both an ipv6 http and an ipv6 https server", func() {
var listenAddr, secureListenAddr string
BeforeEach(func() {
var err error
srv, err = NewServer(Opts{
Handler: handler,
BindAddress: "[::1]:0",
SecureBindAddress: "[::1]:0",
TLS: &options.TLS{
Key: &ipv6KeyDataSource,
Cert: &ipv6CertDataSource,
}, },
}) })
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
@ -478,11 +867,16 @@ var _ = Describe("Server", func() {
DescribeTable("should return the scheme", func(in, expected string) { DescribeTable("should return the scheme", func(in, expected string) {
Expect(getNetworkScheme(in)).To(Equal(expected)) Expect(getNetworkScheme(in)).To(Equal(expected))
}, },
Entry("with no scheme", "127.0.0.1:0", "tcp"), Entry("ipv4 address with no scheme", "127.0.0.1:0", "tcp"),
Entry("with a tcp scheme", "tcp://127.0.0.1:0", "tcp"), Entry("ipv4 address with a tcp scheme", "tcp://127.0.0.1:0", "tcp"),
Entry("with a http scheme", "http://192.168.0.1:1", "tcp"), Entry("ipv4 address with a http scheme", "http://192.168.0.1:1", "tcp"),
Entry("with a unix scheme", "unix://172.168.16.2:2", "unix"), Entry("ipv4 address with a unix scheme", "unix://172.168.16.2:2", "unix"),
Entry("with a random scheme", "random://10.10.10.10:10", "random"), Entry("ipv4 address with a random scheme", "random://10.10.10.10:10", "random"),
Entry("ipv6 address with no scheme", "[::1]:0", "tcp"),
Entry("ipv6 address with a tcp scheme", "tcp://[::1]:0", "tcp"),
Entry("ipv6 address with a http scheme", "http://[::ffff:c0a8:1]:1", "tcp"),
Entry("ipv6 address with a unix scheme", "unix://[::ffff:aca8:1002]:2", "unix"),
Entry("ipv6 address with a random scheme", "random://[::ffff:a0a:a0a]:10", "random"),
) )
}) })
@ -490,11 +884,16 @@ var _ = Describe("Server", func() {
DescribeTable("should remove the scheme", func(in, expected string) { DescribeTable("should remove the scheme", func(in, expected string) {
Expect(getListenAddress(in)).To(Equal(expected)) Expect(getListenAddress(in)).To(Equal(expected))
}, },
Entry("with no scheme", "127.0.0.1:0", "127.0.0.1:0"), Entry("ipv4 address with no scheme", "127.0.0.1:0", "127.0.0.1:0"),
Entry("with a tcp scheme", "tcp://127.0.0.1:0", "127.0.0.1:0"), Entry("ipv4 address with a tcp scheme", "tcp://127.0.0.1:0", "127.0.0.1:0"),
Entry("with a http scheme", "http://192.168.0.1:1", "192.168.0.1:1"), Entry("ipv4 address with a http scheme", "http://192.168.0.1:1", "192.168.0.1:1"),
Entry("with a unix scheme", "unix://172.168.16.2:2", "172.168.16.2:2"), Entry("ipv4 address with a unix scheme", "unix://172.168.16.2:2", "172.168.16.2:2"),
Entry("with a random scheme", "random://10.10.10.10:10", "10.10.10.10:10"), Entry("ipv4 address with a random scheme", "random://10.10.10.10:10", "10.10.10.10:10"),
Entry("ipv6 address with no scheme", "[::1]:0", "[::1]:0"),
Entry("ipv6 address with a tcp scheme", "tcp://[::1]:0", "[::1]:0"),
Entry("ipv6 address with a http scheme", "http://[::ffff:c0a8:1]:1", "[::ffff:c0a8:1]:1"),
Entry("ipv6 address with a unix scheme", "unix://[::ffff:aca8:1002]:2", "[::ffff:aca8:1002]:2"),
Entry("ipv6 address with a random scheme", "random://[::ffff:a0a:a0a]:10", "[::ffff:a0a:a0a]:10"),
) )
}) })
}) })

View File

@ -54,7 +54,7 @@ var (
var _ = BeforeSuite(func() { var _ = BeforeSuite(func() {
var err error var err error
certBytes, keyBytes, err := util.GenerateCert() certBytes, keyBytes, err := util.GenerateCert("127.0.0.1")
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
certOut := new(bytes.Buffer) certOut := new(bytes.Buffer)
Expect(pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: certBytes})).To(Succeed()) Expect(pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: certBytes})).To(Succeed())

View File

@ -33,7 +33,7 @@ func GetCertPool(paths []string) (*x509.CertPool, error) {
} }
// https://golang.org/src/crypto/tls/generate_cert.go as a function // https://golang.org/src/crypto/tls/generate_cert.go as a function
func GenerateCert() ([]byte, []byte, error) { func GenerateCert(ipaddr string) ([]byte, []byte, error) {
var err error var err error
priv, err := rsa.GenerateKey(rand.Reader, 2048) priv, err := rsa.GenerateKey(rand.Reader, 2048)
@ -63,7 +63,7 @@ func GenerateCert() ([]byte, []byte, error) {
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
IPAddresses: []net.IP{net.ParseIP("127.0.0.1")}, IPAddresses: []net.IP{net.ParseIP(ipaddr)},
} }
certBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv) certBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv)
return certBytes, keyBytes, err return certBytes, keyBytes, err