Sentinel checks of mixed values (references and constants)

Hi community,

we’re currently heavily investing in writing Sentinel policies for our platform.
During this development, we discovered a specific/strange behaviour, which impedes sufficient checks in certain cases.

Context:
We have dedicated subscriptions and resource groups for different environments (dev, stage, prod). We’d like to write a Sentinel policy that verifies added VNet integrations (e.g. for the Key Vault or MSSQL Server resources) against the requirement of restrict/prevent cross-environment communication. For example: only allow DEV resources to communicate with DEV, not PROD.

Such VNet integrations can be added by referencing the related Terraform resource or by directly using the ID string.

Example for the Key Vault:

resource "azurerm_key_vault" "example" {
    [...]
    network_acls {
        virtual_network_subnet_ids = [
             azurerm_resource_group.example.id, # TF Reference
             "/subscriptions/<SUB-ID>/resourceGroups/<RG-NAME>/providers/Microsoft.Network/virtualNetworks/<VNET-NAME>/subnets/<SUBNET-NAME>" # ID String
        ]
    }
}

Problem:
What we found is that as soon as a single Terraform reference appears in the list of subnet IDs, the static strings are neither part of the tfconfig nor the tfplan data/mocks, as the whole block is replaced with/part of the after_unknown block only.

tfconfig -> resources:

"network_acls": [
    {
        [...]
        "virtual_network_subnet_ids": {
            "references": [
                "azurerm_subnet.example",
            ],
        },
    },
],

tfplan -> resource_changes:

"after_unknown": {
    [...]
    "network_acls": [
        {
            "virtual_network_subnet_ids": true,
        },
    ],

This prevents us from any (known) way to check this requirement via Sentinel.

Is there any way to view/access also the static strings, when a reference is used in combination?

Many thanks in advance.

@ddetering : Unfortunately, you’ve bumped up against a limitation of the tfconfig/v2 import which is that when a resource attribute is assigned something that is a combination of static strings and references to other resource attributes or variables, the import only shows the references, losing the static strings. Additionally, sometimes, the references are incomplete when the references are to blocks of resources. And the tfplan/v2 import is not useful in this case because the entire attribute with the mixture of stings and references is marked as “known after apply” (computed) as soon as one item in the references is computed.

The only thing you could do in this case would be to run speculative plans against the workspaces that define the resources in question and then check either tfplan/v2 or tfstate/v2 imports to see if there are any disallowed references to objects in the wrong environment. Note that speculative plans cannot be applied and do not show up in the runs history for the workspace, but do trigger Sentinel policy checks.

Roger Berlind

Thanks for your quick answer @rberlind.

That’s actually quite a bad thing for Sentinel, when using it for automated security checks. Especially, because a) the static definitions are also deployed (although not showing up anywhere) and b) a second run/apply of the very same configuration and policy definitions would fail - because references are resolved - which renders Sentinel checks non-deterministic.

Unfortunately, the workaround of using speculative plans does not work in our setup.

Are there plans/ideas on addressing this?

Not that I’m aware of at this time, @ddetering. But I myself have filed an enhancement request in connection with the limitations of the tfconfig/v2 import.

Thanks, @rberlind! We’ll address this as well to our account manager.