fix #120 refactor the rbac code to support customizable claims enforcement function (#265)

This commit is contained in:
wanghong230 2018-06-06 14:20:34 -07:00 committed by GitHub
parent 30a3dba7ad
commit 85078bdb66
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 41 additions and 19 deletions

View file

@ -106,7 +106,7 @@ func NewServer(opts ArgoCDServerOpts) *ArgoCDServer {
errors.CheckError(err)
sessionMgr := util_session.NewSessionManager(settings)
enf := rbac.NewEnforcer(opts.KubeClientset, opts.Namespace, common.ArgoCDRBACConfigMapName)
enf := rbac.NewEnforcer(opts.KubeClientset, opts.Namespace, common.ArgoCDRBACConfigMapName, nil)
enf.EnableEnforce(!opts.DisableAuth)
err = enf.SetBuiltinPolicy(builtinPolicy)
errors.CheckError(err)

View file

@ -248,7 +248,7 @@ func NewFixture() (*Fixture, error) {
return nil, err
}
db := db.NewDB(namespace, kubeClient)
enforcer := rbac.NewEnforcer(kubeClient, namespace, common.ArgoCDRBACConfigMapName)
enforcer := rbac.NewEnforcer(kubeClient, namespace, common.ArgoCDRBACConfigMapName, nil)
enforcer.SetDefaultRole("role:admin")
fixture := &Fixture{

View file

@ -28,11 +28,15 @@ const (
defaultRBACSyncPeriod = 10 * time.Minute
)
// ClaimsEnforcerFunc is func template
type ClaimsEnforcerFunc func(rvals ...interface{}) bool
type Enforcer struct {
*casbin.Enforcer
clientset kubernetes.Interface
namespace string
configmap string
clientset kubernetes.Interface
namespace string
configmap string
claimsEnforcerFunc ClaimsEnforcerFunc
model model.Model
defaultRole string
@ -40,18 +44,19 @@ type Enforcer struct {
userDefinedPolicy string
}
func NewEnforcer(clientset kubernetes.Interface, namespace, configmap string) *Enforcer {
func NewEnforcer(clientset kubernetes.Interface, namespace, configmap string, claimsEnforcer ClaimsEnforcerFunc) *Enforcer {
box := packr.NewBox(".")
modelConf := box.String(builtinModelFile)
model := casbin.NewModel(modelConf)
enf := casbin.Enforcer{}
enf.EnableLog(false)
return &Enforcer{
Enforcer: &enf,
clientset: clientset,
namespace: namespace,
configmap: configmap,
model: model,
Enforcer: &enf,
clientset: clientset,
namespace: namespace,
configmap: configmap,
model: model,
claimsEnforcerFunc: claimsEnforcer,
}
}
@ -61,6 +66,13 @@ func (e *Enforcer) SetDefaultRole(roleName string) {
e.defaultRole = roleName
}
// SetClaimsEnforcerFunc sets a claims enforce function during enforcement. The claims enforce function
// can extract claims from JWT token and do the proper enforcement based on user, group or any information
// available in the input parameter list
func (e *Enforcer) SetClaimsEnforcerFunc(claimsEnforcer ClaimsEnforcerFunc) {
e.claimsEnforcerFunc = claimsEnforcer
}
// Enforce is a wrapper around casbin.Enforce to additionally enforce a default role
func (e *Enforcer) Enforce(rvals ...interface{}) bool {
if e.Enforcer.Enforce(rvals...) {
@ -75,6 +87,16 @@ func (e *Enforcer) Enforce(rvals ...interface{}) bool {
// EnforceClaims checks if the first value is a jwt.Claims and runs enforce against its groups and sub
func (e *Enforcer) EnforceClaims(rvals ...interface{}) bool {
// User default claims enforcer if it is nil
if e.claimsEnforcerFunc == nil {
return e.defaultEnforceClaims(rvals...)
}
return e.claimsEnforcerFunc(rvals...)
}
func (e *Enforcer) defaultEnforceClaims(rvals ...interface{}) bool {
claims, ok := rvals[0].(jwt.Claims)
if !ok {
if rvals[0] == nil {

View file

@ -47,7 +47,7 @@ func fakeConfigMap(policy ...string) *apiv1.ConfigMap {
// TestBuiltinPolicyEnforcer tests the builtin policy rules
func TestBuiltinPolicyEnforcer(t *testing.T) {
kubeclientset := fake.NewSimpleClientset()
enf := NewEnforcer(kubeclientset, fakeNamespace, fakeConfgMapName)
enf := NewEnforcer(kubeclientset, fakeNamespace, fakeConfgMapName, nil)
err := enf.syncUpdate(fakeConfigMap())
assert.Nil(t, err)
@ -85,7 +85,7 @@ func TestBuiltinPolicyEnforcer(t *testing.T) {
func TestPolicyInformer(t *testing.T) {
cm := fakeConfigMap()
kubeclientset := fake.NewSimpleClientset(cm)
enf := NewEnforcer(kubeclientset, fakeNamespace, fakeConfgMapName)
enf := NewEnforcer(kubeclientset, fakeNamespace, fakeConfgMapName, nil)
ctx := context.Background()
ctx, cancel := context.WithCancel(ctx)
@ -113,7 +113,7 @@ func TestPolicyInformer(t *testing.T) {
// TestProjectIsolationEnforcement verifies the ability to create Project specific policies
func TestProjectIsolationEnforcement(t *testing.T) {
kubeclientset := fake.NewSimpleClientset(fakeConfigMap())
enf := NewEnforcer(kubeclientset, fakeNamespace, fakeConfgMapName)
enf := NewEnforcer(kubeclientset, fakeNamespace, fakeConfgMapName, nil)
policy := `
p, role:foo-admin, *, *, foo/*
p, role:bar-admin, *, *, bar/*
@ -133,7 +133,7 @@ g, bob, role:bar-admin
// TestProjectReadOnly verifies the ability to have a read only role in a Project
func TestProjectReadOnly(t *testing.T) {
kubeclientset := fake.NewSimpleClientset(fakeConfigMap())
enf := NewEnforcer(kubeclientset, fakeNamespace, fakeConfgMapName)
enf := NewEnforcer(kubeclientset, fakeNamespace, fakeConfgMapName, nil)
policy := `
p, role:foo-readonly, *, get, foo/*
g, alice, role:foo-readonly
@ -148,7 +148,7 @@ g, alice, role:foo-readonly
func TestEnforceClaims(t *testing.T) {
kubeclientset := fake.NewSimpleClientset(fakeConfigMap())
enf := NewEnforcer(kubeclientset, fakeNamespace, fakeConfgMapName)
enf := NewEnforcer(kubeclientset, fakeNamespace, fakeConfgMapName, nil)
enf.SetBuiltinPolicy(box.String(builtinPolicyFile))
policy := `
g, org2:team2, role:admin
@ -179,7 +179,7 @@ g, bob, role:admin
// TestDefaultRole tests the ability to set a default role
func TestDefaultRole(t *testing.T) {
kubeclientset := fake.NewSimpleClientset()
enf := NewEnforcer(kubeclientset, fakeNamespace, fakeConfgMapName)
enf := NewEnforcer(kubeclientset, fakeNamespace, fakeConfgMapName, nil)
err := enf.syncUpdate(fakeConfigMap())
assert.Nil(t, err)
enf.SetBuiltinPolicy(box.String(builtinPolicyFile))
@ -196,7 +196,7 @@ func TestDefaultRole(t *testing.T) {
// TestURLAsObjectName tests the ability to have a URL as an object name
func TestURLAsObjectName(t *testing.T) {
kubeclientset := fake.NewSimpleClientset()
enf := NewEnforcer(kubeclientset, fakeNamespace, fakeConfgMapName)
enf := NewEnforcer(kubeclientset, fakeNamespace, fakeConfgMapName, nil)
err := enf.syncUpdate(fakeConfigMap())
assert.Nil(t, err)
policy := `
@ -216,7 +216,7 @@ p, cathy, repositories, *, foo/*
func TestEnforceNilClaims(t *testing.T) {
kubeclientset := fake.NewSimpleClientset(fakeConfigMap())
enf := NewEnforcer(kubeclientset, fakeNamespace, fakeConfgMapName)
enf := NewEnforcer(kubeclientset, fakeNamespace, fakeConfgMapName, nil)
enf.SetBuiltinPolicy(box.String(builtinPolicyFile))
assert.False(t, enf.EnforceClaims(nil, "applications", "get", "foo/obj"))
enf.SetDefaultRole("role:readonly")