Skip to content

Commit 9ec0e20

Browse files
committed
Automatically allow egress IPs on ManagedSeeds
Signed-off-by: Justin Lamp <[email protected]>
1 parent a2359a5 commit 9ec0e20

File tree

4 files changed

+125
-0
lines changed

4 files changed

+125
-0
lines changed

charts/gardener-extension-acl/templates/rbac.yaml

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,23 @@ rules:
144144
- watch
145145
---
146146
apiVersion: rbac.authorization.k8s.io/v1
147+
kind: Role
148+
metadata:
149+
labels:
150+
{{ include "labels" . | indent 4 }}
151+
name: {{ include "name" . }}
152+
namespace: kube-system
153+
rules:
154+
- apiGroups:
155+
- ""
156+
resources:
157+
- configmaps
158+
resourceNames:
159+
- shoot-info
160+
verbs:
161+
- get
162+
---
163+
apiVersion: rbac.authorization.k8s.io/v1
147164
kind: ClusterRoleBinding
148165
metadata:
149166
name: {{ include "name" . }}
@@ -157,3 +174,19 @@ subjects:
157174
- kind: ServiceAccount
158175
name: {{ include "name" . }}
159176
namespace: {{ .Release.Namespace }}
177+
---
178+
apiVersion: rbac.authorization.k8s.io/v1
179+
kind: RoleBinding
180+
metadata:
181+
name: {{ include "name" . }}
182+
namespace: kube-system
183+
labels:
184+
{{ include "labels" . | indent 4 }}
185+
roleRef:
186+
apiGroup: rbac.authorization.k8s.io
187+
kind: Role
188+
name: {{ include "name" . }}
189+
subjects:
190+
- kind: ServiceAccount
191+
name: {{ include "name" . }}
192+
namespace: {{ .Release.Namespace }}

pkg/controller/actuator.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import (
3636
"github.com/pkg/errors"
3737
istionetworkv1beta1 "istio.io/client-go/pkg/apis/networking/v1beta1"
3838
appsv1 "k8s.io/api/apps/v1"
39+
corev1 "k8s.io/api/core/v1"
3940
"k8s.io/apimachinery/pkg/runtime"
4041
"k8s.io/apimachinery/pkg/runtime/serializer"
4142
"k8s.io/client-go/rest"
@@ -48,6 +49,8 @@ import (
4849
"github.com/stackitcloud/gardener-extension-acl/pkg/extensionspec"
4950
"github.com/stackitcloud/gardener-extension-acl/pkg/helper"
5051
"github.com/stackitcloud/gardener-extension-acl/pkg/imagevector"
52+
53+
apierrors "k8s.io/apimachinery/pkg/api/errors"
5154
)
5255

5356
const (
@@ -147,6 +150,14 @@ func (a *actuator) Reconcile(ctx context.Context, log logr.Logger, ex *extension
147150

148151
alwaysAllowedCIDRs = append(alwaysAllowedCIDRs, helper.GetSeedSpecificAllowedCIDRs(cluster.Seed)...)
149152

153+
// On ManagedSeeds the shoot-info ConfigMap contains the egress CIDRs of the cluster
154+
// These CIDRs need to be allowed in order for the external API reachability check to work
155+
if egressCIDRs, err := a.getSeedEgressIPOnManagedSeeds(ctx); err != nil {
156+
return err
157+
} else if len(egressCIDRs) > 0 {
158+
alwaysAllowedCIDRs = append(alwaysAllowedCIDRs, egressCIDRs...)
159+
}
160+
150161
if len(a.extensionConfig.AdditionalAllowedCIDRs) >= 1 {
151162
alwaysAllowedCIDRs = append(alwaysAllowedCIDRs, a.extensionConfig.AdditionalAllowedCIDRs...)
152163
}
@@ -446,3 +457,25 @@ func (a *actuator) findDefaultIstioLabels(
446457

447458
return gw.Spec.Selector, nil
448459
}
460+
461+
// getSeedEgressIPOnManagedSeeds returns the egressIP CIDRs of the ManagedSeed, if the
462+
// Seed is not a shoot, it will return an empty list
463+
func (a *actuator) getSeedEgressIPOnManagedSeeds(ctx context.Context) ([]string, error) {
464+
cm := corev1.ConfigMap{}
465+
if err := a.client.Get(ctx, client.ObjectKey{
466+
Name: "shoot-info",
467+
Namespace: "kube-system"},
468+
&cm); err != nil {
469+
if apierrors.IsNotFound(err) {
470+
return []string{}, nil
471+
}
472+
return nil, err
473+
}
474+
475+
cidrs, ok := cm.Data["egressCIDRs"]
476+
if !ok {
477+
return nil, errors.New("unable to get egress CIDRs from shoot-info ConfigMap")
478+
}
479+
480+
return strings.Split(cidrs, ","), nil
481+
}

pkg/controller/actuator_test.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,40 @@ var _ = Describe("actuator test", func() {
222222
})
223223
})
224224

225+
Describe("reconciliation of an extension object running on a managedSeed", func() {
226+
BeforeEach(func() {
227+
createShootInfo([]string{"1.1.1.1/32", "1.1.1.2/32"})
228+
})
229+
230+
AfterEach(func() {
231+
deleteShootInfo()
232+
})
233+
234+
It("should create ACLs including egressIPs of managedSeed", func() {
235+
extSpec := extensionspec.ExtensionSpec{
236+
Rule: &envoyfilters.ACLRule{
237+
Cidrs: []string{"1.2.3.4/24"},
238+
Action: "ALLOW",
239+
Type: "remote_ip",
240+
},
241+
}
242+
extSpecJSON, err := json.Marshal(extSpec)
243+
Expect(err).NotTo(HaveOccurred())
244+
ext := createNewExtension(shootNamespace1, extSpecJSON)
245+
Expect(ext).To(Not(BeNil()))
246+
247+
Expect(a.Reconcile(ctx, logger, ext)).To(Succeed())
248+
249+
mr := &v1alpha1.ManagedResource{}
250+
Expect(k8sClient.Get(ctx, types.NamespacedName{Name: ResourceNameSeed, Namespace: shootNamespace1}, mr)).To(Succeed())
251+
secret := &corev1.Secret{}
252+
Expect(k8sClient.Get(ctx, types.NamespacedName{Name: mr.Spec.SecretRefs[0].Name, Namespace: shootNamespace1}, secret)).To(Succeed())
253+
Expect(secret.Data["seed"]).To(ContainSubstring("1.2.3.4"))
254+
Expect(secret.Data["seed"]).To(ContainSubstring("1.1.1.1"))
255+
Expect(secret.Data["seed"]).To(ContainSubstring("1.1.1.2"))
256+
})
257+
})
258+
225259
Describe("a shoot switching the istio namespace (e.g. when being migrated to HA)", func() {
226260
It("should modify the EnvoyFilter objects accordingly", func() {
227261
By("1) creating the EnvoyFilter object correctly in the ORIGINAL namespace")

pkg/controller/suite_test.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55
"path/filepath"
66
"strconv"
7+
"strings"
78
"testing"
89

910
gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1"
@@ -18,6 +19,7 @@ import (
1819
istionetworkingv1beta1 "istio.io/client-go/pkg/apis/networking/v1beta1"
1920
appsv1 "k8s.io/api/apps/v1"
2021
corev1 "k8s.io/api/core/v1"
22+
v1 "k8s.io/api/core/v1"
2123
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
2224
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2325
"k8s.io/apimachinery/pkg/runtime"
@@ -247,6 +249,29 @@ func createNewCluster(shootNamespace string) {
247249
Expect(k8sClient.Create(ctx, cluster)).ShouldNot(HaveOccurred())
248250
}
249251

252+
func createShootInfo(cidrs []string) {
253+
cm := &v1.ConfigMap{
254+
ObjectMeta: metav1.ObjectMeta{
255+
Name: "shoot-info",
256+
Namespace: "kube-system",
257+
},
258+
Data: map[string]string{
259+
"egressCIDRs": strings.Join(cidrs, ","),
260+
},
261+
}
262+
Expect(k8sClient.Create(ctx, cm)).ShouldNot(HaveOccurred())
263+
}
264+
265+
func deleteShootInfo() {
266+
cm := &v1.ConfigMap{
267+
ObjectMeta: metav1.ObjectMeta{
268+
Name: "shoot-info",
269+
Namespace: "kube-system",
270+
},
271+
}
272+
Expect(k8sClient.Delete(ctx, cm)).ShouldNot(HaveOccurred())
273+
}
274+
250275
func deleteNamespace(name string) {
251276
namespace := &corev1.Namespace{
252277
ObjectMeta: metav1.ObjectMeta{

0 commit comments

Comments
 (0)