Skip to content

Commit 52d3b9d

Browse files
committed
update docs
1 parent 33742f1 commit 52d3b9d

File tree

16 files changed

+583
-162
lines changed

16 files changed

+583
-162
lines changed

.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,15 @@
11
# logs
2+
azurereview.log
23
/log/*.log
34

45
# Data folder
56
monkey-reports*
67

8+
# Azurite
9+
__azurite_db_queue__.json
10+
__azurite_db_queue_extent__.json
11+
12+
site/
713
*.csv
814
*bak
915
*.ps1.bak

Invoke-Monkey365.ps1

Lines changed: 131 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ Function Invoke-Monkey365{
224224

225225
# Secure secret of the client requesting the token.
226226
[Parameter(Mandatory = $true, ParameterSetName = 'ClientSecret-App')]
227-
[securestring]$ClientSecret,
227+
[System.Security.SecureString]$ClientSecret,
228228

229229
# Secure secret of the client requesting the token.
230230
[Parameter(Mandatory = $true, ParameterSetName = 'ClientSecret-InputObject', HelpMessage = 'PsCredential')]
@@ -255,7 +255,7 @@ Function Invoke-Monkey365{
255255

256256
# Secure password of the certificate
257257
[Parameter(Mandatory = $false,ParameterSetName = 'ClientAssertionCertificate-File', HelpMessage = 'Certificate password')]
258-
[Security.SecureString]$CertFilePassword,
258+
[System.Security.SecureString]$CertFilePassword,
259259

260260
[parameter(Mandatory= $false, HelpMessage= "json file with all rules")]
261261
[ValidateScript({
@@ -306,7 +306,13 @@ Function Invoke-Monkey365{
306306
[Switch]$ForceMSALDesktop,
307307

308308
[Parameter(Mandatory=$false, HelpMessage="List available collectors")]
309-
[Switch]$ListCollector
309+
[Switch]$ListCollector,
310+
311+
[Parameter(Mandatory=$false, HelpMessage="List available rules")]
312+
[Switch]$ListRule,
313+
314+
[Parameter(Mandatory=$false, HelpMessage="List available frameworks")]
315+
[Switch]$ListFramework
310316
)
311317
dynamicparam{
312318
# Set available instance class
@@ -389,7 +395,7 @@ Function Invoke-Monkey365{
389395
$paramDictionary.Add($rsrc_pname, $rsrc_type_dynParam)
390396
}
391397
#Add parameters for Microsoft365 instance
392-
if($null -ne (Get-Variable -Name Instance -ErrorAction Ignore) -and $Instance -eq 'Microsoft365'){
398+
If($null -ne (Get-Variable -Name Instance -ErrorAction Ignore) -and $Instance -eq 'Microsoft365'){
393399
#Create the -ScanSites string parameter
394400
$attributeCollection = New-Object -TypeName System.Collections.ObjectModel.Collection[System.Attribute]
395401
# define a new parameter attribute
@@ -400,6 +406,43 @@ Function Invoke-Monkey365{
400406
$rg_type_dynParam = New-Object -TypeName System.Management.Automation.RuntimeDefinedParameter($rg_pname,
401407
[string[]], $attributeCollection)
402408
$paramDictionary.Add($rg_pname, $rg_type_dynParam)
409+
#Add PowerBI/Fabric ClientId parameter attribute
410+
$clientIdAttr = New-Object System.Management.Automation.ParameterAttribute
411+
$clientIdAttr.Mandatory = $false
412+
$clientIdAttrCollection = New-Object -Type System.Collections.ObjectModel.Collection[System.Attribute]
413+
$clientIdAttrCollection.Add($clientIdAttr)
414+
$clientIdParam = New-Object System.Management.Automation.RuntimeDefinedParameter('PowerBIClientId', [System.String], $clientIdAttrCollection)
415+
$paramDictionary.Add('PowerBIClientId', $clientIdParam)
416+
#Add PowerBI/Fabric Client Secret parameter attribute
417+
$clientSecretAttr = New-Object System.Management.Automation.ParameterAttribute
418+
$clientSecretAttr.Mandatory = $false
419+
$clientSecretAttrCollection = New-Object -Type System.Collections.ObjectModel.Collection[System.Attribute]
420+
$clientSecretAttrCollection.Add($clientSecretAttr)
421+
$clientSecretParam = New-Object System.Management.Automation.RuntimeDefinedParameter('PowerBIClientSecret', [System.Security.SecureString], $clientSecretAttrCollection)
422+
$paramDictionary.Add('PowerBIClientSecret', $clientSecretParam)
423+
#Add PowerBI/Fabric PSCredential parameter attribute
424+
$pscredAttr = New-Object System.Management.Automation.ParameterAttribute
425+
$pscredAttr.Mandatory = $false
426+
$pscredAttrCollection = New-Object -Type System.Collections.ObjectModel.Collection[System.Attribute]
427+
$pscredAttrCollection.Add($pscredAttr)
428+
$pscredParam = New-Object System.Management.Automation.RuntimeDefinedParameter('PowerBIClientCredentials', [System.Management.Automation.PSCredential], $pscredAttrCollection)
429+
$paramDictionary.Add('PowerBIClientCredentials', $pscredParam)
430+
#Add PowerBI/Fabric Certificate parameter attribute
431+
$certFileAttr = New-Object System.Management.Automation.ParameterAttribute
432+
$certFileAttr.Mandatory = $false
433+
$certFileAttrCollection = New-Object -Type System.Collections.ObjectModel.Collection[System.Attribute]
434+
$certFileAttrCollection.Add($certFileAttr)
435+
$validateScriptAttr = New-Object System.Management.Automation.ValidateScriptAttribute({ Test-Path -Path $_ -PathType Leaf })
436+
$certFileAttrCollection.Add($validateScriptAttr)
437+
$certFileParam = New-Object System.Management.Automation.RuntimeDefinedParameter('PowerBICertificateFile', [System.IO.FileInfo], $certFileAttrCollection)
438+
$paramDictionary.Add('PowerBICertificateFile', $certFileParam)
439+
#Add PowerBI/Fabric Certificate password parameter attribute
440+
$certPassAttr = New-Object System.Management.Automation.ParameterAttribute
441+
$certPassAttr.Mandatory = $false
442+
$certPassAttrCollection = New-Object -Type System.Collections.ObjectModel.Collection[System.Attribute]
443+
$certPassAttrCollection.Add($certPassAttr)
444+
$passParam = New-Object System.Management.Automation.RuntimeDefinedParameter('PowerBICertificatePassword', [System.Security.SecureString], $certPassAttrCollection)
445+
$paramDictionary.Add('PowerBICertificatePassword', $passParam)
403446
}
404447
# return the collection of dynamic parameters
405448
$paramDictionary
@@ -428,10 +471,10 @@ Function Invoke-Monkey365{
428471
#Get command Metadata
429472
$MetaData = New-Object -TypeName "System.Management.Automation.CommandMetaData" (Get-Command -Name "Format-MonkeyCollector")
430473
$newPsboundParams = [ordered]@{}
431-
if($null -ne $MetaData){
474+
If($null -ne $MetaData){
432475
$param = $MetaData.Parameters.Keys
433-
foreach($p in $param.GetEnumerator()){
434-
if($PSBoundParameters.ContainsKey($p)){
476+
ForEach($p in $param.GetEnumerator()){
477+
If($PSBoundParameters.ContainsKey($p)){
435478
$newPsboundParams.Add($p,$PSBoundParameters[$p])
436479
}
437480
}
@@ -452,7 +495,87 @@ Function Invoke-Monkey365{
452495
[void]$newPsboundParams.Add('Provider',$PSBoundParameters['Instance']);
453496
}
454497
#Execute command
455-
Format-MonkeyCollector @newPsboundParams
498+
$a = Format-MonkeyCollector @newPsboundParams
499+
Write-Output $a -NoEnumerate
500+
}
501+
return
502+
}
503+
#Check if list collectors
504+
If($PSBoundParameters.ContainsKey('ListRule') -and $PSBoundParameters['ListRule'].IsPresent){
505+
#Get command Metadata
506+
$MetaData = New-Object -TypeName "System.Management.Automation.CommandMetaData" (Get-Command -Name "Get-Rule")
507+
$newPsboundParams = [ordered]@{}
508+
if($null -ne $MetaData){
509+
$param = $MetaData.Parameters.Keys
510+
foreach($p in $param.GetEnumerator()){
511+
if($PSBoundParameters.ContainsKey($p)){
512+
$newPsboundParams.Add($p,$PSBoundParameters[$p])
513+
}
514+
}
515+
#Add verbose, debug
516+
$newPsboundParams.Add('Verbose',$O365Object.verbose)
517+
$newPsboundParams.Add('Debug',$O365Object.debug)
518+
$newPsboundParams.Add('InformationAction',$O365Object.InformationAction)
519+
#Add pretty print
520+
[void]$newPsboundParams.Add('Pretty',$true);
521+
#Add RulesPath
522+
If($newPsboundParams.Contains('RulesPath')){
523+
$newPsboundParams.RulesPath = $O365Object.rulesPath;
524+
}
525+
Else{
526+
[void]$newPsboundParams.Add('RulesPath',$O365Object.rulesPath);
527+
}
528+
#Remove RuleSet if null
529+
If($newPsboundParams.Contains('RuleSet') -and $null -eq $newPsboundParams['RuleSet']){
530+
[void]$newPsboundParams.Remove('RuleSet');
531+
}
532+
#Remove instance if EntraID is selected
533+
If($newPsboundParams.Contains('Instance') -and $newPsboundParams['Instance'] -eq 'EntraID'){
534+
[void]$newPsboundParams.Remove('Instance');
535+
}
536+
#Remove Instance if null
537+
If($newPsboundParams.Contains('Instance') -and $null -eq $newPsboundParams['Instance']){
538+
[void]$newPsboundParams.Remove('Instance');
539+
}
540+
#Execute command
541+
Get-Rule @newPsboundParams
542+
}
543+
return
544+
}
545+
#Check if list collectors
546+
If($PSBoundParameters.ContainsKey('ListFramework') -and $PSBoundParameters['ListFramework'].IsPresent){
547+
#Get command Metadata
548+
$MetaData = New-Object -TypeName "System.Management.Automation.CommandMetaData" (Get-Command -Name "Get-Framework")
549+
$newPsboundParams = [ordered]@{}
550+
If($null -ne $MetaData){
551+
$param = $MetaData.Parameters.Keys
552+
ForEach($p in $param.GetEnumerator()){
553+
If($PSBoundParameters.ContainsKey($p)){
554+
$newPsboundParams.Add($p,$PSBoundParameters[$p])
555+
}
556+
}
557+
#Add verbose, debug
558+
$newPsboundParams.Add('Verbose',$O365Object.verbose)
559+
$newPsboundParams.Add('Debug',$O365Object.debug)
560+
$newPsboundParams.Add('InformationAction',$O365Object.InformationAction)
561+
#Remove Ruleset if not present
562+
If($null -eq $newPsboundParams.Item('RuleSet')){
563+
[void]$newPsboundParams.Remove('RuleSet');
564+
}
565+
#Remove RulesPath if not present
566+
If($null -eq $newPsboundParams.Item('RulesPath')){
567+
[void]$newPsboundParams.Remove('RulesPath');
568+
}
569+
#Remove Ruleset when RulesPath is also selected
570+
If($null -ne $newPsboundParams.Item('RuleSet') -and $null -ne $newPsboundParams.Item('RulesPath')){
571+
[void]$newPsboundParams.Remove('RuleSet');
572+
}
573+
#If none is present, add default path
574+
If($newPsboundParams.Keys -notcontains "RuleSet" -and $newPsboundParams.Keys -notcontains "RulesPath"){
575+
[void]$newPsboundParams.Add('RulesPath',$O365Object.rulesPath);
576+
}
577+
#Execute command
578+
Get-Framework @newPsboundParams
456579
}
457580
return
458581
}
@@ -525,10 +648,6 @@ Function Invoke-Monkey365{
525648
Remove-Variable -Name OutFolder -Scope Script -Force -ErrorAction Ignore
526649
#Remove returnData variable
527650
Remove-Variable -Name returnData -Scope Script -Force -ErrorAction Ignore
528-
#Remove LogQueue
529-
Remove-Variable -Name MonkeyLogQueue -Scope Global -ErrorAction Ignore -Force
530-
#collect garbage
531-
[System.GC]::GetTotalMemory($true) | out-null
532651
}
533652
}
534653
}
143 KB
Loading

docs/assets/images/listrules.png

242 KB
Loading
194 KB
Loading

docs/authentication/authFlows/ropc.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ author: Juan Garrido
66

77
The Microsoft identity platform supports the OAuth 2.0 Resource Owner Password Credentials (ROPC) grant, which allows an application to sign in the user by directly handling their password. In this flow, client identification (e.g. user's email address) and user's credentials is sent to the identity server, and then a token is received.
88

9-
## Security Note
10-
There are multiple scenarios in which ROPC is not supported, such as hybrid identity federation access (Azure AD and ADFS) or when conditional access policies are enabled. There are more secure and available recommended alternatives, such as [Interactive authentication](interactive.md) or [Service Principal](sp.md).
9+
???+ Warning "Security Note"
10+
There are multiple scenarios in which ROPC is not supported, such as hybrid identity federation access (Entra ID and ADFS) or when conditional access policies are enabled. There are more secure and available recommended alternatives, such as [Interactive authentication](interactive.md) or [Service Principal](sp.md).
1111

1212
## Usage Examples
1313

docs/authentication/limitations.md

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,21 @@ Review the following sections to learn about current limitations of Monkey365 on
88

99
## SharePoint Online in PowerShell Core
1010

11-
Monkey365 is using the **SharePoint Online Management Shell** ClientId when Interactive authentication flow is used. In order to give support to .NET Core, developers must set the reply URI to **http://localhost**, because .NET Core does not have an integrated UI. Due to **SharePoint Online Management Shell** is not configured to use **http://localhost** in the reply URI, authentication methods such as [Interactive browser authentication](authFlows/interactive.md) or [Authentication with a username and password](authFlows/ropc.md) are not supported in SharePoint Online when Monkey365 is executed using PowerShell Core (PowerShell 6 or later and PowerShell in NIX environments). The following options are available to avoid authentication issues:
11+
When using the Interactive authentication flow, Monkey365 relies on the **SharePoint Online Management Shell ClientId**. To support .NET Core, which lacks a built-in user interface, developers must configure the reply URI as `http://localhost`. However, since the SharePoint Online Management Shell is not set up to accept `http://localhost` as a reply URI, certain authentication methods like [Interactive browser authentication](authFlows/interactive.md) or [Authentication with a username and password](authFlows/ropc.md) are not compatible with SharePoint Online when Monkey365 is run via PowerShell Core (PowerShell 6+, including NIX environments).
1212

13-
### Change the authentication flow
13+
To avoid authentication issues, consider the following alternatives:
1414

15-
* Change the authentication flow to [Device Code Authentication](authFlows/devicecode.md) or [Certificate-based Authentication](authFlows/sp.md).
15+
* Switch Authentication Flow
1616

17-
* Execute Monkey365 using the PowerShell V5 Default version. <span style="color:red">*Only valid on Windows environments*</span>
17+
Use [Device Code Authentication](authFlows/devicecode.md) or [Certificate-based Authentication](authFlows/sp.md) instead of the Interactive flow.
1818

19-
* Use the `-ForceMSALDesktop` parameter will force PowerShell 6 and higher to load .NET MSAL libraries instead of .NET core versions. <span style="color:red">*Only valid on Windows environments*</span>
19+
* Run Monkey365 with PowerShell V5
20+
21+
This option is only applicable in Windows environments and allows compatibility with the default authentication setup.
22+
23+
* Use the `-ForceMSALDesktop` Parameter
24+
25+
This forces PowerShell 6 and above to load the .NET MSAL desktop libraries instead of the .NET Core versions. This workaround is also limited to Windows environments.
2026

2127
## References
2228

docs/authentication/overview.md

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,17 @@ Monkey365 offers many ways to connect to both Azure and Microsoft 365 environmen
66
* [Interactive browser authentication](authFlows/interactive.md)
77
* [Authentication with a username and password](authFlows/ropc.md)
88
* [Device Code Authentication](authFlows/devicecode.md)
9-
* [Client Credential Authentication](authFlows/sp.md)
9+
* [Client Credential Authentication](authFlows/sp.md)
10+
11+
## Using service principals
12+
13+
Service principals in Microsoft Entra serve as representations of applications within a specific tenant. They outline the application's capabilities, the resources it can interact with, and the users permitted to utilize it. When an application is registered in Microsoft Entra ID, a service principal is automatically generated, enabling secure authentication and resource access for the application.
14+
15+
To set up a service principal for use with Monkey365, you'll need to follow these steps:
16+
17+
* Register an Application in Microsoft Entra ID
18+
* Create a Client Secret or Certificate
19+
* Assign API Permissions
20+
* Assign the required roles
21+
22+
Check the [Service Principal authentication section](sp_authentication/getting_started.md) for manual steps. Additionally, Monkey365 includes a [built-in utility](sp_authentication/automatic_setup.md) that streamlines the creation and configuration of Entra ID applications.
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
---
2+
author: Juan Garrido
3+
---
4+
5+
# Getting Started
6+
7+
Monkey365 includes a built-in utility that streamlines the creation and configuration of Entra ID applications for the following Microsoft services:
8+
9+
* Microsoft Graph
10+
* Microsoft Teams
11+
* Exchange Online
12+
* SharePoint Online
13+
14+
The utility automates the creation of an Entra ID application, configures permissions based on the selected services, and generates a certificate for authentication, which it then uploaded. It also assigns service-specific roles to the application. For instance, if SharePoint Online is chosen, the utility will grant the application the `SharePoint Online Administrator`role. If Exchange Online is chosen, the helper will grant the application the `Global Reader` role.
15+
16+
# Automatic Application Setup with Monkey365
17+
18+
## Running the Utility with Default Settings
19+
20+
To run the utility with default settings from the Monkey365 installation directory, use the following:
21+
22+
```PowerShell
23+
$p = @{
24+
TenantId = '00000000-0000-0000-0000-000000000000';
25+
Services = 'ExchangeOnline','MicrosoftGraph','MicrosoftTeams','SharePointOnline';
26+
}
27+
Register-Monkey365Application @p
28+
```
29+
30+
## Customizing Parameters (e.g., Certificate)
31+
32+
To override default settings—such as specifying a custom certificate—use this version of the script:
33+
34+
```PowerShell
35+
$p = @{
36+
TenantId = '00000000-0000-0000-0000-000000000000';
37+
Services = 'ExchangeOnline','MicrosoftGraph','MicrosoftTeams','SharePointOnline';
38+
Certificate = 'C:\Monkey365.cer'
39+
}
40+
Register-Monkey365Application @p
41+
```
42+
43+
After registering the application, you may need to manually grant admin consent for required permissions. To do this, navigate to:
44+
45+
* Azure Entra ID > App registrations
46+
* Select the Monkey365 app
47+
* Go to API permissions, and click !Grant admin consent for *your organisation*.
48+
49+
50+
???+ note
51+
You will need the following for Monkey365:
52+
53+
- Tenant ID: Found under Azure Entra ID > Overview.
54+
- Client ID: From the app registration overview.
55+
- Certificate: The one you created earlier.

0 commit comments

Comments
 (0)