storage: S3 client wrapper and admin Basic-auth middleware
S3 module wraps aws-sdk-s3 against MinIO. Two clients on purpose: - The bytes-mover client points at S3_ENDPOINT (internal minio:9000 over the storage Docker network). - The presign-only client points at S3_PUBLIC_ENDPOINT (https://s3.asxp.io via Traefik) so the URLs it mints resolve from a browser. force_path_style on both because subdomain-style URLs would require wildcard DNS under s3.asxp.io. AdminAuth is a tiny Rack middleware that 401s any request under /admin unless HTTP Basic credentials match ADMIN_USER / ADMIN_PASSWORD from env. Fails closed if either env var is missing.
This commit is contained in:
parent
a605ccdc52
commit
0dc31fbafe
2 changed files with 74 additions and 0 deletions
50
lib/s3.rb
Normal file
50
lib/s3.rb
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
require 'aws-sdk-s3'
|
||||
|
||||
module S3
|
||||
module_function
|
||||
|
||||
def client
|
||||
@client ||= Aws::S3::Client.new(
|
||||
region: ENV.fetch('S3_REGION', 'us-east-1'),
|
||||
endpoint: ENV.fetch('S3_ENDPOINT'),
|
||||
access_key_id: ENV.fetch('S3_ACCESS_KEY'),
|
||||
secret_access_key: ENV.fetch('S3_SECRET_KEY'),
|
||||
force_path_style: true
|
||||
)
|
||||
end
|
||||
|
||||
# Separate client whose endpoint is the public hostname; used only to mint
|
||||
# presigned URLs that a browser can dereference. Bytes never travel through
|
||||
# this client.
|
||||
def presign_client
|
||||
@presign_client ||= Aws::S3::Client.new(
|
||||
region: ENV.fetch('S3_REGION', 'us-east-1'),
|
||||
endpoint: ENV.fetch('S3_PUBLIC_ENDPOINT'),
|
||||
access_key_id: ENV.fetch('S3_ACCESS_KEY'),
|
||||
secret_access_key: ENV.fetch('S3_SECRET_KEY'),
|
||||
force_path_style: true
|
||||
)
|
||||
end
|
||||
|
||||
def bucket
|
||||
ENV.fetch('S3_BUCKET')
|
||||
end
|
||||
|
||||
def put(key, bytes, content_type: 'application/pdf')
|
||||
client.put_object(
|
||||
bucket: bucket,
|
||||
key: key,
|
||||
body: bytes,
|
||||
content_type: content_type
|
||||
)
|
||||
key
|
||||
end
|
||||
|
||||
def presigned_url(key, expires_in: 300, filename: nil)
|
||||
params = { bucket: bucket, key: key }
|
||||
if filename
|
||||
params[:response_content_disposition] = %(attachment; filename="#{filename}")
|
||||
end
|
||||
Aws::S3::Presigner.new(client: presign_client).presigned_url(:get_object, **params, expires_in: expires_in)
|
||||
end
|
||||
end
|
||||
Loading…
Add table
Add a link
Reference in a new issue