mirror of
https://github.com/goharbor/harbor.git
synced 2024-11-19 00:36:02 +01:00
Merge pull request #2158 from ywk253100/170427_pm
Implement security context for secret
This commit is contained in:
commit
80d83d97bd
48
src/common/secret/store.go
Normal file
48
src/common/secret/store.go
Normal 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]
|
||||||
|
}
|
39
src/common/secret/store_test.go
Normal file
39
src/common/secret/store_test.go
Normal 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"))
|
||||||
|
}
|
@ -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
|
|
||||||
}
|
}
|
74
src/common/security/secret/context.go
Normal file
74
src/common/security/secret/context.go
Normal 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
|
||||||
|
}
|
134
src/common/security/secret/context_test.go
Normal file
134
src/common/security/secret/context_test.go
Normal 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)
|
||||||
|
}
|
@ -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 (
|
||||||
|
@ -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
20
src/ui/pms/service.go
Normal 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 {
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user