github.com/argoproj/argo-cd/v2@v2.10.9/server/project/project_test.go (about)

     1  package project
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"strings"
     7  	"testing"
     8  
     9  	"github.com/argoproj/argo-cd/v2/util/db"
    10  
    11  	"github.com/argoproj/pkg/sync"
    12  	"github.com/golang-jwt/jwt/v4"
    13  	"github.com/google/uuid"
    14  	"github.com/stretchr/testify/assert"
    15  	"google.golang.org/grpc/codes"
    16  	"google.golang.org/grpc/status"
    17  	corev1 "k8s.io/api/core/v1"
    18  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    19  	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    20  	"k8s.io/client-go/kubernetes/fake"
    21  	k8scache "k8s.io/client-go/tools/cache"
    22  
    23  	"github.com/argoproj/argo-cd/v2/common"
    24  	"github.com/argoproj/argo-cd/v2/pkg/apiclient/project"
    25  	"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
    26  	apps "github.com/argoproj/argo-cd/v2/pkg/client/clientset/versioned/fake"
    27  	informer "github.com/argoproj/argo-cd/v2/pkg/client/informers/externalversions"
    28  	"github.com/argoproj/argo-cd/v2/server/rbacpolicy"
    29  	"github.com/argoproj/argo-cd/v2/test"
    30  	"github.com/argoproj/argo-cd/v2/util/assets"
    31  	jwtutil "github.com/argoproj/argo-cd/v2/util/jwt"
    32  	"github.com/argoproj/argo-cd/v2/util/rbac"
    33  	"github.com/argoproj/argo-cd/v2/util/session"
    34  	"github.com/argoproj/argo-cd/v2/util/settings"
    35  )
    36  
    37  const testNamespace = "default"
    38  
    39  func TestProjectServer(t *testing.T) {
    40  	kubeclientset := fake.NewSimpleClientset(&corev1.ConfigMap{
    41  		ObjectMeta: v1.ObjectMeta{
    42  			Namespace: testNamespace,
    43  			Name:      "argocd-cm",
    44  			Labels: map[string]string{
    45  				"app.kubernetes.io/part-of": "argocd",
    46  			},
    47  		},
    48  	}, &corev1.Secret{
    49  		ObjectMeta: v1.ObjectMeta{
    50  			Name:      "argocd-secret",
    51  			Namespace: testNamespace,
    52  		},
    53  		Data: map[string][]byte{
    54  			"admin.password":   []byte("test"),
    55  			"server.secretkey": []byte("test"),
    56  		},
    57  	})
    58  	settingsMgr := settings.NewSettingsManager(context.Background(), kubeclientset, testNamespace)
    59  	enforcer := newEnforcer(kubeclientset)
    60  	existingProj := v1alpha1.AppProject{
    61  		ObjectMeta: v1.ObjectMeta{Name: "test", Namespace: testNamespace},
    62  		Spec: v1alpha1.AppProjectSpec{
    63  			Destinations: []v1alpha1.ApplicationDestination{
    64  				{Namespace: "ns1", Server: "https://server1"},
    65  				{Namespace: "ns2", Server: "https://server2"},
    66  			},
    67  			SourceRepos: []string{"https://github.com/argoproj/argo-cd.git"},
    68  		},
    69  	}
    70  	existingApp := v1alpha1.Application{
    71  		ObjectMeta: v1.ObjectMeta{Name: "test", Namespace: "default"},
    72  		Spec:       v1alpha1.ApplicationSpec{Source: &v1alpha1.ApplicationSource{}, Project: "test", Destination: v1alpha1.ApplicationDestination{Namespace: "ns3", Server: "https://server3"}},
    73  	}
    74  
    75  	policyTemplate := "p, proj:%s:%s, applications, %s, %s/%s, %s"
    76  
    77  	ctx := context.Background()
    78  	fakeAppsClientset := apps.NewSimpleClientset()
    79  	factory := informer.NewSharedInformerFactoryWithOptions(fakeAppsClientset, 0, informer.WithNamespace(""), informer.WithTweakListOptions(func(options *metav1.ListOptions) {}))
    80  	projInformer := factory.Argoproj().V1alpha1().AppProjects().Informer()
    81  	go projInformer.Run(ctx.Done())
    82  	if !k8scache.WaitForCacheSync(ctx.Done(), projInformer.HasSynced) {
    83  		panic("Timed out waiting forfff caches to sync")
    84  	}
    85  
    86  	t.Run("TestNormalizeProj", func(t *testing.T) {
    87  		sessionMgr := session.NewSessionManager(settingsMgr, test.NewFakeProjLister(), "", nil, session.NewUserStateStorage(nil))
    88  		projectWithRole := existingProj.DeepCopy()
    89  		roleName := "roleName"
    90  		role1 := v1alpha1.ProjectRole{Name: roleName, JWTTokens: []v1alpha1.JWTToken{{IssuedAt: 1}}}
    91  		projectWithRole.Spec.Roles = append(projectWithRole.Spec.Roles, role1)
    92  		argoDB := db.NewDB("default", settingsMgr, kubeclientset)
    93  		projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(projectWithRole), enforcer, sync.NewKeyLock(), sessionMgr, nil, projInformer, settingsMgr, argoDB)
    94  		err := projectServer.NormalizeProjs()
    95  		assert.NoError(t, err)
    96  
    97  		appList, err := projectServer.appclientset.ArgoprojV1alpha1().AppProjects(projectWithRole.Namespace).List(context.Background(), v1.ListOptions{})
    98  		assert.NoError(t, err)
    99  		assert.Equal(t, appList.Items[0].Status.JWTTokensByRole[roleName].Items[0].IssuedAt, int64(1))
   100  		assert.ElementsMatch(t, appList.Items[0].Status.JWTTokensByRole[roleName].Items, appList.Items[0].Spec.Roles[0].JWTTokens)
   101  
   102  	})
   103  
   104  	t.Run("TestClusterUpdateDenied", func(t *testing.T) {
   105  
   106  		enforcer.SetDefaultRole("role:projects")
   107  		_ = enforcer.SetBuiltinPolicy("p, role:projects, projects, update, *, allow")
   108  		argoDB := db.NewDB("default", settingsMgr, kubeclientset)
   109  		projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(&existingProj, &existingApp), enforcer, sync.NewKeyLock(), nil, nil, projInformer, settingsMgr, argoDB)
   110  
   111  		updatedProj := existingProj.DeepCopy()
   112  		updatedProj.Spec.Destinations = nil
   113  
   114  		_, err := projectServer.Update(context.Background(), &project.ProjectUpdateRequest{Project: updatedProj})
   115  
   116  		assert.Equal(t, status.Error(codes.PermissionDenied, "permission denied: clusters, update, https://server1"), err)
   117  	})
   118  
   119  	t.Run("TestReposUpdateDenied", func(t *testing.T) {
   120  
   121  		enforcer.SetDefaultRole("role:projects")
   122  		_ = enforcer.SetBuiltinPolicy("p, role:projects, projects, update, *, allow")
   123  		argoDB := db.NewDB("default", settingsMgr, kubeclientset)
   124  		projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(&existingProj, &existingApp), enforcer, sync.NewKeyLock(), nil, nil, projInformer, settingsMgr, argoDB)
   125  
   126  		updatedProj := existingProj.DeepCopy()
   127  		updatedProj.Spec.SourceRepos = nil
   128  
   129  		_, err := projectServer.Update(context.Background(), &project.ProjectUpdateRequest{Project: updatedProj})
   130  
   131  		assert.Equal(t, status.Error(codes.PermissionDenied, "permission denied: repositories, update, https://github.com/argoproj/argo-cd.git"), err)
   132  	})
   133  
   134  	t.Run("TestClusterResourceWhitelistUpdateDenied", func(t *testing.T) {
   135  
   136  		enforcer.SetDefaultRole("role:projects")
   137  		_ = enforcer.SetBuiltinPolicy("p, role:projects, projects, update, *, allow")
   138  		argoDB := db.NewDB("default", settingsMgr, kubeclientset)
   139  		projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(&existingProj, &existingApp), enforcer, sync.NewKeyLock(), nil, nil, projInformer, settingsMgr, argoDB)
   140  
   141  		updatedProj := existingProj.DeepCopy()
   142  		updatedProj.Spec.ClusterResourceWhitelist = []metav1.GroupKind{{}}
   143  
   144  		_, err := projectServer.Update(context.Background(), &project.ProjectUpdateRequest{Project: updatedProj})
   145  
   146  		assert.Equal(t, status.Error(codes.PermissionDenied, "permission denied: clusters, update, https://server1"), err)
   147  	})
   148  
   149  	t.Run("TestNamespaceResourceBlacklistUpdateDenied", func(t *testing.T) {
   150  
   151  		enforcer.SetDefaultRole("role:projects")
   152  		_ = enforcer.SetBuiltinPolicy("p, role:projects, projects, update, *, allow")
   153  		argoDB := db.NewDB("default", settingsMgr, kubeclientset)
   154  		projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(&existingProj, &existingApp), enforcer, sync.NewKeyLock(), nil, nil, projInformer, settingsMgr, argoDB)
   155  
   156  		updatedProj := existingProj.DeepCopy()
   157  		updatedProj.Spec.NamespaceResourceBlacklist = []metav1.GroupKind{{}}
   158  
   159  		_, err := projectServer.Update(context.Background(), &project.ProjectUpdateRequest{Project: updatedProj})
   160  
   161  		assert.Equal(t, status.Error(codes.PermissionDenied, "permission denied: clusters, update, https://server1"), err)
   162  	})
   163  
   164  	enforcer = newEnforcer(kubeclientset)
   165  
   166  	t.Run("TestRemoveDestinationSuccessful", func(t *testing.T) {
   167  		existingApp := v1alpha1.Application{
   168  			ObjectMeta: v1.ObjectMeta{Name: "test", Namespace: "default"},
   169  			Spec:       v1alpha1.ApplicationSpec{Source: &v1alpha1.ApplicationSource{}, Project: "test", Destination: v1alpha1.ApplicationDestination{Namespace: "ns3", Server: "https://server3"}},
   170  		}
   171  
   172  		argoDB := db.NewDB("default", settingsMgr, kubeclientset)
   173  		projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(&existingProj, &existingApp), enforcer, sync.NewKeyLock(), nil, nil, projInformer, settingsMgr, argoDB)
   174  
   175  		updatedProj := existingProj.DeepCopy()
   176  		updatedProj.Spec.Destinations = updatedProj.Spec.Destinations[1:]
   177  
   178  		_, err := projectServer.Update(context.Background(), &project.ProjectUpdateRequest{Project: updatedProj})
   179  
   180  		assert.Nil(t, err)
   181  	})
   182  
   183  	t.Run("TestRemoveDestinationUsedByApp", func(t *testing.T) {
   184  		existingApp := v1alpha1.Application{
   185  			ObjectMeta: v1.ObjectMeta{Name: "test", Namespace: "default"},
   186  			Spec:       v1alpha1.ApplicationSpec{Source: &v1alpha1.ApplicationSource{}, Project: "test", Destination: v1alpha1.ApplicationDestination{Namespace: "ns1", Server: "https://server1"}},
   187  		}
   188  
   189  		argoDB := db.NewDB("default", settingsMgr, kubeclientset)
   190  		projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(&existingProj, &existingApp), enforcer, sync.NewKeyLock(), nil, nil, projInformer, settingsMgr, argoDB)
   191  
   192  		updatedProj := existingProj.DeepCopy()
   193  		updatedProj.Spec.Destinations = updatedProj.Spec.Destinations[1:]
   194  
   195  		_, err := projectServer.Update(context.Background(), &project.ProjectUpdateRequest{Project: updatedProj})
   196  
   197  		assert.NotNil(t, err)
   198  		statusCode, _ := status.FromError(err)
   199  		assert.Equal(t, codes.InvalidArgument, statusCode.Code())
   200  	})
   201  
   202  	t.Run("TestRemoveSourceSuccessful", func(t *testing.T) {
   203  		existingApp := v1alpha1.Application{
   204  			ObjectMeta: v1.ObjectMeta{Name: "test", Namespace: "default"},
   205  			Spec:       v1alpha1.ApplicationSpec{Source: &v1alpha1.ApplicationSource{}, Project: "test"},
   206  		}
   207  
   208  		argoDB := db.NewDB("default", settingsMgr, kubeclientset)
   209  		projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(&existingProj, &existingApp), enforcer, sync.NewKeyLock(), nil, nil, projInformer, settingsMgr, argoDB)
   210  
   211  		updatedProj := existingProj.DeepCopy()
   212  		updatedProj.Spec.SourceRepos = []string{}
   213  
   214  		_, err := projectServer.Update(context.Background(), &project.ProjectUpdateRequest{Project: updatedProj})
   215  
   216  		assert.Nil(t, err)
   217  	})
   218  
   219  	t.Run("TestRemoveSourceUsedByApp", func(t *testing.T) {
   220  		existingApp := v1alpha1.Application{
   221  			ObjectMeta: v1.ObjectMeta{Name: "test", Namespace: "default"},
   222  			Spec:       v1alpha1.ApplicationSpec{Project: "test", Source: &v1alpha1.ApplicationSource{RepoURL: "https://github.com/argoproj/argo-cd.git"}},
   223  		}
   224  
   225  		argoDB := db.NewDB("default", settingsMgr, kubeclientset)
   226  		projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(&existingProj, &existingApp), enforcer, sync.NewKeyLock(), nil, nil, projInformer, settingsMgr, argoDB)
   227  
   228  		updatedProj := existingProj.DeepCopy()
   229  		updatedProj.Spec.SourceRepos = []string{}
   230  
   231  		_, err := projectServer.Update(context.Background(), &project.ProjectUpdateRequest{Project: updatedProj})
   232  
   233  		assert.NotNil(t, err)
   234  		statusCode, _ := status.FromError(err)
   235  		assert.Equal(t, codes.InvalidArgument, statusCode.Code())
   236  	})
   237  
   238  	t.Run("TestRemoveSourceUsedByAppSuccessfulIfPermittedByAnotherSrc", func(t *testing.T) {
   239  		proj := existingProj.DeepCopy()
   240  		proj.Spec.SourceRepos = []string{"https://github.com/argoproj/argo-cd.git", "https://github.com/argoproj/*"}
   241  		existingApp := v1alpha1.Application{
   242  			ObjectMeta: v1.ObjectMeta{Name: "test", Namespace: "default"},
   243  			Spec:       v1alpha1.ApplicationSpec{Project: "test", Source: &v1alpha1.ApplicationSource{RepoURL: "https://github.com/argoproj/argo-cd.git"}},
   244  		}
   245  		argoDB := db.NewDB("default", settingsMgr, kubeclientset)
   246  		projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(proj, &existingApp), enforcer, sync.NewKeyLock(), nil, nil, projInformer, settingsMgr, argoDB)
   247  
   248  		updatedProj := proj.DeepCopy()
   249  		updatedProj.Spec.SourceRepos = []string{"https://github.com/argoproj/*"}
   250  
   251  		res, err := projectServer.Update(context.Background(), &project.ProjectUpdateRequest{Project: updatedProj})
   252  
   253  		assert.NoError(t, err)
   254  		assert.ElementsMatch(t, res.Spec.SourceRepos, updatedProj.Spec.SourceRepos)
   255  	})
   256  
   257  	t.Run("TestRemoveDestinationUsedByAppSuccessfulIfPermittedByAnotherDestination", func(t *testing.T) {
   258  		proj := existingProj.DeepCopy()
   259  		proj.Spec.Destinations = []v1alpha1.ApplicationDestination{
   260  			{Namespace: "org1-team1", Server: "https://server1"},
   261  			{Namespace: "org1-*", Server: "https://server1"},
   262  		}
   263  		existingApp := v1alpha1.Application{
   264  			ObjectMeta: v1.ObjectMeta{Name: "test", Namespace: "default"},
   265  			Spec: v1alpha1.ApplicationSpec{Source: &v1alpha1.ApplicationSource{}, Project: "test", Destination: v1alpha1.ApplicationDestination{
   266  				Server:    "https://server1",
   267  				Namespace: "org1-team1",
   268  			}},
   269  		}
   270  
   271  		argoDB := db.NewDB("default", settingsMgr, kubeclientset)
   272  
   273  		projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(proj, &existingApp), enforcer, sync.NewKeyLock(), nil, nil, projInformer, settingsMgr, argoDB)
   274  
   275  		updatedProj := proj.DeepCopy()
   276  		updatedProj.Spec.Destinations = []v1alpha1.ApplicationDestination{
   277  			{Namespace: "org1-*", Server: "https://server1"},
   278  		}
   279  
   280  		res, err := projectServer.Update(context.Background(), &project.ProjectUpdateRequest{Project: updatedProj})
   281  
   282  		assert.NoError(t, err)
   283  		assert.ElementsMatch(t, res.Spec.Destinations, updatedProj.Spec.Destinations)
   284  	})
   285  
   286  	t.Run("TestDeleteProjectSuccessful", func(t *testing.T) {
   287  		argoDB := db.NewDB("default", settingsMgr, kubeclientset)
   288  		projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(&existingProj), enforcer, sync.NewKeyLock(), nil, nil, projInformer, settingsMgr, argoDB)
   289  
   290  		_, err := projectServer.Delete(context.Background(), &project.ProjectQuery{Name: "test"})
   291  
   292  		assert.Nil(t, err)
   293  	})
   294  
   295  	t.Run("TestDeleteDefaultProjectFailure", func(t *testing.T) {
   296  		defaultProj := v1alpha1.AppProject{
   297  			ObjectMeta: v1.ObjectMeta{Name: "default", Namespace: "default"},
   298  			Spec:       v1alpha1.AppProjectSpec{},
   299  		}
   300  		argoDB := db.NewDB("default", settingsMgr, kubeclientset)
   301  		projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(&defaultProj), enforcer, sync.NewKeyLock(), nil, nil, projInformer, settingsMgr, argoDB)
   302  
   303  		_, err := projectServer.Delete(context.Background(), &project.ProjectQuery{Name: defaultProj.Name})
   304  		statusCode, _ := status.FromError(err)
   305  		assert.Equal(t, codes.InvalidArgument, statusCode.Code())
   306  	})
   307  
   308  	t.Run("TestDeleteProjectReferencedByApp", func(t *testing.T) {
   309  		existingApp := v1alpha1.Application{
   310  			ObjectMeta: v1.ObjectMeta{Name: "test", Namespace: "default"},
   311  			Spec:       v1alpha1.ApplicationSpec{Project: "test"},
   312  		}
   313  
   314  		argoDB := db.NewDB("default", settingsMgr, kubeclientset)
   315  		projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(&existingProj, &existingApp), enforcer, sync.NewKeyLock(), nil, nil, projInformer, settingsMgr, argoDB)
   316  
   317  		_, err := projectServer.Delete(context.Background(), &project.ProjectQuery{Name: "test"})
   318  
   319  		assert.NotNil(t, err)
   320  		statusCode, _ := status.FromError(err)
   321  		assert.Equal(t, codes.InvalidArgument, statusCode.Code())
   322  	})
   323  
   324  	// configure a user named "admin" which is denied by default
   325  	enforcer = newEnforcer(kubeclientset)
   326  	_ = enforcer.SetBuiltinPolicy(`p, *, *, *, *, deny`)
   327  	enforcer.SetClaimsEnforcerFunc(nil)
   328  	// nolint:staticcheck
   329  	ctx = context.WithValue(context.Background(), "claims", &jwt.MapClaims{"groups": []string{"my-group"}})
   330  	policyEnf := rbacpolicy.NewRBACPolicyEnforcer(enforcer, nil)
   331  	policyEnf.SetScopes([]string{"groups"})
   332  
   333  	tokenName := "testToken"
   334  	id := "testId"
   335  
   336  	t.Run("TestCreateTokenDenied", func(t *testing.T) {
   337  		sessionMgr := session.NewSessionManager(settingsMgr, test.NewFakeProjLister(), "", nil, session.NewUserStateStorage(nil))
   338  		projectWithRole := existingProj.DeepCopy()
   339  		projectWithRole.Spec.Roles = []v1alpha1.ProjectRole{{Name: tokenName}}
   340  
   341  		argoDB := db.NewDB("default", settingsMgr, kubeclientset)
   342  		projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(projectWithRole), enforcer, sync.NewKeyLock(), sessionMgr, policyEnf, projInformer, settingsMgr, argoDB)
   343  		_, err := projectServer.CreateToken(ctx, &project.ProjectTokenCreateRequest{Project: projectWithRole.Name, Role: tokenName, ExpiresIn: 1})
   344  		assert.EqualError(t, err, "rpc error: code = PermissionDenied desc = permission denied: projects, update, test")
   345  	})
   346  
   347  	t.Run("TestCreateTokenSuccessfullyUsingGroup", func(t *testing.T) {
   348  		sessionMgr := session.NewSessionManager(settingsMgr, test.NewFakeProjLister(), "", nil, session.NewUserStateStorage(nil))
   349  		projectWithRole := existingProj.DeepCopy()
   350  		projectWithRole.Spec.Roles = []v1alpha1.ProjectRole{{Name: tokenName, Groups: []string{"my-group"}}}
   351  		argoDB := db.NewDB("default", settingsMgr, kubeclientset)
   352  		projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(projectWithRole), enforcer, sync.NewKeyLock(), sessionMgr, policyEnf, projInformer, settingsMgr, argoDB)
   353  		_, err := projectServer.CreateToken(ctx, &project.ProjectTokenCreateRequest{Project: projectWithRole.Name, Role: tokenName, ExpiresIn: 1})
   354  		assert.NoError(t, err)
   355  	})
   356  
   357  	_ = enforcer.SetBuiltinPolicy(`p, role:admin, projects, update, *, allow`)
   358  
   359  	t.Run("TestCreateTokenSuccessfully", func(t *testing.T) {
   360  		projectWithRole := existingProj.DeepCopy()
   361  		projectWithRole.Spec.Roles = []v1alpha1.ProjectRole{{Name: tokenName}}
   362  		clientset := apps.NewSimpleClientset(projectWithRole)
   363  
   364  		sessionMgr := session.NewSessionManager(settingsMgr, test.NewFakeProjListerFromInterface(clientset.ArgoprojV1alpha1().AppProjects("default")), "", nil, session.NewUserStateStorage(nil))
   365  		argoDB := db.NewDB("default", settingsMgr, kubeclientset)
   366  		projectServer := NewServer("default", fake.NewSimpleClientset(), clientset, enforcer, sync.NewKeyLock(), sessionMgr, policyEnf, projInformer, settingsMgr, argoDB)
   367  		tokenResponse, err := projectServer.CreateToken(context.Background(), &project.ProjectTokenCreateRequest{Project: projectWithRole.Name, Role: tokenName, ExpiresIn: 100})
   368  		assert.NoError(t, err)
   369  		claims, _, err := sessionMgr.Parse(tokenResponse.Token)
   370  		assert.NoError(t, err)
   371  
   372  		mapClaims, err := jwtutil.MapClaims(claims)
   373  		subject, ok := mapClaims["sub"].(string)
   374  		assert.True(t, ok)
   375  		expectedSubject := fmt.Sprintf(JWTTokenSubFormat, projectWithRole.Name, tokenName)
   376  		assert.Equal(t, expectedSubject, subject)
   377  		assert.NoError(t, err)
   378  	})
   379  
   380  	t.Run("TestCreateTokenWithIDSuccessfully", func(t *testing.T) {
   381  		projectWithRole := existingProj.DeepCopy()
   382  		projectWithRole.Spec.Roles = []v1alpha1.ProjectRole{{Name: tokenName}}
   383  		clientset := apps.NewSimpleClientset(projectWithRole)
   384  
   385  		sessionMgr := session.NewSessionManager(settingsMgr, test.NewFakeProjListerFromInterface(clientset.ArgoprojV1alpha1().AppProjects("default")), "", nil, session.NewUserStateStorage(nil))
   386  		argoDB := db.NewDB("default", settingsMgr, kubeclientset)
   387  		projectServer := NewServer("default", fake.NewSimpleClientset(), clientset, enforcer, sync.NewKeyLock(), sessionMgr, policyEnf, projInformer, settingsMgr, argoDB)
   388  		tokenResponse, err := projectServer.CreateToken(context.Background(), &project.ProjectTokenCreateRequest{Project: projectWithRole.Name, Role: tokenName, ExpiresIn: 1, Id: id})
   389  		assert.NoError(t, err)
   390  		claims, _, err := sessionMgr.Parse(tokenResponse.Token)
   391  		assert.NoError(t, err)
   392  
   393  		mapClaims, err := jwtutil.MapClaims(claims)
   394  		subject, ok := mapClaims["sub"].(string)
   395  		assert.True(t, ok)
   396  		expectedSubject := fmt.Sprintf(JWTTokenSubFormat, projectWithRole.Name, tokenName)
   397  		assert.Equal(t, expectedSubject, subject)
   398  		assert.NoError(t, err)
   399  	})
   400  
   401  	t.Run("TestCreateTokenWithSameIdDeny", func(t *testing.T) {
   402  		projectWithRole := existingProj.DeepCopy()
   403  		projectWithRole.Spec.Roles = []v1alpha1.ProjectRole{{Name: tokenName}}
   404  		clientset := apps.NewSimpleClientset(projectWithRole)
   405  
   406  		sessionMgr := session.NewSessionManager(settingsMgr, test.NewFakeProjListerFromInterface(clientset.ArgoprojV1alpha1().AppProjects("default")), "", nil, session.NewUserStateStorage(nil))
   407  		argoDB := db.NewDB("default", settingsMgr, kubeclientset)
   408  		projectServer := NewServer("default", fake.NewSimpleClientset(), clientset, enforcer, sync.NewKeyLock(), sessionMgr, policyEnf, projInformer, settingsMgr, argoDB)
   409  		tokenResponse, err := projectServer.CreateToken(context.Background(), &project.ProjectTokenCreateRequest{Project: projectWithRole.Name, Role: tokenName, ExpiresIn: 1, Id: id})
   410  
   411  		assert.NoError(t, err)
   412  		claims, _, err := sessionMgr.Parse(tokenResponse.Token)
   413  		assert.NoError(t, err)
   414  
   415  		mapClaims, err := jwtutil.MapClaims(claims)
   416  		subject, ok := mapClaims["sub"].(string)
   417  		assert.True(t, ok)
   418  		expectedSubject := fmt.Sprintf(JWTTokenSubFormat, projectWithRole.Name, tokenName)
   419  		assert.Equal(t, expectedSubject, subject)
   420  		assert.NoError(t, err)
   421  
   422  		_, err1 := projectServer.CreateToken(context.Background(), &project.ProjectTokenCreateRequest{Project: projectWithRole.Name, Role: tokenName, ExpiresIn: 1, Id: id})
   423  		expectedErr := fmt.Sprintf("rpc error: code = InvalidArgument desc = rpc error: code = InvalidArgument desc = Token id '%s' has been used. ", id)
   424  		assert.EqualError(t, err1, expectedErr)
   425  	})
   426  
   427  	_ = enforcer.SetBuiltinPolicy(`p, *, *, *, *, deny`)
   428  
   429  	t.Run("TestDeleteTokenDenied", func(t *testing.T) {
   430  		sessionMgr := session.NewSessionManager(settingsMgr, test.NewFakeProjLister(), "", nil, session.NewUserStateStorage(nil))
   431  		projWithToken := existingProj.DeepCopy()
   432  		issuedAt := int64(1)
   433  		secondIssuedAt := issuedAt + 1
   434  		token := v1alpha1.ProjectRole{Name: tokenName, JWTTokens: []v1alpha1.JWTToken{{IssuedAt: issuedAt}, {IssuedAt: secondIssuedAt}}}
   435  		projWithToken.Spec.Roles = append(projWithToken.Spec.Roles, token)
   436  		argoDB := db.NewDB("default", settingsMgr, kubeclientset)
   437  		projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(projWithToken), enforcer, sync.NewKeyLock(), sessionMgr, policyEnf, projInformer, settingsMgr, argoDB)
   438  		_, err := projectServer.DeleteToken(ctx, &project.ProjectTokenDeleteRequest{Project: projWithToken.Name, Role: tokenName, Iat: issuedAt})
   439  		assert.EqualError(t, err, "rpc error: code = PermissionDenied desc = permission denied: projects, update, test")
   440  	})
   441  
   442  	t.Run("TestDeleteTokenSuccessfullyWithGroup", func(t *testing.T) {
   443  		sessionMgr := session.NewSessionManager(settingsMgr, test.NewFakeProjLister(), "", nil, session.NewUserStateStorage(nil))
   444  		projWithToken := existingProj.DeepCopy()
   445  		issuedAt := int64(1)
   446  		secondIssuedAt := issuedAt + 1
   447  		token := v1alpha1.ProjectRole{Name: tokenName, Groups: []string{"my-group"}, JWTTokens: []v1alpha1.JWTToken{{IssuedAt: issuedAt}, {IssuedAt: secondIssuedAt}}}
   448  		projWithToken.Spec.Roles = append(projWithToken.Spec.Roles, token)
   449  		argoDB := db.NewDB("default", settingsMgr, kubeclientset)
   450  		projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(projWithToken), enforcer, sync.NewKeyLock(), sessionMgr, policyEnf, projInformer, settingsMgr, argoDB)
   451  		_, err := projectServer.DeleteToken(ctx, &project.ProjectTokenDeleteRequest{Project: projWithToken.Name, Role: tokenName, Iat: issuedAt})
   452  		assert.NoError(t, err)
   453  	})
   454  
   455  	_ = enforcer.SetBuiltinPolicy(`p, role:admin, projects, get, *, allow
   456  p, role:admin, projects, update, *, allow`)
   457  
   458  	t.Run("TestDeleteTokenSuccessfully", func(t *testing.T) {
   459  		sessionMgr := session.NewSessionManager(settingsMgr, test.NewFakeProjLister(), "", nil, session.NewUserStateStorage(nil))
   460  		projWithToken := existingProj.DeepCopy()
   461  		issuedAt := int64(1)
   462  		secondIssuedAt := issuedAt + 1
   463  		token := v1alpha1.ProjectRole{Name: tokenName, JWTTokens: []v1alpha1.JWTToken{{IssuedAt: issuedAt}, {IssuedAt: secondIssuedAt}}}
   464  		projWithToken.Spec.Roles = append(projWithToken.Spec.Roles, token)
   465  		argoDB := db.NewDB("default", settingsMgr, kubeclientset)
   466  		projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(projWithToken), enforcer, sync.NewKeyLock(), sessionMgr, policyEnf, projInformer, settingsMgr, argoDB)
   467  		_, err := projectServer.DeleteToken(ctx, &project.ProjectTokenDeleteRequest{Project: projWithToken.Name, Role: tokenName, Iat: issuedAt})
   468  		assert.NoError(t, err)
   469  		projWithoutToken, err := projectServer.Get(context.Background(), &project.ProjectQuery{Name: projWithToken.Name})
   470  		assert.NoError(t, err)
   471  		assert.Len(t, projWithoutToken.Spec.Roles, 1)
   472  		assert.Len(t, projWithoutToken.Spec.Roles[0].JWTTokens, 1)
   473  		assert.Equal(t, projWithoutToken.Spec.Roles[0].JWTTokens[0].IssuedAt, secondIssuedAt)
   474  	})
   475  
   476  	_ = enforcer.SetBuiltinPolicy(`p, role:admin, projects, get, *, allow
   477  p, role:admin, projects, update, *, allow`)
   478  
   479  	t.Run("TestDeleteTokenByIdSuccessfully", func(t *testing.T) {
   480  		sessionMgr := session.NewSessionManager(settingsMgr, test.NewFakeProjLister(), "", nil, session.NewUserStateStorage(nil))
   481  		projWithToken := existingProj.DeepCopy()
   482  		issuedAt := int64(1)
   483  		secondIssuedAt := issuedAt + 1
   484  		id := "testId"
   485  		uniqueId, _ := uuid.NewRandom()
   486  		secondId := uniqueId.String()
   487  		token := v1alpha1.ProjectRole{Name: tokenName, JWTTokens: []v1alpha1.JWTToken{{IssuedAt: issuedAt, ID: id}, {IssuedAt: secondIssuedAt, ID: secondId}}}
   488  		projWithToken.Spec.Roles = append(projWithToken.Spec.Roles, token)
   489  		argoDB := db.NewDB("default", settingsMgr, kubeclientset)
   490  		projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(projWithToken), enforcer, sync.NewKeyLock(), sessionMgr, policyEnf, projInformer, settingsMgr, argoDB)
   491  		_, err := projectServer.DeleteToken(ctx, &project.ProjectTokenDeleteRequest{Project: projWithToken.Name, Role: tokenName, Iat: secondIssuedAt, Id: id})
   492  		assert.NoError(t, err)
   493  		projWithoutToken, err := projectServer.Get(context.Background(), &project.ProjectQuery{Name: projWithToken.Name})
   494  		assert.NoError(t, err)
   495  		assert.Len(t, projWithoutToken.Spec.Roles, 1)
   496  		assert.Len(t, projWithoutToken.Spec.Roles[0].JWTTokens, 1)
   497  		assert.Equal(t, projWithoutToken.Spec.Roles[0].JWTTokens[0].IssuedAt, secondIssuedAt)
   498  	})
   499  
   500  	enforcer = newEnforcer(kubeclientset)
   501  
   502  	t.Run("TestCreateTwoTokensInRoleSuccess", func(t *testing.T) {
   503  		sessionMgr := session.NewSessionManager(settingsMgr, test.NewFakeProjLister(), "", nil, session.NewUserStateStorage(nil))
   504  		projWithToken := existingProj.DeepCopy()
   505  		tokenName := "testToken"
   506  		token := v1alpha1.ProjectRole{Name: tokenName, JWTTokens: []v1alpha1.JWTToken{{IssuedAt: 1}}}
   507  		projWithToken.Spec.Roles = append(projWithToken.Spec.Roles, token)
   508  		argoDB := db.NewDB("default", settingsMgr, kubeclientset)
   509  		projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(projWithToken), enforcer, sync.NewKeyLock(), sessionMgr, policyEnf, projInformer, settingsMgr, argoDB)
   510  		_, err := projectServer.CreateToken(context.Background(), &project.ProjectTokenCreateRequest{Project: projWithToken.Name, Role: tokenName})
   511  		assert.Nil(t, err)
   512  		projWithTwoTokens, err := projectServer.Get(context.Background(), &project.ProjectQuery{Name: projWithToken.Name})
   513  		assert.Nil(t, err)
   514  		assert.Len(t, projWithTwoTokens.Spec.Roles, 1)
   515  		assert.Len(t, projWithTwoTokens.Spec.Roles[0].JWTTokens, 2)
   516  	})
   517  
   518  	t.Run("TestAddWildcardSource", func(t *testing.T) {
   519  
   520  		proj := existingProj.DeepCopy()
   521  		wildSourceRepo := "*"
   522  		proj.Spec.SourceRepos = append(proj.Spec.SourceRepos, wildSourceRepo)
   523  		argoDB := db.NewDB("default", settingsMgr, kubeclientset)
   524  		projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(proj), enforcer, sync.NewKeyLock(), nil, policyEnf, projInformer, settingsMgr, argoDB)
   525  		request := &project.ProjectUpdateRequest{Project: proj}
   526  		updatedProj, err := projectServer.Update(context.Background(), request)
   527  		assert.Nil(t, err)
   528  		assert.Equal(t, wildSourceRepo, updatedProj.Spec.SourceRepos[1])
   529  	})
   530  
   531  	t.Run("TestCreateRolePolicySuccessfully", func(t *testing.T) {
   532  		action := "create"
   533  		object := "testApplication"
   534  		roleName := "testRole"
   535  		effect := "allow"
   536  
   537  		projWithRole := existingProj.DeepCopy()
   538  		role := v1alpha1.ProjectRole{Name: roleName, JWTTokens: []v1alpha1.JWTToken{{IssuedAt: 1}}}
   539  		policy := fmt.Sprintf(policyTemplate, projWithRole.Name, roleName, action, projWithRole.Name, object, effect)
   540  		role.Policies = append(role.Policies, policy)
   541  		projWithRole.Spec.Roles = append(projWithRole.Spec.Roles, role)
   542  		argoDB := db.NewDB("default", settingsMgr, kubeclientset)
   543  		projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(projWithRole), enforcer, sync.NewKeyLock(), nil, policyEnf, projInformer, settingsMgr, argoDB)
   544  		request := &project.ProjectUpdateRequest{Project: projWithRole}
   545  		_, err := projectServer.Update(context.Background(), request)
   546  		assert.Nil(t, err)
   547  		t.Log(projWithRole.Spec.Roles[0].Policies[0])
   548  		expectedPolicy := fmt.Sprintf(policyTemplate, projWithRole.Name, role.Name, action, projWithRole.Name, object, effect)
   549  		assert.Equal(t, projWithRole.Spec.Roles[0].Policies[0], expectedPolicy)
   550  	})
   551  
   552  	t.Run("TestValidatePolicyDuplicatePolicyFailure", func(t *testing.T) {
   553  		action := "create"
   554  		object := "testApplication"
   555  		roleName := "testRole"
   556  		effect := "allow"
   557  
   558  		projWithRole := existingProj.DeepCopy()
   559  		role := v1alpha1.ProjectRole{Name: roleName, JWTTokens: []v1alpha1.JWTToken{{IssuedAt: 1}}}
   560  		policy := fmt.Sprintf(policyTemplate, projWithRole.Name, roleName, action, projWithRole.Name, object, effect)
   561  		role.Policies = append(role.Policies, policy)
   562  		role.Policies = append(role.Policies, policy)
   563  		projWithRole.Spec.Roles = append(projWithRole.Spec.Roles, role)
   564  		argoDB := db.NewDB("default", settingsMgr, kubeclientset)
   565  		projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(projWithRole), enforcer, sync.NewKeyLock(), nil, nil, projInformer, settingsMgr, argoDB)
   566  		request := &project.ProjectUpdateRequest{Project: projWithRole}
   567  		_, err := projectServer.Update(context.Background(), request)
   568  		expectedErr := fmt.Sprintf("rpc error: code = AlreadyExists desc = policy '%s' already exists for role '%s'", policy, roleName)
   569  		assert.EqualError(t, err, expectedErr)
   570  	})
   571  
   572  	t.Run("TestValidateProjectAccessToSeparateProjectObjectFailure", func(t *testing.T) {
   573  		action := "create"
   574  		object := "testApplication"
   575  		roleName := "testRole"
   576  		otherProject := "other-project"
   577  		effect := "allow"
   578  
   579  		projWithRole := existingProj.DeepCopy()
   580  		role := v1alpha1.ProjectRole{Name: roleName, JWTTokens: []v1alpha1.JWTToken{{IssuedAt: 1}}}
   581  		policy := fmt.Sprintf(policyTemplate, projWithRole.Name, roleName, action, otherProject, object, effect)
   582  		role.Policies = append(role.Policies, policy)
   583  		projWithRole.Spec.Roles = append(projWithRole.Spec.Roles, role)
   584  		argoDB := db.NewDB("default", settingsMgr, kubeclientset)
   585  		projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(projWithRole), enforcer, sync.NewKeyLock(), nil, nil, projInformer, settingsMgr, argoDB)
   586  		request := &project.ProjectUpdateRequest{Project: projWithRole}
   587  		_, err := projectServer.Update(context.Background(), request)
   588  		assert.Contains(t, err.Error(), "object must be of form 'test/*' or 'test/<APPNAME>'")
   589  	})
   590  
   591  	t.Run("TestValidateProjectIncorrectProjectInRoleFailure", func(t *testing.T) {
   592  		action := "create"
   593  		object := "testApplication"
   594  		roleName := "testRole"
   595  		otherProject := "other-project"
   596  		effect := "allow"
   597  
   598  		projWithRole := existingProj.DeepCopy()
   599  		role := v1alpha1.ProjectRole{Name: roleName, JWTTokens: []v1alpha1.JWTToken{{IssuedAt: 1}}}
   600  		invalidPolicy := fmt.Sprintf(policyTemplate, otherProject, roleName, action, projWithRole.Name, object, effect)
   601  		role.Policies = append(role.Policies, invalidPolicy)
   602  		projWithRole.Spec.Roles = append(projWithRole.Spec.Roles, role)
   603  		argoDB := db.NewDB("default", settingsMgr, kubeclientset)
   604  		projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(projWithRole), enforcer, sync.NewKeyLock(), nil, nil, projInformer, settingsMgr, argoDB)
   605  		request := &project.ProjectUpdateRequest{Project: projWithRole}
   606  		_, err := projectServer.Update(context.Background(), request)
   607  		assert.Contains(t, err.Error(), "policy subject must be: 'proj:test:testRole'")
   608  	})
   609  
   610  	t.Run("TestValidateProjectIncorrectTokenInRoleFailure", func(t *testing.T) {
   611  		action := "create"
   612  		object := "testApplication"
   613  		roleName := "testRole"
   614  		otherToken := "other-token"
   615  		effect := "allow"
   616  
   617  		projWithRole := existingProj.DeepCopy()
   618  		role := v1alpha1.ProjectRole{Name: roleName, JWTTokens: []v1alpha1.JWTToken{{IssuedAt: 1}}}
   619  		invalidPolicy := fmt.Sprintf(policyTemplate, projWithRole.Name, otherToken, action, projWithRole.Name, object, effect)
   620  		role.Policies = append(role.Policies, invalidPolicy)
   621  		projWithRole.Spec.Roles = append(projWithRole.Spec.Roles, role)
   622  		argoDB := db.NewDB("default", settingsMgr, kubeclientset)
   623  		projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(projWithRole), enforcer, sync.NewKeyLock(), nil, nil, projInformer, settingsMgr, argoDB)
   624  		request := &project.ProjectUpdateRequest{Project: projWithRole}
   625  		_, err := projectServer.Update(context.Background(), request)
   626  		assert.Contains(t, err.Error(), "policy subject must be: 'proj:test:testRole'")
   627  	})
   628  
   629  	t.Run("TestValidateProjectInvalidEffectFailure", func(t *testing.T) {
   630  		action := "create"
   631  		object := "testApplication"
   632  		roleName := "testRole"
   633  		effect := "testEffect"
   634  
   635  		projWithRole := existingProj.DeepCopy()
   636  		role := v1alpha1.ProjectRole{Name: roleName, JWTTokens: []v1alpha1.JWTToken{{IssuedAt: 1}}}
   637  		invalidPolicy := fmt.Sprintf(policyTemplate, projWithRole.Name, roleName, action, projWithRole.Name, object, effect)
   638  		role.Policies = append(role.Policies, invalidPolicy)
   639  		projWithRole.Spec.Roles = append(projWithRole.Spec.Roles, role)
   640  		argoDB := db.NewDB("default", settingsMgr, kubeclientset)
   641  		projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(projWithRole), enforcer, sync.NewKeyLock(), nil, nil, projInformer, settingsMgr, argoDB)
   642  		request := &project.ProjectUpdateRequest{Project: projWithRole}
   643  		_, err := projectServer.Update(context.Background(), request)
   644  		assert.Contains(t, err.Error(), "effect must be: 'allow' or 'deny'")
   645  	})
   646  
   647  	t.Run("TestNormalizeProjectRolePolicies", func(t *testing.T) {
   648  		action := "create"
   649  		object := "testApplication"
   650  		roleName := "testRole"
   651  		effect := "allow"
   652  
   653  		projWithRole := existingProj.DeepCopy()
   654  		role := v1alpha1.ProjectRole{Name: roleName, JWTTokens: []v1alpha1.JWTToken{{IssuedAt: 1}}}
   655  		noSpacesPolicyTemplate := strings.Replace(policyTemplate, " ", "", -1)
   656  		invalidPolicy := fmt.Sprintf(noSpacesPolicyTemplate, projWithRole.Name, roleName, action, projWithRole.Name, object, effect)
   657  		role.Policies = append(role.Policies, invalidPolicy)
   658  		projWithRole.Spec.Roles = append(projWithRole.Spec.Roles, role)
   659  		argoDB := db.NewDB("default", settingsMgr, kubeclientset)
   660  		projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(projWithRole), enforcer, sync.NewKeyLock(), nil, nil, projInformer, settingsMgr, argoDB)
   661  		request := &project.ProjectUpdateRequest{Project: projWithRole}
   662  		updateProj, err := projectServer.Update(context.Background(), request)
   663  		assert.Nil(t, err)
   664  		expectedPolicy := fmt.Sprintf(policyTemplate, projWithRole.Name, roleName, action, projWithRole.Name, object, effect)
   665  		assert.Equal(t, expectedPolicy, updateProj.Spec.Roles[0].Policies[0])
   666  	})
   667  
   668  	t.Run("TestSyncWindowsActive", func(t *testing.T) {
   669  		sessionMgr := session.NewSessionManager(settingsMgr, test.NewFakeProjLister(), "", nil, session.NewUserStateStorage(nil))
   670  		projectWithSyncWindows := existingProj.DeepCopy()
   671  		projectWithSyncWindows.Spec.SyncWindows = v1alpha1.SyncWindows{}
   672  		win := &v1alpha1.SyncWindow{Kind: "allow", Schedule: "* * * * *", Duration: "1h"}
   673  		projectWithSyncWindows.Spec.SyncWindows = append(projectWithSyncWindows.Spec.SyncWindows, win)
   674  		argoDB := db.NewDB("default", settingsMgr, kubeclientset)
   675  		projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(projectWithSyncWindows), enforcer, sync.NewKeyLock(), sessionMgr, nil, projInformer, settingsMgr, argoDB)
   676  		res, err := projectServer.GetSyncWindowsState(ctx, &project.SyncWindowsQuery{Name: projectWithSyncWindows.Name})
   677  		assert.NoError(t, err)
   678  		assert.Equal(t, 1, len(res.Windows))
   679  	})
   680  
   681  	t.Run("TestGetSyncWindowsStateCannotGetProjectDetails", func(t *testing.T) {
   682  		sessionMgr := session.NewSessionManager(settingsMgr, test.NewFakeProjLister(), "", nil, session.NewUserStateStorage(nil))
   683  		projectWithSyncWindows := existingProj.DeepCopy()
   684  		projectWithSyncWindows.Spec.SyncWindows = v1alpha1.SyncWindows{}
   685  		win := &v1alpha1.SyncWindow{Kind: "allow", Schedule: "* * * * *", Duration: "1h"}
   686  		projectWithSyncWindows.Spec.SyncWindows = append(projectWithSyncWindows.Spec.SyncWindows, win)
   687  		argoDB := db.NewDB("default", settingsMgr, kubeclientset)
   688  		projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(projectWithSyncWindows), enforcer, sync.NewKeyLock(), sessionMgr, nil, projInformer, settingsMgr, argoDB)
   689  		res, err := projectServer.GetSyncWindowsState(ctx, &project.SyncWindowsQuery{Name: "incorrect"})
   690  		assert.Contains(t, err.Error(), "not found")
   691  		assert.Nil(t, res)
   692  	})
   693  
   694  	t.Run("TestGetSyncWindowsStateDenied", func(t *testing.T) {
   695  		enforcer = newEnforcer(kubeclientset)
   696  		_ = enforcer.SetBuiltinPolicy(`p, *, *, *, *, deny`)
   697  		enforcer.SetClaimsEnforcerFunc(nil)
   698  		// nolint:staticcheck
   699  		ctx := context.WithValue(context.Background(), "claims", &jwt.MapClaims{"groups": []string{"my-group"}})
   700  
   701  		sessionMgr := session.NewSessionManager(settingsMgr, test.NewFakeProjLister(), "", nil, session.NewUserStateStorage(nil))
   702  		projectWithSyncWindows := existingProj.DeepCopy()
   703  		win := &v1alpha1.SyncWindow{Kind: "allow", Schedule: "* * * * *", Duration: "1h"}
   704  		projectWithSyncWindows.Spec.SyncWindows = append(projectWithSyncWindows.Spec.SyncWindows, win)
   705  		argoDB := db.NewDB("default", settingsMgr, kubeclientset)
   706  		projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(projectWithSyncWindows), enforcer, sync.NewKeyLock(), sessionMgr, nil, projInformer, settingsMgr, argoDB)
   707  		_, err := projectServer.GetSyncWindowsState(ctx, &project.SyncWindowsQuery{Name: projectWithSyncWindows.Name})
   708  		assert.EqualError(t, err, "rpc error: code = PermissionDenied desc = permission denied: projects, get, test")
   709  	})
   710  
   711  }
   712  
   713  func newEnforcer(kubeclientset *fake.Clientset) *rbac.Enforcer {
   714  	enforcer := rbac.NewEnforcer(kubeclientset, testNamespace, common.ArgoCDRBACConfigMapName, nil)
   715  	_ = enforcer.SetBuiltinPolicy(assets.BuiltinPolicyCSV)
   716  	enforcer.SetDefaultRole("role:admin")
   717  	enforcer.SetClaimsEnforcerFunc(func(claims jwt.Claims, rvals ...interface{}) bool {
   718  		return true
   719  	})
   720  	return enforcer
   721  }