Commit 2069f5b6 authored by Aaron Dees's avatar Aaron Dees
Browse files

Merge branch 'add_queries_to_authentication' into 'devel'

Add queries to authentication

See merge request oilgas/ltfs/fiphoboserver!31
parents eeee4384 ee649fa4
Pipeline #1406 passed with stages
in 6 minutes and 24 seconds
......@@ -25,6 +25,7 @@ The implementation of this class follows the guidelines from [https://docs.aws.a
| [set_authorisation_info](#fiphoboserver-s3_utilities-S3_authorisation-set_authorisation_info) | get the information about authorisation from the header and save it to member variables |
| [extract_string_part](#fiphoboserver-s3_utilities-S3_authorisation-extract_string_part) | Extract information from a string. |
| [split_signed_headers](#fiphoboserver-s3_utilities-S3_authorisation-split_signed_headers) | split up the "SignedHeaders" value of the HTTP request |
| [split_queries](#fiphoboserver-s3_utilities-S3_authorisation-split_queries) | split up the queries string of the HTTP request (thats the part of the request path after '?') |
| [split_credentials](#fiphoboserver-s3_utilities-S3_authorisation-split_credentials) | split up the "Credential" value of the HTTP request |
......@@ -45,7 +46,8 @@ The implementation of this class follows the guidelines from [https://docs.aws.a
| [m_user_key](#fiphoboserver-s3_utilities-S3_authorisation-m_user_key) | the key that belongs to [m_user_identifier][fiphoboserver-s3_utilities-S3_authorisation-m_user_identifier] |
| [m_date](#fiphoboserver-s3_utilities-S3_authorisation-m_date) | the date as saved in the credentials of the request |
| [m_region](#fiphoboserver-s3_utilities-S3_authorisation-m_region) | the S3 region as saved in the credentials of the request |
| [m_signed_headers](#fiphoboserver-s3_utilities-S3_authorisation-m_signed_headers) | a list of the headers that have been used to sign the request |
| [m_signed_headers](#fiphoboserver-s3_utilities-S3_authorisation-m_signed_headers) | a (sorted) list of the headers that have been used to sign the request |
| [m_queries](#fiphoboserver-s3_utilities-S3_authorisation-m_queries) | a (sorted) list of all queries split up into key and value |
| [m_signature](#fiphoboserver-s3_utilities-S3_authorisation-m_signature) | the signature stored in the request |
| [m_payload](#fiphoboserver-s3_utilities-S3_authorisation-m_payload) | the payload of the request |
......@@ -235,6 +237,33 @@ This function saves the headers into
[Go to Top](#fiphoboserver-s3_utilities-S3_authorisation)
### <a name='fiphoboserver-s3_utilities-S3_authorisation-split_queries' /> private void fiphoboserver::s3_utilities::S3_authorisation::split_queries (std::string queries)
split up the queries string of the HTTP request (thats the part of the request path after '?')
#### Parameters:
| Type | Name | Description |
| ---- | ---- | ---- |
| std::string | queries | the complete query string |
This function saves each query into
[m_queries][fiphoboserver-s3_utilities-S3_authorisation-m_queries]
[Go to Top](#fiphoboserver-s3_utilities-S3_authorisation)
### <a name='fiphoboserver-s3_utilities-S3_authorisation-split_credentials' /> private void fiphoboserver::s3_utilities::S3_authorisation::split_credentials (std::string credentials)
......@@ -497,7 +526,20 @@ the S3 region as saved in the credentials of the request
### <a name='fiphoboserver-s3_utilities-S3_authorisation-m_signed_headers' /> private fiphoboserver::s3_utilities::S3_authorisation::m_signed_headers
a list of the headers that have been used to sign the request
a (sorted) list of the headers that have been used to sign the request
[Go to Top](#fiphoboserver-s3_utilities-S3_authorisation)
### <a name='fiphoboserver-s3_utilities-S3_authorisation-m_queries' /> private fiphoboserver::s3_utilities::S3_authorisation::m_queries
a (sorted) list of all queries split up into key and value
......@@ -634,6 +676,7 @@ checks if the authorisation was successful
[fiphoboserver-s3_utilities-S3_authorisation-create_canonical_request]:./S3_authorisation.md#fiphoboserver-s3_utilities-S3_authorisation-create_canonical_request
[fiphoboserver-s3_utilities-S3_authorisation-create_string_to_sign]:./S3_authorisation.md#fiphoboserver-s3_utilities-S3_authorisation-create_string_to_sign
[fiphoboserver-s3_utilities-S3_authorisation-m_date]:./S3_authorisation.md#fiphoboserver-s3_utilities-S3_authorisation-m_date
[fiphoboserver-s3_utilities-S3_authorisation-m_queries]:./S3_authorisation.md#fiphoboserver-s3_utilities-S3_authorisation-m_queries
[fiphoboserver-s3_utilities-S3_authorisation-m_region]:./S3_authorisation.md#fiphoboserver-s3_utilities-S3_authorisation-m_region
[fiphoboserver-s3_utilities-S3_authorisation-m_signed_headers]:./S3_authorisation.md#fiphoboserver-s3_utilities-S3_authorisation-m_signed_headers
[fiphoboserver-s3_utilities-S3_authorisation-m_user_identifier]:./S3_authorisation.md#fiphoboserver-s3_utilities-S3_authorisation-m_user_identifier
......
......@@ -23,6 +23,7 @@ class to extract the S3 specific information from proxygens HTTPMessage headers
| [get_meta_data](#fiphoboserver-s3_utilities-S3_header-get_meta_data) | gets the S3 metadata stored in the HTTP headers |
| [print_all_headers](#fiphoboserver-s3_utilities-S3_header-print_all_headers) | print all headers to std out |
| [get_header_by_name](#fiphoboserver-s3_utilities-S3_header-get_header_by_name) | extract one header value from the headers |
| [get_queries](#fiphoboserver-s3_utilities-S3_header-get_queries) | extract the query string from the headers |
| [get_method](#fiphoboserver-s3_utilities-S3_header-get_method) | get the HTTP method the header belongs to |
......@@ -297,6 +298,36 @@ extract one header value from the headers
#### Qualifiers:
* const
* inline
[Go to Top](#fiphoboserver-s3_utilities-S3_header)
### <a name='fiphoboserver-s3_utilities-S3_header-get_queries' /> public std::string fiphoboserver::s3_utilities::S3_header::get_queries () const
extract the query string from the headers
#### Returns:
| Type | Description |
| ---- | ---- |
| std::string | the query string of the request or an empty_string if it doesn't have one |
#### Qualifiers:
* const
* inline
......
......@@ -81,6 +81,7 @@ bool S3_authorisation::set_authorisation_info(const S3_header& headers)
}
split_signed_headers(all_signed_headers);
split_queries(headers.get_queries());
split_credentials(credentials);
// print_info();
......@@ -109,10 +110,45 @@ void S3_authorisation::split_signed_headers(std::string all_signed_headers)
{
size_t index = 0;
while (index != all_signed_headers.npos) {
index = all_signed_headers.find(';');
m_signed_headers.push_back(all_signed_headers.substr(0, index));
index = all_signed_headers.find(';');
std::string header_lowercase = all_signed_headers.substr(0, index);
std::transform(
header_lowercase.begin(), header_lowercase.end(),
header_lowercase.begin(), ::tolower);
m_signed_headers.push_back(header_lowercase);
all_signed_headers = all_signed_headers.substr(index + 1);
}
// in all tests this was already sorted, but calling sort here as precaution
// it should be rather fast because this list is not long even if unsorted
std::sort(m_signed_headers.begin(), m_signed_headers.end());
}
void S3_authorisation::split_queries(std::string queries)
{
if (queries.empty()) {
return;
}
size_t index = 0;
while (index != queries.npos) {
index = queries.find('&');
std::string query = queries.substr(0, index);
size_t equality_sign_index = query.find('=');
if (equality_sign_index != query.npos) {
m_queries.push_back(std::make_pair<std::string, std::string>(
query.substr(0, equality_sign_index),
query.substr(equality_sign_index + 1)));
}
else {
m_queries.push_back(
std::make_pair<std::string, std::string>(query.c_str(), ""));
}
queries = queries.substr(index + 1);
}
// in all tests this was already sorted, but calling sort here as precaution
// it should be rather fast because this list is not long even if unsorted
std::sort(m_queries.begin(), m_queries.end());
}
void S3_authorisation::split_credentials(std::string credentials)
......@@ -226,7 +262,14 @@ std::string S3_authorisation::create_canonical_request(
result_stream << headers.get_method() << '\n';
result_stream << '/' << uri_encode(headers.get_key(), false) << '\n';
// TODO insert queries! Issue #46
if (!m_queries.empty()) {
for (size_t i = 0; i < m_queries.size() - 1; ++i) {
result_stream << m_queries[i].first << '=' << m_queries[i].second
<< '&';
}
result_stream << m_queries[m_queries.size() - 1].first << '='
<< m_queries[m_queries.size() - 1].second;
}
result_stream << '\n';
for (auto it = m_signed_headers.begin(); it != m_signed_headers.end();
......
......@@ -129,6 +129,15 @@ class S3_authorisation {
///
void split_signed_headers(std::string all_signed_headers);
///
/// @brief split up the queries string of the HTTP request (thats the part
/// of the request path after '?')
///
/// @param queries the complete query string
///
/// This function saves each query into @ref m_queries
///
void split_queries(std::string queries);
///
/// @brief split up the "Credential" value of the HTTP request
///
/// @param credentials the value of the Credential header
......@@ -206,8 +215,11 @@ class S3_authorisation {
std::string m_date;
/// @brief the S3 region as saved in the credentials of the request
std::string m_region;
/// @brief a list of the headers that have been used to sign the request
/// @brief a (sorted) list of the headers that have been used to sign the
/// request
std::vector<std::string> m_signed_headers;
/// @brief a (sorted) list of all queries split up into key and value
std::vector<std::pair<std::string, std::string>> m_queries;
/// @brief the signature stored in the request
std::string m_signature;
/// @brief the payload of the request
......
......@@ -151,6 +151,9 @@ class S3_header {
{
std::cout << "Printing all headers for " << m_headers->getPath()
<< "\n";
if (!m_headers->getQueryString().empty()) {
std::cout << "Queries: " << m_headers->getQueryString() << '\n';
}
m_headers->getHeaders().forEach(
[&](const std::string& header, const std::string& val) {
std::cout << header << ": " << val << "\n";
......@@ -171,6 +174,14 @@ class S3_header {
return m_headers->getHeaders().getSingleOrEmpty(header_name);
}
///
/// @brief extract the query string from the headers
///
/// @returns the query string of the request or an empty_string if it
/// doesn't have one
///
std::string get_queries() const { return m_headers->getQueryString(); }
///
/// @brief get the HTTP method the header belongs to
///
......
......@@ -263,6 +263,50 @@ SCENARIO("S3 header authorisation", "[authorisation]")
user_of_stream.close();
}
}
GIVEN("A GET bucket request with queries")
{
message->setMethod(proxygen::HTTPMethod::GET);
message->setURL("/");
WHEN("The GET request contains one empty valued query")
{
message->setQueryString("lifecycle");
headers.add(
"x-amz-content-sha256",
"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855");
headers.add(
"Authorization",
"AWS4-HMAC-SHA256 Credential=AKIAIOSFODNN7EXAMPLE/20130524/us-east-1/s3/aws4_request,SignedHeaders=host;x-amz-content-sha256;x-amz-date,Signature=fea454ca298b7da1c68078a5d1bdbfbbe0d65c699e0f91ac7a200a0136783543");
s3_header.set_headers(std::move(message));
THEN("The authorisation is valid")
{
REQUIRE(
auth.authorise(s3_header) == Authorisation_status::valid);
}
}
WHEN("The GET request contains two queries")
{
message->setQueryString("max-keys=2&prefix=J");
headers.add(
"x-amz-content-sha256",
"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855");
headers.add(
"Authorization",
"AWS4-HMAC-SHA256 Credential=AKIAIOSFODNN7EXAMPLE/20130524/us-east-1/s3/aws4_request,SignedHeaders=host;x-amz-content-sha256;x-amz-date,Signature=34b48302e7b5fa45bde8084f4b7868a86f0a534bc59db6670ed5711ef69dc6f7");
s3_header.set_headers(std::move(message));
THEN("The authorisation is valid")
{
REQUIRE(
auth.authorise(s3_header) == Authorisation_status::valid);
}
}
}
GIVEN("a PUT request")
{
message->setMethod(proxygen::HTTPMethod::PUT);
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment