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

lua API: add base64Escape function to stream handle #12552

Merged
merged 4 commits into from
Aug 17, 2020
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
10 changes: 10 additions & 0 deletions docs/root/configuration/http/http_filters/lua_filter.rst
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,16 @@ the length of the signature. *data* is the content which will be hashed. *dataLe
The function returns a pair. If the first element is *true*, the second element will be empty
which means signature is verified; otherwise, the second element will store the error message.

.. _config_http_filters_lua_stream_handle_api_base64_escape:

base64Escape()
^^^^^^^^^^^^^^
.. code-block:: lua

local base64_encoded = handle:base64Escape("input string")

Encodes the input string as base64. This can be useful for escaping binary data.

.. _config_http_filters_lua_header_wrapper:

Header object API
Expand Down
1 change: 1 addition & 0 deletions docs/root/version_history/current.rst
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ New Features
* 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.
* lua: added Lua API for :ref:`base64 escaping a string <config_http_filters_lua_stream_handle_api_base64_escape>`.
* overload management: add :ref:`scaling <envoy_v3_api_field_config.overload.v3.Trigger.scaled>` trigger for OverloadManager actions.
* postgres network filter: :ref:`metadata <config_network_filters_postgres_proxy_dynamic_metadata>` is produced based on SQL query.
* ratelimit: added :ref:`enable_x_ratelimit_headers <envoy_v3_api_msg_extensions.filters.http.ratelimit.v3.RateLimit>` option to enable `X-RateLimit-*` headers as defined in `draft RFC <https://tools.ietf.org/id/draft-polli-ratelimit-headers-03.html>`_.
Expand Down
11 changes: 11 additions & 0 deletions source/extensions/filters/http/lua/lua_filter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
#include "common/crypto/utility.h"
#include "common/http/message_impl.h"

#include "absl/strings/escaping.h"

namespace Envoy {
namespace Extensions {
namespace HttpFilters {
Expand Down Expand Up @@ -599,6 +601,15 @@ int StreamHandleWrapper::luaImportPublicKey(lua_State* state) {
return 1;
}

int StreamHandleWrapper::luaBase64Escape(lua_State* state) {
// Get input string.
absl::string_view input = luaL_checkstring(state, 2);
auto output = absl::Base64Escape(input);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If absl has base64 support can we get rid of base64.h/cc and/or pass through to absl? (Fine as follow up). cc @lizan @jmarantz

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, might be possible to pass through to absl, seems it can do base64 / hex. One thing it doesn't do for base64 is encoding our buffer without linearizing.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK I will file a follow up issue here.

lua_pushlstring(state, output.data(), output.length());

return 1;
}

FilterConfig::FilterConfig(const envoy::extensions::filters::http::lua::v3::Lua& proto_config,
ThreadLocal::SlotAllocator& tls,
Upstream::ClusterManager& cluster_manager, Api::Api& api)
Expand Down
10 changes: 9 additions & 1 deletion source/extensions/filters/http/lua/lua_filter.h
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,8 @@ class StreamHandleWrapper : public Filters::Common::Lua::BaseLuaObject<StreamHan
{"streamInfo", static_luaStreamInfo},
{"connection", static_luaConnection},
{"importPublicKey", static_luaImportPublicKey},
{"verifySignature", static_luaVerifySignature}};
{"verifySignature", static_luaVerifySignature},
{"base64Escape", static_luaBase64Escape}};
}

private:
Expand Down Expand Up @@ -268,6 +269,13 @@ class StreamHandleWrapper : public Filters::Common::Lua::BaseLuaObject<StreamHan
*/
DECLARE_LUA_CLOSURE(StreamHandleWrapper, luaBodyIterator);

/**
* Base64 escape a string.
* @param1 (string) string to be base64 escaped.
* @return (string) base64 escaped string.
*/
DECLARE_LUA_FUNCTION(StreamHandleWrapper, luaBase64Escape);

int doSynchronousHttpCall(lua_State* state, Tracing::Span& span);
int doAsynchronousHttpCall(lua_State* state, Tracing::Span& span);

Expand Down
27 changes: 27 additions & 0 deletions test/extensions/filters/http/lua/lua_filter_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2191,6 +2191,33 @@ TEST_F(LuaHttpFilterTest, LuaFilterRefSourceCodeNotExist) {
EXPECT_EQ(nullptr, request_headers.get(Http::LowerCaseString("hello")));
}

TEST_F(LuaHttpFilterTest, LuaFilterBase64Escape) {
const std::string SCRIPT{R"EOF(
function envoy_on_request(request_handle)
local base64Encoded = request_handle:base64Escape("foobar")
request_handle:logTrace(base64Encoded)
end

function envoy_on_response(response_handle)
local base64Encoded = response_handle:base64Escape("barfoo")
response_handle:logTrace(base64Encoded)
end
)EOF"};

InSequence s;
setup(SCRIPT);

Http::TestRequestHeaderMapImpl request_headers{{":path", "/"}};

EXPECT_CALL(*filter_, scriptLog(spdlog::level::trace, StrEq("Zm9vYmFy")));
EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter_->decodeHeaders(request_headers, true));

Http::TestResponseHeaderMapImpl response_headers{{":status", "200"}};

EXPECT_CALL(*filter_, scriptLog(spdlog::level::trace, StrEq("YmFyZm9v")));
EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter_->encodeHeaders(response_headers, true));
}

} // namespace
} // namespace Lua
} // namespace HttpFilters
Expand Down