diff --git a/Entra ID/Get-EntraIdAppAccessToken.ps1 b/Entra ID/Get-EntraIdAppAccessToken.ps1 new file mode 100644 index 0000000..01132a5 --- /dev/null +++ b/Entra ID/Get-EntraIdAppAccessToken.ps1 @@ -0,0 +1,187 @@ +<# +.SYNOPSIS + Authenticates to Microsoft Graph using either a certificate or client secret and retrieves an access token. + +.DESCRIPTION + This script supports two authentication methods for accessing Microsoft Graph: certificate-based and client secret-based. + Depending on the provided parameters, it constructs the appropriate request and retrieves an OAuth 2.0 access token from + Microsoft Identity Platform. + +.PARAMETER Certificate + The X.509 certificate used for certificate-based authentication. This parameter is mandatory for the CertificateAuth parameter set. + +.PARAMETER PfxCertificate + The PFX certificate used for signing the JWT in certificate-based authentication. This parameter is mandatory for the CertificateAuth parameter set. + +.PARAMETER ClientId + The client ID of the application in Azure AD. This parameter is mandatory for the ClientSecretAuth parameter set. + +.PARAMETER ClientSecret + The client secret associated with the application in Azure AD. This parameter is mandatory for the ClientSecretAuth parameter set. + +.PARAMETER Scope + The scope of the access request. The default value is 'https://graph.microsoft.com/.default'. + +.PARAMETER TenantId + The Azure AD tenant ID. This parameter is mandatory. + +.PARAMETER ApplicationId + The application ID of the Azure AD application. This parameter is mandatory. + +.NOTES + For more information on Microsoft identity platform and OAuth 2.0, visit: + https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-client-creds-grant-flow + +.EXAMPLE + PS> $tenantId = (Get-AzContext).Tenant.Id + PS> $appId = (Get-AzADApplication -DisplayName 'someapp').AppId + PS> $pfxCert = get-pfxcertificate -FilePath 'path\to\your\pfx\file.pfx' + PS> $cert = get-pfxcertificate -FilePath 'path\to\your\cert\file.cer' + PS> .\Get-EntraIdAppAccessToken.ps1 -Certificate $cert -PfxCertificate $pfxCert -TenantId $tenantId -ApplicationId $appId + + + This example demonstrates how to use certificate-based authentication to retrieve an access token from Microsoft Graph. + +.EXAMPLE + PS> $tenantId = (Get-AzContext).Tenant.Id + PS> $appId = (Get-AzADApplication -DisplayName 'Entra ID').AppId + PS> .\Get-EntraIdAppAccessToken.ps1 -ClientId $appId -ClientSecret $secureSecret -TenantId $tenantId -ApplicationId $appId + + + This example demonstrates how to use client secret-based authentication to retrieve an access token from Microsoft Graph. +#> +[CmdletBinding()] +param +( + [Parameter(Mandatory, ParameterSetName = 'CertificateAuth')] + [ValidateNotNullOrEmpty()] + [System.Security.Cryptography.X509Certificates.X509Certificate2]$Certificate, + + [Parameter(Mandatory, ParameterSetName = 'CertificateAuth')] + [ValidateNotNullOrEmpty()] + [System.Security.Cryptography.X509Certificates.X509Certificate2]$PfxCertificate, + + [Parameter(Mandatory, ParameterSetName = 'ClientSecretAuth')] + [ValidateNotNullOrEmpty()] + [string]$ClientId, + + [Parameter(Mandatory, ParameterSetName = 'ClientSecretAuth')] + [ValidateNotNullOrEmpty()] + [SecureString]$ClientSecret, + + [Parameter()] + [ValidateNotNullOrEmpty()] + [string]$Scope = 'https://graph.microsoft.com/.default', + + [Parameter(Mandatory)] + [ValidateNotNullOrEmpty()] + [string]$TenantId, + + [Parameter(Mandatory)] + [ValidateNotNullOrEmpty()] + [string]$ApplicationId +) + +$ErrorActionPreference = 'Stop' + +$httpBody = @{ + client_id = $ApplicationId + scope = $Scope + grant_type = "client_credentials" +} + +$getIrmParams = @{ + ## Dont use tenant name here or you will get "Specified tenant identifier ...... is neither a valid DNS name, nor a valid external domain" + Uri = "https://login.microsoftonline.com/$TenantId/oauth2/v2.0/token" + Method = 'POST' + ContentType = "application/x-www-form-urlencoded" +} + +switch ($PSCmdlet.ParameterSetName) { + 'CertificateAuth' { + # Create base64 hash of certificate + $CertificateBase64Hash = [System.Convert]::ToBase64String($Certificate.GetCertHash()) + + # Create JWT timestamp for expiration + $StartDate = (Get-Date "1970-01-01T00:00:00Z" ).ToUniversalTime() + $JWTExpirationTimeSpan = (New-TimeSpan -Start $StartDate -End (Get-Date).ToUniversalTime().AddMinutes(2)).TotalSeconds + $JWTExpiration = [math]::Round($JWTExpirationTimeSpan, 0) + + # Create JWT validity start timestamp + $NotBeforeExpirationTimeSpan = (New-TimeSpan -Start $StartDate -End ((Get-Date).ToUniversalTime())).TotalSeconds + $NotBefore = [math]::Round($NotBeforeExpirationTimeSpan, 0) + + # Create JWT header + $JWTHeader = @{ + alg = "RS256" + typ = "JWT" + # Use the CertificateBase64Hash and replace/strip to match web encoding of base64 + x5t = $CertificateBase64Hash -replace '\+', '-' -replace '/', '_' -replace '=' + } + + # Create JWT payload + $JWTPayLoad = @{ + # What endpoint is allowed to use this JWT + ## Dont use tenant name here or you will get "Specified tenant identifier ...... is neither a valid DNS name, nor a valid external domain" + aud = "https://login.microsoftonline.com/$TenantId/oauth2/token" + exp = $JWTExpiration # Expiration timestamp + iss = $ApplicationId # Issuer = your application + jti = [guid]::NewGuid() # JWT ID: random guid + nbf = $NotBefore # Not to be used before + sub = $ApplicationId # JWT Subject + } + + # Convert header and payload to base64 + $JWTHeaderToByte = [System.Text.Encoding]::UTF8.GetBytes(($JWTHeader | ConvertTo-Json)) + $EncodedHeader = [System.Convert]::ToBase64String($JWTHeaderToByte) + + $JWTPayLoadToByte = [System.Text.Encoding]::UTF8.GetBytes(($JWTPayload | ConvertTo-Json)) + $EncodedPayload = [System.Convert]::ToBase64String($JWTPayLoadToByte) + + # Join header and Payload with "." to create a valid (unsigned) JWT + $JWT = $EncodedHeader + "." + $EncodedPayload + + # Get the private key object of your certificate + $privKey = ([System.Security.Cryptography.X509Certificates.RSACertificateExtensions]::GetRSAPrivateKey($PfxCertificate)) + + # Define RSA signature and hashing algorithm + $RSAPadding = [Security.Cryptography.RSASignaturePadding]::Pkcs1 + $HashAlgorithm = [Security.Cryptography.HashAlgorithmName]::SHA256 + + # Create a signature of the JWT + $Signature = [Convert]::ToBase64String( + $privKey.SignData([System.Text.Encoding]::UTF8.GetBytes($JWT), $HashAlgorithm, $RSAPadding) + ) -replace '\+', '-' -replace '/', '_' -replace '=' + + # Join the signature to the JWT with "." + $jwt = $JWT + "." + $Signature + + $httpBody += @{ + client_assertion = $jwt + client_assertion_type = "urn:ietf:params:oauth:client-assertion-type:jwt-bearer" + } + + $getIrmParams += @{ + Headers = @{ + Authorization = "Bearer $JWT" + } + Body = $httpBody + } + } + 'ClientSecretAuth' { + $httpBody.client_secret = [System.Net.NetworkCredential]::new("", $ClientSecret).Password + $getIrmParams += @{ + Headers = @{ + Authorization = "Bearer $JWT" + } + Body = $httpBody + } + } + default { + throw "Unrecognized input: [$_]" + } +} + +$Request = Invoke-RestMethod @getIrmParams + +$Request.access_token \ No newline at end of file diff --git a/Microsoft Exchange Online/Add-ExchangeOnlineMailboxAlias.ps1 b/Microsoft Exchange Online/Add-ExchangeOnlineMailboxAlias.ps1 new file mode 100644 index 0000000..d1e2fc7 --- /dev/null +++ b/Microsoft Exchange Online/Add-ExchangeOnlineMailboxAlias.ps1 @@ -0,0 +1,53 @@ +#requires -Modules @{ModuleName="ExchangeOnlineManagement";ModuleVersion="3.5.0"} + +<# +.SYNOPSIS + Adds a new alias to an existing mailbox in Exchange Online. + +.DESCRIPTION + This script retrieves the specified mailbox using the provided identity and adds a new alias email address. + The new alias is constructed using the provided alias and the domain from the mailbox's primary SMTP address. + If the mailbox cannot be found, an appropriate error message is displayed. + +.PARAMETER Identity + The identity of the mailbox (e.g., email address, user principal name, or alias) to which the new alias will be added. + This parameter is mandatory. + +.PARAMETER Alias + The alias to be added to the mailbox. This parameter is mandatory. + +.NOTES + This script requires the ExchangeOnlineManagement module version 3.5.0 or higher. + For more information on managing Exchange Online mailboxes, visit: + https://docs.microsoft.com/en-us/powershell/exchange/exchange-online/exchange-online-powershell + +.EXAMPLE + PS> .\Add-MailboxAlias.ps1 -Identity "user@example.com" -Alias "newalias" + + This example adds the alias "newalias@example.com" to the mailbox identified by "user@example.com". +#> + + +[CmdletBinding()] +param ( + [Parameter(Mandatory)] + [string]$Identity, + + [Parameter(Mandatory)] + [string]$Alias +) + +$errorActionPreference = "Stop" + +try { + $mbox = Get-Mailbox -Identity $Identity +} catch { + if ($_.Exception.Message -like "*because object '*' couldn't be found*") { + throw "Mailbox not found for user: $Identity" + } else { + throw $_ + } +} + +$newEmail = "$Alias@$(([mailaddress]$mbox.PrimarySmtpAddress).Host)" +Set-Mailbox -Identity $Identity -EmailAddresses @{Add = $newEmail } \ No newline at end of file diff --git a/Microsoft Exchange Online/Add-ExchangeOnlineMailboxPermission.ps1 b/Microsoft Exchange Online/Add-ExchangeOnlineMailboxPermission.ps1 new file mode 100644 index 0000000..a1cf7ca --- /dev/null +++ b/Microsoft Exchange Online/Add-ExchangeOnlineMailboxPermission.ps1 @@ -0,0 +1,160 @@ +#requires -Modules @{ModuleName="ExchangeOnlineManagement";ModuleVersion="3.5.0"} + +<# +.SYNOPSIS + Adds permissions to a mailbox in an Exchange environment. + +.DESCRIPTION + This script is a wrapper around the `Add-MailboxPermission` cmdlet, providing a variety of parameter sets to handle different scenarios. + It supports adding access rights, setting mailbox owner, and handling inheritance types for mailbox permissions. + +.PARAMETER AccessRights + Specifies the access rights to assign to the user on the mailbox. This parameter is mandatory for the AccessRights parameter set. + +.PARAMETER AutoMapping + Specifies whether automapping is enabled. Used in conjunction with the AccessRights and Instance parameter sets. + +.PARAMETER Deny + Specifies whether to deny the specified access rights. Used in conjunction with the AccessRights and Instance parameter sets. + +.PARAMETER GroupMailbox + Specifies whether the mailbox is a group mailbox. Used in conjunction with the Owner, Instance, and AccessRights parameter sets. + +.PARAMETER Identity + Specifies the mailbox to which permissions are being added. This parameter is mandatory for multiple parameter sets. + +.PARAMETER IgnoreDefaultScope + Specifies whether to ignore the default scope and search in the entire forest. + +.PARAMETER InheritanceType + Specifies the type of inheritance for the permission. Used in conjunction with the AccessRights and Instance parameter sets. + +.PARAMETER Owner + Specifies the owner of the mailbox. This parameter is mandatory for the Owner parameter set. + +.PARAMETER User + Specifies the user to whom the permissions are being granted. This parameter is mandatory for the AccessRights parameter set. + +.NOTES + For more information on the `Add-MailboxPermission` cmdlet, visit: + https://learn.microsoft.com/en-us/powershell/module/exchange/add-mailboxpermission + +.EXAMPLE + PS> .\Add-ExchangeOnlineMailboxPermission.ps1 -Identity "UserMailbox" -User "AnotherUser" -AccessRights FullAccess + + This example grants the 'FullAccess' permission to 'AnotherUser' on 'UserMailbox'. + +.EXAMPLE + PS> .\Add-ExchangeOnlineMailboxPermission.ps1 -Identity "UserMailbox" -Owner "NewOwner" + + This example sets 'NewOwner' as the owner of 'UserMailbox'. + +.EXAMPLE + PS> .\Add-ExchangeOnlineMailboxPermission.ps1 -Identity "UserMailbox" -User "AnotherUser" -AccessRights FullAccess -Deny + + This example denies the 'FullAccess' permission to 'AnotherUser' on 'UserMailbox'. + +.EXAMPLE + PS> .\Add-ExchangeOnlineMailboxPermission.ps1 -Identity "UserMailbox" -ClearAutoMapping + + This example clears automapping for 'UserMailbox'. +#> + + +[CmdletBinding(DefaultParameterSetName='AccessRights', SupportsShouldProcess=$true, ConfirmImpact='Medium')] +param( + [Parameter(ParameterSetName='AccessRights', Mandatory=$true)] + [Parameter(ParameterSetName='Instance')] + [System.Object[]] + ${AccessRights}, + + [Parameter(ParameterSetName='AccessRights')] + [Parameter(ParameterSetName='Instance')] + [System.Object] + ${AutoMapping}, + + [Parameter(ParameterSetName='AccessRights')] + [Parameter(ParameterSetName='Instance')] + [switch] + ${Deny}, + + [Parameter(ParameterSetName='Owner')] + [Parameter(ParameterSetName='Instance')] + [Parameter(ParameterSetName='AccessRights')] + [switch] + ${GroupMailbox}, + + [Parameter(ParameterSetName='ClearAutoMapping', Mandatory=$true, Position=0, ValueFromPipelineByPropertyName=$true)] + [Parameter(ParameterSetName='ResetDefault', Mandatory=$true, Position=0, ValueFromPipelineByPropertyName=$true)] + [Parameter(ParameterSetName='Owner', Mandatory=$true, Position=0, ValueFromPipelineByPropertyName=$true)] + [Parameter(ParameterSetName='AccessRights', Mandatory=$true, Position=0, ValueFromPipelineByPropertyName=$true)] + [Parameter(ParameterSetName='Instance', Position=0)] + [System.Object] + ${Identity}, + + [switch] + ${IgnoreDefaultScope}, + + [Parameter(ParameterSetName='AccessRights')] + [Parameter(ParameterSetName='Instance')] + [System.DirectoryServices.ActiveDirectorySecurityInheritance] + ${InheritanceType}, + + [Parameter(ParameterSetName='Owner', Mandatory=$true)] + [System.Object] + ${Owner}, + + [Parameter(ParameterSetName='AccessRights', Mandatory=$true)] + [Parameter(ParameterSetName='Instance')] + [System.Object] + ${User}) + +begin +{ + try { + $outBuffer = $null + if ($PSBoundParameters.TryGetValue('OutBuffer', [ref]$outBuffer)) + { + $PSBoundParameters['OutBuffer'] = 1 + } + + $wrappedCmd = $ExecutionContext.InvokeCommand.GetCommand('Add-MailboxPermission', [System.Management.Automation.CommandTypes]::Function) + $scriptCmd = {& $wrappedCmd @PSBoundParameters } + + $steppablePipeline = $scriptCmd.GetSteppablePipeline() + $steppablePipeline.Begin($PSCmdlet) + } catch { + throw + } +} + +process +{ + try { + $steppablePipeline.Process($_) + } catch { + throw + } +} + +end +{ + try { + $steppablePipeline.End() + } catch { + throw + } +} + +clean +{ + if ($null -ne $steppablePipeline) { + $steppablePipeline.Clean() + } +} +<# + +.ForwardHelpTargetName Add-MailboxPermission +.ForwardHelpCategory Function + +#> diff --git a/Microsoft Exchange Online/New-ExchangeOnlineMailbox.ps1 b/Microsoft Exchange Online/New-ExchangeOnlineMailbox.ps1 new file mode 100644 index 0000000..c8874b8 --- /dev/null +++ b/Microsoft Exchange Online/New-ExchangeOnlineMailbox.ps1 @@ -0,0 +1,437 @@ +#requires -Modules @{ModuleName="ExchangeOnlineManagement";ModuleVersion="3.5.0"} + +<# +.SYNOPSIS + Creates a new mailbox in an Exchange environment with various options for user, room, shared, and more. + +.DESCRIPTION + The script wraps around the New-Mailbox cmdlet, providing a rich set of parameters to create different types of mailboxes. + It supports various parameter sets to handle specific scenarios such as creating room mailboxes, shared mailboxes, equipment mailboxes, + and more. The cmdlet also integrates with Microsoft Online Services for federated users and supports remote and inactive mailboxes. + +.PARAMETER ActiveSyncMailboxPolicy + Specifies the ActiveSync mailbox policy to apply to the new mailbox. + +.PARAMETER Alias + Specifies the alias for the new mailbox. This parameter is required. + +.PARAMETER Archive + Specifies whether to create an archive mailbox for the user. + +.PARAMETER Discovery + Specifies that the mailbox is a discovery mailbox. This parameter is mandatory for the Discovery parameter set. + +.PARAMETER DisplayName + Specifies the display name for the new mailbox. + +.PARAMETER EnableRoomMailboxAccount + Specifies whether to enable the account for a room mailbox. This parameter is mandatory for the EnableRoomMailboxAccount parameter set. + +.PARAMETER Equipment + Specifies that the mailbox is an equipment mailbox. This parameter is mandatory for the Equipment parameter set. + +.PARAMETER FederatedIdentity + Specifies the federated identity for a federated user. This parameter is mandatory for the MicrosoftOnlineServicesFederatedUser and FederatedUser parameter sets. + +.PARAMETER FirstName + Specifies the first name of the user for the new mailbox. + +.PARAMETER Force + Forces the command to execute without asking for user confirmation. + +.PARAMETER HoldForMigration + Specifies that the mailbox is being held for migration. This parameter is used with the PublicFolder parameter set. + +.PARAMETER ImmutableId + Specifies the immutable ID for the mailbox. + +.PARAMETER InactiveMailbox + Specifies the inactive mailbox object. Used in various parameter sets that involve inactive or removed mailboxes. + +.PARAMETER Initials + Specifies the initials of the user. + +.PARAMETER IsExcludedFromServingHierarchy + Specifies whether the public folder mailbox is excluded from serving the hierarchy. + +.PARAMETER LastName + Specifies the last name of the user for the new mailbox. + +.PARAMETER MailboxPlan + Specifies the mailbox plan to apply to the new mailbox. Used in various parameter sets. + +.PARAMETER MailboxRegion + Specifies the region for the new mailbox. + +.PARAMETER MicrosoftOnlineServicesID + Specifies the Microsoft Online Services ID for the user. This parameter is mandatory in certain parameter sets. + +.PARAMETER Migration + Specifies that the mailbox is created for migration purposes. This parameter is mandatory for the Migration parameter set. + +.PARAMETER ModeratedBy + Specifies the users who moderate the mailbox. Used in various parameter sets. + +.PARAMETER ModerationEnabled + Specifies whether moderation is enabled for the mailbox. Used in various parameter sets. + +.PARAMETER Name + Specifies the name of the new mailbox. This parameter is mandatory and positional. + +.PARAMETER Office + Specifies the office location of the new mailbox. Used in room and linked room mailboxes. + +.PARAMETER OrganizationalUnit + Specifies the organizational unit (OU) for the new mailbox. + +.PARAMETER Password + Specifies the password for the new mailbox. This parameter is mandatory in certain parameter sets. + +.PARAMETER Phone + Specifies the phone number for the new mailbox. Used in room and linked room mailboxes. + +.PARAMETER PrimarySmtpAddress + Specifies the primary SMTP address for the new mailbox. + +.PARAMETER PublicFolder + Specifies that the mailbox is a public folder mailbox. This parameter is mandatory for the PublicFolder parameter set. + +.PARAMETER RemotePowerShellEnabled + Specifies whether remote PowerShell is enabled for the new mailbox. + +.PARAMETER RemovedMailbox + Specifies the removed mailbox object. Used in various parameter sets involving removed or inactive mailboxes. + +.PARAMETER ResetPasswordOnNextLogon + Specifies whether the user must reset the password on next logon. + +.PARAMETER ResourceCapacity + Specifies the resource capacity for the new mailbox. Used in room and linked room mailboxes. + +.PARAMETER RoleAssignmentPolicy + Specifies the role assignment policy for the new mailbox. + +.PARAMETER Room + Specifies that the mailbox is a room mailbox. This parameter is mandatory for the Room parameter set. + +.PARAMETER RoomMailboxPassword + Specifies the password for the room mailbox account. This parameter is mandatory for the EnableRoomMailboxAccount parameter set. + +.PARAMETER SendModerationNotifications + Specifies how moderation notifications are sent. Used in various parameter sets. + +.PARAMETER Shared + Specifies that the mailbox is a shared mailbox. This parameter is mandatory for the Shared parameter set. + +.PARAMETER TargetAllMDBs + Specifies whether to target all mailbox databases. + +.EXAMPLE + PS> .\New-Mailbox.ps1 -Name "John Doe" -Alias "jdoe" -Password (ConvertTo-SecureString "P@ssw0rd" -AsPlainText -Force) -DisplayName "John Doe" -FirstName "John" -LastName "Doe" -User + + This example creates a new user mailbox for John Doe with the specified parameters. + +.EXAMPLE + PS> .\New-Mailbox.ps1 -Name "ConferenceRoom1" -Alias "confroom1" -Room -RoomMailboxPassword (ConvertTo-SecureString "P@ssw0rd" -AsPlainText -Force) -Office "Head Office" + + This example creates a new room mailbox for a conference room at the Head Office location. + +.EXAMPLE + PS> .\New-Mailbox.ps1 -Name "Shared Mailbox" -Alias "sharedmail" -Shared + + This example creates a new shared mailbox with the specified parameters. +#> + +[CmdletBinding(DefaultParameterSetName = 'User', SupportsShouldProcess = $true, ConfirmImpact = 'Medium')] +param( + [System.Object] + ${ActiveSyncMailboxPolicy}, + + [ValidateNotNullOrEmpty()] + [string] + ${Alias}, + + [switch] + ${Archive}, + + [Parameter(ParameterSetName = 'Discovery', Mandatory = $true)] + [switch] + ${Discovery}, + + [string] + ${DisplayName}, + + [Parameter(ParameterSetName = 'EnableRoomMailboxAccount', Mandatory = $true)] + [bool] + ${EnableRoomMailboxAccount}, + + [Parameter(ParameterSetName = 'Equipment', Mandatory = $true)] + [switch] + ${Equipment}, + + [Parameter(ParameterSetName = 'MicrosoftOnlineServicesFederatedUser', Mandatory = $true)] + [Parameter(ParameterSetName = 'FederatedUser', Mandatory = $true)] + [string] + ${FederatedIdentity}, + + [string] + ${FirstName}, + + [switch] + ${Force}, + + [Parameter(ParameterSetName = 'PublicFolder')] + [switch] + ${HoldForMigration}, + + [string] + ${ImmutableId}, + + [Parameter(ParameterSetName = 'User', ValueFromPipeline = $true)] + [Parameter(ParameterSetName = 'InactiveMailbox', Mandatory = $true, ValueFromPipeline = $true)] + [Parameter(ParameterSetName = 'WindowsLiveCustomDomains', ValueFromPipeline = $true)] + [Parameter(ParameterSetName = 'MicrosoftOnlineServicesID', ValueFromPipeline = $true)] + [Parameter(ParameterSetName = 'WindowsLiveID', ValueFromPipeline = $true)] + [System.Object] + ${InactiveMailbox}, + + [string] + ${Initials}, + + [Parameter(ParameterSetName = 'PublicFolder')] + [bool] + ${IsExcludedFromServingHierarchy}, + + [string] + ${LastName}, + + [Parameter(ParameterSetName = 'MicrosoftOnlineServicesID')] + [Parameter(ParameterSetName = 'RemoteArchive')] + [Parameter(ParameterSetName = 'MicrosoftOnlineServicesFederatedUser')] + [Parameter(ParameterSetName = 'FederatedUser')] + [Parameter(ParameterSetName = 'InactiveMailbox')] + [Parameter(ParameterSetName = 'RemovedMailbox')] + [Parameter(ParameterSetName = 'ImportLiveId')] + [Parameter(ParameterSetName = 'DisabledUser')] + [Parameter(ParameterSetName = 'MailboxPlan')] + [Parameter(ParameterSetName = 'WindowsLiveCustomDomains')] + [Parameter(ParameterSetName = 'WindowsLiveID')] + [Parameter(ParameterSetName = 'User')] + [System.Object] + ${MailboxPlan}, + + [ValidateNotNullOrEmpty()] + [string] + ${MailboxRegion}, + + [Parameter(ParameterSetName = 'EnableRoomMailboxAccount')] + [Parameter(ParameterSetName = 'MicrosoftOnlineServicesFederatedUser', Mandatory = $true)] + [Parameter(ParameterSetName = 'MicrosoftOnlineServicesID', Mandatory = $true)] + [System.Object] + ${MicrosoftOnlineServicesID}, + + [Parameter(ParameterSetName = 'Migration', Mandatory = $true)] + [switch] + ${Migration}, + + [Parameter(ParameterSetName = 'GroupMailbox')] + [Parameter(ParameterSetName = 'RemoteArchive')] + [Parameter(ParameterSetName = 'InactiveMailbox')] + [Parameter(ParameterSetName = 'RemovedMailbox')] + [Parameter(ParameterSetName = 'DisabledUser')] + [Parameter(ParameterSetName = 'ImportLiveId')] + [Parameter(ParameterSetName = 'WindowsLiveCustomDomains')] + [Parameter(ParameterSetName = 'MailboxPlan')] + [Parameter(ParameterSetName = 'MicrosoftOnlineServicesID')] + [Parameter(ParameterSetName = 'WindowsLiveID')] + [Parameter(ParameterSetName = 'Equipment')] + [Parameter(ParameterSetName = 'Room')] + [Parameter(ParameterSetName = 'LinkedRoomMailbox')] + [Parameter(ParameterSetName = 'LinkedWithSyncMailbox')] + [Parameter(ParameterSetName = 'Linked')] + [Parameter(ParameterSetName = 'TeamMailboxITPro')] + [Parameter(ParameterSetName = 'TeamMailboxIW')] + [Parameter(ParameterSetName = 'Shared')] + [Parameter(ParameterSetName = 'User')] + [System.Object] + ${ModeratedBy}, + + [Parameter(ParameterSetName = 'RemoteArchive')] + [Parameter(ParameterSetName = 'InactiveMailbox')] + [Parameter(ParameterSetName = 'RemovedMailbox')] + [Parameter(ParameterSetName = 'DisabledUser')] + [Parameter(ParameterSetName = 'ImportLiveId')] + [Parameter(ParameterSetName = 'WindowsLiveCustomDomains')] + [Parameter(ParameterSetName = 'MailboxPlan')] + [Parameter(ParameterSetName = 'MicrosoftOnlineServicesID')] + [Parameter(ParameterSetName = 'WindowsLiveID')] + [Parameter(ParameterSetName = 'Equipment')] + [Parameter(ParameterSetName = 'Room')] + [Parameter(ParameterSetName = 'LinkedRoomMailbox')] + [Parameter(ParameterSetName = 'LinkedWithSyncMailbox')] + [Parameter(ParameterSetName = 'Linked')] + [Parameter(ParameterSetName = 'TeamMailboxITPro')] + [Parameter(ParameterSetName = 'TeamMailboxIW')] + [Parameter(ParameterSetName = 'Shared')] + [Parameter(ParameterSetName = 'User')] + [bool] + ${ModerationEnabled}, + + [Parameter(Mandatory = $true, Position = 0, ValueFromPipelineByPropertyName = $true)] + [string] + ${Name}, + + [Parameter(ParameterSetName = 'LinkedRoomMailbox')] + [Parameter(ParameterSetName = 'Room')] + [string] + ${Office}, + + [System.Object] + ${OrganizationalUnit}, + + [Parameter(ParameterSetName = 'MicrosoftOnlineServicesID')] + [Parameter(ParameterSetName = 'RemoteArchive', Mandatory = $true)] + [Parameter(ParameterSetName = 'InactiveMailbox')] + [Parameter(ParameterSetName = 'RemovedMailbox')] + [Parameter(ParameterSetName = 'DisabledUser')] + [Parameter(ParameterSetName = 'Discovery')] + [Parameter(ParameterSetName = 'Migration')] + [Parameter(ParameterSetName = 'Arbitration')] + [Parameter(ParameterSetName = 'WindowsLiveID', Mandatory = $true)] + [Parameter(ParameterSetName = 'TeamMailboxITPro')] + [Parameter(ParameterSetName = 'TeamMailboxIW')] + [Parameter(ParameterSetName = 'Shared')] + [Parameter(ParameterSetName = 'Scheduling')] + [Parameter(ParameterSetName = 'Equipment')] + [Parameter(ParameterSetName = 'Room')] + [Parameter(ParameterSetName = 'LinkedRoomMailbox')] + [Parameter(ParameterSetName = 'LinkedWithSyncMailbox')] + [Parameter(ParameterSetName = 'Linked')] + [Parameter(ParameterSetName = 'User', Mandatory = $true)] + [securestring] + ${Password}, + + [Parameter(ParameterSetName = 'LinkedRoomMailbox')] + [Parameter(ParameterSetName = 'Room')] + [string] + ${Phone}, + + [System.Object] + ${PrimarySmtpAddress}, + + [Parameter(ParameterSetName = 'PublicFolder', Mandatory = $true)] + [switch] + ${PublicFolder}, + + [bool] + ${RemotePowerShellEnabled}, + + [Parameter(ParameterSetName = 'User', ValueFromPipeline = $true)] + [Parameter(ParameterSetName = 'ImportLiveId', ValueFromPipeline = $true)] + [Parameter(ParameterSetName = 'RemoteArchive', ValueFromPipeline = $true)] + [Parameter(ParameterSetName = 'RemovedMailbox', Mandatory = $true, ValueFromPipeline = $true)] + [Parameter(ParameterSetName = 'WindowsLiveCustomDomains', ValueFromPipeline = $true)] + [Parameter(ParameterSetName = 'MicrosoftOnlineServicesFederatedUser', ValueFromPipeline = $true)] + [Parameter(ParameterSetName = 'FederatedUser', ValueFromPipeline = $true)] + [Parameter(ParameterSetName = 'MicrosoftOnlineServicesID', ValueFromPipeline = $true)] + [Parameter(ParameterSetName = 'WindowsLiveID', ValueFromPipeline = $true)] + [System.Object] + ${RemovedMailbox}, + + [bool] + ${ResetPasswordOnNextLogon}, + + [Parameter(ParameterSetName = 'LinkedRoomMailbox')] + [Parameter(ParameterSetName = 'Room')] + [System.Object] + ${ResourceCapacity}, + + [System.Object] + ${RoleAssignmentPolicy}, + + [Parameter(ParameterSetName = 'EnableRoomMailboxAccount', Mandatory = $true)] + [Parameter(ParameterSetName = 'Room', Mandatory = $true)] + [switch] + ${Room}, + + [Parameter(ParameterSetName = 'EnableRoomMailboxAccount')] + [securestring] + ${RoomMailboxPassword}, + + [Parameter(ParameterSetName = 'GroupMailbox')] + [Parameter(ParameterSetName = 'RemoteArchive')] + [Parameter(ParameterSetName = 'InactiveMailbox')] + [Parameter(ParameterSetName = 'RemovedMailbox')] + [Parameter(ParameterSetName = 'DisabledUser')] + [Parameter(ParameterSetName = 'ImportLiveId')] + [Parameter(ParameterSetName = 'WindowsLiveCustomDomains')] + [Parameter(ParameterSetName = 'MailboxPlan')] + [Parameter(ParameterSetName = 'MicrosoftOnlineServicesID')] + [Parameter(ParameterSetName = 'WindowsLiveID')] + [Parameter(ParameterSetName = 'Equipment')] + [Parameter(ParameterSetName = 'Room')] + [Parameter(ParameterSetName = 'LinkedRoomMailbox')] + [Parameter(ParameterSetName = 'LinkedWithSyncMailbox')] + [Parameter(ParameterSetName = 'Linked')] + [Parameter(ParameterSetName = 'TeamMailboxITPro')] + [Parameter(ParameterSetName = 'TeamMailboxIW')] + [Parameter(ParameterSetName = 'Shared')] + [Parameter(ParameterSetName = 'User')] + [System.Object] + ${SendModerationNotifications}, + + [Parameter(ParameterSetName = 'Shared', Mandatory = $true)] + [switch] + ${Shared}, + + [switch] + ${TargetAllMDBs}) + +begin +{ + try { + $outBuffer = $null + if ($PSBoundParameters.TryGetValue('OutBuffer', [ref]$outBuffer)) { + $PSBoundParameters['OutBuffer'] = 1 + } + + $wrappedCmd = $ExecutionContext.InvokeCommand.GetCommand('New-Mailbox', [System.Management.Automation.CommandTypes]::Function) + $scriptCmd = { & $wrappedCmd @PSBoundParameters } + + $steppablePipeline = $scriptCmd.GetSteppablePipeline() + $steppablePipeline.Begin($PSCmdlet) + } catch { + throw + } +} + +process +{ + try { + $steppablePipeline.Process($_) + } catch { + throw + } +} + +end +{ + try { + $steppablePipeline.End() + } catch { + throw + } +} + +clean +{ + if ($null -ne $steppablePipeline) { + $steppablePipeline.Clean() + } +} +<# + +.ForwardHelpTargetName New-Mailbox +.ForwardHelpCategory Function + +#> \ No newline at end of file diff --git a/Microsoft SharePoint Online/Add-SharePointOnlineGroupMember.ps1 b/Microsoft SharePoint Online/Add-SharePointOnlineGroupMember.ps1 new file mode 100644 index 0000000..72af195 --- /dev/null +++ b/Microsoft SharePoint Online/Add-SharePointOnlineGroupMember.ps1 @@ -0,0 +1,125 @@ +#requires -Modules @{ModuleName="pnp.powershell";ModuleVersion="2.4.0"} + +<# +.SYNOPSIS + Connects to a SharePoint tenant and adds a specified user to a specified group. + +.DESCRIPTION + This script connects to a SharePoint tenant using either certificate-based or client secret-based authentication. + It verifies the existence of the specified group and user within the SharePoint tenant. If both the group and + user are found, it adds the user to the group. + +.PARAMETER EntraIdTenantId + The GUID representing the Entra ID (Azure Active Directory) Tenant ID. + +.PARAMETER SharePointTenant + The name of the SharePoint tenant. + +.PARAMETER PrivateKeyFilePath + The file path to the private key used for certificate-based authentication. + +.PARAMETER PrivateKeyPassword + The password for the private key used in certificate-based authentication. + +.PARAMETER ClientId + The client ID for the Azure AD application. + +.PARAMETER ClientSecret + The client secret for client secret-based authentication. + +.PARAMETER GroupName + The name of the SharePoint group to which the user will be added. + +.PARAMETER LoginName + The login name of the user to be added to the group. + +.PARAMETER SiteUrl + The URL of the SharePoint site. This parameter is optional. + +.NOTES + To run this script, you need the PnP PowerShell module installed with version 2.4.0 or higher. + For more information on PnP PowerShell, visit: https://pnp.github.io/powershell/ + +.EXAMPLE + PS> .\Add-SharePointOnlineGroupMember.ps1 -EntraIdTenantId "00000000-0000-0000-0000-000000000000" -SharePointTenant "yourtenant" ` + -PrivateKeyFilePath "C:\keys\privatekey.pfx" -PrivateKeyPassword (ConvertTo-SecureString "password" -AsPlainText -Force) ` + -ClientId "00000000-0000-0000-0000-000000000000" -GroupName "TeamSite Members" -LoginName "user@domain.com" + Connects to the specified SharePoint tenant using certificate-based authentication and adds the user to the specified group. + +.EXAMPLE + PS> .\Add-SharePointOnlineGroupMember.ps1 -EntraIdTenantId "00000000-0000-0000-0000-000000000000" -SharePointTenant "yourtenant" ` + -ClientId "00000000-0000-0000-0000-000000000000" -ClientSecret (ConvertTo-SecureString "secret" -AsPlainText -Force) ` + -GroupName "TeamSite Members" -LoginName "user@domain.com" + Connects to the specified SharePoint tenant using client secret-based authentication and adds the user to the specified group. +#> + +[CmdletBinding()] +param( + [Parameter(Mandatory)] + [guid]$EntraIdTenantId, + + [Parameter(Mandatory)] + [ValidateNotNullOrEmpty()] + [string]$SharePointTenant, + + [Parameter(Mandatory, ParameterSetName = 'CertificateAuth')] + [ValidateNotNullOrEmpty()] + [string]$PrivateKeyFilePath, + + [Parameter(Mandatory, ParameterSetName = 'CertificateAuth')] + [ValidateNotNullOrEmpty()] + [securestring]$PrivateKeyPassword, + + [Parameter(Mandatory)] + [ValidateNotNullOrEmpty()] + [string]$ClientId, + + [Parameter(Mandatory, ParameterSetName = 'ClientSecretAuth')] + [ValidateNotNullOrEmpty()] + [securestring]$ClientSecret, + + [Parameter(Mandatory)] + [ValidateNotNullOrEmpty()] + [string]$GroupName, + + [Parameter(Mandatory)] + [ValidateNotNullOrEmpty()] + [string]$LoginName, + + [Parameter()] + [ValidateNotNullOrEmpty()] + [uri]$SiteUrl +) + +$ErrorActionPreference = 'Stop' + +$connectParams = @{ + ClientId = $ClientId + Tenant = $EntraIdTenantId + Url = "https://$SharePointTenant.sharepoint.com" +} + +if ($PSCmdlet.ParameterSetName -eq 'CertificateAuth') { + $connectParams.CertificatePath = $PrivateKeyFilePath + $connectParams.CertificatePassword = $PrivateKeyPassword +} else { + $connectParams.ClientSecret = $ClientSecret +} + +Connect-PnPOnline @connectParams + +try { + $null = Get-PnPSiteGroup -Group $GroupName +} catch { + if ($_.Exception.Message -like '*Group not found*') { + throw "The group [$GroupName] was not found" + } else { + throw $_ + } +} + +if (-not (Get-PnpUser -Identity $LoginName)) { + throw "User [$LoginName] was not found" +} + +Add-PnPGroupMember -LoginName $LoginName -Group $GroupName \ No newline at end of file diff --git a/Microsoft SharePoint Online/Get-SharePointOnlineGroupMember.ps1 b/Microsoft SharePoint Online/Get-SharePointOnlineGroupMember.ps1 new file mode 100644 index 0000000..817c8bd --- /dev/null +++ b/Microsoft SharePoint Online/Get-SharePointOnlineGroupMember.ps1 @@ -0,0 +1,145 @@ +#requires -Modules @{ModuleName="pnp.powershell";ModuleVersion="2.4.0"} + +<# +.SYNOPSIS + Connects to a SharePoint tenant and retrieves members of specified site groups. + +.DESCRIPTION + This script connects to a SharePoint tenant using either certificate or client secret authentication, then retrieves and lists + members of the specified site groups. The connection parameters are specified through mandatory parameters, and the script + ensures that proper authentication is used based on the provided parameters. + +.PARAMETER EntraIdTenantId + The GUID of the Entra ID (Azure AD) tenant. + +.PARAMETER SharePointTenant + The name of the SharePoint tenant. + +.PARAMETER PrivateKeyFilePath + The file path to the private key used for certificate authentication. This parameter is mandatory if using certificate + authentication. + +.PARAMETER PrivateKeyPassword + The password for the private key file used for certificate authentication. This parameter is mandatory if using certificate + authentication. + +.PARAMETER ClientId + The client ID of the Azure AD app registration. + +.PARAMETER ClientSecret + The client secret used for client secret authentication. This parameter is mandatory if using client secret authentication. + +.PARAMETER GroupName + The name of the SharePoint group to retrieve members from. Optional parameter. + +.PARAMETER SiteUrl + The URL of the SharePoint site to retrieve groups from. Optional parameter. + +.NOTES + For more information on using PnP PowerShell, visit: https://pnp.github.io/powershell/ + +.EXAMPLE + PS> .\Get-SharePointGroupMembers.ps1 -EntraIdTenantId 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' -SharePointTenant 'contoso' -ClientId 'xxxx-xxxx-xxxx-xxxx' -ClientSecret (ConvertTo-SecureString 'your-secret' -AsPlainText -Force) + + + Connects to the SharePoint tenant 'contoso' using client secret authentication and lists members of all site groups. + +.EXAMPLE + $sharePointOnlineRequiredResourceAccess = @( + @{ + ResourceAppId = "00000003-0000-0ff1-ce00-000000000000" ## Sharepoint Online resource app id + ResourceAccess = @( + @{ + Id = "fbcd29d2-fcca-4405-aded-518d457caae4" # Permission ID: Sites.ReadWrite.All + Type = "Role" + } + ) + } + ) + $app = New-AzADApplication -DisplayName SharePointOnlineSiteAuth -RequiredResourceAccess $sharePointOnlineRequiredResourceAccess + PS> Connect-AzAccount + PS> $tenantId = (Get-AzContext).Tenant.Id + PS> $cert = New-SelfSignedCertificate -DnsName PowerShellAuth -CertStoreLocation cert:\CurrentUser\My + PS> $pwd = ConvertTo-SecureString -String "P@ss0word!" -Force -AsPlainText + PS> Export-PfxCertificate -Cert $cert -FilePath .\cert.pfx -Password $pwd + PS> Export-Certificate -Cert $cert -FilePath .\cert.cer + + ## remove the cert from the cert store + PS> $cert | Remove-Item + + PS> $PfxCertificate = Get-PfxCertificate -FilePath ~/cert.pfx -Password (ConvertTo-SecureString -String 'P@ss0word!' -AsPlainText -Force) + + PS> .\Get-SharePointGroupMembers.ps1 -EntraIdTenantId $tenantId -SharePointTenant 'contoso' -ClientId $app.AppId -PrivateKeyFilePath '.\cert.pfx -PrivateKeyPassword $pwd -GroupName 'Site Members' + + + Connects to the SharePoint tenant 'contoso' using certificate authentication and lists members of the 'Site Members' group. +#> + +[CmdletBinding()] +param( + [Parameter(Mandatory)] + [guid]$EntraIdTenantId, + + [Parameter(Mandatory)] + [ValidateNotNullOrEmpty()] + [string]$SharePointTenant, + + [Parameter(Mandatory, ParameterSetName = 'CertificateAuth')] + [ValidateNotNullOrEmpty()] + [string]$PrivateKeyFilePath, + + [Parameter(Mandatory, ParameterSetName = 'CertificateAuth')] + [ValidateNotNullOrEmpty()] + [securestring]$PrivateKeyPassword, + + [Parameter(Mandatory)] + [ValidateNotNullOrEmpty()] + [string]$ClientId, + + [Parameter(Mandatory, ParameterSetName = 'ClientSecretAuth')] + [ValidateNotNullOrEmpty()] + [securestring]$ClientSecret, + + [Parameter()] + [ValidateNotNullOrEmpty()] + [string]$GroupName, + + [Parameter()] + [ValidateNotNullOrEmpty()] + [uri]$SiteUrl +) + +$ErrorActionPreference = 'Stop' + +$connectParams = @{ + ClientId = $ClientId + Tenant = $EntraIdTenantId + Url = "https://$SharePointTenant.sharepoint.com" +} + +if ($PSCmdlet.ParameterSetName -eq 'CertificateAuth') { + $connectParams.CertificatePath = $PrivateKeyFilePath + $connectParams.CertificatePassword = $PrivateKeyPassword +} else { + $connectParams.ClientSecret = $ClientSecret +} + +Connect-PnPOnline @connectParams + +$getSiteGroupParams = @{} +if ($PSBoundParameters.ContainsKey('GroupName')) { + $getSiteGroupParams.Group = $GroupName +} +if ($PSBoundParameters.ContainsKey('SiteUrl')) { + $getSiteGroupParams.Site = $SiteUrl.ToString() +} + +Get-PnPSiteGroup @getSiteGroupParams -PipelineVariable 'group' | ForEach-Object { + Get-PnPGroupMember -Group $group.Title | ForEach-Object { + [pscustomobject]@{ + GroupName = $group.Title + LoginName = $_.LoginName + Title = $_.Title + } + } +} \ No newline at end of file diff --git a/Microsoft SharePoint Online/Get-SharePointOnlineSiteStorageSize.ps1 b/Microsoft SharePoint Online/Get-SharePointOnlineSiteStorageSize.ps1 new file mode 100644 index 0000000..95176da --- /dev/null +++ b/Microsoft SharePoint Online/Get-SharePointOnlineSiteStorageSize.ps1 @@ -0,0 +1,111 @@ +#requires -Modules @{ModuleName="pnp.powershell";ModuleVersion="2.4.0"} + +<# +.SYNOPSIS + Connects to a SharePoint tenant and retrieves a list of site collections with their URLs and storage usage. + +.DESCRIPTION + This script connects to a SharePoint tenant using either certificate-based or client secret-based authentication. + It retrieves and lists all site collections within the SharePoint tenant, displaying each site's URL and current storage usage in megabytes. + +.PARAMETER EntraIdTenantId + The GUID representing the Entra ID (Azure Active Directory) Tenant ID. + +.PARAMETER SharePointTenant + The name of the SharePoint tenant. + +.PARAMETER PrivateKeyFilePath + The file path to the private key used for certificate-based authentication. + +.PARAMETER PrivateKeyPassword + The password for the private key used in certificate-based authentication. + +.PARAMETER ClientId + The client ID for the Azure AD application. + +.PARAMETER ClientSecret + The client secret for client secret-based authentication. + +.PARAMETER SiteUrl + The URL of a specific SharePoint site. This parameter is optional and, if provided, the script will retrieve information for this site only. + +.NOTES + To run this script, you need the PnP PowerShell module installed with version 2.4.0 or higher. + For more information on PnP PowerShell, visit: https://pnp.github.io/powershell/ + +.EXAMPLE + PS> .\Get-SharePointOnlineSiteStorageSize -EntraIdTenantId "00000000-0000-0000-0000-000000000000" -SharePointTenant "yourtenant" ` + -PrivateKeyFilePath "C:\keys\privatekey.pfx" -PrivateKeyPassword (ConvertTo-SecureString "password" -AsPlainText -Force) ` + -ClientId "00000000-0000-0000-0000-000000000000" + Connects to the specified SharePoint tenant using certificate-based authentication and retrieves all site collections with their URLs and storage usage. + +.EXAMPLE + PS> .\Get-SharePointOnlineSiteStorageSize -EntraIdTenantId "00000000-0000-0000-0000-000000000000" -SharePointTenant "yourtenant" ` + -ClientId "00000000-0000-0000-0000-000000000000" -ClientSecret (ConvertTo-SecureString "secret" -AsPlainText -Force) + Connects to the specified SharePoint tenant using client secret-based authentication and retrieves all site collections with their URLs and storage usage. + +.EXAMPLE + PS> .\Get-SharePointOnlineSiteStorageSize -EntraIdTenantId "00000000-0000-0000-0000-000000000000" -SharePointTenant "yourtenant" ` + -ClientId "00000000-0000-0000-0000-000000000000" -ClientSecret (ConvertTo-SecureString "secret" -AsPlainText -Force) ` + -SiteUrl "https://yourtenant.sharepoint.com/sites/specificsite" + Connects to the specified SharePoint tenant using client secret-based authentication and retrieves information for the specified site only. +#> + +[CmdletBinding()] +param( + [Parameter(Mandatory)] + [guid]$EntraIdTenantId, + + [Parameter(Mandatory)] + [ValidateNotNullOrEmpty()] + [string]$SharePointTenant, + + [Parameter(Mandatory, ParameterSetName = 'CertificateAuth')] + [ValidateNotNullOrEmpty()] + [string]$PrivateKeyFilePath, + + [Parameter(Mandatory, ParameterSetName = 'CertificateAuth')] + [ValidateNotNullOrEmpty()] + [securestring]$PrivateKeyPassword, + + [Parameter(Mandatory)] + [ValidateNotNullOrEmpty()] + [string]$ClientId, + + [Parameter(Mandatory, ParameterSetName = 'ClientSecretAuth')] + [ValidateNotNullOrEmpty()] + [securestring]$ClientSecret, + + [Parameter()] + [ValidateNotNullOrEmpty()] + [uri]$SiteUrl +) + +$ErrorActionPreference = 'Stop' + +$connectParams = @{ + ClientId = $ClientId + Tenant = $EntraIdTenantId + Url = "https://$SharePointTenant.sharepoint.com" +} + +if ($PSCmdlet.ParameterSetName -eq 'CertificateAuth') { + $connectParams.CertificatePath = $PrivateKeyFilePath + $connectParams.CertificatePassword = $PrivateKeyPassword +} else { + $connectParams.ClientSecret = $ClientSecret +} + +Connect-PnPOnline @connectParams + +$getPnPSiteParams = @{} +if ($PSBoundParameters.ContainsKey('SiteUrl')) { + $getPnPSiteParams.Identity = $SiteUrl.ToString() +} + +Get-PnPTenantSite @getPnPSiteParams | ForEach-Object { + [pscustomobject]@{ + SiteUrl = $_.Url + SizeMB = $_.StorageUsageCurrent + } +} \ No newline at end of file diff --git a/Microsoft SharePoint Online/Invoke-SharePointOnlineFileDownload.ps1 b/Microsoft SharePoint Online/Invoke-SharePointOnlineFileDownload.ps1 new file mode 100644 index 0000000..fe28cb3 --- /dev/null +++ b/Microsoft SharePoint Online/Invoke-SharePointOnlineFileDownload.ps1 @@ -0,0 +1,128 @@ +#requires -Modules @{ModuleName="pnp.powershell";ModuleVersion="2.4.0"} + +<# +.SYNOPSIS + Connects to a SharePoint tenant and downloads a specified file from the site to a local folder. + +.DESCRIPTION + This script connects to a SharePoint tenant using either certificate-based or client secret-based authentication. + It downloads a file from the specified SharePoint path to a local folder. The script ensures that the destination + folder exists and supports overwriting the file if the -Force switch is specified. + +.PARAMETER EntraIdTenantId + The GUID representing the Entra ID (Azure Active Directory) Tenant ID. + +.PARAMETER SharePointTenant + The name of the SharePoint tenant. + +.PARAMETER PrivateKeyFilePath + The file path to the private key used for certificate-based authentication. + +.PARAMETER PrivateKeyPassword + The password for the private key used in certificate-based authentication. + +.PARAMETER ClientId + The client ID for the Azure AD application. + +.PARAMETER ClientSecret + The client secret for client secret-based authentication. + +.PARAMETER SourceFilePath + The URI path of the source file in the SharePoint site. + +.PARAMETER DestinationFolderPath + The local path to the folder where the file will be downloaded. The folder must exist. + +.PARAMETER Force + If specified, forces the download by overwriting the file if it already exists in the destination folder. + +.NOTES + To run this script, you need the PnP PowerShell module installed with version 2.4.0 or higher. + For more information on PnP PowerShell, visit: https://pnp.github.io/powershell/ + +.EXAMPLE + PS> .\Invoke-SharePointOnlineFileDownload.ps1 -EntraIdTenantId "00000000-0000-0000-0000-000000000000" -SharePointTenant "yourtenant" ` + -PrivateKeyFilePath "C:\keys\privatekey.pfx" -PrivateKeyPassword (ConvertTo-SecureString "password" -AsPlainText -Force) ` + -ClientId "00000000-0000-0000-0000-000000000000" -SourceFilePath "/sites/sitecollection/documents/file.txt" ` + -DestinationFolderPath "C:\Downloads" + Connects to the specified SharePoint tenant using certificate-based authentication and downloads the specified file to the local folder. + +.EXAMPLE + PS> .\Invoke-SharePointOnlineFileDownload -EntraIdTenantId "00000000-0000-0000-0000-000000000000" -SharePointTenant "yourtenant" ` + -ClientId "00000000-0000-0000-0000-000000000000" -ClientSecret (ConvertTo-SecureString "secret" -AsPlainText -Force) ` + -SourceFilePath "/sites/sitecollection/documents/file.txt" -DestinationFolderPath "C:\Downloads" -Force + Connects to the specified SharePoint tenant using client secret-based authentication and downloads the specified file to the local folder, + overwriting the file if it already exists. +#> + +[CmdletBinding()] +param( + [Parameter(Mandatory)] + [guid]$EntraIdTenantId, + + [Parameter(Mandatory)] + [ValidateNotNullOrEmpty()] + [string]$SharePointTenant, + + [Parameter(Mandatory, ParameterSetName = 'CertificateAuth')] + [ValidateNotNullOrEmpty()] + [string]$PrivateKeyFilePath, + + [Parameter(Mandatory, ParameterSetName = 'CertificateAuth')] + [ValidateNotNullOrEmpty()] + [securestring]$PrivateKeyPassword, + + [Parameter(Mandatory)] + [ValidateNotNullOrEmpty()] + [string]$ClientId, + + [Parameter(Mandatory, ParameterSetName = 'ClientSecretAuth')] + [ValidateNotNullOrEmpty()] + [securestring]$ClientSecret, + + [Parameter(Mandatory)] + [ValidateNotNullOrEmpty()] + [uri]$SourceFilePath, + + [Parameter(Mandatory)] + [ValidateNotNullOrEmpty()] + [ValidateScript( + { Test-Path -Path $_ -PathType Container }, + ErrorMessage = 'The folder [{0}] does not exist.' + )] + [string]$DestinationFolderPath, + + [Parameter()] + [switch]$Force +) + +$ErrorActionPreference = 'Stop' + +$tenantUrl = "https://$SharePointTenant.sharepoint.com" + +$connectParams = @{ + ClientId = $ClientId + Tenant = $EntraIdTenantId + Url = $tenantUrl +} + +if ($PSCmdlet.ParameterSetName -eq 'CertificateAuth') { + $connectParams.CertificatePath = $PrivateKeyFilePath + $connectParams.CertificatePassword = $PrivateKeyPassword +} else { + $connectParams.ClientSecret = $ClientSecret +} + +Connect-PnPOnline @connectParams + +$sourceFileUrl = '{0}/{1}' -f $tenantUrl, $SourceFilePath +$encodedSourceFileUrl = [uri]::EscapeUriString($sourceFileUrl) + +$pnpFileParams = @{ + Url = $encodedSourceFileUrl + Path = $DestinationFolderPath + FileName = ($SourceFilePath | Split-Path -Leaf) + AsFile = $true +} +$pnpFileParams.Force = $Force.IsPresent ? $true : $false +Get-PnPFile @pnpFileParams \ No newline at end of file diff --git a/Microsoft SharePoint Online/Invoke-SharePointOnlineFileUpload.ps1 b/Microsoft SharePoint Online/Invoke-SharePointOnlineFileUpload.ps1 new file mode 100644 index 0000000..abf9957 --- /dev/null +++ b/Microsoft SharePoint Online/Invoke-SharePointOnlineFileUpload.ps1 @@ -0,0 +1,118 @@ +#requires -Modules @{ModuleName="pnp.powershell";ModuleVersion="2.4.0"} + +<# +.SYNOPSIS + Connects to a SharePoint Online site and uploads a file to a specified folder. + +.DESCRIPTION + This script connects to a SharePoint Online site using either certificate authentication or client secret authentication. + After establishing the connection, it uploads a specified file to a destination folder within the SharePoint site. + +.PARAMETER EntraIdTenantId + The GUID of the Azure AD tenant ID. + +.PARAMETER SharePointTenant + The SharePoint Online tenant name. + +.PARAMETER PrivateKeyFilePath + The file path of the private key used for certificate authentication. + +.PARAMETER PrivateKeyPassword + The password for the private key used for certificate authentication. + +.PARAMETER ClientId + The Client ID of the Azure AD application. + +.PARAMETER ClientSecret + The client secret of the Azure AD application used for client secret authentication. + +.PARAMETER SourceFilePath + The full path of the source file to be uploaded. + +.PARAMETER DestinationFolderPath + The destination folder path within the SharePoint Online site where the file will be uploaded. + +.NOTES + Requires the 'pnp.powershell' module version 2.4.0 or higher. + For more information on PnP PowerShell, visit: https://pnp.github.io/powershell/ + +.EXAMPLE + PS> .\Invoke-SharePointOnlineFileUpload -EntraIdTenantId '00000000-0000-0000-0000-000000000000' -SharePointTenant 'contoso' -PrivateKeyFilePath + 'C:\path\to\privatekey.pfx' -PrivateKeyPassword (ConvertTo-SecureString -String 'password' -AsPlainText -Force) -ClientId + '00000000-0000-0000-0000-000000000000' -SourceFilePath 'C:\path\to\sourcefile.txt' -DestinationFolderPath 'Shared Documents' + + This example connects to the SharePoint Online site 'https://contoso.sharepoint.com' using certificate authentication + and uploads the file 'C:\path\to\sourcefile.txt' to the 'Shared Documents' folder. + +.EXAMPLE + PS> .\Invoke-SharePointOnlineFileUpload -EntraIdTenantId '00000000-0000-0000-0000-000000000000' -SharePointTenant 'contoso' -ClientId + '00000000-0000-0000-0000-000000000000' -ClientSecret (ConvertTo-SecureString -String 'clientsecret' -AsPlainText -Force) -SourceFilePath + 'C:\path\to\sourcefile.txt' -DestinationFolderPath 'Shared Documents' + + This example connects to the SharePoint Online site 'https://contoso.sharepoint.com' using client secret authentication + and uploads the file 'C:\path\to\sourcefile.txt' to the 'Shared Documents' folder. +#> + + +[CmdletBinding()] +param( + [Parameter(Mandatory)] + [guid]$EntraIdTenantId, + + [Parameter(Mandatory)] + [ValidateNotNullOrEmpty()] + [string]$SharePointTenant, + + [Parameter(Mandatory, ParameterSetName = 'CertificateAuth')] + [ValidateNotNullOrEmpty()] + [string]$PrivateKeyFilePath, + + [Parameter(Mandatory, ParameterSetName = 'CertificateAuth')] + [ValidateNotNullOrEmpty()] + [securestring]$PrivateKeyPassword, + + [Parameter(Mandatory)] + [ValidateNotNullOrEmpty()] + [string]$ClientId, + + [Parameter(Mandatory, ParameterSetName = 'ClientSecretAuth')] + [ValidateNotNullOrEmpty()] + [securestring]$ClientSecret, + + [Parameter(Mandatory)] + [ValidateNotNullOrEmpty()] + [ValidateScript( + { Test-Path -Path $_ -PathType Leaf }, + ErrorMessage = 'The file [{0}] does not exist.' + )] + [uri]$SourceFilePath, + + [Parameter(Mandatory)] + [ValidateNotNullOrEmpty()] + [string]$DestinationFolderPath +) + +$ErrorActionPreference = 'Stop' + +$tenantUrl = "https://$SharePointTenant.sharepoint.com" + +$connectParams = @{ + ClientId = $ClientId + Tenant = $EntraIdTenantId + Url = $tenantUrl +} + +if ($PSCmdlet.ParameterSetName -eq 'CertificateAuth') { + $connectParams.CertificatePath = $PrivateKeyFilePath + $connectParams.CertificatePassword = $PrivateKeyPassword +} else { + $connectParams.ClientSecret = $ClientSecret +} + +Connect-PnPOnline @connectParams + +$pnpFileParams = @{ + Path = $SourceFilePath + Folder = $DestinationFolderPath +} +Add-PnPFile @pnpFileParams diff --git a/Microsoft SharePoint Online/New-SharePointOnlineSite.ps1 b/Microsoft SharePoint Online/New-SharePointOnlineSite.ps1 new file mode 100644 index 0000000..9169d61 --- /dev/null +++ b/Microsoft SharePoint Online/New-SharePointOnlineSite.ps1 @@ -0,0 +1,123 @@ +#requires -Modules @{ModuleName="pnp.powershell";ModuleVersion="2.4.0"} +#requires -Modules @{ModuleName="Az.Accounts";ModuleVersion="2.15.1"} + +<# +.SYNOPSIS +Creates a new SharePoint site using PnP PowerShell with either certificate or client secret authentication. + +.DESCRIPTION +This script connects to a SharePoint Online tenant and creates a new site. The connection can be established using either +certificate-based or client secret-based authentication, depending on the provided parameters. + +.PARAMETER Title +The title of the new SharePoint site. + +.PARAMETER Name +The name (URL segment) of the new SharePoint site. + +.PARAMETER Type +The type of the SharePoint site. Valid values are 'TeamSite', 'CommunicationSite', and 'TeamSiteWithoutMicrosoft365Group'. + +.PARAMETER EntraIdTenantId +The Azure AD tenant ID. If logged into Azure AD, this can be retrieved with (Get-AzContext).Tenant.Id. + +.PARAMETER SharePointTenant +The SharePoint tenant name (e.g., "contoso" for "contoso.sharepoint.com"). + +.PARAMETER Owner +An array of owners for the new SharePoint site. + +.PARAMETER PrivateKeyFilePath +The file path to the private key for certificate-based authentication. Required when using the CertificateAuth parameter set. + +.PARAMETER PrivateKeyPassword +The password for the private key. Required when using the CertificateAuth parameter set. + +.PARAMETER ClientId +The client ID for the Azure AD application. + +.PARAMETER ClientSecret +The client secret for client secret-based authentication. Required when using the ClientSecretAuth parameter set. + +.NOTES +Requires the PnP PowerShell module (v2.4.0) and Az.Accounts module (v2.15.1). +For more information on PnP PowerShell, visit: https://pnp.github.io/powershell/ + +.EXAMPLE + + PS> $tenantId = (Get-AzContext).Tenant.Id + PS> $app = Get-AzADApplication -DisplayName "SharePoint Online" + PS> .\New-SharePointOnlineSite.ps1 -Title "New Team Site" -Name "newteamsite" -Type "TeamSite" -EntraIdTenantId $tenantId + -SharePointTenant "contoso" -Owner "user@contoso.com" -ClientId $app.AppId -ClientSecret (ConvertTo-SecureString "your-client-secret" -AsPlainText -Force) + + Creates a new Team Site using client secret authentication. + +.EXAMPLE + + PS> $tenantId = (Get-AzContext).Tenant.Id + PS> $app = Get-AzADApplication -DisplayName "SharePoint Online" + PS> .\New-SharePointOnlineSite.ps1 -Title "New Communication Site" -Name "newcommsite" -Type "CommunicationSite" -EntraIdTenantId $tenantId + -SharePointTenant "contoso" -Owner "user@contoso.com" -ClientId $app.AppId -PrivateKeyFilePath "path\to\privatekey.pfx" + -PrivateKeyPassword (ConvertTo-SecureString "your-password" -AsPlainText -Force) + + Creates a new Communication Site using certificate-based authentication. +#> +[CmdletBinding()] +param( + [Parameter(Mandatory)] + [string]$Title, + + [Parameter(Mandatory)] + [ValidateNotNullOrEmpty()] + [string]$Name, + + [Parameter(Mandatory)] + [ValidateSet('TeamSite', 'CommunicationSite', 'TeamSiteWithoutMicrosoft365Group')] + [string]$Type, + + [Parameter(Mandatory)] + [guid]$EntraIdTenantId, + + [Parameter(Mandatory)] + [ValidateNotNullOrEmpty()] + [string]$SharePointTenant, + + [Parameter(Mandatory)] + [ValidateNotNullOrEmpty()] + [string[]]$Owner, + + [Parameter(Mandatory, ParameterSetName = 'CertificateAuth')] + [ValidateNotNullOrEmpty()] + [string]$PrivateKeyFilePath, + + [Parameter(Mandatory, ParameterSetName = 'CertificateAuth')] + [ValidateNotNullOrEmpty()] + [securestring]$PrivateKeyPassword, + + [Parameter(Mandatory)] + [ValidateNotNullOrEmpty()] + [string]$ClientId, + + [Parameter(Mandatory, ParameterSetName = 'ClientSecretAuth')] + [ValidateNotNullOrEmpty()] + [securestring]$ClientSecret +) + +$ErrorActionPreference = 'Stop' + +$connectParams = @{ + ClientId = $ClientId + Tenant = $EntraIdTenantId + Url = "https://$SharePointTenant.sharepoint.com" +} + +if ($PSCmdlet.ParameterSetName -eq 'CertificateAuth') { + $connectParams.CertificatePath = $PrivateKeyFilePath + $connectParams.CertificatePassword = $CertificatePassword +} else { + $connectParams.ClientSecret = $ClientSecret +} + +Connect-PnPOnline @connectParams + +New-PnPSite -Type $Type -Title $Title -Url "https://$SharePointTenant.sharepoint.com/sites/$Name" -Owner ($Owner -join ";") \ No newline at end of file diff --git a/Security/Get-UserLogonHistory.ps1 b/Security/Get-UserLogonHistory.ps1 new file mode 100644 index 0000000..41346a6 --- /dev/null +++ b/Security/Get-UserLogonHistory.ps1 @@ -0,0 +1,196 @@ +<# +.SYNOPSIS + Retrieves user session information from event logs, including logon and logoff times. + +.DESCRIPTION + This script queries the event logs to determine user session activity, including logon and logoff events. It handles various + session start and stop events, processes the events to extract relevant information such as username, logon ID, and logon type, + and attempts to match logoff events to logon events to calculate session duration. + +.NOTES + More information about XPath queries in event logs: https://docs.microsoft.com/en-us/windows/win32/wes/querying-for-event-data + +.EXAMPLE + PS> Get-UserLogonHistory + + Retrieves a list of historical user sessions. +#> + +[CmdletBinding()] +param +() + +function Get-LoggedInUser { + Get-Process -IncludeUserName | Where-Object { $_.UserName -and $_.UserName -notmatch "^NT *|^Window Manager" } | Select-Object -ExpandProperty UserName -Unique +} + +function GetEventUserName { + param ( + [Parameter(Mandatory)] + [System.Xml.XmlDocument]$EventRecord + ) + + $script:eventNamespace.AddNamespace("evt", "http://schemas.microsoft.com/win/2004/08/events/event") + $targetUserName = $EventRecord.SelectSingleNode("//evt:Data[@Name='TargetUserName']", $script:eventNamespace).InnerText + $targetDomainName = $EventRecord.SelectSingleNode("//evt:Data[@Name='TargetDomainName']", $script:eventNamespace).InnerText + + if ($targetDomainName) { + "$targetDomainName\$targetUserName" + } else { + $targetUserName + } + +} + +function GetEventLogonType { + param ( + [Parameter(Mandatory)] + [System.Xml.XmlDocument]$EventRecord + ) + + ($EventRecord.Event.EventData.Data | Where-Object { $_.Name -eq 'LogonType' }).'#text' +} + +function GetUserLogonId { + param ( + [Parameter(Mandatory)] + [System.Xml.XmlDocument]$EventRecord + ) + + $userLogonId = ($EventRecord.Event.EventData.Data | Where-Object { $_.Name -eq 'TargetLogonId' }).'#text' + if (-not $userLogonId) { + $userLogonId = ($EventRecord.Event.EventData.Data | Where-Object { $_.Name -eq 'LogonId' }).'#text' + } + + $userLogonId +} + +function GetLogoffEvent { + param ( + [Parameter()] + [ValidateNotNullOrEmpty()] + [datetime]$LogonStartTime, + + [Parameter()] + [ValidateNotNullOrEmpty()] + [string]$UserLogonId + ) + + ## This assumes event is the most recent one that matches the criteria + @($script:Events).where({ + $xEvt = [xml]$_.ToXml() + [datetime]$_.TimeCreated -gt $LogonStartTime -and + $_.ID -in $script:sessionStopIds -and + (GetUserLogonId -EventRecord $xEvt) -eq $UserLogonId + }) | Select-Object -Last 1 +} + +try { + + #region Defie all of the events to indicate session start or top + $sessionEvents = @( + @{ 'Label' = 'Logon'; 'EventType' = 'SessionStart'; 'LogName' = 'Security'; 'ID' = 4624 } ## Advanced Audit Policy --> System Audit Policies --> Logon/Logoff --> Audit Logon + @{ 'Label' = 'Logoff'; 'EventType' = 'SessionStop'; 'LogName' = 'Security'; 'ID' = 4647 } ## Advanced Audit Policy --> System Audit Policies --> Logon/Logoff --> Audit Logoff + @{ 'Label' = 'Startup'; 'EventType' = 'SessionStop'; 'LogName' = 'System'; 'ID' = 6005 } ## Audit Policy --> Audit System Events + @{ 'Label' = 'RdpSessionReconnect'; 'EventType' = 'SessionStart'; 'LogName' = 'Security'; 'ID' = 4778 } ## Advanced Audit Policy --> System Audit Policies --> Logon/Logoff --> Audit Other Logon/Logoff Events + @{ 'Label' = 'RdpSessionDisconnect'; 'EventType' = 'SessionStop'; 'LogName' = 'Security'; 'ID' = 4779 } ## Advanced Audit Policy --> System Audit Policies --> Logon/Logoff --> Audit Other Logon/Logoff Events + @{ 'Label' = 'Locked'; 'EventType' = 'SessionStop'; 'LogName' = 'Security'; 'ID' = 4800 } ## Advanced Audit Policy --> System Audit Policies --> Logon/Logoff --> Audit Other Logon/Logoff Events + @{ 'Label' = 'Unlocked'; 'EventType' = 'SessionStart'; 'LogName' = 'Security'; 'ID' = 4801 } ## Advanced Audit Policy --> System Audit Policies --> Logon/Logoff --> Audit Other Logon/Logoff Events + ) + + ## All of the IDs that designate when user activity starts + $sessionStartIds = ($sessionEvents | Where-Object { $_.EventType -eq 'SessionStart' }).ID + ## All of the IDs that designate when user activity stops + $script:sessionStopIds = ($sessionEvents | Where-Object { $_.EventType -eq 'SessionStop' }).ID + #endregion + + ## Define all of the log names we'll be querying + $logNames = ($sessionEvents.LogName | Select-Object -Unique) + + ## These are not all logon types but only those that are relevant to user activity (not internal services) + $userLogonTypes = @{ + 2 = "Interactive" + 7 = "Unlock" + 10 = "RemoteInteractive" + 11 = "CachedInteractive" + } + + ## Build the XPath query for the security event log in order to query events as fast as possible + ## It would be better if TargetDomainName could be filtered by anything with a space in it but due to XPath 1.0 + ## restrictions, it's not possible. + $xPath = @" +*[ + ( + EventData[Data[@Name='TargetDomainName'] != 'Window Manager'] and + EventData[Data[@Name='TargetDomainName'] != 'NT AUTHORITY'] and + EventData[Data[@Name='TargetDomainName'] != 'Font Driver Host'] + ) and + (EventData[Data[@Name='LogonType'] = '$($userLogonTypes.Keys -join "'] or + EventData[Data[@Name='LogonType'] = '")'] + ) or + ( + System[ + (EventID=$($script:sessionStopIds -join " or EventID=")) + ] + ) +] +"@ + ## Query the computer's event logs using the Xpath filter + if (-not ($script:events = Get-WinEvent -LogName $logNames -FilterXPath $xPath)) { + Write-Warning -Message 'No logon events found'. + } else { + $script:eventNamespace = New-Object System.Xml.XmlNamespaceManager(([xml]$script:events[0].ToXml()).NameTable) + Write-Verbose -Message "Found [$($script:events.Count)] events to look through" + + $loggedInUsers = Get-LoggedInUser + + ## Find all user start activity events and begin parsing + @($script:events).where({ $_.Id -in $sessionStartIds }).foreach({ + try { + $xEvt = [xml]$_.ToXml() + + $userName = GetEventUserName -Event $xEvt + $logonEvtId = $_.Id + + $startTime = $_.TimeCreated + + $userLogonId = GetUserLogonId -EventRecord $xEvt + + $userLogonType = GetEventLogonType -EventRecord $xEvt + + Write-Verbose -Message "New session start event found: event ID [$logonEvtId] username [$userName] user logonID [$($userLogonId)] user logon type [$userLogonType] time [$($startTime)]" + ## Try to match up the user activity end event with the start event we're processing + if (-not ($logoffEvent = GetLogoffEvent -LogonStartTime $startTime -UserLogonId $userLogonId)) { + ## If no logoff event is found, the user might still be logged in + if ($userName -in $loggedInUsers) { + $stopTime = Get-Date + $stopAction = 'Still logged in' + } else { + throw "Could not find a session end event for logon ID [$($userLogonId)] username [$userName] start event time [$startTime]." + } + } else { + ## Capture the user activity end time + $stopTime = $logoffEvent.TimeCreated + Write-Verbose -Message "Session stop event ID is [$($logoffEvent.Id)]" + $stopAction = @($sessionEvents).where({ $_.ID -eq $logoffEvent.Id }).Label + } + + $sessionTimespan = New-TimeSpan -Start $startTime -End $stopTime + + [pscustomobject]@{ + 'Username' = $userName + 'UserLogonId' = $userLogonId + 'StartTime' = $startTime + 'StartAction' = @($sessionEvents).where({ $_.ID -eq $logonEvtId }).Label + 'StopTime' = $stopTime ? $stopTime : 'Still logged in' + 'StopAction' = $stopTime ? $stopAction : 'Still logged in' + 'Session Active Time' = $sessionTimespan + } + } catch { + Write-Warning -Message $_.Exception.Message + } + }) + } +} catch { + $PSCmdlet.ThrowTerminatingError($_) +} \ No newline at end of file diff --git a/Utility/Convert-Certificate.ps1 b/Utility/Convert-Certificate.ps1 new file mode 100644 index 0000000..b1bccf7 --- /dev/null +++ b/Utility/Convert-Certificate.ps1 @@ -0,0 +1,152 @@ +<# +.SYNOPSIS + Converts a certificate from one format to another. + +.DESCRIPTION + This script converts a certificate file from one format to another, supporting PFX, PEM, and DER formats. + It handles the conversion based on the source and destination file extensions, and optionally uses a password + for PFX files. The script can also force overwrite the destination file if it already exists. + +.PARAMETER SourcePath + The path to the source certificate file. The file must exist. + +.PARAMETER DestinationPath + The path to the destination certificate file. The script will convert the source certificate to this file. + +.PARAMETER Password + The password for the PFX certificate, if applicable. + +.PARAMETER Force + Forces the script to overwrite the destination file if it already exists. + +.NOTES + To validate the converted certificates, you can use the following OpenSSL commands: + - For PEM: `openssl x509 -in ./output.pem -inform pem -text -noout` + - For DER: `openssl verify -CAfile ./output.der ./output.der` + - For PFX: `openssl pkcs12 -info -in ./output.pfx` + +.EXAMPLE + PS> .\Convert-Certificate.ps1 -SourcePath 'C:\path\to\cert.pfx' -DestinationPath 'C:\path\to\cert.pem' -Password (ConvertTo-SecureString 'password' -AsPlainText -Force) -Force + + This example converts a PFX certificate to a PEM certificate, using a specified password and forcing overwrite of the destination file. + +.EXAMPLE + PS> .\Convert-Certificate.ps1 -SourcePath 'C:\path\to\cert.pem' -DestinationPath 'C:\path\to\cert.der' + + This example converts a PEM certificate to a DER certificate. + +.EXAMPLE + PS> .\Convert-Certificate.ps1 -SourcePath 'C:\path\to\cert.der' -DestinationPath 'C:\path\to\cert.pem' + + This example converts a DER certificate to a PEM certificate. +#> +[CmdletBinding()] +param ( + [Parameter(Mandatory)] + [ValidateNotNullOrEmpty()] + [ValidateScript( + { Test-Path -Path $_ -PathType Leaf }, + ErrorMessage = 'The file [{0}] does not exist.' + )] + [string]$SourcePath, + + [Parameter(Mandatory)] + [ValidateNotNullOrEmpty()] + [string]$DestinationPath, + + [Parameter()] + [ValidateNotNullOrEmpty()] + [securestring]$Password, + + [Parameter()] + [switch]$Force +) + +$ErrorActionPreference = 'Stop' + +# Function to extract file extension and convert to certificate type +function Get-CertificateType { + param ( + [string]$Path + ) + $extension = [System.IO.Path]::GetExtension($Path).TrimStart('.') + switch ($extension.ToUpper()) { + 'PFX' { return 'PFX' } + 'PEM' { return 'PEM' } + 'DER' { return 'DER' } + default { throw "Unsupported file extension: $extension" } + } +} + +try { + $SourceType = Get-CertificateType -Path $SourcePath + $DestinationType = Get-CertificateType -Path $DestinationPath + + # Check if destination file exists and handle based on $Force parameter + if (Test-Path -Path $DestinationPath -PathType Leaf) { + if (-not $Force) { + throw "The destination file already exists. Use -Force to overwrite." + } + } + + switch ($SourceType) { + 'PFX' { + $pfxPassword = $Password | ConvertFrom-SecureString -AsPlainText + $cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2($SourcePath, $pfxPassword) + + if ($DestinationType -eq 'PEM') { + $pemBytes = [System.Text.Encoding]::UTF8.GetBytes($cert.Export([System.Security.Cryptography.X509Certificates.X509ContentType]::Cert)) + [System.IO.File]::WriteAllBytes($DestinationPath, $pemBytes) + } elseif ($DestinationType -eq 'DER') { + $derBytes = $cert.Export([System.Security.Cryptography.X509Certificates.X509ContentType]::Cert) + [System.IO.File]::WriteAllBytes($DestinationPath, $derBytes) + } + } + 'PEM' { + if ($DestinationType -eq 'PFX') { + $pfxPassword = $Password | ConvertFrom-SecureString -AsPlainText + $pemContent = Get-Content $SourcePath -Raw + $certCollection = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2Collection + $certCollection.ImportFromPem($pemContent) + + # Assuming you want to export the first certificate in the collection + $cert = $certCollection[0] + $bytes = $cert.Export([System.Security.Cryptography.X509Certificates.X509ContentType]::Pfx, $pfxPassword) + [System.IO.File]::WriteAllBytes($DestinationPath, $bytes) + } elseif ($DestinationType -eq 'DER') { + $pemContent = Get-Content $SourcePath -Raw + $certCollection = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2Collection + $certCollection.ImportFromPem($pemContent) + + # Assuming you want to export the first certificate in the collection + $cert = $certCollection[0] + $derBytes = $cert.Export([System.Security.Cryptography.X509Certificates.X509ContentType]::Cert) + [System.IO.File]::WriteAllBytes($DestinationPath, $derBytes) + } + } + 'DER' { + if ($DestinationType -eq 'PFX') { + throw "Cannot convert from DER to PFX without the private key." + } elseif ($DestinationType -eq 'PEM') { + try { + $derBytes = [System.IO.File]::ReadAllBytes($SourcePath) + # Ensure that the byte array is not empty or malformed + if ($derBytes.Length -eq 0) { + throw "The DER file appears to be empty or invalid." + } + + # Load the certificate from DER bytes using the constructor + $cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2($derBytes, $null, [System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::DefaultKeySet) + + # Export the certificate to PEM format + $pemBytes = [System.Text.Encoding]::UTF8.GetBytes("-----BEGIN CERTIFICATE-----`n" + [System.Convert]::ToBase64String($cert.RawData, 'InsertLineBreaks') + "`n-----END CERTIFICATE-----") + [System.IO.File]::WriteAllBytes($DestinationPath, $pemBytes) + } catch { + throw "Failed to load or convert the DER file: $($_.Exception.Message)" + } + } + } + } +} catch { + throw "An error occurred during the certificate conversion: $($_.Exception.Message)" +} \ No newline at end of file diff --git a/Utility/Get-WindowsEventLogRecord.ps1 b/Utility/Get-WindowsEventLogRecord.ps1 new file mode 100644 index 0000000..96f905b --- /dev/null +++ b/Utility/Get-WindowsEventLogRecord.ps1 @@ -0,0 +1,129 @@ +# Requires -Version 7.0 + +<# +.SYNOPSIS + Retrieves events from the event log based on specified criteria. + +.DESCRIPTION + This script uses the Get-WinEvent cmdlet to query and retrieve events from the event log. It supports filtering by log name, + event levels, event IDs, sources, and time ranges. The script builds an XPath query string based on the provided parameters + to fetch the matching events. + +.PARAMETER LogName + Specifies the name of the event log to query. + +.PARAMETER Level + Specifies the level(s) of the events to retrieve. Valid values are 'Error', 'Warning', 'Information', 'Critical', and 'Verbose'. + +.PARAMETER EventID + Specifies the event ID(s) of the events to retrieve. + +.PARAMETER Source + Specifies the source(s) of the events to retrieve. + +.PARAMETER StartTime + Specifies the start time for the events to retrieve. Only events created on or after this time are retrieved. + +.PARAMETER EndTime + Specifies the end time for the events to retrieve. Only events created on or before this time are retrieved. + +.PARAMETER MaxEvents + Specifies the maximum number of events to retrieve. + +.NOTES + Requires PowerShell version 7.0 or later. + For more information on Get-WinEvent, visit: https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.diagnostics/get-winevent + +.EXAMPLE + PS> .\Get-WindowsEventLogRecord.ps1 -LogName 'Application' -Level 'Error', 'Warning' -StartTime (Get-Date).AddDays(-1) + + This example retrieves error and warning events from the 'Application' log that were created in the last day. + +.EXAMPLE + PS> .\Get-WindowsEventLogRecord.ps1 -LogName 'System' -EventID 1000, 2000 -Source 'Microsoft-Windows-Winlogon' + + This example retrieves events with IDs 1000 and 2000 from the 'System' log, where the source is 'Microsoft-Windows-Winlogon'. + +.EXAMPLE + PS> .\Get-WindowsEventLogRecord.ps1 -LogName 'Security' -Level 'Information' -MaxEvents 50 + + This example retrieves the top 50 informational events from the 'Security' log. +#> + + +[CmdletBinding()] +param ( + [Parameter()] + [ValidateNotNullOrEmpty()] + [string]$LogName, + + [Parameter()] + [ValidateSet("Error", "Warning", "Information", "Critical", "Verbose")] + [string[]]$Level, + + [Parameter()] + [int[]]$EventID, + + [Parameter()] + [string[]]$Source, + + [Parameter()] + [datetime]$StartTime, + + [Parameter()] + [datetime]$EndTime, + + [Parameter()] + [int]$MaxEvents +) + +$params = @{} + +if ($PSBoundParameters.ContainsKey('LogName')) { + $params.LogName = $LogName +} + +$xpathQuery = "*[System[" +$conditions = @() +if ($EventID) { $conditions += "EventID=" + ($EventID -join ' or EventID=') } +if ($Level) { + $levelMapping = @{ + 'Critical' = 1 + 'Error' = 2 + 'Warning' = 3 + 'Information' = 4 + 'Verbose' = 5 + } + $levelConditions = $Level | ForEach-Object { "Level=$($levelMapping[$_])" } + $conditions += "(" + ($levelConditions -join ' or ') + ")" +} + +if ($StartTime) { + $conditions += "TimeCreated[@SystemTime>='$($StartTime.ToString("s"))']" +} +if ($EndTime) { + $conditions += "TimeCreated[@SystemTime<='$($EndTime.ToString("s"))']" +} + +if ($Source) { + $conditions += "(Provider[@Name='" + ($Source -join "'] or Provider[@Name='") + "'])" +} + +if ($conditions.Count -gt 0) { + $xpathQuery += $conditions -join ' and ' +} +$xpathQuery += "]]" + +# Validate that at least one filtering parameter is provided +if ($xpathQuery -eq "*[System[]]" -and -not $LogName) { + throw "You must specify at least one filtering parameter (LogName, EventID, Level, Source, User, Message, StartTime, or EndTime)." +} + +$params.FilterXPath = $xpathQuery + +try { + Get-WinEvent @params | Select-Object TimeCreated, Id, LevelDisplayName, ProviderName, UserId, MachineName, LogName, Message +} catch { + Write-Error "An error occurred while retrieving events: $($_.Exception.Message)" +} + diff --git a/Utility/Get-WindowsUptime.ps1 b/Utility/Get-WindowsUptime.ps1 new file mode 100644 index 0000000..d6de172 --- /dev/null +++ b/Utility/Get-WindowsUptime.ps1 @@ -0,0 +1,22 @@ +<# +.SYNOPSIS + Retrieves the system uptime. + +.DESCRIPTION + This script calculates the duration the system has been up since the last boot. It uses CIM (Common Information Model) to query + the Win32_OperatingSystem class and obtain the last boot-up time. Then, it calculates the difference between the current date and + the last boot-up time to determine the uptime duration. + +.EXAMPLE + PS> .\Get-WindowsUptime.ps1 + + Retrieves and displays the system uptime. +#> + +[CmdletBinding()] +param () + +$uptime = Get-CimInstance -ClassName Win32_OperatingSystem | Select-Object -ExpandProperty LastBootUpTime + +# Calculate the uptime duration +(Get-Date) - $uptime \ No newline at end of file diff --git a/Utility/Restart-Computer.ps1 b/Utility/Restart-Computer.ps1 new file mode 100644 index 0000000..9285162 --- /dev/null +++ b/Utility/Restart-Computer.ps1 @@ -0,0 +1,137 @@ +<# +.SYNOPSIS + Restarts the specified computer(s). + +.DESCRIPTION + This script uses the Restart-Computer cmdlet from the Microsoft.PowerShell.Management module to restart one or more computers. + It supports various authentication methods and can be configured to wait for the restart to complete, with options for timeout + and delay between checks. + +.PARAMETER WsmanAuthentication + Specifies the authentication method to be used for the WSMan connection. Valid values are 'Default', 'Basic', 'Negotiate', + 'CredSSP', 'Digest', and 'Kerberos'. + +.PARAMETER ComputerName + Specifies the computer(s) to restart. This can be a name, alias, or IP address. This parameter supports pipeline input. + +.PARAMETER Credential + Specifies the user account credentials to use for the restart operation. + +.PARAMETER Force + Forces the restart of the computer(s) without prompting for confirmation. + +.PARAMETER Wait + Waits for the restart to complete before continuing. + +.PARAMETER Timeout + Specifies the maximum amount of time (in seconds) to wait for the computer(s) to restart. A value of -1 means to wait indefinitely. + +.PARAMETER For + Specifies the service types to wait for after the restart. This is used in conjunction with the Wait parameter. + +.PARAMETER Delay + Specifies the delay (in seconds) between checks to determine if the computer(s) have restarted. + +.NOTES + For more information, visit: https://go.microsoft.com/fwlink/?LinkID=2097060 + +.EXAMPLE + PS> .\Restart-Computer.ps1 -ComputerName 'Server01' -Credential (Get-Credential) -Force -Wait -Timeout 300 + + This example restarts 'Server01' using specified credentials, forces the restart without prompting for confirmation, + waits for the restart to complete, and specifies a timeout of 300 seconds. + +.EXAMPLE + PS> .\Restart-Computer.ps1 -ComputerName 'Server01','Server02' -WsmanAuthentication 'Kerberos' -Wait -Delay 10 + + This example restarts 'Server01' and 'Server02' using Kerberos authentication, waits for the restart to complete, + and sets a delay of 10 seconds between checks. +#> + + +[CmdletBinding(DefaultParameterSetName = 'DefaultSet', SupportsShouldProcess = $true, ConfirmImpact = 'Medium', HelpUri = 'https://go.microsoft.com/fwlink/?LinkID=2097060', RemotingCapability = 'OwnedByCommand')] +param( + [Parameter(ParameterSetName = 'DefaultSet')] + [ValidateSet('Default', 'Basic', 'Negotiate', 'CredSSP', 'Digest', 'Kerberos')] + [string] + ${WsmanAuthentication}, + + [Parameter(Position = 0, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)] + [Alias('CN', '__SERVER', 'Server', 'IPAddress')] + [ValidateNotNullOrEmpty()] + [string[]] + ${ComputerName}, + + [Parameter(Position = 1)] + [ValidateNotNullOrEmpty()] + [pscredential] + [System.Management.Automation.CredentialAttribute()] + ${Credential}, + + [Alias('f')] + [switch] + ${Force}, + + [Parameter(ParameterSetName = 'DefaultSet')] + [switch] + ${Wait}, + + [Parameter(ParameterSetName = 'DefaultSet')] + [Alias('TimeoutSec')] + [ValidateRange(-1, 2147483647)] + [int] + ${Timeout}, + + [Parameter(ParameterSetName = 'DefaultSet')] + [Microsoft.PowerShell.Commands.WaitForServiceTypes] + ${For}, + + [Parameter(ParameterSetName = 'DefaultSet')] + [ValidateRange(1, 32767)] + [short] + ${Delay}) + +begin { + try { + $outBuffer = $null + if ($PSBoundParameters.TryGetValue('OutBuffer', [ref]$outBuffer)) { + $PSBoundParameters['OutBuffer'] = 1 + } + + $wrappedCmd = $ExecutionContext.InvokeCommand.GetCommand('Microsoft.PowerShell.Management\Restart-Computer', [System.Management.Automation.CommandTypes]::Cmdlet) + $scriptCmd = { & $wrappedCmd @PSBoundParameters } + + $steppablePipeline = $scriptCmd.GetSteppablePipeline($myInvocation.CommandOrigin) + $steppablePipeline.Begin($PSCmdlet) + } catch { + throw + } +} + +process { + try { + $steppablePipeline.Process($_) + } catch { + throw + } +} + +end { + try { + $steppablePipeline.End() + } catch { + throw + } +} + +clean { + if ($null -ne $steppablePipeline) { + $steppablePipeline.Clean() + } +} +<# + +.ForwardHelpTargetName Microsoft.PowerShell.Management\Restart-Computer +.ForwardHelpCategory Cmdlet + +#> \ No newline at end of file diff --git a/Windows Update/Get-WindowsUpdate.ps1 b/Windows Update/Get-WindowsUpdate.ps1 new file mode 100644 index 0000000..6ce4b58 --- /dev/null +++ b/Windows Update/Get-WindowsUpdate.ps1 @@ -0,0 +1,318 @@ +#requires -modules @{ModuleName='PSWindowsUpdate'; ModuleVersion='2.2.1.4'} + +<# +.SYNOPSIS + This script retrieves Windows updates on a local computer using various parameters to control the update process. + +.DESCRIPTION + The script utilizes the PSWindowsUpdate module to get Windows updates. It provides options to send reports, schedule updates, + accept all updates, hide updates, and specify various criteria for update selection. The script supports Windows Update and + Microsoft Update services. + +.PARAMETER SendReport + Sends a report of the update status. + +.PARAMETER PSWUSettings + A hashtable of settings for the PSWindowsUpdate module. + +.PARAMETER SendHistory + Sends the update history report. + +.PARAMETER ScheduleJob + Schedules the update job to run at a specified date and time. + +.PARAMETER AcceptAll + Automatically accepts all updates. + +.PARAMETER RecurseCycle + Specifies the number of recursive cycles for checking updates. + +.PARAMETER Hide + Hides the specified updates. + +.PARAMETER ServiceID + Specifies the service ID for the updates (parameter set: 'ServiceID'). + +.PARAMETER WindowsUpdate + Specifies to use Windows Update (parameter set: 'WindowsUpdate'). + +.PARAMETER MicrosoftUpdate + Specifies to use Microsoft Update (parameter set: 'MicrosoftUpdate'). + +.PARAMETER Criteria + Specifies criteria for selecting updates. + +.PARAMETER UpdateType + Specifies the type of updates to manage (Driver or Software). + +.PARAMETER DeploymentAction + Specifies the deployment action (Installation or Uninstallation). + +.PARAMETER IsAssigned + Filters updates that are assigned. + +.PARAMETER IsPresent + Filters updates that are present. + +.PARAMETER BrowseOnly + Browses for updates without installing them. + +.PARAMETER AutoSelectOnWebSites + Automatically selects updates on websites. + +.PARAMETER UpdateID + Specifies the IDs of updates to include. + +.PARAMETER NotUpdateID + Specifies the IDs of updates to exclude. + +.PARAMETER RevisionNumber + Specifies the revision number of updates. + +.PARAMETER CategoryIDs + Specifies the category IDs of updates. + +.PARAMETER IsInstalled + Filters updates that are installed. + +.PARAMETER IsHidden + Filters updates that are hidden. + +.PARAMETER WithHidden + Includes hidden updates. + +.PARAMETER ShowPreSearchCriteria + Shows the pre-search criteria. + +.PARAMETER RootCategories + Specifies the root categories of updates (e.g., Critical Updates, Security Updates, etc.). + +.PARAMETER Category + Specifies categories of updates to include. + +.PARAMETER KBArticleID + Specifies the KB article IDs of updates. + +.PARAMETER Title + Specifies the title of updates. + +.PARAMETER Severity + Specifies the severity of updates (e.g., Critical, Important, etc.). + +.PARAMETER NotCategory + Specifies categories of updates to exclude. + +.PARAMETER NotKBArticleID + Specifies the KB article IDs of updates to exclude. + +.PARAMETER NotTitle + Specifies the title of updates to exclude. + +.PARAMETER NotSeverity + Specifies the severity of updates to exclude. + +.PARAMETER IgnoreUserInput + Aliased as 'Silent', ignores user input during the update process. + +.PARAMETER IgnoreRebootRequired + Ignores reboot requirements after updates are installed. + +.PARAMETER AutoSelectOnly + Automatically selects updates to be installed. + +.PARAMETER MaxSize + Specifies the maximum size of updates to include. + +.PARAMETER MinSize + Specifies the minimum size of updates to include. + +.PARAMETER Debuger + Enables debugging for the update process. + +.NOTES + Requires the 'PSWindowsUpdate' module version 2.2.1.4 or higher. + For more information on PSWindowsUpdate, visit: https://github.com/PSWindowsUpdate/PSWindowsUpdate + +.EXAMPLE + PS> .\Manage-WindowsUpdate.ps1 -Install -AutoReboot + + This example installs all available updates and automatically reboots the computer after installation. + +.EXAMPLE + PS> .\Manage-WindowsUpdate.ps1 -Download -SendReport + + This example downloads all available updates and sends a report of the update status. +#> + +[CmdletBinding(DefaultParameterSetName = 'Default', SupportsShouldProcess = $true, ConfirmImpact = 'High')] +param( + [switch] + ${SendReport}, + + [hashtable] + ${PSWUSettings}, + + [switch] + ${SendHistory}, + + [datetime] + ${ScheduleJob}, + + [switch] + ${AcceptAll}, + + [int] + ${RecurseCycle}, + + [switch] + ${Hide}, + + [Parameter(ParameterSetName = 'ServiceID')] + [string] + ${ServiceID}, + + [Parameter(ParameterSetName = 'WindowsUpdate')] + [switch] + ${WindowsUpdate}, + + [Parameter(ParameterSetName = 'MicrosoftUpdate')] + [switch] + ${MicrosoftUpdate}, + + [string] + ${Criteria}, + + [ValidateSet('Driver', 'Software')] + [string] + ${UpdateType}, + + [ValidateSet('Installation', 'Uninstallation')] + [string] + ${DeploymentAction}, + + [switch] + ${IsAssigned}, + + [switch] + ${IsPresent}, + + [switch] + ${BrowseOnly}, + + [switch] + ${AutoSelectOnWebSites}, + + [string[]] + ${UpdateID}, + + [string[]] + ${NotUpdateID}, + + [int] + ${RevisionNumber}, + + [string[]] + ${CategoryIDs}, + + [switch] + ${IsInstalled}, + + [switch] + ${IsHidden}, + + [switch] + ${WithHidden}, + + [switch] + ${ShowPreSearchCriteria}, + + [ValidateSet('Critical Updates', 'Definition Updates', 'Drivers', 'Feature Packs', 'Security Updates', 'Service Packs', 'Tools', 'Update Rollups', 'Updates', 'Upgrades', 'Microsoft')] + [string[]] + ${RootCategories}, + + [string[]] + ${Category}, + + [string[]] + ${KBArticleID}, + + [string] + ${Title}, + + [ValidateSet('Critical', 'Important', 'Moderate', 'Low', 'Unspecified')] + [string[]] + ${Severity}, + + [string[]] + ${NotCategory}, + + [string[]] + ${NotKBArticleID}, + + [string] + ${NotTitle}, + + [ValidateSet('Critical', 'Important', 'Moderate', 'Low', 'Unspecified')] + [string[]] + ${NotSeverity}, + + [Alias('Silent')] + [switch] + ${IgnoreUserInput}, + + [switch] + ${AutoSelectOnly}, + + [long] + ${MaxSize}, + + [long] + ${MinSize}, + + [switch] + ${Debuger}) + +begin { + try { + $outBuffer = $null + if ($PSBoundParameters.TryGetValue('OutBuffer', [ref]$outBuffer)) { + $PSBoundParameters['OutBuffer'] = 1 + } + + $wrappedCmd = $ExecutionContext.InvokeCommand.GetCommand('PSWindowsUpdate\Get-WindowsUpdate', [System.Management.Automation.CommandTypes]::Cmdlet) + $scriptCmd = { & $wrappedCmd @PSBoundParameters } + + $steppablePipeline = $scriptCmd.GetSteppablePipeline($myInvocation.CommandOrigin) + $steppablePipeline.Begin($PSCmdlet) + } catch { + throw + } +} + +process { + try { + $steppablePipeline.Process($_) + } catch { + throw + } +} + +end { + try { + $steppablePipeline.End() + } catch { + throw + } +} + +clean { + if ($null -ne $steppablePipeline) { + $steppablePipeline.Clean() + } +} +<# + +.ForwardHelpTargetName PSWindowsUpdate\Get-WindowsUpdate +.ForwardHelpCategory Cmdlet + +#> diff --git a/Windows Update/Install-WindowsUpdate.ps1 b/Windows Update/Install-WindowsUpdate.ps1 new file mode 100644 index 0000000..17f2884 --- /dev/null +++ b/Windows Update/Install-WindowsUpdate.ps1 @@ -0,0 +1,364 @@ +#requires -modules @{ModuleName='PSWindowsUpdate'; ModuleVersion='2.2.1.4'} + +<# +.SYNOPSIS + This script facilitates the installation, downloading, and management of Windows updates on one or multiple computers. + +.DESCRIPTION + The script utilizes the PSWindowsUpdate module to manage Windows updates. It supports various parameters for filtering + and specifying the updates to be managed, including scheduling options, criteria for selection, and actions to be taken. + The script also supports reporting and history features, allowing for detailed control and monitoring of update activities. + +.PARAMETER SendReport + Sends a report of the update status. + +.PARAMETER PSWUSettings + A hashtable of settings for PSWindowsUpdate module. + +.PARAMETER SendHistory + Sends the update history report. + +.PARAMETER ScheduleJob + Schedules the update job to run at a specified date and time. + +.PARAMETER AcceptAll + Automatically accepts all updates. + +.PARAMETER RecurseCycle + Specifies the number of recursive cycles for checking updates. + +.PARAMETER Hide + Hides the specified updates. + +.PARAMETER Download + Downloads the specified updates. + +.PARAMETER ForceDownload + Forces the download of updates, ignoring any preconditions. + +.PARAMETER Install + Installs the specified updates. + +.PARAMETER ForceInstall + Forces the installation of updates, ignoring any preconditions. + +.PARAMETER AutoReboot + Automatically reboots the computer after installing updates. + +.PARAMETER IgnoreReboot + Ignores reboot requests after installing updates. + +.PARAMETER ScheduleReboot + Schedules a reboot at a specified date and time after updates are installed. + +.PARAMETER ServiceID + Specifies the service ID for the updates (parameter set: 'ServiceID'). + +.PARAMETER WindowsUpdate + Specifies to use Windows Update (parameter set: 'WindowsUpdate'). + +.PARAMETER MicrosoftUpdate + Specifies to use Microsoft Update (parameter set: 'MicrosoftUpdate'). + +.PARAMETER Criteria + Specifies criteria for selecting updates. + +.PARAMETER UpdateType + Specifies the type of updates to manage (Driver or Software). + +.PARAMETER DeploymentAction + Specifies the deployment action (Installation or Uninstallation). + +.PARAMETER IsAssigned + Filters updates that are assigned. + +.PARAMETER IsPresent + Filters updates that are present. + +.PARAMETER BrowseOnly + Browses for updates without installing them. + +.PARAMETER AutoSelectOnWebSites + Automatically selects updates on websites. + +.PARAMETER UpdateID + Specifies the IDs of updates to include. + +.PARAMETER NotUpdateID + Specifies the IDs of updates to exclude. + +.PARAMETER RevisionNumber + Specifies the revision number of updates. + +.PARAMETER CategoryIDs + Specifies the category IDs of updates. + +.PARAMETER IsInstalled + Filters updates that are installed. + +.PARAMETER IsHidden + Filters updates that are hidden. + +.PARAMETER WithHidden + Includes hidden updates. + +.PARAMETER ShowPreSearchCriteria + Shows the pre-search criteria. + +.PARAMETER RootCategories + Specifies the root categories of updates (e.g., Critical Updates, Security Updates, etc.). + +.PARAMETER Category + Specifies categories of updates to include. + +.PARAMETER KBArticleID + Specifies the KB article IDs of updates. + +.PARAMETER Title + Specifies the title of updates. + +.PARAMETER Severity + Specifies the severity of updates (e.g., Critical, Important, etc.). + +.PARAMETER NotCategory + Specifies categories of updates to exclude. + +.PARAMETER NotKBArticleID + Specifies the KB article IDs of updates to exclude. + +.PARAMETER NotTitle + Specifies the title of updates to exclude. + +.PARAMETER NotSeverity + Specifies the severity of updates to exclude. + +.PARAMETER IgnoreUserInput + Aliased as 'Silent', ignores user input during the update process. + +.PARAMETER IgnoreRebootRequired + Ignores reboot requirements after updates are installed. + +.PARAMETER AutoSelectOnly + Automatically selects updates to be installed. + +.PARAMETER MaxSize + Specifies the maximum size of updates to include. + +.PARAMETER MinSize + Specifies the minimum size of updates to include. + +.PARAMETER Debuger + Enables debugging for the update process. + +.NOTES + Requires the 'PSWindowsUpdate' module version 2.2.1.4 or higher. + For more information on PSWindowsUpdate, visit: https://github.com/PSWindowsUpdate/PSWindowsUpdate + +.EXAMPLE + PS> .\Install-WindowsUpdate.ps1 -ComputerName 'Server01' -Install -AutoReboot + + This example installs updates on 'Server01' and automatically reboots the computer after installation. + +.EXAMPLE + PS> .\Install-WindowsUpdate.ps1 -ComputerName 'Server01','Server02' -Download -SendReport + + This example downloads updates on 'Server01' and 'Server02' and sends a report of the update status. +#> + + +[CmdletBinding(DefaultParameterSetName = 'Default', SupportsShouldProcess = $true, ConfirmImpact = 'High')] +param( + [switch] + ${SendReport}, + + [hashtable] + ${PSWUSettings}, + + [switch] + ${SendHistory}, + + [datetime] + ${ScheduleJob}, + + [switch] + ${AcceptAll}, + + [int] + ${RecurseCycle}, + + [switch] + ${Hide}, + + [switch] + ${Download}, + + [switch] + ${ForceDownload}, + + [switch] + ${Install}, + + [switch] + ${ForceInstall}, + + [switch] + ${AutoReboot}, + + [switch] + ${IgnoreReboot}, + + [datetime] + ${ScheduleReboot}, + + [Parameter(ParameterSetName = 'ServiceID')] + [string] + ${ServiceID}, + + [Parameter(ParameterSetName = 'WindowsUpdate')] + [switch] + ${WindowsUpdate}, + + [Parameter(ParameterSetName = 'MicrosoftUpdate')] + [switch] + ${MicrosoftUpdate}, + + [string] + ${Criteria}, + + [ValidateSet('Driver', 'Software')] + [string] + ${UpdateType}, + + [ValidateSet('Installation', 'Uninstallation')] + [string] + ${DeploymentAction}, + + [switch] + ${IsAssigned}, + + [switch] + ${IsPresent}, + + [switch] + ${BrowseOnly}, + + [switch] + ${AutoSelectOnWebSites}, + + [string[]] + ${UpdateID}, + + [string[]] + ${NotUpdateID}, + + [int] + ${RevisionNumber}, + + [string[]] + ${CategoryIDs}, + + [switch] + ${IsInstalled}, + + [switch] + ${IsHidden}, + + [switch] + ${WithHidden}, + + [switch] + ${ShowPreSearchCriteria}, + + [ValidateSet('Critical Updates', 'Definition Updates', 'Drivers', 'Feature Packs', 'Security Updates', 'Service Packs', 'Tools', 'Update Rollups', 'Updates', 'Upgrades', 'Microsoft')] + [string[]] + ${RootCategories}, + + [string[]] + ${Category}, + + [string[]] + ${KBArticleID}, + + [string] + ${Title}, + + [ValidateSet('Critical', 'Important', 'Moderate', 'Low', 'Unspecified')] + [string[]] + ${Severity}, + + [string[]] + ${NotCategory}, + + [string[]] + ${NotKBArticleID}, + + [string] + ${NotTitle}, + + [ValidateSet('Critical', 'Important', 'Moderate', 'Low', 'Unspecified')] + [string[]] + ${NotSeverity}, + + [Alias('Silent')] + [switch] + ${IgnoreUserInput}, + + [switch] + ${IgnoreRebootRequired}, + + [switch] + ${AutoSelectOnly}, + + [long] + ${MaxSize}, + + [long] + ${MinSize}, + + [switch] + ${Debuger}) + +begin { + try { + $outBuffer = $null + if ($PSBoundParameters.TryGetValue('OutBuffer', [ref]$outBuffer)) { + $PSBoundParameters['OutBuffer'] = 1 + } + + $wrappedCmd = $ExecutionContext.InvokeCommand.GetCommand('PSWindowsUpdate\Get-WindowsUpdate', [System.Management.Automation.CommandTypes]::Cmdlet) + $scriptCmd = { & $wrappedCmd @PSBoundParameters } + + $steppablePipeline = $scriptCmd.GetSteppablePipeline($myInvocation.CommandOrigin) + $steppablePipeline.Begin($PSCmdlet) + } catch { + throw + } +} + +process { + try { + $steppablePipeline.Process($_) + } catch { + throw + } +} + +end { + try { + $steppablePipeline.End() + } catch { + throw + } +} + +clean { + if ($null -ne $steppablePipeline) { + $steppablePipeline.Clean() + } +} +<# + +.ForwardHelpTargetName PSWindowsUpdate\Get-WindowsUpdate +.ForwardHelpCategory Cmdlet + +#> \ No newline at end of file