Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

KeyVault resource has incorrect/inconsistent diff results after pulumi import #3964

Open
gpduck opened this issue Feb 18, 2025 · 8 comments
Open
Assignees
Labels
kind/bug Some behavior is incorrect or out of spec

Comments

@gpduck
Copy link

gpduck commented Feb 18, 2025

What happened?

After running pulumi import to import a key vault resource, the next diff shows the virtualNetworkRules entry would be deleted even though the pulumi program is generating the same values as what was imported. If I add a second entry to the array the diff then shows that the first entry is being updated due to different case and the second element is being added as new (both as expected). I have seen this behavior on the accessPolicies array as well, but my example program didn't behave the same way on that property.

Example

  1. Run the program to create the resources
  2. Run the import command to import the key vault as a second resource
  3. Uncomment the second instance of the key vault that matches the imported resource
  4. Running pulumi up/preview incorrectly shows the virtualNetworkRules property being deleted
  5. Uncomment the second entry in the array and run preview again and the diff behaves as expected for both properties
import { Config } from '@pulumi/pulumi';
import { ResourceGroup } from '@pulumi/azure-native/resources';
import { VirtualNetwork,Subnet } from '@pulumi/azure-native/network';
import { Vault } from '@pulumi/azure-native/keyvault';
import { getClientConfigOutput } from '@pulumi/azure-native/authorization';

const location = 'eastus2';
const azConfig = new Config('azure-native');
const rg = new ResourceGroup('rg', {
  location,
});

const vnet = new VirtualNetwork('vnet', {
  resourceGroupName: rg.name,
  addressSpace: {
    addressPrefixes: ['10.0.0.0/16'],
  }
});

const subnet = new Subnet('subnet', {
  resourceGroupName: rg.name,
  virtualNetworkName: vnet.name,
  addressPrefix: '10.0.0.0/24',
  serviceEndpoints: [
    {
      locations: ['*'],
      service: 'Microsoft.KeyVault',
    }
  ]
});

const vault = new Vault('kv', {
  resourceGroupName: rg.name,
  properties: {
    accessPolicies: [
      {
        objectId: getClientConfigOutput().objectId,
        tenantId: azConfig.require('tenantId'),
        permissions: {
          certificates: ['Get', 'List', 'Backup', 'Restore'],
          keys: ['Get', 'List', 'Backup', 'Restore'],
          secrets: ['Get', 'List', 'Backup', 'Restore'],
        }
      },
    ],
    sku: {
      family: 'A',
      name: 'standard',
    },
    tenantId: azConfig.require('tenantId'),
    networkAcls: {
      defaultAction: 'Deny',
      virtualNetworkRules: [
        { id: subnet.id },
      ]
    }
  },
});

export const kvid = vault.id;

// pulumi import azure-native:keyvault:Vault kv-imported $(pulumi stack output kvid) --yes

// const vaultImported = new Vault('kv-imported', {
//   resourceGroupName: rg.name,
//   properties: {
//     accessPolicies: [
//       {
//         objectId: getClientConfigOutput().objectId,
//         tenantId: azConfig.require('tenantId'),
//         permissions: {
//           certificates: ['Get', 'List', 'Backup', 'Restore'],
//           keys: ['Get', 'List', 'Backup', 'Restore'],
//           secrets: ['Get', 'List', 'Backup', 'Restore'],
//         }
//       },
//     ],
//     sku: {
//       family: 'A',
//       name: 'standard',
//     },
//     tenantId: azConfig.require('tenantId'),
//     networkAcls: {
//       defaultAction: 'Deny',
//       virtualNetworkRules: [
//         { id: subnet.id },
//         // { id: subnet.id },
//       ]
//     }
//   },
// });

Output of pulumi about

CLI
Version 3.135.1
Go Version go1.23.2
Go Compiler gc

Plugins
KIND NAME VERSION
resource azure-native 2.88.0
language nodejs unknown

Host
OS ubuntu
Version 22.04
Arch x86_64

This project is written in nodejs: executable='/usr/bin/node' version='v20.18.2'

Current Stack: org/ducktest5-pulumi/dev

TYPE URN
pulumi:pulumi:Stack urn:pulumi:dev::ducktest5-pulumi::pulumi:pulumi:Stack::ducktest5-pulumi-dev
pulumi:providers:azure-native urn:pulumi:dev::ducktest5-pulumi::pulumi:providers:azure-native::default_2_88_0
azure-native:resources:ResourceGroup urn:pulumi:dev::ducktest5-pulumi::azure-native:resources:ResourceGroup::rg
azure-native:network:VirtualNetwork urn:pulumi:dev::ducktest5-pulumi::azure-native:network:VirtualNetwork::vnet
azure-native:network:Subnet urn:pulumi:dev::ducktest5-pulumi::azure-native:network:Subnet::subnet
azure-native:keyvault:Vault urn:pulumi:dev::ducktest5-pulumi::azure-native:keyvault:Vault::kv
azure-native:keyvault:Vault urn:pulumi:dev::ducktest5-pulumi::azure-native:keyvault:Vault::kv-imported

Found no pending operations associated with org/dev

Backend
Name pulumi.com
Organizations org
Token type personal

Dependencies:
NAME VERSION
@pulumi/azure-native 2.88.0
@pulumi/pulumi 3.150.0
@types/node 18.19.76

Pulumi locates its logs in /tmp by default

Additional context

No response

Contributing

Vote on this issue by adding a 👍 reaction.
To contribute a fix for this issue, leave a comment (and link to your pull request, if you've opened one already).

@gpduck gpduck added kind/bug Some behavior is incorrect or out of spec needs-triage Needs attention from the triage team labels Feb 18, 2025
@PawelHaracz
Copy link

We have something similar with access policies in key vault. Every time when run pulumi preview, we got removed access policies and added once more time the same.

@rquitales
Copy link
Member

This might be a similar root cause to #1355, and likely relates to how we're diff'ing inputs. We'll add this to our backlog for further review. Thanks for reporting!

@rquitales rquitales removed the needs-triage Needs attention from the triage team label Feb 19, 2025
@gpduck
Copy link
Author

gpduck commented Feb 19, 2025

This seems like a different situation, the changes are entirely within the one resource and it's reporting that it's going to delete a value that is actually being set by the code, and then adding an additional value makes the one it was going to delete suddenly come back in addition to the new one.

@gpduck
Copy link
Author

gpduck commented Feb 20, 2025

The handling of the virtualNetworksRules array seems to be off. If I set the value to the subnet ID as a plain string, run pulumi up, and then change the string to a different value the diff shows that the value is being deleted from the array instead of displaying it as a modification. If I do the same thing to an entry in the ipRules array the diff properly shows the value being changed.

@EronWright EronWright self-assigned this Feb 21, 2025
@EronWright

This comment has been minimized.

@EronWright
Copy link
Contributor

EronWright commented Feb 21, 2025

I see the reason why virtualNetworkRules is considered to be changed. The id within virtualNetworkRules has slightly different casing than the value of subnet.id.

For example:

/subscriptions/0282681f-7a9e-424b-80b2-96babd57a8a1/resourcegroups/rg821a0fcc/providers/microsoft.network/virtualnetworks/vnet06de1ea5/subnets/subnet

Versus:

/subscriptions/0282681f-7a9e-424b-80b2-96babd57a8a1/resourceGroups/rg821a0fcc/providers/Microsoft.Network/virtualNetworks/vnet06de1ea5/subnets/subnet

From "Naming rules and restrictions for Azure resources", resource names are case-insensitive. Basically the KeyVault resource has a lower-cased representation of the subnet id, and the diff logic appears to use a case-sensitive comparison.

@EronWright
Copy link
Contributor

EronWright commented Feb 22, 2025

Image

Here's a breakdown of the root causes as best I can tell:

  • virtualNetworkRules
    • comparison should be case-insensitive.
    • the provider's diff logic computed an update but was displayed as a delete.
  • enabledForDeployment, networkAcls.bypass
    • the diff logic doesn't understand when a field is 'unset' to its default value; it flags it as a delete.
  • provisioningState , vaultUri
    • these fields should be modeled as pure output/computed values
  • publicNetworkAccess
    • the Pulumi schema has the default value of enabled but the server-side default is Enabled, because:
    • the Azure API rest specs have the wrong casing (and the field is not an enum)

@PawelHaracz
Copy link

Thanks for your comment, can you tell me is it possible to do something to not show it on the plan? Developers when seeing it are some afraid that will break something

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind/bug Some behavior is incorrect or out of spec
Projects
None yet
Development

No branches or pull requests

4 participants