github.com/pusher/oauth2_proxy@v3.2.0+incompatible/options_test.go (about) 1 package main 2 3 import ( 4 "crypto" 5 "fmt" 6 "net/url" 7 "strings" 8 "testing" 9 "time" 10 11 "github.com/stretchr/testify/assert" 12 ) 13 14 func testOptions() *Options { 15 o := NewOptions() 16 o.Upstreams = append(o.Upstreams, "http://127.0.0.1:8080/") 17 o.CookieSecret = "foobar" 18 o.ClientID = "bazquux" 19 o.ClientSecret = "xyzzyplugh" 20 o.EmailDomains = []string{"*"} 21 return o 22 } 23 24 func errorMsg(msgs []string) string { 25 result := make([]string, 0) 26 result = append(result, "Invalid configuration:") 27 result = append(result, msgs...) 28 return strings.Join(result, "\n ") 29 } 30 31 func TestNewOptions(t *testing.T) { 32 o := NewOptions() 33 o.EmailDomains = []string{"*"} 34 err := o.Validate() 35 assert.NotEqual(t, nil, err) 36 37 expected := errorMsg([]string{ 38 "missing setting: cookie-secret", 39 "missing setting: client-id", 40 "missing setting: client-secret"}) 41 assert.Equal(t, expected, err.Error()) 42 } 43 44 func TestGoogleGroupOptions(t *testing.T) { 45 o := testOptions() 46 o.GoogleGroups = []string{"googlegroup"} 47 err := o.Validate() 48 assert.NotEqual(t, nil, err) 49 50 expected := errorMsg([]string{ 51 "missing setting: google-admin-email", 52 "missing setting: google-service-account-json"}) 53 assert.Equal(t, expected, err.Error()) 54 } 55 56 func TestGoogleGroupInvalidFile(t *testing.T) { 57 o := testOptions() 58 o.GoogleGroups = []string{"test_group"} 59 o.GoogleAdminEmail = "admin@example.com" 60 o.GoogleServiceAccountJSON = "file_doesnt_exist.json" 61 err := o.Validate() 62 assert.NotEqual(t, nil, err) 63 64 expected := errorMsg([]string{ 65 "invalid Google credentials file: file_doesnt_exist.json", 66 }) 67 assert.Equal(t, expected, err.Error()) 68 } 69 70 func TestInitializedOptions(t *testing.T) { 71 o := testOptions() 72 assert.Equal(t, nil, o.Validate()) 73 } 74 75 // Note that it's not worth testing nonparseable URLs, since url.Parse() 76 // seems to parse damn near anything. 77 func TestRedirectURL(t *testing.T) { 78 o := testOptions() 79 o.RedirectURL = "https://myhost.com/oauth2/callback" 80 assert.Equal(t, nil, o.Validate()) 81 expected := &url.URL{ 82 Scheme: "https", Host: "myhost.com", Path: "/oauth2/callback"} 83 assert.Equal(t, expected, o.redirectURL) 84 } 85 86 func TestProxyURLs(t *testing.T) { 87 o := testOptions() 88 o.Upstreams = append(o.Upstreams, "http://127.0.0.1:8081") 89 assert.Equal(t, nil, o.Validate()) 90 expected := []*url.URL{ 91 {Scheme: "http", Host: "127.0.0.1:8080", Path: "/"}, 92 // note the '/' was added 93 {Scheme: "http", Host: "127.0.0.1:8081", Path: "/"}, 94 } 95 assert.Equal(t, expected, o.proxyURLs) 96 } 97 98 func TestProxyURLsError(t *testing.T) { 99 o := testOptions() 100 o.Upstreams = append(o.Upstreams, "127.0.0.1:8081") 101 err := o.Validate() 102 assert.NotEqual(t, nil, err) 103 104 expected := errorMsg([]string{ 105 "error parsing upstream: parse 127.0.0.1:8081: " + 106 "first path segment in URL cannot contain colon"}) 107 assert.Equal(t, expected, err.Error()) 108 } 109 110 func TestCompiledRegex(t *testing.T) { 111 o := testOptions() 112 regexps := []string{"/foo/.*", "/ba[rz]/quux"} 113 o.SkipAuthRegex = regexps 114 assert.Equal(t, nil, o.Validate()) 115 actual := make([]string, 0) 116 for _, regex := range o.CompiledRegex { 117 actual = append(actual, regex.String()) 118 } 119 assert.Equal(t, regexps, actual) 120 } 121 122 func TestCompiledRegexError(t *testing.T) { 123 o := testOptions() 124 o.SkipAuthRegex = []string{"(foobaz", "barquux)"} 125 err := o.Validate() 126 assert.NotEqual(t, nil, err) 127 128 expected := errorMsg([]string{ 129 "error compiling regex=\"(foobaz\" error parsing regexp: " + 130 "missing closing ): `(foobaz`", 131 "error compiling regex=\"barquux)\" error parsing regexp: " + 132 "unexpected ): `barquux)`"}) 133 assert.Equal(t, expected, err.Error()) 134 135 o.SkipAuthRegex = []string{"foobaz", "barquux)"} 136 err = o.Validate() 137 assert.NotEqual(t, nil, err) 138 139 expected = errorMsg([]string{ 140 "error compiling regex=\"barquux)\" error parsing regexp: " + 141 "unexpected ): `barquux)`"}) 142 assert.Equal(t, expected, err.Error()) 143 } 144 145 func TestDefaultProviderApiSettings(t *testing.T) { 146 o := testOptions() 147 assert.Equal(t, nil, o.Validate()) 148 p := o.provider.Data() 149 assert.Equal(t, "https://accounts.google.com/o/oauth2/auth?access_type=offline", 150 p.LoginURL.String()) 151 assert.Equal(t, "https://www.googleapis.com/oauth2/v3/token", 152 p.RedeemURL.String()) 153 assert.Equal(t, "", p.ProfileURL.String()) 154 assert.Equal(t, "profile email", p.Scope) 155 } 156 157 func TestPassAccessTokenRequiresSpecificCookieSecretLengths(t *testing.T) { 158 o := testOptions() 159 assert.Equal(t, nil, o.Validate()) 160 161 assert.Equal(t, false, o.PassAccessToken) 162 o.PassAccessToken = true 163 o.CookieSecret = "cookie of invalid length-" 164 assert.NotEqual(t, nil, o.Validate()) 165 166 o.PassAccessToken = false 167 o.CookieRefresh = time.Duration(24) * time.Hour 168 assert.NotEqual(t, nil, o.Validate()) 169 170 o.CookieSecret = "16 bytes AES-128" 171 assert.Equal(t, nil, o.Validate()) 172 173 o.CookieSecret = "24 byte secret AES-192--" 174 assert.Equal(t, nil, o.Validate()) 175 176 o.CookieSecret = "32 byte secret for AES-256------" 177 assert.Equal(t, nil, o.Validate()) 178 } 179 180 func TestCookieRefreshMustBeLessThanCookieExpire(t *testing.T) { 181 o := testOptions() 182 assert.Equal(t, nil, o.Validate()) 183 184 o.CookieSecret = "0123456789abcdefabcd" 185 o.CookieRefresh = o.CookieExpire 186 assert.NotEqual(t, nil, o.Validate()) 187 188 o.CookieRefresh -= time.Duration(1) 189 assert.Equal(t, nil, o.Validate()) 190 } 191 192 func TestBase64CookieSecret(t *testing.T) { 193 o := testOptions() 194 assert.Equal(t, nil, o.Validate()) 195 196 // 32 byte, base64 (urlsafe) encoded key 197 o.CookieSecret = "yHBw2lh2Cvo6aI_jn_qMTr-pRAjtq0nzVgDJNb36jgQ=" 198 assert.Equal(t, nil, o.Validate()) 199 200 // 32 byte, base64 (urlsafe) encoded key, w/o padding 201 o.CookieSecret = "yHBw2lh2Cvo6aI_jn_qMTr-pRAjtq0nzVgDJNb36jgQ" 202 assert.Equal(t, nil, o.Validate()) 203 204 // 24 byte, base64 (urlsafe) encoded key 205 o.CookieSecret = "Kp33Gj-GQmYtz4zZUyUDdqQKx5_Hgkv3" 206 assert.Equal(t, nil, o.Validate()) 207 208 // 16 byte, base64 (urlsafe) encoded key 209 o.CookieSecret = "LFEqZYvYUwKwzn0tEuTpLA==" 210 assert.Equal(t, nil, o.Validate()) 211 212 // 16 byte, base64 (urlsafe) encoded key, w/o padding 213 o.CookieSecret = "LFEqZYvYUwKwzn0tEuTpLA" 214 assert.Equal(t, nil, o.Validate()) 215 } 216 217 func TestValidateSignatureKey(t *testing.T) { 218 o := testOptions() 219 o.SignatureKey = "sha1:secret" 220 assert.Equal(t, nil, o.Validate()) 221 assert.Equal(t, o.signatureData.hash, crypto.SHA1) 222 assert.Equal(t, o.signatureData.key, "secret") 223 } 224 225 func TestValidateSignatureKeyInvalidSpec(t *testing.T) { 226 o := testOptions() 227 o.SignatureKey = "invalid spec" 228 err := o.Validate() 229 assert.Equal(t, err.Error(), "Invalid configuration:\n"+ 230 " invalid signature hash:key spec: "+o.SignatureKey) 231 } 232 233 func TestValidateSignatureKeyUnsupportedAlgorithm(t *testing.T) { 234 o := testOptions() 235 o.SignatureKey = "unsupported:default secret" 236 err := o.Validate() 237 assert.Equal(t, err.Error(), "Invalid configuration:\n"+ 238 " unsupported signature hash algorithm: "+o.SignatureKey) 239 } 240 241 func TestValidateCookie(t *testing.T) { 242 o := testOptions() 243 o.CookieName = "_valid_cookie_name" 244 assert.Equal(t, nil, o.Validate()) 245 } 246 247 func TestValidateCookieBadName(t *testing.T) { 248 o := testOptions() 249 o.CookieName = "_bad_cookie_name{}" 250 err := o.Validate() 251 assert.Equal(t, err.Error(), "Invalid configuration:\n"+ 252 fmt.Sprintf(" invalid cookie name: %q", o.CookieName)) 253 } 254 255 func TestSkipOIDCDiscovery(t *testing.T) { 256 o := testOptions() 257 o.Provider = "oidc" 258 o.OIDCIssuerURL = "https://login.microsoftonline.com/fabrikamb2c.onmicrosoft.com/v2.0/" 259 o.SkipOIDCDiscovery = true 260 261 err := o.Validate() 262 assert.Equal(t, "Invalid configuration:\n"+ 263 fmt.Sprintf(" missing setting: login-url\n missing setting: redeem-url\n missing setting: oidc-jwks-url"), err.Error()) 264 265 o.LoginURL = "https://login.microsoftonline.com/fabrikamb2c.onmicrosoft.com/oauth2/v2.0/authorize?p=b2c_1_sign_in" 266 o.RedeemURL = "https://login.microsoftonline.com/fabrikamb2c.onmicrosoft.com/oauth2/v2.0/token?p=b2c_1_sign_in" 267 o.OIDCJwksURL = "https://login.microsoftonline.com/fabrikamb2c.onmicrosoft.com/discovery/v2.0/keys" 268 269 assert.Equal(t, nil, o.Validate()) 270 } 271 272 func TestGCPHealthcheck(t *testing.T) { 273 o := testOptions() 274 o.GCPHealthChecks = true 275 assert.Equal(t, nil, o.Validate()) 276 }