diff --git a/01-tutorials/08-AgentCore-policy/01-Getting-Started/AgentCore-Policy-Demo.ipynb b/01-tutorials/08-AgentCore-policy/01-Getting-Started/AgentCore-Policy-Demo.ipynb index 08897ebd..8761cec3 100644 --- a/01-tutorials/08-AgentCore-policy/01-Getting-Started/AgentCore-Policy-Demo.ipynb +++ b/01-tutorials/08-AgentCore-policy/01-Getting-Started/AgentCore-Policy-Demo.ipynb @@ -2328,39 +2328,7 @@ "execution_count": null, "metadata": {}, "outputs": [], - "source": [ - "from bedrock_agentcore_starter_toolkit.operations.policy.client import PolicyClient\n", - "\n", - "# Policy client creation\n", - "policy_client = PolicyClient(region_name=region)\n", - "policy_client.logger.setLevel(logging.INFO)\n", - "\n", - "# Create Cedar policy\n", - "print(\"\\nπŸ“ Creating Cedar Policy...\")\n", - "print(f\" Policy Engine ID: {engine['policyEngineArn']}\")\n", - "GATEWAY_ARN = config[\"gateway\"][\"gateway_arn\"]\n", - "\n", - "# Define the Cedar policy statement\n", - "cedar_statement = (\n", - " f\"permit(principal, \"\n", - " f'action == AgentCore::Action::\"ApplicationToolTarget___create_application\", '\n", - " f'resource == AgentCore::Gateway::\"{GATEWAY_ARN}\") '\n", - " f\"when {{ context.input.coverage_amount <= 1000000 }};\"\n", - ")\n", - "\n", - "policy = policy_client.create_or_get_policy(\n", - " policy_engine_id=engine[\"policyEngineId\"],\n", - " name=\"create_application_policy\",\n", - " description=\"Allow application creation under $1M\",\n", - " definition={\"cedar\": {\"statement\": cedar_statement}},\n", - ")\n", - "print(f\"βœ“ Policy: {policy['policyId']}\\n\")\n", - "\n", - "# Save to config\n", - "config[\"policy_id\"] = policy[\"policyId\"]\n", - "with open(\"config.json\", \"w\") as f:\n", - " json.dump(config, f, indent=2)" - ] + "source": "from bedrock_agentcore_starter_toolkit.operations.policy.client import PolicyClient\n\n# Policy client creation\npolicy_client = PolicyClient(region_name=region)\npolicy_client.logger.setLevel(logging.INFO)\n\n# Create Cedar policy\nprint(\"\\nπŸ“ Creating Cedar Policy...\")\nprint(f\" Policy Engine ID: {engine['policyEngineArn']}\")\nGATEWAY_ARN = config[\"gateway\"][\"gateway_arn\"]\n\n# Define the Cedar policy statement\ncedar_statement = (\n f\"permit(principal, \"\n f'action == AgentCore::Action::\"ApplicationToolTarget___create_application\", '\n f'resource == AgentCore::Gateway::\"{GATEWAY_ARN}\") '\n f\"when {{ context.input.coverage_amount <= 1000000 }};\"\n)\n\ntry:\n policy = policy_client.create_or_get_policy(\n policy_engine_id=engine[\"policyEngineId\"],\n name=\"create_application_policy\",\n description=\"Allow application creation under $1M\",\n definition={\"cedar\": {\"statement\": cedar_statement}},\n )\n print(f\"βœ“ Policy: {policy['policyId']}\\n\")\nexcept Exception as e:\n print(f\"⚠️ Policy creation failed: {e}\")\n print(\" This may be due to Cedar validation findings (e.g., policy too restrictive or schema issues).\")\n print(\" Retrying with validation_mode='IGNORE_ALL_FINDINGS'...\")\n policy = policy_client.create_or_get_policy(\n policy_engine_id=engine[\"policyEngineId\"],\n name=\"create_application_policy\",\n description=\"Allow application creation under $1M\",\n definition={\"cedar\": {\"statement\": cedar_statement}},\n validation_mode=\"IGNORE_ALL_FINDINGS\",\n )\n print(f\"βœ“ Policy created with IGNORE_ALL_FINDINGS: {policy['policyId']}\\n\")\n\n# Save to config\nconfig[\"policy_id\"] = policy[\"policyId\"]\nwith open(\"config.json\", \"w\") as f:\n json.dump(config, f, indent=2)" }, { "cell_type": "markdown", diff --git a/01-tutorials/08-AgentCore-policy/02-Natural-Language-Policy-Authoring/NL-Authoring-Policy.ipynb b/01-tutorials/08-AgentCore-policy/02-Natural-Language-Policy-Authoring/NL-Authoring-Policy.ipynb index cdd2cefa..aaed1884 100644 --- a/01-tutorials/08-AgentCore-policy/02-Natural-Language-Policy-Authoring/NL-Authoring-Policy.ipynb +++ b/01-tutorials/08-AgentCore-policy/02-Natural-Language-Policy-Authoring/NL-Authoring-Policy.ipynb @@ -43,18 +43,303 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 1, + "metadata": { + "execution": { + "iopub.execute_input": "2026-04-14T18:59:30.398716Z", + "iopub.status.busy": "2026-04-14T18:59:30.398590Z", + "iopub.status.idle": "2026-04-14T18:59:33.799092Z", + "shell.execute_reply": "2026-04-14T18:59:33.798404Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Looking in indexes: https://pypi.org/simple, https://plugin.us-east-1.prod.workshops.aws\r\n", + "Requirement already satisfied: boto3>=1.42.0 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from -r requirements.txt (line 5)) (1.42.2)\r\n", + "Requirement already satisfied: botocore>=1.34.0 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from -r requirements.txt (line 6)) (1.42.89)\r\n", + "Requirement already satisfied: bedrock-agentcore-starter-toolkit>=0.2.4 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from -r requirements.txt (line 9)) (0.3.5)\r\n", + "Requirement already satisfied: requests>=2.31.0 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from -r requirements.txt (line 12)) (2.32.5)\r\n", + "Requirement already satisfied: jupyter>=1.0.0 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from -r requirements.txt (line 15)) (1.1.1)\r\n", + "Requirement already satisfied: ipykernel>=6.25.0 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from -r requirements.txt (line 16)) (7.1.0)\r\n", + "Requirement already satisfied: notebook>=7.0.0 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from -r requirements.txt (line 17)) (7.5.5)\r\n", + "Requirement already satisfied: python-dateutil>=2.8.2 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from -r requirements.txt (line 20)) (2.9.0.post0)\r\n", + "Requirement already satisfied: python-json-logger>=2.0.7 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from -r requirements.txt (line 23)) (4.1.0)\r\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Requirement already satisfied: jmespath<2.0.0,>=0.7.1 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from boto3>=1.42.0->-r requirements.txt (line 5)) (1.0.1)\r\n", + "Requirement already satisfied: s3transfer<0.17.0,>=0.16.0 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from boto3>=1.42.0->-r requirements.txt (line 5)) (0.16.0)\r\n", + "Requirement already satisfied: urllib3!=2.2.0,<3,>=1.25.4 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from botocore>=1.34.0->-r requirements.txt (line 6)) (2.5.0)\r\n", + "Requirement already satisfied: six>=1.5 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from python-dateutil>=2.8.2->-r requirements.txt (line 20)) (1.17.0)\r\n", + "Requirement already satisfied: autopep8>=2.3.2 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from bedrock-agentcore-starter-toolkit>=0.2.4->-r requirements.txt (line 9)) (2.3.2)\r\n", + "Requirement already satisfied: bedrock-agentcore>=1.1.0 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from bedrock-agentcore-starter-toolkit>=0.2.4->-r requirements.txt (line 9)) (1.1.0)\r\n", + "Requirement already satisfied: docstring-parser<1.0,>=0.15 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from bedrock-agentcore-starter-toolkit>=0.2.4->-r requirements.txt (line 9)) (0.17.0)\r\n", + "Requirement already satisfied: httpx>=0.28.1 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from bedrock-agentcore-starter-toolkit>=0.2.4->-r requirements.txt (line 9)) (0.28.1)\r\n", + "Requirement already satisfied: jinja2>=3.1.6 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from bedrock-agentcore-starter-toolkit>=0.2.4->-r requirements.txt (line 9)) (3.1.6)\r\n", + "Requirement already satisfied: openapi-spec-validator>=0.7.2 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from bedrock-agentcore-starter-toolkit>=0.2.4->-r requirements.txt (line 9)) (0.7.2)\r\n", + "Requirement already satisfied: prance>=25.4.8.0 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from bedrock-agentcore-starter-toolkit>=0.2.4->-r requirements.txt (line 9)) (25.4.8.0)\r\n", + "Requirement already satisfied: prompt-toolkit>=3.0.51 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from bedrock-agentcore-starter-toolkit>=0.2.4->-r requirements.txt (line 9)) (3.0.52)\r\n", + "Requirement already satisfied: py-openapi-schema-to-json-schema>=0.0.3 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from bedrock-agentcore-starter-toolkit>=0.2.4->-r requirements.txt (line 9)) (0.0.3)\r\n", + "Requirement already satisfied: pydantic<2.41.3,>=2.0.0 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from bedrock-agentcore-starter-toolkit>=0.2.4->-r requirements.txt (line 9)) (2.12.5)\r\n", + "Requirement already satisfied: pyyaml>=6.0.2 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from bedrock-agentcore-starter-toolkit>=0.2.4->-r requirements.txt (line 9)) (6.0.3)\r\n", + "Requirement already satisfied: questionary>=2.1.0 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from bedrock-agentcore-starter-toolkit>=0.2.4->-r requirements.txt (line 9)) (2.1.1)\r\n", + "Requirement already satisfied: rich>=13.0.0 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from bedrock-agentcore-starter-toolkit>=0.2.4->-r requirements.txt (line 9)) (14.2.0)\r\n", + "Requirement already satisfied: ruamel-yaml>=0.18.14 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from bedrock-agentcore-starter-toolkit>=0.2.4->-r requirements.txt (line 9)) (0.18.16)\r\n", + "Requirement already satisfied: starlette>=0.46.2 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from bedrock-agentcore-starter-toolkit>=0.2.4->-r requirements.txt (line 9)) (0.50.0)\r\n", + "Requirement already satisfied: toml>=0.10.2 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from bedrock-agentcore-starter-toolkit>=0.2.4->-r requirements.txt (line 9)) (0.10.2)\r\n", + "Requirement already satisfied: typer>=0.19.0 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from bedrock-agentcore-starter-toolkit>=0.2.4->-r requirements.txt (line 9)) (0.20.0)\r\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Requirement already satisfied: typing-extensions<5.0.0,>=4.13.2 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from bedrock-agentcore-starter-toolkit>=0.2.4->-r requirements.txt (line 9)) (4.15.0)\r\n", + "Requirement already satisfied: uvicorn>=0.34.2 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from bedrock-agentcore-starter-toolkit>=0.2.4->-r requirements.txt (line 9)) (0.38.0)\r\n", + "Requirement already satisfied: annotated-types>=0.6.0 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from pydantic<2.41.3,>=2.0.0->bedrock-agentcore-starter-toolkit>=0.2.4->-r requirements.txt (line 9)) (0.7.0)\r\n", + "Requirement already satisfied: pydantic-core==2.41.5 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from pydantic<2.41.3,>=2.0.0->bedrock-agentcore-starter-toolkit>=0.2.4->-r requirements.txt (line 9)) (2.41.5)\r\n", + "Requirement already satisfied: typing-inspection>=0.4.2 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from pydantic<2.41.3,>=2.0.0->bedrock-agentcore-starter-toolkit>=0.2.4->-r requirements.txt (line 9)) (0.4.2)\r\n", + "Requirement already satisfied: charset_normalizer<4,>=2 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from requests>=2.31.0->-r requirements.txt (line 12)) (3.4.4)\r\n", + "Requirement already satisfied: idna<4,>=2.5 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from requests>=2.31.0->-r requirements.txt (line 12)) (3.11)\r\n", + "Requirement already satisfied: certifi>=2017.4.17 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from requests>=2.31.0->-r requirements.txt (line 12)) (2025.11.12)\r\n", + "Requirement already satisfied: jupyter-console in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from jupyter>=1.0.0->-r requirements.txt (line 15)) (6.6.3)\r\n", + "Requirement already satisfied: nbconvert in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from jupyter>=1.0.0->-r requirements.txt (line 15)) (7.17.1)\r\n", + "Requirement already satisfied: ipywidgets in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from jupyter>=1.0.0->-r requirements.txt (line 15)) (8.1.8)\r\n", + "Requirement already satisfied: jupyterlab in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from jupyter>=1.0.0->-r requirements.txt (line 15)) (4.5.6)\r\n", + "Requirement already satisfied: appnope>=0.1.2 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from ipykernel>=6.25.0->-r requirements.txt (line 16)) (0.1.4)\r\n", + "Requirement already satisfied: comm>=0.1.1 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from ipykernel>=6.25.0->-r requirements.txt (line 16)) (0.2.3)\r\n", + "Requirement already satisfied: debugpy>=1.6.5 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from ipykernel>=6.25.0->-r requirements.txt (line 16)) (1.8.17)\r\n", + "Requirement already satisfied: ipython>=7.23.1 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from ipykernel>=6.25.0->-r requirements.txt (line 16)) (9.7.0)\r\n", + "Requirement already satisfied: jupyter-client>=8.0.0 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from ipykernel>=6.25.0->-r requirements.txt (line 16)) (8.6.3)\r\n", + "Requirement already satisfied: jupyter-core!=5.0.*,>=4.12 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from ipykernel>=6.25.0->-r requirements.txt (line 16)) (5.9.1)\r\n", + "Requirement already satisfied: matplotlib-inline>=0.1 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from ipykernel>=6.25.0->-r requirements.txt (line 16)) (0.2.1)\r\n", + "Requirement already satisfied: nest-asyncio>=1.4 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from ipykernel>=6.25.0->-r requirements.txt (line 16)) (1.6.0)\r\n", + "Requirement already satisfied: packaging>=22 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from ipykernel>=6.25.0->-r requirements.txt (line 16)) (25.0)\r\n", + "Requirement already satisfied: psutil>=5.7 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from ipykernel>=6.25.0->-r requirements.txt (line 16)) (7.1.3)\r\n", + "Requirement already satisfied: pyzmq>=25 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from ipykernel>=6.25.0->-r requirements.txt (line 16)) (27.1.0)\r\n", + "Requirement already satisfied: tornado>=6.2 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from ipykernel>=6.25.0->-r requirements.txt (line 16)) (6.5.2)\r\n", + "Requirement already satisfied: traitlets>=5.4.0 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from ipykernel>=6.25.0->-r requirements.txt (line 16)) (5.14.3)\r\n", + "Requirement already satisfied: jupyter-server<3,>=2.4.0 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from notebook>=7.0.0->-r requirements.txt (line 17)) (2.17.0)\r\n", + "Requirement already satisfied: jupyterlab-server<3,>=2.28.0 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from notebook>=7.0.0->-r requirements.txt (line 17)) (2.28.0)\r\n", + "Requirement already satisfied: notebook-shim<0.3,>=0.2 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from notebook>=7.0.0->-r requirements.txt (line 17)) (0.2.4)\r\n", + "Requirement already satisfied: anyio>=3.1.0 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from jupyter-server<3,>=2.4.0->notebook>=7.0.0->-r requirements.txt (line 17)) (4.12.0)\r\n", + "Requirement already satisfied: argon2-cffi>=21.1 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from jupyter-server<3,>=2.4.0->notebook>=7.0.0->-r requirements.txt (line 17)) (25.1.0)\r\n", + "Requirement already satisfied: jupyter-events>=0.11.0 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from jupyter-server<3,>=2.4.0->notebook>=7.0.0->-r requirements.txt (line 17)) (0.12.0)\r\n", + "Requirement already satisfied: jupyter-server-terminals>=0.4.4 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from jupyter-server<3,>=2.4.0->notebook>=7.0.0->-r requirements.txt (line 17)) (0.5.4)\r\n", + "Requirement already satisfied: nbformat>=5.3.0 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from jupyter-server<3,>=2.4.0->notebook>=7.0.0->-r requirements.txt (line 17)) (5.10.4)\r\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Requirement already satisfied: prometheus-client>=0.9 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from jupyter-server<3,>=2.4.0->notebook>=7.0.0->-r requirements.txt (line 17)) (0.25.0)\r\n", + "Requirement already satisfied: send2trash>=1.8.2 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from jupyter-server<3,>=2.4.0->notebook>=7.0.0->-r requirements.txt (line 17)) (2.1.0)\r\n", + "Requirement already satisfied: terminado>=0.8.3 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from jupyter-server<3,>=2.4.0->notebook>=7.0.0->-r requirements.txt (line 17)) (0.18.1)\r\n", + "Requirement already satisfied: websocket-client>=1.7 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from jupyter-server<3,>=2.4.0->notebook>=7.0.0->-r requirements.txt (line 17)) (1.9.0)\r\n", + "Requirement already satisfied: async-lru>=1.0.0 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from jupyterlab->jupyter>=1.0.0->-r requirements.txt (line 15)) (2.3.0)\r\n", + "Requirement already satisfied: jupyter-lsp>=2.0.0 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from jupyterlab->jupyter>=1.0.0->-r requirements.txt (line 15)) (2.3.1)\r\n", + "Requirement already satisfied: setuptools>=41.1.0 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from jupyterlab->jupyter>=1.0.0->-r requirements.txt (line 15)) (82.0.1)\r\n", + "Requirement already satisfied: httpcore==1.* in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from httpx>=0.28.1->bedrock-agentcore-starter-toolkit>=0.2.4->-r requirements.txt (line 9)) (1.0.9)\r\n", + "Requirement already satisfied: h11>=0.16 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from httpcore==1.*->httpx>=0.28.1->bedrock-agentcore-starter-toolkit>=0.2.4->-r requirements.txt (line 9)) (0.16.0)\r\n", + "Requirement already satisfied: babel>=2.10 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from jupyterlab-server<3,>=2.28.0->notebook>=7.0.0->-r requirements.txt (line 17)) (2.18.0)\r\n", + "Requirement already satisfied: json5>=0.9.0 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from jupyterlab-server<3,>=2.28.0->notebook>=7.0.0->-r requirements.txt (line 17)) (0.14.0)\r\n", + "Requirement already satisfied: jsonschema>=4.18.0 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from jupyterlab-server<3,>=2.28.0->notebook>=7.0.0->-r requirements.txt (line 17)) (4.25.1)\r\n", + "Requirement already satisfied: argon2-cffi-bindings in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from argon2-cffi>=21.1->jupyter-server<3,>=2.4.0->notebook>=7.0.0->-r requirements.txt (line 17)) (25.1.0)\r\n", + "Requirement already satisfied: pycodestyle>=2.12.0 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from autopep8>=2.3.2->bedrock-agentcore-starter-toolkit>=0.2.4->-r requirements.txt (line 9)) (2.14.0)\r\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Requirement already satisfied: pre-commit>=4.2.0 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from bedrock-agentcore>=1.1.0->bedrock-agentcore-starter-toolkit>=0.2.4->-r requirements.txt (line 9)) (4.5.0)\r\n", + "Requirement already satisfied: websockets>=12.0 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from bedrock-agentcore>=1.1.0->bedrock-agentcore-starter-toolkit>=0.2.4->-r requirements.txt (line 9)) (15.0.1)\r\n", + "Requirement already satisfied: awscrt==0.31.2 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from botocore[crt]>=1.42.1->bedrock-agentcore-starter-toolkit>=0.2.4->-r requirements.txt (line 9)) (0.31.2)\r\n", + "Requirement already satisfied: decorator>=4.3.2 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from ipython>=7.23.1->ipykernel>=6.25.0->-r requirements.txt (line 16)) (5.2.1)\r\n", + "Requirement already satisfied: ipython-pygments-lexers>=1.0.0 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from ipython>=7.23.1->ipykernel>=6.25.0->-r requirements.txt (line 16)) (1.1.1)\r\n", + "Requirement already satisfied: jedi>=0.18.1 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from ipython>=7.23.1->ipykernel>=6.25.0->-r requirements.txt (line 16)) (0.19.2)\r\n", + "Requirement already satisfied: pexpect>4.3 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from ipython>=7.23.1->ipykernel>=6.25.0->-r requirements.txt (line 16)) (4.9.0)\r\n", + "Requirement already satisfied: pygments>=2.11.0 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from ipython>=7.23.1->ipykernel>=6.25.0->-r requirements.txt (line 16)) (2.19.2)\r\n", + "Requirement already satisfied: stack_data>=0.6.0 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from ipython>=7.23.1->ipykernel>=6.25.0->-r requirements.txt (line 16)) (0.6.3)\r\n", + "Requirement already satisfied: wcwidth in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from prompt-toolkit>=3.0.51->bedrock-agentcore-starter-toolkit>=0.2.4->-r requirements.txt (line 9)) (0.2.14)\r\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Requirement already satisfied: parso<0.9.0,>=0.8.4 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from jedi>=0.18.1->ipython>=7.23.1->ipykernel>=6.25.0->-r requirements.txt (line 16)) (0.8.5)\r\n", + "Requirement already satisfied: MarkupSafe>=2.0 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from jinja2>=3.1.6->bedrock-agentcore-starter-toolkit>=0.2.4->-r requirements.txt (line 9)) (3.0.3)\r\n", + "Requirement already satisfied: attrs>=22.2.0 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from jsonschema>=4.18.0->jupyterlab-server<3,>=2.28.0->notebook>=7.0.0->-r requirements.txt (line 17)) (25.4.0)\r\n", + "Requirement already satisfied: jsonschema-specifications>=2023.03.6 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from jsonschema>=4.18.0->jupyterlab-server<3,>=2.28.0->notebook>=7.0.0->-r requirements.txt (line 17)) (2025.9.1)\r\n", + "Requirement already satisfied: referencing>=0.28.4 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from jsonschema>=4.18.0->jupyterlab-server<3,>=2.28.0->notebook>=7.0.0->-r requirements.txt (line 17)) (0.36.2)\r\n", + "Requirement already satisfied: rpds-py>=0.7.1 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from jsonschema>=4.18.0->jupyterlab-server<3,>=2.28.0->notebook>=7.0.0->-r requirements.txt (line 17)) (0.30.0)\r\n", + "Requirement already satisfied: platformdirs>=2.5 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from jupyter-core!=5.0.*,>=4.12->ipykernel>=6.25.0->-r requirements.txt (line 16)) (4.5.0)\r\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Requirement already satisfied: rfc3339-validator in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->notebook>=7.0.0->-r requirements.txt (line 17)) (0.1.4)\r\n", + "Requirement already satisfied: rfc3986-validator>=0.1.1 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->notebook>=7.0.0->-r requirements.txt (line 17)) (0.1.1)\r\n", + "Requirement already satisfied: fqdn in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->notebook>=7.0.0->-r requirements.txt (line 17)) (1.5.1)\r\n", + "Requirement already satisfied: isoduration in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->notebook>=7.0.0->-r requirements.txt (line 17)) (20.11.0)\r\n", + "Requirement already satisfied: jsonpointer>1.13 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->notebook>=7.0.0->-r requirements.txt (line 17)) (3.1.1)\r\n", + "Requirement already satisfied: rfc3987-syntax>=1.1.0 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->notebook>=7.0.0->-r requirements.txt (line 17)) (1.1.0)\r\n", + "Requirement already satisfied: uri-template in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->notebook>=7.0.0->-r requirements.txt (line 17)) (1.3.0)\r\n", + "Requirement already satisfied: webcolors>=24.6.0 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->notebook>=7.0.0->-r requirements.txt (line 17)) (25.10.0)\r\n", + "Requirement already satisfied: beautifulsoup4 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from nbconvert->jupyter>=1.0.0->-r requirements.txt (line 15)) (4.14.3)\r\n", + "Requirement already satisfied: bleach!=5.0.0 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from bleach[css]!=5.0.0->nbconvert->jupyter>=1.0.0->-r requirements.txt (line 15)) (6.3.0)\r\n", + "Requirement already satisfied: defusedxml in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from nbconvert->jupyter>=1.0.0->-r requirements.txt (line 15)) (0.7.1)\r\n", + "Requirement already satisfied: jupyterlab-pygments in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from nbconvert->jupyter>=1.0.0->-r requirements.txt (line 15)) (0.3.0)\r\n", + "Requirement already satisfied: mistune<4,>=2.0.3 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from nbconvert->jupyter>=1.0.0->-r requirements.txt (line 15)) (3.2.0)\r\n", + "Requirement already satisfied: nbclient>=0.5.0 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from nbconvert->jupyter>=1.0.0->-r requirements.txt (line 15)) (0.10.4)\r\n", + "Requirement already satisfied: pandocfilters>=1.4.1 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from nbconvert->jupyter>=1.0.0->-r requirements.txt (line 15)) (1.5.1)\r\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Requirement already satisfied: webencodings in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from bleach!=5.0.0->bleach[css]!=5.0.0->nbconvert->jupyter>=1.0.0->-r requirements.txt (line 15)) (0.5.1)\r\n", + "Requirement already satisfied: tinycss2<1.5,>=1.1.0 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from bleach[css]!=5.0.0->nbconvert->jupyter>=1.0.0->-r requirements.txt (line 15)) (1.4.0)\r\n", + "Requirement already satisfied: fastjsonschema>=2.15 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from nbformat>=5.3.0->jupyter-server<3,>=2.4.0->notebook>=7.0.0->-r requirements.txt (line 17)) (2.21.2)\r\n", + "Requirement already satisfied: jsonschema-path<0.4.0,>=0.3.1 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from openapi-spec-validator>=0.7.2->bedrock-agentcore-starter-toolkit>=0.2.4->-r requirements.txt (line 9)) (0.3.4)\r\n", + "Requirement already satisfied: lazy-object-proxy<2.0.0,>=1.7.1 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from openapi-spec-validator>=0.7.2->bedrock-agentcore-starter-toolkit>=0.2.4->-r requirements.txt (line 9)) (1.12.0)\r\n", + "Requirement already satisfied: openapi-schema-validator<0.7.0,>=0.6.0 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from openapi-spec-validator>=0.7.2->bedrock-agentcore-starter-toolkit>=0.2.4->-r requirements.txt (line 9)) (0.6.3)\r\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Requirement already satisfied: pathable<0.5.0,>=0.4.1 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from jsonschema-path<0.4.0,>=0.3.1->openapi-spec-validator>=0.7.2->bedrock-agentcore-starter-toolkit>=0.2.4->-r requirements.txt (line 9)) (0.4.4)\r\n", + "Requirement already satisfied: ptyprocess>=0.5 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from pexpect>4.3->ipython>=7.23.1->ipykernel>=6.25.0->-r requirements.txt (line 16)) (0.7.0)\r\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Requirement already satisfied: chardet>=5.2 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from prance>=25.4.8.0->bedrock-agentcore-starter-toolkit>=0.2.4->-r requirements.txt (line 9)) (5.2.0)\r\n", + "Requirement already satisfied: cfgv>=2.0.0 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from pre-commit>=4.2.0->bedrock-agentcore>=1.1.0->bedrock-agentcore-starter-toolkit>=0.2.4->-r requirements.txt (line 9)) (3.5.0)\r\n", + "Requirement already satisfied: identify>=1.0.0 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from pre-commit>=4.2.0->bedrock-agentcore>=1.1.0->bedrock-agentcore-starter-toolkit>=0.2.4->-r requirements.txt (line 9)) (2.6.15)\r\n", + "Requirement already satisfied: nodeenv>=0.11.1 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from pre-commit>=4.2.0->bedrock-agentcore>=1.1.0->bedrock-agentcore-starter-toolkit>=0.2.4->-r requirements.txt (line 9)) (1.9.1)\r\n", + "Requirement already satisfied: virtualenv>=20.10.0 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from pre-commit>=4.2.0->bedrock-agentcore>=1.1.0->bedrock-agentcore-starter-toolkit>=0.2.4->-r requirements.txt (line 9)) (20.35.4)\r\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Requirement already satisfied: lark>=1.2.2 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from rfc3987-syntax>=1.1.0->jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->notebook>=7.0.0->-r requirements.txt (line 17)) (1.3.1)\r\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Requirement already satisfied: markdown-it-py>=2.2.0 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from rich>=13.0.0->bedrock-agentcore-starter-toolkit>=0.2.4->-r requirements.txt (line 9)) (4.0.0)\r\n", + "Requirement already satisfied: mdurl~=0.1 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from markdown-it-py>=2.2.0->rich>=13.0.0->bedrock-agentcore-starter-toolkit>=0.2.4->-r requirements.txt (line 9)) (0.1.2)\r\n", + "Requirement already satisfied: ruamel.yaml.clib>=0.2.7 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from ruamel-yaml>=0.18.14->bedrock-agentcore-starter-toolkit>=0.2.4->-r requirements.txt (line 9)) (0.2.15)\r\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Requirement already satisfied: executing>=1.2.0 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from stack_data>=0.6.0->ipython>=7.23.1->ipykernel>=6.25.0->-r requirements.txt (line 16)) (2.2.1)\r\n", + "Requirement already satisfied: asttokens>=2.1.0 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from stack_data>=0.6.0->ipython>=7.23.1->ipykernel>=6.25.0->-r requirements.txt (line 16)) (3.0.1)\r\n", + "Requirement already satisfied: pure-eval in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from stack_data>=0.6.0->ipython>=7.23.1->ipykernel>=6.25.0->-r requirements.txt (line 16)) (0.2.3)\r\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Requirement already satisfied: click>=8.0.0 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from typer>=0.19.0->bedrock-agentcore-starter-toolkit>=0.2.4->-r requirements.txt (line 9)) (8.3.1)\r\n", + "Requirement already satisfied: shellingham>=1.3.0 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from typer>=0.19.0->bedrock-agentcore-starter-toolkit>=0.2.4->-r requirements.txt (line 9)) (1.5.4)\r\n", + "Requirement already satisfied: distlib<1,>=0.3.7 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from virtualenv>=20.10.0->pre-commit>=4.2.0->bedrock-agentcore>=1.1.0->bedrock-agentcore-starter-toolkit>=0.2.4->-r requirements.txt (line 9)) (0.4.0)\r\n", + "Requirement already satisfied: filelock<4,>=3.12.2 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from virtualenv>=20.10.0->pre-commit>=4.2.0->bedrock-agentcore>=1.1.0->bedrock-agentcore-starter-toolkit>=0.2.4->-r requirements.txt (line 9)) (3.20.0)\r\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Requirement already satisfied: cffi>=1.0.1 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from argon2-cffi-bindings->argon2-cffi>=21.1->jupyter-server<3,>=2.4.0->notebook>=7.0.0->-r requirements.txt (line 17)) (2.0.0)\r\n", + "Requirement already satisfied: pycparser in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from cffi>=1.0.1->argon2-cffi-bindings->argon2-cffi>=21.1->jupyter-server<3,>=2.4.0->notebook>=7.0.0->-r requirements.txt (line 17)) (2.23)\r\n", + "Requirement already satisfied: soupsieve>=1.6.1 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from beautifulsoup4->nbconvert->jupyter>=1.0.0->-r requirements.txt (line 15)) (2.8.3)\r\n", + "Requirement already satisfied: widgetsnbextension~=4.0.14 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from ipywidgets->jupyter>=1.0.0->-r requirements.txt (line 15)) (4.0.15)\r\n", + "Requirement already satisfied: jupyterlab_widgets~=3.0.15 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from ipywidgets->jupyter>=1.0.0->-r requirements.txt (line 15)) (3.0.16)\r\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Requirement already satisfied: arrow>=0.15.0 in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from isoduration->jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->notebook>=7.0.0->-r requirements.txt (line 17)) (1.4.0)\r\n", + "Requirement already satisfied: tzdata in /Users/bhrsrini/projects/Agentcore/Policy/.venv/lib/python3.13/site-packages (from arrow>=0.15.0->isoduration->jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->notebook>=7.0.0->-r requirements.txt (line 17)) (2026.1)\r\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\r\n", + "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m A new release of pip is available: \u001b[0m\u001b[31;49m25.3\u001b[0m\u001b[39;49m -> \u001b[0m\u001b[32;49m26.0.1\u001b[0m\r\n", + "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m To update, run: \u001b[0m\u001b[32;49m/Users/bhrsrini/projects/Agentcore/Policy/.venv/bin/python -m pip install --upgrade pip\u001b[0m\r\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Note: you may need to restart the kernel to use updated packages.\n" + ] + } + ], "source": [ "%pip install -r requirements.txt" ] }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 2, + "metadata": { + "execution": { + "iopub.execute_input": "2026-04-14T18:59:33.801038Z", + "iopub.status.busy": "2026-04-14T18:59:33.800876Z", + "iopub.status.idle": "2026-04-14T18:59:35.946916Z", + "shell.execute_reply": "2026-04-14T18:59:35.945095Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Region: us-east-1\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "βœ… AWS Credentials Verified\n", + " Account: 849138760372\n", + " User/Role: arn:aws:sts::849138760372:assumed-role/admin/bhrsrini-Isengard\n" + ] + } + ], "source": [ "# Import required libraries\n", "import sys\n", @@ -102,9 +387,29 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 3, + "metadata": { + "execution": { + "iopub.execute_input": "2026-04-14T18:59:35.951940Z", + "iopub.status.busy": "2026-04-14T18:59:35.951482Z", + "iopub.status.idle": "2026-04-14T18:59:35.966125Z", + "shell.execute_reply": "2026-04-14T18:59:35.965245Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "πŸ” Checking for configuration...\n", + "Looking for: 08-AgentCore-policy/01-Getting-Started/config.json\n", + "βœ… Configuration file found!\n", + "βœ… Configuration is complete!\n", + "\n", + "======================================================================\n" + ] + } + ], "source": [ "# Check if Gateway for Insurance Underwriting exists\n", "\n", @@ -215,9 +520,46 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 4, + "metadata": { + "execution": { + "iopub.execute_input": "2026-04-14T18:59:35.968469Z", + "iopub.status.busy": "2026-04-14T18:59:35.968314Z", + "iopub.status.idle": "2026-04-14T18:59:39.072538Z", + "shell.execute_reply": "2026-04-14T18:59:39.071267Z" + } + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 11:59:38,698 - bedrock_agentcore.policy - INFO - Creating or getting Policy Engine: InsurancePolicyEngine_NL2Cedar\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "πŸ”§ Creating Policy Engine...\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 11:59:39,023 - bedrock_agentcore.policy - INFO - βœ“ Found existing Policy Engine: InsurancePolicyEngine_NL2Cedar\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "βœ“ Policy Engine: InsurancePolicyEngine_NL2Cedar-dyq0mkonbr\n", + "\n" + ] + } + ], "source": [ "from bedrock_agentcore_starter_toolkit.operations.policy.client import PolicyClient\n", "\n", @@ -279,10 +621,132 @@ ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], + "source": [ + "### Cedar Policy Validation Findings\n", + "\n", + "When NL2Cedar generates a Cedar policy, it runs the generated Cedar through a multi-step validation process before returning it. This may produce **findings** that describe issues with the policy:\n", + "\n", + "| Finding Type | Meaning |\n", + "|---|---|\n", + "| `INVALID` | Cedar syntax or schema error β€” may block policy creation under strict mode |\n", + "| `WARNING` | Non-blocking issue β€” policy is syntactically valid but may behave unexpectedly |\n", + "\n", + "Findings can cause the `generatedPolicies` list to be empty if the service withholds assets with critical issues. Even when assets are present, calling `create_policy` may raise a validation error if findings exist.\n", + "\n", + "To override this and create the policy regardless of findings, pass `validation_mode=\"IGNORE_ALL_FINDINGS\"` to `create_policy` or `create_or_get_policy`. This notebook uses it **only as a fallback** β€” attempted after the default creation fails.\n", + "\n", + "> πŸ“– See [Policy Generation Validation Findings](https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/policy-generation-validation.html#policy-generation-findings) for details on each finding type and remediation guidance." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "execution": { + "iopub.execute_input": "2026-04-14T18:59:39.076527Z", + "iopub.status.busy": "2026-04-14T18:59:39.076310Z", + "iopub.status.idle": "2026-04-14T18:59:52.453197Z", + "shell.execute_reply": "2026-04-14T18:59:52.452375Z" + } + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 11:59:39,077 - bedrock_agentcore.policy - INFO - Generating policies from natural language: nl_policy_1776193179\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 11:59:39,078 - bedrock_agentcore.policy - INFO - Starting Policy Generation: nl_policy_1776193179\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "πŸ“ Generating Cedar Policy from Natural language...\n", + "\n", + "πŸ“ Simple natural language statement\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 11:59:39,324 - bedrock_agentcore.policy - INFO - βœ“ Policy Generation initiated: arn:aws:bedrock-agentcore:us-east-1:849138760372:policy-engine/InsurancePolicyEngine_NL2Cedar-dyq0mkonbr/policy-generation/nl_policy_1776193179-1z2ndmrcxt\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 11:59:39,325 - bedrock_agentcore.policy - INFO - Started generation nl_policy_1776193179-1z2ndmrcxt, waiting for completion...\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 11:59:39,500 - bedrock_agentcore.policy - INFO - Generation in progress (attempt 1/30)...\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 11:59:41,680 - bedrock_agentcore.policy - INFO - Generation in progress (attempt 2/30)...\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 11:59:43,843 - bedrock_agentcore.policy - INFO - Generation in progress (attempt 3/30)...\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 11:59:46,003 - bedrock_agentcore.policy - INFO - Generation in progress (attempt 4/30)...\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 11:59:48,152 - bedrock_agentcore.policy - INFO - Generation in progress (attempt 5/30)...\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 11:59:50,299 - bedrock_agentcore.policy - INFO - βœ“ Policy generation complete\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 11:59:52,311 - bedrock_agentcore.policy - INFO - Fetching generated policy assets...\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 11:59:52,449 - bedrock_agentcore.policy - INFO - βœ“ Fetched 1 generated policies\n" + ] + } + ], "source": [ "# Create Cedar policy\n", "print(\"\\n\\U0001f4dd Generating Cedar Policy from Natural language...\")\n", @@ -301,31 +765,61 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 6, + "metadata": { + "execution": { + "iopub.execute_input": "2026-04-14T18:59:52.457004Z", + "iopub.status.busy": "2026-04-14T18:59:52.456796Z", + "iopub.status.idle": "2026-04-14T18:59:52.477949Z", + "shell.execute_reply": "2026-04-14T18:59:52.477103Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cedar Policy:\n", + "============================================================\n", + "permit(\n", + " principal,\n", + " action == AgentCore::Action::\"ApplicationToolTarget___create_application\",\n", + " resource == AgentCore::Gateway::\"arn:aws:bedrock-agentcore:us-east-1:849138760372:gateway/gw-insurance-underwriting-mih1stx5g3\"\n", + ") when {\n", + " (((context.input).coverage_amount) < 1000000) && ((((context.input).applicant_region) == \"US\") || (((context.input).applicant_region) == \"CA\"))\n", + "};\n", + "============================================================\n" + ] + } + ], "source": [ "cedar_statement = None\n", "if result.get(\"status\") == \"GENERATED\" and result.get(\"generatedPolicies\"):\n", " generated_policy = result[\"generatedPolicies\"][0]\n", " findings = generated_policy.get(\"findings\", [])\n", " invalid = [f for f in findings if f.get(\"type\") == \"INVALID\"]\n", + " warnings = [f for f in findings if f.get(\"type\") == \"WARNING\"]\n", " if invalid:\n", - " print(\"⚠️ Policy generation returned INVALID findings:\")\n", + " print(\"⚠️ Policy generation returned INVALID findings (policy creation will be retried with IGNORE_ALL_FINDINGS):\")\n", " for f in invalid:\n", - " print(f\" {f.get('description', 'Unknown')}\")\n", + " print(f\" β€’ {f.get('description', 'Unknown')}\")\n", + " if warnings:\n", + " print(\"⚠️ Policy generation returned WARNING findings (policy creation may be retried with IGNORE_ALL_FINDINGS):\")\n", + " for f in warnings:\n", + " print(f\" β€’ {f.get('description', 'Unknown')}\")\n", + " cedar_statement = (\n", + " generated_policy.get(\"definition\", {}).get(\"cedar\", {}).get(\"statement\")\n", + " )\n", + " if cedar_statement:\n", + " print(\"Generated Cedar Policy:\")\n", + " print(\"=\" * 60)\n", + " print(cedar_statement)\n", + " print(\"=\" * 60)\n", " else:\n", - " cedar_statement = (\n", - " generated_policy.get(\"definition\", {}).get(\"cedar\", {}).get(\"statement\")\n", - " )\n", - " if cedar_statement:\n", - " print(\"Generated Cedar Policy:\")\n", - " print(\"=\" * 60)\n", - " print(cedar_statement)\n", - " print(\"=\" * 60)\n", - " else:\n", - " print(\"⚠️ No Cedar statement in generated policy\")\n", - " print(\"Raw asset:\", generated_policy)\n" + " print(\"⚠️ No Cedar statement in generated policy\")\n", + " print(\"Raw asset:\", generated_policy)\n", + "elif not result.get(\"generatedPolicies\"):\n", + " print(\"⚠️ generatedPolicies list is empty β€” NL2Cedar produced no assets (possibly due to findings blocking generation)\")" ] }, { @@ -337,26 +831,83 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 7, + "metadata": { + "execution": { + "iopub.execute_input": "2026-04-14T18:59:52.480332Z", + "iopub.status.busy": "2026-04-14T18:59:52.480172Z", + "iopub.status.idle": "2026-04-14T18:59:59.543966Z", + "shell.execute_reply": "2026-04-14T18:59:59.540987Z" + } + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 11:59:52,481 - bedrock_agentcore.policy - INFO - Creating or getting Policy: application_creation_policy\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 11:59:52,644 - bedrock_agentcore.policy - INFO - Creating Policy: application_creation_policy\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 11:59:52,974 - bedrock_agentcore.policy - INFO - βœ“ Policy creation initiated: arn:aws:bedrock-agentcore:us-east-1:849138760372:policy-engine/InsurancePolicyEngine_NL2Cedar-dyq0mkonbr/policy/application_creation_policy-ypxw2drkj7\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 11:59:52,977 - bedrock_agentcore.policy - INFO - Waiting for Policy to be active...\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 11:59:59,519 - bedrock_agentcore.policy - INFO - βœ“ Policy is active\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "βœ“ Policy ready: application_creation_policy-ypxw2drkj7\n" + ] + } + ], "source": [ "if cedar_statement:\n", " try:\n", - " application_creation_policy = policy_client.create_policy(\n", + " application_creation_policy = policy_client.create_or_get_policy(\n", " policy_engine_id=config[\"policy_engine_id\"],\n", " name=\"application_creation_policy\",\n", " description=\"Allow application creation when coverage is under $1M and region is US or CA\",\n", " definition={\"cedar\": {\"statement\": cedar_statement}},\n", " )\n", - " print(f\"βœ“ Policy created: {application_creation_policy['policyId']}\")\n", + " print(f\"βœ“ Policy ready: {application_creation_policy['policyId']}\")\n", " except Exception as e:\n", - " if \"already exists\" in str(e).lower() or \"conflict\" in str(type(e).__name__).lower():\n", - " print(\"⚠️ Policy 'application_creation_policy' already exists, continuing...\")\n", - " else:\n", - " raise\n", + " # Creation failed (e.g. validation findings blocked it) β€” retry with IGNORE_ALL_FINDINGS\n", + " print(f\"⚠️ Policy creation failed: {e}\")\n", + " print(\" Retrying with validation_mode='IGNORE_ALL_FINDINGS'...\")\n", + " application_creation_policy = policy_client.create_or_get_policy(\n", + " policy_engine_id=config[\"policy_engine_id\"],\n", + " name=\"application_creation_policy\",\n", + " description=\"Allow application creation when coverage is under $1M and region is US or CA\",\n", + " definition={\"cedar\": {\"statement\": cedar_statement}},\n", + " validation_mode=\"IGNORE_ALL_FINDINGS\",\n", + " )\n", + " print(f\"βœ“ Policy ready with IGNORE_ALL_FINDINGS: {application_creation_policy['policyId']}\")\n", "else:\n", - " print(\"⚠️ Skipping policy creation: no valid Cedar statement was generated\")\n" + " print(\"⚠️ Skipping policy creation: no Cedar statement was generated\")" ] }, { @@ -373,9 +924,156 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 8, + "metadata": { + "execution": { + "iopub.execute_input": "2026-04-14T18:59:59.545695Z", + "iopub.status.busy": "2026-04-14T18:59:59.545580Z", + "iopub.status.idle": "2026-04-14T19:00:19.389326Z", + "shell.execute_reply": "2026-04-14T19:00:19.388380Z" + } + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 11:59:59,547 - bedrock_agentcore.policy - INFO - Generating policies from natural language: nl_policy_1776193199\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 11:59:59,547 - bedrock_agentcore.policy - INFO - Starting Policy Generation: nl_policy_1776193199\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "πŸ“ Multi-line statement\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 11:59:59,803 - bedrock_agentcore.policy - INFO - βœ“ Policy Generation initiated: arn:aws:bedrock-agentcore:us-east-1:849138760372:policy-engine/InsurancePolicyEngine_NL2Cedar-dyq0mkonbr/policy-generation/nl_policy_1776193199-c_a8ekl0ns\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 11:59:59,804 - bedrock_agentcore.policy - INFO - Started generation nl_policy_1776193199-c_a8ekl0ns, waiting for completion...\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 11:59:59,947 - bedrock_agentcore.policy - INFO - Generation in progress (attempt 1/30)...\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 12:00:02,120 - bedrock_agentcore.policy - INFO - Generation in progress (attempt 2/30)...\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 12:00:04,271 - bedrock_agentcore.policy - INFO - Generation in progress (attempt 3/30)...\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 12:00:06,438 - bedrock_agentcore.policy - INFO - Generation in progress (attempt 4/30)...\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 12:00:08,602 - bedrock_agentcore.policy - INFO - Generation in progress (attempt 5/30)...\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 12:00:10,774 - bedrock_agentcore.policy - INFO - Generation in progress (attempt 6/30)...\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 12:00:12,891 - bedrock_agentcore.policy - INFO - Generation in progress (attempt 7/30)...\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 12:00:15,044 - bedrock_agentcore.policy - INFO - Generation in progress (attempt 8/30)...\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 12:00:17,195 - bedrock_agentcore.policy - INFO - βœ“ Policy generation complete\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 12:00:19,199 - bedrock_agentcore.policy - INFO - Fetching generated policy assets...\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 12:00:19,335 - bedrock_agentcore.policy - INFO - βœ“ Fetched 2 generated policies\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cedar Policy:\n", + "============================================================\n", + "forbid(\n", + " principal,\n", + " action == AgentCore::Action::\"ApplicationToolTarget___create_application\",\n", + " resource == AgentCore::Gateway::\"arn:aws:bedrock-agentcore:us-east-1:849138760372:gateway/gw-insurance-underwriting-mih1stx5g3\"\n", + ") when {\n", + " !(!(((context.input).coverage_amount) <= 0))\n", + "};\n", + "============================================================\n", + "Generated Cedar Policy:\n", + "============================================================\n", + "permit(\n", + " principal,\n", + " action == AgentCore::Action::\"RiskModelToolTarget___invoke_risk_model\",\n", + " resource == AgentCore::Gateway::\"arn:aws:bedrock-agentcore:us-east-1:849138760372:gateway/gw-insurance-underwriting-mih1stx5g3\"\n", + ") when {\n", + " ((context.input).data_governance_approval) == true\n", + "};\n", + "============================================================\n" + ] + } + ], "source": [ "print(\"\\nπŸ“ Multi-line statement\")\n", "\n", @@ -414,9 +1112,331 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 9, + "metadata": { + "execution": { + "iopub.execute_input": "2026-04-14T19:00:19.392382Z", + "iopub.status.busy": "2026-04-14T19:00:19.392170Z", + "iopub.status.idle": "2026-04-14T19:00:59.956104Z", + "shell.execute_reply": "2026-04-14T19:00:59.955161Z" + } + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 12:00:19,403 - bedrock_agentcore.policy - INFO - Generating policies from natural language: nl_policy_1776193219\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 12:00:19,404 - bedrock_agentcore.policy - INFO - Starting Policy Generation: nl_policy_1776193219\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "πŸ“ Principal Scope statements\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 12:00:19,675 - bedrock_agentcore.policy - INFO - βœ“ Policy Generation initiated: arn:aws:bedrock-agentcore:us-east-1:849138760372:policy-engine/InsurancePolicyEngine_NL2Cedar-dyq0mkonbr/policy-generation/nl_policy_1776193219-h3b085ns_m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 12:00:19,677 - bedrock_agentcore.policy - INFO - Started generation nl_policy_1776193219-h3b085ns_m, waiting for completion...\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 12:00:19,854 - bedrock_agentcore.policy - INFO - Generation in progress (attempt 1/30)...\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 12:00:21,970 - bedrock_agentcore.policy - INFO - Generation in progress (attempt 2/30)...\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 12:00:24,117 - bedrock_agentcore.policy - INFO - Generation in progress (attempt 3/30)...\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 12:00:26,271 - bedrock_agentcore.policy - INFO - Generation in progress (attempt 4/30)...\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 12:00:28,399 - bedrock_agentcore.policy - INFO - Generation in progress (attempt 5/30)...\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 12:00:30,560 - bedrock_agentcore.policy - INFO - βœ“ Policy generation complete\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 12:00:32,572 - bedrock_agentcore.policy - INFO - Fetching generated policy assets...\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 12:00:32,824 - bedrock_agentcore.policy - INFO - βœ“ Fetched 1 generated policies\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 12:00:32,825 - bedrock_agentcore.policy - INFO - Generating policies from natural language: nl_policy_1776193232\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 12:00:32,826 - bedrock_agentcore.policy - INFO - Starting Policy Generation: nl_policy_1776193232\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "============================================================\n", + "Natural Language: Allow principals with username \"test-user\" to invoke the risk model tool\n", + "Generated Cedar Policy:\n", + "============================================================\n", + "permit(\n", + " principal,\n", + " action == AgentCore::Action::\"RiskModelToolTarget___invoke_risk_model\",\n", + " resource == AgentCore::Gateway::\"arn:aws:bedrock-agentcore:us-east-1:849138760372:gateway/gw-insurance-underwriting-mih1stx5g3\"\n", + ") when {\n", + " (principal.hasTag(\"username\")) && ((principal.getTag(\"username\")) == \"test-user\")\n", + "};\n", + "============================================================\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 12:00:33,074 - bedrock_agentcore.policy - INFO - βœ“ Policy Generation initiated: arn:aws:bedrock-agentcore:us-east-1:849138760372:policy-engine/InsurancePolicyEngine_NL2Cedar-dyq0mkonbr/policy-generation/nl_policy_1776193232-g0luio2sq5\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 12:00:33,074 - bedrock_agentcore.policy - INFO - Started generation nl_policy_1776193232-g0luio2sq5, waiting for completion...\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 12:00:33,230 - bedrock_agentcore.policy - INFO - Generation in progress (attempt 1/30)...\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 12:00:35,403 - bedrock_agentcore.policy - INFO - Generation in progress (attempt 2/30)...\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 12:00:37,669 - bedrock_agentcore.policy - INFO - Generation in progress (attempt 3/30)...\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 12:00:39,869 - bedrock_agentcore.policy - INFO - Generation in progress (attempt 4/30)...\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 12:00:42,093 - bedrock_agentcore.policy - INFO - Generation in progress (attempt 5/30)...\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 12:00:44,258 - bedrock_agentcore.policy - INFO - βœ“ Policy generation complete\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 12:00:46,261 - bedrock_agentcore.policy - INFO - Fetching generated policy assets...\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 12:00:46,454 - bedrock_agentcore.policy - INFO - βœ“ Fetched 1 generated policies\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 12:00:46,458 - bedrock_agentcore.policy - INFO - Generating policies from natural language: nl_policy_1776193246\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 12:00:46,459 - bedrock_agentcore.policy - INFO - Starting Policy Generation: nl_policy_1776193246\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "============================================================\n", + "Natural Language: Forbid principals to access the approval tool unless they have the scope group:Controller [\"scope\"]\n", + "Generated Cedar Policy:\n", + "============================================================\n", + "forbid(\n", + " principal,\n", + " action in [AgentCore::Action::\"ApprovalToolTarget\"],\n", + " resource == AgentCore::Gateway::\"arn:aws:bedrock-agentcore:us-east-1:849138760372:gateway/gw-insurance-underwriting-mih1stx5g3\"\n", + ") when {\n", + " !((principal.hasTag(\"scope\")) && ((principal.getTag(\"scope\")) like \"*group:Controller*\"))\n", + "};\n", + "============================================================\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 12:00:46,728 - bedrock_agentcore.policy - INFO - βœ“ Policy Generation initiated: arn:aws:bedrock-agentcore:us-east-1:849138760372:policy-engine/InsurancePolicyEngine_NL2Cedar-dyq0mkonbr/policy-generation/nl_policy_1776193246-o9h8la5kyd\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 12:00:46,728 - bedrock_agentcore.policy - INFO - Started generation nl_policy_1776193246-o9h8la5kyd, waiting for completion...\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 12:00:46,890 - bedrock_agentcore.policy - INFO - Generation in progress (attempt 1/30)...\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 12:00:49,057 - bedrock_agentcore.policy - INFO - Generation in progress (attempt 2/30)...\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 12:00:51,251 - bedrock_agentcore.policy - INFO - Generation in progress (attempt 3/30)...\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 12:00:53,390 - bedrock_agentcore.policy - INFO - Generation in progress (attempt 4/30)...\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 12:00:55,572 - bedrock_agentcore.policy - INFO - Generation in progress (attempt 5/30)...\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 12:00:57,716 - bedrock_agentcore.policy - INFO - βœ“ Policy generation complete\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 12:00:59,723 - bedrock_agentcore.policy - INFO - Fetching generated policy assets...\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 12:00:59,950 - bedrock_agentcore.policy - INFO - βœ“ Fetched 1 generated policies\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "============================================================\n", + "Natural Language: Block principals from using risk model tool and approval tool unless the principal has role \"senior-adjuster\"\n", + "Generated Cedar Policy:\n", + "============================================================\n", + "forbid(\n", + " principal,\n", + " action in [AgentCore::Action::\"RiskModelToolTarget\",AgentCore::Action::\"ApprovalToolTarget\"],\n", + " resource == AgentCore::Gateway::\"arn:aws:bedrock-agentcore:us-east-1:849138760372:gateway/gw-insurance-underwriting-mih1stx5g3\"\n", + ") when {\n", + " !((principal.hasTag(\"role\")) && ((principal.getTag(\"role\")) == \"senior-adjuster\"))\n", + "};\n", + "============================================================\n" + ] + } + ], "source": [ "print(\"\\nπŸ“ Principal Scope statements\")\n", "\n", @@ -463,9 +1483,250 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 10, + "metadata": { + "execution": { + "iopub.execute_input": "2026-04-14T19:00:59.961362Z", + "iopub.status.busy": "2026-04-14T19:00:59.961045Z", + "iopub.status.idle": "2026-04-14T19:01:32.755562Z", + "shell.execute_reply": "2026-04-14T19:01:32.754906Z" + } + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 12:01:00,081 - bedrock_agentcore.policy - INFO - 🧹 Cleaning up Policy Engine: InsurancePolicyEngine_NL2Cedar-dyq0mkonbr\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "🧹 Cleaning up Policy Engine...\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 12:01:00,439 - bedrock_agentcore.policy - INFO - Found 1 policies to delete\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 12:01:00,440 - bedrock_agentcore.policy - INFO - β€’ Deleting policy: application_creation_policy\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 12:01:00,440 - bedrock_agentcore.policy - INFO - Deleting Policy: application_creation_policy-ypxw2drkj7\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 12:01:00,711 - bedrock_agentcore.policy - INFO - βœ“ Policy deletion initiated: application_creation_policy-ypxw2drkj7\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 12:01:00,712 - bedrock_agentcore.policy - INFO - βœ“ Policy deletion initiated: application_creation_policy\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 12:01:05,130 - bedrock_agentcore.policy - INFO - βœ“ Policy deleted\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 12:01:05,133 - bedrock_agentcore.policy - INFO - β€’ Deleting policy engine: InsurancePolicyEngine_NL2Cedar-dyq0mkonbr\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 12:01:05,139 - bedrock_agentcore.policy - INFO - Deleting Policy Engine: InsurancePolicyEngine_NL2Cedar-dyq0mkonbr\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 12:01:05,411 - bedrock_agentcore.policy - INFO - βœ“ Policy Engine deletion initiated: InsurancePolicyEngine_NL2Cedar-dyq0mkonbr\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 12:01:05,413 - bedrock_agentcore.policy - INFO - βœ“ Policy engine deleted\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 12:01:05,421 - bedrock_agentcore.policy - INFO - βœ… Policy Engine cleanup complete\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 12:01:05,440 - bedrock_agentcore.gateway - INFO - 🧹 Cleaning up Gateway resources...\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 12:01:05,440 - bedrock_agentcore.gateway - INFO - β€’ Finding targets for gateway: gw-insurance-underwriting-mih1stx5g3\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "βœ“ Policy Engine cleaned up\n", + "\n", + "🧹 Cleaning up Gateway...\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 12:01:05,780 - bedrock_agentcore.gateway - INFO - Found 3 targets to delete\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 12:01:05,780 - bedrock_agentcore.gateway - INFO - β€’ Deleting target: JEM7QJNM6C\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 12:01:05,949 - bedrock_agentcore.gateway - INFO - βœ“ Target deletion initiated: JEM7QJNM6C\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 12:01:10,957 - bedrock_agentcore.gateway - INFO - β€’ Deleting target: QBKMNZSOB6\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 12:01:11,132 - bedrock_agentcore.gateway - INFO - βœ“ Target deletion initiated: QBKMNZSOB6\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 12:01:16,137 - bedrock_agentcore.gateway - INFO - β€’ Deleting target: ZJC11T4QSN\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 12:01:16,334 - bedrock_agentcore.gateway - INFO - βœ“ Target deletion initiated: ZJC11T4QSN\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 12:01:21,342 - bedrock_agentcore.gateway - INFO - β€’ Verifying targets deletion...\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 12:01:26,532 - bedrock_agentcore.gateway - INFO - βœ“ All targets deleted\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 12:01:26,534 - bedrock_agentcore.gateway - INFO - β€’ Deleting gateway: gw-insurance-underwriting-mih1stx5g3\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 12:01:26,731 - bedrock_agentcore.gateway - INFO - βœ“ Gateway deleted: gw-insurance-underwriting-mih1stx5g3\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 12:01:26,775 - bedrock_agentcore.gateway - INFO - β€’ Deleting Cognito domain: agentcore-7c8344ad\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 12:01:27,466 - bedrock_agentcore.gateway - INFO - βœ“ Cognito domain deleted\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 12:01:32,484 - bedrock_agentcore.gateway - INFO - β€’ Deleting Cognito user pool: us-east-1_bZgWrWOLe\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 12:01:32,733 - bedrock_agentcore.gateway - INFO - βœ“ Cognito user pool deleted\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-04-14 12:01:32,735 - bedrock_agentcore.gateway - INFO - βœ… Cleanup complete\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "βœ… Cleanup complete!\n" + ] + } + ], "source": [ "from bedrock_agentcore_starter_toolkit.operations.gateway.client import GatewayClient\n", "from bedrock_agentcore_starter_toolkit.operations.policy.client import PolicyClient\n", @@ -510,4 +1771,4 @@ }, "nbformat": 4, "nbformat_minor": 4 -} \ No newline at end of file +} diff --git a/01-tutorials/08-AgentCore-policy/03-Fine-Grained-Access-Control/policy_for_agentcore_tutorial.ipynb b/01-tutorials/08-AgentCore-policy/03-Fine-Grained-Access-Control/policy_for_agentcore_tutorial.ipynb index a0ff2ad5..2e977bd3 100644 --- a/01-tutorials/08-AgentCore-policy/03-Fine-Grained-Access-Control/policy_for_agentcore_tutorial.ipynb +++ b/01-tutorials/08-AgentCore-policy/03-Fine-Grained-Access-Control/policy_for_agentcore_tutorial.ipynb @@ -355,143 +355,7 @@ "execution_count": null, "metadata": {}, "outputs": [], - "source": [ - "# Gateway control client for managing gateway configuration\n", - "gateway_control_client = session.client(\"bedrock-agentcore-control\", region_name=REGION)\n", - "\n", - "\n", - "def get_gateway_details() -> Dict[str, Any]:\n", - " \"\"\"Get current gateway details.\"\"\"\n", - " return gateway_control_client.get_gateway(gatewayIdentifier=GATEWAY_ID)\n", - "\n", - "\n", - "def wait_for_gateway_ready(max_wait: int = 300, poll_interval: int = 5) -> bool:\n", - " \"\"\"Wait for gateway to reach READY state.\"\"\"\n", - " terminal_states = {\"READY\", \"FAILED\", \"UPDATE_UNSUCCESSFUL\"}\n", - " start_time = time.time()\n", - "\n", - " while time.time() - start_time < max_wait:\n", - " gateway = get_gateway_details()\n", - " status = gateway.get(\"status\", \"UNKNOWN\")\n", - " print(f\" Gateway status: {status}\")\n", - "\n", - " if status == \"READY\":\n", - " return True\n", - " if status in terminal_states:\n", - " print(f\" βœ— Gateway reached terminal state: {status}\")\n", - " return False\n", - "\n", - " time.sleep(poll_interval)\n", - "\n", - " print(\" βœ— Timeout waiting for gateway\")\n", - " return False\n", - "\n", - "\n", - "def validate_and_fix_gateway_authorizer() -> bool:\n", - " \"\"\"\n", - " Validate gateway authorizer configuration and fix if needed.\n", - "\n", - " Cognito access tokens don't have an 'aud' claim, so allowedAudience\n", - " must not be set or the gateway will reject valid tokens.\n", - "\n", - " Returns:\n", - " True if configuration is valid or was fixed successfully\n", - " \"\"\"\n", - " print(\"\\nValidating Gateway Authorizer Configuration\")\n", - " print(\"=\" * 70)\n", - "\n", - " gw = get_gateway_details()\n", - " jwt_config = gw.get(\"authorizerConfiguration\", {}).get(\"customJWTAuthorizer\", {})\n", - "\n", - " # Check current configuration\n", - " discovery_url = jwt_config.get(\"discoveryUrl\")\n", - " allowed_clients = jwt_config.get(\"allowedClients\", [])\n", - " allowed_audience = jwt_config.get(\"allowedAudience\", [])\n", - " allowed_scopes = jwt_config.get(\"allowedScopes\", [])\n", - "\n", - " print(f\" Discovery URL: {discovery_url or 'NOT SET'}\")\n", - " print(f\" Allowed Clients: {allowed_clients}\")\n", - " print(f\" Allowed Audience: {allowed_audience}\")\n", - " print(f\" Allowed Scopes: {allowed_scopes}\")\n", - "\n", - " # Build expected discovery URL\n", - " expected_discovery_url = f\"https://cognito-idp.{REGION}.amazonaws.com/{USER_POOL_ID}/.well-known/openid-configuration\"\n", - "\n", - " # Check if configuration needs fixing\n", - " needs_fix = False\n", - " reasons = []\n", - "\n", - " if not discovery_url:\n", - " needs_fix = True\n", - " reasons.append(\"Discovery URL not set\")\n", - " elif discovery_url != expected_discovery_url:\n", - " needs_fix = True\n", - " reasons.append(\"Discovery URL mismatch\")\n", - "\n", - " if CLIENT_ID not in allowed_clients:\n", - " needs_fix = True\n", - " reasons.append(f\"Client ID {CLIENT_ID} not in allowed clients\")\n", - "\n", - " # Cognito access tokens don't have 'aud' claim - allowedAudience must be empty\n", - " if allowed_audience:\n", - " needs_fix = True\n", - " reasons.append(\n", - " \"allowedAudience is set but Cognito access tokens don't have 'aud' claim\"\n", - " )\n", - "\n", - " if not needs_fix:\n", - " print(\"\\nβœ“ Gateway authorizer configuration is valid\")\n", - " return True\n", - "\n", - " print(\"\\n⚠️ Configuration needs fixing:\")\n", - " for reason in reasons:\n", - " print(f\" - {reason}\")\n", - "\n", - " # Fix the configuration\n", - " print(\"\\n⏳ Updating gateway authorizer configuration...\")\n", - "\n", - " # Get scope from config if available\n", - " scope = CONFIG.get(\"client_info\", {}).get(\"scope\", \"\")\n", - "\n", - " new_auth_config = {\n", - " \"customJWTAuthorizer\": {\n", - " \"discoveryUrl\": expected_discovery_url,\n", - " \"allowedClients\": [CLIENT_ID],\n", - " # Do NOT set allowedAudience - Cognito access tokens don't have 'aud' claim\n", - " }\n", - " }\n", - "\n", - " # Add scope if configured\n", - " if scope:\n", - " new_auth_config[\"customJWTAuthorizer\"][\"allowedScopes\"] = [scope]\n", - "\n", - " try:\n", - " gateway_control_client.update_gateway(\n", - " gatewayIdentifier=GATEWAY_ID,\n", - " name=gw.get(\"name\"),\n", - " roleArn=gw.get(\"roleArn\"),\n", - " protocolType=gw.get(\"protocolType\", \"MCP\"),\n", - " authorizerType=\"CUSTOM_JWT\",\n", - " authorizerConfiguration=new_auth_config,\n", - " policyEngineConfiguration=gw.get(\"policyEngineConfiguration\", {}),\n", - " )\n", - "\n", - " print(\"\\n⏳ Waiting for gateway to become READY...\")\n", - " if wait_for_gateway_ready():\n", - " print(\"\\nβœ“ Gateway authorizer configuration fixed successfully\")\n", - " return True\n", - " else:\n", - " print(\"\\nβœ— Gateway did not reach READY state\")\n", - " return False\n", - "\n", - " except ClientError as e:\n", - " print(f\"\\nβœ— Error updating gateway: {e}\")\n", - " return False\n", - "\n", - "\n", - "# Validate and fix gateway authorizer if needed\n", - "validate_and_fix_gateway_authorizer()" - ] + "source": "# Gateway control client for managing gateway configuration\ngateway_control_client = session.client(\"bedrock-agentcore-control\", region_name=REGION)\n\n\ndef get_gateway_details() -> Dict[str, Any]:\n \"\"\"Get current gateway details.\"\"\"\n return gateway_control_client.get_gateway(gatewayIdentifier=GATEWAY_ID)\n\n\ndef wait_for_gateway_ready(max_wait: int = 300, poll_interval: int = 5) -> bool:\n \"\"\"Wait for gateway to reach READY state.\"\"\"\n terminal_states = {\"READY\", \"FAILED\", \"UPDATE_UNSUCCESSFUL\"}\n start_time = time.time()\n\n while time.time() - start_time < max_wait:\n gateway = get_gateway_details()\n status = gateway.get(\"status\", \"UNKNOWN\")\n print(f\" Gateway status: {status}\")\n\n if status == \"READY\":\n return True\n if status in terminal_states:\n print(f\" βœ— Gateway reached terminal state: {status}\")\n return False\n\n time.sleep(poll_interval)\n\n print(\" βœ— Timeout waiting for gateway\")\n return False\n\n\ndef validate_and_fix_gateway_authorizer() -> bool:\n \"\"\"\n Validate gateway authorizer configuration and fix if needed.\n\n Cognito access tokens don't have an 'aud' claim, so allowedAudience\n must not be set or the gateway will reject valid tokens.\n\n Returns:\n True if configuration is valid or was fixed successfully\n \"\"\"\n print(\"\\nValidating Gateway Authorizer Configuration\")\n print(\"=\" * 70)\n\n gw = get_gateway_details()\n jwt_config = gw.get(\"authorizerConfiguration\", {}).get(\"customJWTAuthorizer\", {})\n\n # Check current configuration\n discovery_url = jwt_config.get(\"discoveryUrl\")\n allowed_clients = jwt_config.get(\"allowedClients\", [])\n allowed_audience = jwt_config.get(\"allowedAudience\", [])\n allowed_scopes = jwt_config.get(\"allowedScopes\", [])\n\n print(f\" Discovery URL: {discovery_url or 'NOT SET'}\")\n print(f\" Allowed Clients: {allowed_clients}\")\n print(f\" Allowed Audience: {allowed_audience}\")\n print(f\" Allowed Scopes: {allowed_scopes}\")\n\n # Build expected discovery URL\n expected_discovery_url = f\"https://cognito-idp.{REGION}.amazonaws.com/{USER_POOL_ID}/.well-known/openid-configuration\"\n\n # Check if configuration needs fixing\n needs_fix = False\n reasons = []\n\n if not discovery_url:\n needs_fix = True\n reasons.append(\"Discovery URL not set\")\n elif discovery_url != expected_discovery_url:\n needs_fix = True\n reasons.append(\"Discovery URL mismatch\")\n\n if CLIENT_ID not in allowed_clients:\n needs_fix = True\n reasons.append(f\"Client ID {CLIENT_ID} not in allowed clients\")\n\n # Cognito access tokens don't have 'aud' claim - allowedAudience must be empty\n if allowed_audience:\n needs_fix = True\n reasons.append(\n \"allowedAudience is set but Cognito access tokens don't have 'aud' claim\"\n )\n\n if not needs_fix:\n print(\"\\nβœ“ Gateway authorizer configuration is valid\")\n return True\n\n print(\"\\n⚠️ Configuration needs fixing:\")\n for reason in reasons:\n print(f\" - {reason}\")\n\n # Fix the configuration\n print(\"\\n⏳ Updating gateway authorizer configuration...\")\n\n # Get scope from config if available\n scope = CONFIG.get(\"client_info\", {}).get(\"scope\", \"\")\n\n new_auth_config = {\n \"customJWTAuthorizer\": {\n \"discoveryUrl\": expected_discovery_url,\n \"allowedClients\": [CLIENT_ID],\n # Do NOT set allowedAudience - Cognito access tokens don't have 'aud' claim\n }\n }\n\n # Add scope if configured\n if scope:\n new_auth_config[\"customJWTAuthorizer\"][\"allowedScopes\"] = [scope]\n\n try:\n # Only include policyEngineConfiguration if one is already attached\n pe_config = gw.get(\"policyEngineConfiguration\", {})\n update_params = dict(\n gatewayIdentifier=GATEWAY_ID,\n name=gw.get(\"name\"),\n roleArn=gw.get(\"roleArn\"),\n protocolType=gw.get(\"protocolType\", \"MCP\"),\n authorizerType=\"CUSTOM_JWT\",\n authorizerConfiguration=new_auth_config,\n )\n if pe_config and pe_config.get(\"arn\"):\n update_params[\"policyEngineConfiguration\"] = pe_config\n\n gateway_control_client.update_gateway(**update_params)\n\n print(\"\\n⏳ Waiting for gateway to become READY...\")\n if wait_for_gateway_ready():\n print(\"\\nβœ“ Gateway authorizer configuration fixed successfully\")\n return True\n else:\n print(\"\\nβœ— Gateway did not reach READY state\")\n return False\n\n except ClientError as e:\n print(f\"\\nβœ— Error updating gateway: {e}\")\n return False\n\n\n# Validate and fix gateway authorizer if needed\nvalidate_and_fix_gateway_authorizer()" }, { "cell_type": "markdown", @@ -1172,73 +1036,7 @@ "execution_count": null, "metadata": {}, "outputs": [], - "source": [ - "# Note: gateway_control_client, get_gateway_details, and wait_for_gateway_ready\n", - "# are already defined in Step 1.3\n", - "\n", - "\n", - "def attach_policy_engine_to_gateway(mode: str = \"ENFORCE\") -> bool:\n", - " \"\"\"\n", - " Attach the Policy Engine to the Gateway if not already attached.\n", - "\n", - " Args:\n", - " mode: Policy engine mode ('LOG_ONLY' or 'ENFORCE')\n", - "\n", - " Returns:\n", - " True if successful or already attached, False otherwise\n", - " \"\"\"\n", - " print(\"\\nAttaching Policy Engine to Gateway\")\n", - " print(\"=\" * 70)\n", - "\n", - " # Get current gateway configuration\n", - " gateway_config = get_gateway_details()\n", - "\n", - " # Check if policy engine is already attached\n", - " existing_pe = gateway_config.get(\"policyEngineConfiguration\", {})\n", - " if existing_pe.get(\"arn\"):\n", - " print(f\"βœ“ Policy Engine already attached: {existing_pe.get('arn')}\")\n", - " print(f\" Mode: {existing_pe.get('mode', 'N/A')}\")\n", - " return True\n", - "\n", - " # Get policy engine ARN\n", - " engine = get_policy_engine(POLICY_ENGINE_ID)\n", - " if not engine:\n", - " print(\"βœ— Could not get policy engine details\")\n", - " return False\n", - "\n", - " policy_engine_arn = engine.get(\"policyEngineArn\")\n", - " print(f\" Policy Engine ARN: {policy_engine_arn}\")\n", - " print(f\" Mode: {mode}\")\n", - "\n", - " try:\n", - " # Use boto3 client to update gateway\n", - " gateway_control_client.update_gateway(\n", - " gatewayIdentifier=GATEWAY_ID,\n", - " name=gateway_config.get(\"name\"),\n", - " roleArn=gateway_config.get(\"roleArn\"),\n", - " protocolType=gateway_config.get(\"protocolType\", \"MCP\"),\n", - " authorizerType=gateway_config.get(\"authorizerType\", \"CUSTOM_JWT\"),\n", - " policyEngineConfiguration={\"arn\": policy_engine_arn, \"mode\": mode},\n", - " )\n", - "\n", - " print(\"βœ“ Gateway update request accepted\")\n", - " print(\"\\n⏳ Waiting for gateway to become READY...\")\n", - "\n", - " if wait_for_gateway_ready():\n", - " print(\"βœ“ Policy Engine attached successfully\")\n", - " return True\n", - " else:\n", - " print(\"βœ— Gateway did not reach READY state\")\n", - " return False\n", - "\n", - " except ClientError as e:\n", - " print(f\"βœ— Error updating gateway: {e}\")\n", - " return False\n", - "\n", - "\n", - "# Attach policy engine to gateway\n", - "attach_policy_engine_to_gateway(mode=\"ENFORCE\")" - ] + "source": "# Note: gateway_control_client, get_gateway_details, and wait_for_gateway_ready\n# are already defined in Step 1.3\n\n\ndef attach_policy_engine_to_gateway(mode: str = \"ENFORCE\") -> bool:\n \"\"\"\n Attach the Policy Engine to the Gateway if not already attached.\n If a different policy engine is already attached, re-attach with the current one.\n\n Args:\n mode: Policy engine mode ('LOG_ONLY' or 'ENFORCE')\n\n Returns:\n True if successful or already attached, False otherwise\n \"\"\"\n print(\"\\nAttaching Policy Engine to Gateway\")\n print(\"=\" * 70)\n\n # Get current gateway configuration\n gateway_config = get_gateway_details()\n\n # Check if the correct policy engine is already attached\n existing_pe = gateway_config.get(\"policyEngineConfiguration\", {})\n engine = get_policy_engine(POLICY_ENGINE_ID)\n if not engine:\n print(\"βœ— Could not get policy engine details\")\n return False\n\n policy_engine_arn = engine.get(\"policyEngineArn\")\n\n if existing_pe.get(\"arn\") == policy_engine_arn and existing_pe.get(\"mode\") == mode:\n print(f\"βœ“ Correct Policy Engine already attached: {existing_pe.get('arn')}\")\n print(f\" Mode: {existing_pe.get('mode', 'N/A')}\")\n return True\n\n if existing_pe.get(\"arn\"):\n print(f\" Replacing attached policy engine: {existing_pe.get('arn')}\")\n print(f\" Policy Engine ARN: {policy_engine_arn}\")\n print(f\" Mode: {mode}\")\n\n try:\n # Must preserve existing authorizer configuration when updating gateway\n auth_config = gateway_config.get(\"authorizerConfiguration\", {})\n\n gateway_control_client.update_gateway(\n gatewayIdentifier=GATEWAY_ID,\n name=gateway_config.get(\"name\"),\n roleArn=gateway_config.get(\"roleArn\"),\n protocolType=gateway_config.get(\"protocolType\", \"MCP\"),\n authorizerType=gateway_config.get(\"authorizerType\", \"CUSTOM_JWT\"),\n authorizerConfiguration=auth_config,\n policyEngineConfiguration={\"arn\": policy_engine_arn, \"mode\": mode},\n )\n\n print(\"βœ“ Gateway update request accepted\")\n print(\"\\n⏳ Waiting for gateway to become READY...\")\n\n if wait_for_gateway_ready():\n print(\"βœ“ Policy Engine attached successfully\")\n return True\n else:\n print(\"βœ— Gateway did not reach READY state\")\n return False\n\n except ClientError as e:\n print(f\"βœ— Error updating gateway: {e}\")\n return False\n\n\n# Attach policy engine to gateway\nattach_policy_engine_to_gateway(mode=\"ENFORCE\")" }, { "cell_type": "markdown", @@ -1275,61 +1073,7 @@ "execution_count": null, "metadata": {}, "outputs": [], - "source": [ - "def cleanup_existing_policies(require_confirmation: bool = True) -> int:\n", - " \"\"\"\n", - " Delete all existing policies in the policy engine.\n", - "\n", - " Args:\n", - " require_confirmation: If True, asks user for confirmation before deleting\n", - "\n", - " Returns:\n", - " Number of policies deleted\n", - " \"\"\"\n", - " print(\"\\n🧹 Checking for existing policies...\")\n", - " print(\"=\" * 70)\n", - "\n", - " policies = list_policies()\n", - "\n", - " if not policies:\n", - " print(\"βœ“ No existing policies found. Ready to proceed.\")\n", - " return 0\n", - "\n", - " print(f\"\\n⚠️ Found {len(policies)} existing policy/policies:\")\n", - " for p in policies:\n", - " print(\n", - " f\" - {p.get('name', 'unnamed')} (ID: {p.get('policyId')}, Status: {p.get('status')})\"\n", - " )\n", - "\n", - " if require_confirmation:\n", - " print(\"\\n\" + \"-\" * 70)\n", - " confirm = (\n", - " input(\"Do you want to DELETE all existing policies? (yes/no): \")\n", - " .strip()\n", - " .lower()\n", - " )\n", - " if confirm != \"yes\":\n", - " print(\"\\n⏭️ Skipping cleanup. Existing policies will remain.\")\n", - " print(\" Note: This may cause unexpected policy evaluation results.\")\n", - " return 0\n", - "\n", - " print(\"\\nπŸ—‘οΈ Deleting existing policies...\")\n", - " deleted_count = 0\n", - " for p in policies:\n", - " policy_id = p.get(\"policyId\")\n", - " if policy_id and delete_policy(policy_id):\n", - " deleted_count += 1\n", - "\n", - " print(f\"\\nβœ“ Deleted {deleted_count}/{len(policies)} policies\")\n", - " return deleted_count\n", - "\n", - "\n", - "# Track created policies for cleanup at the end\n", - "CREATED_POLICIES = []\n", - "\n", - "# Clean up existing policies before starting tests\n", - "cleanup_existing_policies(require_confirmation=True)" - ] + "source": "def cleanup_existing_policies(require_confirmation: bool = True) -> int:\n \"\"\"\n Delete all existing policies in the policy engine.\n\n Args:\n require_confirmation: If True, asks user for confirmation before deleting\n\n Returns:\n Number of policies deleted\n \"\"\"\n print(\"\\n🧹 Checking for existing policies...\")\n print(\"=\" * 70)\n\n policies = list_policies()\n\n if not policies:\n print(\"βœ“ No existing policies found. Ready to proceed.\")\n return 0\n\n print(f\"\\n⚠️ Found {len(policies)} existing policy/policies:\")\n for p in policies:\n print(\n f\" - {p.get('name', 'unnamed')} (ID: {p.get('policyId')}, Status: {p.get('status')})\"\n )\n\n if require_confirmation:\n print(\"\\n\" + \"-\" * 70)\n confirm = (\n input(\"Do you want to DELETE all existing policies? (yes/no): \")\n .strip()\n .lower()\n )\n if confirm != \"yes\":\n print(\"\\n⏭️ Skipping cleanup. Existing policies will remain.\")\n print(\" Note: This may cause unexpected policy evaluation results.\")\n return 0\n\n print(\"\\nπŸ—‘οΈ Deleting existing policies...\")\n deleted_count = 0\n for p in policies:\n policy_id = p.get(\"policyId\")\n if policy_id and delete_policy(policy_id):\n deleted_count += 1\n\n print(f\"\\nβœ“ Deleted {deleted_count}/{len(policies)} policies\")\n return deleted_count\n\n\n# Track created policies for cleanup at the end\nCREATED_POLICIES = []\n\n# Clean up existing policies before starting tests (no confirmation needed)\ncleanup_existing_policies(require_confirmation=False)" }, { "cell_type": "markdown", @@ -1343,24 +1087,7 @@ "execution_count": null, "metadata": {}, "outputs": [], - "source": [ - "print(\"=\" * 70)\n", - "print(\"TEST SCENARIO 1: Department-Based Access Control\")\n", - "print(\"=\" * 70)\n", - "\n", - "# Configure Lambda with department_name = \"finance\"\n", - "claims_finance = {\n", - " \"department_name\": \"finance\",\n", - " \"employee_level\": \"senior\",\n", - " \"cost_center\": \"CC-1001\",\n", - "}\n", - "\n", - "lambda_arn = create_lambda_function(claims_finance)\n", - "configure_cognito_trigger(lambda_arn)\n", - "\n", - "print(\"\\nβœ“ Lambda configured with claims:\")\n", - "print(json.dumps(claims_finance, indent=2))" - ] + "source": "print(\"=\" * 70)\nprint(\"TEST SCENARIO 1: Department-Based Access Control\")\nprint(\"=\" * 70)\n\n# Configure Lambda with department_name = \"finance\"\nclaims_finance = {\n \"department_name\": \"finance\",\n \"employee_level\": \"senior\",\n \"cost_center\": \"CC-1001\",\n}\n\nlambda_arn = create_lambda_function(claims_finance)\nconfigure_cognito_trigger(lambda_arn)\n\n# Wait for Lambda trigger to propagate before requesting a token\nprint(\"\\n⏳ Waiting for Cognito trigger to propagate...\")\ntime.sleep(15)\n\nprint(\"\\nβœ“ Lambda configured with claims:\")\nprint(json.dumps(claims_finance, indent=2))" }, { "cell_type": "markdown", @@ -1743,26 +1470,7 @@ { "cell_type": "markdown", "metadata": {}, - "source": [ - "---\n", - "\n", - "## Part 7: Test Scenario 3 - Principal ID-Based Access Control\n", - "\n", - "In this scenario, we create a policy that only allows requests from a specific principal (identified by the `sub` claim in Client Credentials Flow).\n", - "\n", - "### Cedar Policy Pattern\n", - "\n", - "In Policy for Amazon Bedrock AgentCore, the principal has a single attribute that can be evaluated: `id`. For Client Credentials Flow, this corresponds to the `sub` claim in the JWT token (which equals the `client_id`):\n", - "\n", - "```cedar\n", - "permit(principal, action, resource)\n", - "when {\n", - " principal.id == \"your-client-id\"\n", - "};\n", - "```\n", - "\n", - "**Note**: Unlike custom claims accessed via `principal.hasTag()` and `principal.getTag()`, the principal ID is accessed directly via `principal.id`." - ] + "source": "---\n\n## Part 7: Test Scenario 3 - Principal ID-Based Access Control\n\nIn this scenario, we create a policy that only allows requests from a specific principal (identified by the `sub` claim in Client Credentials Flow).\n\n### Cedar Policy Pattern\n\nIn Client Credentials Flow, the `sub` claim in the JWT token equals the `client_id`. Because all JWT claims are surfaced as **principal tags**, the caller's identity can be matched via `getTag(\"sub\")`:\n\n```cedar\npermit(principal, action, resource)\nwhen {\n principal.hasTag(\"sub\") &&\n principal.getTag(\"sub\") == \"your-client-id\"\n};\n```\n\n**Note**: The `sub` claim in a Cognito M2M access token equals the app client's `client_id`. Checking `getTag(\"sub\")` uniquely identifies the calling principal, equivalent to a principal-ID check." }, { "cell_type": "code", @@ -1793,35 +1501,7 @@ "execution_count": null, "metadata": {}, "outputs": [], - "source": [ - "policy_name = f\"principal_id_policy_{int(time.time())}\"\n", - "\n", - "# In Client Credentials Flow, principal.id equals the 'sub' claim (which is the client_id)\n", - "cedar_statement = f'''permit(principal,\n", - " action == AgentCore::Action::\"RefundToolTarget___refund\",\n", - " resource == AgentCore::Gateway::\"{GATEWAY_ARN}\")\n", - "when {{\n", - " principal.id == \"{CLIENT_ID}\"\n", - "}};'''\n", - "\n", - "print(f\"Cedar statement:\\n{cedar_statement}\")\n", - "\n", - "policy_id = create_cedar_policy(\n", - " policy_name=policy_name,\n", - " cedar_statement=cedar_statement,\n", - " description=f\"Allow requests only from principal.id: {CLIENT_ID}\",\n", - ")\n", - "\n", - "if policy_id:\n", - " CREATED_POLICIES.append(policy_id)\n", - "\n", - " # Wait for policy to become ACTIVE\n", - " print(\"\\n⏳ Waiting for policy to become ACTIVE...\")\n", - " if wait_for_policy_active(policy_id):\n", - " print(\"βœ“ Policy is ACTIVE and ready for testing\")\n", - " else:\n", - " print(\"\\n⚠️ Policy did not become ACTIVE. Tests may fail.\")" - ] + "source": "policy_name = f\"principal_id_policy_{int(time.time())}\"\n\n# In Client Credentials Flow, the 'sub' claim equals client_id and is accessible\n# as a principal tag via getTag(\"sub\")\ncedar_statement = f'''permit(principal,\n action == AgentCore::Action::\"RefundToolTarget___refund\",\n resource == AgentCore::Gateway::\"{GATEWAY_ARN}\")\nwhen {{\n principal.hasTag(\"sub\") &&\n principal.getTag(\"sub\") == \"{CLIENT_ID}\"\n}};'''\n\nprint(f\"Cedar statement:\\n{cedar_statement}\")\n\npolicy_id = create_cedar_policy(\n policy_name=policy_name,\n cedar_statement=cedar_statement,\n description=f\"Allow requests only from principal with sub (client_id): {CLIENT_ID}\",\n)\n\nif policy_id:\n CREATED_POLICIES.append(policy_id)\n\n # Wait for policy to become ACTIVE\n print(\"\\n⏳ Waiting for policy to become ACTIVE...\")\n if wait_for_policy_active(policy_id):\n print(\"βœ“ Policy is ACTIVE and ready for testing\")\n else:\n print(\"\\n⚠️ Policy did not become ACTIVE. Tests may fail.\")" }, { "cell_type": "markdown", @@ -1835,33 +1515,7 @@ "execution_count": null, "metadata": {}, "outputs": [], - "source": [ - "print(\"\\n\" + \"=\" * 70)\n", - "print(f\"Test 3.1: Request with principal.id='{CLIENT_ID}'\")\n", - "print(\"=\" * 70)\n", - "\n", - "token = get_bearer_token()\n", - "claims = decode_token(token)\n", - "# In Client Credentials Flow, 'sub' claim equals client_id and maps to principal.id\n", - "print(f\"\\nToken 'sub' claim (principal.id): {claims.get('sub')}\")\n", - "print(f\"Token 'client_id' claim: {claims.get('client_id')}\")\n", - "\n", - "result = make_gateway_request(\n", - " bearer_token=token,\n", - " tool_name=\"RefundToolTarget___refund\",\n", - " arguments={\"amount\": 500, \"orderId\": \"test-principal-id\"},\n", - ")\n", - "\n", - "print(\"\\nRequest: RefundToolTarget___refund(amount=500)\")\n", - "print(\"\\nResponse:\")\n", - "print(json.dumps(result, indent=2))\n", - "\n", - "outcome = analyze_response(result)\n", - "display_test_result(\"ALLOWED\", outcome, \"Matching principal.id should be ALLOWED\")\n", - "\n", - "print(\"\\nπŸ’‘ Note: To test DENY scenario, you would need a different\")\n", - "print(\" Amazon Cognito app client with a different client_id (sub)\")" - ] + "source": "print(\"\\n\" + \"=\" * 70)\nprint(f\"Test 3.1: Request with sub (client_id)='{CLIENT_ID}'\")\nprint(\"=\" * 70)\n\ntoken = get_bearer_token()\nclaims = decode_token(token)\n# In Client Credentials Flow, 'sub' claim equals client_id and maps to principal tag \"sub\"\nprint(f\"\\nToken 'sub' claim (used as getTag('sub')): {claims.get('sub')}\")\nprint(f\"Token 'client_id' claim: {claims.get('client_id')}\")\n\nresult = make_gateway_request(\n bearer_token=token,\n tool_name=\"RefundToolTarget___refund\",\n arguments={\"amount\": 500, \"orderId\": \"test-principal-id\"},\n)\n\nprint(\"\\nRequest: RefundToolTarget___refund(amount=500)\")\nprint(\"\\nResponse:\")\nprint(json.dumps(result, indent=2))\n\noutcome = analyze_response(result)\ndisplay_test_result(\"ALLOWED\", outcome, \"Matching principal sub (client_id) should be ALLOWED\")\n\nprint(\"\\nπŸ’‘ Note: To test DENY scenario, you would need a different\")\nprint(\" Amazon Cognito app client with a different client_id (sub)\")" }, { "cell_type": "markdown", diff --git a/01-tutorials/09-AgentCore-E2E/strands-agents/lab-03-agentcore-gateway.ipynb b/01-tutorials/09-AgentCore-E2E/strands-agents/lab-03-agentcore-gateway.ipynb index f61127c7..26f800e8 100644 --- a/01-tutorials/09-AgentCore-E2E/strands-agents/lab-03-agentcore-gateway.ipynb +++ b/01-tutorials/09-AgentCore-E2E/strands-agents/lab-03-agentcore-gateway.ipynb @@ -50,7 +50,7 @@ "\n", "For the inbound authentication, the AgentCore Gateway analyzes the OAuth token passed during invocation to decide allow or deny the access to a tool in the gateway. If a tool needs access to external resources, the AgentCore Gateway can use outbound authentication via API Key, IAM or OAuth Token to allow or deny the access to the external resource.\n", "\n", - "During the inbound authorization flow, an agent or the MCP client calls an MCP tool in the AgentCore Gateway adding an OAuth access token (generated from the user’s IdP). AgentCore Gateway then validates the OAuth access token and performs inbound authorization.\n", + "During the inbound authorization flow, an agent or the MCP client calls an MCP tool in the AgentCore Gateway adding an OAuth access token (generated from the user\u2019s IdP). AgentCore Gateway then validates the OAuth access token and performs inbound authorization.\n", "\n", "If the tool running in AgentCore Gateway needs to access external resources, OAuth will retrieve credentials of downstream resources using the resource credential provider for the Gateway target. AgentCore Gateway pass the authorization credentials to the caller to get access to the downstream API.\n", "\n", @@ -126,7 +126,7 @@ " region_name=REGION,\n", ")\n", "\n", - "print(\"βœ… Libraries imported successfully!\")" + "print(\"\u2705 Libraries imported successfully!\")" ] }, { @@ -194,7 +194,7 @@ " return f\"Search error: {str(e)}\"\n", "\n", "\n", - "print(\"βœ… Web search tool ready\")\n", + "print(\"\u2705 Web search tool ready\")\n", "```" ] }, @@ -321,7 +321,7 @@ "\n", " time.sleep(3)\n", " \n", - " print(f\"βœ… Gateway created successfully with ID: {gateway_id}\")\n", + " print(f\"\u2705 Gateway created successfully with ID: {gateway_id}\")\n", "\n", "except Exception:\n", " # If gateway exists, collect existing gateway ID from SSM\n", @@ -362,7 +362,7 @@ "\n", " # Validate API spec file exists\n", " if not os.path.exists(api_spec_file):\n", - " print(f\"❌ API specification file not found: {api_spec_file}\")\n", + " print(f\"\u274c API specification file not found: {api_spec_file}\")\n", " sys.exit(1)\n", "\n", " api_spec = load_api_spec(api_spec_file)\n", @@ -390,10 +390,10 @@ " credentialProviderConfigurations=credential_config,\n", " )\n", "\n", - " print(f\"βœ… Gateway target created: {create_target_response['targetId']}\")\n", + " print(f\"\u2705 Gateway target created: {create_target_response['targetId']}\")\n", "\n", "except Exception as e:\n", - " print(f\"❌ Error creating gateway target: {str(e)}\")" + " print(f\"\u274c Error creating gateway target: {str(e)}\")" ] }, { @@ -426,7 +426,7 @@ " tools = mcp_client.list_tools_sync()\n", " print(f\" Found {len(tools)} tool(s):\\n\")\n", " for tool in tools:\n", - " print(f\" βœ… {tool.mcp_tool.name}\")\n", + " print(f\" \u2705 {tool.mcp_tool.name}\")\n", " print(f\" {tool.mcp_tool.description}\\n\")" ] }, @@ -504,7 +504,7 @@ " raise e\n", "\n", "\n", - "print(\"βœ… Customer support agent created successfully!\")" + "print(\"\u2705 Customer support agent created successfully!\")" ] }, { @@ -553,7 +553,7 @@ "# Run the tests\n", "test_agent_responses(test_prompts)\n", "\n", - "print(\"\\\\nβœ… Basic testing completed!\")" + "print(\"\\\\n\u2705 Basic testing completed!\")" ] }, { @@ -584,15 +584,15 @@ "# Try to import from toolkit, fall back to custom implementation if not available\n", "try:\n", " from bedrock_agentcore_starter_toolkit.operations.policy.client import PolicyClient\n", - " print(\"βœ… Using toolkit PolicyClient\")\n", + " print(\"\u2705 Using toolkit PolicyClient\")\n", "except ImportError:\n", " from utils.policy_utils import PolicyClient\n", - " print(\"βœ… Using custom PolicyClient (toolkit policy module not available)\")\n", + " print(\"\u2705 Using custom PolicyClient (toolkit policy module not available)\")\n", "\n", "# Initialize the policy client\n", "policy_client = PolicyClient(region_name=REGION)\n", "\n", - "print(\"\\nπŸ”§ Creating Policy Engine...\")\n", + "print(\"\\n\ud83d\udd27 Creating Policy Engine...\")\n", "\n", "# Create or get existing policy engine\n", "# The policy engine is a container for all our authorization policies\n", @@ -605,7 +605,7 @@ "engine_arn = engine['policyEngineArn']\n", "put_ssm_parameter(\"/app/customersupport/agentcore/policy_engine_id\", engine_id)\n", "\n", - "print(f\"\\nβœ… Policy Engine ready\")\n", + "print(f\"\\n\u2705 Policy Engine ready\")\n", "print(f\" Engine ID: {engine_id}\")\n", "print(f\" Engine ARN: {engine_arn}\")" ] @@ -631,7 +631,7 @@ "source": [ "import time\n", "# Create Cedar policy for approve tool (write scope)\n", - "print(\"\\nπŸ“ Generating Cedar Policy from Natural language...\")\n", + "print(\"\\n\ud83d\udcdd Generating Cedar Policy from Natural language...\")\n", "\n", "nl_input = \"Allow tag username == 'testuser' to perform check warranty status on the customer support gateway.\"\n", "\n", @@ -643,7 +643,7 @@ " fetch_assets=True,\n", ")\n", "\n", - "print(\"βœ… Policy generated from natural language\")" + "print(\"\u2705 Policy generated from natural language\")" ] }, { @@ -653,11 +653,11 @@ "metadata": {}, "outputs": [], "source": [ - "print(\"πŸ“‹ Generated Cedar Policies:\\n\")\n", + "print(\"\ud83d\udccb Generated Cedar Policies:\\n\")\n", "print(\"=\" * 80)\n", "\n", "# Allow warranty status policy\n", - "print(\"\\n1️⃣ Warranty Status\")\n", + "print(\"\\n1\ufe0f\u20e3 Warranty Status\")\n", "print(\"-\" * 80)\n", "warranty_tool_policy_cedar = warranty_tool_policy[\"generatedPolicies\"][0][\"definition\"][\"cedar\"][\"statement\"]\n", "print(warranty_tool_policy_cedar)\n", @@ -730,29 +730,70 @@ "metadata": {}, "outputs": [], "source": [ - "print(\"πŸ”§ Creating policies in Policy Engine...\\n\")\n", + "print(\"\ud83d\udd27 Creating policies in Policy Engine...\\n\")\n", + "\n", + "import time as _time\n", + "\n", + "def _cleanup_failed_policy(pe_id, name):\n", + " \"\"\"Delete any CREATE_FAILED policy with the given name to allow clean retry.\"\"\"\n", + " try:\n", + " cp_client = boto3.client(\"bedrock-agentcore-control\", region_name=REGION)\n", + " existing = cp_client.list_policies(policyEngineId=pe_id)\n", + " for p in existing.get(\"policies\", []):\n", + " if p[\"name\"] == name and p[\"status\"] == \"CREATE_FAILED\":\n", + " cp_client.delete_policy(policyEngineId=pe_id, policyId=p[\"policyId\"])\n", + " print(f\" Deleted stale CREATE_FAILED policy: {name}\")\n", + " _time.sleep(2)\n", + " except Exception:\n", + " pass\n", "\n", "# Create allow both tools policy\n", - "warranty_result = policy_client.create_or_get_policy(\n", - " policy_engine_id=engine[\"policyEngineId\"],\n", - " name=\"allow_policy\",\n", - " description=\"Allow web_search and check_warranty_status calls\",\n", - " definition=allow_policy\n", - ")\n", - "print(\"βœ… Policy ready: allow_policy\")\n", + "try:\n", + " warranty_result = policy_client.create_or_get_policy(\n", + " policy_engine_id=engine[\"policyEngineId\"],\n", + " name=\"allow_policy\",\n", + " description=\"Allow web_search and check_warranty_status calls\",\n", + " definition=allow_policy\n", + " )\n", + " print(\"\u2705 Policy ready: allow_policy\")\n", + "except Exception as e:\n", + " print(f\"\u26a0\ufe0f Policy creation failed: {e}\")\n", + " print(\" Retrying with validation_mode='IGNORE_ALL_FINDINGS'...\")\n", + " _cleanup_failed_policy(engine[\"policyEngineId\"], \"allow_policy\")\n", + " warranty_result = policy_client.create_or_get_policy(\n", + " policy_engine_id=engine[\"policyEngineId\"],\n", + " name=\"allow_policy\",\n", + " description=\"Allow web_search and check_warranty_status calls\",\n", + " definition=allow_policy,\n", + " validation_mode=\"IGNORE_ALL_FINDINGS\",\n", + " )\n", + " print(\"\u2705 Policy ready with IGNORE_ALL_FINDINGS: allow_policy\")\n", "print(\" Tools allowed: check_warranty_status and web_search\\n\")\n", "\n", "# Create deny web search list policy\n", - "web_search_deny_result = policy_client.create_or_get_policy(\n", - " policy_engine_id=engine[\"policyEngineId\"],\n", - " name=\"deny_web_search\",\n", - " description=\"Deny web_search tool call for iPhone 8\",\n", - " definition=deny_web_search_policy\n", - ")\n", - "print(\"βœ… Policy ready: deny_web_search\")\n", + "try:\n", + " web_search_deny_result = policy_client.create_or_get_policy(\n", + " policy_engine_id=engine[\"policyEngineId\"],\n", + " name=\"deny_web_search\",\n", + " description=\"Deny web_search tool call for iPhone 8\",\n", + " definition=deny_web_search_policy\n", + " )\n", + " print(\"\u2705 Policy ready: deny_web_search\")\n", + "except Exception as e:\n", + " print(f\"\u26a0\ufe0f Policy creation failed: {e}\")\n", + " print(\" Retrying with validation_mode='IGNORE_ALL_FINDINGS'...\")\n", + " _cleanup_failed_policy(engine[\"policyEngineId\"], \"deny_web_search\")\n", + " web_search_deny_result = policy_client.create_or_get_policy(\n", + " policy_engine_id=engine[\"policyEngineId\"],\n", + " name=\"deny_web_search\",\n", + " description=\"Deny web_search tool call for iPhone 8\",\n", + " definition=deny_web_search_policy,\n", + " validation_mode=\"IGNORE_ALL_FINDINGS\",\n", + " )\n", + " print(\"\u2705 Policy ready with IGNORE_ALL_FINDINGS: deny_web_search\")\n", "print(\" Tools denied conditionally: web_search\\n\")\n", "\n", - "print(\"βœ… All policies ready!\")" + "print(\"\u2705 All policies ready!\")" ] }, { @@ -776,7 +817,7 @@ "role_name = role_arn.split('/')[-1] \n", "\n", "iam_client = boto3.client('iam')\n", - "print(\"πŸ”§ Updating Gateway IAM role with Policy Engine permissions...\")\n", + "print(\"\ud83d\udd27 Updating Gateway IAM role with Policy Engine permissions...\")\n", "\n", "# Policy document that grants access to Policy Engine\n", "policy_document = {\n", @@ -803,16 +844,16 @@ " PolicyDocument=json.dumps(policy_document)\n", " )\n", " \n", - " print(f\"βœ… IAM role updated successfully\")\n", + " print(f\"\u2705 IAM role updated successfully\")\n", " print(f\" Role: {role_name}\")\n", " print(f\" Added permissions: GetPolicyEngine, GetPolicy, ListPolicies\")\n", - " print(\"\\n⏳ Waiting 10 seconds for IAM changes to propagate...\")\n", + " print(\"\\n\u23f3 Waiting 10 seconds for IAM changes to propagate...\")\n", " time.sleep(10)\n", " \n", - " print(\"βœ… Ready to attach Policy Engine\")\n", + " print(\"\u2705 Ready to attach Policy Engine\")\n", " \n", "except Exception as e:\n", - " print(f\"❌ Error updating IAM role: {e}\")\n", + " print(f\"\u274c Error updating IAM role: {e}\")\n", " print(\"\\nYou may need to manually add these permissions to the role.\")" ] }, @@ -838,7 +879,7 @@ "# Initialize gateway client\n", "gateway_client_toolkit = GatewayClient(region_name=REGION)\n", "\n", - "print(\"πŸ”§ Attaching Policy Engine to Gateway...\")\n", + "print(\"\ud83d\udd27 Attaching Policy Engine to Gateway...\")\n", "print(f\" Mode: ENFORCE (policies will block unauthorized requests)\\n\")\n", "\n", "# Attach the policy engine to the gateway\n", @@ -848,11 +889,11 @@ " mode=\"ENFORCE\"\n", ")\n", "\n", - "print(\"βœ… Policy Engine attached successfully!\")\n", + "print(\"\u2705 Policy Engine attached successfully!\")\n", "print(f\" Gateway ID: {gateway['id']}\")\n", "print(f\" Policy Engine: {engine['policyEngineId']}\")\n", "print(f\" Mode: ENFORCE\")\n", - "print(\"\\nπŸ”’ Authorization is now active!\")" + "print(\"\\n\ud83d\udd12 Authorization is now active!\")" ] }, { @@ -893,7 +934,7 @@ "# Run the tests\n", "test_agent_responses(test_prompts)\n", "\n", - "print(\"\\\\nβœ… Policy testing completed!\")" + "print(\"\\\\n\u2705 Policy testing completed!\")" ] }, { @@ -901,7 +942,7 @@ "id": "81ab1e33-04ae-4469-91d5-e85a0a0e4070", "metadata": {}, "source": [ - "### Congratulations! πŸŽ‰\n", + "### Congratulations! \ud83c\udf89\n", "\n", "\n", "You have successfully completed Lab 3: Securely connect tools to your Agent with AgentCore Gateway\n", @@ -968,4 +1009,4 @@ }, "nbformat": 4, "nbformat_minor": 5 -} +} \ No newline at end of file