2023-05-19 - archived - use personal repo to continue following my Azure notes
-
Easy auth:
- In resource explorer, location for easy auth is
/providers/Microsoft.Web/sites/APP-SERVICE-NAME/config/authsettingsV2/list?api-version=2020-12-01
- Login: https://APP-SERVICE-NAME.azurewebsites.net/.auth/login/aad
- Logout: https://APP-SERVICE-NAME.azurewebsites.net/.auth/logout
- loginParameters for easy auth single app only: ["response_type=code id_token","scope=openid offline_access profile"]
- loginParameters for easy auth single app only + Graph: ["response_type=code id_token","scope=openid offline_access profile https://graph.microsoft.com/User.Read"]
- loginParameters for easy auth single app only + Graph + 2nd app's API: ["response_type=code id_token","scope=openid offline_access profile https://graph.microsoft.com/User.Read api://SECOND-APP-CLIENT-ID/user_impersonation"]
"identityProviders": { "azureActiveDirectory": { "enabled": true, "registration": { "openIdIssuer": "https://sts.windows.net/51397421-87d6-42c1-8bab-98305329d75c/v2.0", "clientId": "4480f5c3-01a7-426a-b602-dba4e7b3f776", "clientSecretSettingName": "MICROSOFT_PROVIDER_AUTHENTICATION_SECRET" }, "login": { "loginParameters": [ "response_type=code id_token", "scope=openid offline_access profile https://graph.microsoft.com/User.Read" ], "disableWWWAuthenticate": false }, "validation": { "jwtClaimChecks": {}, "allowedAudiences": [], "defaultAuthorizationPolicy": { "allowedPrincipals": {} } } }} ```
- In resource explorer, location for easy auth is
# acquire logged in user context
export CURRENT_USER=$(az account show --query user.name -o tsv)
export CURRENT_USER_OBJECTID=$(az ad user show --id $CURRENT_USER --query objectId -o tst)
Example of sorting all subscriptions by name. Supporting documentation for sort_by
.
az account list --query "sort_by([].{Name:name, SubscriptionId:id, TenantId:tenantId}, &Name)" --output table
- Iterators and paging through results
- Brian's blob post: Async Iterators in the Azure SDK for JavaScript/TypeScript
- In order to get continuation token for next page, you have to call .next()
- Error: "The directory object quota limit for the Principal has been exceeded. Please ask your administrator to increase the quota limit or delete objects to reduce the used quota." - StackOverflow showing PowerShell command to fix
-
Easy auth settings
- WEBSITE_AUTH_CLIENT - don't create - is created and hidden when you configure easy auth
- MICROSOFT_PROVIDER_AUTHENTICATION_SECRET - set this to the app registration secret
- WEBSITE_AUTH_TENANT_ID - this is either your tenant or "COMMON", might be another name depending on how the config is programmed in JS
-
Port
- 8080 is default
- change via App Setting -> WEBSITES_PORT or use following
process.env.PORT || 3000
-
Install NPM packages after Zip deploy
- App Setting -> SCM_DO_BUILD_DURING_DEPLOYMENT -> true - this setting is created for you if you create app service from VSCode
-
Configure logging to container logs
- Monitoring -> Logs -> Enable
- Download lixux logs: https://YOUR-RESOURCE-NAME.scm.azurewebsites.net/api/logs/docker/zip
-
Configure application insights
- Settings -> Configuration -> Turn on Application Insights
-
Configure easy auth:
- Add Authentication with Microsoft Identity provider, copy client id to notepad (id and secret are already in app settings for you)
- Configure
authsettingsV2
in Azure Resource Explorer (link above) to add thelogin
section"identityProviders": { "azureActiveDirectory": { "enabled": true, "login": { "loginParameters":[ "response_type=code id_token", "scope=openid offline_access profile https://graph.microsoft.com/User.Read" ] } } } },
-
View logs
- container startup logs: /Logs/*_docker.log
- runtime logs (console.log: /Logs/*_default_docker.log
- easyauth: /Logs/*_easyauth_docker.log
Azure cloud shell allows you to use Azure CLI without having to install it.
- Has jq (commandline JSON processor) installed
- AdventureWorks
- Convert SQL API JSON to MongoDB API BSON - .NET gist
- Cosmisworks data - customers and products
- Customers.json
- Products.json
- Azure SDK for Cosmos DB
- CosmicWorks - GitHub repo
- cosmos-db-mongodb-api-javascript-samples - GitHub repo
- MongoDB aggregations book
- Cognitive Search 10K books
- Server-side JS - Azure/azure-cosmosdb-js-server
- Node sp sample
postgresql://USER@RESOURCENAME:PASSWORD@RESOURCENAME.postgres.database.azure.com:5432/DATABASENAME?&sslmode=require
- Create SAS token in portal then compare to SAS token created with generateBlobSASQueryParameters
- Timer trigger won't run if you are logging to Application Insights with too high a sampling rate
- Timer trigger may stop working if functions run past default timeout (set the default timeout explicitly)
- Review "Diagnose and solve problems" in portal to find issues
{
"bindings": [
{
"type": "httpTrigger",
"name": "req",
"direction": "in",
"methods": [ "get" ],
"route": "products/{category:alpha}/{id:int?}"
},
{
"type": "http",
"name": "res",
"direction": "out"
}
]
}
Notice that blob trigger follows the queue trigger settings.
{
"version": "2.0",
"extensions": {
"queues": {
"maxPollingInterval": "00:00:02",
"visibilityTimeout" : "00:00:30",
"batchSize": 16,
"maxDequeueCount": 5, // retries the function for that blob 5 times by default
"newBatchThreshold": 8,
"messageEncoding": "base64"
}
}
}
- name: 'Run Azure Functions Action'
uses: Azure/functions-action@v1
id: fa
with:
app-name: 'AdvocacyGithubTraffic'
slot-name: 'Production'
package: '${{ env.AZURE_FUNCTIONAPP_PACKAGE_PATH }}/output'
publish-profile: ${{ secrets.AZUREAPPSERVICE_PUBLISHPROFILE_6F0DB2747FBF4EFFADD6A4472638F303 }}
- name: Upload artifact for deployment job
uses: actions/upload-artifact@v2
with:
name: ${{ secrets.DEPLOY_APP_NAME }}
path: |
.
!./node_modules
- Found in basic-express-typescript
- Combine with App Service deployment
- Install NPM packages after Zip deploy
- App Setting -> SCM_DO_BUILD_DURING_DEPLOYMENT -> true
If learn sandbox doesn't let you in, recreate a new one which resets.
- Must switch tenant to Sandbox tenant in both portal and VSCode
The Learn sandbox subscription has the following name and tenant ID:
- Name: Concierge Subscription
- Tenant ID: 604c1504-c6a3-4080-81aa-b33091104187
// package.json - type: "module"
import graph from '@microsoft/microsoft-graph-client';
import 'isomorphic-fetch';
const getAuthenticatedClient = (accessToken) => {
// Initialize Graph client
const client = graph.Client.init({
// Use the provided access token to authenticate requests
authProvider: (done) => {
done(null, accessToken);
}
});
return client;
}
// https://developer.microsoft.com/en-us/graph/graph-explorer
// https://jwt.ms/
// https://github.com/Azure-Samples/ms-identity-easyauth-nodejs-storage-graphapi/blob/main/2-WebApp-graphapi-on-behalf/controllers/graphController.js
const main = async (accessToken) => {
try {
const graphClient = getAuthenticatedClient(accessToken);
const profile = await graphClient
.api('/me')
.get();
return profile;
} catch (err) {
throw err;
}
}
const accessToken = "... replace with your access token ...";
main(accessToken).then((userData)=>{
console.log(userData);
}).catch((err)=>{
console.log(err);
})
// package.json - type: "module"
import axios from 'axios';
// https://developer.microsoft.com/en-us/graph/graph-explorer
// https://jwt.ms/
const main = async (accessToken) => {
try {
const url = 'https://graph.microsoft.com/v1.0/me';
const options = {
method: 'GET',
headers: {
Authorization: 'Bearer ' + accessToken,
'Content-type': 'application/json',
},
};
const graphResponse = await axios.get(url, options);
const { data } = await graphResponse;
return data;
} catch (err) {
throw err;
}
}
const accessToken = "... replace with your access token ...";
main(accessToken).then((userData)=>{
console.log(userData);
}).catch((err)=>{
console.log(err);
})
- Look up extension in marketplace
- On extensions page on marketplace, find source code repo under project details
- Open issue on repo
In ./.vscode/launch.json
file:
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Launch Program",
"skipFiles": [
"<node_internals>/**"
],
// Use the ${file} variables
"program": "${workspaceFolder}\\${file}"
}
]
}
In ./.vscode/launch.json
file:
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Launch Program",
"skipFiles": [
"<node_internals>/**"
],
"program": "${workspaceFolder}\\${file}",
// Use this line to indicate an external terminal - such as reading into program from user input
"console": "externalTerminal"
}
]
}
- Always run functions app in docker container because Functions runtime are directly tied to Node runtime
- Make sure Azure Functions extensions in installed and loaded in VS Code in the container. The extenion may be in ./vscode/extensions.json, but may not be loaded correctly