You gotta keep privileges separated
Tags: azure, devops, security, discuss
Published: 2019-04-06 05:51:28

---
title: You gotta keep privileges separated
published: true 
description: Learn what and how to create service principals, a recommended pattern for limiting privileges to only what is required when developing applications or scripts.  
tags: azure, devops, security, discuss
series: "Azure Building Block Fundamentals"
---

Ever have an automated process just suddenly stop working even though you've made no changes to the process? There's nothing like the pure adrenaline of debugging why no one's commits are getting deployed to production for a critical fix and yet everything is reporting "green". Of course, there were little things that could get fixed, but those things were just distractions at that moment. Everyone had an opinion of what was going on and just wanted it fixed now! While I had the most seniority within the operations team, some expressed that it was the lack of my expertise causing the problem. That did give me a clue towards finding the problem. Something HAD changed. The engineer who had set up the CD pipeline had recently left. A little sleuthing, and I realized that he had used his credentials to get the automated deploy to work... so when he left, his credentials got disabled and it just failed silently. 

>**Don't have Azure?** [Grab a free subscription](https://azure.microsoft.com/en-us/free?&WT.mc_id=devto-blog-jedavis). 

When writing scripts for automation or building out a service, don't run under your own credentials. This creates a single point of failure on you for the service. It's also good practice to separate out concerns between environments. [This way even if someone accidentally runs a test command against production, it won't have disastrous results.](https://www.theregister.co.uk/2017/06/05/dev_accidentally_nuked_production_database_was_allegedly_instantly_fired/)

One recommended approach is to use _service principals_. An Azure service principal is an identity for use with applications, services, and tools to access Azure resources. Using service principals allows us to assign specific permissions that are limited in scope to precisely what is required so we can minimize the impact if it's compromised! 

We can assign different [built-in roles](https://docs.microsoft.com/en-us/azure/role-based-access-control/built-in-roles) to a service principal as well as create custom roles if the built-ins aren't sufficient. There isn't a one-to-one relationship with roles and service principals. Service principals can have multiple roles. 

After you've [installed the Azure CLI](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli?WT.mc_id=devto-blog-jedavis&view=azure-cli-latest) or downloaded the [docker image](https://docs.microsoft.com/en-us/cli/azure/run-azure-cli-docker?WT.mc_id=devto-blog-jedavis&view=azure-cli-latest), you can start using the CLI. I'm running these examples in docker. If you've installed directly, you can ignore the docker command. 


```bash
$ docker run -it microsoft/azure-cli
```

We get the [_az_ command](https://docs.microsoft.com/en-us/cli/azure/?WT.mc_id=devto-blog-jedavis&view=azure-cli-latest) which has a lot of different functionality. We're going to focus on managing a service principal for this article. First, we need to login.
 

```bash
bash-4.4# az login
```

If the CLI can reach a web browser, it will open it up and have you login. Otherwise, a URL is provided from the command line to visit along with a code to enter into the sign-on page. 

Depending on your usage of Azure, you may have different subscriptions. Before running commands in the CLI, it's useful to check out your subscriptions using `az account list`. I added `-o table` to get easier for me to read output versus the default JSON output. Here is a modified version of my output showing that I've got 2 accounts, one that is my Pay-As-You-Go account that I upgraded after my Azure Free Account expired, and one that is my work-related subscription. 

```bash
bash-4.4# az account list -o table
Name                      CloudName    SubscriptionId                        State    IsDefault
------------------------  -----------  ------------------------------------  -------  -----------
my-pay-as-you-go          AzureCloud   00000000-0000-0000-0000-100000000000  Enabled  False
Visual Studio Enterprise  AzureCloud   00000000-0000-0000-0000-100000000001  Enabled  True
```

I want to make sure that I use my "Visual Studio Enterprise" for this walk-through so I'm going to set my subscription explicitly. 

```bash
bash-4.4# az account set --subscription="00000000-0000-0000-0000-100000000001"
```

Next, I want to manage the service principal. I can get more information about an Azure CLI command before running it by adding a *-h* flag.

```bash
bash-4.4# az ad sp -h

Group
    az ad sp : Manage Azure Active Directory service principals for automation authentication.

Subgroups:
    credential      : Manage a service principals credentials.
    owner           : Manage service principal owners.

Commands:
    create          : Create a service principal.
    create-for-rbac : Create a service principal and configure its access to Azure resources.
    delete          : Delete a service principal and its role assignments.
    list            : List service principals.
    show            : Get the details of a service principal.
```
Breaking this down into its components I'm using the `az` cli, with the `ad` option for Active Directory and the `sp` suboption for service principal. 

I'm going to use the `create-for-rbac` option with a principal name of SigjeServiceDemoPrincipal and grant the *Reader* role to the principal. If a role isn't specified at creation time, a default role of *Contributor* is assigned to the principal. The *Reader* role lets the principal view all resources but make no changes. The *Contributor* role lets you manage everything except changing access to resources. Role assignments can get pretty complex. 

```bash
bash-4.4# az ad sp create-for-rbac --name SigjeServiceDemoPrincipal --role Reader
Changing "SigjeServiceDemoPrincipal" to a valid URI of "http://SigjeServiceDemoPrincipal", which is the required format used for service principal names
{
  "appId": "00000000-1111-0000-0000-000000000000",
  "displayName": "SigjeServiceDemoPrincipal",
  "name": "http://SigjeServiceDemoPrincipal",
  "password": "My Sekret Password",
  "tenant": "11111111-0000-0000-0000-000000000000"
}
```

Without specifying anything extra, Azure will generate and provide a random password for my new service principal. 

We can take the appId and use it to examine our just created service principal with `az role assignment list --assignee --id "00000000-1111-0000-0000-000000000000"` which will respond with a JSON object that contains information about our service principal. 

```json
[
  {
    "canDelegate": null,
    "id": "/subscriptions/00000000-0000-0000-0000-100000000001/providers/Microsoft.Authorization/roleAssignments/b681786a",
    "name": "b681786a",
    "principalId": "00000000-1111-0000-0000-000000000000",
    "principalName": "http://SigjeServiceDemoPrincipal",
    "roleDefinitionId": "/subscriptions/00000000-0000-0000-0000-100000000001/providers/Microsoft.Authorization/roleDefinitions/acdd72a7",
    "roleDefinitionName": "Reader",
    "scope": "/subscriptions/00000000-0000-0000-0000-100000000001",
    "type": "Microsoft.Authorization/roleAssignments"
  }
]
```

The scope of this role assignment is for the entire subscription `"scope": "/subscriptions/00000000-0000-0000-0000-100000000001"`. Scope is the level that the role assignment applies to. In this case, it's every resource within the subscription. 

![Scope can be within Management group | Subscription | Resource Group | Resource ](https://thepracticaldev.s3.amazonaws.com/i/x95a0y5ltc784wlgaigv.png)

In this diagram, from the top to the bottom we have the most to least access in terms of scope to resources.

Finally, I clean up the service principal because I don't want to just leave this service principal sitting around in my subscription with  `az ad sp delete --id "00000000-1111-0000-0000-000000000000"` which will respond with *Removing role assignments*.

## What Next 

Ideally, I wouldn't set up a service principal for automation to authenticate with a password that I would then embed somewhere. Instead, we can do certificate-based authentication, and even store the certificate in Azure Key Vault. We can also specify the scope of our service principal right at creation time rather than modifying it afterward so we can limit service principals to have access to specific resources. 

Share your misadventures with personal credentials or any questions you have below!

Resources:

* [Grab a free subscription](https://azure.microsoft.com/en-us/free?&WT.mc_id=devto-blog-jedavis)
* [Install the Azure CLI](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli?WT.mc_id=devto-blog-jedavis&view=azure-cli-latest)
* [Run from a Docker container](https://docs.microsoft.com/en-us/cli/azure/run-azure-cli-docker?WT.mc_id=devto-blog-jedavis&view=azure-cli-latest)
* [azure-cli Dockerfile](https://hub.docker.com/r/microsoft/azure-cli/dockerfile)
* [Azure CLI deepdive](https://docs.microsoft.com/en-us/cli/azure/?WT.mc_id=devto-blog-jedavis&view=azure-cli-latest)
* [Create a Service Principal using the CLI](https://docs.microsoft.com/en-us/cli/azure/create-an-azure-service-principal-azure-cli?WT.mc_id=devto-blog-jedavis&view=azure-cli-latest)
* [Built-in Roles for Azure Resources](https://docs.microsoft.com/en-us/azure/role-based-access-control/built-in-roles)