Avoid use of Service Principals in Azure

  • Stan
  • March 6, 2023

Introduction

One of the main reasons companies use cloud, is to leverage identity-and-access (IAM) services 👤, such as Azure Active Directory (AAD). Most mature organizations have gone through the steps of defense-in-depth and taken additional measures, such as conditional access policies, configuration of risky sign-ins, and perhaps even introduced Privileged Access Management (PIM). All online identities need to be secured adequately. The common saying “security is as strong as the weakest link 🔗” applies even more in the cloud. However, most modern organizations still make use of Service Principal (SP) for their applications.

What is a Service Principal?

Long story short, a SP is a type of security principal, which provides an identity for an application. Rights can be assigned to this identity, just like normal AAD identities. Most common assignments are things like database or Key Vault access. Most of the time, the application needs access to the most valuable and critical asset in your organization: your business data. 🪙 Microsoft Documentation about Service Principals

So that is the big deal? 🤷‍♂️

A SP is signed into using the application ID (read: username), and a secret (read: password). This is a stark contrast to the introduction of this post, you are signing into your most valuable assets, using just a username and a password. In addition, sign-in behavior of the service principal is often overlooked, allowing attackers to use the key at any time they like once it is compromised. Due to the nature of the SP, a new application using the identity can be overlooked or dismissed as “benign activities”. While it’s possible to harden SP to a certain extent, most organizations don’t do this and there are often better alternatives out there. Let’s talk about that next.

Alternative: Managed Identities 💡

Often, it is possible to use Managed Identities instead of Service Principals. A Managed Identity can be assigned to a single application (usually system-assigned) or to multiple applications (user-assigned). You can assign rights, such as Key Vault access to this identity. So how is this different from the SP? The key difference is the way the identity is accessed. The Managed Identity can only be accessed from within the application. An internal endpoint is exposed on the application server (such as the Virtual Machine, or App Service). Only using this internal endpoint, authentication tokens are given to the application. This means that if an attacker wants to use the Managed Identity, they need access to the application server first before signing in. There is no key, so you don’t have to worry about key management or rotation policies.

A practical scenario: Code

You can use the Azure Identity library in many programming languages 💻 to manage the authentication for you. Simply import the dependencies and use the built-in classes to sign into your Azure Active Directory. After uploading the code to your chosen environment, the app will automatically authenticate itself using the configured identity. Here is an example using Java. In this example, the application has access to Key Vault secrets and displays the secret with the name “DummySecret”.

/**
 * The default credential first checks environment variables for configuration.
 * If environment configuration is incomplete, it will try managed identity.
 */
public void createDefaultAzureCredential() {
    DefaultAzureCredential defaultCredential = new DefaultAzureCredentialBuilder().build();

    // Azure SDK client builders accept the credential as a parameter
    SecretClient secretClient = new SecretClientBuilder()
        .vaultUrl("https://{YOUR_VAULT_NAME}.vault.azure.net")
        .credential(defaultCredential)
        .buildClient();
    KeyVaultSecret secret = secretClient.setSecret("DummySecret", "DummyValue");

    System.out.println(String.format("Successfully created the secret with name %s and value %s",
        secret.getName(), secret.getValue()));
}

Source: https://github.com/Azure/azure-sdk-for-java/wiki/Azure-Identity-Examples

Another practical scenario: Infrastructure Key Vault access

In this scenario, we want to deploy a program that doesn’t have the Azure Authentication library implemented or available. We would still like to secure the secrets 🔑 and make them available using environment variables. In this case it’s possible to use Key Vault references. Instead of adding the secrets directly into the application, you add them to a Key Vault, after adding the secrets there you reference the location to the application. The application uses a Managed Identity to authenticate itself to the secrets and makes them available to application. In this scenario it is very easy to revoke access or grant access to applications on demand.

alter-text
An example of Key Vault references, that can be accessed using environment variables.

For more information about this implementation, please read this article from Microsoft: https://learn.microsoft.com/en-us/azure/app-service/app-service-key-vault-references

How developers should test their applications

Often, this approach to security is met with resistance from the development team, they will ask you how they can test their applications if you make it impossible for “human” identities to access any secrets, even in lower environments. However, the exact opposite is the truth in this case. Using the DefaultAzureCredentialBuilder, your application can automatically detect in which environment it is running. It does this by trying each possibility one by one, as outlined in the image below.

alter-text
Sign in order of DefaultAzureCredentialBuilder, source: devblogs.microsoft.com

Your developers can use any of the orange blocks to mimic the application identity. The main benefit of this is that developers never have to exchange application secrets, and instead use their own Azure AD account. If a developer is offboarded or breached, their account can simply be deactivated, which is sufficient to revoke all access to the applications and data. Please note that the developers have to be granted access to the Key Vault their Azure AD accounts for this to work. In the screenshot below is an example of this implementation.

alter-text
An example of RBAC using identities and developers for the same test Key Vault

Conclusion

Service Principals can be dangerous to use, if the key is compromised, an attacker may gain access to all your data. Luckily we have a better and more secure alternative to them. Managed Identities can be implemented into nearly any application that needs to access cloud services in your environment. They can be implemented in your own code, or using third party applications, that consume secrets using environment variables. Please give this a shot in your Azure environment.

Sources List:

Related Posts

Create a scalable private deployment pool

  • Stan
  • March 12, 2023

Introduction Sometimes you may find yourself in a scenario where you need a private deployment pool. For whatever reason, the Microsoft Hosted agent, cannot work for your organization.

Read more

First Post!

  • Stan
  • January 24, 2021

Welcome to this blog This blog is here to log my findings that I have with public cloud. I will be making posts along with my work that I find interesting to report about.

Read more