worxspace / PSPulumi

GNU General Public License v3.0
7 stars 1 forks source link

Cannot provide correct structure to $parameters param in authorization.PolicyAssignment #14

Open NNG9y1PQdXl opened 1 year ago

NNG9y1PQdXl commented 1 year ago

I have tried to create a policy assignment, based on existing in-built definition and settigns taken from other assignment of the same defintion, already present in another RG, with the following code example:

    $ReadRG1 = Invoke-AzureNativeFunctionResourcesGetResourceGroup -resourceGroupName "rg-mgmt-dev"
    $projectTags = [ordered]@{
        project     = "mgmt"
        owner     = "test.user"
    }
    $ReadPolicy1 = Invoke-AzureNativeFunctionAuthorizationGetPolicyAssignment -scope $ReadRG1.reference("id") -policyAssignmentName "inherit-project-tag"
    $TestRGProps = @{
        pulumiid            = "testRG"
        resourceGroupName   = "TestRG2"
        tags                = $projectTags
    }
    $deployRG2 = New-AzureNativeResourcesResourceGroup @TestRGProps
    $tagNameProject = @{ "tagName" = New-AzureNativeTypeAuthorizationParameterValuesValue $projectTags.Keys[0]}
    $Policy1AssgnprojectToRg2Props = @{
        policyAssignmentName    = $ReadPolicy1.reference("name")
        policyDefinitionId      = $ReadPolicy1.reference("policyDefinitionId")
        parameters              = $tagNameProject
        description             = $ReadPolicy1.reference("description")
        displayName             = $ReadPolicy1.reference("displayName")
        metadata                = @{
                                        assignedBy  = "Pulumi"
                                    }
        enforcementMode         = "Default"
        identity                = (New-AzureNativeTypeAuthorizationIdentity -type SystemAssigned)
        scope                   = $deployRG2.reference("id")
        pulumiid                = "policy1AssgnmentToRg2"
    }
    New-AzureNativeAuthorizationPolicyAssignment @Policy1AssgnprojectToRg2Props

This param, as per (https://www.powershellgallery.com/packages/pspulumiyaml.azurenative.authorization/0.0.4): "The parameter values for the assigned policy rule. The keys are the parameter names.", but there is no way I could find to define a key for ParameterValuesValue class. What it does, is take a single string and packs it into:

value: 'mgmt'

...but YAML authorization:PolicyAssignment expects following structure for parameter:

tagName:
    value: mgmt

To sum up, YAML expects more complicated structure, but PSPulumi will only pass a ParameterValuesValue object. Either PSPulumi will not accept the hashtable with correct structure, throwing error: "MethodInvocationException: Exception calling "Invoke" with "0" argument(s): "Cannot process argument transformation on parameter 'parameters'. Cannot create object of type "ParameterValuesValue". The property'tagName' was not found for the 'ParameterValuesValue' object. The settable properties are: [value <System.Object>]."

...or YAML backend will reject the simple ParameterValuesValue passed as parameter:

Error: azure-native:authorization:PolicyAssignment is not assignable from {parameters: {value: string}, identity: {type: string}, metadata: {assignedBy: string}, policyDefinitionId: string, displayName: string, scope: string, enforcementMode: string, description: string, policyAssignmentName: string}
      on <stdout from compiler pwsh> line 21:
      21:         "parameters": {
      22:           "value": "project"
    Cannot assign '{parameters: {value: string}, identity: {type: string}, metadata: {assignedBy: string}, policyDefinitionId: string, displayName: string, scope: string, enforcementMode: string, description: string, policyAssignmentName: string}' to 'azure-native:authorization:PolicyAssignment':
      parameters: Cannot assign '{value: string}' to 'Map<azure-native:authorization:ParameterValuesValue>':
        value: Cannot assign type 'string' to type 'azure-native:authorization:ParameterValuesValue'

I tried a few other ideas, including nesting one ParameterValuesValue into another, but I couldn't find a solution that would both be accepted by PSPulumi and YAML backbone. So what I did, is change the object type from ParameterValuesValue to hashtable:

        [parameter(mandatory=$False,HelpMessage='The parameter values for the assigned policy rule. The keys are the parameter names.)')]
        [hashtable]
        $parameters,

I might be missing something very obvious, but this approach, at least it works:

Do you want to perform this update? details
  pulumi:pulumi:Stack: (same)
    [urn=urn:pulumi:dev::Demo::pulumi:pulumi:Stack::Demo-dev]
~ pulumi:pulumi:Stack: (refresh)
    [urn=urn:pulumi:dev::Demo::pulumi:pulumi:Stack::Demo-dev]
    ~ azure-native:resources:ResourceGroup: (refresh)
        [id=/subscriptions/[subscriptionID]/resourceGroups/TestRG2]
        [urn=urn:pulumi:dev::Demo::azure-native:resources:ResourceGroup::testRG]
    ~ azure-native:authorization:PolicyAssignment: (refresh)
        [id=/subscriptions/[subscriptionID]/resourceGroups/TestRG2/providers/Microsoft.Authorization/policyAssignments/inherit-owner-tag]
        [urn=urn:pulumi:dev::Demo::azure-native:authorization:PolicyAssignment::policy2AssgnmentToRg2]
    ~ azure-native:authorization:PolicyAssignment: (refresh)
        [id=/subscriptions/[subscriptionID]/resourceGroups/TestRG2/providers/Microsoft.Authorization/policyAssignments/inherit-project-tag]
        [urn=urn:pulumi:dev::Demo::azure-native:authorization:PolicyAssignment::policy1AssgnmentToRg2]
Oechiih commented 1 year ago

Hi @NNG9y1PQdXl Thank you very much for using the tool and providing feedback! Looks like your code is perfectly fine and there's an issue with how PSPulumiYAML generates maps for Pulumi. In this particular example Pulumi expect the following YAML

...
parameters:
  tagName:
    value: "mgmt"
...

Which amounts to this in JSON:

...
parameters: {
  tagname: {
    value: "mgmt"
  }
}
...

Which then in Pwsh is this:

...
@{
  parameters= @{
    tagName = @{
      value = "mgmt"
    }
}
...

However what we give it is:

...
parameters:
  tagName: "mgmt"
...

So essentially Pulumi expects a map of maps, but we give it a just a map. Actually not even necessarily that. You correctly used "New-AzureNativeTypeAuthorizationParameterValuesValue" but the CMDLet itself is incorrect. If you passed that value directly then it wouldn't work either (though using it that way would be the desired experience). As you create a hashtable from what the CMDLet returns you're already one step closer to the correct format but still one step off.

Tl;Dr: Pulumi expects a nested map in YAML but we provide it with just a regular map (if at all).

We'll check how often that particular use-case happens and we'll push a fix as soon as we can.

Cheers Oechiih