Skip to content

Commit f515847

Browse files
Move S3 ambient credentials out of AccessConfig (#578)
1 parent 329626a commit f515847

File tree

5 files changed

+36
-33
lines changed

5 files changed

+36
-33
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 1.2.5
2+
3+
**Fix**: move S3 ambient_credentials out of AccessConfig
4+
15
## 1.2.4
26

37
**Fix**: properly handle Together API 5xx errors as ProviderError instead of UserError

test/integration/connectors/test_s3.py

Lines changed: 15 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -295,13 +295,13 @@ class TestS3AmbientCredentials:
295295

296296
def test_ambient_credentials_field_default(self):
297297
"""Test that ambient_credentials defaults to False"""
298-
access_config = S3AccessConfig()
299-
assert access_config.ambient_credentials is False
298+
connection_config = S3ConnectionConfig()
299+
assert connection_config.ambient_credentials is False
300300

301301
def test_ambient_credentials_field_explicit(self):
302302
"""Test setting ambient_credentials explicitly"""
303-
access_config = S3AccessConfig(ambient_credentials=True)
304-
assert access_config.ambient_credentials is True
303+
connection_config = S3ConnectionConfig(ambient_credentials=True)
304+
assert connection_config.ambient_credentials is True
305305

306306
def test_default_blocks_automatic_credentials(self):
307307
"""Test that default behavior blocks automatic credential pickup"""
@@ -341,8 +341,7 @@ def test_ambient_credentials_requires_env_var(self, monkeypatch):
341341
# Clear the environment variable
342342
monkeypatch.delenv("ALLOW_AMBIENT_CREDENTIALS_S3", raising=False)
343343

344-
access_config = S3AccessConfig(ambient_credentials=True)
345-
connection_config = S3ConnectionConfig(access_config=access_config, anonymous=False)
344+
connection_config = S3ConnectionConfig(ambient_credentials=True, anonymous=False)
346345

347346
# Should raise error when env var is not set
348347
with pytest.raises(
@@ -356,8 +355,7 @@ def test_ambient_credentials_enables_ambient_mode(self, monkeypatch):
356355
# Set the environment variable
357356
monkeypatch.setenv("ALLOW_AMBIENT_CREDENTIALS_S3", "true")
358357

359-
access_config = S3AccessConfig(ambient_credentials=True)
360-
connection_config = S3ConnectionConfig(access_config=access_config, anonymous=False)
358+
connection_config = S3ConnectionConfig(ambient_credentials=True, anonymous=False)
361359

362360
config = connection_config.get_access_config()
363361

@@ -373,9 +371,11 @@ def test_ambient_credentials_field_excluded_from_config(self):
373371
access_config = S3AccessConfig(
374372
key="test-key",
375373
secret="test-secret",
376-
ambient_credentials=True, # Should be excluded
377374
)
378-
connection_config = S3ConnectionConfig(access_config=access_config)
375+
connection_config = S3ConnectionConfig(
376+
access_config=access_config,
377+
ambient_credentials=True, # Should be excluded from final config
378+
)
379379

380380
config = connection_config.get_access_config()
381381

@@ -412,8 +412,7 @@ def test_endpoint_url_preserved_with_all_auth_modes(self, monkeypatch):
412412

413413
# Test with ambient credentials
414414
monkeypatch.setenv("ALLOW_AMBIENT_CREDENTIALS_S3", "true")
415-
access_config = S3AccessConfig(ambient_credentials=True)
416-
connection_config = S3ConnectionConfig(access_config=access_config, endpoint_url=endpoint)
415+
connection_config = S3ConnectionConfig(ambient_credentials=True, endpoint_url=endpoint)
417416
config = connection_config.get_access_config()
418417
assert config["endpoint_url"] == endpoint
419418

@@ -424,8 +423,7 @@ def test_endpoint_url_preserved_with_all_auth_modes(self, monkeypatch):
424423

425424
def test_authentication_error_raised(self):
426425
"""Test that authentication error is raised when automatic credentials would be used"""
427-
access_config = S3AccessConfig(ambient_credentials=False)
428-
connection_config = S3ConnectionConfig(access_config=access_config, anonymous=False)
426+
connection_config = S3ConnectionConfig(ambient_credentials=False, anonymous=False)
429427

430428
# This should raise UserAuthError with helpful message
431429
with pytest.raises(UserAuthError) as exc_info:
@@ -440,8 +438,7 @@ def test_ambient_credentials_env_var_variations(self, monkeypatch):
440438
"""Test that only 'true' (case-insensitive) values for ALLOW_AMBIENT_CREDENTIALS_S3 work"""
441439
valid_values = ["true", "TRUE", "True", "tRuE"]
442440

443-
access_config = S3AccessConfig(ambient_credentials=True)
444-
connection_config = S3ConnectionConfig(access_config=access_config, anonymous=False)
441+
connection_config = S3ConnectionConfig(ambient_credentials=True, anonymous=False)
445442

446443
for value in valid_values:
447444
monkeypatch.setenv("ALLOW_AMBIENT_CREDENTIALS_S3", value)
@@ -460,8 +457,7 @@ def test_ambient_credentials_info_logged(self, caplog, monkeypatch):
460457
# Ensure we capture INFO level logs
461458
caplog.set_level(logging.INFO)
462459

463-
access_config = S3AccessConfig(ambient_credentials=True)
464-
connection_config = S3ConnectionConfig(access_config=access_config, anonymous=False)
460+
connection_config = S3ConnectionConfig(ambient_credentials=True, anonymous=False)
465461

466462
# This should trigger the ambient credentials info log
467463
config = connection_config.get_access_config()
@@ -491,7 +487,7 @@ async def test_s3_destination_with_ambient_credentials(self, upload_file: Path,
491487

492488
# Use ambient credentials (no explicit key/secret provided)
493489
connection_config = S3ConnectionConfig(
494-
access_config=S3AccessConfig(ambient_credentials=True),
490+
ambient_credentials=True,
495491
)
496492
upload_config = S3UploaderConfig(remote_url=destination_path)
497493
uploader = S3Uploader(connection_config=connection_config, upload_config=upload_config)

test/integration/embedders/test_togetherai.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ def get_api_key() -> str:
2727
return api_key
2828

2929

30+
# TODO: re-enable these tests when TogetherAI API is fixed
31+
32+
33+
@pytest.mark.skip(reason="TogetherAI API disabled")
3034
@requires_env(API_KEY)
3135
def test_togetherai_embedder(embedder_file: Path):
3236
api_key = get_api_key()
@@ -40,6 +44,7 @@ def test_togetherai_embedder(embedder_file: Path):
4044
validate_embedding_output(original_elements=original_elements, output_elements=results)
4145

4246

47+
@pytest.mark.skip(reason="TogetherAI API disabled")
4348
@requires_env(API_KEY)
4449
def test_raw_togetherai_embedder(embedder_file: Path):
4550
api_key = get_api_key()
@@ -53,13 +58,15 @@ def test_raw_togetherai_embedder(embedder_file: Path):
5358
)
5459

5560

61+
@pytest.mark.skip(reason="TogetherAI API disabled")
5662
def test_raw_togetherai_embedder_invalid_credentials():
5763
embedder = TogetherAIEmbeddingEncoder(config=TogetherAIEmbeddingConfig(api_key="fake_api_key"))
5864

5965
with pytest.raises(UserAuthError):
6066
embedder.get_exemplary_embedding()
6167

6268

69+
@pytest.mark.skip(reason="TogetherAI API disabled")
6370
@requires_env(API_KEY)
6471
@pytest.mark.asyncio
6572
async def test_raw_async_togetherai_embedder(embedder_file: Path):

unstructured_ingest/__version__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = "1.2.4" # pragma: no cover
1+
__version__ = "1.2.5" # pragma: no cover

unstructured_ingest/processes/connectors/fsspec/s3.py

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -57,13 +57,6 @@ class S3AccessConfig(FsspecAccessConfig):
5757
token: Optional[str] = Field(
5858
default=None, description="If not anonymous, use this security token, if specified."
5959
)
60-
ambient_credentials: bool = Field(
61-
default=False,
62-
description="Explicitly allow using ambient AWS credentials from .aws folder, "
63-
"environment variables, or IAM roles. Requires ALLOW_AMBIENT_CREDENTIALS_S3 environment "
64-
"variable to also be set to 'true' (case insensitive) for security. When False (default), "
65-
"only explicit credentials or anonymous access are allowed.",
66-
)
6760

6861

6962
class S3ConnectionConfig(FsspecConnectionConfig):
@@ -77,6 +70,13 @@ class S3ConnectionConfig(FsspecConnectionConfig):
7770
anonymous: bool = Field(
7871
default=False, description="Connect to s3 without local AWS credentials."
7972
)
73+
ambient_credentials: bool = Field(
74+
default=False,
75+
description="Explicitly allow using ambient AWS credentials from .aws folder, "
76+
"environment variables, or IAM roles. Requires ALLOW_AMBIENT_CREDENTIALS_S3 environment "
77+
"variable to also be set to 'true' (case insensitive) for security. When False (default), "
78+
"only explicit credentials or anonymous access are allowed.",
79+
)
8080
connector_type: str = Field(default=CONNECTOR_TYPE, init=False)
8181

8282
def get_access_config(self) -> dict[str, Any]:
@@ -91,13 +91,9 @@ def get_access_config(self) -> dict[str, Any]:
9191
access_configs = {"anon": False}
9292
# Avoid injecting None by filtering out k,v pairs where the value is None
9393
access_configs.update(
94-
{
95-
k: v
96-
for k, v in access_config.model_dump().items()
97-
if v is not None and k != "ambient_credentials"
98-
}
94+
{k: v for k, v in access_config.model_dump().items() if v is not None}
9995
)
100-
elif access_config.ambient_credentials:
96+
elif self.ambient_credentials:
10197
if os.getenv("ALLOW_AMBIENT_CREDENTIALS_S3", "").lower() == "true":
10298
logger.info(
10399
"Using ambient AWS credentials (environment variables, .aws folder, IAM roles)"

0 commit comments

Comments
 (0)