Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add translation for GKE Security Policy #191

Merged
merged 2 commits into from
Sep 17, 2024
Merged
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
4 changes: 4 additions & 0 deletions pkg/i2gw/intermediate/provider_gce.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,15 @@ type GceGatewayIR struct {
type GceHTTPRouteIR struct{}
type GceServiceIR struct {
SessionAffinity *SessionAffinityConfig
SecurityPolicy *SecurityPolicyConfig
}
type SessionAffinityConfig struct {
AffinityType string
CookieTTLSec *int64
}
type SecurityPolicyConfig struct {
Name string
}

func mergeGceGatewayIR(current, existing *GceGatewayIR) *GceGatewayIR {
// If either GceGatewayIR is nil, return the other one as the merged result.
Expand Down
6 changes: 6 additions & 0 deletions pkg/i2gw/providers/gce/extensions/input_extensions.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,9 @@ func BuildIRSessionAffinityConfig(beConfig *backendconfigv1.BackendConfig) *inte
CookieTTLSec: beConfig.Spec.SessionAffinity.AffinityCookieTtlSec,
}
}

func BuildIRSecurityPolicyConfig(beConfig *backendconfigv1.BackendConfig) *intermediate.SecurityPolicyConfig {
return &intermediate.SecurityPolicyConfig{
Name: beConfig.Spec.SecurityPolicy.Name,
}
}
5 changes: 5 additions & 0 deletions pkg/i2gw/providers/gce/extensions/output_extensions.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,8 @@ func BuildBackendPolicySessionAffinityConfig(serviceIR intermediate.ProviderSpec
}
return &saConfig
}

func BuildBackendPolicySecurityPolicyConfig(serviceIR intermediate.ProviderSpecificServiceIR) *string {
securityPolicy := serviceIR.Gce.SecurityPolicy.Name
return &securityPolicy
}
59 changes: 59 additions & 0 deletions pkg/i2gw/providers/gce/gateway_converter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ func Test_irToGateway(t *testing.T) {
saTypeClientIP := "CLIENT_IP"
testCookieTTLSec := int64(10)
saTypeCookie := "GENERATED_COOKIE"
testSecurityPolicy := "test-security-policy"

testGateway := gatewayv1.Gateway{
ObjectMeta: metav1.ObjectMeta{Name: testGatewayName, Namespace: testNamespace},
Expand Down Expand Up @@ -143,6 +144,28 @@ func Test_irToGateway(t *testing.T) {
if err != nil {
t.Errorf("Failed to generate unstructured GCP Backend Policy with ClientIP-based session affinity feature: %v", err)
}

testSpGCPBackendPolicy := gkegatewayv1.GCPBackendPolicy{
ObjectMeta: metav1.ObjectMeta{
Namespace: testNamespace,
Name: testSaBackendPolicyName,
},
Spec: gkegatewayv1.GCPBackendPolicySpec{
Default: &gkegatewayv1.GCPBackendPolicyConfig{
SecurityPolicy: &testSecurityPolicy,
},
TargetRef: v1alpha2.NamespacedPolicyTargetReference{
Group: "",
Kind: "Service",
Name: gatewayv1.ObjectName(testServiceName),
},
},
}
testSpGCPBackendPolicy.SetGroupVersionKind(GCPBackendPolicyGVK)
testSpGCPBackendPolicyUnstructured, err := i2gw.CastToUnstructured(&testSpGCPBackendPolicy)
if err != nil {
t.Errorf("Failed to generate unstructured GCP Backend Policy with Security Policy feature: %v", err)
}
testCases := []struct {
name string
ir intermediate.IR
Expand Down Expand Up @@ -222,6 +245,42 @@ func Test_irToGateway(t *testing.T) {
},
expectedErrors: field.ErrorList{},
},
{
name: "ingress with a Backend Config specifying Security Policy",
ir: intermediate.IR{
Gateways: map[types.NamespacedName]intermediate.GatewayContext{
{Namespace: testNamespace, Name: testGatewayName}: {
Gateway: testGateway,
},
},
HTTPRoutes: map[types.NamespacedName]intermediate.HTTPRouteContext{
{Namespace: testNamespace, Name: testHTTPRouteName}: {
HTTPRoute: testHTTPRoute,
},
},
Services: map[types.NamespacedName]intermediate.ProviderSpecificServiceIR{
{Namespace: testNamespace, Name: testServiceName}: {
Gce: &intermediate.GceServiceIR{
SecurityPolicy: &intermediate.SecurityPolicyConfig{
Name: testSecurityPolicy,
},
},
},
},
},
expectedGatewayResources: i2gw.GatewayResources{
Gateways: map[types.NamespacedName]gatewayv1.Gateway{
{Namespace: testNamespace, Name: testGatewayName}: testGateway,
},
HTTPRoutes: map[types.NamespacedName]gatewayv1.HTTPRoute{
{Namespace: testNamespace, Name: testHTTPRouteName}: testHTTPRoute,
},
GatewayExtensions: []unstructured.Unstructured{
*testSpGCPBackendPolicyUnstructured,
},
},
expectedErrors: field.ErrorList{},
},
}

for _, tc := range testCases {
Expand Down
6 changes: 6 additions & 0 deletions pkg/i2gw/providers/gce/gce_extensions.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,9 @@ func beConfigToGceServiceIR(beConfig *backendconfigv1.BackendConfig) intermediat
if beConfig.Spec.SessionAffinity != nil {
gceServiceIR.SessionAffinity = extensions.BuildIRSessionAffinityConfig(beConfig)
}
if beConfig.Spec.SecurityPolicy != nil {
gceServiceIR.SecurityPolicy = extensions.BuildIRSecurityPolicyConfig(beConfig)
}

return gceServiceIR
}
Expand Down Expand Up @@ -190,6 +193,9 @@ func addBackendPolicyIfConfigured(serviceNamespacedName types.NamespacedName, se
if serviceIR.Gce.SessionAffinity != nil {
backendPolicy.Spec.Default.SessionAffinity = extensions.BuildBackendPolicySessionAffinityConfig(serviceIR)
}
if serviceIR.Gce.SecurityPolicy != nil {
backendPolicy.Spec.Default.SecurityPolicy = extensions.BuildBackendPolicySecurityPolicyConfig(serviceIR)
}

return &backendPolicy
}
123 changes: 123 additions & 0 deletions pkg/i2gw/providers/gce/ir_converter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ func Test_convertToIR(t *testing.T) {
saTypeClientIP := "CLIENT_IP"
testCookieTTLSec := int64(10)
saTypeCookie := "GENERATED_COOKIE"
testSecurityPolicy := "test-security-policy"

testCases := []struct {
name string
Expand Down Expand Up @@ -889,6 +890,128 @@ func Test_convertToIR(t *testing.T) {
},
expectedErrors: field.ErrorList{},
},
{
name: "ingress with a Backend Config specifying Security Policy",
ingresses: map[types.NamespacedName]*networkingv1.Ingress{
{Namespace: testNamespace, Name: extIngClassIngressName}: {
ObjectMeta: metav1.ObjectMeta{
Name: extIngClassIngressName,
Namespace: testNamespace,
Annotations: map[string]string{networkingv1beta1.AnnotationIngressClass: gceIngressClass},
},
Spec: networkingv1.IngressSpec{
Rules: []networkingv1.IngressRule{{
Host: testHost,
IngressRuleValue: networkingv1.IngressRuleValue{
HTTP: &networkingv1.HTTPIngressRuleValue{
Paths: []networkingv1.HTTPIngressPath{{
Path: "/",
PathType: &iPrefix,
Backend: networkingv1.IngressBackend{
Service: &networkingv1.IngressServiceBackend{
Name: testServiceName,
Port: networkingv1.ServiceBackendPort{
Number: 80,
},
},
},
}},
},
},
}},
},
},
},
services: map[types.NamespacedName]*apiv1.Service{
{Namespace: testNamespace, Name: testServiceName}: {
ObjectMeta: metav1.ObjectMeta{
Namespace: testNamespace,
Name: testServiceName,
Annotations: map[string]string{
backendConfigKey: `{"default":"test-backendconfig"}`,
},
},
},
},
backendConfigs: map[types.NamespacedName]*backendconfigv1.BackendConfig{
{Namespace: testNamespace, Name: testBackendConfigName}: {
ObjectMeta: metav1.ObjectMeta{
Namespace: testNamespace,
Name: testBackendConfigName,
},
Spec: backendconfigv1.BackendConfigSpec{
SecurityPolicy: &backendconfigv1.SecurityPolicyConfig{
Name: testSecurityPolicy,
},
},
},
},
expectedIR: intermediate.IR{
Gateways: map[types.NamespacedName]intermediate.GatewayContext{
{Namespace: testNamespace, Name: gceIngressClass}: {
Gateway: gatewayv1.Gateway{
ObjectMeta: metav1.ObjectMeta{Name: gceIngressClass, Namespace: testNamespace},
Spec: gatewayv1.GatewaySpec{
GatewayClassName: gceL7GlobalExternalManagedGatewayClass,
Listeners: []gatewayv1.Listener{{
Name: "test-mydomain-com-http",
Port: 80,
Protocol: gatewayv1.HTTPProtocolType,
Hostname: ptrTo(gatewayv1.Hostname(testHost)),
}},
},
},
},
},
HTTPRoutes: map[types.NamespacedName]intermediate.HTTPRouteContext{
{Namespace: testNamespace, Name: fmt.Sprintf("%s-test-mydomain-com", extIngClassIngressName)}: {
HTTPRoute: gatewayv1.HTTPRoute{
ObjectMeta: metav1.ObjectMeta{Name: fmt.Sprintf("%s-test-mydomain-com", extIngClassIngressName), Namespace: testNamespace},
Spec: gatewayv1.HTTPRouteSpec{
CommonRouteSpec: gatewayv1.CommonRouteSpec{
ParentRefs: []gatewayv1.ParentReference{{
Name: gceIngressClass,
}},
},
Hostnames: []gatewayv1.Hostname{gatewayv1.Hostname(testHost)},
Rules: []gatewayv1.HTTPRouteRule{
{
Matches: []gatewayv1.HTTPRouteMatch{
{
Path: &gatewayv1.HTTPPathMatch{
Type: &gPathPrefix,
Value: ptrTo("/"),
},
},
},
BackendRefs: []gatewayv1.HTTPBackendRef{
{
BackendRef: gatewayv1.BackendRef{
BackendObjectReference: gatewayv1.BackendObjectReference{
Name: gatewayv1.ObjectName(testServiceName),
Port: ptrTo(gatewayv1.PortNumber(80)),
},
},
},
},
},
},
},
},
},
},
Services: map[types.NamespacedName]intermediate.ProviderSpecificServiceIR{
{Namespace: testNamespace, Name: testServiceName}: {
Gce: &intermediate.GceServiceIR{
SecurityPolicy: &intermediate.SecurityPolicyConfig{
Name: testSecurityPolicy,
},
},
},
},
},
expectedErrors: field.ErrorList{},
},
}

for _, tc := range testCases {
Expand Down
Loading