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

Dynamically secure RouteGroups using Kubernetes TLS Secrets #2814

Merged
merged 23 commits into from
Jan 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
93f2431
Add RouteGroup tests for securing TLS using secrets
rickhlx Jan 1, 2024
c71636b
Add TLS spec for RouteGroups
rickhlx Jan 1, 2024
c358be5
Load TLS certs to registry from RouteGroup TLS definition
rickhlx Jan 1, 2024
4553fe7
Add description to addRouteGroupTLS function
rickhlx Jan 1, 2024
5c5bca5
Refactor using function to add TLS cert to registry
rickhlx Jan 1, 2024
5e99692
add fixtures for when no tls secret is defined
rickhlx Jan 1, 2024
99ac3bf
Skip adding cert to registry when no secret is defined
rickhlx Jan 1, 2024
4aca418
Update RouteGroup CRD with TLS spec
rickhlx Jan 1, 2024
f175dd0
Fix comments for new functions and typos
rickhlx Jan 2, 2024
bccbca3
Use plain value instead of pointer for secretID
rickhlx Jan 3, 2024
2b529a3
Use Debug log level when no secrets defined in TLS
rickhlx Jan 3, 2024
ded3e16
Log hosts in tls and hosts in route or ingress when no match
rickhlx Jan 3, 2024
04e8061
Add logging for non matching tls and ingress/routegroup
rickhlx Jan 3, 2024
0daaddf
Remove unneeded deployment definition from tests
rickhlx Jan 3, 2024
73aac01
Update fixture tests with log checks
rickhlx Jan 3, 2024
090e10b
Remove all unused Deployments from Ingress fixtures
rickhlx Jan 3, 2024
5795c51
Fix how cert registry is passed to addTLSCertToRegistry
rickhlx Jan 3, 2024
9bf60a0
Add missing newlines for ingress tls fixtures
rickhlx Jan 6, 2024
31348fc
Add local variable for ingress hosts in addSpecIngressTLSV1
rickhlx Jan 6, 2024
d9671ac
Log Error when no TLS hosts match Ingress and RouteGroups hosts
rickhlx Jan 8, 2024
2ceba75
Add missing newlines to fixture log files
rickhlx Jan 8, 2024
0e82071
Update fixture for tests for error log
rickhlx Jan 8, 2024
6750482
Update with latest version of routegroup_crd
rickhlx Jan 8, 2024
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
14 changes: 14 additions & 0 deletions dataclients/kubernetes/definitions/routegroups.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ type RouteGroupSpec struct {
// Routes specifies the list of route based on path, method
// and predicates.
Routes []*RouteSpec `json:"routes,omitempty"`

// TLS specifies the list of Kubernetes TLS secrets to
// be used to terminate the TLS connection
TLS []*RouteTLSSpec `json:"tls,omitempty"`
}

// SkipperBackend is the type safe version of skipperBackendParser
Expand Down Expand Up @@ -155,6 +159,16 @@ type RouteSpec struct {
Methods []string `json:"methods,omitempty"`
}

type RouteTLSSpec struct {
// Hosts specifies the list of hosts included in the
// TLS certificate
Hosts []string `json:"hosts,omitempty"`

// SecretName specifies the Kubernetes TLS secret to be
// used to terminate the TLS SNI connection
SecretName string `json:"secretName,omitempty"`
}

func backendsWithDuplicateName(name string) error {
return fmt.Errorf("backends with duplicate name: %s", name)
}
Expand Down
27 changes: 25 additions & 2 deletions dataclients/kubernetes/deploy/apply/routegroups_crd.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
# This is a copy of https://github.com/szuecs/routegroup-client/blob/master/zalando.org_routegroups.yaml
# DO NOT EDIT.
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
Expand Down Expand Up @@ -216,6 +214,31 @@ spec:
type: object
minItems: 1
type: array
tls:
description: TLS defines which Kubernetes secret will be used to terminate
the connection based on the matching hostnames
items:
properties:
hosts:
description: TLS hosts specify the list of hosts included in
the TLS secret. The values in this list must match the host
name(s) used for the RouteGroup in order to terminate TLS
for the host(s).
items:
pattern: "^[a-z0-9]([-a-z0-9]*[a-z0-9])?([.][a-z0-9]([-a-z0-9]*[a-z0-9])?)*$"
type: string
minItems: 1
type: array
secretName:
description: SecretName is the name of the secret used to terminate
TLS traffic. Secret should reside in the same namespace as
the RouteGroup.
type: string
required:
- hosts
- secretName
type: object
type: array
required:
- backends
type: object
Expand Down
21 changes: 0 additions & 21 deletions dataclients/kubernetes/ingress.go
Original file line number Diff line number Diff line change
Expand Up @@ -337,27 +337,6 @@ func hasCatchAllRoutes(routes []*eskip.Route) bool {
return false
}

// addHostTLSCert adds a TLS certificate to the certificate registry per host when the referenced
// secret is found and is a valid TLS secret.
func addHostTLSCert(ic *ingressContext, hosts []string, secretID *definitions.ResourceID) {
secret, ok := ic.state.secrets[*secretID]
if !ok {
ic.logger.Errorf("Failed to find secret %s in namespace %s", secretID.Name, secretID.Namespace)
return
}
cert, err := generateTLSCertFromSecret(secret)
if err != nil {
ic.logger.Errorf("Failed to generate TLS certificate from secret: %v", err)
return
}
for _, host := range hosts {
err := ic.certificateRegistry.ConfigureCertificate(host, cert)
if err != nil {
ic.logger.Errorf("Failed to configure certificate: %v", err)
}
}
}

// convert logs if an invalid found, but proceeds with the valid ones.
// Reporting failures in Ingress status is not possible, because
// Ingress status field only supports IP and Hostname as string.
Expand Down
24 changes: 20 additions & 4 deletions dataclients/kubernetes/ingressv1.go
Original file line number Diff line number Diff line change
Expand Up @@ -293,15 +293,31 @@ func (ing *ingress) addSpecRuleV1(ic *ingressContext, ru *definitions.RuleV1) er
// addSpecIngressTLSV1 is used to add TLS Certificates from Ingress resources. Certificates will be added
// only if the Ingress rule host matches a host in TLS config
func (ing *ingress) addSpecIngressTLSV1(ic *ingressContext, ingtls *definitions.TLSV1) {
ingressHosts := definitions.GetHostsFromIngressRulesV1(ic.ingressV1)

// Hosts in the tls section need to explicitly match the host in the rules section.
hostlist := compareStringList(ingtls.Hosts, definitions.GetHostsFromIngressRulesV1(ic.ingressV1))
hostlist := compareStringList(ingtls.Hosts, ingressHosts)
if len(hostlist) == 0 {
ic.logger.Infof("No matching tls hosts found")
ic.logger.Errorf("No matching tls hosts found - tls hosts: %s, ingress hosts: %s", ingtls.Hosts, ingressHosts)
return
} else if len(hostlist) != len(ingtls.Hosts) {
ic.logger.Infof("Hosts in TLS and Ingress don't match: tls hosts: %s, ingress hosts: %s", ingtls.Hosts, definitions.GetHostsFromIngressRulesV1(ic.ingressV1))
}

// Skip adding certs to registry since no certs defined
if ingtls.SecretName == "" {
ic.logger.Debugf("No tls secret defined for hosts - %s", ingtls.Hosts)
return
}

// Secrets should always reside in same namespace as the Ingress
secretID := &definitions.ResourceID{Name: ingtls.SecretName, Namespace: ic.ingressV1.Metadata.Namespace}
addHostTLSCert(ic, hostlist, secretID)
secretID := definitions.ResourceID{Name: ingtls.SecretName, Namespace: ic.ingressV1.Metadata.Namespace}
secret, ok := ic.state.secrets[secretID]
if !ok {
ic.logger.Errorf("Failed to find secret %s in namespace %s", secretID.Name, secretID.Namespace)
return
}
addTLSCertToRegistry(ic.certificateRegistry, ic.logger, hostlist, secret)
}

// converts the default backend if any
Expand Down
18 changes: 17 additions & 1 deletion dataclients/kubernetes/kube.go
Original file line number Diff line number Diff line change
Expand Up @@ -422,7 +422,7 @@ func (c *Client) loadAndConvert() ([]*eskip.Route, error) {
return nil, err
}

rg, err := c.routeGroups.convert(state, defaultFilters, loggingEnabled)
rg, err := c.routeGroups.convert(state, defaultFilters, loggingEnabled, c.ClusterClient.certificateRegistry)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -595,3 +595,19 @@ func compareStringList(a, b []string) []string {
}
return c
}

// addTLSCertToRegistry adds a TLS certificate to the certificate registry per host using the provided
// Kubernetes TLS secret
func addTLSCertToRegistry(cr *certregistry.CertRegistry, logger *logger, hosts []string, secret *secret) {
cert, err := generateTLSCertFromSecret(secret)
if err != nil {
logger.Errorf("Failed to generate TLS certificate from secret: %v", err)
AlexanderYastrebov marked this conversation as resolved.
Show resolved Hide resolved
return
}
for _, host := range hosts {
err := cr.ConfigureCertificate(host, cert)
if err != nil {
logger.Errorf("Failed to configure certificate: %v", err)
}
}
}
47 changes: 46 additions & 1 deletion dataclients/kubernetes/routegroup.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"github.com/zalando/skipper/dataclients/kubernetes/definitions"
"github.com/zalando/skipper/eskip"
"github.com/zalando/skipper/loadbalancer"
"github.com/zalando/skipper/secrets/certregistry"
)

const backendNameTracingTagName = "skipper.backend_name"
Expand Down Expand Up @@ -39,6 +40,7 @@ type routeGroupContext struct {
provideHTTPSRedirect bool
calculateTraffic func([]*definitions.BackendReference) map[string]backendTraffic
defaultLoadBalancerAlgorithm string
certificateRegistry *certregistry.CertRegistry
}

type routeContext struct {
Expand Down Expand Up @@ -478,7 +480,36 @@ func splitHosts(hosts []string, domains []string) ([]string, []string) {
return internalHosts, externalHosts
}

func (r *routeGroups) convert(s *clusterState, df defaultFilters, loggingEnabled bool) ([]*eskip.Route, error) {
// addRouteGroupTLS compares the RouteGroup host list and the RouteGroup TLS host list
// and adds the TLS secret to the registry if a match is found.
func (r *routeGroups) addRouteGroupTLS(ctx *routeGroupContext, tls *definitions.RouteTLSSpec) {
// Host in the tls section need to explicitly match the host in the RouteGroup
hostlist := compareStringList(tls.Hosts, ctx.routeGroup.Spec.UniqueHosts())
Copy link
Member

Choose a reason for hiding this comment

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

I think what we want here is to check if tls.Hosts is a subset of ctx.routeGroup.Spec.UniqueHosts().
compareStringList returns all items from tls.Hosts that are also part of ctx.routeGroup.Spec.UniqueHosts().
So it reduces the hostlist.

Did you do this by intention and I miss something?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We only want to add certs which have a match from from tls.Hosts and the routeGroup hosts, so reducing the list is desired. If there are no matches we log and return, but if there are matches, we use the reduced list to add the matching tls certs to the registry.

We could log the non-matching hosts in tls.hosts to help debugging a miss configuration. What do you think?

Copy link
Member

Choose a reason for hiding this comment

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

Yes logging makes sense.
I wonder in case of an update that is applied wrong, what we want to have as behavior. For example a timeline like this:

  1. rg foo has tls.hosts foo.example, bar.example and there is a referenced secret that has only these two names foo.example, bar.example as hosts in SAN
  2. rg was updated to add baz.example and remove bar.example in tls.hosts

The current behavior would drop bar.example.

Should this better stop updating it, such that bar.example is not replaced by baz.example ?!

I am thinking of migrations, but can not come up with an idea how this could break less with either case, so from my side we can also just log it.

@AlexanderYastrebov wdyt?

Copy link
Member

Choose a reason for hiding this comment

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

Maybe this should be a part of validator and invalid routegroup should be rejected. We already use validator in webhook and dataclient.

Copy link
Member

Choose a reason for hiding this comment

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

The same is for Ingress - we plan to add ingress validator to dataclient, see #2757

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Is this something we could handle in a separate PR to keep the scope limited? Happy to work on getting in validator for both Ingress and RouteGroup.

Copy link
Member

Choose a reason for hiding this comment

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

Lets have it like it is now (log mismatch) and add tls validation for ingress and routegroup as a future improvement (makes sense after we land #2757).
@MustafaSaber FYI

if len(hostlist) == 0 {
ctx.logger.Errorf("No matching tls hosts found - tls hosts: %s, routegroup hosts: %s", tls.Hosts, ctx.routeGroup.Spec.UniqueHosts())
return
} else if len(hostlist) != len(tls.Hosts) {
ctx.logger.Infof("Hosts in TLS and RouteGroup don't match: tls hosts: %s, routegroup hosts: %s", tls.Hosts, ctx.routeGroup.Spec.UniqueHosts())
AlexanderYastrebov marked this conversation as resolved.
Show resolved Hide resolved
}

// Skip adding certs to registry since no certs defined
rickhlx marked this conversation as resolved.
Show resolved Hide resolved
if tls.SecretName == "" {
ctx.logger.Debugf("No tls secret defined for hosts - %s", tls.Hosts)
return
}

// Secrets should always reside in the same namespace as the RouteGroup
secretID := definitions.ResourceID{Name: tls.SecretName, Namespace: ctx.routeGroup.Metadata.Namespace}
secret, ok := ctx.state.secrets[secretID]
if !ok {
ctx.logger.Errorf("Failed to find secret %s in namespace %s", secretID.Name, secretID.Namespace)
return
}
addTLSCertToRegistry(ctx.certificateRegistry, ctx.logger, hostlist, secret)

}

func (r *routeGroups) convert(s *clusterState, df defaultFilters, loggingEnabled bool, cr *certregistry.CertRegistry) ([]*eskip.Route, error) {
var rs []*eskip.Route
redirect := createRedirectInfo(r.options.ProvideHTTPSRedirect, r.options.HTTPSRedirectCode)

Expand Down Expand Up @@ -530,6 +561,7 @@ func (r *routeGroups) convert(s *clusterState, df defaultFilters, loggingEnabled
allowedExternalNames: r.options.AllowedExternalNames,
calculateTraffic: getBackendTrafficCalculator[*definitions.BackendReference](r.options.BackendTrafficAlgorithm),
defaultLoadBalancerAlgorithm: r.options.DefaultLoadBalancerAlgorithm,
certificateRegistry: cr,
}

ri, err := transformRouteGroup(ctx)
Expand All @@ -546,6 +578,12 @@ func (r *routeGroups) convert(s *clusterState, df defaultFilters, loggingEnabled
ri = append(ri, catchAll...)
}

if ctx.certificateRegistry != nil {
for _, ctxTls := range rg.Spec.TLS {
r.addRouteGroupTLS(ctx, ctxTls)
}
}

rs = append(rs, ri...)
}

Expand All @@ -565,6 +603,7 @@ func (r *routeGroups) convert(s *clusterState, df defaultFilters, loggingEnabled
allowedExternalNames: r.options.AllowedExternalNames,
calculateTraffic: getBackendTrafficCalculator[*definitions.BackendReference](r.options.BackendTrafficAlgorithm),
defaultLoadBalancerAlgorithm: r.options.DefaultLoadBalancerAlgorithm,
certificateRegistry: cr,
}

internalRi, err := transformRouteGroup(internalCtx)
Expand All @@ -584,6 +623,12 @@ func (r *routeGroups) convert(s *clusterState, df defaultFilters, loggingEnabled

applyEastWestRangePredicates(internalRi, r.options.KubernetesEastWestRangePredicates)

if internalCtx.certificateRegistry != nil {
for _, ctxTls := range rg.Spec.TLS {
r.addRouteGroupTLS(internalCtx, ctxTls)
}
}

rs = append(rs, internalRi...)
}
}
Expand Down
4 changes: 4 additions & 0 deletions dataclients/kubernetes/routegroups_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,7 @@ func TestRouteGroupExternalName(t *testing.T) {
func TestRouteGroupDefaultLoadBalancerAlgorithm(t *testing.T) {
kubernetestest.FixturesToTest(t, "testdata/routegroups/loadbalancer-algorithm")
}

func TestRouteGroupTLS(t *testing.T) {
kubernetestest.FixturesToTest(t, "testdata/routegroups/tls")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
kubernetes-enable-tls: true
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
level=info msg="Hosts in TLS and Ingress don't match: tls hosts: \[example.org bar.org\], ingress hosts: \[example.org\]" kind=Ingress name=myapp-ingress ns=default
level=info msg="adding certificate to registry - example.org"
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
apiVersion: v1
kind: Service
metadata:
labels:
app: myapp-deployment
name: myapp-service
spec:
clusterIP: 10.3.190.1
ports:
- name: this-is-my-service-port-name
port: 8080
protocol: TCP
targetPort: my-port
selector:
app: myapp
type: ClusterIP
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
labels:
app: myapp
name: myapp-ingress
namespace: default
spec:
tls:
- secretName: myapp-secret
hosts:
- example.org
- bar.org
rules:
- host: example.org
http:
paths:
- backend:
service:
name: myapp-service
port:
number: 8080
pathType: ImplementationSpecific
---
apiVersion: v1
kind: Endpoints
metadata:
labels:
app: myapp-deployment
name: myapp-service
subsets:
- addresses:
- ip: 10.3.0.3
targetRef:
kind: Pod
name: myapp-deployment-6786bf95fd-fnqnq
ports:
- name: this-is-my-service-port-name
port: 80
protocol: TCP
---
apiVersion: v1
kind: Secret
metadata:
name: myapp-secret
namespace: default
type: kubernetes.io/tls
data:
tls.crt: |
LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUZhekNDQTFPZ0F3SUJBZ0lVZm9WZWI1Y3Y2alZlOC9ZQWFVaGVJejJCSXBNd0RRWUpLb1pJaHZjTkFRRUwKQlFBd1JURUxNQWtHQTFVRUJoTUNRVlV4RXpBUkJnTlZCQWdNQ2xOdmJXVXRVM1JoZEdVeElUQWZCZ05WQkFvTQpHRWx1ZEdWeWJtVjBJRmRwWkdkcGRITWdVSFI1SUV4MFpEQWVGdzB5TWpBek1UQXlNREU0TURSYUZ3MHlNekF6Ck1UQXlNREU0TURSYU1FVXhDekFKQmdOVkJBWVRBa0ZWTVJNd0VRWURWUVFJREFwVGIyMWxMVk4wWVhSbE1TRXcKSHdZRFZRUUtEQmhKYm5SbGNtNWxkQ0JYYVdSbmFYUnpJRkIwZVNCTWRHUXdnZ0lpTUEwR0NTcUdTSWIzRFFFQgpBUVVBQTRJQ0R3QXdnZ0lLQW9JQ0FRRE10ZGpVUUhzUGJDamNQMjJORmpKN3NzOXJYOVEydmloVVpLN2cvbGF4Cm1hMnpmelV6QitKUUNhdTlFZkRQUVpqVC91NWVGL29vaUtqbGI1Q25USEZMbG52eFd6N1pKN0hWYzAzTnZhWEUKUk54VmdPMXNCbkxSME9URTZRampBYW9lU29RSnFDMEI2em5KdTlNaVdUeVVsY2xWNHVocmZERGZUK1hUcHNrVgpLV2pnMG9ORCtFN01zMTlsRTRwMVYrV0dPWVRub0E1a3pvS2Z4aGpIN3R6SWZwbXFTWGJ2RGxkOWNacUJGbEtHCjBGeWFxK2pUS1lkRWtRL2xQekxJQWtaWW5NVVJDcklJYkZ3WHpuV3VqYzNQYVNnQkdCSmowVFlsN1Z6SExzM2sKL2dCdzd4N1FZZk41SGFZckhYN0FqMlQ4b2Z2a2xhcUxDRDFUaS9nM3dNVzgyR0NJVW52OW13Z3F5TFJoSHBscgpiUmV0a3BSU0JueDlOMWtac2VkaFVoR2FuS3I5MVhrajBySlRTcnBNUkZsSjdVWTlzTEMwenRwVGtMTjlvMnZpCmxrVFd0S3dKTzZXTzBsOTNDSitsWXhUcndNU3RLT0JDN2tVOXdhcVN3REQ0MHJtS1c3VTE0TlVhcTVIYlVISTYKMmY3UzBxVlRhb255VUN6OUVhVmJLaTV0SDFuVkJ1SWwzUDFRQS9RMkh1ZWo5TTU5YWlaT0lDVnhmQmJUbUNIeApyeG5pai83MWlDbTcrMWllNUxIMTI4Y2krNW1nRTQvditPZFZwM0RucVkycmFNeUFJMFBJNGVNVFlmc2tRWVFkCjlCRU8rVkI4ZGdtcnlSR2dPaHNSWFFieXFNOERYTXc4S1BrS2IxTjBwR2l1NXVNRVFKaHd4S3N6T0JGWGtyRG8KQndJREFRQUJvMU13VVRBZEJnTlZIUTRFRmdRVUVXTTh0WjRsVng0MlFMeE8xSE03dGRCZUMvOHdId1lEVlIwagpCQmd3Rm9BVUVXTTh0WjRsVng0MlFMeE8xSE03dGRCZUMvOHdEd1lEVlIwVEFRSC9CQVV3QXdFQi96QU5CZ2txCmhraUc5dzBCQVFzRkFBT0NBZ0VBd3UwN2doaHRyUkNMZ0JuNENHbE5vVkxLRkx2SjQ3T21GUUc1eVp5MTEvdzkKaC9oblJMeDVCbk8wb1lZMmw4M0Z3OUozUWVIaThDTk84Ujc4NTRmRk56WGMxSEFZa1RWc1VZbE9wOW4wTTYwSgpKb3MyUFA5TldNTUpCcFg3Q3JQYUZRRjJoU09hb1NqaXZ1dVoxRnQrZVZEY3FWMjM0VFkrK25hYzBRc053RTYrCnpMai91TGFEM0xWUXh6Y2RuNWMrYVpSNjV0K3I0Q0RsWW1MMGVJY2RTeXF5UUtUWDlMaE1lVXQ3RUxJdEpnVkgKZDdSaDRuRU8rRDVhVEszNkZNSk9TM0VUL0Y1RksrT2QzVmgwMW9RTTJwR0dqQ3A3d2dMeWxNNTVaMWhsTnVXMQo4YWp2eHJDNWVVd2RkaTA4WWFBQjlpR1VRLzRmeUFmQkNkNjJZVVRXSUhib1NMKy84MEpySFZIQnhTaWZ0NmRFClI0SVBtbmtoakovOFcvK1g1WThvOFdrVUF3Zm00QWpOL3ZOZGUxWm1NSVFsSEZhQVRuWUJEaXBaOElSUnBndFEKcnc4d044U0NOV0plZHppdlVoYjdXdUdHbndCcDZ1Wjg1TDUzblN3SFBBS2Y3eGNhTXROVnpuZ1VJaXU1bm9PNwpZSFFzcG1xRVhQQzQ4NERmMHhTUWllUUhTWGxPUVFXS285QTQ5ZXM1NnV2ZGw0c0pTbW9uUTZMblgzV21sUGFGCmdxQSs2ZXZHanVqQmppaTBybncvUWpxY3NteHNtWU84alpGY21pZWpJL3AxUE1OalBpRWJjZGhrNFNrdDlxdnkKcDhvTXVLVzFLNHFpRUp0R1VOT3hkUEt2b1V1MWllQUtuY0FtdUhxdWNHWDBva2JrdmZjT0tYQjFoRi9kK1gwPQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
AlexanderYastrebov marked this conversation as resolved.
Show resolved Hide resolved
tls.key: |
LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUpSQUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQ1M0d2dna3FBZ0VBQW9JQ0FRRE10ZGpVUUhzUGJDamMKUDIyTkZqSjdzczlyWDlRMnZpaFVaSzdnL2xheG1hMnpmelV6QitKUUNhdTlFZkRQUVpqVC91NWVGL29vaUtqbApiNUNuVEhGTGxudnhXejdaSjdIVmMwM052YVhFUk54VmdPMXNCbkxSME9URTZRampBYW9lU29RSnFDMEI2em5KCnU5TWlXVHlVbGNsVjR1aHJmRERmVCtYVHBza1ZLV2pnMG9ORCtFN01zMTlsRTRwMVYrV0dPWVRub0E1a3pvS2YKeGhqSDd0eklmcG1xU1hidkRsZDljWnFCRmxLRzBGeWFxK2pUS1lkRWtRL2xQekxJQWtaWW5NVVJDcklJYkZ3WAp6bld1amMzUGFTZ0JHQkpqMFRZbDdWekhMczNrL2dCdzd4N1FZZk41SGFZckhYN0FqMlQ4b2Z2a2xhcUxDRDFUCmkvZzN3TVc4MkdDSVVudjltd2dxeUxSaEhwbHJiUmV0a3BSU0JueDlOMWtac2VkaFVoR2FuS3I5MVhrajBySlQKU3JwTVJGbEo3VVk5c0xDMHp0cFRrTE45bzJ2aWxrVFd0S3dKTzZXTzBsOTNDSitsWXhUcndNU3RLT0JDN2tVOQp3YXFTd0RENDBybUtXN1UxNE5VYXE1SGJVSEk2MmY3UzBxVlRhb255VUN6OUVhVmJLaTV0SDFuVkJ1SWwzUDFRCkEvUTJIdWVqOU01OWFpWk9JQ1Z4ZkJiVG1DSHhyeG5pai83MWlDbTcrMWllNUxIMTI4Y2krNW1nRTQvditPZFYKcDNEbnFZMnJhTXlBSTBQSTRlTVRZZnNrUVlRZDlCRU8rVkI4ZGdtcnlSR2dPaHNSWFFieXFNOERYTXc4S1BrSwpiMU4wcEdpdTV1TUVRSmh3eEtzek9CRlhrckRvQndJREFRQUJBb0lDQVFDZ1M4enI5MG5sZTdaTE1NZWg4TDI3Ckt2dE1ndzl6aGxlaUxlemFkWTZCSjJ0aTRMdFJxRnpJZTZvbE5RVXg1Wlc4ZXlWQVBOcEFIekxSNWhpSlNFeDIKK2ZFM3YxRnBUYkh0Q0lybURoamRwV1k2OWVmejdPQy85eWtNSDhZN3E3UUFZQzBnT3JaemlEUUtDYTk4ZUEvOQo4WVJrWW5mSW9zaktOSkFzdWE4L2lOdDlJSnAxQU4wRFlYblRkZ2UzZHdwZG5uQzV4eFUrVG83dWVYb3lKSkp4CjFPQ1MvVS9LUlpxd3VlSllMcGlVeEZlZkxmbjBUOUtDR0cwdi85ck56eW95ZlIrN0JucitLWXU3Z0ltYUU2UVQKUTY1MW5OblptNXNnKzhyb2xYZllWaVVXU2NnQk9KSWtSdGsxYmJVeEo1ZldVeWtoaHlpeUVkT2p0amk1djVPVgpzN0o5V1dzcW9qYUdacG8vTUc0VllsRzA4N0VYR1c3ZUt2U2JWL1VCTHEzcEZtUEVYUjFGVUZyL0xFT2M0MmZnCmEvOGgyQ2M2N2p6Z1EzbHpFY0VzSzZJMnZud3FESzlXR1hBd2hXZG9zUG1QVzFKQ2JOMkhXcUxHTHdJTnZCbG0KcnJQUjFQN1Rhc2ZHZE1jaER4QVdKUkJXblNUdzJyZUo0YVp5dlk5Tk1hdHdodHBvQnJrR3pGVjNYZEV6SEZxVwpjaHJDdnZKSURQdzBqaUN2akdSdnRLYWZ2WWJ5dktvaFNTQTNpMjhtYlB1TzBuSEdacEJ6OEZMTzA3d0Fmd1ZyCkdWWWNxSGdVRk5BYUp1Qld4WndMR0NGeU9sWUJadVNRL0ZONjJZQ091Vm1SRVpTWmtqekFuczhqNVBBdnBSUFgKVFJsM3dxakdrV3BlSHg3clM1OXdVUUtDQVFFQTdsZk5NdFc3b1dvNC90b0dvaE1LK3RXOWphN3JPd08wZ0VNdQo5OGV6WitOakJsRGdoOVRkTk1JMFZqekNZeGxIQUM0MnZxcHZ1TG1rSk40Rm8xY0lDaVFjS01FYitxOGRMUzFZClhXRlRKdFdMY1poUXFUampCNWlRZ1QvZFpBS3dHT3ZSQlVuRi9id0VKeEhTLzZBYk1YaWs4bVlpWWNZZkI3bTUKMkZBcUZHUmdhQjJOMXBiMmduU3hDRW12UjhHbk1Bam9MY2x3S0FHYUtwMVFmK1hCL25wVlpFVXpRL3hxSkZrWgppa21YUDZ5ekpZbXF6UnRGVHhTZDVqQ3hVMTBDMDVSREEraFUydTd0VGU4SW5sTmtpYWhud0xLOHlBUkg0Z201CjlXRmZ0KzBCQ1BDVkFHTk00NjdmcEt5VmwzODdsdG5pSkF0RG1oYXJ6Z2dNeVBidXN3S0NBUUVBMitBeStsVTIKMkFURHN2Wmp6OEc0alI3RnN4MUhYK1pmbTdtTVhKajVYMWhVekduRHZzcngwSE16Z0Zxbk9pYTlrNXpBaFhNSQpwZnl5RitPR0RVb3c3eXJzWGtTeWZDWTYyUVBSRkd2Z01qMUhoYUUwQzlkSWVXZmNlOTVlUUFVZ0FsVjlDRkQrCjlaYmtUMzZPZy9VTUVWU0dkdUhFVVFiRW52Qnp2Zm9UOVJkcEQ3eWd2Sk03T0RFR1A2Z1djNkVXOUcrWXpJNG8Ka2k4SEVRbDJRa1N2cTJkVVBjSzNoZVFvbHJCWERUWk9QeS8vaG1jbkpnbEMvUW1nSUdyWHhQN0F3TjkrU2hYSAo4d1RMcVd1cll1eWpQdkkraXlLR0tHaTk2NmhwNW5JVDdjcllFOStJWlpQQWJrbFRXUVg0SGNrYzhtMTFMZkJQCjAxT2NZMit4clp1TFhRS0NBUUVBcEIzVFR3aTdQVWVPWFhZMWtRNTV4Z1M5bER6NC90YnJTRko2bWVWcDFNUlAKWUg3NlRLMjNiK2UxOEJmQVprcDJpRnBLR2ZuMEdnZkNUaHlQVjB6TFhXaEY5NDRaUFFHdG5ua1YycDcwaWM0TApTYm51K01jU0ZSM3Bpd1kxNVBLdzNVZ3IwbTlkSlAxOUFvWVVleTU4NnhDK3k2YW1VQnNETE9lblg1cTdqdlViCktUWUlmOVhOZ2tEbDBlWWpDczcrMTJXYXNrUjl0UjU5VUpDb2FKa0Zmcnd2NW01OEFYbGlnUXJWT2xLNEVnRlMKRGl3QWIyRXkxV1JGNGNadnBBNXNydEh0WDFod2JaeU56TmNtWVJiZEtLak1ZSFR5NXV1RHI5S3d1SlZIT3JlNAp1YlluYzIvczl1NW9VdFQvNEtTY25LQUZSbnAzSHpnekx4aDk3VGVUWHdLQ0FRRUF3TTBRaG5oUWRnMS9lUjhhCm1LTzY2MnZQV2VkVG5lRUpkeWkxenNDSThyVW03blBUcENxYTdma0djUWVNMmEzODBFSkVnd0JDMWlJR0hISnoKS3BZaTRLV1h6SFdhdU1oaEU4aUgvc3MxTlhpTWpiMjBRS25QTUQ0RmxVeUJBc3c3ckRCQVNobVQ1OUFmZFNGNQpZSFp3MVlWenZ5enJFMDNHL2NQRkNoSU9pL3l5TUkxcnVNKzF2dWttSEkyTTJtbW9Fa0VGRUdHYmE4djIrMVo3CnIxSkJaQ0JnT3lQUi80TDRvR0lTZzFCYVBvZ2RIVUs0amw3U3NjVk45djhaSXZGc0hmUWI3bVM1QnZ6dWhTb1gKaDlBT3VYUjdxVTlscW10bUZnMkFod1VET3FHQzViSStEU3dKTWV2MFBQekIrNFJOY0xyUVpLN3pvRkFSc3hQUApEbmQxTlFLQ0FRQXlJM0xCOUQxUlg1NkhEYmI4WTZobk1wM2xTTmU3aWxpNy8zMjNCczB2QTZ6R0hod2o4ajlnCjVHcEJSd2ZXdCszUkRvZlQrL1h3K1MxTmdUTVJxWkw3M3V3VjdIWnhaTkE4NU5TUDk2bG5EbmpXN3NzTFhtY0wKRFRNQy83UVBaOU1xYmt4SXNDV0wwaml2bSs0a0UrSStqWXlHdkx0a2hlU1NHOU5pOGM1SzlwdjF1Z3ZVOUpwSAo0QlRSblhCd2JOUnVMZ3JpcHJwZjJKS2dYQmlPWEFTZUVmbzMvSTRETjZISWxwUFdoRDkwb0MyaWhvU3JrL2lVCmFMSnVCUmhncDJBelFYMWlBMDcxczNJR3ZlUERnN1RYd2Y4ZDM2bFhnVWNTTEJ0N2FmVzNoOGordEVCZ1FQTEwKVk9seXgzYzVNdVpaZDhHWXBKNGUwUDFJYWJzN2ZwZEEKLS0tLS1FTkQgUFJJVkFURSBLRVktLS0tLQo=
Original file line number Diff line number Diff line change
@@ -1,27 +1,3 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-deployment
labels:
app: myapp
spec:
replicas: 1
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: myapp:v1
ports:
- containerPort: 80
name: my-port
protocol: TCP
---
apiVersion: v1
kind: Service
metadata:
Expand Down
24 changes: 0 additions & 24 deletions dataclients/kubernetes/testdata/ingressV1/tls/tls-invalid-tls.yaml
Original file line number Diff line number Diff line change
@@ -1,27 +1,3 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-deployment
labels:
app: myapp
spec:
replicas: 1
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: myapp:v1
ports:
- containerPort: 80
name: my-port
protocol: TCP
---
apiVersion: v1
kind: Service
metadata:
Expand Down
Loading