Skip to content

Commit effc418

Browse files
committed
add support for parameter Resource
1 parent f98103c commit effc418

File tree

5 files changed

+158
-53
lines changed

5 files changed

+158
-53
lines changed

src/Accounts/Accounts/Accounts.format.ps1xml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,35 @@
171171
</TableRowEntries>
172172
</TableControl>
173173
</View>
174+
<View>
175+
<Name>Microsoft.Azure.Commands.Profile.Models.PSAccessToken</Name>
176+
<ViewSelectedBy>
177+
<TypeName>Microsoft.Azure.Commands.Profile.Models.PSAccessToken</TypeName>
178+
</ViewSelectedBy>
179+
<ListControl>
180+
<ListEntries>
181+
<ListEntry>
182+
<ListItems>
183+
<ListItem>
184+
<PropertyName>Token</PropertyName>
185+
</ListItem>
186+
<ListItem>
187+
<PropertyName>ExpiresOn</PropertyName>
188+
</ListItem>
189+
<ListItem>
190+
<PropertyName>Type</PropertyName>
191+
</ListItem>
192+
<ListItem>
193+
<PropertyName>TenantId</PropertyName>
194+
</ListItem>
195+
<ListItem>
196+
<PropertyName>UserId</PropertyName>
197+
</ListItem>
198+
</ListItems>
199+
</ListEntry>
200+
</ListEntries>
201+
</ListControl>
202+
</View>
174203
<View>
175204
<Name>Microsoft.Azure.Commands.Profile.Models.PSAzureSubscriptionPolicy</Name>
176205
<ViewSelectedBy>
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
//
2+
// Copyright Microsoft Corporation
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
// http://www.apache.org/licenses/LICENSE-2.0
7+
// Unless required by applicable law or agreed to in writing, software
8+
// distributed under the License is distributed on an "AS IS" BASIS,
9+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10+
// See the License for the specific language governing permissions and
11+
// limitations under the License.
12+
// ----------------------------------------------------------------------------------
13+
14+
using System;
15+
16+
namespace Microsoft.Azure.Commands.Profile.Models
17+
{
18+
public class PSAccessToken
19+
{
20+
public string Token { get; set; }
21+
22+
public DateTimeOffset ExpiresOn { get; set; }
23+
24+
public string TenantId { get; set; }
25+
26+
public string UserId { get; set; }
27+
28+
public string Type { get; } = "Bearer";
29+
}
30+
}

src/Accounts/Accounts/Token/GetAzureRmAccessToken.cs

Lines changed: 65 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -14,117 +14,133 @@
1414

1515
using System;
1616
using System.Collections.Generic;
17-
using System.Linq;
1817
using System.Management.Automation;
19-
using System.Net.Http;
20-
using System.Threading;
2118

2219
using Microsoft.Azure.Commands.Common.Authentication;
2320
using Microsoft.Azure.Commands.Common.Authentication.Abstractions;
24-
using Microsoft.Azure.Commands.Common.Authentication.Models;
21+
using Microsoft.Azure.Commands.Profile.Models;
2522
using Microsoft.Azure.Commands.ResourceManager.Common;
2623
using Microsoft.Azure.Commands.ResourceManager.Common.ArgumentCompleters;
24+
using Microsoft.Azure.PowerShell.Authenticators;
2725

28-
namespace Microsoft.Azure.Commands.Profile.Token
26+
namespace Microsoft.Azure.Commands.Profile
2927
{
30-
[Cmdlet(VerbsCommon.Get, AzureRMConstants.AzureRMPrefix + "AccessToken")]
31-
[OutputType(typeof(string))]
28+
[Cmdlet(VerbsCommon.Get, AzureRMConstants.AzureRMPrefix + "AccessToken", DefaultParameterSetName = KnownResourceNameParameterSet)]
29+
[OutputType(typeof(PSAccessToken))]
3230
public class GetAzureRmAccessTokenCommand : AzureRMCmdlet
3331
{
34-
private const string AuthorizationHeaderName = "Authorization";
35-
private const string ResourceUriParameterSet = "ResourceUri";
32+
private const string ResourceUrlParameterSet = "ResourceUrl";
3633
private const string KnownResourceNameParameterSet = "KnownResourceTypeName";
3734

38-
//TODO: Support ResourceUri directly
39-
//[Parameter(ParameterSetName = ResourceUriParameterSet, Mandatory = false)]
40-
//public string Resource { get; set; }
35+
[Parameter(ParameterSetName = ResourceUrlParameterSet,
36+
Mandatory = true,
37+
HelpMessage = "Resource url for that you're requesting token, e.g. 'http://graph.windows.net/'.")]
38+
[ValidateNotNullOrEmpty]
39+
[Alias("Resource", "ResourceUri")]
40+
public string ResourceUrl { get; set; }
4141

4242
[Parameter(ParameterSetName = KnownResourceNameParameterSet,
4343
Mandatory = false,
44-
HelpMessage = "Optional resouce type name, supported values: AadGraph, Analysis, Arm, Attest, DataLake, KeyVault, OperationInsights, Synapse. Default value is Arm if not specified.")]
44+
HelpMessage = "Optional resouce type name, supported values: AadGraph, Analysis, Arm, Attestation, Batch, DataLake, KeyVault, OperationInsights, ResourceManager, Synapse. Default value is Arm if not specified.")]
4545
[PSArgumentCompleter(
4646
SupportedResourceNames.AadGraph,
4747
SupportedResourceNames.Analysis,
4848
SupportedResourceNames.Arm,
4949
SupportedResourceNames.Attest,
50+
SupportedResourceNames.Batch,
5051
SupportedResourceNames.DataLake,
5152
SupportedResourceNames.KeyVault,
53+
SupportedResourceNames.ManagedHsm,
5254
SupportedResourceNames.OperationInsights,
55+
SupportedResourceNames.ResourceManager,
5356
SupportedResourceNames.Synapse
5457
)]
5558
public string ResourceTypeName { get; set; }
5659

5760
//Use tenant in default context if not specified
61+
//TODO: Should not specify TenantId for MSI, CloudShell(?)
5862
[Parameter(Mandatory = false, HelpMessage = "Optional Tenant Id. Use tenant id of default context if not specified.")]
5963
public string TenantId { get; set; }
6064

6165
public override void ExecuteCmdlet()
6266
{
6367
base.ExecuteCmdlet();
6468

65-
string resourceId = null;
69+
string resourceUrlOrId;
6670

67-
if (ResourceTypeName == null)
71+
if (ParameterSetName == KnownResourceNameParameterSet)
6872
{
69-
ResourceTypeName = SupportedResourceNames.Arm;
73+
if (ResourceTypeName == null)
74+
{
75+
ResourceTypeName = SupportedResourceNames.Arm;
76+
}
77+
if (!SupportedResourceNames.ResourceNameMap.ContainsKey(ResourceTypeName))
78+
{
79+
throw new ArgumentException(Properties.Resources.InvalidResourceTypeName.FormatInvariant(ResourceTypeName), nameof(ResourceTypeName));
80+
}
81+
resourceUrlOrId = SupportedResourceNames.ResourceNameMap[ResourceTypeName];
7082
}
71-
if (!SupportedResourceNames.ResourceNameMap.ContainsKey(ResourceTypeName))
83+
else
7284
{
73-
throw new ArgumentException(Properties.Resources.InvalidResourceTypeName.FormatInvariant(ResourceTypeName), nameof(ResourceTypeName));
85+
resourceUrlOrId = ResourceUrl;
7486
}
7587

76-
resourceId = SupportedResourceNames.ResourceNameMap[ResourceTypeName];
77-
78-
resourceId = string.IsNullOrEmpty(resourceId) ? AzureEnvironment.Endpoint.ActiveDirectoryServiceEndpointResourceId : resourceId;
79-
8088
IAzureContext context = DefaultContext;
81-
if (!string.IsNullOrEmpty(TenantId) && !string.Equals(context.Tenant.Id, TenantId, StringComparison.OrdinalIgnoreCase))
89+
if(TenantId == null)
8290
{
83-
var profile = DefaultProfile as AzureRmProfile;
84-
context = profile.Contexts.FirstOrDefault(c =>
85-
string.Equals(c.Value.Tenant.Id, TenantId, StringComparison.OrdinalIgnoreCase)).Value;
86-
if (context == null)
87-
{
88-
throw new ArgumentException(Properties.Resources.InvalidTenantId.FormatInvariant(TenantId), nameof(TenantId));
89-
}
91+
TenantId = context.Tenant?.Id;
9092
}
91-
var credential = AzureSession.Instance.AuthenticationFactory.GetServiceClientCredentials(
92-
context,
93-
resourceId);
94-
var requestMessage = new HttpRequestMessage();
95-
credential.ProcessHttpRequestAsync(requestMessage, default(CancellationToken)).ConfigureAwait(false).GetAwaiter().GetResult();
96-
if (requestMessage.Headers.Contains(AuthorizationHeaderName))
93+
94+
IAccessToken accessToken = AzureSession.Instance.AuthenticationFactory.Authenticate(
95+
context.Account,
96+
context.Environment,
97+
TenantId,
98+
null,
99+
ShowDialog.Never,
100+
null,
101+
null,
102+
resourceUrlOrId);
103+
104+
var result = new PSAccessToken()
97105
{
98-
var token = requestMessage.Headers.GetValues(AuthorizationHeaderName)
99-
?.FirstOrDefault()?.Substring("Bearer ".Length);
100-
WriteObject(token);
101-
}
106+
Token = accessToken.AccessToken,
107+
TenantId = TenantId,
108+
UserId = accessToken.UserId,
109+
};
110+
result.ExpiresOn = (accessToken as MsalAccessToken)?.ExpiredOn ?? result.ExpiresOn;
111+
112+
WriteObject(result);
102113
}
103114

104115
internal class SupportedResourceNames
105116
{
106-
//TODO: Support 'Batch' and 'ManagedHsm', need to upate AzureEnvironmentExtensions.GetTokenAudience() to support more endpoints
107-
108117
public const string Arm = "Arm";
109118
public const string AadGraph = "AadGraph";
119+
public const string Batch = "Batch";
110120
public const string DataLake = "DataLake";
111121
public const string KeyVault = "KeyVault";
122+
public const string ResourceManager = "ResourceManager"; //endpoint is same as Arm
112123

113124
public const string Analysis = "Analysis";
114-
public const string Attest = "Attest";
125+
public const string Attest = "Attestation";
115126
public const string OperationInsights = "OperationInsights";
116127
public const string Synapse = "Synapse";
128+
public const string ManagedHsm = "ManagedHsm";
117129

118130
internal static Dictionary<string, string> ResourceNameMap = new Dictionary<string, string>()
119131
{
120132
{ Arm, AzureEnvironment.Endpoint.ActiveDirectoryServiceEndpointResourceId },
121-
{ AadGraph, AzureEnvironment.Endpoint.Graph}, //Only exception that not using xxxResourceId because of implementation of GetTokenAudience
122-
{ DataLake, AzureEnvironment.Endpoint.DataLakeEndpointResourceId},
123-
{ KeyVault, AzureEnvironment.Endpoint.AzureKeyVaultServiceEndpointResourceId},
124-
{ Analysis, AzureEnvironment.ExtendedEndpoint.AnalysisServicesEndpointResourceId},
133+
{ AadGraph, AzureEnvironment.Endpoint.GraphEndpointResourceId },
134+
{ Batch, AzureEnvironment.Endpoint.BatchEndpointResourceId },
135+
{ DataLake, AzureEnvironment.Endpoint.DataLakeEndpointResourceId },
136+
{ KeyVault, AzureEnvironment.Endpoint.AzureKeyVaultServiceEndpointResourceId },
137+
{ ResourceManager, AzureEnvironment.Endpoint.ActiveDirectoryServiceEndpointResourceId },
138+
139+
{ Analysis, AzureEnvironment.ExtendedEndpoint.AnalysisServicesEndpointResourceId },
125140
{ Attest, AzureEnvironment.ExtendedEndpoint.AzureAttestationServiceEndpointResourceId },
126-
{ OperationInsights, AzureEnvironment.ExtendedEndpoint.OperationalInsightsEndpointResourceId},
127-
{ Synapse, AzureEnvironment.ExtendedEndpoint.AzureSynapseAnalyticsEndpointResourceId},
141+
{ OperationInsights, AzureEnvironment.ExtendedEndpoint.OperationalInsightsEndpointResourceId },
142+
{ Synapse, AzureEnvironment.ExtendedEndpoint.AzureSynapseAnalyticsEndpointResourceId },
143+
{ ManagedHsm, AzureEnvironment.ExtendedEndpoint.ManagedHsmServiceEndpointResourceId }
128144
};
129145
}
130146
}

src/Accounts/Accounts/help/Get-AzAccessToken.md

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,16 @@ Get raw access token
1212

1313
## SYNTAX
1414

15-
### KnownResourceTypeName
15+
### KnownResourceTypeName (Default)
1616
```
17-
Get-AzAccessToken -ResourceTypeName <String> [-TenantId <String>] [-DefaultProfile <IAzureContextContainer>]
17+
Get-AzAccessToken [-ResourceTypeName <String>] [-TenantId <String>] [-DefaultProfile <IAzureContextContainer>]
18+
[<CommonParameters>]
19+
```
20+
21+
### ResourceUrl
22+
When using ResourceUrl, please make sure the value is correct for current Azure environment. You may refer to the value of `(Get-AzContext).Environment`.
23+
```
24+
Get-AzAccessToken -ResourceUrl <String> [-TenantId <String>] [-DefaultProfile <IAzureContextContainer>]
1825
[<CommonParameters>]
1926
```
2027

@@ -37,6 +44,13 @@ PS C:\> Get-AzAccessToken -ResourceTypeName AadGraph
3744

3845
Get access token of AAD graph endpoint for current account
3946

47+
### Example 3 Get raw access token for AAD graph endpoint
48+
```powershell
49+
PS C:\> Get-AzAccessToken -Resource "https://graph.windows.net/"
50+
```
51+
52+
Get access token of AAD graph endpoint for current account
53+
4054
## PARAMETERS
4155

4256
### -DefaultProfile
@@ -55,13 +69,28 @@ Accept wildcard characters: False
5569
```
5670
5771
### -ResourceTypeName
58-
Optional resouce type name, supported values: AadGraph, Analysis, Arm, Attest, DataLake, KeyVault, OperationInsights, Synapse. Default value is Arm if not specified.
72+
Optional resouce type name, supported values: AadGraph, Analysis, Arm, Attestation, Batch, DataLake, KeyVault, OperationInsights, ResourceManager, Synapse. Default value is Arm if not specified.
5973
6074
```yaml
6175
Type: System.String
6276
Parameter Sets: KnownResourceTypeName
6377
Aliases:
6478

79+
Required: False
80+
Position: Named
81+
Default value: None
82+
Accept pipeline input: False
83+
Accept wildcard characters: False
84+
```
85+
86+
### -ResourceUrl
87+
Resource url for that you're requesting token, e.g. 'http://graph.windows.net/'.
88+
89+
```yaml
90+
Type: System.String
91+
Parameter Sets: ResourceUrl
92+
Aliases: Resource, ResourceUri
93+
6594
Required: True
6695
Position: Named
6796
Default value: None
@@ -75,6 +104,7 @@ Optional Tenant Id. Use tenant id of default context if not specified.
75104
```yaml
76105
Type: System.String
77106
Parameter Sets: (All)
107+
Aliases:
78108

79109
Required: False
80110
Position: Named

src/Accounts/Authenticators/MsalAccessToken.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ public class MsalAccessToken : IAccessToken
3939

4040
public IDictionary<string, string> ExtendedProperties { get; } = new ConcurrentDictionary<string, string>(StringComparer.OrdinalIgnoreCase);
4141

42-
private DateTimeOffset ExpiredOn { get; set; }
42+
public DateTimeOffset ExpiredOn { get; set; }
4343

4444
private readonly static TimeSpan ExpirationThreshold = TimeSpan.FromMinutes(5);
4545

0 commit comments

Comments
 (0)