github.com/argoproj/argo-cd@v1.8.7/util/rbac/rbac_norace_test.go (about)

     1  // +build !race
     2  
     3  package rbac
     4  
     5  import (
     6  	"context"
     7  	"testing"
     8  	"time"
     9  
    10  	"github.com/stretchr/testify/assert"
    11  	apiv1 "k8s.io/api/core/v1"
    12  	"k8s.io/client-go/kubernetes/fake"
    13  )
    14  
    15  // TestPolicyInformer verifies the informer will get updated with a new configmap
    16  func TestPolicyInformer(t *testing.T) {
    17  
    18  	// !race:
    19  	// A BUNCH of data race warnings thrown by running this test and the next... it's tough to guess to what degree this
    20  	// is primarily a casbin issue or a Argo CD RBAC issue... A least one data race is an `rbac.go` with
    21  	// itself, a bunch are in casbin. You can see the full list by doing a `go test -race github.com/argoproj/argo-cd/util/rbac`
    22  	//
    23  	// It couldn't hurt to take a look at this code to decide if Argo CD is properly handling concurrent data
    24  	// access here, but in the mean time I have disabled data race testing of this test.
    25  
    26  	cm := fakeConfigMap()
    27  	cm.Data[ConfigMapPolicyCSVKey] = "p, admin, applications, delete, */*, allow"
    28  	kubeclientset := fake.NewSimpleClientset(cm)
    29  	enf := NewEnforcer(kubeclientset, fakeNamespace, fakeConfigMapName, nil)
    30  
    31  	ctx := context.Background()
    32  	ctx, cancel := context.WithCancel(ctx)
    33  	defer cancel()
    34  	go enf.runInformer(ctx, func(cm *apiv1.ConfigMap) error {
    35  		return nil
    36  	})
    37  
    38  	loaded := false
    39  	for i := 1; i <= 20; i++ {
    40  		if enf.Enforce("admin", "applications", "delete", "foo/bar") {
    41  			loaded = true
    42  			break
    43  		}
    44  		time.Sleep(50 * time.Millisecond)
    45  	}
    46  	assert.True(t, loaded, "Policy update failed to load")
    47  
    48  	// update the configmap and update policy
    49  	delete(cm.Data, ConfigMapPolicyCSVKey)
    50  	err := enf.syncUpdate(cm, noOpUpdate)
    51  	assert.Nil(t, err)
    52  	assert.False(t, enf.Enforce("admin", "applications", "delete", "foo/bar"))
    53  }
    54  
    55  // TestResourceActionWildcards verifies the ability to use wildcards in resources and actions
    56  func TestResourceActionWildcards(t *testing.T) {
    57  
    58  	// !race:
    59  	// Same as TestPolicyInformer
    60  
    61  	kubeclientset := fake.NewSimpleClientset(fakeConfigMap())
    62  	enf := NewEnforcer(kubeclientset, fakeNamespace, fakeConfigMapName, nil)
    63  	policy := `
    64  p, alice, *, get, foo/obj, allow
    65  p, bob, repositories, *, foo/obj, allow
    66  p, cathy, *, *, foo/obj, allow
    67  p, dave, applications, get, foo/obj, allow
    68  p, dave, applications/*, get, foo/obj, allow
    69  p, eve, *, get, foo/obj, deny
    70  p, mallory, repositories, *, foo/obj, deny
    71  p, mallory, repositories, *, foo/obj, allow
    72  p, mike, *, *, foo/obj, allow
    73  p, mike, *, *, foo/obj, deny
    74  p, trudy, applications, get, foo/obj, allow
    75  p, trudy, applications/*, get, foo/obj, allow
    76  p, trudy, applications/secrets, get, foo/obj, deny
    77  p, danny, applications, get, */obj, allow
    78  p, danny, applications, get, proj1/a*p1, allow
    79  `
    80  	_ = enf.SetUserPolicy(policy)
    81  
    82  	// Verify the resource wildcard
    83  	assert.True(t, enf.Enforce("alice", "applications", "get", "foo/obj"))
    84  	assert.True(t, enf.Enforce("alice", "applications/resources", "get", "foo/obj"))
    85  	assert.False(t, enf.Enforce("alice", "applications/resources", "delete", "foo/obj"))
    86  
    87  	// Verify action wildcards work
    88  	assert.True(t, enf.Enforce("bob", "repositories", "get", "foo/obj"))
    89  	assert.True(t, enf.Enforce("bob", "repositories", "delete", "foo/obj"))
    90  	assert.False(t, enf.Enforce("bob", "applications", "get", "foo/obj"))
    91  
    92  	// Verify resource and action wildcards work in conjunction
    93  	assert.True(t, enf.Enforce("cathy", "repositories", "get", "foo/obj"))
    94  	assert.True(t, enf.Enforce("cathy", "repositories", "delete", "foo/obj"))
    95  	assert.True(t, enf.Enforce("cathy", "applications", "get", "foo/obj"))
    96  	assert.True(t, enf.Enforce("cathy", "applications/resources", "delete", "foo/obj"))
    97  
    98  	// Verify wildcards with sub-resources
    99  	assert.True(t, enf.Enforce("dave", "applications", "get", "foo/obj"))
   100  	assert.True(t, enf.Enforce("dave", "applications/logs", "get", "foo/obj"))
   101  
   102  	// Verify the resource wildcard
   103  	assert.False(t, enf.Enforce("eve", "applications", "get", "foo/obj"))
   104  	assert.False(t, enf.Enforce("eve", "applications/resources", "get", "foo/obj"))
   105  	assert.False(t, enf.Enforce("eve", "applications/resources", "delete", "foo/obj"))
   106  
   107  	// Verify action wildcards work
   108  	assert.False(t, enf.Enforce("mallory", "repositories", "get", "foo/obj"))
   109  	assert.False(t, enf.Enforce("mallory", "repositories", "delete", "foo/obj"))
   110  	assert.False(t, enf.Enforce("mallory", "applications", "get", "foo/obj"))
   111  
   112  	// Verify resource and action wildcards work in conjunction
   113  	assert.False(t, enf.Enforce("mike", "repositories", "get", "foo/obj"))
   114  	assert.False(t, enf.Enforce("mike", "repositories", "delete", "foo/obj"))
   115  	assert.False(t, enf.Enforce("mike", "applications", "get", "foo/obj"))
   116  	assert.False(t, enf.Enforce("mike", "applications/resources", "delete", "foo/obj"))
   117  
   118  	// Verify wildcards with sub-resources
   119  	assert.True(t, enf.Enforce("trudy", "applications", "get", "foo/obj"))
   120  	assert.True(t, enf.Enforce("trudy", "applications/logs", "get", "foo/obj"))
   121  	assert.False(t, enf.Enforce("trudy", "applications/secrets", "get", "foo/obj"))
   122  
   123  	// Verify trailing wildcards don't grant full access
   124  	assert.True(t, enf.Enforce("danny", "applications", "get", "foo/obj"))
   125  	assert.True(t, enf.Enforce("danny", "applications", "get", "bar/obj"))
   126  	assert.False(t, enf.Enforce("danny", "applications", "get", "foo/bar"))
   127  	assert.True(t, enf.Enforce("danny", "applications", "get", "proj1/app1"))
   128  	assert.False(t, enf.Enforce("danny", "applications", "get", "proj1/app2"))
   129  }