This guide will walk you through the steps required to install the gate(s) from your GitHub repository.
You will have to create one app for each of the gates you want to install.
Before proceeding with the installation, you need to create a GitHub App. The GitHub App will be used to authenticate the gates and to provide the required permissions to the gates.
Head to the official documentation for more information on how to create a GitHub App, or follow this simplified guide.
To create a GitHub App, follow these steps:
- Go to your GitHub account settings OR your organization settings and click on "Developer settings".
- Click on "GitHub Apps" and then click on "New GitHub App". Fill in the required information for your app, including the name, description, and homepage URL.
- Under "Webhook URL", enter the URL for your webhook function.
- This url is going to be
name-of-your-function
.azurewebsites.net/api/GATE
- where
GATE
is eitherDeployHoursGate
orIssuesGate
- You can also use a custom domain but you will need to configure it yourself.
- where
name-of-your-function
is the name of the function that you used when you deployed the function app and needs to be globally unique.- So before setting it here check if it exists (or you change it later if needed).
- This url is going to be
- Under "Webhook secret", enter a secret key that will be used to sign your webhook requests (optional but recommended).
- Under "Permissions & events", select the permissions and events that your app will need to access (see Permissions and Events below which permissions and events are need for each of the gates).
- Click on "Create GitHub App" to create your app.
- Take note of the Application ID in the
General
tab. You will need this later. - Generate a private key by clicking on the
Generate a private key
button. The key will be automatically downloaded, keep the file for later.
Warning If you setup the app as public, it means it can be installed by anyone who knows the application slug (but you need to make it public if you want to install the application in multiple organizations).
Once you've created your GitHub App, you'll need to install it on your repository(ies). We will do this later, first we will deploy the gate.
The Deploy Hours gate requires the following permissions:
- Repository Permissions:
- Deployments - Read and Write
- Single File - Read Only
- With the path
.github/deployhours-gate.yml
- With the path
- Events:
- Deployment protection rule
The Issues gate requires the following permissions:
- Repository Permissions:
- Deployments - Read and Write
- Actions - Read
- Issues - Read
- Single File - Read Only
- With the path
.github/issues-gate.yml
- With the path
- Events:
- Deployment protection rule
it may require more permissions depending on the search queries you intended to use (eg: include Pull Requests in the search query).
The Setup has scripts that provisions and configures the required Azure resources.
Run the script(s) for the gate(s) that you want to use.
There are two scripts:
- provision-deployhours-gate.sh - provisions the Azure resources for the Deploy Hours gate.
- provision-issues-gate.sh - provisions the Azure resources for the Issues gate.
There are the required Azure Subscription permissions for the scripts:
To Provision Resources
- Contributor at the subscription level if you want to create a new resource group.
- If the resource group(s) are already exist create Contributor at the resource group level.
To create the Service Principal
- At least
Microsoft.Authorization/*/Write
at the subscription level. Application Administrator
orApplication Developer
role at the Azure Directory level
If you don't have enough permissions to create the service principal, you can ask someone with the required permissions to create it and then configure manually on the GitHub Repository (See Configuring OIDC Manually
The scripts have the same parameters (run the script with the -h
or --help
parameter to information about all parameters).
This is the minimum set of parameters that you need to provide:
- Application Id
- Application Certificate
- Azure Resource Group name (it will be created it if doesn't exist).
- The repository name that contains the gate source code and it will be used to deploy the gate(s). This step is optional but if you skip it you will have to manually configure the gate(s).
For example, to provision the Deploy Hours Gate
, you can run the provision-issues-gate.sh
command:
Click to expand to see provision-issues-gate.sh execution example
$ ./provision-issues-gate.sh --app-id APP_ID_NUMBER --key-file CERTIFICATEFILE.PEM -g RESOURCE_GROUP_NAME --repo tspascoal/GitHubActions.Gates.Samples --function-name FUNCTION_NAME
Using subscription: XXXXX Sub
Creating Resource Group RESOURCE_GROUP_NAME in eastus if it doesn't exist
Deploying resources to RESOURCE_GROUP_NAME:
Function App Name: FUNCTION_NAME
Function App Short Name: issues
Service Bus Queue Name: issuesProcessing
App Insights Location: eastus
GitHub Application ID: 3XXXXX
GitHub Application Private Key: issues.pem
Deployment Outputs:
{
"functionAppId": {
"type": "String",
"value": "/subscriptions/XXXXX-XXXXXX-XXXXX-XXXXXX/resourceGroups/issues-gate/providers/Microsoft.Web/sites/issues-gate"
}
}
Creating service principal issues-gate-sp
Deleting credentials for e1c40616-4629-431e-b712-33f5eb5e240f
deleting credential with key 448891ac-0bf9-4bbb-a6bc-05a109d2e027
Adding OIDC federated credential to service principal issues-gate-sp
Creating federated credential for e1c40616-4629-431e-b712-33f5eb5e240f
Creating Federated Credential for repo tspascoal/GitHubActions.Gates.Samples default branch
"b626b464-2c23-4822-acb7-f9f5ce6765c5"
Federated credential tspascoal-GitHubActions.Gates.Samples-main already exists. Will skip variable creation.
If you want to recreate the federated credential, delete it first, with following command:
az ad app federated-credential delete --id e1c40616-4629-431e-b712-33f5eb5e240f --federated-credential-id tspascoal-GitHubActions.Gates.Samples-main
Creating Federated Credential for prod environment
"de136105-51ad-4b10-bbfd-8dd9abda99a7"
Federated credential tspascoal-GitHubActions.Gates.Samples-Prod-issues-gate already exists. Will skip variable creation.
If you want to recreate the federated credential, delete it first, with following command:
az ad app federated-credential delete --id e1c40616-4629-431e-b712-33f5eb5e240f --federated-credential-id tspascoal-GitHubActions.Gates.Samples-Prod-issues-gate
Setting RBAC permissions for the service principal.
Assigning Reader role to e1c40616-4629-431e-b712-33f5eb5e240f on [/subscriptions/XXXXX-XXXXXX-XXXXX-XXXXXX/resourceGroups/issues-gate]
Already assigned. Skipping it.
Assigning Contributor role to e1c40616-4629-431e-b712-33f5eb5e240f on [/subscriptions/XXXXX-XXXXXX-XXXXX-XXXXXX/resourceGroups/issues-gate/providers/Microsoft.Web/sites/issues-gate]
Already assigned. Skipping it.
Adding variables client-id,tenant-id and subscription-id to repo tspascoal/GitHubActions.Gates.Samples
updating variable ISSUES_GATE_CLIENT_ID
updating variable ISSUES_GATE_APP_NAME
setting secret ISSUES_GATE_TENANT_ID
setting secret ISSUES_GATE_SUBSCRIPTION_ID
Done!
Note The script has the following requirements:
These are the minimum set of parameters that you need to provide, replace the words in all caps with the appropriate values.
The script will:
- Create a resource group if it doesn't exist (
eastus
location by default or change it with--location
parameter). - Azure Resources:
- Create a Service Principal (with
deployhours-gate-sp
orissues-gate-sp
name. Change it with--sp-name
parameter) (Note: only if the repository is specified)- Adds two federated credentials (OIDC) to the Service Principal
- One that can be used to deploy from the main branch and another from the production environment.
- NO other credentials are added to the Service Principal.
Note if you pass an existing service principal, it will be reused and any credential it has will be deleted.
- Adds two federated credentials (OIDC) to the Service Principal
- Azure Storage Account (to store the function app code and data).
- Azure Key Vault
- Grants Read Access to the Azure Function App Managed Identity.
- Stores the following values in Key Vault
- GitHub App Private Key
- Webhook Secret
- The connection string to access the storage account.
- Azure Service Bus (Basic SKU)
- Grant access to Service Bus to the Azure Function App Managed Identity.
- Azure App Service Plan (dynamic SKU)
- Azure Function App
- Grants contributor access to the Service Principal for deployment.
- Azure Application Insights (
eastus
location or change it with--appinsights-location
parameter).
- Create a Service Principal (with
- Configure the Azure Function App with the required settings:
- GitHub Application Id
- A reference to Certificate in Key Vault
- A reference to Webhook Secret in Key Vault
- A reference to the connection string to access the storage account in Key Vault (both web jobs storage and content share storage).
- Service Bus Namespace
- Application Insights Instrumentation Key
- Optionally restricts the IP addresses to GitHub Webhooks IP addresses (Beware: If you enable this, you will have to guarantee they will be update if GitHub makes changes to webhooks IP addresses).
- Adds the following variables to the repository (if repository specified) These variables are used to deploy the gates to the function app (see Deploying the Gates:
DEPLOYHOURS_GATE_CLIENT_ID
DEPLOYHOURS_GATE_APP_NAME
- Adds the following secrets to the repository (if repository specified) These secrets are used to deploy the gates to the function app (see Deploying the Gates:
DEPLOYHOURS_GATE_TENANT_ID
DEPLOYHOURS_GATE_SUBSCRIPTION_ID
Note Only
bash
scripts are provided, to run this in windows either use Windows WSL, cygwin or Git bash shell.
If you haven't provided a repository name to the script or you don't have permissions to create the service principal, you will have to manually configure the OIDC for the Azure Function App (or deploy the gates manually).
You will need to ask your Azure Administrator (or create it yourself if you have enough permissions but want to do it manually instead of using the script) to create a Service Principal with the following permissions:
- Contributor access at the subscription level (not recommended)
- Contributor access at the resource group level you created.
- Contributor access at the Azure Function (recommended way to follow the least privilege principle)
The Service principal will need to have two federated credentials, one that can be used to deploy from the main branch and another from the production environment.
- For the main branch, set the following parameters:
- Organization - The account or organization name of the GitHub repository you will be deploying from
- Repository - The name of the GitHub repository you will be deploying from
- Entity Type - Branch
- Branch - The name of the branch you will be deploying from (
main
)
- For the production environment, set the following parameters:
- Organization - The account or organization name of the GitHub repository you will be deploying from
- Repository - The name of the GitHub repository you will be deploying from
- Entty Type - Environment
- Environment - The environment name. It should be
Prod-FUNCTIONAPPNAME
(where FUNCTIONAPPNAME is the name of the Azure Function App you will be deploying to)
In order to configure the OIDC for the Azure Function App, you will need to be provided with the following information (if you want to use credentials instead of OIDC you will need to change the Azure/Login action parameters in the deploy-deployhours-gate.yml file):
- Client Id (the azure portal shows it as Application Id)
- Azure Directory Tenant Id
- Azure Subscription Id
*Note: You can use the same service principal for both the gates if you like.
Now that you have a service principal with the required permissions, you will need to configure the OIDC for your GitHub repository
Those values will need to be stored in Repository:
- variables:
DEPLOYHOURS_GATE_CLIENT_ID
DEPLOYHOURS_GATE_APP_NAME
- The name of the Azure Function App you specified in the script.
- secrets:
DEPLOYHOURS_GATE_TENANT_ID
DEPLOYHOURS_GATE_SUBSCRIPTION_ID
*Note: If configuring the Issues gate, use the prefix
ISSUES_GATE_
instead ofDEPLOYHOURS_GATE_
in the variable/secret names.
If you have configured your enterprise or Organization IP allow lists, you will need to enable the Functions Outbound IP in Applications IP allow list.
The function gates are exposed to the internet therefore they can be called by anyone. If you configured the GitHub application with a secret the integrity of the request is guaranteed since the secret is used to sign the request and the code verifies the signature, so while the request is not tampered with, it can be still called by anyone if they know the URL, this may result in higher charges if someone decides to call the function app repeatedly.
If you are worried about this scenario, access to the function app can be restricted by IP using Azure built-in features by setting up App Service access restrictions to guarantee that only request coming from GitHub will be allowed to call the function app.
This can be configured by passing --set-ip-restrictions
to the setup script. It will add the GitHub's WebHook IP ranges to the function app's access restrictions. The IP ranges are retrieved from the GitHub Meta API.
Or you can configure an existing function app with the script set-function-ip-restrictions.sh
(setup folder) by passing the resource group and the gate function name. (or do it manually on the portal, automate with the Azure CLI or Azure PowerShell).
This script adds the IPs listed in the meta API with an allow
access entry in the function access restrictions. It will remove any other IP (which have the ghhook
name) that is not in the list. (this ensures IPs that you may have added manually are not removed). And it will add a deny all rule at the end.
Warning GitHub webhooks IPs may change over time, so you will need to ensure that the IP allow list is updated accordingly.
In order to deploy the gates you have two options:
- Create a GitHub Release, this will deploy both gates.
- Manually trigger the workflow to deploy the gate(s) you wish to deploy:
- deploy-deployhours-gate.yml to deploy the DeployHours gate.
- issues-gate.yml to deploy the Issues gate.
If you don't want to use GitHub Actions to deploy the gates, you can deploy them manually, see the following guides depending on the IDE you are using:
With:
And you will have to configure the app following settings:
APPINSIGHTS_INSTRUMENTATIONKEY
- The instrumentation key of the Application Insights instance you want to use.SERVICEBUS_CONNECTION__fullyQualifiedNamespace
- The service bus name (this will use the function managed identity to access the service bus)SERVICEBUS_CONNECTION
Use this instead of the previous one if you want to use a service bus connection string instead of the managed identity. (store it on key vault preferably). This won't work if you have used the script to deploy the gates since it disables local authentication the service bus (see).
GHAPP_ID
- The GitHub Application IdGHAPP_PEMCERTIFICATE
- The GitHub Application PEM certificate (store it on key vault preferably)GHAPP_WEBHOOKSECRET
- The GitHub Application Webhook Secret IF you configured it (store it on key vault preferably)
Both gates have a test endpoint that you can use to test the deployment. The endpoint is /api/ValidateSettings
and it will return the following
information:
-
Configuration Settings. The relevant settings will be shown and the sensitive ones will be masked (but their length will be returned)
-
The (relevant) app settings values (some of them will be masked and their size will be returned)
-
GitHub App. The App name, description, url and events it is subscribed to.
This endpoint is protected so you need a valid token to call it.
Get the token from:
- Azure Portal:
- Either in the App Keys menu of the Azure Function App or in the Functions menu, in the "Get Function Url" option.
- With Azure CLI
functionapp
command
The url will be something like https://YOURFUNCTIONAPP.azurewebsites.net/api/ValidateSettings?code=YOURTOKEN
It will return HTML so it's human readable with just a browser.
If you optionally pass a installId
query parameter, the endpoint will return the installation information for that installation id (this can only be done after the app is installed in the repository).
If no GitHub App data is found then it means the GitHub call has failed because either the application id or certificate are incorrect.
Now that the gates have been deployed, you will need to install the application in your GitHub repositor(y/ies) so you can configure the gates you your repositor(y/ies).
See Installing GitHub Apps for more information, or use the shortened version here:
- Go to the "Install App" page for your GitHub App.
- Click on "Install" to install the app on your repository.
- Select the repository where you want to install the app (or all repositories)
- It will need to be installed on all repositories you wish to run the gate on OR repositories which has date the gates will need (eg: The issues gate per your configuration might read issue data from other repositories)
This either requires admin privileges on the account/organization, in case you don't have enough permissions the GitHub administrator will need to approve the installation.
Now that everything is deployed and installed, you will need to configure the gates.
Jump to the Configuring the gates documentation for more info.