This is a fun, small nbdkit Python plugin using the Boto3 AWS SDK:
#!/usr/sbin/nbdkit python import nbdkit import boto3 from contextlib import closing API_VERSION = 2 def thread_model(): return nbdkit.THREAD_MODEL_PARALLEL def config(key, value): global access_key, secret_key, endpoint_url, bucket_name, key_name if key == "access-key" or key == "access_key": access_key = value elif key == "secret-key" or key == "secret_key": secret_key = value elif key == "endpoint-url" or key == "endpoint_url": endpoint_url = value elif key == "bucket": bucket_name = value elif key == "key": key_name = value else: raise Exception("unknown parameter %s" % key) def open(readonly): global access_key, secret_key, endpoint_url s3 = boto3.client("s3", aws_access_key_id = access_key, aws_secret_access_key = secret_key, endpoint_url = endpoint_url) if s3 is None: raise Exception("could not connect to S3") return s3 def get_size(s3): global bucket_name, key_name resp = s3.get_object(Bucket = bucket_name, Key = key_name) size = resp['ResponseMetadata']['HTTPHeaders']['content-length'] return int(size) def pread(s3, buf, offset, flags): global bucket_name, key_name size = len(buf) rnge = 'bytes=%d-%d' % (offset, offset+size-1) resp = s3.get_object(Bucket = bucket_name, Key = key_name, Range = rnge) body = resp['Body'] with closing(body): buf[:] = body.read(size)
This lets you loop mount a single object (file):
$ ./nbdkit-S3-plugin -f -v -U /tmp/sock \
access_key="XYZ" secret_key="XYZ" \
bucket="my_files" key="fedora-28.iso"
$ sudo nbd-client -b 2048 -unix /tmp/sock /dev/nbd0
Negotiation: ..size = 583MB
$ ls /dev/nbd0
nbd0 nbd0p1 nbd0p2
$ sudo mount -o ro /dev/nbd0p1 /tmp/mnt
$ ls -l /tmp/mnt
total 11
dr-xr-xr-x. 3 root root 2048 Apr 25 2018 EFI
-rw-r--r--. 1 root root 2532 Apr 23 2018 Fedora-Legal-README.txt
dr-xr-xr-x. 3 root root 2048 Apr 25 2018 images
drwxrwxr-x. 2 root root 2048 Apr 25 2018 isolinux
-rw-r--r--. 1 root root 1063 Apr 21 2018 LICENSE
-r--r--r--. 1 root root 454 Apr 25 2018 TRANS.TBL
I should note this is a bit different from s3fs which is a FUSE driver that mounts all the files in a bucket.