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

Error Waiting for the Azure CLI - Error Parsing JSON Result #343

Closed
v6 opened this issue Oct 27, 2020 · 18 comments · Fixed by #358
Closed

Error Waiting for the Azure CLI - Error Parsing JSON Result #343

v6 opened this issue Oct 27, 2020 · 18 comments · Fixed by #358

Comments

@v6
Copy link

v6 commented Oct 27, 2020

Community Note

  • Please vote on this issue by adding a 👍 reaction to the original issue to help the community and maintainers prioritise this request
  • Please do not leave "+1" or "me too" comments, they generate extra noise for issue followers and do not help prioritise the request
  • If you are interested in working on this issue or have submitted a pull request, please leave a comment

Terraform (and AzureAD Provider) Version

vault-identity1[develop !?]$ terraform -v
Terraform v0.13.5
+ provider registry.terraform.io/hashicorp/azuread v1.0.0
vault-identity[develop !?]$ 

Affected Resource(s)

  • provider "azuread"

Terraform Configuration Files

This can be reproduced with only 2 files:

backends.tf

# Using multiple workspaces:
terraform {
  backend "remote" {
    hostname = "app.terraform.io"
    organization = "my-company"

    workspaces {
      prefix = "vault-identity-"
    }
  }
}

providers.tf

# Configure the Azure AD Provider
provider "azuread" {
  version = "~> 1.0.0"

  # NOTE: This relies on authentication via the Azure CLI.
  # see here for more info: https://terraform.io/docs/providers/azuread/

  tenant_id = "4c69d615-9554-4839-8aac-07898be2c4ac"
}

# Retrieve domain information
data "azuread_domains" "maindomain" {
  only_initial = true
}

The error I run into, after successful authentication with az login --tenant $TENANT_ID, is as follows:

vault-identity[develop !?]$ terraform plan azure-ad-oidc
Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.


Error: building AzureAD Client: obtain subscription(a0496e39-63e6-4ab6-a1e1-2cdbc77582d2) from Azure CLI: Error parsing json result from the Azure CLI: Error waiting for the Azure CLI: exit status 1

  on azure-ad-oidc/providers.tf line 2, in provider "azuread":
   2: provider "azuread" {

The above output reflects running this with local execution, but I also got stuck on the same crap when I tried remote execution.

I mean, a parsing error? What is that supposed to mean? Is there any way I could even see what it was even trying to parse?

Please refer to this forum post, too: https://discuss.hashicorp.com/t/error-building-azuread-client-obtain-subscription-error-waiting-for-the-azure-cli/16694

Debug Output

https://gist.github.com/v6/e7a8e88901c2d50968fb3443bff6bb99

Expected Behavior

Terraform should have succeeded, or at least shown the JSON that it supposedly cannot parse.

Actual Behavior

Got some vague or misleading error about JSON.

Steps to Reproduce

Run terraform plan with the provided configuration.

Important Factoids

This seems to rely heavily on the azure CLI.

References

@manicminer
Copy link
Contributor

Hi @v6, thanks for reporting. There are a couple of known issues with Azure CLI authentication and I believe you're hitting one of them. We have fixes in testing at the moment.

In the meantime, you can work around this by using service principal authentication (setting ARM_CLIENT_ID / ARM_CLIENT_SECRET env vars) but we hope to resolve this soon.

@scschneider
Copy link

I had a similar issue. Where we specify ARM_SUBSCRIPTION_ID and ARM_TENANT_ID prior to deployment and get the following error:

Error: building AzureAD Client: obtain subscription({TENANT_ID_HERE} ) from Azure CLI: Error parsing json result from the Azure CLI: Error waiting for the Azure CLI: exit status 1

The error looks like it is trying to obtain a subscription and use the tenant id in place of the subscription id (at least that is what it looks like) and when we remove the ARM_TENANT_ID from environment variables, Terraform proceeds without errors.

@manicminer
Copy link
Contributor

Correct, the provider is passing a subscription ID to the CLI and using the tenant ID as the value. This was to maintain compatibility with the CLI, which overloads the two depending on the scenario. However, at around the time that v1 of the provider was released, the CLI behavior changed.

The workaround in the meantime is to try az login --allow-no-subscriptions --tenant TENANT_ID, which enables subscriptionless tenants to appear in the output of az account and targets the specified tenant (making it, or one of its subscriptions, the default). Failing that, revert to v0.11 and repeat these steps.

A fix for this will land shortly.

@Warns
Copy link

Warns commented Nov 4, 2020

I have the same issue using Github Actions, terraform workflow log shows the following error msg:
Error: building AzureAD Client: obtain subscription() from Azure CLI: Error parsing json result from the Azure CLI: Error waiting for the Azure CLI: exit status 1 on <empty> line 0: (source code not available)

Though terraform plan doesn't bring up this error when running locally, as logged in to Azure CLI

@ausfestivus
Copy link

ausfestivus commented Nov 5, 2020

In the meantime, you can work around this by using service principal authentication (setting ARM_CLIENT_ID / ARM_CLIENT_SECRET env vars) but we hope to resolve this soon.

Any tips for those of us getting our AAD SPs via the Vault Azure Secrets Engine using Dynamic credentials? We cant set those environment variables.
This issue is a hard block for us if it cant be resolved.

@tombuildsstuff
Copy link
Contributor

@ausfestivus you should be able to achieve the same thing by threading the dynamic variables through, for example:

variable "client_id" {}
variable "client_secret" {}

provider "azuread" {
  client_id = var.client_id
  client_secret = var.client_secret
  // ...
}

It's worth noting that we don't support using the Azure CLI with a Service Principal (since it behaves differently in subtle ways when doing so) - as we already provide native support for using a Service Principal (via a Client Certificate or a Client Secret) - so you'd need to define the Service Principal credentials either inline (as shown above) or using Environment Variables.

@ausfestivus
Copy link

Maybe Im confused here. Im pretty sure Im already threading the dynamic SP secret through to the azuread provider from Vault in this way.

I will need to write up a more thorough fault desc with some code snippets here which I will do once i've gotten the days meetings out of the way.

@ausfestivus
Copy link

There is a gist at https://gist.github.com/ausfestivus/d3f8107fc395497e87efb600e8a401c3 of the prototype im working on and the error that TFE displays when it is run.

@manicminer
Copy link
Contributor

@ausfestivus Azure CLI authentication is the fallback when no other auth mechanism is found to be configured. I suspect the values you're passing for client_id and/or client_secret are empty.

@ausfestivus
Copy link

If client_id and client_secret values are empty I would expect an error from terraform saying as much.

@manicminer
Copy link
Contributor

manicminer commented Nov 6, 2020

If client_id and client_secret values are empty I would expect an error from terraform saying as much.

That isn't the case, if they are empty then the authentication method(s) that use those properties are ignored and the next method is attempted. Try this:

terraform {
  required_version = ">= 0.13.5"
  required_providers {
    azuread = {
      source = "hashicorp/azuread"
      #version = "~> 1.0"
      version = "=0.11.0"
    }
  }
}

provider "azuread" {
  client_id     = ""
  client_secret = ""
  tenant_id     = var.azure_tenant_id
}

@ausfestivus
Copy link

Those changes are in and the behaviour im seeing has not changed. New gist https://gist.github.com/ausfestivus/ccc0684121669bc7b8a4efb7403f8752

Had to delete the old one because I leaked something in the revision when I posted the updated code. 🙄

@manicminer
Copy link
Contributor

manicminer commented Nov 9, 2020

@ausfestivus The way in which authentication is performed is not substantially different between azurerm and azuread. As I mentioned earlier, if you have configured a client_id and secret/certificate, it will be used, but if those are unconfigured, the provider will fall back to attempting CLI authentication.

If the values for your provider configuration are not being evaluated and sent to the provider, that is an upstream issue and I would suggest raising that on terraform-core.

@tombuildsstuff
Copy link
Contributor

Also worth noting that both the Azure Backend, AzureAD, AzureRM (and Azure Stack) all share the same auth mechanisms, but will need to be configured in those provider blocks if using inline variables. Based on the example above your specifying inline credentials for the AzureAD but not the Terraform Backend - meaning that whilst the credentials for AzureAD may be being set, the Azure Backend will attempt to use the CLI credentials to authenticate if none are specified

@thpang

This comment has been minimized.

@ghost
Copy link

ghost commented Nov 25, 2020

This has been released in version 1.1.0 of the provider. Please see the Terraform documentation on provider versioning or reach out if you need any assistance upgrading. As an example:

provider "azuread" {
    version = "~> 1.1.0"
}
# ... other configuration ...

@thpang
Copy link

thpang commented Dec 11, 2020

Still finding that with tf 0.13.5 and tf 0.14.x there is still the need for the ARM_ environment variables and that supplying the values for the client_id, client_secret, etc with TF_VAR's is not sufficient. Which is a breaking change from tf 0.13.4

Snippet:

terraform {
  required_version = "~> 0.13"

  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "2.39.0"
    }
    azureread = {
      source  = "hashicorp/azuread"
      version = "1.1.1"
    }
}

provider "azurerm" {

  subscription_id = var.subscription_id
  client_id       = var.client_id
  client_secret   = var.client_secret
  tenant_id       = var.tenant_id
  partner_id      = var.partner_id

  features {}
}

provider "azuread" {
  client_id     = var.client_id
  client_secret = var.client_secret
  tenant_id     = var.tenant_id
}

Where azurerm seems to use these values, azuread still requires the ARM_ env's setup.

What was actually fixed with the 1.1.0 version of azuread?

Looking for a way to only use TF_VARs instead of ARM_ env's

@ghost
Copy link

ghost commented Dec 25, 2020

I'm going to lock this issue because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues.

If you feel this issue should be reopened, we encourage creating a new issue linking back to this one for added context. If you feel I made an error 🤖 🙉 , please reach out to my human friends 👉 [email protected]. Thanks!

@ghost ghost locked as resolved and limited conversation to collaborators Dec 25, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.