@macaw-ai/client 0.0.0-stage → 0.9.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (142) hide show
  1. package/LICENSE.md +339 -0
  2. package/bin/install.js +422 -0
  3. package/package.json +37 -4
  4. package/payload/README.md +56 -0
  5. package/payload/secureAI/LICENSE +190 -0
  6. package/payload/secureAI/NOTICE +5 -0
  7. package/payload/secureAI/demos/policy-controls/1_uncontrolled.py +139 -0
  8. package/payload/secureAI/demos/policy-controls/2_with_macaw.py +139 -0
  9. package/payload/secureAI/demos/policy-controls/3_with_user_policies.py +162 -0
  10. package/payload/secureAI/demos/policy-controls/credentials.txt +12 -0
  11. package/payload/secureAI/demos/policy-controls/malicious_report.txt +21 -0
  12. package/payload/secureAI/demos/policy-controls/sales_report.txt +20 -0
  13. package/payload/secureAI/demos/tutorial-1-rbac/README.md +143 -0
  14. package/payload/secureAI/demos/tutorial-1-rbac/app.py +147 -0
  15. package/payload/secureAI/demos/tutorial-1-rbac/authprompts_demo.py +306 -0
  16. package/payload/secureAI/demos/tutorial-1-rbac/config/claims-config.yaml +152 -0
  17. package/payload/secureAI/demos/tutorial-1-rbac/demo_secureopenai_with_policies.py +150 -0
  18. package/payload/secureAI/demos/tutorial-1-rbac/policies/bu_Analytics.json +8 -0
  19. package/payload/secureAI/demos/tutorial-1-rbac/policies/company_FinTech_Corp.json +70 -0
  20. package/payload/secureAI/demos/tutorial-1-rbac/policies/llm-base.json +69 -0
  21. package/payload/secureAI/demos/tutorial-1-rbac/policies/team_Reporting.json +8 -0
  22. package/payload/secureAI/demos/tutorial-1-rbac/policies/user_alice.json +32 -0
  23. package/payload/secureAI/demos/tutorial-1-rbac/policies/user_bob.json +28 -0
  24. package/payload/secureAI/demos/tutorial-1-rbac/policies/user_carol.json +34 -0
  25. package/payload/secureAI/demos/tutorial-1-rbac/requirements.txt +6 -0
  26. package/payload/secureAI/demos/tutorial-1-rbac/setup/auth0_complete_setup.sh +392 -0
  27. package/payload/secureAI/demos/tutorial-1-rbac/setup/keycloak_complete_setup.sh +320 -0
  28. package/payload/secureAI/demos/tutorial-2-intent/Policies/alation-remote-proxy.json +155 -0
  29. package/payload/secureAI/demos/tutorial-2-intent/Policies/bu.json +22 -0
  30. package/payload/secureAI/demos/tutorial-2-intent/Policies/company.json +17 -0
  31. package/payload/secureAI/demos/tutorial-2-intent/Policies/user_alice.json +48 -0
  32. package/payload/secureAI/demos/tutorial-2-intent/Policies/user_bob.json +83 -0
  33. package/payload/secureAI/demos/tutorial-2-intent/README.md +213 -0
  34. package/payload/secureAI/demos/tutorial-2-intent/script.py +188 -0
  35. package/payload/secureAI/demos/tutorial-2-intent/setup/alation_verifier.py +177 -0
  36. package/payload/secureAI/demos/tutorial-2-intent/setup/get_alation_user_token.py +180 -0
  37. package/payload/secureAI/examples/README.md +244 -0
  38. package/payload/secureAI/examples/anthropic/anthropic_1a_dropin_simple.py +103 -0
  39. package/payload/secureAI/examples/anthropic/anthropic_1b_multiuser_bind.py +190 -0
  40. package/payload/secureAI/examples/anthropic/anthropic_1b_multiuser_bind_streaming.py +190 -0
  41. package/payload/secureAI/examples/anthropic/anthropic_1c_a2a_invoke.py +156 -0
  42. package/payload/secureAI/examples/attestations/1a_trade_alice.py +215 -0
  43. package/payload/secureAI/examples/attestations/1a_trade_bob.py +164 -0
  44. package/payload/secureAI/examples/attestations/1b_grant_admin.py +170 -0
  45. package/payload/secureAI/examples/attestations/1b_grant_researcher.py +231 -0
  46. package/payload/secureAI/examples/attestations/README.md +128 -0
  47. package/payload/secureAI/examples/langchain/langchain_1a_dropin_simple.py +199 -0
  48. package/payload/secureAI/examples/langchain/langchain_1b_multiuser.py +262 -0
  49. package/payload/secureAI/examples/langchain/langchain_1c_orchestration.py +332 -0
  50. package/payload/secureAI/examples/langchain/langchain_1d_llm_openai.py +130 -0
  51. package/payload/secureAI/examples/langchain/langchain_1e_llm_anthropic.py +130 -0
  52. package/payload/secureAI/examples/langchain/langchain_1f_memory.py +214 -0
  53. package/payload/secureAI/examples/litellm/litellm_1a_dropin_simple.py +131 -0
  54. package/payload/secureAI/examples/mcp/1a_simple_invocation.py +115 -0
  55. package/payload/secureAI/examples/mcp/1b_discovery_and_resources.py +142 -0
  56. package/payload/secureAI/examples/mcp/1c_logging_client.py +100 -0
  57. package/payload/secureAI/examples/mcp/1d_progress_client.py +100 -0
  58. package/payload/secureAI/examples/mcp/1e_sampling_client.py +150 -0
  59. package/payload/secureAI/examples/mcp/1e_sampling_server.py +90 -0
  60. package/payload/secureAI/examples/mcp/1f_elicitation_client.py +127 -0
  61. package/payload/secureAI/examples/mcp/1f_elicitation_server.py +73 -0
  62. package/payload/secureAI/examples/mcp/1g_roots_client.py +122 -0
  63. package/payload/secureAI/examples/mcp/1g_roots_server.py +85 -0
  64. package/payload/secureAI/examples/mcp/2a_proxy_snowflake.py +212 -0
  65. package/payload/secureAI/examples/mcp/2b_proxy_databricks.py +299 -0
  66. package/payload/secureAI/examples/mcp/2c_proxy_stdio_fetch.py +91 -0
  67. package/payload/secureAI/examples/mcp/2d_proxy_stdio_salesforce.py +119 -0
  68. package/payload/secureAI/examples/mcp/2e_proxy_multiuser.py +136 -0
  69. package/payload/secureAI/examples/mcp/2f_proxy_stdio_databricks.py +144 -0
  70. package/payload/secureAI/examples/mcp/3a_native_mcp_client.py +104 -0
  71. package/payload/secureAI/examples/mcp/3b_native_mcp_proxy.py +114 -0
  72. package/payload/secureAI/examples/mcp/3c_native_mcp_sampling.py +180 -0
  73. package/payload/secureAI/examples/mcp/3d_native_mcp_2026.py +135 -0
  74. package/payload/secureAI/examples/mcp/securemcp_calculator.py +248 -0
  75. package/payload/secureAI/examples/mcp/securemcp_server.py +75 -0
  76. package/payload/secureAI/examples/openai/openai_1a_dropin_simple.py +102 -0
  77. package/payload/secureAI/examples/openai/openai_1b_multiuser_bind.py +193 -0
  78. package/payload/secureAI/examples/openai/openai_1b_multiuser_bind_streaming.py +199 -0
  79. package/payload/secureAI/examples/openai/openai_1c_a2a_invoke.py +156 -0
  80. package/payload/secureAI/examples/openai/openai_1d_invocation_patterns.py +337 -0
  81. package/payload/secureAI/examples/phishing-resistance/1a_login_alice.py +180 -0
  82. package/payload/secureAI/examples/phishing-resistance/1b_trade_alice.py +241 -0
  83. package/payload/secureAI/examples/phishing-resistance/1b_trade_bob.py +164 -0
  84. package/payload/secureAI/examples/phishing-resistance/README.md +124 -0
  85. package/payload/secureAI/examples/phishing-resistance/get_token.py +114 -0
  86. package/payload/secureAI/examples/pydantic_ai/README.md +88 -0
  87. package/payload/secureAI/examples/pydantic_ai/policies/app_pydantic-agent.json +10 -0
  88. package/payload/secureAI/examples/pydantic_ai/pydanticai_1a_dropin_simple.py +90 -0
  89. package/payload/secureAI/examples/pydantic_ai/pydanticai_1b_model_routing.py +85 -0
  90. package/payload/secureAI/examples/pydantic_ai/pydanticai_1c_native_tools.py +83 -0
  91. package/payload/secureAI/examples/pydantic_ai/pydanticai_1d_multiuser_bind.py +104 -0
  92. package/payload/secureAI/examples/pydantic_ai/pydanticai_1e_mcp_compose.py +92 -0
  93. package/payload/secureAI/macaw_adapters/__init__.py +55 -0
  94. package/payload/secureAI/macaw_adapters/anthropic/REFERENCE.md +374 -0
  95. package/payload/secureAI/macaw_adapters/anthropic/__init__.py +22 -0
  96. package/payload/secureAI/macaw_adapters/anthropic/secure_anthropic.py +792 -0
  97. package/payload/secureAI/macaw_adapters/anthropic_ext_tools/__init__.py +25 -0
  98. package/payload/secureAI/macaw_adapters/anthropic_ext_tools/secure_anthropic.py +840 -0
  99. package/payload/secureAI/macaw_adapters/langchain/REFERENCE.md +234 -0
  100. package/payload/secureAI/macaw_adapters/langchain/__init__.py +100 -0
  101. package/payload/secureAI/macaw_adapters/langchain/_utils.py +83 -0
  102. package/payload/secureAI/macaw_adapters/langchain/agents.py +296 -0
  103. package/payload/secureAI/macaw_adapters/langchain/anthropic.py +456 -0
  104. package/payload/secureAI/macaw_adapters/langchain/callbacks.py +306 -0
  105. package/payload/secureAI/macaw_adapters/langchain/memory.py +352 -0
  106. package/payload/secureAI/macaw_adapters/langchain/openai.py +410 -0
  107. package/payload/secureAI/macaw_adapters/langchain/tools.py +174 -0
  108. package/payload/secureAI/macaw_adapters/litellm/README.md +216 -0
  109. package/payload/secureAI/macaw_adapters/litellm/__init__.py +143 -0
  110. package/payload/secureAI/macaw_adapters/litellm/secure_litellm.py +686 -0
  111. package/payload/secureAI/macaw_adapters/mcp/REFERENCE.md +460 -0
  112. package/payload/secureAI/macaw_adapters/mcp/__init__.py +65 -0
  113. package/payload/secureAI/macaw_adapters/mcp/_endpoint.py +193 -0
  114. package/payload/secureAI/macaw_adapters/mcp/_endpoint2.py +225 -0
  115. package/payload/secureAI/macaw_adapters/mcp/_serve.py +25 -0
  116. package/payload/secureAI/macaw_adapters/mcp/client.py +721 -0
  117. package/payload/secureAI/macaw_adapters/mcp/decorators.py +228 -0
  118. package/payload/secureAI/macaw_adapters/mcp/fastmcp_compat.py +353 -0
  119. package/payload/secureAI/macaw_adapters/mcp/mcp.py +785 -0
  120. package/payload/secureAI/macaw_adapters/mcp/proxy.py +626 -0
  121. package/payload/secureAI/macaw_adapters/mcp/server.py +317 -0
  122. package/payload/secureAI/macaw_adapters/mcp/subscriptions.py +450 -0
  123. package/payload/secureAI/macaw_adapters/openai/REFERENCE.md +368 -0
  124. package/payload/secureAI/macaw_adapters/openai/__init__.py +22 -0
  125. package/payload/secureAI/macaw_adapters/openai/secure_openai.py +833 -0
  126. package/payload/secureAI/macaw_adapters/openai_ext_tools/REFERENCE.md +368 -0
  127. package/payload/secureAI/macaw_adapters/openai_ext_tools/__init__.py +25 -0
  128. package/payload/secureAI/macaw_adapters/openai_ext_tools/secure_openai.py +876 -0
  129. package/payload/secureAI/macaw_adapters/pydantic_ai/__init__.py +36 -0
  130. package/payload/secureAI/macaw_adapters/pydantic_ai/_core.py +257 -0
  131. package/payload/secureAI/macaw_adapters/pydantic_ai/agent.py +218 -0
  132. package/payload/secureAI/macaw_adapters/pydantic_ai/model.py +99 -0
  133. package/payload/secureAI/macaw_adapters/pydantic_ai/toolset.py +86 -0
  134. package/payload/secureAI/test_harness_quick.py +296 -0
  135. package/wheels/macaw_adapters-0.9.10.1-py3-none-any.whl +0 -0
  136. package/wheels/macaw_client-0.9.10.1-cp312-cp312-macosx_11_0_arm64.whl +0 -0
  137. package/wheels/macaw_client-0.9.10.1-cp312-cp312-manylinux_2_17_x86_64.whl +0 -0
  138. package/wheels/macaw_client-0.9.10.1-cp314-cp314-macosx_11_0_arm64.whl +0 -0
  139. package/wheels/macaw_client-0.9.10.1-cp314-cp314-manylinux_2_17_x86_64.whl +0 -0
  140. package/wheels/macaw_client-0.9.10.1-cp314-cp314-win_amd64.whl +0 -0
  141. package/wheels/macaw_client-0.9.10.1-cp39-cp39-macosx_11_0_arm64.whl +0 -0
  142. package/README.md +0 -3
@@ -0,0 +1,320 @@
1
+ #!/bin/bash
2
+ #
3
+ # Complete Keycloak Setup - Creates realm, client, and users
4
+ #
5
+ # Prerequisites:
6
+ # 1. Docker installed
7
+ # 2. Run Keycloak: docker run -d -p 8080:8080 -e KEYCLOAK_ADMIN=admin -e KEYCLOAK_ADMIN_PASSWORD=admin123 quay.io/keycloak/keycloak:23.0 start-dev
8
+ #
9
+
10
+ set -e
11
+
12
+ # Configuration - customize these as needed
13
+ KEYCLOAK_PORT="${KEYCLOAK_PORT:-8080}"
14
+ KEYCLOAK_ADMIN="${KEYCLOAK_ADMIN:-admin}"
15
+ KEYCLOAK_ADMIN_PASSWORD="${KEYCLOAK_ADMIN_PASSWORD:-admin123}"
16
+ REALM_NAME="fintech"
17
+ CLIENT_ID="financial-analyzer"
18
+ CLIENT_SECRET="change-me-in-production"
19
+
20
+ # Colors
21
+ RED='\033[0;31m'
22
+ GREEN='\033[0;32m'
23
+ YELLOW='\033[1;33m'
24
+ NC='\033[0m'
25
+
26
+ echo "=========================================="
27
+ echo "Complete Keycloak Configuration"
28
+ echo "=========================================="
29
+
30
+ # Check if jq is installed
31
+ if ! command -v jq &> /dev/null; then
32
+ echo -e "${RED}jq is required but not installed.${NC}"
33
+ echo "Install with: brew install jq (macOS) or apt install jq (Linux)"
34
+ exit 1
35
+ fi
36
+
37
+ # Function to get/refresh admin token
38
+ get_admin_token() {
39
+ local token=$(curl -s -X POST "http://localhost:${KEYCLOAK_PORT}/realms/master/protocol/openid-connect/token" \
40
+ -H "Content-Type: application/x-www-form-urlencoded" \
41
+ -d "username=${KEYCLOAK_ADMIN}" \
42
+ -d "password=${KEYCLOAK_ADMIN_PASSWORD}" \
43
+ -d "grant_type=password" \
44
+ -d "client_id=admin-cli" | jq -r '.access_token')
45
+
46
+ if [ -z "$token" ] || [ "$token" = "null" ]; then
47
+ echo -e "${RED}Failed to authenticate. Is Keycloak running?${NC}"
48
+ exit 1
49
+ fi
50
+
51
+ echo "$token"
52
+ }
53
+
54
+ # Get admin token
55
+ echo -e "${YELLOW}Step 1: Authenticating as admin...${NC}"
56
+ ADMIN_TOKEN=$(get_admin_token)
57
+ echo -e "${GREEN}OK Admin authenticated${NC}"
58
+
59
+ # Create or update FinTech realm
60
+ echo -e "${YELLOW}Step 2: Creating/updating FinTech realm...${NC}"
61
+
62
+ # Delete existing realm completely (to start fresh)
63
+ echo " Deleting existing realm (if it exists)..."
64
+ DELETE_RESULT=$(curl -s -w "%{http_code}" -X DELETE "http://localhost:${KEYCLOAK_PORT}/admin/realms/${REALM_NAME}" \
65
+ -H "Authorization: Bearer ${ADMIN_TOKEN}")
66
+
67
+ DELETE_CODE="${DELETE_RESULT: -3}"
68
+ if [ "$DELETE_CODE" = "204" ]; then
69
+ echo " OK Existing realm deleted"
70
+ elif [ "$DELETE_CODE" = "404" ]; then
71
+ echo " OK No existing realm to delete"
72
+ fi
73
+
74
+ # Wait a moment for cleanup
75
+ sleep 2
76
+
77
+ # Create new realm
78
+ curl -s -X POST "http://localhost:${KEYCLOAK_PORT}/admin/realms" \
79
+ -H "Authorization: Bearer ${ADMIN_TOKEN}" \
80
+ -H "Content-Type: application/json" \
81
+ -d '{
82
+ "realm": "'${REALM_NAME}'",
83
+ "enabled": true,
84
+ "displayName": "FinTech Corporation",
85
+ "loginWithEmailAllowed": true,
86
+ "duplicateEmailsAllowed": false,
87
+ "resetPasswordAllowed": true,
88
+ "editUsernameAllowed": false,
89
+ "bruteForceProtected": false
90
+ }'
91
+
92
+ echo -e "${GREEN}OK FinTech realm created${NC}"
93
+
94
+ # Create the OAuth client
95
+ echo -e "${YELLOW}Step 3: Creating financial-analyzer client...${NC}"
96
+
97
+ curl -s -X POST "http://localhost:${KEYCLOAK_PORT}/admin/realms/${REALM_NAME}/clients" \
98
+ -H "Authorization: Bearer ${ADMIN_TOKEN}" \
99
+ -H "Content-Type: application/json" \
100
+ -d '{
101
+ "clientId": "'${CLIENT_ID}'",
102
+ "name": "Financial Analyzer Application",
103
+ "enabled": true,
104
+ "protocol": "openid-connect",
105
+ "publicClient": false,
106
+ "secret": "'${CLIENT_SECRET}'",
107
+ "directAccessGrantsEnabled": true,
108
+ "standardFlowEnabled": true,
109
+ "implicitFlowEnabled": false,
110
+ "serviceAccountsEnabled": false,
111
+ "authorizationServicesEnabled": false,
112
+ "redirectUris": ["http://localhost:3000/*", "http://localhost:8000/*"],
113
+ "webOrigins": ["http://localhost:3000", "http://localhost:8000"],
114
+ "attributes": {
115
+ "use.refresh.tokens": "true"
116
+ }
117
+ }'
118
+
119
+ echo -e "${GREEN}OK Client created${NC}"
120
+
121
+ # Get the client UUID for mapper configuration
122
+ CLIENT_UUID=$(curl -s "http://localhost:${KEYCLOAK_PORT}/admin/realms/${REALM_NAME}/clients?clientId=${CLIENT_ID}" \
123
+ -H "Authorization: Bearer ${ADMIN_TOKEN}" | jq -r '.[0].id')
124
+
125
+ # Create custom attribute mappers
126
+ echo -e "${YELLOW}Step 4: Creating attribute mappers...${NC}"
127
+
128
+ create_mapper() {
129
+ local name=$1
130
+ local attribute=$2
131
+
132
+ curl -s -X POST "http://localhost:${KEYCLOAK_PORT}/admin/realms/${REALM_NAME}/clients/${CLIENT_UUID}/protocol-mappers/models" \
133
+ -H "Authorization: Bearer ${ADMIN_TOKEN}" \
134
+ -H "Content-Type: application/json" \
135
+ -d '{
136
+ "name": "'$name'",
137
+ "protocol": "openid-connect",
138
+ "protocolMapper": "oidc-usermodel-attribute-mapper",
139
+ "consentRequired": false,
140
+ "config": {
141
+ "userinfo.token.claim": "true",
142
+ "user.attribute": "'$attribute'",
143
+ "id.token.claim": "true",
144
+ "access.token.claim": "true",
145
+ "claim.name": "'$attribute'",
146
+ "jsonType.label": "String"
147
+ }
148
+ }' 2>/dev/null || echo " (Mapper $name may already exist)"
149
+ }
150
+
151
+ create_mapper "organization-mapper" "organization"
152
+ create_mapper "business_unit-mapper" "business_unit"
153
+ create_mapper "team-mapper" "team"
154
+ create_mapper "clearance_level-mapper" "clearance_level"
155
+
156
+ echo -e "${GREEN}OK Mappers created${NC}"
157
+
158
+ # Create realm roles
159
+ echo -e "${YELLOW}Step 5: Creating realm roles...${NC}"
160
+ ADMIN_TOKEN=$(get_admin_token)
161
+
162
+ create_role() {
163
+ local role=$1
164
+ local desc=$2
165
+
166
+ local existing_role=$(curl -s "http://localhost:${KEYCLOAK_PORT}/admin/realms/${REALM_NAME}/roles/${role}" \
167
+ -H "Authorization: Bearer ${ADMIN_TOKEN}")
168
+
169
+ if echo "$existing_role" | jq -e 'has("name")' > /dev/null 2>&1; then
170
+ echo " OK Role $role already exists"
171
+ return 0
172
+ fi
173
+
174
+ local result=$(curl -s -w "%{http_code}" -X POST "http://localhost:${KEYCLOAK_PORT}/admin/realms/${REALM_NAME}/roles" \
175
+ -H "Authorization: Bearer ${ADMIN_TOKEN}" \
176
+ -H "Content-Type: application/json" \
177
+ -d '{"name": "'"$role"'", "description": "'"$desc"'"}')
178
+
179
+ local http_code="${result: -3}"
180
+ if [ "$http_code" = "201" ] || [ "$http_code" = "409" ]; then
181
+ echo " OK Role $role created/exists"
182
+ else
183
+ echo " FAIL Failed to create role $role (HTTP $http_code)"
184
+ fi
185
+ }
186
+
187
+ create_role "analyst" "Financial Analyst role"
188
+ create_role "manager" "Manager role"
189
+ create_role "admin" "Administrator role"
190
+
191
+ echo -e "${GREEN}OK Roles created${NC}"
192
+
193
+ # Create users
194
+ echo -e "${YELLOW}Step 6: Creating users...${NC}"
195
+ ADMIN_TOKEN=$(get_admin_token)
196
+
197
+ create_user_with_password() {
198
+ local username=$1
199
+ local email=$2
200
+ local firstname=$3
201
+ local lastname=$4
202
+ local password=$5
203
+ local org=$6
204
+ local bu=$7
205
+ local team=$8
206
+ local clearance=$9
207
+
208
+ local json_data=$(cat <<EOF
209
+ {"username": "$username", "email": "$email", "firstName": "$firstname", "lastName": "$lastname", "enabled": true, "emailVerified": true, "attributes": {"organization": ["$org"], "business_unit": ["$bu"], "team": ["$team"], "clearance_level": ["$clearance"]}}
210
+ EOF
211
+ )
212
+ local create_result=$(curl -s -w "%{http_code}" -X POST "http://localhost:${KEYCLOAK_PORT}/admin/realms/${REALM_NAME}/users" \
213
+ -H "Authorization: Bearer ${ADMIN_TOKEN}" \
214
+ -H "Content-Type: application/json" \
215
+ -d "$json_data")
216
+
217
+ local create_code="${create_result: -3}"
218
+
219
+ if [ "$create_code" = "201" ] || [ "$create_code" = "409" ]; then
220
+ echo " OK User $username created/exists"
221
+
222
+ local user_id=$(curl -s "http://localhost:${KEYCLOAK_PORT}/admin/realms/${REALM_NAME}/users?username=${username}" \
223
+ -H "Authorization: Bearer ${ADMIN_TOKEN}" | jq -r '.[0].id')
224
+
225
+ if [ ! -z "$user_id" ] && [ "$user_id" != "null" ]; then
226
+ local pwd_result=$(curl -s -w "%{http_code}" -X PUT "http://localhost:${KEYCLOAK_PORT}/admin/realms/${REALM_NAME}/users/${user_id}/reset-password" \
227
+ -H "Authorization: Bearer ${ADMIN_TOKEN}" \
228
+ -H "Content-Type: application/json" \
229
+ -d '{"type": "password", "value": "'"$password"'", "temporary": false}')
230
+
231
+ local pwd_code="${pwd_result: -3}"
232
+ if [ "$pwd_code" = "204" ]; then
233
+ echo " OK Password set for $username"
234
+ else
235
+ echo " FAIL Failed to set password for $username"
236
+ fi
237
+ fi
238
+ else
239
+ echo " FAIL Failed to create user $username (HTTP $create_code)"
240
+ fi
241
+ }
242
+
243
+ # Demo users with their organizational attributes
244
+ create_user_with_password "alice" "alice@example.com" "Alice" "Johnson" "Alice123!" "FinTech Corp" "Analytics" "Reporting" "standard"
245
+ create_user_with_password "bob" "bob@example.com" "Bob" "Smith" "Bob@123!" "FinTech Corp" "Analytics" "Management" "elevated"
246
+ create_user_with_password "carol" "carol@example.com" "Carol" "Davis" "Carol123!" "FinTech Corp" "Technology" "Infrastructure" "full"
247
+
248
+ echo -e "${GREEN}OK Users created${NC}"
249
+
250
+ # Assign roles to users
251
+ echo -e "${YELLOW}Step 7: Assigning roles to users...${NC}"
252
+ ADMIN_TOKEN=$(get_admin_token)
253
+
254
+ ALICE_ID=$(curl -s "http://localhost:${KEYCLOAK_PORT}/admin/realms/${REALM_NAME}/users?username=alice" \
255
+ -H "Authorization: Bearer ${ADMIN_TOKEN}" | jq -r '.[0].id')
256
+ BOB_ID=$(curl -s "http://localhost:${KEYCLOAK_PORT}/admin/realms/${REALM_NAME}/users?username=bob" \
257
+ -H "Authorization: Bearer ${ADMIN_TOKEN}" | jq -r '.[0].id')
258
+ CAROL_ID=$(curl -s "http://localhost:${KEYCLOAK_PORT}/admin/realms/${REALM_NAME}/users?username=carol" \
259
+ -H "Authorization: Bearer ${ADMIN_TOKEN}" | jq -r '.[0].id')
260
+
261
+ get_role() {
262
+ local role_name=$1
263
+ local role_data=$(curl -s "http://localhost:${KEYCLOAK_PORT}/admin/realms/${REALM_NAME}/roles/${role_name}" \
264
+ -H "Authorization: Bearer ${ADMIN_TOKEN}")
265
+
266
+ if echo "$role_data" | jq -e 'has("name")' > /dev/null 2>&1; then
267
+ echo "$role_data"
268
+ else
269
+ echo "null"
270
+ fi
271
+ }
272
+
273
+ ANALYST_ROLE=$(get_role "analyst")
274
+ MANAGER_ROLE=$(get_role "manager")
275
+ ADMIN_ROLE=$(get_role "admin")
276
+
277
+ assign_role() {
278
+ local user_id=$1
279
+ local user_name=$2
280
+ local role_data=$3
281
+ local role_name=$4
282
+
283
+ if [ ! -z "$user_id" ] && [ "$user_id" != "null" ] && [ "$role_data" != "null" ]; then
284
+ curl -s -X POST "http://localhost:${KEYCLOAK_PORT}/admin/realms/${REALM_NAME}/users/${user_id}/role-mappings/realm" \
285
+ -H "Authorization: Bearer ${ADMIN_TOKEN}" \
286
+ -H "Content-Type: application/json" \
287
+ -d "[$role_data]" 2>/dev/null
288
+ echo " OK $user_name assigned $role_name role"
289
+ fi
290
+ }
291
+
292
+ assign_role "$ALICE_ID" "Alice" "$ANALYST_ROLE" "analyst"
293
+ assign_role "$BOB_ID" "Bob" "$MANAGER_ROLE" "manager"
294
+ assign_role "$CAROL_ID" "Carol" "$ADMIN_ROLE" "admin"
295
+
296
+ echo -e "${GREEN}OK Roles assigned${NC}"
297
+
298
+ echo ""
299
+ echo "=========================================="
300
+ echo "KEYCLOAK SETUP COMPLETE!"
301
+ echo "=========================================="
302
+ echo ""
303
+ echo "Keycloak Admin Console:"
304
+ echo " http://localhost:8080/admin"
305
+ echo " Username: admin"
306
+ echo " Password: admin123"
307
+ echo ""
308
+ echo "FinTech Realm:"
309
+ echo " Realm: fintech"
310
+ echo " Client ID: financial-analyzer"
311
+ echo " Client Secret: change-me-in-production"
312
+ echo ""
313
+ echo "Test Users:"
314
+ echo " alice / Alice123! (Analyst)"
315
+ echo " bob / Bob@123! (Manager)"
316
+ echo " carol / Carol123! (Admin)"
317
+ echo ""
318
+ echo "Next step:"
319
+ echo " export OPENAI_API_KEY=sk-your-key"
320
+ echo " python3 app.py"
@@ -0,0 +1,155 @@
1
+ {
2
+ "policy_id": "app:alation-remote-proxy",
3
+ "version": "0.8.0",
4
+ "scope": "global",
5
+ "resources": [
6
+ "tool:alation-remote-proxy/run_query_sql_custom_adi",
7
+ "tool:alation-remote-proxy/run_data_product_query_macaw_ii",
8
+ "tool:alation-remote-proxy/run_analytics_agent_macaw",
9
+ "tool:alation-remote-proxy/run_generate_pdf_from_a_chat_macaw"
10
+ ],
11
+ "constraints": {
12
+ "denied_parameters": {
13
+ "tool:alation-remote-proxy/run_analytics_agent_macaw": {
14
+ "query": [
15
+ "*DELETE *",
16
+ "*delete *",
17
+ "*DROP *",
18
+ "*drop *",
19
+ "*TRUNCATE*",
20
+ "*truncate*",
21
+ "*ALTER *",
22
+ "*alter *",
23
+ "*MERGE *",
24
+ "*merge *",
25
+ "*CREATE *",
26
+ "*create *",
27
+ "*INSERT *",
28
+ "*insert *",
29
+ "*GRANT *",
30
+ "*grant *",
31
+ "*REVOKE*",
32
+ "*revoke*",
33
+ "*VACUUM*",
34
+ "*vacuum*",
35
+ "*COPY INTO*",
36
+ "*copy into*",
37
+ "*EXECUTE IMMEDIATE*",
38
+ "*execute immediate*"
39
+ ],
40
+ "sql": [
41
+ "*DELETE *",
42
+ "*delete *",
43
+ "*DROP *",
44
+ "*drop *",
45
+ "*TRUNCATE*",
46
+ "*truncate*",
47
+ "*ALTER *",
48
+ "*alter *",
49
+ "*MERGE *",
50
+ "*merge *",
51
+ "*CREATE *",
52
+ "*create *",
53
+ "*INSERT *",
54
+ "*insert *",
55
+ "*GRANT *",
56
+ "*grant *",
57
+ "*REVOKE*",
58
+ "*revoke*",
59
+ "*VACUUM*",
60
+ "*vacuum*",
61
+ "*COPY INTO*",
62
+ "*copy into*",
63
+ "*EXECUTE IMMEDIATE*",
64
+ "*execute immediate*"
65
+ ]
66
+ },
67
+ "tool:alation-remote-proxy/run_data_product_query_macaw_ii": {
68
+ "sql": [
69
+ "*DELETE *",
70
+ "*delete *",
71
+ "*DROP *",
72
+ "*drop *",
73
+ "*TRUNCATE*",
74
+ "*truncate*",
75
+ "*ALTER *",
76
+ "*alter *",
77
+ "*MERGE *",
78
+ "*merge *",
79
+ "*CREATE *",
80
+ "*create *",
81
+ "*INSERT *",
82
+ "*insert *",
83
+ "*GRANT *",
84
+ "*grant *",
85
+ "*REVOKE*",
86
+ "*revoke*",
87
+ "*VACUUM*",
88
+ "*vacuum*",
89
+ "*COPY INTO*",
90
+ "*copy into*",
91
+ "*EXECUTE IMMEDIATE*",
92
+ "*execute immediate*"
93
+ ]
94
+ },
95
+ "tool:alation-remote-proxy/run_query_sql_custom_adi": {
96
+ "sql": [
97
+ "*DELETE *",
98
+ "*delete *",
99
+ "*DROP *",
100
+ "*drop *",
101
+ "*TRUNCATE*",
102
+ "*truncate*",
103
+ "*ALTER *",
104
+ "*alter *",
105
+ "*MERGE *",
106
+ "*merge *",
107
+ "*CREATE *",
108
+ "*create *",
109
+ "*INSERT *",
110
+ "*insert *",
111
+ "*GRANT *",
112
+ "*grant *",
113
+ "*REVOKE*",
114
+ "*revoke*",
115
+ "*VACUUM*",
116
+ "*vacuum*",
117
+ "*COPY INTO*",
118
+ "*copy into*",
119
+ "*EXECUTE IMMEDIATE*",
120
+ "*execute immediate*"
121
+ ]
122
+ }
123
+ },
124
+ "parameters": {
125
+ "tool:alation-remote-proxy/run_analytics_agent_macaw": {
126
+ "stmt_type": {
127
+ "allowed_values": [
128
+ "select",
129
+ "update"
130
+ ],
131
+ "type": "string"
132
+ }
133
+ },
134
+ "tool:alation-remote-proxy/run_data_product_query_macaw_ii": {
135
+ "stmt_type": {
136
+ "allowed_values": [
137
+ "select",
138
+ "update"
139
+ ],
140
+ "type": "string"
141
+ }
142
+ },
143
+ "tool:alation-remote-proxy/run_query_sql_custom_adi": {
144
+ "stmt_type": {
145
+ "allowed_values": [
146
+ "select",
147
+ "update"
148
+ ],
149
+ "type": "string"
150
+ }
151
+ }
152
+ }
153
+ },
154
+ "description": "Alation native MCP via SecureMCPProxy -- statement-type allow-list + destructive-SQL denies; per-caller gates live in user:alice / user:bob."
155
+ }
@@ -0,0 +1,22 @@
1
+ {
2
+ "policy_id": "bu:analytics",
3
+ "version": "0.1.1",
4
+ "scope": "global",
5
+ "resources": [],
6
+ "extends": "company:alation-MACAW",
7
+ "constraints": {
8
+ "parameters": {
9
+ "tool:*/complete": {
10
+ "max_tokens": {
11
+ "max": 1000000
12
+ }
13
+ },
14
+ "tool:*/generate": {
15
+ "max_tokens": {
16
+ "max": 1000000
17
+ }
18
+ }
19
+ }
20
+ },
21
+ "description": "Analytics BU"
22
+ }
@@ -0,0 +1,17 @@
1
+ {
2
+ "policy_id": "company:alation-MACAW",
3
+ "version": "1.0.1",
4
+ "scope": "global",
5
+ "resources": [
6
+ "tool:**",
7
+ "llm:**",
8
+ "agent:**"
9
+ ],
10
+ "denied_resources": [
11
+ "data:sensitive/*"
12
+ ],
13
+ "constraints": {
14
+ "rate_limit": 100
15
+ },
16
+ "description": "My security policy"
17
+ }
@@ -0,0 +1,48 @@
1
+ {
2
+ "policy_id": "user:alice",
3
+ "version": "0.6.1",
4
+ "scope": "global",
5
+ "resources": [
6
+ "tool:alation-remote-proxy/run_query_sql_custom_adi",
7
+ "tool:openai-service/generate"
8
+ ],
9
+ "extends": "bu:analytics",
10
+ "constraints": {
11
+ "attestations": {
12
+ "eng_comp_attestation": {
13
+ "approval_criteria": "role:manager",
14
+ "description": "Analyst touched eng_comp -- requires a manager (bob) to attest",
15
+ "one_time": true,
16
+ "time_to_live": 300,
17
+ "timeout": 300
18
+ }
19
+ },
20
+ "parameters": {
21
+ "tool:alation-remote-proxy/run_query_sql_custom_adi": {
22
+ "stmt_type": {
23
+ "allowed_values": [
24
+ "select",
25
+ "update"
26
+ ],
27
+ "type": "string"
28
+ }
29
+ },
30
+ "tool:openai-service/generate": {
31
+ "max_tokens": {
32
+ "max": 100,
33
+ "type": "integer"
34
+ },
35
+ "model": {
36
+ "allowed_values": [
37
+ "gpt-4o-mini"
38
+ ],
39
+ "type": "string"
40
+ }
41
+ }
42
+ }
43
+ },
44
+ "attestations": [
45
+ "eng_comp_attestation::{ params.touches_eng_comp == 'true' }"
46
+ ],
47
+ "description": "bob -- role: analyst (narrower LLM access than bob). Any statement touching eng_comp attests to a manager; other tables ungated within the select/update allow-list; DELETE/DDL denied. OpenAI: gpt-4o-mini only, max_tokens<=100."
48
+ }
@@ -0,0 +1,83 @@
1
+ {
2
+ "policy_id": "user:bob",
3
+ "version": "0.3.5",
4
+ "scope": "global",
5
+ "resources": [
6
+ "tool:alation-remote-proxy/run_query_sql_custom_adi",
7
+ "tool:alation-remote-proxy/run_data_product_query_macaw_ii",
8
+ "tool:alation-remote-proxy/run_analytics_agent_macaw",
9
+ "tool:alation-remote-proxy/run_generate_pdf_from_a_chat_macaw",
10
+ "tool:openai-service/generate",
11
+ "tool:anthropic-service/generate"
12
+ ],
13
+ "extends": "bu:analytics",
14
+ "constraints": {
15
+ "attestations": {
16
+ "eng_comp_update_attestation": {
17
+ "approval_criteria": "role:admin",
18
+ "description": "Admin UPDATE on eng_comp -- requires an admin to attest",
19
+ "one_time": true,
20
+ "time_to_live": 300,
21
+ "timeout": 300
22
+ }
23
+ },
24
+ "parameters": {
25
+ "tool:alation-remote-proxy/run_analytics_agent_macaw": {
26
+ "stmt_type": {
27
+ "allowed_values": [
28
+ "select",
29
+ "update"
30
+ ],
31
+ "type": "string"
32
+ }
33
+ },
34
+ "tool:alation-remote-proxy/run_data_product_query_macaw_ii": {
35
+ "stmt_type": {
36
+ "allowed_values": [
37
+ "select",
38
+ "update"
39
+ ],
40
+ "type": "string"
41
+ }
42
+ },
43
+ "tool:alation-remote-proxy/run_query_sql_custom_adi": {
44
+ "stmt_type": {
45
+ "allowed_values": [
46
+ "select",
47
+ "update"
48
+ ],
49
+ "type": "string"
50
+ }
51
+ },
52
+ "tool:anthropic-service/generate": {
53
+ "max_tokens": {
54
+ "max": 100,
55
+ "type": "integer"
56
+ },
57
+ "model": {
58
+ "allowed_values": [
59
+ "claude-sonnet-5"
60
+ ],
61
+ "type": "string"
62
+ }
63
+ },
64
+ "tool:openai-service/generate": {
65
+ "max_tokens": {
66
+ "max": 2000,
67
+ "type": "integer"
68
+ },
69
+ "model": {
70
+ "allowed_values": [
71
+ "gpt-4o-mini",
72
+ "gpt-4o"
73
+ ],
74
+ "type": "string"
75
+ }
76
+ }
77
+ }
78
+ },
79
+ "attestations": [
80
+ "eng_comp_update_attestation::{ params.touches_eng_comp == 'true' AND params.stmt_type == 'update' }"
81
+ ],
82
+ "description": "alice -- role: manager (broader LLM access than alice). Alation: select/update, eng_comp UPDATE attests, DELETE/DDL denied. OpenAI: gpt-4o-mini+gpt-4o, max_tokens<=2000. Anthropic: claude-sonnet-5, max_tokens<=100."
83
+ }