Skip to content

Commit

Permalink
lua: Expose SSL connection info (#12174)
Browse files Browse the repository at this point in the history
This patch adds Lua APIs to access SSL connection info of a connection.

Signed-off-by: Dhi Aurrahman <dio@tetrate.io>
  • Loading branch information
dio authored Jul 30, 2020
1 parent 702f1fb commit 68f7288
Show file tree
Hide file tree
Showing 11 changed files with 691 additions and 13 deletions.
218 changes: 215 additions & 3 deletions docs/root/configuration/http/http_filters/lua_filter.rst
Original file line number Diff line number Diff line change
Expand Up @@ -562,6 +562,17 @@ dynamicMetadata()
Returns a :ref:`dynamic metadata object <config_http_filters_lua_stream_info_dynamic_metadata_wrapper>`.

downstreamSslConnection()
^^^^^^^^^^^^^^^^^^^^^^^^^

.. code-block:: lua
streamInfo:downstreamSslConnection()
Returns :repo:`information <include/envoy/ssl/connection.h>` related to the current SSL connection.

Returns a downstream :ref:`SSL connection info object <config_http_filters_lua_ssl_socket_info>`.

.. _config_http_filters_lua_stream_info_dynamic_metadata_wrapper:

Dynamic metadata object API
Expand Down Expand Up @@ -625,7 +636,7 @@ Connection object API
---------------------

ssl()
^^^^^^^^
^^^^^

.. code-block:: lua
Expand All @@ -638,6 +649,207 @@ ssl()
Returns :repo:`SSL connection <include/envoy/ssl/connection.h>` object when the connection is
secured and *nil* when it is not.

.. note::
Returns an :ref:`SSL connection info object <config_http_filters_lua_ssl_socket_info>`.

.. _config_http_filters_lua_ssl_socket_info:

SSL connection object API
-------------------------

peerCertificatePresented()
^^^^^^^^^^^^^^^^^^^^^^^^^^

.. code-block:: lua
if downstreamSslConnection:peerCertificatePresented() then
print("peer certificate is presented")
end
Returns bool whether the peer certificate is presented.

peerCertificateValidated()
^^^^^^^^^^^^^^^^^^^^^^^^^^

.. code-block:: lua
if downstreamSslConnection:peerCertificateVaidated() then
print("peer certificate is valiedated")
end
Returns bool whether the peer certificate was validated.

uriSanLocalCertificate()
^^^^^^^^^^^^^^^^^^^^^^^^

.. code-block:: lua
-- For example, uriSanLocalCertificate contains {"san1", "san2"}
local certs = downstreamSslConnection:uriSanLocalCertificate()
-- The following prints san1,san2
handle:logTrace(table.concat(certs, ","))
Returns the URIs (as a table) in the SAN field of the local certificate. Returns an empty table if
there is no local certificate, or no SAN field, or no URI SAN entries.

sha256PeerCertificateDigest()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

.. code-block:: lua
downstreamSslConnection:sha256PeerCertificateDigest()
Returns the SHA256 digest of the peer certificate. Returns ``""`` if there is no peer certificate
which can happen in TLS (non-mTLS) connections.

serialNumberPeerCertificate()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

.. code-block:: lua
downstreamSslConnection:serialNumberPeerCertificate()
Returns the serial number field of the peer certificate. Returns ``""`` if there is no peer
certificate, or no serial number.

issuerPeerCertificate()
^^^^^^^^^^^^^^^^^^^^^^^

.. code-block:: lua
downstreamSslConnection:issuerPeerCertificate()
Returns the issuer field of the peer certificate in RFC 2253 format. Returns ``""`` if there is no
peer certificate, or no issuer.

subjectPeerCertificate()
^^^^^^^^^^^^^^^^^^^^^^^^

.. code-block:: lua
downstreamSslConnection:subjectPeerCertificate()
Return the subject field of the peer certificate in RFC 2253 format. Returns ``""`` if there is no
peer certificate, or no subject.

uriSanPeerCertificate()
^^^^^^^^^^^^^^^^^^^^^^^

.. code-block:: lua
downstreamSslConnection:uriSanPeerCertificate()
Returns the URIs (as a table) in the SAN field of the peer certificate. Returns en empty table if
there is no peer certificate, or no SAN field, or no URI SAN entries.

subjectLocalCertificate()
^^^^^^^^^^^^^^^^^^^^^^^^^

.. code-block:: lua
downstreamSslConnection:subjectLocalCertificate()
Returns the subject field of the local certificate in RFC 2253 format. Returns ``""`` if there is no
local certificate, or no subject.

urlEncodedPemEncodedPeerCertificate()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

.. code-block:: lua
downstreamSslConnection:urlEncodedPemEncodedPeerCertificate()
Returns the URL-encoded PEM-encoded representation of the peer certificate. Returns ``""`` if there
is no peer certificate or encoding fails.

urlEncodedPemEncodedPeerCertificateChain()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

.. code-block:: lua
downstreamSslConnection:urlEncodedPemEncodedPeerCertificateChain()
Returnns the URL-encoded PEM-encoded representation of the full peer certificate chain including the
leaf certificate. Returns ``""`` if there is no peer certificate or encoding fails.

dnsSansPeerCertificate()
^^^^^^^^^^^^^^^^^^^^^^^^

.. code-block:: lua
downstreamSslConnection:dnsSansPeerCertificate()
Returns the DNS entries (as a table) in the SAN field of the peer certificate. Returns an empty
table if there is no peer certificate, or no SAN field, or no DNS SAN entries.

dnsSansLocalCertificate()
^^^^^^^^^^^^^^^^^^^^^^^^^

.. code-block:: lua
downstreamSslConnection:dnsSansLocalCertificate()
Returns the DNS entries (as a table) in the SAN field of the local certificate. Returns an empty
table if there is no local certificate, or no SAN field, or no DNS SAN entries.

validFromPeerCertificate()
^^^^^^^^^^^^^^^^^^^^^^^^^^

.. code-block:: lua
downstreamSslConnection:validFromPeerCertificate()
Returns the time (timestamp-since-epoch in seconds) that the peer certificate was issued and should
be considered valid from. Returns ``0`` if there is no peer certificate.

In Lua, we usually use ``os.time(os.date("!*t"))`` to get current timestamp-since-epoch in seconds.

expirationPeerCertificate()
^^^^^^^^^^^^^^^^^^^^^^^^^^^

.. code-block:: lua
downstreamSslConnection:validFromPeerCertificate()
Returns the time (timestamp-since-epoch in seconds) that the peer certificate expires and should not
be considered valid after. Returns ``0`` if there is no peer certificate.

In Lua, we usually use ``os.time(os.date("!*t"))`` to get current timestamp-since-epoch in seconds.

sessionId()
^^^^^^^^^^^

.. code-block:: lua
downstreamSslConnection:sessionId()
Returns the hex-encoded TLS session ID as defined in RFC 5246.

ciphersuiteId()
^^^^^^^^^^^^^^^^

.. code-block:: lua
downstreamSslConnection:ciphersuiteId()
Returns the standard ID (hex-encoded) for the ciphers used in the established TLS connection.
Returns ``"0xffff"`` if there is no current negotiated ciphersuite.

ciphersuiteString()
^^^^^^^^^^^^^^^^^^^

.. code-block:: lua
downstreamSslConnection:ciphersuiteString()
Returns the OpenSSL name for the set of ciphers used in the established TLS connection. Returns
``""`` if there is no current negotiated ciphersuite.

tlsVersion()
^^^^^^^^^^^^

.. code-block:: lua
downstreamSslConnection:urlEncodedPemEncodedPeerCertificateChain()
Currently the SSL connection object has no exposed APIs.
Returns the TLS version (e.g., TLSv1.2, TLSv1.3) used in the established TLS connection.
1 change: 1 addition & 0 deletions docs/root/version_history/current.rst
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ New Features
* http: added support for :ref:`%DOWNSTREAM_PEER_FINGERPRINT_1% <config_http_conn_man_headers_custom_request_headers>` as custom header.
* http: introduced new HTTP/1 and HTTP/2 codec implementations that will remove the use of exceptions for control flow due to high risk factors and instead use error statuses. The old behavior is used by default, but the new codecs can be enabled for testing by setting the runtime feature `envoy.reloadable_features.new_codec_behavior` to true. The new codecs will be in development for one month, and then enabled by default while the old codecs are deprecated.
* load balancer: added a :ref:`configuration<envoy_v3_api_msg_config.cluster.v3.Cluster.LeastRequestLbConfig>` option to specify the active request bias used by the least request load balancer.
* lua: added Lua APIs to access :ref:`SSL connection info <config_http_filters_lua_ssl_socket_info>` object.
* postgres network filter: :ref:`metadata <config_network_filters_postgres_proxy_dynamic_metadata>` is produced based on SQL query.
* redis: added fault injection support :ref:`fault injection for redis proxy <envoy_v3_api_field_extensions.filters.network.redis_proxy.v3.RedisProxy.faults>`, described further in :ref:`configuration documentation <config_network_filters_redis_proxy>`.
* router: added new
Expand Down
10 changes: 5 additions & 5 deletions include/envoy/ssl/connection.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ class ConnectionInfo {
virtual bool peerCertificateValidated() const PURE;

/**
* @return std::string the URIs in the SAN field of the local certificate. Returns {} if there is
* no local certificate, or no SAN field, or no URI.
* @return absl::Span<const std::string>the URIs in the SAN field of the local certificate.
* Returns {} if there is no local certificate, or no SAN field, or no URI.
**/
virtual absl::Span<const std::string> uriSanLocalCertificate() const PURE;

Expand Down Expand Up @@ -72,8 +72,8 @@ class ConnectionInfo {
virtual const std::string& subjectPeerCertificate() const PURE;

/**
* @return std::string the URIs in the SAN field of the peer certificate. Returns {} if there is
*no peer certificate, or no SAN field, or no URI.
* @return absl::Span<const std::string> the URIs in the SAN field of the peer certificate.
* Returns {} if there is no peer certificate, or no SAN field, or no URI.
**/
virtual absl::Span<const std::string> uriSanPeerCertificate() const PURE;

Expand Down Expand Up @@ -142,7 +142,7 @@ class ConnectionInfo {
* if a peer cert exists and it contains the specified extension.
*
* Note: This is used out of tree, check with @snowp before removing.
* @param extension_name name of extension to look up
* @param extension_name name of extension to look up.
* @return absl::optional<std::string> the raw octets of the extension ``ASN.1`` object, if it
* exists.
*/
Expand Down
11 changes: 11 additions & 0 deletions source/common/common/hex.cc
Original file line number Diff line number Diff line change
Expand Up @@ -73,4 +73,15 @@ std::string Hex::uint32ToHex(uint32_t value) {

return encode(data.data(), data.size());
}

std::string Hex::uint16ToHex(uint16_t value) {
std::array<uint8_t, 2> data;

// This is explicitly done for performance reasons
// using std::stringstream with std::hex is ~3 orders of magnitude slower.
data[1] = (value & 0x00FF);
data[0] = (value & 0xFF00) >> 8;

return encode(data.data(), data.size());
}
} // namespace Envoy
8 changes: 8 additions & 0 deletions source/common/common/hex.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,5 +49,13 @@ class Hex final {
* @return value as hexadecimal string
*/
static std::string uint32ToHex(uint32_t value);

/**
* Converts the given 16-bit unsigned integer into a hexadecimal string.
* The result is always a string of 4 characters left padded with zeroes.
* @param value The unsigned integer to be converted.
* @return value as hexadecimal string
*/
static std::string uint16ToHex(uint16_t value);
};
} // namespace Envoy
1 change: 1 addition & 0 deletions source/extensions/filters/common/lua/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ envoy_cc_library(
deps = [
":lua_lib",
"//include/envoy/buffer:buffer_interface",
"//source/common/common:hex_lib",
"//source/common/protobuf",
],
)
Loading

0 comments on commit 68f7288

Please sign in to comment.