Skip to content

Commit a1475c7

Browse files
committed
update init and utils functions
1 parent 28769cf commit a1475c7

4 files changed

Lines changed: 306 additions & 1 deletion

File tree

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
# Monkey365 - the PowerShell Cloud Security Tool for Azure and Microsoft 365 (copyright 2022) by Juan Garrido
2+
#
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+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
Function ConvertTo-Monkey365AccessToken{
16+
<#
17+
.SYNOPSIS
18+
Utility to convert access tokens into a closed version of an AuthenticationTokenResult object
19+
20+
.DESCRIPTION
21+
Utility to convert access tokens into a closed version of an AuthenticationTokenResult object
22+
23+
.INPUTS
24+
25+
.OUTPUTS
26+
27+
.EXAMPLE
28+
29+
.NOTES
30+
Author : Juan Garrido
31+
Twitter : @tr1ana
32+
File Name : ConvertTo-Monkey365AccessToken
33+
Version : 1.0
34+
35+
.LINK
36+
https://github.com/silverhack/monkey365
37+
#>
38+
[Diagnostics.CodeAnalysis.SuppressMessageAttribute("InjectionRisk.Create", "", Scope="Function")]
39+
[CmdletBinding()]
40+
[OutputType([System.Management.Automation.PSCustomObject])]
41+
Param (
42+
[parameter(Mandatory=$True, ValueFromPipeline = $True, HelpMessage="Access Token")]
43+
[String]$InputObject
44+
)
45+
Process{
46+
Try{
47+
#Set Null
48+
$at_info = $authObject = $null
49+
#Set authType
50+
$authType = 'Unknown';
51+
If($null -ne (Get-Command -Name "Read-JWTtoken" -ErrorAction ignore)){
52+
Try{
53+
$at_info = Read-JWTtoken -token $InputObject | Select-Object appid,app_displayname,idtyp,scp,aud,exp,tid -ErrorAction Ignore
54+
}
55+
Catch{
56+
Write-Error $_
57+
}
58+
}
59+
If($null -ne $at_info){
60+
#Check if expired token
61+
$expiry = [System.DateTimeOffset]::FromUnixTimeSeconds($at_info.exp).UtcDateTime
62+
$now = [System.DateTime]::Now.ToUniversalTime();
63+
If($expiry -ge $now){
64+
#Get idTyp
65+
If($null -ne $at_info.idtyp){
66+
If($at_info.idtyp.ToLower() -eq "user"){
67+
$authType = 'Interactive'
68+
}
69+
Else{
70+
$authType = 'Certificate_Credentials'
71+
}
72+
}
73+
#Set PsCustomObject
74+
$authObject = [PsCustomObject]@{
75+
AuthType = $authType;
76+
resource = $at_info.aud;
77+
clientId = $at_info.appid;
78+
renewable = $false;
79+
AccessToken = $InputObject;
80+
ExpiresOn = [System.DateTimeOffset]::FromUnixTimeSeconds($at_info.exp);
81+
TenantId = $at_info.tid;
82+
Scopes = [System.Collections.Generic.HashSet[System.String]]::new()
83+
}
84+
#Set Scopes
85+
#Add .default
86+
[void]$authObject.Scopes.Add(('{0}/.default' -f $authObject.resource));
87+
If($null -ne $at_info.scp -and $at_info.idtyp.ToLower() -eq "user"){
88+
ForEach($scope in @($at_info.scp).GetEnumerator()){
89+
[void]$authObject.Scopes.Add(('{0}/{1}' -f $authObject.resource,$scope));
90+
}
91+
}
92+
#Add IsNearExpiry script method
93+
$authObject | Add-Member -Type ScriptMethod -Name IsNearExpiry -Value {
94+
return ([System.Datetime]::UtcNow -gt $this.ExpiresOn.UtcDateTime.AddMinutes(-15))
95+
}
96+
#return object
97+
return $authObject;
98+
}
99+
Else{
100+
Write-Warning ("Expired token for {0}" -f $at_info.aud)
101+
}
102+
}
103+
}
104+
Catch{
105+
Write-Error $_
106+
}
107+
}
108+
}

core/utils/Get-MonkeyPowerBIBackend.ps1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ Function Get-MonkeyPowerBIBackend{
4242
$rawQuery = ('{0}/v1.0/myorg/admin/groups?$top=1' -f $O365Object.Environment.PowerBIAPI);
4343
#Get Auth header
4444
$AuthHeader = @{
45-
Authorization = $O365Object.auth_tokens.PowerBI.CreateAuthorizationHeader();
45+
Authorization = ("Bearer {0}" -f $O365Object.auth_tokens.PowerBI.AccessToken);
4646
}
4747
}
4848
Process{
Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
# Monkey365 - the PowerShell Cloud Security Tool for Azure and Microsoft 365 (copyright 2022) by Juan Garrido
2+
#
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+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
function Import-ExternalAccessToken {
16+
<#
17+
.SYNOPSIS
18+
Utility to import external access tokens into internal Monkey365 auth object
19+
20+
.DESCRIPTION
21+
Utility to import external access tokens into internal Monkey365 auth object
22+
23+
.INPUTS
24+
25+
.OUTPUTS
26+
27+
.EXAMPLE
28+
29+
.NOTES
30+
Author : Juan Garrido
31+
Twitter : @tr1ana
32+
File Name : Import-ExternalAccessToken
33+
Version : 1.0
34+
35+
.LINK
36+
https://github.com/silverhack/monkey365
37+
#>
38+
Param (
39+
[parameter(Mandatory=$True, HelpMessage="Access Token")]
40+
[Object]$InputObject
41+
)
42+
Begin{
43+
#Set null
44+
$initialDomain = $spoAdminUrl = $spoUrl = $null;
45+
#Set Array
46+
$allAuthObjects = [System.Collections.Generic.List[System.Management.Automation.PsObject]]::new()
47+
ForEach($at in @($InputObject).Where({$null -ne $_})){
48+
#Get Access Token
49+
$accessToken = $at | ConvertTo-Monkey365AccessToken
50+
If($null -ne $accessToken){
51+
[void]$allAuthObjects.Add($accessToken);
52+
}
53+
}
54+
}
55+
Process{
56+
Try{
57+
If($allAuthObjects.Count -gt 0){
58+
#Check if mixed tokens were passed
59+
$nonMixedTokens = @($allAuthObjects | Select-Object -ExpandProperty TenantId -Unique).Count -eq 1
60+
If($nonMixedTokens -and $nonMixedTokens -eq $O365Object.TenantId){
61+
#Get Tokens for SPO
62+
$spoAt = $allAuthObjects.Where({$_.resource -eq '00000003-0000-0ff1-ce00-000000000000'})
63+
If($spoAt.Count -gt 0){
64+
#Access Token for SharePoint Online detected
65+
#Get Token for MSGraph
66+
$msGraph = $allAuthObjects.Where({$_.resource -match "https://graph.microsoft.com?.$|.us?.$|microsoftgraph.chinacloudapi.cn?.$";}) | Select-Object -First 1 -ErrorAction Ignore
67+
If($null -ne $msGraph){
68+
#Get domains
69+
$domains = Get-MonkeyMSGraphObject -Authentication $msGraph -Environment $O365Object.Environment -ObjectType domains
70+
IF($null -ne $domains){
71+
$O365Object.Tenant.MyDomain = @($domains).Where({$_.isDefault}) | Select-Object -ExpandProperty id -ErrorAction Ignore
72+
}
73+
If($O365Object.initParams.ContainsKey('SpoSites') -and @($O365Object.initParams.SpoSites).Count -gt 0){
74+
[uri]$dnsName = $O365Object.initParams.SpoSites | Select-Object -First 1
75+
$initialDomain = ("{0}" -f $dnsName.DnsSafeHost)
76+
}
77+
Else{
78+
If($null -ne $domains){
79+
$initialDomain = @($domains).Where({$_.supportedServices -like "*OfficeCommunicationsOnline*" -and $_.isDefault -eq $true}) | Select-Object -ExpandProperty id -ErrorAction Ignore
80+
}
81+
}
82+
}
83+
If($null -ne $initialDomain){
84+
$CloudType = $O365Object.cloudEnvironment;
85+
$sps_p = @{
86+
Endpoint = $initialDomain;
87+
Environment = $CloudType;
88+
InformationAction = $O365Object.InformationAction;
89+
Verbose = $O365Object.verbose;
90+
Debug = $O365Object.debug;
91+
}
92+
$spoAdminUrl = Get-SharepointAdminUrl @sps_p
93+
$spoUrl = Get-SharepointUrl @sps_p
94+
}
95+
If($null -ne $spoAdminUrl -and $null -ne $spoUrl){
96+
#Get Tokens for SPO Admin Url
97+
$spoAt = $allAuthObjects.Where({$_.resource -eq '00000003-0000-0ff1-ce00-000000000000'})
98+
ForEach($spoToken in $spoAt){
99+
#Test site connection
100+
$adminConnected = Test-SiteConnection -Authentication $spoToken -Site $spoAdminUrl
101+
If($adminConnected){
102+
#Update token and break
103+
$spoToken.resource = $spoAdminUrl;
104+
break
105+
}
106+
}
107+
#Get Tokens for SPO
108+
$spoAt = $allAuthObjects.Where({$_.resource -eq '00000003-0000-0ff1-ce00-000000000000'})
109+
ForEach($spoToken in $spoAt){
110+
#Test site connection
111+
$connected = Test-SiteConnection -Authentication $spoToken -Site $spoUrl
112+
If($connected){
113+
#Update token and break
114+
$spoToken.resource = $spoUrl;
115+
break
116+
}
117+
}
118+
}
119+
Else{
120+
$msg = @{
121+
MessageData = ($message.SPOTokenImportErrorMessage);
122+
callStack = (Get-PSCallStack | Select-Object -First 1);
123+
logLevel = 'warning';
124+
InformationAction = $O365Object.InformationAction;
125+
Tags = @('Monkey365ImportTokenInfo');
126+
}
127+
Write-Warning @msg
128+
#Clear tokens for SPO
129+
$allAuthObjects = $allAuthObjects.Where({$_.resource -ne '00000003-0000-0ff1-ce00-000000000000'})
130+
}
131+
}
132+
}
133+
Else{
134+
$msg = @{
135+
MessageData = ($message.MixedTokensErrorMessage);
136+
callStack = (Get-PSCallStack | Select-Object -First 1);
137+
logLevel = 'warning';
138+
InformationAction = $O365Object.InformationAction;
139+
Tags = @('Monkey365ImportTokenInfo');
140+
}
141+
Write-Warning @msg
142+
#Clear array
143+
$allAuthObjects.Clear()
144+
}
145+
}
146+
}
147+
Catch{
148+
Write-Error $_
149+
}
150+
}
151+
End{
152+
If($allAuthObjects.Count -gt 0){
153+
#Importing tokens
154+
ForEach($accessToken in $allAuthObjects){
155+
$tokenResource = Read-JWTtoken -token $accessToken.AccessToken | Select-Object -ExpandProperty aud -ErrorAction Ignore | Get-MSServiceFromAudience
156+
If($null -ne $tokenResource){
157+
$msg = @{
158+
MessageData = ($message.ValidTokenInfoMessage -f $tokenResource);
159+
callStack = (Get-PSCallStack | Select-Object -First 1);
160+
logLevel = 'info';
161+
InformationAction = $O365Object.InformationAction;
162+
Tags = @('Monkey365ImportTokenInfo');
163+
}
164+
Write-Information @msg
165+
$msg = @{
166+
MessageData = ($message.ImportTokenInfoMessage);
167+
callStack = (Get-PSCallStack | Select-Object -First 1);
168+
logLevel = 'info';
169+
InformationAction = $O365Object.InformationAction;
170+
Tags = @('Monkey365ImportTokenInfo');
171+
}
172+
Write-Information @msg
173+
If($tokenResource.ToLower() -eq 'sharepoint'){
174+
If($accessToken.resource.ToLower() -match "admin"){
175+
$O365Object.auth_tokens.SharePointAdminOnline = $accessToken;
176+
}
177+
Else{
178+
$O365Object.auth_tokens.SharePointOnline = $accessToken;
179+
}
180+
}
181+
ElseIf($tokenResource.ToLower() -eq 'exchangeonline'){
182+
$O365Object.auth_tokens.ExchangeOnline = $accessToken;
183+
$O365Object.auth_tokens.ComplianceCenter = $accessToken;
184+
}
185+
Else{
186+
$O365Object.auth_tokens.Item($tokenResource) = $accessToken;
187+
}
188+
}
189+
}
190+
}
191+
}
192+
}

core/utils/localized.psd1

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,4 +185,9 @@ CompressingJob = Compressing Monkey data into {0}
185185
TokenAcquiredGenericMessage = A new token was successfully acquired
186186
LocalCDNMessage = Local CDN set at {0}
187187
LocalCDNErrorMessage = Unable to produce local html report. The error was {0}
188+
ValidTokenInfoMessage = A valid access token was found for {0}
189+
ImportTokenInfoMessage = Import token into Monkey365
190+
MixedTokensErrorMessage = Unable to import access tokens. Missing TenantId parameter or mixed tokens detected
191+
SPOTokenImportErrorMessage = Unable to import access token for SharePoint Online. Unable to get valid URL
192+
ConnectImportTokenErrorMessage = Unable to execute Monkey365 using external access tokens
188193
'@;

0 commit comments

Comments
 (0)