Monday, April 23, 2018

Using Azure Service Principal login with Ansible

The problem

When using the Azure REST API from Ansible using the uri module you need to ensure you are authenticated towards Azure. The easiest way to do that is to set a Bearer token based on a Service Principal user on Azure. 

This is the official Azure REST API documentation: https://docs.microsoft.com/en-us/rest/api/azure/

This is how you can create a service principal:

When you have created an Azure service principal you will have 4 necessary pieces of information:

  • Tenant id (the protected resource)
  • Client id (username)
  • Client secret (password)
  • Subscription id (you already had that from your user profile)
Make sure to save those values to an Ansible Vault. In my example I have called them:

  • vault_az_tenant_id
  • vault_az_client_id
  • vault_az_client_secret
  • vault_az_subscription_id

The solution

Create a playbook.yml with the following information:

---
- hosts: localhost
  vars:
    az_tenant_id: "{{ vault_az_tenant_id }}"
    az_client_id: "{{ vault_az_client_id }}"
    az_client_secret: "{{ vault_az_client_secret }}"
    az_subscription_id: "{{ vault_az_subscription_id }}"
    az_token_url: "https://login.microsoftonline.com/{{ az_tenant_id }}/oauth2/token"
    az_token_body: >
        resource=https://management.core.windows.net/
        &client_id={{ az_client_id }}
        &grant_type=client_credentials
        &client_secret={{ az_client_secret }}

  tasks:
    - name: Login to Azure
      uri:
        url: "{{ az_token_url }}"
        method: POST
        body: "{{ az_token_body }}"
        headers:
          Content-Type: "application/x-www-form-urlencoded"
        status_code: 200
      register: login

    - name: Setting Bearer token as fact
      set_fact:
        az_bearer: "{{ login.json.access_token }}"
 

That is how easy it is to authenticate with Azure from the Ansible uri module. Thanks to Vivek to helping out with the az_token_body.

Now every time you us the Ansible uri module in the same playbook, you just need to add the Bearer token to the request header, like this:

- uri:
        url: "{{ whatever-azure-url }}"
        method: POST
        headers:
          Authorization: "Bearer {{ az_bearer }}"

2 comments: