feat: allowed external IPs is grouped in ServiceOptions

This commit is contained in:
Dario Tranchitella
2021-07-23 08:28:20 +02:00
parent d43ad2f9f8
commit 18912a002b
8 changed files with 34 additions and 27 deletions
+8 -5
View File
@@ -201,12 +201,15 @@ func (t *Tenant) ConvertTo(dstRaw conversion.Hub) error {
}
}
if t.Spec.ExternalServiceIPs != nil {
dst.Spec.ExternalServiceIPs = &capsulev1beta1.ExternalServiceIPsSpec{
if dst.Spec.ServiceOptions == nil {
dst.Spec.ServiceOptions = &capsulev1beta1.ServiceOptions{}
}
dst.Spec.ServiceOptions.ExternalServiceIPs = &capsulev1beta1.ExternalServiceIPsSpec{
Allowed: make([]capsulev1beta1.AllowedIP, len(t.Spec.ExternalServiceIPs.Allowed)),
}
for i, IP := range t.Spec.ExternalServiceIPs.Allowed {
dst.Spec.ExternalServiceIPs.Allowed[i] = capsulev1beta1.AllowedIP(IP)
dst.Spec.ServiceOptions.ExternalServiceIPs.Allowed[i] = capsulev1beta1.AllowedIP(IP)
}
}
@@ -459,12 +462,12 @@ func (t *Tenant) ConvertFrom(srcRaw conversion.Hub) error {
})
}
}
if src.Spec.ExternalServiceIPs != nil {
if src.Spec.ServiceOptions != nil && src.Spec.ServiceOptions.ExternalServiceIPs != nil {
t.Spec.ExternalServiceIPs = &ExternalServiceIPsSpec{
Allowed: make([]AllowedIP, len(src.Spec.ExternalServiceIPs.Allowed)),
Allowed: make([]AllowedIP, len(src.Spec.ServiceOptions.ExternalServiceIPs.Allowed)),
}
for i, IP := range src.Spec.ExternalServiceIPs.Allowed {
for i, IP := range src.Spec.ServiceOptions.ExternalServiceIPs.Allowed {
t.Spec.ExternalServiceIPs.Allowed[i] = AllowedIP(IP)
}
}
+3 -3
View File
@@ -49,6 +49,9 @@ func generateTenantsSpecs() (Tenant, capsulev1beta1.Tenant) {
NodePort: pointer.BoolPtr(false),
ExternalName: pointer.BoolPtr(false),
},
ExternalServiceIPs: &capsulev1beta1.ExternalServiceIPsSpec{
Allowed: []capsulev1beta1.AllowedIP{"192.168.0.1"},
},
}
var v1beta1AllowedListSpec = &capsulev1beta1.AllowedListSpec{
Exact: []string{"foo", "bar"},
@@ -251,9 +254,6 @@ func generateTenantsSpecs() (Tenant, capsulev1beta1.Tenant) {
},
},
},
ExternalServiceIPs: &capsulev1beta1.ExternalServiceIPsSpec{
Allowed: []capsulev1beta1.AllowedIP{"192.168.0.1"},
},
ImagePullPolicies: []capsulev1beta1.ImagePullPolicySpec{"Always", "IfNotPresent"},
PriorityClasses: &capsulev1beta1.AllowedListSpec{
Exact: []string{"default"},
+13
View File
@@ -0,0 +1,13 @@
// Copyright 2020-2021 Clastix Labs
// SPDX-License-Identifier: Apache-2.0
package v1beta1
type AllowedServices struct {
//+kubebuilder:default=true
// Specifies if NodePort service type resources are allowed for the Tenant. Default is true. Optional.
NodePort *bool `json:"nodePort,omitempty"`
//+kubebuilder:default=true
// Specifies if ExternalName service type resources are allowed for the Tenant. Default is true. Optional.
ExternalName *bool `json:"externalName,omitempty"`
}
+2 -9
View File
@@ -8,13 +8,6 @@ type ServiceOptions struct {
AdditionalMetadata *AdditionalMetadataSpec `json:"additionalMetadata,omitempty"`
// Block or deny certain type of Services. Optional.
AllowedServices *AllowedServices `json:"allowedServices,omitempty"`
}
type AllowedServices struct {
//+kubebuilder:default=true
// Specifies if NodePort service type resources are allowed for the Tenant. Default is true. Optional.
NodePort *bool `json:"nodePort,omitempty"`
//+kubebuilder:default=true
// Specifies if ExternalName service type resources are allowed for the Tenant. Default is true. Optional.
ExternalName *bool `json:"externalName,omitempty"`
// Specifies the external IPs that can be used in Services with type ClusterIP. An empty list means all the IPs are allowed. Optional.
ExternalServiceIPs *ExternalServiceIPsSpec `json:"externalIPs,omitempty"`
}
-2
View File
@@ -37,8 +37,6 @@ type TenantSpec struct {
ResourceQuota *ResourceQuotaSpec `json:"resourceQuotas,omitempty"`
// Specifies additional RoleBindings assigned to the Tenant. Capsule will ensure that all namespaces in the Tenant always contain the RoleBinding for the given ClusterRole. Optional.
AdditionalRoleBindings []AdditionalRoleBindingsSpec `json:"additionalRoleBindings,omitempty"`
// Specifies the external IPs that can be used in Services with type ClusterIP. An empty list means all the IPs are allowed. Optional.
ExternalServiceIPs *ExternalServiceIPsSpec `json:"externalServiceIPs,omitempty"`
// Specify the allowed values for the imagePullPolicies option in Pod resources. Capsule assures that all Pod resources created in the Tenant can use only one of the allowed policy. Optional.
ImagePullPolicies []ImagePullPolicySpec `json:"imagePullPolicies,omitempty"`
// Specifies the allowed IngressClasses assigned to the Tenant. Capsule assures that all Ingress resources created in the Tenant can use only one of the allowed IngressClasses. Optional.
+5 -5
View File
@@ -291,6 +291,11 @@ func (in *ServiceOptions) DeepCopyInto(out *ServiceOptions) {
*out = new(AllowedServices)
(*in).DeepCopyInto(*out)
}
if in.ExternalServiceIPs != nil {
in, out := &in.ExternalServiceIPs, &out.ExternalServiceIPs
*out = new(ExternalServiceIPsSpec)
(*in).DeepCopyInto(*out)
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceOptions.
@@ -436,11 +441,6 @@ func (in *TenantSpec) DeepCopyInto(out *TenantSpec) {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
if in.ExternalServiceIPs != nil {
in, out := &in.ExternalServiceIPs, &out.ExternalServiceIPs
*out = new(ExternalServiceIPsSpec)
(*in).DeepCopyInto(*out)
}
if in.ImagePullPolicies != nil {
in, out := &in.ImagePullPolicies, &out.ImagePullPolicies
*out = make([]ImagePullPolicySpec, len(*in))
+3 -3
View File
@@ -60,12 +60,12 @@ func (r *handler) handleService(ctx context.Context, clt client.Client, decoder
return &response
}
if svc.Spec.ExternalIPs == nil || tnt.Spec.ExternalServiceIPs == nil {
if svc.Spec.ExternalIPs == nil || (tnt.Spec.ServiceOptions == nil || tnt.Spec.ServiceOptions.ExternalServiceIPs == nil) {
return nil
}
ipInCIDR := func(ip net.IP) bool {
for _, allowed := range tnt.Spec.ExternalServiceIPs.Allowed {
for _, allowed := range tnt.Spec.ServiceOptions.ExternalServiceIPs.Allowed {
if !strings.Contains(string(allowed), "/") {
allowed += "/32"
}
@@ -85,7 +85,7 @@ func (r *handler) handleService(ctx context.Context, clt client.Client, decoder
if !ipInCIDR(ip) {
recorder.Eventf(&tnt, corev1.EventTypeWarning, "ForbiddenExternalServiceIP", "Service %s/%s external IP %s is forbidden for the current Tenant", req.Namespace, req.Name, ip.String())
response := admission.Denied(NewExternalServiceIPForbidden(tnt.Spec.ExternalServiceIPs.Allowed).Error())
response := admission.Denied(NewExternalServiceIPForbidden(tnt.Spec.ServiceOptions.ExternalServiceIPs.Allowed).Error())
return &response
}