DEV Community

Cover image for Bypass AWS_ENDPOINT to interact with any S3 compatible service from CockroachDB
Fabio Ghirardello for Cockroach Labs

Posted on

Bypass AWS_ENDPOINT to interact with any S3 compatible service from CockroachDB

In this blog I will demonstrate how you can trick an application or service, in our case CockroachDB, into thinking it's communicating with AWS S3 when in fact another service lays behind the scenes.

CockroachDB is perfectly capable to interact with any S3 compatible services. Following the instructions of the AWS SDK, you can add parameter AWS_ENDPOINT to your URI to tell CockroachDB what server to hit instead of the default AWS servers. This is clearly documented here.

However, this blog comes as a follow up from a customer interaction where their requirement was to NOT use AWS_ENDPOINT in their URI, yet still using their own private S3 compatible service.

Setup

Create a t2.micro or similar instance on your favorite cloud provider.
For this exercise, the instance has the below details:

OS         : Ubuntu 20.04 LTS
Public IP  : 54.83.105.95
Private IP : 10.10.81.189
Enter fullscreen mode Exit fullscreen mode

Install and Configure MinIO

MinIO is a S3 compatible service and it is my favorite choice for when I want to play locally with the S3 API. We will therefore use the MinIO Server as our custom endpoint instead of AWS S3.

Below the steps to run MinIO, also available in the official docs.

# download the binary
wget https://dl.min.io/server/minio/release/linux-amd64/minio
chmod +x minio
./minio server data
Enter fullscreen mode Exit fullscreen mode

At this point MinIO is running in insecure mode.
It will also have created the configuration folders at ${HOME}/.minio/certs.
Stop the server with Ctrl+C, then configure secure access with TLS.

# allow minio to start on port 443
sudo setcap cap_net_bind_service=+ep minio

# create the private key
cd .minio/certs
openssl genrsa -out private.key 2048
chmod 400 private.key
Enter fullscreen mode Exit fullscreen mode

Create a file named openssl.conf with the content below. Check the alt_names section carefully: in this context, fabio is the name of the s3 bucket.

[req]
distinguished_name = req_distinguished_name
x509_extensions = v3_req
prompt = no

[req_distinguished_name]
C = US
ST = VA
L = Somewhere
O = MyOrg
OU = MyOU
CN = MyServerName

[v3_req]
subjectAltName = @alt_names

[alt_names]
IP.1 = 127.0.0.1
IP.2 = 54.83.105.95
IP.3 = 10.10.81.189
DNS.1 = localhost
DNS.2 = s3.amazonaws.com
DNS.3 = fabio.s3.amazonaws.com
Enter fullscreen mode Exit fullscreen mode

Create the public cert

openssl req -new -x509 -nodes -days 730 -key private.key -out public.crt -config openssl.conf
Enter fullscreen mode Exit fullscreen mode

Setup MinIO Server to use Virtual Hosted-Style, as per here.
This is required to match AWS S3 style.

export MINIO_DOMAIN=s3.amazonaws.com
Enter fullscreen mode Exit fullscreen mode

Finally, start the MinIO Server

$ ~/minio server --console-address ":9001" --address ":443" ~/data

API: https://10.10.82.1  https://127.0.0.1     
RootUser: minioadmin 
RootPass: minioadmin 

Console: https://10.10.82.1:9001 https://127.0.0.1:9001   
RootUser: minioadmin 
RootPass: minioadmin 

Command-line: https://docs.min.io/docs/minio-client-quickstart-guide
   $ mc alias set myminio https://10.10.82.1 minioadmin minioadmin

Documentation: https://docs.min.io
WARNING: Detected default credentials 'minioadmin:minioadmin', we recommend that you change these values with 'MINIO_ROOT_USER' and 'MINIO_ROOT_PASSWORD' environment variables
Enter fullscreen mode Exit fullscreen mode

Point your browser at https://54.83.105.95:9001 to access the MinIO Console. As the self-signed certificate is invalid, the browser might not allow you to continue. In Brave Browser, and other Chrome based browsers, type thisisunsafe anywhere on the screen (not on the address toolbar) to continue and disregard the warning.

Login with minioadmin/minioadmin, which are the default login details. Once logged in, you'll see the Dashboard page, below

minio-dashboard

Using the menu on the left, create a bucket called fabio.

bucket

Then create a User fabio with any password you want. Make sure assign the consoleAdmin, readwrite and diagnostic policies to the user, so you don't run into any permission issue. Later on, you can refine these permissions.

Alt Text

Then, click on the user you just created and create a Service Account, and make sure you save the keys. In my example, the keys are:

Access Key: I6SX7TO71RZY79FXDK1T
Secret Key: 7TxSqDyrvOXCV+EWkRvZKSOXETriFik5LKNWmkQm
Enter fullscreen mode Exit fullscreen mode

Alt Text

Finally, go to Settings and change the region to us-east-1.

Alt Text

This will prompt you to RESTART the server. Do so by stopping the server, and restarting it.

Perfect, you're all set! MinIO Server is up and running in secure mode, and you've a service account to interact with it.

Next, we configure the OS.

Linux OS configuration

For CockroachDB to trust the certificate, we must add it to the system cert pool. We also need to redirect the traffic aimed at AWS servers to MinIO's.

Allow self-signed certs

In Ubuntu, this is how you go about, as per here

sudo mkdir /usr/local/share/ca-certificates/extra
sudo cp ~/.minio/certs/public.crt /usr/local/share/ca-certificates/extra/
sudo update-ca-certificates
Enter fullscreen mode Exit fullscreen mode

Routing

Edit file /etc/hosts and add these entries to route all traffic directed to Amazon AWS servers to the MinIO Server instead.
Again, fabio is the name of the bucket.

54.83.105.95 s3.amazonaws.com
54.83.105.95 s3.us-east-1.amazonaws.com
54.83.105.95 fabio.s3.amazonaws.com 
Enter fullscreen mode Exit fullscreen mode

Good, we're all set from OS point of view. Next, we test with CockroachDB.

CockroachDB

Install and start CockroachDB. We will use the single-node feature as we're only trying to prove it works from a functionality perspective.

As always, the offical installation docs are here.

curl https://binaries.cockroachdb.com/cockroach-v21.1.10.linux-amd64.tgz | tar -xz && sudo cp -i cockroach-v21.1.10.linux-amd64/cockroach /usr/local/bin/
cockroach start-single-node --insecure --background
Enter fullscreen mode Exit fullscreen mode

Connect to the SQL prompt as root:

cockroach sql --insecure
Enter fullscreen mode Exit fullscreen mode

Create a user - doesn't have to be an admin -, then logout and log back in as that user

CREATE USER fabio WITH CREATEDB;
Enter fullscreen mode Exit fullscreen mode
cockroach sql --insecure -u fabio
Enter fullscreen mode Exit fullscreen mode

As user fabio, create a simple test table and export it. Make sure you update the keys with your values!

CREATE DATABASE fabio;
USE fabio;

CREATE TABLE test AS 
  SELECT a 
  FROM generate_series(1,100) AS a;

-- notice that we don't use AWS_ENDPOINT in the URI
EXPORT INTO CSV     
  's3://fabio?AWS_ACCESS_KEY_ID=I6SX7TO71RZY79FXDK1T&AWS_SECRET_ACCESS_KEY=7TxSqDyrvOXCV+EWkRvZKSOXETriFik5LKNWmkQm'
  FROM TABLE test;
Enter fullscreen mode Exit fullscreen mode
                              filename                             | rows | bytes
-------------------------------------------------------------------+------+--------
  export16ad4c7f75f4fe180000000000000001-n701156393427501057.0.csv |  100 |   292
(1 row)

Time: 38ms total (execution 38ms / network 0ms)
Enter fullscreen mode Exit fullscreen mode

As root, take a full cluster backup

BACKUP INTO
  's3://fabio?AWS_ACCESS_KEY_ID=I6SX7TO71RZY79FXDK1T&AWS_SECRET_ACCESS_KEY=7TxSqDyrvOXCV+EWkRvZKSOXETriFik5LKNWmkQm';
Enter fullscreen mode Exit fullscreen mode
        job_id       |  status   | fraction_completed | rows | index_entries | bytes
---------------------+-----------+--------------------+------+---------------+--------
  701160820164395009 | succeeded |                  1 |  126 |            14 |  5920
(1 row)
Enter fullscreen mode Exit fullscreen mode

Refresh the MinIO Console to see your files

Alt Text

Awesome! The CockroachDB end-user has no clue that the engine behind the scenes is MinIO instead of AWS, and CockroachDB is happy to IMPORT, EXPORT, BACKUP and RESTORE from S3, be it AWS' or Minio's.

Reference

Top comments (0)