Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions charts/gardener-extension-acl/templates/rbac.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,14 @@ rules:
- delete
resources:
- envoyfilters
- apiGroups:
- ""
resources:
- services
verbs:
- get
- list
- watch
- apiGroups:
- extensions.gardener.cloud
resources:
Expand Down Expand Up @@ -144,6 +152,23 @@ rules:
- watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
labels:
{{ include "labels" . | indent 4 }}
name: {{ include "name" . }}
namespace: kube-system
rules:
- apiGroups:
- ""
resources:
- configmaps
resourceNames:
- shoot-info
verbs:
- get
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: {{ include "name" . }}
Expand All @@ -157,3 +182,19 @@ subjects:
- kind: ServiceAccount
name: {{ include "name" . }}
namespace: {{ .Release.Namespace }}
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: {{ include "name" . }}
namespace: kube-system
labels:
{{ include "labels" . | indent 4 }}
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: {{ include "name" . }}
subjects:
- kind: ServiceAccount
name: {{ include "name" . }}
namespace: {{ .Release.Namespace }}
12 changes: 12 additions & 0 deletions cmd/gardener-extension-acl/app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,17 @@ import (

extensionscontroller "github.com/gardener/gardener/extensions/pkg/controller"
"github.com/gardener/gardener/extensions/pkg/util"
v1beta1constants "github.com/gardener/gardener/pkg/apis/core/v1beta1/constants"
extensionsv1alpha1 "github.com/gardener/gardener/pkg/apis/extensions/v1alpha1"
"github.com/spf13/cobra"
istionetworkv1alpha3 "istio.io/client-go/pkg/apis/networking/v1alpha3"
istionetworkv1beta1 "istio.io/client-go/pkg/apis/networking/v1beta1"
admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
componentbaseconfigv1alpha1 "k8s.io/component-base/config/v1alpha1"
"sigs.k8s.io/controller-runtime/pkg/cache"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/manager"

Expand Down Expand Up @@ -78,6 +81,15 @@ func (o *Options) run(ctx context.Context) error {
},
}

// Only cache services that are needed to check for ProxyProto usage
mgrOpts.Cache.ByObject = map[client.Object]cache.ByObject{
&corev1.Service{}: {
Label: labels.Set{
"app": v1beta1constants.DefaultIngressGatewayAppLabelValue,
}.AsSelector(),
},
}

mgr, err := manager.New(o.restOptions.Completed().Config, mgrOpts)
if err != nil {
return fmt.Errorf("could not instantiate controller-manager: %s", err)
Expand Down
2 changes: 1 addition & 1 deletion deploy/extension/base/controller-registration.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ kind: ControllerDeployment
metadata:
name: acl
helm:
rawChart: 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
rawChart: H4sIAAAAAAAAA+0ba2/jNnI/61fwvFd0t6jkRxynNbBA0yS3DZAXkm0Oh6IIaIm22UiiSkrOeh/3229IyhKtR2Q7u97b1vPBlsjhcMh5cIakJph7JCTcJm9jEgrKQhu7fvvZp4QOwMH+vvoHKP6r5+5ev9vb7w0Gsrzb73a7z9D+J+WiBhIRY47QM85Y/BheU/1XCpNq+TtT4gd0EjJOnt6HFPCg36+VP4i9IP9Brz94hjpP77oZ/ubyf46ucBwTHgoUM6Qljh6mJESjhPoeDScowu49nhDhWM/RmykVSCRRxHgMD6AlPpr4bIQCHLtTwP4eceLjmM4ItIunRjkOPSAQkgnUshC9iDgZ07fEQw8U8P7x0kGXoT9HLFQtJUsoIhz5NCSO5Rzf3N3EwBuQOGJBAARuj26QR7mwnAmN2+pXs285o3e8rX4XBdNJW/4sXsUsbOeERjC+JEJj6hNhfeeIhwh+R/gefuMAnv8LqLeYU5YIdHp8Ah1GnP1B3NhyqEdwW+NBkeXMhMs80ra+tFRXhxr7P5piHjtzHPifoI8m++91Dor239nb39n/NgBH9JZwKfchmnUtHEXZa6vrdFqWR4TLaRSrokP0C6wLyJXagcaMo3hK0OtUhdDh0RnK1MixQhyQIapWMGu26KXjQDdfkcH8xaDG/mMSRODGifgUkeD68d+gCy5hF/9tARrlfwdrPKzDwomjTdeCBv/f7fUK/r/X6e/t7fz/NuD9ext5EIhB1NWSDruF7I8frRqnLZFJ6CkUy2zp4xHxhQOrh3NP5pqGeklGEMcR0COHsrakv0SjhsQM+0nKyPv3iIaun3gZew5KGz7CSLltkUFJZYhqMNL+VU/lUdAQNCZ0iWruXBOfYEGcC2DuUc5oADG0ZgwhWUHH6J6G3qlALRFzCJGhx1vZM/QicVGGWVMM7BJJZYrFlYqlgdAU9/YHwwIlJ8aTvFkEfcVj1PpG/PSNKGJyEjFBIdCeP0ZC9VxBcLgxQZgxY/I+fvzSZvG3gUb/77JwTCcBjmwltxnkPYzbDOK3B05jskqO0BT/9weF/B8eDnb+fyuQeqIl27xVMr5ciFhapm3bViFVkM5rCDm0VI9zHFkBibGHYzwEm9ahf7XzrtajtJGIcJVnVcXaXWg/Pazw7pL8BygEfY5RX2Iv2FE9irtlpR2iD5LIoyNfJvdXdE+N9u+RyGfzACZh4+2ABvvf398rxn/d7mCX/28FioYN8Y5oZ9Z9nAl/ZfNe25ARwJROpjaeYQqF1Kfx3NbLDoQPgiXcBftcKKrj+izx2vE8AvKAFXPm+4Sv5A9ERFzZISczKof7CxUyMjmjAY2HqKNqIp+6WGjOU9eQFh6xBAgp3gUMSXoKzb3a4zxbzS8NNIGFfaUEjLmVgMOQxWqbVCyKVvTTKAV3Stx7kQTG8p0beKUDXpLnCxXToX86b1I+nZ9BgldyQ7e1UkTQeqkGreNR4CPnzQj3dIGpBxIg0H5gHPRvUpI5sz2YEYR9nz0Qb7UWHIRGA2KDkgvCgcm8fYOofljwuFAbCTAxDEY5P/KxEBfLO1xiLkCu9o+dToosO6QuOXRdqToXj1uNEhvoM4Z0gWfzYTcZmwYliWWsNOEoo10lvn/FQKPnS1peqDObYT4xBGQj2w7wW2mibsI5TJXNiXyRG+ivDIq5darnFPlmHrrCpC7pTQn246nS2vVpG42b+vGowCOf2EZzk2pafZTXgjr8wWiIWt+3irT0aYLNIsKVrdq52dZxqptcLlocZg2KtMFjenJRlm5Gmaz3qiaaKmAuUVH7tLY8h3nVVs8iqy74E+x5VDbH/qE2jiPq8dLs5Vh2akO2K/HM4dZQqp7GkjMoMZYZdLphXGQpM7603mTlsbYVPZNwZiq5truzk8Pjk+u7k7OTozenlxd3F4fnJzdXh0cnGSZCar/gX5wFQ6MQoTElvndNxsulabn0pcPM8TvZklk3D00Of8Hv6fnh65NbYPby+u7y9uT639enb0q8DlGqDnlI3K6MkdcQVLZSmzhZoVoXY/YfoFnR4gOKOQ1yz9vtNIhKEDBy6YXBtmBdM2dYKeYVpzPwGBNyIlzsY314Mca+IAamiyMdbVAilmXkcRYN0W+HZ2e/G+WwkhyKCxZeQyQ4BI4TUqz8VcjlZQABba9Y9ZqzJCrXwUBcFkRXnMnjx2UudIhzrdevYzLGiR9vqh4z5icBOZfLkCgreUNoYHAVSApad8sqZI4ZvJI8zi3MU0mUaw1DD6K0NK7KvbtIVc1p3ihTzfREC+WceUCj3+sYg0pH+aXD+0ZozP8iBg5d8ESdAI4Sb0LWTgQb73/0i/s/e52D3f2PrUBqgJMYvZARf1XK8xJ1q7aAIhUm5rniFfOOM0X5WSnK50sa18n2IJ78NUyTS1+TF8mocbxPzvK+CjfQaP98hN0nXgRp2v85KJ3/Hhx0+jv73wYUrVqJGyfxFLLcdypwcu5/UOde+ZavD3NG+DXzyToGvo7p8sSX67yNgDUVOalF3zYzfSqAOeALymFlHqUI0unIfx+q1cODtFr1FGVPSQQsE/XoQqCSPnpg7erRCFplOaQFbA7RGQxZlDlqtcot0rRfrMRaiWJmiMU9r3JHrpaE0PyHQqbK3NOvNBxzLCD6cuOEb4GXHLXw2gYDi5PVGKiUU4mruk3BMlMBDiGC87LSBiYMbXio0pactVRZVlKHbGXbUAjwashBW2OFLoAqsGBRqE6dVR5e06kx1NIAyxNe5xRqVZIzn4hiwQhMHExXl+cYhao1mV1XGi1IuTiJRUu/QXgf6pfPrBhyY72Knfx8pZGLvOtNJ8Rl4B9o+LgIVeBVkETa4RMJLspVUKfrVt7VMpgxhryYozrT8QIqpN1wMoFZ5I/zGSRyMy6cPJDRlLF7nS8mutHq/mtT2VSvbQUWJ0DvAc9X9CTrr+2lRX2dVXudGF/eqUk3zGtX+yrzzQ4favRJgORiGxa/isDgabHOz9pFfbaQB7pINwsX0/AIh4BVDsYa+IGkR95aVzOtG98snU+sJb/aHG1Dpdtgdmu0aSvT/n8z30+N/xvzvzSYxZrnjTLBpv2fvW63sP/Tg8Jd/rcNqL3YU9DVL7qTA6bI1M7zMlNv2D3J9vW/9ER+pdBo/7MIP/U7oKb733vF+3/dg/3Bwc7+twGFAxgpbRLKfVKvajGXhihP1GSQWlzFASmmUHfFvMMUjfBP7Tf0nm4F04tQ0Ly8sFymd3GzGxaqkJqnSVmVvqjx7XffWtmxFw3T02zz7MiNEsUqJ38mlMOMteo5cnISDrRDVGTNWo8MpNjMONKT14YCxucbsaCbbsJF2nJ5fxshMCIIsbPT7qorZbK8dK2s6QwOEHQWZQpRl+hjN+O8XzJuIjs53lezH79tqPH/Mz2jn+YD0Eb/v79X+v57d/63HdAXx5SzXHyoMUSTqculb4epce9prO/S1XwTJE1/MkQqWIit0gWz0/EFi6/AnUhjt8xjtiHqyQIju5euCIikLll519Z+J2hZprNrDfrntGVZYOwSL12ssnsGVT6/7L0VbSBtLTtSSbrR4bSuid7iASaMu10SsXD5DLqAwto7X/mNFOMCW7ZKFQlZ5btpQ/Tb75ZVfeFK1z1HVTcq5M3352hxLX6onvPLFBgiP6LKENJzeW2oxjSOIzFst4U7fcD8HY1/8sjMwe8SThyXBXl5/uSIe9K+kx/pp8SN23dpP6bycTJx1OGFbOeQpNN1Uj1ML3VKcstsKg1sdZye8yMIZaGoQ70DlH7M3No5/R3sYAc72MEOdrCDHezgf4TOeGQAUAAA
values:
image:
tag: latest
Expand Down
85 changes: 83 additions & 2 deletions pkg/controller/actuator.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import (
"github.com/pkg/errors"
istionetworkv1beta1 "istio.io/client-go/pkg/apis/networking/v1beta1"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/serializer"
"k8s.io/client-go/rest"
Expand All @@ -48,6 +49,8 @@ import (
"github.com/stackitcloud/gardener-extension-acl/pkg/extensionspec"
"github.com/stackitcloud/gardener-extension-acl/pkg/helper"
"github.com/stackitcloud/gardener-extension-acl/pkg/imagevector"

apierrors "k8s.io/apimachinery/pkg/api/errors"
)

const (
Expand Down Expand Up @@ -147,6 +150,21 @@ func (a *actuator) Reconcile(ctx context.Context, log logr.Logger, ex *extension

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

// This relies on the LB hairpinning in-cluster traffic out and back in
// through the Seed's egress IP, which is the common case when the LB
// exposes ipMode: Proxy and the CNI does not short-circuit clusterIP
// traffic (e.g., Cilium with bpfSocketLBHostnsOnly: true).
if ok, err := a.usesProxyTypeLBService(ctx, istioNamespace); err != nil {
log.Error(err, "unable to get Istio Ingressgateway service", "namespace", istioNamespace)
return err
} else if ok {
egressCIDRs, err := a.getSeedEgressIPOnManagedSeeds(ctx)
if err != nil {
return err
}
alwaysAllowedCIDRs = append(alwaysAllowedCIDRs, egressCIDRs...)
}

if len(a.extensionConfig.AdditionalAllowedCIDRs) >= 1 {
alwaysAllowedCIDRs = append(alwaysAllowedCIDRs, a.extensionConfig.AdditionalAllowedCIDRs...)
}
Expand Down Expand Up @@ -260,14 +278,14 @@ func (a *actuator) createSeedResources(
spec *extensionspec.ExtensionSpec,
cluster *controller.Cluster,
hosts []string,
shootSpecificCIRDs []string,
shootSpecificCIDRs []string,
alwaysAllowedCIDRs []string,
istioNamespace string,
istioLabels map[string]string,
) error {
var err error

alwaysAllowedCIDRs = append(alwaysAllowedCIDRs, shootSpecificCIRDs...)
alwaysAllowedCIDRs = append(alwaysAllowedCIDRs, shootSpecificCIDRs...)

apiEnvoyFilterSpec, err := envoyfilters.BuildAPIEnvoyFilterSpecForHelmChart(
spec.Rule, hosts, alwaysAllowedCIDRs, istioLabels,
Expand Down Expand Up @@ -447,3 +465,66 @@ func (a *actuator) findDefaultIstioLabels(

return gw.Spec.Selector, nil
}

// usesProxyTypeLBService checks the `istio-ingressgateway` LoadBalancer Service
// selected by its labels whether it is exposing the service with the Proxy IPMode
func (a *actuator) usesProxyTypeLBService(
ctx context.Context,
namespace string,
) (bool, error) {
svc := corev1.Service{}
err := a.client.Get(
ctx,
client.ObjectKey{
Name: v1beta1constants.DefaultSNIIngressServiceName,
Namespace: namespace,
},
&svc)
if err != nil {
if apierrors.IsNotFound(err) {
return false, nil
}
return false, err
}

for _, ing := range svc.Status.LoadBalancer.Ingress {
if m := ing.IPMode; m != nil && *m == corev1.LoadBalancerIPModeProxy {
return true, nil
}
}

return false, nil
}

// getSeedEgressIPOnManagedSeeds returns the egressIP CIDRs of the ManagedSeed, if the
// Seed is not a shoot, it will return an empty list
func (a *actuator) getSeedEgressIPOnManagedSeeds(ctx context.Context) ([]string, error) {
cm := corev1.ConfigMap{}
if err := a.client.Get(ctx,
client.ObjectKey{
Name: v1beta1constants.ConfigMapNameShootInfo,
Namespace: "kube-system",
},
&cm); err != nil {
if apierrors.IsNotFound(err) {
return []string{}, nil
}
return nil, err
}

cidrsStr, ok := cm.Data["egressCIDRs"]
if !ok {
return nil, errors.New("unable to get egress CIDRs from shoot-info ConfigMap")
}

var cidrs []string
for i := range strings.SplitSeq(cidrsStr, ",") {
_, _, err := net.ParseCIDR(i)
if err != nil {
return nil, err
}
cidrs = append(cidrs, i)
}

return cidrs, nil
}
102 changes: 102 additions & 0 deletions pkg/controller/actuator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/utils/ptr"

"github.com/stackitcloud/gardener-extension-acl/pkg/controller/config"
"github.com/stackitcloud/gardener-extension-acl/pkg/envoyfilters"
Expand All @@ -26,11 +27,13 @@ var _ = Describe("actuator test", func() {
shootNamespace1, shootNamespace2 string
istioNamespace1, istioNamespace2 string
istioNamespace1Selector, istioNamespace2Selector map[string]string
istioIngressGatewayServiceName string
)

BeforeEach(func() {
shootNamespace1 = createNewShootNamespace()
istioNamespace1 = createNewIstioNamespace()
istioIngressGatewayServiceName = "istio-ingressgateway"
istioNamespace1Selector = map[string]string{
"app": "istio-ingressgateway",
"istio": istioNamespace1,
Expand All @@ -41,6 +44,24 @@ var _ = Describe("actuator test", func() {
createNewIstioDeployment(istioNamespace1, istioNamespace1Selector)
createNewCluster(shootNamespace1)
createNewInfrastructure(shootNamespace1)
createNewService(
istioIngressGatewayServiceName,
istioNamespace1,
istioNamespace1Selector,
corev1.ServiceTypeLoadBalancer,
)
updateServiceStatus(
istioIngressGatewayServiceName,
istioNamespace1,
corev1.ServiceStatus{
LoadBalancer: corev1.LoadBalancerStatus{
Ingress: []corev1.LoadBalancerIngress{{
IP: "1.1.1.1",
IPMode: ptr.To(corev1.LoadBalancerIPModeProxy),
}},
},
},
)

a = getNewActuator()
})
Expand Down Expand Up @@ -222,6 +243,87 @@ var _ = Describe("actuator test", func() {
})
})

Describe("reconciliation of an extension object running on a managedSeed", func() {
AfterEach(func() {
deleteShootInfo()
})

It("should not get the egressIPs if the LoadBalancer IPMode is not set to Proxy", func() {
updateServiceStatus(
istioIngressGatewayServiceName,
istioNamespace1,
corev1.ServiceStatus{},
)
Expect(a.usesProxyTypeLBService(ctx, istioNamespace1)).To(BeFalse())

updateServiceStatus(
istioIngressGatewayServiceName,
istioNamespace1,
corev1.ServiceStatus{
LoadBalancer: corev1.LoadBalancerStatus{
Ingress: []corev1.LoadBalancerIngress{{
IP: "1.1.1.1",
IPMode: ptr.To(corev1.LoadBalancerIPModeVIP),
}},
},
},
)
Expect(a.usesProxyTypeLBService(ctx, istioNamespace1)).To(BeFalse())
})

It("should get the egressIPs if the LoadBalancer IPMode is set to Proxy", func() {
Expect(a.usesProxyTypeLBService(ctx, istioNamespace1)).To(BeTrue())
})

It("should return an empty slice of egressIPs if no shoot-info ConfigMap exists", func() {
cidrs, err := a.getSeedEgressIPOnManagedSeeds(ctx)
Expect(err).ToNot(HaveOccurred())
Expect(cidrs).To(BeEmpty())
})

It("should fail to return egressIPs if the shoot-info ConfigMap contains invalid CIDRs", func() {
createShootInfo([]string{"1.1.1.1", "1.1.1.2/32"})

_, err := a.getSeedEgressIPOnManagedSeeds(ctx)
Expect(err).To(HaveOccurred())
})

It("should return the egressIP CIDRs of the shoot-info ConfigMap", func() {
c := []string{"1.1.1.1/32", "1.1.1.2/32"}
createShootInfo(c)

cidrs, err := a.getSeedEgressIPOnManagedSeeds(ctx)
Expect(err).ToNot(HaveOccurred())
Expect(cidrs).To(BeEquivalentTo(c))
})

It("should create ACLs including egressIPs of managedSeed", func() {
Comment thread
hown3d marked this conversation as resolved.
createShootInfo([]string{"1.1.1.1/32", "1.1.1.2/32"})

extSpec := extensionspec.ExtensionSpec{
Rule: &envoyfilters.ACLRule{
Cidrs: []string{"1.2.3.4/24"},
Action: "ALLOW",
Type: "remote_ip",
},
}
extSpecJSON, err := json.Marshal(extSpec)
Expect(err).NotTo(HaveOccurred())
ext := createNewExtension(shootNamespace1, extSpecJSON)
Expect(ext).To(Not(BeNil()))

Expect(a.Reconcile(ctx, logger, ext)).To(Succeed())

mr := &v1alpha1.ManagedResource{}
Expect(k8sClient.Get(ctx, types.NamespacedName{Name: ResourceNameSeed, Namespace: shootNamespace1}, mr)).To(Succeed())
secret := &corev1.Secret{}
Expect(k8sClient.Get(ctx, types.NamespacedName{Name: mr.Spec.SecretRefs[0].Name, Namespace: shootNamespace1}, secret)).To(Succeed())
Expect(secret.Data["seed"]).To(ContainSubstring("1.2.3.4"))
Expect(secret.Data["seed"]).To(ContainSubstring("1.1.1.1"))
Expect(secret.Data["seed"]).To(ContainSubstring("1.1.1.2"))
})
})

Describe("a shoot switching the istio namespace (e.g. when being migrated to HA)", func() {
It("should modify the EnvoyFilter objects accordingly", func() {
By("1) creating the EnvoyFilter object correctly in the ORIGINAL namespace")
Expand Down
Loading