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  }