Add test for empty label selector and fix ACL name
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
This commit is contained in:
		
							parent
							
								
									c67a4c62f1
								
							
						
					
					
						commit
						8f4ae31562
					
				|  | @ -75,7 +75,7 @@ type ImageRepositorySpec struct { | |||
| } | ||||
| 
 | ||||
| type AccessFrom struct { | ||||
| 	NamespaceSelectors []NamespaceSelector `json:"namespaceSelector,omitempty"` | ||||
| 	NamespaceSelectors []NamespaceSelector `json:"namespaceSelectors,omitempty"` | ||||
| } | ||||
| 
 | ||||
| type NamespaceSelector struct { | ||||
|  |  | |||
|  | @ -296,7 +296,7 @@ spec: | |||
|               accessFrom: | ||||
|                 description: AccessFrom defines an ACL for allowing cross-namespace references to the ImageRepository object based on the caller's namespace labels. | ||||
|                 properties: | ||||
|                   namespaceSelector: | ||||
|                   namespaceSelectors: | ||||
|                     items: | ||||
|                       properties: | ||||
|                         matchLabels: | ||||
|  |  | |||
|  | @ -6,3 +6,7 @@ metadata: | |||
| spec: | ||||
|   image: ghcr.io/stefanprodan/podinfo | ||||
|   interval: 1m0s | ||||
|   accessFrom: | ||||
|     namespaceSelectors: | ||||
|       - matchLabels: | ||||
|           kubernetes.io/metadata.name: flux-system | ||||
|  |  | |||
|  | @ -332,29 +332,17 @@ func (r *ImagePolicyReconciler) hasAccessToRepository(ctx context.Context, polic | |||
| 	} | ||||
| 	policyLabels := policyNamespace.GetLabels() | ||||
| 
 | ||||
| 	// deny access if the policy namespace has no labels
 | ||||
| 	if len(policyLabels) == 0 { | ||||
| 		return false, fmt.Errorf("ImageRepository '%s/%s' can't be accessed due to missing lables on namespace '%s'", | ||||
| 			repo.Namespace, repo.Name, policy.Namespace) | ||||
| 	} | ||||
| 
 | ||||
| 	// check if the policy namespace labels match any ACL
 | ||||
| 	var allowed bool | ||||
| 	for _, selector := range acl.NamespaceSelectors { | ||||
| 		sel, err := metav1.LabelSelectorAsSelector(&metav1.LabelSelector{MatchLabels: selector.MatchLabels}) | ||||
| 		if err != nil { | ||||
| 			return false, err | ||||
| 		} | ||||
| 		if sel.Matches(labels.Set(policyLabels)) { | ||||
| 			allowed = true | ||||
| 			break | ||||
| 			return true, nil | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if !allowed { | ||||
| 		return allowed, fmt.Errorf("ImageRepository '%s/%s' can't be accessed due to lables mismatch on namespace '%s'", | ||||
| 	return false, fmt.Errorf("ImageRepository '%s/%s' can't be accessed due to labels mismatch on namespace '%s'", | ||||
| 		repo.Namespace, repo.Name, policy.Namespace) | ||||
| } | ||||
| 
 | ||||
| 	return allowed, nil | ||||
| } | ||||
|  |  | |||
|  | @ -458,6 +458,85 @@ var _ = Describe("ImagePolicy controller", func() { | |||
| 			}) | ||||
| 		}) | ||||
| 
 | ||||
| 		When("is in different namespace with no empty match labels", func() { | ||||
| 			It("grants access", func() { | ||||
| 				policyNamespace := &corev1.Namespace{} | ||||
| 				policyNamespace.Name = "acl-" + randStringRunes(5) | ||||
| 
 | ||||
| 				Expect(k8sClient.Create(context.Background(), policyNamespace)).To(Succeed()) | ||||
| 				defer k8sClient.Delete(context.Background(), policyNamespace) | ||||
| 
 | ||||
| 				versions := []string{"1.0.0", "1.0.1"} | ||||
| 				imgRepo := loadImages(registryServer, "acl-image-"+randStringRunes(5), versions) | ||||
| 
 | ||||
| 				repo := imagev1.ImageRepository{ | ||||
| 					Spec: imagev1.ImageRepositorySpec{ | ||||
| 						Interval: metav1.Duration{Duration: reconciliationInterval}, | ||||
| 						Image:    imgRepo, | ||||
| 						AccessFrom: &imagev1.AccessFrom{ | ||||
| 							NamespaceSelectors: []imagev1.NamespaceSelector{ | ||||
| 								{ | ||||
| 									MatchLabels: make(map[string]string), | ||||
| 								}, | ||||
| 							}, | ||||
| 						}, | ||||
| 					}, | ||||
| 				} | ||||
| 				repoObjectName := types.NamespacedName{ | ||||
| 					Name:      "acl-repo-" + randStringRunes(5), | ||||
| 					Namespace: "default", | ||||
| 				} | ||||
| 				repo.Name = repoObjectName.Name | ||||
| 				repo.Namespace = repoObjectName.Namespace | ||||
| 
 | ||||
| 				ctx, cancel := context.WithTimeout(context.Background(), contextTimeout) | ||||
| 				defer cancel() | ||||
| 
 | ||||
| 				r := imageRepoReconciler | ||||
| 				Expect(r.Create(ctx, &repo)).To(Succeed()) | ||||
| 
 | ||||
| 				Eventually(func() bool { | ||||
| 					err := r.Get(ctx, repoObjectName, &repo) | ||||
| 					return err == nil && repo.Status.LastScanResult != nil | ||||
| 				}, timeout, interval).Should(BeTrue()) | ||||
| 				Expect(repo.Status.CanonicalImageName).To(Equal(imgRepo)) | ||||
| 				Expect(repo.Status.LastScanResult.TagCount).To(Equal(len(versions))) | ||||
| 
 | ||||
| 				polObjectName := types.NamespacedName{ | ||||
| 					Name:      "acl-pol-" + randStringRunes(5), | ||||
| 					Namespace: policyNamespace.Name, | ||||
| 				} | ||||
| 				pol := imagev1.ImagePolicy{ | ||||
| 					Spec: imagev1.ImagePolicySpec{ | ||||
| 						ImageRepositoryRef: meta.NamespacedObjectReference{ | ||||
| 							Name:      repoObjectName.Name, | ||||
| 							Namespace: repoObjectName.Namespace, | ||||
| 						}, | ||||
| 						Policy: imagev1.ImagePolicyChoice{ | ||||
| 							SemVer: &imagev1.SemVerPolicy{ | ||||
| 								Range: "1.0.x", | ||||
| 							}, | ||||
| 						}, | ||||
| 					}, | ||||
| 				} | ||||
| 				pol.Namespace = polObjectName.Namespace | ||||
| 				pol.Name = polObjectName.Name | ||||
| 
 | ||||
| 				ctx, cancel = context.WithTimeout(context.Background(), contextTimeout) | ||||
| 				defer cancel() | ||||
| 
 | ||||
| 				Expect(r.Create(ctx, &pol)).To(Succeed()) | ||||
| 
 | ||||
| 				Eventually(func() bool { | ||||
| 					err := r.Get(ctx, polObjectName, &pol) | ||||
| 					return err == nil && pol.Status.LatestImage != "" | ||||
| 				}, timeout, interval).Should(BeTrue()) | ||||
| 				Expect(pol.Status.LatestImage).To(Equal(imgRepo + ":1.0.1")) | ||||
| 
 | ||||
| 				Expect(r.Delete(ctx, &pol)).To(Succeed()) | ||||
| 			}) | ||||
| 		}) | ||||
| 
 | ||||
| 		When("is in different namespace with matching ACL", func() { | ||||
| 			It("grants access", func() { | ||||
| 				policyNamespace := &corev1.Namespace{} | ||||
|  |  | |||
|  | @ -30,7 +30,7 @@ Resource Types: | |||
| <tbody> | ||||
| <tr> | ||||
| <td> | ||||
| <code>namespaceSelector</code><br> | ||||
| <code>namespaceSelectors</code><br> | ||||
| <em> | ||||
| <a href="#image.toolkit.fluxcd.io/v1beta1.NamespaceSelector"> | ||||
| []NamespaceSelector | ||||
|  |  | |||
|  | @ -132,8 +132,8 @@ spec: | |||
|   secretRef: | ||||
|     name: regcred | ||||
|   accessFrom: | ||||
|   - namespaceSelector: | ||||
|       matchLabels: | ||||
|     namespaceSelectors: | ||||
|       - matchLabels: | ||||
|           kubernetes.io/metadata.name: flux-system | ||||
| ``` | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue