Skip to content

Commit d2b0c24

Browse files
authored
Merge pull request #2821 from reusto/feature/provideconnection2connect
Add connection paramter to Connect-PnPOnline
2 parents 2f387d0 + 6cc2dae commit d2b0c24

File tree

3 files changed

+81
-55
lines changed

3 files changed

+81
-55
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/).
4141
- Added support for specifying the ContentUrl and WebsiteUrl configuration in `Add-PnPTeamsTab` cmdlet when trying to add a SharePoint page or list as a tab in Teams channel. [#2807](https://github.com/pnp/powershell/pull/2807)
4242
- Added `-CheckinType` parameter to `Add-PnPFile` cmdlet which provides the option to specify the checkin type for a file. The default value is set to `MinorCheckIn`. [#2806](https://github.com/pnp/powershell/pull/2806)
4343
- Added `-ApplicationId` as alias for `-ClientId` in `Connect-PnPOnline` and `Request-PnPAccessToken` cmdlets. [#2805](https://github.com/pnp/powershell/pull/2805)
44+
- Added `-Connection` option to `Connect-PnPOnline` which allows of reusing an authenticated connection to connect to a different site [#2821](https://github.com/pnp/powershell/pull/2821)
4445

4546
### Changed
4647

@@ -78,6 +79,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/).
7879

7980
### Contributors
8081

82+
- [reusto]
8183
- Ronald Mavarez [ronaldmavarez]
8284
- [lilealdai]
8385
- Martin Lingstuyl [martinlingstuyl]

documentation/Connect-PnPOnline.md

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,36 +19,36 @@ Connect to a SharePoint site
1919
Connect-PnPOnline [-ReturnConnection] [-Url] <String> [-Credentials <CredentialPipeBind>] [-CurrentCredentials]
2020
[-CreateDrive] [-DriveName <String>] [-ClientId <String>] [-RedirectUri <String>]
2121
[-AzureEnvironment <AzureEnvironment>] [-TenantAdminUrl <String>]
22-
[-TransformationOnPrem] [-ValidateConnection]
22+
[-TransformationOnPrem] [-ValidateConnection] [-Connection <PnPConnection>]
2323
```
2424

2525
### SharePoint ACS (Legacy) App Only
2626
```
2727
Connect-PnPOnline [-ReturnConnection] [-Url] <String> [-Realm <String>] -ClientSecret <String> [-CreateDrive]
2828
[-DriveName <String>] -ClientId <String> [-AzureEnvironment <AzureEnvironment>] [-TenantAdminUrl <String>]
29-
[-ValidateConnection]
29+
[-ValidateConnection] [-Connection <PnPConnection>]
3030
```
3131

3232
### App-Only with Azure Active Directory
3333
```
3434
Connect-PnPOnline [-ReturnConnection] [-Url] <String> [-CreateDrive] [-DriveName <String>] -ClientId <String>
3535
-Tenant <String> [-CertificatePath <String>] [-CertificateBase64Encoded <String>]
3636
[-CertificatePassword <SecureString>] [-AzureEnvironment <AzureEnvironment>] [-TenantAdminUrl <String>]
37-
[-ValidateConnection]
37+
[-ValidateConnection] [-Connection <PnPConnection>]
3838
```
3939

4040
### App-Only with Azure Active Directory using a certificate from the Windows Certificate Management Store by thumbprint
4141
```
4242
Connect-PnPOnline [-ReturnConnection] [-Url] <String> [-CreateDrive] [-DriveName <String>] -ClientId <String>
4343
-Tenant <String> -Thumbprint <String> [-AzureEnvironment <AzureEnvironment>] [-TenantAdminUrl <String>]
44-
[-ValidateConnection]
44+
[-ValidateConnection] [-Connection <PnPConnection>]
4545
```
4646

4747
### PnP Management Shell / DeviceLogin
4848
```
4949
Connect-PnPOnline [-ReturnConnection] [-Url] <String> [-CreateDrive] [-DriveName <String>] [-DeviceLogin]
5050
[-LaunchBrowser] [-ClientId <String>] [-AzureEnvironment <AzureEnvironment>]
51-
[-ValidateConnection]
51+
[-ValidateConnection] [-Connection <PnPConnection>]
5252
```
5353

5454
### Web Login for Multi Factor Authentication
@@ -61,7 +61,7 @@ Connect-PnPOnline [-ReturnConnection] [-Url] <String> [-CreateDrive] [-DriveName
6161
### Interactive for Multi Factor Authentication
6262
```
6363
Connect-PnPOnline -Interactive [-ReturnConnection] -Url <String> [-CreateDrive] [-DriveName <String>] [-LaunchBrowser]
64-
[-ClientId <String>] [-AzureEnvironment <AzureEnvironment>] [-TenantAdminUrl <String>] [-ForceAuthentication] [-ValidateConnection]
64+
[-ClientId <String>] [-AzureEnvironment <AzureEnvironment>] [-TenantAdminUrl <String>] [-ForceAuthentication] [-ValidateConnection] [-Connection <PnPConnection>]
6565
```
6666

6767
### On-premises login for page transformation from on-premises SharePoint to SharePoint Online
@@ -84,7 +84,7 @@ Connect-PnPOnline -Url <String> [-UserAssignedManagedIdentityObjectId <String>]
8484
Connect-PnPOnline [-ReturnConnection] [-Url] <String> [-EnvironmentVariable] [-CurrentCredentials]
8585
[-CreateDrive] [-DriveName <String>] [-RedirectUri <String>]
8686
[-AzureEnvironment <AzureEnvironment>] [-TenantAdminUrl <String>]
87-
[-TransformationOnPrem] [-ValidateConnection]
87+
[-TransformationOnPrem] [-ValidateConnection] [-Connection <PnPConnection>]
8888
```
8989

9090
## DESCRIPTION
@@ -343,6 +343,20 @@ Accept pipeline input: False
343343
Accept wildcard characters: False
344344
```
345345
346+
### -Connection
347+
Optional connection to be reused by the new connection. Retrieve the value for this parameter by either specifying -ReturnConnection on Connect-PnPOnline or by executing Get-PnPConnection.
348+
349+
```yaml
350+
Type: PnPConnection
351+
Parameter Sets: Credentials, SharePoint ACS (Legacy) App Only, App-Only with Azure Active Directory, App-Only with Azure Active Directory using a certificate from the Windows Certificate Management Store by thumbprint, SPO Management Shell Credentials, PnP Management Shell / DeviceLogin, Interactive login for Multi Factor Authentication, Environment Variable
352+
353+
Required: False
354+
Position: Named
355+
Default value: PnPConnection.Current
356+
Accept pipeline input: False
357+
Accept wildcard characters: False
358+
```
359+
346360
### -CreateDrive
347361
If you want to create a PSDrive connected to the URL
348362

src/Commands/Base/ConnectOnline.cs

Lines changed: 58 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,16 @@ public class ConnectOnline : BasePSCmdlet
7575
[Parameter(Mandatory = true, Position = 0, ParameterSetName = ParameterSet_ENVIRONMENTVARIABLE, ValueFromPipeline = true)]
7676
public string Url;
7777

78+
[Parameter(Mandatory = false, ParameterSetName = ParameterSet_CREDENTIALS)]
79+
[Parameter(Mandatory = false, ParameterSetName = ParameterSet_ACSAPPONLY)]
80+
[Parameter(Mandatory = false, ParameterSetName = ParameterSet_APPONLYAADCERTIFICATE)]
81+
[Parameter(Mandatory = false, ParameterSetName = ParameterSet_APPONLYAADTHUMBPRINT)]
82+
[Parameter(Mandatory = false, ParameterSetName = ParameterSet_SPOMANAGEMENT)]
83+
[Parameter(Mandatory = false, ParameterSetName = ParameterSet_DEVICELOGIN)]
84+
[Parameter(Mandatory = false, ParameterSetName = ParameterSet_INTERACTIVE)]
85+
[Parameter(Mandatory = false, ParameterSetName = ParameterSet_ENVIRONMENTVARIABLE)]
86+
public PnPConnection Connection = PnPConnection.Current;
87+
7888
[Parameter(Mandatory = false, ParameterSetName = ParameterSet_CREDENTIALS)]
7989
[Parameter(Mandatory = false, ParameterSetName = ParameterSet_SPOMANAGEMENT)]
8090
public CredentialPipeBind Credentials;
@@ -237,7 +247,7 @@ protected void Connect(ref CancellationToken cancellationToken)
237247
}
238248
}
239249

240-
PnPConnection connection = null;
250+
PnPConnection newConnection = null;
241251

242252
PSCredential credentials = null;
243253
if (Credentials != null)
@@ -249,42 +259,42 @@ protected void Connect(ref CancellationToken cancellationToken)
249259
switch (ParameterSetName)
250260
{
251261
case ParameterSet_SPOMANAGEMENT:
252-
connection = ConnectSpoManagement();
262+
newConnection = ConnectSpoManagement();
253263
break;
254264
case ParameterSet_DEVICELOGIN:
255-
connection = ConnectDeviceLogin();
265+
newConnection = ConnectDeviceLogin();
256266
break;
257267
case ParameterSet_APPONLYAADCERTIFICATE:
258-
connection = ConnectAppOnlyWithCertificate();
268+
newConnection = ConnectAppOnlyWithCertificate();
259269
break;
260270
case ParameterSet_APPONLYAADTHUMBPRINT:
261-
connection = ConnectAppOnlyWithCertificate();
271+
newConnection = ConnectAppOnlyWithCertificate();
262272
break;
263273
case ParameterSet_ACCESSTOKEN:
264-
connection = ConnectAccessToken();
274+
newConnection = ConnectAccessToken();
265275
break;
266276
case ParameterSet_ACSAPPONLY:
267-
connection = ConnectACSAppOnly();
277+
newConnection = ConnectACSAppOnly();
268278
break;
269279
case ParameterSet_CREDENTIALS:
270-
connection = ConnectCredentials(credentials);
280+
newConnection = ConnectCredentials(credentials);
271281
break;
272282
case ParameterSet_MANAGEDIDENTITY:
273-
connection = ConnectManagedIdentity();
283+
newConnection = ConnectManagedIdentity();
274284
break;
275285
case ParameterSet_WEBLOGIN:
276-
connection = ConnectWebLogin();
286+
newConnection = ConnectWebLogin();
277287
break;
278288
case ParameterSet_INTERACTIVE:
279-
connection = ConnectInteractive();
289+
newConnection = ConnectInteractive();
280290
break;
281291
case ParameterSet_ENVIRONMENTVARIABLE:
282-
connection = ConnectEnvironmentVariable();
292+
newConnection = ConnectEnvironmentVariable();
283293
break;
284294
}
285295

286296
// Ensure a connection instance has been created by now
287-
if (connection == null)
297+
if (newConnection == null)
288298
{
289299
// No connection instance was created
290300
throw new PSInvalidOperationException("Unable to connect using provided arguments");
@@ -293,9 +303,9 @@ protected void Connect(ref CancellationToken cancellationToken)
293303
// Connection has been established
294304
WriteVerbose($"PnP PowerShell Cmdlets ({new SemanticVersion(Assembly.GetExecutingAssembly().GetName().Version)})");
295305

296-
if (connection.Url != null)
306+
if (newConnection.Url != null)
297307
{
298-
var hostUri = new Uri(connection.Url);
308+
var hostUri = new Uri(newConnection.Url);
299309
Environment.SetEnvironmentVariable("PNPPSHOST", hostUri.Host);
300310
Environment.SetEnvironmentVariable("PNPPSSITE", hostUri.LocalPath);
301311
}
@@ -309,11 +319,11 @@ protected void Connect(ref CancellationToken cancellationToken)
309319
{
310320
// Try requesting the site Id to validate that the site to which is being connected exists
311321
WriteVerbose($"Validating if the site at {Url} exists");
312-
connection.Context.Load(connection.Context.Site, p => p.Id);
322+
newConnection.Context.Load(newConnection.Context.Site, p => p.Id);
313323

314324
try
315325
{
316-
connection.Context.ExecuteQueryRetry();
326+
newConnection.Context.ExecuteQueryRetry();
317327
WriteVerbose($"Site at {Url} exists");
318328
}
319329
catch (System.Net.WebException e) when (e.Message.Contains("404"))
@@ -325,13 +335,13 @@ protected void Connect(ref CancellationToken cancellationToken)
325335

326336
if (ReturnConnection)
327337
{
328-
WriteObject(connection);
338+
WriteObject(newConnection);
329339
}
330340
else
331341
{
332-
PnPConnection.Current = connection;
342+
PnPConnection.Current = newConnection;
333343
}
334-
if (CreateDrive && connection.Context != null)
344+
if (CreateDrive && newConnection.Context != null)
335345
{
336346
var provider = SessionState.Provider.GetAll().FirstOrDefault(p => p.Name.Equals(SPOProvider.PSProviderName, StringComparison.InvariantCultureIgnoreCase));
337347
if (provider != null)
@@ -357,9 +367,9 @@ protected void Connect(ref CancellationToken cancellationToken)
357367
private PnPConnection ConnectACSAppOnly()
358368
{
359369
CmdletMessageWriter.WriteFormattedMessage(this, new CmdletMessageWriter.Message { Text = "Connecting with Client Secret uses legacy authentication and provides limited functionality. We can for instance not execute requests towards the Microsoft Graph, which limits cmdlets related to Microsoft Teams, Microsoft Planner, Microsoft Flow and Microsoft 365 Groups. You can hide this warning by using Connect-PnPOnline [your parameters] -WarningAction Ignore", Formatted = true, Type = CmdletMessageWriter.MessageType.Warning });
360-
if (PnPConnection.Current?.ClientId == ClientId &&
361-
PnPConnection.Current?.ClientSecret == ClientSecret &&
362-
PnPConnection.Current?.Tenant == Realm)
370+
if (Connection?.ClientId == ClientId &&
371+
Connection?.ClientSecret == ClientSecret &&
372+
Connection?.Tenant == Realm)
363373
{
364374
ReuseAuthenticationManager();
365375
}
@@ -397,14 +407,14 @@ private PnPConnection ConnectDeviceLogin()
397407
{
398408
Uri oldUri = null;
399409

400-
if (PnPConnection.Current != null)
410+
if (Connection != null)
401411
{
402-
if (PnPConnection.Current.Url != null)
412+
if (Connection.Url != null)
403413
{
404-
oldUri = new Uri(PnPConnection.Current.Url);
414+
oldUri = new Uri(Connection.Url);
405415
}
406416
}
407-
if (oldUri != null && oldUri.Host == new Uri(Url).Host && PnPConnection.Current?.ConnectionMethod == ConnectionMethod.DeviceLogin)
417+
if (oldUri != null && oldUri.Host == new Uri(Url).Host && Connection?.ConnectionMethod == ConnectionMethod.DeviceLogin)
408418
{
409419
ReuseAuthenticationManager();
410420
}
@@ -447,9 +457,9 @@ private PnPConnection ConnectAppOnlyWithCertificate()
447457
throw new FileNotFoundException("Certificate not found");
448458
}
449459
X509Certificate2 certificate = CertificateHelper.GetCertificateFromPath(CertificatePath, CertificatePassword);
450-
if (PnPConnection.Current?.ClientId == ClientId &&
451-
PnPConnection.Current?.Tenant == Tenant &&
452-
PnPConnection.Current?.Certificate?.Thumbprint == certificate.Thumbprint)
460+
if (Connection?.ClientId == ClientId &&
461+
Connection?.Tenant == Tenant &&
462+
Connection?.Certificate?.Thumbprint == certificate.Thumbprint)
453463
{
454464
ReuseAuthenticationManager();
455465
}
@@ -460,9 +470,9 @@ private PnPConnection ConnectAppOnlyWithCertificate()
460470
var certificateBytes = Convert.FromBase64String(CertificateBase64Encoded);
461471
var certificate = new X509Certificate2(certificateBytes, CertificatePassword);
462472

463-
if (PnPConnection.Current?.ClientId == ClientId &&
464-
PnPConnection.Current?.Tenant == Tenant &&
465-
PnPConnection.Current?.Certificate?.Thumbprint == certificate.Thumbprint)
473+
if (Connection?.ClientId == ClientId &&
474+
Connection?.Tenant == Tenant &&
475+
Connection?.Certificate?.Thumbprint == certificate.Thumbprint)
466476
{
467477
ReuseAuthenticationManager();
468478
}
@@ -482,9 +492,9 @@ private PnPConnection ConnectAppOnlyWithCertificate()
482492
{
483493
throw new PSArgumentException("The certificate specified does not have a private key.", nameof(Thumbprint));
484494
}
485-
if (PnPConnection.Current?.ClientId == ClientId &&
486-
PnPConnection.Current?.Tenant == Tenant &&
487-
PnPConnection.Current?.Certificate?.Thumbprint == certificate.Thumbprint)
495+
if (Connection?.ClientId == ClientId &&
496+
Connection?.Tenant == Tenant &&
497+
Connection?.Certificate?.Thumbprint == certificate.Thumbprint)
488498
{
489499
ReuseAuthenticationManager();
490500
}
@@ -531,10 +541,10 @@ private PnPConnection ConnectCredentials(PSCredential credentials, Initializatio
531541
ClientId = PnPConnection.PnPManagementShellClientId;
532542
}
533543

534-
if (PnPConnection.Current?.ClientId == ClientId)
544+
if (Connection?.ClientId == ClientId)
535545
{
536-
if (credentials != null && PnPConnection.Current?.PSCredential?.UserName == credentials.UserName &&
537-
PnPConnection.Current?.PSCredential.GetNetworkCredential().Password == credentials.GetNetworkCredential().Password)
546+
if (credentials != null && Connection?.PSCredential?.UserName == credentials.UserName &&
547+
Connection?.PSCredential.GetNetworkCredential().Password == credentials.GetNetworkCredential().Password)
538548
{
539549
ReuseAuthenticationManager();
540550
}
@@ -574,9 +584,9 @@ private PnPConnection ConnectInteractive()
574584
{
575585
ClientId = PnPConnection.PnPManagementShellClientId;
576586
}
577-
if (PnPConnection.Current?.ClientId == ClientId && PnPConnection.Current?.ConnectionMethod == ConnectionMethod.Credentials)
587+
if (Connection?.ClientId == ClientId && Connection?.ConnectionMethod == ConnectionMethod.Credentials)
578588
{
579-
if (IsSameOrAdminHost(new Uri(Url), new Uri(PnPConnection.Current.Url)))
589+
if (IsSameOrAdminHost(new Uri(Url), new Uri(Connection.Url)))
580590
{
581591
ReuseAuthenticationManager();
582592
}
@@ -618,9 +628,9 @@ private PnPConnection ConnectEnvironmentVariable(InitializationType initializati
618628
SecureString secPassword = StringToSecureString(azureCertPassword);
619629

620630
X509Certificate2 certificate = CertificateHelper.GetCertificateFromPath(azureCertificatePath, secPassword);
621-
if (PnPConnection.Current?.ClientId == azureClientId &&
622-
PnPConnection.Current?.Tenant == Tenant &&
623-
PnPConnection.Current?.Certificate?.Thumbprint == certificate.Thumbprint)
631+
if (Connection?.ClientId == azureClientId &&
632+
Connection?.Tenant == Tenant &&
633+
Connection?.Certificate?.Thumbprint == certificate.Thumbprint)
624634
{
625635
ReuseAuthenticationManager();
626636
}
@@ -637,10 +647,10 @@ private PnPConnection ConnectEnvironmentVariable(InitializationType initializati
637647
SecureString secPassword = StringToSecureString(password);
638648
var credentials = new PSCredential(username, secPassword);
639649

640-
if (PnPConnection.Current?.ClientId == azureClientId)
650+
if (Connection?.ClientId == azureClientId)
641651
{
642-
if (credentials != null && PnPConnection.Current?.PSCredential?.UserName == credentials.UserName &&
643-
PnPConnection.Current?.PSCredential.GetNetworkCredential().Password == credentials.GetNetworkCredential().Password)
652+
if (credentials != null && Connection?.PSCredential?.UserName == credentials.UserName &&
653+
Connection?.PSCredential.GetNetworkCredential().Password == credentials.GetNetworkCredential().Password)
644654
{
645655
ReuseAuthenticationManager();
646656
}
@@ -739,7 +749,7 @@ protected override void StopProcessing()
739749

740750
private void ReuseAuthenticationManager()
741751
{
742-
var contextSettings = PnPConnection.Current.Context?.GetContextSettings();
752+
var contextSettings = Connection.Context?.GetContextSettings();
743753
PnPConnection.CachedAuthenticationManager = contextSettings?.AuthenticationManager;
744754
}
745755

0 commit comments

Comments
 (0)