Add test for empty label selector and fix ACL name

Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
This commit is contained in:
Stefan Prodan 2021-08-06 16:08:56 +03:00
parent c67a4c62f1
commit 8f4ae31562
No known key found for this signature in database
GPG Key ID: 3299AEB0E4085BAF
7 changed files with 92 additions and 21 deletions

View File

@ -75,7 +75,7 @@ type ImageRepositorySpec struct {
}
type AccessFrom struct {
NamespaceSelectors []NamespaceSelector `json:"namespaceSelector,omitempty"`
NamespaceSelectors []NamespaceSelector `json:"namespaceSelectors,omitempty"`
}
type NamespaceSelector struct {

View File

@ -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:

View File

@ -6,3 +6,7 @@ metadata:
spec:
image: ghcr.io/stefanprodan/podinfo
interval: 1m0s
accessFrom:
namespaceSelectors:
- matchLabels:
kubernetes.io/metadata.name: flux-system

View File

@ -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'",
repo.Namespace, repo.Name, policy.Namespace)
}
return allowed, nil
return false, fmt.Errorf("ImageRepository '%s/%s' can't be accessed due to labels mismatch on namespace '%s'",
repo.Namespace, repo.Name, policy.Namespace)
}

View File

@ -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{}

View File

@ -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

View File

@ -132,9 +132,9 @@ spec:
secretRef:
name: regcred
accessFrom:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: flux-system
namespaceSelectors:
- matchLabels:
kubernetes.io/metadata.name: flux-system
```
**Note** that the `kubernetes.io/metadata.name` is a readonly label added by Kubernetes >= 1.21