I have a very simple use case: I want to call an external service from my pod and use egress gateway to apply a client certificate to the outgoing request (TLS origination). I don’t want to verify any certificates.
I can easily achieve it using stunnel with a following simple configuration:
client = yes
accept = 8181
connect = destination:443
cert = /certs/certificate.pem
key = /certs/private.key
When I call (HTTP) stunnel:8181/something, stunnel will do the TLS upgrade, use the client certificate and forward the request to (HTTPS) destination:443/something
I have been trying to set this up using Egress Gateway since istio 1.3. My latest attempt with istio 1.7 and SDS (auto mTLS disabled) has been also unsuccessful:
I need a ServiceEntry, Gateway, DestinationRule and a VirtualService just to setup the traffic flow through the Egress Gateway. This works fine and my Egress Gateway forwards the request to the correct destination.
To enable the TLS origination, I need to create a secret with the certificate (in istio-system namespace) + an additional Destination Rule.
According to the link above, the Secret should be created like this:
> kubectl create secret generic gibaskbx-client-cacert --from-file=certificate.pem -n istio-system
However, the istio-proxy logs then shows warnings and errors:
2020-09-03T13:58:14.045870Z warn secretfetcher failed load CA only secret from gibaskbx-client-cacert: no ‘cacert’ or ‘tls.crt’ key in the secret
2020-09-03T13:58:14.045908Z info secretfetcher Fail to extract secret gibaskbx-client-cacert found by direct api call
2020-09-03T13:58:14.045917Z warn secretfetcher Cannot find secret gibaskbx-client-cacert, searching for fallback secret gateway-fallback
2020-09-03T13:58:14.045926Z error secretfetcher cannot find secret gibaskbx-client-cacert and cannot find fallback secret gateway-fallback
When I create the secret like this, the error goes away:
kubectl create secret tls gibaskbx-client-cacert -n istio-system
In both cases, TLS origination does not work.
This is my DestinationRule:
apiVersion: networking.istio .io/v1alpha3
credentialName: gibaskbx-client # this must match the secret created earlier without the “-cacert” suffix
And this is how I test it (using deliberately https://):
kubectl exec -it $SOURCE_POD -c sleep -n platform – curl -k -v -sL -o /dev/null -D - https://webapi.developers.erstegroup.com/api/slsp/sandbox/v1/psd2-ais/v1/accounts
The result is:
* Trying 188.8.131.52:443…
* Connected to webapi.developers.erstegroup .com (184.108.40.206) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
* CAfile: /etc/ssl/certs/ca-certificates.crt
} [5 bytes data]
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
} [512 bytes data]
* OpenSSL SSL_connect: SSL_ERROR_SYSCALL in connection to webapi.developers.erstegroup .com:443
* Closing connection 0
command terminated with exit code 35
Without applying the final DestinationRule, I get error code 56 at the very end of the TLS handshake, but that seems to be expected:
* OpenSSL SSL_read: SSL_ERROR_ SYSCALL, errno 0
* Closing connection 0
command terminated with exit code 56
My Gateway uses tls mode: PASSTHROUGH if that’s of any significance.
- Has anyone achieved a working TLS origination like this?
- Why should the Secret holding the client certificate be named with -cacert as a suffix?
- Should the Secret holding the client certificate be a tls secret or a generic secret? What about the key?
- Isn’t it too complex to setup such a simple use case? (compared to stunnel)?!?