Deploying To IP Restricted Azure Function Apps Using GitHub Actions

Deploying To IP Restricted Azure Function Apps Using GitHub Actions

In the previous post we blocked our function app to be available only to the APIM via ip restrictions.

This secures our function app and it isn’t available publicly, any one that tries to access our function app url will get “HTTP 403 Forbidden”.

This secures our function app; now what about deploying code changes to the function app via GitHub Actions? we should be able to CI/CD to our function app, but there is a problem here. The GitHub action will fail with the same “HTTP 403 Forbidden”, this is because GitHub actions run on runners (its a hosted virtual environment), each time we run the Action we get a new runner and it can have a different ip address. So how can we get around this? do we white list the entire GitHub ip range?

GitHub’s ip ranges can change any time, so will have to keep scanning for changes to these ranges and proactively update our ip restrictions, this is not very scalable or practical. So what are other ways of getting around this? we have a couple of ways to get around this.

Possible Solutions

There are two viable solutions here

1. Use a self-hosted runner

Where you bring your own VM’s with static ip’s and whitelist these static ip’s

Pros:

  • Full control over your devops agents
  • Can optimize/reuse these agents for various CI/CD workloads for your cloud and on-prem deployments

Cons:

  • You have to provision and maintain your own VM’s, there will be time and effort required for this
  • Extra costs to maintain your own VM(s), although this could be optimized by turning them off after hours etc
  • You miss out on the free GitHub Action minutes you get
  • Extra work of provisioning VM’s, installing all the tooling for builds, maintaining and paying for them

2. Do some extra steps in the existing GitHub Actions

  1. Use the Azure CLI
  2. Do an az login
  3. Grab the public ip of the GitHub runner, you could use a simple public api like the ipify api to grab the public ip of the Github Runner
  4. Use az cli to update ip restriction to add this additional ip
  5. Do-your-normal-Deployment
  6. Use az cli to remove the ip added in step 4

Pros:

  • You use the same GitHub runner and workflow
  • No effort in provisioning or maintaining extra virtual machines yourself
  • Little bit of extra code is all that is needed

Cons:

  • There is a possibility that the GitHub action runner fails/crashes after doing step 4 but before it had a chance to get to step 5, you could be left with an extra ip address white listed in your app until you run the workflow again.

This post is all about how to go about doing option 2 (do some extra steps in the existing GitHub Actions), although there is one con (ie: the GitHub runner crashing during step 5 and leaving an ip address of the runner there), in my view this is a very small risk. The chances of a crash precisely at that point are low and even it does happen the risk of having the runner ip (only 1 extra ip) for a short duration until your next run happens is very low.

Show me the code

If you want to skip and just get to the code:

In the above GitHub Action it is deploying a hello world function app; it is doing a dotnet build, package and deploy. Those are all the standard bits of deploying a function app; lets go over the interesting bits

  1. Getting the GitHub Runners public ip
  2. Whitelisting this ip
  3. After a successful deploy of our app, we remove the ip added in step 2

For the first step we are using a public package haythem/public-ip@v1.2 to get the ip. We can also manually do a curl our >selves to the ipify api and grab the public ip ourselves. For the purposes of this demo we will use this package.

Step 1 - getting the GitHub runners public ip

1
2
3
- name: Public IP
id: ip
uses: haythem/public-ip@v1.2
  • Next for the second step we use the az cli to add the ip address.
  • First we use az webapp config to set the –use-same-restrictions-for-scm-site false, here we are saying don’t apply the same restriction as the main site to the scm site
  • Our main site is still safe with the right ip restrictions, our scm site is now ready for changes
  • Next we use az functionapp config access-restriction to add the GitHub runner ip to just the scm site

Step 2 - white listing the GitHub runner’s public ip

1
2
3
4
5
6
7
- name: 'Allow Github Runner IpAddress'
uses: azure/CLI@v1
with:
azcliversion: 2.37.0
inlineScript: |
az webapp config access-restriction set -g $ -n func-app-iprest-demo --use-same-restrictions-for-scm-site false
az functionapp config access-restriction add -g $ -n func-app-iprest-demo --rule-name github_runner --action Allow --ip-address $ --priority 100 --scm-site true

Finally we remove the ip address we added from the previous step and set the scm site access the same as our main site

Step 3 - after successful deploy, remove the GitHub runner’s public ip

1
2
3
4
5
6
7
- name: 'Remove Github Runner IpAddress'
uses: azure/CLI@v1
with:
azcliversion: 2.37.0
inlineScript: |
az functionapp config access-restriction remove -g $ -n func-app-iprest-demo --rule-name github_runner --scm-site true
az webapp config access-restriction set -g $ -n func-app-iprest-demo --use-same-restrictions-for-scm-site true

Finally 👏! we can now deploy using GitHub Actions to ip restricted function apps 🙌.

References

As always a big thank you to Unsplash for providing a huge range of images for free

Author

Ricky Gummadi

Posted on

2022-08-07

Updated on

2022-08-21

Licensed under

Comments