Skip to content

Commit

Permalink
Update Access Controlling (#84)
Browse files Browse the repository at this point in the history
* Add clean policy updated

* Update access controlling lab
  • Loading branch information
simonkurtz-MSFT authored Jan 8, 2025
1 parent 883b16e commit ef3f929
Show file tree
Hide file tree
Showing 3 changed files with 195 additions and 492 deletions.
217 changes: 129 additions & 88 deletions labs/access-controlling/access-controlling.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -47,36 +47,26 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 1,
"metadata": {
"metadata": {}
},
"outputs": [],
"source": [
"import os\n",
"import json\n",
"import datetime\n",
"import requests\n",
"\n",
"deployment_name = os.path.basename(os.path.dirname(globals()['__vsc_ipynb_file__']))\n",
"resource_group_name = f\"lab-{deployment_name}\" # change the name to match your naming style\n",
"resource_group_location = \"westeurope\"\n",
"apim_resource_name = \"apim\"\n",
"apim_resource_location = \"westeurope\"\n",
"apim_resource_sku = \"Basicv2\"\n",
"openai_resources = [ {\"name\": \"openai1\", \"location\": \"swedencentral\"}, {\"name\": \"openai2\", \"location\": \"francecentral\"} ] # list of OpenAI resources to deploy. Clear this list to use only the mock resources\n",
"openai_resources_sku = \"S0\"\n",
"\n",
"openai_resources = [\n",
" {\"name\": \"openai1\", \"location\": \"swedencentral\"},\n",
" {\"name\": \"openai2\", \"location\": \"francecentral\"}\n",
"]\n",
"openai_model_name = \"gpt-35-turbo\"\n",
"openai_model_version = \"0613\"\n",
"openai_deployment_name = \"gpt-35-turbo\"\n",
"openai_api_version = \"2024-02-01\"\n",
"openai_specification_url='https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cognitiveservices/data-plane/AzureOpenAI/inference/stable/' + openai_api_version + '/inference.json'\n",
"openai_backend_pool = \"openai-backend-pool\"\n",
"mock_backend_pool = \"mock-backend-pool\"\n",
"mock_webapps = [ {\"name\": \"openaimock1\", \"endpoint\": \"https://openaimock1.azurewebsites.net\"}, {\"name\": \"openaimock2\", \"endpoint\": \"https://openaimock2.azurewebsites.net\"} ]\n",
"\n",
"log_analytics_name = \"workspace\"\n",
"app_insights_name = 'insights'\n",
"\n",
"app_registration_name = \"ai-gateway-openai-app\"\n"
]
Expand All @@ -96,11 +86,20 @@
"metadata": {},
"outputs": [],
"source": [
"# type: ignore\n",
"\n",
"cmd_stdout = ! az account show --query homeTenantId --output tsv\n",
"tenant_id = cmd_stdout.n\n",
"print(f\"👉🏻 Tenant Id: {tenant_id}\")\n",
"\n",
"client_id = ! az ad app list --filter \"displayName eq '{app_registration_name}'\" --query [0].appId --output tsv\n",
"\n",
"if not client_id:\n",
" client_id = ! az ad app create --display-name {app_registration_name} --query appId --is-fallback-public-client true --output tsv\n",
"\n",
"cmd_stdout = ! az ad app create --display-name {app_registration_name} --query appId --is-fallback-public-client true --output tsv\n",
"client_id = cmd_stdout.n\n"
"client_id = client_id[0] if client_id else None\n",
"\n",
"print(f\"👉🏻 Client Id: {client_id}\")\n"
]
},
{
Expand All @@ -118,11 +117,17 @@
"metadata": {},
"outputs": [],
"source": [
"# %load ../../shared/snippets/create-az-resource-group.py\n",
"# type: ignore\n",
"\n",
"import datetime\n",
"\n",
"resource_group_stdout = ! az group create --name {resource_group_name} --location {resource_group_location}\n",
"\n",
"if resource_group_stdout.n.startswith(\"ERROR\"):\n",
" print(resource_group_stdout)\n",
"else:\n",
" print(\"✅ Azure Resource Group \", resource_group_name, \" created ⌚ \", datetime.datetime.now().time())"
" print(f\"✅ Azure Resource Group {resource_group_name} created ⌚ {datetime.datetime.now().time()}\")\n"
]
},
{
Expand All @@ -141,43 +146,44 @@
"metadata": {},
"outputs": [],
"source": [
"if len(openai_resources) > 0:\n",
" backend_id = openai_backend_pool if len(openai_resources) > 1 else openai_resources[0].get(\"name\")\n",
"elif len(mock_webapps) > 0:\n",
" backend_id = mock_backend_pool if len(mock_backend_pool) > 1 else mock_webapps[0].get(\"name\")\n",
"# %load ../../shared/snippets/create-az-deployment.py\n",
"# type: ignore\n",
"\n",
"import json\n",
"\n",
"backend_id = \"openai-backend-pool\" if len(openai_resources) > 1 else openai_resources[0].get(\"name\")\n",
"\n",
"with open(\"policy.xml\", 'r') as policy_xml_file:\n",
" policy_template_xml = policy_xml_file.read()\n",
" policy_xml = policy_template_xml.replace(\"{backend-id}\", backend_id).replace(\"{aad-client-application-id}\", client_id).replace(\"{aad-tenant-id}\", tenant_id)\n",
" policy_xml = policy_xml_file.read()\n",
"\n",
" if \"{backend-id}\" in policy_xml:\n",
" policy_xml = policy_xml.replace(\"{backend-id}\", backend_id)\n",
"\n",
" if \"{aad-client-application-id}\" in policy_xml:\n",
" policy_xml = policy_xml.replace(\"{aad-client-application-id}\", client_id)\n",
"\n",
" if \"{aad-tenant-id}\" in policy_xml:\n",
" policy_xml = policy_xml.replace(\"{aad-tenant-id}\", tenant_id)\n",
"\n",
" policy_xml_file.close()\n",
"open(\"policy.xml\", 'w').write(policy_xml)\n",
"open(\"policy-updated.xml\", 'w').write(policy_xml)\n",
"\n",
"bicep_parameters = {\n",
" \"$schema\": \"https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#\",\n",
" \"contentVersion\": \"1.0.0.0\",\n",
" \"parameters\": {\n",
" \"mockWebApps\": { \"value\": mock_webapps },\n",
" \"mockBackendPoolName\": { \"value\": mock_backend_pool },\n",
" \"openAIBackendPoolName\": { \"value\": openai_backend_pool },\n",
" \"openAIConfig\": { \"value\": openai_resources },\n",
" \"openAIDeploymentName\": { \"value\": openai_deployment_name },\n",
" \"openAISku\": { \"value\": openai_resources_sku },\n",
" \"openAIModelName\": { \"value\": openai_model_name },\n",
" \"openAIModelVersion\": { \"value\": openai_model_version },\n",
" \"openAIAPISpecURL\": { \"value\": openai_specification_url },\n",
" \"apimResourceName\": { \"value\": apim_resource_name},\n",
" \"apimResourceLocation\": { \"value\": apim_resource_location},\n",
" \"apimSku\": { \"value\": apim_resource_sku},\n",
" \"logAnalyticsName\": { \"value\": log_analytics_name },\n",
" \"applicationInsightsName\": { \"value\": app_insights_name }\n",
" }\n",
" \"$schema\": \"https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#\",\n",
" \"contentVersion\": \"1.0.0.0\",\n",
" \"parameters\": {\n",
" \"openAIConfig\": { \"value\": openai_resources },\n",
" \"openAIDeploymentName\": { \"value\": openai_deployment_name },\n",
" \"openAIModelName\": { \"value\": openai_model_name },\n",
" \"openAIModelVersion\": { \"value\": openai_model_version },\n",
" \"openAIAPIVersion\": { \"value\": openai_api_version }\n",
" }\n",
"}\n",
"\n",
"with open('params.json', 'w') as bicep_parameters_file:\n",
" bicep_parameters_file.write(json.dumps(bicep_parameters))\n",
"\n",
"! az deployment group create --name {deployment_name} --resource-group {resource_group_name} --template-file \"main.bicep\" --parameters \"params.json\"\n",
"\n",
"open(\"policy.xml\", 'w').write(policy_template_xml)\n"
"! az deployment group create --name {deployment_name} --resource-group {resource_group_name} --template-file \"main.bicep\" --parameters \"params.json\"\n"
]
},
{
Expand All @@ -196,23 +202,55 @@
"metadata": {},
"outputs": [],
"source": [
"deployment_stdout = ! az deployment group show --name {deployment_name} -g {resource_group_name} --query properties.outputs.apimServiceId.value -o tsv\n",
"apim_service_id = deployment_stdout.n\n",
"print(\"👉🏻 APIM Service Id: \", apim_service_id)\n",
"\n",
"deployment_stdout = ! az deployment group show --name {deployment_name} -g {resource_group_name} --query properties.outputs.apimSubscriptionKey.value -o tsv\n",
"apim_subscription_key = deployment_stdout.n\n",
"deployment_stdout = ! az deployment group show --name {deployment_name} -g {resource_group_name} --query properties.outputs.apimResourceGatewayURL.value -o tsv\n",
"apim_resource_gateway_url = deployment_stdout.n\n",
"print(\"👉🏻 API Gateway URL: \", apim_resource_gateway_url)\n",
"\n",
"deployment_stdout = ! az deployment group show --name {deployment_name} -g {resource_group_name} --query properties.outputs.logAnalyticsWorkspaceId.value -o tsv\n",
"workspace_id = deployment_stdout.n\n",
"print(\"👉🏻 Workspace ID: \", workspace_id)\n",
"\n",
"deployment_stdout = ! az deployment group show --name {deployment_name} -g {resource_group_name} --query properties.outputs.applicationInsightsAppId.value -o tsv\n",
"app_id = deployment_stdout.n\n",
"print(\"👉🏻 App ID: \", app_id)"
"# %load ../../shared/snippets/deployment-outputs.py\n",
"# type: ignore\n",
"\n",
"# Obtain all of the outputs from the deployment\n",
"stdout = ! az deployment group show --name {deployment_name} -g {resource_group_name} --query properties.outputs -o json\n",
"outputs = json.loads(stdout.n)\n",
"\n",
"# Extract the individual properties\n",
"apim_service_id = outputs.get('apimServiceId', {}).get('value', '')\n",
"apim_subscription_key = outputs.get('apimSubscriptionKey', {}).get('value', '')\n",
"apim_subscription1_key = outputs.get('apimSubscription1Key', {}).get('value', '')\n",
"apim_subscription2_key = outputs.get('apimSubscription2Key', {}).get('value', '')\n",
"apim_subscription3_key = outputs.get('apimSubscription3Key', {}).get('value', '')\n",
"apim_resource_gateway_url = outputs.get('apimResourceGatewayURL', {}).get('value', '')\n",
"workspace_id = outputs.get('logAnalyticsWorkspaceId', {}).get('value', '')\n",
"app_id = outputs.get('applicationInsightsAppId', {}).get('value', '')\n",
"function_app_resource_name = outputs.get('functionAppResourceName', {}).get('value', '')\n",
"cosmosdb_connection_string = outputs.get('cosmosDBConnectionString', {}).get('value', '')\n",
"\n",
"# Print the extracted properties if they are not empty\n",
"if apim_service_id:\n",
" print(f\"👉🏻 APIM Service Id: {apim_service_id}\")\n",
"\n",
"if apim_subscription_key:\n",
" print(f\"👉🏻 APIM Subscription Key (masked): ****{apim_subscription_key[-4:]}\")\n",
"\n",
"if apim_subscription1_key:\n",
" print(f\"👉🏻 APIM Subscription Key 1 (masked): ****{apim_subscription1_key[-4:]}\")\n",
"\n",
"if apim_subscription2_key:\n",
" print(f\"👉🏻 APIM Subscription Key 2 (masked): ****{apim_subscription2_key[-4:]}\")\n",
"\n",
"if apim_subscription3_key:\n",
" print(f\"👉🏻 APIM Subscription Key 3 (masked): ****{apim_subscription3_key[-4:]}\")\n",
"\n",
"if apim_resource_gateway_url:\n",
" print(f\"👉🏻 APIM API Gateway URL: {apim_resource_gateway_url}\")\n",
"\n",
"if workspace_id:\n",
" print(f\"👉🏻 Workspace ID: {workspace_id}\")\n",
"\n",
"if app_id:\n",
" print(f\"👉🏻 App ID: {app_id}\")\n",
"\n",
"if function_app_resource_name:\n",
" print(f\"👉🏻 Function Name: {function_app_resource_name}\")\n",
"\n",
"if cosmosdb_connection_string:\n",
" print(f\"👉🏻 Cosmos DB Connection String: {cosmosdb_connection_string}\")\n"
]
},
{
Expand Down Expand Up @@ -247,21 +285,17 @@
"outputs": [],
"source": [
"import json\n",
"import logging\n",
"\n",
"import requests\n",
"import msal\n",
"\n",
"app = msal.PublicClientApplication(\n",
" client_id, authority=\"https://login.microsoftonline.com/\" + tenant_id)\n",
"app = msal.PublicClientApplication(client_id, authority = \"https://login.microsoftonline.com/\" + tenant_id)\n",
"\n",
"flow = app.initiate_device_flow(scopes = [\"User.Read\"])\n",
"\n",
"flow = app.initiate_device_flow(scopes=[\"User.Read\"])\n",
"if \"user_code\" not in flow:\n",
" raise ValueError(\n",
" \"Fail to create device flow. Err: %s\" % json.dumps(flow, indent=4))\n",
" \"Fail to create device flow. Err: %s\" % json.dumps(flow, indent = 4))\n",
"\n",
"print(flow[\"message\"])\n",
"\n"
"print(flow[\"message\"])"
]
},
{
Expand All @@ -278,6 +312,8 @@
"metadata": {},
"outputs": [],
"source": [
"import requests\n",
"\n",
"result = app.acquire_token_by_device_flow(flow)\n",
"\n",
"if \"access_token\" in result:\n",
Expand All @@ -286,7 +322,7 @@
" graph_data = requests.get( # Use token to call downstream service\n",
" \"https://graph.microsoft.com/v1.0/me\",\n",
" headers={'Authorization': 'Bearer ' + access_token},).json()\n",
" print(\"Graph API call result: %s\" % json.dumps(graph_data, indent=2))\n",
" print(\"Graph API call result: %s\" % json.dumps(graph_data, indent = 2))\n",
" # print(access_token) # Use a tool like https://jwt.io/ to decode the access token and see its contents\n",
"else:\n",
" print(result.get(\"error\"))\n",
Expand All @@ -311,15 +347,17 @@
"source": [
"url = apim_resource_gateway_url + \"/openai/deployments/\" + openai_deployment_name + \"/chat/completions?api-version=\" + openai_api_version\n",
"\n",
"messages={\"messages\":[\n",
" {\"role\": \"system\", \"content\": \"You are a sarcastic, unhelpful assistant.\"},\n",
"messages = { \"messages\": [\n",
" {\"role\": \"system\", \"content\": \"You are a sarcastic unhelpful assistant.\"},\n",
" {\"role\": \"user\", \"content\": \"Can you tell me the time, please?\"}\n",
"]}\n",
"response = requests.post(url, headers = {'api-key':apim_subscription_key, 'Authorization': 'Bearer ' + access_token}, json = messages)\n",
"print(\"status code: \", response.status_code)\n",
"\n",
"response = requests.post(url, headers = {'api-key': apim_subscription_key, 'Authorization': 'Bearer ' + access_token}, json = messages)\n",
"print(f\"status code: {response.status_code}\")\n",
"\n",
"if (response.status_code == 200):\n",
" data = json.loads(response.text)\n",
" print(\"response: \", data.get(\"choices\")[0].get(\"message\").get(\"content\"))\n",
" print(f\"response: {data.get(\"choices\")[0].get(\"message\").get(\"content\")}\")\n",
"else:\n",
" print(response.text)\n"
]
Expand All @@ -340,18 +378,21 @@
"metadata": {},
"outputs": [],
"source": [
"\n",
"from openai import AzureOpenAI\n",
"messages=[\n",
" {\"role\": \"system\", \"content\": \"You are a sarcastic, unhelpful assistant.\"},\n",
"\n",
"messages = [\n",
" {\"role\": \"system\", \"content\": \"You are a sarcastic unhelpful assistant.\"},\n",
" {\"role\": \"user\", \"content\": \"Can you tell me the time, please?\"}\n",
"]\n",
"\n",
"client = AzureOpenAI(\n",
" azure_endpoint=apim_resource_gateway_url,\n",
" api_key=apim_subscription_key,\n",
" api_version=openai_api_version \n",
" azure_endpoint = apim_resource_gateway_url,\n",
" api_key = apim_subscription_key,\n",
" api_version = openai_api_version\n",
")\n",
"response = client.chat.completions.create(model=openai_model_name, messages=messages, extra_headers={\"Authorization\": \"Bearer \" + access_token})\n",
"\n",
"response = client.chat.completions.create(model = openai_model_name, messages = messages, extra_headers = {\"Authorization\": \"Bearer \" + access_token}) # type: ignore\n",
"\n",
"print(response.choices[0].message.content)\n"
]
},
Expand All @@ -369,7 +410,7 @@
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"display_name": ".venv",
"language": "python",
"name": "python3"
},
Expand All @@ -383,7 +424,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.12.2"
"version": "3.12.0"
}
},
"nbformat": 4,
Expand Down
Loading

0 comments on commit ef3f929

Please sign in to comment.