fix AWS S3 startup for production deployments
Docker server image / build-and-push (push) Successful in 1m7s
Docker server image / build-and-push (push) Successful in 1m7s
Pass S3_REGION and S3_PUBLIC_USE_SSL through compose, treat blank public SSL as unset, and skip CreateBucket when IAM only allows access to an existing bucket.
This commit is contained in:
@@ -24,7 +24,9 @@ services:
|
|||||||
S3_ENDPOINT: ${S3_ENDPOINT:-seaweedfs:8333}
|
S3_ENDPOINT: ${S3_ENDPOINT:-seaweedfs:8333}
|
||||||
S3_PUBLIC_ENDPOINT: ${S3_PUBLIC_ENDPOINT:-localhost:8333}
|
S3_PUBLIC_ENDPOINT: ${S3_PUBLIC_ENDPOINT:-localhost:8333}
|
||||||
S3_BUCKET: ${S3_BUCKET:-officeconvert}
|
S3_BUCKET: ${S3_BUCKET:-officeconvert}
|
||||||
|
S3_REGION: ${S3_REGION:-}
|
||||||
S3_USE_SSL: ${S3_USE_SSL:-false}
|
S3_USE_SSL: ${S3_USE_SSL:-false}
|
||||||
|
S3_PUBLIC_USE_SSL: ${S3_PUBLIC_USE_SSL:-}
|
||||||
S3_ACCESS_KEY: ${S3_ACCESS_KEY:-minioadmin}
|
S3_ACCESS_KEY: ${S3_ACCESS_KEY:-minioadmin}
|
||||||
S3_SECRET_KEY: ${S3_SECRET_KEY:-minioadmin}
|
S3_SECRET_KEY: ${S3_SECRET_KEY:-minioadmin}
|
||||||
S3_SESSION_TTL_SECONDS: ${S3_SESSION_TTL_SECONDS:-3600}
|
S3_SESSION_TTL_SECONDS: ${S3_SESSION_TTL_SECONDS:-3600}
|
||||||
|
|||||||
@@ -23,7 +23,9 @@ services:
|
|||||||
S3_ENDPOINT: ${S3_ENDPOINT:-seaweedfs:8333}
|
S3_ENDPOINT: ${S3_ENDPOINT:-seaweedfs:8333}
|
||||||
S3_PUBLIC_ENDPOINT: ${S3_PUBLIC_ENDPOINT:-localhost:8333}
|
S3_PUBLIC_ENDPOINT: ${S3_PUBLIC_ENDPOINT:-localhost:8333}
|
||||||
S3_BUCKET: ${S3_BUCKET:-officeconvert}
|
S3_BUCKET: ${S3_BUCKET:-officeconvert}
|
||||||
|
S3_REGION: ${S3_REGION:-}
|
||||||
S3_USE_SSL: ${S3_USE_SSL:-false}
|
S3_USE_SSL: ${S3_USE_SSL:-false}
|
||||||
|
S3_PUBLIC_USE_SSL: ${S3_PUBLIC_USE_SSL:-}
|
||||||
S3_ACCESS_KEY: ${S3_ACCESS_KEY:-minioadmin}
|
S3_ACCESS_KEY: ${S3_ACCESS_KEY:-minioadmin}
|
||||||
S3_SECRET_KEY: ${S3_SECRET_KEY:-minioadmin}
|
S3_SECRET_KEY: ${S3_SECRET_KEY:-minioadmin}
|
||||||
S3_SESSION_TTL_SECONDS: ${S3_SESSION_TTL_SECONDS:-3600}
|
S3_SESSION_TTL_SECONDS: ${S3_SESSION_TTL_SECONDS:-3600}
|
||||||
|
|||||||
@@ -31,10 +31,10 @@ class ServerConfig:
|
|||||||
def load_server_config() -> ServerConfig:
|
def load_server_config() -> ServerConfig:
|
||||||
"""Load server configuration from environment variables."""
|
"""Load server configuration from environment variables."""
|
||||||
s3_secure = os.getenv("S3_USE_SSL", "false").lower() == "true"
|
s3_secure = os.getenv("S3_USE_SSL", "false").lower() == "true"
|
||||||
public_ssl_env = os.getenv("S3_PUBLIC_USE_SSL")
|
public_ssl_env = os.getenv("S3_PUBLIC_USE_SSL", "").strip()
|
||||||
s3_public_secure = (
|
s3_public_secure = (
|
||||||
public_ssl_env.lower() == "true"
|
public_ssl_env.lower() == "true"
|
||||||
if public_ssl_env is not None
|
if public_ssl_env
|
||||||
else s3_secure
|
else s3_secure
|
||||||
)
|
)
|
||||||
region_env = os.getenv("S3_REGION", "").strip()
|
region_env = os.getenv("S3_REGION", "").strip()
|
||||||
|
|||||||
@@ -86,16 +86,19 @@ class S3Store:
|
|||||||
def ensure_bucket(self, bucket_name: str) -> None:
|
def ensure_bucket(self, bucket_name: str) -> None:
|
||||||
"""Create a bucket if it does not already exist.
|
"""Create a bucket if it does not already exist.
|
||||||
|
|
||||||
Uses CreateBucket only, not HeadBucket. Some S3-compatible stores
|
Tries CreateBucket first (idempotent on SeaweedFS and when the caller
|
||||||
(including SeaweedFS) mishandle or over-restrict HeadBucket; the MinIO
|
owns the bucket). AWS production IAM often grants object access only on
|
||||||
client's bucket_exists() maps non-NoSuchBucket errors to failures.
|
a pre-provisioned bucket; in that case CreateBucket returns
|
||||||
Idempotent create covers the same contract with fewer round trips.
|
AccessDenied even though HeadBucket succeeds.
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
self._client.make_bucket(bucket_name)
|
self._client.make_bucket(bucket_name)
|
||||||
except S3Error as exc:
|
except S3Error as exc:
|
||||||
if exc.code in ("BucketAlreadyOwnedByYou", "BucketAlreadyExists"):
|
if exc.code in ("BucketAlreadyOwnedByYou", "BucketAlreadyExists"):
|
||||||
return
|
return
|
||||||
|
if exc.code in ("AccessDenied", "Forbidden"):
|
||||||
|
if self._client.bucket_exists(bucket_name):
|
||||||
|
return
|
||||||
raise
|
raise
|
||||||
|
|
||||||
def presigned_put_url(self, bucket_name: str, object_key: str, *, ttl_seconds: int) -> str:
|
def presigned_put_url(self, bucket_name: str, object_key: str, *, ttl_seconds: int) -> str:
|
||||||
|
|||||||
Reference in New Issue
Block a user