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
43 changes: 43 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,16 @@ rules:
- delete
resources:
- envoyfilters
- apiGroups:
- ""
resources:
- services
resourceNames:
- istio-ingressgateway
verbs:
- get
- list
- watch
- apiGroups:
- extensions.gardener.cloud
resources:
Expand Down Expand Up @@ -144,6 +154,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 +184,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 }}
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: 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
values:
image:
tag: latest
Expand Down
86 changes: 84 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 @@ -87,13 +90,15 @@ func NewActuator(mgr manager.Manager, cfg config.Config) extension.Actuator {
return &actuator{
extensionConfig: cfg,
client: mgr.GetClient(),
reader: mgr.GetAPIReader(),
config: mgr.GetConfig(),
decoder: serializer.NewCodecFactory(mgr.GetScheme(), serializer.EnableStrict).UniversalDecoder(),
}
}

type actuator struct {
client client.Client
reader client.Reader
config *rest.Config
decoder runtime.Decoder
extensionConfig config.Config
Expand Down Expand Up @@ -147,6 +152,18 @@ func (a *actuator) Reconcile(ctx context.Context, log logr.Logger, ex *extension

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

// In casese where the istio-ingressgateway is exposed with the Proxy IPMode some
// CNIs (like cilium for example) do not hairpin NAT the traffic to it, which
// will result in the destination IP being set to the egressIP of the cluster.
// In that case the AlertManager ApiServerNoteReachable check will fail.
if a.usesProxyTypeLBService(ctx, log, istioLabels) {
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 +277,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 @@ -446,3 +463,68 @@ 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,
log logr.Logger,
labels map[string]string,
) bool {
svcs := corev1.ServiceList{}
labelsSelector := client.MatchingLabels(labels)
fieldSelector := client.MatchingFields{"metadata.name": v1beta1constants.DefaultSNIIngressServiceName}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This does not cover support for ExposureClasses as they use a different service name. Please add support for that.

err := a.reader.List(ctx, &svcs, labelsSelector, fieldSelector)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why a list with field selector metadata.name and not a simple Get?

if err != nil {
log.Error(err, "unable to fetch Services for Istio Ingressgateways", "labels", labels)
return false
}

switch len(svcs.Items) {
case 1:
for _, ing := range svcs.Items[0].Status.LoadBalancer.Ingress {
if m := ing.IPMode; m != nil && *m == corev1.LoadBalancerIPModeProxy {
return true
}
}
case 0:
log.Error(nil, "unable to find Istio Ingressgateway service", "name", v1beta1constants.DefaultSNIIngressServiceName, "labels", labels)
default:
log.Error(nil, "found more than one IngressGateway service", "name", v1beta1constants.DefaultSNIIngressServiceName, "labels", labels)
}

return false
}

// 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
}
104 changes: 104 additions & 0 deletions pkg/controller/actuator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@ import (
extensionsv1alpha1 "github.com/gardener/gardener/pkg/apis/extensions/v1alpha1"
"github.com/gardener/gardener/pkg/apis/resources/v1alpha1"
. "github.com/gardener/gardener/pkg/utils/test/matchers"
"github.com/go-logr/logr"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
istionetworkingv1beta1 "istio.io/client-go/pkg/apis/networking/v1beta1"
corev1 "k8s.io/api/core/v1"
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 +28,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 +45,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 +244,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, logr.Logger{}, istioNamespace1Selector)).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, logr.Logger{}, istioNamespace1Selector)).To(BeFalse())
})

It("should get the egressIPs if the LoadBalancer IPMode is set to Proxy", func() {
Expect(a.usesProxyTypeLBService(ctx, logr.Logger{}, istioNamespace1Selector)).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() {
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 Expand Up @@ -453,6 +556,7 @@ var _ = Describe("actuator unit test", func() {
func getNewActuator() *actuator {
return &actuator{
client: k8sClient,
reader: k8sClient,
config: cfg,
extensionConfig: config.Config{
ChartPath: "../../charts",
Expand Down
Loading