Salesforce, Python, SQL, & other ways to put your data where you need it

Need event music? 🎸

Live and recorded jazz, pop, and meditative music for your virtual conference / Zoom wedding / yoga class / private party with quality sound and a smooth technical experience

How many Entra App Registrations do I need?

25 Oct 2023 🔖 security devops integration git azure
💬 EN

Table of Contents

Creating an App Registration (and its corresponding Service Principal) in Microsoft Entra ID (formerly known as “Azure Active Directory,” “Azure AD,” or “AAD”) lets a code-deployment-automation “CI/CD pipeline” (such as an Azure DevOps Pipeline or a GitHub Action) access the Azure cloud resources onto which you’d like to deploy your code.

But just how many of them do you need per project / application / workload?


It depends a lot upon how your team likes to organize and name things. (Remember, it’s generally considered better for a software development team to stick to a single standard than for that standard to be “perfect.”)

Creating more than 1 app registration might help you leverage the concept of privilege separation to reduce accidents and incidents by following the principal of least privilege.

That said, it’s not the only way to separate privileges. Also influential are:

  • The separation (or lack thereof) of repositories and deployment automations in your Git repository host (such as Azure DevOps Pipelines, GitHub, etc.).
  • Various security-oriented settings in your Git repository host.
  • The Tenant / Subscription / Resource Group patterns into which your company clumps Azure resources.
  • Choosing the least-privileged Azure RBAC role that can accomplish a necessary task.
    • (e.g. “Website Contributor” instead of “Contributor.”)

Example architecture

  1. Your team of software developers works within the Payroll subdepartment of the Human Resources (“HR”) department at your company.
  2. You’re rolling out a big project known as the “Hello World” project.
  3. Your infrastructure isn’t the type where you can have 100% of your nonproduction runtime environments be ephemeral, so you first deploy most of your code into a lowest “dev” nonproduction environment, then deploy it again into a higher “stg” environment, and finally deploy it into a production “prd” environment.
  4. Each environment contains the following Azure resources:
    • An Azure Key Vault
    • An Azure Storage Blob
    • An Azure Data Factory with a System-Assigned Managed Identity (“SAMI”) enabled.
      • Its dev version automatically backs itself up into a Git-tracked code repository called hr-payroll-hw-adf.
    • An Azure Function App nicknamed “bonjour” with a SAMI enabled.
      • Git repo name hr-payroll-hw-func-bonjour.
    • An Azure Function App nicknamed “hola.”
      • Git repo name hr-payroll-hw-func-hola
    • An Azure App Service nicknamed “gutentag.”
      • Git repo name hr-payroll-hw-api-gutentag.
    • An Azure Static Web App nicknamed “ciao.”
      • Git repo name hr-payroll-hw-ui-ciao
    • An Azure RBAC role assignment with:
      • a principal of the “bonjour” function app’s SAMI,
      • a role of “Key Vault Reader,” and
      • a scope of the Key Vault resource ID,
      • because the Key Vault contains connection details to a 3rd-party application that the “bonjour” function needs to be able to query during runtime.
    • An Azure RBAC role assignment with
      • a principal of the data factory’s SAMI,
      • a role of “Key Vault Reader,” and
      • a scope of the Key Vault resource ID,
      • because the Key Vault contains connection details to a 3rd-party application that data factory needs to be able to query during runtime.
    • An Azure RBAC role assignment with
      • a principal of the data factory’s SAMI,
      • a role of “Storage Blob Data Contributor,” and
      • a scope of the Storage Blob resource ID,
      • because the data factory needs to be able to write files into the storage blob during runtime.

Note the use of system-assigned managed identity, not app registrations, for inter-Azure-resource permissions during runtime.

SAMI is always preferable to user-assigned managed identity or app registrations when it is available.

(It simply happens to not be available in Azure DevOps Pipelines or GitHub Actions at the time this article was written.)


Quantity considerations

Recap:

We’ve got 5 Git repositories (“repos”), each with their own deployment automation “CI/CD pipeline.”

So that’s 5 pipelines.

Each pipeline involves 3 “stages” of deployment (except ADF which only deploys to higher environments, so 2 for that one).

That makes for a total of 14 mini-projects/apps/workloads within the larger “Hello World” application universe.

  • Q: Does that mean we need to create 14 Entra App Registrations?
  • A: Not necessarily.

14 app registrations

Off the top of my head, when using Azure DevOps Pipelines, I’m not sure I can think of a great reason to have 14 different Entra identities to run your 5 pipelines as.

Maybe it could help you do some typo-accident dummy-checking if you can see the word dev, stg, or prd while writing each stage of each pipeline codebase.

I’m not convinced it would help with malicious tampering, though, since ultimately each pipeline will authenticate to Azure using all (2-)3 of its environment-scoped Entra identities.

If someone can edit the repo, they can just backspace out stg and type prd in part of the pipeline definition if they want to make trouble, right?

Feel free to debate this in the comments! I might be missing something important.

With GitHub Actions, I better see the motivation to have 14 different App Registrations. GitHub Actions automatically reaches out to a different “federated credential” at every stage of deployment if you use its “environments” feature as a restriction.

This means that if you’re already protecting your GitHub Actions stages with “environment” restrictions, you’re going to need to create 14 “federated credentials” in Entra anyway just to get things working.

I suppose you might as well consider attaching 1 federated identity apiece to 14 different Entra app registrations and enjoy a bit of accident risk reduction.

14 app registrations might be named something like this:

  1. hr-payroll-hello-world-dev-function-app-bonjour-cicd
    • Serves as principal when having 1 “Website Contributor” Azure RBAC role assignment created, with a scope of the dev bonjour function resource ID.
    • Has a federated identity credential for the hr-payroll-hw-func-bonjour repo.
      • (Perhaps, specifically, its dev flavor, if using GitHub Actions and your CI/CD pipeline stages use GitHub “environments.”)
  2. hr-payroll-hello-world-dev-function-app-hola-cicd
    • Serves as principal when having 1 “Website Contributor” Azure RBAC role assignment created, with a scope of the dev hola function resource ID.
    • Has a federated identity credential for the hr-payroll-hw-func-hola repo.
      • (Perhaps, specifically, its dev flavor, if using GitHub Actions and your CI/CD pipeline stages use GitHub “environments.”)
  3. hr-payroll-hello-world-dev-app-service-cicd
    • Serves as principal when having 1 “Website Contributor” Azure RBAC role assignment created, with a scope of the dev gutentag app service resource ID.
    • Has a federated identity credential for the hr-payroll-hw-api-gutentag repo.
      • (Perhaps, specifically, its dev flavor, if using GitHub Actions and your CI/CD pipeline stages use GitHub “environments.”)
  4. hr-payroll-hello-world-dev-ui-cicd
    • Serves as principal when having 1 “Website Contributor” Azure RBAC role assignment created, with a scope of the dev ciao static web app resource ID.
    • Has a federated identity credential for the hr-payroll-hw-ui-ciao repo.
      • (Perhaps, specifically, its dev flavor, if using GitHub Actions and your CI/CD pipeline stages use GitHub “environments.”)
  5. hr-payroll-hello-world-stg-data-factory-cicd
    • Serves as principal when having 1 “Data Factory Contributor” Azure RBAC role assignment created, with a scope of the stg data factory resource ID.
    • Has a federated identity credential for the hr-payroll-hw-adf repo.
      • (Perhaps, specifically, its stg flavor, if using GitHub Actions and your CI/CD pipeline stages use GitHub “environments.”)
  6. hr-payroll-hello-world-stg-function-app-bonjour-cicd
    • Serves as principal when having 1 “Website Contributor” Azure RBAC role assignment created, with a scope of the stg bonjour function resource ID.
    • Has a federated identity credential for the hr-payroll-hw-func-bonjour repo.
      • (Perhaps, specifically, its stg flavor, if using GitHub Actions and your CI/CD pipeline stages use GitHub “environments.”)
  7. hr-payroll-hello-world-stg-function-app-hola-cicd
    • Serves as principal when having 1 “Website Contributor” Azure RBAC role assignment created, with a scope of the stg hola function resource ID.
    • Has a federated identity credential for the hr-payroll-hw-func-hola repo.
      • (Perhaps, specifically, its stg flavor, if using GitHub Actions and your CI/CD pipeline stages use GitHub “environments.”)
  8. hr-payroll-hello-world-stg-app-service-cicd
    • Serves as principal when having 1 “Website Contributor” Azure RBAC role assignment created, with a scope of the stg gutentag app service resource ID.
    • Has a federated identity credential for the hr-payroll-hw-api-gutentag repo.
      • (Perhaps, specifically, its stg flavor, if using GitHub Actions and your CI/CD pipeline stages use GitHub “environments.”)
  9. hr-payroll-hello-world-stg-ui-cicd
    • Serves as principal when having 1 “Website Contributor” Azure RBAC role assignment created, with a scope of the stg ciao static web app resource ID.
    • Has a federated identity credential for the hr-payroll-hw-ui-ciao repo.
      • (Perhaps, specifically, its stg flavor, if using GitHub Actions and your CI/CD pipeline stages use GitHub “environments.”)
  10. hr-payroll-hello-world-prd-data-factory-cicd
    • Serves as principal when having 1 “Data Factory Contributor” Azure RBAC role assignment created, with a scope of the prd data factory resource ID.
    • Has a federated identity credential for the hr-payroll-hw-adf repo.
      • (Perhaps, specifically, its prd flavor, if using GitHub Actions and your CI/CD pipeline stages use GitHub “environments.”)
  11. hr-payroll-hello-world-prd-function-app-bonjour-cicd
    • Serves as principal when having 1 “Website Contributor” Azure RBAC role assignment created, with a scope of the prd bonjour function resource ID.
    • Has a federated identity credential for the hr-payroll-hw-func-bonjour repo.
      • (Perhaps, specifically, its prd flavor, if using GitHub Actions and your CI/CD pipeline stages use GitHub “environments.”)
  12. hr-payroll-hello-world-prd-function-app-hola-cicd
    • Serves as principal when having 1 “Website Contributor” Azure RBAC role assignment created, with a scope of the prd hola function resource ID.
    • Has a federated identity credential for the hr-payroll-hw-func-hola repo.
      • (Perhaps, specifically, its prd flavor, if using GitHub Actions and your CI/CD pipeline stages use GitHub “environments.”)
  13. hr-payroll-hello-world-prd-app-service-cicd
    • Serves as principal when having 1 “Website Contributor” Azure RBAC role assignment created, with a scope of the prd gutentag app service resource ID.
    • Has a federated identity credential for the hr-payroll-hw-ui-ciao repo.
      • (Perhaps, specifically, its prd flavor, if using GitHub Actions and your CI/CD pipeline stages use GitHub “environments.”)
  14. hr-payroll-hello-world-prd-ui-cicd
    • Serves as principal when having 1 “Website Contributor” Azure RBAC role assignment created, with a scope of the prd ciao static web app resource ID.
    • Has a federated identity credential for the hr-payroll-hw-ui-ciao repo.
      • (Perhaps, specifically, its prd flavor, if using GitHub Actions and your CI/CD pipeline stages use GitHub “environments.”)

5 app registrations

If you have different teams working on each of the 5 repos, I can totally see creating 5 App Registrations:

  1. hr-payroll-hello-world-data-factory-cicd
    • Serves as principal when having 2 “Data Factory Contributor” Azure RBAC role assignments created, each with a scope to one of the 2 higher-level data factory resource IDs (stg, prd).
    • Has a federated identity credential for the hr-payroll-hw-adf repo.
      • (Or perhaps 2, if using GitHub Actions and your CI/CD pipeline stages use GitHub “environments.”)
  2. hr-payroll-hello-world-function-app-bonjour-cicd
    • Serves as principal when having 3 “Website Contributor” Azure RBAC role assignments created, each with a scope to one of the 3 bonjour function resource IDs (dev, stg, prd).
    • Has a federated identity credential for the hr-payroll-hw-func-bonjour repo.
      • (Or perhaps 3, if using GitHub Actions and your CI/CD pipeline stages use GitHub “environments.”)
  3. hr-payroll-hello-world-function-app-hola-cicd
    • Serves as principal when having 3 “Website Contributor” Azure RBAC role assignments created, each with a scope to one of the 3 hola function resource IDs (dev, stg, prd).
    • Has a federated identity credential for the hr-payroll-hw-func-hola repo.
      • (Or perhaps 3, if using GitHub Actions and your CI/CD pipeline stages use GitHub “environments.”)
  4. hr-payroll-hello-world-app-service-cicd
    • Serves as principal when having 3 “Website Contributor” Azure RBAC role assignments created, each with a scope to one of the 3 gutentag app service resource IDs (dev, stg, prd).
    • Has a federated identity credential for the hr-payroll-hw-api-gutentag repo.
      • (Or perhaps 3, if using GitHub Actions and your CI/CD pipeline stages use GitHub “environments.”)
  5. hr-payroll-hello-world-ui-cicd
    • Serves as principal when having 3 “Website Contributor” Azure RBAC role assignments created, each with a scope to one of the 3 ciao static web app resource IDs (dev, stg, prd).
    • Has a federated identity credential for the hr-payroll-hw-ui-ciao repo.
      • (Or perhaps 3, if using GitHub Actions and your CI/CD pipeline stages use GitHub “environments.”)

That way, a malicious (or careless) front-end developer can’t overwrite a function’s codebase by adding some function code to the hr-payroll-hw-ui-ciao and edit its deployment automation CI/CD pipeline to deploy their new code onto one of the “hola” Azure Function App resources.

2 app registrations

Similarly, maybe you’re not worried about accidents or malice between the 4 web apps, and have the same developers working on them all, anyway, and you don’t expect that to ever change. In that case, perhaps you’d want something more like:

  1. hr-payroll-hello-world-data-factory-cicd
    • Serves as principal when having 2 “Data Factory Contributor” Azure RBAC role assignments created, each with a scope to one of the 2 higher-level data factory resource IDs (stg, prd).
    • Has a federated identity credential for the hr-payroll-hw-adf repo.
      • (Or perhaps 2, if using GitHub Actions and your CI/CD pipeline stages use GitHub “environments.”)
  2. hr-payroll-hello-world-web-cicd
    • Serves as principal when having 12 “Website Contributor” Azure RBAC role assignments created, each with a scope to one of the 12 web-related resource IDs (3 environments x 4 web-related resources).
      • (Alternatively, if those 12 resources live within Azure “resource groups” that don’t contain any other Azure resources that a “Website Contributor” role could produce accidents or tampering against, you could scope to those resource groups and create fewer total role assignments.)
    • Has a federated identity credential for the hr-payroll-hw-func-bonjour repo.
      • (Or perhaps 3, if using GitHub Actions and your CI/CD pipeline stages use GitHub “environments.”)
    • Has a federated identity credential for the hr-payroll-hw-func-hola repo.
      • (Or perhaps 3, if using GitHub Actions and your CI/CD pipeline stages use GitHub “environments.”)
    • Has a federated identity credential for the hr-payroll-hw-api-gutentag repo.
      • (Or perhaps 3, if using GitHub Actions and your CI/CD pipeline stages use GitHub “environments.”)
    • Has a federated identity credential for the hr-payroll-hw-ui-ciao repo.
      • (Or perhaps 3, if using GitHub Actions and your CI/CD pipeline stages use GitHub “environments.”)
    • Alternatively, if all 4 of your web-related repos are in the same Azure DevOps Project, you could get away with just 1 federated identity credential for a single web-related ADO Service Connection to this 1 web-related Entra app registration.

If you’re using GitHub Actions with “environments” and want a wee bit of help reducing opportunities for accidents, but the “14 app registrations” option seems like overkill, perhaps instead of 2 app registrations (-data-factory-cicd and -web-cicd), you have 5 (dev-web-cicd, stg-data-factory-cicd, stg-web-cicd, prd-data-factory-cicd, and prd-web-cicd).

1 app registration

You could just make 1 app registration called:

  1. hr-payroll-hello-world-cicd
    • Serves as principal when having 2 “Data Factory Contributor” Azure RBAC role assignments created, each with a scope to one of the 2 higher-level data factory resource IDs (stg, prd).
    • Serves as principal when having 12 “Website Contributor” Azure RBAC role assignments created, each with a scope to one of the 12 web-related resource IDs (3 environments x 4 web-related resources).
      • (Alternatively, if those 12 resources live within Azure “resource groups” that don’t contain any other Azure resources that a “Website Contributor” role could produce accidents or tampering against, you could scope to those resource groups and create fewer total role assignments.)
    • Has a federated identity credential for the hr-payroll-hw-adf repo.
      • (Or perhaps 2, if using GitHub Actions and your CI/CD pipeline stages use GitHub “environments.”)
    • Has a federated identity credential for the hr-payroll-hw-func-bonjour repo.
      • (Or perhaps 3, if using GitHub Actions and your CI/CD pipeline stages use GitHub “environments.”)
    • Has a federated identity credential for the hr-payroll-hw-func-hola repo.
      • (Or perhaps 3, if using GitHub Actions and your CI/CD pipeline stages use GitHub “environments.”)
    • Has a federated identity credential for the hr-payroll-hw-api-gutentag repo.
      • (Or perhaps 3, if using GitHub Actions and your CI/CD pipeline stages use GitHub “environments.”)
    • Has a federated identity credential for the hr-payroll-hw-ui-ciao repo.
      • (Or perhaps 3, if using GitHub Actions and your CI/CD pipeline stages use GitHub “environments.”)
    • Alternatively, if all 5 of your repos are in the same Azure DevOps Project, you could get away with just 1 federated identity credential for a single ADO Service Connection to this 1 Entra app registration.

If you’re using GitHub Actions with “environments” and want a wee bit of help reducing opportunities for accidents, perhaps instead of 1 app registration (-cicd), you have 5 (-dev-cicd, -stg-cicd, and -prd-cicd).

Of course, this would let a malicious web developer (or intruder!) write a deployment automation CI/CD pipeline that mucks about with the Data Factory’s definition. Who knows – maybe they’ll…

  • Rewrite the Data Factory to email themselves a report of all colleagues’ social security numbers.
  • Accidentally break the Data Factory’s configuration and ruin years worth of data integrity.

Lessons learned

It’s up to your team to develop standards that work for you.

I hope this article has helped you better think through the security and ease-of-maintenance implications of your many options as you face one of the “two hardest problems in computer science:” naming things.


Further reading

--- ---