Closed calexandre closed 2 years ago
Absolutely... not tested this exact scenario but the functionality should be available on all files in the custom library_path
as we universally implemented the templatefile()
function to import these.
The built-in template file variables are based on the following map object:
builtin_template_file_variables = {
root_scope_id = basename(local.root_id)
root_scope_resource_id = local.root_id
current_scope_id = basename(local.scope_id)
current_scope_resource_id = local.scope_id
default_location = local.default_location
location = local.default_location
builtin = local.builtin_library_path
builtin_library_path = local.builtin_library_path
custom = local.custom_library_path
custom_library_path = local.custom_library_path
}
And this can be extended by setting the template_file_variables
input variable against your module block, with a custom map(string)
object value. As long as the key
matches the variable used in the template, the value
should be inserted at import, allowing you to perform your custom substitution.
NOTE: We have intentionally ordered the merge to ensure the
builtin_template_file_variables
value is applied in preference over any conflicting values provided intemplate_file_variables
to prevent unexpected module behaviour, so please ensure you use unique template variable names.
Hope this helps, but feel free to ask if you need further clarification.
In a related note (as I'm guessing you may wish to over-ride these values for the built-in policies), we are currently working with @TobiasKeitsch to update the module behaviour so customer-specified parameters take precedence over those managed by the management
child module. This will probably help you to more easily set this value across our built-in Policy Assignments too.
You can find more information on Issue #97 and PR #98
And one more point. As only string
values are supported in the vars
input for templatefile()
, if you want to enter a more complex type such as array
or object
into your template, you should be able to use the jsonencode()
function to create a correctly formatted JSON string representation of your substitution. It's just worth noting that this may cause problems with some linting tools if you're running code quality checks in your pipeline(s).
@kevdhowell thank you! We will try your suggestions today and I'll report back the results :) Is there any documentation space prepared for this particular use-case? I could submit a documentation PR if you need.
I could submit a documentation PR if you need.
If you could @calexandre, that would be awesome! I'll leave this issue open as a placeholder for tracking. Thank you!
I tested your suggestion, and I am able to use the template_file_variables
. However, I was expecting Terraform to detect some changes based on the value of my change...
MY goal is to replace the hardcored workspace
like I mentioned above, and ended with something like this:
archetype_extension_org.json
"Deploy-Nsg-FlowLogs-to-LA": {
"workspace": "${log_analytics_workspace_id}"
}
And then in my enterprise-scale.tf
where the module is used:
template_file_variables = {
log_analytics_workspace_id = "xpto"
}
Note that I actually used the xpto
value just to check if Terraform would plan a change, which it didn't...
Any thoughts on this @krowlandson ?
Hi, I looked into your issue and tried to replicate it but it worked as intended for me, you can see my test further down.
In your initial config you don't have any policy_assignment
that matches your parameters key Deploy-Nsg-FlowLogs-to-LA
.
Is the value hardcoded in the policy_assignment_**.tmpl.json
file and maybe the parameters from the archetype_extension_**.tmpl.json
is ignored?
One test to verify is to set null
value for the parameter in the policy_assignment_**.tmpl.json
file to verify that the parameter is used. like this:
"parameters": {
"workspace": {
"value": null
}
},
I started with the following configuration
archetype_extension_es_root.tmpl.json
:
{
"extend_es_root": {
"policy_assignments": [
"Deploy-NSG-Flowlog-to-LA"
],
"policy_definitions": [],
"policy_set_definitions": [],
"role_definitions": [],
"archetype_config": {
"parameters": {
"Deploy-NSG-Flowlog-to-LA": {
"workspace" : "/subscriptions/<guid>/resourcegroups/issue104/providers/microsoft.operationalinsights/workspaces/la-issue104"
}
},
"access_control": {}
}
}
}
Then I tried to changed to use the template_file_variables. This did not trigger any changes.
Files:
archetype_extension_es_root.tmpl.json
:
{
"extend_es_root": {
"policy_assignments": [
"Deploy-NSG-Flowlog-to-LA"
],
"policy_definitions": [],
"policy_set_definitions": [],
"role_definitions": [],
"archetype_config": {
"parameters": {
"Deploy-NSG-Flowlog-to-LA": {
"workspace" : "${log_analytics_workspace_id}"
}
},
"access_control": {}
}
}
}
es_issue104.tf
:
module "enterprise_scale" {
source = "Azure/caf-enterprise-scale/azurerm"
version = "0.3.1"
root_parent_id = data.azurerm_client_config.current.tenant_id
default_location = "westeurope"
root_id = "es-i104"
root_name = "es-i104"
library_path = "${path.root}/lib"
template_file_variables = {
log_analytics_workspace_id = "/subscriptions/<guid>/resourcegroups/issue104/providers/microsoft.operationalinsights/workspaces/la-issue104"
}
}
Finally I changed log_analytics_workspace_id in template_file_variables
to a mockup value of xpto
just as you tried.
This triggered a change as it is supposed to:
Terraform will perform the following actions:
# module.enterprise_scale.azurerm_policy_assignment.enterprise_scale["/providers/Microsoft.Management/managementGroups/es-i104/providers/Microsoft.Authorization/policyAssignments/Deploy-NSG-Flowlog-to-LA"] must be replaced
-/+ resource "azurerm_policy_assignment" "enterprise_scale" {
~ id = "/providers/Microsoft.Management/managementGroups/es-i104/providers/Microsoft.Authorization/policyAssignments/Deploy-NSG-Flowlog-to-LA" -> (known after apply)
~ metadata = jsonencode(
{
- createdBy = "<redacted>"
- createdOn = "2021-05-17T20:32:47.5535361Z"
- updatedBy = null
- updatedOn = null
}
) -> (known after apply)
name = "Deploy-NSG-Flowlog-to-LA"
~ parameters = jsonencode(
~ {
~ workspace = {
~ value = "/subscriptions/<guid>/resourcegroups/issue104/providers/microsoft.operationalinsights/workspaces/la-issue104" -> "xpto"
}
} # forces replacement
)
# (6 unchanged attributes hidden)
~ identity {
~ principal_id = "<redacted>" -> (known after apply)
~ tenant_id = "<redacted>" -> (known after apply)
# (1 unchanged attribute hidden)
}
}
Hmm thanks for the feedback @TobiasKeitsch! I will try to execute some more tests tomorrow and report back...
Hi @calexandre... just wanted to check in to see how you're progressing with this issue? Were you able to resolve this or do you believe there is still an issue we need to investigate? Thank you
Hello @krowlandson, sorry for the late response, I've been a little busy in the last week..
I was finally able to give this issue some attention and after trying @TobiasKeitsch approach, and I'm still unable to achieve a successful plan...
Some notes regarding the mentioned approach:
Deploy-Nsg-FlowLogs-to-LA
vs Deploy-NSG-Flowlog-to-LA
) Deploy-Nsg-FlowLogs-to-LA
is a policy definition and not an assignment... I guess this makes a huge difference?Deploy-Nsg-FlowLogs-to-LA
to my archetype's policy_definitions
section, the plan executes Ok, but still without any changes... :( Deploy-Nsg-FlowLogs-to-LA
to the archetype's policy_assignments
section, which of course ended with an error because it is a definition and not an assignment:╷
│ Error: Invalid index
│
│ on .terraform/modules/enterprise_scale/modules/archetypes/locals.policy_assignments.tf line 92, in locals:
│ 92: template = local.archetype_policy_assignments_map[policy_assignment]
│ ├────────────────
│ │ local.archetype_policy_assignments_map is object with 30 attributes
│
│ The given key does not identify an element in this collection value.
Since this is a built-in policy definition, should I be trying to pass a value to the definition, or should I create a new policy assignment instead?
You need to create a policy assignment, I used the same name as the definition unfortunately.
In the archetype you need to define both the definition and the assignment, and in the parameter object you should map it to the name of the policy assignment that you create.
That explains a lot :)
Could you share the policy assignment you created? Could use a working example :)
You can always reference the Policy Assignment templates (and others) which are bundled with the module.
For example, the Deny-Resource-Locations
Policy Assignment is an example of one which references a "built-in" Policy Definition, whilst Deny-RDP-From-Internet
references a "custom" Policy Definition provisioned by the module. This let's you see how we use the default template variables to customise these during import, which will behave in the same way with values provided via the template_file_variables
input variable.
Also worth noting that you do not have to provide parameters within the template (just a placeholder for the parameters block), unless you want to hard code values into the assignment.
In practice, we would recommend settings these at the scope of assignment using the parameters
object within archetype_config
.
Thank you for the explanation! :) I will try again today using your recommendations and report back 👍
Once we cut the next release, this issue should be addressed by the updates to the [Variables] template_file_variables page on our Wiki.
Community Note
Description
Is it possible to add some kind of variable substitution on
archetype_extension_org.json
? We have a use-case where we are want to specify theworkspace-id
for theDeploy-Nsg-FlowLogs-to-LA
policy, and unless there's a way to pass that variable from Terraform to the Policy, we are pretty much stuck with the hardcoded value...Basically, I'm looking to know if its possible to use something in the form of:
Our
archetype_extension_org.json
with theDeploy-Nsg-FlowLogs-to-LA
with a "hardcoded" workspace id...