func TestGroupAdder(t *testing.T) { adder := authenticator.Request( NewGroupAdder( authenticator.RequestFunc(func(req *http.Request) (user.Info, bool, error) { return &user.DefaultInfo{Name: "user", Groups: []string{"original"}}, true, nil }), []string{"added"}, ), ) user, _, _ := adder.AuthenticateRequest(nil) if !reflect.DeepEqual(user.GetGroups(), []string{"original", "added"}) { t.Errorf("Expected original,added groups, got %#v", user.GetGroups()) } }
func (impersonateAuthorizer) Authorize(a authorizer.Attributes) (authorized bool, reason string, err error) { user := a.GetUser() switch { case user.GetName() == "system:admin": return true, "", nil case user.GetName() == "tester": return false, "", fmt.Errorf("works on my machine") case user.GetName() == "deny-me": return false, "denied", nil } if len(user.GetGroups()) > 0 && user.GetGroups()[0] == "wheel" && a.GetVerb() == "impersonate" && a.GetResource() == "users" { return true, "", nil } if len(user.GetGroups()) > 0 && user.GetGroups()[0] == "sa-impersonater" && a.GetVerb() == "impersonate" && a.GetResource() == "serviceaccounts" { return true, "", nil } if len(user.GetGroups()) > 0 && user.GetGroups()[0] == "regular-impersonater" && a.GetVerb() == "impersonate" && a.GetResource() == "users" { return true, "", nil } if len(user.GetGroups()) > 1 && user.GetGroups()[1] == "group-impersonater" && a.GetVerb() == "impersonate" && a.GetResource() == "groups" { return true, "", nil } if len(user.GetGroups()) > 1 && user.GetGroups()[1] == "extra-setter-scopes" && a.GetVerb() == "impersonate" && a.GetResource() == "userextras" && a.GetSubresource() == "scopes" { return true, "", nil } if len(user.GetGroups()) > 1 && user.GetGroups()[1] == "extra-setter-particular-scopes" && a.GetVerb() == "impersonate" && a.GetResource() == "userextras" && a.GetSubresource() == "scopes" && a.GetName() == "scope-a" { return true, "", nil } if len(user.GetGroups()) > 1 && user.GetGroups()[1] == "extra-setter-project" && a.GetVerb() == "impersonate" && a.GetResource() == "userextras" && a.GetSubresource() == "project" { return true, "", nil } return false, "deny by default", nil }
func TestTLSConfig(t *testing.T) { // Verify the cert/key pair works. cert1 := path.Join(os.TempDir(), "oidc-cert-1") key1 := path.Join(os.TempDir(), "oidc-key-1") cert2 := path.Join(os.TempDir(), "oidc-cert-2") key2 := path.Join(os.TempDir(), "oidc-key-2") defer os.Remove(cert1) defer os.Remove(key1) defer os.Remove(cert2) defer os.Remove(key2) oidctesting.GenerateSelfSignedCert(t, "127.0.0.1", cert1, key1) oidctesting.GenerateSelfSignedCert(t, "127.0.0.1", cert2, key2) tests := []struct { testCase string serverCertFile string serverKeyFile string trustedCertFile string wantErr bool }{ { testCase: "provider using untrusted custom cert", serverCertFile: cert1, serverKeyFile: key1, wantErr: true, }, { testCase: "provider using untrusted cert", serverCertFile: cert1, serverKeyFile: key1, trustedCertFile: cert2, wantErr: true, }, { testCase: "provider using trusted cert", serverCertFile: cert1, serverKeyFile: key1, trustedCertFile: cert1, wantErr: false, }, } for _, tc := range tests { func() { op := oidctesting.NewOIDCProvider(t, "") srv, err := op.ServeTLSWithKeyPair(tc.serverCertFile, tc.serverKeyFile) if err != nil { t.Errorf("%s: %v", tc.testCase, err) return } defer srv.Close() issuer := srv.URL clientID := "client-foo" options := OIDCOptions{ IssuerURL: srv.URL, ClientID: clientID, CAFile: tc.trustedCertFile, UsernameClaim: "email", GroupsClaim: "groups", } authenticator, err := New(options) if err != nil { t.Errorf("%s: failed to initialize authenticator: %v", tc.testCase, err) return } defer authenticator.Close() email := "*****@*****.**" groups := []string{"group1", "group2"} sort.Strings(groups) token := generateGoodToken(t, op, issuer, "user-1", clientID, "email", email, "groups", groups) // Because this authenticator behaves differently for subsequent requests, run these // tests multiple times (but expect the same result). for i := 1; i < 4; i++ { user, ok, err := authenticator.AuthenticateToken(token) if err != nil { if !tc.wantErr { t.Errorf("%s (req #%d): failed to authenticate token: %v", tc.testCase, i, err) } continue } if tc.wantErr { t.Errorf("%s (req #%d): expected error authenticating", tc.testCase, i) continue } if !ok { t.Errorf("%s (req #%d): did not get user or error", tc.testCase, i) continue } if gotUsername := user.GetName(); email != gotUsername { t.Errorf("%s (req #%d): GetName() expected=%q got %q", tc.testCase, i, email, gotUsername) } gotGroups := user.GetGroups() sort.Strings(gotGroups) if !reflect.DeepEqual(gotGroups, groups) { t.Errorf("%s (req #%d): GetGroups() expected=%q got %q", tc.testCase, i, groups, gotGroups) } } }() } }
func TestX509(t *testing.T) { multilevelOpts := DefaultVerifyOptions() multilevelOpts.Roots = x509.NewCertPool() multilevelOpts.Roots.AddCert(getCertsFromFile(t, "root")[0]) testCases := map[string]struct { Insecure bool Certs []*x509.Certificate Opts x509.VerifyOptions User UserConversion ExpectUserName string ExpectGroups []string ExpectOK bool ExpectErr bool }{ "non-tls": { Insecure: true, ExpectOK: false, ExpectErr: false, }, "tls, no certs": { ExpectOK: false, ExpectErr: false, }, "self signed": { Opts: getDefaultVerifyOptions(t), Certs: getCerts(t, selfSignedCert), User: CommonNameUserConversion, ExpectErr: true, }, "server cert": { Opts: getDefaultVerifyOptions(t), Certs: getCerts(t, serverCert), User: CommonNameUserConversion, ExpectErr: true, }, "server cert allowing non-client cert usages": { Opts: x509.VerifyOptions{Roots: getRootCertPool(t)}, Certs: getCerts(t, serverCert), User: CommonNameUserConversion, ExpectUserName: "******", ExpectGroups: []string{"My Org"}, ExpectOK: true, ExpectErr: false, }, "common name": { Opts: getDefaultVerifyOptions(t), Certs: getCerts(t, clientCNCert), User: CommonNameUserConversion, ExpectUserName: "******", ExpectGroups: []string{"My Org"}, ExpectOK: true, ExpectErr: false, }, "ca with multiple organizations": { Opts: x509.VerifyOptions{ Roots: getRootCertPoolFor(t, caWithGroups), }, Certs: getCerts(t, caWithGroups), User: CommonNameUserConversion, ExpectUserName: "******", ExpectGroups: []string{"My Org", "My Org 1", "My Org 2"}, ExpectOK: true, ExpectErr: false, }, "empty dns": { Opts: getDefaultVerifyOptions(t), Certs: getCerts(t, clientCNCert), User: DNSNameUserConversion, ExpectOK: false, ExpectErr: false, }, "dns": { Opts: getDefaultVerifyOptions(t), Certs: getCerts(t, clientDNSCert), User: DNSNameUserConversion, ExpectUserName: "******", ExpectOK: true, ExpectErr: false, }, "empty email": { Opts: getDefaultVerifyOptions(t), Certs: getCerts(t, clientCNCert), User: EmailAddressUserConversion, ExpectOK: false, ExpectErr: false, }, "email": { Opts: getDefaultVerifyOptions(t), Certs: getCerts(t, clientEmailCert), User: EmailAddressUserConversion, ExpectUserName: "******", ExpectOK: true, ExpectErr: false, }, "custom conversion error": { Opts: getDefaultVerifyOptions(t), Certs: getCerts(t, clientCNCert), User: UserConversionFunc(func(chain []*x509.Certificate) (user.Info, bool, error) { return nil, false, errors.New("custom error") }), ExpectOK: false, ExpectErr: true, }, "custom conversion success": { Opts: getDefaultVerifyOptions(t), Certs: getCerts(t, clientCNCert), User: UserConversionFunc(func(chain []*x509.Certificate) (user.Info, bool, error) { return &user.DefaultInfo{Name: "custom"}, true, nil }), ExpectUserName: "******", ExpectOK: true, ExpectErr: false, }, "future cert": { Opts: x509.VerifyOptions{ CurrentTime: time.Now().Add(time.Duration(-100 * time.Hour * 24 * 365)), Roots: getRootCertPool(t), }, Certs: getCerts(t, clientCNCert), User: CommonNameUserConversion, ExpectOK: false, ExpectErr: true, }, "expired cert": { Opts: x509.VerifyOptions{ CurrentTime: time.Now().Add(time.Duration(100 * time.Hour * 24 * 365)), Roots: getRootCertPool(t), }, Certs: getCerts(t, clientCNCert), User: CommonNameUserConversion, ExpectOK: false, ExpectErr: true, }, "multi-level, valid": { Opts: multilevelOpts, Certs: getCertsFromFile(t, "client-valid", "intermediate"), User: CommonNameUserConversion, ExpectUserName: "******", ExpectOK: true, ExpectErr: false, }, "multi-level, expired": { Opts: multilevelOpts, Certs: getCertsFromFile(t, "client-expired", "intermediate"), User: CommonNameUserConversion, ExpectOK: false, ExpectErr: true, }, } for k, testCase := range testCases { req, _ := http.NewRequest("GET", "/", nil) if !testCase.Insecure { req.TLS = &tls.ConnectionState{PeerCertificates: testCase.Certs} } a := New(testCase.Opts, testCase.User) user, ok, err := a.AuthenticateRequest(req) if testCase.ExpectErr && err == nil { t.Errorf("%s: Expected error, got none", k) continue } if !testCase.ExpectErr && err != nil { t.Errorf("%s: Got unexpected error: %v", k, err) continue } if testCase.ExpectOK != ok { t.Errorf("%s: Expected ok=%v, got %v", k, testCase.ExpectOK, ok) continue } if testCase.ExpectOK { if testCase.ExpectUserName != user.GetName() { t.Errorf("%s: Expected user.name=%v, got %v", k, testCase.ExpectUserName, user.GetName()) } groups := user.GetGroups() sort.Strings(testCase.ExpectGroups) sort.Strings(groups) if !reflect.DeepEqual(testCase.ExpectGroups, groups) { t.Errorf("%s: Expected user.groups=%v, got %v", k, testCase.ExpectGroups, groups) } } } }