magodo/terraform-provider-restful

Add precheck to data.restful_resource

LaurentLesle opened this issue · 0 comments

The goal of this feature is to add a precheck condition before the the data source return the value. It may be useful when you need to ensure the a cache has been updated with an expected attribute value

Scenario is:

  • Create with azuread an application
  • Set API roles with azuread_application api_access
  • Call data restful_resource with this precheck to verify id the previous api access are in the response body
  • grant admin consent

Reuse similar approach as:
Nested Schema for precheck
Required:

path (String) The path used to query readiness, relative to the base_url of the provider.
status (Attributes) The expected status sentinels for each polling state. (see below for nested schema)
status_locator (String) Specifies how to discover the status property. The format is either code or scope.path, where scope can be either header or body, and the path is using the gjson syntax.
Optional:

default_delay_sec (Number) The interval between two pollings if there is no Retry-After in the response header, in second.
header (Map of String) The header parameters. This overrides the header set in the resource block.
query (Map of List of String) The query parameters. This overrides the query set in the resource block.

Code snipet:

locals {
  azuread_applications = {
    "tenant-root" = {
      display_name          = "tenant-root"
      password_display_name = "Bootstrap process password."
      end_date_relative     = "744h" # 31 days
      rotate_every_x_days   = "1"
      api_access = {
        api_client_id = data.azuread_application_published_app_ids.well_known.result["MicrosoftGraph"]
        role_ids = [
          data.azuread_service_principal.msgraph.app_role_ids["Application.ReadWrite.OwnedBy"],
          data.azuread_service_principal.msgraph.app_role_ids["User.Read.All"],
          data.azuread_service_principal.msgraph.app_role_ids["Group.Read.All"],
          data.azuread_service_principal.msgraph.app_role_ids["GroupMember.Read.All"]
        ]
        scope_ids = []
      }
      owners = [
        local.running_context.principal_id
      ]
    }
  }
}

module "application" {
  source = "../modules/azuread/application"

  for_each = local.azuread_applications

  display_name    = each.value.display_name
  owners = each.value.owners
}

data "azuread_application_published_app_ids" "well_known" {}

data "azuread_service_principal" "msgraph" {
  client_id = data.azuread_application_published_app_ids.well_known.result["MicrosoftGraph"]
}

resource "azuread_application_api_access" "this" {
  for_each = local.azuread_applications

  application_id = module.application[each.key].id
  api_client_id  = each.value.api_access.api_client_id

  role_ids = each.value.api_access.role_ids

  scope_ids = each.value.api_access.scope_ids

  
}

data "restful_resource" "check_cache_propagation" {
  provider   = restful.msgraph
  depends_on = [azuread_application_api_access.this]


  for_each = local.azuread_applications

  id = format("applications/%s", module.application[each.key].client_id)

  # NEW Feature requested
  precheck = [
    for role_id in each.value.api_access.role_ids : {
      api = {
        path = format("applications/%s", module.application[each.key].client_id)

        # Search for the resourceAppId first then check each resource access are in the response body
        status_locator = "{requiredResourceAccess.#(resourceAppId==${each.value.api_access.api_client_id}):requiredResourceAccess.#.resourceAccess(id==${role_id})}"
      }
    }
  ]

}

# Now cache has been updated we can proceed with the admin consent

resource "restful_operation" "grant_admin_consent" {
  provider   = restful.iam
  depends_on = [data.restful_resource.check_cache_propagation]

  for_each = local.azuread_applications

  path = format("api/RegisteredApplications/%s/Consent", module.application[each.key].client_id)
  header = {
    x-ms-client-request-id = uuid()
  }
  query = {
    onBehalfOfAll = [true]
  }
  method = "POST"
}