Merge pull request #484 from oauth2-proxy/cookie-options-rename
Replace configuration loading with Viper
This commit is contained in:
		
						commit
						eae652d986
					
				|  | @ -11,14 +11,18 @@ | ||||||
| - Migration from Pusher to independent org may have introduced breaking changes for your environment. | - Migration from Pusher to independent org may have introduced breaking changes for your environment. | ||||||
|   - See the changes listed below for PR [#464](https://github.com/oauth2-proxy/oauth2-proxy/pull/464) for full details |   - See the changes listed below for PR [#464](https://github.com/oauth2-proxy/oauth2-proxy/pull/464) for full details | ||||||
|   - Binaries renamed from `oauth2_proxy` to `oauth2-proxy` |   - Binaries renamed from `oauth2_proxy` to `oauth2-proxy` | ||||||
| 
 |  | ||||||
| - [#440](https://github.com/oauth2-proxy/oauth2-proxy/pull/440) Switch Azure AD Graph API to Microsoft Graph API (@johejo) | - [#440](https://github.com/oauth2-proxy/oauth2-proxy/pull/440) Switch Azure AD Graph API to Microsoft Graph API (@johejo) | ||||||
|   - The Azure AD Graph API has been [deprecated](https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-graph-api) and is being replaced by the Microsoft Graph API. |   - The Azure AD Graph API has been [deprecated](https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-graph-api) and is being replaced by the Microsoft Graph API. | ||||||
|       If your application relies on the access token being passed to it to access the Azure AD Graph API, you should migrate your application to use the Microsoft Graph API. |       If your application relies on the access token being passed to it to access the Azure AD Graph API, you should migrate your application to use the Microsoft Graph API. | ||||||
|       Existing behaviour can be retained by setting  `-resource=https://graph.windows.net`. |       Existing behaviour can be retained by setting  `-resource=https://graph.windows.net`. | ||||||
|  | - [#484](https://github.com/oauth2-proxy/oauth2-proxy/pull/484) Configuration loading has been replaced with Viper and PFlag | ||||||
|  |   - Flags now require a `--` prefix before the option | ||||||
|  |   - Previously flags allowed either `-` or `--` to prefix the option name | ||||||
|  |   - Eg `-provider` must now be `--provider` | ||||||
| 
 | 
 | ||||||
| ## Changes since v5.1.0 | ## Changes since v5.1.0 | ||||||
| 
 | 
 | ||||||
|  | - [#484](https://github.com/oauth2-proxy/oauth2-proxy/pull/484) Replace configuration loading with Viper (@JoelSpeed) | ||||||
| - [#499](https://github.com/oauth2-proxy/oauth2-proxy/pull/469) Add `-user-id-claim` to support generic claims in addition to email | - [#499](https://github.com/oauth2-proxy/oauth2-proxy/pull/469) Add `-user-id-claim` to support generic claims in addition to email | ||||||
| - [#486](https://github.com/oauth2-proxy/oauth2-proxy/pull/486) Add new linters (@johejo) | - [#486](https://github.com/oauth2-proxy/oauth2-proxy/pull/486) Add new linters (@johejo) | ||||||
| - [#440](https://github.com/oauth2-proxy/oauth2-proxy/pull/440) Switch Azure AD Graph API to Microsoft Graph API (@johejo) | - [#440](https://github.com/oauth2-proxy/oauth2-proxy/pull/440) Switch Azure AD Graph API to Microsoft Graph API (@johejo) | ||||||
|  |  | ||||||
|  | @ -1,54 +0,0 @@ | ||||||
| package main |  | ||||||
| 
 |  | ||||||
| import ( |  | ||||||
| 	"os" |  | ||||||
| 	"reflect" |  | ||||||
| 	"strings" |  | ||||||
| ) |  | ||||||
| 
 |  | ||||||
| // EnvOptions holds program options loaded from the process environment
 |  | ||||||
| type EnvOptions map[string]interface{} |  | ||||||
| 
 |  | ||||||
| // LoadEnvForStruct loads environment variables for each field in an options
 |  | ||||||
| // struct passed into it.
 |  | ||||||
| //
 |  | ||||||
| // Fields in the options struct must have an `env` and `cfg` tag to be read
 |  | ||||||
| // from the environment
 |  | ||||||
| func (cfg EnvOptions) LoadEnvForStruct(options interface{}) { |  | ||||||
| 	val := reflect.ValueOf(options) |  | ||||||
| 	var typ reflect.Type |  | ||||||
| 	if val.Kind() == reflect.Ptr { |  | ||||||
| 		typ = val.Elem().Type() |  | ||||||
| 	} else { |  | ||||||
| 		typ = val.Type() |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	for i := 0; i < typ.NumField(); i++ { |  | ||||||
| 		// pull out the struct tags:
 |  | ||||||
| 		//    flag - the name of the command line flag
 |  | ||||||
| 		//    deprecated - (optional) the name of the deprecated command line flag
 |  | ||||||
| 		//    cfg - (optional, defaults to underscored flag) the name of the config file option
 |  | ||||||
| 		field := typ.Field(i) |  | ||||||
| 		fieldV := reflect.Indirect(val).Field(i) |  | ||||||
| 
 |  | ||||||
| 		if field.Type.Kind() == reflect.Struct && field.Anonymous { |  | ||||||
| 			cfg.LoadEnvForStruct(fieldV.Interface()) |  | ||||||
| 			continue |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		flagName := field.Tag.Get("flag") |  | ||||||
| 		envName := field.Tag.Get("env") |  | ||||||
| 		cfgName := field.Tag.Get("cfg") |  | ||||||
| 		if cfgName == "" && flagName != "" { |  | ||||||
| 			cfgName = strings.ReplaceAll(flagName, "-", "_") |  | ||||||
| 		} |  | ||||||
| 		if envName == "" || cfgName == "" { |  | ||||||
| 			// resolvable fields must have the `env` and `cfg` struct tag
 |  | ||||||
| 			continue |  | ||||||
| 		} |  | ||||||
| 		v := os.Getenv(envName) |  | ||||||
| 		if v != "" { |  | ||||||
| 			cfg[cfgName] = v |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  | @ -1,46 +0,0 @@ | ||||||
| package main_test |  | ||||||
| 
 |  | ||||||
| import ( |  | ||||||
| 	"os" |  | ||||||
| 	"testing" |  | ||||||
| 
 |  | ||||||
| 	proxy "github.com/oauth2-proxy/oauth2-proxy" |  | ||||||
| 	"github.com/stretchr/testify/assert" |  | ||||||
| ) |  | ||||||
| 
 |  | ||||||
| type EnvTest struct { |  | ||||||
| 	TestField string `cfg:"target_field" env:"TEST_ENV_FIELD"` |  | ||||||
| 	EnvTestEmbed |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| type EnvTestEmbed struct { |  | ||||||
| 	TestFieldEmbed string `cfg:"target_field_embed" env:"TEST_ENV_FIELD_EMBED"` |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func TestLoadEnvForStruct(t *testing.T) { |  | ||||||
| 
 |  | ||||||
| 	cfg := make(proxy.EnvOptions) |  | ||||||
| 	cfg.LoadEnvForStruct(&EnvTest{}) |  | ||||||
| 
 |  | ||||||
| 	_, ok := cfg["target_field"] |  | ||||||
| 	assert.Equal(t, ok, false) |  | ||||||
| 
 |  | ||||||
| 	os.Setenv("TEST_ENV_FIELD", "1234abcd") |  | ||||||
| 	cfg.LoadEnvForStruct(&EnvTest{}) |  | ||||||
| 	v := cfg["target_field"] |  | ||||||
| 	assert.Equal(t, v, "1234abcd") |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func TestLoadEnvForStructWithEmbeddedFields(t *testing.T) { |  | ||||||
| 
 |  | ||||||
| 	cfg := make(proxy.EnvOptions) |  | ||||||
| 	cfg.LoadEnvForStruct(&EnvTest{}) |  | ||||||
| 
 |  | ||||||
| 	_, ok := cfg["target_field_embed"] |  | ||||||
| 	assert.Equal(t, ok, false) |  | ||||||
| 
 |  | ||||||
| 	os.Setenv("TEST_ENV_FIELD_EMBED", "1234abcd") |  | ||||||
| 	cfg.LoadEnvForStruct(&EnvTest{}) |  | ||||||
| 	v := cfg["target_field_embed"] |  | ||||||
| 	assert.Equal(t, v, "1234abcd") |  | ||||||
| } |  | ||||||
							
								
								
									
										5
									
								
								go.mod
								
								
								
								
							
							
						
						
									
										5
									
								
								go.mod
								
								
								
								
							|  | @ -3,7 +3,6 @@ module github.com/oauth2-proxy/oauth2-proxy | ||||||
| go 1.14 | go 1.14 | ||||||
| 
 | 
 | ||||||
| require ( | require ( | ||||||
| 	github.com/BurntSushi/toml v0.3.1 |  | ||||||
| 	github.com/alicebob/miniredis/v2 v2.11.2 | 	github.com/alicebob/miniredis/v2 v2.11.2 | ||||||
| 	github.com/bitly/go-simplejson v0.5.0 | 	github.com/bitly/go-simplejson v0.5.0 | ||||||
| 	github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 // indirect | 	github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 // indirect | ||||||
|  | @ -13,10 +12,12 @@ require ( | ||||||
| 	github.com/go-redis/redis/v7 v7.2.0 | 	github.com/go-redis/redis/v7 v7.2.0 | ||||||
| 	github.com/kr/pretty v0.2.0 // indirect | 	github.com/kr/pretty v0.2.0 // indirect | ||||||
| 	github.com/mbland/hmacauth v0.0.0-20170912233209-44256dfd4bfa | 	github.com/mbland/hmacauth v0.0.0-20170912233209-44256dfd4bfa | ||||||
| 	github.com/mreiferson/go-options v1.0.0 | 	github.com/mitchellh/mapstructure v1.1.2 | ||||||
| 	github.com/onsi/ginkgo v1.12.0 | 	github.com/onsi/ginkgo v1.12.0 | ||||||
| 	github.com/onsi/gomega v1.9.0 | 	github.com/onsi/gomega v1.9.0 | ||||||
| 	github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 // indirect | 	github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 // indirect | ||||||
|  | 	github.com/spf13/pflag v1.0.3 | ||||||
|  | 	github.com/spf13/viper v1.6.3 | ||||||
| 	github.com/stretchr/testify v1.5.1 | 	github.com/stretchr/testify v1.5.1 | ||||||
| 	github.com/yhat/wsutil v0.0.0-20170731153501-1d66fa95c997 | 	github.com/yhat/wsutil v0.0.0-20170731153501-1d66fa95c997 | ||||||
| 	golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 | 	golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 | ||||||
|  |  | ||||||
							
								
								
									
										114
									
								
								go.sum
								
								
								
								
							
							
						
						
									
										114
									
								
								go.sum
								
								
								
								
							|  | @ -4,67 +4,118 @@ cloud.google.com/go v0.38.0 h1:ROfEUZz+Gh5pa62DJWXSaonyu3StP6EA6lPEXPI6mCo= | ||||||
| cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= | cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= | ||||||
| github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= | github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= | ||||||
| github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= | github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= | ||||||
|  | github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= | ||||||
|  | github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= | ||||||
|  | github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= | ||||||
| github.com/alicebob/gopher-json v0.0.0-20180125190556-5a6b3ba71ee6 h1:45bxf7AZMwWcqkLzDAQugVEwedisr5nRJ1r+7LYnv0U= | github.com/alicebob/gopher-json v0.0.0-20180125190556-5a6b3ba71ee6 h1:45bxf7AZMwWcqkLzDAQugVEwedisr5nRJ1r+7LYnv0U= | ||||||
| github.com/alicebob/gopher-json v0.0.0-20180125190556-5a6b3ba71ee6/go.mod h1:SGnFV6hVsYE877CKEZ6tDNTjaSXYUk6QqoIK6PrAtcc= | github.com/alicebob/gopher-json v0.0.0-20180125190556-5a6b3ba71ee6/go.mod h1:SGnFV6hVsYE877CKEZ6tDNTjaSXYUk6QqoIK6PrAtcc= | ||||||
| github.com/alicebob/miniredis/v2 v2.11.2 h1:OtWO7akm5otuhssnE/sNfsWxG4gZ8DbGhShDtRrByJs= | github.com/alicebob/miniredis/v2 v2.11.2 h1:OtWO7akm5otuhssnE/sNfsWxG4gZ8DbGhShDtRrByJs= | ||||||
| github.com/alicebob/miniredis/v2 v2.11.2/go.mod h1:VL3UDEfAH59bSa7MuHMuFToxkqyHh69s/WUbYlOAuyg= | github.com/alicebob/miniredis/v2 v2.11.2/go.mod h1:VL3UDEfAH59bSa7MuHMuFToxkqyHh69s/WUbYlOAuyg= | ||||||
|  | github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= | ||||||
|  | github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= | ||||||
|  | github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= | ||||||
| github.com/bitly/go-simplejson v0.5.0 h1:6IH+V8/tVMab511d5bn4M7EwGXZf9Hj6i2xSwkNEM+Y= | github.com/bitly/go-simplejson v0.5.0 h1:6IH+V8/tVMab511d5bn4M7EwGXZf9Hj6i2xSwkNEM+Y= | ||||||
| github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA= | github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA= | ||||||
| github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY= | github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY= | ||||||
| github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= | github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= | ||||||
| github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= | github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= | ||||||
|  | github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= | ||||||
| github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= | github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= | ||||||
| github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= | github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= | ||||||
| github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= | github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= | ||||||
| github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= | github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= | ||||||
|  | github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= | ||||||
|  | github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= | ||||||
| github.com/coreos/go-oidc v2.2.1+incompatible h1:mh48q/BqXqgjVHpy2ZY7WnWAbenxRjsz9N1i1YxjHAk= | github.com/coreos/go-oidc v2.2.1+incompatible h1:mh48q/BqXqgjVHpy2ZY7WnWAbenxRjsz9N1i1YxjHAk= | ||||||
| github.com/coreos/go-oidc v2.2.1+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= | github.com/coreos/go-oidc v2.2.1+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= | ||||||
|  | github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= | ||||||
|  | github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= | ||||||
|  | github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= | ||||||
| github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= | github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= | ||||||
| github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | ||||||
|  | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= | ||||||
|  | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | ||||||
| github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= | github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= | ||||||
| github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= | github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= | ||||||
|  | github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= | ||||||
| github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= | github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= | ||||||
| github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= | github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= | ||||||
| github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= | github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= | ||||||
| github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= | github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= | ||||||
| github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= | github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= | ||||||
| github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= | github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= | ||||||
|  | github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= | ||||||
|  | github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= | ||||||
|  | github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= | ||||||
|  | github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= | ||||||
| github.com/go-redis/redis/v7 v7.2.0 h1:CrCexy/jYWZjW0AyVoHlcJUeZN19VWlbepTh1Vq6dJs= | github.com/go-redis/redis/v7 v7.2.0 h1:CrCexy/jYWZjW0AyVoHlcJUeZN19VWlbepTh1Vq6dJs= | ||||||
| github.com/go-redis/redis/v7 v7.2.0/go.mod h1:JDNMw23GTyLNC4GZu9njt15ctBQVn7xjRfnwdHj/Dcg= | github.com/go-redis/redis/v7 v7.2.0/go.mod h1:JDNMw23GTyLNC4GZu9njt15ctBQVn7xjRfnwdHj/Dcg= | ||||||
|  | github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= | ||||||
|  | github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= | ||||||
|  | github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= | ||||||
| github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= | ||||||
| github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= | ||||||
|  | github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= | ||||||
| github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= | github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= | ||||||
| github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= | github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= | ||||||
| github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= | ||||||
|  | github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= | ||||||
| github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= | github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= | ||||||
| github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= | github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= | ||||||
| github.com/gomodule/redigo v1.7.1-0.20190322064113-39e2c31b7ca3 h1:6amM4HsNPOvMLVc2ZnyqrjeQ92YAVWn7T4WBKK87inY= | github.com/gomodule/redigo v1.7.1-0.20190322064113-39e2c31b7ca3 h1:6amM4HsNPOvMLVc2ZnyqrjeQ92YAVWn7T4WBKK87inY= | ||||||
| github.com/gomodule/redigo v1.7.1-0.20190322064113-39e2c31b7ca3/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4= | github.com/gomodule/redigo v1.7.1-0.20190322064113-39e2c31b7ca3/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4= | ||||||
| github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= | github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= | ||||||
|  | github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= | ||||||
| github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= | github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= | ||||||
| github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY= | github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY= | ||||||
| github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= | github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= | ||||||
|  | github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= | ||||||
| github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= | github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= | ||||||
| github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= | github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= | ||||||
| github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= | github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= | ||||||
| github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM= | github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM= | ||||||
| github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= | github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= | ||||||
|  | github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= | ||||||
|  | github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= | ||||||
|  | github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= | ||||||
|  | github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= | ||||||
|  | github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= | ||||||
|  | github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= | ||||||
| github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= | github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= | ||||||
| github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU= | github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU= | ||||||
| github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= | github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= | ||||||
|  | github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= | ||||||
|  | github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= | ||||||
| github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= | github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= | ||||||
| github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= | github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= | ||||||
|  | github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= | ||||||
|  | github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= | ||||||
| github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= | github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= | ||||||
|  | github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= | ||||||
|  | github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= | ||||||
|  | github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= | ||||||
|  | github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= | ||||||
|  | github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= | ||||||
|  | github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= | ||||||
|  | github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= | ||||||
| github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= | ||||||
| github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs= | github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs= | ||||||
| github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= | github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= | ||||||
| github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= | ||||||
| github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= | github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= | ||||||
| github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= | ||||||
|  | github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4= | ||||||
|  | github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= | ||||||
|  | github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= | ||||||
| github.com/mbland/hmacauth v0.0.0-20170912233209-44256dfd4bfa h1:hI1uC2A3vJFjwvBn0G0a7QBRdBUp6Y048BtLAHRTKPo= | github.com/mbland/hmacauth v0.0.0-20170912233209-44256dfd4bfa h1:hI1uC2A3vJFjwvBn0G0a7QBRdBUp6Y048BtLAHRTKPo= | ||||||
| github.com/mbland/hmacauth v0.0.0-20170912233209-44256dfd4bfa/go.mod h1:8vxFeeg++MqgCHwehSuwTlYCF0ALyDJbYJ1JsKi7v6s= | github.com/mbland/hmacauth v0.0.0-20170912233209-44256dfd4bfa/go.mod h1:8vxFeeg++MqgCHwehSuwTlYCF0ALyDJbYJ1JsKi7v6s= | ||||||
| github.com/mreiferson/go-options v1.0.0 h1:RMLidydGlDWpL+lQTXo0bVIf/XT2CTq7AEJMoz5/VWs= | github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= | ||||||
| github.com/mreiferson/go-options v1.0.0/go.mod h1:zHtCks/HQvOt8ATyfwVe3JJq2PPuImzXINPRTC03+9w= | github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= | ||||||
|  | github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= | ||||||
|  | github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= | ||||||
|  | github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= | ||||||
|  | github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= | ||||||
|  | github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= | ||||||
| github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= | github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= | ||||||
| github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= | github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= | ||||||
| github.com/onsi/ginkgo v1.12.0 h1:Iw5WCbBcaAAd0fpRb1c9r5YCylv4XDoCSigm1zLevwU= | github.com/onsi/ginkgo v1.12.0 h1:Iw5WCbBcaAAd0fpRb1c9r5YCylv4XDoCSigm1zLevwU= | ||||||
|  | @ -73,20 +124,63 @@ github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1Cpa | ||||||
| github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= | github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= | ||||||
| github.com/onsi/gomega v1.9.0 h1:R1uwffexN6Pr340GtYRIdZmAiN4J+iw6WG4wog1DUXg= | github.com/onsi/gomega v1.9.0 h1:R1uwffexN6Pr340GtYRIdZmAiN4J+iw6WG4wog1DUXg= | ||||||
| github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= | github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= | ||||||
|  | github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc= | ||||||
|  | github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= | ||||||
|  | github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= | ||||||
| github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= | ||||||
| github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= | ||||||
| github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 h1:J9b7z+QKAmPf4YLrFg6oQUotqHQeUNWwkvo7jZp1GLU= | github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 h1:J9b7z+QKAmPf4YLrFg6oQUotqHQeUNWwkvo7jZp1GLU= | ||||||
| github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= | github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= | ||||||
|  | github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= | ||||||
|  | github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= | ||||||
|  | github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= | ||||||
|  | github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= | ||||||
| github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= | github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= | ||||||
|  | github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= | ||||||
|  | github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= | ||||||
|  | github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= | ||||||
|  | github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= | ||||||
|  | github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= | ||||||
|  | github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= | ||||||
|  | github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= | ||||||
|  | github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= | ||||||
|  | github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= | ||||||
|  | github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= | ||||||
|  | github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= | ||||||
|  | github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= | ||||||
|  | github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= | ||||||
|  | github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI= | ||||||
|  | github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= | ||||||
|  | github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8= | ||||||
|  | github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= | ||||||
|  | github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk= | ||||||
|  | github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= | ||||||
|  | github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg= | ||||||
|  | github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= | ||||||
|  | github.com/spf13/viper v1.6.3 h1:pDDu1OyEDTKzpJwdq4TiuLyMsUgRa/BT5cn5O62NoHs= | ||||||
|  | github.com/spf13/viper v1.6.3/go.mod h1:jUMtyi0/lB5yZH/FjyGAoH7IMNrIhlBf6pXZmbMDvzw= | ||||||
| github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | ||||||
|  | github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | ||||||
|  | github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= | ||||||
|  | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= | ||||||
| github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= | github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= | ||||||
| github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= | github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= | ||||||
|  | github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= | ||||||
|  | github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= | ||||||
|  | github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= | ||||||
|  | github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= | ||||||
|  | github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= | ||||||
| github.com/yhat/wsutil v0.0.0-20170731153501-1d66fa95c997 h1:1+FQ4Ns+UZtUiQ4lP0sTCyKSQ0EXoiwAdHZB0Pd5t9Q= | github.com/yhat/wsutil v0.0.0-20170731153501-1d66fa95c997 h1:1+FQ4Ns+UZtUiQ4lP0sTCyKSQ0EXoiwAdHZB0Pd5t9Q= | ||||||
| github.com/yhat/wsutil v0.0.0-20170731153501-1d66fa95c997/go.mod h1:DIGbh/f5XMAessMV/uaIik81gkDVjUeQ9ApdaU7wRKE= | github.com/yhat/wsutil v0.0.0-20170731153501-1d66fa95c997/go.mod h1:DIGbh/f5XMAessMV/uaIik81gkDVjUeQ9ApdaU7wRKE= | ||||||
| github.com/yuin/gopher-lua v0.0.0-20191220021717-ab39c6098bdb h1:ZkM6LRnq40pR1Ox0hTHlnpkcOTuFIDQpZ1IN8rKKhX0= | github.com/yuin/gopher-lua v0.0.0-20191220021717-ab39c6098bdb h1:ZkM6LRnq40pR1Ox0hTHlnpkcOTuFIDQpZ1IN8rKKhX0= | ||||||
| github.com/yuin/gopher-lua v0.0.0-20191220021717-ab39c6098bdb/go.mod h1:gqRgreBUhTSL0GeU64rtZ3Uq3wtjOa/TB2YfrtkCbVQ= | github.com/yuin/gopher-lua v0.0.0-20191220021717-ab39c6098bdb/go.mod h1:gqRgreBUhTSL0GeU64rtZ3Uq3wtjOa/TB2YfrtkCbVQ= | ||||||
|  | go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= | ||||||
| go.opencensus.io v0.21.0 h1:mU6zScU4U1YAFPHEHYk+3JC4SY7JxgkqS10ZOSyksNg= | go.opencensus.io v0.21.0 h1:mU6zScU4U1YAFPHEHYk+3JC4SY7JxgkqS10ZOSyksNg= | ||||||
| go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= | go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= | ||||||
|  | go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= | ||||||
|  | go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= | ||||||
|  | go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= | ||||||
|  | golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= | ||||||
| golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M= | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M= | ||||||
| golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= | ||||||
| golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= | golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= | ||||||
|  | @ -98,11 +192,14 @@ golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHl | ||||||
| golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | ||||||
| golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | ||||||
| golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | ||||||
|  | golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | ||||||
|  | golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | ||||||
| golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | ||||||
| golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | ||||||
| golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= | ||||||
| golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c h1:uOCk1iQW6Vc18bnC13MfzScl+wdKBmM9Y9kU7Z83/lw= | golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c h1:uOCk1iQW6Vc18bnC13MfzScl+wdKBmM9Y9kU7Z83/lw= | ||||||
| golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= | golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= | ||||||
|  | golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= | ||||||
| golang.org/x/net v0.0.0-20190923162816-aa69164e4478 h1:l5EDrHhldLYb3ZRHDUhXF7Om7MvYXnkV9/iQNo1lX6g= | golang.org/x/net v0.0.0-20190923162816-aa69164e4478 h1:l5EDrHhldLYb3ZRHDUhXF7Om7MvYXnkV9/iQNo1lX6g= | ||||||
| golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= | golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= | ||||||
| golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= | golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= | ||||||
|  | @ -117,7 +214,10 @@ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJ | ||||||
| golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | ||||||
| golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | ||||||
| golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||||||
|  | golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||||||
| golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||||||
|  | golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||||||
|  | golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||||||
| golang.org/x/sys v0.0.0-20190204203706-41f3e6584952/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | golang.org/x/sys v0.0.0-20190204203706-41f3e6584952/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||||||
| golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||||||
| golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b h1:ag/x1USPSsqHud38I9BAC88qdNLDHHtQ4mlgQIZPPNA= | golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b h1:ag/x1USPSsqHud38I9BAC88qdNLDHHtQ4mlgQIZPPNA= | ||||||
|  | @ -131,11 +231,14 @@ golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3 | ||||||
| golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= | golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= | ||||||
| golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= | golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= | ||||||
| golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= | golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= | ||||||
|  | golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= | ||||||
|  | golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | ||||||
| golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | ||||||
| golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | ||||||
| golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= | golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= | ||||||
| golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= | golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= | ||||||
| golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= | golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= | ||||||
|  | golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= | ||||||
| golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= | golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= | ||||||
| golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7 h1:9zdDQZ7Thm29KFXgAX/+yaf3eVbP7djjWp/dXAppNCc= | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7 h1:9zdDQZ7Thm29KFXgAX/+yaf3eVbP7djjWp/dXAppNCc= | ||||||
| golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | ||||||
|  | @ -152,21 +255,28 @@ google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRn | ||||||
| google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 h1:gSJIx1SDwno+2ElGhA4+qG2zF97qiUzTM+rQ0klBOcE= | google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 h1:gSJIx1SDwno+2ElGhA4+qG2zF97qiUzTM+rQ0klBOcE= | ||||||
| google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= | google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= | ||||||
| google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= | google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= | ||||||
|  | google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= | ||||||
| google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= | google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= | ||||||
| google.golang.org/grpc v1.27.0 h1:rRYRFMVgRv6E0D70Skyfsr28tDXIuuPZyWGMPdMcnXg= | google.golang.org/grpc v1.27.0 h1:rRYRFMVgRv6E0D70Skyfsr28tDXIuuPZyWGMPdMcnXg= | ||||||
| google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= | google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= | ||||||
|  | gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= | ||||||
| gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= | ||||||
| gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | ||||||
|  | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | ||||||
| gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= | gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= | ||||||
| gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | ||||||
| gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= | gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= | ||||||
| gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= | gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= | ||||||
|  | gopkg.in/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno= | ||||||
|  | gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= | ||||||
| gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= | gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= | ||||||
| gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= | gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= | ||||||
|  | gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= | ||||||
| gopkg.in/square/go-jose.v2 v2.4.1 h1:H0TmLt7/KmzlrDOpa1F+zr0Tk90PbJYBfsVUmRLrf9Y= | gopkg.in/square/go-jose.v2 v2.4.1 h1:H0TmLt7/KmzlrDOpa1F+zr0Tk90PbJYBfsVUmRLrf9Y= | ||||||
| gopkg.in/square/go-jose.v2 v2.4.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= | gopkg.in/square/go-jose.v2 v2.4.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= | ||||||
| gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= | gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= | ||||||
| gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= | gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= | ||||||
|  | gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= | ||||||
| gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= | gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= | ||||||
| gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= | gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= | ||||||
| gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= | ||||||
|  |  | ||||||
							
								
								
									
										22
									
								
								main.go
								
								
								
								
							
							
						
						
									
										22
									
								
								main.go
								
								
								
								
							|  | @ -12,9 +12,9 @@ import ( | ||||||
| 	"syscall" | 	"syscall" | ||||||
| 	"time" | 	"time" | ||||||
| 
 | 
 | ||||||
| 	"github.com/BurntSushi/toml" | 	"github.com/oauth2-proxy/oauth2-proxy/pkg/apis/options" | ||||||
| 	options "github.com/mreiferson/go-options" |  | ||||||
| 	"github.com/oauth2-proxy/oauth2-proxy/pkg/logger" | 	"github.com/oauth2-proxy/oauth2-proxy/pkg/logger" | ||||||
|  | 	"github.com/spf13/pflag" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| func main() { | func main() { | ||||||
|  | @ -149,7 +149,10 @@ func main() { | ||||||
| 
 | 
 | ||||||
| 	flagSet.String("user-id-claim", "email", "which claim contains the user ID") | 	flagSet.String("user-id-claim", "email", "which claim contains the user ID") | ||||||
| 
 | 
 | ||||||
| 	flagSet.Parse(os.Args[1:]) | 	pflagSet := pflag.NewFlagSet("oauth2-proxy", pflag.ExitOnError) | ||||||
|  | 	pflagSet.AddGoFlagSet(flagSet) | ||||||
|  | 
 | ||||||
|  | 	pflagSet.Parse(os.Args[1:]) | ||||||
| 
 | 
 | ||||||
| 	if *showVersion { | 	if *showVersion { | ||||||
| 		fmt.Printf("oauth2-proxy %s (built with %s)\n", VERSION, runtime.Version()) | 		fmt.Printf("oauth2-proxy %s (built with %s)\n", VERSION, runtime.Version()) | ||||||
|  | @ -157,18 +160,13 @@ func main() { | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	opts := NewOptions() | 	opts := NewOptions() | ||||||
| 
 | 	err := options.Load(*config, pflagSet, opts) | ||||||
| 	cfg := make(EnvOptions) |  | ||||||
| 	if *config != "" { |  | ||||||
| 		_, err := toml.DecodeFile(*config, &cfg) |  | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 			logger.Fatalf("ERROR: failed to load config file %s - %s", *config, err) | 		logger.Printf("ERROR: Failed to load config: %v", err) | ||||||
|  | 		os.Exit(1) | ||||||
| 	} | 	} | ||||||
| 	} |  | ||||||
| 	cfg.LoadEnvForStruct(opts) |  | ||||||
| 	options.Resolve(opts, flagSet, cfg) |  | ||||||
| 
 | 
 | ||||||
| 	err := opts.Validate() | 	err = opts.Validate() | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		logger.Printf("%s", err) | 		logger.Printf("%s", err) | ||||||
| 		os.Exit(1) | 		os.Exit(1) | ||||||
|  |  | ||||||
|  | @ -247,7 +247,7 @@ func NewOAuthProxy(opts *Options, validator func(string) bool) *OAuthProxy { | ||||||
| 			panic(fmt.Sprintf("unknown upstream protocol %s", u.Scheme)) | 			panic(fmt.Sprintf("unknown upstream protocol %s", u.Scheme)) | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	for _, u := range opts.CompiledRegex { | 	for _, u := range opts.compiledRegex { | ||||||
| 		logger.Printf("compiled skip-auth-regex => %q", u) | 		logger.Printf("compiled skip-auth-regex => %q", u) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -264,23 +264,23 @@ func NewOAuthProxy(opts *Options, validator func(string) bool) *OAuthProxy { | ||||||
| 
 | 
 | ||||||
| 	logger.Printf("OAuthProxy configured for %s Client ID: %s", opts.provider.Data().ProviderName, opts.ClientID) | 	logger.Printf("OAuthProxy configured for %s Client ID: %s", opts.provider.Data().ProviderName, opts.ClientID) | ||||||
| 	refresh := "disabled" | 	refresh := "disabled" | ||||||
| 	if opts.CookieRefresh != time.Duration(0) { | 	if opts.Cookie.Refresh != time.Duration(0) { | ||||||
| 		refresh = fmt.Sprintf("after %s", opts.CookieRefresh) | 		refresh = fmt.Sprintf("after %s", opts.Cookie.Refresh) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	logger.Printf("Cookie settings: name:%s secure(https):%v httponly:%v expiry:%s domains:%s path:%s samesite:%s refresh:%s", opts.CookieName, opts.CookieSecure, opts.CookieHTTPOnly, opts.CookieExpire, strings.Join(opts.CookieDomains, ","), opts.CookiePath, opts.CookieSameSite, refresh) | 	logger.Printf("Cookie settings: name:%s secure(https):%v httponly:%v expiry:%s domains:%s path:%s samesite:%s refresh:%s", opts.Cookie.Name, opts.Cookie.Secure, opts.Cookie.HTTPOnly, opts.Cookie.Expire, strings.Join(opts.Cookie.Domains, ","), opts.Cookie.Path, opts.Cookie.SameSite, refresh) | ||||||
| 
 | 
 | ||||||
| 	return &OAuthProxy{ | 	return &OAuthProxy{ | ||||||
| 		CookieName:     opts.CookieName, | 		CookieName:     opts.Cookie.Name, | ||||||
| 		CSRFCookieName: fmt.Sprintf("%v_%v", opts.CookieName, "csrf"), | 		CSRFCookieName: fmt.Sprintf("%v_%v", opts.Cookie.Name, "csrf"), | ||||||
| 		CookieSeed:     opts.CookieSecret, | 		CookieSeed:     opts.Cookie.Secret, | ||||||
| 		CookieDomains:  opts.CookieDomains, | 		CookieDomains:  opts.Cookie.Domains, | ||||||
| 		CookiePath:     opts.CookiePath, | 		CookiePath:     opts.Cookie.Path, | ||||||
| 		CookieSecure:   opts.CookieSecure, | 		CookieSecure:   opts.Cookie.Secure, | ||||||
| 		CookieHTTPOnly: opts.CookieHTTPOnly, | 		CookieHTTPOnly: opts.Cookie.HTTPOnly, | ||||||
| 		CookieExpire:   opts.CookieExpire, | 		CookieExpire:   opts.Cookie.Expire, | ||||||
| 		CookieRefresh:  opts.CookieRefresh, | 		CookieRefresh:  opts.Cookie.Refresh, | ||||||
| 		CookieSameSite: opts.CookieSameSite, | 		CookieSameSite: opts.Cookie.SameSite, | ||||||
| 		Validator:      validator, | 		Validator:      validator, | ||||||
| 
 | 
 | ||||||
| 		RobotsPath:        "/robots.txt", | 		RobotsPath:        "/robots.txt", | ||||||
|  | @ -303,7 +303,7 @@ func NewOAuthProxy(opts *Options, validator func(string) bool) *OAuthProxy { | ||||||
| 		skipAuthPreflight:    opts.SkipAuthPreflight, | 		skipAuthPreflight:    opts.SkipAuthPreflight, | ||||||
| 		skipJwtBearerTokens:  opts.SkipJwtBearerTokens, | 		skipJwtBearerTokens:  opts.SkipJwtBearerTokens, | ||||||
| 		jwtBearerVerifiers:   opts.jwtBearerVerifiers, | 		jwtBearerVerifiers:   opts.jwtBearerVerifiers, | ||||||
| 		compiledRegex:        opts.CompiledRegex, | 		compiledRegex:        opts.compiledRegex, | ||||||
| 		SetXAuthRequest:      opts.SetXAuthRequest, | 		SetXAuthRequest:      opts.SetXAuthRequest, | ||||||
| 		PassBasicAuth:        opts.PassBasicAuth, | 		PassBasicAuth:        opts.PassBasicAuth, | ||||||
| 		SetBasicAuth:         opts.SetBasicAuth, | 		SetBasicAuth:         opts.SetBasicAuth, | ||||||
|  |  | ||||||
|  | @ -164,7 +164,7 @@ func TestRobotsTxt(t *testing.T) { | ||||||
| 	opts := NewOptions() | 	opts := NewOptions() | ||||||
| 	opts.ClientID = "asdlkjx" | 	opts.ClientID = "asdlkjx" | ||||||
| 	opts.ClientSecret = "alkgks" | 	opts.ClientSecret = "alkgks" | ||||||
| 	opts.CookieSecret = "asdkugkj" | 	opts.Cookie.Secret = "asdkugkj" | ||||||
| 	opts.Validate() | 	opts.Validate() | ||||||
| 
 | 
 | ||||||
| 	proxy := NewOAuthProxy(opts, func(string) bool { return true }) | 	proxy := NewOAuthProxy(opts, func(string) bool { return true }) | ||||||
|  | @ -179,7 +179,7 @@ func TestIsValidRedirect(t *testing.T) { | ||||||
| 	opts := NewOptions() | 	opts := NewOptions() | ||||||
| 	opts.ClientID = "skdlfj" | 	opts.ClientID = "skdlfj" | ||||||
| 	opts.ClientSecret = "fgkdsgj" | 	opts.ClientSecret = "fgkdsgj" | ||||||
| 	opts.CookieSecret = "ljgiogbj" | 	opts.Cookie.Secret = "ljgiogbj" | ||||||
| 	// Should match domains that are exactly foo.bar and any subdomain of bar.foo
 | 	// Should match domains that are exactly foo.bar and any subdomain of bar.foo
 | ||||||
| 	opts.WhitelistDomains = []string{ | 	opts.WhitelistDomains = []string{ | ||||||
| 		"foo.bar", | 		"foo.bar", | ||||||
|  | @ -398,10 +398,10 @@ func TestBasicAuthPassword(t *testing.T) { | ||||||
| 	opts.Upstreams = append(opts.Upstreams, providerServer.URL) | 	opts.Upstreams = append(opts.Upstreams, providerServer.URL) | ||||||
| 	// The CookieSecret must be 32 bytes in order to create the AES
 | 	// The CookieSecret must be 32 bytes in order to create the AES
 | ||||||
| 	// cipher.
 | 	// cipher.
 | ||||||
| 	opts.CookieSecret = "xyzzyplughxyzzyplughxyzzyplughxp" | 	opts.Cookie.Secret = "xyzzyplughxyzzyplughxyzzyplughxp" | ||||||
| 	opts.ClientID = "dlgkj" | 	opts.ClientID = "dlgkj" | ||||||
| 	opts.ClientSecret = "alkgret" | 	opts.ClientSecret = "alkgret" | ||||||
| 	opts.CookieSecure = false | 	opts.Cookie.Secure = false | ||||||
| 	opts.PassBasicAuth = true | 	opts.PassBasicAuth = true | ||||||
| 	opts.SetBasicAuth = true | 	opts.SetBasicAuth = true | ||||||
| 	opts.PassUserHeaders = true | 	opts.PassUserHeaders = true | ||||||
|  | @ -582,10 +582,10 @@ func NewPassAccessTokenTest(opts PassAccessTokenTestOptions) *PassAccessTokenTes | ||||||
| 	} | 	} | ||||||
| 	// The CookieSecret must be 32 bytes in order to create the AES
 | 	// The CookieSecret must be 32 bytes in order to create the AES
 | ||||||
| 	// cipher.
 | 	// cipher.
 | ||||||
| 	t.opts.CookieSecret = "xyzzyplughxyzzyplughxyzzyplughxp" | 	t.opts.Cookie.Secret = "xyzzyplughxyzzyplughxyzzyplughxp" | ||||||
| 	t.opts.ClientID = "slgkj" | 	t.opts.ClientID = "slgkj" | ||||||
| 	t.opts.ClientSecret = "gfjgojl" | 	t.opts.ClientSecret = "gfjgojl" | ||||||
| 	t.opts.CookieSecure = false | 	t.opts.Cookie.Secure = false | ||||||
| 	t.opts.PassAccessToken = opts.PassAccessToken | 	t.opts.PassAccessToken = opts.PassAccessToken | ||||||
| 	t.opts.Validate() | 	t.opts.Validate() | ||||||
| 
 | 
 | ||||||
|  | @ -735,7 +735,7 @@ func NewSignInPageTest(skipProvider bool) *SignInPageTest { | ||||||
| 	var sipTest SignInPageTest | 	var sipTest SignInPageTest | ||||||
| 
 | 
 | ||||||
| 	sipTest.opts = NewOptions() | 	sipTest.opts = NewOptions() | ||||||
| 	sipTest.opts.CookieSecret = "adklsj2" | 	sipTest.opts.Cookie.Secret = "adklsj2" | ||||||
| 	sipTest.opts.ClientID = "lkdgj" | 	sipTest.opts.ClientID = "lkdgj" | ||||||
| 	sipTest.opts.ClientSecret = "sgiufgoi" | 	sipTest.opts.ClientSecret = "sgiufgoi" | ||||||
| 	sipTest.opts.SkipProviderButton = skipProvider | 	sipTest.opts.SkipProviderButton = skipProvider | ||||||
|  | @ -841,10 +841,10 @@ func NewProcessCookieTest(opts ProcessCookieTestOpts, modifiers ...OptionsModifi | ||||||
| 	} | 	} | ||||||
| 	pcTest.opts.ClientID = "asdfljk" | 	pcTest.opts.ClientID = "asdfljk" | ||||||
| 	pcTest.opts.ClientSecret = "lkjfdsig" | 	pcTest.opts.ClientSecret = "lkjfdsig" | ||||||
| 	pcTest.opts.CookieSecret = "0123456789abcdefabcd" | 	pcTest.opts.Cookie.Secret = "0123456789abcdefabcd" | ||||||
| 	// First, set the CookieRefresh option so proxy.AesCipher is created,
 | 	// First, set the CookieRefresh option so proxy.AesCipher is created,
 | ||||||
| 	// needed to encrypt the access_token.
 | 	// needed to encrypt the access_token.
 | ||||||
| 	pcTest.opts.CookieRefresh = time.Hour | 	pcTest.opts.Cookie.Refresh = time.Hour | ||||||
| 	pcTest.opts.Validate() | 	pcTest.opts.Validate() | ||||||
| 
 | 
 | ||||||
| 	pcTest.proxy = NewOAuthProxy(pcTest.opts, func(email string) bool { | 	pcTest.proxy = NewOAuthProxy(pcTest.opts, func(email string) bool { | ||||||
|  | @ -915,7 +915,7 @@ func TestProcessCookieNoCookieError(t *testing.T) { | ||||||
| 
 | 
 | ||||||
| func TestProcessCookieRefreshNotSet(t *testing.T) { | func TestProcessCookieRefreshNotSet(t *testing.T) { | ||||||
| 	pcTest := NewProcessCookieTestWithOptionsModifiers(func(opts *Options) { | 	pcTest := NewProcessCookieTestWithOptionsModifiers(func(opts *Options) { | ||||||
| 		opts.CookieExpire = time.Duration(23) * time.Hour | 		opts.Cookie.Expire = time.Duration(23) * time.Hour | ||||||
| 	}) | 	}) | ||||||
| 	reference := time.Now().Add(time.Duration(-2) * time.Hour) | 	reference := time.Now().Add(time.Duration(-2) * time.Hour) | ||||||
| 
 | 
 | ||||||
|  | @ -932,7 +932,7 @@ func TestProcessCookieRefreshNotSet(t *testing.T) { | ||||||
| 
 | 
 | ||||||
| func TestProcessCookieFailIfCookieExpired(t *testing.T) { | func TestProcessCookieFailIfCookieExpired(t *testing.T) { | ||||||
| 	pcTest := NewProcessCookieTestWithOptionsModifiers(func(opts *Options) { | 	pcTest := NewProcessCookieTestWithOptionsModifiers(func(opts *Options) { | ||||||
| 		opts.CookieExpire = time.Duration(24) * time.Hour | 		opts.Cookie.Expire = time.Duration(24) * time.Hour | ||||||
| 	}) | 	}) | ||||||
| 	reference := time.Now().Add(time.Duration(25) * time.Hour * -1) | 	reference := time.Now().Add(time.Duration(25) * time.Hour * -1) | ||||||
| 	startSession := &sessions.SessionState{Email: "michael.bland@gsa.gov", AccessToken: "my_access_token", CreatedAt: reference} | 	startSession := &sessions.SessionState{Email: "michael.bland@gsa.gov", AccessToken: "my_access_token", CreatedAt: reference} | ||||||
|  | @ -947,7 +947,7 @@ func TestProcessCookieFailIfCookieExpired(t *testing.T) { | ||||||
| 
 | 
 | ||||||
| func TestProcessCookieFailIfRefreshSetAndCookieExpired(t *testing.T) { | func TestProcessCookieFailIfRefreshSetAndCookieExpired(t *testing.T) { | ||||||
| 	pcTest := NewProcessCookieTestWithOptionsModifiers(func(opts *Options) { | 	pcTest := NewProcessCookieTestWithOptionsModifiers(func(opts *Options) { | ||||||
| 		opts.CookieExpire = time.Duration(24) * time.Hour | 		opts.Cookie.Expire = time.Duration(24) * time.Hour | ||||||
| 	}) | 	}) | ||||||
| 	reference := time.Now().Add(time.Duration(25) * time.Hour * -1) | 	reference := time.Now().Add(time.Duration(25) * time.Hour * -1) | ||||||
| 	startSession := &sessions.SessionState{Email: "michael.bland@gsa.gov", AccessToken: "my_access_token", CreatedAt: reference} | 	startSession := &sessions.SessionState{Email: "michael.bland@gsa.gov", AccessToken: "my_access_token", CreatedAt: reference} | ||||||
|  | @ -1017,7 +1017,7 @@ func TestAuthOnlyEndpointUnauthorizedOnNoCookieSetError(t *testing.T) { | ||||||
| 
 | 
 | ||||||
| func TestAuthOnlyEndpointUnauthorizedOnExpiration(t *testing.T) { | func TestAuthOnlyEndpointUnauthorizedOnExpiration(t *testing.T) { | ||||||
| 	test := NewAuthOnlyEndpointTest(func(opts *Options) { | 	test := NewAuthOnlyEndpointTest(func(opts *Options) { | ||||||
| 		opts.CookieExpire = time.Duration(24) * time.Hour | 		opts.Cookie.Expire = time.Duration(24) * time.Hour | ||||||
| 	}) | 	}) | ||||||
| 	reference := time.Now().Add(time.Duration(25) * time.Hour * -1) | 	reference := time.Now().Add(time.Duration(25) * time.Hour * -1) | ||||||
| 	startSession := &sessions.SessionState{ | 	startSession := &sessions.SessionState{ | ||||||
|  | @ -1149,7 +1149,7 @@ func TestAuthSkippedForPreflightRequests(t *testing.T) { | ||||||
| 	opts.Upstreams = append(opts.Upstreams, upstream.URL) | 	opts.Upstreams = append(opts.Upstreams, upstream.URL) | ||||||
| 	opts.ClientID = "aljsal" | 	opts.ClientID = "aljsal" | ||||||
| 	opts.ClientSecret = "jglkfsdgj" | 	opts.ClientSecret = "jglkfsdgj" | ||||||
| 	opts.CookieSecret = "dkfjgdls" | 	opts.Cookie.Secret = "dkfjgdls" | ||||||
| 	opts.SkipAuthPreflight = true | 	opts.SkipAuthPreflight = true | ||||||
| 	opts.Validate() | 	opts.Validate() | ||||||
| 
 | 
 | ||||||
|  | @ -1196,7 +1196,7 @@ type SignatureTest struct { | ||||||
| 
 | 
 | ||||||
| func NewSignatureTest() *SignatureTest { | func NewSignatureTest() *SignatureTest { | ||||||
| 	opts := NewOptions() | 	opts := NewOptions() | ||||||
| 	opts.CookieSecret = "cookie secret" | 	opts.Cookie.Secret = "cookie secret" | ||||||
| 	opts.ClientID = "client ID" | 	opts.ClientID = "client ID" | ||||||
| 	opts.ClientSecret = "client secret" | 	opts.ClientSecret = "client secret" | ||||||
| 	opts.EmailDomains = []string{"acm.org"} | 	opts.EmailDomains = []string{"acm.org"} | ||||||
|  | @ -1343,7 +1343,7 @@ type ajaxRequestTest struct { | ||||||
| func newAjaxRequestTest() *ajaxRequestTest { | func newAjaxRequestTest() *ajaxRequestTest { | ||||||
| 	test := &ajaxRequestTest{} | 	test := &ajaxRequestTest{} | ||||||
| 	test.opts = NewOptions() | 	test.opts = NewOptions() | ||||||
| 	test.opts.CookieSecret = "sdflsw" | 	test.opts.Cookie.Secret = "sdflsw" | ||||||
| 	test.opts.ClientID = "gkljfdl" | 	test.opts.ClientID = "gkljfdl" | ||||||
| 	test.opts.ClientSecret = "sdflkjs" | 	test.opts.ClientSecret = "sdflkjs" | ||||||
| 	test.opts.Validate() | 	test.opts.Validate() | ||||||
|  | @ -1401,11 +1401,11 @@ func TestAjaxForbiddendRequest(t *testing.T) { | ||||||
| 
 | 
 | ||||||
| func TestClearSplitCookie(t *testing.T) { | func TestClearSplitCookie(t *testing.T) { | ||||||
| 	opts := NewOptions() | 	opts := NewOptions() | ||||||
| 	opts.CookieName = "oauth2" | 	opts.Cookie.Name = "oauth2" | ||||||
| 	opts.CookieDomains = []string{"abc"} | 	opts.Cookie.Domains = []string{"abc"} | ||||||
| 	store, err := cookie.NewCookieSessionStore(&opts.SessionOptions, &opts.CookieOptions) | 	store, err := cookie.NewCookieSessionStore(&opts.Session, &opts.Cookie) | ||||||
| 	assert.Equal(t, err, nil) | 	assert.Equal(t, err, nil) | ||||||
| 	p := OAuthProxy{CookieName: opts.CookieName, CookieDomains: opts.CookieDomains, sessionStore: store} | 	p := OAuthProxy{CookieName: opts.Cookie.Name, CookieDomains: opts.Cookie.Domains, sessionStore: store} | ||||||
| 	var rw = httptest.NewRecorder() | 	var rw = httptest.NewRecorder() | ||||||
| 	req := httptest.NewRequest("get", "/", nil) | 	req := httptest.NewRequest("get", "/", nil) | ||||||
| 
 | 
 | ||||||
|  | @ -1430,11 +1430,11 @@ func TestClearSplitCookie(t *testing.T) { | ||||||
| 
 | 
 | ||||||
| func TestClearSingleCookie(t *testing.T) { | func TestClearSingleCookie(t *testing.T) { | ||||||
| 	opts := NewOptions() | 	opts := NewOptions() | ||||||
| 	opts.CookieName = "oauth2" | 	opts.Cookie.Name = "oauth2" | ||||||
| 	opts.CookieDomains = []string{"abc"} | 	opts.Cookie.Domains = []string{"abc"} | ||||||
| 	store, err := cookie.NewCookieSessionStore(&opts.SessionOptions, &opts.CookieOptions) | 	store, err := cookie.NewCookieSessionStore(&opts.Session, &opts.Cookie) | ||||||
| 	assert.Equal(t, err, nil) | 	assert.Equal(t, err, nil) | ||||||
| 	p := OAuthProxy{CookieName: opts.CookieName, CookieDomains: opts.CookieDomains, sessionStore: store} | 	p := OAuthProxy{CookieName: opts.Cookie.Name, CookieDomains: opts.Cookie.Domains, sessionStore: store} | ||||||
| 	var rw = httptest.NewRecorder() | 	var rw = httptest.NewRecorder() | ||||||
| 	req := httptest.NewRequest("get", "/", nil) | 	req := httptest.NewRequest("get", "/", nil) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										63
									
								
								options.go
								
								
								
								
							
							
						
						
									
										63
									
								
								options.go
								
								
								
								
							|  | @ -64,11 +64,8 @@ type Options struct { | ||||||
| 	Banner                   string   `flag:"banner" cfg:"banner" env:"OAUTH2_PROXY_BANNER"` | 	Banner                   string   `flag:"banner" cfg:"banner" env:"OAUTH2_PROXY_BANNER"` | ||||||
| 	Footer                   string   `flag:"footer" cfg:"footer" env:"OAUTH2_PROXY_FOOTER"` | 	Footer                   string   `flag:"footer" cfg:"footer" env:"OAUTH2_PROXY_FOOTER"` | ||||||
| 
 | 
 | ||||||
| 	// Embed CookieOptions
 | 	Cookie  options.CookieOptions  `cfg:",squash"` | ||||||
| 	options.CookieOptions | 	Session options.SessionOptions `cfg:",squash"` | ||||||
| 
 |  | ||||||
| 	// Embed SessionOptions
 |  | ||||||
| 	options.SessionOptions |  | ||||||
| 
 | 
 | ||||||
| 	Upstreams                     []string      `flag:"upstream" cfg:"upstreams" env:"OAUTH2_PROXY_UPSTREAMS"` | 	Upstreams                     []string      `flag:"upstream" cfg:"upstreams" env:"OAUTH2_PROXY_UPSTREAMS"` | ||||||
| 	SkipAuthRegex                 []string      `flag:"skip-auth-regex" cfg:"skip_auth_regex" env:"OAUTH2_PROXY_SKIP_AUTH_REGEX"` | 	SkipAuthRegex                 []string      `flag:"skip-auth-regex" cfg:"skip_auth_regex" env:"OAUTH2_PROXY_SKIP_AUTH_REGEX"` | ||||||
|  | @ -134,7 +131,7 @@ type Options struct { | ||||||
| 	// internal values that are set after config validation
 | 	// internal values that are set after config validation
 | ||||||
| 	redirectURL        *url.URL | 	redirectURL        *url.URL | ||||||
| 	proxyURLs          []*url.URL | 	proxyURLs          []*url.URL | ||||||
| 	CompiledRegex      []*regexp.Regexp | 	compiledRegex      []*regexp.Regexp | ||||||
| 	provider           providers.Provider | 	provider           providers.Provider | ||||||
| 	sessionStore       sessionsapi.SessionStore | 	sessionStore       sessionsapi.SessionStore | ||||||
| 	signatureData      *SignatureData | 	signatureData      *SignatureData | ||||||
|  | @ -158,14 +155,14 @@ func NewOptions() *Options { | ||||||
| 		HTTPSAddress:        ":443", | 		HTTPSAddress:        ":443", | ||||||
| 		ForceHTTPS:          false, | 		ForceHTTPS:          false, | ||||||
| 		DisplayHtpasswdForm: true, | 		DisplayHtpasswdForm: true, | ||||||
| 		CookieOptions: options.CookieOptions{ | 		Cookie: options.CookieOptions{ | ||||||
| 			CookieName:     "_oauth2_proxy", | 			Name:     "_oauth2_proxy", | ||||||
| 			CookieSecure:   true, | 			Secure:   true, | ||||||
| 			CookieHTTPOnly: true, | 			HTTPOnly: true, | ||||||
| 			CookieExpire:   time.Duration(168) * time.Hour, | 			Expire:   time.Duration(168) * time.Hour, | ||||||
| 			CookieRefresh:  time.Duration(0), | 			Refresh:  time.Duration(0), | ||||||
| 		}, | 		}, | ||||||
| 		SessionOptions: options.SessionOptions{ | 		Session: options.SessionOptions{ | ||||||
| 			Type: "cookie", | 			Type: "cookie", | ||||||
| 		}, | 		}, | ||||||
| 		SetXAuthRequest:                  false, | 		SetXAuthRequest:                  false, | ||||||
|  | @ -227,7 +224,7 @@ func (o *Options) Validate() error { | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	msgs := make([]string, 0) | 	msgs := make([]string, 0) | ||||||
| 	if o.CookieSecret == "" { | 	if o.Cookie.Secret == "" { | ||||||
| 		msgs = append(msgs, "missing setting: cookie-secret") | 		msgs = append(msgs, "missing setting: cookie-secret") | ||||||
| 	} | 	} | ||||||
| 	if o.ClientID == "" { | 	if o.ClientID == "" { | ||||||
|  | @ -372,61 +369,61 @@ func (o *Options) Validate() error { | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	for _, u := range o.SkipAuthRegex { | 	for _, u := range o.SkipAuthRegex { | ||||||
| 		CompiledRegex, err := regexp.Compile(u) | 		compiledRegex, err := regexp.Compile(u) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			msgs = append(msgs, fmt.Sprintf("error compiling regex=%q %s", u, err)) | 			msgs = append(msgs, fmt.Sprintf("error compiling regex=%q %s", u, err)) | ||||||
| 			continue | 			continue | ||||||
| 		} | 		} | ||||||
| 		o.CompiledRegex = append(o.CompiledRegex, CompiledRegex) | 		o.compiledRegex = append(o.compiledRegex, compiledRegex) | ||||||
| 	} | 	} | ||||||
| 	msgs = parseProviderInfo(o, msgs) | 	msgs = parseProviderInfo(o, msgs) | ||||||
| 
 | 
 | ||||||
| 	var cipher *encryption.Cipher | 	var cipher *encryption.Cipher | ||||||
| 	if o.PassAccessToken || o.SetAuthorization || o.PassAuthorization || (o.CookieRefresh != time.Duration(0)) { | 	if o.PassAccessToken || o.SetAuthorization || o.PassAuthorization || (o.Cookie.Refresh != time.Duration(0)) { | ||||||
| 		validCookieSecretSize := false | 		validCookieSecretSize := false | ||||||
| 		for _, i := range []int{16, 24, 32} { | 		for _, i := range []int{16, 24, 32} { | ||||||
| 			if len(secretBytes(o.CookieSecret)) == i { | 			if len(secretBytes(o.Cookie.Secret)) == i { | ||||||
| 				validCookieSecretSize = true | 				validCookieSecretSize = true | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		var decoded bool | 		var decoded bool | ||||||
| 		if string(secretBytes(o.CookieSecret)) != o.CookieSecret { | 		if string(secretBytes(o.Cookie.Secret)) != o.Cookie.Secret { | ||||||
| 			decoded = true | 			decoded = true | ||||||
| 		} | 		} | ||||||
| 		if !validCookieSecretSize { | 		if !validCookieSecretSize { | ||||||
| 			var suffix string | 			var suffix string | ||||||
| 			if decoded { | 			if decoded { | ||||||
| 				suffix = fmt.Sprintf(" note: cookie secret was base64 decoded from %q", o.CookieSecret) | 				suffix = fmt.Sprintf(" note: cookie secret was base64 decoded from %q", o.Cookie.Secret) | ||||||
| 			} | 			} | ||||||
| 			msgs = append(msgs, fmt.Sprintf( | 			msgs = append(msgs, fmt.Sprintf( | ||||||
| 				"cookie_secret must be 16, 24, or 32 bytes "+ | 				"cookie_secret must be 16, 24, or 32 bytes "+ | ||||||
| 					"to create an AES cipher when "+ | 					"to create an AES cipher when "+ | ||||||
| 					"pass_access_token == true or "+ | 					"pass_access_token == true or "+ | ||||||
| 					"cookie_refresh != 0, but is %d bytes.%s", | 					"cookie_refresh != 0, but is %d bytes.%s", | ||||||
| 				len(secretBytes(o.CookieSecret)), suffix)) | 				len(secretBytes(o.Cookie.Secret)), suffix)) | ||||||
| 		} else { | 		} else { | ||||||
| 			var err error | 			var err error | ||||||
| 			cipher, err = encryption.NewCipher(secretBytes(o.CookieSecret)) | 			cipher, err = encryption.NewCipher(secretBytes(o.Cookie.Secret)) | ||||||
| 			if err != nil { | 			if err != nil { | ||||||
| 				msgs = append(msgs, fmt.Sprintf("cookie-secret error: %v", err)) | 				msgs = append(msgs, fmt.Sprintf("cookie-secret error: %v", err)) | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	o.SessionOptions.Cipher = cipher | 	o.Session.Cipher = cipher | ||||||
| 	sessionStore, err := sessions.NewSessionStore(&o.SessionOptions, &o.CookieOptions) | 	sessionStore, err := sessions.NewSessionStore(&o.Session, &o.Cookie) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		msgs = append(msgs, fmt.Sprintf("error initialising session storage: %v", err)) | 		msgs = append(msgs, fmt.Sprintf("error initialising session storage: %v", err)) | ||||||
| 	} else { | 	} else { | ||||||
| 		o.sessionStore = sessionStore | 		o.sessionStore = sessionStore | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if o.CookieRefresh >= o.CookieExpire { | 	if o.Cookie.Refresh >= o.Cookie.Expire { | ||||||
| 		msgs = append(msgs, fmt.Sprintf( | 		msgs = append(msgs, fmt.Sprintf( | ||||||
| 			"cookie_refresh (%s) must be less than "+ | 			"cookie_refresh (%s) must be less than "+ | ||||||
| 				"cookie_expire (%s)", | 				"cookie_expire (%s)", | ||||||
| 			o.CookieRefresh.String(), | 			o.Cookie.Refresh.String(), | ||||||
| 			o.CookieExpire.String())) | 			o.Cookie.Expire.String())) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if len(o.GoogleGroups) > 0 || o.GoogleAdminEmail != "" || o.GoogleServiceAccountJSON != "" { | 	if len(o.GoogleGroups) > 0 || o.GoogleAdminEmail != "" || o.GoogleServiceAccountJSON != "" { | ||||||
|  | @ -441,16 +438,16 @@ func (o *Options) Validate() error { | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	switch o.CookieSameSite { | 	switch o.Cookie.SameSite { | ||||||
| 	case "", "none", "lax", "strict": | 	case "", "none", "lax", "strict": | ||||||
| 	default: | 	default: | ||||||
| 		msgs = append(msgs, fmt.Sprintf("cookie_samesite (%s) must be one of ['', 'lax', 'strict', 'none']", o.CookieSameSite)) | 		msgs = append(msgs, fmt.Sprintf("cookie_samesite (%s) must be one of ['', 'lax', 'strict', 'none']", o.Cookie.SameSite)) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// Sort cookie domains by length, so that we try longer (and more specific)
 | 	// Sort cookie domains by length, so that we try longer (and more specific)
 | ||||||
| 	// domains first
 | 	// domains first
 | ||||||
| 	sort.Slice(o.CookieDomains, func(i, j int) bool { | 	sort.Slice(o.Cookie.Domains, func(i, j int) bool { | ||||||
| 		return len(o.CookieDomains[i]) > len(o.CookieDomains[j]) | 		return len(o.Cookie.Domains[i]) > len(o.Cookie.Domains[j]) | ||||||
| 	}) | 	}) | ||||||
| 
 | 
 | ||||||
| 	msgs = parseSignatureKey(o, msgs) | 	msgs = parseSignatureKey(o, msgs) | ||||||
|  | @ -627,9 +624,9 @@ func newVerifierFromJwtIssuer(jwtIssuer jwtIssuer) (*oidc.IDTokenVerifier, error | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func validateCookieName(o *Options, msgs []string) []string { | func validateCookieName(o *Options, msgs []string) []string { | ||||||
| 	cookie := &http.Cookie{Name: o.CookieName} | 	cookie := &http.Cookie{Name: o.Cookie.Name} | ||||||
| 	if cookie.String() == "" { | 	if cookie.String() == "" { | ||||||
| 		return append(msgs, fmt.Sprintf("invalid cookie name: %q", o.CookieName)) | 		return append(msgs, fmt.Sprintf("invalid cookie name: %q", o.Cookie.Name)) | ||||||
| 	} | 	} | ||||||
| 	return msgs | 	return msgs | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -22,7 +22,7 @@ const ( | ||||||
| func testOptions() *Options { | func testOptions() *Options { | ||||||
| 	o := NewOptions() | 	o := NewOptions() | ||||||
| 	o.Upstreams = append(o.Upstreams, "http://127.0.0.1:8080/") | 	o.Upstreams = append(o.Upstreams, "http://127.0.0.1:8080/") | ||||||
| 	o.CookieSecret = cookieSecret | 	o.Cookie.Secret = cookieSecret | ||||||
| 	o.ClientID = clientID | 	o.ClientID = clientID | ||||||
| 	o.ClientSecret = clientSecret | 	o.ClientSecret = clientSecret | ||||||
| 	o.EmailDomains = []string{"*"} | 	o.EmailDomains = []string{"*"} | ||||||
|  | @ -51,7 +51,7 @@ func TestNewOptions(t *testing.T) { | ||||||
| 
 | 
 | ||||||
| func TestClientSecretFileOptionFails(t *testing.T) { | func TestClientSecretFileOptionFails(t *testing.T) { | ||||||
| 	o := NewOptions() | 	o := NewOptions() | ||||||
| 	o.CookieSecret = cookieSecret | 	o.Cookie.Secret = cookieSecret | ||||||
| 	o.ClientID = clientID | 	o.ClientID = clientID | ||||||
| 	o.ClientSecretFile = clientSecret | 	o.ClientSecretFile = clientSecret | ||||||
| 	o.EmailDomains = []string{"*"} | 	o.EmailDomains = []string{"*"} | ||||||
|  | @ -81,7 +81,7 @@ func TestClientSecretFileOption(t *testing.T) { | ||||||
| 	defer os.Remove(clientSecretFileName) | 	defer os.Remove(clientSecretFileName) | ||||||
| 
 | 
 | ||||||
| 	o := NewOptions() | 	o := NewOptions() | ||||||
| 	o.CookieSecret = cookieSecret | 	o.Cookie.Secret = cookieSecret | ||||||
| 	o.ClientID = clientID | 	o.ClientID = clientID | ||||||
| 	o.ClientSecretFile = clientSecretFileName | 	o.ClientSecretFile = clientSecretFileName | ||||||
| 	o.EmailDomains = []string{"*"} | 	o.EmailDomains = []string{"*"} | ||||||
|  | @ -165,7 +165,7 @@ func TestCompiledRegex(t *testing.T) { | ||||||
| 	o.SkipAuthRegex = regexps | 	o.SkipAuthRegex = regexps | ||||||
| 	assert.Equal(t, nil, o.Validate()) | 	assert.Equal(t, nil, o.Validate()) | ||||||
| 	actual := make([]string, 0) | 	actual := make([]string, 0) | ||||||
| 	for _, regex := range o.CompiledRegex { | 	for _, regex := range o.compiledRegex { | ||||||
| 		actual = append(actual, regex.String()) | 		actual = append(actual, regex.String()) | ||||||
| 	} | 	} | ||||||
| 	assert.Equal(t, regexps, actual) | 	assert.Equal(t, regexps, actual) | ||||||
|  | @ -212,20 +212,20 @@ func TestPassAccessTokenRequiresSpecificCookieSecretLengths(t *testing.T) { | ||||||
| 
 | 
 | ||||||
| 	assert.Equal(t, false, o.PassAccessToken) | 	assert.Equal(t, false, o.PassAccessToken) | ||||||
| 	o.PassAccessToken = true | 	o.PassAccessToken = true | ||||||
| 	o.CookieSecret = "cookie of invalid length-" | 	o.Cookie.Secret = "cookie of invalid length-" | ||||||
| 	assert.NotEqual(t, nil, o.Validate()) | 	assert.NotEqual(t, nil, o.Validate()) | ||||||
| 
 | 
 | ||||||
| 	o.PassAccessToken = false | 	o.PassAccessToken = false | ||||||
| 	o.CookieRefresh = time.Duration(24) * time.Hour | 	o.Cookie.Refresh = time.Duration(24) * time.Hour | ||||||
| 	assert.NotEqual(t, nil, o.Validate()) | 	assert.NotEqual(t, nil, o.Validate()) | ||||||
| 
 | 
 | ||||||
| 	o.CookieSecret = "16 bytes AES-128" | 	o.Cookie.Secret = "16 bytes AES-128" | ||||||
| 	assert.Equal(t, nil, o.Validate()) | 	assert.Equal(t, nil, o.Validate()) | ||||||
| 
 | 
 | ||||||
| 	o.CookieSecret = "24 byte secret AES-192--" | 	o.Cookie.Secret = "24 byte secret AES-192--" | ||||||
| 	assert.Equal(t, nil, o.Validate()) | 	assert.Equal(t, nil, o.Validate()) | ||||||
| 
 | 
 | ||||||
| 	o.CookieSecret = "32 byte secret for AES-256------" | 	o.Cookie.Secret = "32 byte secret for AES-256------" | ||||||
| 	assert.Equal(t, nil, o.Validate()) | 	assert.Equal(t, nil, o.Validate()) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -233,11 +233,11 @@ func TestCookieRefreshMustBeLessThanCookieExpire(t *testing.T) { | ||||||
| 	o := testOptions() | 	o := testOptions() | ||||||
| 	assert.Equal(t, nil, o.Validate()) | 	assert.Equal(t, nil, o.Validate()) | ||||||
| 
 | 
 | ||||||
| 	o.CookieSecret = "0123456789abcdefabcd" | 	o.Cookie.Secret = "0123456789abcdefabcd" | ||||||
| 	o.CookieRefresh = o.CookieExpire | 	o.Cookie.Refresh = o.Cookie.Expire | ||||||
| 	assert.NotEqual(t, nil, o.Validate()) | 	assert.NotEqual(t, nil, o.Validate()) | ||||||
| 
 | 
 | ||||||
| 	o.CookieRefresh -= time.Duration(1) | 	o.Cookie.Refresh -= time.Duration(1) | ||||||
| 	assert.Equal(t, nil, o.Validate()) | 	assert.Equal(t, nil, o.Validate()) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -246,23 +246,23 @@ func TestBase64CookieSecret(t *testing.T) { | ||||||
| 	assert.Equal(t, nil, o.Validate()) | 	assert.Equal(t, nil, o.Validate()) | ||||||
| 
 | 
 | ||||||
| 	// 32 byte, base64 (urlsafe) encoded key
 | 	// 32 byte, base64 (urlsafe) encoded key
 | ||||||
| 	o.CookieSecret = "yHBw2lh2Cvo6aI_jn_qMTr-pRAjtq0nzVgDJNb36jgQ=" | 	o.Cookie.Secret = "yHBw2lh2Cvo6aI_jn_qMTr-pRAjtq0nzVgDJNb36jgQ=" | ||||||
| 	assert.Equal(t, nil, o.Validate()) | 	assert.Equal(t, nil, o.Validate()) | ||||||
| 
 | 
 | ||||||
| 	// 32 byte, base64 (urlsafe) encoded key, w/o padding
 | 	// 32 byte, base64 (urlsafe) encoded key, w/o padding
 | ||||||
| 	o.CookieSecret = "yHBw2lh2Cvo6aI_jn_qMTr-pRAjtq0nzVgDJNb36jgQ" | 	o.Cookie.Secret = "yHBw2lh2Cvo6aI_jn_qMTr-pRAjtq0nzVgDJNb36jgQ" | ||||||
| 	assert.Equal(t, nil, o.Validate()) | 	assert.Equal(t, nil, o.Validate()) | ||||||
| 
 | 
 | ||||||
| 	// 24 byte, base64 (urlsafe) encoded key
 | 	// 24 byte, base64 (urlsafe) encoded key
 | ||||||
| 	o.CookieSecret = "Kp33Gj-GQmYtz4zZUyUDdqQKx5_Hgkv3" | 	o.Cookie.Secret = "Kp33Gj-GQmYtz4zZUyUDdqQKx5_Hgkv3" | ||||||
| 	assert.Equal(t, nil, o.Validate()) | 	assert.Equal(t, nil, o.Validate()) | ||||||
| 
 | 
 | ||||||
| 	// 16 byte, base64 (urlsafe) encoded key
 | 	// 16 byte, base64 (urlsafe) encoded key
 | ||||||
| 	o.CookieSecret = "LFEqZYvYUwKwzn0tEuTpLA==" | 	o.Cookie.Secret = "LFEqZYvYUwKwzn0tEuTpLA==" | ||||||
| 	assert.Equal(t, nil, o.Validate()) | 	assert.Equal(t, nil, o.Validate()) | ||||||
| 
 | 
 | ||||||
| 	// 16 byte, base64 (urlsafe) encoded key, w/o padding
 | 	// 16 byte, base64 (urlsafe) encoded key, w/o padding
 | ||||||
| 	o.CookieSecret = "LFEqZYvYUwKwzn0tEuTpLA" | 	o.Cookie.Secret = "LFEqZYvYUwKwzn0tEuTpLA" | ||||||
| 	assert.Equal(t, nil, o.Validate()) | 	assert.Equal(t, nil, o.Validate()) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -292,16 +292,16 @@ func TestValidateSignatureKeyUnsupportedAlgorithm(t *testing.T) { | ||||||
| 
 | 
 | ||||||
| func TestValidateCookie(t *testing.T) { | func TestValidateCookie(t *testing.T) { | ||||||
| 	o := testOptions() | 	o := testOptions() | ||||||
| 	o.CookieName = "_valid_cookie_name" | 	o.Cookie.Name = "_valid_cookie_name" | ||||||
| 	assert.Equal(t, nil, o.Validate()) | 	assert.Equal(t, nil, o.Validate()) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func TestValidateCookieBadName(t *testing.T) { | func TestValidateCookieBadName(t *testing.T) { | ||||||
| 	o := testOptions() | 	o := testOptions() | ||||||
| 	o.CookieName = "_bad_cookie_name{}" | 	o.Cookie.Name = "_bad_cookie_name{}" | ||||||
| 	err := o.Validate() | 	err := o.Validate() | ||||||
| 	assert.Equal(t, err.Error(), "invalid configuration:\n"+ | 	assert.Equal(t, err.Error(), "invalid configuration:\n"+ | ||||||
| 		fmt.Sprintf("  invalid cookie name: %q", o.CookieName)) | 		fmt.Sprintf("  invalid cookie name: %q", o.Cookie.Name)) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func TestSkipOIDCDiscovery(t *testing.T) { | func TestSkipOIDCDiscovery(t *testing.T) { | ||||||
|  |  | ||||||
|  | @ -4,13 +4,13 @@ import "time" | ||||||
| 
 | 
 | ||||||
| // CookieOptions contains configuration options relating to Cookie configuration
 | // CookieOptions contains configuration options relating to Cookie configuration
 | ||||||
| type CookieOptions struct { | type CookieOptions struct { | ||||||
| 	CookieName     string        `flag:"cookie-name" cfg:"cookie_name" env:"OAUTH2_PROXY_COOKIE_NAME"` | 	Name     string        `flag:"cookie-name" cfg:"cookie_name" env:"OAUTH2_PROXY_COOKIE_NAME"` | ||||||
| 	CookieSecret   string        `flag:"cookie-secret" cfg:"cookie_secret" env:"OAUTH2_PROXY_COOKIE_SECRET"` | 	Secret   string        `flag:"cookie-secret" cfg:"cookie_secret" env:"OAUTH2_PROXY_COOKIE_SECRET"` | ||||||
| 	CookieDomains  []string      `flag:"cookie-domain" cfg:"cookie_domain" env:"OAUTH2_PROXY_COOKIE_DOMAIN"` | 	Domains  []string      `flag:"cookie-domain" cfg:"cookie_domain" env:"OAUTH2_PROXY_COOKIE_DOMAIN"` | ||||||
| 	CookiePath     string        `flag:"cookie-path" cfg:"cookie_path" env:"OAUTH2_PROXY_COOKIE_PATH"` | 	Path     string        `flag:"cookie-path" cfg:"cookie_path" env:"OAUTH2_PROXY_COOKIE_PATH"` | ||||||
| 	CookieExpire   time.Duration `flag:"cookie-expire" cfg:"cookie_expire" env:"OAUTH2_PROXY_COOKIE_EXPIRE"` | 	Expire   time.Duration `flag:"cookie-expire" cfg:"cookie_expire" env:"OAUTH2_PROXY_COOKIE_EXPIRE"` | ||||||
| 	CookieRefresh  time.Duration `flag:"cookie-refresh" cfg:"cookie_refresh" env:"OAUTH2_PROXY_COOKIE_REFRESH"` | 	Refresh  time.Duration `flag:"cookie-refresh" cfg:"cookie_refresh" env:"OAUTH2_PROXY_COOKIE_REFRESH"` | ||||||
| 	CookieSecure   bool          `flag:"cookie-secure" cfg:"cookie_secure" env:"OAUTH2_PROXY_COOKIE_SECURE"` | 	Secure   bool          `flag:"cookie-secure" cfg:"cookie_secure" env:"OAUTH2_PROXY_COOKIE_SECURE"` | ||||||
| 	CookieHTTPOnly bool          `flag:"cookie-httponly" cfg:"cookie_httponly" env:"OAUTH2_PROXY_COOKIE_HTTPONLY"` | 	HTTPOnly bool          `flag:"cookie-httponly" cfg:"cookie_httponly" env:"OAUTH2_PROXY_COOKIE_HTTPONLY"` | ||||||
| 	CookieSameSite string        `flag:"cookie-samesite" cfg:"cookie_samesite" env:"OAUTH2_PROXY_COOKIE_SAMESITE"` | 	SameSite string        `flag:"cookie-samesite" cfg:"cookie_samesite" env:"OAUTH2_PROXY_COOKIE_SAMESITE"` | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -0,0 +1,134 @@ | ||||||
|  | package options | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"fmt" | ||||||
|  | 	"reflect" | ||||||
|  | 	"strings" | ||||||
|  | 
 | ||||||
|  | 	"github.com/mitchellh/mapstructure" | ||||||
|  | 	"github.com/spf13/pflag" | ||||||
|  | 	"github.com/spf13/viper" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | // Load reads in the config file at the path given, then merges in environment
 | ||||||
|  | // variables (prefixed with `OAUTH2_PROXY`) and finally merges in flags from the flagSet.
 | ||||||
|  | // If a config value is unset and the flag has a non-zero value default, this default will be used.
 | ||||||
|  | // Eg. A field defined:
 | ||||||
|  | //    FooBar `cfg:"foo_bar" flag:"foo-bar"`
 | ||||||
|  | // Can be set in the config file as `foo_bar="baz"`, in the environment as `OAUTH2_PROXY_FOO_BAR=baz`,
 | ||||||
|  | // or via the command line flag `--foo-bar=baz`.
 | ||||||
|  | func Load(configFileName string, flagSet *pflag.FlagSet, into interface{}) error { | ||||||
|  | 	v := viper.New() | ||||||
|  | 	v.SetConfigFile(configFileName) | ||||||
|  | 	v.SetConfigType("toml") // Config is in toml format
 | ||||||
|  | 	v.SetEnvPrefix("OAUTH2_PROXY") | ||||||
|  | 	v.AutomaticEnv() | ||||||
|  | 	v.SetTypeByDefaultValue(true) | ||||||
|  | 
 | ||||||
|  | 	if configFileName != "" { | ||||||
|  | 		err := v.ReadInConfig() | ||||||
|  | 		if err != nil { | ||||||
|  | 			return fmt.Errorf("unable to load config file: %w", err) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	err := registerFlags(v, "", flagSet, into) | ||||||
|  | 	if err != nil { | ||||||
|  | 		// This should only happen if there is a programming error
 | ||||||
|  | 		return fmt.Errorf("unable to register flags: %w", err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// UnmarhsalExact will return an error if the config includes options that are
 | ||||||
|  | 	// not mapped to felds of the into struct
 | ||||||
|  | 	err = v.UnmarshalExact(into, decodeFromCfgTag) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return fmt.Errorf("error unmarshalling config: %w", err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // registerFlags uses `cfg` and `flag` tags to associate flags in the flagSet
 | ||||||
|  | // to the fields in the options interface provided.
 | ||||||
|  | // Each exported field in the options must have a `cfg` tag otherwise an error will occur.
 | ||||||
|  | // - For fields, set `cfg` and `flag` so that `flag` is the name of the flag associated to this config option
 | ||||||
|  | // - For exported fields that are not user facing, set the `cfg` to `,internal`
 | ||||||
|  | // - For structs containing user facing fields, set the `cfg` to `,squash`
 | ||||||
|  | func registerFlags(v *viper.Viper, prefix string, flagSet *pflag.FlagSet, options interface{}) error { | ||||||
|  | 	val := reflect.ValueOf(options) | ||||||
|  | 	var typ reflect.Type | ||||||
|  | 	if val.Kind() == reflect.Ptr { | ||||||
|  | 		typ = val.Elem().Type() | ||||||
|  | 	} else { | ||||||
|  | 		typ = val.Type() | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	for i := 0; i < typ.NumField(); i++ { | ||||||
|  | 		// pull out the struct tags:
 | ||||||
|  | 		//    flag - the name of the command line flag
 | ||||||
|  | 		//    cfg - the name of the config file option
 | ||||||
|  | 		field := typ.Field(i) | ||||||
|  | 		fieldV := reflect.Indirect(val).Field(i) | ||||||
|  | 		fieldName := strings.Join([]string{prefix, field.Name}, ".") | ||||||
|  | 
 | ||||||
|  | 		cfgName := field.Tag.Get("cfg") | ||||||
|  | 		if cfgName == ",internal" { | ||||||
|  | 			// Public but internal types that should not be exposed to users, skip them
 | ||||||
|  | 			continue | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if isUnexported(field.Name) { | ||||||
|  | 			// Unexported fields cannot be set by a user, so won't have tags or flags, skip them
 | ||||||
|  | 			continue | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if field.Type.Kind() == reflect.Struct { | ||||||
|  | 			if cfgName != ",squash" { | ||||||
|  | 				return fmt.Errorf("field %q does not have required cfg tag: `,squash`", fieldName) | ||||||
|  | 			} | ||||||
|  | 			err := registerFlags(v, fieldName, flagSet, fieldV.Interface()) | ||||||
|  | 			if err != nil { | ||||||
|  | 				return err | ||||||
|  | 			} | ||||||
|  | 			continue | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		flagName := field.Tag.Get("flag") | ||||||
|  | 		if flagName == "" || cfgName == "" { | ||||||
|  | 			return fmt.Errorf("field %q does not have required tags (cfg, flag)", fieldName) | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if flagSet == nil { | ||||||
|  | 			return fmt.Errorf("flagset cannot be nil") | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		f := flagSet.Lookup(flagName) | ||||||
|  | 		if f == nil { | ||||||
|  | 			return fmt.Errorf("field %q does not have a registered flag", flagName) | ||||||
|  | 		} | ||||||
|  | 		err := v.BindPFlag(cfgName, f) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return fmt.Errorf("error binding flag for field %q: %w", fieldName, err) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // decodeFromCfgTag sets the Viper decoder to read the names from the `cfg` tag
 | ||||||
|  | // on each struct entry.
 | ||||||
|  | func decodeFromCfgTag(c *mapstructure.DecoderConfig) { | ||||||
|  | 	c.TagName = "cfg" | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // isUnexported checks if a field name starts with a lowercase letter and therefore
 | ||||||
|  | // if it is unexported.
 | ||||||
|  | func isUnexported(name string) bool { | ||||||
|  | 	if len(name) == 0 { | ||||||
|  | 		// This should never happen
 | ||||||
|  | 		panic("field name has len 0") | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	first := string(name[0]) | ||||||
|  | 	return first == strings.ToLower(first) | ||||||
|  | } | ||||||
|  | @ -0,0 +1,300 @@ | ||||||
|  | package options | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"fmt" | ||||||
|  | 	"io/ioutil" | ||||||
|  | 	"os" | ||||||
|  | 	"testing" | ||||||
|  | 
 | ||||||
|  | 	. "github.com/onsi/ginkgo" | ||||||
|  | 	. "github.com/onsi/ginkgo/extensions/table" | ||||||
|  | 	. "github.com/onsi/gomega" | ||||||
|  | 	"github.com/spf13/pflag" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | func TestOptionsSuite(t *testing.T) { | ||||||
|  | 	RegisterFailHandler(Fail) | ||||||
|  | 	RunSpecs(t, "Options Suite") | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | var _ = Describe("Load", func() { | ||||||
|  | 	Context("with a testOptions structure", func() { | ||||||
|  | 		type TestOptionSubStruct struct { | ||||||
|  | 			StringSliceOption []string `flag:"string-slice-option" cfg:"string_slice_option"` | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		type TestOptions struct { | ||||||
|  | 			StringOption string              `flag:"string-option" cfg:"string_option"` | ||||||
|  | 			Sub          TestOptionSubStruct `cfg:",squash"` | ||||||
|  | 			// Check exported but internal fields do not break loading
 | ||||||
|  | 			Internal *string `cfg:",internal"` | ||||||
|  | 			// Check unexported fields do not break loading
 | ||||||
|  | 			unexported string | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		type MissingSquashTestOptions struct { | ||||||
|  | 			StringOption string `flag:"string-option" cfg:"string_option"` | ||||||
|  | 			Sub          TestOptionSubStruct | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		type MissingCfgTestOptions struct { | ||||||
|  | 			StringOption string              `flag:"string-option"` | ||||||
|  | 			Sub          TestOptionSubStruct `cfg:",squash"` | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		type MissingFlagTestOptions struct { | ||||||
|  | 			StringOption string              `cfg:"string_option"` | ||||||
|  | 			Sub          TestOptionSubStruct `cfg:",squash"` | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		var testOptionsConfigBytes = []byte(` | ||||||
|  | 			string_option="foo" | ||||||
|  | 			string_slice_option="a,b,c,d" | ||||||
|  | 		`) | ||||||
|  | 
 | ||||||
|  | 		var testOptionsFlagSet *pflag.FlagSet | ||||||
|  | 
 | ||||||
|  | 		type testOptionsTableInput struct { | ||||||
|  | 			env            map[string]string | ||||||
|  | 			args           []string | ||||||
|  | 			configFile     []byte | ||||||
|  | 			flagSet        func() *pflag.FlagSet | ||||||
|  | 			expectedErr    error | ||||||
|  | 			input          interface{} | ||||||
|  | 			expectedOutput interface{} | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		BeforeEach(func() { | ||||||
|  | 			testOptionsFlagSet = pflag.NewFlagSet("testFlagSet", pflag.ExitOnError) | ||||||
|  | 			testOptionsFlagSet.String("string-option", "default", "") | ||||||
|  | 			testOptionsFlagSet.StringSlice("string-slice-option", []string{"a", "b"}, "") | ||||||
|  | 		}) | ||||||
|  | 
 | ||||||
|  | 		DescribeTable("Load", | ||||||
|  | 			func(o *testOptionsTableInput) { | ||||||
|  | 				var configFileName string | ||||||
|  | 
 | ||||||
|  | 				if o.configFile != nil { | ||||||
|  | 					By("Creating a config file") | ||||||
|  | 					configFile, err := ioutil.TempFile("", "oauth2-proxy-test-legacy-config-file") | ||||||
|  | 					Expect(err).ToNot(HaveOccurred()) | ||||||
|  | 					defer configFile.Close() | ||||||
|  | 
 | ||||||
|  | 					_, err = configFile.Write(o.configFile) | ||||||
|  | 					Expect(err).ToNot(HaveOccurred()) | ||||||
|  | 					defer os.Remove(configFile.Name()) | ||||||
|  | 
 | ||||||
|  | 					configFileName = configFile.Name() | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				if len(o.env) > 0 { | ||||||
|  | 					By("Setting environment variables") | ||||||
|  | 					for k, v := range o.env { | ||||||
|  | 						os.Setenv(k, v) | ||||||
|  | 						defer os.Unsetenv(k) | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				Expect(o.flagSet).ToNot(BeNil()) | ||||||
|  | 				flagSet := o.flagSet() | ||||||
|  | 				Expect(flagSet).ToNot(BeNil()) | ||||||
|  | 
 | ||||||
|  | 				if len(o.args) > 0 { | ||||||
|  | 					By("Parsing flag arguments") | ||||||
|  | 					Expect(flagSet.Parse(o.args)).To(Succeed()) | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				var input interface{} | ||||||
|  | 				if o.input != nil { | ||||||
|  | 					input = o.input | ||||||
|  | 				} else { | ||||||
|  | 					input = &TestOptions{} | ||||||
|  | 				} | ||||||
|  | 				err := Load(configFileName, flagSet, input) | ||||||
|  | 				if o.expectedErr != nil { | ||||||
|  | 					Expect(err).To(MatchError(o.expectedErr.Error())) | ||||||
|  | 				} else { | ||||||
|  | 					Expect(err).ToNot(HaveOccurred()) | ||||||
|  | 				} | ||||||
|  | 				Expect(input).To(Equal(o.expectedOutput)) | ||||||
|  | 			}, | ||||||
|  | 			Entry("with just a config file", &testOptionsTableInput{ | ||||||
|  | 				configFile: testOptionsConfigBytes, | ||||||
|  | 				flagSet:    func() *pflag.FlagSet { return testOptionsFlagSet }, | ||||||
|  | 				expectedOutput: &TestOptions{ | ||||||
|  | 					StringOption: "foo", | ||||||
|  | 					Sub: TestOptionSubStruct{ | ||||||
|  | 						StringSliceOption: []string{"a", "b", "c", "d"}, | ||||||
|  | 					}, | ||||||
|  | 				}, | ||||||
|  | 			}), | ||||||
|  | 			Entry("when setting env variables", &testOptionsTableInput{ | ||||||
|  | 				configFile: testOptionsConfigBytes, | ||||||
|  | 				env: map[string]string{ | ||||||
|  | 					"OAUTH2_PROXY_STRING_OPTION":       "bar", | ||||||
|  | 					"OAUTH2_PROXY_STRING_SLICE_OPTION": "a,b,c", | ||||||
|  | 				}, | ||||||
|  | 				flagSet: func() *pflag.FlagSet { return testOptionsFlagSet }, | ||||||
|  | 				expectedOutput: &TestOptions{ | ||||||
|  | 					StringOption: "bar", | ||||||
|  | 					Sub: TestOptionSubStruct{ | ||||||
|  | 						StringSliceOption: []string{"a", "b", "c"}, | ||||||
|  | 					}, | ||||||
|  | 				}, | ||||||
|  | 			}), | ||||||
|  | 			Entry("when setting flags", &testOptionsTableInput{ | ||||||
|  | 				configFile: testOptionsConfigBytes, | ||||||
|  | 				env: map[string]string{ | ||||||
|  | 					"OAUTH2_PROXY_STRING_OPTION":       "bar", | ||||||
|  | 					"OAUTH2_PROXY_STRING_SLICE_OPTION": "a,b,c", | ||||||
|  | 				}, | ||||||
|  | 				args: []string{ | ||||||
|  | 					"--string-option", "baz", | ||||||
|  | 					"--string-slice-option", "a,b,c,d,e", | ||||||
|  | 				}, | ||||||
|  | 				flagSet: func() *pflag.FlagSet { return testOptionsFlagSet }, | ||||||
|  | 				expectedOutput: &TestOptions{ | ||||||
|  | 					StringOption: "baz", | ||||||
|  | 					Sub: TestOptionSubStruct{ | ||||||
|  | 						StringSliceOption: []string{"a", "b", "c", "d", "e"}, | ||||||
|  | 					}, | ||||||
|  | 				}, | ||||||
|  | 			}), | ||||||
|  | 			Entry("when setting flags multiple times", &testOptionsTableInput{ | ||||||
|  | 				configFile: testOptionsConfigBytes, | ||||||
|  | 				env: map[string]string{ | ||||||
|  | 					"OAUTH2_PROXY_STRING_OPTION":       "bar", | ||||||
|  | 					"OAUTH2_PROXY_STRING_SLICE_OPTION": "a,b,c", | ||||||
|  | 				}, | ||||||
|  | 				args: []string{ | ||||||
|  | 					"--string-option", "baz", | ||||||
|  | 					"--string-slice-option", "x", | ||||||
|  | 					"--string-slice-option", "y", | ||||||
|  | 					"--string-slice-option", "z", | ||||||
|  | 				}, | ||||||
|  | 				flagSet: func() *pflag.FlagSet { return testOptionsFlagSet }, | ||||||
|  | 				expectedOutput: &TestOptions{ | ||||||
|  | 					StringOption: "baz", | ||||||
|  | 					Sub: TestOptionSubStruct{ | ||||||
|  | 						StringSliceOption: []string{"x", "y", "z"}, | ||||||
|  | 					}, | ||||||
|  | 				}, | ||||||
|  | 			}), | ||||||
|  | 			Entry("when setting env variables without a config file", &testOptionsTableInput{ | ||||||
|  | 				env: map[string]string{ | ||||||
|  | 					"OAUTH2_PROXY_STRING_OPTION":       "bar", | ||||||
|  | 					"OAUTH2_PROXY_STRING_SLICE_OPTION": "a,b,c", | ||||||
|  | 				}, | ||||||
|  | 				flagSet: func() *pflag.FlagSet { return testOptionsFlagSet }, | ||||||
|  | 				expectedOutput: &TestOptions{ | ||||||
|  | 					StringOption: "bar", | ||||||
|  | 					Sub: TestOptionSubStruct{ | ||||||
|  | 						StringSliceOption: []string{"a", "b", "c"}, | ||||||
|  | 					}, | ||||||
|  | 				}, | ||||||
|  | 			}), | ||||||
|  | 			Entry("when setting flags without a config file", &testOptionsTableInput{ | ||||||
|  | 				env: map[string]string{ | ||||||
|  | 					"OAUTH2_PROXY_STRING_OPTION":       "bar", | ||||||
|  | 					"OAUTH2_PROXY_STRING_SLICE_OPTION": "a,b,c", | ||||||
|  | 				}, | ||||||
|  | 				args: []string{ | ||||||
|  | 					"--string-option", "baz", | ||||||
|  | 					"--string-slice-option", "a,b,c,d,e", | ||||||
|  | 				}, | ||||||
|  | 				flagSet: func() *pflag.FlagSet { return testOptionsFlagSet }, | ||||||
|  | 				expectedOutput: &TestOptions{ | ||||||
|  | 					StringOption: "baz", | ||||||
|  | 					Sub: TestOptionSubStruct{ | ||||||
|  | 						StringSliceOption: []string{"a", "b", "c", "d", "e"}, | ||||||
|  | 					}, | ||||||
|  | 				}, | ||||||
|  | 			}), | ||||||
|  | 			Entry("when setting flags without a config file", &testOptionsTableInput{ | ||||||
|  | 				env: map[string]string{ | ||||||
|  | 					"OAUTH2_PROXY_STRING_OPTION":       "bar", | ||||||
|  | 					"OAUTH2_PROXY_STRING_SLICE_OPTION": "a,b,c", | ||||||
|  | 				}, | ||||||
|  | 				args: []string{ | ||||||
|  | 					"--string-option", "baz", | ||||||
|  | 					"--string-slice-option", "a,b,c,d,e", | ||||||
|  | 				}, | ||||||
|  | 				flagSet: func() *pflag.FlagSet { return testOptionsFlagSet }, | ||||||
|  | 				expectedOutput: &TestOptions{ | ||||||
|  | 					StringOption: "baz", | ||||||
|  | 					Sub: TestOptionSubStruct{ | ||||||
|  | 						StringSliceOption: []string{"a", "b", "c", "d", "e"}, | ||||||
|  | 					}, | ||||||
|  | 				}, | ||||||
|  | 			}), | ||||||
|  | 			Entry("when nothing is set it should use flag defaults", &testOptionsTableInput{ | ||||||
|  | 				flagSet: func() *pflag.FlagSet { return testOptionsFlagSet }, | ||||||
|  | 				expectedOutput: &TestOptions{ | ||||||
|  | 					StringOption: "default", | ||||||
|  | 					Sub: TestOptionSubStruct{ | ||||||
|  | 						StringSliceOption: []string{"a", "b"}, | ||||||
|  | 					}, | ||||||
|  | 				}, | ||||||
|  | 			}), | ||||||
|  | 			Entry("with an invalid config file", &testOptionsTableInput{ | ||||||
|  | 				configFile:     []byte(`slice_option = foo`), | ||||||
|  | 				flagSet:        func() *pflag.FlagSet { return testOptionsFlagSet }, | ||||||
|  | 				expectedErr:    fmt.Errorf("unable to load config file: While parsing config: (1, 16): never reached"), | ||||||
|  | 				expectedOutput: &TestOptions{}, | ||||||
|  | 			}), | ||||||
|  | 			Entry("with an invalid flagset", &testOptionsTableInput{ | ||||||
|  | 				flagSet: func() *pflag.FlagSet { | ||||||
|  | 					// Missing a flag
 | ||||||
|  | 					f := pflag.NewFlagSet("testFlagSet", pflag.ExitOnError) | ||||||
|  | 					f.String("string-option", "default", "") | ||||||
|  | 					return f | ||||||
|  | 				}, | ||||||
|  | 				expectedErr:    fmt.Errorf("unable to register flags: field \"string-slice-option\" does not have a registered flag"), | ||||||
|  | 				expectedOutput: &TestOptions{}, | ||||||
|  | 			}), | ||||||
|  | 			Entry("with an struct is missing the squash tag", &testOptionsTableInput{ | ||||||
|  | 				flagSet:        func() *pflag.FlagSet { return testOptionsFlagSet }, | ||||||
|  | 				expectedErr:    fmt.Errorf("unable to register flags: field \".Sub\" does not have required cfg tag: `,squash`"), | ||||||
|  | 				input:          &MissingSquashTestOptions{}, | ||||||
|  | 				expectedOutput: &MissingSquashTestOptions{}, | ||||||
|  | 			}), | ||||||
|  | 			Entry("with a field is missing the cfg tag", &testOptionsTableInput{ | ||||||
|  | 				flagSet:        func() *pflag.FlagSet { return testOptionsFlagSet }, | ||||||
|  | 				expectedErr:    fmt.Errorf("unable to register flags: field \".StringOption\" does not have required tags (cfg, flag)"), | ||||||
|  | 				input:          &MissingCfgTestOptions{}, | ||||||
|  | 				expectedOutput: &MissingCfgTestOptions{}, | ||||||
|  | 			}), | ||||||
|  | 			Entry("with a field is missing the flag tag", &testOptionsTableInput{ | ||||||
|  | 				flagSet:        func() *pflag.FlagSet { return testOptionsFlagSet }, | ||||||
|  | 				expectedErr:    fmt.Errorf("unable to register flags: field \".StringOption\" does not have required tags (cfg, flag)"), | ||||||
|  | 				input:          &MissingFlagTestOptions{}, | ||||||
|  | 				expectedOutput: &MissingFlagTestOptions{}, | ||||||
|  | 			}), | ||||||
|  | 			Entry("with existing unexported fields", &testOptionsTableInput{ | ||||||
|  | 				flagSet: func() *pflag.FlagSet { return testOptionsFlagSet }, | ||||||
|  | 				input: &TestOptions{ | ||||||
|  | 					unexported: "unexported", | ||||||
|  | 				}, | ||||||
|  | 				expectedOutput: &TestOptions{ | ||||||
|  | 					StringOption: "default", | ||||||
|  | 					Sub: TestOptionSubStruct{ | ||||||
|  | 						StringSliceOption: []string{"a", "b"}, | ||||||
|  | 					}, | ||||||
|  | 					unexported: "unexported", | ||||||
|  | 				}, | ||||||
|  | 			}), | ||||||
|  | 			Entry("with an unknown option in the config file", &testOptionsTableInput{ | ||||||
|  | 				configFile:  []byte(`unknown_option="foo"`), | ||||||
|  | 				flagSet:     func() *pflag.FlagSet { return testOptionsFlagSet }, | ||||||
|  | 				expectedErr: fmt.Errorf("error unmarshalling config: 1 error(s) decoding:\n\n* '' has invalid keys: unknown_option"), | ||||||
|  | 				// Viper will unmarshal before returning the error, so this is the default output
 | ||||||
|  | 				expectedOutput: &TestOptions{ | ||||||
|  | 					StringOption: "default", | ||||||
|  | 					Sub: TestOptionSubStruct{ | ||||||
|  | 						StringSliceOption: []string{"a", "b"}, | ||||||
|  | 					}, | ||||||
|  | 				}, | ||||||
|  | 			}), | ||||||
|  | 		) | ||||||
|  | 	}) | ||||||
|  | }) | ||||||
|  | @ -5,30 +5,26 @@ import "github.com/oauth2-proxy/oauth2-proxy/pkg/encryption" | ||||||
| // SessionOptions contains configuration options for the SessionStore providers.
 | // SessionOptions contains configuration options for the SessionStore providers.
 | ||||||
| type SessionOptions struct { | type SessionOptions struct { | ||||||
| 	Type   string             `flag:"session-store-type" cfg:"session_store_type" env:"OAUTH2_PROXY_SESSION_STORE_TYPE"` | 	Type   string             `flag:"session-store-type" cfg:"session_store_type" env:"OAUTH2_PROXY_SESSION_STORE_TYPE"` | ||||||
| 	Cipher *encryption.Cipher | 	Cipher *encryption.Cipher `cfg:",internal"` | ||||||
| 	CookieStoreOptions | 	Redis  RedisStoreOptions  `cfg:",squash"` | ||||||
| 	RedisStoreOptions |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // CookieSessionStoreType is used to indicate the CookieSessionStore should be
 | // CookieSessionStoreType is used to indicate the CookieSessionStore should be
 | ||||||
| // used for storing sessions.
 | // used for storing sessions.
 | ||||||
| var CookieSessionStoreType = "cookie" | var CookieSessionStoreType = "cookie" | ||||||
| 
 | 
 | ||||||
| // CookieStoreOptions contains configuration options for the CookieSessionStore.
 |  | ||||||
| type CookieStoreOptions struct{} |  | ||||||
| 
 |  | ||||||
| // RedisSessionStoreType is used to indicate the RedisSessionStore should be
 | // RedisSessionStoreType is used to indicate the RedisSessionStore should be
 | ||||||
| // used for storing sessions.
 | // used for storing sessions.
 | ||||||
| var RedisSessionStoreType = "redis" | var RedisSessionStoreType = "redis" | ||||||
| 
 | 
 | ||||||
| // RedisStoreOptions contains configuration options for the RedisSessionStore.
 | // RedisStoreOptions contains configuration options for the RedisSessionStore.
 | ||||||
| type RedisStoreOptions struct { | type RedisStoreOptions struct { | ||||||
| 	RedisConnectionURL     string   `flag:"redis-connection-url" cfg:"redis_connection_url" env:"OAUTH2_PROXY_REDIS_CONNECTION_URL"` | 	ConnectionURL          string   `flag:"redis-connection-url" cfg:"redis_connection_url" env:"OAUTH2_PROXY_REDIS_CONNECTION_URL"` | ||||||
| 	UseSentinel            bool     `flag:"redis-use-sentinel" cfg:"redis_use_sentinel" env:"OAUTH2_PROXY_REDIS_USE_SENTINEL"` | 	UseSentinel            bool     `flag:"redis-use-sentinel" cfg:"redis_use_sentinel" env:"OAUTH2_PROXY_REDIS_USE_SENTINEL"` | ||||||
| 	SentinelMasterName     string   `flag:"redis-sentinel-master-name" cfg:"redis_sentinel_master_name" env:"OAUTH2_PROXY_REDIS_SENTINEL_MASTER_NAME"` | 	SentinelMasterName     string   `flag:"redis-sentinel-master-name" cfg:"redis_sentinel_master_name" env:"OAUTH2_PROXY_REDIS_SENTINEL_MASTER_NAME"` | ||||||
| 	SentinelConnectionURLs []string `flag:"redis-sentinel-connection-urls" cfg:"redis_sentinel_connection_urls" env:"OAUTH2_PROXY_REDIS_SENTINEL_CONNECTION_URLS"` | 	SentinelConnectionURLs []string `flag:"redis-sentinel-connection-urls" cfg:"redis_sentinel_connection_urls" env:"OAUTH2_PROXY_REDIS_SENTINEL_CONNECTION_URLS"` | ||||||
| 	UseCluster             bool     `flag:"redis-use-cluster" cfg:"redis_use_cluster" env:"OAUTH2_PROXY_REDIS_USE_CLUSTER"` | 	UseCluster             bool     `flag:"redis-use-cluster" cfg:"redis_use_cluster" env:"OAUTH2_PROXY_REDIS_USE_CLUSTER"` | ||||||
| 	ClusterConnectionURLs  []string `flag:"redis-cluster-connection-urls" cfg:"redis_cluster_connection_urls" env:"OAUTH2_PROXY_REDIS_CLUSTER_CONNECTION_URLS"` | 	ClusterConnectionURLs  []string `flag:"redis-cluster-connection-urls" cfg:"redis_cluster_connection_urls" env:"OAUTH2_PROXY_REDIS_CLUSTER_CONNECTION_URLS"` | ||||||
| 	RedisCAPath            string   `flag:"redis-ca-path" cfg:"redis_ca_path" env:"OAUTH2_PROXY_REDIS_CA_PATH"` | 	CAPath                 string   `flag:"redis-ca-path" cfg:"redis_ca_path" env:"OAUTH2_PROXY_REDIS_CA_PATH"` | ||||||
| 	RedisInsecureTLS       bool     `flag:"redis-insecure-skip-tls-verify" cfg:"redis_insecure_skip_tls_verify" env:"OAUTH2_PROXY_REDIS_INSECURE_SKIP_TLS_VERIFY"` | 	InsecureSkipTLSVerify  bool     `flag:"redis-insecure-skip-tls-verify" cfg:"redis_insecure_skip_tls_verify" env:"OAUTH2_PROXY_REDIS_INSECURE_SKIP_TLS_VERIFY"` | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -38,19 +38,19 @@ func MakeCookie(req *http.Request, name string, value string, path string, domai | ||||||
| 
 | 
 | ||||||
| // MakeCookieFromOptions constructs a cookie based on the given *options.CookieOptions,
 | // MakeCookieFromOptions constructs a cookie based on the given *options.CookieOptions,
 | ||||||
| // value and creation time
 | // value and creation time
 | ||||||
| func MakeCookieFromOptions(req *http.Request, name string, value string, opts *options.CookieOptions, expiration time.Duration, now time.Time) *http.Cookie { | func MakeCookieFromOptions(req *http.Request, name string, value string, cookieOpts *options.CookieOptions, expiration time.Duration, now time.Time) *http.Cookie { | ||||||
| 	domain := GetCookieDomain(req, opts.CookieDomains) | 	domain := GetCookieDomain(req, cookieOpts.Domains) | ||||||
| 
 | 
 | ||||||
| 	if domain != "" { | 	if domain != "" { | ||||||
| 		return MakeCookie(req, name, value, opts.CookiePath, domain, opts.CookieHTTPOnly, opts.CookieSecure, expiration, now, ParseSameSite(opts.CookieSameSite)) | 		return MakeCookie(req, name, value, cookieOpts.Path, domain, cookieOpts.HTTPOnly, cookieOpts.Secure, expiration, now, ParseSameSite(cookieOpts.SameSite)) | ||||||
| 	} | 	} | ||||||
| 	// If nothing matches, create the cookie with the shortest domain
 | 	// If nothing matches, create the cookie with the shortest domain
 | ||||||
| 	logger.Printf("Warning: request host %q did not match any of the specific cookie domains of %q", GetRequestHost(req), strings.Join(opts.CookieDomains, ",")) | 	logger.Printf("Warning: request host %q did not match any of the specific cookie domains of %q", GetRequestHost(req), strings.Join(cookieOpts.Domains, ",")) | ||||||
| 	defaultDomain := "" | 	defaultDomain := "" | ||||||
| 	if len(opts.CookieDomains) > 0 { | 	if len(cookieOpts.Domains) > 0 { | ||||||
| 		defaultDomain = opts.CookieDomains[len(opts.CookieDomains)-1] | 		defaultDomain = cookieOpts.Domains[len(cookieOpts.Domains)-1] | ||||||
| 	} | 	} | ||||||
| 	return MakeCookie(req, name, value, opts.CookiePath, defaultDomain, opts.CookieHTTPOnly, opts.CookieSecure, expiration, now, ParseSameSite(opts.CookieSameSite)) | 	return MakeCookie(req, name, value, cookieOpts.Path, defaultDomain, cookieOpts.HTTPOnly, cookieOpts.Secure, expiration, now, ParseSameSite(cookieOpts.SameSite)) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // GetCookieDomain returns the correct cookie domain given a list of domains
 | // GetCookieDomain returns the correct cookie domain given a list of domains
 | ||||||
|  |  | ||||||
|  | @ -49,12 +49,12 @@ func (s *SessionStore) Save(rw http.ResponseWriter, req *http.Request, ss *sessi | ||||||
| // Load reads sessions.SessionState information from Cookies within the
 | // Load reads sessions.SessionState information from Cookies within the
 | ||||||
| // HTTP request object
 | // HTTP request object
 | ||||||
| func (s *SessionStore) Load(req *http.Request) (*sessions.SessionState, error) { | func (s *SessionStore) Load(req *http.Request) (*sessions.SessionState, error) { | ||||||
| 	c, err := loadCookie(req, s.CookieOptions.CookieName) | 	c, err := loadCookie(req, s.CookieOptions.Name) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		// always http.ErrNoCookie
 | 		// always http.ErrNoCookie
 | ||||||
| 		return nil, fmt.Errorf("cookie %q not present", s.CookieOptions.CookieName) | 		return nil, fmt.Errorf("cookie %q not present", s.CookieOptions.Name) | ||||||
| 	} | 	} | ||||||
| 	val, _, ok := encryption.Validate(c, s.CookieOptions.CookieSecret, s.CookieOptions.CookieExpire) | 	val, _, ok := encryption.Validate(c, s.CookieOptions.Secret, s.CookieOptions.Expire) | ||||||
| 	if !ok { | 	if !ok { | ||||||
| 		return nil, errors.New("cookie signature not valid") | 		return nil, errors.New("cookie signature not valid") | ||||||
| 	} | 	} | ||||||
|  | @ -70,7 +70,7 @@ func (s *SessionStore) Load(req *http.Request) (*sessions.SessionState, error) { | ||||||
| // clear the session
 | // clear the session
 | ||||||
| func (s *SessionStore) Clear(rw http.ResponseWriter, req *http.Request) error { | func (s *SessionStore) Clear(rw http.ResponseWriter, req *http.Request) error { | ||||||
| 	// matches CookieName, CookieName_<number>
 | 	// matches CookieName, CookieName_<number>
 | ||||||
| 	var cookieNameRegex = regexp.MustCompile(fmt.Sprintf("^%s(_\\d+)?$", s.CookieOptions.CookieName)) | 	var cookieNameRegex = regexp.MustCompile(fmt.Sprintf("^%s(_\\d+)?$", s.CookieOptions.Name)) | ||||||
| 
 | 
 | ||||||
| 	for _, c := range req.Cookies() { | 	for _, c := range req.Cookies() { | ||||||
| 		if cookieNameRegex.MatchString(c.Name) { | 		if cookieNameRegex.MatchString(c.Name) { | ||||||
|  | @ -94,10 +94,10 @@ func (s *SessionStore) setSessionCookie(rw http.ResponseWriter, req *http.Reques | ||||||
| // authentication details
 | // authentication details
 | ||||||
| func (s *SessionStore) makeSessionCookie(req *http.Request, value string, now time.Time) []*http.Cookie { | func (s *SessionStore) makeSessionCookie(req *http.Request, value string, now time.Time) []*http.Cookie { | ||||||
| 	if value != "" { | 	if value != "" { | ||||||
| 		value = encryption.SignedValue(s.CookieOptions.CookieSecret, s.CookieOptions.CookieName, value, now) | 		value = encryption.SignedValue(s.CookieOptions.Secret, s.CookieOptions.Name, value, now) | ||||||
| 	} | 	} | ||||||
| 	c := s.makeCookie(req, s.CookieOptions.CookieName, value, s.CookieOptions.CookieExpire, now) | 	c := s.makeCookie(req, s.CookieOptions.Name, value, s.CookieOptions.Expire, now) | ||||||
| 	if len(c.Value) > 4096-len(s.CookieOptions.CookieName) { | 	if len(c.Value) > 4096-len(s.CookieOptions.Name) { | ||||||
| 		return splitCookie(c) | 		return splitCookie(c) | ||||||
| 	} | 	} | ||||||
| 	return []*http.Cookie{c} | 	return []*http.Cookie{c} | ||||||
|  |  | ||||||
|  | @ -40,7 +40,7 @@ type SessionStore struct { | ||||||
| // NewRedisSessionStore initialises a new instance of the SessionStore from
 | // NewRedisSessionStore initialises a new instance of the SessionStore from
 | ||||||
| // the configuration given
 | // the configuration given
 | ||||||
| func NewRedisSessionStore(opts *options.SessionOptions, cookieOpts *options.CookieOptions) (sessions.SessionStore, error) { | func NewRedisSessionStore(opts *options.SessionOptions, cookieOpts *options.CookieOptions) (sessions.SessionStore, error) { | ||||||
| 	client, err := newRedisCmdable(opts.RedisStoreOptions) | 	client, err := newRedisCmdable(opts.Redis) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, fmt.Errorf("error constructing redis client: %v", err) | 		return nil, fmt.Errorf("error constructing redis client: %v", err) | ||||||
| 	} | 	} | ||||||
|  | @ -74,16 +74,16 @@ func newRedisCmdable(opts options.RedisStoreOptions) (Client, error) { | ||||||
| 		return newClusterClient(client), nil | 		return newClusterClient(client), nil | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	opt, err := redis.ParseURL(opts.RedisConnectionURL) | 	opt, err := redis.ParseURL(opts.ConnectionURL) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, fmt.Errorf("unable to parse redis url: %s", err) | 		return nil, fmt.Errorf("unable to parse redis url: %s", err) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if opts.RedisInsecureTLS { | 	if opts.InsecureSkipTLSVerify { | ||||||
| 		opt.TLSConfig.InsecureSkipVerify = true | 		opt.TLSConfig.InsecureSkipVerify = true | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if opts.RedisCAPath != "" { | 	if opts.CAPath != "" { | ||||||
| 		rootCAs, err := x509.SystemCertPool() | 		rootCAs, err := x509.SystemCertPool() | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			logger.Printf("failed to load system cert pool for redis connection, falling back to empty cert pool") | 			logger.Printf("failed to load system cert pool for redis connection, falling back to empty cert pool") | ||||||
|  | @ -91,9 +91,9 @@ func newRedisCmdable(opts options.RedisStoreOptions) (Client, error) { | ||||||
| 		if rootCAs == nil { | 		if rootCAs == nil { | ||||||
| 			rootCAs = x509.NewCertPool() | 			rootCAs = x509.NewCertPool() | ||||||
| 		} | 		} | ||||||
| 		certs, err := ioutil.ReadFile(opts.RedisCAPath) | 		certs, err := ioutil.ReadFile(opts.CAPath) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			return nil, fmt.Errorf("failed to load %q, %v", opts.RedisCAPath, err) | 			return nil, fmt.Errorf("failed to load %q, %v", opts.CAPath, err) | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		// Append our cert to the system pool
 | 		// Append our cert to the system pool
 | ||||||
|  | @ -117,13 +117,13 @@ func (store *SessionStore) Save(rw http.ResponseWriter, req *http.Request, s *se | ||||||
| 
 | 
 | ||||||
| 	// Old sessions that we are refreshing would have a request cookie
 | 	// Old sessions that we are refreshing would have a request cookie
 | ||||||
| 	// New sessions don't, so we ignore the error. storeValue will check requestCookie
 | 	// New sessions don't, so we ignore the error. storeValue will check requestCookie
 | ||||||
| 	requestCookie, _ := req.Cookie(store.CookieOptions.CookieName) | 	requestCookie, _ := req.Cookie(store.CookieOptions.Name) | ||||||
| 	value, err := s.EncodeSessionState(store.CookieCipher) | 	value, err := s.EncodeSessionState(store.CookieCipher) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
| 	ctx := req.Context() | 	ctx := req.Context() | ||||||
| 	ticketString, err := store.storeValue(ctx, value, store.CookieOptions.CookieExpire, requestCookie) | 	ticketString, err := store.storeValue(ctx, value, store.CookieOptions.Expire, requestCookie) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
|  | @ -131,7 +131,7 @@ func (store *SessionStore) Save(rw http.ResponseWriter, req *http.Request, s *se | ||||||
| 	ticketCookie := store.makeCookie( | 	ticketCookie := store.makeCookie( | ||||||
| 		req, | 		req, | ||||||
| 		ticketString, | 		ticketString, | ||||||
| 		store.CookieOptions.CookieExpire, | 		store.CookieOptions.Expire, | ||||||
| 		s.CreatedAt, | 		s.CreatedAt, | ||||||
| 	) | 	) | ||||||
| 
 | 
 | ||||||
|  | @ -142,12 +142,12 @@ func (store *SessionStore) Save(rw http.ResponseWriter, req *http.Request, s *se | ||||||
| // Load reads sessions.SessionState information from a ticket
 | // Load reads sessions.SessionState information from a ticket
 | ||||||
| // cookie within the HTTP request object
 | // cookie within the HTTP request object
 | ||||||
| func (store *SessionStore) Load(req *http.Request) (*sessions.SessionState, error) { | func (store *SessionStore) Load(req *http.Request) (*sessions.SessionState, error) { | ||||||
| 	requestCookie, err := req.Cookie(store.CookieOptions.CookieName) | 	requestCookie, err := req.Cookie(store.CookieOptions.Name) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, fmt.Errorf("error loading session: %s", err) | 		return nil, fmt.Errorf("error loading session: %s", err) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	val, _, ok := encryption.Validate(requestCookie, store.CookieOptions.CookieSecret, store.CookieOptions.CookieExpire) | 	val, _, ok := encryption.Validate(requestCookie, store.CookieOptions.Secret, store.CookieOptions.Expire) | ||||||
| 	if !ok { | 	if !ok { | ||||||
| 		return nil, fmt.Errorf("cookie signature not valid") | 		return nil, fmt.Errorf("cookie signature not valid") | ||||||
| 	} | 	} | ||||||
|  | @ -161,12 +161,12 @@ func (store *SessionStore) Load(req *http.Request) (*sessions.SessionState, erro | ||||||
| 
 | 
 | ||||||
| // loadSessionFromString loads the session based on the ticket value
 | // loadSessionFromString loads the session based on the ticket value
 | ||||||
| func (store *SessionStore) loadSessionFromString(ctx context.Context, value string) (*sessions.SessionState, error) { | func (store *SessionStore) loadSessionFromString(ctx context.Context, value string) (*sessions.SessionState, error) { | ||||||
| 	ticket, err := decodeTicket(store.CookieOptions.CookieName, value) | 	ticket, err := decodeTicket(store.CookieOptions.Name, value) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	resultBytes, err := store.Client.Get(ctx, ticket.asHandle(store.CookieOptions.CookieName)) | 	resultBytes, err := store.Client.Get(ctx, ticket.asHandle(store.CookieOptions.Name)) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
|  | @ -199,7 +199,7 @@ func (store *SessionStore) Clear(rw http.ResponseWriter, req *http.Request) erro | ||||||
| 	http.SetCookie(rw, clearCookie) | 	http.SetCookie(rw, clearCookie) | ||||||
| 
 | 
 | ||||||
| 	// If there was an existing cookie we should clear the session in redis
 | 	// If there was an existing cookie we should clear the session in redis
 | ||||||
| 	requestCookie, err := req.Cookie(store.CookieOptions.CookieName) | 	requestCookie, err := req.Cookie(store.CookieOptions.Name) | ||||||
| 	if err != nil && err == http.ErrNoCookie { | 	if err != nil && err == http.ErrNoCookie { | ||||||
| 		// No existing cookie so can't clear redis
 | 		// No existing cookie so can't clear redis
 | ||||||
| 		return nil | 		return nil | ||||||
|  | @ -207,17 +207,17 @@ func (store *SessionStore) Clear(rw http.ResponseWriter, req *http.Request) erro | ||||||
| 		return fmt.Errorf("error retrieving cookie: %v", err) | 		return fmt.Errorf("error retrieving cookie: %v", err) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	val, _, ok := encryption.Validate(requestCookie, store.CookieOptions.CookieSecret, store.CookieOptions.CookieExpire) | 	val, _, ok := encryption.Validate(requestCookie, store.CookieOptions.Secret, store.CookieOptions.Expire) | ||||||
| 	if !ok { | 	if !ok { | ||||||
| 		return fmt.Errorf("cookie signature not valid") | 		return fmt.Errorf("cookie signature not valid") | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// We only return an error if we had an issue with redis
 | 	// We only return an error if we had an issue with redis
 | ||||||
| 	// If there's an issue decoding the ticket, ignore it
 | 	// If there's an issue decoding the ticket, ignore it
 | ||||||
| 	ticket, _ := decodeTicket(store.CookieOptions.CookieName, val) | 	ticket, _ := decodeTicket(store.CookieOptions.Name, val) | ||||||
| 	if ticket != nil { | 	if ticket != nil { | ||||||
| 		ctx := req.Context() | 		ctx := req.Context() | ||||||
| 		err := store.Client.Del(ctx, ticket.asHandle(store.CookieOptions.CookieName)) | 		err := store.Client.Del(ctx, ticket.asHandle(store.CookieOptions.Name)) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			return fmt.Errorf("error clearing cookie from redis: %s", err) | 			return fmt.Errorf("error clearing cookie from redis: %s", err) | ||||||
| 		} | 		} | ||||||
|  | @ -228,11 +228,11 @@ func (store *SessionStore) Clear(rw http.ResponseWriter, req *http.Request) erro | ||||||
| // makeCookie makes a cookie, signing the value if present
 | // makeCookie makes a cookie, signing the value if present
 | ||||||
| func (store *SessionStore) makeCookie(req *http.Request, value string, expires time.Duration, now time.Time) *http.Cookie { | func (store *SessionStore) makeCookie(req *http.Request, value string, expires time.Duration, now time.Time) *http.Cookie { | ||||||
| 	if value != "" { | 	if value != "" { | ||||||
| 		value = encryption.SignedValue(store.CookieOptions.CookieSecret, store.CookieOptions.CookieName, value, now) | 		value = encryption.SignedValue(store.CookieOptions.Secret, store.CookieOptions.Name, value, now) | ||||||
| 	} | 	} | ||||||
| 	return cookies.MakeCookieFromOptions( | 	return cookies.MakeCookieFromOptions( | ||||||
| 		req, | 		req, | ||||||
| 		store.CookieOptions.CookieName, | 		store.CookieOptions.Name, | ||||||
| 		value, | 		value, | ||||||
| 		store.CookieOptions, | 		store.CookieOptions, | ||||||
| 		expires, | 		expires, | ||||||
|  | @ -256,12 +256,12 @@ func (store *SessionStore) storeValue(ctx context.Context, value string, expirat | ||||||
| 	stream := cipher.NewCFBEncrypter(block, ticket.Secret) | 	stream := cipher.NewCFBEncrypter(block, ticket.Secret) | ||||||
| 	stream.XORKeyStream(ciphertext, []byte(value)) | 	stream.XORKeyStream(ciphertext, []byte(value)) | ||||||
| 
 | 
 | ||||||
| 	handle := ticket.asHandle(store.CookieOptions.CookieName) | 	handle := ticket.asHandle(store.CookieOptions.Name) | ||||||
| 	err = store.Client.Set(ctx, handle, ciphertext, expiration) | 	err = store.Client.Set(ctx, handle, ciphertext, expiration) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return "", err | 		return "", err | ||||||
| 	} | 	} | ||||||
| 	return ticket.encodeTicket(store.CookieOptions.CookieName), nil | 	return ticket.encodeTicket(store.CookieOptions.Name), nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // getTicket retrieves an existing ticket from the cookie if present,
 | // getTicket retrieves an existing ticket from the cookie if present,
 | ||||||
|  | @ -272,14 +272,14 @@ func (store *SessionStore) getTicket(requestCookie *http.Cookie) (*TicketData, e | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// An existing cookie exists, try to retrieve the ticket
 | 	// An existing cookie exists, try to retrieve the ticket
 | ||||||
| 	val, _, ok := encryption.Validate(requestCookie, store.CookieOptions.CookieSecret, store.CookieOptions.CookieExpire) | 	val, _, ok := encryption.Validate(requestCookie, store.CookieOptions.Secret, store.CookieOptions.Expire) | ||||||
| 	if !ok { | 	if !ok { | ||||||
| 		// Cookie is invalid, create a new ticket
 | 		// Cookie is invalid, create a new ticket
 | ||||||
| 		return newTicket() | 		return newTicket() | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// Valid cookie, decode the ticket
 | 	// Valid cookie, decode the ticket
 | ||||||
| 	ticket, err := decodeTicket(store.CookieOptions.CookieName, val) | 	ticket, err := decodeTicket(store.CookieOptions.Name, val) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		// If we can't decode the ticket we have to create a new one
 | 		// If we can't decode the ticket we have to create a new one
 | ||||||
| 		return newTicket() | 		return newTicket() | ||||||
|  |  | ||||||
|  | @ -47,25 +47,25 @@ var _ = Describe("NewSessionStore", func() { | ||||||
| 
 | 
 | ||||||
| 			It("have the correct name set", func() { | 			It("have the correct name set", func() { | ||||||
| 				if len(cookies) == 1 { | 				if len(cookies) == 1 { | ||||||
| 					Expect(cookies[0].Name).To(Equal(cookieOpts.CookieName)) | 					Expect(cookies[0].Name).To(Equal(cookieOpts.Name)) | ||||||
| 				} else { | 				} else { | ||||||
| 					for _, cookie := range cookies { | 					for _, cookie := range cookies { | ||||||
| 						Expect(cookie.Name).To(ContainSubstring(cookieOpts.CookieName)) | 						Expect(cookie.Name).To(ContainSubstring(cookieOpts.Name)) | ||||||
| 					} | 					} | ||||||
| 				} | 				} | ||||||
| 			}) | 			}) | ||||||
| 
 | 
 | ||||||
| 			It("have the correct path set", func() { | 			It("have the correct path set", func() { | ||||||
| 				for _, cookie := range cookies { | 				for _, cookie := range cookies { | ||||||
| 					Expect(cookie.Path).To(Equal(cookieOpts.CookiePath)) | 					Expect(cookie.Path).To(Equal(cookieOpts.Path)) | ||||||
| 				} | 				} | ||||||
| 			}) | 			}) | ||||||
| 
 | 
 | ||||||
| 			It("have the correct domain set", func() { | 			It("have the correct domain set", func() { | ||||||
| 				for _, cookie := range cookies { | 				for _, cookie := range cookies { | ||||||
| 					specifiedDomain := "" | 					specifiedDomain := "" | ||||||
| 					if len(cookieOpts.CookieDomains) > 0 { | 					if len(cookieOpts.Domains) > 0 { | ||||||
| 						specifiedDomain = cookieOpts.CookieDomains[0] | 						specifiedDomain = cookieOpts.Domains[0] | ||||||
| 					} | 					} | ||||||
| 					Expect(cookie.Domain).To(Equal(specifiedDomain)) | 					Expect(cookie.Domain).To(Equal(specifiedDomain)) | ||||||
| 				} | 				} | ||||||
|  | @ -73,19 +73,19 @@ var _ = Describe("NewSessionStore", func() { | ||||||
| 
 | 
 | ||||||
| 			It("have the correct HTTPOnly set", func() { | 			It("have the correct HTTPOnly set", func() { | ||||||
| 				for _, cookie := range cookies { | 				for _, cookie := range cookies { | ||||||
| 					Expect(cookie.HttpOnly).To(Equal(cookieOpts.CookieHTTPOnly)) | 					Expect(cookie.HttpOnly).To(Equal(cookieOpts.HTTPOnly)) | ||||||
| 				} | 				} | ||||||
| 			}) | 			}) | ||||||
| 
 | 
 | ||||||
| 			It("have the correct secure set", func() { | 			It("have the correct secure set", func() { | ||||||
| 				for _, cookie := range cookies { | 				for _, cookie := range cookies { | ||||||
| 					Expect(cookie.Secure).To(Equal(cookieOpts.CookieSecure)) | 					Expect(cookie.Secure).To(Equal(cookieOpts.Secure)) | ||||||
| 				} | 				} | ||||||
| 			}) | 			}) | ||||||
| 
 | 
 | ||||||
| 			It("have the correct SameSite set", func() { | 			It("have the correct SameSite set", func() { | ||||||
| 				for _, cookie := range cookies { | 				for _, cookie := range cookies { | ||||||
| 					Expect(cookie.SameSite).To(Equal(cookiesapi.ParseSameSite(cookieOpts.CookieSameSite))) | 					Expect(cookie.SameSite).To(Equal(cookiesapi.ParseSameSite(cookieOpts.SameSite))) | ||||||
| 				} | 				} | ||||||
| 			}) | 			}) | ||||||
| 
 | 
 | ||||||
|  | @ -168,8 +168,8 @@ var _ = Describe("NewSessionStore", func() { | ||||||
| 				BeforeEach(func() { | 				BeforeEach(func() { | ||||||
| 					By("Using a valid cookie with a different providers session encoding") | 					By("Using a valid cookie with a different providers session encoding") | ||||||
| 					broken := "BrokenSessionFromADifferentSessionImplementation" | 					broken := "BrokenSessionFromADifferentSessionImplementation" | ||||||
| 					value := encryption.SignedValue(cookieOpts.CookieSecret, cookieOpts.CookieName, broken, time.Now()) | 					value := encryption.SignedValue(cookieOpts.Secret, cookieOpts.Name, broken, time.Now()) | ||||||
| 					cookie := cookiesapi.MakeCookieFromOptions(request, cookieOpts.CookieName, value, cookieOpts, cookieOpts.CookieExpire, time.Now()) | 					cookie := cookiesapi.MakeCookieFromOptions(request, cookieOpts.Name, value, cookieOpts, cookieOpts.Expire, time.Now()) | ||||||
| 					request.AddCookie(cookie) | 					request.AddCookie(cookie) | ||||||
| 
 | 
 | ||||||
| 					err := ss.Save(response, request, session) | 					err := ss.Save(response, request, session) | ||||||
|  | @ -245,7 +245,7 @@ var _ = Describe("NewSessionStore", func() { | ||||||
| 				}) | 				}) | ||||||
| 
 | 
 | ||||||
| 				It("loads a session equal to the original session", func() { | 				It("loads a session equal to the original session", func() { | ||||||
| 					if cookieOpts.CookieSecret == "" { | 					if cookieOpts.Secret == "" { | ||||||
| 						// Only Email and User stored in session when encrypted
 | 						// Only Email and User stored in session when encrypted
 | ||||||
| 						Expect(loadedSession.Email).To(Equal(session.Email)) | 						Expect(loadedSession.Email).To(Equal(session.Email)) | ||||||
| 						Expect(loadedSession.User).To(Equal(session.User)) | 						Expect(loadedSession.User).To(Equal(session.User)) | ||||||
|  | @ -290,7 +290,7 @@ var _ = Describe("NewSessionStore", func() { | ||||||
| 					BeforeEach(func() { | 					BeforeEach(func() { | ||||||
| 						switch ss.(type) { | 						switch ss.(type) { | ||||||
| 						case *redis.SessionStore: | 						case *redis.SessionStore: | ||||||
| 							mr.FastForward(cookieOpts.CookieRefresh + time.Minute) | 							mr.FastForward(cookieOpts.Refresh + time.Minute) | ||||||
| 						} | 						} | ||||||
| 					}) | 					}) | ||||||
| 
 | 
 | ||||||
|  | @ -304,7 +304,7 @@ var _ = Describe("NewSessionStore", func() { | ||||||
| 					BeforeEach(func() { | 					BeforeEach(func() { | ||||||
| 						switch ss.(type) { | 						switch ss.(type) { | ||||||
| 						case *redis.SessionStore: | 						case *redis.SessionStore: | ||||||
| 							mr.FastForward(cookieOpts.CookieExpire + time.Minute) | 							mr.FastForward(cookieOpts.Expire + time.Minute) | ||||||
| 						} | 						} | ||||||
| 
 | 
 | ||||||
| 						loadedSession, err = ss.Load(request) | 						loadedSession, err = ss.Load(request) | ||||||
|  | @ -341,14 +341,14 @@ var _ = Describe("NewSessionStore", func() { | ||||||
| 		Context("with non-default options", func() { | 		Context("with non-default options", func() { | ||||||
| 			BeforeEach(func() { | 			BeforeEach(func() { | ||||||
| 				cookieOpts = &options.CookieOptions{ | 				cookieOpts = &options.CookieOptions{ | ||||||
| 					CookieName:     "_cookie_name", | 					Name:     "_cookie_name", | ||||||
| 					CookiePath:     "/path", | 					Path:     "/path", | ||||||
| 					CookieExpire:   time.Duration(72) * time.Hour, | 					Expire:   time.Duration(72) * time.Hour, | ||||||
| 					CookieRefresh:  time.Duration(2) * time.Hour, | 					Refresh:  time.Duration(2) * time.Hour, | ||||||
| 					CookieSecure:   false, | 					Secure:   false, | ||||||
| 					CookieHTTPOnly: false, | 					HTTPOnly: false, | ||||||
| 					CookieDomains:  []string{"example.com"}, | 					Domains:  []string{"example.com"}, | ||||||
| 					CookieSameSite: "strict", | 					SameSite: "strict", | ||||||
| 				} | 				} | ||||||
| 
 | 
 | ||||||
| 				var err error | 				var err error | ||||||
|  | @ -364,8 +364,8 @@ var _ = Describe("NewSessionStore", func() { | ||||||
| 				secret := make([]byte, 32) | 				secret := make([]byte, 32) | ||||||
| 				_, err := rand.Read(secret) | 				_, err := rand.Read(secret) | ||||||
| 				Expect(err).ToNot(HaveOccurred()) | 				Expect(err).ToNot(HaveOccurred()) | ||||||
| 				cookieOpts.CookieSecret = base64.URLEncoding.EncodeToString(secret) | 				cookieOpts.Secret = base64.URLEncoding.EncodeToString(secret) | ||||||
| 				cipher, err := encryption.NewCipher(utils.SecretBytes(cookieOpts.CookieSecret)) | 				cipher, err := encryption.NewCipher(utils.SecretBytes(cookieOpts.Secret)) | ||||||
| 				Expect(err).ToNot(HaveOccurred()) | 				Expect(err).ToNot(HaveOccurred()) | ||||||
| 				Expect(cipher).ToNot(BeNil()) | 				Expect(cipher).ToNot(BeNil()) | ||||||
| 				opts.Cipher = cipher | 				opts.Cipher = cipher | ||||||
|  | @ -384,13 +384,13 @@ var _ = Describe("NewSessionStore", func() { | ||||||
| 
 | 
 | ||||||
| 		// Set default options in CookieOptions
 | 		// Set default options in CookieOptions
 | ||||||
| 		cookieOpts = &options.CookieOptions{ | 		cookieOpts = &options.CookieOptions{ | ||||||
| 			CookieName:     "_oauth2_proxy", | 			Name:     "_oauth2_proxy", | ||||||
| 			CookiePath:     "/", | 			Path:     "/", | ||||||
| 			CookieExpire:   time.Duration(168) * time.Hour, | 			Expire:   time.Duration(168) * time.Hour, | ||||||
| 			CookieRefresh:  time.Duration(1) * time.Hour, | 			Refresh:  time.Duration(1) * time.Hour, | ||||||
| 			CookieSecure:   true, | 			Secure:   true, | ||||||
| 			CookieHTTPOnly: true, | 			HTTPOnly: true, | ||||||
| 			CookieSameSite: "", | 			SameSite: "", | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		session = &sessionsapi.SessionState{ | 		session = &sessionsapi.SessionState{ | ||||||
|  | @ -428,7 +428,7 @@ var _ = Describe("NewSessionStore", func() { | ||||||
| 			mr, err = miniredis.Run() | 			mr, err = miniredis.Run() | ||||||
| 			Expect(err).ToNot(HaveOccurred()) | 			Expect(err).ToNot(HaveOccurred()) | ||||||
| 			opts.Type = options.RedisSessionStoreType | 			opts.Type = options.RedisSessionStoreType | ||||||
| 			opts.RedisConnectionURL = "redis://" + mr.Addr() | 			opts.Redis.ConnectionURL = "redis://" + mr.Addr() | ||||||
| 		}) | 		}) | ||||||
| 
 | 
 | ||||||
| 		AfterEach(func() { | 		AfterEach(func() { | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue