Skip to content

Commit

Permalink
Add param to forward headers from the auth server to the origin
Browse files Browse the repository at this point in the history
  • Loading branch information
Ftywan committed Dec 21, 2022
1 parent ac0c764 commit aebcb08
Show file tree
Hide file tree
Showing 5 changed files with 109 additions and 0 deletions.
4 changes: 4 additions & 0 deletions plugins/authproxy/Makefile.inc
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,7 @@ authproxy_authproxy_la_SOURCES = \
authproxy/authproxy.cc \
authproxy/utils.cc \
authproxy/utils.h

check_PROGRAMS += authproxy/authproxy_test
authproxy_authproxy_test_CPPFLAGS = $(AM_CPPFLAGS) -I$(abs_top_srcdir)/tests/include
authproxy_authproxy_test_SOURCES = authproxy/tests/authproxy_test.cc
39 changes: 39 additions & 0 deletions plugins/authproxy/authproxy.cc
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
#include <ts/remap.h>

using std::strlen;
using std::string_view;

struct AuthRequestContext;

Expand All @@ -55,10 +56,12 @@ static TSCont AuthOsDnsContinuation;

struct AuthOptions {
std::string hostname;
std::string forward_header_prefix;
int hostport = -1;
AuthRequestTransform transform = nullptr;
bool force = false;
bool cache_internal_requests = false;
std::string_view forwardHeaderPrefix;

AuthOptions() = default;
~AuthOptions() = default;
Expand Down Expand Up @@ -622,6 +625,38 @@ StateAuthorized(AuthRequestContext *auth, void *)
TSHttpTxnConfigIntSet(auth->txn, TS_CONFIG_HTTP_CACHE_IGNORE_AUTHENTICATION, 1);
}

if (!options->forward_header_prefix.empty()) {
// Copy headers with configured prefix in the authentication response to the original request
TSMLoc field_loc;
TSMLoc next_field_loc;
TSMBuffer request_bufp;
TSMLoc request_hdr;

TSReleaseAssert(TSHttpTxnClientReqGet(auth->txn, &request_bufp, &request_hdr) == TS_SUCCESS);
field_loc = TSMimeHdrFieldGet(auth->rheader.buffer, auth->rheader.header, 0);
TSReleaseAssert(field_loc != TS_NULL_MLOC);

while (field_loc) {
int key_len = 0;
int val_len = 0;

char *key = const_cast<char *>(TSMimeHdrFieldNameGet(auth->rheader.buffer, auth->rheader.header, field_loc, &key_len));
char *val =
const_cast<char *>(TSMimeHdrFieldValueStringGet(auth->rheader.buffer, auth->rheader.header, field_loc, -1, &val_len));

if (key && val && ContainsPrefix(string_view(key, key_len), options->forward_header_prefix)) {
// Append the matched header key/val to the original request
HttpSetMimeHeader(request_bufp, request_hdr, string_view(key, key_len), string_view(val, val_len));
}

// Validate the next header field
next_field_loc = TSMimeHdrFieldNext(auth->rheader.buffer, auth->rheader.header, field_loc);
TSHandleMLocRelease(auth->rheader.buffer, auth->rheader.header, field_loc);
field_loc = next_field_loc;
}
}

// Proceed with the modified request
TSHttpTxnReenable(auth->txn, TS_EVENT_HTTP_CONTINUE);
return TS_EVENT_CONTINUE;
}
Expand Down Expand Up @@ -693,6 +728,7 @@ AuthParseOptions(int argc, const char **argv)
{const_cast<char *>("auth-transform"), required_argument, nullptr, 't'},
{const_cast<char *>("force-cacheability"), no_argument, nullptr, 'c'},
{const_cast<char *>("cache-internal"), no_argument, nullptr, 'i'},
{const_cast<char *>("forward-header-prefix"), required_argument, nullptr, 'f'},
{nullptr, 0, nullptr, 0},
};

Expand All @@ -717,6 +753,9 @@ AuthParseOptions(int argc, const char **argv)
case 'i':
options->cache_internal_requests = true;
break;
case 'f':
options->forward_header_prefix = optarg;
break;
case 't':
if (strcasecmp(optarg, "redirect") == 0) {
options->transform = AuthWriteRedirectedRequest;
Expand Down
39 changes: 39 additions & 0 deletions plugins/authproxy/tests/authproxy_test.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include <string_view>
#define CATCH_CONFIG_MAIN /* include main function */
#include <catch.hpp> /* catch unit-test framework */
#include "../utils.h"

using std::string_view;
TEST_CASE("Util methods", "[authproxy][utility]")
{
SECTION("ContainsPrefix()")
{
CHECK(ContainsPrefix(string_view{"abcdef"}, "abc") == true);
CHECK(ContainsPrefix(string_view{"abc"}, "abcdef") == false);
CHECK(ContainsPrefix(string_view{"abcdef"}, "abd") == false);
CHECK(ContainsPrefix(string_view{"abc"}, "abc") == true);
CHECK(ContainsPrefix(string_view{""}, "") == true);
CHECK(ContainsPrefix(string_view{"abc"}, "") == true);
CHECK(ContainsPrefix(string_view{""}, "abc") == false);
CHECK(ContainsPrefix(string_view{"abcdef"}, "abc\0") == true);
CHECK(ContainsPrefix(string_view{"abcdef\0"}, "abc\0") == true);
}
}
18 changes: 18 additions & 0 deletions plugins/authproxy/utils.cc
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include <getopt.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string_view>

void
HttpDebugHeader(TSMBuffer mbuf, TSMLoc mhdr)
Expand Down Expand Up @@ -81,6 +82,23 @@ HttpSetMimeHeader(TSMBuffer mbuf, TSMLoc mhdr, const char *name, const char *val
TSHandleMLocRelease(mbuf, mhdr, mloc);
}

void
HttpSetMimeHeader(TSMBuffer mbuf, TSMLoc mhdr, const std::string_view name, const std::string_view value)
{
TSMLoc mloc;
mloc = TSMimeHdrFieldFind(mbuf, mhdr, name.data(), name.size());
if (mloc == TS_NULL_MLOC) {
TSReleaseAssert(TSMimeHdrFieldCreateNamed(mbuf, mhdr, name.data(), name.size(), &mloc) == TS_SUCCESS);
} else {
TSReleaseAssert(TSMimeHdrFieldValuesClear(mbuf, mhdr, mloc) == TS_SUCCESS);
}

TSReleaseAssert(TSMimeHdrFieldValueStringInsert(mbuf, mhdr, mloc, 0 /* index */, value.data(), value.size()) == TS_SUCCESS);
TSReleaseAssert(TSMimeHdrFieldAppend(mbuf, mhdr, mloc) == TS_SUCCESS);

TSHandleMLocRelease(mbuf, mhdr, mloc);
}

unsigned
HttpGetContentLength(TSMBuffer mbuf, TSMLoc mhdr)
{
Expand Down
9 changes: 9 additions & 0 deletions plugins/authproxy/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@

#pragma once

#include <string>
#include <string_view>
#include <ts/ts.h>
#include <netinet/in.h>
#include <memory>
Expand Down Expand Up @@ -102,8 +104,15 @@ unsigned HttpGetContentLength(TSMBuffer mbuf, TSMLoc mhdr);
// Set the value of an arbitrary HTTP header.
void HttpSetMimeHeader(TSMBuffer mbuf, TSMLoc mhdr, const char *name, const char *value);
void HttpSetMimeHeader(TSMBuffer mbuf, TSMLoc mhdr, const char *name, unsigned value);
void HttpSetMimeHeader(TSMBuffer mbuf, TSMLoc mhdr, const std::string_view name, const std::string_view value);

// Dump the given HTTP header to the debug log.
void HttpDebugHeader(TSMBuffer mbuf, TSMLoc mhdr);

// Check if the string contains the prefix
inline bool
ContainsPrefix(const std::string_view str, const std::string &prefix)
{
return str.size() < prefix.size() ? false : (strncmp(str.data(), prefix.data(), prefix.size()) == 0);
}
// vim: set ts=4 sw=4 et :

0 comments on commit aebcb08

Please sign in to comment.