package service import ( "fmt" "testing" "github.com/DATA-DOG/go-sqlmock" "github.com/google/uuid" "github.com/paralus/paralus/pkg/audit" "go.uber.org/zap" ) func getLogger() *zap.Logger { ao := audit.AuditOptions{ LogPath: "/dev/stdout", MaxSizeMB: 1, MaxBackups: 10, // Should we let sidecar do rotation? MaxAgeDays: 10, // Make these configurable via env } return audit.GetAuditLogger(&ao) } func performBasicAuthzChecks(t *testing.T, mazc mockAuthzClient, cpCount, dpCount, cugCount, dugCount, crpmCount, drpmCount int) { if len(mazc.cp) != cpCount { t.Errorf("unexpected number of calls to Authz CreatePolicies; expctex '%v', got '%v'", cpCount, len(mazc.cp)) } if len(mazc.dp) != dpCount { t.Errorf("unexpected number of calls to Authz DeletePolicies; expctex '%v', got '%v'", dpCount, len(mazc.dp)) } if len(mazc.cug) != cugCount { t.Errorf("unexpected number of calls to Authz CreateUserGroups; expctex '%v', got '%v'", cugCount, len(mazc.cug)) } if len(mazc.dug) != dugCount { t.Errorf("unexpected number of calls to Authz DeleteUserGroups; expctex '%v', got '%v'", dugCount, len(mazc.dug)) } if len(mazc.crpm) != crpmCount { t.Errorf("unexpected number of calls to Authz CreateRolePermissionMapping; expctex '%v', got '%v'", crpmCount, len(mazc.crpm)) } if len(mazc.drpm) != drpmCount { t.Errorf("unexpected number of calls to Authz DeleteRolePermissionMapping; expctex '%v', got '%v'", drpmCount, len(mazc.drpm)) } } func performBasicAuthProviderChecks(t *testing.T, ma mockAuthProvider, cCount, uCount, rCount, dCount int) { if len(ma.c) != cCount { t.Errorf("unexpected number of calls to Auth Provider Create; expctex '%v', got '%v'", cCount, len(ma.c)) } if len(ma.u) != uCount { t.Errorf("unexpected number of calls to Auth Provider Update; expctex '%v', got '%v'", uCount, len(ma.u)) } if len(ma.r) != rCount { t.Errorf("unexpected number of calls to Auth Provider GetRecoveryLink; expctex '%v', got '%v'", rCount, len(ma.r)) } if len(ma.d) != dCount { t.Errorf("unexpected number of calls to Auth Provider Delete; expctex '%v', got '%v'", dCount, len(ma.d)) } } func idname(uid string, resource string) string { return resource + "-" + uid } func idnamea(uid string, resource string) *string { name := resource + "-" + uid return &name } func addFetchEmptyExpecteation(mock sqlmock.Sqlmock, resource string) { mock.ExpectQuery(`SELECT "` + resource + `"."id" FROM "authsrv_` + resource + `" AS "` + resource + `"`). WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id"})) } func addFailingFetchExpecteation(mock sqlmock.Sqlmock, resource string) { mock.ExpectQuery(`SELECT "` + resource + `"."id" FROM "authsrv_` + resource + `" AS "` + resource + `"`). WithArgs().WillReturnError(fmt.Errorf("no data available")) } func addFetchIdExpectation(mock sqlmock.Sqlmock, resource string) string { uid := uuid.New().String() mock.ExpectQuery(`SELECT "` + resource + `"."id" FROM "authsrv_` + resource + `" AS "` + resource + `"`). WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(uid)) return uid } func addFetchByIdExpectation(mock sqlmock.Sqlmock, resource, uid string) { mock.ExpectQuery(`SELECT "` + resource + `"."id".* FROM "authsrv_` + resource + `" AS "` + resource + `" WHERE .id = '` + uid + `'.`). WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id", "name"}).AddRow(uid, resource+"-"+uid)) } func addFetchIdByNameExpectation(mock sqlmock.Sqlmock, resource, name string) string { uid := uuid.NewString() mock.ExpectQuery(`SELECT "` + resource + `"."id" FROM "authsrv_` + resource + `" AS "` + resource + `" WHERE .name = '` + name + `'.`). WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(uid)) return uid } func addFetchExpectation(mock sqlmock.Sqlmock, resource string) string { uid := uuid.New().String() mock.ExpectQuery(`SELECT "` + resource + `"."id".* FROM "authsrv_` + resource + `" AS "` + resource + `"`). WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id", "name"}).AddRow(uid, resource+"-name")) return uid } func addFetchByNameExpectation(mock sqlmock.Sqlmock, resource string, uid string) { mock.ExpectQuery(`SELECT "` + resource + `"."id", "` + resource + `"."name", .* FROM "authsrv_` + resource + `" AS "` + resource + `" WHERE .*name = '` + resource + `-` + uid + `'`). WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id", "name"}).AddRow(uid, resource+"-"+uid)) } func addDeleteExpectation(mock sqlmock.Sqlmock, resource string, uid string) { mock.ExpectExec(`UPDATE "authsrv_` + resource + `" AS "` + resource + `" SET trash = TRUE WHERE .id = '` + uid). WillReturnResult(sqlmock.NewResult(1, 1)) } func addUnavailableExpectation(mock sqlmock.Sqlmock, resource, partner, org, uid string) { mock.ExpectQuery(`SELECT "` + resource + `"."id" FROM "authsrv_` + resource + `" AS "` + resource + `" WHERE .organization_id = '` + org + `'. AND .partner_id = '` + partner + `'. AND .name = '` + resource + `-` + uid + `'.`). WillReturnError(fmt.Errorf("no data available")) } func addParterOrgFetchExpectation(mock sqlmock.Sqlmock) (string, string) { pid := uuid.New().String() oid := uuid.New().String() mock.ExpectQuery(`SELECT "partner"."id" FROM "authsrv_partner" AS "partner"`). WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(pid)) mock.ExpectQuery(`SELECT "organization"."id" FROM "authsrv_organization" AS "organization"`). WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(oid)) return pid, oid } func addOrgParterFetchExpectation(mock sqlmock.Sqlmock) (string, string) { pid := uuid.New().String() oid := uuid.New().String() mock.ExpectQuery(`SELECT "organization"."id" FROM "authsrv_organization" AS "organization"`). WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(oid)) mock.ExpectQuery(`SELECT "partner"."id" FROM "authsrv_partner" AS "partner"`). WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(pid)) return pid, oid } func addResourceRoleFetchExpectation(mock sqlmock.Sqlmock, scope string) string { uid := uuid.New().String() mock.ExpectQuery(`SELECT "resourcerole"."id".* FROM "authsrv_resourcerole" AS "resourcerole"`). WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id", "name", "scope"}).AddRow(uid, "role-"+uid, scope)) return uid } func addGroupUserMappingsUpdateExpectation(mock sqlmock.Sqlmock, group string) { mock.ExpectQuery(`UPDATE "authsrv_groupaccount" AS "groupaccount" SET trash = TRUE WHERE ."group_id" = '` + group + `'. AND .trash = false. RETURNING *`). WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(uuid.New().String())) } func addUserGroupMappingsUpdateExpectation(mock sqlmock.Sqlmock, account string) { mock.ExpectQuery(`UPDATE "authsrv_groupaccount" AS "groupaccount" SET trash = TRUE WHERE ."account_id" = '` + account + `'. AND .trash = false. RETURNING *`). WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(uuid.New().String())) } func addUserIdFetchExpectation(mock sqlmock.Sqlmock) string { uid := uuid.New().String() mock.ExpectQuery(`SELECT "identities"."id" FROM "identities" WHERE .*traits ->> 'email' = 'user-` + uid + `'`). WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id", "traits"}).AddRow(uid, []byte(`{"email":"user-`+uid+`", "first_name": "John", "last_name": "Doe", "description": "The OG user."}`))) return uid } func addUserFetchExpectation(mock sqlmock.Sqlmock) string { uid := uuid.New().String() mock.ExpectQuery(`SELECT "identities"."id".* FROM "identities" WHERE .*traits ->> 'email' = 'user-` + uid + `'`). WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id", "traits"}).AddRow(uid, []byte(`{"email":"user-`+uid+`", "first_name": "John", "last_name": "Doe", "description": "The OG user."}`))) return uid } func addUserFullFetchExpectation(mock sqlmock.Sqlmock) string { uid := uuid.New().String() mock.ExpectQuery(`SELECT "identities"."id", "identities"."schema_id", "identities"."traits", "identities"."created_at", "identities"."updated_at", "identities"."state", "identities"."state_changed_at", "identities"."nid", "identity_credential"."id" AS "identity_credential__id", "identity_credential"."identity_id" AS "identity_credential__identity_id", "identity_credential"."identity_credential_type_id" AS "identity_credential__identity_credential_type_id", "identity_credential__identity_credential_type"."id" AS "identity_credential__identity_credential_type__id", "identity_credential__identity_credential_type"."name" AS "identity_credential__identity_credential_type__name" FROM "identities" LEFT JOIN "identity_credentials" AS "identity_credential" ON ."identity_credential"."identity_id" = "identities"."id". LEFT JOIN "identity_credential_types" AS "identity_credential__identity_credential_type" ON ."identity_credential__identity_credential_type"."id" = "identity_credential"."identity_credential_type_id". WHERE .traits ->> 'email' = 'user-` + uid + `'.`). WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id", "traits", "identity_credential__identity_credential_type__name"}).AddRow(uid, []byte(`{"email":"user-`+uid+`", "first_name": "John", "last_name": "Doe", "description": "The OG user."}`), "password")) return uid } func addUserFullFetchExpectationWithIdpGroups(mock sqlmock.Sqlmock) string { uid := uuid.New().String() mock.ExpectQuery(`SELECT "identities"."id", "identities"."schema_id", "identities"."traits", "identities"."created_at", "identities"."updated_at", "identities"."state", "identities"."state_changed_at", "identities"."nid", "identity_credential"."id" AS "identity_credential__id", "identity_credential"."identity_id" AS "identity_credential__identity_id", "identity_credential"."identity_credential_type_id" AS "identity_credential__identity_credential_type_id", "identity_credential__identity_credential_type"."id" AS "identity_credential__identity_credential_type__id", "identity_credential__identity_credential_type"."name" AS "identity_credential__identity_credential_type__name" FROM "identities" LEFT JOIN "identity_credentials" AS "identity_credential" ON ."identity_credential"."identity_id" = "identities"."id". LEFT JOIN "identity_credential_types" AS "identity_credential__identity_credential_type" ON ."identity_credential__identity_credential_type"."id" = "identity_credential"."identity_credential_type_id". WHERE .traits ->> 'email' = 'user-` + uid + `'.`). WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id", "traits", "identity_credential__identity_credential_type__name"}).AddRow(uid, []byte(`{"email":"user-`+uid+`", "first_name": "John", "last_name": "Doe", "description": "The OG user.", "idp_group": "BigShot"}`), "password")) return uid } func addUsersGroupFetchExpectation(mock sqlmock.Sqlmock, user string) string { uid := uuid.New().String() mock.ExpectQuery(`SELECT "group"."id".* FROM "authsrv_group" AS "group" JOIN authsrv_groupaccount ON authsrv_groupaccount.group_id="group".id WHERE .authsrv_groupaccount.account_id = '` + user + `'`). WithArgs().WillReturnRows(sqlmock.NewRows([]string{"name"}). AddRow("group-" + uid)) return uid } func addUserRoleMappingsFetchExpectation(mock sqlmock.Sqlmock, user string, project string) { uid := uuid.New().String() mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role FROM "authsrv_accountresourcerole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_accountresourcerole.role_id WHERE .authsrv_accountresourcerole.account_id = '` + user + `'`). WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role"}).AddRow("role-" + uid)) mock.ExpectQuery(`SELECT distinct authsrv_resourcerole.name as role, authsrv_project.name as project FROM "authsrv_projectaccountresourcerole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_projectaccountresourcerole.role_id JOIN authsrv_project ON authsrv_project.id=authsrv_projectaccountresourcerole.project_id WHERE .authsrv_projectaccountresourcerole.account_id = '` + user + `'`). WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role", "project"}).AddRow("role-"+uid, "project-"+project)) mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role, authsrv_project.name as project, namespace FROM "authsrv_projectaccountnamespacerole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_projectaccountnamespacerole.role_id JOIN authsrv_project ON authsrv_project.id=authsrv_projectaccountnamespacerole.project_id WHERE .authsrv_projectaccountnamespacerole.account_id = '` + user + `'`). WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role", "project", "namespace"}).AddRow("role-"+uid, "project-"+project, "ns")) } func addUserRoleMappingsUpdateExpectation(mock sqlmock.Sqlmock, uuuid string) string { uid := uuid.New().String() mock.ExpectQuery(`UPDATE "authsrv_accountresourcerole" AS "accountresourcerole" SET trash = TRUE WHERE ."account_id" = '` + uuuid + `'. AND .trash = false. RETURNING *`). WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(uid)) mock.ExpectQuery(`UPDATE "authsrv_projectaccountresourcerole" AS "projectaccountresourcerole" SET trash = TRUE WHERE ."account_id" = '` + uuuid + `'. AND .trash = false. RETURNING *`). WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(uid)) mock.ExpectQuery(`UPDATE "authsrv_projectaccountnamespacerole" AS "projectaccountnamespacerole" SET trash = TRUE WHERE ."account_id" = '` + uuuid + `'. AND .trash = false. RETURNING *`). WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(uid)) return uid } func addGroupRoleMappingsFetchExpectation(mock sqlmock.Sqlmock, group string, project string) { uid := uuid.New().String() mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role, authsrv_group.name as group FROM "authsrv_grouprole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_grouprole.role_id JOIN authsrv_group ON authsrv_group.id=authsrv_grouprole.group_id WHERE`). WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role", "group"}).AddRow("role-"+uid, "group-"+group)) mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role, authsrv_project.name as project, authsrv_group.name as group FROM "authsrv_projectgrouprole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_projectgrouprole.role_id JOIN authsrv_project ON authsrv_project.id=authsrv_projectgrouprole.project_id JOIN authsrv_group ON authsrv_group.id=authsrv_projectgrouprole.group_id WHERE`). WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role", "project"}).AddRow("role-"+uid, "project-"+project)) mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role, authsrv_project.name as project, namespace, authsrv_group.name as group FROM "authsrv_projectgroupnamespacerole"`). WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role", "project", "namespace"}).AddRow("role-"+uid, "project-"+project, "ns")) } func addGroupRoleMappingsUpdateExpectation(mock sqlmock.Sqlmock, group string) string { uid := uuid.New().String() mock.ExpectQuery(`UPDATE "authsrv_grouprole" AS "grouprole" SET trash = TRUE WHERE ."group_id" = '` + group + `'. AND .trash = false. RETURNING *`). WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(uid)) mock.ExpectQuery(`UPDATE "authsrv_projectgrouprole" AS "projectgrouprole" SET trash = TRUE WHERE ."group_id" = '` + group + `'. AND .trash = false. RETURNING *`). WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(uid)) mock.ExpectQuery(`UPDATE "authsrv_projectgroupnamespacerole" AS "projectgroupnamespacerole" SET trash = TRUE WHERE ."group_id" = '` + group + `'. AND .trash = false. RETURNING *`). WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(uid)) return uid } func addSentryLookupExpectation(mock sqlmock.Sqlmock, users []string, partner, org string) { rows := sqlmock.NewRows([]string{"account_id"}) for _, u := range users { rows.AddRow(u) } mock.ExpectQuery(`SELECT DISTINCT account_id FROM "sentry_account_permission" AS "sap" WHERE .partner_id = '` + partner + `'. AND .organization_id = '` + org + `'`). WithArgs().WillReturnRows(rows) }