Merge pull request #2717 from ywk253100/170706_integration

Update auth context as Admiral's API changed
This commit is contained in:
Wenkai Yin 2017-07-07 11:03:13 +08:00 committed by GitHub
commit 186538010d
6 changed files with 106 additions and 34 deletions

View File

@ -20,10 +20,12 @@ import (
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"net/http" "net/http"
"strconv"
"strings" "strings"
"github.com/vmware/harbor/src/common" "github.com/vmware/harbor/src/common"
"github.com/vmware/harbor/src/common/models" "github.com/vmware/harbor/src/common/models"
"github.com/vmware/harbor/src/common/utils"
"github.com/vmware/harbor/src/common/utils/log" "github.com/vmware/harbor/src/common/utils/log"
) )
@ -37,9 +39,10 @@ const (
) )
type project struct { type project struct {
DocumentSelfLink string `json:"documentSelfLink"` SelfLink string `json:"documentSelfLink"`
Name string `json:"name"` Name string `json:"name"`
Roles []string `json:"roles"` Roles []string `json:"roles"`
Properties map[string]string `json:"customProperties"`
} }
// AuthContext ... // AuthContext ...
@ -63,29 +66,19 @@ func (a *AuthContext) IsSysAdmin() bool {
// GetProjectRoles ... // GetProjectRoles ...
func (a *AuthContext) GetProjectRoles(projectIDOrName interface{}) []int { func (a *AuthContext) GetProjectRoles(projectIDOrName interface{}) []int {
var isID bool id, name, err := utils.ParseProjectIDOrName(projectIDOrName)
var id int64 if err != nil {
var name string log.Errorf("failed to parse project ID or name: %v", err)
return []int{}
id, isID = projectIDOrName.(int64)
if !isID {
name, _ = projectIDOrName.(string)
} }
roles := []string{} roles := []string{}
for _, project := range a.Projects { for _, project := range a.Projects {
p := convertProject(project) p := convertProject(project)
if isID { if p.ProjectID == id || p.Name == name {
if p.ProjectID == id {
roles = append(roles, project.Roles...) roles = append(roles, project.Roles...)
break break
} }
} else {
if p.Name == name {
roles = append(roles, project.Roles...)
break
}
}
} }
return convertRoles(roles) return convertRoles(roles)
@ -100,12 +93,29 @@ func (a *AuthContext) GetMyProjects() []*models.Project {
return projects return projects
} }
// TODO populate harbor ID to the project
// convert project returned by Admiral to project used in Harbor // convert project returned by Admiral to project used in Harbor
func convertProject(p *project) *models.Project { func convertProject(p *project) *models.Project {
project := &models.Project{ project := &models.Project{
Name: p.Name, Name: p.Name,
} }
index := ""
if p.Properties != nil {
index = p.Properties["__projectIndex"]
}
if len(index) == 0 {
log.Errorf("property __projectIndex not found when parsing project")
return project
}
id, err := strconv.ParseInt(index, 10, 64)
if err != nil {
log.Errorf("failed to parse __projectIndex %s: %v", index, err)
return project
}
project.ProjectID = id
return project return project
} }

View File

@ -44,6 +44,7 @@ func TestGetProjectRoles(t *testing.T) {
&project{ &project{
Name: "project", Name: "project",
Roles: []string{projectAdminRole, developerRole, guestRole}, Roles: []string{projectAdminRole, developerRole, guestRole},
Properties: map[string]string{"__projectIndex": "9"},
}, },
}, },
} }
@ -52,7 +53,9 @@ func TestGetProjectRoles(t *testing.T) {
roles := ctx.GetProjectRoles("project") roles := ctx.GetProjectRoles("project")
assert.Equal(t, 3, len(roles)) assert.Equal(t, 3, len(roles))
// TODO add test case with ID // test with ID
roles = ctx.GetProjectRoles(9)
assert.Equal(t, 3, len(roles))
} }
func TestGetMyProjects(t *testing.T) { func TestGetMyProjects(t *testing.T) {

View File

@ -17,7 +17,7 @@ package admiral
import ( import (
"github.com/vmware/harbor/src/common" "github.com/vmware/harbor/src/common"
"github.com/vmware/harbor/src/common/models" "github.com/vmware/harbor/src/common/models"
"github.com/vmware/harbor/src/common/security/authcontext" "github.com/vmware/harbor/src/common/security/admiral/authcontext"
"github.com/vmware/harbor/src/common/utils/log" "github.com/vmware/harbor/src/common/utils/log"
"github.com/vmware/harbor/src/ui/projectmanager" "github.com/vmware/harbor/src/ui/projectmanager"
) )

View File

@ -16,6 +16,7 @@ package utils
import ( import (
"crypto/rand" "crypto/rand"
"errors"
"fmt" "fmt"
"net" "net"
"net/url" "net/url"
@ -125,3 +126,34 @@ func ParseTimeStamp(timestamp string) (*time.Time, error) {
t := time.Unix(i, 0) t := time.Unix(i, 0)
return &t, nil return &t, nil
} }
// ParseProjectIDOrName parses value to ID(int64) or name(string)
func ParseProjectIDOrName(value interface{}) (int64, string, error) {
if value == nil {
return 0, "", errors.New("harborIDOrName is nil")
}
var id int64
var name string
switch value.(type) {
case int:
i := value.(int)
id = int64(i)
if id == 0 {
return 0, "", fmt.Errorf("invalid ID: 0")
}
case int64:
id = value.(int64)
if id == 0 {
return 0, "", fmt.Errorf("invalid ID: 0")
}
case string:
name = value.(string)
if len(name) == 0 {
return 0, "", fmt.Errorf("empty name")
}
default:
return 0, "", fmt.Errorf("unsupported type")
}
return id, name, nil
}

View File

@ -211,3 +211,35 @@ func TestParseTimeStamp(t *testing.T) {
assert.Nil(t, err) assert.Nil(t, err)
assert.Equal(t, now, result.Unix()) assert.Equal(t, now, result.Unix())
} }
func TestParseHarborIDOrName(t *testing.T) {
// nil input
id, name, err := ParseProjectIDOrName(nil)
assert.NotNil(t, err)
// invalid ID
id, name, err = ParseProjectIDOrName(0)
assert.NotNil(t, err)
// invalid name
id, name, err = ParseProjectIDOrName("")
assert.NotNil(t, err)
// valid int ID
id, name, err = ParseProjectIDOrName(1)
assert.Nil(t, err)
assert.Equal(t, int64(1), id)
assert.Equal(t, "", name)
// valid int64 ID
id, name, err = ParseProjectIDOrName(int64(1))
assert.Nil(t, err)
assert.Equal(t, int64(1), id)
assert.Equal(t, "", name)
// valid name
id, name, err = ParseProjectIDOrName("project")
assert.Nil(t, err)
assert.Equal(t, int64(0), id)
assert.Equal(t, "project", name)
}

View File

@ -24,7 +24,7 @@ import (
secstore "github.com/vmware/harbor/src/common/secret" secstore "github.com/vmware/harbor/src/common/secret"
"github.com/vmware/harbor/src/common/security" "github.com/vmware/harbor/src/common/security"
"github.com/vmware/harbor/src/common/security/admiral" "github.com/vmware/harbor/src/common/security/admiral"
"github.com/vmware/harbor/src/common/security/authcontext" "github.com/vmware/harbor/src/common/security/admiral/authcontext"
"github.com/vmware/harbor/src/common/security/local" "github.com/vmware/harbor/src/common/security/local"
"github.com/vmware/harbor/src/common/security/secret" "github.com/vmware/harbor/src/common/security/secret"
"github.com/vmware/harbor/src/common/utils/log" "github.com/vmware/harbor/src/common/utils/log"
@ -99,19 +99,14 @@ func (s *secretReqCtxModifier) Modify(ctx *beegoctx.Context) bool {
if len(scrt) == 0 { if len(scrt) == 0 {
return false return false
} }
log.Debug("got secret from request") log.Debug("got secret from request")
var pm projectmanager.ProjectManager log.Debug("using global project manager")
if config.WithAdmiral() { pm := config.GlobalProjectMgr
// TODO project manager with harbor service accout
} else {
log.Debug("using local database project manager")
pm = config.GlobalProjectMgr
}
log.Debug("creating a secret security context...") log.Debug("creating a secret security context...")
securCtx := secret.NewSecurityContext(scrt, s.store) securCtx := secret.NewSecurityContext(scrt, s.store)
setSecurCtxAndPM(ctx.Request, securCtx, pm) setSecurCtxAndPM(ctx.Request, securCtx, pm)
return true return true