Azure / azure-libraries-for-net

Azure libraries for .Net
MIT License
379 stars 192 forks source link

[BUG] Key Vault update is failing with Fluent API because of api version 2021-06-01-preview requires publicNetworkAccess property #1258

Closed r4hulp closed 2 years ago

r4hulp commented 3 years ago

Description When you get a key vault resource (using client.GenericResources.GetById(resourceId);) and try to update it, it throws the following error. The 'PublicNetworkAccess' property can not be empty. Please specify an authorized value.

After fiddling around in network traces, I managed to figure out the exact reason why is it failing. The culprit is the new api-version=2021-06-01-preview. The new API version requires the property publicNetworkAccess if you want to update the resource. However, while creating the resource using Azure Portal does not set this property at all.

Steps to reproduce

With Azure Resource Manager Fluent API -

  1. Create a new Key Vault resource in Azure Portal.
  2. Get the Key Vault Resource IGenericResource resource = client.GenericResources.GetById(resourceId); - Notice the API Version (resource.ApiVersion) being returned by this method, it is set to 2021-06-01-preview. Also, notice the properties being retrieved. The property publicNetworkAccess is missing.

image

  1. Now update the Key Vault (e.g. in my case, I updated with a set of custom tags).
    
    var result = await resource.Update().WithApiVersion(resource.ApiVersion).WithProperties(resource.Properties).WithTags(resourceNewTags).ApplyAsync();
3. This will throw an exception - `The 'PublicNetworkAccess' property can not be empty. Please specify an authorized value.`

***Exception or Stack Trace***

at Microsoft.Azure.Management.ResourceManager.Fluent.ResourcesOperations.

d__22.MoveNext() at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult() at Microsoft.Azure.Management.ResourceManager.Fluent.ResourcesOperations. d__11.MoveNext() at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult() at Microsoft.Azure.Management.ResourceManager.Fluent.ResourcesOperationsExtensions. d__6.MoveNext() at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() at Microsoft.Azure.Management.ResourceManager.Fluent.GenericResourceImpl.d__18.MoveNext() at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() at Microsoft.Azure.Management.ResourceManager.Fluent.Core.ResourceActions.Creatable`4.-CreateResourceAsync>d__15.MoveNext() at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() at Microsoft.Azure.Management.ResourceManager.Fluent.Core.DAG.CreatorTaskItem`1.d__6.MoveNext() at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter.GetResult() at Microsoft.Azure.Management.ResourceManager.Fluent.Core.DAG.TaskGroupBase`1. d__14.MoveNext() at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() at Microsoft.Azure.Management.ResourceManager.Fluent.Core.ResourceActions.CreatableUpdatable`5.d__3.MoveNext() at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult() at SensitiveInformation.ClassName.d__6.MoveNext() in C:\hidden_sensitive_information\class_name.cs:line 204 at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() at SensitiveInformation.ClassName.d__14.MoveNext() in C:\hidden_sensitive_information\class_name.cs:line 201 ``` ***Code Snippet*** ``` await resource.Update() .WithApiVersion(resource.ApiVersion) .WithProperties(resource.Properties) .WithTags(resourceNewTags).ApplyAsync(); ``` **Expected behavior** The method `IGenericResource resource = client.GenericResources.GetById(resourceId);` should return property `publicNetworkAccess` of an existing resource. Or make it an optional field (as the provisioning of key vault resource from the portal does not require that field at all) **Setup (please complete the following information):** Library - **Microsoft.Azure.Management.Fluent** v 1.37.1 Rest API - **api-version=2021-04-01-preview** **Information Checklist** - [x] Bug Description Added - [x] Repro Steps Added - [x] Setup information Added
ghost commented 3 years ago

Thanks for the feedback! We are routing this to the appropriate team for follow-up. cc @RandalliLama, @schaabs, @jlichwa.

Issue Details
**Description** When you get a key vault resource (using `client.GenericResources.GetById(resourceId);`) and try to update it, it throws the following error. `The 'PublicNetworkAccess' property can not be empty. Please specify an authorized value.` After fiddling around in network traces, I managed to figure out the exact reason why is it failing. The culprit is the new `api-version=2021-06-01-preview`. The new API version requires the property `publicNetworkAccess` if you want to update the resource. However, while creating the resource using Azure Portal does not set this property at all. **Steps to reproduce** #### With Azure Resource Manager Fluent API - 1. Create a new Key Vault resource in Azure Portal. 1. Get the Key Vault Resource `IGenericResource resource = client.GenericResources.GetById(resourceId);` - Notice the API Version (`resource.ApiVersion`) being returned by this method, it is set to **`2021-06-01-preview`**. Also, notice the properties being retrieved. The property `publicNetworkAccess` is missing. ![image](https://user-images.githubusercontent.com/292704/129724313-70bdee2b-e4ce-4952-9594-7861e3aa6ed6.png) 2. Now update the Key Vault (e.g. in my case, I updated with a set of custom tags). ``` var result = await resource.Update().WithApiVersion(resource.ApiVersion).WithProperties(resource.Properties).WithTags(resourceNewTags).ApplyAsync(); ``` 3. This will throw an exception - `The 'PublicNetworkAccess' property can not be empty. Please specify an authorized value.` ***Exception or Stack Trace*** ``` at Microsoft.Azure.Management.ResourceManager.Fluent.ResourcesOperations. d__22.MoveNext() at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult() at Microsoft.Azure.Management.ResourceManager.Fluent.ResourcesOperations. d__11.MoveNext() at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult() at Microsoft.Azure.Management.ResourceManager.Fluent.ResourcesOperationsExtensions. d__6.MoveNext() at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() at Microsoft.Azure.Management.ResourceManager.Fluent.GenericResourceImpl.d__18.MoveNext() at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() at Microsoft.Azure.Management.ResourceManager.Fluent.Core.ResourceActions.Creatable`4.-CreateResourceAsync>d__15.MoveNext() at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() at Microsoft.Azure.Management.ResourceManager.Fluent.Core.DAG.CreatorTaskItem`1.d__6.MoveNext() at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter.GetResult() at Microsoft.Azure.Management.ResourceManager.Fluent.Core.DAG.TaskGroupBase`1. d__14.MoveNext() at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() at Microsoft.Azure.Management.ResourceManager.Fluent.Core.ResourceActions.CreatableUpdatable`5.d__3.MoveNext() at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult() at SensitiveInformation.ClassName.d__6.MoveNext() in C:\hidden_sensitive_information\class_name.cs:line 204 at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() at SensitiveInformation.ClassName.d__14.MoveNext() in C:\hidden_sensitive_information\class_name.cs:line 201 ``` ***Code Snippet*** ``` await resource.Update() .WithApiVersion(resource.ApiVersion) .WithProperties(resource.Properties) .WithTags(resourceNewTags).ApplyAsync(); ``` **Expected behavior** The method `IGenericResource resource = client.GenericResources.GetById(resourceId);` should return property `publicNetworkAccess` of an existing resource. Or make it an optional field (as the provisioning of key vault resource from the portal does not require that field at all) **Setup (please complete the following information):** Library - **Microsoft.Azure.Management.Fluent** v 1.37.1 Rest API - **api-version=2021-04-01-preview** **Information Checklist** - [x] Bug Description Added - [x] Repro Steps Added - [x] Setup information Added
Author: r4hulp
Assignees: -
Labels: `KeyVault`, `Service Attention`
Milestone: -
weidongxu-microsoft commented 3 years ago

Loop in service on question of why PublicNetworkAccess now becomes a required property (while it is not required in either VaultProperties nor VaultPatchProperties in swagger https://github.com/Azure/azure-rest-api-specs/blob/main/specification/keyvault/resource-manager/Microsoft.KeyVault/preview/2021-06-01-preview/keyvault.json#L1312-L1321).

weidongxu-microsoft commented 3 years ago

Generally it is suggested to fix the api-version when interacting with GenericResource. Though in theory service is backward-compatible, but in many case it does not.

r4hulp commented 3 years ago

@weidongxu-microsoft - not sure if these comments are directed towards me or your team.

weidongxu-microsoft commented 3 years ago

@r4hulp It is about the usage of the GenericResource.

BTW, new .NET SDK will get previewed at https://azure.github.io/azure-sdk/releases/latest/mgmt/dotnet.html, about the end of August.

r4hulp commented 3 years ago

I don't understand one thing though, why is the property publicNetworkAccess not being set by default while creating the Key Vault resource if it is supposed to be a required field?

weidongxu-microsoft commented 3 years ago

@r4hulp If you create the vault on Portal, and in last step click "download template", you can see it is created via "2018-02-14" api-version, which does not contain this publicNetworkAccess property/feature in the first place.

{
    "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
        "name": {
            "type": "string"
        },
        "location": {
            "type": "string"
        },
        "sku": {
            "type": "string"
        },
        "accessPolicies": {
            "type": "array"
        },
        "tenant": {
            "type": "string"
        },
        "enabledForDeployment": {
            "type": "bool"
        },
        "enabledForTemplateDeployment": {
            "type": "bool"
        },
        "enabledForDiskEncryption": {
            "type": "bool"
        },
        "enableRbacAuthorization": {
            "type": "bool"
        },
        "enableSoftDelete": {
            "type": "bool"
        },
        "softDeleteRetentionInDays": {
            "type": "int"
        },
        "networkAcls": {
            "type": "object"
        }
    },
    "variables": {},
    "resources": [
        {
            "apiVersion": "2018-02-14",
            "name": "[parameters('name')]",
            "location": "[parameters('location')]",
            "type": "Microsoft.KeyVault/vaults",
            "properties": {
                "enabledForDeployment": "[parameters('enabledForDeployment')]",
                "enabledForTemplateDeployment": "[parameters('enabledForTemplateDeployment')]",
                "enabledForDiskEncryption": "[parameters('enabledForDiskEncryption')]",
                "enableRbacAuthorization": "[parameters('enableRbacAuthorization')]",
                "accessPolicies": "[parameters('accessPolicies')]",
                "tenantId": "[parameters('tenant')]",
                "sku": {
                    "name": "[parameters('sku')]",
                    "family": "A"
                },
                "enableSoftDelete": "[parameters('enableSoftDelete')]",
                "softDeleteRetentionInDays": "[parameters('softDeleteRetentionInDays')]",
                "networkAcls": "[parameters('networkAcls')]"
            },
            "tags": {},
            "dependsOn": []
        }
    ],
    "outputs": {}
}
r4hulp commented 3 years ago

@r4hulp If you create the vault on Portal, and in last step click "download template", you can see it is created via "2018-02-14" api-version, which does not contain this publicNetworkAccess property/feature in the first place.

{
    "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
        "name": {
            "type": "string"
        },
        "location": {
            "type": "string"
        },
        "sku": {
            "type": "string"
        },
        "accessPolicies": {
            "type": "array"
        },
        "tenant": {
            "type": "string"
        },
        "enabledForDeployment": {
            "type": "bool"
        },
        "enabledForTemplateDeployment": {
            "type": "bool"
        },
        "enabledForDiskEncryption": {
            "type": "bool"
        },
        "enableRbacAuthorization": {
            "type": "bool"
        },
        "enableSoftDelete": {
            "type": "bool"
        },
        "softDeleteRetentionInDays": {
            "type": "int"
        },
        "networkAcls": {
            "type": "object"
        }
    },
    "variables": {},
    "resources": [
        {
            "apiVersion": "2018-02-14",
            "name": "[parameters('name')]",
            "location": "[parameters('location')]",
            "type": "Microsoft.KeyVault/vaults",
            "properties": {
                "enabledForDeployment": "[parameters('enabledForDeployment')]",
                "enabledForTemplateDeployment": "[parameters('enabledForTemplateDeployment')]",
                "enabledForDiskEncryption": "[parameters('enabledForDiskEncryption')]",
                "enableRbacAuthorization": "[parameters('enableRbacAuthorization')]",
                "accessPolicies": "[parameters('accessPolicies')]",
                "tenantId": "[parameters('tenant')]",
                "sku": {
                    "name": "[parameters('sku')]",
                    "family": "A"
                },
                "enableSoftDelete": "[parameters('enableSoftDelete')]",
                "softDeleteRetentionInDays": "[parameters('softDeleteRetentionInDays')]",
                "networkAcls": "[parameters('networkAcls')]"
            },
            "tags": {},
            "dependsOn": []
        }
    ],
    "outputs": {}
}

Understood, but then apiVersion in the code below should be consistent with the API version the resource was created.

IGenericResource resource = client.GenericResources.GetById(resourceId);
string apiVersion = resource.ApiVersion

I created a new Key Vault in Portal, and the template in Export Template section has API Version 2021-04-01-preview (see the image below) -

image

However if I query the exact resource using Azure Resource Manager i.e. client.GenericResources.GetById(resourceId);, it has API Version 2021-06-01-preview. This is inconsistent in my opinion.

image

Does GetById(resourceId) always returns latest and greatest ApiVersion? If yes, is there any way to know which API Version the resource was created with?

weidongxu-microsoft commented 3 years ago

@r4hulp This is the reason I was suggesting to provide the apiVersion to GetById in the first place (or provide it to Update later).

Without user providing the api-verison, SDK would had to go find one. Generally it has only one choice: take the latest version, which is "2021-06-01-preview" for vault. (Some later version of API would have another option to take a default version, which is "2019-09-01" for vault).

If you are using the GenericResource API, generally it is up to you to provide the api-version to SDK.

If you know it is vault, you can go with Vault API, which do know the api-version.

r4hulp commented 3 years ago

@r4hulp This is the reason I was suggesting to provide the apiVersion to GetById in the first place (or provide it to Update later).

Without user providing the api-verison, SDK would had to go find one. Generally it has only one choice: take the latest version, which is "2021-06-01-preview" for vault. (Some later version of API would have another option to take a default version, which is "2019-09-01" for vault).

If you are using the GenericResource API, generally it is up to you to provide the api-version to SDK.

If you know it is vault, you can go with Vault API, which do know the api-version.

That's a problem, we don't know if it is a vault, we loop through all the available resources in the resource group and apply one custom tag to them dynamically. It is hard to identify and pass in the api-version for each and every resource. If there was a way to get the apiVersion used while provisioning the resource, we could use that value itself to update to avoid such breaking scenarios. I can't find a way to get apiVersion used to create the resource in GenericResource API.

What would you suggest in this case?

weidongxu-microsoft commented 3 years ago

@r4hulp When the new SDK gets out, you should be able to do the tagging on the dedicated APIs. https://docs.microsoft.com/en-us/rest/api/resources/tags

The current SDK is pretty old and does not include the tagging API.

weidongxu-microsoft commented 3 years ago

If you still need to stick with current SDK for some time, you can try this (which do a PATCH):

            var ret = azure.GenericResources.Manager.Inner.Resources.UpdateByIdAsync(resource.Id, resource.ApiVersion, new GenericResourceInner()
            {
                Tags = new Dictionary<String, String> {
                    { "a", "b" }
                }
            }).Result;
r4hulp commented 3 years ago

If you still need to stick with the current SDK for some time, you can try this (which do a PATCH):

            var ret = azure.GenericResources.Manager.Inner.Resources.UpdateByIdAsync(resource.Id, resource.ApiVersion, new GenericResourceInner()
            {
                Tags = new Dictionary<String, String> {
                    { "a", "b" }
                }
            }).Result;

The patch method also expects the PublicNetworkAccess property (which is weird in my opinion).

{"error":{"code":"BadRequest","message":"The 'PublicNetworkAccess' property can not be empty. Please specify an authorized value."}}

ghost commented 3 years ago

Thanks for the feedback! We are routing this to the appropriate team for follow-up. cc @RandalliLama, @schaabs, @jlichwa.

Issue Details
**Description** When you get a key vault resource (using `client.GenericResources.GetById(resourceId);`) and try to update it, it throws the following error. `The 'PublicNetworkAccess' property can not be empty. Please specify an authorized value.` After fiddling around in network traces, I managed to figure out the exact reason why is it failing. The culprit is the new `api-version=2021-06-01-preview`. The new API version requires the property `publicNetworkAccess` if you want to update the resource. However, while creating the resource using Azure Portal does not set this property at all. **Steps to reproduce** #### With Azure Resource Manager Fluent API - 1. Create a new Key Vault resource in Azure Portal. 1. Get the Key Vault Resource `IGenericResource resource = client.GenericResources.GetById(resourceId);` - Notice the API Version (`resource.ApiVersion`) being returned by this method, it is set to **`2021-06-01-preview`**. Also, notice the properties being retrieved. The property `publicNetworkAccess` is missing. ![image](https://user-images.githubusercontent.com/292704/129724313-70bdee2b-e4ce-4952-9594-7861e3aa6ed6.png) 2. Now update the Key Vault (e.g. in my case, I updated with a set of custom tags). ``` var result = await resource.Update().WithApiVersion(resource.ApiVersion).WithProperties(resource.Properties).WithTags(resourceNewTags).ApplyAsync(); ``` 3. This will throw an exception - `The 'PublicNetworkAccess' property can not be empty. Please specify an authorized value.` ***Exception or Stack Trace*** ``` at Microsoft.Azure.Management.ResourceManager.Fluent.ResourcesOperations. d__22.MoveNext() at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult() at Microsoft.Azure.Management.ResourceManager.Fluent.ResourcesOperations. d__11.MoveNext() at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult() at Microsoft.Azure.Management.ResourceManager.Fluent.ResourcesOperationsExtensions. d__6.MoveNext() at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() at Microsoft.Azure.Management.ResourceManager.Fluent.GenericResourceImpl.d__18.MoveNext() at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() at Microsoft.Azure.Management.ResourceManager.Fluent.Core.ResourceActions.Creatable`4.-CreateResourceAsync>d__15.MoveNext() at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() at Microsoft.Azure.Management.ResourceManager.Fluent.Core.DAG.CreatorTaskItem`1.d__6.MoveNext() at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter.GetResult() at Microsoft.Azure.Management.ResourceManager.Fluent.Core.DAG.TaskGroupBase`1. d__14.MoveNext() at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() at Microsoft.Azure.Management.ResourceManager.Fluent.Core.ResourceActions.CreatableUpdatable`5.d__3.MoveNext() at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult() at SensitiveInformation.ClassName.d__6.MoveNext() in C:\hidden_sensitive_information\class_name.cs:line 204 at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() at SensitiveInformation.ClassName.d__14.MoveNext() in C:\hidden_sensitive_information\class_name.cs:line 201 ``` ***Code Snippet*** ``` await resource.Update() .WithApiVersion(resource.ApiVersion) .WithProperties(resource.Properties) .WithTags(resourceNewTags).ApplyAsync(); ``` **Expected behavior** The method `IGenericResource resource = client.GenericResources.GetById(resourceId);` should return property `publicNetworkAccess` of an existing resource. Or make it an optional field (as the provisioning of key vault resource from the portal does not require that field at all) **Setup (please complete the following information):** Library - **Microsoft.Azure.Management.Fluent** v 1.37.1 Rest API - **api-version=2021-04-01-preview** **Information Checklist** - [x] Bug Description Added - [x] Repro Steps Added - [x] Setup information Added
Author: r4hulp
Assignees: -
Labels: `KeyVault`, `Service Attention`, `Mgmt`
Milestone: -
weidongxu-microsoft commented 3 years ago

@RandalliLama, @schaabs, @jlichwa Please help check on keyvault service. A PATCH to key vault which only update tags should not cause this kind of 400 BadRequest. Even ARM would do this to update resource tag.

Request: PATCH https://management.azure.com/subscriptions/###/resourceGroups/rg-weidxu1/providers/Microsoft.KeyVault/vaults/kvweidxu112321?api-version=2021-06-01-preview
  body: {
  "tags": {
    "a": "b"
  }
}

Response:
{
  "error": {
    "code": "BadRequest",
    "message": "The 'PublicNetworkAccess' property can not be empty. Please specify an authorized value."
  }
}
weidongxu-microsoft commented 3 years ago

I am making (a possible last big update) on SDK to have it support tagging API. https://github.com/Azure/azure-libraries-for-net/pull/1261

Though next release date is not decided yet.

            var ret = azure.GenericResources.Manager.Inner.Tags.UpdateAtScopeAsync(r.Id, new TagsPatchResource()
            {
                Operation = TagsPatchOperation.Replace,
                Properties = new TagsInner()
                {
                    TagsProperty = new Dictionary<string, string>()
                    {
                        { "tag", "value" }
                    }
                }
            }).Result;
r4hulp commented 3 years ago

Thanks. For the time being, we have written a fallback code to connect to Tags API instead of using SDK. Will be awaiting the release

weidongxu-microsoft commented 3 years ago

1.38.0 released