Merge pull request #2158 from ywk253100/170427_pm

Implement security context for secret
This commit is contained in:
Wenkai Yin 2017-05-02 13:12:20 +08:00 committed by GitHub
commit 80d83d97bd
10 changed files with 322 additions and 8 deletions

View File

@ -0,0 +1,48 @@
// Copyright (c) 2017 VMware, Inc. All Rights Reserved.
//
// 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 secret
const (
// AdminserverUser is the name of adminserver user
AdminserverUser = "harbor-adminserver"
// JobserviceUser is the name of jobservice user
JobserviceUser = "harbor-jobservice"
// UIUser is the name of ui user
UIUser = "harbor-ui"
)
// Store the secrets and provides methods to validate secrets
type Store struct {
// the key is secret
// the value is username
secrets map[string]string
}
// NewStore ...
func NewStore(secrets map[string]string) *Store {
return &Store{
secrets: secrets,
}
}
// IsValid returns whether the secret is valid
func (s *Store) IsValid(secret string) bool {
return len(s.GetUsername(secret)) != 0
}
// GetUsername returns the corresponding username of the secret
func (s *Store) GetUsername(secret string) string {
return s.secrets[secret]
}

View File

@ -0,0 +1,39 @@
// Copyright (c) 2017 VMware, Inc. All Rights Reserved.
//
// 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 secret
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestIsValid(t *testing.T) {
store := NewStore(map[string]string{
"secret1": "username1",
})
assert.False(t, store.IsValid("invalid_secret"))
assert.True(t, store.IsValid("secret1"))
}
func TestGetUsername(t *testing.T) {
store := NewStore(map[string]string{
"secret1": "username1",
})
assert.Equal(t, "", store.GetUsername("invalid_secret"))
assert.Equal(t, "username1", store.GetUsername("secret1"))
}

View File

@ -18,15 +18,14 @@ package security
type Context interface { type Context interface {
// IsAuthenticated returns whether the context has been authenticated or not // IsAuthenticated returns whether the context has been authenticated or not
IsAuthenticated() bool IsAuthenticated() bool
// GetUsername returns the username of user related to the context
GetUsername() string
// IsSysAdmin returns whether the user is system admin // IsSysAdmin returns whether the user is system admin
IsSysAdmin() bool IsSysAdmin() bool
// HasReadPerm returns whether the user has read permission to the project // HasReadPerm returns whether the user has read permission to the project
// whose ID is projectID HasReadPerm(projectIDOrName interface{}) bool
HasReadPerm(projectID int64) bool
// HasWritePerm returns whether the user has write permission to the project // HasWritePerm returns whether the user has write permission to the project
// whose ID is projectID HasWritePerm(projectIDOrName interface{}) bool
HasWritePerm(projectID int64) bool
// HasAllPerm returns whether the user has all permissions to the project // HasAllPerm returns whether the user has all permissions to the project
// whose ID is projectID HasAllPerm(projectIDOrName interface{}) bool
HasAllPerm(projectID int64) bool
} }

View File

@ -0,0 +1,74 @@
// Copyright (c) 2017 VMware, Inc. All Rights Reserved.
//
// 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 secret
import (
"github.com/vmware/harbor/src/common/secret"
)
// SecurityContext implements security.Context interface based on secret store
type SecurityContext struct {
secret string
store *secret.Store
}
// NewSecurityContext ...
func NewSecurityContext(secret string, store *secret.Store) *SecurityContext {
return &SecurityContext{
secret: secret,
store: store,
}
}
// IsAuthenticated returns true if the secret is valid
func (s *SecurityContext) IsAuthenticated() bool {
if s.store == nil {
return false
}
return s.store.IsValid(s.secret)
}
// GetUsername returns the corresponding username of the secret
// or null if the secret is invalid
func (s *SecurityContext) GetUsername() string {
if s.store == nil {
return ""
}
return s.store.GetUsername(s.secret)
}
// IsSysAdmin always returns false
func (s *SecurityContext) IsSysAdmin() bool {
return false
}
// HasReadPerm returns true if the corresponding user of the secret
// is jobservice, otherwise returns false
func (s *SecurityContext) HasReadPerm(projectIDOrName interface{}) bool {
if s.store == nil {
return false
}
return s.store.GetUsername(s.secret) == secret.JobserviceUser
}
// HasWritePerm always returns false
func (s *SecurityContext) HasWritePerm(projectIDOrName interface{}) bool {
return false
}
// HasAllPerm always returns false
func (s *SecurityContext) HasAllPerm(projectIDOrName interface{}) bool {
return false
}

View File

@ -0,0 +1,134 @@
// Copyright (c) 2017 VMware, Inc. All Rights Reserved.
//
// 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 secret
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/vmware/harbor/src/common/secret"
)
func TestIsAuthenticated(t *testing.T) {
// secret store is null
context := NewSecurityContext("", nil)
isAuthenticated := context.IsAuthenticated()
assert.False(t, isAuthenticated)
//invalid secret
context = NewSecurityContext("invalid_secret",
secret.NewStore(map[string]string{
"secret": "username",
}))
isAuthenticated = context.IsAuthenticated()
assert.False(t, isAuthenticated)
//valid secret
context = NewSecurityContext("secret",
secret.NewStore(map[string]string{
"secret": "username",
}))
isAuthenticated = context.IsAuthenticated()
assert.True(t, isAuthenticated)
}
func TestGetUsername(t *testing.T) {
// secret store is null
context := NewSecurityContext("", nil)
username := context.GetUsername()
assert.Equal(t, "", username)
//invalid secret
context = NewSecurityContext("invalid_secret",
secret.NewStore(map[string]string{
"secret": "username",
}))
username = context.GetUsername()
assert.Equal(t, "", username)
//valid secret
context = NewSecurityContext("secret",
secret.NewStore(map[string]string{
"secret": "username",
}))
username = context.GetUsername()
assert.Equal(t, "username", username)
}
func TestIsSysAdmin(t *testing.T) {
context := NewSecurityContext("secret",
secret.NewStore(map[string]string{
"secret": "username",
}))
isSysAdmin := context.IsSysAdmin()
assert.False(t, isSysAdmin)
}
func TestHasReadPerm(t *testing.T) {
// secret store is null
context := NewSecurityContext("", nil)
hasReadPerm := context.HasReadPerm("project_name")
assert.False(t, hasReadPerm)
//invalid secret
context = NewSecurityContext("invalid_secret",
secret.NewStore(map[string]string{
"jobservice_secret": secret.JobserviceUser,
}))
hasReadPerm = context.HasReadPerm("project_name")
assert.False(t, hasReadPerm)
//valid secret, project name
context = NewSecurityContext("jobservice_secret",
secret.NewStore(map[string]string{
"jobservice_secret": secret.JobserviceUser,
}))
hasReadPerm = context.HasReadPerm("project_name")
assert.True(t, hasReadPerm)
//valid secret, project ID
hasReadPerm = context.HasReadPerm(1)
assert.True(t, hasReadPerm)
}
func TestHasWritePerm(t *testing.T) {
context := NewSecurityContext("secret",
secret.NewStore(map[string]string{
"secret": "username",
}))
// project name
hasWritePerm := context.HasWritePerm("project_name")
assert.False(t, hasWritePerm)
// project ID
hasWritePerm = context.HasWritePerm(1)
assert.False(t, hasWritePerm)
}
func TestHasAllPerm(t *testing.T) {
context := NewSecurityContext("secret",
secret.NewStore(map[string]string{
"secret": "username",
}))
// project name
hasAllPerm := context.HasAllPerm("project_name")
assert.False(t, hasAllPerm)
// project ID
hasAllPerm = context.HasAllPerm(1)
assert.False(t, hasAllPerm)
}

View File

@ -19,8 +19,8 @@ import (
"strings" "strings"
"github.com/astaxie/beego/context" "github.com/astaxie/beego/context"
"github.com/vmware/harbor/src/common/security"
"github.com/vmware/harbor/src/common/utils/log" "github.com/vmware/harbor/src/common/utils/log"
"github.com/vmware/harbor/src/ui/security"
) )
const ( const (

View File

@ -12,4 +12,4 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
package secret package db

20
src/ui/pms/service.go Normal file
View File

@ -0,0 +1,20 @@
// Copyright (c) 2017 VMware, Inc. All Rights Reserved.
//
// 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 project
// PMS is the project mamagement service which abstracts
// the operations related to projects
type PMS interface {
}