Skip to content

Commit cfb7d83

Browse files
gautamdshethpeterdelegateGautam Sheth
authored
PeterRevsbech-feature/add-X509KeyStorageFlags (#4324)
* Possiblity to overwrite default X509KeyStorageFlags in Connect-PnPOnline * Refactor Connect-PnPOnline cmdlet to support X509KeyStorageFlags parameter --------- Co-authored-by: PeterRevsbech <prv@delegate.dk> Co-authored-by: Gautam Sheth <gautam.sheth@staffbase.com>
1 parent 7801b87 commit cfb7d83

File tree

3 files changed

+50
-6
lines changed

3 files changed

+50
-6
lines changed

documentation/Connect-PnPOnline.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,18 @@ Connects to the Azure AD with WAM (aka native Windows authentication prompt), ac
282282

283283
WAM is a more secure & faster way of authenticating in Windows OS. It supports Windows Hello, FIDO keys , conditional access policies and more.
284284

285+
### EXAMPLE 9
286+
```powershell
287+
$keyStorageflags = [System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::MachineKeySet -bor [System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::PersistKeySet
288+
289+
Connect-PnPOnline -Url "contoso.sharepoint.com" -ClientId 6c5c98c7-e05a-4a0f-bcfa-0cfc65aa1f28 -CertificateBase64Encoded $base64encodedstring -X509KeyStorageFlags $keyStorageflags -Tenant 'contoso.onmicrosoft.com'
290+
```
291+
292+
Connects using an Azure Active Directory registered application using a certificate with a private key that has been base64 encoded.
293+
See [Security App-only EntraId guidance](https://learn.microsoft.com/sharepoint/dev/solution-guidance/security-apponly-azuread) for a sample on how to get started.
294+
295+
See [X509 key storage flags](https://learn.microsoft.com/dotnet/api/system.security.cryptography.x509certificates.x509keystorageflags) for information on how to configure key storage when creating the certificate.
296+
285297
## PARAMETERS
286298

287299
### -AccessToken
@@ -874,6 +886,24 @@ Accept pipeline input: False
874886
Accept wildcard characters: False
875887
```
876888

889+
### -X509KeyStorageFlags
890+
891+
Defines where and how to import the private key of an X.509 certificate.
892+
893+
This enumeration supports a bitwise combination of its member values.
894+
895+
```yaml
896+
Type: System.Security.Cryptography.X509Certificates.X509KeyStorageFlags
897+
Parameter Sets: App-Only with Azure Active Directory
898+
Aliases:
899+
900+
Required: False
901+
Position: Named
902+
Default value: None
903+
Accept pipeline input: False
904+
Accept wildcard characters: False
905+
```
906+
877907
## RELATED LINKS
878908

879909
[Microsoft 365 Patterns and Practices](https://aka.ms/m365pnp)

src/Commands/Base/ConnectOnline.cs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,9 @@ public class ConnectOnline : BasePSCmdlet
189189
[Parameter(Mandatory = false, ParameterSetName = ParameterSet_APPONLYAADCERTIFICATE)]
190190
public string CertificateBase64Encoded;
191191

192+
[Parameter(Mandatory = false, ParameterSetName = ParameterSet_APPONLYAADCERTIFICATE)]
193+
public X509KeyStorageFlags X509KeyStorageFlags;
194+
192195
[Parameter(Mandatory = false, ParameterSetName = ParameterSet_APPONLYAADCERTIFICATE)]
193196
public SecureString CertificatePassword;
194197

@@ -631,10 +634,11 @@ private PnPConnection ConnectAppOnlyWithCertificate()
631634
throw new FileNotFoundException("Certificate not found");
632635
}
633636

634-
X509Certificate2 certificate = CertificateHelper.GetCertificateFromPath(this, CertificatePath, CertificatePassword);
637+
X509Certificate2 certificate = CertificateHelper.GetCertificateFromPath(this, CertificatePath, CertificatePassword, X509KeyStorageFlags);
635638
if (Connection?.ClientId == ClientId &&
636639
Connection?.Tenant == Tenant &&
637640
Connection?.Certificate?.Thumbprint == certificate.Thumbprint)
641+
638642
{
639643
ReuseAuthenticationManager();
640644
}
@@ -644,7 +648,13 @@ private PnPConnection ConnectAppOnlyWithCertificate()
644648
else if (ParameterSpecified(nameof(CertificateBase64Encoded)))
645649
{
646650
var certificateBytes = Convert.FromBase64String(CertificateBase64Encoded);
647-
var certificate = new X509Certificate2(certificateBytes, CertificatePassword);
651+
if (!ParameterSpecified(nameof(X509KeyStorageFlags)))
652+
{
653+
X509KeyStorageFlags = X509KeyStorageFlags.Exportable |
654+
X509KeyStorageFlags.MachineKeySet |
655+
X509KeyStorageFlags.PersistKeySet;
656+
}
657+
var certificate = new X509Certificate2(certificateBytes, CertificatePassword, X509KeyStorageFlags);
648658

649659
if (Connection?.ClientId == ClientId &&
650660
Connection?.Tenant == Tenant &&

src/Commands/Utilities/CertificateHelper.cs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -128,10 +128,15 @@ internal static X509Certificate2 GetCertificateFromStore(string thumbprint)
128128
/// <param name="cmdlet">Cmdlet executing this function</param>
129129
/// <param name="certificatePath">Path to the private key certificate file</param>
130130
/// <param name="certificatePassword">Password to open the certificate or NULL if no password set on the certificate</param>
131+
/// <param name="x509KeyStorageFlags">Key storage flags for created X509Certificate2</param>
131132
/// <returns>X509Certificate2 instance</returns>
132133
/// <exception cref="PSArgumentException">Thrown if the certificate cannot be read</exception>
133134
/// <exception cref="FileNotFoundException">Thrown if the certificate cannot be found at the provided path</exception>
134-
internal static X509Certificate2 GetCertificateFromPath(Cmdlet cmdlet, string certificatePath, SecureString certificatePassword)
135+
internal static X509Certificate2 GetCertificateFromPath(Cmdlet cmdlet, string certificatePath, SecureString certificatePassword,
136+
X509KeyStorageFlags x509KeyStorageFlags =
137+
X509KeyStorageFlags.Exportable |
138+
X509KeyStorageFlags.MachineKeySet |
139+
X509KeyStorageFlags.PersistKeySet)
135140
{
136141
if (System.IO.File.Exists(certificatePath))
137142
{
@@ -152,9 +157,8 @@ internal static X509Certificate2 GetCertificateFromPath(Cmdlet cmdlet, string ce
152157
var certificate = new X509Certificate2(
153158
certificateBytes,
154159
certificatePassword,
155-
X509KeyStorageFlags.Exportable |
156-
X509KeyStorageFlags.MachineKeySet |
157-
X509KeyStorageFlags.PersistKeySet);
160+
x509KeyStorageFlags
161+
);
158162
return certificate;
159163
}
160164
catch (CryptographicException e)

0 commit comments

Comments
 (0)