Closed dzmitry-kankalovich closed 3 years ago
TL;DR: is it possible to extract peer (client) TLS certificate either via Lua plugin or Go plugin?
It seems like we've found a workaround on the basis of this changeset and likely proceed with that.
So, in a nutshell, this is a solution to what we asked originally:
Besides the ability to forward the XFCC (x-forwarded-client-cert) header to the upstream service, we've just confirmed that we can access the raw Client TLS Certificate, its certificate chain, and its metadata by reading the same XFCC header value in the Go plugin (Filter). Apparently, this header is conveniently added before the request gets processed by Filters.
So, I guess even though the ExtAuth
protocol by itself won't allow the forward of the underlying Client TLS Cert to the Filter, the workaround with the XFCC header still gets us what we need.
PS: we haven't checked if the same is possible with Lua plugins.
At this point, there is a viable workaround, at least for the Go Plugin (Filter) case, so this feature request is no more "must", but rather a "nice" to have a thing in my mind.
We are though relying on the fact that XFCC is attached to the original request before Filters execution, and IDK if this is guaranteed to stay the same in future versions of Ambassador - this is one thing. Another thing is that documentation and overall plugin development framework does not feel on par with the competition like Kong, and this by itself slows down the progress, but it goes beyond the scope of what we're discussing here.
I feel like this feature request might be closed. I've added some more keywords here so that other people can find this issue and a workaround solution.
UPDATE: As of AEM 1.14.0 it is now possible to extract client cert via Lua scripts:
lua_scripts: |
function envoy_on_request(handle)
local si = handle:streamInfo():downstreamSslConnection()
if si == nil then
handle:headers():add("X-Lua-XFCC", "No SSL Context")
else
if si:peerCertificatePresented() then
handle:headers():add("X-Lua-XFCC", si:subjectPeerCertificate())
else
handle:headers():add("X-Lua-XFCC", "None")
end
end
end
Please describe your use case / problem. We're using Ambassador Edge Stack (AES) to front the API for the IoT devices via Emissary-Ingress acting as API gateway. In the case of IoT, a typical approach for the authentication with remote API is to use Mutual TLS (mTLS).
So, the IoT device presents an X509 certificate, which does the following:
Now, in the context of API GW, we have no problems establishing mTLS to achieve Num.1 - we provision a standalone Host with mTLS enabled, supply the CA chain & keys and we're good. But the troubles arise with Num.2 - attempt to read and pass forward the peer (client) certificate metadata.
As of now, there seems to be no way to extract certificate meta and pass it forward to the upstream service. There were two ways to do that which we explored:
FilterPlugin
.Describe the solution you'd like Given the current architecture of Emissary, it's probably simpler to upgrade to Envoy v1.16 than to re-do the architecture of the
FilterPlugin
. We have only one concern here - these Lua scripts doing request transformation are global, affecting every request, regardless of the host and path. Ideally, that should be host-path scoped, just like Filters.Another way to do it is to automatically extract this data and pass it further upstream, like Kong does it. Still, it will cover only basic cases, so programmatic access to the underlying cert is more preferable.
Describe alternatives you've considered As of now, looks like we'll be forced to duplicate some cert meta in the API request body, headers, or params. Not as elegant as supplying them via peer certificate, and potentially error-prone.
Additional context N/A