terraform-provider-azuread: Error: ODataId was nil when creating an azuread_group resource

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

$ terraform -v
Terraform v1.0.7
on linux_amd64
+ provider registry.terraform.io/hashicorp/azuread v2.2.1
+ provider registry.terraform.io/hashicorp/azurerm v2.77.0
+ provider registry.terraform.io/hashicorp/random v3.1.0

Affected Resource(s)

  • azuread_group

Terraform Configuration Files

provider "azurerm" {
  features {}
}

data "azuread_client_config" "current" {}

resource "azuread_group" "example" {
  display_name     = "example"
  owners               = [data.azuread_client_config.current.object_id]
  security_enabled = true
}

Debug Output

azuread_group.example: Creating...

│ Error: Could not retrieve owner principal object "00000000-0000-0000-0000-000000000000"
│ 
│   with azuread_group.example,
│   on main.tf line 41, in resource "azuread_group" "example":
│   41: resource "azuread_group" "example" {
│ 
│ ODataId was nil

Expected Behavior

The group should have been successfully created

Actual Behavior

An error occurred mentioning ODataId was nil

Steps to Reproduce

export ARM_CLIENT_ID="..."
export ARM_CLIENT_SECRET="..."
export ARM_SUBSCRIPTION_ID="..."
export ARM_TENANT_ID="..."
export ARM_ENVIRONMENT=usgovernment

terraform apply

Important Factoids

We are attempting to create groups in our Azure Active Directory hosted in Azure US Government.

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Reactions: 101
  • Comments: 107 (23 by maintainers)

Commits related to this issue

Most upvoted comments

Thanks to everyone who has posted debug logs. At this time we’re fairly confident of the causes of this issue and a comprehensive workaround will be included in this week’s release. I have now removed the test builds as mentioned. We no longer need further log output to diagnose this issue, thanks!

If you have used a test build and have still seen errors like ODataId was nil or DirectoryObject encountered with nil ODataId, this is likely because the workaround in the test build was not applied to every code path - for example the test build did not fix the azuread_group_member resource, and did not fix the updating of any resource.

If you are seeing the error Invalid URL format specified in payload, this is also due to breaking changes in the API, which the released workaround will address.

One last note: if you are affected by this issue, please do not post +1 or “me too” comments as it distracts from helpful discussion - instead please upvote the issue (👍 reaction on the initial comment) as this does help us to gauge the impact radius of this issue. Many thanks!

As per the above notice, please upgrade to version 2.6.0 of the AzureAD provider which implements a fix for this issue.

At first this issue seemed to affect a small number of tenants but the radius grew over the last few days to affect a large number of tenants. Thank you to all who commented, debugged and otherwise contributed to identifying and resolving this issue, and for all the discussion points - your involvement is greatly appreciated!

For anyone who effectively downgraded their provider to a v1.x release to sidestep this API issue, a gentle reminder to remember the upgrade guide when you update your configurations to work with v2.6.0.

Edit: If Terraform is not yet picking up the new version for you, please allow several minutes as the TF Registry updates

@callppatel @anarsen Good points both of you. I do think, tho, that demanding timeframes for fixes in OSS software that people are using without paying anything at all, is a bit over-the-top.

Also impacted by this in regular non-government Azure. Cannot create azuread_application resources.

│ Error: Could not create application │ │ with module.example_service_principal_2.azuread_application.this, │ on …/…/main.tf line 3, in resource “azuread_application” “this”: │ 3: resource “azuread_application” “this” { │ │ json.Marshal(): json: error calling MarshalJSON for type msgraph.Application: json: error calling MarshalJSON for type *msgraph.Owners: marshaling Owners: encountered DirectoryObject with nil ODataId

@manicminer I just spoke with an Azure Graph API support engineer and learned two things:

  1. There was indeed a recent change made to the @odata.id field to bring the format of it up to odata v4 specifications, which I would imagine is why this just “broke” the azuread Terraform provider

  2. Azure stated that Terraform should NOT use the @odata.id, @odata.type or @odata.context fields because they are considered annotations and not user data. They can change at any time. Azure said that there is an id field which is in the payload of all of the API’s responses which should be used instead of @odata.id. These annotation fields (all fields that start with @ are annotations) should only ever be used by backend Azure systems internal to Microsoft.

Hey!

Looking at the debug output, I’ve noticed the following header in Graph API responses:

Content-Type: application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8

I then tried the following curl request, using the URL that is used by the TF provider in my case:

curl -v \
  -H 'Authorization: Bearer ey...' \
  -H 'Accept: application/json;odata.metadata=full;charset=utf-8' \
  'https://graph.microsoft.com/v1.0/<tenant ID>/directoryObjects/<app ID>'

Notice the odata.metadata=full in Accept header. As a result, I got the response with @odata.id attribute:

{"@odata.context":"https://graph.microsoft.com/v1.0/$metadata#directoryObjects/$entity","@odata.type":"#microsoft.graph.application","@odata.id":"directoryObjects('<app ID>')","@odata.editLink":... }

Perhaps the Microsoft has recently changed the definition of what is "minimial" OData, and this why the ID is no longer returned by default?

With TypeScript library, including the "Accept" header can be achieved like this:

import * as graph from "@microsoft/microsoft-graph-client";

const client: graph.Client = ...;
const directoryObject = await client
  .api("<tenant ID>/directoryObjects/<app ID>")
  .header("Accept", "application/json;odata.metadata=full;charset=utf-8")
  .get();

@manicminer Perhaps a similar approach could be used with Go library for Microsoft Graph? Looking at the ticket you submitted ( microsoftgraph/msgraph-metadata#94 ), it’s been quiet for 9days and I suspect there might as well be “working as intended” -kind of response incoming form MS.

Perhaps meanwhile implement the full metadata fetching by the client, since this is quite a big blocker (can’t really use the provider at all when operating in tenant affected by MS change)? I also think that explicitly specifying full metadata is more futureproof solution in general.

Edit: I notice that there may be no official MSGraph client for Go (?). Looks like “Hamilton” library is used to query MSGraph. I think it boils down to allowing customization for this line: https://github.com/manicminer/hamilton/blob/80ee8faed5254353670568f803f5828e5467a6f4/msgraph/client.go#L143

As of today, I’m also experiencing a similar error with AzureCloud (not government),

but it’s even with azuread_application creation.

I suspect this is the same issue, it looks like a response that doesn’t contain what azuread provider is expecting.

I can create a separate issue, but I suspect this is the same root cause.

Error:

│ Error: Could not create application
│
│   with azuread_application.app_registration,
│   on active-directory.tf line 15, in resource "azuread_application" "app_registration":
│   15: resource "azuread_application" "app_registration" {
│
│ json.Marshal(): json: error calling MarshalJSON for type msgraph.Application: json: error calling MarshalJSON for type
│ *msgraph.Owners: marshaling Owners: encountered DirectoryObject with nil ODataId

Providers:

terraform {
  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "2.77.0"
    }
    azuread = {
      source  = "hashicorp/azuread"
      version = "2.5.0"
    }
  }

Debug output:

========================================= End AzureAD Request: timestamp=2021-10-01T13:00:10.846-0700
2021-10-01T13:00:12.071-0700 [INFO]  provider.terraform-provider-azuread_v2.5.0_x5.exe: 2021/10/01 13:00:12 [DEBUG] Begin AzureAD Response for GET https://graph.microsoft.com/v1.0/[REDACTED]/directoryObjects/[REDACTED]: ==========================================
HTTP/1.1 200 OK
Transfer-Encoding: chunked
Cache-Control: no-cache
Client-Request-Id: [REDACTED]
Content-Type: application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8
Date: Fri, 01 Oct 2021 20:00:11 GMT
Odata-Version: 4.0
Request-Id: [REDACTED]
Strict-Transport-Security: max-age=31536000
Vary: Accept-Encoding
X-Ms-Ags-Diagnostic: {"ServerInfo":{"DataCenter":"West US 2","Slice":"E","Ring":"1","ScaleUnit":"000","RoleInstance":"[REDACTED]"}}
X-Ms-Resource-Unit: 1

1db
{"@odata.context":"https://graph.microsoft.com/v1.0/$metadata#directoryObjects/$entity","@odata.type":"#microsoft.graph.user","id":"[REDACTED]","businessPhones":["[REDACTED]"],"displayName":"Dmytry Emery","givenName":"Dmytry","jobTitle":"[REDACTED]","mail":"[REDACTED]","mobilePhone":null,"officeLocation":[REDACTED]","preferredLanguage":null,"surname":"Emery","userPrincipalName":"[REDACTED]"}
0
========================================== End AzureAD Response: timestamp=2021-10-01T13:00:12.071-0700

I’m facing the same issue

I got the following error:

json.Marshal(): json: error calling MarshalJSON for type msgraph.Application:
json: error calling MarshalJSON for type *msgraph.Owners: marshaling Owners:
encountered DirectoryObject with nil ODataId

Here is the provider versions

terraform {
  required_version = ">=0.14.0"
  required_providers {
    random = {
      source  = "hashicorp/random"
      version = "3.0.0"
    }
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "=2.58.0"
    }
    azuread = {
      source  = "hashicorp/azuread"
      version = "~> 2.4.0"
    }
  }
}

@everyone screaming for a timeframe: Do you require the features in >= 2.0.0 of the provider? If not, just reference 1.6.0 and be happy until the fix is out.

You can’t downgrade once you upgraded and store it terraform state. Terraform doesn’t like downgrade to lower version.

“that demanding timeframes for fixes in OSS software, is a bit over-the-top” I am not sure I can agree with that, OSS software is no different than any proprietary software in terms of support and being agile IMHO. Only difference is that it is supported by community not by a company or a person. And I don’t think, people collaborating on the OSS, actually “demand” anything “timeframe or fix”, they simply “request” with their fellow OSS developers. And success of OSS movement depends on such collaboration.

That’s my 2 cents.

@anarsen Are you suggesting that using the : azuread = { source = “hashicorp/azuread” version = “1.6.0” }

should solve the problem, if I am using the resource for the first time?

@callppatel @anarsen Good points both of you. I do think, tho, that demanding timeframes for fixes in OSS software that people are using without paying anything at all, is a bit over-the-top.

Dead right.

We’re seeing this issue too – Not on Gov Cloud, standard Azure Environment. Occurs when trying to create an azuread_group and also an azuread_service_principal. Ignoring the owner property had no impact (which is expected as noted above, the field being required and defaulting to the logged in user)

If it helps, here is the debug log when performing the operation:

resource "azuread_group" "vpn_users" {
  display_name       = "VPN Users"
  assignable_to_role = true
  security_enabled   = true
}

terraform output - xxxx is my own object ID of my user account (running apply locally)

azuread_group.vpn_users: Creating...
╷
│ Error: Could not retrieve calling principal object "xxxxx"
│ 
│   with azuread_group.vpn_users,
│   on virtual-network.tf line 76, in resource "azuread_group" "vpn_users":
│   76: resource "azuread_group" "vpn_users" {
│ 
│ ODataId was nil

debug – tenant and object IDs replaced with xxxx

2021-10-05T16:08:41.332Z [TRACE] GRPCProvider: ConfigureProvider
2021-10-05T16:08:41.909Z [TRACE] vertex "provider[\"registry.terraform.io/hashicorp/azuread\"]": visit complete
2021-10-05T16:08:41.909Z [TRACE] vertex "azuread_group.vpn_users (expand)": starting visit (*terraform.nodeExpandApplyableResource)
2021-10-05T16:08:41.909Z [TRACE] vertex "azuread_group.vpn_users (expand)": expanding dynamic subgraph
2021-10-05T16:08:41.909Z [TRACE] vertex "azuread_group.vpn_users (expand)": entering dynamic subgraph
2021-10-05T16:08:41.909Z [TRACE] vertex "azuread_group.vpn_users": starting visit (*terraform.NodeApplyableResource)
2021-10-05T16:08:41.909Z [TRACE] vertex "azuread_group.vpn_users": visit complete
2021-10-05T16:08:41.909Z [TRACE] vertex "azuread_group.vpn_users (expand)": dynamic subgraph completed successfully
2021-10-05T16:08:41.909Z [TRACE] vertex "azuread_group.vpn_users (expand)": visit complete
2021-10-05T16:08:41.909Z [TRACE] vertex "azuread_group.vpn_users": starting visit (*terraform.NodeApplyableResourceInstance)
2021-10-05T16:08:41.909Z [TRACE] readDiff: Read Create change from plan for azuread_group.vpn_users
2021-10-05T16:08:41.909Z [TRACE] readResourceInstanceState: reading state for azuread_group.vpn_users
2021-10-05T16:08:41.909Z [TRACE] readResourceInstanceState: no state present for azuread_group.vpn_users
2021-10-05T16:08:41.909Z [TRACE] readDiff: Read Create change from plan for azuread_group.vpn_users
2021-10-05T16:08:41.910Z [TRACE] Re-validating config for "azuread_group.vpn_users"
2021-10-05T16:08:41.910Z [TRACE] GRPCProvider: ValidateResourceConfig
2021-10-05T16:08:41.911Z [TRACE] GRPCProvider: PlanResourceChange
2021-10-05T16:08:41.913Z [WARN]  Provider "registry.terraform.io/hashicorp/azuread" produced an invalid plan for azuread_group.vpn_users, but we are tolerating it because it is using the legacy plugin SDK.
    The following problems may be the cause of any confusing errors from downstream operations:
      - .prevent_duplicate_names: planned value cty.False for a non-computed attribute
2021-10-05T16:08:41.913Z [TRACE] checkPlannedChange: Verifying that actual change (action Create) matches planned change (action Create)
2021-10-05T16:08:41.913Z [TRACE] readResourceInstanceState: reading state for azuread_group.vpn_users
2021-10-05T16:08:41.913Z [TRACE] readResourceInstanceState: no state present for azuread_group.vpn_users
2021-10-05T16:08:41.914Z [INFO]  Starting apply for azuread_group.vpn_users
2021-10-05T16:08:41.914Z [DEBUG] azuread_group.vpn_users: applying the planned Create change
2021-10-05T16:08:41.914Z [TRACE] GRPCProvider: ApplyResourceChange
2021-10-05T16:08:41.915Z [INFO]  provider.terraform-provider-azuread_v2.4.0_x5: 2021/10/05 16:08:41 [DEBUG] setting computed for "members" from ComputedKeys: timestamp=2021-10-05T16:08:41.915Z
2021-10-05T16:08:41.915Z [INFO]  provider.terraform-provider-azuread_v2.4.0_x5: 2021/10/05 16:08:41 [DEBUG] setting computed for "owners" from ComputedKeys: timestamp=2021-10-05T16:08:41.915Z
2021-10-05T16:08:41.915Z [INFO]  provider.terraform-provider-azuread_v2.4.0_x5: 2021/10/05 16:08:41 [DEBUG] setting computed for "proxy_addresses" from ComputedKeys: timestamp=2021-10-05T16:08:41.915Z
2021-10-05T16:08:41.916Z [INFO]  provider.terraform-provider-azuread_v2.4.0_x5: 2021/10/05 16:08:41 [DEBUG] Begin AzureAD Request: ==========================================
GET /v1.0/xxxxx/directoryObjects/yyyy HTTP/1.1
Host: graph.microsoft.com
User-Agent: HashiCorp Terraform/1.0.8 (+https://www.terraform.io) Terraform Plugin SDK/2.7.0 terraform-provider-azuread/2.4.0 Hamilton (Go-http-client/1.1) pid-222c6c49-1b0a-5959-a213-6608f9eb8820
Accept: application/json
Content-Type: application/json; charset=utf-8
Accept-Encoding: gzip


========================================= End AzureAD Request: timestamp=2021-10-05T16:08:41.916Z
2021-10-05T16:08:42.108Z [INFO]  provider.terraform-provider-azuread_v2.4.0_x5: 2021/10/05 16:08:42 [DEBUG] Begin AzureAD Response for GET https://graph.microsoft.com/v1.0/xxxxxx/directoryObjects/xxxxx: ==========================================
HTTP/1.1 200 OK
Transfer-Encoding: chunked
Cache-Control: no-cache
Client-Request-Id: 9241d9b8-f317-4248-b5cb-e92417b1a634
Content-Type: application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8
Date: Tue, 05 Oct 2021 16:08:40 GMT
Odata-Version: 4.0
Request-Id: 9241d9b8-f317-4248-b5cb-e92417b1a634
Strict-Transport-Security: max-age=31536000
Vary: Accept-Encoding
X-Ms-Ags-Diagnostic: {"ServerInfo":{"DataCenter":"North Central US","Slice":"E","Ring":"5","ScaleUnit":"003","RoleInstance":"CH01EPF00004E6B"}}
X-Ms-Resource-Unit: 1

183
{"@odata.context":"https://graph.microsoft.com/v1.0/$metadata#directoryObjects/$entity","@odata.type":"#microsoft.graph.user","id":"xxxxxx","businessPhones":[],"displayName":"Ken Sykora","givenName":"Ken","jobTitle":null,"mail":null,"mobilePhone":null,"officeLocation":null,"preferredLanguage":null,"surname":"Sykora","userPrincipalName":"<email address redacted>"}
0


========================================== End AzureAD Response: timestamp=2021-10-05T16:08:42.107Z
2021-10-05T16:08:42.109Z [TRACE] maybeTainted: azuread_group.vpn_users encountered an error during creation, so it is now marked as tainted
2021-10-05T16:08:42.109Z [TRACE] NodeAbstractResouceInstance.writeResourceInstanceState to workingState for azuread_group.vpn_users
2021-10-05T16:08:42.109Z [TRACE] NodeAbstractResouceInstance.writeResourceInstanceState: removing state object for azuread_group.vpn_users
2021-10-05T16:08:42.109Z [TRACE] evalApplyProvisioners: azuread_group.vpn_users is tainted, so skipping provisioning
2021-10-05T16:08:42.109Z [TRACE] maybeTainted: azuread_group.vpn_users was already tainted, so nothing to do
2021-10-05T16:08:42.109Z [TRACE] NodeAbstractResouceInstance.writeResourceInstanceState to workingState for azuread_group.vpn_users
2021-10-05T16:08:42.109Z [TRACE] NodeAbstractResouceInstance.writeResourceInstanceState: removing state object for azuread_group.vpn_users
2021-10-05T16:08:42.110Z [TRACE] vertex "azuread_group.vpn_users": visit complete
2021-10-05T16:08:42.110Z [TRACE] dag/walk: upstream of "provider[\"registry.terraform.io/hashicorp/azuread\"] (close)" errored, so skipping
2021-10-05T16:08:42.110Z [TRACE] dag/walk: upstream of "meta.count-boundary (EachMode fixup)" errored, so skipping
2021-10-05T16:08:42.110Z [TRACE] dag/walk: upstream of "root" errored, so skipping

@helayoty Thanks for the report, are you also running in Azure Government? L4?

No, Azure.

Thanks for resolving this so quickly! I am back up and running.

Thanks for the quick action on resolving this folks, much appreciated!

We are also anxiously waiting for the fix. Can you please confirm at what time tomorrow we should expect it to be available. thanks in advance.

The test builds were only for investigation purposes and not a workaround, and have hence been removed. Please check tomorrow’s release for fixes to this breaking change in the API. Thanks!

Thanks to everyone who has posted debug logs. At this time we’re fairly confident of the causes of this issue and a comprehensive workaround will be included in this week’s release. I have now removed the test builds as mentioned. We no longer need further log output to diagnose this issue, thanks!

If you have used a test build and have still seen errors like ODataId was nil or DirectoryObject encountered with nil ODataId, this is likely because the workaround in the test build was not applied to every code path - for example the test build did not fix the azuread_group_member resource, and did not fix the updating of any resource.

If you are seeing the error Invalid URL format specified in payload, this is also due to breaking changes in the API, which the released workaround will address.

One last note: if you are affected by this issue, please do not post +1 or “me too” comments as it distracts from helpful discussion - instead please upvote the issue (👍 reaction on the initial comment) as this does help us to gauge the impact radius of this issue. Many thanks!

@manicminer - Do we have any workaround for this? We have huge impact due to this.

To provide update, this error has nothing to do with not requesting provider within the module, the configuration works on all other resources except azuread_group_member

we have added required provider within the module as well as within the main template.

@manicminer When using

azuread = {
 source = manicminer/azuread
 version = "12.1.0"
}

for azuread_group_member we are getting the following error:

Error: Adding group member "01234567-aaaa-bbbb-cccc-891234567891" to group "01234567-aaaa-bbbb-cccc-891234567891"
with module.iar-adgroup-member.azuread_group_member.adgroupmember,
 on .terraform\modules\iar-adgroup-member\modules\azuread\azuread-group-member\main.tf line 8, in resource 
  "azuread_group_member" "adgroupmember":
   8: resource "azuread_group_member" "adgroupmember" {

GroupsClient.BaseClient.Post(): unexpected status 400 with OData error:
BadRequest: Invalid URL format specified in payload.

@manicminer When using

azuread = {
 source = manicminer/azuread
 version = "12.1.0"
}

for azuread_group_member we are getting the following error:

Error: Adding group member "01234567-aaaa-bbbb-cccc-891234567891" to group "01234567-aaaa-bbbb-cccc-891234567891"
with module.iar-adgroup-member.azuread_group_member.adgroupmember,
 on .terraform\modules\iar-adgroup-member\modules\azuread\azuread-group-member\main.tf line 8, in resource 
  "azuread_group_member" "adgroupmember":
   8: resource "azuread_group_member" "adgroupmember" {

GroupsClient.BaseClient.Post(): unexpected status 400 with OData error:
BadRequest: Invalid URL format specified in payload.

There are my current providers and it works

required_providers {
  azurerm = {
    source  = "hashicorp/azurerm"
    version = "2.79.1"
  }
  azuread = {
    # Fix temporaire : https://github.com/hashicorp/terraform-provider-azuread/issues/588#issuecomment-934282919
    source  = "manicminer/azuread"
    version = "12.1.0"

    # source  = "hashicorp/azuread"
    # version = "2.5.0"
  }
  azuredevops = {
    source = "microsoft/azuredevops"
  }

MS has responded with this concerning the comment above:

Let me reach out to our PG (Product Group) on this. We discussed about this issue in our case Triage this morning and based on the discussion I understood that @OData.id was added first which broke peoples code. During the discussion, I understood that there is an issue with that format and our PG Team is working on it to fix , Since there is no proper documentation , I could not answer to your questions. Let me first ask our PG on the status on this issue, and I will reach out to you.

@stazz @mlcooper Many thanks for digging into this.

(cc @bher2000, @helayoty, @DmytryEmery, @Bj3MaS) I’m working on an implementation to support OData-related HTTP headers and have pushed a test build to manicminer/terraform-provider-azuread. This is another class of issue that is not affecting any of our testing tenants, so if anyone affected by this issue is able to test and give feedback it would be highly appreciated!

You can give this a spin by modifying your terraform block:

terraform {
  required_providers {
    azuread = {
      source = "manicminer/azuread"
      version = "12.0.1"
    }
  }
}

This is not a reviewed release and is cut from a development branch. Please do not use this in a production tenant. I’ll be deleting the release artifacts in time so it will only work until then.

Thanks!

I did some research and in the odata standard there are some standard request parameters that can be used, including odata.metadata=minimal and odata.metadata=full. So I agree with @stazz, I think that line in the Hamilton library simply always needs to use odata.metadata=full. You can see the odata standard here.

@manicminer, Thanks for the update and details on this issue! While its unfortunate we cannot use this module for now its honestly not super surprising that Azure Government Cloud is causing the issue 😃. I will put in a ticket with Azure support on our side about this issue and link this thread.

Thanks again for the quick response!

Hi all guys. could some body help me to know why I’m receiving this error on my TF module. │ ApplicationsClient.BaseClient.Post(): unexpected status 403 with OData │ error: Authorization_RequestDenied: Insufficient privileges to complete the │ operation. I am using an Access Key and Secret on my config using a Service Principal. and I have configured Microsoft Graph > User.ReadWrite.All Thank you in advance

@Maximo1990 - You will need to have one of the following roles: application roles: Application.ReadWrite.All or Directory.ReadWrite.All More info listed here: https://registry.terraform.io/providers/hashicorp/azuread/latest/docs/resources/application Cheers!

@brnwn4 thanks for your help, let me try whit this roles.

@Maximo1990 - No problem. Should work out, i initially hit the same error on my initial deploy with a SP.

Confirmed fixed. Big thanks to @manicminer

azuread:index:ServicePrincipal (nameofSp): error: 1 error occurred: * Could not create service principal: json.Marshal(): json: error calling MarshalJSON for type *msgraph.Owners: marshaling Owners: encountered DirectoryObject with nil ODataId

Just reporting that this is now occurring on SP creation as well (using pulumi).

@everyone screaming for a timeframe: Do you require the features in >= 2.0.0 of the provider? If not, just reference 1.6.0 and be happy until the fix is out.

Could you add a fix in the terraform provider please ? This issue is impacting a lot of projects 😦

@manicminer I have now removed the test builds as mentioned. Does it means your

      source = "manicminer/azuread"
      version = "12.1.0"

is not available anymore ?

This is showstopper for us. Can we get solution around this.

Thank you @mlcooper for asking! That is a bit worrying answer, but let’s hope they manage to sort it out. I hope that whatever their final result is, they would make it uniform across whole API.

@manicminer That is interesting - in your examples above, clearly part of the request body(ies) container @odata fields, which based on what Azure told me yesterday, doesn’t make full sense to me. I will ask them about it right now. However, none of your examples that I can see require @odata.id in the request, and all of the responses do contain the id field which Azure said to use instead of the @odata.id field.

The <fieldName>@odata.bind fields references other objects by their @odata.id attribute. Using the schema ID (id field value) for this doesn’t work and produces errors like:

Invalid URL format specified in @odata.bind for owners

Hmm, good catch. I thought “I wonder if specifying owners via separate REST API call would make it work”, and checked the spec. However, it looks like even there, the ID is specified with "@odata.id".

@mlcooper Since you got case going on with MS support, what do they say to that? Seems like there is some contradiction in saying @-properties are to be used only by internal MS services vs public API reference documentation using them.

I agree - I am reaching out to MS about this now.

@manicminer in my case azuread_application affected

Could not retrieve owner principal object "e7...."
...
ODataId was nil

Can confirm using manicminer/azuread version 12.1.0 fixed the problem

@manicminer Thanks to your new version 12.1.0 I was able to deploy azuread_applications with owners.

Currently, this could be used as a workaround instead of creating resources manually and then importing them with terraform:

  1. Change the official hashicorp/azuread provider to manicminer/azuread version 12.1.0
  2. Deploy problematic resources (in my case azuread_applications with owners)
  3. Change back to the official hashicorp/azuread provider and use terraform init -upgrade

Thanks @stazz - I didn’t touch the update code yet so there’s probably a bugbear in there that needs the workaround too.

We’re using the beta endpoint for Applications as there are some properties we support that haven’t made it to the 1.0 API yet.

In terms of IDs versus OData IDs, generally we use the underlying object IDs wherever possible, however when creating an object sometimes the only way to specify relational fields is via OData fields. This is a problem for owners in general because, aside from other considerations for complex objects like Groups, you can create objects with no owners and be left unable to update them without the necessary permissions. Others like Groups no longer permit new objects without owners.

@manicminer The hacks are the backbone of everything 😉 The 12.1.0 version worked! I could create an app now, with owners and also without.

There was just small hiccup: when I change owners value:

  • If application already has an owner, the owner is not removed
  • If application does not have an owner, TF crashes:
2021-10-04T17:06:32.733Z [INFO]  plugin.terraform-provider-azuread_v12.1.0: 2021/10/04 17:06:32 [DEBUG] Begin AzureAD Request: ==========================================
POST /beta/<tenant ID>/applications/<app GUID>/owners/$ref HTTP/1.1
Host: graph.microsoft.com
User-Agent: HashiCorp Terraform/0.14.9 (+https://www.terraform.io) Terraform Plugin SDK/2.7.0 terraform-provider-azuread/dev Hamilton (Go-http-client/1.1) pid-<guid>
Content-Length: 72
Accept: application/json; charset=utf-8; IEEE754Compatible=false
Content-Type: application/json; charset=utf-8
Odata-Maxversion: 4.0
Odata-Version: 4.0
Accept-Encoding: gzip

{"@odata.id":"directoryObjects('<guid>')"}
2021-10-04T17:06:32.780Z [INFO]  plugin.terraform-provider-azuread_v12.1.0: 2021/10/04 17:06:32 [DEBUG] Begin AzureAD Response for POST https://graph.microsoft.com/beta/<tenantID>/applications/<app GUID>/owners/$ref: ==========================================
HTTP/1.1 400 Bad Request
Transfer-Encoding: chunked
Client-Request-Id: <guid>
Content-Type: application/json
Date: Mon, 04 Oct 2021 17:06:32 GMT
Request-Id: <guid>
Strict-Transport-Security: max-age=31536000
Vary: Accept-Encoding
X-Ms-Ags-Diagnostic: {"ServerInfo":{"DataCenter":"West Europe","Slice":"E","Ring":"5","ScaleUnit":"004","RoleInstance":"AM2PEPF000088EF"}}

ef
{"error":{"code":"BadRequest","message":"Invalid URL format specified in payload.","innerError":{"date":"2021-10-04T17:06:32","request-id":"<guid>","client-request-id":"<guid>"}}}
0

I can see it is passing this directoryObject('<guid>') in POST request, which is causing havoc. I also notice that URL has beta prefix - is that on purpose?

I have an active case opened with the Graph API team at Microsoft. If I were to send them this trace I just posted, would they be able to also quickly and clearly see there is a bug with their API?

Here’s the minimal’s test app TF code:

terraform {
  required_version = ">= 1.0.0"
  required_providers {
    azuread = {
      source  = "manicminer/azuread"
      version = "12.0.0"
    }
  }
}

provider "azuread" {
  tenant_id = var.azure_tenant_id
}

data "azuread_client_config" "current" {}

resource "azuread_application" "grafana" {
  display_name     = "Grafana Test"
  owners           = [data.azuread_client_config.current.object_id]
  sign_in_audience = "AzureADMyOrg"
}

And here’s some debug info:

2021-10-04T16:09:24.464+0200 [INFO]  provider.terraform-provider-azuread_v12.0.0: 2021/10/04 16:09:24 [DEBUG] Begin AzureAD Request: ==========================================
POST /beta/<REDACTED>/applications HTTP/1.1
Host: graph.microsoft.com
User-Agent: HashiCorp Terraform/1.0.4 (+https://www.terraform.io) Terraform Plugin SDK/2.7.0 terraform-provider-azuread/dev Hamilton (Go-http-client/1.1) pid-222c6c49-1b0a-5959-a213-6608f9eb8820
Content-Length: 781
Accept: application/json; charset=utf-8; IEEE754Compatible=false
Content-Type: application/json; charset=utf-8
Odata-Maxversion: 4.01
Odata-Version: 4.01
Accept-Encoding: gzip

{"groupMembershipClaims":null,"owners@odata.bind":["directoryObjects('<REDACTED>')"],"api":{"acceptMappedClaims":false,"knownClientApplications":[],"oauth2PermissionScopes":[],"requestedAccessTokenVersion":1},"appRoles":[],"displayName":"Grafana Test","identifierUris":[],"info":{"marketingUrl":"","privacyStatementUrl":"","supportUrl":"","termsOfServiceUrl":""},"isDeviceOnlyAuthSupported":false,"isFallbackPublicClient":false,"oauth2RequirePostResponse":false,"optionalClaims":{},"publicClient":{"redirectUris":[]},"requiredResourceAccess":[],"signInAudience":"AzureADMyOrg","spa":{"redirectUris":[]},"web":{"homePageUrl":null,"implicitGrantSettings":{"enableAccessTokenIssuance":false,"enableIdTokenIssuance":false},"logoutUrl":null,"redirectUris":[]}}
========================================= End AzureAD Request: timestamp=2021-10-04T16:09:24.464+0200
2021-10-04T16:09:24.620+0200 [INFO]  provider.terraform-provider-azuread_v12.0.0: 2021/10/04 16:09:24 [DEBUG] Begin AzureAD Response for POST https://graph.microsoft.com/beta/<REDACTED>/applications: ==========================================
HTTP/1.1 400 Bad Request
Transfer-Encoding: chunked
Client-Request-Id: b4b6aee5-a7d7-495b-a424-74a0979e1851
Content-Type: application/json
Date: Mon, 04 Oct 2021 14:09:25 GMT
Deprecation: 
Link: <https://developer.microsoft-tst.com/en-us/graph/changes?$filterby=beta,PrivatePreview:Restricted_AU_Properties&from=2021-04-01&to=2021-05-01>;rel="deprecation";type="text/html"
Request-Id: b4b6aee5-a7d7-495b-a424-74a0979e1851
Strict-Transport-Security: max-age=31536000
Sunset: 
Vary: Accept-Encoding
X-Ms-Ags-Diagnostic: {"ServerInfo":{"DataCenter":"West Europe","Slice":"E","Ring":"5","ScaleUnit":"000","RoleInstance":"AM1PEPF00006ADA"}}

fd
{"error":{"code":"BadRequest","message":"Invalid URL format specified in @odata.bind for owners","innerError":{"date":"2021-10-04T14:09:25","request-id":"b4b6aee5-a7d7-495b-a424-74a0979e1851","client-request-id":"b4b6aee5-a7d7-495b-a424-74a0979e1851"}}}
0


========================================== End AzureAD Response: timestamp=2021-10-04T16:09:24.620+0200

@manicminer I’ve just tested your solution, and unfortunately it doesn’t work. Earlier I stumbled upon this issue:

azuread_application.grafana: Creating...
│ Error: Could not create application
│ 
│   with azuread_application.grafana,
│   on azuread.tf line 7, in resource "azuread_application" "grafana":
│    7: resource "azuread_application" "grafana" {
│ 
│ json.Marshal(): json: error calling MarshalJSON for type
│ msgraph.Application: json: error calling MarshalJSON for type
│ *msgraph.Owners: marshaling Owners: encountered DirectoryObject with nil
│ ODataId

Now with a custom version 12.0.0 there is another problem:

azuread_application.grafana: Creating...
│ Error: Could not create application
│ 
│   with azuread_application.grafana,
│   on azuread.tf line 7, in resource "azuread_application" "grafana":
│    7: resource "azuread_application" "grafana" {
│ 
│ ApplicationsClient.BaseClient.Post(): unexpected status 400 with OData
│ error: BadRequest: Invalid URL format specified in @odata.bind for owners