Skip to content

Commit 8d3e42f

Browse files
committed
feat: backchannel logout request client tls configuration
1 parent f320673 commit 8d3e42f

File tree

6 files changed

+195
-9
lines changed

6 files changed

+195
-9
lines changed

consent/strategy_default.go

+19-9
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ package consent
2222

2323
import (
2424
"context"
25+
"crypto/tls"
2526
"net/http"
2627
"net/url"
2728
"strconv"
@@ -67,17 +68,20 @@ const (
6768
)
6869

6970
type DefaultStrategy struct {
70-
c *config.Provider
71-
r InternalRegistry
71+
c *config.Provider
72+
r InternalRegistry
73+
tlsClientConfig *tls.Config
7274
}
7375

74-
func NewStrategy(
75-
r InternalRegistry,
76-
c *config.Provider,
77-
) *DefaultStrategy {
76+
func NewStrategy(r InternalRegistry, c *config.Provider) *DefaultStrategy {
77+
clientConfig, err := c.TLSClientConfig()
78+
if err != nil {
79+
r.Logger().WithError(err).Fatalf("Unable to setup backchannel logout request client TLS configuration.")
80+
}
7881
return &DefaultStrategy{
79-
c: c,
80-
r: r,
82+
c: c,
83+
r: r,
84+
tlsClientConfig: clientConfig,
8185
}
8286
}
8387

@@ -697,7 +701,13 @@ func (s *DefaultStrategy) executeBackChannelLogout(ctx context.Context, r *http.
697701
}
698702

699703
var wg sync.WaitGroup
700-
hc := httpx.NewResilientClient()
704+
hc := httpx.NewResilientClient(
705+
httpx.ResilientClientWithClient(&http.Client{
706+
Timeout: time.Minute,
707+
Transport: &http.Transport{
708+
TLSClientConfig: s.tlsClientConfig,
709+
},
710+
}))
701711
wg.Add(len(tasks))
702712

703713
var execute = func(t task) {

driver/config/tls.go

+41
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@ package config
22

33
import (
44
"crypto/tls"
5+
"strings"
6+
7+
"github.com/hashicorp/go-secure-stdlib/tlsutil"
8+
"github.com/pkg/errors"
59

610
"github.com/ory/x/tlsx"
711
)
@@ -19,6 +23,10 @@ const (
1923
KeyTLSKeyString = "serve." + KeySuffixTLSKeyString
2024
KeyTLSCertPath = "serve." + KeySuffixTLSCertPath
2125
KeyTLSKeyPath = "serve." + KeySuffixTLSKeyPath
26+
27+
KeyClientTLSCipherSuites = "client.tls.cipher_suites"
28+
KeyClientTLSMinVer = "client.tls.min_version"
29+
KeyClientTLSMaxVer = "client.tls.max_version"
2230
)
2331

2432
type TLSConfig interface {
@@ -47,6 +55,39 @@ func (p *Provider) TLS(iface ServeInterface) TLSConfig {
4755
}
4856
}
4957

58+
func (p *Provider) TLSClientConfig() (*tls.Config, error) {
59+
tlsClientConfig := new(tls.Config)
60+
61+
if p.p.Exists(KeyClientTLSCipherSuites) {
62+
keyCipherSuites := p.p.Strings(KeyClientTLSCipherSuites)
63+
cipherSuites, err := tlsutil.ParseCiphers(strings.Join(keyCipherSuites[:], ","))
64+
if err != nil {
65+
return nil, errors.WithMessage(err, "Unable to setup client TLS configuration")
66+
}
67+
tlsClientConfig.CipherSuites = cipherSuites
68+
}
69+
70+
if p.p.Exists(KeyClientTLSMinVer) {
71+
keyMinVer := p.p.String(KeyClientTLSMinVer)
72+
if tlsMinVer, found := tlsutil.TLSLookup[keyMinVer]; !found {
73+
return nil, errors.Errorf("Unable to setup client TLS configuration. Invalid minimum TLS version: %s", keyMinVer)
74+
} else {
75+
tlsClientConfig.MinVersion = tlsMinVer
76+
}
77+
}
78+
79+
if p.p.Exists(KeyClientTLSMaxVer) {
80+
keyMaxVer := p.p.String(KeyClientTLSMaxVer)
81+
if tlsMaxVer, found := tlsutil.TLSLookup[keyMaxVer]; !found {
82+
return nil, errors.Errorf("Unable to setup client TLS configuration. Invalid maximum TLS version: %s", keyMaxVer)
83+
} else {
84+
tlsClientConfig.MaxVersion = tlsMaxVer
85+
}
86+
}
87+
88+
return tlsClientConfig, nil
89+
}
90+
5091
type tlsConfig struct {
5192
enabled bool
5293
allowTerminationFrom []string

driver/config/tls_test.go

+71
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
package config
2+
3+
import (
4+
"crypto/tls"
5+
"testing"
6+
7+
"github.com/stretchr/testify/assert"
8+
9+
"github.com/ory/x/configx"
10+
"github.com/ory/x/logrusx"
11+
)
12+
13+
func TestTLSClientConfig_CipherSuite(t *testing.T) {
14+
l := logrusx.New("", "")
15+
c := MustNew(l, configx.WithValue("client.tls.cipher_suites", []string{"TLS_AES_128_GCM_SHA256", "TLS_AES_256_GCM_SHA384"}))
16+
17+
tlsClientConfig, err := c.TLSClientConfig()
18+
assert.NoError(t, err)
19+
cipherSuites := tlsClientConfig.CipherSuites
20+
21+
assert.Len(t, cipherSuites, 2)
22+
assert.Equal(t, tls.TLS_AES_128_GCM_SHA256, cipherSuites[0])
23+
assert.Equal(t, tls.TLS_AES_256_GCM_SHA384, cipherSuites[1])
24+
}
25+
26+
func TestTLSClientConfig_InvalidCipherSuite(t *testing.T) {
27+
l := logrusx.New("", "")
28+
c := MustNew(l, configx.WithValue("client.tls.cipher_suites", []string{"TLS_AES_128_GCM_SHA256", "TLS_INVALID_CIPHER_SUITE"}))
29+
30+
_, err := c.TLSClientConfig()
31+
32+
assert.EqualError(t, err, "Unable to setup client TLS configuration: unsupported cipher \"TLS_INVALID_CIPHER_SUITE\"")
33+
}
34+
35+
func TestTLSClientConfig_MinVersion(t *testing.T) {
36+
l := logrusx.New("", "")
37+
c := MustNew(l, configx.WithValue("client.tls.min_version", "tls13"))
38+
39+
tlsClientConfig, err := c.TLSClientConfig()
40+
41+
assert.NoError(t, err)
42+
assert.Equal(t, uint16(tls.VersionTLS13), tlsClientConfig.MinVersion)
43+
}
44+
45+
func TestTLSClientConfig_InvalidMinVersion(t *testing.T) {
46+
l := logrusx.New("", "")
47+
c := MustNew(l, configx.WithValue("client.tls.min_version", "tlsx"))
48+
49+
_, err := c.TLSClientConfig()
50+
51+
assert.EqualError(t, err, "Unable to setup client TLS configuration. Invalid minimum TLS version: tlsx")
52+
}
53+
54+
func TestTLSClientConfig_MaxVersion(t *testing.T) {
55+
l := logrusx.New("", "")
56+
c := MustNew(l, configx.WithValue("client.tls.max_version", "tls10"))
57+
58+
tlsClientConfig, err := c.TLSClientConfig()
59+
60+
assert.NoError(t, err)
61+
assert.Equal(t, uint16(tls.VersionTLS10), tlsClientConfig.MaxVersion)
62+
}
63+
64+
func TestTLSClientConfig_InvalidMaxTlsVersion(t *testing.T) {
65+
l := logrusx.New("", "")
66+
c := MustNew(l, configx.WithValue("client.tls.max_version", "tlsx"))
67+
68+
_, err := c.TLSClientConfig()
69+
70+
assert.EqualError(t, err, "Unable to setup client TLS configuration. Invalid maximum TLS version: tlsx")
71+
}

go.mod

+1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ require (
3333
github.com/gorilla/sessions v1.2.0
3434
github.com/gtank/cryptopasta v0.0.0-20170601214702-1f550f6f2f69
3535
github.com/hashicorp/go-cleanhttp v0.5.2
36+
github.com/hashicorp/go-secure-stdlib/tlsutil v0.1.1
3637
github.com/jackc/pgx/v4 v4.13.0
3738
github.com/jmoiron/sqlx v1.3.4
3839
github.com/julienschmidt/httprouter v1.3.0

go.sum

+8
Original file line numberDiff line numberDiff line change
@@ -922,8 +922,15 @@ github.com/hashicorp/go-retryablehttp v0.7.0 h1:eu1EI/mbirUgP5C8hVsTNaGZreBDlYiw
922922
github.com/hashicorp/go-retryablehttp v0.7.0/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY=
923923
github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
924924
github.com/hashicorp/go-rootcerts v1.0.1/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8=
925+
github.com/hashicorp/go-secure-stdlib/parseutil v0.1.1 h1:78ki3QBevHwYrVxnyVeaEz+7WtifHhauYF23es/0KlI=
926+
github.com/hashicorp/go-secure-stdlib/parseutil v0.1.1/go.mod h1:QmrqtbKuxxSWTN3ETMPuB+VtEiBJ/A9XhoYGv8E1uD8=
927+
github.com/hashicorp/go-secure-stdlib/strutil v0.1.1 h1:nd0HIW15E6FG1MsnArYaHfuw9C2zgzM8LxkG5Ty/788=
928+
github.com/hashicorp/go-secure-stdlib/strutil v0.1.1/go.mod h1:gKOamz3EwoIoJq7mlMIRBpVTAUn8qPCrEclOKKWhD3U=
929+
github.com/hashicorp/go-secure-stdlib/tlsutil v0.1.1 h1:Yc026VyMyIpq1UWRnakHRG01U8fJm+nEfEmjoAb00n8=
930+
github.com/hashicorp/go-secure-stdlib/tlsutil v0.1.1/go.mod h1:l8slYwnJA26yBz+ErHpp2IRCLr0vuOMGBORIz4rRiAs=
925931
github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8=
926932
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
933+
github.com/hashicorp/go-sockaddr v1.0.2 h1:ztczhD1jLxIRjVejw8gFomI1BQZOe2WoVOu0SyteCQc=
927934
github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A=
928935
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
929936
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
@@ -1501,6 +1508,7 @@ github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58/go.mod h1:6lfF
15011508
github.com/ruudk/golang-pdf417 v0.0.0-20201230142125-a7e3863a1245/go.mod h1:pQAZKsJ8yyVxGRWYNEm9oFB8ieLgKFnamEyDmSA0BRk=
15021509
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
15031510
github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
1511+
github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk=
15041512
github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc=
15051513
github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4=
15061514
github.com/sagikazarmark/crypt v0.3.0/go.mod h1:uD/D+6UF4SrIR1uGEv7bBNkNqLGqUr43MRiaGWX1Nig=

spec/config.json

+55
Original file line numberDiff line numberDiff line change
@@ -452,6 +452,61 @@
452452
}
453453
}
454454
},
455+
"client.tls": {
456+
"type": "object",
457+
"additionalProperties": false,
458+
"description": "Configures http client TLS settings.",
459+
"properties": {
460+
"min_version": {
461+
"type": "string",
462+
"description": "Minimum supported TLS version.",
463+
"examples": [
464+
"tls10","tls11","tls12","tls13"
465+
]
466+
},
467+
"max_version": {
468+
"type": "string",
469+
"description": "Maximum supported TLS version.",
470+
"examples": [
471+
"tls10","tls11","tls12","tls13"
472+
]
473+
},
474+
"cipher_suites": {
475+
"type": "array",
476+
"description": "A list of supported cipher suites.",
477+
"items": {
478+
"type": "string"
479+
},
480+
"examples": [
481+
"TLS_RSA_WITH_RC4_128_SHA",
482+
"TLS_RSA_WITH_3DES_EDE_CBC_SHA",
483+
"TLS_RSA_WITH_AES_128_CBC_SHA",
484+
"TLS_RSA_WITH_AES_256_CBC_SHA",
485+
"TLS_RSA_WITH_AES_128_CBC_SHA256",
486+
"TLS_RSA_WITH_AES_128_GCM_SHA256",
487+
"TLS_RSA_WITH_AES_256_GCM_SHA384",
488+
"TLS_ECDHE_ECDSA_WITH_RC4_128_SHA",
489+
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
490+
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",
491+
"TLS_ECDHE_RSA_WITH_RC4_128_SHA",
492+
"TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA",
493+
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
494+
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
495+
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
496+
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
497+
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
498+
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
499+
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
500+
"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
501+
"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305",
502+
"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305",
503+
"TLS_AES_128_GCM_SHA256",
504+
"TLS_AES_256_GCM_SHA384",
505+
"TLS_CHACHA20_POLY1305_SHA256"
506+
]
507+
}
508+
}
509+
},
455510
"dsn": {
456511
"type": "string",
457512
"description": "Sets the data source name. This configures the backend where Ory Hydra persists data. If dsn is \"memory\", data will be written to memory and is lost when you restart this instance. Ory Hydra supports popular SQL databases. For more detailed configuration information go to: https://www.ory.sh/docs/hydra/dependencies-environment#sql"

0 commit comments

Comments
 (0)