Skip to content

Commit 4ce79b5

Browse files
feat(runtime): Add Runtime, Memory and Identity permissions for auto-created execution role (#132)
1 parent 025658f commit 4ce79b5

File tree

4 files changed

+94
-108
lines changed

4 files changed

+94
-108
lines changed

src/bedrock_agentcore_starter_toolkit/utils/runtime/entrypoint.py

Lines changed: 0 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -32,47 +32,6 @@ def parse_entrypoint(entrypoint: str) -> Tuple[Path, str]:
3232
return file_path, file_name
3333

3434

35-
def handle_requirements_file(
36-
requirements_file: Optional[str] = None, build_dir: Optional[Path] = None
37-
) -> Optional[str]:
38-
"""Handle requirements file selection and validation.
39-
40-
Args:
41-
requirements_file: Optional path to requirements file
42-
build_dir: Build directory, defaults to current directory
43-
44-
Returns:
45-
Validated requirements file path or None
46-
47-
Raises:
48-
ValueError: If specified requirements file is invalid
49-
"""
50-
if build_dir is None:
51-
build_dir = Path.cwd()
52-
53-
if requirements_file:
54-
log.info("Validating requirements file: %s", requirements_file)
55-
# Validate provided requirements file
56-
try:
57-
deps = validate_requirements_file(build_dir, requirements_file)
58-
log.info("Requirements file validated: %s", requirements_file)
59-
return requirements_file
60-
except (FileNotFoundError, ValueError) as e:
61-
log.error("Requirements file validation failed: %s", e)
62-
raise ValueError(str(e)) from e
63-
64-
# Auto-detect dependencies (no validation needed, just detection)
65-
log.info("Auto-detecting dependencies in: %s", build_dir)
66-
deps = detect_dependencies(build_dir)
67-
68-
if deps.found:
69-
log.info("Dependencies detected: %s", deps.file)
70-
return None # Let operations handle the detected file
71-
else:
72-
log.info("No dependency files found")
73-
return None # No file found or specified
74-
75-
7635
@dataclass
7736
class DependencyInfo:
7837
"""Information about project dependencies."""

src/bedrock_agentcore_starter_toolkit/utils/runtime/templates/execution_role_policy.json.j2

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,71 @@
7070
}
7171
},
7272
{
73-
"Sid": "GetAgentAccessToken",
73+
"Sid": "BedrockAgentCoreRuntime",
74+
"Effect": "Allow",
75+
"Action": [
76+
"bedrock-agentcore:InvokeAgentRuntime"
77+
],
78+
"Resource": [
79+
"arn:aws:bedrock-agentcore:{{ region }}:{{ account_id }}:runtime/*"
80+
]
81+
},
82+
{
83+
"Sid": "BedrockAgentCoreMemoryCreateMemory",
84+
"Effect": "Allow",
85+
"Action": [
86+
"bedrock-agentcore:CreateMemory"
87+
],
88+
"Resource": "*"
89+
},
90+
{
91+
"Sid": "BedrockAgentCoreMemory",
92+
"Effect": "Allow",
93+
"Action": [
94+
"bedrock-agentcore:CreateEvent",
95+
"bedrock-agentcore:GetEvent",
96+
"bedrock-agentcore:GetMemory",
97+
"bedrock-agentcore:GetMemoryRecord",
98+
"bedrock-agentcore:ListActors",
99+
"bedrock-agentcore:ListEvents",
100+
"bedrock-agentcore:ListMemoryRecords",
101+
"bedrock-agentcore:ListSessions",
102+
"bedrock-agentcore:DeleteEvent",
103+
"bedrock-agentcore:DeleteMemoryRecord",
104+
"bedrock-agentcore:RetrieveMemoryRecords"
105+
],
106+
"Resource": [
107+
"arn:aws:bedrock-agentcore:{{ region }}:{{ account_id }}:memory/*"
108+
]
109+
},
110+
{
111+
"Sid": "BedrockAgentCoreIdentityGetResourceApiKey",
112+
"Effect": "Allow",
113+
"Action": [
114+
"bedrock-agentcore:GetResourceApiKey"
115+
],
116+
"Resource": [
117+
"arn:aws:bedrock-agentcore:{{ region }}:{{ account_id }}:token-vault/default",
118+
"arn:aws:bedrock-agentcore:{{ region }}:{{ account_id }}:token-vault/default/apikeycredentialprovider/*",
119+
"arn:aws:bedrock-agentcore:{{ region }}:{{ account_id }}:workload-identity-directory/default",
120+
"arn:aws:bedrock-agentcore:{{ region }}:{{ account_id }}:workload-identity-directory/default/workload-identity/{{ agent_name }}-*"
121+
]
122+
},
123+
{
124+
"Sid": "BedrockAgentCoreIdentityGetResourceOauth2Token",
125+
"Effect": "Allow",
126+
"Action": [
127+
"bedrock-agentcore:GetResourceOauth2Token"
128+
],
129+
"Resource": [
130+
"arn:aws:bedrock-agentcore:{{ region }}:{{ account_id }}:token-vault/default",
131+
"arn:aws:bedrock-agentcore:{{ region }}:{{ account_id }}:token-vault/default/oauth2credentialprovider/*",
132+
"arn:aws:bedrock-agentcore:{{ region }}:{{ account_id }}:workload-identity-directory/default",
133+
"arn:aws:bedrock-agentcore:{{ region }}:{{ account_id }}:workload-identity-directory/default/workload-identity/{{ agent_name }}-*"
134+
]
135+
},
136+
{
137+
"Sid": "BedrockAgentCoreIdentityGetWorkloadAccessToken",
74138
"Effect": "Allow",
75139
"Action": [
76140
"bedrock-agentcore:GetWorkloadAccessToken",

tests/utils/runtime/test_entrypoint.py

Lines changed: 0 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
from bedrock_agentcore_starter_toolkit.utils.runtime.entrypoint import (
99
detect_dependencies,
1010
get_python_version,
11-
handle_requirements_file,
1211
parse_entrypoint,
1312
validate_requirements_file,
1413
)
@@ -34,71 +33,6 @@ def test_parse_entrypoint_file_not_found(self):
3433
parse_entrypoint("nonexistent.py")
3534

3635

37-
class TestHandleRequirementsFile:
38-
"""Test handle_requirements_file function."""
39-
40-
def test_handle_requirements_file_with_file(self, tmp_path):
41-
"""Test with provided requirements file."""
42-
req_file = tmp_path / "requirements.txt"
43-
req_file.write_text("requests==2.25.1")
44-
45-
with patch(
46-
"bedrock_agentcore_starter_toolkit.utils.runtime.entrypoint.validate_requirements_file"
47-
) as mock_validate:
48-
mock_deps = Mock()
49-
mock_validate.return_value = mock_deps
50-
51-
result = handle_requirements_file(str(req_file), tmp_path)
52-
assert result == str(req_file)
53-
mock_validate.assert_called_once_with(tmp_path, str(req_file))
54-
55-
def test_handle_requirements_file_validation_fails(self, tmp_path):
56-
"""Test with invalid requirements file."""
57-
with patch(
58-
"bedrock_agentcore_starter_toolkit.utils.runtime.entrypoint.validate_requirements_file",
59-
side_effect=ValueError("Invalid file"),
60-
):
61-
with pytest.raises(ValueError, match="Invalid file"):
62-
handle_requirements_file("invalid.txt", tmp_path)
63-
64-
def test_handle_requirements_file_auto_detect_found(self, tmp_path):
65-
"""Test auto-detection when dependencies are found."""
66-
with patch("bedrock_agentcore_starter_toolkit.utils.runtime.entrypoint.detect_dependencies") as mock_detect:
67-
mock_deps = Mock()
68-
mock_deps.found = True
69-
mock_deps.file = "requirements.txt"
70-
mock_detect.return_value = mock_deps
71-
72-
result = handle_requirements_file(None, tmp_path)
73-
assert result is None # Should return None to let operations handle it
74-
mock_detect.assert_called_once_with(tmp_path)
75-
76-
def test_handle_requirements_file_auto_detect_not_found(self, tmp_path):
77-
"""Test auto-detection when no dependencies are found."""
78-
with patch("bedrock_agentcore_starter_toolkit.utils.runtime.entrypoint.detect_dependencies") as mock_detect:
79-
mock_deps = Mock()
80-
mock_deps.found = False
81-
mock_detect.return_value = mock_deps
82-
83-
result = handle_requirements_file(None, tmp_path)
84-
assert result is None
85-
mock_detect.assert_called_once_with(tmp_path)
86-
87-
def test_handle_requirements_file_default_build_dir(self):
88-
"""Test with default build directory."""
89-
with patch("bedrock_agentcore_starter_toolkit.utils.runtime.entrypoint.Path.cwd") as mock_cwd:
90-
mock_cwd.return_value = Path("/current/dir")
91-
92-
with patch("bedrock_agentcore_starter_toolkit.utils.runtime.entrypoint.detect_dependencies") as mock_detect:
93-
mock_deps = Mock()
94-
mock_deps.found = False
95-
mock_detect.return_value = mock_deps
96-
97-
result = handle_requirements_file(None, None)
98-
assert result is None
99-
mock_detect.assert_called_once_with(Path("/current/dir"))
100-
101-
10236
class TestDependencies:
10337
"""Test dependency detection functionality."""
10438

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
from bedrock_agentcore import BedrockAgentCoreApp
2+
from bedrock_agentcore.memory import MemoryClient
3+
from random import randint
4+
5+
app = BedrockAgentCoreApp()
6+
client = MemoryClient(region_name="us-west-2")
7+
8+
@app.entrypoint
9+
def entrypoint(_payload):
10+
print("Receiving payload:", _payload)
11+
memory_id = create_memory()
12+
13+
return {"memory_id": memory_id}
14+
15+
def create_memory():
16+
name = "CustomerSupportAgentMemory" + str(randint(1, 10000))
17+
description="Memory for customer support conversations"
18+
19+
memory = client.create_memory(
20+
name=name,
21+
description=description,
22+
)
23+
24+
print(f"Memory ID: {memory.get('id')}")
25+
print(f"Memory: {memory}")
26+
27+
return memory.get('id')
28+
29+
app.run()

0 commit comments

Comments
 (0)