Skip to content

Commit 494c79a

Browse files
authored
[Az.KeyVault] Included policy while importing Certificate to a KeyVault (#21472)
* Half way upload. * Second time commit-halp way * sync 4/2 * Done transfer to track2 * sync 4/5 * Complete import cert with policy * complete all cases for policy * Update ChangeLog * Remove unnecessary lines * Resolve comments * Update pfx file name * Update according to comments * Remove unnecessary dependecies * Modify the actions number * Update the contentType validation * solve paramaterset ambigious * Update ChangeLog.md * Merge the exceptions, update help file * Merge the exceptions, update help file * Resolve the comments 4/27 * Update descriptions of policyobject and policypath
1 parent 50e2bfe commit 494c79a

12 files changed

+663
-32
lines changed
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
BeforeAll {
2+
$vaultName = 'nori-kv765'
3+
. "..\Scripts\Common.ps1"
4+
}
5+
6+
Describe "Import Certificate with policy" {
7+
It "ImportCertificateFromFileWithPolicyParameterSet" {
8+
$certName = Get-CertificateName
9+
$certFilePath = "..\Resources\importCertWithPolicy.pfx"
10+
$policy = New-AzKeyVaultCertificatePolicy -SecretContentType "application/x-pkcs12" -SubjectName "CN=contoso.com" -IssuerName "Self" -ValidityInMonths 6 -ReuseKeyOnRenewal
11+
12+
$cert = Import-AzKeyVaultCertificate -VaultName $vaultName -Name $certName -FilePath $certFilePath -PolicyObject $policy
13+
$cert.Policy.SecretContentType | Should -Be "application/x-pkcs12"
14+
}
15+
It "ImportCertificateFromFileWithPolicyFileParameterSet" {
16+
$certName = Get-CertificateName
17+
$certFilePath = "..\Resources\importCertWithPolicy.pfx"
18+
$policyPath = "..\Resources\certPolicy.json"
19+
20+
$cert = Import-AzKeyVaultCertificate -VaultName $vaultName -Name $certName -FilePath $certFilePath -PolicyPath $policyPath
21+
$cert.Policy.SecretContentType | Should -Be "application/x-pkcs12"
22+
}
23+
It "ImportWithPrivateKeyFromStringWithPolicyFileParameterSet" {
24+
$certName = Get-CertificateName
25+
$certFilePath = "..\Resources\importCertWithPolicy.pfx"
26+
$policyPath = "..\Resources\certPolicy.json"
27+
$Base64StringCertificate = [System.Convert]::ToBase64String([System.IO.File]::ReadAllBytes($certFilePath))
28+
29+
$cert = Import-AzKeyVaultCertificate -VaultName $vaultName -Name $certName -CertificateString $Base64StringCertificate -PolicyPath $policyPath
30+
$cert.Policy.SecretContentType | Should -Be "application/x-pkcs12"
31+
}
32+
It "ImportWithPrivateKeyFromCollectionWithPolicyFileParameterSet" {
33+
$certName = Get-CertificateName
34+
$certFilePath = "..\Resources\importCertWithPolicy.pfx"
35+
$policyPath = "..\Resources\certPolicy.json"
36+
$certCollection = [System.Security.Cryptography.X509Certificates.X509Certificate2Collection]::new()
37+
$certCollection.Import($certFilePath, $null, [System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::Exportable)
38+
39+
$cert = Import-AzKeyVaultCertificate -VaultName $vaultName -Name $certName -CertificateCollection $certCollection -PolicyPath $policyPath
40+
$cert.Policy.SecretContentType | Should -Be "application/x-pkcs12"
41+
}
42+
}
43+
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
{
2+
"id": "https://myvault.vault.azure.net/certificates/updateCert01/policy",
3+
"key_props": {
4+
"exportable": true,
5+
"kty": "RSA",
6+
"key_size": 2048,
7+
"reuse_key": false
8+
},
9+
10+
"secret_props": {
11+
"contentType": "application/x-pkcs12"
12+
},
13+
14+
"x509_props": {
15+
"subject": "CN=KeyVaultTest",
16+
"ekus": [],
17+
"key_usage": [],
18+
"validity_months": 297
19+
},
20+
21+
"lifetime_actions": [
22+
{
23+
"trigger": {
24+
"lifetime_percentage": 80
25+
},
26+
"action": {
27+
"action_type": "EmailContacts"
28+
}
29+
}
30+
],
31+
32+
"issuer": {
33+
"name": "Unknown"
34+
},
35+
"attributes": {
36+
"enabled": true,
37+
"created": 1482188947,
38+
"updated": 1482188947
39+
}
40+
}
Binary file not shown.

src/KeyVault/KeyVault/ChangeLog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
- Additional information about change #1
1919
-->
2020
## Upcoming Release
21+
* Added parameter `PolicyPath` and `PolicyObject` in `Import-AzKeyVaultCertificate` to support custom policy [#20780]
2122

2223
## Version 4.9.3
2324
* Added breaking changes for `Invoke-AzKeyVaultKeyOperation`. The encoded/decoded way between string and bytes in `Invoke-AzKeyVaultKeyOperation` will change to UTF8.

src/KeyVault/KeyVault/Commands/Certificate/ImportAzureKeyVaultCertificate.cs

Lines changed: 49 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,21 @@ public class ImportAzureKeyVaultCertificate : KeyVaultCmdletBase
108108
HelpMessage = "Specifies the password for the certificate and private key base64 encoded string to import.")]
109109
public SecureString Password { get; set; }
110110

111+
/// <summary>
112+
/// File Path
113+
/// </summary>
114+
[Parameter(Mandatory = false,
115+
HelpMessage = "A file path to specify management policy for the certificate that contains JSON encoded policy definition. Mutual-exclusive to PolicyObject.")]
116+
public string PolicyPath { get; set; }
117+
118+
/// <summary>
119+
/// File Path
120+
/// </summary>
121+
[Parameter(Mandatory = false,
122+
ValueFromPipeline = true,
123+
HelpMessage = "An in-memory object to specify management policy for the certificate. Mutual-exclusive to PolicyPath.")]
124+
public PSKeyVaultCertificatePolicy PolicyObject { get; set; }
125+
111126
/// <summary>
112127
/// Certificate Collection
113128
/// </summary>
@@ -131,6 +146,7 @@ public class ImportAzureKeyVaultCertificate : KeyVaultCmdletBase
131146
protected override void BeginProcessing()
132147
{
133148
FilePath = this.TryResolvePath(FilePath);
149+
PolicyPath = this.TryResolvePath(PolicyPath);
134150
base.BeginProcessing();
135151
}
136152

@@ -143,6 +159,34 @@ private void ValidateParameters()
143159
{
144160
throw new AzPSArgumentException(string.Format(Resources.FileNotFound, this.FilePath), nameof(FilePath));
145161
}
162+
if (IsPemFile(FilePath))
163+
{
164+
ContentType = Constants.PemContentType;
165+
}
166+
else
167+
{
168+
ContentType = Constants.Pkcs12ContentType;
169+
}
170+
}
171+
if (this.IsParameterBound(c => c.CertificateCollection))
172+
{
173+
ContentType = Constants.Pkcs12ContentType;
174+
}
175+
if (this.IsParameterBound(c => c.PolicyPath) && this.IsParameterBound(c => c.PolicyObject))
176+
{
177+
throw new AzPSArgumentException($"Parameter {nameof(PolicyPath)} conflicts with Parameter {nameof(PolicyObject)}. Only one of these 2 parameters could be imported at once.", nameof(PolicyPath));
178+
}
179+
if (this.IsParameterBound(c => c.PolicyPath))
180+
{
181+
if (!File.Exists(PolicyPath))
182+
{
183+
throw new AzPSArgumentException(string.Format(Resources.FileNotFound, this.PolicyPath), nameof(PolicyPath));
184+
}
185+
PolicyObject = PSKeyVaultCertificatePolicy.FromJsonFile(PolicyPath);
186+
}
187+
if (PolicyObject != null && PolicyObject.SecretContentType != ContentType)
188+
{
189+
throw new AzPSArgumentException($"User input {ContentType} conflicts with the ContentType stated as {PolicyObject.SecretContentType} in Certificate Policy.", ContentType);
146190
}
147191
}
148192

@@ -162,7 +206,7 @@ public override void ExecuteCmdlet()
162206
if (IsPemFile(FilePath))
163207
{
164208
byte[] pemBytes = File.ReadAllBytes(FilePath);
165-
certBundle = this.Track2DataClient.ImportCertificate(VaultName, Name, pemBytes, Password, Tag?.ConvertToDictionary(), Constants.PemContentType);
209+
certBundle = this.Track2DataClient.ImportCertificate(VaultName, Name, pemBytes, Password, Tag?.ConvertToDictionary(), Constants.PemContentType, certPolicy: PolicyObject);
166210
}
167211
else
168212
{
@@ -179,8 +223,9 @@ public override void ExecuteCmdlet()
179223

180224
if (doImport)
181225
{
226+
182227
byte[] base64Bytes = userProvidedCertColl.Export(X509ContentType.Pfx, Password?.ConvertToString());
183-
certBundle = this.Track2DataClient.ImportCertificate(VaultName, Name, base64Bytes, Password, Tag?.ConvertToDictionary());
228+
certBundle = this.Track2DataClient.ImportCertificate(VaultName, Name, base64Bytes, Password, Tag?.ConvertToDictionary(), certPolicy: PolicyObject);
184229
}
185230
else
186231
{
@@ -194,12 +239,11 @@ public override void ExecuteCmdlet()
194239
break;
195240

196241
case ImportWithPrivateKeyFromCollectionParameterSet:
197-
certBundle = this.DataServiceClient.ImportCertificate(VaultName, Name, CertificateCollection, Tag?.ConvertToDictionary());
198-
242+
certBundle = this.Track2DataClient.ImportCertificate(VaultName, Name, CertificateCollection, null, Tag?.ConvertToDictionary(), certPolicy: PolicyObject);
199243
break;
200244

201245
case ImportWithPrivateKeyFromStringParameterSet:
202-
certBundle = this.Track2DataClient.ImportCertificate(VaultName, Name, CertificateString, Password, Tag?.ConvertToDictionary(), ContentType);
246+
certBundle = this.Track2DataClient.ImportCertificate(VaultName, Name, CertificateString, Password, Tag?.ConvertToDictionary(), ContentType, certPolicy: PolicyObject);
203247

204248
break;
205249
}

src/KeyVault/KeyVault/Models/IKeyVaultDataServiceClient.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -164,11 +164,11 @@ public interface IKeyVaultDataServiceClient
164164

165165
PSKeyVaultCertificate MergeCertificate(string vaultName, string certName, byte[] certBytes, Dictionary<string, string> tags);
166166

167-
PSKeyVaultCertificate ImportCertificate(string vaultName, string certName, byte[] certificate, SecureString certPassword, IDictionary<string, string> tags, string contentType = Constants.Pkcs12ContentType);
167+
PSKeyVaultCertificate ImportCertificate(string vaultName, string certName, byte[] certificate, SecureString certPassword, IDictionary<string, string> tags, string contentType = Constants.Pkcs12ContentType, PSKeyVaultCertificatePolicy certPolicy = null);
168168

169-
PSKeyVaultCertificate ImportCertificate(string vaultName, string certName, string base64CertString, SecureString certPassword, IDictionary<string, string> tags, string contentType = Constants.Pkcs12ContentType);
169+
PSKeyVaultCertificate ImportCertificate(string vaultName, string certName, string base64CertString, SecureString certPassword, IDictionary<string, string> tags, string contentType = Constants.Pkcs12ContentType, PSKeyVaultCertificatePolicy certPolicy = null);
170170

171-
PSKeyVaultCertificate ImportCertificate(string vaultName, string certName, X509Certificate2Collection certificateCollection, IDictionary<string, string> tags, string contentType = Constants.Pkcs12ContentType);
171+
PSKeyVaultCertificate ImportCertificate(string vaultName, string certName, X509Certificate2Collection certificateCollection, SecureString certPassword, IDictionary<string, string> tags, string contentType = Constants.Pkcs12ContentType, PSKeyVaultCertificatePolicy certPolicy = null);
172172

173173
PSDeletedKeyVaultCertificate DeleteCertificate(string vaultName, string certName);
174174

src/KeyVault/KeyVault/Models/KeyVaultDataServiceClient.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -817,12 +817,12 @@ public PSKeyVaultCertificate MergeCertificate(string vaultName, string certName,
817817

818818
}
819819

820-
public PSKeyVaultCertificate ImportCertificate(string vaultName, string certName, byte[] certificate, SecureString certPassword, IDictionary<string, string> tags, string contentType = Constants.Pkcs12ContentType)
820+
public PSKeyVaultCertificate ImportCertificate(string vaultName, string certName, byte[] certificate, SecureString certPassword, IDictionary<string, string> tags, string contentType = Constants.Pkcs12ContentType, PSKeyVaultCertificatePolicy certPolicyPath = null)
821821
{
822822
return ImportCertificate(vaultName, certName, Convert.ToBase64String(certificate), certPassword, tags, contentType);
823823
}
824824

825-
public PSKeyVaultCertificate ImportCertificate(string vaultName, string certName, string base64CertColl, SecureString certPassword, IDictionary<string, string> tags, string contentType = Constants.Pkcs12ContentType)
825+
public PSKeyVaultCertificate ImportCertificate(string vaultName, string certName, string base64CertColl, SecureString certPassword, IDictionary<string, string> tags, string contentType = Constants.Pkcs12ContentType, PSKeyVaultCertificatePolicy certPolicyPath = null)
826826
{
827827
if (string.IsNullOrEmpty(vaultName))
828828
throw new ArgumentNullException(nameof(vaultName));
@@ -855,7 +855,7 @@ public PSKeyVaultCertificate ImportCertificate(string vaultName, string certName
855855
return new PSKeyVaultCertificate(certBundle);
856856
}
857857

858-
public PSKeyVaultCertificate ImportCertificate(string vaultName, string certName, X509Certificate2Collection certificateCollection, IDictionary<string, string> tags, string contentType = Constants.Pkcs12ContentType)
858+
public PSKeyVaultCertificate ImportCertificate(string vaultName, string certName, X509Certificate2Collection certificateCollection, SecureString certPassword, IDictionary<string, string> tags, string contentType = Constants.Pkcs12ContentType, PSKeyVaultCertificatePolicy certPolicy = null)
859859
{
860860
if (string.IsNullOrEmpty(vaultName))
861861
throw new ArgumentNullException(nameof(vaultName));

src/KeyVault/KeyVault/Models/PSKeyVaultCertificate.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ public class PSKeyVaultCertificate : PSKeyVaultCertificateIdentityItem
3030
public string SecretId { get; internal set; }
3131
public string Thumbprint { get; set; }
3232

33+
public PSKeyVaultCertificatePolicy Policy { get; set; }
3334
public string RecoveryLevel { get; private set; }
3435

3536
internal PSKeyVaultCertificate(CertificateBundle certificateBundle, VaultUriHelper vaultUriHelper)
@@ -156,6 +157,7 @@ internal PSKeyVaultCertificate(KeyVaultCertificateWithPolicy keyVaultCertificate
156157

157158
KeyId = keyVaultCertificate.KeyId?.ToString();
158159
SecretId = keyVaultCertificate.SecretId?.ToString();
160+
Policy = PSKeyVaultCertificatePolicy.FromTrack2CertificatePolicy(keyVaultCertificate.Policy);
159161

160162
if (keyVaultCertificate.Properties != null)
161163
{

0 commit comments

Comments
 (0)