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

     1  //go:build !race
     2  // +build !race
     3  
     4  package rbac
     5  
     6  import (
     7  	"context"
     8  	"testing"
     9  	"time"
    10  
    11  	"github.com/stretchr/testify/assert"
    12  	"github.com/stretchr/testify/require"
    13  	corev1 "k8s.io/api/core/v1"
    14  	"k8s.io/client-go/kubernetes/fake"
    15  )
    16  
    17  // TestPolicyInformer verifies the informer will get updated with a new configmap
    18  func TestPolicyInformer(t *testing.T) {
    19  	// !race:
    20  	// A BUNCH of data race warnings thrown by running this test and the next... it's tough to guess to what degree this
    21  	// is primarily a casbin issue or a Argo CD RBAC issue... A least one data race is an `rbac.go` with
    22  	// 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`
    23  	//
    24  	// It couldn't hurt to take a look at this code to decide if Argo CD is properly handling concurrent data
    25  	// access here, but in the mean time I have disabled data race testing of this test.
    26  
    27  	cm := fakeConfigMap()
    28  	cm.Data[ConfigMapPolicyCSVKey] = "p, admin, applications, delete, */*, allow"
    29  	kubeclientset := fake.NewClientset(cm)
    30  	enf := NewEnforcer(kubeclientset, fakeNamespace, fakeConfigMapName, nil)
    31  
    32  	ctx := t.Context()
    33  	ctx, cancel := context.WithCancel(ctx)
    34  	defer cancel()
    35  	go enf.runInformer(ctx, func(_ *corev1.ConfigMap) error {
    36  		return nil
    37  	})
    38  
    39  	loaded := false
    40  	for i := 1; i <= 20; i++ {
    41  		if enf.Enforce("admin", "applications", "delete", "foo/bar") {
    42  			loaded = true
    43  			break
    44  		}
    45  		time.Sleep(50 * time.Millisecond)
    46  	}
    47  	assert.True(t, loaded, "Policy update failed to load")
    48  
    49  	// update the configmap and update policy
    50  	delete(cm.Data, ConfigMapPolicyCSVKey)
    51  	err := enf.syncUpdate(cm, noOpUpdate)
    52  	require.NoError(t, err)
    53  	assert.False(t, enf.Enforce("admin", "applications", "delete", "foo/bar"))
    54  }
    55  
    56  // TestResourceActionWildcards verifies the ability to use wildcards in resources and actions
    57  func TestResourceActionWildcards(t *testing.T) {
    58  	// !race:
    59  	// Same as TestPolicyInformer
    60  
    61  	kubeclientset := fake.NewClientset(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  }