mirror of https://github.com/dexidp/dex.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
464 lines
9.8 KiB
464 lines
9.8 KiB
package integration |
|
|
|
import ( |
|
"encoding/base64" |
|
"fmt" |
|
"net/http" |
|
"net/http/httptest" |
|
"net/url" |
|
"testing" |
|
|
|
"github.com/coreos/go-oidc/oidc" |
|
"github.com/kylelemons/godebug/pretty" |
|
"google.golang.org/api/googleapi" |
|
|
|
"github.com/coreos/dex/admin" |
|
"github.com/coreos/dex/client" |
|
"github.com/coreos/dex/db" |
|
"github.com/coreos/dex/schema/adminschema" |
|
"github.com/coreos/dex/server" |
|
"github.com/coreos/dex/user" |
|
) |
|
|
|
const ( |
|
adminAPITestSecret = "admin_secret" |
|
) |
|
|
|
type adminAPITestFixtures struct { |
|
ur user.UserRepo |
|
pwr user.PasswordInfoRepo |
|
cr client.ClientRepo |
|
adAPI *admin.AdminAPI |
|
adSrv *server.AdminServer |
|
hSrv *httptest.Server |
|
hc *http.Client |
|
adClient *adminschema.Service |
|
} |
|
|
|
func (t *adminAPITestFixtures) close() { |
|
t.hSrv.Close() |
|
} |
|
|
|
var ( |
|
adminUsers = []user.UserWithRemoteIdentities{ |
|
{ |
|
User: user.User{ |
|
ID: "ID-1", |
|
Email: "Email-1@example.com", |
|
}, |
|
}, |
|
{ |
|
User: user.User{ |
|
ID: "ID-2", |
|
Email: "Email-2@example.com", |
|
}, |
|
}, |
|
{ |
|
User: user.User{ |
|
ID: "ID-3", |
|
Email: "Email-3@example.com", |
|
}, |
|
}, |
|
} |
|
|
|
adminPasswords = []user.PasswordInfo{ |
|
{ |
|
UserID: "ID-1", |
|
Password: []byte("hi."), |
|
}, |
|
} |
|
) |
|
|
|
type adminAPITransport struct { |
|
secret string |
|
} |
|
|
|
func (a *adminAPITransport) RoundTrip(r *http.Request) (*http.Response, error) { |
|
r.Header.Set("Authorization", a.secret) |
|
return http.DefaultTransport.RoundTrip(r) |
|
} |
|
|
|
func makeAdminAPITestFixtures() *adminAPITestFixtures { |
|
f := &adminAPITestFixtures{} |
|
|
|
dbMap, ur, pwr, um := makeUserObjects(adminUsers, adminPasswords) |
|
|
|
var cliCount int |
|
secGen := func() ([]byte, error) { |
|
return []byte(fmt.Sprintf("client_%v", cliCount)), nil |
|
} |
|
cr := db.NewClientRepoWithSecretGenerator(dbMap, secGen) |
|
|
|
f.cr = cr |
|
f.ur = ur |
|
f.pwr = pwr |
|
f.adAPI = admin.NewAdminAPI(ur, pwr, cr, um, "local") |
|
f.adSrv = server.NewAdminServer(f.adAPI, nil, adminAPITestSecret) |
|
f.hSrv = httptest.NewServer(f.adSrv.HTTPHandler()) |
|
f.hc = &http.Client{ |
|
Transport: &adminAPITransport{ |
|
secret: adminAPITestSecret, |
|
}, |
|
} |
|
f.adClient, _ = adminschema.NewWithBasePath(f.hc, f.hSrv.URL) |
|
|
|
return f |
|
} |
|
|
|
func TestGetAdmin(t *testing.T) { |
|
|
|
tests := []struct { |
|
id string |
|
errCode int |
|
}{ |
|
{ |
|
id: "ID-1", |
|
errCode: -1, |
|
}, |
|
{ |
|
id: "ID-2", |
|
errCode: http.StatusNotFound, |
|
}, |
|
} |
|
|
|
for i, tt := range tests { |
|
func() { |
|
f := makeAdminAPITestFixtures() |
|
defer f.close() |
|
admn, err := f.adClient.Admin.Get(tt.id).Do() |
|
if tt.errCode != -1 { |
|
if err == nil { |
|
t.Errorf("case %d: err was nil", i) |
|
return |
|
} |
|
gErr, ok := err.(*googleapi.Error) |
|
if !ok { |
|
t.Errorf("case %d: not a googleapi Error: %q", i, err) |
|
return |
|
} |
|
|
|
if gErr.Code != tt.errCode { |
|
t.Errorf("case %d: want=%d, got=%d", i, tt.errCode, gErr.Code) |
|
return |
|
} |
|
} else { |
|
if err != nil { |
|
t.Errorf("case %d: err != nil: %q", i, err) |
|
} |
|
if admn == nil { |
|
t.Errorf("case %d: admn was nil", i) |
|
} |
|
|
|
if admn.Id != "ID-1" { |
|
t.Errorf("case %d: want=%q, got=%q", i, tt.id, admn.Id) |
|
} |
|
} |
|
}() |
|
} |
|
} |
|
|
|
func TestCreateAdmin(t *testing.T) { |
|
tests := []struct { |
|
admn *adminschema.Admin |
|
errCode int |
|
secret string |
|
noSecret bool |
|
}{ |
|
{ |
|
admn: &adminschema.Admin{ |
|
Email: "foo@example.com", |
|
Password: "foopass", |
|
}, |
|
errCode: -1, |
|
}, |
|
{ |
|
admn: &adminschema.Admin{ |
|
Email: "foo@example.com", |
|
Password: "foopass", |
|
}, |
|
errCode: http.StatusUnauthorized, |
|
secret: "bad_secret", |
|
}, |
|
{ |
|
admn: &adminschema.Admin{ |
|
Email: "foo@example.com", |
|
Password: "foopass", |
|
}, |
|
errCode: http.StatusUnauthorized, |
|
noSecret: true, |
|
}, |
|
{ |
|
// duplicate Email |
|
admn: &adminschema.Admin{ |
|
Email: "Email-1@example.com", |
|
Password: "foopass", |
|
}, |
|
errCode: http.StatusBadRequest, |
|
}, |
|
{ |
|
// missing Email |
|
admn: &adminschema.Admin{ |
|
Password: "foopass", |
|
}, |
|
errCode: http.StatusBadRequest, |
|
}, |
|
} |
|
for i, tt := range tests { |
|
func() { |
|
f := makeAdminAPITestFixtures() |
|
if tt.secret != "" { |
|
f.hc.Transport = &adminAPITransport{ |
|
secret: tt.secret, |
|
} |
|
} |
|
if tt.noSecret { |
|
f.hc.Transport = http.DefaultTransport |
|
} |
|
defer f.close() |
|
|
|
admn, err := f.adClient.Admin.Create(tt.admn).Do() |
|
if tt.errCode != -1 { |
|
if err == nil { |
|
t.Errorf("case %d: err was nil", i) |
|
return |
|
} |
|
gErr, ok := err.(*googleapi.Error) |
|
if !ok { |
|
t.Errorf("case %d: not a googleapi Error: %q", i, err) |
|
return |
|
} |
|
|
|
if gErr.Code != tt.errCode { |
|
t.Errorf("case %d: want=%d, got=%d", i, tt.errCode, gErr.Code) |
|
return |
|
} |
|
} else { |
|
if err != nil { |
|
t.Errorf("case %d: err != nil: %q", i, err) |
|
} |
|
|
|
tt.admn.Id = admn.Id |
|
if diff := pretty.Compare(tt.admn, admn); diff != "" { |
|
t.Errorf("case %d: Compare(want, got) = %v", i, diff) |
|
} |
|
|
|
gotAdmn, err := f.adClient.Admin.Get(admn.Id).Do() |
|
if err != nil { |
|
t.Errorf("case %d: err != nil: %q", i, err) |
|
} |
|
if diff := pretty.Compare(admn, gotAdmn); diff != "" { |
|
t.Errorf("case %d: Compare(want, got) = %v", i, diff) |
|
} |
|
|
|
usr, err := f.ur.GetByRemoteIdentity(nil, user.RemoteIdentity{ |
|
ConnectorID: "local", |
|
ID: tt.admn.Id, |
|
}) |
|
if err != nil { |
|
t.Errorf("case %d: err != nil: %q", i, err) |
|
} |
|
|
|
if usr.ID != tt.admn.Id { |
|
t.Errorf("case %d: want=%q, got=%q", i, tt.admn.Id, usr.ID) |
|
} |
|
|
|
} |
|
}() |
|
} |
|
} |
|
|
|
func TestCreateClient(t *testing.T) { |
|
oldGen := admin.ClientIDGenerator |
|
admin.ClientIDGenerator = func(hostport string) (string, error) { |
|
return fmt.Sprintf("client_%v", hostport), nil |
|
} |
|
defer func() { |
|
admin.ClientIDGenerator = oldGen |
|
}() |
|
|
|
mustParseURL := func(s string) *url.URL { |
|
u, err := url.Parse(s) |
|
if err != nil { |
|
t.Fatalf("couldn't parse URL: %v", err) |
|
} |
|
return u |
|
} |
|
addIDAndSecret := func(cli adminschema.Client) *adminschema.Client { |
|
cli.Id = "client_auth.example.com" |
|
cli.Secret = base64.URLEncoding.EncodeToString([]byte("client_0")) |
|
return &cli |
|
} |
|
|
|
adminClientGood := adminschema.Client{ |
|
RedirectURIs: []string{"https://auth.example.com/"}, |
|
} |
|
clientGood := client.Client{ |
|
Credentials: oidc.ClientCredentials{ |
|
ID: "client_auth.example.com", |
|
}, |
|
Metadata: oidc.ClientMetadata{ |
|
RedirectURIs: []url.URL{*mustParseURL("https://auth.example.com/")}, |
|
}, |
|
} |
|
|
|
adminAdminClient := adminClientGood |
|
adminAdminClient.IsAdmin = true |
|
clientGoodAdmin := clientGood |
|
clientGoodAdmin.Admin = true |
|
|
|
adminMultiRedirect := adminClientGood |
|
adminMultiRedirect.RedirectURIs = []string{"https://auth.example.com/", "https://auth2.example.com/"} |
|
clientMultiRedirect := clientGoodAdmin |
|
clientMultiRedirect.Metadata.RedirectURIs = append( |
|
clientMultiRedirect.Metadata.RedirectURIs, |
|
*mustParseURL("https://auth2.example.com/")) |
|
|
|
tests := []struct { |
|
req adminschema.ClientCreateRequest |
|
want adminschema.ClientCreateResponse |
|
wantClient client.Client |
|
wantError int |
|
}{ |
|
{ |
|
req: adminschema.ClientCreateRequest{}, |
|
wantError: http.StatusBadRequest, |
|
}, |
|
{ |
|
req: adminschema.ClientCreateRequest{ |
|
Client: &adminschema.Client{ |
|
IsAdmin: true, |
|
}, |
|
}, |
|
wantError: http.StatusBadRequest, |
|
}, |
|
{ |
|
req: adminschema.ClientCreateRequest{ |
|
Client: &adminschema.Client{ |
|
RedirectURIs: []string{"909090"}, |
|
}, |
|
}, |
|
wantError: http.StatusBadRequest, |
|
}, |
|
{ |
|
req: adminschema.ClientCreateRequest{ |
|
Client: &adminClientGood, |
|
}, |
|
want: adminschema.ClientCreateResponse{ |
|
Client: addIDAndSecret(adminClientGood), |
|
}, |
|
wantClient: clientGood, |
|
}, |
|
{ |
|
req: adminschema.ClientCreateRequest{ |
|
Client: &adminAdminClient, |
|
}, |
|
want: adminschema.ClientCreateResponse{ |
|
Client: addIDAndSecret(adminAdminClient), |
|
}, |
|
wantClient: clientGoodAdmin, |
|
}, |
|
{ |
|
req: adminschema.ClientCreateRequest{ |
|
Client: &adminMultiRedirect, |
|
}, |
|
want: adminschema.ClientCreateResponse{ |
|
Client: addIDAndSecret(adminMultiRedirect), |
|
}, |
|
wantClient: clientMultiRedirect, |
|
}, |
|
} |
|
|
|
for i, tt := range tests { |
|
if i != 3 { |
|
continue |
|
} |
|
f := makeAdminAPITestFixtures() |
|
|
|
resp, err := f.adClient.Client.Create(&tt.req).Do() |
|
if tt.wantError != 0 { |
|
if err == nil { |
|
t.Errorf("case %d: want non-nil error.", i) |
|
continue |
|
} |
|
|
|
aErr, ok := err.(*googleapi.Error) |
|
if !ok { |
|
t.Errorf("case %d: could not assert as adminSchema.Error: %v", i, err) |
|
continue |
|
} |
|
if aErr.Code != tt.wantError { |
|
t.Errorf("case %d: want aErr.Code=%v, got %v", i, tt.wantError, aErr.Code) |
|
continue |
|
} |
|
continue |
|
} |
|
|
|
if err != nil { |
|
t.Errorf("case %d: unexpected error creating client: %v", i, err) |
|
continue |
|
} |
|
|
|
if diff := pretty.Compare(tt.want, resp); diff != "" { |
|
t.Errorf("case %d: Compare(want, got) = %v", i, diff) |
|
} |
|
|
|
repoClient, err := f.cr.Get(resp.Client.Id) |
|
if err != nil { |
|
t.Errorf("case %d: Unexpected error getting client: %v", i, err) |
|
} |
|
|
|
if diff := pretty.Compare(tt.wantClient, repoClient); diff != "" { |
|
t.Errorf("case %d: Compare(wantClient, repoClient) = %v", i, diff) |
|
} |
|
} |
|
} |
|
|
|
func TestGetState(t *testing.T) { |
|
tests := []struct { |
|
addUsers []user.User |
|
want adminschema.State |
|
}{ |
|
{ |
|
addUsers: []user.User{ |
|
user.User{ |
|
ID: "ID-admin", |
|
Email: "Admin@example.com", |
|
Admin: true, |
|
}, |
|
}, |
|
want: adminschema.State{ |
|
AdminUserCreated: true, |
|
}, |
|
}, |
|
{ |
|
want: adminschema.State{ |
|
AdminUserCreated: false, |
|
}, |
|
}, |
|
} |
|
|
|
for i, tt := range tests { |
|
func() { |
|
f := makeAdminAPITestFixtures() |
|
defer f.close() |
|
|
|
for _, usr := range tt.addUsers { |
|
err := f.ur.Create(nil, usr) |
|
if err != nil { |
|
t.Fatalf("case %d: err != nil: %v", i, err) |
|
} |
|
} |
|
|
|
got, err := f.adClient.State.Get().Do() |
|
if err != nil { |
|
t.Errorf("case %d: err != nil: %q", i, err) |
|
} |
|
|
|
if diff := pretty.Compare(tt.want, got); diff != "" { |
|
t.Errorf("case %d: Compare(want, got) = %v", i, diff) |
|
} |
|
|
|
}() |
|
} |
|
|
|
}
|
|
|