2020-12-04 11:11 pm #FestiveTechCalendar
In this walk-through, you will be guided through securing your Azure Functions so that a random user can’t just execute your functions, even if they have the function key and full function URL. Therefore, by the end of this walk-through you’ll have more security available than what you would get from just using a function key alone.
The overarching goal is to create your public-facing Application Programming Interface (API) in such a way that you can leverage Azure Functions without the functions being open to the world, and then you can use Azure API Management (APIM) as a public-facing facade to let specific customers into the appropriate APIs.
With APIM, you will not only be able to expose your own APIs as needed, but you can also route users to a third-party API without them even knowing you are using the third-party API, if you need to do so. Even if the customers do know that you are using a third-party API, all they need from you is one URL to access all of the APIs you need to expose to them. This also protects the customers from having to know what your third-party API key is, since they will never need to call the third-party API directly.
APIM also has additional gains when it comes to dealing with bad players. With APIM you can easily throttle users on an API. If you use a plan other than the consumption plan, you can further throttle the API by specific IP or subscription key. This functionality won’t be covered in this walk-through, but you will be set up to use it if you want to go deeper in the future.
This walkthrough is featured in day 6 of the festive tech calendar!
Watch the video of me working through this walkthrough here: Festive Tech Calendar [day 6]: Azure Functions and APIM
More info about the Festive Tech Calendar
To get started, you will need the following:
To simulate your current functions at Azure, for use in this walk-through you’ll just use a simple function app. This function app will contain a couple of simple functions so that you can see a few of the features of APIM later in the walk-through.
SimpleFunctionsSelect a folder that makes sense to you for storing the function app, then hit the
Create
button.Http Trigger
and use the Storage emulator
and give the function an authorization level of Function
.SimpleAuthorizationFunction
by right-clicking on the Function1.cs
file and renaming:SimpleAuthorizationFunctionMake sure to also update the FunctionName attribute to reflect the new name.
Add -> New Azure Function
.SimpleAnonymousFunction
SimpleAnonymousFunctionFor this function, choose
Anonymous
authorization and an Http Trigger
http://localhost:7071/api/SimpleAnonymousFunction?name=brian
Azure Cloud Shell
and select Bash
as the terminal. When the terminal is connected, run the following command [note: you should change the location to a region near you [az account list-locations –query “[].{Name:name}” -o table]]:rgname="azurefunctionsandapim" echo $rgname loc="centralus" echo $loc az group create --location $loc --name $rgname
storagename="afandapimstor$RANDOM" echo $storagename az storage account create --name $storagename --location $loc --resource-group $rgname --sku Standard_LRSThis will create your storage account for the Azure Function App.
fAppName="afandapimfa$RANDOM" echo $fAppName az functionapp create --name $fAppName --storage-account $storagename --consumption-plan-location $loc --resource-group $rgname --functions-version 3
NOTE: Make sure your function version matches what you created in Visual Studio (likely 3 at this point).This will create everything you need to deploy the app. Browse to the resource group to see all of the provisioned resources.
Build -> Publish
Azure
and Next
.Azure Function App (Windows)
and Next
Finish
Publish
Functions
to see that everything deployed as expected.SimpleAuthorizationFunction
to navigate to the function in the portal. Once there, click on Get Function URL
to get the URL for the public-facing function.&name=yourname
to the end to see that it is working as expected.https://afandapimfa28230.azurewebsites.net/api/SimpleAuthorizationFunction?code=RcJ1...&name=brian
The functions are publicly-exposed, so anyone with the key can execute them. In this task you will lock the functions down so that only authenticated users can execute the functions.
In the previous step, you’ve already proved that the functions are public, because they are accessible from postman. Now you need to lock them down.
Authentication / Authorization
option under Settings
.App Service Authentication
. Then select Azure Active Directory
. This will open the Azure Active Directory Settings
for the function app.Express
. Then save with the default settings by hitting OK
. If you already had an AD App, you could select it here, but you likely don’t, so you need to create a new one.OK
, you’ll return to the Authentication / Authorization
window. Make sure to hit Save
to actually save the application settings.Advanced
instance. Navigate away from the function app by going to the home directory at azure or going to some other resource, then come back to the function app. Select the Authentication / Authorization
option again, then change Active Directory to Advanced
. This will show you the Client ID and secret. Make a note of the Client ID and secret for use later in this walk-through.OK
and Save
again, so that your changes are applied. As a final step, make sure to select Log in with Azure Active Directory
in the Action to take when request is not authenticated
dropdown.401 - Unauthorized
error on execution of the function.In this task you will create the APIM that you will use for your public-facing facade. You will then create a couple of APIs to separate functions so you can see how the different subscriptions can give access to different clients.
After creating a couple of APIs, you will create a couple of Products, each having one or more subscriptions.
Create a Resource
.API Management
and select it when it pops up in the dropdown.Create
button.mypublicapiEnter whatever you want for the organization name, and your email for administrator email. Select the
Consumption
plan in the drop down (Consumption will spin up quickly, others take somewhere around 45 minutes to provision). In the end, you should have settings similar to what is shown here:Monitoring
tab, you will likely want to have Application Insights enabled in the real world. For this, you don’t need it. In my instance, I am turning it on and using the same AI instance that is being used by my function app. This is also likely not ideal as you probably don’t want to mix and match these resources into the same AI instance.IMPORTANT: In order for this APIM to communicate with the Azure Function App, you need to make sure that this APIM has a managed identity. You can enable that now during creation. In case you forget or didn’t do this, the way to do this will be covered shortly. For the demo, I’m leaving it unchecked on purpose.
off
for this demo - even though this may not be totally feasible in the real world, it should be the safest. Review and Create the APIM instance. This is another opportunity to get a coffee. If you selected a version other than the Consumption
plan, you should probably go to lunch. The APIM should be up in about 3-5 minutes. When the deployment completes, you can go to the resource group and drill into the APIM, or you can search for it by searching for API Management Services in the top search bar. Either way, find the APIM you created and navigate to it.APIs
, Subscriptions
, and the Gateway URL
which is named after the name you put in for the APIM instance. Additionally, another important menu is Managed Identities
which is not shown, but is in the left menu under Security.
APIs
option in the left menu.Function App
option to select the function app for use in the API.Authorization
function. Then hit Select
.AllPublicDataAlso change the API URL suffix to
PublicThen hit the
Create
button.GET
method, and then hit the Test
button at the top.Send
button to send a request.AllCustomerDataUse the URL Suffix
CustomerUse the same function app and include bot of your available functions. As before, none of the functions will be authorized, but the API is in place.
Public
data, exposing the SimpleAnonymousFunction
from the AllPublicData
API. The second product will expose the Customer
data, with access to both of the methods from the AllCustomerData
API. You could create an additional product to span both APIs, if you needed to do so. Create a new product by hitting the Products
option in the left menu. Then hit the + Add
button at the top.UnrestrictedGive it a description like
This is the Public Data ProductSet it to
Published
and leave the check boxes for Requires subscription
checked and Requires approval
unchecked. Then hit the Select API
button For this one, only select the AllPublicData
Then hit Create
Customer
API. Call this new APIClientAdditionally, make sure that this product also requires a subscription to be able to be used.
+ Add subscription
and create a new subscription with the namePremiumClientAnd the display name
Premium
.Subscriptions
. Note that your product subscription is also shown here.PublicBasicwith DisplayName
Basic
, and make sure to drill into the subscription and make a note of the subscription key.Unrestricted
Ocp-Apim-Subscription-Key
. This will be critical for your call. In Postman, create a new request. Use the GET
URL and save the request asAllPublicData Get SimpleAuthWhich points to the URL
https://mypublicapi.azure-api.net/Public/SimpleAnonymousFunction
Note: Your API will vary, of course.And hit the send button. You should a message similar to the following:
Ocp-Apim-Subscription-KeySet the value to one of the keys from your
Basic
subscription. Then resend the request. The message should change back to a 401 - You do not have permission.The main trick to getting this to work is to let your APIM instance work as if it is an authenticated user, so that the APIM can leverage your Azure Functions.
Managed Identities
which is under the Security
. Set the status to On
for System Assigned
(If you already set this, you will already have a system assigned id).Save
, then Yes
to create the id.App Registrations
now.All APIs
then click on the Policies
to open the All APIs -> Policies
window:<inbound />
policies:<authentication-managed-identity resource="your-function-app-client-id-goes-here" />
Name
to get the expected result.In this walk-through, you have seen how you can easily create a function app, deploy it to azure, lock down the function app to require authentication, and then use a public-facing facade created by the Azure APIM to allow users to get into the correct functions via subscription keys.
At the end of this walk-through, you have made it so the only gateway into your azure functions (APIs) is via the APIM or an authenticated user. When this is set, direct calls to your functions are blocked unless the user is authenticated. Additionally, you prevented direct calls to your APIM methods by requiring a subscription on each of the APIs. You saw how to easily add products and subscriptions to group your clients, and noted that you can easily rotate these subscription tokens if things go off track.
If you enjoyed this walk through, you should go deeper. At Opsgility, we have a training where you can explore these concepts and more in our Azure App Security challenge, and you can also earn a badge by completing this training. Check out our schedule here, or contact us to find out more about how you can take the Azure App Security challenge or other trainings through Skill Me UP Academy.
Additional concepts you will want to learn to enhance your knowledge include using the APIM to throttle bad players, version your APIs, connect to Azure Key Vault and get secrets, and do other things like make sure that users can’t see what your APIs are doing via the functions.
Categories: : C#, Azure, Azure Functions, APIM, Managed Identity, Azure AD