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

Fix issue with host header and canonicalURI #9

Merged
merged 2 commits into from
Feb 8, 2024
Merged

Conversation

jhiemstrawisc
Copy link
Member

@jhiemstrawisc jhiemstrawisc commented Feb 7, 2024

There were actually two issues that broke authenticated buckets. The first was that we weren't properly setting the host header. The second was that we weren't generating a valid canonical URI that gets signed and sent as a part of the Authorization header. The solution to both of these was to parse the hostUrl more carefully, and in only one spot.

Testing this is a bit of a challenging setup, so I'll try to loosely sketch this out here. This is from my notes, and it assumes you're running in a linux container as root. The container will need all the tools for building c++, as well as xrootd and the minio server binary. You'll also need a non-root user to run the xrootd process under. I'm also assuming you have some experience dealing with XRootD and all its funkiness.

Download & install minio server

Then, from terminal:
export MINIO_ROOT_USER="admin"
export MINIO_ROOT_PASSWORD="password"

The plugin operates under "virtual hosted" requests instead of amazon's old "path style" requests. To get minio working in this setup, you need to export the env var:
export MINIO_DOMAIN=`hostname`

And you also need to add this line to bottom of /etc/hosts:
172.17.0.XXXX      <bucket name>.<hostname>
where the '172.17.0.XXX' ip address should match the other IPs you see there, and where <bucket name> is the name of a
bucket you plan to create or have already created. I usually use 'test-bucket'

Next, launch the server to the path you want to export:
MINIO_ROOT_USER=$MINIO_ROOT_USER MINIO_ROOT_PASSWORD=$MINIO_ROOT_PASSWORD minio server `pwd`/test --console-address ":9001"

Now log into the server via browser to config test buckets: http://localhost:9001
user = admin
password = password

Then create a bucket (I usually call it test-bucket, explained above) and add a test file. Set the bucket to "private". Create
a user with "readwrite" permissions and configure an access/secret key for the user. Keep track of them, and write them
to `/etc/xrootd/access.key` and `/etc/xrootd/secret.key`

After building the plugin, you can test by using this xrootd config:

all.export  /
xrd.protocol http:8080 libXrdHttp.so

# Setting up S3 plugin
ofs.osslib <path to libXrdS3.so>
xrootd.async off

s3.service_name     s3.amazonaws.com
s3.region           us-east-1
# Next is whatever url your minio server gives you as its s3 endpoint, usually like below
s3.service_url      http://<hostname>:9000

# These should point to wherever you actually wrote the keys to
s3.access_key_file  /etc/xrootd/access.key
s3.secret_key_file  /etc/xrootd/secret.key

ofs.trace all
xrd.trace all -sched
http.trace all

Run the plugin under your non-root user: xrootd -c <configfile name>. You should get through all of the xrootd initialization.

Phew, you made it through all that! Give yourself a pat on the shoulder and do a quick stretch.

Finally, you should be able to get the test file from your s3 endpoint via your browser at:
http://localhost:1094/s3.amazonaws.com/us-east-1/<bucket name>/<object name>

Closes #7

There were actually two issues that broke authenticated buckets. The first
was that we weren't properly setting the host header. The second was that
we weren't generating a valid canonical URI that gets signed and sent as
a part of the Authorization header. The solution to both of these was to
parse the hostUrl more carefully, and in only one spot.
Copy link
Collaborator

@turetske turetske left a comment

Choose a reason for hiding this comment

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

Looks good except for wanting an added comment at the top of the function. Mostly to slowly update the documentation for this code as changes happen.

src/S3Commands.cc Show resolved Hide resolved
@jhiemstrawisc jhiemstrawisc merged commit 66430cb into main Feb 8, 2024
1 check passed
Copy link
Contributor

Choose a reason for hiding this comment

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

[lint] reported by reviewdog 🐶

Suggested change
// Takes in the configured `s3.service_url` and uses the bucket/object requested
// to generate the virtual host URL, as well as the canonical URI (which is the
// path to the object).
bool AmazonRequest::parseURL(const std::string &url, const std::string &bucket,
const std::string &object, std::string &host,
std::string &path) {
auto i = url.find("://");
if (i == std::string::npos) {
return false;
}
// protocol = substring( url, 0, i );
auto j = url.find("/", i + 3);
if (j == std::string::npos) {
host = bucket + "." + substring(url, i + 3);
path = "/" + object;

@@ -34,7 +34,11 @@ std::string AmazonRequest::canonicalizeQueryString() {
return AWSv4Impl::canonicalizeQueryString( query_parameters );
Copy link
Contributor

Choose a reason for hiding this comment

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

[lint] reported by reviewdog 🐶

Suggested change
return AWSv4Impl::canonicalizeQueryString( query_parameters );
return AWSv4Impl::canonicalizeQueryString(query_parameters);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Malformed Host header when configured with access/secret keys
2 participants