Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added

- Updated docs for the module.
- Release Candidate
- Update wiki pages.

## [0.2.0-preview0001] - 2025-03-14

### Added

- Added cert options to the GraphAppToolkit send email.
- Updated auth methods to invoke needed permissions only.
- Added private functions to handle existing certs and secrets.
Expand Down
228 changes: 154 additions & 74 deletions README.md

Large diffs are not rendered by default.

90 changes: 85 additions & 5 deletions README2.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,20 +77,100 @@ Publish-TkEmailApp -ExistingAppObjectId <String> -CertPrefix <String> [-CertThum
| <nobr>ReturnParamSplat</nobr> | | If specified, return the parameter splat for use in other functions. | false | false | False |
| <nobr>DoNotUseDomainSuffix</nobr> | | Switch to add session domain suffix to the app name. | false | false | False |
### Note
This cmdlet requires that the user running the cmdlet have the necessary permissions to create the app and connect to Exchange Online. Permissions required for app registration: - 'Application.ReadWrite.All' - 'DelegatedPermissionGrant.ReadWrite.All' - 'Directory.ReadWrite.All' - 'RoleManagement.ReadWrite.Directory' Permissions granted to the app: - 'Mail.Send' \(Application\\) - Send mail as any user Exchange application policy restricts send to a mail enabled security group
This cmdlet requires that the user running the cmdlet have the necessary permissions to create the app and connect to Exchange Online.

### Examples
**EXAMPLE 1**
```powershell
Publish-TkEmailApp -AppPrefix 'Gtk' -AuthorizedSenderUserName 'user@example.com' -MailEnabledSendingGroup 'group@example.com'
# Permissions required for app registration:
- 'Application.ReadWrite.All'
- 'DelegatedPermissionGrant.ReadWrite.All'
- 'Directory.ReadWrite.All'
- 'RoleManagement.ReadWrite.Directory'
# Permissions granted to the app:
- 'Mail.Send' (Application) - Send mail as any user
# Exchange application policy restricts send to a mail enabled security group
# Ensure a mail enabled sending group is created first:
$DefaultDomain = 'contoso.com'
$MailEnabledSendingGroupToCreate = "CTSO-GraphAPIMail"
# Creates a mail-enabled security group named "MySenders" using a default domain
$group = New-MailEnabledSendingGroup -Name $MailEnabledSendingGroupToCreate -DefaultDomain $DefaultDomain
# Create a new Graph Email App for a single tenant
$LicensedUserToSendAs = 'helpdesk@contoso.com'
Publish-TkEmailApp `
-AuthorizedSenderUserName $LicensedUserToSendAs `
-MailEnabledSendingGroup $group.PrimarySmtpAddress `
-ReturnParamSplat
# Returns an app named like 'GraphToolKit-Gtk-<Session AD Domain>-As-helpdesk'
# Returns a param splat that can be used as input for the send mail function:
# Example:
$params = @{
AppId = 'your-app-id'
Id = 'your-app-object-id'
AppName = 'GraphToolKit-Gtk-<Session AD Domain>-As-helpdesk'
CertificateSubject = 'GraphToolKit-GTK-<Session AD Domain>-As-helpdesk'
AppRestrictedSendGroup = 'CTSO-GraphAPIMail@contoso.com'
CertExpires = 'yyyy-MM-dd HH:mm:ss'
CertThumbprint = 'your-cert-thumbprint'
ConsentUrl = 'https://login.microsoftonline.com/<your-tenant-id>/adminconsent?client_id=<your-app-id>'
DefaultDomain = 'contoso.com'
SendAsUser = 'helpdesk'
SendAsUserEmail = 'helpdesk@contoso.com'
TenantID = 'your-tenant-id'
}
```
Creates a new Graph Email App with the specified parameters.


**EXAMPLE 2**
```powershell
Publish-TkEmailApp -ExistingAppObjectId '12345678-1234-1234-1234-1234567890ab' -CertPrefix 'Cert'
# Create a multi client app registration where one app exists and multiple certificates are associated to the app:
# Initial setup:
# Create the group as before (or reuse the existing group) and run the following commands:
$LicensedUserToSendAs = 'helpdesk@contoso.com'
$CertPrefix = "CTSO" # First Company prefix. This will be used to prefix the certificate subject.
Publish-TkEmailApp `
-CertPrefix $CertPrefix `
-AuthorizedSenderUserName $LicensedUserToSendAs `
-MailEnabledSendingGroup $group.PrimarySmtpAddress `
-ReturnParamSplat
# Returns an app named like 'GraphToolKit-Gtk-<Session AD Domain>-As-helpdesk'
$params = @{
AppId = 'your-app-id'
Id = 'your-app-object-id'
AppName = 'GraphToolKit-Gtk-<Session AD Domain>-As-helpdesk'
CertificateSubject = 'GraphToolKit-CTSO-<Session AD Domain>-As-helpdesk'
AppRestrictedSendGroup = 'CTSO-GraphAPIMail@contoso.com'
CertExpires = 'yyyy-MM-dd HH:mm:ss'
CertThumbprint = 'your-cert-thumbprint'
ConsentUrl = 'https://login.microsoftonline.com/<your-tenant-id>/adminconsent?client_id=<your-app-id>'
DefaultDomain = 'contoso.com'
SendAsUser = 'helpdesk'
SendAsUserEmail = 'helpdesk@contoso.com'
TenantID = 'your-tenant-id'
}
$useExistingParams = @{
ExistingAppObjectId = $params.Id
CertPrefix = 'NewCompany'
OverwriteVaultSecret = $true # optional, if you want to overwrite the existing vault secret
ReturnParamSplat = $true # optional, returns the param splat
}
Publish-TkEmailApp @useExistingParams
# The new Cert will be prefixed with the new company prefix and will allow the current client to authenticate.
# Back in the app registrations console, if you look at the internal notes in the properties of the app:
# The app's "Internal Notes" will be populated with the following json:
# Assists in tracking the app's usage and configuration.
{
"GraphEmailAppFor": "helpdesk@contoso.com",
"RestrictedToGroup": "CTSO-GraphAPIMail@contoso.com",
"AppPermissions": "Mail.Send",
"New-Company_ClientIP": "<Public IP Address of the client where the app was called>",
"New-Company_Host": "<Host of the client where the app was called>",
"NewCoolCompany_ClientIP": "<Public IP Address of the client where the app was called>",
"NewCoolCompany_Host": "Host of the client where the app was called>"
}
# New cert additions added through the toolkit will append new client info to these notes.
```
Uses an existing app and attaches a certificate with the specified prefix.


## Publish-TkM365AuditApp
### Synopsis
Expand Down
103 changes: 86 additions & 17 deletions docs/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<!--
<auto-generated>
<synopsis>
This code was generated by a psDoc. on: 03/14/2025 09:22:12
This code was generated by a psDoc. on: 03/14/2025 14:18:51
Get it here: https://github.com/ChaseFlorell/psDoc
</synopsis>
<description>
Expand Down Expand Up @@ -387,30 +387,99 @@ <h3> Parameters </h3>
<div class='panel-heading'>
<h3 class='panel-title'> Note </h3>
</div>
<div class='panel-body'>This cmdlet requires that the user running the cmdlet have the necessary permissions to create the app and connect to Exchange Online.
Permissions required for app registration:
- 'Application.ReadWrite.All'
- 'DelegatedPermissionGrant.ReadWrite.All'
- 'Directory.ReadWrite.All'
- 'RoleManagement.ReadWrite.Directory'

Permissions granted to the app:
- 'Mail.Send' (Application) - Send mail as any user
Exchange application policy restricts send to a mail enabled security group</div>
<div class='panel-body'>This cmdlet requires that the user running the cmdlet have the necessary permissions to create the app and connect to Exchange Online.</div>
</div>
<div>
<h3> Examples </h3>
</div>
<div class='panel panel-default'>
<div class='panel-body'>
<strong>EXAMPLE 1</strong>
<pre class="brush: ps">Publish-TkEmailApp -AppPrefix 'Gtk' -AuthorizedSenderUserName 'user@example.com' -MailEnabledSendingGroup 'group@example.com'</pre>
<div><p>Creates a new Graph Email App with the specified parameters.</p>
</div>
<pre class="brush: ps"># Permissions required for app registration:
- 'Application.ReadWrite.All'
- 'DelegatedPermissionGrant.ReadWrite.All'
- 'Directory.ReadWrite.All'
- 'RoleManagement.ReadWrite.Directory'
# Permissions granted to the app:
- 'Mail.Send' (Application) - Send mail as any user
# Exchange application policy restricts send to a mail enabled security group
# Ensure a mail enabled sending group is created first:
$DefaultDomain = 'contoso.com'
$MailEnabledSendingGroupToCreate = "CTSO-GraphAPIMail"
# Creates a mail-enabled security group named "MySenders" using a default domain
$group = New-MailEnabledSendingGroup -Name $MailEnabledSendingGroupToCreate -DefaultDomain $DefaultDomain
# Create a new Graph Email App for a single tenant
$LicensedUserToSendAs = 'helpdesk@contoso.com'
Publish-TkEmailApp `
-AuthorizedSenderUserName $LicensedUserToSendAs `
-MailEnabledSendingGroup $group.PrimarySmtpAddress `
-ReturnParamSplat
# Returns an app named like 'GraphToolKit-Gtk-&lt;Session AD Domain&gt;-As-helpdesk'
# Returns a param splat that can be used as input for the send mail function:
# Example:
$params = @{
AppId = 'your-app-id'
Id = 'your-app-object-id'
AppName = 'GraphToolKit-Gtk-&lt;Session AD Domain&gt;-As-helpdesk'
CertificateSubject = 'GraphToolKit-GTK-&lt;Session AD Domain&gt;-As-helpdesk'
AppRestrictedSendGroup = 'CTSO-GraphAPIMail@contoso.com'
CertExpires = 'yyyy-MM-dd HH:mm:ss'
CertThumbprint = 'your-cert-thumbprint'
ConsentUrl = 'https://login.microsoftonline.com/&lt;your-tenant-id&gt;/adminconsent?client_id=&lt;your-app-id&gt;'
DefaultDomain = 'contoso.com'
SendAsUser = 'helpdesk'
SendAsUserEmail = 'helpdesk@contoso.com'
TenantID = 'your-tenant-id'
}</pre>
<div></div>
<strong>EXAMPLE 2</strong>
<pre class="brush: ps">Publish-TkEmailApp -ExistingAppObjectId '12345678-1234-1234-1234-1234567890ab' -CertPrefix 'Cert'</pre>
<div><p>Uses an existing app and attaches a certificate with the specified prefix.</p>
</div>
<pre class="brush: ps"># Create a multi client app registration where one app exists and multiple certificates are associated to the app:
# Initial setup:
# Create the group as before (or reuse the existing group) and run the following commands:
$LicensedUserToSendAs = 'helpdesk@contoso.com'
$CertPrefix = "CTSO" # First Company prefix. This will be used to prefix the certificate subject.
Publish-TkEmailApp `
-CertPrefix $CertPrefix `
-AuthorizedSenderUserName $LicensedUserToSendAs `
-MailEnabledSendingGroup $group.PrimarySmtpAddress `
-ReturnParamSplat
# Returns an app named like 'GraphToolKit-Gtk-&lt;Session AD Domain&gt;-As-helpdesk'
$params = @{
AppId = 'your-app-id'
Id = 'your-app-object-id'
AppName = 'GraphToolKit-Gtk-&lt;Session AD Domain&gt;-As-helpdesk'
CertificateSubject = 'GraphToolKit-CTSO-&lt;Session AD Domain&gt;-As-helpdesk'
AppRestrictedSendGroup = 'CTSO-GraphAPIMail@contoso.com'
CertExpires = 'yyyy-MM-dd HH:mm:ss'
CertThumbprint = 'your-cert-thumbprint'
ConsentUrl = 'https://login.microsoftonline.com/&lt;your-tenant-id&gt;/adminconsent?client_id=&lt;your-app-id&gt;'
DefaultDomain = 'contoso.com'
SendAsUser = 'helpdesk'
SendAsUserEmail = 'helpdesk@contoso.com'
TenantID = 'your-tenant-id'
}
$useExistingParams = @{
ExistingAppObjectId = $params.Id
CertPrefix = 'NewCompany'
OverwriteVaultSecret = $true # optional, if you want to overwrite the existing vault secret
ReturnParamSplat = $true # optional, returns the param splat
}
Publish-TkEmailApp @useExistingParams
# The new Cert will be prefixed with the new company prefix and will allow the current client to authenticate.
# Back in the app registrations console, if you look at the internal notes in the properties of the app:
# The app's "Internal Notes" will be populated with the following json:
# Assists in tracking the app's usage and configuration.
{
"GraphEmailAppFor": "helpdesk@contoso.com",
"RestrictedToGroup": "CTSO-GraphAPIMail@contoso.com",
"AppPermissions": "Mail.Send",
"New-Company_ClientIP": "&lt;Public IP Address of the client where the app was called&gt;",
"New-Company_Host": "&lt;Host of the client where the app was called&gt;",
"NewCoolCompany_ClientIP": "&lt;Public IP Address of the client where the app was called&gt;",
"NewCoolCompany_Host": "Host of the client where the app was called&gt;"
}
# New cert additions added through the toolkit will append new client info to these notes.</pre>
<div></div>
</div>
</div>
<p class='pull-right'><a onclick='document.body.scrollTop = document.documentElement.scrollTop = 0;' style='cursor: pointer;'>Top of page</a>
Expand Down
4 changes: 2 additions & 2 deletions help/GraphAppToolkit.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ Locale: en-US

# GraphAppToolkit Module
## Description
The GraphAppToolkit module provides a collection of PowerShell functions to automate the management of Azure AD (Entra ID) application registrations. It streamlines the deployment of Microsoft Graph-powered applications, focusing on app-only authentication using certificates, secure credential storage, and operational automation. This module is designed to: - Enable certificate-based authentication for Microsoft Graph applications. - Simplify email sending from service principals. - Automate Intune (MEM) policy management . - Deploy M365 audit apps with read-write permissions. - Securely manage mail-enabled security groups for restricted send scenarios. GraphAppToolkit is ideal for IT admins, security engineers, and DevOps teams managing Microsoft 365 and Entra ID workloads.
{{ Fill in the Description }}

## GraphAppToolkit Cmdlets
### [New-MailEnabledSendingGroup](New-MailEnabledSendingGroup)
Creates or retrieves a mail-enabled security group with a custom or default domain.

### [Publish-TkEmailApp](Publish-TkEmailApp)
Deploys a new Microsoft Graph Email app and associates it with a certificate for app-only authentication.
Publishes a new or existing Graph Email App with specified configurations.

### [Publish-TkM365AuditApp](Publish-TkM365AuditApp)
Publishes (creates) a new M365 Audit App registration in Entra ID (Azure AD) with a specified certificate.
Expand Down
51 changes: 33 additions & 18 deletions help/New-MailEnabledSendingGroup.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,29 +25,41 @@ New-MailEnabledSendingGroup -Name <String> [-Alias <String>] -DefaultDomain <Str
```

## DESCRIPTION
The New-MailEnabledSendingGroup function ensures that a mail-enabled security
group is available for restricting email sending.
It connects to Exchange Online
to verify if a group of the specified name already exists.
If the existing group
is security-enabled, the function returns it; otherwise, it creates a new group
of type "security" using either a custom primary SMTP address (CustomDomain) or
a constructed address (DefaultDomain).
The New-MailEnabledSendingGroup function ensures that a mail-enabled security group is
available for restricting email sending in Exchange Online.
If a group of the specified
name already exists and is security-enabled, the function returns that group.
Otherwise,
it creates a new security-enabled distribution group.
You can specify either a custom
primary SMTP address (via the 'CustomDomain' parameter set) or construct one using an
alias and default domain (via the 'DefaultDomain' parameter set).
By default, the 'CustomDomain' parameter set is used.
If you wish to construct the SMTP
address from the alias, switch to the 'DefaultDomain' parameter set.

## EXAMPLES

### EXAMPLE 1
```
New-MailEnabledSendingGroup -Name "SecureSenders" -DefaultDomain "contoso.com"
Creates a new mail-enabled security group named "SecureSenders" with a primary SMTP address
of SecureSenders@contoso.com.
```

Creates a new mail-enabled security group named "SecureSenders" with
a primary SMTP address of SecureSenders@contoso.com.
### EXAMPLE 2
```
New-MailEnabledSendingGroup -Name "SecureSenders" -Alias "Senders" -PrimarySmtpAddress "Senders@customdomain.org"
Creates a new mail-enabled security group named "SecureSenders" with an alias "Senders"
and a primary SMTP address of Senders@customdomain.org.
```

## PARAMETERS

### -Name
The name of the mail-enabled security group to create or retrieve.
This is also used as
the alias if no separate Alias parameter is provided.

```yaml
Type: String
Expand Down Expand Up @@ -78,8 +90,9 @@ Accept wildcard characters: False
```

### -PrimarySmtpAddress
(CustomDomain parameter set) The primary SMTP address to assign when using
a custom domain (e.g., MyGroup@contoso.com).
(CustomDomain parameter set) The full SMTP address for the group (e.g.
"MyGroup@contoso.com").
This parameter is mandatory when using the 'CustomDomain' parameter set.

```yaml
Type: String
Expand All @@ -94,8 +107,9 @@ Accept wildcard characters: False
```

### -DefaultDomain
(DefaultDomain parameter set) The domain to append to the alias, forming
an SMTP address (e.g., Alias@DefaultDomain).
(DefaultDomain parameter set) The domain portion to be appended to the group alias (e.g.
"Alias@DefaultDomain").
This parameter is mandatory when using the 'DefaultDomain' parameter set.

```yaml
Type: String
Expand All @@ -110,7 +124,8 @@ Accept wildcard characters: False
```

### -WhatIf
Shows what would happen if the cmdlet runs. The cmdlet is not run.
Shows what would happen if the cmdlet runs.
The cmdlet is not run.

```yaml
Type: SwitchParameter
Expand Down Expand Up @@ -165,8 +180,8 @@ This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable
### Microsoft.Exchange.Data.Directory.Management.DistributionGroup
### Returns the newly created or existing mail-enabled security group object.
## NOTES
Requires connectivity to Exchange Online.
The caller must have sufficient
privileges to create or modify distribution groups.
- Requires connectivity to Exchange Online (Connect-TkMsService -ExchangeOnline).
- The caller must have sufficient privileges to create or modify distribution groups.
- DefaultParameterSetName = 'CustomDomain'.

## RELATED LINKS
Loading