> C#/.NET Azure Function
Rural Water Azure Functions
C#/.NET 6.0 Azure Function application developed to enable an existing third party system to make a request to the Azure function and retrieve data from PostgreSQL.
The external third party system didn't have the capability to perform any OAUTH 2.0 token grant flows and was only able to make REST API requests with minimal headers like Authorization and provide an ApiKey, without engaging a third party consultancy for feature requests.
The azure function exposes an endpoint to the public and is locked down with IP whitelisting, Azure Function keys, and an ApiKey for authorization after a request is successfully made to the Azure Function.
The API request is then parsed and transformed into a GraphQL request which is sent to a secure system that the Azure Function has permissions to communicate with, which in turn makes the request to retrieve data from PostgreSQL. Once the data is retrieved it is then returned as a JSON response to the client/system.
Pre-requisites running in local development
- Create a
local.settings.json
in the root directory using the example provided and populate the environment variables. - Populate the 'Password' key with the password of your account used to generate Access Token for you registered application using 'Password Credentials' flow.
- To run the azure functions run
func start
and 'allow' connections.
Pre-requisites running in production environment e.g. deployed Function
- Deploy the Azure Function to your tenancy.
- Create an Azure Key Vault to connect your Azure Function following this tutorial. https://www.youtube.com/watch?v=6HKj5hOuD00
- Make sure you have turned on System Assigned Identity for the Azure Function via Settings -> Identity and applied it's Object (principal) ID to the Azure Key Vault's access policy, as per video above.
- Reference local.settings.json.example for the steps below.
- After watching the tutorial above, navigate to your Azure Function and go to Settings -> Configuration -> Application settings add the application options with the following 'name' syntax 'AuthOptions:keyName' and add the appropriate value for your applications configuration.
- Repeat the above for your secrets 'Secrets:keyName' and have the value reference the URL to the secrets in the Azure Key Vault e.g. '@Microsoft.KeyVault(SecretUri=https://xxx.vault.azure.net/secrets/ApiKey/xxxxxxxxxx)'
- Navigate to App keys and create a new host key for the Azure Function, host keys apply to all HTTP functions.
- These options and secrets will get injected into the application during runtime.
- (OPTIONAL) If you don't want to use AuthorizationLevel.Function, you can add the created Host key's value to configuration with key name 'Secrets:ApiKey' and incoming requests can use 'Authorization' header with key 'ApiKey', and utilize the AuthorizationHelper.ValidateApiKey method to authorize the request.
Troubleshooting notes
- If the client/tenant id you are pointing the Azure Function towards sits in a different tenancy/directory as to where the user account is created in Active Directory, you will receive the following error:
AADSTS50020: User account 'Unhandled exception inside AuthenticationHelper.' from identity provider 'https://sts.windows.net/xxxxx/' does not exist in tenant 'Directory Name' and cannot access the application 'xxxxxxx'(xxxxxxx) in that tenant. The account needs to be added as an external user in the tenant first. Sign out and sign in again with a different Azure Active Directory user account.
To resolve this login to the portal application on that environment using the user account that you are using for the Password Credentials flow and accept the prompts to allow the user access.
- Make sure CORS is configured to accept your Azure Functions URL/domain in the App API's ConfigMap