git.iko.soy/typeable/oauth2-proxy
on master help sign in
Merge pull request #869 from grnhse/streamline-provider-naming
f6ae15eNick Meves
CHANGELOG.md+3−2
@@ -43,11 +43,12 @@
43
43
44## Changes since v6.1.1
44## Changes since v6.1.1
45
45
46−- [#925](https://github.com/oauth2-proxy/oauth2-rpoxy/pull/925) Fix basic auth legacy header conversion (@JoelSpeed)
46+- [#925](https://github.com/oauth2-proxy/oauth2-proxy/pull/925) Fix basic auth legacy header conversion (@JoelSpeed)
47−- [#916](https://github.com/oauth2-proxy/oauth2-rpoxy/pull/916) Add AlphaOptions struct to prepare for alpha config loading (@JoelSpeed)
47+- [#916](https://github.com/oauth2-proxy/oauth2-proxy/pull/916) Add AlphaOptions struct to prepare for alpha config loading (@JoelSpeed)
48- [#923](https://github.com/oauth2-proxy/oauth2-proxy/pull/923) Support TLS 1.3 (@aajisaka)
48- [#923](https://github.com/oauth2-proxy/oauth2-proxy/pull/923) Support TLS 1.3 (@aajisaka)
49- [#918](https://github.com/oauth2-proxy/oauth2-proxy/pull/918) Fix log header output (@JoelSpeed)
49- [#918](https://github.com/oauth2-proxy/oauth2-proxy/pull/918) Fix log header output (@JoelSpeed)
50- [#911](https://github.com/oauth2-proxy/oauth2-proxy/pull/911) Validate provider type on startup.
50- [#911](https://github.com/oauth2-proxy/oauth2-proxy/pull/911) Validate provider type on startup.
51+- [#869](https://github.com/oauth2-proxy/oauth2-proxy/pull/869) Streamline provider interface method names and signatures (@NickMeves)
51- [#906](https://github.com/oauth2-proxy/oauth2-proxy/pull/906) Set up v6.1.x versioned documentation as default documentation (@JoelSpeed)
52- [#906](https://github.com/oauth2-proxy/oauth2-proxy/pull/906) Set up v6.1.x versioned documentation as default documentation (@JoelSpeed)
52- [#905](https://github.com/oauth2-proxy/oauth2-proxy/pull/905) Remove v5 legacy sessions support (@NickMeves)
53- [#905](https://github.com/oauth2-proxy/oauth2-proxy/pull/905) Remove v5 legacy sessions support (@NickMeves)
53- [#904](https://github.com/oauth2-proxy/oauth2-proxy/pull/904) Set `skip-auth-strip-headers` to `true` by default (@NickMeves)
54- [#904](https://github.com/oauth2-proxy/oauth2-proxy/pull/904) Set `skip-auth-strip-headers` to `true` by default (@NickMeves)
go.mod+4−3
@@ -19,15 +19,16 @@ require (
19 github.com/onsi/gomega v1.10.2
19 github.com/onsi/gomega v1.10.2
20 github.com/pierrec/lz4 v2.5.2+incompatible
20 github.com/pierrec/lz4 v2.5.2+incompatible
21 github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 // indirect
21 github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 // indirect
22− github.com/spf13/pflag v1.0.3
22+ github.com/spf13/pflag v1.0.5
23 github.com/spf13/viper v1.6.3
23 github.com/spf13/viper v1.6.3
24 github.com/stretchr/testify v1.6.1
24 github.com/stretchr/testify v1.6.1
25 github.com/vmihailenco/msgpack/v4 v4.3.11
25 github.com/vmihailenco/msgpack/v4 v4.3.11
26 github.com/yhat/wsutil v0.0.0-20170731153501-1d66fa95c997
26 github.com/yhat/wsutil v0.0.0-20170731153501-1d66fa95c997
27− golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2
27+ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9
28− golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7
28+ golang.org/x/net v0.0.0-20200707034311-ab3426394381
29 golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d
29 golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d
30 google.golang.org/api v0.20.0
30 google.golang.org/api v0.20.0
31 gopkg.in/natefinch/lumberjack.v2 v2.0.0
31 gopkg.in/natefinch/lumberjack.v2 v2.0.0
32 gopkg.in/square/go-jose.v2 v2.4.1
32 gopkg.in/square/go-jose.v2 v2.4.1
33+ k8s.io/apimachinery v0.19.3
33)
34)
go.sum+69
@@ -8,7 +8,10 @@ github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ
8github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
8github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
9github.com/FZambia/sentinel v1.0.0 h1:KJ0ryjKTZk5WMp0dXvSdNqp3lFaW1fNFuEYfrkLOYIc=
9github.com/FZambia/sentinel v1.0.0 h1:KJ0ryjKTZk5WMp0dXvSdNqp3lFaW1fNFuEYfrkLOYIc=
10github.com/FZambia/sentinel v1.0.0/go.mod h1:ytL1Am/RLlAoAXG6Kj5LNuw/TRRQrv2rt2FT26vP5gI=
10github.com/FZambia/sentinel v1.0.0/go.mod h1:ytL1Am/RLlAoAXG6Kj5LNuw/TRRQrv2rt2FT26vP5gI=
11+github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
11github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
12github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
13+github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
14+github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
12github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
15github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
13github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
16github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
14github.com/alicebob/gopher-json v0.0.0-20180125190556-5a6b3ba71ee6/go.mod h1:SGnFV6hVsYE877CKEZ6tDNTjaSXYUk6QqoIK6PrAtcc=
17github.com/alicebob/gopher-json v0.0.0-20180125190556-5a6b3ba71ee6/go.mod h1:SGnFV6hVsYE877CKEZ6tDNTjaSXYUk6QqoIK6PrAtcc=
@@ -48,36 +51,52 @@ github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZm
48github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
51github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
49github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
52github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
50github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
53github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
54+github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
55+github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
56+github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
57+github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
51github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
58github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
52github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
59github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
60+github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
53github.com/frankban/quicktest v1.10.0 h1:Gfh+GAJZOAoKZsIZeZbdn2JF10kN1XHNvjsvQK8gVkE=
61github.com/frankban/quicktest v1.10.0 h1:Gfh+GAJZOAoKZsIZeZbdn2JF10kN1XHNvjsvQK8gVkE=
54github.com/frankban/quicktest v1.10.0/go.mod h1:ui7WezCLWMWxVWr1GETZY3smRy0G4KWq9vcPtJmFl7Y=
62github.com/frankban/quicktest v1.10.0/go.mod h1:ui7WezCLWMWxVWr1GETZY3smRy0G4KWq9vcPtJmFl7Y=
55github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
63github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
56github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
64github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
57github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
65github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
66+github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
58github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
67github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
59github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
68github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
60github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
69github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
61github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
70github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
71+github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
72+github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
73+github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0=
74+github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg=
75+github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc=
76+github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I=
62github.com/go-redis/redis/v8 v8.2.3 h1:eNesND+DWt/sjQOtPFxAbQkTIXaXX00qNLxjVWkZ70k=
77github.com/go-redis/redis/v8 v8.2.3 h1:eNesND+DWt/sjQOtPFxAbQkTIXaXX00qNLxjVWkZ70k=
63github.com/go-redis/redis/v8 v8.2.3/go.mod h1:ysgGY09J/QeDYbu3HikWEIPCwaeOkuNoTgKayTEaEOw=
78github.com/go-redis/redis/v8 v8.2.3/go.mod h1:ysgGY09J/QeDYbu3HikWEIPCwaeOkuNoTgKayTEaEOw=
64github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
79github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
65github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
80github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
66github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
81github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
82+github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
67github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
83github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
68github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
84github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
69github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
85github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
86+github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
70github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
87github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
71github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
88github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
72github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
89github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
73github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
90github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
74github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
91github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
92+github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
75github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
93github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
76github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
94github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
77github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
95github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
78github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
96github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
79github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
97github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
80github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
98github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
99+github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
81github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0=
100github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0=
82github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
101github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
83github.com/gomodule/redigo v1.7.1-0.20190322064113-39e2c31b7ca3/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4=
102github.com/gomodule/redigo v1.7.1-0.20190322064113-39e2c31b7ca3/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4=
@@ -92,6 +111,7 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
92github.com/google/go-cmp v0.5.1 h1:JFrFEBb2xKufg6XkJsJr+WbKb4FQlURi5RUcBveYu9k=
111github.com/google/go-cmp v0.5.1 h1:JFrFEBb2xKufg6XkJsJr+WbKb4FQlURi5RUcBveYu9k=
93github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
112github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
94github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
113github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
114+github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
95github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
115github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
96github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
116github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
97github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
117github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
@@ -99,6 +119,7 @@ github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+
99github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
119github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
100github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM=
120github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM=
101github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
121github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
122+github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg=
102github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
123github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
103github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
124github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
104github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
125github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
@@ -112,7 +133,9 @@ github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
112github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
133github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
113github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
134github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
114github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
135github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
136+github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
115github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
137github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
138+github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
116github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
139github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
117github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
140github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
118github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
141github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
@@ -120,6 +143,7 @@ github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7V
120github.com/justinas/alice v1.2.0 h1:+MHSA/vccVCF4Uq37S42jwlkvI2Xzl7zTPCN5BnZNVo=
143github.com/justinas/alice v1.2.0 h1:+MHSA/vccVCF4Uq37S42jwlkvI2Xzl7zTPCN5BnZNVo=
121github.com/justinas/alice v1.2.0/go.mod h1:fN5HRH/reO/zrUflLfTN43t3vXvKzvZIENsNEe7i7qA=
144github.com/justinas/alice v1.2.0/go.mod h1:fN5HRH/reO/zrUflLfTN43t3vXvKzvZIENsNEe7i7qA=
122github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
145github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
146+github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
123github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
147github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
124github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
148github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
125github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
149github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
@@ -131,6 +155,7 @@ github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
131github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
155github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
132github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4=
156github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4=
133github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
157github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
158+github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
134github.com/matryer/is v1.2.0 h1:92UTHpy8CDwaJ08GqLDzhhuixiBUUD1p3AU6PHddz4A=
159github.com/matryer/is v1.2.0 h1:92UTHpy8CDwaJ08GqLDzhhuixiBUUD1p3AU6PHddz4A=
135github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA=
160github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA=
136github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
161github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
@@ -139,16 +164,23 @@ github.com/mbland/hmacauth v0.0.0-20170912233209-44256dfd4bfa/go.mod h1:8vxFeeg+
139github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
164github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
140github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
165github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
141github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
166github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
167+github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
142github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
168github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
143github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
169github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
170+github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
144github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
171github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
172+github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
145github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78=
173github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78=
146github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
174github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
147github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
175github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
176+github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
148github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
177github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
178+github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
149github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
179github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
150github.com/onsi/ginkgo v1.14.1 h1:jMU0WaQrP0a/YAEq8eJmJKjBoMs+pClEr1vDMlM/Do4=
180github.com/onsi/ginkgo v1.14.1 h1:jMU0WaQrP0a/YAEq8eJmJKjBoMs+pClEr1vDMlM/Do4=
151github.com/onsi/ginkgo v1.14.1/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
181github.com/onsi/ginkgo v1.14.1/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
182+github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
183+github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
152github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
184github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
153github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
185github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
154github.com/onsi/gomega v1.10.2 h1:aY/nuoWlKJud2J6U0E3NWsjlg+0GtwXxgEqthRdzlcs=
186github.com/onsi/gomega v1.10.2 h1:aY/nuoWlKJud2J6U0E3NWsjlg+0GtwXxgEqthRdzlcs=
@@ -158,6 +190,7 @@ github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/9
158github.com/pierrec/lz4 v2.5.2+incompatible h1:WCjObylUIOlKy/+7Abdn34TLIkXiA4UWUMhxq9m9ZXI=
190github.com/pierrec/lz4 v2.5.2+incompatible h1:WCjObylUIOlKy/+7Abdn34TLIkXiA4UWUMhxq9m9ZXI=
159github.com/pierrec/lz4 v2.5.2+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
191github.com/pierrec/lz4 v2.5.2+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
160github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
192github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
193+github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
161github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
194github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
162github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
195github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
163github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 h1:J9b7z+QKAmPf4YLrFg6oQUotqHQeUNWwkvo7jZp1GLU=
196github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 h1:J9b7z+QKAmPf4YLrFg6oQUotqHQeUNWwkvo7jZp1GLU=
@@ -186,14 +219,18 @@ github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8=
186github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
219github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
187github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk=
220github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk=
188github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
221github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
222+github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
189github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
223github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
190github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
224github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
225+github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
226+github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
191github.com/spf13/viper v1.6.3 h1:pDDu1OyEDTKzpJwdq4TiuLyMsUgRa/BT5cn5O62NoHs=
227github.com/spf13/viper v1.6.3 h1:pDDu1OyEDTKzpJwdq4TiuLyMsUgRa/BT5cn5O62NoHs=
192github.com/spf13/viper v1.6.3/go.mod h1:jUMtyi0/lB5yZH/FjyGAoH7IMNrIhlBf6pXZmbMDvzw=
228github.com/spf13/viper v1.6.3/go.mod h1:jUMtyi0/lB5yZH/FjyGAoH7IMNrIhlBf6pXZmbMDvzw=
193github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
229github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
194github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
230github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
195github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
231github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
196github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
232github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
233+github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
197github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
234github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
198github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
235github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
199github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
236github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
@@ -223,6 +260,8 @@ go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
223golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
260golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
224golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
261golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
225golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
262golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
263+golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
264+golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
226golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
265golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
227golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
266golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
228golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
267golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
@@ -237,12 +276,16 @@ golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73r
237golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
276golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
238golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
277golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
239golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
278golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
279+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
240golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
280golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
241golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
281golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
242golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
282golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
243golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
283golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
284+golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
244golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7 h1:AeiKBIuRw3UomYXSbLy0Mc2dDLfdtbT/IVn4keq83P0=
285golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7 h1:AeiKBIuRw3UomYXSbLy0Mc2dDLfdtbT/IVn4keq83P0=
245golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
286golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
287+golang.org/x/net v0.0.0-20200707034311-ab3426394381 h1:VXak5I6aEWmAXeQjA+QSZzlgNrpq9mjcfDemuexIKsU=
288+golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
246golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
289golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
247golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
290golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
248golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
291golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -260,6 +303,7 @@ golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5h
260golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
303golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
261golang.org/x/sys v0.0.0-20190204203706-41f3e6584952/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
304golang.org/x/sys v0.0.0-20190204203706-41f3e6584952/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
262golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
305golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
306+golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
263golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
307golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
264golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
308golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
265golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
309golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -267,14 +311,20 @@ golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7w
267golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
311golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
268golang.org/x/sys v0.0.0-20200519105757-fe76b779f299 h1:DYfZAGf2WMFjMxbgTjaC+2HC7NkNAQs+6Q8b9WEB/F4=
312golang.org/x/sys v0.0.0-20200519105757-fe76b779f299 h1:DYfZAGf2WMFjMxbgTjaC+2HC7NkNAQs+6Q8b9WEB/F4=
269golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
313golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
314+golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4 h1:5/PjkGUjvEU5Gl6BxmvKRPpqo2uNMv4rcHBMwzk/st8=
315+golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
270golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
316golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
271golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
317golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
272golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
318golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
273golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
319golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
320+golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
321+golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
274golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
322golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
275golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
323golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
276golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
324golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
277golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
325golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
326+golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
327+golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
278golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
328golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
279golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
329golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
280golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
330golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
@@ -296,6 +346,8 @@ google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRn
296google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
346google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
297google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 h1:gSJIx1SDwno+2ElGhA4+qG2zF97qiUzTM+rQ0klBOcE=
347google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 h1:gSJIx1SDwno+2ElGhA4+qG2zF97qiUzTM+rQ0klBOcE=
298google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
348google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
349+google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY=
350+google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
299google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
351google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
300google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
352google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
301google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
353google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
@@ -306,13 +358,20 @@ google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ
306google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
358google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
307google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
359google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
308google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
360google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
361+google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
309google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM=
362google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM=
310google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
363google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
364+google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
365+google.golang.org/protobuf v1.24.0 h1:UhZDfRO8JRQru4/+LlLE0BRKGF8L+PICnvYZmx/fEGA=
366+google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
311gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
367gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
312gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
368gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
313gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
369gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
314gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
370gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
371+gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
372+gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
315gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
373gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
374+gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
316gopkg.in/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno=
375gopkg.in/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno=
317gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
376gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
318gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8=
377gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8=
@@ -326,6 +385,7 @@ gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bl
326gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
385gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
327gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
386gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
328gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
387gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
388+gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
329gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
389gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
330gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
390gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
331gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
391gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
@@ -333,3 +393,12 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C
333honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
393honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
334honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
394honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
335honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
395honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
396+k8s.io/apimachinery v0.19.3 h1:bpIQXlKjB4cB/oNpnNnV+BybGPR7iP5oYpsOTEJ4hgc=
397+k8s.io/apimachinery v0.19.3/go.mod h1:DnPGDnARWFvYa3pMHgSxtbZb7gpzzAZ1pTfaUNDVlmA=
398+k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
399+k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=
400+k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
401+k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6/go.mod h1:UuqjUnNftUyPE5H64/qeyjQoUZhGpeFDVdxjTeEVN2o=
402+sigs.k8s.io/structured-merge-diff/v4 v4.0.1/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
403+sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
404+sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
oauthproxy.go+51−61
@@ -13,7 +13,6 @@ import (
13 "strings"
13 "strings"
14 "time"
14 "time"
15
15
16− "github.com/coreos/go-oidc"
17 "github.com/justinas/alice"
16 "github.com/justinas/alice"
18 ipapi "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/ip"
17 ipapi "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/ip"
19 middlewareapi "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/middleware"
18 middlewareapi "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/middleware"
@@ -78,36 +77,34 @@ type OAuthProxy struct {
78 AuthOnlyPath string
77 AuthOnlyPath string
79 UserInfoPath string
78 UserInfoPath string
80
79
81− allowedRoutes []allowedRoute
80+ allowedRoutes []allowedRoute
82− redirectURL *url.URL // the url to receive requests at
81+ redirectURL *url.URL // the url to receive requests at
83− whitelistDomains []string
82+ whitelistDomains []string
84− provider providers.Provider
83+ provider providers.Provider
85− providerNameOverride string
84+ providerNameOverride string
86− sessionStore sessionsapi.SessionStore
85+ sessionStore sessionsapi.SessionStore
87− ProxyPrefix string
86+ ProxyPrefix string
88− SignInMessage string
87+ SignInMessage string
89− basicAuthValidator basic.Validator
88+ basicAuthValidator basic.Validator
90− displayHtpasswdForm bool
89+ displayHtpasswdForm bool
91− serveMux http.Handler
90+ serveMux http.Handler
92− SetXAuthRequest bool
91+ SetXAuthRequest bool
93− PassBasicAuth bool
92+ PassBasicAuth bool
94− SetBasicAuth bool
93+ SetBasicAuth bool
95− SkipProviderButton bool
94+ SkipProviderButton bool
96− PassUserHeaders bool
95+ PassUserHeaders bool
97− BasicAuthPassword string
96+ BasicAuthPassword string
98− PassAccessToken bool
97+ PassAccessToken bool
99− SetAuthorization bool
98+ SetAuthorization bool
100− PassAuthorization bool
99+ PassAuthorization bool
101− PreferEmailToUser bool
100+ PreferEmailToUser bool
102− skipAuthPreflight bool
101+ skipAuthPreflight bool
103− skipJwtBearerTokens bool
102+ skipJwtBearerTokens bool
104− mainJwtBearerVerifier *oidc.IDTokenVerifier
105− extraJwtBearerVerifiers []*oidc.IDTokenVerifier
106− templates *template.Template
103+ templates *template.Template
107− realClientIPParser ipapi.RealClientIPParser
104+ realClientIPParser ipapi.RealClientIPParser
108− trustedIPs *ip.NetSet
105+ trustedIPs *ip.NetSet
109− Banner string
106+ Banner string
110− Footer string
107+ Footer string
111
108
112 sessionChain alice.Chain
109 sessionChain alice.Chain
113 headersChain alice.Chain
110 headersChain alice.Chain
@@ -202,25 +199,23 @@ func NewOAuthProxy(opts *options.Options, validator func(string) bool) (*OAuthPr
202 AuthOnlyPath: fmt.Sprintf("%s/auth", opts.ProxyPrefix),
199 AuthOnlyPath: fmt.Sprintf("%s/auth", opts.ProxyPrefix),
203 UserInfoPath: fmt.Sprintf("%s/userinfo", opts.ProxyPrefix),
200 UserInfoPath: fmt.Sprintf("%s/userinfo", opts.ProxyPrefix),
204
201
205− ProxyPrefix: opts.ProxyPrefix,
202+ ProxyPrefix: opts.ProxyPrefix,
206− provider: opts.GetProvider(),
203+ provider: opts.GetProvider(),
207− providerNameOverride: opts.ProviderName,
204+ providerNameOverride: opts.ProviderName,
208− sessionStore: sessionStore,
205+ sessionStore: sessionStore,
209− serveMux: upstreamProxy,
206+ serveMux: upstreamProxy,
210− redirectURL: redirectURL,
207+ redirectURL: redirectURL,
211− allowedRoutes: allowedRoutes,
208+ allowedRoutes: allowedRoutes,
212− whitelistDomains: opts.WhitelistDomains,
209+ whitelistDomains: opts.WhitelistDomains,
213− skipAuthPreflight: opts.SkipAuthPreflight,
210+ skipAuthPreflight: opts.SkipAuthPreflight,
214− skipJwtBearerTokens: opts.SkipJwtBearerTokens,
211+ skipJwtBearerTokens: opts.SkipJwtBearerTokens,
215− mainJwtBearerVerifier: opts.GetOIDCVerifier(),
216− extraJwtBearerVerifiers: opts.GetJWTBearerVerifiers(),
217− realClientIPParser: opts.GetRealClientIPParser(),
212+ realClientIPParser: opts.GetRealClientIPParser(),
218− SkipProviderButton: opts.SkipProviderButton,
213+ SkipProviderButton: opts.SkipProviderButton,
219− templates: templates,
214+ templates: templates,
220− trustedIPs: trustedIPs,
215+ trustedIPs: trustedIPs,
221− Banner: opts.Banner,
216+ Banner: opts.Banner,
222− Footer: opts.Footer,
217+ Footer: opts.Footer,
223− SignInMessage: buildSignInMessage(opts),
218+ SignInMessage: buildSignInMessage(opts),
224
219
225 basicAuthValidator: basicAuthValidator,
220 basicAuthValidator: basicAuthValidator,
226 displayHtpasswdForm: basicAuthValidator != nil && opts.DisplayHtpasswdForm,
221 displayHtpasswdForm: basicAuthValidator != nil && opts.DisplayHtpasswdForm,
@@ -266,18 +261,13 @@ func buildSessionChain(opts *options.Options, sessionStore sessionsapi.SessionSt
266 chain := alice.New()
261 chain := alice.New()
267
262
268 if opts.SkipJwtBearerTokens {
263 if opts.SkipJwtBearerTokens {
269− sessionLoaders := []middlewareapi.TokenToSessionLoader{}
264+ sessionLoaders := []middlewareapi.TokenToSessionFunc{
270− if opts.GetOIDCVerifier() != nil {
265+ opts.GetProvider().CreateSessionFromToken,
271− sessionLoaders = append(sessionLoaders, middlewareapi.TokenToSessionLoader{
272− Verifier: opts.GetOIDCVerifier(),
273− TokenToSession: opts.GetProvider().CreateSessionStateFromBearerToken,
274− })
275 }
266 }
276
267
277 for _, verifier := range opts.GetJWTBearerVerifiers() {
268 for _, verifier := range opts.GetJWTBearerVerifiers() {
278− sessionLoaders = append(sessionLoaders, middlewareapi.TokenToSessionLoader{
269+ sessionLoaders = append(sessionLoaders,
279− Verifier: verifier,
270+ middlewareapi.CreateTokenToSessionFunc(verifier.Verify))
280− })
281 }
271 }
282
272
283 chain = chain.Append(middleware.NewJwtSessionLoader(sessionLoaders))
273 chain = chain.Append(middleware.NewJwtSessionLoader(sessionLoaders))
@@ -291,7 +281,7 @@ func buildSessionChain(opts *options.Options, sessionStore sessionsapi.SessionSt
291 SessionStore: sessionStore,
281 SessionStore: sessionStore,
292 RefreshPeriod: opts.Cookie.Refresh,
282 RefreshPeriod: opts.Cookie.Refresh,
293 RefreshSessionIfNeeded: opts.GetProvider().RefreshSessionIfNeeded,
283 RefreshSessionIfNeeded: opts.GetProvider().RefreshSessionIfNeeded,
294− ValidateSessionState: opts.GetProvider().ValidateSessionState,
284+ ValidateSessionState: opts.GetProvider().ValidateSession,
295 }))
285 }))
296
286
297 return chain
287 return chain
@@ -416,7 +406,7 @@ func (p *OAuthProxy) enrichSessionState(ctx context.Context, s *sessionsapi.Sess
416 }
406 }
417 }
407 }
418
408
419− return p.provider.EnrichSessionState(ctx, s)
409+ return p.provider.EnrichSession(ctx, s)
420}
410}
421
411
422// MakeCSRFCookie creates a cookie for CSRF
412// MakeCSRFCookie creates a cookie for CSRF
oauthproxy_test.go+1−1
@@ -400,7 +400,7 @@ func (tp *TestProvider) GetEmailAddress(_ context.Context, _ *sessions.SessionSt
400 return tp.EmailAddress, nil
400 return tp.EmailAddress, nil
401}
401}
402
402
403−func (tp *TestProvider) ValidateSessionState(_ context.Context, _ *sessions.SessionState) bool {
403+func (tp *TestProvider) ValidateSession(_ context.Context, _ *sessions.SessionState) bool {
404 return tp.ValidToken
404 return tp.ValidToken
405}
405}
406
406
pkg/apis/middleware/session.go+46−12
@@ -2,23 +2,57 @@ package middleware
2
2
3import (
3import (
4 "context"
4 "context"
5+ "fmt"
5
6
6 "github.com/coreos/go-oidc"
7 "github.com/coreos/go-oidc"
7 sessionsapi "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/sessions"
8 sessionsapi "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/sessions"
8)
9)
9
10
10−// TokenToSessionFunc takes a rawIDToken and an idToken and converts it into a
11+// TokenToSessionFunc takes a raw ID Token and converts it into a SessionState.
11−// SessionState.
12−type TokenToSessionFunc func(ctx context.Context, rawIDToken string, idToken *oidc.IDToken) (*sessionsapi.SessionState, error)
12+type TokenToSessionFunc func(ctx context.Context, token string) (*sessionsapi.SessionState, error)
13
13
14−// TokenToSessionLoader pairs a token verifier with the correct converter function
14+// VerifyFunc takes a raw bearer token and verifies it returning the converted
15−// to convert the ID Token to a SessionState.
15+// oidc.IDToken representation of the token.
16−type TokenToSessionLoader struct {
16+type VerifyFunc func(ctx context.Context, token string) (*oidc.IDToken, error)
17− // Verfier is used to verify that the ID Token was signed by the claimed issuer
18− // and that the token has not been tampered with.
19− Verifier *oidc.IDTokenVerifier
20
17
21− // TokenToSession converts a rawIDToken and an idToken to a SessionState.
18+// CreateTokenToSessionFunc provides a handler that is a default implementation
22− // (Optional) If not set a default basic implementation is used.
19+// for converting a JWT into a session.
23− TokenToSession TokenToSessionFunc
20+func CreateTokenToSessionFunc(verify VerifyFunc) TokenToSessionFunc {
21+ return func(ctx context.Context, token string) (*sessionsapi.SessionState, error) {
22+ var claims struct {
23+ Subject string `json:"sub"`
24+ Email string `json:"email"`
25+ Verified *bool `json:"email_verified"`
26+ PreferredUsername string `json:"preferred_username"`
27+ }
28+
29+ idToken, err := verify(ctx, token)
30+ if err != nil {
31+ return nil, err
32+ }
33+
34+ if err := idToken.Claims(&claims); err != nil {
35+ return nil, fmt.Errorf("failed to parse bearer token claims: %v", err)
36+ }
37+
38+ if claims.Email == "" {
39+ claims.Email = claims.Subject
40+ }
41+
42+ if claims.Verified != nil && !*claims.Verified {
43+ return nil, fmt.Errorf("email in id_token (%s) isn't verified", claims.Email)
44+ }
45+
46+ newSession := &sessionsapi.SessionState{
47+ Email: claims.Email,
48+ User: claims.Subject,
49+ PreferredUsername: claims.PreferredUsername,
50+ AccessToken: token,
51+ IDToken: token,
52+ RefreshToken: "",
53+ ExpiresOn: &idToken.Expiry,
54+ }
55+
56+ return newSession, nil
57+ }
24}
58}
pkg/middleware/jwt_session.go+16−57
@@ -1,30 +1,21 @@
1package middleware
1package middleware
2
2
3import (
3import (
4− "context"
4+ "errors"
5 "fmt"
5 "fmt"
6 "net/http"
6 "net/http"
7 "regexp"
7 "regexp"
8
8
9− "github.com/coreos/go-oidc"
10 "github.com/justinas/alice"
9 "github.com/justinas/alice"
11 middlewareapi "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/middleware"
10 middlewareapi "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/middleware"
12 sessionsapi "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/sessions"
11 sessionsapi "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/sessions"
13 "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/logger"
12 "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/logger"
13+ k8serrors "k8s.io/apimachinery/pkg/util/errors"
14)
14)
15
15
16−const jwtRegexFormat = `^eyJ[a-zA-Z0-9_-]*\.eyJ[a-zA-Z0-9_-]*\.[a-zA-Z0-9_-]+$`
16+const jwtRegexFormat = `^ey[IJ][a-zA-Z0-9_-]*\.ey[IJ][a-zA-Z0-9_-]*\.[a-zA-Z0-9_-]+$`
17−
18−func NewJwtSessionLoader(sessionLoaders []middlewareapi.TokenToSessionLoader) alice.Constructor {
19− for i, loader := range sessionLoaders {
20− if loader.TokenToSession == nil {
21− sessionLoaders[i] = middlewareapi.TokenToSessionLoader{
22− Verifier: loader.Verifier,
23− TokenToSession: createSessionStateFromBearerToken,
24− }
25− }
26− }
27
17
18+func NewJwtSessionLoader(sessionLoaders []middlewareapi.TokenToSessionFunc) alice.Constructor {
28 js := &jwtSessionLoader{
19 js := &jwtSessionLoader{
29 jwtRegex: regexp.MustCompile(jwtRegexFormat),
20 jwtRegex: regexp.MustCompile(jwtRegexFormat),
30 sessionLoaders: sessionLoaders,
21 sessionLoaders: sessionLoaders,
@@ -36,7 +27,7 @@ func NewJwtSessionLoader(sessionLoaders []middlewareapi.TokenToSessionLoader) al
36// Authorization headers.
27// Authorization headers.
37type jwtSessionLoader struct {
28type jwtSessionLoader struct {
38 jwtRegex *regexp.Regexp
29 jwtRegex *regexp.Regexp
39− sessionLoaders []middlewareapi.TokenToSessionLoader
30+ sessionLoaders []middlewareapi.TokenToSessionFunc
40}
31}
41
32
42// loadSession attempts to load a session from a JWT stored in an Authorization
33// loadSession attempts to load a session from a JWT stored in an Authorization
@@ -75,24 +66,27 @@ func (j *jwtSessionLoader) getJwtSession(req *http.Request) (*sessionsapi.Sessio
75 return nil, nil
66 return nil, nil
76 }
67 }
77
68
78− rawBearerToken, err := j.findBearerTokenFromHeader(auth)
69+ token, err := j.findTokenFromHeader(auth)
79 if err != nil {
70 if err != nil {
80 return nil, err
71 return nil, err
81 }
72 }
82
73
74+ // This leading error message only occurs if all session loaders fail
75+ errs := []error{errors.New("unable to verify bearer token")}
83 for _, loader := range j.sessionLoaders {
76 for _, loader := range j.sessionLoaders {
84− bearerToken, err := loader.Verifier.Verify(req.Context(), rawBearerToken)
77+ session, err := loader(req.Context(), token)
85− if err == nil {
78+ if err != nil {
86− // The token was verified, convert it to a session
79+ errs = append(errs, err)
87− return loader.TokenToSession(req.Context(), rawBearerToken, bearerToken)
80+ continue
88 }
81 }
82+ return session, nil
89 }
83 }
90
84
91− return nil, fmt.Errorf("unable to verify jwt token: %q", req.Header.Get("Authorization"))
85+ return nil, k8serrors.NewAggregate(errs)
92}
86}
93
87
94−// findBearerTokenFromHeader finds a valid JWT token from the Authorization header of a given request.
88+// findTokenFromHeader finds a valid JWT token from the Authorization header of a given request.
95−func (j *jwtSessionLoader) findBearerTokenFromHeader(header string) (string, error) {
89+func (j *jwtSessionLoader) findTokenFromHeader(header string) (string, error) {
96 tokenType, token, err := splitAuthHeader(header)
90 tokenType, token, err := splitAuthHeader(header)
97 if err != nil {
91 if err != nil {
98 return "", err
92 return "", err
@@ -132,38 +126,3 @@ func (j *jwtSessionLoader) getBasicToken(token string) (string, error) {
132
126
133 return "", fmt.Errorf("invalid basic auth token found in authorization header")
127 return "", fmt.Errorf("invalid basic auth token found in authorization header")
134}
128}
135−
136−// createSessionStateFromBearerToken is a default implementation for converting
137−// a JWT into a session state.
138−func createSessionStateFromBearerToken(ctx context.Context, rawIDToken string, idToken *oidc.IDToken) (*sessionsapi.SessionState, error) {
139− var claims struct {
140− Subject string `json:"sub"`
141− Email string `json:"email"`
142− Verified *bool `json:"email_verified"`
143− PreferredUsername string `json:"preferred_username"`
144− }
145−
146− if err := idToken.Claims(&claims); err != nil {
147− return nil, fmt.Errorf("failed to parse bearer token claims: %v", err)
148− }
149−
150− if claims.Email == "" {
151− claims.Email = claims.Subject
152− }
153−
154− if claims.Verified != nil && !*claims.Verified {
155− return nil, fmt.Errorf("email in id_token (%s) isn't verified", claims.Email)
156− }
157−
158− newSession := &sessionsapi.SessionState{
159− Email: claims.Email,
160− User: claims.Subject,
161− PreferredUsername: claims.PreferredUsername,
162− AccessToken: rawIDToken,
163− IDToken: rawIDToken,
164− RefreshToken: "",
165− ExpiresOn: &idToken.Expiry,
166− }
167−
168− return newSession, nil
169−}
pkg/middleware/jwt_session_test.go+54−39
@@ -20,12 +20,13 @@ import (
20 . "github.com/onsi/ginkgo"
20 . "github.com/onsi/ginkgo"
21 . "github.com/onsi/ginkgo/extensions/table"
21 . "github.com/onsi/ginkgo/extensions/table"
22 . "github.com/onsi/gomega"
22 . "github.com/onsi/gomega"
23+ k8serrors "k8s.io/apimachinery/pkg/util/errors"
23)
24)
24
25
25type noOpKeySet struct {
26type noOpKeySet struct {
26}
27}
27
28
28−func (noOpKeySet) VerifySignature(ctx context.Context, jwt string) (payload []byte, err error) {
29+func (noOpKeySet) VerifySignature(_ context.Context, jwt string) (payload []byte, err error) {
29 splitStrings := strings.Split(jwt, ".")
30 splitStrings := strings.Split(jwt, ".")
30 payloadString := splitStrings[1]
31 payloadString := splitStrings[1]
31 return base64.RawURLEncoding.DecodeString(payloadString)
32 return base64.RawURLEncoding.DecodeString(payloadString)
@@ -73,13 +74,18 @@ Nnc3a3lGVWFCNUMxQnNJcnJMTWxka1dFaHluYmI4Ongtb2F1dGgtYmFzaWM=`
73 const validToken = "eyJfoobar.eyJfoobar.12345asdf"
74 const validToken = "eyJfoobar.eyJfoobar.12345asdf"
74
75
75 Context("JwtSessionLoader", func() {
76 Context("JwtSessionLoader", func() {
76− var verifier *oidc.IDTokenVerifier
77+ var verifier middlewareapi.VerifyFunc
77 const nonVerifiedToken = validToken
78 const nonVerifiedToken = validToken
78
79
79 BeforeEach(func() {
80 BeforeEach(func() {
80− keyset := noOpKeySet{}
81− verifier = oidc.NewVerifier("https://issuer.example.com", keyset,
81+ verifier = oidc.NewVerifier(
82+ "https://issuer.example.com",
83+ noOpKeySet{},
84+ &oidc.Config{
82− &oidc.Config{ClientID: "https://test.myapp.com", SkipExpiryCheck: true})
85+ ClientID: "https://test.myapp.com",
86+ SkipExpiryCheck: true,
87+ },
88+ ).Verify
83 })
89 })
84
90
85 type jwtSessionLoaderTableInput struct {
91 type jwtSessionLoaderTableInput struct {
@@ -102,10 +108,8 @@ Nnc3a3lGVWFCNUMxQnNJcnJMTWxka1dFaHluYmI4Ongtb2F1dGgtYmFzaWM=`
102
108
103 rw := httptest.NewRecorder()
109 rw := httptest.NewRecorder()
104
110
105− sessionLoaders := []middlewareapi.TokenToSessionLoader{
111+ sessionLoaders := []middlewareapi.TokenToSessionFunc{
106− {
112+ middlewareapi.CreateTokenToSessionFunc(verifier),
107− Verifier: verifier,
108− },
109 }
113 }
110
114
111 // Create the handler with a next handler that will capture the session
115 // Create the handler with a next handler that will capture the session
@@ -167,17 +171,19 @@ Nnc3a3lGVWFCNUMxQnNJcnJMTWxka1dFaHluYmI4Ongtb2F1dGgtYmFzaWM=`
167 const nonVerifiedToken = validToken
171 const nonVerifiedToken = validToken
168
172
169 BeforeEach(func() {
173 BeforeEach(func() {
170− keyset := noOpKeySet{}
171− verifier := oidc.NewVerifier("https://issuer.example.com", keyset,
174+ verifier := oidc.NewVerifier(
175+ "https://issuer.example.com",
176+ noOpKeySet{},
177+ &oidc.Config{
172− &oidc.Config{ClientID: "https://test.myapp.com", SkipExpiryCheck: true})
178+ ClientID: "https://test.myapp.com",
179+ SkipExpiryCheck: true,
180+ },
181+ ).Verify
173
182
174 j = &jwtSessionLoader{
183 j = &jwtSessionLoader{
175 jwtRegex: regexp.MustCompile(jwtRegexFormat),
184 jwtRegex: regexp.MustCompile(jwtRegexFormat),
176− sessionLoaders: []middlewareapi.TokenToSessionLoader{
185+ sessionLoaders: []middlewareapi.TokenToSessionFunc{
177− {
186+ middlewareapi.CreateTokenToSessionFunc(verifier),
178− Verifier: verifier,
179− TokenToSession: createSessionStateFromBearerToken,
180− },
181 },
187 },
182 }
188 }
183 })
189 })
@@ -218,8 +224,11 @@ Nnc3a3lGVWFCNUMxQnNJcnJMTWxka1dFaHluYmI4Ongtb2F1dGgtYmFzaWM=`
218 }),
224 }),
219 Entry("Bearer <nonVerifiedToken>", getJWTSessionTableInput{
225 Entry("Bearer <nonVerifiedToken>", getJWTSessionTableInput{
220 authorizationHeader: fmt.Sprintf("Bearer %s", nonVerifiedToken),
226 authorizationHeader: fmt.Sprintf("Bearer %s", nonVerifiedToken),
227+ expectedErr: k8serrors.NewAggregate([]error{
221− expectedErr: errors.New("unable to verify jwt token: \"Bearer eyJfoobar.eyJfoobar.12345asdf\""),
228+ errors.New("unable to verify bearer token"),
229+ errors.New("oidc: malformed jwt: illegal base64 data at input byte 8"),
230+ }),
222− expectedSession: nil,
231+ expectedSession: nil,
223 }),
232 }),
224 Entry("Bearer <verifiedToken>", getJWTSessionTableInput{
233 Entry("Bearer <verifiedToken>", getJWTSessionTableInput{
225 authorizationHeader: fmt.Sprintf("Bearer %s", verifiedToken),
234 authorizationHeader: fmt.Sprintf("Bearer %s", verifiedToken),
@@ -228,8 +237,11 @@ Nnc3a3lGVWFCNUMxQnNJcnJMTWxka1dFaHluYmI4Ongtb2F1dGgtYmFzaWM=`
228 }),
237 }),
229 Entry("Basic Base64(<nonVerifiedToken>:) (No password)", getJWTSessionTableInput{
238 Entry("Basic Base64(<nonVerifiedToken>:) (No password)", getJWTSessionTableInput{
230 authorizationHeader: "Basic ZXlKZm9vYmFyLmV5SmZvb2Jhci4xMjM0NWFzZGY6",
239 authorizationHeader: "Basic ZXlKZm9vYmFyLmV5SmZvb2Jhci4xMjM0NWFzZGY6",
240+ expectedErr: k8serrors.NewAggregate([]error{
231− expectedErr: errors.New("unable to verify jwt token: \"Basic ZXlKZm9vYmFyLmV5SmZvb2Jhci4xMjM0NWFzZGY6\""),
241+ errors.New("unable to verify bearer token"),
242+ errors.New("oidc: malformed jwt: illegal base64 data at input byte 8"),
243+ }),
232− expectedSession: nil,
244+ expectedSession: nil,
233 }),
245 }),
234 Entry("Basic Base64(<verifiedToken>:x-oauth-basic) (Sentinel password)", getJWTSessionTableInput{
246 Entry("Basic Base64(<verifiedToken>:x-oauth-basic) (Sentinel password)", getJWTSessionTableInput{
235 authorizationHeader: fmt.Sprintf("Basic %s", verifiedTokenXOAuthBasicBase64),
247 authorizationHeader: fmt.Sprintf("Basic %s", verifiedTokenXOAuthBasicBase64),
@@ -239,7 +251,7 @@ Nnc3a3lGVWFCNUMxQnNJcnJMTWxka1dFaHluYmI4Ongtb2F1dGgtYmFzaWM=`
239 )
251 )
240 })
252 })
241
253
242− Context("findBearerTokenFromHeader", func() {
254+ Context("findTokenFromHeader", func() {
243 var j *jwtSessionLoader
255 var j *jwtSessionLoader
244
256
245 BeforeEach(func() {
257 BeforeEach(func() {
@@ -256,7 +268,7 @@ Nnc3a3lGVWFCNUMxQnNJcnJMTWxka1dFaHluYmI4Ongtb2F1dGgtYmFzaWM=`
256
268
257 DescribeTable("with a header",
269 DescribeTable("with a header",
258 func(in findBearerTokenFromHeaderTableInput) {
270 func(in findBearerTokenFromHeaderTableInput) {
259− token, err := j.findBearerTokenFromHeader(in.header)
271+ token, err := j.findTokenFromHeader(in.header)
260 if in.expectedErr != nil {
272 if in.expectedErr != nil {
261 Expect(err).To(MatchError(in.expectedErr))
273 Expect(err).To(MatchError(in.expectedErr))
262 } else {
274 } else {
@@ -381,7 +393,7 @@ Nnc3a3lGVWFCNUMxQnNJcnJMTWxka1dFaHluYmI4Ongtb2F1dGgtYmFzaWM=`
381 )
393 )
382 })
394 })
383
395
384− Context("createSessionStateFromBearerToken", func() {
396+ Context("CreateTokenToSessionFunc", func() {
385 ctx := context.Background()
397 ctx := context.Background()
386 expiresFuture := time.Now().Add(time.Duration(5) * time.Minute)
398 expiresFuture := time.Now().Add(time.Duration(5) * time.Minute)
387 verified := true
399 verified := true
@@ -393,7 +405,7 @@ Nnc3a3lGVWFCNUMxQnNJcnJMTWxka1dFaHluYmI4Ongtb2F1dGgtYmFzaWM=`
393 jwt.StandardClaims
405 jwt.StandardClaims
394 }
406 }
395
407
396− type createSessionStateTableInput struct {
408+ type tokenToSessionTableInput struct {
397 idToken idTokenClaims
409 idToken idTokenClaims
398 expectedErr error
410 expectedErr error
399 expectedUser string
411 expectedUser string
@@ -402,12 +414,19 @@ Nnc3a3lGVWFCNUMxQnNJcnJMTWxka1dFaHluYmI4Ongtb2F1dGgtYmFzaWM=`
402 }
414 }
403
415
404 DescribeTable("when creating a session from an IDToken",
416 DescribeTable("when creating a session from an IDToken",
405− func(in createSessionStateTableInput) {
417+ func(in tokenToSessionTableInput) {
418+ verifier := func(ctx context.Context, token string) (*oidc.IDToken, error) {
406− verifier := oidc.NewVerifier(
419+ oidcVerifier := oidc.NewVerifier(
407− "https://issuer.example.com",
420+ "https://issuer.example.com",
408− noOpKeySet{},
421+ noOpKeySet{},
409− &oidc.Config{ClientID: "asdf1234"},
422+ &oidc.Config{ClientID: "asdf1234"},
410− )
423+ )
424+
425+ idToken, err := oidcVerifier.Verify(ctx, token)
426+ Expect(err).ToNot(HaveOccurred())
427+
428+ return idToken, nil
429+ }
411
430
412 key, err := rsa.GenerateKey(rand.Reader, 2048)
431 key, err := rsa.GenerateKey(rand.Reader, 2048)
413 Expect(err).ToNot(HaveOccurred())
432 Expect(err).ToNot(HaveOccurred())
@@ -415,11 +434,7 @@ Nnc3a3lGVWFCNUMxQnNJcnJMTWxka1dFaHluYmI4Ongtb2F1dGgtYmFzaWM=`
415 rawIDToken, err := jwt.NewWithClaims(jwt.SigningMethodRS256, in.idToken).SignedString(key)
434 rawIDToken, err := jwt.NewWithClaims(jwt.SigningMethodRS256, in.idToken).SignedString(key)
416 Expect(err).ToNot(HaveOccurred())
435 Expect(err).ToNot(HaveOccurred())
417
436
418− // Pass to a dummy Verifier to get an oidc.IDToken from the rawIDToken for our actual test below
437+ session, err := middlewareapi.CreateTokenToSessionFunc(verifier)(ctx, rawIDToken)
419− idToken, err := verifier.Verify(context.Background(), rawIDToken)
420− Expect(err).ToNot(HaveOccurred())
421−
422− session, err := createSessionStateFromBearerToken(ctx, rawIDToken, idToken)
423 if in.expectedErr != nil {
438 if in.expectedErr != nil {
424 Expect(err).To(MatchError(in.expectedErr))
439 Expect(err).To(MatchError(in.expectedErr))
425 Expect(session).To(BeNil())
440 Expect(session).To(BeNil())
@@ -435,7 +450,7 @@ Nnc3a3lGVWFCNUMxQnNJcnJMTWxka1dFaHluYmI4Ongtb2F1dGgtYmFzaWM=`
435 Expect(session.RefreshToken).To(BeEmpty())
450 Expect(session.RefreshToken).To(BeEmpty())
436 Expect(session.PreferredUsername).To(BeEmpty())
451 Expect(session.PreferredUsername).To(BeEmpty())
437 },
452 },
438− Entry("with no email", createSessionStateTableInput{
453+ Entry("with no email", tokenToSessionTableInput{
439 idToken: idTokenClaims{
454 idToken: idTokenClaims{
440 StandardClaims: jwt.StandardClaims{
455 StandardClaims: jwt.StandardClaims{
441 Audience: "asdf1234",
456 Audience: "asdf1234",
@@ -452,7 +467,7 @@ Nnc3a3lGVWFCNUMxQnNJcnJMTWxka1dFaHluYmI4Ongtb2F1dGgtYmFzaWM=`
452 expectedEmail: "123456789",
467 expectedEmail: "123456789",
453 expectedExpires: &expiresFuture,
468 expectedExpires: &expiresFuture,
454 }),
469 }),
455− Entry("with a verified email", createSessionStateTableInput{
470+ Entry("with a verified email", tokenToSessionTableInput{
456 idToken: idTokenClaims{
471 idToken: idTokenClaims{
457 StandardClaims: jwt.StandardClaims{
472 StandardClaims: jwt.StandardClaims{
458 Audience: "asdf1234",
473 Audience: "asdf1234",
@@ -471,7 +486,7 @@ Nnc3a3lGVWFCNUMxQnNJcnJMTWxka1dFaHluYmI4Ongtb2F1dGgtYmFzaWM=`
471 expectedEmail: "foo@example.com",
486 expectedEmail: "foo@example.com",
472 expectedExpires: &expiresFuture,
487 expectedExpires: &expiresFuture,
473 }),
488 }),
474− Entry("with a non-verified email", createSessionStateTableInput{
489+ Entry("with a non-verified email", tokenToSessionTableInput{
475 idToken: idTokenClaims{
490 idToken: idTokenClaims{
476 StandardClaims: jwt.StandardClaims{
491 StandardClaims: jwt.StandardClaims{
477 Audience: "asdf1234",
492 Audience: "asdf1234",
pkg/validation/options.go+5−6
@@ -233,6 +233,9 @@ func parseProviderInfo(o *options.Options, msgs []string) []string {
233 p.ValidateURL, msgs = parseURL(o.ValidateURL, "validate", msgs)
233 p.ValidateURL, msgs = parseURL(o.ValidateURL, "validate", msgs)
234 p.ProtectedResource, msgs = parseURL(o.ProtectedResource, "resource", msgs)
234 p.ProtectedResource, msgs = parseURL(o.ProtectedResource, "resource", msgs)
235
235
236+ // Make the OIDC Verifier accessible to all providers that can support it
237+ p.Verifier = o.GetOIDCVerifier()
238+
236 p.SetAllowedGroups(o.AllowedGroups)
239 p.SetAllowedGroups(o.AllowedGroups)
237
240
238 provider := providers.New(o.ProviderType, p)
241 provider := providers.New(o.ProviderType, p)
@@ -273,18 +276,14 @@ func parseProviderInfo(o *options.Options, msgs []string) []string {
273 p.AllowUnverifiedEmail = o.InsecureOIDCAllowUnverifiedEmail
276 p.AllowUnverifiedEmail = o.InsecureOIDCAllowUnverifiedEmail
274 p.UserIDClaim = o.UserIDClaim
277 p.UserIDClaim = o.UserIDClaim
275 p.GroupsClaim = o.OIDCGroupsClaim
278 p.GroupsClaim = o.OIDCGroupsClaim
276− if o.GetOIDCVerifier() == nil {
279+ if p.Verifier == nil {
277 msgs = append(msgs, "oidc provider requires an oidc issuer URL")
280 msgs = append(msgs, "oidc provider requires an oidc issuer URL")
278− } else {
279− p.Verifier = o.GetOIDCVerifier()
280 }
281 }
281 case *providers.GitLabProvider:
282 case *providers.GitLabProvider:
282 p.AllowUnverifiedEmail = o.InsecureOIDCAllowUnverifiedEmail
283 p.AllowUnverifiedEmail = o.InsecureOIDCAllowUnverifiedEmail
283 p.Groups = o.GitLabGroup
284 p.Groups = o.GitLabGroup
284
285
285− if o.GetOIDCVerifier() != nil {
286− p.Verifier = o.GetOIDCVerifier()
286+ if p.Verifier == nil {
287− } else {
288 // Initialize with default verifier for gitlab.com
287 // Initialize with default verifier for gitlab.com
289 ctx := context.Background()
288 ctx := context.Background()
290
289
providers/digitalocean.go+1−1
@@ -83,6 +83,6 @@ func (p *DigitalOceanProvider) GetEmailAddress(ctx context.Context, s *sessions.
83}
83}
84
84
85// ValidateSessionState validates the AccessToken
85// ValidateSessionState validates the AccessToken
86−func (p *DigitalOceanProvider) ValidateSessionState(ctx context.Context, s *sessions.SessionState) bool {
86+func (p *DigitalOceanProvider) ValidateSession(ctx context.Context, s *sessions.SessionState) bool {
87 return validateToken(ctx, p, s.AccessToken, makeOIDCHeader(s.AccessToken))
87 return validateToken(ctx, p, s.AccessToken, makeOIDCHeader(s.AccessToken))
88}
88}
providers/facebook.go+1−1
@@ -89,6 +89,6 @@ func (p *FacebookProvider) GetEmailAddress(ctx context.Context, s *sessions.Sess
89}
89}
90
90
91// ValidateSessionState validates the AccessToken
91// ValidateSessionState validates the AccessToken
92−func (p *FacebookProvider) ValidateSessionState(ctx context.Context, s *sessions.SessionState) bool {
92+func (p *FacebookProvider) ValidateSession(ctx context.Context, s *sessions.SessionState) bool {
93 return validateToken(ctx, p, s.AccessToken, makeOIDCHeader(s.AccessToken))
93 return validateToken(ctx, p, s.AccessToken, makeOIDCHeader(s.AccessToken))
94}
94}
providers/github.go+2−2
@@ -103,7 +103,7 @@ func (p *GitHubProvider) SetUsers(users []string) {
103}
103}
104
104
105// EnrichSessionState updates the User & Email after the initial Redeem
105// EnrichSessionState updates the User & Email after the initial Redeem
106−func (p *GitHubProvider) EnrichSessionState(ctx context.Context, s *sessions.SessionState) error {
106+func (p *GitHubProvider) EnrichSession(ctx context.Context, s *sessions.SessionState) error {
107 err := p.getEmail(ctx, s)
107 err := p.getEmail(ctx, s)
108 if err != nil {
108 if err != nil {
109 return err
109 return err
@@ -112,7 +112,7 @@ func (p *GitHubProvider) EnrichSessionState(ctx context.Context, s *sessions.Ses
112}
112}
113
113
114// ValidateSessionState validates the AccessToken
114// ValidateSessionState validates the AccessToken
115−func (p *GitHubProvider) ValidateSessionState(ctx context.Context, s *sessions.SessionState) bool {
115+func (p *GitHubProvider) ValidateSession(ctx context.Context, s *sessions.SessionState) bool {
116 return validateToken(ctx, p, s.AccessToken, makeGitHubHeader(s.AccessToken))
116 return validateToken(ctx, p, s.AccessToken, makeGitHubHeader(s.AccessToken))
117}
117}
118
118
providers/gitlab.go+2−2
@@ -188,13 +188,13 @@ func (p *GitLabProvider) createSessionState(ctx context.Context, token *oauth2.T
188}
188}
189
189
190// ValidateSessionState checks that the session's IDToken is still valid
190// ValidateSessionState checks that the session's IDToken is still valid
191−func (p *GitLabProvider) ValidateSessionState(ctx context.Context, s *sessions.SessionState) bool {
191+func (p *GitLabProvider) ValidateSession(ctx context.Context, s *sessions.SessionState) bool {
192 _, err := p.Verifier.Verify(ctx, s.IDToken)
192 _, err := p.Verifier.Verify(ctx, s.IDToken)
193 return err == nil
193 return err == nil
194}
194}
195
195
196// GetEmailAddress returns the Account email address
196// GetEmailAddress returns the Account email address
197−func (p *GitLabProvider) EnrichSessionState(ctx context.Context, s *sessions.SessionState) error {
197+func (p *GitLabProvider) EnrichSession(ctx context.Context, s *sessions.SessionState) error {
198 // Retrieve user info
198 // Retrieve user info
199 userInfo, err := p.getUserInfo(ctx, s)
199 userInfo, err := p.getUserInfo(ctx, s)
200 if err != nil {
200 if err != nil {
providers/gitlab_test.go+6−6
@@ -64,7 +64,7 @@ func TestGitLabProviderBadToken(t *testing.T) {
64 p := testGitLabProvider(bURL.Host)
64 p := testGitLabProvider(bURL.Host)
65
65
66 session := &sessions.SessionState{AccessToken: "unexpected_gitlab_access_token"}
66 session := &sessions.SessionState{AccessToken: "unexpected_gitlab_access_token"}
67− err := p.EnrichSessionState(context.Background(), session)
67+ err := p.EnrichSession(context.Background(), session)
68 assert.Error(t, err)
68 assert.Error(t, err)
69}
69}
70
70
@@ -76,7 +76,7 @@ func TestGitLabProviderUnverifiedEmailDenied(t *testing.T) {
76 p := testGitLabProvider(bURL.Host)
76 p := testGitLabProvider(bURL.Host)
77
77
78 session := &sessions.SessionState{AccessToken: "gitlab_access_token"}
78 session := &sessions.SessionState{AccessToken: "gitlab_access_token"}
79− err := p.EnrichSessionState(context.Background(), session)
79+ err := p.EnrichSession(context.Background(), session)
80 assert.Error(t, err)
80 assert.Error(t, err)
81}
81}
82
82
@@ -89,7 +89,7 @@ func TestGitLabProviderUnverifiedEmailAllowed(t *testing.T) {
89 p.AllowUnverifiedEmail = true
89 p.AllowUnverifiedEmail = true
90
90
91 session := &sessions.SessionState{AccessToken: "gitlab_access_token"}
91 session := &sessions.SessionState{AccessToken: "gitlab_access_token"}
92− err := p.EnrichSessionState(context.Background(), session)
92+ err := p.EnrichSession(context.Background(), session)
93 assert.NoError(t, err)
93 assert.NoError(t, err)
94 assert.Equal(t, "foo@bar.com", session.Email)
94 assert.Equal(t, "foo@bar.com", session.Email)
95}
95}
@@ -103,7 +103,7 @@ func TestGitLabProviderUsername(t *testing.T) {
103 p.AllowUnverifiedEmail = true
103 p.AllowUnverifiedEmail = true
104
104
105 session := &sessions.SessionState{AccessToken: "gitlab_access_token"}
105 session := &sessions.SessionState{AccessToken: "gitlab_access_token"}
106− err := p.EnrichSessionState(context.Background(), session)
106+ err := p.EnrichSession(context.Background(), session)
107 assert.NoError(t, err)
107 assert.NoError(t, err)
108 assert.Equal(t, "FooBar", session.User)
108 assert.Equal(t, "FooBar", session.User)
109}
109}
@@ -118,7 +118,7 @@ func TestGitLabProviderGroupMembershipValid(t *testing.T) {
118 p.Groups = []string{"foo"}
118 p.Groups = []string{"foo"}
119
119
120 session := &sessions.SessionState{AccessToken: "gitlab_access_token"}
120 session := &sessions.SessionState{AccessToken: "gitlab_access_token"}
121− err := p.EnrichSessionState(context.Background(), session)
121+ err := p.EnrichSession(context.Background(), session)
122 assert.NoError(t, err)
122 assert.NoError(t, err)
123 assert.Equal(t, "FooBar", session.User)
123 assert.Equal(t, "FooBar", session.User)
124}
124}
@@ -133,6 +133,6 @@ func TestGitLabProviderGroupMembershipMissing(t *testing.T) {
133 p.Groups = []string{"baz"}
133 p.Groups = []string{"baz"}
134
134
135 session := &sessions.SessionState{AccessToken: "gitlab_access_token"}
135 session := &sessions.SessionState{AccessToken: "gitlab_access_token"}
136− err := p.EnrichSessionState(context.Background(), session)
136+ err := p.EnrichSession(context.Background(), session)
137 assert.Error(t, err)
137 assert.Error(t, err)
138}
138}
providers/google.go+1−1
@@ -179,7 +179,7 @@ func (p *GoogleProvider) Redeem(ctx context.Context, redirectURL, code string) (
179
179
180// EnrichSessionState checks the listed Google Groups configured and adds any
180// EnrichSessionState checks the listed Google Groups configured and adds any
181// that the user is a member of to session.Groups.
181// that the user is a member of to session.Groups.
182−func (p *GoogleProvider) EnrichSessionState(ctx context.Context, s *sessions.SessionState) error {
182+func (p *GoogleProvider) EnrichSession(ctx context.Context, s *sessions.SessionState) error {
183 // TODO (@NickMeves) - Move to pure EnrichSessionState logic and stop
183 // TODO (@NickMeves) - Move to pure EnrichSessionState logic and stop
184 // reusing legacy `groupValidator`.
184 // reusing legacy `groupValidator`.
185 //
185 //
providers/internal_util_test.go+1−1
@@ -32,7 +32,7 @@ func (tp *ValidateSessionStateTestProvider) GetEmailAddress(ctx context.Context,
32
32
33// Note that we're testing the internal validateToken() used to implement
33// Note that we're testing the internal validateToken() used to implement
34// several Provider's ValidateSessionState() implementations
34// several Provider's ValidateSessionState() implementations
35−func (tp *ValidateSessionStateTestProvider) ValidateSessionState(ctx context.Context, s *sessions.SessionState) bool {
35+func (tp *ValidateSessionStateTestProvider) ValidateSession(ctx context.Context, s *sessions.SessionState) bool {
36 return false
36 return false
37}
37}
38
38
providers/linkedin.go+1−1
@@ -94,6 +94,6 @@ func (p *LinkedInProvider) GetEmailAddress(ctx context.Context, s *sessions.Sess
94}
94}
95
95
96// ValidateSessionState validates the AccessToken
96// ValidateSessionState validates the AccessToken
97−func (p *LinkedInProvider) ValidateSessionState(ctx context.Context, s *sessions.SessionState) bool {
97+func (p *LinkedInProvider) ValidateSession(ctx context.Context, s *sessions.SessionState) bool {
98 return validateToken(ctx, p, s.AccessToken, makeLinkedInHeader(s.AccessToken))
98 return validateToken(ctx, p, s.AccessToken, makeLinkedInHeader(s.AccessToken))
99}
99}
providers/oidc.go+9−5
@@ -22,7 +22,6 @@ const emailClaim = "email"
22type OIDCProvider struct {
22type OIDCProvider struct {
23 *ProviderData
23 *ProviderData
24
24
25− Verifier *oidc.IDTokenVerifier
26 AllowUnverifiedEmail bool
25 AllowUnverifiedEmail bool
27 UserIDClaim string
26 UserIDClaim string
28 GroupsClaim string
27 GroupsClaim string
@@ -175,14 +174,19 @@ func (p *OIDCProvider) createSessionState(ctx context.Context, token *oauth2.Tok
175 return newSession, nil
174 return newSession, nil
176}
175}
177
176
178−func (p *OIDCProvider) CreateSessionStateFromBearerToken(ctx context.Context, rawIDToken string, idToken *oidc.IDToken) (*sessions.SessionState, error) {
177+func (p *OIDCProvider) CreateSessionFromToken(ctx context.Context, token string) (*sessions.SessionState, error) {
178+ idToken, err := p.Verifier.Verify(ctx, token)
179+ if err != nil {
180+ return nil, err
181+ }
182+
179 newSession, err := p.createSessionStateInternal(ctx, idToken, nil)
183 newSession, err := p.createSessionStateInternal(ctx, idToken, nil)
180 if err != nil {
184 if err != nil {
181 return nil, err
185 return nil, err
182 }
186 }
183
187
184− newSession.AccessToken = rawIDToken
188+ newSession.AccessToken = token
185− newSession.IDToken = rawIDToken
189+ newSession.IDToken = token
186 newSession.RefreshToken = ""
190 newSession.RefreshToken = ""
187 newSession.ExpiresOn = &idToken.Expiry
191 newSession.ExpiresOn = &idToken.Expiry
188
192
@@ -221,7 +225,7 @@ func (p *OIDCProvider) createSessionStateInternal(ctx context.Context, idToken *
221}
225}
222
226
223// ValidateSessionState checks that the session's IDToken is still valid
227// ValidateSessionState checks that the session's IDToken is still valid
224−func (p *OIDCProvider) ValidateSessionState(ctx context.Context, s *sessions.SessionState) bool {
228+func (p *OIDCProvider) ValidateSession(ctx context.Context, s *sessions.SessionState) bool {
225 _, err := p.Verifier.Verify(ctx, s.IDToken)
229 _, err := p.Verifier.Verify(ctx, s.IDToken)
226 return err == nil
230 return err == nil
227}
231}
providers/oidc_test.go+8−14
@@ -144,16 +144,17 @@ func newOIDCProvider(serverURL *url.URL) *OIDCProvider {
144 Scheme: serverURL.Scheme,
144 Scheme: serverURL.Scheme,
145 Host: serverURL.Host,
145 Host: serverURL.Host,
146 Path: "/api"},
146 Path: "/api"},
147− Scope: "openid profile offline_access"}
147+ Scope: "openid profile offline_access",
148−
149− p := &OIDCProvider{
150− ProviderData: providerData,
151 Verifier: oidc.NewVerifier(
148 Verifier: oidc.NewVerifier(
152 "https://issuer.example.com",
149 "https://issuer.example.com",
153 fakeKeySetStub{},
150 fakeKeySetStub{},
154 &oidc.Config{ClientID: clientID},
151 &oidc.Config{ClientID: clientID},
155 ),
152 ),
153+ }
154+
155+ p := &OIDCProvider{
156+ ProviderData: providerData,
156− UserIDClaim: "email",
157+ UserIDClaim: "email",
157 }
158 }
158
159
159 return p
160 return p
@@ -298,7 +299,7 @@ func TestOIDCProviderRefreshSessionIfNeededWithIdToken(t *testing.T) {
298 assert.Equal(t, refreshToken, existingSession.RefreshToken)
299 assert.Equal(t, refreshToken, existingSession.RefreshToken)
299}
300}
300
301
301−func TestCreateSessionStateFromBearerToken(t *testing.T) {
302+func TestOIDCProviderCreateSessionFromToken(t *testing.T) {
302 const profileURLEmail = "janed@me.com"
303 const profileURLEmail = "janed@me.com"
303
304
304 testCases := map[string]struct {
305 testCases := map[string]struct {
@@ -347,14 +348,7 @@ func TestCreateSessionStateFromBearerToken(t *testing.T) {
347 rawIDToken, err := newSignedTestIDToken(tc.IDToken)
348 rawIDToken, err := newSignedTestIDToken(tc.IDToken)
348 assert.NoError(t, err)
349 assert.NoError(t, err)
349
350
350− keyset := fakeKeySetStub{}
351− verifier := oidc.NewVerifier("https://issuer.example.com", keyset,
352− &oidc.Config{ClientID: "https://test.myapp.com", SkipExpiryCheck: true})
353−
354− idToken, err := verifier.Verify(context.Background(), rawIDToken)
355− assert.NoError(t, err)
356−
357− ss, err := provider.CreateSessionStateFromBearerToken(context.Background(), rawIDToken, idToken)
351+ ss, err := provider.CreateSessionFromToken(context.Background(), rawIDToken)
358 assert.NoError(t, err)
352 assert.NoError(t, err)
359
353
360 assert.Equal(t, tc.ExpectedUser, ss.User)
354 assert.Equal(t, tc.ExpectedUser, ss.User)
providers/provider_data.go+2
@@ -5,6 +5,7 @@ import (
5 "io/ioutil"
5 "io/ioutil"
6 "net/url"
6 "net/url"
7
7
8+ "github.com/coreos/go-oidc"
8 "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/logger"
9 "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/logger"
9)
10)
10
11
@@ -26,6 +27,7 @@ type ProviderData struct {
26 ClientSecretFile string
27 ClientSecretFile string
27 Scope string
28 Scope string
28 Prompt string
29 Prompt string
30+ Verifier *oidc.IDTokenVerifier
29
31
30 // Universal Group authorization data structure
32 // Universal Group authorization data structure
31 // any provider can set to consume
33 // any provider can set to consume
providers/provider_default.go+8−7
@@ -8,8 +8,7 @@ import (
8 "net/url"
8 "net/url"
9 "time"
9 "time"
10
10
11− "github.com/coreos/go-oidc"
11+ "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/middleware"
12−
13 "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/sessions"
12 "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/sessions"
14 "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/requests"
13 "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/requests"
15)
14)
@@ -94,7 +93,7 @@ func (p *ProviderData) GetEmailAddress(_ context.Context, _ *sessions.SessionSta
94
93
95// EnrichSessionState is called after Redeem to allow providers to enrich session fields
94// EnrichSessionState is called after Redeem to allow providers to enrich session fields
96// such as User, Email, Groups with provider specific API calls.
95// such as User, Email, Groups with provider specific API calls.
97−func (p *ProviderData) EnrichSessionState(_ context.Context, _ *sessions.SessionState) error {
96+func (p *ProviderData) EnrichSession(_ context.Context, _ *sessions.SessionState) error {
98 return nil
97 return nil
99}
98}
100
99
@@ -115,7 +114,7 @@ func (p *ProviderData) Authorize(_ context.Context, s *sessions.SessionState) (b
115}
114}
116
115
117// ValidateSessionState validates the AccessToken
116// ValidateSessionState validates the AccessToken
118−func (p *ProviderData) ValidateSessionState(ctx context.Context, s *sessions.SessionState) bool {
117+func (p *ProviderData) ValidateSession(ctx context.Context, s *sessions.SessionState) bool {
119 return validateToken(ctx, p, s.AccessToken, nil)
118 return validateToken(ctx, p, s.AccessToken, nil)
120}
119}
121
120
@@ -125,8 +124,10 @@ func (p *ProviderData) RefreshSessionIfNeeded(_ context.Context, _ *sessions.Ses
125 return false, nil
124 return false, nil
126}
125}
127
126
128−// CreateSessionStateFromBearerToken should be implemented to allow providers
127+// CreateSessionFromToken converts Bearer IDTokens into sessions
129−// to convert ID tokens into sessions
130−func (p *ProviderData) CreateSessionStateFromBearerToken(_ context.Context, _ string, _ *oidc.IDToken) (*sessions.SessionState, error) {
128+func (p *ProviderData) CreateSessionFromToken(ctx context.Context, token string) (*sessions.SessionState, error) {
129+ if p.Verifier != nil {
130+ return middleware.CreateTokenToSessionFunc(p.Verifier.Verify)(ctx, token)
131+ }
131 return nil, ErrNotImplemented
132 return nil, ErrNotImplemented
132}
133}
providers/provider_default_test.go+5−2
@@ -49,10 +49,13 @@ func TestAcrValuesConfigured(t *testing.T) {
49 assert.Contains(t, result, "acr_values=testValue")
49 assert.Contains(t, result, "acr_values=testValue")
50}
50}
51
51
52−func TestEnrichSessionState(t *testing.T) {
52+func TestProviderDataEnrichSession(t *testing.T) {
53+ g := NewWithT(t)
53 p := &ProviderData{}
54 p := &ProviderData{}
54 s := &sessions.SessionState{}
55 s := &sessions.SessionState{}
56+
55− assert.NoError(t, p.EnrichSessionState(context.Background(), s))
57+ err := p.EnrichSession(context.Background(), s)
58+ g.Expect(err).ToNot(HaveOccurred())
56}
59}
57
60
58func TestProviderDataAuthorize(t *testing.T) {
61func TestProviderDataAuthorize(t *testing.T) {
providers/providers.go+3−4
@@ -3,7 +3,6 @@ package providers
3import (
3import (
4 "context"
4 "context"
5
5
6− "github.com/coreos/go-oidc"
7 "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/sessions"
6 "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/sessions"
8)
7)
9
8
@@ -13,12 +12,12 @@ type Provider interface {
13 // DEPRECATED: Migrate to EnrichSessionState
12 // DEPRECATED: Migrate to EnrichSessionState
14 GetEmailAddress(ctx context.Context, s *sessions.SessionState) (string, error)
13 GetEmailAddress(ctx context.Context, s *sessions.SessionState) (string, error)
15 Redeem(ctx context.Context, redirectURI, code string) (*sessions.SessionState, error)
14 Redeem(ctx context.Context, redirectURI, code string) (*sessions.SessionState, error)
16− EnrichSessionState(ctx context.Context, s *sessions.SessionState) error
15+ EnrichSession(ctx context.Context, s *sessions.SessionState) error
17 Authorize(ctx context.Context, s *sessions.SessionState) (bool, error)
16 Authorize(ctx context.Context, s *sessions.SessionState) (bool, error)
18− ValidateSessionState(ctx context.Context, s *sessions.SessionState) bool
17+ ValidateSession(ctx context.Context, s *sessions.SessionState) bool
19 GetLoginURL(redirectURI, finalRedirect string) string
18 GetLoginURL(redirectURI, finalRedirect string) string
20 RefreshSessionIfNeeded(ctx context.Context, s *sessions.SessionState) (bool, error)
19 RefreshSessionIfNeeded(ctx context.Context, s *sessions.SessionState) (bool, error)
21− CreateSessionStateFromBearerToken(ctx context.Context, rawIDToken string, idToken *oidc.IDToken) (*sessions.SessionState, error)
20+ CreateSessionFromToken(ctx context.Context, token string) (*sessions.SessionState, error)
22}
21}
23
22
24// New provides a new Provider based on the configured provider string
23// New provides a new Provider based on the configured provider string