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 Ssl Policy #195

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
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
4 changes: 4 additions & 0 deletions pkg/i2gw/intermediate/provider_gce.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ package intermediate

type GceGatewayIR struct {
EnableHTTPSRedirect bool
SslPolicy *SslPolicyConfig
}
type SslPolicyConfig struct {
Name string
}
type GceHTTPRouteIR struct{}
type GceServiceIR struct {
Expand Down
7 changes: 7 additions & 0 deletions pkg/i2gw/providers/gce/extensions/input_extensions.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (

"github.com/kubernetes-sigs/ingress2gateway/pkg/i2gw/intermediate"
backendconfigv1 "k8s.io/ingress-gce/pkg/apis/backendconfig/v1"
frontendconfigv1beta1 "k8s.io/ingress-gce/pkg/apis/frontendconfig/v1beta1"
)

func ValidateBeConfig(beConfig *backendconfigv1.BackendConfig) error {
Expand Down Expand Up @@ -52,3 +53,9 @@ func BuildIRSecurityPolicyConfig(beConfig *backendconfigv1.BackendConfig) *inter
Name: beConfig.Spec.SecurityPolicy.Name,
}
}

func BuildIRSslPolicyConfig(feConfig *frontendconfigv1beta1.FrontendConfig) *intermediate.SslPolicyConfig {
return &intermediate.SslPolicyConfig{
Name: *feConfig.Spec.SslPolicy,
}
}
8 changes: 6 additions & 2 deletions pkg/i2gw/providers/gce/extensions/output_extensions.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import (
"github.com/kubernetes-sigs/ingress2gateway/pkg/i2gw/intermediate"
)

func BuildBackendPolicySessionAffinityConfig(serviceIR intermediate.ProviderSpecificServiceIR) *gkegatewayv1.SessionAffinityConfig {
func BuildGCPBackendPolicySessionAffinityConfig(serviceIR intermediate.ProviderSpecificServiceIR) *gkegatewayv1.SessionAffinityConfig {
affinityType := serviceIR.Gce.SessionAffinity.AffinityType
saConfig := gkegatewayv1.SessionAffinityConfig{
Type: &affinityType,
Expand All @@ -32,7 +32,11 @@ func BuildBackendPolicySessionAffinityConfig(serviceIR intermediate.ProviderSpec
return &saConfig
}

func BuildBackendPolicySecurityPolicyConfig(serviceIR intermediate.ProviderSpecificServiceIR) *string {
func BuildGCPBackendPolicySecurityPolicyConfig(serviceIR intermediate.ProviderSpecificServiceIR) *string {
securityPolicy := serviceIR.Gce.SecurityPolicy.Name
return &securityPolicy
}

func BuildGCPGatewayPolicySecurityPolicyConfig(gatewayIR intermediate.ProviderSpecificGatewayIR) string {
return gatewayIR.Gce.SslPolicy.Name
}
59 changes: 52 additions & 7 deletions pkg/i2gw/providers/gce/gateway_converter.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,58 @@ func (c *irToGatewayResourcesConverter) irToGateway(ir intermediate.IR) (i2gw.Ga
if len(errs) != 0 {
return i2gw.GatewayResources{}, errs
}
buildGceGatewayExtensions(ir, &gatewayResources)
buildGceServiceExtensions(ir, &gatewayResources)
return gatewayResources, nil
}

func buildGceGatewayExtensions(ir intermediate.IR, gatewayResources *i2gw.GatewayResources) {
for gwyKey, gatewayContext := range ir.Gateways {
gwyPolicy := addGatewayPolicyIfConfigured(gwyKey, gatewayContext.ProviderSpecificIR)
if gwyPolicy == nil {
continue
}
obj, err := i2gw.CastToUnstructured(gwyPolicy)
if err != nil {
notify(notifications.ErrorNotification, "Failed to cast GCPGatewayPolicy to unstructured", gwyPolicy)
continue
}
gatewayResources.GatewayExtensions = append(gatewayResources.GatewayExtensions, *obj)
}
}

func addGatewayPolicyIfConfigured(gatewayNamespacedName types.NamespacedName, gatewayIR intermediate.ProviderSpecificGatewayIR) *gkegatewayv1.GCPGatewayPolicy {
if gatewayIR.Gce == nil {
return nil
}
// If there is no specification related to GCPGatewayPolicy feature, return nil.
if gatewayIR.Gce.SslPolicy == nil {
return nil
}
gcpGatewayPolicy := gkegatewayv1.GCPGatewayPolicy{
ObjectMeta: metav1.ObjectMeta{
Namespace: gatewayNamespacedName.Namespace,
Name: gatewayNamespacedName.Name,
},
Spec: gkegatewayv1.GCPGatewayPolicySpec{
Default: &gkegatewayv1.GCPGatewayPolicyConfig{},
TargetRef: gatewayv1alpha2.NamespacedPolicyTargetReference{
Group: "gateway.networking.k8s.io",
Kind: "Gateway",
Name: gatewayv1.ObjectName(gatewayNamespacedName.Name),
},
},
}
gcpGatewayPolicy.SetGroupVersionKind(GCPGatewayPolicyGVK)
if gatewayIR.Gce.SslPolicy != nil {
gcpGatewayPolicy.Spec.Default.SslPolicy = extensions.BuildGCPGatewayPolicySecurityPolicyConfig(gatewayIR)
}
return &gcpGatewayPolicy
}

func buildGceServiceExtensions(ir intermediate.IR, gatewayResources *i2gw.GatewayResources) {
for svcKey, serviceIR := range ir.Services {
bePolicy := addBackendPolicyIfConfigured(svcKey, serviceIR)
bePolicy := addGCPBackendPolicyIfConfigured(svcKey, serviceIR)
if bePolicy == nil {
continue
}
Expand All @@ -61,11 +106,11 @@ func buildGceServiceExtensions(ir intermediate.IR, gatewayResources *i2gw.Gatewa
}
}

func addBackendPolicyIfConfigured(serviceNamespacedName types.NamespacedName, serviceIR intermediate.ProviderSpecificServiceIR) *gkegatewayv1.GCPBackendPolicy {
func addGCPBackendPolicyIfConfigured(serviceNamespacedName types.NamespacedName, serviceIR intermediate.ProviderSpecificServiceIR) *gkegatewayv1.GCPBackendPolicy {
if serviceIR.Gce == nil {
return nil
}
backendPolicy := gkegatewayv1.GCPBackendPolicy{
gcpBackendPolicy := gkegatewayv1.GCPBackendPolicy{
ObjectMeta: metav1.ObjectMeta{
Namespace: serviceNamespacedName.Namespace,
Name: serviceNamespacedName.Name,
Expand All @@ -79,14 +124,14 @@ func addBackendPolicyIfConfigured(serviceNamespacedName types.NamespacedName, se
},
},
}
backendPolicy.SetGroupVersionKind(GCPBackendPolicyGVK)
gcpBackendPolicy.SetGroupVersionKind(GCPBackendPolicyGVK)

if serviceIR.Gce.SessionAffinity != nil {
backendPolicy.Spec.Default.SessionAffinity = extensions.BuildBackendPolicySessionAffinityConfig(serviceIR)
gcpBackendPolicy.Spec.Default.SessionAffinity = extensions.BuildGCPBackendPolicySessionAffinityConfig(serviceIR)
}
if serviceIR.Gce.SecurityPolicy != nil {
backendPolicy.Spec.Default.SecurityPolicy = extensions.BuildBackendPolicySecurityPolicyConfig(serviceIR)
gcpBackendPolicy.Spec.Default.SecurityPolicy = extensions.BuildGCPBackendPolicySecurityPolicyConfig(serviceIR)
}

return &backendPolicy
return &gcpBackendPolicy
}
70 changes: 64 additions & 6 deletions pkg/i2gw/providers/gce/gateway_converter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,10 @@ import (
)

const (
testGatewayName = "test-gateway"
testHTTPRouteName = "test-http-route"
testSaBackendPolicyName = testServiceName
testGatewayName = "test-gateway"
testHTTPRouteName = "test-http-route"
testSaGCPBackendPolicyName = testServiceName
testSslGCPGatewayPolicyName = testGatewayName
)

var (
Expand Down Expand Up @@ -96,7 +97,7 @@ var (
},
ObjectMeta: metav1.ObjectMeta{
Namespace: testNamespace,
Name: testSaBackendPolicyName,
Name: testSaGCPBackendPolicyName,
},
Spec: gkegatewayv1.GCPBackendPolicySpec{
Default: &gkegatewayv1.GCPBackendPolicyConfig{
Expand All @@ -120,7 +121,7 @@ var (
},
ObjectMeta: metav1.ObjectMeta{
Namespace: testNamespace,
Name: testSaBackendPolicyName,
Name: testSaGCPBackendPolicyName,
},
Spec: gkegatewayv1.GCPBackendPolicySpec{
Default: &gkegatewayv1.GCPBackendPolicyConfig{
Expand All @@ -143,7 +144,7 @@ var (
},
ObjectMeta: metav1.ObjectMeta{
Namespace: testNamespace,
Name: testSaBackendPolicyName,
Name: testSaGCPBackendPolicyName,
},
Spec: gkegatewayv1.GCPBackendPolicySpec{
Default: &gkegatewayv1.GCPBackendPolicyConfig{
Expand All @@ -156,6 +157,27 @@ var (
},
},
}

testSslGCPGatewayPolicy = gkegatewayv1.GCPGatewayPolicy{
TypeMeta: metav1.TypeMeta{
APIVersion: "networking.gke.io/v1",
Kind: "GCPGatewayPolicy",
},
ObjectMeta: metav1.ObjectMeta{
Namespace: testNamespace,
Name: testSslGCPGatewayPolicyName,
},
Spec: gkegatewayv1.GCPGatewayPolicySpec{
Default: &gkegatewayv1.GCPGatewayPolicyConfig{
SslPolicy: testSslPolicy,
},
TargetRef: v1alpha2.NamespacedPolicyTargetReference{
Group: "gateway.networking.k8s.io",
Kind: "Gateway",
Name: gatewayv1.ObjectName(testGatewayName),
},
},
}
)

func Test_irToGateway(t *testing.T) {
Expand All @@ -171,6 +193,10 @@ func Test_irToGateway(t *testing.T) {
if err != nil {
t.Errorf("Failed to generate unstructured GCP Backend Policy with Security Policy feature: %v", err)
}
testSslGCPGatewayPolicyUnstructured, err := i2gw.CastToUnstructured(&testSslGCPGatewayPolicy)
if err != nil {
t.Errorf("Failed to generate unstructured GCP Gateway Policy with Ssl Policy feature: %v", err)
}

testCases := []struct {
name string
Expand Down Expand Up @@ -287,6 +313,38 @@ func Test_irToGateway(t *testing.T) {
},
expectedErrors: field.ErrorList{},
},
{
name: "ingress with a Frontend Config specifying Ssl Policy",
ir: intermediate.IR{
Gateways: map[types.NamespacedName]intermediate.GatewayContext{
{Namespace: testNamespace, Name: testGatewayName}: {
Gateway: testGateway,
ProviderSpecificIR: intermediate.ProviderSpecificGatewayIR{
Gce: &intermediate.GceGatewayIR{
SslPolicy: &intermediate.SslPolicyConfig{Name: testSslPolicy},
},
},
},
},
HTTPRoutes: map[types.NamespacedName]intermediate.HTTPRouteContext{
{Namespace: testNamespace, Name: testHTTPRouteName}: {
HTTPRoute: testHTTPRoute,
},
},
},
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{
*testSslGCPGatewayPolicyUnstructured,
},
},
expectedErrors: field.ErrorList{},
},
}

for _, tc := range testCases {
Expand Down
8 changes: 6 additions & 2 deletions pkg/i2gw/providers/gce/gce.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"github.com/kubernetes-sigs/ingress2gateway/pkg/i2gw/notifications"
"k8s.io/apimachinery/pkg/util/validation/field"
backendconfigv1 "k8s.io/ingress-gce/pkg/apis/backendconfig/v1"
frontendconfigv1beta1 "k8s.io/ingress-gce/pkg/apis/frontendconfig/v1beta1"
)

const ProviderName = "gce"
Expand All @@ -42,12 +43,15 @@ type Provider struct {
}

func NewProvider(conf *i2gw.ProviderConf) i2gw.Provider {
// Add BackendConfig to Schema when reading in-cluster so these resources
// can be recognized.
// Add BackendConfig and FrontendConfig to Schema when reading in-cluster
// so these resources can be recognized.
if conf.Client != nil {
if err := backendconfigv1.AddToScheme(conf.Client.Scheme()); err != nil {
notify(notifications.ErrorNotification, "Failed to add v1 BackendConfig Scheme")
}
if err := frontendconfigv1beta1.AddToScheme(conf.Client.Scheme()); err != nil {
notify(notifications.ErrorNotification, "Failed to add v1beta1 FrontendConfig Scheme")
}
}
return &Provider{
storage: newResourcesStorage(),
Expand Down
62 changes: 62 additions & 0 deletions pkg/i2gw/providers/gce/ir_converter.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import (
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/validation/field"
backendconfigv1 "k8s.io/ingress-gce/pkg/apis/backendconfig/v1"
frontendconfigv1beta1 "k8s.io/ingress-gce/pkg/apis/frontendconfig/v1beta1"
)

type contextKey int
Expand Down Expand Up @@ -82,10 +83,71 @@ func (c *resourcesToIRConverter) convertToIR(storage *storage) (intermediate.IR,
if len(errs) > 0 {
return intermediate.IR{}, errs
}
buildGceGatewayIR(c.ctx, storage, &ir)
buildGceServiceIR(c.ctx, storage, &ir)
return ir, errs
}

func buildGceGatewayIR(ctx context.Context, storage *storage, ir *intermediate.IR) {
if ir.Gateways == nil {
ir.Gateways = make(map[types.NamespacedName]intermediate.GatewayContext)
}

feConfigToGwys := getFrontendConfigMapping(ctx, storage)
for feConfigKey, feConfig := range storage.FrontendConfigs {
if feConfig == nil {
continue
}
gceGatewayIR := feConfigToGceGatewayIR(feConfig)
gateways := feConfigToGwys[feConfigKey]

for _, gwyKey := range gateways {
gatewayContext := ir.Gateways[gwyKey]
gatewayContext.ProviderSpecificIR.Gce = &gceGatewayIR
ir.Gateways[gwyKey] = gatewayContext
}
}
}

type gatewayNames []types.NamespacedName

func getFrontendConfigMapping(ctx context.Context, storage *storage) map[types.NamespacedName]gatewayNames {
feConfigToGwys := make(map[types.NamespacedName]gatewayNames)

for _, ingress := range storage.Ingresses {
gwyKey := types.NamespacedName{Namespace: ingress.Namespace, Name: common.GetIngressClass(*ingress)}
// ing := types.NamespacedName{Namespace: ingress.Namespace, Name: ingress.Name}
ctx = context.WithValue(ctx, serviceKey, ingress)

feConfigName, exists := getFrontendConfigAnnotation(ingress)
if exists {
feConfigKey := types.NamespacedName{Namespace: ingress.Namespace, Name: feConfigName}
feConfigToGwys[feConfigKey] = append(feConfigToGwys[feConfigKey], gwyKey)
continue
}

}
return feConfigToGwys
}

// Get names of the FrontendConfig in the cluster based on the FrontendConfig
// annotation on k8s Services.
func getFrontendConfigAnnotation(ing *networkingv1.Ingress) (string, bool) {
val, ok := ing.ObjectMeta.Annotations[frontendConfigKey]
if !ok {
return "", false
}
return val, true
}

func feConfigToGceGatewayIR(feConfig *frontendconfigv1beta1.FrontendConfig) intermediate.GceGatewayIR {
var gceGatewayIR intermediate.GceGatewayIR
if feConfig.Spec.SslPolicy != nil {
gceGatewayIR.SslPolicy = extensions.BuildIRSslPolicyConfig(feConfig)
}
return gceGatewayIR
}

type serviceNames []types.NamespacedName

func buildGceServiceIR(ctx context.Context, storage *storage, ir *intermediate.IR) {
Expand Down
Loading
Loading