diff --git a/api/v1alpha1/application_types.go b/api/v1alpha1/application_types.go index 47faa0e7..7d17c04a 100644 --- a/api/v1alpha1/application_types.go +++ b/api/v1alpha1/application_types.go @@ -3,9 +3,11 @@ package v1alpha1 import ( "encoding/json" "errors" + "fmt" "github.com/kartverket/skiperator/api/v1alpha1/digdirator" "github.com/kartverket/skiperator/api/v1alpha1/istiotypes" "github.com/kartverket/skiperator/api/v1alpha1/podtypes" + "github.com/kartverket/skiperator/pkg/util" corev1 "k8s.io/api/core/v1" apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -68,7 +70,7 @@ type ApplicationSpec struct { // They can optionally be suffixed with a plus and name of a custom TLS secret located in the istio-gateways namespace. // E.g. "foo.atkv3-dev.kartverket-intern.cloud+env-wildcard-cert" //+kubebuilder:validation:Optional - Ingresses []string `json:"ingresses,omitempty"` + Ingresses *apiextensionsv1.JSON `json:"ingresses,omitempty"` // An optional priority. Supported values are 'low', 'medium' and 'high'. // The default value is 'medium'. @@ -335,6 +337,11 @@ type PrometheusConfig struct { AllowAllMetrics bool `json:"allowAllMetrics,omitempty"` } +type Ingress struct { + Hostname string + Internal *bool +} + func NewDefaultReplicas() Replicas { return Replicas{ Min: 2, @@ -442,15 +449,53 @@ func (a *Application) GetCommonSpec() *CommonSpec { } } +func MarshalledIngresses(ingresses interface{}) (*apiextensionsv1.JSON, error) { + marshalled := &apiextensionsv1.JSON{} + var err error + + if marshalled.Raw, err = json.Marshal(ingresses); err != nil { + return nil, fmt.Errorf("could not marshal ingresses: %w", err) + } + + return marshalled, nil +} + func (s *ApplicationSpec) Hosts() (HostCollection, error) { + var ingressesAsString []string + var ingressesAsObject []Ingress + var errorsFound []error hosts := NewCollection() - var errorsFound []error - for _, ingress := range s.Ingresses { - err := hosts.Add(ingress) + ingresses, err := MarshalledIngresses(s.Ingresses) + if err != nil { + return hosts, err + } + aErr := json.Unmarshal(ingresses.Raw, &ingressesAsString) + + // If the ingress supplied is not a string, we assume it's an object + if aErr != nil { + if mErr := json.Unmarshal(ingresses.Raw, &ingressesAsObject); mErr != nil { + errorsFound = append(errorsFound, mErr) + return NewCollection(), errors.Join(errorsFound...) + } + + for _, ingress := range ingressesAsObject { + if ingress.Internal == nil { + ingress.Internal = util.PointTo(isInternal(ingress.Hostname)) + } + + if aErr := hosts.Add(ingress.Hostname, *ingress.Internal); aErr != nil { + errorsFound = append(errorsFound, aErr) + } + } + return hosts, errors.Join(errorsFound...) + } + + //Handle legacy ingress format + for _, ingress := range ingressesAsString { + err := hosts.Add(ingress, isInternal(ingress)) if err != nil { errorsFound = append(errorsFound, err) - continue } } diff --git a/api/v1alpha1/hosts.go b/api/v1alpha1/hosts.go index 15cc531e..be396a24 100644 --- a/api/v1alpha1/hosts.go +++ b/api/v1alpha1/hosts.go @@ -3,16 +3,20 @@ package v1alpha1 import ( "fmt" "github.com/chmike/domain" + "regexp" "strings" ) const hostnameSecretSeparator = "+" +var internalPattern = regexp.MustCompile(`[^.]\.skip\.statkart\.no|[^.]\.kartverket-intern.cloud`) + // TODO: Add a mechanism for validating that the // hostname is covered by the CustomCertificateSecret if present type Host struct { Hostname string CustomCertificateSecret *string + Internal bool } type HostCollection struct { @@ -25,6 +29,7 @@ func NewHost(hostname string) (*Host, error) { } var h Host + // If hostname is separated by +, the user wants to use a custom certificate results := strings.Split(hostname, hostnameSecretSeparator) @@ -49,7 +54,7 @@ func NewHost(hostname string) (*Host, error) { if err := domain.Check(h.Hostname); err != nil { return nil, fmt.Errorf("%s: failed validation: %w", h.Hostname, err) } - + h.Internal = isInternal(hostname) return &h, nil } @@ -63,14 +68,14 @@ func NewCollection() HostCollection { } } -func (hs *HostCollection) Add(hostname string) error { +func (hs *HostCollection) Add(hostname string, internal bool) error { h, err := NewHost(hostname) if err != nil { return err } + h.Internal = internal existingValue, alreadyPresent := hs.hosts[h.Hostname] - switch alreadyPresent { case true: if existingValue.UsesCustomCert() { @@ -105,3 +110,7 @@ func (hs *HostCollection) Hostnames() []string { func (hs *HostCollection) Count() int { return len(hs.hosts) } + +func isInternal(hostname string) bool { + return internalPattern.MatchString(hostname) +} diff --git a/api/v1alpha1/routing_types.go b/api/v1alpha1/routing_types.go index cdb03de8..0ef283f5 100644 --- a/api/v1alpha1/routing_types.go +++ b/api/v1alpha1/routing_types.go @@ -41,6 +41,9 @@ type RoutingSpec struct { //+kubebuilder:validation:Optional //+kubebuilder:default:=true RedirectToHTTPS *bool `json:"redirectToHTTPS,omitempty"` + + //+kubebuilder:validation:Optional + Internal *bool `json:"internal,omitempty"` } // +kubebuilder:object:generate=true diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index a54de73f..f61098ae 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -78,8 +78,8 @@ func (in *ApplicationSpec) DeepCopyInto(out *ApplicationSpec) { *out = *in if in.Ingresses != nil { in, out := &in.Ingresses, &out.Ingresses - *out = make([]string, len(*in)) - copy(*out, *in) + *out = new(v1.JSON) + (*in).DeepCopyInto(*out) } if in.Command != nil { in, out := &in.Command, &out.Command @@ -506,6 +506,11 @@ func (in *RoutingSpec) DeepCopyInto(out *RoutingSpec) { *out = new(bool) **out = **in } + if in.Internal != nil { + in, out := &in.Internal, &out.Internal + *out = new(bool) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RoutingSpec. diff --git a/config/crd/skiperator.kartverket.no_applications.yaml b/config/crd/skiperator.kartverket.no_applications.yaml index e14da360..26a9572a 100644 --- a/config/crd/skiperator.kartverket.no_applications.yaml +++ b/config/crd/skiperator.kartverket.no_applications.yaml @@ -646,9 +646,7 @@ spec: Ingresses must be lowercase, contain no spaces, be a non-empty string, and have a hostname/domain separated by a period They can optionally be suffixed with a plus and name of a custom TLS secret located in the istio-gateways namespace. E.g. "foo.atkv3-dev.kartverket-intern.cloud+env-wildcard-cert" - items: - type: string - type: array + x-kubernetes-preserve-unknown-fields: true istioSettings: default: telemetry: diff --git a/config/crd/skiperator.kartverket.no_routings.yaml b/config/crd/skiperator.kartverket.no_routings.yaml index c6877df2..68a4c82b 100644 --- a/config/crd/skiperator.kartverket.no_routings.yaml +++ b/config/crd/skiperator.kartverket.no_routings.yaml @@ -45,6 +45,8 @@ spec: properties: hostname: type: string + internal: + type: boolean redirectToHTTPS: default: true type: boolean diff --git a/pkg/resourcegenerator/deployment/deployment.go b/pkg/resourcegenerator/deployment/deployment.go index bb0d6199..f7470430 100644 --- a/pkg/resourcegenerator/deployment/deployment.go +++ b/pkg/resourcegenerator/deployment/deployment.go @@ -204,11 +204,17 @@ func Generate(r reconciliation.Reconciliation) error { } // add an external link to argocd - ingresses := application.Spec.Ingresses + hosts, err := application.Spec.Hosts() + if err != nil { + ctxLog.Error(err, "could not get hosts from application") + return err + } if deployment.Annotations == nil { deployment.Annotations = make(map[string]string) } + var ingresses = hosts.Hostnames() + if len(ingresses) > 0 { deployment.Annotations[AnnotationKeyLinkPrefix] = fmt.Sprintf("https://%s", ingresses[0]) } diff --git a/pkg/resourcegenerator/istio/gateway/application.go b/pkg/resourcegenerator/istio/gateway/application.go index 51460698..c0e9aba6 100644 --- a/pkg/resourcegenerator/istio/gateway/application.go +++ b/pkg/resourcegenerator/istio/gateway/application.go @@ -2,9 +2,9 @@ package gateway import ( "fmt" - skiperatorv1alpha1 "github.com/kartverket/skiperator/api/v1alpha1" "github.com/kartverket/skiperator/pkg/reconciliation" + "github.com/kartverket/skiperator/pkg/resourcegenerator/resourceutils" "github.com/kartverket/skiperator/pkg/util" networkingv1beta1api "istio.io/api/networking/v1beta1" networkingv1beta1 "istio.io/client-go/pkg/apis/networking/v1beta1" @@ -38,7 +38,7 @@ func generateForApplication(r reconciliation.Reconciliation) error { name := fmt.Sprintf("%s-ingress-%x", application.Name, util.GenerateHashFromName(h.Hostname)) gateway := networkingv1beta1.Gateway{ObjectMeta: metav1.ObjectMeta{Namespace: application.Namespace, Name: name}} - gateway.Spec.Selector = util.GetIstioGatewayLabelSelector(h.Hostname) + gateway.Spec.Selector = resourceutils.GetIstioGatewayLabelSelector(h) gatewayServersToAdd := []*networkingv1beta1api.Server{} diff --git a/pkg/resourcegenerator/istio/gateway/routing.go b/pkg/resourcegenerator/istio/gateway/routing.go index 714dbc87..7212ef00 100644 --- a/pkg/resourcegenerator/istio/gateway/routing.go +++ b/pkg/resourcegenerator/istio/gateway/routing.go @@ -2,10 +2,9 @@ package gateway import ( "fmt" - skiperatorv1alpha1 "github.com/kartverket/skiperator/api/v1alpha1" "github.com/kartverket/skiperator/pkg/reconciliation" - "github.com/kartverket/skiperator/pkg/util" + "github.com/kartverket/skiperator/pkg/resourcegenerator/resourceutils" networkingv1beta1api "istio.io/api/networking/v1beta1" networkingv1beta1 "istio.io/client-go/pkg/apis/networking/v1beta1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -31,6 +30,9 @@ func generateForRouting(r reconciliation.Reconciliation) error { if err != nil { return err } + if routing.Spec.Internal != nil { + h.Internal = *routing.Spec.Internal + } gateway := networkingv1beta1.Gateway{ObjectMeta: metav1.ObjectMeta{Namespace: routing.Namespace, Name: routing.GetGatewayName()}} @@ -44,7 +46,7 @@ func generateForRouting(r reconciliation.Reconciliation) error { } } - gateway.Spec.Selector = util.GetIstioGatewayLabelSelector(h.Hostname) + gateway.Spec.Selector = resourceutils.GetIstioGatewayLabelSelector(h) gateway.Spec.Servers = []*networkingv1beta1api.Server{ { Hosts: []string{h.Hostname}, diff --git a/pkg/resourcegenerator/networkpolicy/dynamic/common.go b/pkg/resourcegenerator/networkpolicy/dynamic/common.go index 313204a9..998f265d 100644 --- a/pkg/resourcegenerator/networkpolicy/dynamic/common.go +++ b/pkg/resourcegenerator/networkpolicy/dynamic/common.go @@ -37,14 +37,20 @@ func generateForCommon(r reconciliation.Reconciliation) error { } accessPolicy := object.GetCommonSpec().AccessPolicy - var ingresses []string + var hosts = skiperatorv1alpha1.NewCollection() var inboundPort int32 + if r.GetType() == reconciliation.ApplicationType { - ingresses = object.(*skiperatorv1alpha1.Application).Spec.Ingresses + var err error + hosts, err = object.(*skiperatorv1alpha1.Application).Spec.Hosts() + if err != nil { + ctxLog.Error(err, "Failed to get hosts for networkpolicy", "type", r.GetType(), "namespace", namespace) + return err + } inboundPort = int32(object.(*skiperatorv1alpha1.Application).Spec.Port) } - ingressRules := getIngressRules(accessPolicy, ingresses, r.IsIstioEnabled(), namespace, inboundPort) + ingressRules := getIngressRules(accessPolicy, hosts, r.IsIstioEnabled(), namespace, inboundPort) egressRules := getEgressRules(accessPolicy, namespace) netpolSpec := networkingv1.NetworkPolicySpec{ @@ -113,20 +119,14 @@ func getEgressRule(outboundRule podtypes.InternalRule, namespace string) network } // TODO Clean up better -func getIngressRules(accessPolicy *podtypes.AccessPolicy, ingresses []string, istioEnabled bool, namespace string, port int32) []networkingv1.NetworkPolicyIngressRule { +func getIngressRules(accessPolicy *podtypes.AccessPolicy, hostCollection skiperatorv1alpha1.HostCollection, istioEnabled bool, namespace string, port int32) []networkingv1.NetworkPolicyIngressRule { var ingressRules []networkingv1.NetworkPolicyIngressRule - if ingresses != nil && len(ingresses) > 0 { - if hasInternalIngress(ingresses) { - ingressRules = append(ingressRules, getGatewayIngressRule(true, port)) - } - - if hasExternalIngress(ingresses) { - ingressRules = append(ingressRules, getGatewayIngressRule(false, port)) - } + for _, host := range hostCollection.AllHosts() { + ingressRules = append(ingressRules, getGatewayIngressRule(host.Internal, port)) } - // Allow grafana-agent to scrape + // Allow grafana-agent and Alloy to scrape if istioEnabled { promScrapeRuleGrafana := networkingv1.NetworkPolicyIngressRule{ From: []networkingv1.NetworkPolicyPeer{ @@ -226,26 +226,6 @@ func getNamespaceSelector(rule podtypes.InternalRule, appNamespace string) *meta } } -func hasExternalIngress(ingresses []string) bool { - for _, hostname := range ingresses { - if !util.IsInternal(hostname) { - return true - } - } - - return false -} - -func hasInternalIngress(ingresses []string) bool { - for _, hostname := range ingresses { - if util.IsInternal(hostname) { - return true - } - } - - return false -} - func getGatewayIngressRule(isInternal bool, port int32) networkingv1.NetworkPolicyIngressRule { ingressRule := networkingv1.NetworkPolicyIngressRule{ From: []networkingv1.NetworkPolicyPeer{ @@ -254,6 +234,7 @@ func getGatewayIngressRule(isInternal bool, port int32) networkingv1.NetworkPoli MatchLabels: map[string]string{"kubernetes.io/metadata.name": "istio-gateways"}, }, PodSelector: &metav1.LabelSelector{ + MatchLabels: getIngressGatewayLabel(isInternal), }, }, diff --git a/pkg/resourcegenerator/networkpolicy/dynamic/routing.go b/pkg/resourcegenerator/networkpolicy/dynamic/routing.go index 11fd658a..64fd619d 100644 --- a/pkg/resourcegenerator/networkpolicy/dynamic/routing.go +++ b/pkg/resourcegenerator/networkpolicy/dynamic/routing.go @@ -5,6 +5,7 @@ import ( skiperatorv1alpha1 "github.com/kartverket/skiperator/api/v1alpha1" "github.com/kartverket/skiperator/pkg/reconciliation" + "github.com/kartverket/skiperator/pkg/resourcegenerator/resourceutils" "github.com/kartverket/skiperator/pkg/util" networkingv1 "k8s.io/api/networking/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -27,7 +28,13 @@ func generateForRouting(r reconciliation.Reconciliation) error { for _, route := range routing.Spec.Routes { uniqueTargetApps[getNetworkPolicyName(routing, route.TargetApp)] = route } - + h, err := routing.Spec.GetHost() + if routing.Spec.Internal != nil { + h.Internal = *routing.Spec.Internal + } + if err != nil { + return err + } for netpolName, route := range uniqueTargetApps { networkPolicy := networkingv1.NetworkPolicy{ ObjectMeta: metav1.ObjectMeta{ @@ -50,7 +57,7 @@ func generateForRouting(r reconciliation.Reconciliation) error { MatchLabels: util.GetIstioGatewaySelector(), }, PodSelector: &metav1.LabelSelector{ - MatchLabels: util.GetIstioGatewayLabelSelector(routing.Spec.Hostname), + MatchLabels: resourceutils.GetIstioGatewayLabelSelector(h), }, }, }, diff --git a/pkg/resourcegenerator/resourceutils/helpers.go b/pkg/resourcegenerator/resourceutils/helpers.go index d7bd46cf..8bfcb4a9 100644 --- a/pkg/resourcegenerator/resourceutils/helpers.go +++ b/pkg/resourcegenerator/resourceutils/helpers.go @@ -1,6 +1,7 @@ package resourceutils import ( + "github.com/kartverket/skiperator/api/v1alpha1" skiperatorv1alpha1 "github.com/kartverket/skiperator/api/v1alpha1" apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" ) @@ -16,3 +17,10 @@ func ShouldScaleToZero(jsonReplicas *apiextensionsv1.JSON) bool { } return false } + +func GetIstioGatewayLabelSelector(host *v1alpha1.Host) map[string]string { + if host.Internal { + return map[string]string{"app": "istio-ingress-internal"} + } + return map[string]string{"app": "istio-ingress-external"} +} diff --git a/pkg/util/helperfunctions.go b/pkg/util/helperfunctions.go index a3bf824e..9bd2ca4c 100644 --- a/pkg/util/helperfunctions.go +++ b/pkg/util/helperfunctions.go @@ -8,32 +8,13 @@ import ( "github.com/nais/liberator/pkg/namegen" "hash/fnv" corev1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/validation" - "k8s.io/client-go/tools/record" - "regexp" "sigs.k8s.io/controller-runtime/pkg/client" "strings" - "unicode" ) -//TODO Clean up this file, move functions to more appropriate files - -var internalPattern = regexp.MustCompile(`[^.]\.skip\.statkart\.no|[^.]\.kartverket-intern.cloud`) - -func IsInternal(hostname string) bool { - return internalPattern.MatchString(hostname) -} - -func GetIstioGatewayLabelSelector(hostname string) map[string]string { - if IsInternal(hostname) { - return map[string]string{"app": "istio-ingress-internal"} - } - return map[string]string{"app": "istio-ingress-external"} - -} +// TODO Clean up this file, move functions to more appropriate files func GetHashForStructs(obj []interface{}) string { hash, err := hashstructure.Hash(obj, hashstructure.FormatV2, nil) @@ -57,35 +38,6 @@ func GetConfigMap(client client.Client, ctx context.Context, namespacedName type return configMap, err } -func GetSecret(client client.Client, ctx context.Context, namespacedName types.NamespacedName) (corev1.Secret, error) { - secret := corev1.Secret{} - - err := client.Get(ctx, namespacedName, &secret) - - return secret, err -} - -func GetService(client client.Client, ctx context.Context, namespacedName types.NamespacedName) (corev1.Service, error) { - service := corev1.Service{} - - err := client.Get(ctx, namespacedName, &service) - - return service, err -} - -func ErrIsMissingOrNil(recorder record.EventRecorder, err error, message string, object runtime.Object) bool { - if errors.IsNotFound(err) { - recorder.Eventf( - object, - corev1.EventTypeWarning, "Missing", - message, - ) - } else if err != nil { - return false - } - return true -} - func ErrDoPanic(err error, message string) { if err != nil { errorMessage := fmt.Sprintf(message, err.Error()) @@ -116,24 +68,10 @@ func GetPodAppAndTeamSelector(applicationName string, teamName string) map[strin } } -func HasUpperCaseLetter(word string) bool { - for _, letter := range word { - if unicode.IsUpper(letter) { - return true - } - } - - return false -} - func ResourceNameWithKindPostfix(resourceName string, kind string) string { return strings.ToLower(fmt.Sprintf("%v-%v", resourceName, kind)) } -func GetGatewaySecretName(namespace string, name string) string { - return fmt.Sprintf("%s-%s-ingress", namespace, name) -} - func GetSecretName(prefix string, name string) (string, error) { // https://github.com/nais/naiserator/blob/faed273b68dff8541e1e2889fda5d017730f9796/pkg/resourcecreator/idporten/idporten.go#L82 // https://github.com/nais/naiserator/blob/faed273b68dff8541e1e2889fda5d017730f9796/pkg/resourcecreator/idporten/idporten.go#L170 diff --git a/tests/application/ingress/application-is-internal-vanity-assert.yaml b/tests/application/ingress/application-is-internal-vanity-assert.yaml new file mode 100644 index 00000000..53abe1af --- /dev/null +++ b/tests/application/ingress/application-is-internal-vanity-assert.yaml @@ -0,0 +1,46 @@ +apiVersion: networking.istio.io/v1beta1 +kind: Gateway +metadata: + name: internalvanity-ingress-dc2b250f77a411ad +spec: + selector: + app: istio-ingress-internal +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: internalvanity +spec: + ingress: + - from: + - namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: istio-gateways + podSelector: + matchLabels: + app: istio-ingress-internal + podSelector: + matchLabels: + app: internalvanity +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: internalvanity +spec: + ingress: + - from: + - namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: istio-gateways + podSelector: + matchLabels: + app: istio-ingress-internal + ports: + - port: 8080 + protocol: TCP + podSelector: + matchLabels: + app: internalvanity + policyTypes: + - Ingress diff --git a/tests/application/ingress/application-is-internal-vanity.yaml b/tests/application/ingress/application-is-internal-vanity.yaml new file mode 100644 index 00000000..fe3f59e5 --- /dev/null +++ b/tests/application/ingress/application-is-internal-vanity.yaml @@ -0,0 +1,10 @@ +apiVersion: skiperator.kartverket.no/v1alpha1 +kind: Application +metadata: + name: internalvanity +spec: + image: image + port: 8080 + ingresses: + - hostname: test.kartverket.no + internal: true \ No newline at end of file diff --git a/tests/application/ingress/chainsaw-test.yaml b/tests/application/ingress/chainsaw-test.yaml index d23d073a..7e911029 100644 --- a/tests/application/ingress/chainsaw-test.yaml +++ b/tests/application/ingress/chainsaw-test.yaml @@ -55,3 +55,8 @@ spec: file: application-is-external.yaml - assert: file: application-is-external-assert.yaml + - try: + - create: + file: application-is-internal-vanity.yaml + - assert: + file: application-is-internal-vanity-assert.yaml diff --git a/tests/application/internal-flag/application-internal-flag-assert.yaml b/tests/application/internal-flag/application-internal-flag-assert.yaml new file mode 100644 index 00000000..a1040c22 --- /dev/null +++ b/tests/application/internal-flag/application-internal-flag-assert.yaml @@ -0,0 +1,76 @@ +apiVersion: networking.istio.io/v1beta1 +kind: Gateway +metadata: + name: app-internal-flag-ingress-56cd7aa901014e78 +spec: + selector: + app: istio-ingress-internal + servers: + - hosts: + - example.com + port: + name: http + number: 80 + protocol: HTTP + - hosts: + - example.com + port: + name: https + number: 443 + protocol: HTTPS + tls: + credentialName: chainsaw-routing-internal-flag-app-internal-flag-ingress-56cd7aa901014e78 + mode: SIMPLE + +--- +apiVersion: networking.istio.io/v1beta1 +kind: VirtualService +metadata: + name: app-internal-flag-ingress +spec: + exportTo: + - . + - istio-system + - istio-gateways + gateways: + - app-internal-flag-ingress-56cd7aa901014e78 + hosts: + - example.com + http: + - match: + - port: 80 + withoutHeaders: + :path: + prefix: /.well-known/acme-challenge/ + name: redirect-to-https + redirect: + redirectCode: 308 + scheme: https + - name: default-app-route + route: + - destination: + host: app-internal-flag + port: + number: 8000 +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: app-internal-flag +spec: + ingress: + - from: + - namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: istio-gateways + podSelector: + matchLabels: + app: istio-ingress-internal + ports: + - port: 8000 + protocol: TCP + podSelector: + matchLabels: + app: app-internal-flag + policyTypes: + - Ingress diff --git a/tests/application/internal-flag/application-internal-flag.yaml b/tests/application/internal-flag/application-internal-flag.yaml new file mode 100644 index 00000000..7c64d38f --- /dev/null +++ b/tests/application/internal-flag/application-internal-flag.yaml @@ -0,0 +1,10 @@ +apiVersion: skiperator.kartverket.no/v1alpha1 +kind: Application +metadata: + name: app-internal-flag +spec: + image: image + port: 8000 + ingresses: + - hostname: example.com + internal: true diff --git a/tests/application/internal-flag/application-internal-missing-internal-flag-assert.yaml b/tests/application/internal-flag/application-internal-missing-internal-flag-assert.yaml new file mode 100644 index 00000000..f64d59f0 --- /dev/null +++ b/tests/application/internal-flag/application-internal-missing-internal-flag-assert.yaml @@ -0,0 +1,76 @@ +apiVersion: networking.istio.io/v1beta1 +kind: Gateway +metadata: + name: app-missing-internal-flag-ingress-df26180a7fa049ff +spec: + selector: + app: istio-ingress-internal + servers: + - hosts: + - appmissinginternalflag.atkv3-dev.kartverket-intern.cloud + port: + name: http + number: 80 + protocol: HTTP + - hosts: + - appmissinginternalflag.atkv3-dev.kartverket-intern.cloud + port: + name: https + number: 443 + protocol: HTTPS + tls: + credentialName: chainsaw-routing-internal-flag-app-missing-internal-flag-ingress-df26180a7fa049ff + mode: SIMPLE + +--- +apiVersion: networking.istio.io/v1beta1 +kind: VirtualService +metadata: + name: app-missing-internal-flag-ingress +spec: + exportTo: + - . + - istio-system + - istio-gateways + gateways: + - app-missing-internal-flag-ingress-df26180a7fa049ff + hosts: + - appmissinginternalflag.atkv3-dev.kartverket-intern.cloud + http: + - match: + - port: 80 + withoutHeaders: + :path: + prefix: /.well-known/acme-challenge/ + name: redirect-to-https + redirect: + redirectCode: 308 + scheme: https + - name: default-app-route + route: + - destination: + host: app-missing-internal-flag + port: + number: 8000 +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: app-missing-internal-flag +spec: + ingress: + - from: + - namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: istio-gateways + podSelector: + matchLabels: + app: istio-ingress-internal + ports: + - port: 8000 + protocol: TCP + podSelector: + matchLabels: + app: app-missing-internal-flag + policyTypes: + - Ingress diff --git a/tests/application/internal-flag/application-internal-missing-internal-flag-ext-assert.yaml b/tests/application/internal-flag/application-internal-missing-internal-flag-ext-assert.yaml new file mode 100644 index 00000000..2cd6c7ca --- /dev/null +++ b/tests/application/internal-flag/application-internal-missing-internal-flag-ext-assert.yaml @@ -0,0 +1,76 @@ +apiVersion: networking.istio.io/v1beta1 +kind: Gateway +metadata: + name: app-missing-internal-flag-ext-ingress-56cd7aa901014e78 +spec: + selector: + app: istio-ingress-external + servers: + - hosts: + - example.com + port: + name: http + number: 80 + protocol: HTTP + - hosts: + - example.com + port: + name: https + number: 443 + protocol: HTTPS + tls: + credentialName: chainsaw-routing-internal-flag-app-missing-internal-flag-ext-ingress-56cd7aa901014e78 + mode: SIMPLE + +--- +apiVersion: networking.istio.io/v1beta1 +kind: VirtualService +metadata: + name: app-missing-internal-flag-ext-ingress +spec: + exportTo: + - . + - istio-system + - istio-gateways + gateways: + - app-missing-internal-flag-ext-ingress-56cd7aa901014e78 + hosts: + - example.com + http: + - match: + - port: 80 + withoutHeaders: + :path: + prefix: /.well-known/acme-challenge/ + name: redirect-to-https + redirect: + redirectCode: 308 + scheme: https + - name: default-app-route + route: + - destination: + host: app-missing-internal-flag-ext + port: + number: 8000 +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: app-missing-internal-flag-ext +spec: + ingress: + - from: + - namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: istio-gateways + podSelector: + matchLabels: + app: istio-ingress-external + ports: + - port: 8000 + protocol: TCP + podSelector: + matchLabels: + app: app-missing-internal-flag-ext + policyTypes: + - Ingress diff --git a/tests/application/internal-flag/application-internal-missing-internal-flag-ext.yaml b/tests/application/internal-flag/application-internal-missing-internal-flag-ext.yaml new file mode 100644 index 00000000..0476049c --- /dev/null +++ b/tests/application/internal-flag/application-internal-missing-internal-flag-ext.yaml @@ -0,0 +1,9 @@ +apiVersion: skiperator.kartverket.no/v1alpha1 +kind: Application +metadata: + name: app-missing-internal-flag-ext +spec: + image: image + port: 8000 + ingresses: + - hostname: example.com diff --git a/tests/application/internal-flag/application-internal-missing-internal-flag.yaml b/tests/application/internal-flag/application-internal-missing-internal-flag.yaml new file mode 100644 index 00000000..9c795d31 --- /dev/null +++ b/tests/application/internal-flag/application-internal-missing-internal-flag.yaml @@ -0,0 +1,9 @@ +apiVersion: skiperator.kartverket.no/v1alpha1 +kind: Application +metadata: + name: app-missing-internal-flag +spec: + image: image + port: 8000 + ingresses: + - hostname: appmissinginternalflag.atkv3-dev.kartverket-intern.cloud diff --git a/tests/application/internal-flag/chainsaw-test.yaml b/tests/application/internal-flag/chainsaw-test.yaml new file mode 100644 index 00000000..7e9debc4 --- /dev/null +++ b/tests/application/internal-flag/chainsaw-test.yaml @@ -0,0 +1,25 @@ +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: routes +spec: + skip: false + concurrent: true + skipDelete: false + namespace: chainsaw-routing-internal-flag + steps: + - try: + - apply: + file: application-internal-flag.yaml + - assert: + file: application-internal-flag-assert.yaml + - try: + - apply: + file: application-internal-missing-internal-flag.yaml + - assert: + file: application-internal-missing-internal-flag-assert.yaml + - try: + - apply: + file: application-internal-missing-internal-flag-ext.yaml + - assert: + file: application-internal-missing-internal-flag-ext-assert.yaml diff --git a/tests/routing/internal-flag/application.yaml b/tests/routing/internal-flag/application.yaml new file mode 100644 index 00000000..64637532 --- /dev/null +++ b/tests/routing/internal-flag/application.yaml @@ -0,0 +1,15 @@ +apiVersion: skiperator.kartverket.no/v1alpha1 +kind: Application +metadata: + name: internal-flag-app1 +spec: + image: image + port: 8000 +--- +apiVersion: skiperator.kartverket.no/v1alpha1 +kind: Application +metadata: + name: internal-flag-app2 +spec: + image: image + port: 9000 diff --git a/tests/routing/internal-flag/chainsaw-test.yaml b/tests/routing/internal-flag/chainsaw-test.yaml new file mode 100644 index 00000000..031c9998 --- /dev/null +++ b/tests/routing/internal-flag/chainsaw-test.yaml @@ -0,0 +1,17 @@ +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: routes-internal-flag +spec: + skip: false + concurrent: false + skipDelete: false + namespace: chainsaw-routing-internal-flag + steps: + - try: + - apply: + file: application.yaml + - apply: + file: routing-internal-flag.yaml + - assert: + file: routing-internal-flag-assert.yaml \ No newline at end of file diff --git a/tests/routing/internal-flag/routing-internal-flag-assert.yaml b/tests/routing/internal-flag/routing-internal-flag-assert.yaml new file mode 100644 index 00000000..eb7bc159 --- /dev/null +++ b/tests/routing/internal-flag/routing-internal-flag-assert.yaml @@ -0,0 +1,116 @@ +apiVersion: networking.istio.io/v1beta1 +kind: Gateway +metadata: + name: app-paths-internal-flag-routing-ingress +spec: + selector: + app: istio-ingress-internal + servers: + - hosts: + - example.com + port: + name: http + number: 80 + protocol: HTTP + - hosts: + - example.com + port: + name: https + number: 443 + protocol: HTTPS + tls: + credentialName: chainsaw-routing-internal-flag-app-paths-internal-flag-67aee041 + mode: SIMPLE + +--- +apiVersion: networking.istio.io/v1beta1 +kind: VirtualService +metadata: + name: app-paths-internal-flag-routing-ingress +spec: + exportTo: + - . + - istio-system + - istio-gateways + gateways: + - app-paths-internal-flag-routing-ingress + hosts: + - example.com + http: + - match: + - port: 80 + withoutHeaders: + :path: + prefix: /.well-known/acme-challenge/ + name: redirect-to-https + redirect: + redirectCode: 308 + scheme: https + - match: + - port: 443 + uri: + prefix: /app1 + rewrite: + uri: / + name: internal-flag-app1 + route: + - destination: + host: internal-flag-app1 + port: + number: 8000 + - match: + - port: 443 + uri: + prefix: /new-path + rewrite: + uri: / + name: internal-flag-app2 + route: + - destination: + host: internal-flag-app2 + port: + number: 9000 +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: app-paths-internal-flag-internal-flag-app2-istio-ingress +spec: + podSelector: + matchLabels: + app: internal-flag-app2 + policyTypes: + - Ingress + ingress: + - from: + - namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: istio-gateways + podSelector: + matchLabels: + app: istio-ingress-internal + ports: + - port: 9000 + protocol: TCP +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: app-paths-internal-flag-internal-flag-app1-istio-ingress +spec: + ingress: + - from: + - namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: istio-gateways + podSelector: + matchLabels: + app: istio-ingress-internal + ports: + - port: 8000 + protocol: TCP + podSelector: + matchLabels: + app: internal-flag-app1 + policyTypes: + - Ingress diff --git a/tests/routing/internal-flag/routing-internal-flag.yaml b/tests/routing/internal-flag/routing-internal-flag.yaml new file mode 100644 index 00000000..3f8a319a --- /dev/null +++ b/tests/routing/internal-flag/routing-internal-flag.yaml @@ -0,0 +1,14 @@ +apiVersion: skiperator.kartverket.no/v1alpha1 +kind: Routing +metadata: + name: app-paths-internal-flag +spec: + hostname: example.com + internal: true + routes: + - pathPrefix: /app1 + targetApp: internal-flag-app1 + rewriteUri: true + - pathPrefix: /new-path + targetApp: internal-flag-app2 + rewriteUri: true