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