Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for authenticating using Service Principal with a Client Certificate #2471

Merged
merged 12 commits into from
Dec 11, 2018
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 23 additions & 36 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,9 @@ Using the provider
```
# Configure the Microsoft Azure Provider
provider "azurerm" {
# NOTE: Environment Variables can also be used for Service Principal authentication
# Terraform also supports authenticating via the Azure CLI too.
# see here for more info: http://terraform.io/docs/providers/azurerm/index.html
# more information on the authentication methods supported by
tombuildsstuff marked this conversation as resolved.
Show resolved Hide resolved
# the AzureRM Provider can be found here:
# http://terraform.io/docs/providers/azurerm/index.html

# subscription_id = "..."
# client_id = "..."
Expand All @@ -54,32 +54,17 @@ provider "azurerm" {
}

# Create a resource group
resource "azurerm_resource_group" "main" {
resource "azurerm_resource_group" "test" {
tombuildsstuff marked this conversation as resolved.
Show resolved Hide resolved
name = "production-resources"
location = "West US"
}

# Create a virtual network in the production-resources resource group
resource "azurerm_virtual_network" "network" {
resource "azurerm_virtual_network" "test" {
name = "production-network"
resource_group_name = "${azurerm_resource_group.main.name}"
location = "${azurerm_resource_group.main.location}"
resource_group_name = "${azurerm_resource_group.test.name}"
location = "${azurerm_resource_group.test.location}"
address_space = ["10.0.0.0/16"]

subnet {
name = "subnet1"
address_prefix = "10.0.1.0/24"
}

subnet {
name = "subnet2"
address_prefix = "10.0.2.0/24"
}

subnet {
name = "subnet3"
address_prefix = "10.0.3.0/24"
}
}
```

Expand All @@ -88,7 +73,7 @@ Further [usage documentation is available on the Terraform website](https://www.
Developing the Provider
---------------------------

If you wish to work on the provider, you'll first need [Go](http://www.golang.org) installed on your machine (version 1.9+ is *required*). You'll also need to correctly setup a [GOPATH](http://golang.org/doc/code.html#GOPATH), as well as adding `$GOPATH/bin` to your `$PATH`.
If you wish to work on the provider, you'll first need [Go](http://www.golang.org) installed on your machine (version 1.11+ is *required*). You'll also need to correctly setup a [GOPATH](http://golang.org/doc/code.html#GOPATH), as well as adding `$GOPATH/bin` to your `$PATH`.

To compile the provider, run `make build`. This will build the provider and put the provider binary in the `$GOPATH/bin` directory.

Expand All @@ -99,24 +84,26 @@ $ $GOPATH/bin/terraform-provider-azurerm
...
```

In order to test the provider, you can simply run `make test`.
In order to run the unit tests for the provider, you can run:

```sh
$ make test
```

In order to run the full suite of Acceptance tests, run `make testacc`.
Most of the tests in the provider are Acceptance Tests - which provisions real resources in Azure. It's possible to run the entire acceptance test suite by running `make testacc` - however it's likely you'll want to run a subset, which you can do using a prefix, by running:
tombuildsstuff marked this conversation as resolved.
Show resolved Hide resolved

```
make testacc TESTARGS='-run=TestAccAzureRMResourceGroup'
```

The following ENV variables must be set in your shell prior to running acceptance tests:
- ARM_CLIENT_ID
- ARM_CLIENT_SECRET
- ARM_SUBSCRIPTION_ID
- ARM_TENANT_ID
- ARM_TEST_LOCATION
- ARM_TEST_LOCATION_ALT
The following Environment Variables must be set in your shell prior to running acceptance tests:

*Note:* Acceptance tests create real resources, and often cost money to run.
- `ARM_CLIENT_ID`
- `ARM_CLIENT_SECRET`
- `ARM_SUBSCRIPTION_ID`
- `ARM_TENANT_ID`
- `ARM_ENVIRONMENT`
- `ARM_TEST_LOCATION`
- `ARM_TEST_LOCATION_ALT`

```sh
$ make testacc
```
**Note:** Acceptance tests create real resources in Azure which often cost money to run.
56 changes: 38 additions & 18 deletions azurerm/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,6 @@ func Provider() terraform.ResourceProvider {
DefaultFunc: schema.EnvDefaultFunc("ARM_CLIENT_ID", ""),
},

"client_secret": {
Type: schema.TypeString,
Optional: true,
DefaultFunc: schema.EnvDefaultFunc("ARM_CLIENT_SECRET", ""),
},

"tenant_id": {
Type: schema.TypeString,
Optional: true,
Expand All @@ -48,17 +42,27 @@ func Provider() terraform.ResourceProvider {
DefaultFunc: schema.EnvDefaultFunc("ARM_ENVIRONMENT", "public"),
},

"skip_credentials_validation": {
Type: schema.TypeBool,
// Client Certificate specific fields
"client_certificate_password": {
Type: schema.TypeString,
Optional: true,
DefaultFunc: schema.EnvDefaultFunc("ARM_SKIP_CREDENTIALS_VALIDATION", false),
DefaultFunc: schema.EnvDefaultFunc("ARM_CLIENT_CERTIFICATE_PASSWORD", ""),
},

"skip_provider_registration": {
Type: schema.TypeBool,
"client_certificate_path": {
Type: schema.TypeString,
Optional: true,
DefaultFunc: schema.EnvDefaultFunc("ARM_SKIP_PROVIDER_REGISTRATION", false),
DefaultFunc: schema.EnvDefaultFunc("ARM_CLIENT_CERTIFICATE_PATH", ""),
},

// Client Secret specific fields
"client_secret": {
Type: schema.TypeString,
Optional: true,
DefaultFunc: schema.EnvDefaultFunc("ARM_CLIENT_SECRET", ""),
},

// Managed Service Identity specific fields
"use_msi": {
Type: schema.TypeBool,
Optional: true,
Expand All @@ -69,6 +73,19 @@ func Provider() terraform.ResourceProvider {
Optional: true,
DefaultFunc: schema.EnvDefaultFunc("ARM_MSI_ENDPOINT", ""),
},

// Advanced feature flags
"skip_credentials_validation": {
Type: schema.TypeBool,
Optional: true,
DefaultFunc: schema.EnvDefaultFunc("ARM_SKIP_CREDENTIALS_VALIDATION", false),
},

"skip_provider_registration": {
Type: schema.TypeBool,
Optional: true,
DefaultFunc: schema.EnvDefaultFunc("ARM_SKIP_PROVIDER_REGISTRATION", false),
},
},

DataSourcesMap: map[string]*schema.Resource{
Expand Down Expand Up @@ -315,14 +332,17 @@ func Provider() terraform.ResourceProvider {
func providerConfigure(p *schema.Provider) schema.ConfigureFunc {
return func(d *schema.ResourceData) (interface{}, error) {
builder := &authentication.Builder{
SubscriptionID: d.Get("subscription_id").(string),
ClientID: d.Get("client_id").(string),
ClientSecret: d.Get("client_secret").(string),
TenantID: d.Get("tenant_id").(string),
Environment: d.Get("environment").(string),
MsiEndpoint: d.Get("msi_endpoint").(string),
SubscriptionID: d.Get("subscription_id").(string),
ClientID: d.Get("client_id").(string),
ClientSecret: d.Get("client_secret").(string),
TenantID: d.Get("tenant_id").(string),
Environment: d.Get("environment").(string),
MsiEndpoint: d.Get("msi_endpoint").(string),
ClientCertPassword: d.Get("client_certificate_password").(string),
ClientCertPath: d.Get("client_certificate_path").(string),

// Feature Toggles
SupportsClientCertAuth: true,
SupportsClientSecretAuth: true,
SupportsManagedServiceIdentity: d.Get("use_msi").(bool),
SupportsAzureCliToken: true,
Expand Down
20 changes: 14 additions & 6 deletions website/azurerm.erb
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,25 @@

<li<%= sidebar_current("docs-azurerm-index") %>>
<a href="/docs/providers/azurerm/index.html">Azure Provider</a>
</li>

<li<%= sidebar_current("docs-azurerm-authentication") %>>
<a href="#">Authentication</a>
<ul class="nav nav-visible">
<li<%= sidebar_current("docs-azurerm-index-authentication-azure-cli") %>>
<a href="/docs/providers/azurerm/authenticating_via_azure_cli.html">Authenticating via the Azure CLI</a>
<li<%= sidebar_current("docs-azurerm-authentication-azure-cli") %>>
<a href="/docs/providers/azurerm/auth/azure_cli.html">Authenticating via the Azure CLI</a>
</li>

<li<%= sidebar_current("docs-azurerm-authentication-managed-service-identity") %>>
<a href="/docs/providers/azurerm/auth/managed_service_identity.html">Authenticating via Managed Service Identity</a>
</li>

<li<%= sidebar_current("docs-azurerm-index-authentication-service-principal") %>>
<a href="/docs/providers/azurerm/authenticating_via_service_principal.html">Authenticating via a Service Principal (Shared Account)</a>
<li<%= sidebar_current("docs-azurerm-authentication-service-principal-client-certificate") %>>
<a href="/docs/providers/azurerm/auth/service_principal_client_certificate.html">Authenticating via a Service Principal with a Client Certificate</a>
</li>

<li<%= sidebar_current("docs-azurerm-index-authentication-msi") %>>
<a href="/docs/providers/azurerm/authenticating_via_msi.html">Authenticating via Managed Service Identity</a>
<li<%= sidebar_current("docs-azurerm-authentication-service-principal-client-secret") %>>
<a href="/docs/providers/azurerm/auth/service_principal_client_secret.html">Authenticating via a Service Principal with a Client Secret</a>
</li>
</ul>
</li>
Expand Down
130 changes: 130 additions & 0 deletions website/docs/auth/azure_cli.html.markdown
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
---
layout: "azurerm"
page_title: "Azure Provider: Authenticating via the Azure CLI"
sidebar_current: "docs-azurerm-authentication-azure-cli"
description: |-
This guide will cover how to use the Azure CLI as authentication for the Azure Provider.

---

# Azure Provider: Authenticating using the Azure CLI

Terraform supports a number of different methods for authenticating to Azure:

* Authenticating to Azure using the Azure CLI (which is covered in this guide)
* [Authenticating to Azure using Managed Service Identity](managed_service_identity.html)
* [Authenticating to Azure using a Service Principal and a Client Certificate](service_principal_client_certificate.html)
* [Authenticating to Azure using a Service Principal and a Client Secret](service_principal_client_secret.html)

---

We recommend using either a Service Principal or Managed Service Identity when running in automation (for example on a CI Server) - and authenticating using the Azure CLI when running Terraform locally.

## Important Notes about Authenticating using the Azure CLI

* Prior to version 1.20 the AzureRM Provider used a different method of authorizing via the Azure CLI where credentials reset after an hour - as such we'd recommend upgrading to version 1.20 or later of the AzureRM Provider.
* Terraform only supports authenticating using the `az` CLI (and this must be available on your PATH) - authenticating using the older `azure` CLI or PowerShell Cmdlets is not supported.
* Authenticating via the Azure CLI is only supported when using a User Account. If you're using a Service Principal (for example via `az login --service-principal`) you should instead authenticate via the Service Principal directly (either using a [Client Secret](service_principal_client_secret.html) or a [Client Certificate](service_principal_client_certificate.html)).

---

## Logging into the Azure CLI

~> **Note**: If you're using the **China**, **German** or **Government** Azure Clouds - you'll need to first configure the Azure CLI to work with that Cloud. You can do this by running:

```shell
$ az cloud set --name AzureChinaCloud|AzureGermanCloud|AzureUSGovernment
```

---

Firstly, login to the Azure CLI using:

```shell
$ az login
```

Once logged in - it's possible to list the Subscriptions associated with the account via:

```shell
$ az account list
```

The output (similar to below) will display one or more Subscriptions - with the `id` field being the `subscription_id` field referenced above.

```json
[
{
"cloudName": "AzureCloud",
"id": "00000000-0000-0000-0000-000000000000",
"isDefault": true,
"name": "PAYG Subscription",
"state": "Enabled",
"tenantId": "00000000-0000-0000-0000-000000000000",
"user": {
"name": "[email protected]",
"type": "user"
}
}
]
```

Should you have more than one Subscription, you can specify the Subscription to use via the following command:

```bash
$ az account set --subscription="SUBSCRIPTION_ID"
```

---

## Configuring Azure CLI authentication in Terraform

Now that we're logged into the Azure CLI - we can configure Terraform to use these credentials.

To configure Terraform to use the Default Subscription defined in the Azure CLI - we can use the following Provider block:

```hcl
provider "azurerm" {
# Whilst version is optional, we /strongly recommend/ using it to pin the version of the Provider being used
version = "=1.20.0"
}
```

More information on [the fields supported in the Provider block can be found here](../index.html#argument-reference).

At this point running either `terraform plan` or `terraform apply` should allow Terraform to run using the Azure CLI to authenticate.

---

It's also possible to configure Terraform to use a specific Subscription - for example:

```hcl
provider "azurerm" {
# Whilst version is optional, we /strongly recommend/ using it to pin the version of the Provider being used
version = "=1.20.0"

subscription_id = "00000000-0000-0000-0000-000000000000"
}
```

More information on [the fields supported in the Provider block can be found here](../index.html#argument-reference).

At this point running either `terraform plan` or `terraform apply` should allow Terraform to run using the Azure CLI to authenticate.

---

If you're looking to use Terraform across Tenants - it's possible to do this by configuring the Tenant ID field in the Provider block, as shown below:

```hcl
provider "azurerm" {
# Whilst version is optional, we /strongly recommend/ using it to pin the version of the Provider being used
version = "=1.20.0"

subscription_id = "00000000-0000-0000-0000-000000000000"
tenant_id = "11111111-1111-1111-1111-111111111111"
}
```

More information on [the fields supported in the Provider block can be found here](../index.html#argument-reference).

At this point running either `terraform plan` or `terraform apply` should allow Terraform to run using the Azure CLI to authenticate.
Loading