Skip to content

Commit

Permalink
Update SecretManagement credential use with ACR repos (PowerShell#1498)
Browse files Browse the repository at this point in the history
  • Loading branch information
alerickson committed Apr 1, 2024
1 parent 1f1eca7 commit 8490278
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 88 deletions.
30 changes: 10 additions & 20 deletions src/code/ACRServerAPICalls.cs
Original file line number Diff line number Diff line change
Expand Up @@ -146,10 +146,8 @@ public override FindResults FindName(string packageName, bool includePrerelease,

_cmdletPassedIn.WriteVerbose("Access token retrieved.");

tenantID = Utils.GetSecretInfoFromSecretManagement(
Repository.Name,
repositoryCredentialInfo,
_cmdletPassedIn);
tenantID = repositoryCredentialInfo.SecretName;
_cmdletPassedIn.WriteVerbose($"Tenant ID: {tenantID}");
}

// Call asynchronous network methods in a try/catch block to handle exceptions.
Expand Down Expand Up @@ -284,10 +282,8 @@ public override FindResults FindVersion(string packageName, string version, Reso

_cmdletPassedIn.WriteVerbose("Access token retrieved.");

tenantID = Utils.GetSecretInfoFromSecretManagement(
Repository.Name,
repositoryCredentialInfo,
_cmdletPassedIn);
tenantID = repositoryCredentialInfo.SecretName;
_cmdletPassedIn.WriteVerbose($"Tenant ID: {tenantID}");
}

// Call asynchronous network methods in a try/catch block to handle exceptions.
Expand Down Expand Up @@ -405,10 +401,8 @@ internal static PSResourceInfo Install(

callingCmdlet.WriteVerbose("Access token retrieved.");

tenantID = Utils.GetSecretInfoFromSecretManagement(
repo.Name,
repositoryCredentialInfo,
callingCmdlet);
tenantID = repositoryCredentialInfo.SecretName;
callingCmdlet.WriteVerbose($"Tenant ID: {tenantID}");
}

// Call asynchronous network methods in a try/catch block to handle exceptions.
Expand Down Expand Up @@ -534,10 +528,8 @@ internal static List<PSResourceInfo> Find(PSRepositoryInfo repo, string pkgName,

callingCmdlet.WriteVerbose("Access token retrieved.");

tenantID = Utils.GetSecretInfoFromSecretManagement(
repo.Name,
repositoryCredentialInfo,
callingCmdlet);
tenantID = repositoryCredentialInfo.SecretName;
callingCmdlet.WriteVerbose($"Tenant ID: {tenantID}");
}

// Call asynchronous network methods in a try/catch block to handle exceptions.
Expand Down Expand Up @@ -860,10 +852,8 @@ private bool PushNupkgACR(string outputNupkgDir, string pkgName, NuGetVersion pk

_cmdletPassedIn.WriteVerbose("Access token retrieved.");

tenantID = Utils.GetSecretInfoFromSecretManagement(
repository.Name,
repositoryCredentialInfo,
_cmdletPassedIn);
tenantID = repositoryCredentialInfo.SecretName;
_cmdletPassedIn.WriteVerbose($"Tenant ID: {tenantID}");
}

// Call asynchronous network methods in a try/catch block to handle exceptions.
Expand Down
72 changes: 4 additions & 68 deletions src/code/Utils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -607,6 +607,10 @@ public static PSCredential GetRepositoryCredentialFromSecretManagement(
{
return secretCredential;
}
else if (secretObject.BaseObject is SecureString secretString)
{
return new PSCredential(repositoryCredentialInfo.SecretName, secretString);
}
}

cmdletPassedIn.ThrowTerminatingError(
Expand Down Expand Up @@ -700,74 +704,6 @@ public static string GetACRAccessTokenFromSecretManagement(
return null;
}

public static string GetSecretInfoFromSecretManagement(
string repositoryName,
PSCredentialInfo repositoryCredentialInfo,
PSCmdlet cmdletPassedIn)
{
if (!IsSecretManagementVaultAccessible(repositoryName, repositoryCredentialInfo, cmdletPassedIn))
{
cmdletPassedIn.ThrowTerminatingError(
new ErrorRecord(
new PSInvalidOperationException($"Cannot access Microsoft.PowerShell.SecretManagement vault \"{repositoryCredentialInfo.VaultName}\" for PSResourceRepository ({repositoryName}) authentication."),
"RepositoryCredentialSecretManagementInaccessibleVault",
ErrorCategory.ResourceUnavailable,
cmdletPassedIn));
return null;
}

var results = PowerShellInvoker.InvokeScriptWithHost<object>(
cmdlet: cmdletPassedIn,
script: @"
param (
[string] $VaultName,
[string] $SecretName
)
$module = Microsoft.PowerShell.Core\Import-Module -Name Microsoft.PowerShell.SecretManagement -PassThru
if ($null -eq $module) {
return
}
$secretInfo = & $module ""Get-SecretInfo"" -Name $SecretName -Vault $VaultName
$secretInfo.Metadata
",
args: new object[] { repositoryCredentialInfo.VaultName, repositoryCredentialInfo.SecretName },
out Exception terminatingError);

var secretInfoValue = (results.Count == 1) ? results[0] : null;
if (secretInfoValue == null)
{
cmdletPassedIn.ThrowTerminatingError(
new ErrorRecord(
new PSInvalidOperationException(
message: $"Microsoft.PowerShell.SecretManagement\\Get-Secret encountered an error while reading secret \"{repositoryCredentialInfo.SecretName}\" from vault \"{repositoryCredentialInfo.VaultName}\" for PSResourceRepository ({repositoryName}) authentication.",
innerException: terminatingError),
"ACRRepositoryCannotGetSecretInfoFromVault",
ErrorCategory.InvalidOperation,
cmdletPassedIn));
}

var tenantMetadata = secretInfoValue as ReadOnlyDictionary<string, System.Object>;

// "TenantID" is case sensitive so we want to loop through and do a string comparison to accommodate for this
foreach (var entry in tenantMetadata)
{
if (entry.Key.Equals("TenantId", StringComparison.OrdinalIgnoreCase))
{
return entry.Value as string;
}
}

cmdletPassedIn.ThrowTerminatingError(
new ErrorRecord(
new PSNotSupportedException($"Secret \"{repositoryCredentialInfo.SecretName}\" from vault \"{repositoryCredentialInfo.VaultName}\" has an invalid type. The only supported type is PSCredential."),
"RepositorySecretInfoIsInvalidSecretType",
ErrorCategory.InvalidType,
cmdletPassedIn));

return null;
}

public static void SaveRepositoryCredentialToSecretManagementVault(
string repositoryName,
PSCredentialInfo repositoryCredentialInfo,
Expand Down

0 comments on commit 8490278

Please sign in to comment.