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

[Key Vault] Add Secret URI Parameter to Key Vault Secret Cmdlets #26222

Merged
merged 13 commits into from
Nov 11, 2024
65 changes: 65 additions & 0 deletions src/KeyVault/KeyVault.Test/PesterTests/KeyVaultSecretUri.Tests.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
BeforeAll {
. "$PSScriptRoot\..\Scripts\Common.ps1" # Common setup script

# Load the Az.KeyVault module from the debug artifacts
$psd1Path = Join-Path $PSScriptRoot "../../../../artifacts/Debug/" -Resolve
$keyVaultPsd1 = Join-Path $psd1Path "./Az.KeyVault/Az.KeyVault.psd1" -Resolve
Import-Module $keyVaultPsd1 -Force

# Define key variables
$resourceGroupName = "yash-rg$(Get-Random)" # Use existing resource group
$location = "eastus"
$vaultName = "yashkv$(Get-Random)" # Generate unique Key Vault name
$secretName = "TestSecret"
$secretValue = ConvertTo-SecureString "InitialSecretValue" -AsPlainText -Force

# Set up resource group
New-AzResourceGroup -Name $resourceGroupName -Location $location

# Create a Key Vault in the existing resource group
New-AzKeyVault -ResourceGroupName $resourceGroupName -VaultName $vaultName -Location $location

# Create a new secret in the Key Vault
Set-AzKeyVaultSecret -VaultName $vaultName -Name $secretName -SecretValue $secretValue
}


Describe 'Azure KeyVault Secret URI Live Tests' {

It 'should retrieve the secret using the Secret URI with Get-AzKeyVaultSecret' {
# Construct the secret URI
$secretUri = "https://$vaultName.vault.azure.net/secrets/$secretName"

# Retrieve the secret using its URI
$retrievedSecret = Get-AzKeyVaultSecret -Id $secretUri -AsPlainText

# Validate that the secret is retrieved successfully
$retrievedSecret | Should -Be "InitialSecretValue"
}

It 'should update the secret value using Set-AzKeyVaultSecret' {
# Update the secret value
$newSecretValue = ConvertTo-SecureString "UpdatedSecretValue" -AsPlainText -Force
Set-AzKeyVaultSecret -VaultName $vaultName -Name $secretName -SecretValue $newSecretValue

# Retrieve the updated secret
$retrievedSecret = Get-AzKeyVaultSecret -VaultName $vaultName -Name $secretName -AsPlainText

# Validate the secret has been updated
$retrievedSecret | Should -Be "UpdatedSecretValue"
}

It 'should remove the secret using Remove-AzKeyVaultSecret' {
# Remove the secret
Remove-AzKeyVaultSecret -VaultName $vaultName -Name $secretName -Force

# Ensure the secret is deleted
Get-AzKeyVaultSecret -VaultName $vaultName -Name $secretName | Should -BeNullOrEmpty
}
}

AfterAll {
# Clean up Key Vault & Resource Group)
Remove-AzKeyVault -VaultName $vaultName -ResourceGroupName $resourceGroupName -Force
Remove-AzResourceGroup -Name $resourceGroupName -Force
}
2 changes: 2 additions & 0 deletions src/KeyVault/KeyVault/ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
- Additional information about change #1
-->
## Upcoming Release
* Added Secret URI Parameter to Key Vault Secret Cmdlets [#23053]
* Upgraded Azure.Core to 1.44.1.
notyashhh marked this conversation as resolved.
Show resolved Hide resolved

## Version 6.2.0
* Fixed a parameter validation issue in Set-AzureKeyVaultCertificatePolicy. [#25649]
Expand Down
22 changes: 22 additions & 0 deletions src/KeyVault/KeyVault/Commands/Secret/BackupAzureKeyVaultSecret.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
using System.Management.Automation;
using Microsoft.Azure.Commands.Common.Authentication;
using Microsoft.Azure.Commands.KeyVault.Models;
using Microsoft.Azure.Commands.KeyVault.Models.Secret;
using Microsoft.Azure.Commands.KeyVault.Properties;
using Microsoft.Azure.Commands.ResourceManager.Common.ArgumentCompleters;

Expand All @@ -35,6 +36,7 @@ public class BackupAzureKeyVaultSecret : KeyVaultCmdletBase

private const string BySecretNameParameterSet = "BySecretName";
private const string BySecretObjectParameterSet = "BySecret";
private const string BySecretUriParameterSet = "BySecretUri";

#endregion

Expand Down Expand Up @@ -62,6 +64,17 @@ public class BackupAzureKeyVaultSecret : KeyVaultCmdletBase
[Alias( Constants.SecretName )]
public string Name { get; set; }

/// <summary>
/// KeyVault Secret ID (uri of the secret)
/// </summary>
[Parameter(Mandatory = true,
Position = 0,
ParameterSetName = BySecretUriParameterSet,
HelpMessage = "The URI of the KeyVault Secret.")]
[Alias("SecretId")]
[ValidateNotNullOrEmpty]
public string Id { get; set; }

/// <summary>
/// The secret object to be backed up.
/// </summary>
Expand Down Expand Up @@ -105,6 +118,15 @@ public override void ExecuteCmdlet( )
VaultName = InputObject.VaultName;
}

if (ParameterSetName == BySecretUriParameterSet)
{
var secretUri = new Uri(Id);
SecretUriComponents splitUri = this.SplitSecretUri(secretUri);

VaultName = splitUri.VaultName;
Name = splitUri.SecretName;
}

if ( ShouldProcess( Name, Properties.Resources.BackupSecret ) )
{
if ( string.IsNullOrEmpty( OutputFile ) )
Expand Down
71 changes: 52 additions & 19 deletions src/KeyVault/KeyVault/Commands/Secret/GetAzureKeyVaultSecret.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@
// ----------------------------------------------------------------------------------

using Microsoft.Azure.Commands.KeyVault.Models;
using Microsoft.Azure.Commands.KeyVault.Models.Secret;
using Microsoft.Azure.Commands.ResourceManager.Common.ArgumentCompleters;
using Microsoft.Azure.Management.Internal.Resources.Utilities.Models;
using System;
using System.Management.Automation;
using System.Runtime.InteropServices;
using System.Security;
Expand All @@ -30,14 +32,15 @@ public class GetAzureKeyVaultSecret : KeyVaultCmdletBase
private const string ByVaultNameParameterSet = "ByVaultName";
private const string BySecretNameParameterSet = "BySecretName";
private const string BySecretVersionsParameterSet = "BySecretVersions";
private const string BySecretUriParameterSet = "BySecretUri";

private const string InputObjectByVaultNameParameterSet = "ByInputObjectVaultName";
private const string InputObjectBySecretNameParameterSet = "ByInputObjectSecretName";
private const string InputObjectBySecretVersionsParameterSet = "ByInputObjectSecretVersions";

private const string ResourceIdByVaultNameParameterSet = "ByResourceIdVaultName";
private const string ResourceIdBySecretNameParameterSet = "ByResourceIdSecretName";
private const string ResourceIdBySecretVersionsParameterSet = "ByResourceIdSecretVersions";
private const string ParentResourceIdByVaultNameParameterSet = "ByParentResourceIdVaultName";
private const string ParentResourceIdBySecretNameParameterSet = "ByParentResourceIdSecretName";
private const string ParentResourceIdBySecretVersionsParameterSet = "ByParentResourceIdSecretVersions";

#endregion

Expand Down Expand Up @@ -84,25 +87,38 @@ public class GetAzureKeyVaultSecret : KeyVaultCmdletBase
public PSKeyVault InputObject { get; set; }

/// <summary>
/// KeyVault Resource ID
/// KeyVault Secret ID
/// </summary>
[Parameter(Mandatory = true,
Position = 0,
ParameterSetName = BySecretUriParameterSet,
HelpMessage = "The URI of the KeyVault Secret.")]
[Alias("SecretId")]
[ValidateNotNullOrEmpty]
public string Id { get; set; }


/// <summary>
/// KeyVault Parent Resource ID
/// </summary>
[Parameter(Mandatory = true,
Position = 0,
ValueFromPipelineByPropertyName = true,
ParameterSetName = ResourceIdByVaultNameParameterSet,
ParameterSetName = ParentResourceIdByVaultNameParameterSet,
HelpMessage = "KeyVault Resource Id.")]
[Parameter(Mandatory = true,
Position = 0,
ValueFromPipelineByPropertyName = true,
ParameterSetName = ResourceIdBySecretNameParameterSet,
ParameterSetName = ParentResourceIdBySecretNameParameterSet,
HelpMessage = "KeyVault Resource Id.")]
[Parameter(Mandatory = true,
Position = 0,
ValueFromPipelineByPropertyName = true,
ParameterSetName = ResourceIdBySecretVersionsParameterSet,
ParameterSetName = ParentResourceIdBySecretVersionsParameterSet,
HelpMessage = "KeyVault Resource Id.")]
[Alias("ResourceId")]
[ValidateNotNullOrEmpty]
public string ResourceId { get; set; }
public string ParentResourceId { get; set; }

/// <summary>
/// Secret name
Expand All @@ -117,7 +133,7 @@ public class GetAzureKeyVaultSecret : KeyVaultCmdletBase
HelpMessage = "Secret name. Cmdlet constructs the FQDN of a secret from vault name, currently selected environment and secret name.")]
[Parameter(Mandatory = false,
Position = 1,
ParameterSetName = ResourceIdByVaultNameParameterSet,
ParameterSetName = ParentResourceIdByVaultNameParameterSet,
HelpMessage = "Secret name. Cmdlet constructs the FQDN of a secret from vault name, currently selected environment and secret name.")]
[Parameter(Mandatory = true,
Position = 1,
Expand All @@ -129,7 +145,7 @@ public class GetAzureKeyVaultSecret : KeyVaultCmdletBase
HelpMessage = "Secret name. Cmdlet constructs the FQDN of a secret from vault name, currently selected environment and secret name.")]
[Parameter(Mandatory = true,
Position = 1,
ParameterSetName = ResourceIdBySecretNameParameterSet,
ParameterSetName = ParentResourceIdBySecretNameParameterSet,
HelpMessage = "Secret name. Cmdlet constructs the FQDN of a secret from vault name, currently selected environment and secret name.")]
[Parameter(Mandatory = true,
Position = 1,
Expand All @@ -141,7 +157,7 @@ public class GetAzureKeyVaultSecret : KeyVaultCmdletBase
HelpMessage = "Secret name. Cmdlet constructs the FQDN of a secret from vault name, currently selected environment and secret name.")]
[Parameter(Mandatory = true,
Position = 1,
ParameterSetName = ResourceIdBySecretVersionsParameterSet,
ParameterSetName = ParentResourceIdBySecretVersionsParameterSet,
HelpMessage = "Secret name. Cmdlet constructs the FQDN of a secret from vault name, currently selected environment and secret name.")]
[ValidateNotNullOrEmpty]
[Alias(Constants.SecretName)]
Expand All @@ -160,7 +176,7 @@ public class GetAzureKeyVaultSecret : KeyVaultCmdletBase
Position = 2,
HelpMessage = "Secret version. Cmdlet constructs the FQDN of a secret from vault name, currently selected environment, secret name and secret version.")]
[Parameter(Mandatory = true,
ParameterSetName = ResourceIdBySecretNameParameterSet,
ParameterSetName = ParentResourceIdBySecretNameParameterSet,
Position = 2,
HelpMessage = "Secret version. Cmdlet constructs the FQDN of a secret from vault name, currently selected environment, secret name and secret version.")]
[Alias("SecretVersion")]
Expand All @@ -173,7 +189,7 @@ public class GetAzureKeyVaultSecret : KeyVaultCmdletBase
ParameterSetName = InputObjectBySecretVersionsParameterSet,
HelpMessage = "Specifies whether to include the versions of the secret in the output.")]
[Parameter(Mandatory = true,
ParameterSetName = ResourceIdBySecretVersionsParameterSet,
ParameterSetName = ParentResourceIdBySecretVersionsParameterSet,
HelpMessage = "Specifies whether to include the versions of the secret in the output.")]
public SwitchParameter IncludeVersions { get; set; }

Expand All @@ -184,33 +200,50 @@ public class GetAzureKeyVaultSecret : KeyVaultCmdletBase
ParameterSetName = InputObjectByVaultNameParameterSet,
HelpMessage = "Specifies whether to show the previously deleted secrets in the output.")]
[Parameter(Mandatory = false,
ParameterSetName = ResourceIdByVaultNameParameterSet,
ParameterSetName = ParentResourceIdByVaultNameParameterSet,
HelpMessage = "Specifies whether to show the previously deleted secrets in the output.")]
[Parameter(Mandatory = false,
ParameterSetName = BySecretUriParameterSet,
HelpMessage = "Specifies whether to show the previously deleted secrets in the output.")]
public SwitchParameter InRemovedState { get; set; }

[Parameter(Mandatory = false, ParameterSetName = BySecretNameParameterSet, HelpMessage = "When set, the cmdlet will convert secret in secure string to the decrypted plaintext string as output.")]
[Parameter(Mandatory = false, ParameterSetName = ByVaultNameParameterSet)]
[Parameter(Mandatory = false, ParameterSetName = BySecretUriParameterSet)]
[Parameter(Mandatory = false, ParameterSetName = InputObjectBySecretNameParameterSet)]
[Parameter(Mandatory = false, ParameterSetName = InputObjectByVaultNameParameterSet)]
[Parameter(Mandatory = false, ParameterSetName = ResourceIdBySecretNameParameterSet)]
[Parameter(Mandatory = false, ParameterSetName = ResourceIdByVaultNameParameterSet)]
[Parameter(Mandatory = false, ParameterSetName = ParentResourceIdBySecretNameParameterSet)]
[Parameter(Mandatory = false, ParameterSetName = ParentResourceIdByVaultNameParameterSet)]
public SwitchParameter AsPlainText { get; set; }
#endregion

public override void ExecuteCmdlet()
{
PSKeyVaultSecret secret;

// Check input object
if (InputObject != null)
{
VaultName = InputObject.VaultName.ToString();
}
else if (!string.IsNullOrEmpty(ResourceId))
else if (!string.IsNullOrEmpty(ParentResourceId))
{
var parsedParentResourceId = new ResourceIdentifier(ParentResourceId);
VaultName = parsedParentResourceId.ResourceName;
}

// Handle SecretId (uri) parameter
if (ParameterSetName == BySecretUriParameterSet)
{
var parsedResourceId = new ResourceIdentifier(ResourceId);
VaultName = parsedResourceId.ResourceName;
var secretUri = new Uri(Id);
notyashhh marked this conversation as resolved.
Show resolved Hide resolved
SecretUriComponents splitUri = this.SplitSecretUri(secretUri);

VaultName = splitUri.VaultName;
Name = splitUri.SecretName;
Version = splitUri.SecretVersion;
}

// Check Version/s of Sceret to get.
if (!string.IsNullOrEmpty(Version))
{
secret = DataServiceClient.GetSecret(VaultName, Name, Version);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
// ----------------------------------------------------------------------------------

using Microsoft.Azure.Commands.KeyVault.Models;
using Microsoft.Azure.Commands.KeyVault.Models.Secret;
using Microsoft.Azure.Commands.KeyVault.Properties;
using Microsoft.Azure.Commands.ResourceManager.Common.ArgumentCompleters;
using Microsoft.WindowsAzure.Commands.Common.CustomAttributes;
Expand All @@ -30,6 +31,7 @@ public class RemoveAzureKeyVaultSecret : KeyVaultCmdletBase

private const string ByVaultNameParameterSet = "ByVaultName";
private const string ByInputObjectParameterSet = "ByInputObject";
private const string BySecretUriParameterSet = "BySecretUri";

#endregion

Expand Down Expand Up @@ -57,6 +59,17 @@ public class RemoveAzureKeyVaultSecret : KeyVaultCmdletBase
[Alias(Constants.SecretName)]
public string Name { get; set; }

/// <summary>
/// KeyVault Secret ID (uri of the secret)
/// </summary>
[Parameter(Mandatory = true,
Position = 0,
ParameterSetName = BySecretUriParameterSet,
HelpMessage = "The URI of the KeyVault Secret.")]
[Alias("SecretId")]
[ValidateNotNullOrEmpty]
public string Id { get; set; }

/// <summary>
/// Secret Object
/// </summary>
Expand Down Expand Up @@ -96,7 +109,16 @@ public override void ExecuteCmdlet()
Name = InputObject.Name;
}

if(InRemovedState.IsPresent)
if (ParameterSetName == BySecretUriParameterSet)
notyashhh marked this conversation as resolved.
Show resolved Hide resolved
{
var secretUri = new Uri(Id);
SecretUriComponents splitUri = this.SplitSecretUri(secretUri);

VaultName = splitUri.VaultName;
Name = splitUri.SecretName;
}

if (InRemovedState.IsPresent)
{
ConfirmAction(
Force.IsPresent,
Expand Down
Loading