Skip to content

Commit 1b2ade3

Browse files
committed
add support for assuming a role arn with sts
1 parent 81b7ab4 commit 1b2ade3

File tree

2 files changed

+55
-0
lines changed

2 files changed

+55
-0
lines changed

dvc_s3/__init__.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,10 @@ def _prepare_credentials(self, **config):
219219
# Enable bucket region caching
220220
login_info["cache_regions"] = config.get("cache_regions", True)
221221

222+
role_arn = config.get("role_arn")
223+
if role_arn:
224+
self._assume_role(login_info, role_arn)
225+
222226
config_path = config.get("configpath")
223227
if config_path:
224228
os.environ.setdefault("AWS_CONFIG_FILE", config_path)
@@ -229,6 +233,29 @@ def _prepare_credentials(self, **config):
229233
splitter="dot",
230234
)
231235

236+
@staticmethod
237+
def _assume_role(login_info, role_arn):
238+
import botocore.session
239+
240+
session = botocore.session.Session(
241+
profile=login_info.get("profile"),
242+
)
243+
sts = session.create_client(
244+
"sts",
245+
aws_access_key_id=login_info.get("key"),
246+
aws_secret_access_key=login_info.get("secret"),
247+
aws_session_token=login_info.get("token"),
248+
)
249+
resp = sts.assume_role(
250+
RoleArn=role_arn,
251+
RoleSessionName="dvc",
252+
)
253+
creds = resp["Credentials"]
254+
login_info["key"] = creds["AccessKeyId"]
255+
login_info["secret"] = creds["SecretAccessKey"]
256+
login_info["token"] = creds["SessionToken"]
257+
login_info["profile"] = None
258+
232259
@wrap_prop(threading.Lock())
233260
@cached_property
234261
def fs(self):

dvc_s3/tests/test_s3.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,3 +136,31 @@ def test_key_id_and_secret():
136136
assert fs.fs_args["key"] == key_id
137137
assert fs.fs_args["secret"] == key_secret
138138
assert fs.fs_args["token"] == session_token
139+
140+
141+
def test_assume_role(monkeypatch):
142+
from unittest.mock import MagicMock
143+
144+
role_arn = "arn:aws:iam::123456789012:role/test-role"
145+
146+
mock_sts = MagicMock()
147+
mock_sts.assume_role.return_value = {
148+
"Credentials": {
149+
"AccessKeyId": "assumed-key-id",
150+
"SecretAccessKey": "assumed-secret",
151+
"SessionToken": "assumed-session-token",
152+
}
153+
}
154+
mock_session = MagicMock()
155+
mock_session.create_client.return_value = mock_sts
156+
monkeypatch.setattr("botocore.session.Session", lambda **kwargs: mock_session)
157+
158+
fs = S3FileSystem(url=url, role_arn=role_arn)
159+
assert fs.fs_args["key"] == "assumed-key-id"
160+
assert fs.fs_args["secret"] == "assumed-secret"
161+
assert fs.fs_args["token"] == "assumed-session-token"
162+
assert "profile" not in fs.fs_args
163+
164+
mock_sts.assume_role.assert_called_once_with(
165+
RoleArn=role_arn, RoleSessionName="dvc"
166+
)

0 commit comments

Comments
 (0)