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

support tls termination for tcp traffic #1431

Merged
merged 9 commits into from
May 25, 2023
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
83 changes: 83 additions & 0 deletions docs/latest/user/tls-termination.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# TLS Termination for TCP

This guide will walk through the steps required to configure TLS Terminate mode for TCP traffic via Envoy Gateway. The guide uses a self-signed CA, so it should be used for testing and demonstration purposes only.

## Prerequisites

- OpenSSL to generate TLS assets.

## Installation

Follow the steps from the [Quickstart Guide](quickstart.md) to install Envoy Gateway.

## TLS Certificates
Generate the certificates and keys used by the Gateway to terminate client TLS connections.

Create a root certificate and private key to sign certificates:

```shell
openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -subj '/O=example Inc./CN=example.com' -keyout example.com.key -out example.com.crt
```

Create a certificate and a private key for `www.example.com`:

```shell
openssl req -out www.example.com.csr -newkey rsa:2048 -nodes -keyout www.example.com.key -subj "/CN=www.example.com/O=example organization"
openssl x509 -req -days 365 -CA example.com.crt -CAkey example.com.key -set_serial 0 -in www.example.com.csr -out www.example.com.crt
```

Store the cert/key in a Secret:

```shell
kubectl create secret tls example-cert --key=www.example.com.key --cert=www.example.com.crt
```

Install the TLS Termination for TCP example resources:

```shell
kubectl apply -f https://raw.githubusercontent.com/envoyproxy/gateway/latest/examples/kubernetes/tls-termination.yaml
```

Verify the Gateway status:

```shell
kubectl get gateway/eg -o yaml
```

## Testing

### Clusters without External LoadBalancer Support

Get the name of the Envoy service created the by the example Gateway:

```shell
export ENVOY_SERVICE=$(kubectl get svc -n envoy-gateway-system --selector=gateway.envoyproxy.io/owning-gateway-namespace=default,gateway.envoyproxy.io/owning-gateway-name=eg -o jsonpath='{.items[0].metadata.name}')
```

Port forward to the Envoy service:

```shell
kubectl -n envoy-gateway-system port-forward service/${ENVOY_SERVICE} 8443:443 &
```

Query the example app through Envoy proxy:

```shell
curl -v -HHost:www.example.com --resolve "www.example.com:8443:127.0.0.1" \
--cacert example.com.crt https://www.example.com:8443/get
```

### Clusters with External LoadBalancer Support

Get the External IP of the Gateway:

```shell
export GATEWAY_HOST=$(kubectl get gateway/eg -o jsonpath='{.status.addresses[0].value}')
```

Query the example app through the Gateway:

```shell
curl -v -HHost:www.example.com --resolve "www.example.com:443:${GATEWAY_HOST}" \
--cacert example.com.crt https://www.example.com/get
```
96 changes: 96 additions & 0 deletions examples/kubernetes/tls-termination.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
apiVersion: gateway.networking.k8s.io/v1beta1
kind: GatewayClass
metadata:
name: eg
spec:
controllerName: gateway.envoyproxy.io/gatewayclass-controller
---
apiVersion: gateway.networking.k8s.io/v1beta1
kind: Gateway
metadata:
name: eg
spec:
gatewayClassName: eg
listeners:
- allowedRoutes:
namespaces:
from: Same
name: https
port: 443
protocol: TLS
tls:
certificateRefs:
- group: ""
kind: Secret
name: example-cert
mode: Terminate
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: backend
---
apiVersion: v1
kind: Service
metadata:
name: backend
labels:
app: backend
service: backend
spec:
ports:
- name: http
port: 3000
targetPort: 3000
selector:
app: backend
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: backend
spec:
replicas: 1
selector:
matchLabels:
app: backend
version: v1
template:
metadata:
labels:
app: backend
version: v1
spec:
serviceAccountName: backend
containers:
- image: gcr.io/k8s-staging-ingressconformance/echoserver:v20221109-7ee2f3e
imagePullPolicy: IfNotPresent
name: backend
ports:
- containerPort: 3000
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
---
apiVersion: gateway.networking.k8s.io/v1alpha2
kind: TCPRoute
metadata:
name: backend
spec:
parentRefs:
- group: gateway.networking.k8s.io
kind: Gateway
name: eg
rules:
- backendRefs:
- group: ""
kind: Service
name: backend
port: 3000
weight: 1
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ gateways:
type: Programmed
name: tls
supportedKinds:
- group: gateway.networking.k8s.io
kind: TCPRoute
- group: gateway.networking.k8s.io
kind: TLSRoute
httpRoutes:
Expand Down
8 changes: 8 additions & 0 deletions internal/gatewayapi/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -428,3 +428,11 @@ func irTLSConfigs(tlsSecrets []*v1.Secret) []*ir.TLSListenerConfig {
func irTLSListenerConfigName(secret *v1.Secret) string {
return fmt.Sprintf("%s-%s", secret.Namespace, secret.Name)
}

func protocolSliceToStringSlice(protocols []v1beta1.ProtocolType) []string {
var protocolStrings []string
for _, protocol := range protocols {
protocolStrings = append(protocolStrings, string(protocol))
}
return protocolStrings
}
15 changes: 13 additions & 2 deletions internal/gatewayapi/listener.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ type ListenersTranslator interface {

func (t *Translator) ProcessListeners(gateways []*GatewayContext, xdsIR XdsIRMap, infraIR InfraIRMap, resources *Resources) {
t.validateConflictedLayer7Listeners(gateways)
t.validateConflictedLayer4Listeners(gateways, v1beta1.TCPProtocolType)
t.validateConflictedLayer4Listeners(gateways, v1beta1.TCPProtocolType, v1beta1.TLSProtocolType)
t.validateConflictedLayer4Listeners(gateways, v1beta1.UDPProtocolType)

// Iterate through all listeners to validate spec
Expand Down Expand Up @@ -50,7 +50,18 @@ func (t *Translator) ProcessListeners(gateways []*GatewayContext, xdsIR XdsIRMap
// Process protocol & supported kinds
switch listener.Protocol {
case v1beta1.TLSProtocolType:
t.validateAllowedRoutes(listener, KindTLSRoute)
if listener.TLS != nil {
switch *listener.TLS.Mode {
case v1beta1.TLSModePassthrough:
t.validateAllowedRoutes(listener, KindTLSRoute)
case v1beta1.TLSModeTerminate:
t.validateAllowedRoutes(listener, KindTCPRoute)
default:
t.validateAllowedRoutes(listener, KindTCPRoute, KindTLSRoute)
}
} else {
t.validateAllowedRoutes(listener, KindTCPRoute, KindTLSRoute)
}
case v1beta1.HTTPProtocolType, v1beta1.HTTPSProtocolType:
t.validateAllowedRoutes(listener, KindHTTPRoute, KindGRPCRoute)
case v1beta1.TCPProtocolType:
Expand Down
5 changes: 3 additions & 2 deletions internal/gatewayapi/route.go
Original file line number Diff line number Diff line change
Expand Up @@ -663,9 +663,9 @@ func (t *Translator) processTLSRouteParentRefs(tlsRoute *TLSRouteContext, resour
Name: irTLSListenerName(listener, tlsRoute),
Address: "0.0.0.0",
Port: uint32(containerPort),
TLS: &ir.TLSInspectorConfig{
TLS: &ir.TLS{Passthrough: &ir.TLSInspectorConfig{
SNIs: hosts,
},
}},
Destinations: routeDestinations,
}
gwXdsIR := xdsIR[irKey]
Expand Down Expand Up @@ -946,6 +946,7 @@ func (t *Translator) processTCPRouteParentRefs(tcpRoute *TCPRouteContext, resour
Address: "0.0.0.0",
Port: uint32(containerPort),
Destinations: routeDestinations,
TLS: &ir.TLS{Terminate: irTLSConfigs(listener.tlsSecrets)},
}
gwXdsIR := xdsIR[irKey]
gwXdsIR.TCP = append(gwXdsIR.TCP, irListener)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,8 +146,9 @@ xdsIR:
address: 0.0.0.0
port: 10090
tls:
snis:
- "foo.com"
passthrough:
snis:
- "foo.com"
destinations:
- host: 7.7.7.7
port: 8080
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ xdsIR:
destinations:
- host: "7.7.7.7"
port: 8163
tls: {}

infraIR:
envoy-gateway-gateway-1:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ gateways:
namespaces:
from: All
- name: tcp2
protocol: TCP
protocol: TLS
port: 162
allowedRoutes:
namespaces:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ gateways:
namespaces:
from: All
- name: tcp2
protocol: TCP
protocol: TLS
port: 162
allowedRoutes:
namespaces:
Expand All @@ -39,16 +39,18 @@ gateways:
supportedKinds:
- group: gateway.networking.k8s.io
kind: TCPRoute
- group: gateway.networking.k8s.io
kind: TLSRoute
AttachedRoutes: 0
conditions:
- type: Conflicted
status: "True"
reason: ProtocolConflict
message: Only one TCP listener is allowed in a given port
message: Only one TCP/TLS listener is allowed in a given port
- type: Programmed
status: "False"
reason: Invalid
message: Listener is invalid, see other Conditions for details.
message: Listener must have TLS set when protocol is TLS.
tcpRoutes:
- apiVersion: gateway.networking.k8s.io/v1alpha2
kind: TCPRoute
Expand Down Expand Up @@ -87,6 +89,7 @@ xdsIR:
destinations:
- host: "7.7.7.7"
port: 8163
tls: {}
infraIR:
envoy-gateway-gateway-1:
proxy:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ xdsIR:
- name: "envoy-gateway-gateway-1-tcp-tcproute-1"
address: "0.0.0.0"
port: 10080
tls: {}
destinations:
- host: "7.7.7.7"
port: 8163
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,12 +116,14 @@ xdsIR:
- name: "envoy-gateway-gateway-1-tcp1-tcproute-1"
address: "0.0.0.0"
port: 10162
tls: {}
destinations:
- host: "7.7.7.7"
port: 8163
- name: "envoy-gateway-gateway-1-tcp2-tcproute-2"
address: "0.0.0.0"
port: 10163
tls: {}
destinations:
- host: "7.7.7.7"
port: 8163
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,12 +112,14 @@ xdsIR:
- name: "envoy-gateway-gateway-1-tcp1-tcproute-1"
address: "0.0.0.0"
port: 10161
tls: {}
destinations:
- host: "7.7.7.7"
port: 8163
- name: "envoy-gateway-gateway-1-tcp2-tcproute-1"
address: "0.0.0.0"
port: 10162
tls: {}
destinations:
- host: "7.7.7.7"
port: 8163
Expand Down
Loading