mirror of https://github.com/goharbor/harbor.git
430 lines
12 KiB
Go
430 lines
12 KiB
Go
// Copyright 2018 Project Harbor Authors
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
package ldap
|
|
|
|
import (
|
|
"github.com/stretchr/testify/assert"
|
|
// "fmt"
|
|
// "strings"
|
|
"os"
|
|
"testing"
|
|
|
|
"github.com/goharbor/harbor/src/common"
|
|
"github.com/goharbor/harbor/src/common/dao"
|
|
"github.com/goharbor/harbor/src/common/dao/project"
|
|
"github.com/goharbor/harbor/src/common/models"
|
|
"github.com/goharbor/harbor/src/common/utils/log"
|
|
"github.com/goharbor/harbor/src/common/utils/test"
|
|
"github.com/goharbor/harbor/src/core/api"
|
|
|
|
"github.com/goharbor/harbor/src/core/auth"
|
|
coreConfig "github.com/goharbor/harbor/src/core/config"
|
|
)
|
|
|
|
var ldapTestConfig = map[string]interface{}{
|
|
common.ExtEndpoint: "host01.com",
|
|
common.AUTHMode: "ldap_auth",
|
|
common.DatabaseType: "postgresql",
|
|
common.PostGreSQLHOST: "127.0.0.1",
|
|
common.PostGreSQLPort: 5432,
|
|
common.PostGreSQLUsername: "postgres",
|
|
common.PostGreSQLPassword: "root123",
|
|
common.PostGreSQLDatabase: "registry",
|
|
// config.SelfRegistration: true,
|
|
common.LDAPURL: "ldap://127.0.0.1",
|
|
common.LDAPSearchDN: "cn=admin,dc=example,dc=com",
|
|
common.LDAPSearchPwd: "admin",
|
|
common.LDAPBaseDN: "dc=example,dc=com",
|
|
common.LDAPUID: "uid",
|
|
common.LDAPFilter: "",
|
|
common.LDAPScope: 2,
|
|
common.LDAPTimeout: 30,
|
|
common.AdminInitialPassword: "password",
|
|
common.LDAPGroupSearchFilter: "objectclass=groupOfNames",
|
|
common.LDAPGroupBaseDN: "dc=example,dc=com",
|
|
common.LDAPGroupAttributeName: "cn",
|
|
common.LDAPGroupSearchScope: 2,
|
|
common.LDAPGroupAdminDn: "cn=harbor_users,ou=groups,dc=example,dc=com",
|
|
}
|
|
|
|
func TestMain(m *testing.M) {
|
|
test.InitDatabaseFromEnv()
|
|
coreConfig.InitWithSettings(ldapTestConfig)
|
|
|
|
secretKeyPath := "/tmp/secretkey"
|
|
_, err := test.GenerateKey(secretKeyPath)
|
|
if err != nil {
|
|
log.Errorf("failed to generate secret key: %v", err)
|
|
return
|
|
}
|
|
defer os.Remove(secretKeyPath)
|
|
|
|
if err := os.Setenv("KEY_PATH", secretKeyPath); err != nil {
|
|
log.Fatalf("failed to set env %s: %v", "KEY_PATH", err)
|
|
}
|
|
|
|
// Extract to test utils
|
|
initSqls := []string{
|
|
"insert into harbor_user (username, email, password, realname) values ('member_test_01', 'member_test_01@example.com', '123456', 'member_test_01')",
|
|
"insert into project (name, owner_id) values ('member_test_01', 1)",
|
|
"insert into project (name, owner_id) values ('member_test_02', 1)",
|
|
"insert into user_group (group_name, group_type, ldap_group_dn) values ('test_group_01', 1, 'CN=harbor_users,OU=sample,OU=vmware,DC=harbor,DC=com')",
|
|
"update project set owner_id = (select user_id from harbor_user where username = 'member_test_01') where name = 'member_test_01'",
|
|
"insert into project_member (project_id, entity_id, entity_type, role) values ( (select project_id from project where name = 'member_test_01') , (select user_id from harbor_user where username = 'member_test_01'), 'u', 1)",
|
|
"insert into project_member (project_id, entity_id, entity_type, role) values ( (select project_id from project where name = 'member_test_01') , (select id from user_group where group_name = 'test_group_01'), 'g', 1)",
|
|
}
|
|
|
|
clearSqls := []string{
|
|
"delete from project where name='member_test_01'",
|
|
"delete from project where name='member_test_02'",
|
|
"delete from harbor_user where username='member_test_01' or username='pm_sample'",
|
|
"delete from user_group",
|
|
"delete from project_member",
|
|
}
|
|
dao.ExecuteBatchSQL(initSqls)
|
|
defer dao.ExecuteBatchSQL(clearSqls)
|
|
retCode := m.Run()
|
|
os.Exit(retCode)
|
|
}
|
|
|
|
func TestAuthenticate(t *testing.T) {
|
|
var person models.AuthModel
|
|
var authHelper *Auth
|
|
person.Principal = "test"
|
|
person.Password = "123456"
|
|
user, err := authHelper.Authenticate(person)
|
|
if err != nil {
|
|
t.Errorf("unexpected ldap authenticate fail: %v", err)
|
|
}
|
|
if user.Username != "test" {
|
|
t.Errorf("unexpected ldap user authenticate fail: %s = %s", "user.Username", user.Username)
|
|
}
|
|
person.Principal = "test"
|
|
person.Password = "1"
|
|
user, err = authHelper.Authenticate(person)
|
|
|
|
if _, ok := err.(auth.ErrAuth); !ok {
|
|
t.Errorf("Expected an ErrAuth on wrong password, but got: %v", err)
|
|
}
|
|
person.Principal = ""
|
|
person.Password = ""
|
|
user, err = authHelper.Authenticate(person)
|
|
if _, ok := err.(auth.ErrAuth); !ok {
|
|
t.Errorf("Expected an ErrAuth on empty credentials, but got: %v", err)
|
|
}
|
|
// authenticate the second time
|
|
person2 := models.AuthModel{
|
|
Principal: "test",
|
|
Password: "123456",
|
|
}
|
|
user2, err := authHelper.Authenticate(person2)
|
|
|
|
if err != nil {
|
|
t.Errorf("unexpected ldap error: %v", err)
|
|
}
|
|
|
|
if user2 == nil {
|
|
t.Errorf("Can not login user with person2 %+v", person2)
|
|
}
|
|
}
|
|
|
|
func TestSearchUser(t *testing.T) {
|
|
var username = "test"
|
|
var auth *Auth
|
|
user, err := auth.SearchUser(username)
|
|
if err != nil {
|
|
t.Errorf("Search user failed %v", err)
|
|
}
|
|
if user == nil {
|
|
t.Errorf("Search user failed %v", user)
|
|
}
|
|
}
|
|
func TestAuthenticateWithAdmin(t *testing.T) {
|
|
var person models.AuthModel
|
|
var authHelper *Auth
|
|
person.Principal = "mike"
|
|
person.Password = "zhu88jie"
|
|
user, err := authHelper.Authenticate(person)
|
|
if err != nil {
|
|
t.Errorf("unexpected ldap authenticate fail: %v", err)
|
|
}
|
|
if user.Username != "mike" {
|
|
t.Errorf("unexpected ldap user authenticate fail: %s = %s", "user.Username", user.Username)
|
|
}
|
|
if !user.HasAdminRole {
|
|
t.Errorf("ldap user mike should have admin role!")
|
|
}
|
|
}
|
|
func TestAuthenticateWithoutAdmin(t *testing.T) {
|
|
var person models.AuthModel
|
|
var authHelper *Auth
|
|
person.Principal = "user001"
|
|
person.Password = "Test1@34"
|
|
user, err := authHelper.Authenticate(person)
|
|
if err != nil {
|
|
t.Errorf("unexpected ldap authenticate fail: %v", err)
|
|
}
|
|
if user.Username != "user001" {
|
|
t.Errorf("unexpected ldap user authenticate fail: %s = %s", "user.Username", user.Username)
|
|
}
|
|
if user.HasAdminRole {
|
|
t.Errorf("ldap user user001 should not have admin role!")
|
|
}
|
|
}
|
|
func TestSearchUser_02(t *testing.T) {
|
|
var username = "nonexist"
|
|
var auth *Auth
|
|
user, _ := auth.SearchUser(username)
|
|
if user != nil {
|
|
t.Errorf("Should failed to search nonexist user")
|
|
}
|
|
|
|
}
|
|
|
|
func TestOnBoardUser(t *testing.T) {
|
|
user := &models.User{
|
|
Username: "sample",
|
|
Email: "sample@example.com",
|
|
Realname: "Sample",
|
|
}
|
|
|
|
var auth *Auth
|
|
err := auth.OnBoardUser(user)
|
|
if err != nil {
|
|
t.Errorf("Failed to onboard user")
|
|
}
|
|
if user.UserID <= 0 {
|
|
t.Errorf("Failed to onboard user")
|
|
}
|
|
assert.Equal(t, "sample@example.com", user.Email)
|
|
}
|
|
|
|
func TestOnBoardUser_02(t *testing.T) {
|
|
user := &models.User{
|
|
Username: "sample02",
|
|
Realname: "Sample02",
|
|
}
|
|
var auth *Auth
|
|
err := auth.OnBoardUser(user)
|
|
if err != nil {
|
|
t.Errorf("Failed to onboard user")
|
|
}
|
|
if user.UserID <= 0 {
|
|
t.Errorf("Failed to onboard user")
|
|
}
|
|
|
|
assert.Equal(t, "", user.Email)
|
|
dao.CleanUser(int64(user.UserID))
|
|
}
|
|
|
|
func TestOnBoardUser_03(t *testing.T) {
|
|
user := &models.User{
|
|
Username: "sample03@example.com",
|
|
Realname: "Sample03",
|
|
}
|
|
var auth *Auth
|
|
err := auth.OnBoardUser(user)
|
|
if err != nil {
|
|
t.Errorf("Failed to onboard user")
|
|
}
|
|
if user.UserID <= 0 {
|
|
t.Errorf("Failed to onboard user")
|
|
}
|
|
|
|
assert.Equal(t, "sample03@example.com", user.Email)
|
|
dao.CleanUser(int64(user.UserID))
|
|
}
|
|
|
|
func TestAuthenticateHelperOnBoardUser(t *testing.T) {
|
|
user := models.User{
|
|
Username: "test01",
|
|
Realname: "test01",
|
|
Email: "test01@example.com",
|
|
}
|
|
|
|
err := auth.OnBoardUser(&user)
|
|
if err != nil {
|
|
t.Errorf("Failed to onboard user error: %v", err)
|
|
}
|
|
|
|
if user.UserID <= 0 {
|
|
t.Errorf("Failed to onboard user, userid: %v", user.UserID)
|
|
}
|
|
|
|
}
|
|
|
|
func TestOnBoardGroup(t *testing.T) {
|
|
group := models.UserGroup{
|
|
GroupName: "harbor_group2",
|
|
LdapGroupDN: "cn=harbor_group2,ou=groups,dc=example,dc=com",
|
|
}
|
|
newGroupName := "group_name123"
|
|
err := auth.OnBoardGroup(&group, newGroupName)
|
|
if err != nil {
|
|
t.Errorf("Failed to OnBoardGroup, %+v", group)
|
|
}
|
|
if group.GroupName != "group_name123" {
|
|
t.Errorf("The OnBoardGroup should have name %v", newGroupName)
|
|
}
|
|
}
|
|
|
|
func TestAuthenticateHelperSearchUser(t *testing.T) {
|
|
|
|
user, err := auth.SearchUser("test")
|
|
if err != nil {
|
|
t.Error("Failed to search user, test")
|
|
}
|
|
|
|
if user == nil {
|
|
t.Error("Failed to search user test")
|
|
}
|
|
}
|
|
|
|
func TestPostAuthentication(t *testing.T) {
|
|
|
|
assert := assert.New(t)
|
|
user1 := &models.User{
|
|
Username: "test003",
|
|
Email: "test003@vmware.com",
|
|
Realname: "test003",
|
|
}
|
|
|
|
queryCondition := models.User{
|
|
Username: "test003",
|
|
Realname: "test003",
|
|
}
|
|
|
|
err := auth.OnBoardUser(user1)
|
|
assert.Nil(err)
|
|
|
|
user2 := &models.User{
|
|
Username: "test003",
|
|
Email: "234invalidmail@@@@@",
|
|
}
|
|
|
|
auth.PostAuthenticate(user2)
|
|
|
|
dbUser, err := dao.GetUser(queryCondition)
|
|
if err != nil {
|
|
t.Fatalf("Failed to get user, error %v", err)
|
|
}
|
|
assert.EqualValues("test003@vmware.com", dbUser.Email)
|
|
|
|
user3 := &models.User{
|
|
Username: "test003",
|
|
}
|
|
|
|
auth.PostAuthenticate(user3)
|
|
dbUser, err = dao.GetUser(queryCondition)
|
|
if err != nil {
|
|
t.Fatalf("Failed to get user, error %v", err)
|
|
}
|
|
assert.EqualValues("test003@vmware.com", dbUser.Email)
|
|
|
|
user4 := &models.User{
|
|
Username: "test003",
|
|
Email: "test003@example.com",
|
|
}
|
|
|
|
auth.PostAuthenticate(user4)
|
|
|
|
dbUser, err = dao.GetUser(queryCondition)
|
|
if err != nil {
|
|
t.Fatalf("Failed to get user, error %v", err)
|
|
}
|
|
assert.EqualValues("test003@example.com", dbUser.Email)
|
|
dao.CleanUser(int64(dbUser.UserID))
|
|
}
|
|
|
|
func TestSearchAndOnBoardUser(t *testing.T) {
|
|
userID, err := auth.SearchAndOnBoardUser("mike02")
|
|
defer dao.CleanUser(int64(userID))
|
|
if err != nil {
|
|
t.Errorf("Error occurred when SearchAndOnBoardUser: %v", err)
|
|
}
|
|
if userID == 0 {
|
|
t.Errorf("Can not search and onboard user %v", "mike")
|
|
}
|
|
}
|
|
func TestAddProjectMemberWithLdapUser(t *testing.T) {
|
|
currentProject, err := dao.GetProjectByName("member_test_01")
|
|
if err != nil {
|
|
t.Errorf("Error occurred when GetProjectByName: %v", err)
|
|
}
|
|
member := models.MemberReq{
|
|
ProjectID: currentProject.ProjectID,
|
|
MemberUser: models.User{
|
|
Username: "mike",
|
|
},
|
|
Role: models.PROJECTADMIN,
|
|
}
|
|
pmid, err := api.AddProjectMember(currentProject.ProjectID, member)
|
|
if err != nil {
|
|
t.Errorf("Error occurred in AddOrUpdateProjectMember: %v", err)
|
|
}
|
|
if pmid == 0 {
|
|
t.Errorf("Error occurred in AddOrUpdateProjectMember: pmid:%v", pmid)
|
|
}
|
|
|
|
currentProject, err = dao.GetProjectByName("member_test_02")
|
|
if err != nil {
|
|
t.Errorf("Error occurred when GetProjectByName: %v", err)
|
|
}
|
|
member2 := models.MemberReq{
|
|
ProjectID: currentProject.ProjectID,
|
|
MemberUser: models.User{
|
|
Username: "mike",
|
|
},
|
|
Role: models.PROJECTADMIN,
|
|
}
|
|
pmid, err = api.AddProjectMember(currentProject.ProjectID, member2)
|
|
if err != nil {
|
|
t.Errorf("Error occurred in AddOrUpdateProjectMember: %v", err)
|
|
}
|
|
if pmid == 0 {
|
|
t.Errorf("Error occurred in AddOrUpdateProjectMember: pmid:%v", pmid)
|
|
}
|
|
}
|
|
func TestAddProjectMemberWithLdapGroup(t *testing.T) {
|
|
currentProject, err := dao.GetProjectByName("member_test_01")
|
|
if err != nil {
|
|
t.Errorf("Error occurred when GetProjectByName: %v", err)
|
|
}
|
|
member := models.MemberReq{
|
|
ProjectID: currentProject.ProjectID,
|
|
MemberGroup: models.UserGroup{
|
|
LdapGroupDN: "cn=harbor_users,ou=groups,dc=example,dc=com",
|
|
GroupType: 1,
|
|
},
|
|
Role: models.PROJECTADMIN,
|
|
}
|
|
pmid, err := api.AddProjectMember(currentProject.ProjectID, member)
|
|
if err != nil {
|
|
t.Errorf("Error occurred in AddOrUpdateProjectMember: %v", err)
|
|
}
|
|
if pmid == 0 {
|
|
t.Errorf("Error occurred in AddOrUpdateProjectMember: pmid: %v", pmid)
|
|
}
|
|
queryMember := models.Member{
|
|
ProjectID: currentProject.ProjectID,
|
|
}
|
|
memberList, err := project.GetProjectMember(queryMember)
|
|
if err != nil {
|
|
t.Errorf("Failed to query project member, %v, error: %v", queryMember, err)
|
|
}
|
|
if len(memberList) == 0 {
|
|
t.Errorf("Failed to query project member, %v", queryMember)
|
|
}
|
|
}
|