Compare commits
10 Commits
scylla-4.4
...
next-4.4
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c37f5938fd | ||
|
|
fa90112787 | ||
|
|
f5895e5c04 | ||
|
|
ce944911f2 | ||
|
|
b220130e4a | ||
|
|
de4f5b3b1f | ||
|
|
84a42570ec | ||
|
|
001f57ec0c | ||
|
|
3279718d52 | ||
|
|
c128994f90 |
@@ -1,7 +1,7 @@
|
||||
#!/bin/sh
|
||||
|
||||
PRODUCT=scylla
|
||||
VERSION=4.4.8
|
||||
VERSION=4.4.9
|
||||
|
||||
if test -f version
|
||||
then
|
||||
|
||||
@@ -93,6 +93,10 @@ public:
|
||||
[&] (const json::json_return_type& json_return_value) {
|
||||
slogger.trace("api_handler success case");
|
||||
if (json_return_value._body_writer) {
|
||||
// Unfortunately, write_body() forces us to choose
|
||||
// from a fixed and irrelevant list of "mime-types"
|
||||
// at this point. But we'll override it with the
|
||||
// one (application/x-amz-json-1.0) below.
|
||||
rep->write_body("json", std::move(json_return_value._body_writer));
|
||||
} else {
|
||||
rep->_content += json_return_value._res;
|
||||
@@ -105,14 +109,15 @@ public:
|
||||
|
||||
return make_ready_future<std::unique_ptr<reply>>(std::move(rep));
|
||||
});
|
||||
}), _type("json") { }
|
||||
}) { }
|
||||
|
||||
api_handler(const api_handler&) = default;
|
||||
future<std::unique_ptr<reply>> handle(const sstring& path,
|
||||
std::unique_ptr<request> req, std::unique_ptr<reply> rep) override {
|
||||
return _f_handle(std::move(req), std::move(rep)).then(
|
||||
[this](std::unique_ptr<reply> rep) {
|
||||
rep->done(_type);
|
||||
rep->set_mime_type("application/x-amz-json-1.0");
|
||||
rep->done();
|
||||
return make_ready_future<std::unique_ptr<reply>>(std::move(rep));
|
||||
});
|
||||
}
|
||||
@@ -126,7 +131,6 @@ protected:
|
||||
}
|
||||
|
||||
future_handler_function _f_handle;
|
||||
sstring _type;
|
||||
};
|
||||
|
||||
class gated_handler : public handler_base {
|
||||
@@ -192,24 +196,31 @@ future<> server::verify_signature(const request& req) {
|
||||
throw api_error::missing_authentication_token("Authorization header is mandatory for signature verification");
|
||||
}
|
||||
std::string host = host_it->second;
|
||||
std::vector<std::string_view> credentials_raw = split(authorization_it->second, ' ');
|
||||
std::string_view authorization_header = authorization_it->second;
|
||||
auto pos = authorization_header.find_first_of(' ');
|
||||
if (pos == std::string_view::npos || authorization_header.substr(0, pos) != "AWS4-HMAC-SHA256") {
|
||||
throw api_error::invalid_signature(format("Authorization header must use AWS4-HMAC-SHA256 algorithm: {}", authorization_header));
|
||||
}
|
||||
authorization_header.remove_prefix(pos+1);
|
||||
std::string credential;
|
||||
std::string user_signature;
|
||||
std::string signed_headers_str;
|
||||
std::vector<std::string_view> signed_headers;
|
||||
for (std::string_view entry : credentials_raw) {
|
||||
do {
|
||||
// Either one of a comma or space can mark the end of an entry
|
||||
pos = authorization_header.find_first_of(" ,");
|
||||
std::string_view entry = authorization_header.substr(0, pos);
|
||||
if (pos != std::string_view::npos) {
|
||||
authorization_header.remove_prefix(pos + 1);
|
||||
}
|
||||
if (entry.empty()) {
|
||||
continue;
|
||||
}
|
||||
std::vector<std::string_view> entry_split = split(entry, '=');
|
||||
if (entry_split.size() != 2) {
|
||||
if (entry != "AWS4-HMAC-SHA256") {
|
||||
throw api_error::invalid_signature(format("Only AWS4-HMAC-SHA256 algorithm is supported. Found: {}", entry));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
std::string_view auth_value = entry_split[1];
|
||||
// Commas appear as an additional (quite redundant) delimiter
|
||||
if (auth_value.back() == ',') {
|
||||
auth_value.remove_suffix(1);
|
||||
}
|
||||
if (entry_split[0] == "Credential") {
|
||||
credential = std::string(auth_value);
|
||||
} else if (entry_split[0] == "Signature") {
|
||||
@@ -219,7 +230,8 @@ future<> server::verify_signature(const request& req) {
|
||||
signed_headers = split(auth_value, ';');
|
||||
std::sort(signed_headers.begin(), signed_headers.end());
|
||||
}
|
||||
}
|
||||
} while (pos != std::string_view::npos);
|
||||
|
||||
std::vector<std::string_view> credential_split = split(credential, '/');
|
||||
if (credential_split.size() != 5) {
|
||||
throw api_error::validation(format("Incorrect credential information format: {}", credential));
|
||||
|
||||
21
dist/common/scripts/scylla_raid_setup
vendored
21
dist/common/scripts/scylla_raid_setup
vendored
@@ -30,6 +30,8 @@ import distro
|
||||
from pathlib import Path
|
||||
from scylla_util import *
|
||||
from subprocess import run
|
||||
import distro
|
||||
from pkg_resources import parse_version
|
||||
|
||||
if __name__ == '__main__':
|
||||
if os.getuid() > 0:
|
||||
@@ -115,6 +117,25 @@ if __name__ == '__main__':
|
||||
pkg_install('xfsprogs')
|
||||
if not shutil.which('mdadm'):
|
||||
pkg_install('mdadm')
|
||||
# XXX: Workaround for mdmonitor.service issue on CentOS8
|
||||
if is_redhat_variant() and distro.version() == '8':
|
||||
mdadm_rpm = run('rpm -q mdadm', shell=True, check=True, capture_output=True, encoding='utf-8').stdout.strip()
|
||||
match = re.match(r'^mdadm-([0-9]+\.[0-9]+-[a-zA-Z0-9]+)\.', mdadm_rpm)
|
||||
mdadm_version = match.group(1)
|
||||
if parse_version('4.1-14') < parse_version(mdadm_version):
|
||||
repo_data = '''
|
||||
[BaseOS_8_3_2011]
|
||||
name=CentOS8.3.2011 - Base
|
||||
baseurl=http://vault.centos.org/8.3.2011/BaseOS/$basearch/os/
|
||||
gpgcheck=1
|
||||
enabled=0
|
||||
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial
|
||||
'''[1:-1]
|
||||
with open('/etc/yum.repos.d/CentOS-Vault-8.3.repo', 'w') as f:
|
||||
f.write(repo_data)
|
||||
run('dnf downgrade --enablerepo=BaseOS_8_3_2011 -y mdadm', shell=True, check=True)
|
||||
run('dnf install -y python3-dnf-plugin-versionlock', shell=True, check=True)
|
||||
run('dnf versionlock add mdadm', shell=True, check=True)
|
||||
try:
|
||||
md_service = systemd_unit('mdmonitor.service')
|
||||
except SystemdException:
|
||||
|
||||
2
dist/docker/redhat/Dockerfile
vendored
2
dist/docker/redhat/Dockerfile
vendored
@@ -6,7 +6,7 @@ ENV container docker
|
||||
|
||||
# The SCYLLA_REPO_URL argument specifies the URL to the RPM repository this Docker image uses to install Scylla. The default value is the Scylla's unstable RPM repository, which contains the daily build.
|
||||
ARG SCYLLA_REPO_URL=http://downloads.scylladb.com/rpm/unstable/centos/branch-4.4/latest/scylla.repo
|
||||
ARG VERSION=4.4.8
|
||||
ARG VERSION=4.4.9
|
||||
|
||||
ADD scylla_bashrc /scylla_bashrc
|
||||
|
||||
|
||||
5
dist/docker/redhat/scyllasetup.py
vendored
5
dist/docker/redhat/scyllasetup.py
vendored
@@ -121,12 +121,13 @@ class ScyllaSetup:
|
||||
if self._apiAddress is not None:
|
||||
args += ["--api-address %s" % self._apiAddress]
|
||||
|
||||
if self._alternatorPort is not None:
|
||||
if self._alternatorAddress is not None:
|
||||
args += ["--alternator-address %s" % self._alternatorAddress]
|
||||
|
||||
if self._alternatorPort is not None:
|
||||
args += ["--alternator-port %s" % self._alternatorPort]
|
||||
|
||||
if self._alternatorHttpsPort is not None:
|
||||
args += ["--alternator-address %s" % self._alternatorAddress]
|
||||
args += ["--alternator-https-port %s" % self._alternatorHttpsPort]
|
||||
|
||||
if self._alternatorWriteIsolation is not None:
|
||||
|
||||
@@ -57,6 +57,8 @@ future<> feed_writer(flat_mutation_reader&& rd, Writer&& wr) {
|
||||
auto f2 = rd.is_buffer_empty() ? rd.fill_buffer(db::no_timeout) : make_ready_future<>();
|
||||
return when_all_succeed(std::move(f1), std::move(f2)).discard_result();
|
||||
});
|
||||
}).then([&wr] {
|
||||
wr.consume_end_of_stream();
|
||||
}).then_wrapped([&wr] (future<> f) {
|
||||
if (f.failed()) {
|
||||
auto ex = f.get_exception();
|
||||
@@ -70,7 +72,6 @@ future<> feed_writer(flat_mutation_reader&& rd, Writer&& wr) {
|
||||
return make_exception_future<>(std::move(ex));
|
||||
});
|
||||
} else {
|
||||
wr.consume_end_of_stream();
|
||||
return wr.close();
|
||||
}
|
||||
});
|
||||
|
||||
2
seastar
2
seastar
Submodule seastar updated: 59eeadc720...1fb2187322
@@ -85,3 +85,20 @@ def test_signature_too_futuristic(dynamodb, test_table):
|
||||
response = requests.post(url, headers=headers, verify=False)
|
||||
assert not response.ok
|
||||
assert "InvalidSignatureException" in response.text and "Signature not yet current" in response.text
|
||||
|
||||
# A test that commas can be uses instead of whitespace to separate components
|
||||
# of the Authorization headers - reproducing issue #9568.
|
||||
def test_authorization_no_whitespace(dynamodb, test_table):
|
||||
# Unlike the above tests which checked error cases so didn't need to
|
||||
# calculate a real signature, in this test we really a correct signature,
|
||||
# so we use a function we already have in test_manual_requests.py.
|
||||
from test_manual_requests import get_signed_request
|
||||
payload = '{"TableName": "' + test_table.name + '", "Item": {"p": {"S": "x"}, "c": {"S": "x"}}}'
|
||||
req = get_signed_request(dynamodb, 'PutItem', payload)
|
||||
# Boto3 separates the components of the Authorization header by spaces.
|
||||
# Let's remove all of them except the first one (which separates the
|
||||
# signature algorithm name from the rest) and check the result still works:
|
||||
a = req.headers['Authorization'].split()
|
||||
req.headers['Authorization'] = a[0] + ' ' + ''.join(a[1:])
|
||||
response = requests.post(req.url, headers=req.headers, data=req.body, verify=False)
|
||||
assert response.ok
|
||||
|
||||
@@ -154,3 +154,25 @@ def test_incorrect_numbers(dynamodb, test_table):
|
||||
req = get_signed_request(dynamodb, 'PutItem', payload)
|
||||
response = requests.post(req.url, headers=req.headers, data=req.body, verify=False)
|
||||
assert "ValidationException" in response.text and "numeric" in response.text
|
||||
|
||||
# Although the DynamoDB API responses are JSON, additional conventions apply
|
||||
# to these responses - such as how error codes are encoded in JSON. For this
|
||||
# reason, DynamoDB uses the content type 'application/x-amz-json-1.0' instead
|
||||
# of the standard 'application/json'. This test verifies that we return the
|
||||
# correct content type header.
|
||||
# While most DynamoDB libraries we tried do not care about an unexpected
|
||||
# content-type, it turns out that one (aiodynamo) does. Moreover, AWS already
|
||||
# defined x-amz-json-1.1 - see
|
||||
# https://awslabs.github.io/smithy/1.0/spec/aws/aws-json-1_1-protocol.html
|
||||
# which differs (only) in how it encodes error replies.
|
||||
# So in the future it may become even more important that Scylla return the
|
||||
# correct content type.
|
||||
def test_content_type(dynamodb, test_table):
|
||||
payload = '{"TableName": "' + test_table.name + '", "Item": {"p": {"S": "x"}, "c": {"S": "x"}}}'
|
||||
# Note that get_signed_request() uses x-amz-json-1.0 to encode the
|
||||
# *request*. In the future this may or may not effect the content type
|
||||
# in the response (today, DynamoDB doesn't allow any other content type
|
||||
# in the request anyway).
|
||||
req = get_signed_request(dynamodb, 'PutItem', payload)
|
||||
response = requests.post(req.url, headers=req.headers, data=req.body, verify=False)
|
||||
assert response.headers['Content-Type'] == 'application/x-amz-json-1.0'
|
||||
|
||||
Submodule tools/java updated: 14e635e5de...e8accfbf45
Reference in New Issue
Block a user