-
Notifications
You must be signed in to change notification settings - Fork 10
TLS setup
A secure TLS setup is good example of the need to implement security across all architectural layers; HTTP headers, server configuration, certificate settings and recently DNS must all align for a domain to be established as a root of trust.
Certificate provisioning for the Tracker project is fully automated using Cert Manager.
Cert Manager provides Custom Resource Definitions (CRDs) that describes the where certificates come from, and the certificate itself.
Let's Encrypt is the entity that issues certificates for the Tracker project. This is represented using the Issuer
object supplied by Cert Manager.
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: letsencrypt
namespace: istio-system
spec:
acme:
email: mike@korora.ca
preferredChain: ""
privateKeySecretRef:
name: letsencrypt-prod
server: https://acme-v02.api.letsencrypt.org/directory
solvers:
- http01:
ingress:
class: istio
selector: {}
status: {}
In line with the declarative approach that Kubernetes takes, certificates are requested via a statement that a certificate should exist that takes the form of a Certificate
object.
[mike@ouroboros tracker]$ cat app/gke/certificate.yaml
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: ingress-cert
namespace: istio-system
spec:
commonName: tracker.alpha.canada.ca
dnsNames:
- tracker.alpha.canada.ca
- suivi.alpha.canada.ca
issuerRef:
kind: Issuer
name: letsencrypt
privateKey:
algorithm: RSA
encoding: PKCS8 # ITSP.40.062 6.2 Signature Algorithms
size: 4096
secretName: tracker-credential
status: {}
This object ends up using certificatesigningrequests
and certificaterequest
objects to send a request to the issuer, complete the ACME protocols HTTP-01 challenge, and save the result in a Kubernetes secret with the name specified by the secretName
field.
As the name implies, the HTTP-01 challenge takes place over HTTP, but Let's Encrypt employs a multi-vantage-point verification process to mitigate against MITM attacks.
Incoming requests are recieved by Istio's ingress gateway which then forwards the request among it's network of centrally controlled proxies according the the routing policy objects defined in the project.
Istio supplies a Gateway
object that uses the secret created by the Certificate
object above. The Gateway
is where layer 4 concerns like ports and layer 6 details like TLS are handled, leaving layer 7 routing to a separate VirtualService object.
The details of Treasury Board's ITPIN can be mapped pretty directly to the properties of the Gateway
object.
[mike@ouroboros tracker]$ cat app/gke/publicgateway.yaml
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: publicgateway
namespace: istio-system
labels:
istio: publicgateway
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "*"
tls:
httpsRedirect: true # ITPIN 6.1.1 redirected from HTTP
- port:
number: 443
name: https
protocol: HTTPS # ITPIN 6.1.1 is configured for HTTPS
hosts:
- "*"
tls:
mode: SIMPLE
credentialName: tracker-credential
privateKey: sds
serverCertificate: sds
minProtocolVersion: TLSV1_2 # ITPIN 6.1.3 implements TLS 1.2, or subsequent versions
cipherSuites: # ITPIN 6.1.3 uses supported cryptographic algorithms
- TLS_AES_128_GCM_SHA256
- TLS_AES_256_GCM_SHA384
- TLS_CHACHA20_POLY1305_SHA256
- TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
- TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
- TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
Web applications recieve HTTP requests and return HTTP responses, meaning the headers are typically the provice of the application developer. There are a few headers we always want set for our application, like the HSTS header required by the ITPIN.
Istio doesn't provide a nice interface for this particular use-case, but does provide the EnvoyFilter
object as a mechanism to talk directly to the Envoy proxy it uses for ingress.
Using that we can patch all outgoing requests so that security headers like HSTS are consistently applied.
[mike@ouroboros tracker]$ cat platform/components/istio/envoy-security-headers-filter.yaml
apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
name: security-headers
namespace: istio-system
spec:
workloadSelector:
labels:
istio: ingressgateway
configPatches:
- applyTo: HTTP_FILTER
match:
context: GATEWAY
listener:
filterChain:
filter:
name: "envoy.http_connection_manager"
subFilter:
name: "envoy.router"
patch: # Patch outgoing requests for ITPIN 6.1.2: has HSTS enabled
operation: INSERT_BEFORE
value:
name: envoy.lua
typed_config:
"@type": "type.googleapis.com/envoy.config.filter.http.lua.v2.Lua"
inlineCode: |
function envoy_on_response(response_handle)
if not response_handle:headers():get("X-Frame-Options") then
response_handle:headers():add("X-Frame-Options", "deny");
end
if not response_handle:headers():get("Strict-Transport-Security") then
response_handle:headers():add("Strict-Transport-Security", "max-age=31536000; includeSubDomains");
end
end
This project was built by the Treasury Board of Canada Secretariat in collaboration with the Canadian Centre for Cyber Security.