├── Enums
├── ActionAD.ps1
├── ActionAzureAD.ps1
├── ActionExchange.ps1
├── ActionExchangeOnline.ps1
├── Condition.ps1
├── Connect.ps1
├── TriggerComputer.ps1
├── TriggerGroup.ps1
├── TriggerUserAD.ps1
└── TriggerUserAzureAD.ps1
├── Examples
├── CreateConfiguration.ps1
├── MyConfiguration1.xml
├── RunBook.BackupDefinedUser.ps1
├── RunBook.EnableRemoteMailbox.ps1
├── RunBook.JustTrigger-NoAction.ps1
├── RunBook.UsersAddOffboarded.ps1
├── RunBook.UsersAzure.ps1
├── RunBook.UsersAzurePlayLicenses.ps1
├── RunBook.UsersDisable.ps1
├── RunBook.UsersEnableOffboarded.ps1
├── RunBook.UsersEnabledAddedToGroup.ps1
├── RunBook.UsersOffboarding.1.ps1
├── RunBook.UsersOffboarding.2.ps1
└── RunBook.UsersRevive.ps1
├── PSAutomator.psd1
├── PSAutomator.psm1
├── Private
├── ActiveDirectory
│ ├── Add-WinADUserGroups.ps1
│ ├── Get-ADAdministrativeGroups.ps1
│ ├── Get-WinADGroups.ps1
│ ├── Get-WinADGroupsByDN.ps1
│ ├── Get-WinADGroupsTranslate.ps1
│ ├── Get-WinADOrganizationalUnitData.ps1
│ ├── Get-WinADOrganizationalUnitFromDN.ps1
│ ├── Get-WinADUserSnapshot.ps1
│ ├── Get-WinADUsers.ps1
│ ├── Get-WinADUsersByOU.ps1
│ ├── Get-WinADUsersTranslate.ps1
│ ├── Get-WinADusersByDN.ps1
│ ├── Remove-WinADUserGroups.ps1
│ ├── Set-WinADGroupSynchronization.ps1
│ ├── Set-WinADUserFields.ps1
│ ├── Set-WinADUserSettingGAL.ps1
│ └── Set-WinADUserStatus.ps1
├── AzureAD
│ ├── Get-WinAzureADUsers.ps1
│ ├── Set-WinAzureADUserField.ps1
│ ├── Set-WinAzureADUserLicense.ps1
│ └── Set-WinAzureADUserStatus.ps1
├── Configuration
│ └── Get-PSAutomatorConfiguration.ps1
├── Main
│ ├── Complete-WorkFlow.ps1
│ ├── Get-WinDocumentationText.ps1
│ ├── Resolve-IgnoreTexts.ps1
│ ├── Search-ObjectToIgnore.ps1
│ ├── Start-Configuration.ps1
│ ├── Submit-ActionActiveDirectory.ps1
│ ├── Submit-ActionAzureActiveDirectory.ps1
│ ├── Submit-ActionExchange.ps1
│ ├── Submit-ConditionEmptyOrNull.ps1
│ ├── Submit-ConditionFields.ps1
│ └── Submit-ConditionOrganizationalUnit.ps1
├── Output
│ ├── Out-ActionStatus.ps1
│ ├── Out-ConfigurationStatus.ps1
│ ├── Out-ConnectionStatus.ps1
│ ├── Out-ServiceStatus.ps1
│ └── Out-TriggerStatus.ps1
└── Parameters
│ ├── Script.Debug.ps1
│ ├── Script.GroupProperties.ps1
│ ├── Script.UserProperties.ps1
│ └── Script.WriteParameters.ps1
├── Public
├── Configuration
│ └── New-PSAutomatorConfiguration.ps1
└── Main
│ ├── Action.ps1
│ ├── Condition.ps1
│ ├── Connect.ps1
│ ├── Service.ps1
│ └── Trigger.ps1
├── Publish
└── Manage-Module.ps1
└── README.MD
/Enums/ActionAD.ps1:
--------------------------------------------------------------------------------
1 | Add-Type -TypeDefinition @"
2 | using System;
3 |
4 | namespace PSAutomator
5 | {
6 | [Flags]
7 | public enum ActionAD {
8 | AccountAddGroupsSpecific,
9 | AccountDisable,
10 | AccountEnable,
11 | AccountHideInGAL,
12 | AccountShowInGAL,
13 | AccountRemoveGroupsAll,
14 | AccountRemoveGroupsSecurity,
15 | AccountRemoveGroupsDistribution,
16 | AccountRemoveGroupsSpecific, // Array - Specific groups
17 | AccountRemoveGroupsDomainLocal, // true - false
18 | AccountRemoveGroupsGlobal, // true - false
19 | AccountRemoveGroupsUniversal, // true - false
20 | AccountRename,
21 | AccountSnapshot
22 | }
23 | }
24 | "@
--------------------------------------------------------------------------------
/Enums/ActionAzureAD.ps1:
--------------------------------------------------------------------------------
1 | Add-Type -TypeDefinition @"
2 | using System;
3 |
4 | namespace PSAutomator
5 | {
6 | [Flags]
7 | public enum ActionAzureAD {
8 | AccountAddGroupsSpecific,
9 | AccountDisable,
10 | AccountEnable,
11 | AccountRemoveGroupsAll,
12 | AccountRemoveGroupsSecurity,
13 | AccountRemoveGroupsDistribution,
14 | AccountRemoveGroupsSpecific, // Array - Specific groups
15 | AccountRename,
16 | AccountSnapshot,
17 | AddLicense,
18 | RemoveLicense,
19 | RemoveLicenseAll,
20 | ReplaceLicense,
21 | EnableMFA,
22 | DisableMFA,
23 | SetUserRole,
24 | SetField,
25 | SynchronizeFields
26 | }
27 | }
28 | "@
--------------------------------------------------------------------------------
/Enums/ActionExchange.ps1:
--------------------------------------------------------------------------------
1 | Add-Type -TypeDefinition @"
2 | using System;
3 |
4 | namespace PSAutomator
5 | {
6 | [Flags]
7 | public enum ActionExchange {
8 | MailboxConvertToSharedMailbox, // True/False
9 | MailboxEmailAddressPolicyEnable, // True/False
10 | ContactConvertToMailContact, // Array
11 | MailboxRemoteEnable
12 | }
13 | }
14 | "@
--------------------------------------------------------------------------------
/Enums/ActionExchangeOnline.ps1:
--------------------------------------------------------------------------------
1 | Add-Type -TypeDefinition @"
2 | using System;
3 |
4 | namespace PSAutomator
5 | {
6 | [Flags]
7 | public enum ActionExchangeOnline {
8 | MailboxConvertToSharedMailbox, // True/False
9 | MailboxEmailAddressPolicyEnable, // True/False
10 | ContactConvertToMailContact // Array
11 | }
12 | }
13 | "@
--------------------------------------------------------------------------------
/Enums/Condition.ps1:
--------------------------------------------------------------------------------
1 | Add-Type -TypeDefinition @"
2 | using System;
3 |
4 | namespace PSAutomator
5 | {
6 | [Flags]
7 | public enum Condition {
8 | EmptyOrNull,
9 | Field,
10 | GroupMembership,
11 | OrganizationalUnit
12 | }
13 | }
14 | "@
--------------------------------------------------------------------------------
/Enums/Connect.ps1:
--------------------------------------------------------------------------------
1 | Add-Type -TypeDefinition @"
2 | using System;
3 |
4 | namespace PSAutomator
5 | {
6 | public enum Connect {
7 | ActiveDirectory,
8 | Azure,
9 | AzureAD,
10 | Exchange,
11 | ExchangeOnline
12 | }
13 | }
14 | "@
--------------------------------------------------------------------------------
/Enums/TriggerComputer.ps1:
--------------------------------------------------------------------------------
1 | Add-Type -TypeDefinition @"
2 | using System;
3 |
4 | namespace PSAutomator
5 | {
6 | [Flags]
7 | public enum TriggerComputer {
8 | Always,
9 | OrganizationalUnit,
10 | GroupMembership,
11 | Filter
12 | }
13 | }
14 | "@
--------------------------------------------------------------------------------
/Enums/TriggerGroup.ps1:
--------------------------------------------------------------------------------
1 | Add-Type -TypeDefinition @"
2 | using System;
3 |
4 | namespace PSAutomator
5 | {
6 | [Flags]
7 | public enum TriggerGroup {
8 | Always,
9 | OrganizationalUnit,
10 | Filter
11 | }
12 | }
13 | "@
--------------------------------------------------------------------------------
/Enums/TriggerUserAD.ps1:
--------------------------------------------------------------------------------
1 | Add-Type -TypeDefinition @"
2 | using System;
3 |
4 | namespace PSAutomator
5 | {
6 | [Flags]
7 | public enum TriggerUserAD {
8 | Always,
9 | OrganizationalUnit,
10 | GroupMembership,
11 | Filter
12 | }
13 | }
14 | "@
--------------------------------------------------------------------------------
/Enums/TriggerUserAzureAD.ps1:
--------------------------------------------------------------------------------
1 | Add-Type -TypeDefinition @"
2 | using System;
3 |
4 | namespace PSAutomator
5 | {
6 | [Flags]
7 | public enum TriggerUserAzureAD {
8 | All,
9 |
10 | ByFields,
11 | //ByCountry,
12 | //ByCity,
13 | //ByDepartment,
14 | //ByState,
15 | //ByTitle,
16 | //ByUsageLocation,
17 |
18 | Deleted,
19 | Domain,
20 |
21 | //HasErrors,
22 |
23 | Unlicensed,
24 | UserPrincipalName,
25 |
26 | Search,
27 | Synchronized
28 | }
29 | }
30 | "@
--------------------------------------------------------------------------------
/Examples/CreateConfiguration.ps1:
--------------------------------------------------------------------------------
1 | $Configuration = [ordered] @{
2 | Prettify = [ordered] @{
3 | CompanyName = 'Evotec'
4 | Debug = @{
5 | Verbose = $false
6 | }
7 | DisplayConsole = @{
8 | Standard = @{
9 | ShowTime = $true
10 | LogFile = ""
11 | TimeFormat = "yyyy-MM-dd HH:mm:ss"
12 | }
13 | }
14 | }
15 | Services = [ordered] @{
16 | OnPremises = [ordered] @{
17 | ActiveDirectory = [ordered] @{
18 | Credentials = [ordered] @{
19 | Username = ''
20 | Password = ''
21 | PasswordAsSecure = $true
22 | PasswordFromFile = $true
23 | }
24 | Use = $true
25 | Prefix = ''
26 | SessionName = 'Active Directory'
27 | }
28 | Exchange = [ordered] @{
29 | Credentials = [ordered] @{
30 | UserName = '' # if Kerberos leave empty (domain joined computers usually)
31 | Password = '' # same as above
32 | PasswordAsSecure = $true
33 | PasswordFromFile = $true
34 | }
35 | Use = $false
36 | Prefix = ''
37 |
38 | SessionName = 'Exchange On-Premises'
39 | Authentication = 'Kerberos'
40 | ConnectionURI = 'http://ex2013x3.ad.evotec.xyz/PowerShell'
41 | LeaveOpen = $true
42 |
43 | }
44 | }
45 | Office365 = [ordered] @{
46 | Credentials = [ordered] @{
47 | Username = 'przemyslaw.klys@evotec.pl'
48 | Password = 'C:\Support\Important\Password-O365-Evotec.txt'
49 | PasswordAsSecure = $true
50 | PasswordFromFile = $true
51 | }
52 | Azure = [ordered] @{
53 | Use = $true
54 | SessionName = 'O365 Azure MSOL' # MSOL
55 | }
56 | AzureAD = [ordered] @{
57 | Use = $false
58 | SessionName = 'O365 Azure AD' # Azure
59 | Prefix = ''
60 | }
61 | ExchangeOnline = [ordered] @{
62 | Use = $false
63 | Authentication = 'Basic'
64 | ConnectionURI = 'https://outlook.office365.com/powershell-liveid/'
65 | Prefix = 'O365'
66 | SessionName = 'O365 Exchange'
67 | }
68 | Teams = [ordered] @{
69 | Use = $false
70 | Prefix = ''
71 | SessionName = 'O365 Teams'
72 | }
73 | }
74 | }
75 | }
76 |
77 | New-PSAutomatorConfiguration -Configuration $Configuration -Path 'Examples\MyConfiguration1.xml'
--------------------------------------------------------------------------------
/Examples/MyConfiguration1.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | System.Collections.Specialized.OrderedDictionary
5 | System.Object
6 |
7 |
8 |
9 | Prettify
10 |
11 |
12 |
13 |
14 | CompanyName
15 | Evotec
16 |
17 |
18 | Debug
19 |
20 |
21 | System.Collections.Hashtable
22 | System.Object
23 |
24 |
25 |
26 | Verbose
27 | false
28 |
29 |
30 |
31 |
32 |
33 | DisplayConsole
34 |
35 |
36 |
37 |
38 | Standard
39 |
40 |
41 |
42 |
43 | ShowTime
44 | true
45 |
46 |
47 | TimeFormat
48 | yyyy-MM-dd HH:mm:ss
49 |
50 |
51 | LogFile
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 | Services
65 |
66 |
67 |
68 |
69 | OnPremises
70 |
71 |
72 |
73 |
74 | ActiveDirectory
75 |
76 |
77 |
78 |
79 | Credentials
80 |
81 |
82 |
83 |
84 | Username
85 |
86 |
87 |
88 | Password
89 |
90 |
91 |
92 | PasswordAsSecure
93 | true
94 |
95 |
96 | PasswordFromFile
97 | true
98 |
99 |
100 |
101 |
102 |
103 | Use
104 | true
105 |
106 |
107 | Prefix
108 |
109 |
110 |
111 | SessionName
112 | Active Directory
113 |
114 |
115 |
116 |
117 |
118 | Exchange
119 |
120 |
121 |
122 |
123 | Credentials
124 |
125 |
126 |
127 |
128 | UserName
129 |
130 |
131 |
132 | Password
133 |
134 |
135 |
136 | PasswordAsSecure
137 | true
138 |
139 |
140 | PasswordFromFile
141 | true
142 |
143 |
144 |
145 |
146 |
147 | Use
148 | false
149 |
150 |
151 | Prefix
152 |
153 |
154 |
155 | SessionName
156 | Exchange On-Premises
157 |
158 |
159 | Authentication
160 | Kerberos
161 |
162 |
163 | ConnectionURI
164 | http://ex2013x3.ad.evotec.xyz/PowerShell
165 |
166 |
167 | LeaveOpen
168 | true
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 | Office365
178 |
179 |
180 |
181 |
182 | Credentials
183 |
184 |
185 |
186 |
187 | Username
188 | przemyslaw.klys@evotec.pl
189 |
190 |
191 | Password
192 | C:\Support\Important\Password-O365-Evotec.txt
193 |
194 |
195 | PasswordAsSecure
196 | true
197 |
198 |
199 | PasswordFromFile
200 | true
201 |
202 |
203 |
204 |
205 |
206 | Azure
207 |
208 |
209 |
210 |
211 | Use
212 | true
213 |
214 |
215 | SessionName
216 | O365 Azure MSOL
217 |
218 |
219 |
220 |
221 |
222 | AzureAD
223 |
224 |
225 |
226 |
227 | Use
228 | false
229 |
230 |
231 | SessionName
232 | O365 Azure AD
233 |
234 |
235 | Prefix
236 |
237 |
238 |
239 |
240 |
241 |
242 | ExchangeOnline
243 |
244 |
245 |
246 |
247 | Use
248 | false
249 |
250 |
251 | Authentication
252 | Basic
253 |
254 |
255 | ConnectionURI
256 | https://outlook.office365.com/powershell-liveid/
257 |
258 |
259 | Prefix
260 | O365
261 |
262 |
263 | SessionName
264 | O365 Exchange
265 |
266 |
267 |
268 |
269 |
270 | Teams
271 |
272 |
273 |
274 |
275 | Use
276 | false
277 |
278 |
279 | Prefix
280 |
281 |
282 |
283 | SessionName
284 | O365 Teams
285 |
286 |
287 |
288 |
289 |
290 |
291 |
292 |
293 |
294 |
295 |
296 |
297 |
--------------------------------------------------------------------------------
/Examples/RunBook.BackupDefinedUser.ps1:
--------------------------------------------------------------------------------
1 | Clear-Host
2 | Import-Module PSAutomator -Force #-Verbose
3 | Import-Module PSSharedGoods -Force
4 |
5 | Service -Name 'Active Directory Offboarding' -ConfigurationPath 'C:\Support\GitHub\PSAutomator\Examples\MyConfiguration1.xml' {
6 | Trigger -Name 'OU Offboarded Users' -User Filter -Value @{ Filter = "UserPrincipalName -eq 'przemyslaw.klys@ad.evotec.xyz'"; SearchBase = 'OU=Users,OU=Production,DC=ad,DC=evotec,DC=xyz' } |
7 | Condition -Name 'No conditions' |
8 | Condition -Name 'Ignore Windows Email Address if Empty or null' -Condition EmptyOrNull -Value EmailAddress |
9 | Action -Name 'Make User Snapshot' -ActiveDirectory AccountSnapshot -Value 'C:\Users\pklys\Desktop\MyExport' -WhatIf
10 | }
--------------------------------------------------------------------------------
/Examples/RunBook.EnableRemoteMailbox.ps1:
--------------------------------------------------------------------------------
1 | Clear-Host
2 | Import-Module PSAutomator -Force #-Verbose
3 | Import-Module PSSharedGoods -Force
4 |
5 | Service -Name 'Active Directory Remote Mailbox' -ConfigurationPath 'C:\Support\GitHub\PSAutomator\Examples\MyConfiguration1.xml' {
6 | Trigger -Name 'OU Offboarded Users' -User Filter -Value @{ Filter = '*'; SearchBase = 'OU=Production,DC=ad,DC=evotec,DC=xyz' } |
7 | Condition -Name 'Member of Disabled Users' -Condition GroupMembership -Value @{ Field = 'Name'; Operator = 'eq'; Value = 'Disabled Users' } |
8 | Condition -Name 'Not member of OU' -Condition OrganizationalUnit -Value @{ Field = 'DistinguishedName'; Operator = 'notlike'; Valuee = 'Users-Offboarded*' } |
9 | #Condition -Name 'Ignore MyUser Account' -Condition Field -Value @{ Field = 'UserPrincipalName'; Operator = 'notlike'; Value = 'myuser*' } |
10 | Condition |
11 | Action -Name 'Make User Snapshot' -ActiveDirectory AccountSnapshot -Value 'C:\Users\pklys\Desktop\MyExport' -WhatIf |
12 | Action -Name 'Enable remote mailbox on Office 365' -Exchange MailboxRemoteEnable -WhatIf
13 |
14 | }
--------------------------------------------------------------------------------
/Examples/RunBook.JustTrigger-NoAction.ps1:
--------------------------------------------------------------------------------
1 | Clear-Host
2 | Import-Module PSAutomator -Force #-Verbose
3 | Import-Module PSSharedGoods #-Force
4 |
5 | Service -Name 'Active Directory Offboarding' -Status Enable -ConfigurationPath 'C:\Support\GitHub\PSAutomator\Examples\MyConfiguration1.xml' {
6 | Trigger -Name 'OU Offboarded Users' -User OrganizationalUnit -Value 'OU=Users-Offboarded,OU=Production,DC=ad,DC=evotec,DC=xyz'
7 | }
8 |
--------------------------------------------------------------------------------
/Examples/RunBook.UsersAddOffboarded.ps1:
--------------------------------------------------------------------------------
1 | Clear-Host
2 | Import-Module PSAutomator -Force #-Verbose
3 | Import-Module PSSharedGoods -Force
4 |
5 | Service -Name 'Active Directory Add Users To Group' {
6 | Trigger -Name 'Find Offboarded Users' -User OrganizationalUnit -Value 'OU=Users-Offboarded,OU=Production,DC=ad,DC=evotec,DC=xyz' |
7 | Condition |
8 | Action -Name 'Add Users To Disabled Group' -ActiveDirectory AccountAddGroupsSpecific -Value 'Disabled Users' -WhatIf
9 | }
--------------------------------------------------------------------------------
/Examples/RunBook.UsersAzure.ps1:
--------------------------------------------------------------------------------
1 | Clear-Host
2 | Import-Module PSAutomator -Force #-Verbose
3 | Import-Module PSSharedGoods #-Force
4 |
5 | Service -Name 'Active Directory Offboarding' -Status Enable -ConfigurationPath 'C:\Support\GitHub\PSAutomator\Examples\MyConfiguration1.xml' {
6 | Trigger -Name 'Synchronized Users from AD' -UserAzureAD Synchronized |
7 | Condition -Name 'Ignore Synchronization Account' -Condition Field -Value @{ Field = 'UserPrincipalName'; Operator = 'notlike'; Value = 'Sync_ADConnect*' } |
8 | Action -Name 'Disable Synchronized Users' -AzureActiveDirectory AccountDisable -WhatIf
9 | }
10 |
--------------------------------------------------------------------------------
/Examples/RunBook.UsersAzurePlayLicenses.ps1:
--------------------------------------------------------------------------------
1 | Clear-Host
2 | Import-Module PSAutomator -Force #-Verbose
3 | Import-Module PSSharedGoods -Force
4 |
5 | Service -Name 'Removing Licenses from Some Users' -Status Enable -ConfigurationPath 'C:\Support\GitHub\PSAutomator\Examples\MyConfiguration1.xml' {
6 | Trigger -Name 'All users in Azure AD' -UserAzureAD All |
7 | Condition -Name 'Ignore Synchronization Account' -Condition Field -Value @{ Field = 'UserPrincipalName'; Operator = 'notlike'; Value = 'Sync_ADConnect*' } |
8 | Condition -Name 'Only Licensed Users' -Condition Field -Value @{ Field = 'IsLicensed'; Operator = 'eq'; Value = $true } |
9 | Condition -Name 'Only Synchronized Users' -Condition Field -Value @{ Field = 'LastDirSyncTime'; Operator = 'ne'; Value = $null } |
10 | Action -Name 'Remove all licenses' -AzureActiveDirectory RemoveLicenseAll #-WhatIf
11 | }
12 |
13 | return
14 |
15 | Service -Name 'Adding licenses to Some users' -Status Enable -ConfigurationPath 'C:\Support\GitHub\PSAutomator\Examples\MyConfiguration1.xml' {
16 | Trigger -Name 'All unlicensed users in Azure AD' -UserAzureAD Unlicensed |
17 | Condition -Name 'Ignore Synchronization Account' -Condition Field -Value @{ Field = 'UserPrincipalName'; Operator = 'notlike'; Value = 'Sync_ADConnect*' } |
18 | Condition -Name 'Only Synchronized Users' -Condition Field -Value @{ Field = 'LastDirSyncTime'; Operator = 'ne'; Value = $null } |
19 | Action -Name 'Set usage location' -AzureActiveDirectory SetField -Value @{ Field = 'UsageLocation'; Value = 'PL' } |
20 | Action -Name 'Add business essentials license' -AzureActiveDirectory AddLicense -Value 'evotecpoland:O365_BUSINESS_ESSENTIALS' |
21 | Action -Name 'Add flow license' -AzureActiveDirectory AddLicense -Value 'evotecpoland:FLOW_FREE'
22 | }
23 |
24 | <#
25 | evotecpoland:FLOW_FREE
26 | evotecpoland:STANDARDPACK
27 |
28 | AccountSkuId ActiveUnits WarningUnits ConsumedUnits
29 | ------------ ----------- ------------ -------------
30 | evotecpoland:DESKLESSPACK 2 0 2
31 | evotecpoland:FLOW_FREE 10000 0 1
32 | evotecpoland:O365_BUSINESS_ESSENTIALS 2 0 2
33 | evotecpoland:STANDARDPACK 1 0 1
34 |
35 | #>
--------------------------------------------------------------------------------
/Examples/RunBook.UsersDisable.ps1:
--------------------------------------------------------------------------------
1 | Clear-Host
2 | Import-Module PSAutomator -Force #-Verbose
3 | Import-Module PSSharedGoods #-Force
4 |
5 | Service -Name 'Active Directory Disable Users in Group' {
6 | Trigger -Name 'User is a member of Disabled Users group' -User GroupMembership -Value 'Disabled Users' |
7 | Condition -Name 'Ignore Email Address like *@evotec.pl' -Condition Field -Value @{ Field = 'EmailAddress'; Operator = 'notlike'; Value = '*@evotec.pl' } |
8 | Condition -Name 'Ignore Email Address if Empty or Null' -Condition EmptyOrNull -Value EmailAddress |
9 | Action -Name 'Disable Evotec Users' -ActiveDirectory AccountDisable -WhatIf
10 | }
--------------------------------------------------------------------------------
/Examples/RunBook.UsersEnableOffboarded.ps1:
--------------------------------------------------------------------------------
1 | Clear-Host
2 | Import-Module PSAutomator -Force #-Verbose
3 | Import-Module PSSharedGoods #-Force
4 |
5 | Service -Name 'Active Directory Enable Users in OU' {
6 | Trigger -Name 'Find Offboarded Users' -User OrganizationalUnit -Value 'OU=Users-Offboarded,OU=Production,DC=ad,DC=evotec,DC=xyz' |
7 | Condition |
8 | Action -Name 'Enable Offboarded Users' -ActiveDirectory AccountEnable -WhatIf |
9 | Action -Name 'Add to group GDS-TestGroup5' -ActiveDirectory AccountAddGroupsSpecific -Value 'GDS-TestGroup5' -WhatIf |
10 | Action -Name 'Add to group GDS-TestGroup4' -ActiveDirectory AccountAddGroupsSpecific -Value 'GDS-TestGroup4' -Whatif |
11 | Action -Name 'Remove Offboarded Tag' -ActiveDirectory AccountRename -Value @{ Action = 'RemoveText'; Fields = 'DisplayName', 'Name' ; Text = ' (offboarded)'; } -WhatIf
12 | }
--------------------------------------------------------------------------------
/Examples/RunBook.UsersEnabledAddedToGroup.ps1:
--------------------------------------------------------------------------------
1 | Clear-Host
2 | Import-Module PSAutomator -Force #-Verbose
3 | Import-Module PSSharedGoods #-Force
4 |
5 | Service -Name 'Active Directory Offboarding' -ConfigurationPath 'C:\Support\GitHub\PSAutomator\Examples\MyConfiguration.xml' {
6 | Trigger -Name 'Reenabling my users for testing purposes' -User OrganizationalUnit -Value 'OU=Users-Offboarded,OU=Production,DC=ad,DC=evotec,DC=xyz' |
7 | Condition -Name 'No conditions' |
8 | Condition -Name 'Ignore Windows Email Address if Empty or null' -Condition EmptyOrNull -Value EmailAddress |
9 | Action -Name 'Enable AD Account' -ActiveDirectory AccountEnable -WhatIf |
10 | Action -Name 'Add user to Disabled Users' -ActiveDirectory AccountAddGroupsSpecific -Value 'Disabled Users' -WhatIf
11 | }
--------------------------------------------------------------------------------
/Examples/RunBook.UsersOffboarding.1.ps1:
--------------------------------------------------------------------------------
1 | Clear-Host
2 | Import-Module PSAutomator -Force #-Verbose
3 | Import-Module PSSharedGoods #-Force
4 |
5 | Service -Name 'Active Directory Prepare Users' {
6 | Trigger -Name 'Offboard Users' -User OrganizationalUnit -Value 'OU=Users-Offboarded,OU=Production,DC=ad,DC=evotec,DC=xyz' |
7 | Condition |
8 | Action -Name 'Disable Users' -ActiveDirectory AccountDisable -WhatIf |
9 | Action -Name 'Add to group' -ActiveDirectory AccountAddGroupsSpecific -Value 'Disabled Users' -WhatIf
10 | }
--------------------------------------------------------------------------------
/Examples/RunBook.UsersOffboarding.2.ps1:
--------------------------------------------------------------------------------
1 | Clear-Host
2 | Import-Module PSAutomator -Force #-Verbose
3 | Import-Module PSSharedGoods -Force
4 |
5 | Service -Name 'Active Directory Offboarding' -ConfigurationPath 'C:\Support\GitHub\PSAutomator\Examples\MyConfiguration.xml' {
6 | Trigger -Name 'OU Offboarded Users' -User OrganizationalUnit -Value 'OU=Users-Offboarded,OU=Production,DC=ad,DC=evotec,DC=xyz' |
7 | Condition -Name 'No conditions' |
8 | Condition -Name 'Ignore Windows Email Address if Empty or null' -Condition EmptyOrNull -Value 'EmailAddress' |
9 | Action -Name 'Make User Snapshot' -ActiveDirectory AccountSnapshot -Value 'C:\Users\pklys\Desktop\MyExport' -Whatif |
10 | Action -Name 'Disable AD Account' -ActiveDirectory AccountDisable -WhatIf |
11 | Action -Name 'Hide account in GAL' -ActiveDirectory AccountHideInGAL -WhatIf |
12 | Action -Name 'Remove all security groups' -ActiveDirectory AccountRemoveGroupsSecurity -WhatIf |
13 | Action -Name 'Rename Account' -ActiveDirectory AccountRename -Value @{ Action = 'AddText'; Where = 'After'; Fields = 'DisplayName', 'Name'; Text = ' (offboarded)'; } -WhatIf
14 | }
--------------------------------------------------------------------------------
/Examples/RunBook.UsersRevive.ps1:
--------------------------------------------------------------------------------
1 | Clear-Host
2 | Import-Module PSAutomator -Force #-Verbose
3 | Import-Module PSSharedGoods #-Force
4 |
5 | Service -Name 'Active Directory Prepare Users' {
6 | Trigger -Name 'Enable already Offboarded Users' -User OrganizationalUnit -Value 'OU=Users-Offboarded,OU=Production,DC=ad,DC=evotec,DC=xyz' |
7 | Condition |
8 | Action -Name 'Enable Users' -ActiveDirectory AccountEnable -WhatIf |
9 | Action -Name 'Remove Users From Group' -ActiveDirectory AccountRemoveGroupsSpecific -Value 'Disabled Users' -WhatIf
10 | }
--------------------------------------------------------------------------------
/PSAutomator.psd1:
--------------------------------------------------------------------------------
1 | @{
2 | AliasesToExport = 'Ignore'
3 | Author = 'Przemyslaw Klys'
4 | CmdletsToExport = @()
5 | CompanyName = 'Evotec'
6 | Copyright = '(c) 2018 Przemyslaw Klys. All rights reserved.'
7 | Description = 'PowerShell Module is new approach to onboarding, offboarding and business as usual processes running in companies infrastructure. Usually each company has different rules, different approaches on how processes should look like and this module takes an easy approach that''s similar to what you can find in services like IFTTT or Microsoft Flow'
8 | FunctionsToExport = @('New-PSAutomatorConfiguration', 'Action', 'Condition', 'Connect', 'Service', 'Trigger')
9 | GUID = '1be9e392-28cb-4ac6-aba7-b924defbf9da'
10 | ModuleVersion = '0.0.3'
11 | PowerShellVersion = '5.1'
12 | PrivateData = @{
13 | PSData = @{
14 | Tags = @('ActiveDirectory', 'Offboarding', 'Onboarding', 'Windows')
15 | ProjectUri = 'https://github.com/EvotecIT/PSAutomator'
16 | IconUri = 'https://evotec.xyz/wp-content/uploads/2018/10/PSAutomator.png'
17 | }
18 | }
19 | RequiredModules = @('PSSharedGoods', 'PSWriteColor')
20 | RootModule = 'PSAutomator.psm1'
21 | }
--------------------------------------------------------------------------------
/PSAutomator.psm1:
--------------------------------------------------------------------------------
1 | #Get public and private function definition files.
2 | $Public = @( Get-ChildItem -Path $PSScriptRoot\Public\*.ps1 -ErrorAction SilentlyContinue -Recurse )
3 | $Private = @( Get-ChildItem -Path $PSScriptRoot\Private\*.ps1 -ErrorAction SilentlyContinue -Recurse )
4 |
5 | $AssemblyFolders = Get-ChildItem -Path $PSScriptRoot\Lib -Directory -ErrorAction SilentlyContinue
6 | if ($AssemblyFolders.BaseName -contains 'Standard') {
7 | $Assembly = @( Get-ChildItem -Path $PSScriptRoot\Lib\Standard\*.dll -ErrorAction SilentlyContinue )
8 | } else {
9 | if ($PSEdition -eq 'Core') {
10 | $Assembly = @( Get-ChildItem -Path $PSScriptRoot\Lib\Core\*.dll -ErrorAction SilentlyContinue )
11 | } else {
12 | $Assembly = @( Get-ChildItem -Path $PSScriptRoot\Lib\Default\*.dll -ErrorAction SilentlyContinue )
13 | }
14 | }
15 | $FoundErrors = @(
16 | Foreach ($Import in @($Assembly)) {
17 | try {
18 | Add-Type -Path $Import.Fullname -ErrorAction Stop
19 | } catch [System.Reflection.ReflectionTypeLoadException] {
20 | Write-Warning "Processing $($Import.Name) Exception: $($_.Exception.Message)"
21 | $LoaderExceptions = $($_.Exception.LoaderExceptions) | Sort-Object -Unique
22 | foreach ($E in $LoaderExceptions) {
23 | Write-Warning "Processing $($Import.Name) LoaderExceptions: $($E.Message)"
24 | }
25 | $true
26 | #Write-Error -Message "StackTrace: $($_.Exception.StackTrace)"
27 | } catch {
28 | Write-Warning "Processing $($Import.Name) Exception: $($_.Exception.Message)"
29 | $LoaderExceptions = $($_.Exception.LoaderExceptions) | Sort-Object -Unique
30 | foreach ($E in $LoaderExceptions) {
31 | Write-Warning "Processing $($Import.Name) LoaderExceptions: $($E.Message)"
32 | }
33 | $true
34 | #Write-Error -Message "StackTrace: $($_.Exception.StackTrace)"
35 | }
36 | }
37 | #Dot source the files
38 | Foreach ($Import in @($Private + $Public)) {
39 | Try {
40 | . $Import.Fullname
41 | } Catch {
42 | Write-Error -Message "Failed to import functions from $($import.Fullname): $_"
43 | $true
44 | }
45 | }
46 | )
47 |
48 | if ($FoundErrors.Count -gt 0) {
49 | $ModuleName = (Get-ChildItem $PSScriptRoot\*.psd1).BaseName
50 | Write-Warning "Importing module $ModuleName failed. Fix errors before continuing."
51 | break
52 | }
53 |
54 | Export-ModuleMember -Function '*' -Alias '*'
--------------------------------------------------------------------------------
/Private/ActiveDirectory/Add-WinADUserGroups.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | Output of Get-ADPrincipalGroupmembership:
3 |
4 | distinguishedName : CN=Organization Management,OU=Microsoft Exchange Security Groups,DC=ad,DC=evotec,DC=xyz
5 | GroupCategory : Security
6 | GroupScope : Universal
7 | name : Organization Management
8 | objectClass : group
9 | objectGUID : 551c2400-f0d2-4aa6-8dbf-f9722ceb8675
10 | SamAccountName : Organization Management
11 | SID : S-1-5-21-853615985-2870445339-3163598659-1117
12 |
13 | #>
14 |
15 | function Add-WinADUserGroups {
16 | <#
17 | .SYNOPSIS
18 | Adds a user to specified Active Directory groups.
19 |
20 | .DESCRIPTION
21 | This function adds a user to the specified Active Directory groups. It retrieves the user's current group memberships and adds the user to the specified groups if they are not already a member.
22 |
23 | .PARAMETER User
24 | The user object to add to the groups.
25 |
26 | .PARAMETER Groups
27 | An array of group names to add the user to.
28 |
29 | .PARAMETER FieldSearch
30 | The field to search for group names. Default is 'Name'.
31 |
32 | .PARAMETER WhatIf
33 | Specifies whether to perform a test run without making any changes.
34 |
35 | .EXAMPLE
36 | Add-WinADUserGroups -User $UserObject -Groups @("Group1", "Group2")
37 |
38 | Adds the user specified by $UserObject to the groups "Group1" and "Group2".
39 |
40 | .EXAMPLE
41 | Add-WinADUserGroups -User $UserObject -Groups @("Group1", "Group2") -FieldSearch 'SamAccountName'
42 |
43 | Adds the user specified by $UserObject to the groups "Group1" and "Group2" using 'SamAccountName' for group name search.
44 |
45 | .NOTES
46 | File Name : Add-WinADUserGroups.ps1
47 | Prerequisite : Requires Active Directory module.
48 | #>
49 | [CmdletBinding()]
50 | [alias("Add-ADUserGroups")]
51 | param(
52 | [parameter(Mandatory = $true)][Object] $User,
53 | [string[]] $Groups,
54 | [string] $FieldSearch = 'Name',
55 | [switch] $WhatIf
56 | )
57 | $Object = @()
58 | try {
59 | $ADgroups = Get-ADPrincipalGroupMembership -Identity $User.DistinguishedName | Where-Object {$_.Name -ne "Domain Users" }
60 | } catch {
61 | $ErrorMessage = $_.Exception.Message -replace "`n", " " -replace "`r", " "
62 | $Object += @{ Status = $false; Output = $Group.Name; Extended = $ErrorMessage }
63 | }
64 | if ($Groups) {
65 | foreach ($Group in $Groups) {
66 | if ($ADgroups.$FieldSearch -notcontains $Group) {
67 | try {
68 | if (-not $WhatIf) {
69 | Add-ADGroupMember -Identity $Group -Members $User.DistinguishedName -ErrorAction Stop
70 | }
71 | $Object += @{ Status = $true; Output = $Group; Extended = 'Added to group.' }
72 |
73 | } catch {
74 | $ErrorMessage = $_.Exception.Message -replace "`n", " " -replace "`r", " "
75 | $Object += @{ Status = $false; Output = $Group; Extended = $ErrorMessage }
76 | }
77 | } else {
78 | # Turned off to not clutter view, may required turning back on.
79 | #$Object += @{ Status = $false; Output = $Group; Extended = 'Already exists.' }
80 | }
81 | }
82 | }
83 | return $Object
84 | }
--------------------------------------------------------------------------------
/Private/ActiveDirectory/Get-ADAdministrativeGroups.ps1:
--------------------------------------------------------------------------------
1 | function Get-ADADministrativeGroups {
2 | <#
3 | .SYNOPSIS
4 | Retrieves administrative groups information from Active Directory.
5 |
6 | .DESCRIPTION
7 | This function retrieves information about administrative groups in Active Directory based on the specified parameters.
8 |
9 | .PARAMETER Type
10 | Specifies the type of administrative groups to retrieve. Valid values are 'DomainAdmins' and 'EnterpriseAdmins'.
11 |
12 | .PARAMETER Forest
13 | Specifies the name of the forest to query for administrative groups.
14 |
15 | .PARAMETER ExcludeDomains
16 | Specifies an array of domains to exclude from the query.
17 |
18 | .PARAMETER IncludeDomains
19 | Specifies an array of domains to include in the query.
20 |
21 | .PARAMETER ExtendedForestInformation
22 | Specifies additional information about the forest to include in the query.
23 |
24 | .EXAMPLE
25 | Get-ADADministrativeGroups -Type DomainAdmins, EnterpriseAdmins
26 |
27 | Output (Where VALUE is Get-ADGroup output):
28 | Name Value
29 | ---- -----
30 | ByNetBIOS {EVOTEC\Domain Admins, EVOTEC\Enterprise Admins, EVOTECPL\Domain Admins}
31 | ad.evotec.xyz {DomainAdmins, EnterpriseAdmins}
32 | ad.evotec.pl {DomainAdmins}
33 |
34 | .NOTES
35 | This function requires Active Directory module to be installed on the system.
36 | #>
37 | [cmdletBinding()]
38 | param(
39 | [parameter(Mandatory)][validateSet('DomainAdmins', 'EnterpriseAdmins')][string[]] $Type,
40 | [alias('ForestName')][string] $Forest,
41 | [string[]] $ExcludeDomains,
42 | [alias('Domain', 'Domains')][string[]] $IncludeDomains,
43 | [System.Collections.IDictionary] $ExtendedForestInformation
44 | )
45 | $ADDictionary = [ordered] @{ }
46 | $ADDictionary['ByNetBIOS'] = [ordered] @{ }
47 | $ADDictionary['BySID'] = [ordered] @{ }
48 |
49 | $ForestInformation = Get-WinADForestDetails -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation
50 | foreach ($Domain in $ForestInformation.Domains) {
51 | $ADDictionary[$Domain] = [ordered] @{ }
52 | $QueryServer = $ForestInformation['QueryServers'][$Domain]['HostName'][0]
53 | $DomainInformation = Get-ADDomain -Server $QueryServer
54 |
55 | if ($Type -contains 'DomainAdmins') {
56 | Get-ADGroup -Filter "SID -eq '$($DomainInformation.DomainSID)-512'" -Server $QueryServer -ErrorAction SilentlyContinue | ForEach-Object {
57 | $ADDictionary['ByNetBIOS']["$($DomainInformation.NetBIOSName)\$($_.Name)"] = $_
58 | $ADDictionary[$Domain]['DomainAdmins'] = "$($DomainInformation.NetBIOSName)\$($_.Name)"
59 | $ADDictionary['BySID'][$_.SID.Value] = $_
60 | }
61 | }
62 | }
63 | # We need to treat EnterpriseAdmins separatly as it should be always available, not only when requested specific domain
64 | foreach ($Domain in $ForestInformation.Forest.Domains) {
65 | if (-not $ADDictionary[$Domain]) {
66 | $ADDictionary[$Domain] = [ordered] @{ }
67 | }
68 | if ($Type -contains 'EnterpriseAdmins') {
69 | $QueryServer = $ForestInformation['QueryServers'][$Domain]['HostName'][0]
70 | $DomainInformation = Get-ADDomain -Server $QueryServer
71 |
72 | Get-ADGroup -Filter "SID -eq '$($DomainInformation.DomainSID)-519'" -Server $QueryServer -ErrorAction SilentlyContinue | ForEach-Object {
73 | $ADDictionary['ByNetBIOS']["$($DomainInformation.NetBIOSName)\$($_.Name)"] = $_
74 | $ADDictionary[$Domain]['EnterpriseAdmins'] = "$($DomainInformation.NetBIOSName)\$($_.Name)"
75 | $ADDictionary['BySID'][$_.SID.Value] = $_ #"$($DomainInformation.NetBIOSName)\$($_.Name)"
76 | }
77 | }
78 | }
79 | return $ADDictionary
80 | }
81 |
82 | #Get-WinADForestDetails -IncludeDomains 'ad.evotec.xyz'
83 | #Get-ADADministrativeGroups -Type DomainAdmins, EnterpriseAdmins -IncludeDomains 'ad.evotec.pl'
--------------------------------------------------------------------------------
/Private/ActiveDirectory/Get-WinADGroups.ps1:
--------------------------------------------------------------------------------
1 | function Get-WinADGroups {
2 | [CmdletBinding()]
3 | param(
4 | $Filter,
5 | $OrganizationalUnit
6 | )
7 | $Splatting = @{}
8 | if ($Filter -eq $null -and $OrganizationalUnit -eq $null) {
9 | $Splatting = $Filter
10 | } else {
11 | if ($OrganizationalUnit) {
12 | $Splatting.SearchBase = $OrganizationalUnit
13 | }
14 | if ($Filter) {
15 | $Splatting.Filter = $Filter
16 | }
17 | }
18 | $Groups = Get-ADGroup @Splatting -Properties $Script:GroupProperties
19 | return $Groups
20 | }
21 |
22 | #Get-ADGroup -Filter * -Properties * # $Script:GroupProperties
23 |
24 |
25 | #Get-WinADGroupsByDN -DistinguishedName 'CN=Disabled Users,OU=SecurityGroups,OU=Groups,OU=Production,DC=ad,DC=evotec,DC=xyz' -Field 'Name'
26 |
--------------------------------------------------------------------------------
/Private/ActiveDirectory/Get-WinADGroupsByDN.ps1:
--------------------------------------------------------------------------------
1 | function Get-WinADGroupsByDN {
2 |
3 | <# Returns one of the values
4 | DistinguishedName : CN=Disabled Users,OU=SecurityGroups,OU=Groups,OU=Production,DC=ad,DC=evotec,DC=xyz
5 | GroupCategory : Security
6 | GroupScope : Universal
7 | Name : Disabled Users
8 | ObjectClass : group
9 | ObjectGUID : b7b5961e-e190-4f01-973f-abdf824261a3
10 | SamAccountName : Disabled Users
11 | SID : S-1-5-21-853615985-2870445339-3163598659-1162
12 | #>
13 |
14 | param(
15 | [alias('DN')][string[]] $DistinguishedName,
16 | [string] $Field = 'Name', # return field
17 | [switch] $All
18 | )
19 | $Output = foreach ($DN in $DistinguishedName) {
20 | try {
21 | Get-AdGroup -Identity $DN
22 | } catch {
23 | # returns empty, basically ignores stuff
24 | }
25 | }
26 | if ($All) {
27 | return $Output
28 | } else {
29 | return $Output.$Field
30 | }
31 | }
32 |
33 |
34 |
35 |
36 | #Get-WinADUsersByDN -DistinguishedName 'CN=Przemyslaw Klys,OU=Users,OU=Production,DC=ad,DC=evotec,DC=xyz'
--------------------------------------------------------------------------------
/Private/ActiveDirectory/Get-WinADGroupsTranslate.ps1:
--------------------------------------------------------------------------------
1 | function Get-WinADGroupsTranslate {
2 | param (
3 | [System.Object[]] $Groups
4 | )
5 | $ReturnGroups = @(
6 | foreach ($Group in $Groups) {
7 | #$User = $Users | Where { $_.DistinguishedName -eq $Group.ManagedBy }
8 | [PSCustomObject] @{
9 | 'Group Name' = $Group.Name
10 | 'Group Display Name' = $Group.DisplayName
11 | 'Group Category' = $Group.GroupCategory
12 | 'Group Scope' = $Group.GroupScope
13 | 'Group SID' = $Group.SID.Value
14 | 'High Privileged Group' = if ($Group.AdminCount -eq 1) { $True } else { $False }
15 | 'Member Count' = $Group.Members.Count
16 | 'MemberOf Count' = $Group.MemberOf.Count
17 | 'Manager' = $Group.ManagedBy
18 | #'Manager' = $User.Name
19 | #'Manager Email' = $User.EmailAddress
20 | #'Group Members' = (Get-ADObjectFromDistingusishedName -ADCatalog $Data.DomainUsersFullList, $Data.DomainComputersFullList, $Data.DomainGroupsFullList -DistinguishedName $Group.Members -Type 'SamAccountName')
21 | 'Group Members' = $Group.Members
22 | }
23 | }
24 | )
25 | return $ReturnGroups
26 | }
27 |
--------------------------------------------------------------------------------
/Private/ActiveDirectory/Get-WinADOrganizationalUnitData.ps1:
--------------------------------------------------------------------------------
1 | function Get-WinADOrganizationalUnitData {
2 | <#
3 | .SYNOPSIS
4 | Retrieves detailed information about Active Directory Organizational Units.
5 |
6 | .DESCRIPTION
7 | This function retrieves detailed information about the specified Active Directory Organizational Units, including properties like CanonicalName, City, Country, Description, and more.
8 |
9 | .PARAMETER OrganizationalUnit
10 | Specifies the Organizational Units to retrieve information for.
11 |
12 | .EXAMPLE
13 | Get-WinADOrganizationalUnitData -OrganizationalUnit 'OU=Users-O365,OU=Production,DC=ad,DC=evotec,DC=xyz'
14 | Retrieves information for the specified Organizational Unit 'Users-O365' under 'Production' in the Active Directory domain 'ad.evotec.xyz'.
15 |
16 | .NOTES
17 | Output of function:
18 | CanonicalName : ad.evotec.xyz/Production/Users-O365
19 | City :
20 | CN :
21 | Country : PL
22 | Created : 09.11.2018 17:38:32
23 | Description : OU for Synchronization of Users to Office 365
24 | DisplayName :
25 | DistinguishedName : OU=Users-O365,OU=Production,DC=ad,DC=evotec,DC=xyz
26 | LinkedGroupPolicyObjects : {cn={74D09C6F-35E9-4743-BCF7-F87D7010C60D},cn=policies,cn=system,DC=ad,DC=evotec,DC=xyz}
27 | ManagedBy :
28 | Modified : 19.11.2018 22:54:47
29 | Name : Users-O365
30 | PostalCode :
31 | ProtectedFromAccidentalDeletion : True
32 | State :
33 | StreetAddress :
34 |
35 | #>
36 | [CmdletBinding()]
37 | param(
38 | [string[]] $OrganizationalUnit
39 | )
40 | $Output = foreach ($OU in $OrganizationalUnit) {
41 | $Data = Get-ADOrganizationalUnit -Identity $OU -Properties CanonicalName, City, CN, Country, Created, Description, DisplayName, DistinguishedName, ManagedBy, Modified, Name, OU, PostalCode, ProtectedFromAccidentalDeletion, State, StreetAddress
42 |
43 | [PsCustomobject][Ordered] @{
44 | CanonicalName = $Data.CanonicalName
45 | City = $Data.City
46 | CN = $Data.CN
47 | Country = $Data.Country
48 | Created = $Data.Created
49 | Description = $Data.Description
50 | DisplayName = $Data.DisplayName
51 | DistinguishedName = $Data.DistinguishedName
52 | LinkedGroupPolicyObjects = $Data.LinkedGroupPolicyObjects
53 | ManagedBy = Get-WinADUsersByDN -DistinguishedName $U.ManagedBy
54 | Modified = $Data.Modified
55 | Name = $Data.Name
56 | PostalCode = $Data.PostalCode
57 | ProtectedFromAccidentalDeletion = $Data.ProtectedFromAccidentalDeletion
58 | State = $Data.State
59 | StreetAddress = $Data.StreetAddress
60 | }
61 | }
62 | return $Output
63 | }
--------------------------------------------------------------------------------
/Private/ActiveDirectory/Get-WinADOrganizationalUnitFromDN.ps1:
--------------------------------------------------------------------------------
1 | function Get-WinADOrganizationalUnitFromDN {
2 | <#
3 | .SYNOPSIS
4 | This function extracts the Organizational Unit (OU) from a given Distinguished Name (DN).
5 |
6 | .DESCRIPTION
7 | This function takes a Distinguished Name (DN) as input and returns the Organizational Unit (OU) part of it.
8 |
9 | .PARAMETER DistinguishedName
10 | Specifies the Distinguished Name (DN) from which to extract the Organizational Unit (OU).
11 |
12 | .EXAMPLE
13 | Extract the Organizational Unit (OU) from a Distinguished Name.
14 |
15 | $DistinguishedName = 'CN=Przemyslaw Klys,OU=Users,OU=Production,DC=ad,DC=evotec,DC=xyz'
16 | Get-WinADOrganizationalUnitFromDN -DistinguishedName $DistinguishedName
17 |
18 | .NOTES
19 | This function uses regular expressions to extract the Organizational Unit (OU) from the given Distinguished Name (DN).
20 | #>
21 | [CmdletBinding()]
22 | param(
23 | $DistinguishedName
24 | )
25 | return [Regex]::Match($DistinguishedName,'(?=OU)(.*\n?)(?<=.)').Value
26 | }
--------------------------------------------------------------------------------
/Private/ActiveDirectory/Get-WinADUserSnapshot.ps1:
--------------------------------------------------------------------------------
1 | function Get-WinADUserSnapshot {
2 | <#
3 | .SYNOPSIS
4 | Retrieves a snapshot of Active Directory user information and saves it to an XML file.
5 |
6 | .DESCRIPTION
7 | The Get-WinADUserSnapshot function retrieves detailed information about an Active Directory user and saves it to an XML file specified by the XmlPath parameter.
8 |
9 | .PARAMETER User
10 | Specifies the Active Directory user object for which to retrieve the snapshot.
11 |
12 | .PARAMETER XmlPath
13 | Specifies the path where the XML snapshot file will be saved.
14 |
15 | .PARAMETER WhatIf
16 | Indicates whether the operation should only be simulated without actually saving the snapshot.
17 |
18 | .EXAMPLE
19 | Get-WinADUserSnapshot -User $userObject -XmlPath "C:\Snapshots" -WhatIf
20 | Retrieves a snapshot of the user object and simulates saving it to the specified path.
21 |
22 | .EXAMPLE
23 | Get-WinADUserSnapshot -User $userObject -XmlPath "C:\Snapshots"
24 | Retrieves a snapshot of the user object and saves it to the specified path.
25 |
26 | #>
27 | [CmdletBinding()]
28 | [alias("Get-ADUserSnapshot")]
29 | param (
30 | [parameter(Mandatory = $true)][Object] $User,
31 | [string] $XmlPath,
32 | [switch] $WhatIf
33 | )
34 | $Object = @()
35 | try {
36 | $FullData = Get-ADUser -Identity $User.DistinguishedName -Properties *
37 | if (($XmlPath) -and (Test-Path $XmlPath)) {
38 | $FullPath = [IO.Path]::Combine($XmlPath, "$($User.SamAccountName).xml") #
39 | if (-not $WhatIf) {
40 | $FullData | Export-Clixml -Path $FullPath -ErrorAction Stop
41 | }
42 | $Object += @{ Status = $true; Output = $User.SamAccountName; Extended = "Saved to $FullPath" }
43 |
44 | } else {
45 | $Object += @{ Status = $false; Output = $User.SamAccountName; Extended = 'XmlPath Incorrect' }
46 | }
47 | } catch {
48 | $ErrorMessage = $_.Exception.Message -replace "`n", " " -replace "`r", " "
49 | $Object += @{ Status = $false; Output = $User.SamAccountName; Extended = $ErrorMessage }
50 | }
51 | return $Object
52 | }
--------------------------------------------------------------------------------
/Private/ActiveDirectory/Get-WinADUsers.ps1:
--------------------------------------------------------------------------------
1 | function Get-WinADUsers {
2 | [CmdletBinding()]
3 | param(
4 | $Filter,
5 | $OrganizationalUnit,
6 | $Group
7 | )
8 | $Splatting = @{}
9 | if ($OrganizationalUnit) {
10 | $Splatting.SearchBase = $OrganizationalUnit
11 | $Splatting.Filter = '*'
12 | }
13 | if ($Filter) {
14 | if ($Filter -is [hashtable]) {
15 | # $Splatting.Filter = $Filter.Filter
16 | # $Splatting.SearchBase = $Filter.SearchBase
17 | $Splatting = $Filter
18 | } elseif ($Filter -is [string]) {
19 | $Splatting.Filter = $Filter
20 | } else {
21 |
22 | }
23 | }
24 |
25 | #Write-Color $Group -Color Red
26 | if ($Group) {
27 | $Users = @()
28 | $GroupMembers = Get-ADGroupMember -Identity $Group
29 | #Get-ADUser $Groupmembers
30 | $Users = foreach ($Member in $GroupMembers) {
31 | #Write-COlor $Member -Color Red
32 | Get-ADUser -Identity $Member -Properties $Script:UserProperties #| Select-Object $Script:UserProperties
33 | }
34 | } else {
35 | $Users = Get-ADUser @Splatting -Properties $Script:UserProperties #| Select-Object $Script:UserProperties
36 | }
37 |
38 |
39 | $UserList = foreach ($U in $Users) {
40 | $Manager = Get-WinADUsersByDN -DistinguishedName $U.Manager
41 | $PrimaryGroup = Get-WinADGroupsByDN -DistinguishedName $U.PrimaryGroup -All #-Field 'Name'
42 | $Groups = Get-WinADGroupsByDN -DistinguishedName $U.MemberOf -All #-Field 'Name'
43 | $OrganizationalUnit = Get-WinADOrganizationalUnitFromDN -DistinguishedName $U.DistinguishedName
44 | $OrganizationalUnitData = Get-WinADOrganizationalUnitData -OrganizationalUnit $OrganizationalUnit
45 |
46 | [PsCustomObject][ordered] @{
47 | 'Name' = $U.Name
48 | 'UserPrincipalName' = $U.UserPrincipalName
49 | 'SamAccountName' = $U.SamAccountName
50 | 'Display Name' = $U.DisplayName
51 | 'Given Name' = $U.GivenName
52 | 'Surname' = $U.Surname
53 | 'EmailAddress' = $U.EmailAddress
54 | 'PasswordExpired' = $U.PasswordExpired
55 | 'PasswordLastSet' = $U.PasswordLastSet
56 | 'Password Last Changed' = if ($U.PasswordLastSet -ne $Null) { "$(-$($U.PasswordLastSet - [DateTime]::Today).Days) days" } else { 'N/A'}
57 | 'PasswordNotRequired' = $U.PasswordNotRequired
58 | 'PasswordNeverExpires' = $U.PasswordNeverExpires
59 | 'Enabled' = $U.Enabled
60 | 'Manager' = $Manager.Name
61 | 'Manager Email' = $Manager.EmailAddress
62 | 'DateExpiry' = Convert-ToDateTime -Timestring $($U."msDS-UserPasswordExpiryTimeComputed") #-Verbose
63 | "DaysToExpire" = (Convert-TimeToDays -StartTime (GET-DATE) -EndTime (Convert-ToDateTime -Timestring $($U."msDS-UserPasswordExpiryTimeComputed")))
64 | "AccountExpirationDate" = $U.AccountExpirationDate
65 | "AccountLockoutTime" = $U.AccountLockoutTime
66 | "AllowReversiblePasswordEncryption" = $U.AllowReversiblePasswordEncryption
67 | "BadLogonCount" = $U.BadLogonCount
68 | "CannotChangePassword" = $U.CannotChangePassword
69 | "CanonicalName" = $U.CanonicalName
70 |
71 | "Description" = $U.Description
72 | "DistinguishedName" = $U.DistinguishedName
73 | "EmployeeID" = $U.EmployeeID
74 | "EmployeeNumber" = $U.EmployeeNumber
75 | "LastBadPasswordAttempt" = $U.LastBadPasswordAttempt
76 | "LastLogonDate" = $U.LastLogonDate
77 | 'Last Logon Days' = if ($U.LastLogonDate -ne $Null) { "$(-$($U.LastLogonDate - [DateTime]::Today).Days) days" } else { 'N/A'}
78 |
79 | "Created" = $U.Created
80 | "Modified" = $U.Modified
81 | "Protected" = $U.ProtectedFromAccidentalDeletion
82 |
83 | "PrimaryGroup" = $PrimaryGroup # Whole Object
84 | "MemberOf" = $Groups #Whole Objects
85 | #"Domain" = $Domain
86 | 'Identity' = $U.Identity
87 | 'OU' = $OrganizationalUnit
88 | 'OrganizationalUnit' = $OrganizationalUnitData
89 | }
90 |
91 | }
92 | return $UserList
93 | }
94 | <#
95 |
96 | $Splat = @{
97 | Filter = '*'
98 | }
99 |
100 | $Splat = @{
101 | Filter = "UserPrincipalName -eq 'przemyslaw.klys@ad.evotec.xyz'"
102 | SearchBase = 'OU=Users,OU=Production,DC=ad,DC=evotec,DC=xyz'
103 | }
104 |
105 | Get-ADUser @Splat
106 | #>
107 |
108 | <#
109 |
110 | $Script:UserProperties = 'Name', 'UserPrincipalName', 'SamAccountName', 'Enabled', 'PasswordLastSet', `
111 | 'PasswordExpired', 'PasswordNeverExpires', 'PasswordNotRequired', 'EmailAddress', 'DisplayName', 'GivenName', `
112 | 'Surname', 'Manager', "AccountExpirationDate", "AccountLockoutTime", "AllowReversiblePasswordEncryption", `
113 | "BadLogonCount", "CannotChangePassword", "CanonicalName", "Description", "DistinguishedName", "EmployeeID", `
114 | "EmployeeNumber", "LastBadPasswordAttempt", "LastLogonDate", "Created", "Modified", "PrimaryGroup", "MemberOf", `
115 | 'msDS-UserPasswordExpiryTimeComputed','msExchHideFromAddressLists'
116 |
117 |
118 | $User = Get-WinADUsers -Filter "UserPrincipalName -eq 'przemyslaw.klys@ad.evotec.xyz'"
119 | #$User.MemberOf.Name
120 | #$User."MemberOf.Name"
121 |
122 | $string = 'memberOf.Name'
123 | $value = $user
124 | foreach($part in $string.Split('.')){
125 | $Part
126 | $value = $value."$part"
127 | }
128 | #>
129 |
130 | #Get-Aduser -Filter * -Properties * | Select-Object MemberOf
131 |
132 | #>
133 | <#
134 | $Script:UserProperties = 'Name', 'UserPrincipalName', 'SamAccountName', 'Enabled', 'PasswordLastSet', `
135 | 'PasswordExpired', 'PasswordNeverExpires', 'PasswordNotRequired', 'EmailAddress', 'DisplayName', 'GivenName', `
136 | 'Surname', 'Manager', "AccountExpirationDate", "AccountLockoutTime", "AllowReversiblePasswordEncryption", `
137 | "BadLogonCount", "CannotChangePassword", "CanonicalName", "Description", "DistinguishedName", "EmployeeID", `
138 | "EmployeeNumber", "LastBadPasswordAttempt", "LastLogonDate", "Created", "Modified", "PrimaryGroup", "MemberOf", `
139 | 'msDS-UserPasswordExpiryTimeComputed','msExchHideFromAddressLists'
140 |
141 | Get-WinADUsers -Filter '*'
142 |
143 | #>
--------------------------------------------------------------------------------
/Private/ActiveDirectory/Get-WinADUsersByOU.ps1:
--------------------------------------------------------------------------------
1 | function Get-WinADUsersByOU {
2 | <#
3 | .SYNOPSIS
4 | Retrieves Active Directory users within a specified Organizational Unit.
5 |
6 | .DESCRIPTION
7 | This function retrieves Active Directory users within the specified Organizational Unit.
8 |
9 | .PARAMETER OrganizationalUnit
10 | Specifies the Organizational Unit from which to retrieve users.
11 |
12 | .EXAMPLE
13 | Get-WinADUsersByOU -OrganizationalUnit "OU=Sales,DC=Contoso,DC=com"
14 | Retrieves all users within the Sales Organizational Unit in the Contoso domain.
15 |
16 | #>
17 | [CmdletBinding()]
18 | param (
19 | $OrganizationalUnit
20 | )
21 | $OU = Get-ADOrganizationalUnit $OrganizationalUnit
22 | if ($OU.ObjectClass -eq 'OrganizationalUnit') {
23 | try {
24 | $Users = Get-ADUser -SearchBase $OU -Filter * -Properties $Script:UserProperties
25 | } catch {
26 | Write-Color @Script:WriteParameters -Text '[i]', ' One or more properties are invalid - Terminating', ' Terminating' -Color Yellow, White, Red
27 | return
28 | }
29 | }
30 | return $Users
31 | }
--------------------------------------------------------------------------------
/Private/ActiveDirectory/Get-WinADUsersTranslate.ps1:
--------------------------------------------------------------------------------
1 | function Get-WinADUsersTranslate {
2 | [CmdletBinding()]
3 | param(
4 | [System.Object[]] $Users
5 | )
6 | $UserList = @()
7 | foreach ($U in $Users) {
8 | $UserList += [PSCustomObject] @{
9 | 'Name' = $U.Name
10 | 'UserPrincipalName' = $U.UserPrincipalName
11 | 'SamAccountName' = $U.SamAccountName
12 | 'Display Name' = $U.DisplayName
13 | 'Given Name' = $U.GivenName
14 | 'Surname' = $U.Surname
15 | 'EmailAddress' = $U.EmailAddress
16 | 'PasswordExpired' = $U.PasswordExpired
17 | 'PasswordLastSet' = $U.PasswordLastSet
18 | 'PasswordLastChanged' = if ($U.PasswordLastSet -ne $Null) { "$(-$($U.PasswordLastSet - [DateTime]::Today).Days)" } else { ''}
19 | 'PasswordNotRequired' = $U.PasswordNotRequired
20 | 'PasswordNeverExpires' = $U.PasswordNeverExpires
21 | 'Enabled' = $U.Enabled
22 | 'Manager' = $U.Manager # (Get-ADObjectFromDistingusishedName -ADCatalog $ADCatalogUsers -DistinguishedName $U.Manager).Name
23 | # 'Manager Email' = (Get-ADObjectFromDistingusishedName -ADCatalog $ADCatalogUsers -DistinguishedName $U.Manager).EmailAddress
24 | 'DateExpiry' = Convert-ToDateTime -Timestring $($U."msDS-UserPasswordExpiryTimeComputed") -Verbose
25 | "DaysToExpire" = (Convert-TimeToDays -StartTime GET-DATE -EndTime (Convert-ToDateTime -Timestring $($U."msDS-UserPasswordExpiryTimeComputed")))
26 | "AccountExpirationDate" = $U.AccountExpirationDate
27 | "AccountLockoutTime" = $U.AccountLockoutTime
28 | "AllowReversiblePasswordEncryption" = $U.AllowReversiblePasswordEncryption
29 | "BadLogonCount" = $U.BadLogonCount
30 | "CannotChangePassword" = $U.CannotChangePassword
31 | "CanonicalName" = $U.CanonicalName
32 |
33 | "Description" = $U.Description
34 | "DistinguishedName" = $U.DistinguishedName
35 | "EmployeeID" = $U.EmployeeID
36 | "EmployeeNumber" = $U.EmployeeNumber
37 | "LastBadPasswordAttempt" = $U.LastBadPasswordAttempt
38 | "LastLogonDate" = $U.LastLogonDate
39 |
40 | "Created" = $U.Created
41 | "Modified" = $U.Modified
42 | "Protected" = $U.ProtectedFromAccidentalDeletion
43 |
44 | "PrimaryGroup" = $U.PrimaryGroup # (Get-ADObjectFromDistingusishedName -ADCatalog $ADCatalog -DistinguishedName $U.PrimaryGroup -Type 'SamAccountName')
45 | "MemberOf" = $U.MemberOf # (Get-ADObjectFromDistingusishedName -ADCatalog $ADCatalog -DistinguishedName $U.MemberOf -Type 'SamAccountName' -Splitter ', ')
46 | "Domain" = $Domain
47 | }
48 |
49 | }
50 | return $UserList
51 | }
52 |
53 | <#
54 |
55 | $Users = Get-ADUser -Filter * -Properties 'Name', 'UserPrincipalName', 'SamAccountName', 'Enabled', 'PasswordLastSet', `
56 | 'PasswordExpired', 'PasswordNeverExpires', 'PasswordNotRequired', 'EmailAddress', 'DisplayName', 'GivenName', `
57 | 'Surname', 'Manager', "AccountExpirationDate", "AccountLockoutTime", "AllowReversiblePasswordEncryption", `
58 | "BadLogonCount", "CannotChangePassword", "CanonicalName", "Description", "DistinguishedName", "EmployeeID", `
59 | "EmployeeNumber", "LastBadPasswordAttempt", "LastLogonDate", "Created", "Modified", "PrimaryGroup", "MemberOf", `
60 | 'msDS-UserPasswordExpiryTimeComputed'
61 |
62 | Get-WinADUsers -Users $Users | Format-Table -AutoSize
63 |
64 | #>
--------------------------------------------------------------------------------
/Private/ActiveDirectory/Get-WinADusersByDN.ps1:
--------------------------------------------------------------------------------
1 | function Get-WinADUsersByDN {
2 | <#
3 | .SYNOPSIS
4 | Retrieves Active Directory user information based on the provided DistinguishedName(s).
5 |
6 | .DESCRIPTION
7 | This function retrieves Active Directory user information based on the provided DistinguishedName(s). It returns specific user properties for the given DistinguishedName(s).
8 |
9 | .PARAMETER DistinguishedName
10 | Specifies the DistinguishedName(s) of the user(s) to retrieve information for.
11 |
12 | .PARAMETER Field
13 | Specifies the specific field to return for each user. Default value is 'DisplayName'.
14 |
15 | .PARAMETER All
16 | Indicates whether to return all properties of the user(s).
17 |
18 | .EXAMPLE
19 | Get-WinADUsersByDN -DistinguishedName "CN=John Doe,OU=Users,DC=contoso,DC=com"
20 | Retrieves the DisplayName of the user with the specified DistinguishedName.
21 |
22 | .EXAMPLE
23 | Get-WinADUsersByDN -DistinguishedName "CN=Jane Smith,OU=Users,DC=contoso,DC=com" -Field "EmailAddress"
24 | Retrieves the EmailAddress of the user with the specified DistinguishedName.
25 |
26 | .EXAMPLE
27 | Get-WinADUsersByDN -DistinguishedName "CN=Admin,OU=Users,DC=contoso,DC=com" -All
28 | Retrieves all properties of the user with the specified DistinguishedName.
29 |
30 | #>
31 | param(
32 | [alias('DN')][string[]]$DistinguishedName,
33 | [string] $Field = 'DisplayName', # return field
34 | [switch] $All
35 | )
36 | $Properties = 'DistinguishedName', 'Enabled', 'GivenName', 'Name', 'SamAccountName', 'SID', 'Surname', 'UserPrincipalName', 'EmailAddress', 'DisplayName'
37 |
38 | $Users = foreach ($DN in $DistinguishedName) {
39 | try {
40 | get-aduser -Identity $DN -Properties $Properties
41 | } catch {
42 | # returns empty, basically ignores stuff
43 | }
44 | }
45 |
46 | if ($All) {
47 | return $Users #.PSObject.Properties.Name
48 | } else {
49 | return $Users.$Field
50 | }
51 | }
--------------------------------------------------------------------------------
/Private/ActiveDirectory/Remove-WinADUserGroups.ps1:
--------------------------------------------------------------------------------
1 | function Remove-WinADUserGroups {
2 | <#
3 | .SYNOPSIS
4 | Removes specified Active Directory groups from a user.
5 |
6 | .DESCRIPTION
7 | This function removes specified Active Directory groups from a user account. It provides options to remove groups based on category, scope, or all groups.
8 |
9 | .PARAMETER User
10 | The user object from which groups will be removed.
11 |
12 | .PARAMETER GroupCategory
13 | Specifies the category of groups to remove. Valid values are "Distribution" and "Security".
14 |
15 | .PARAMETER GroupScope
16 | Specifies the scope of groups to remove. Valid values are "DomainLocal", "Global", and "Universal".
17 |
18 | .PARAMETER Groups
19 | An array of specific group names to remove.
20 |
21 | .PARAMETER All
22 | If specified, removes all groups from the user.
23 |
24 | .PARAMETER WhatIf
25 | Shows what would happen if the command runs without actually running it.
26 |
27 | .EXAMPLE
28 | Remove-WinADUserGroups -User $User -All
29 | Removes all groups from the specified user account.
30 |
31 | .EXAMPLE
32 | Remove-WinADUserGroups -User $User -GroupCategory "Security" -GroupScope "Global"
33 | Removes all security groups with a global scope from the specified user account.
34 | #>
35 | [CmdletBinding()]
36 | [alias("Remove-ADUserGroups")]
37 | param(
38 | [parameter(Mandatory = $true)][Object] $User,
39 | [ValidateSet("Distribution", "Security")][String] $GroupCategory ,
40 | [ValidateSet("DomainLocal", "Global", "Universal")][String] $GroupScope,
41 | [string[]] $Groups,
42 | [switch] $All,
43 | [switch] $WhatIf
44 | )
45 | $Object = @()
46 | try {
47 | $ADgroups = Get-ADPrincipalGroupMembership -Identity $User.DistinguishedName -ErrorAction Stop | Where-Object { $_.Name -ne "Domain Users" }
48 | } catch {
49 | $ErrorMessage = $_.Exception.Message -replace "`n", " " -replace "`r", " "
50 | $Object += @{ Status = $false; Output = $Group.Name; Extended = $ErrorMessage }
51 | }
52 | if ($ADgroups) {
53 | if ($All) {
54 | #Write-Color @Script:WriteParameters -Text '[i]', ' Removing groups ', ($ADgroups.Name -join ', '), ' from user ', $User.DisplayName -Color White, Yellow, Green, White, Yellow
55 | foreach ($Group in $ADgroups) {
56 | try {
57 | if (-not $WhatIf) {
58 | Remove-ADPrincipalGroupMembership -Identity $User.DistinguishedName -MemberOf $Group -Confirm:$false -ErrorAction Stop
59 | }
60 | $Object += @{ Status = $true; Output = $Group.Name; Extended = 'Removed from group.' }
61 | } catch {
62 | $ErrorMessage = $_.Exception.Message -replace "`n", " " -replace "`r", " "
63 | $Object += @{ Status = $false; Output = $Group.Name; Extended = $ErrorMessage }
64 | }
65 | }
66 | }
67 | if ($GroupCategory) {
68 | $ADGroupsByCategory = $ADgroups | Where-Object { $_.GroupCategory -eq $GroupCategory }
69 | if ($ADGroupsByCategory) {
70 | #Write-Color @Script:WriteParameters -Text '[i]', ' Removing groups (by category - ', $GroupCategory, ") ", ($ADGroupsByCategory.Name -join ', '), ' from user ', $User.DisplayName -Colo White, Yellow, Green, White, Yellow, White, Blue
71 | foreach ($Group in $ADGroupsByCategory) {
72 | try {
73 | if (-not $WhatIf) {
74 | Remove-ADPrincipalGroupMembership -Identity $User.DistinguishedName -MemberOf $Group -Confirm:$false -ErrorAction Stop
75 | }
76 | $Object += @{ Status = $true; Output = $Group.Name; Extended = 'Removed from group.' }
77 | } catch {
78 | $ErrorMessage = $_.Exception.Message -replace "`n", " " -replace "`r", " "
79 | $Object += @{ Status = $false; Output = $Group.Name; Extended = $ErrorMessage }
80 | }
81 | }
82 | }
83 | }
84 | if ($GroupScope) {
85 | $ADGroupsByScope = $ADgroups | Where-Object { $_.GroupScope -eq $GroupScope }
86 | if ($ADGroupsByScope) {
87 | #Write-Color @Script:WriteParameters -Text '[i]', ' Removing groups (by scope ', " - $GroupScope) ", ($ADGroupsByScope.Name -join ', '), ' from user ', $User.DisplayName -Color White, Yellow, Green, White, Yellow, White, Blue
88 | foreach ($Group in $ADGroupsByScope) {
89 | try {
90 | if (-not $WhatIf) {
91 | Remove-ADPrincipalGroupMembership -Identity $User.DistinguishedName -MemberOf $Group -Confirm:$false -ErrorAction Stop
92 | }
93 | $Object += @{ Status = $true; Output = $Group.Name; Extended = 'Removed from group.' }
94 | } catch {
95 | $ErrorMessage = $_.Exception.Message -replace "`n", " " -replace "`r", " "
96 | $Object += @{ Status = $false; Output = $Group.Name; Extended = $ErrorMessage }
97 | }
98 | }
99 | }
100 | }
101 | if ($Groups) {
102 | foreach ($Group in $Groups) {
103 | $ADGroupsByName = $ADgroups | Where-Object { $_.Name -like $Group }
104 | if ($ADGroupsByName) {
105 | #Write-Color @Script:WriteParameters -Text '[i]', ' Removing groups (by name) ', ($ADGroupsByName.Name -join ', '), ' from user ', $User.DisplayName -Color White, Yellow, Green, White, Yellow, White, Yellow
106 | try {
107 | if (-not $WhatIf) {
108 | Remove-ADPrincipalGroupMembership -Identity $User.DistinguishedName -MemberOf $ADGroupsByName -Confirm:$false -ErrorAction Stop
109 | }
110 | $Object += @{ Status = $true; Output = $Group.Name; Extended = 'Removed from group.' }
111 | } catch {
112 | $ErrorMessage = $_.Exception.Message -replace "`n", " " -replace "`r", " "
113 | $Object += @{ Status = $false; Output = $Group.Name; Extended = $ErrorMessage }
114 | }
115 | } else {
116 | $Object += @{ Status = $false; Output = $Group.Name; Extended = 'Not available on user.' }
117 | }
118 | }
119 | }
120 | }
121 | return $Object
122 | }
123 |
--------------------------------------------------------------------------------
/Private/ActiveDirectory/Set-WinADGroupSynchronization.ps1:
--------------------------------------------------------------------------------
1 | <#
2 |
3 | $Group1 = 'GDS-TestGroup1'
4 | $Group2 = 'GDS-TestGroup2'
5 |
6 | Set-WinADGroupSynchronization -GroupFrom $Group1 -GroupTo $Group2 -Type 'All' -Recursive None
7 | #>
8 |
9 | function Set-WinADGroupSynchronization {
10 | <#
11 | .SYNOPSIS
12 | Sets up synchronization between two Active Directory groups.
13 |
14 | .DESCRIPTION
15 | This function sets up synchronization between two Active Directory groups by copying members from one group to another based on specified criteria.
16 |
17 | .PARAMETER GroupFrom
18 | The name of the source Active Directory group from which members will be synchronized.
19 |
20 | .PARAMETER GroupTo
21 | The name of the target Active Directory group to which members will be synchronized.
22 |
23 | .PARAMETER Type
24 | Specifies the type of members to synchronize. Valid values are 'User', 'Group', or 'All'. Default is 'User'.
25 |
26 | .PARAMETER Recursive
27 | Specifies the type of synchronization to perform. Valid values are 'None', 'RecursiveFrom', 'RecursiveBoth', or 'RecursiveTo'. Default is 'None'.
28 |
29 | .PARAMETER WhatIf
30 | Shows what would happen if the synchronization is performed without actually performing it.
31 |
32 | .EXAMPLE
33 | Set-WinADGroupSynchronization -GroupFrom 'GDS-TestGroup1' -GroupTo 'GDS-TestGroup2' -Type 'All' -Recursive None
34 | Synchronizes all members from 'GDS-TestGroup1' to 'GDS-TestGroup2' without recursion.
35 |
36 | .EXAMPLE
37 | Set-WinADGroupSynchronization -GroupFrom 'GDS-TestGroup1' -GroupTo 'GDS-TestGroup2' -Type 'User' -Recursive RecursiveBoth
38 | Synchronizes only user members from 'GDS-TestGroup1' to 'GDS-TestGroup2' with recursion in both groups.
39 |
40 | #>
41 | [CmdletBinding()]
42 | param(
43 | [parameter(Mandatory = $true)][string] $GroupFrom,
44 | [parameter(Mandatory = $true)][string] $GroupTo,
45 | [parameter(Mandatory = $false)][ValidateSet("User", "Group", "All")][string] $Type = 'User',
46 | [parameter(Mandatory = $false)][ValidateSet("None", "RecursiveFrom", "RecursiveBoth", "RecursiveTo")] $Recursive = 'None',
47 | [switch] $WhatIf
48 | )
49 | Begin {
50 | $Object = @()
51 | if ($Recursive -eq 'None') {
52 | $GroupFromRecursive = $false
53 | $GroupToRecursive = $false
54 | } elseif ($Recursive -eq 'RecursiveFrom') {
55 | $GroupFromRecursive = $true
56 | $GroupToRecursive = $false
57 | } elseif ($Recursive -eq 'RecursiveBoth') {
58 | $GroupFromRecursive = $true
59 | $GroupToRecursive = $true
60 | } else {
61 | $GroupFromRecursive = $false
62 | $GroupToRecursive = $true
63 | }
64 | }
65 | Process {
66 | try {
67 |
68 | $GroupMembersFrom = Get-ADGroupMember -Identity $GroupFrom -Recursive:$GroupFromRecursive | Select-Object Name, ObjectClass, SamAccountName, UserPrincipalName
69 | } catch {
70 | $ErrorMessage = $_.Exception.Message -replace "`n", " " -replace "`r", " "
71 | $Object += @{ Status = $false; Output = $Group.Name; Extended = $ErrorMessage }
72 | }
73 | try {
74 | $GroupMembersTo = Get-ADGroupMember -Identity $GroupTo -Recursive:$GroupToRecursive | Select-Object Name, ObjectClass, SamAccountName, UserPrincipalName
75 | } catch {
76 | $ErrorMessage = $_.Exception.Message -replace "`n", " " -replace "`r", " "
77 | $Object += @{ Status = $false; Output = $Group.Name; Extended = $ErrorMessage }
78 | }
79 | if ($Object.Count -gt 0) {
80 | # Something went seriously wrong. Terminate ASAP
81 | return $Object
82 | }
83 |
84 | foreach ($User in $GroupMembersFrom) {
85 | if ($User.ObjectClass -eq "user") {
86 | if ($Type -eq 'User' -or $Type -eq 'All') {
87 | if ($GroupMembersTo.SamAccountName -notcontains $User.SamAccountName) {
88 | #Write-Color "Not a member ", $User.SamAccountName, " of $GroupTo", ". Adding!" -Color Red -LogFile $LogFile
89 | try {
90 | if (-not $WhatIf) {
91 | Add-ADGroupMember -Identity $GroupTo -Members $User.SamAccountName
92 | }
93 | $Object += @{ Status = $true; Output = $User.SamAccountName; Extended = "Added to group $GroupTo" }
94 | } catch {
95 | $ErrorMessage = $_.Exception.Message -replace "`n", " " -replace "`r", " "
96 | $Object += @{ Status = $false; Output = $Group.Name; Extended = $ErrorMessage }
97 | }
98 | }
99 | }
100 | } else {
101 | if ($Type -eq 'Group' -or $Type -eq 'All') {
102 | if ($GroupMembersTo.SamAccountName -notcontains $User.SamAccountName) {
103 | #Write-Color "Not a member ", $User.SamAccountName, " of $GroupTo", ". Adding!" -Color Red -LogFile $LogFile
104 | try {
105 | if (-not $WhatIf) {
106 | Add-ADGroupMember -Identity $GroupTo -Members $User.SamAccountName
107 | }
108 | $Object += @{ Status = $true; Output = $User.SamAccountName; Extended = "Added to group $GroupTo" }
109 | } catch {
110 | $ErrorMessage = $_.Exception.Message -replace "`n", " " -replace "`r", " "
111 | $Object += @{ Status = $false; Output = $Group.Name; Extended = $ErrorMessage }
112 | }
113 | }
114 | }
115 | }
116 | }
117 | foreach ($User in $GroupMembersTo) {
118 | if ($User.ObjectClass -eq "user") {
119 | if ($Type -eq 'User' -or $Type -eq 'All') {
120 | if ($GroupMembersFrom.SamAccountName -notcontains $User.SamAccountName) {
121 | Write-Color "Not a member of $GroupFrom - requires removal from $GroupTo ", $User.SamAccountName -Color Red -LogFile $LogFile
122 | try {
123 | if (-not $WhatIf) {
124 | Remove-ADGroupMember -Identity $GroupTo -Members $User.SamAccountName -Confirm:$false
125 | }
126 | $Object += @{ Status = $true; Output = $User.SamAccountName; Extended = "Removed from group $GroupTo" }
127 | } catch {
128 | $ErrorMessage = $_.Exception.Message -replace "`n", " " -replace "`r", " "
129 | $Object += @{ Status = $false; Output = $Group.Name; Extended = $ErrorMessage }
130 | }
131 | }
132 | }
133 | } else {
134 | if ($Type -eq 'Group' -or $Type -eq 'All') {
135 | if ($GroupMembersFrom.SamAccountName -notcontains $User.SamAccountName) {
136 | Write-Color "Not a member of $GroupFrom - requires removal from $GroupTo ", $User.SamAccountName -Color Red -LogFile $LogFile
137 | try {
138 | if (-not $WhatIf) {
139 | Remove-ADGroupMember -Identity $GroupTo -Members $User.SamAccountName -Confirm:$false
140 | }
141 | $Object += @{ Status = $true; Output = $User.SamAccountName; Extended = "Removed from group $GroupTo" }
142 | } catch {
143 | $ErrorMessage = $_.Exception.Message -replace "`n", " " -replace "`r", " "
144 | $Object += @{ Status = $false; Output = $Group.Name; Extended = $ErrorMessage }
145 | }
146 | }
147 | }
148 | }
149 | }
150 | }
151 | End {
152 | return $object
153 | }
154 | }
--------------------------------------------------------------------------------
/Private/ActiveDirectory/Set-WinADUserFields.ps1:
--------------------------------------------------------------------------------
1 | function Set-WinADUserFields {
2 | <#
3 | .SYNOPSIS
4 | Sets specified fields for an Active Directory user with additional options.
5 |
6 | .DESCRIPTION
7 | This function allows setting specified fields for an Active Directory user with the option to add text before or after the existing field value.
8 |
9 | .PARAMETER User
10 | Specifies the Active Directory user object to modify.
11 |
12 | .PARAMETER Option
13 | Specifies whether to add the text before or after the existing field value. Valid values are 'Before' and 'After'.
14 |
15 | .PARAMETER TextToAdd
16 | Specifies the text to add before or after the existing field value.
17 |
18 | .PARAMETER TextToRemove
19 | Specifies the text to remove from the existing field value.
20 |
21 | .PARAMETER Fields
22 | Specifies an array of fields to modify for the user.
23 |
24 | .PARAMETER WhatIf
25 | Indicates that the cmdlet should display what changes would occur without actually making any changes.
26 |
27 | .EXAMPLE
28 | Set-WinADUserFields -User $user -Option 'After' -TextToAdd 'New' -Fields 'Name'
29 | Adds the text 'New' after the existing 'Name' field value for the specified user.
30 |
31 | .EXAMPLE
32 | Set-WinADUserFields -User $user -Option 'Before' -TextToAdd 'Old' -Fields 'Description'
33 | Adds the text 'Old' before the existing 'Description' field value for the specified user.
34 | #>
35 | [CmdletBinding()]
36 | [alias("Set-ADUserName")]
37 | param (
38 | [parameter(Mandatory = $true)][Object] $User,
39 | [parameter(Mandatory = $false)][ValidateSet("Before", "After")][String] $Option,
40 | [string] $TextToAdd,
41 | [string] $TextToRemove,
42 | [string[]] $Fields,
43 | [switch] $WhatIf
44 | )
45 | $Object = @()
46 | if ($TextToAdd) {
47 | foreach ($Field in $Fields) {
48 | if ($User.$Field -notlike "*$TextToAdd*") {
49 |
50 | if ($Option -eq 'After') {
51 | $NewName = "$($User.$Field)$TextToAdd"
52 | } elseif ($Option -eq 'Before') {
53 | $NewName = "$TextToAdd$($User."$Field")"
54 | }
55 | if ($NewName -ne $User.$Field) {
56 | if ($Field -eq 'Name') {
57 | try {
58 | if (-not $WhatIf) {
59 | Rename-ADObject -Identity $User.DistinguishedName -NewName $NewName #-WhatIf
60 | }
61 | $Object += @{ Status = $true; Output = $User.SamAccountName; Extended = "Renamed account '$Field' to '$NewName'" }
62 |
63 | } catch {
64 | $ErrorMessage = $_.Exception.Message -replace "`n", " " -replace "`r", " "
65 | $Object += @{ Status = $false; Output = $User.SamAccountName; Extended = $ErrorMessage }
66 | }
67 | } else {
68 | $Splat = @{
69 | Identity = $User.DistinguishedName
70 | "$Field" = $NewName
71 | }
72 | try {
73 | if (-not $WhatIf) {
74 | Set-ADUser @Splat
75 | }
76 | $Object += @{ Status = $true; Output = $User.SamAccountName; Extended = "Renamed field '$Field' to '$NewName'" }
77 |
78 | } catch {
79 | $ErrorMessage = $_.Exception.Message -replace "`n", " " -replace "`r", " "
80 | $Object += @{ Status = $false; Output = $User.SamAccountName; Extended = $ErrorMessage }
81 | }
82 | }
83 |
84 |
85 | }
86 |
87 | }
88 | }
89 | }
90 | if ($TextToRemove) {
91 | foreach ($Field in $Fields) {
92 | if ($User.$Field -like "*$TextToRemove*") {
93 | $NewName = $($User.$Field).Replace($TextToRemove, '')
94 | if ($Field -eq 'Name') {
95 | try {
96 | if (-not $WhatIf) {
97 | Rename-ADObject -Identity $User.DistinguishedName -NewName $NewName #-WhatIf
98 | }
99 | $Object += @{ Status = $true; Output = $User.SamAccountName; Extended = "Renamed account '$Field' to '$NewName'" }
100 |
101 | } catch {
102 | $ErrorMessage = $_.Exception.Message -replace "`n", " " -replace "`r", " "
103 | $Object += @{ Status = $false; Output = $User.SamAccountName; Extended = "Field: '$Field' Error: '$ErrorMessage'" }
104 | }
105 | } else {
106 | $Splat = @{
107 | Identity = $User.DistinguishedName
108 | "$Field" = $NewName
109 | }
110 | try {
111 | if (-not $WhatIf) {
112 | Set-ADUser @Splat #-WhatIf
113 | }
114 | $Object += @{ Status = $true; Output = $User.SamAccountName; Extended = "Renamed field $Field to $NewName" }
115 |
116 | } catch {
117 | $ErrorMessage = $_.Exception.Message -replace "`n", " " -replace "`r", " "
118 | $Object += @{ Status = $false; Output = $User.SamAccountName; Extended = "Field: $Field Error: $ErrorMessage" }
119 | }
120 | }
121 | }
122 | }
123 |
124 | }
125 | return $Object
126 | }
--------------------------------------------------------------------------------
/Private/ActiveDirectory/Set-WinADUserSettingGAL.ps1:
--------------------------------------------------------------------------------
1 | Function Set-WinADUserSettingGAL {
2 | <#
3 | .SYNOPSIS
4 | Sets the Exchange Global Address List (GAL) visibility for a specified user.
5 |
6 | .DESCRIPTION
7 | This function allows you to hide or show a user in the Global Address List (GAL) of Exchange.
8 | It updates the msExchHideFromAddressLists attribute of the user object in Active Directory.
9 |
10 | .PARAMETER User
11 | Specifies the user object for which the GAL visibility needs to be set.
12 |
13 | .PARAMETER Option
14 | Specifies whether to 'Hide' or 'Show' the user in the GAL.
15 |
16 | .PARAMETER WhatIf
17 | Displays what would happen if the command runs without actually running the command.
18 |
19 | .EXAMPLE
20 | Set-WinADUserSettingGAL -User "JohnDoe" -Option "Hide"
21 | Hides the user "JohnDoe" from the Global Address List.
22 |
23 | .EXAMPLE
24 | Set-WinADUserSettingGAL -User "JaneSmith" -Option "Show"
25 | Shows the user "JaneSmith" in the Global Address List.
26 |
27 | #>
28 | [CmdletBinding()]
29 | [alias("Set-ADUserSettingGAL")]
30 | param (
31 | [parameter(Mandatory = $true)][Object] $User,
32 | [parameter(Mandatory = $true)][ValidateSet("Hide", "Show")][String]$Option,
33 | [switch] $WhatIf
34 | )
35 | $Object = @()
36 | if ($User) {
37 | if ($Option -eq 'Hide') {
38 | if (-not $User.msExchHideFromAddressLists) {
39 | #Write-Color @Script:WriteParameters -Text '[i]', ' Hiding user ', $User.DisplayName, ' in GAL (Exchange Address Lists)' -Color White, Yellow, Green, White, Yellow
40 | try {
41 | if (-not $WhatIf) {
42 | Set-ADObject -Identity $User.DistinguishedName -Replace @{msExchHideFromAddressLists = $true}
43 | }
44 | $Object += @{ Status = $true; Output = $User.SamAccountName; Extended = 'Hidden from GAL.' }
45 | } catch {
46 | $ErrorMessage = $_.Exception.Message -replace "`n", " " -replace "`r", " "
47 | $Object += @{ Status = $false; Output = $User.SamAccountName; Extended = $ErrorMessage }
48 | }
49 | }
50 | } elseif ($Option -eq 'Show') {
51 | if ($User.msExchHideFromAddressLists) {
52 | #Write-Color @Script:WriteParameters -Text '[i]', ' Unhiding user ', $User.DisplayName, ' in GAL (Exchange Address Lists)' -Color White, Yellow, Green, White, Yellow
53 | try {
54 | if ($WhatIf) {
55 | Set-ADObject -Identity $User.DistinguishedName -Clear msExchHideFromAddressLists
56 | }
57 | $Object += @{ Status = $true; Output = $User.SamAccountName; Extended = 'Unhidden in GAL.' }
58 | } catch {
59 | $ErrorMessage = $_.Exception.Message -replace "`n", " " -replace "`r", " "
60 | $Object += @{ Status = $false; Output = $User.SamAccountName; Extended = $ErrorMessage }
61 | }
62 | }
63 | }
64 | }
65 | return $Object
66 | }
--------------------------------------------------------------------------------
/Private/ActiveDirectory/Set-WinADUserStatus.ps1:
--------------------------------------------------------------------------------
1 | function Set-WinADUserStatus {
2 | <#
3 | .SYNOPSIS
4 | Enables or disables a user account in Active Directory.
5 |
6 | .DESCRIPTION
7 | The Set-WinADUserStatus function enables or disables a specified user account in Active Directory based on the provided option. It also provides an option to simulate the action using the WhatIf switch.
8 |
9 | .PARAMETER User
10 | Specifies the user account to enable or disable.
11 |
12 | .PARAMETER Option
13 | Specifies whether to enable or disable the user account. Valid values are "Enable" or "Disable".
14 |
15 | .PARAMETER WhatIf
16 | Indicates that the cmdlet should display what would happen if it were to run, without actually performing any action.
17 |
18 | .EXAMPLE
19 | Set-WinADUserStatus -User $user -Option "Enable"
20 | Enables the user account specified by $user in Active Directory.
21 |
22 | .EXAMPLE
23 | Set-WinADUserStatus -User $user -Option "Disable" -WhatIf
24 | Displays what would happen if the user account specified by $user were to be disabled in Active Directory, without actually disabling it.
25 |
26 | #>
27 | [CmdletBinding()]
28 | [alias("Set-ADUserStatus")]
29 | param (
30 | [parameter(Mandatory = $true)][Object] $User,
31 | [parameter(Mandatory = $true)][ValidateSet("Enable", "Disable")][String] $Option,
32 | [switch] $WhatIf
33 | # $WriteParameters
34 | )
35 | $Object = @()
36 | if ($Option -eq 'Enable' -and $User.Enabled -eq $false) {
37 | #if (-not $WriteParameters) {
38 | # Write-Color @Script:WriteParameters -Text 'Enabling user ', $User.DisplayName, ' in Active Directory.' -Color Yellow, Green, White, Yellow
39 | #} else {
40 | # Write-Color @WriteParameters
41 | #}
42 | try {
43 | if (-not $WhatIf) {
44 | Set-ADUser -Identity $User.DistinguishedName -Enabled $true
45 | }
46 | $Object += @{ Status = $true; Output = $User.SamAccountName; Extended = 'Enabled user.' }
47 | } catch {
48 | $ErrorMessage = $_.Exception.Message -replace "`n", " " -replace "`r", " "
49 | $Object += @{ Status = $false; Output = $User.SamAccountName; Extended = $ErrorMessage }
50 | }
51 | } elseif ($Option -eq 'Disable' -and $User.Enabled -eq $true) {
52 | #if (-not $WriteParameters) {
53 | # Write-Color @Script:WriteParameters -Text 'Disabling user ', $User.DisplayName, 'in Active Directory.' -Color Yellow, Green, White, Yellow
54 | #} else {
55 | # Write-Color @WriteParameters
56 | #}
57 | try {
58 | if (-not $WhatIf) {
59 | Set-ADUser -Identity $User.DistinguishedName -Enabled $false
60 | }
61 | $Object += @{ Status = $true; Output = $User.SamAccountName; Extended = 'Disabled user.' }
62 |
63 | } catch {
64 | $ErrorMessage = $_.Exception.Message -replace "`n", " " -replace "`r", " "
65 | $Object += @{ Status = $false; Output = $User.SamAccountName; Extended = $ErrorMessage }
66 | }
67 | }
68 | return $Object
69 | }
--------------------------------------------------------------------------------
/Private/AzureAD/Get-WinAzureADUsers.ps1:
--------------------------------------------------------------------------------
1 | function Get-WinAzureADUsers {
2 | [CmdletBinding()]
3 | param(
4 | [ValidateSet("All", "DisabledOnly", "EnabledOnly")][string] $Filter = 'All',
5 | [int] $MaxResults = 5000000,
6 | [string] $UserPrincipalName,
7 | [switch] $ReturnDeletedUsers,
8 | [switch] $ReturnUnlicensedUsers,
9 | [string] $Country,
10 | [string] $City,
11 | [string] $Department,
12 | [string] $State,
13 | [switch] $Synchronized,
14 | [string] $DomainName,
15 | [string] $Title,
16 | [switch] $All,
17 | [switch] $LicenseReconciliationNeededOnly,
18 | [string] $SearchString,
19 | [switch] $HasErrorsOnly,
20 | [Guid] $TenantId,
21 | [string] $UsageLocation
22 |
23 | )
24 |
25 | $UserSplat = @{}
26 | if ($UserPrincipalName) { $UserSplat.UserPrincipalName = $UserPrincipalName }
27 |
28 | if ($DomainName) { $UserSplat.DomainName = $DomainName }
29 |
30 | if ($MaxResults) { $UserSplat.MaxResults = $MaxResults }
31 |
32 | <#
33 | EnabledFilter = $Filter
34 | ReturnDeletedUsers = $ReturnDeletedUsers
35 | UnlicensedUsersOnly = $ReturnUnlicensedUsers
36 |
37 | Country = $Country
38 | City = $City
39 | State = $State
40 | UsageLocation = $UsageLocation
41 |
42 | Title = $Title
43 | Department = $Department
44 |
45 |
46 |
47 | LicenseReconciliationNeededOnly = $LicenseReconciliationNeededOnly
48 | SearchString = $SearchString
49 | HasErrorsOnly = $HasErrorsOnly
50 | TenantID = $TenantId
51 | #>
52 |
53 | if ($All) {
54 | #$UserSplat.All = $All
55 | #$UserSplat.DomainName = 'evotec.xyz'
56 |
57 | }
58 |
59 | $Users = Get-MsolUser -All:$All -Synchronized:$Synchronized -ReturnDeletedUsers:$ReturnDeletedUsers -UnlicensedUsersOnly:$ReturnUnlicensedUsers
60 | $Users
61 |
62 | }
63 |
64 | #Get-WinAzureADUsers -MaxResults 3 -Country 'Poland' -ReturnDeletedUsers -ReturnUnlicensedUsers
--------------------------------------------------------------------------------
/Private/AzureAD/Set-WinAzureADUserField.ps1:
--------------------------------------------------------------------------------
1 | function Set-WinAzureADUserField {
2 | [CmdletBinding()]
3 | param (
4 | [parameter(Mandatory = $true)][Object] $User,
5 | [parameter(Mandatory = $false)][Object] $Value,
6 | [switch] $WhatIf
7 | )
8 |
9 | $Splat = @{}
10 | $Splat.UserPrincipalName = $User.UserPrincipalName
11 | $Splat.ErrorAction = 'Stop'
12 | if ($Value) {
13 | $Field = "$($Value.Field)"
14 | if ($Field -eq 'UserPrincipalName') {
15 | # if UserPrincipalName it means user wants to rename UserPrincipalName
16 | # that requires different method
17 | $Field = 'NewUserPrincipalName'
18 | }
19 | $Data = $Value.Value
20 | $Splat.$Field = $Data
21 | }
22 |
23 | $Object = @()
24 | if ($User.$Field -ne $Data) {
25 | try {
26 | if (-not $WhatIf) {
27 | if ($Field -eq 'UserPrincipalName') {
28 | Set-MsolUserPrincipalName @Splat
29 | } else {
30 | Set-MsolUser @Splat
31 | }
32 | }
33 |
34 | $Object += @{ Status = $true; Output = $User.UserPrincipalName; Extended = "Set $Field to $Data" }
35 | } catch {
36 | $ErrorMessage = $_.Exception.Message -replace "`n", " " -replace "`r", " " -Replace ' ',' '
37 | $Object += @{ Status = $false; Output = $User.UserPrincipalName; Extended = $ErrorMessage }
38 | }
39 | }
40 | return $Object
41 | }
--------------------------------------------------------------------------------
/Private/AzureAD/Set-WinAzureADUserLicense.ps1:
--------------------------------------------------------------------------------
1 | function Set-WinAzureADUserLicense {
2 | [CmdletBinding()]
3 | param (
4 | [parameter(Mandatory = $true)][Object] $User,
5 | [parameter(Mandatory = $true)][ValidateSet("Add", "Remove", "RemoveAll", "Replace")][String] $Option,
6 | [parameter(Mandatory = $false)][string] $License,
7 | [parameter(Mandatory = $false)][string] $LicenseToReplace,
8 | [switch] $WhatIf
9 | )
10 | $Object = @()
11 | if ($Option -eq 'Add') {
12 | try {
13 | if (-not $WhatIf) {
14 | Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -AddLicenses $License -ErrorAction Stop
15 | }
16 | $Object += @{ Status = $true; Output = $User.UserPrincipalName; Extended = "Added license $License to user." }
17 | } catch {
18 | $ErrorMessage = $_.Exception.Message -replace "`n", " " -replace "`r", " "
19 | $Object += @{ Status = $false; Output = $User.UserPrincipalName; Extended = $ErrorMessage }
20 | }
21 | } elseif ($Option -eq 'Remove') {
22 | try {
23 | if (-not $WhatIf) {
24 | Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -RemoveLicenses $License -ErrorAction Stop
25 | }
26 | $Object += @{ Status = $true; Output = $User.UserPrincipalName; Extended = "Removed license $License from user." }
27 | } catch {
28 | $ErrorMessage = $_.Exception.Message -replace "`n", " " -replace "`r", " "
29 | $Object += @{ Status = $false; Output = $User.UserPrincipalName; Extended = $ErrorMessage }
30 | }
31 | } elseif ($Option -eq 'RemoveAll') {
32 | try {
33 | foreach ($License in $User.Licenses.AccountSKUID) {
34 | if (-not $WhatIf) {
35 | Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -RemoveLicenses $License -ErrorAction Stop
36 | }
37 | $Object += @{ Status = $true; Output = $User.UserPrincipalName; Extended = "Removed license $License from user." }
38 | }
39 | } catch {
40 | $ErrorMessage = $_.Exception.Message -replace "`n", " " -replace "`r", " "
41 | $Object += @{ Status = $false; Output = $User.UserPrincipalName; Extended = $ErrorMessage }
42 | }
43 | } elseif ($Option -eq 'Replace') {
44 | [bool] $Success = $true
45 | try {
46 | if (-not $WhatIf) {
47 | Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -AddLicenses $License
48 | }
49 | $Object += @{ Status = $true; Output = $User.UserPrincipalName; Extended = "Added license $License to user before removing $LicenseToReplace." }
50 | } catch {
51 | $ErrorMessage = $_.Exception.Message -replace "`n", " " -replace "`r", " "
52 | $Object += @{ Status = $false; Output = $User.UserPrincipalName; Extended = $ErrorMessage }
53 | $Success = $false
54 | }
55 | if ($Success) {
56 | try {
57 | if (-not $WhatIf) {
58 | Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -RemoveLicenses $License -ErrorAction Stop
59 | }
60 | $Object += @{ Status = $true; Output = $User.UserPrincipalName; Extended = "Removed license $LicenseToReplace from user." }
61 | } catch {
62 | $ErrorMessage = $_.Exception.Message -replace "`n", " " -replace "`r", " "
63 | $Object += @{ Status = $false; Output = $User.UserPrincipalName; Extended = $ErrorMessage }
64 | }
65 | }
66 | }
67 | return $Object
68 | }
--------------------------------------------------------------------------------
/Private/AzureAD/Set-WinAzureADUserStatus.ps1:
--------------------------------------------------------------------------------
1 | function Set-WinAzureADUserStatus {
2 | [CmdletBinding()]
3 | param (
4 | [parameter(Mandatory = $true)][Object] $User,
5 | [parameter(Mandatory = $true)][ValidateSet("Enable", "Disable")][String] $Option,
6 | [switch] $WhatIf
7 | )
8 | $Object = @()
9 | if ($Option -eq 'Enable' -and $User.BlockCredential -eq $true) {
10 | try {
11 | if (-not $WhatIf) {
12 | Set-MsolUser -UserPrincipalName $User.UserPrincipalName -BlockCredential $false
13 | }
14 | $Object += @{ Status = $true; Output = $User.UserPrincipalName; Extended = 'Enabled user.' }
15 | } catch {
16 | $ErrorMessage = $_.Exception.Message -replace "`n", " " -replace "`r", " "
17 | $Object += @{ Status = $false; Output = $User.UserPrincipalName; Extended = $ErrorMessage }
18 | }
19 | } elseif ($Option -eq 'Disable' -and $User.BlockCredential -eq $false) {
20 | try {
21 | if (-not $WhatIf) {
22 | Set-MsolUser -UserPrincipalName $User.UserPrincipalName -BlockCredential $true
23 | }
24 | $Object += @{ Status = $true; Output = $User.UserPrincipalName; Extended = 'Disabled user.' }
25 | } catch {
26 | $ErrorMessage = $_.Exception.Message -replace "`n", " " -replace "`r", " "
27 | $Object += @{ Status = $false; Output = $User.UserPrincipalName; Extended = $ErrorMessage }
28 | }
29 | }
30 | return $Object
31 | }
--------------------------------------------------------------------------------
/Private/Configuration/Get-PSAutomatorConfiguration.ps1:
--------------------------------------------------------------------------------
1 | function Get-PSAutomatorConfiguration {
2 | [CmdletBinding()]
3 | param(
4 | $ConfigurationPath
5 | )
6 | if (($ConfigurationPath) -and (Test-Path $ConfigurationPath)) {
7 | $Script:Configuration = Import-Clixml -Path $ConfigurationPath
8 | } else {
9 | $Script:Configuration = $null
10 | }
11 | }
--------------------------------------------------------------------------------
/Private/Main/Complete-WorkFlow.ps1:
--------------------------------------------------------------------------------
1 | Function Complete-WorkFlow {
2 | [CmdletBinding()]
3 | param (
4 | [Parameter(ValueFromPipeline = $true, Mandatory = $false, Position = 0)] $Object
5 | )
6 | Begin {
7 |
8 | }
9 | Process {
10 | if ($null -eq $Object) {
11 | Write-Warning "Complete-WorkFlow can't be used out of order. Terminating!"
12 | Exit
13 | }
14 | Start-Configuration -Configuration $Script:Configuration
15 |
16 | foreach ($Trigger in $Object.Triggers) {
17 | Out-TriggerStatus -Trigger $Trigger
18 |
19 | if ($Trigger.Type -eq 'User') {
20 | switch ($Trigger.Trigger) {
21 | Always {
22 | $Object.ProcessingData.Users += Get-WinADUsers -Filter '*'
23 | }
24 | Filter {
25 | $Object.ProcessingData.Users += Get-WinADUsers -Filter $Trigger.Value
26 | }
27 | GroupMembership {
28 | $Object.ProcessingData.Users += Get-WinADUsers -Group $Trigger.Value
29 | }
30 | OrganizationalUnit {
31 | $Object.ProcessingData.Users += Get-WinADUsers -OrganizationalUnit $Trigger.Value
32 | }
33 | }
34 | }
35 | if ($Trigger.Type -eq 'UserAzureAD') {
36 | switch ($Trigger.Trigger) {
37 | All {
38 | $Object.ProcessingData.Users += Get-WinAzureADUsers -All
39 | }
40 | ByFields {
41 | $Object.ProcessingData.Users += Get-WinAzureADUsers -Trigger $Trigger.Value
42 | }
43 | Deleted {
44 | $Object.ProcessingData.Users += Get-WinAzureADUsers -ReturnDeletedUsers
45 | }
46 | Domain {
47 | $Object.ProcessingData.Users += Get-WinAzureADUsers -Trigger $Trigger.Value
48 | }
49 | Synchronized {
50 | $Object.ProcessingData.Users += Get-WinAzureADUsers -Synchronized
51 | }
52 | Unlicensed {
53 | $Object.ProcessingData.Users += Get-WinAzureADUsers -ReturnUnlicensedUsers
54 | }
55 | UserPrincipalName {
56 | $Object.ProcessingData.Users += Get-WinAzureADUsers -UserPrincipalName $Trigger.Value
57 | }
58 | Search {
59 | $Object.ProcessingData.Users += Get-WinAzureADUsers -Trigger $Trigger.Value
60 | }
61 | }
62 | }
63 | }
64 |
65 |
66 | foreach ($Condition in $Object.Conditions) {
67 | if (-not [string]::IsNullOrEmpty($Condition.Value) -and $Condition.Condition -ne $null) {
68 | if ($Condition.Value -is [string]) {
69 | $WriteInformation = @{
70 | Text = '[+]', ' Running Condition', ' for ', $Condition.Name, ' as ', $Condition.Condition
71 | Color = [ConsoleColor]::Magenta, [ConsoleColor]::White, [ConsoleColor]::White, `
72 | [ConsoleColor]::Magenta, [ConsoleColor]::White, [ConsoleColor]::Magenta, [ConsoleColor]::White, [ConsoleColor]::Magenta, `
73 | [ConsoleColor]::White, [ConsoleColor]::Magenta
74 | StartSpaces = 4
75 | }
76 | } else {
77 | $WriteInformation = @{
78 | Text = '[+]', ' Running Condition', ' for ', $Condition.Name, ' as ', $Condition.Condition, ' with operator ', $Condition.Value.Operator, ' on field ', $Condition.Value.Field
79 | Color = [ConsoleColor]::Magenta, [ConsoleColor]::White, [ConsoleColor]::White, `
80 | [ConsoleColor]::Magenta, [ConsoleColor]::White, [ConsoleColor]::Magenta, [ConsoleColor]::White, [ConsoleColor]::Magenta, `
81 | [ConsoleColor]::White, [ConsoleColor]::Magenta
82 | StartSpaces = 4
83 | }
84 | }
85 | Write-Color @WriteInformation
86 | switch ($Condition.Condition) {
87 | EmptyOrNull {
88 | $Object.ProcessingData.Users = Submit-ConditionEmptyOrNull -Object $Object.ProcessingData.Users -Value $Condition.Value
89 | }
90 | Field {
91 | $Object.ProcessingData.Users = Submit-ConditionFields -Type 'Default' -Object $Object.ProcessingData.Users -Value $Condition.Value
92 | }
93 | GroupMembership {
94 | $Object.ProcessingData.Users = Submit-ConditionFields -Type 'GroupMembership' -Object $Object.ProcessingData.Users -Value $Condition.Value
95 | }
96 | OrganizationalUnit {
97 | $Object.ProcessingData.Users = Submit-ConditionFields -Type 'OrganizationalUnit' -Object $Object.ProcessingData.Users -Value $Condition.Value
98 | }
99 | }
100 | } else {
101 | $WriteInformation = @{
102 | Text = '[-]', ' Running Condition', ' for ', $Condition.Name, ' was skipped due to either ', 'Condition', ' or/and ', 'Value', ' missing.'
103 | Color = [ConsoleColor]::Red, [ConsoleColor]::White, [ConsoleColor]::White, `
104 | [ConsoleColor]::Red, [ConsoleColor]::White, [ConsoleColor]::Red, [ConsoleColor]::White, [ConsoleColor]::Red, [ConsoleColor]::White, [ConsoleColor]::Red, [ConsoleColor]::White
105 | StartSpaces = 4
106 | }
107 | Write-Color @WriteInformation
108 | }
109 | }
110 |
111 |
112 | $CountUsers = Get-ObjectCount -Object $Object.ProcessingData.Users
113 |
114 | foreach ($Action in $Object.Actions) {
115 |
116 | $WriteInformation = @{
117 | Color = [ConsoleColor]::DarkGreen, [ConsoleColor]::White, [ConsoleColor]::DarkGreen, [ConsoleColor]::White, `
118 | [ConsoleColor]::DarkGreen, [ConsoleColor]::White, [ConsoleColor]::DarkGreen, [ConsoleColor]::White, [ConsoleColor]::DarkGreen
119 | StartSpaces = 4
120 | }
121 | if ($Action.WhatIf) {
122 | $WriteInformation.Text = '[+] ', 'Action ', $Action.Name, ' on ', $CountUsers, ' objects based on trigger (pretending only!)' #, $Trigger.Trigger, ' with value ', $Trigger.Value
123 | } else {
124 | $WriteInformation.Text = '[*] ', 'Action ', $Action.Name, ' on ', $CountUsers, ' objects based on trigger' #, $Trigger.Trigger, ' with value ', $Trigger.Value
125 | }
126 | Write-Color @WriteInformation
127 |
128 | if ($Action.Type -eq 'ActiveDirectory') {
129 | Submit-ActionActiveDirectory -Object $Object -Action $Action
130 | }
131 | if ($Action.Type -eq 'AzureActiveDirectory') {
132 | Submit-ActionAzureActiveDirectory -Object $Object -Action $Action
133 | }
134 | if ($Action.Type -eq 'Exchange') {
135 |
136 | }
137 | }
138 | }
139 | End {
140 | return $Object
141 | }
142 | }
--------------------------------------------------------------------------------
/Private/Main/Get-WinDocumentationText.ps1:
--------------------------------------------------------------------------------
1 | function Get-WinDocumentationText {
2 | [CmdletBinding()]
3 | param (
4 | [string[]] $Text,
5 | [Object] $Forest,
6 | [string] $Domain
7 | )
8 |
9 | $Replacement = @{
10 | '' = $Forest.ForestName
11 | '' = $Forest.RootDSE.defaultNamingContext
12 | '' = $Domain
13 | '' = $Forest.FoundDomains.$Domain.DomainInformation.NetBIOSName
14 | '' = $Forest.FoundDomains.$Domain.DomainInformation.DistinguishedName
15 | }
16 | $Array = @()
17 | foreach ($T in $Text) {
18 | foreach ($Key in $Replacement.Keys) {
19 | if ($T -like "*$Key*") {
20 | if ($Replacement.$Key) {
21 | $T = $T.Replace($Key, $Replacement.$Key)
22 | } else {
23 | Write-Warning "Replacing $Key failed. No value available for substition"
24 | }
25 | }
26 | }
27 | $Array += $T
28 | }
29 | return $Array
30 | }
--------------------------------------------------------------------------------
/Private/Main/Resolve-IgnoreTexts.ps1:
--------------------------------------------------------------------------------
1 | function Resolve-IgnoreTexts {
2 | param (
3 | [string[]] $IgnoreText
4 | )
5 | $Ignores = New-ArrayList
6 | foreach ($Ignore in $IgnoreText) {
7 | if ($Script:ActiveDirectory.Domains) {
8 | foreach ($Domain in $Script:ActiveDirectory.Domains) {
9 | $Text = Get-WinDocumentationText -Text $Ignore -Forest $Script:ActiveDirectory.Forest -Domain $Domain
10 | Add-ToArrayAdvanced -List $Ignores -Element $Text -SkipNull -RequireUnique
11 | }
12 | } else {
13 | $Text = Get-WinDocumentationText -Text $Ignore -Forest $Script:ActiveDirectory.Forest -Domain ''
14 | Add-ToArrayAdvanced -List $Ignores -Element $Text -SkipNull -RequireUnique
15 | }
16 | }
17 | return $Ignores
18 | }
19 |
--------------------------------------------------------------------------------
/Private/Main/Search-ObjectToIgnore.ps1:
--------------------------------------------------------------------------------
1 | function Search-ObjectToIgnore {
2 | [CmdletBinding()]
3 | param(
4 | $Object,
5 | $Ignore
6 | )
7 | #Write-Color @Script:WriteParameters -Text '[i]', ' Processing object ', $Object.DisplayName, ' for ignore list candidate' -Color Yellow, White, Red
8 | foreach ($Key in $Ignore.Keys) {
9 | if ($Key -eq 'MatchingEmptyOrNull') {
10 | foreach ($SubKey in $Ignore.$Key.Keys) {
11 | $FieldType = $SubKey
12 | $IgnoreValues = $Ignore.$Key.$SubKey
13 | foreach ($Value in $IgnoreValues) {
14 | if ($FieldType -and $Value) {
15 | if ([String]::IsNullOrWhiteSpace($Object.$FieldType)) {
16 | Write-Color @Script:WriteParameters -Text '[i]', ' Adding object ', $Object.DisplayName, ' to Ignore List because field: ', $FieldType, ' is null or empty.' -Color Yellow, White, Red, White, Green, White, Yellow, White
17 | return
18 | }
19 | }
20 | }
21 | }
22 | }
23 | if ($Key -eq 'MatchingObjects') {
24 | foreach ($SubKey in $Ignore.$Key.Keys) {
25 | $FieldType = $SubKey
26 | $IgnoreValues = $Ignore.$Key.$SubKey
27 | foreach ($Value in $IgnoreValues) {
28 | if ($FieldType -and $Value) {
29 | if ($FieldType -eq 'Mailbox') {
30 | if ($Object.$Value) {
31 | # for example $Contact.WindowsEmailAddress
32 | $User = Get-User $($Object.$Value) -ErrorAction SilentlyContinue
33 | if ($User) {
34 | Write-Color @Script:WriteParameters -Text '[i]', ' Adding object ', $Object.DisplayName, ' to Ignore List because Exchange Mailbox ', $User.DisplayName, ' already exists.' -Color Yellow, White, Red, White, Green, White, Yellow, White
35 | return
36 | }
37 | }
38 | } elseif ($FieldType -eq 'ADUser') {
39 | if ($Object.$Value) {
40 | # for example $Contact.WindowsEmailAddress
41 | $User = Get-ADUser $($Object.$Value) -ErrorAction SilentlyContinue
42 | if ($User) {
43 | Write-Color @Script:WriteParameters -Text '[i]', ' Adding object ', $Object.DisplayName, ' to Ignore List because AD User ', $User.DisplayName, ' already exists.' -Color Yellow, White, Red, White, Green, White, Yellow, White
44 | return
45 | }
46 | }
47 | }
48 | }
49 | }
50 | }
51 | }
52 | if ($Key -eq 'MatchingFields') {
53 | foreach ($SubKey in $Ignore.$Key.Keys) {
54 | $FieldType = $SubKey
55 | $IgnoreValues = $Ignore.$Key.$SubKey
56 | foreach ($Value in $IgnoreValues) {
57 | if ($FieldType -and $Value) {
58 | if ($Object.$FieldType -like $Value) {
59 | Write-Color @Script:WriteParameters -Text '[i]', ' Adding object ', $Object.DisplayName, ' to Ignore List because field: ', $FieldType, ' with Value: ', $Value, ' matched.' -Color Yellow, White, Red, White, Green, White, Yellow, White
60 | return
61 | }
62 | }
63 | }
64 | }
65 | }
66 | }
67 | return $Object
68 | }
--------------------------------------------------------------------------------
/Private/Main/Start-Configuration.ps1:
--------------------------------------------------------------------------------
1 | function Start-Configuration {
2 | param(
3 | $Configuration
4 | )
5 | Out-ConfigurationStatus -Option 'Start'
6 | if ($Configuration.Services.OnPremises.ActiveDirectory.Use) {
7 | $CommandOutput = Connect-WinService -Type 'ActiveDirectory' `
8 | -Credentials $Configuration.Services.OnPremises.ActiveDirectory.Credentials `
9 | -Service $Configuration.Services.OnPremises.ActiveDirectory -Verbose:$false -Output
10 | Out-ConnectionStatus -CommandOutput $CommandOutput
11 | }
12 | if ($Configuration.Services.OnPremises.Exchange.Use) {
13 | $CommandOutput = Connect-WinService -Type 'Exchange' `
14 | -Credentials $Configuration.Services.OnPremises.Exchange.Credentials `
15 | -Service $Configuration.Services.OnPremises.Exchange -Verbose:$false -Output
16 | Out-ConnectionStatus -CommandOutput $CommandOutput
17 | }
18 | if ($Configuration.Services.Office365.Azure.Use) {
19 | $CommandOutput = Connect-WinService -Type 'Azure' `
20 | -Credentials $Configuration.Services.Office365.Credentials `
21 | -Service $Configuration.Services.Office365.Azure -Verbose:$false -Output
22 | Out-ConnectionStatus -CommandOutput $CommandOutput
23 | }
24 | if ($Configuration.Services.Office365.AzureAD.Use) {
25 | $CommandOutput = Connect-WinService -Type 'AzureAD' `
26 | -Credentials $Configuration.Services.Office365.Credentials `
27 | -Service $Configuration.Services.Office365.AzureAD -Verbose:$false -Output
28 | Out-ConnectionStatus -CommandOutput $CommandOutput
29 | }
30 | if ($Configuration.Services.Office365.ExchangeOnline.Use) {
31 | $CommandOutput = Connect-WinService -Type 'ExchangeOnline' `
32 | -Credentials $Configuration.Services.Office365.Credentials `
33 | -Service $Configuration.Services.Office365.ExchangeOnline -Verbose:$false -Output
34 | Out-ConnectionStatus -CommandOutput $CommandOutput
35 | }
36 | if ($Configuration.Services.Office365.Teams.Use) {
37 | $CommandOutput = Connect-WinService -Type 'MicrosoftTeams' `
38 | -Credentials $Configuration.Services.Office365.Credentials `
39 | -Service $Configuration.Services.Office365.Teams -Verbose:$false -Output
40 | Out-ConnectionStatus -CommandOutput $CommandOutput
41 | }
42 | Out-ConfigurationStatus -Option 'End'
43 | }
--------------------------------------------------------------------------------
/Private/Main/Submit-ActionActiveDirectory.ps1:
--------------------------------------------------------------------------------
1 | function Submit-ActionActiveDirectory {
2 | [CmdletBinding()]
3 | param(
4 | $Object,
5 | $Action
6 | )
7 | foreach ($User in $Object.ProcessingData.Users) {
8 | switch ( $Action.Action ) {
9 | AccountAddGroupsSpecific {
10 | $CommandOutput = Add-WinADUserGroups -User $User -Groups $Action.Value -FieldSearch 'Name' -WhatIf:$Action.WhatIf
11 | Out-ActionStatus -CommandOutput $CommandOutput -User $User -Name $Action.Name -WhatIf:$Action.WhatIf
12 | }
13 | AccountDisable {
14 | $CommandOutput = Set-WinADUserStatus -User $User -Option Disable -WhatIf:$Action.WhatIf
15 | Out-ActionStatus -CommandOutput $CommandOutput -User $User -Name $Action.Name -WhatIf:$Action.WhatIf
16 | }
17 | AccountEnable {
18 | $CommandOutput = Set-WinADUserStatus -User $User -Option Enable -WhatIf:$Action.WhatIf
19 | Out-ActionStatus -CommandOutput $CommandOutput -User $User -Name $Action.Name -WhatIf:$Action.WhatIf
20 | }
21 | AccountHideInGAL {
22 | $CommandOutput = Set-WinADUserSettingGAL -User $User -Option Hide -WhatIf:$Action.WhatIf
23 | Out-ActionStatus -CommandOutput $CommandOutput -User $User -Name $Action.Name -WhatIf:$Action.WhatIf
24 | }
25 | AccountShowInGAL {
26 | $CommandOutput = Set-WinADUserSettingGAL -User $User -Option Show -WhatIf:$Action.WhatIf
27 | Out-ActionStatus -CommandOutput $CommandOutput -User $User -Name $Action.Name -WhatIf:$Action.WhatIf
28 | }
29 | AccountRemoveGroupsAll {
30 | $CommandOutput = Remove-WinADUserGroups -User $User -All -WhatIf:$Action.WhatIf
31 | Out-ActionStatus -CommandOutput $CommandOutput -User $User -Name $Action.Name -WhatIf:$Action.WhatIf
32 | }
33 | AccountRemoveGroupsSecurity {
34 | $CommandOutput = Remove-WinADUserGroups -User $User -GroupCategory Security -WhatIf:$Action.WhatIf
35 | Out-ActionStatus -CommandOutput $CommandOutput -User $User -Name $Action.Name -WhatIf:$Action.WhatIf
36 | }
37 | AccountRemoveGroupsDistribution {
38 | $CommandOutput = Remove-WinADUserGroups -User $User -GroupCategory Distribution -WhatIf:$Action.WhatIf
39 | Out-ActionStatus -CommandOutput $CommandOutput -User $User -Name $Action.Name -WhatIf:$Action.WhatIf
40 | }
41 | AccountRemoveGroupsDomainLocal {
42 | $CommandOutput = Remove-WinADUserGroups -User $User -GroupScope DomainLocal -WhatIf:$Action.WhatIf
43 | Out-ActionStatus -CommandOutput $CommandOutput -User $User -Name $Action.Name -WhatIf:$Action.WhatIf
44 | }
45 | AccountRemoveGroupsGlobal {
46 | $CommandOutput = Remove-WinADUserGroups -User $User -GroupScope Global -WhatIf:$Action.WhatIf
47 | Out-ActionStatus -CommandOutput $CommandOutput -User $User -Name $Action.Name -WhatIf:$Action.WhatIf
48 | }
49 | AccountRemoveGroupsUniversal {
50 | $CommandOutput = Remove-WinADUserGroups -User $User -GroupScope Universal -WhatIf:$Action.WhatIf
51 | Out-ActionStatus -CommandOutput $CommandOutput -User $User -Name $Action.Name -WhatIf:$Action.WhatIf
52 | }
53 | AccountRemoveGroupsSpecific {
54 | $CommandOutput = Remove-WinADUserGroups -User $User -Groups $Action.Value -WhatIf:$Action.WhatIf
55 | Out-ActionStatus -CommandOutput $CommandOutput -User $User -Name $Action.Name -WhatIf:$Action.WhatIf
56 | }
57 | AccountRename {
58 | if ($Action.Value.Action -eq 'AddText') {
59 | $CommandOutput = Set-WinADUserFields -User $User -Option $Action.Value.Where -TextToAdd $Action.Value.Text -Fields $Action.Value.Fields -WhatIf:$Action.WhatIf
60 | Out-ActionStatus -CommandOutput $CommandOutput -User $User -Name $Action.Name -WhatIf:$Action.WhatIf
61 | } elseif ($Action.Value.Action -eq 'RemoveText') {
62 | $CommandOutput = Set-WinADUserFields -User $User -TextToRemove $Action.Value.Text -Fields $Action.Value.Fields -WhatIf:$Action.WhatIf
63 | Out-ActionStatus -CommandOutput $CommandOutput -User $User -Name $Action.Name -WhatIf:$Action.WhatIf
64 | }
65 | }
66 | AccountSnapshot {
67 | $CommandOutput = Get-WinADUserSnapshot -User $User -XmlPath $Action.Value -WhatIf:$Action.WhatIf
68 | Out-ActionStatus -CommandOutput $CommandOutput -User $User -Name $Action.Name -WhatIf:$Action.WhatIf
69 | }
70 | }
71 | }
72 |
73 | }
--------------------------------------------------------------------------------
/Private/Main/Submit-ActionAzureActiveDirectory.ps1:
--------------------------------------------------------------------------------
1 | function Submit-ActionAzureActiveDirectory {
2 | [CmdletBinding()]
3 | param(
4 | $Object,
5 | $Action
6 | )
7 | foreach ($User in $Object.ProcessingData.Users) {
8 | switch ( $Action.Action ) {
9 | AccountAddGroupsSpecific {
10 |
11 | }
12 | AccountDisable {
13 | $CommandOutput = Set-WinAzureADUserStatus -User $User -Option Disable -WhatIf:$Action.WhatIf
14 | Out-ActionStatus -CommandOutput $CommandOutput -UserAzureAD $User -Name $Action.Name -WhatIf:$Action.WhatIf
15 | }
16 | AccountEnable {
17 | $CommandOutput = Set-WinAzureADUserStatus -User $User -Option Enable -WhatIf:$Action.WhatIf
18 | Out-ActionStatus -CommandOutput $CommandOutput -UserAzureAD $User -Name $Action.Name -WhatIf:$Action.WhatIf
19 | }
20 | AccountRemoveGroupsAll {
21 |
22 | }
23 | AccountRemoveGroupsSecurity {
24 |
25 | }
26 | AccountRemoveGroupsDistribution {
27 |
28 | }
29 | AccountRemoveGroupsSpecific {
30 |
31 | }
32 | AccountRename {
33 |
34 | }
35 | AccountSnapshot {
36 |
37 | }
38 | AddLicense {
39 | $CommandOutput = Set-WinAzureADUserLicense -User $User -Option Add -License $Action.Value -WhatIf:$Action.WhatIf
40 | Out-ActionStatus -CommandOutput $CommandOutput -UserAzureAD $User -Name $Action.Name -WhatIf:$Action.WhatIf
41 | }
42 | RemoveLicense {
43 | $CommandOutput = Set-WinAzureADUserLicense -User $User -Option Remove -License $Action.Value -WhatIf:$Action.WhatIf
44 | Out-ActionStatus -CommandOutput $CommandOutput -UserAzureAD $User -Name $Action.Name -WhatIf:$Action.WhatIf
45 | }
46 | RemoveLicenseAll {
47 | $CommandOutput = Set-WinAzureADUserLicense -User $User -Option RemoveAll -License '' -WhatIf:$Action.WhatIf
48 | Out-ActionStatus -CommandOutput $CommandOutput -UserAzureAD $User -Name $Action.Name -WhatIf:$Action.WhatIf
49 | }
50 | ReplaceLicense {
51 | $CommandOutput = Set-WinAzureADUserLicense -User $User -Option Replace -License $Action.Value -WhatIf:$Action.WhatIf
52 | Out-ActionStatus -CommandOutput $CommandOutput -UserAzureAD $User -Name $Action.Name -WhatIf:$Action.WhatIf
53 | }
54 | EnableMFA {
55 |
56 | }
57 | DisableMFA {
58 |
59 | }
60 | SetUserRole {
61 |
62 | }
63 | SetField {
64 | $CommandOutput = Set-WinAzureADUserField -User $User -Value $Action.Value -WhatIf:$Action.WhatIf
65 | Out-ActionStatus -CommandOutput $CommandOutput -UserAzureAD $User -Name $Action.Name -WhatIf:$Action.WhatIf
66 | }
67 | SynchronizeFields {
68 |
69 | }
70 |
71 | }
72 | }
73 | }
--------------------------------------------------------------------------------
/Private/Main/Submit-ActionExchange.ps1:
--------------------------------------------------------------------------------
1 | function Submit-ActionExchange {
2 | [CmdletBinding()]
3 | param(
4 | $Object,
5 | $Action
6 | )
7 | foreach ($User in $Object.ProcessingData.Users) {
8 | switch ( $Action.Action ) {
9 | MailboxConvertToSharedMailbox {
10 |
11 | }
12 | MailboxEmailAddressPolicyEnable {
13 |
14 | }
15 | ContactConvertToMailContact {
16 |
17 | }
18 | MailboxRemoteEnable {
19 |
20 | }
21 | }
22 | }
23 | }
24 |
25 | function Set-WinExchangeRemoteMailbox {
26 | param(
27 |
28 | )
29 |
30 | $RemoteRoutingAddress = ''
31 | Enable-RemoteMailbox -Identity $User.DistinguishedName -RemoteRoutingAddress $RemoteRoutingAddress
32 | }
33 |
34 |
--------------------------------------------------------------------------------
/Private/Main/Submit-ConditionEmptyOrNull.ps1:
--------------------------------------------------------------------------------
1 | function Submit-ConditionEmptyOrNull {
2 | param(
3 | [Object] $Object,
4 | [Object] $Value
5 | )
6 | $Field = "$Value"
7 | $ObjectOutput = $Object | Where-Object { $null -ne $_.$Field -and $_.$Field -ne '' }
8 |
9 | #$CountBefore = $Object.Count
10 | #$CountAfter = $ObjectOutput.Count
11 |
12 | return $ObjectOutput
13 | }
--------------------------------------------------------------------------------
/Private/Main/Submit-ConditionFields.ps1:
--------------------------------------------------------------------------------
1 | function Submit-ConditionFields {
2 | [CmdletBinding()]
3 | param(
4 | [Object] $Object,
5 | [Object] $Value,
6 | [string] $Type = 'Default'
7 | )
8 | [string] $Field = ''
9 | if ($Type -eq 'Default') {
10 | $Field = "$($Value.Field)"
11 | } elseif ($Type -eq 'OrganizationalUnit') {
12 | $Field = "$($Value.Field)"
13 | } elseif ($Type -eq 'GroupMembership') {
14 | $Field = "$($Value.Field)"
15 | }
16 |
17 | [string] $Operator = $Value.Operator
18 | [Object] $Value = $Value.Value
19 |
20 | # Negative
21 | if ($Operator -eq 'notlike') {
22 | if ($Type -eq 'OrganizationalUnit') {
23 | return $Object | Where-Object { $_.OrganizationalUnit.$Field -notlike $Value }
24 | } elseif ($Type -eq 'GroupMembership') {
25 | return $Object | Where-Object { $_.MemberOf.$Field -notlike $Value }
26 | } else {
27 |
28 | return $Object | Where-Object { $_.$Field -notlike $Value }
29 | }
30 | }
31 | if ($Operator -eq 'notcontains') {
32 | if ($Type -eq 'OrganizationalUnit') {
33 | return $Object | Where-Object { $_.OrganizationalUnit.$Field -notcontains $Value }
34 | } elseif ($Type -eq 'GroupMembership') {
35 | return $Object | Where-Object { $_.MemberOf.$Field -notcontains $Value }
36 | } else {
37 | return $Object | Where-Object { $_.$Field -notcontains $Value }
38 | }
39 | }
40 | if ($Operator -eq 'ne') {
41 | if ($Type -eq 'OrganizationalUnit') {
42 | return $Object | Where-Object { $_.OrganizationalUnit.$Field -ne $Value }
43 | } elseif ($Type -eq 'GroupMembership') {
44 | return $Object | Where-Object { $_.MemberOf.$Field -ne $Value }
45 | } else {
46 | return $Object | Where-Object { $_.$Field -ne $Value }
47 | }
48 | }
49 | if ($Operator -eq 'cnotlike') {
50 | if ($Type -eq 'OrganizationalUnit') {
51 | return $Object | Where-Object { $_.OrganizationalUnit.$Field -cnotlike $Value }
52 | } elseif ($Type -eq 'GroupMembership') {
53 | return $Object | Where-Object { $_.MemberOf.$Field -cnotlike $Value }
54 | } else {
55 | return $Object | Where-Object { $_.$Field -cnotlike $Value }
56 | }
57 | }
58 | if ($Operator -eq 'cne') {
59 | if ($Type -eq 'OrganizationalUnit') {
60 | return $Object | Where-Object { $_.OrganizationalUnit.$Field -cne $Value }
61 | } elseif ($Type -eq 'GroupMembership') {
62 | return $Object | Where-Object { $_.MemberOf.$Field -cne $Value }
63 | } else {
64 | return $Object | Where-Object { $_.$Field -cne $Value }
65 | }
66 | }
67 | if ($Operator -eq 'cnotcontains') {
68 | if ($Type -eq 'OrganizationalUnit') {
69 | return $Object | Where-Object { $_.OrganizationalUnit.$Field -cnotcontains $Value }
70 | } elseif ($Type -eq 'GroupMembership') {
71 | return $Object | Where-Object { $_.MemberOf.$Field -cnotcontains $Value }
72 | } else {
73 | return $Object | Where-Object { $_.$Field -cnotcontains $Value }
74 | }
75 | }
76 |
77 | # Positive
78 | if ($Operator -eq 'like') {
79 | if ($Type -eq 'OrganizationalUnit') {
80 | return $Object | Where-Object { $_.OrganizationalUnit.$Field -like $Value }
81 | } elseif ($Type -eq 'GroupMembership') {
82 | return $Object | Where-Object { $_.MemberOf.$Field -like $Value }
83 | } else {
84 | return $Object | Where-Object { $_.$Field -like $Value }
85 | }
86 | }
87 | if ($Operator -eq 'contains') {
88 | if ($Type -eq 'OrganizationalUnit') {
89 | return $Object | Where-Object { $_.OrganizationalUnit.$Field -contains $Value }
90 | } elseif ($Type -eq 'GroupMembership') {
91 | return $Object | Where-Object { $_.MemberOf.$Field -contains $Value }
92 | } else {
93 | return $Object | Where-Object { $_.$Field -contains $Value }
94 | }
95 | }
96 | if ($Operator -eq 'eq') {
97 | if ($Type -eq 'OrganizationalUnit') {
98 | return $Object | Where-Object { $_.OrganizationalUnit.$Field -eq $Value }
99 | } elseif ($Type -eq 'GroupMembership') {
100 | return $Object | Where-Object { $_.MemberOf.$Field -eq $Value }
101 | } else {
102 | return $Object | Where-Object { $_.$Field -eq $Value }
103 | }
104 | }
105 | if ($Operator -eq 'clike') {
106 | if ($Type -eq 'OrganizationalUnit') {
107 | return $Object | Where-Object { $_.OrganizationalUnit.$Field -clike $Value }
108 | } elseif ($Type -eq 'GroupMembership') {
109 | return $Object | Where-Object { $_.MemberOf.$Field -clike $Value }
110 | } else {
111 | return $Object | Where-Object { $_.$Field -clike $Value }
112 | }
113 | }
114 | if ($Operator -eq 'ceq') {
115 | if ($Type -eq 'OrganizationalUnit') {
116 | return $Object | Where-Object { $_.OrganizationalUnit.$Field -ceq $Value }
117 | } elseif ($Type -eq 'GroupMembership') {
118 | return $Object | Where-Object { $_.MemberOf.$Field -ceq $Value }
119 | } else {
120 | return $Object | Where-Object { $_.$Field -ceq $Value }
121 | }
122 | }
123 | if ($Operator -eq 'ccontains') {
124 | if ($Type -eq 'OrganizationalUnit') {
125 | return $Object | Where-Object { $_.OrganizationalUnit.$Field -ccontains $Value }
126 | } elseif ($Type -eq 'GroupMembership') {
127 | return $Object | Where-Object { $_.MemberOf.$Field -ccontains $Value }
128 | } else {
129 | return $Object | Where-Object { $_.$Field -ccontains $Value }
130 | }
131 | }
132 |
133 |
134 | if ($Operator -eq 'gt') {
135 | if ($Type -eq 'OrganizationalUnit') {
136 | return $Object | Where-Object { $_.OrganizationalUnit.$Field -gt $Value }
137 | } elseif ($Type -eq 'GroupMembership') {
138 | return $Object | Where-Object { $_.MemberOf.$Field -gt $Value }
139 | } else {
140 | return $Object | Where-Object { $_.$Field -gt $Value }
141 | }
142 | }
143 |
144 | if ($Operator -eq 'ge') {
145 | if ($Type -eq 'OrganizationalUnit') {
146 | return $Object | Where-Object { $_.OrganizationalUnit.$Field -ge $Value }
147 | } elseif ($Type -eq 'GroupMembership') {
148 | return $Object | Where-Object { $_.MemberOf.$Field -ge $Value }
149 | } else {
150 | return $Object | Where-Object { $_.$Field -ge $Value }
151 | }
152 | }
153 |
154 | if ($Operator -eq 'lt') {
155 | if ($Type -eq 'OrganizationalUnit') {
156 | return $Object | Where-Object { $_.OrganizationalUnit.$Field -lt $Value }
157 | } elseif ($Type -eq 'GroupMembership') {
158 | return $Object | Where-Object { $_.MemberOf.$Field -lt $Value }
159 | } else {
160 | return $Object | Where-Object { $_.$Field -lt $Value }
161 | }
162 | }
163 |
164 | if ($Operator -eq 'le') {
165 | if ($Type -eq 'OrganizationalUnit') {
166 | return $Object | Where-Object { $_.OrganizationalUnit.$Field -le $Value }
167 | } elseif ($Type -eq 'GroupMembership') {
168 | return $Object | Where-Object { $_.MemberOf.$Field -le $Value }
169 | } else {
170 | return $Object | Where-Object { $_.$Field -le $Value }
171 | }
172 | }
173 |
174 | if ($Operator -eq 'match') {
175 | if ($Type -eq 'OrganizationalUnit') {
176 | return $Object | Where-Object { $_.OrganizationalUnit.$Field -match $Value }
177 | } elseif ($Type -eq 'GroupMembership') {
178 | return $Object | Where-Object { $_.MemberOf.$Field -match $Value }
179 | } else {
180 | return $Object | Where-Object { $_.$Field -match $Value }
181 | }
182 | }
183 |
184 | if ($Operator -eq 'match') {
185 | if ($Type -eq 'OrganizationalUnit') {
186 | return $Object | Where-Object { $_.OrganizationalUnit.$Field -notmatch $Value }
187 | } elseif ($Type -eq 'GroupMembership') {
188 | return $Object | Where-Object { $_.MemberOf.$Field -notmatch $Value }
189 | } else {
190 | return $Object | Where-Object { $_.$Field -match $Value }
191 | }
192 | }
193 | }
--------------------------------------------------------------------------------
/Private/Main/Submit-ConditionOrganizationalUnit.ps1:
--------------------------------------------------------------------------------
1 | function Submit-ConditionOrganizationalUnit {
2 | param(
3 |
4 | )
5 | }
--------------------------------------------------------------------------------
/Private/Output/Out-ActionStatus.ps1:
--------------------------------------------------------------------------------
1 | function Out-ActionStatus {
2 | [CmdletBinding(DefaultParameterSetName = 'ActiveDirectory')]
3 | param(
4 | [parameter(Mandatory = $false)][Array] $CommandOutput,
5 | [parameter(Mandatory = $true, ParameterSetName = "ActiveDirectory")][Object] $User,
6 | [parameter(Mandatory = $true, ParameterSetName = "AzureActiveDirectory")][Object] $UserAzureAD, # [Microsoft.Online.Administration.User] $UserAzureAD,
7 | [parameter(Mandatory = $true)][string] $Name,
8 | [switch] $WhatIf
9 | )
10 | switch ($PSCmdlet.ParameterSetName) {
11 | ActiveDirectory {
12 | $UserInformation = $User.DistinguishedName
13 | }
14 | AzureActiveDirectory {
15 | $UserInformation = $UserAzureAD.UserPrincipalName
16 | }
17 | }
18 | if ($WhatIf) {
19 | $WriteSuccess = @{
20 | Text = '[+] ', 'WhatIf: ', 'Execution ', $Name, ' on account ', $UserInformation, ' done.'
21 | Color = [System.ConsoleColor]::Cyan, [System.ConsoleColor]::DarkMagenta, [System.ConsoleColor]::White, [System.ConsoleColor]::Cyan,
22 | [System.ConsoleColor]::White, [System.ConsoleColor]::Cyan, [System.ConsoleColor]::White, [System.ConsoleColor]::Cyan,
23 | [System.ConsoleColor]::White, [System.ConsoleColor]::Cyan
24 | StartSpaces = 8
25 | }
26 | $WriteSkip = @{
27 | Text = '[+] ', 'WhatIf: ', 'Execution ', $Name, ' on account ', $UserInformation, ' done.'
28 | Color = 'Yellow', [System.ConsoleColor]::DarkMagenta, 'White', 'Yellow', 'White', 'Yellow', 'White', 'Yellow', 'White', 'Yellow'
29 | StartSpaces = 8
30 | }
31 |
32 | $WriteStatusSuccess = @{
33 | StartSpaces = 12
34 | Color = 'Green', [System.ConsoleColor]::DarkMagenta, 'White', 'Green', 'White', 'Green'
35 | }
36 | $WriteStatusFail = @{
37 | StartSpaces = 12
38 | Color = 'Red', [System.ConsoleColor]::DarkMagenta, 'White', 'Red', 'White', 'Red'
39 | }
40 |
41 | } else {
42 | $WriteSuccess = @{
43 | Text = '[+] ', 'Execution ', $Name, ' on account ', $UserInformation, ' done.'
44 | Color = 'Cyan', 'White', 'Cyan', 'White', 'Cyan', 'White', 'Cyan', 'White', 'Cyan'
45 | StartSpaces = 8
46 | }
47 | $WriteSkip = @{
48 | Text = '[+] ', 'Execution ', $Name, ' on account ', $UserInformation, ' done.'
49 | Color = 'Yellow', 'White', 'Yellow', 'White', 'Yellow', 'White', 'Yellow', 'White', 'Yellow'
50 | StartSpaces = 8
51 | }
52 |
53 | $WriteStatusSuccess = @{
54 | StartSpaces = 12
55 | Color = 'Green', 'White', 'Green', 'White', 'Green'
56 | }
57 | $WriteStatusFail = @{
58 | StartSpaces = 12
59 | Color = 'Red', 'White', 'Red', 'White', 'Red'
60 | }
61 | }
62 |
63 | if ($CommandOutput) {
64 | Write-Color @WriteSuccess
65 | foreach ($Output in $CommandOutput) {
66 | if ($Output.Status) {
67 | if ($WhatIf) {
68 | Write-Color @WriteStatusSuccess -Text '[+] ', 'WhatIf: ', 'Successfully processed ', $Output.Output, ' Extended information: ', $Output.Extended
69 | } else {
70 | Write-Color @WriteStatusSuccess -Text '[+] ', 'Successfully processed ', $Output.Output, ' Extended information: ', $Output.Extended
71 | }
72 | } else {
73 | if ($WhatIf) {
74 | Write-Color @WriteStatusFail -Text '[-] ', 'Whatif: ', 'Skipped ', $Output.Output, ' Extended information: ', $Output.Extended
75 | } else {
76 | Write-Color @WriteStatusFail -Text '[-] ', 'Skipped ', $Output.Output, ' Extended information: ', $Output.Extended
77 | }
78 | }
79 | }
80 | } else {
81 | Write-Color @WriteSkip
82 | }
83 | }
--------------------------------------------------------------------------------
/Private/Output/Out-ConfigurationStatus.ps1:
--------------------------------------------------------------------------------
1 | function Out-ConfigurationStatus {
2 | [CmdletBinding()]
3 | param(
4 | [parameter(Mandatory = $false)][Array] $CommandOutput,
5 | [string] $Option = 'Start'
6 | )
7 |
8 | $WriteStatusSuccess = @{
9 | StartSpaces = 4
10 | Color = 'Green', 'White', 'Green', 'White', 'Green', 'White', 'Green'
11 | }
12 | $WriteStatusEnd = @{
13 | StartSpaces = 4
14 | Color = 'Green', 'White', 'Green', 'White', 'Green', 'White', 'Green'
15 | }
16 | $WriteStatusFail = @{
17 | StartSpaces = 4
18 | Color = 'Red', 'White', 'Red', 'White', 'Red', 'White', 'Red'
19 | }
20 | if ($Option -eq 'Start') {
21 | Write-Color @WriteStatusSuccess -Text '[+] ', 'Running ', 'Configuration'
22 | } elseif ($Option -eq 'End') {
23 | Write-Color @WriteStatusEnd -Text '[+] ', 'Ending ', 'Configuration'
24 | } else {
25 | Write-Color @WriteStatusFail -Text '[-] ', 'Failed ', 'Configuration'
26 | }
27 | }
--------------------------------------------------------------------------------
/Private/Output/Out-ConnectionStatus.ps1:
--------------------------------------------------------------------------------
1 | function Out-ConnectionStatus {
2 | [CmdletBinding()]
3 | param(
4 | [parameter(Mandatory = $false)][Array] $CommandOutput
5 | )
6 |
7 | $WriteStatusSuccess = @{
8 | StartSpaces = 8
9 | Color = 'Green', 'White', 'Green', 'White', 'Green', 'White', 'Green'
10 | }
11 | $WriteStatusFail = @{
12 | StartSpaces = 8
13 | Color = 'Red', 'White', 'Red', 'White', 'Red', 'White', 'Red'
14 | }
15 | if ($CommandOutput) {
16 | foreach ($Output in $CommandOutput) {
17 | if ($Output.Status) {
18 | Write-Color @WriteStatusSuccess -Text '[+] ', 'Running ', 'Connection', ' for ', $Output.Output, ' Extended information: ', $Output.Extended
19 | } else {
20 | Write-Color @WriteStatusFail -Text '[-] ', 'Running ', 'Connection', ' for ', $Output.Output, ' Extended information: ', $Output.Extended
21 | }
22 | }
23 | }
24 | }
--------------------------------------------------------------------------------
/Private/Output/Out-ServiceStatus.ps1:
--------------------------------------------------------------------------------
1 | function Out-ServiceStatus {
2 | param(
3 | [string] $Name
4 | )
5 | $WriteInformation = @{
6 | Text = '[i]', ' Running ', 'Service', ' for ', $Name
7 | Color = [ConsoleColor]::Green, [ConsoleColor]::White, [ConsoleColor]::Green, [ConsoleColor]::White, [ConsoleColor]::Green
8 | StartSpaces = 0
9 | }
10 | Write-Color @WriteInformation
11 | }
--------------------------------------------------------------------------------
/Private/Output/Out-TriggerStatus.ps1:
--------------------------------------------------------------------------------
1 | function Out-TriggerStatus {
2 | param(
3 | $Trigger
4 | )
5 | $WriteInformation = @{
6 | Text = '[+]', ' Running Trigger', ' for ', $Trigger.Name
7 | Color = [ConsoleColor]::Green, [ConsoleColor]::White, [ConsoleColor]::White, [ConsoleColor]::Green
8 | StartSpaces = 4
9 | }
10 | Write-Color @WriteInformation
11 | }
--------------------------------------------------------------------------------
/Private/Parameters/Script.Debug.ps1:
--------------------------------------------------------------------------------
1 | $Script:Debug = @{
2 | Verbose = $false
3 | }
--------------------------------------------------------------------------------
/Private/Parameters/Script.GroupProperties.ps1:
--------------------------------------------------------------------------------
1 | $Script:GroupProperties = @(
2 | 'Name',
3 | 'DisplayName',
4 | 'GroupCategory',
5 | 'GroupScope',
6 | 'SID',
7 | 'AdminCount',
8 | 'Members',
9 | 'MemberOf',
10 | 'ManagedBy',
11 | 'Created',
12 | 'Modified',
13 | 'SamAccountName',
14 | 'CanonicalName'
15 | )
--------------------------------------------------------------------------------
/Private/Parameters/Script.UserProperties.ps1:
--------------------------------------------------------------------------------
1 | $Script:UserProperties = @(
2 | 'Name',
3 | 'UserPrincipalName',
4 | 'SamAccountName',
5 | 'Enabled',
6 | 'PasswordLastSet',
7 | 'PasswordExpired',
8 | 'PasswordNeverExpires',
9 | 'PasswordNotRequired',
10 | 'EmailAddress',
11 | 'DisplayName',
12 | 'GivenName',
13 | 'Surname',
14 | 'Manager',
15 | 'AccountExpirationDate',
16 | 'AccountLockoutTime',
17 | 'AllowReversiblePasswordEncryption',
18 | 'BadLogonCount',
19 | 'CannotChangePassword',
20 | 'CanonicalName',
21 | 'Description',
22 | 'DistinguishedName',
23 | 'EmployeeID',
24 | 'EmployeeNumber',
25 | 'LastBadPasswordAttempt',
26 | 'LastLogonDate',
27 | 'Created',
28 | 'Modified',
29 | 'PrimaryGroup',
30 | 'MemberOf',
31 | 'msDS-UserPasswordExpiryTimeComputed',
32 | 'msExchHideFromAddressLists'
33 | )
--------------------------------------------------------------------------------
/Private/Parameters/Script.WriteParameters.ps1:
--------------------------------------------------------------------------------
1 | # Default value / overwritten if set in config
2 | $Script:WriteParameters = @{
3 | ShowTime = $true
4 | LogFile = ""
5 | TimeFormat = "yyyy-MM-dd HH:mm:ss"
6 | }
--------------------------------------------------------------------------------
/Public/Configuration/New-PSAutomatorConfiguration.ps1:
--------------------------------------------------------------------------------
1 | function New-PSAutomatorConfiguration {
2 | [CmdletBinding()]
3 | param(
4 | [Object] $Configuration,
5 | $Path
6 | )
7 | if ($Configuration) {
8 | $Configuration | Export-Clixml -Path $Path -Encoding UTF8
9 | }
10 | }
--------------------------------------------------------------------------------
/Public/Main/Action.ps1:
--------------------------------------------------------------------------------
1 | Function Action {
2 | [CmdletBinding()]
3 | param (
4 | [Parameter(Mandatory = $false, ValueFromPipeline = $true, Position = 0)] $Object,
5 | [parameter(Mandatory = $false)] [string] $Name,
6 | [parameter(Mandatory = $false, ParameterSetName = "ActiveDirectory")][PSAutomator.ActionAD] $ActiveDirectory,
7 | [parameter(Mandatory = $false, ParameterSetName = "AzureActiveDirectory")][PSAutomator.ActionAzureAD] $AzureActiveDirectory,
8 | [parameter(Mandatory = $false, ParameterSetName = "Exchange")][PSAutomator.ActionExchange] $Exchange,
9 | [parameter(Mandatory = $false)] [Object] $Value,
10 | [parameter(Mandatory = $false)] [switch] $WhatIf
11 | )
12 | Begin {}
13 | Process {
14 | if ($Object -eq $null) {
15 | Write-Warning "Action can't be used out of order. Terminating!"
16 | Exit
17 | }
18 | $Action = @{
19 | Name = $Name
20 | Value = $Value
21 | Type = $PSCmdlet.ParameterSetName
22 | WhatIf = $WhatIf
23 | }
24 | switch ($PSCmdlet.ParameterSetName) {
25 | ActiveDirectory {
26 | $Action.Action = $ActiveDirectory
27 | }
28 | AzureActiveDirectory {
29 | $Action.Action = $AzureActiveDirectory
30 | }
31 | Exchange {
32 | $Action.Action = $Exchange
33 | }
34 | }
35 |
36 | # Add prepared data to Object
37 | $Object.Actions += $Action
38 | }
39 | End {
40 | return $Object
41 | }
42 | }
--------------------------------------------------------------------------------
/Public/Main/Condition.ps1:
--------------------------------------------------------------------------------
1 | function Condition {
2 | [CmdletBinding()]
3 | [alias('Ignore')]
4 | param(
5 | [Parameter(ValueFromPipeline = $true, Mandatory = $false, Position = 0)] $Object,
6 | [string] $Name,
7 | [alias('Ignore')][PSAutomator.Condition] $Condition,
8 | [Object] $Value
9 | )
10 | Begin {}
11 | Process {
12 | if ($Object -eq $null) {
13 | Write-Warning "Condition can't be used out of order. Terminating!"
14 | Exit
15 | }
16 | $Object.Conditions += @{
17 | Name = if ($Name -eq '') { 'No name given' } else { $Name }
18 | Condition = $Condition
19 | Value = $Value
20 | }
21 | }
22 | End {
23 | return $Object
24 | }
25 | }
--------------------------------------------------------------------------------
/Public/Main/Connect.ps1:
--------------------------------------------------------------------------------
1 | function Connect {
2 | [CmdletBinding()]
3 | param (
4 | [PSAutomator.Connect] $Service,
5 | [string] $UserName,
6 | [string] $Password,
7 | [switch] $AsSecure,
8 | [switch] $FromFile
9 | )
10 | }
--------------------------------------------------------------------------------
/Public/Main/Service.ps1:
--------------------------------------------------------------------------------
1 | Function Service {
2 | [CmdletBinding()]
3 | param(
4 | [Parameter(Mandatory = $true, Position = 0)][string] $Name,
5 | [string] $Status,
6 | [Alias('Tags')][string[]] $Tag = @(),
7 | [string] $ConfigurationPath,
8 | [Parameter(Position = 1)][ValidateNotNull()][ScriptBlock] $ServiceData = $(Throw "No test script block is provided. (Have you put the open curly brace on the next line?)")
9 | )
10 | Begin {
11 | $TimeRun = Start-TimeLog
12 | }
13 | Process {
14 | if ($Status -eq 'Disable') { return }
15 | Out-ServiceStatus -Name $Name
16 | Get-PSAutomatorConfiguration -ConfigurationPath $ConfigurationPath
17 |
18 | $Object = Invoke-Command -ScriptBlock $ServiceData
19 | $Final = Complete-WorkFlow -Object $Object
20 | }
21 | End {
22 | $TimeEnd = $TimeRun | Stop-TimeLog -Option 'Array'
23 |
24 | $WriteInformation = @{
25 | Text = '[i]', ' Ending Service for ', $Name, ' - Time to Execute: ', $TimeEnd
26 | Color = [ConsoleColor]::Green, [ConsoleColor]::White, [ConsoleColor]::Green, [ConsoleColor]::Green, [ConsoleColor]::White
27 | LinesAfter = 1
28 | StartSpaces = 0
29 | }
30 | Write-Color @WriteInformation
31 |
32 | # Finish Service
33 | $Script:Configuration = $null
34 | return #$Final
35 | }
36 | }
--------------------------------------------------------------------------------
/Public/Main/Trigger.ps1:
--------------------------------------------------------------------------------
1 | Function Trigger {
2 | [CmdletBinding()]
3 | param (
4 | [Parameter(Mandatory = $false, ValueFromPipeline = $true, Position = 0)] $Object,
5 | [parameter(Mandatory = $false)] [string] $Name,
6 | [parameter(Mandatory = $false, ParameterSetName = "User")][PSAutomator.TriggerUserAD] $User,
7 | [parameter(Mandatory = $false, ParameterSetName = "UserAzureAD")][PSAutomator.TriggerUserAzureAD] $UserAzureAD,
8 | [parameter(Mandatory = $false, ParameterSetName = "Group")][PSAutomator.TriggerGroup] $Group,
9 | [parameter(Mandatory = $false, ParameterSetName = "Computer")][PSAutomator.TriggerComputer] $Computer,
10 | [parameter(Mandatory = $false)] [Object] $Value
11 | )
12 | Begin {
13 |
14 | }
15 | Process {
16 | if ($null -eq $Object) {
17 | # if object is null it's the first one
18 | $Object = [ordered] @{
19 | Triggers = @()
20 | Conditions = @()
21 | Ignores = @()
22 | Actions = @()
23 | ProcessingData = @{
24 | Users = @()
25 | }
26 | }
27 | }
28 | $Trigger += @{
29 | Name = $Name
30 | Value = $Value
31 | Type = $PSCmdlet.ParameterSetName
32 | }
33 | switch ($PSCmdlet.ParameterSetName) {
34 | User {
35 | $Trigger.Trigger = $User
36 | }
37 | UserAzureAD {
38 | $Trigger.Trigger = $UserAzureAD
39 | }
40 | Group {
41 | $Trigger.Trigger = $Group
42 | }
43 | Computer {
44 | $Trigger.Trigger = $Computer
45 | }
46 |
47 | }
48 | $Object.Triggers += $Trigger
49 | }
50 | End {
51 | return $Object
52 | }
53 | }
--------------------------------------------------------------------------------
/Publish/Manage-Module.ps1:
--------------------------------------------------------------------------------
1 | Clear-Host
2 |
3 | $Configuration = @{
4 | Information = @{
5 | ModuleName = 'PSAutomator'
6 | DirectoryProjects = 'C:\Support\GitHub'
7 | Manifest = @{
8 | # Minimum version of the Windows PowerShell engine required by this module
9 | PowerShellVersion = '5.1'
10 |
11 | ModuleVersion = '0.0.3'
12 |
13 | # ID used to uniquely identify this module
14 | GUID = '1be9e392-28cb-4ac6-aba7-b924defbf9da'
15 | # Author of this module
16 | Author = 'Przemyslaw Klys'
17 | # Company or vendor of this module
18 | CompanyName = 'Evotec'
19 | # Copyright statement for this module
20 | Copyright = '(c) 2018 Przemyslaw Klys. All rights reserved.'
21 | # Description of the functionality provided by this module
22 | Description = "PowerShell Module is new approach to onboarding, offboarding and business as usual processes running in companies infrastructure. Usually each company has different rules, different approaches on how processes should look like and this module takes an easy approach that's similar to what you can find in services like IFTTT or Microsoft Flow"
23 | # Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export.
24 | # Tags applied to this module. These help with module discovery in online galleries.
25 | Tags = @('ActiveDirectory', 'Offboarding', 'Onboarding', 'Windows')
26 |
27 | IconUri = 'https://evotec.xyz/wp-content/uploads/2018/10/PSAutomator.png'
28 |
29 | ProjectUri = 'https://github.com/EvotecIT/PSAutomator'
30 |
31 | RequiredModules = @('PSSharedGoods', 'PSWriteColor')
32 |
33 | }
34 | }
35 | Options = @{
36 | Merge = @{
37 | Sort = 'None'
38 | FormatCodePSM1 = @{
39 | Enabled = $true
40 | RemoveComments = $true
41 | FormatterSettings = @{
42 | IncludeRules = @(
43 | 'PSPlaceOpenBrace',
44 | 'PSPlaceCloseBrace',
45 | 'PSUseConsistentWhitespace',
46 | 'PSUseConsistentIndentation',
47 | 'PSAlignAssignmentStatement',
48 | 'PSUseCorrectCasing'
49 | )
50 |
51 | Rules = @{
52 | PSPlaceOpenBrace = @{
53 | Enable = $true
54 | OnSameLine = $true
55 | NewLineAfter = $true
56 | IgnoreOneLineBlock = $true
57 | }
58 |
59 | PSPlaceCloseBrace = @{
60 | Enable = $true
61 | NewLineAfter = $false
62 | IgnoreOneLineBlock = $true
63 | NoEmptyLineBefore = $false
64 | }
65 |
66 | PSUseConsistentIndentation = @{
67 | Enable = $true
68 | Kind = 'space'
69 | PipelineIndentation = 'IncreaseIndentationAfterEveryPipeline'
70 | IndentationSize = 4
71 | }
72 |
73 | PSUseConsistentWhitespace = @{
74 | Enable = $true
75 | CheckInnerBrace = $true
76 | CheckOpenBrace = $true
77 | CheckOpenParen = $true
78 | CheckOperator = $true
79 | CheckPipe = $true
80 | CheckSeparator = $true
81 | }
82 |
83 | PSAlignAssignmentStatement = @{
84 | Enable = $true
85 | CheckHashtable = $true
86 | }
87 |
88 | PSUseCorrectCasing = @{
89 | Enable = $true
90 | }
91 | }
92 | }
93 | }
94 | FormatCodePSD1 = @{
95 | Enabled = $true
96 | RemoveComments = $false
97 | }
98 | Integrate = @{
99 | ApprovedModules = 'PSWriteColor', 'Connectimo', 'PSUnifi', 'PSWebToolbox', 'PSMyPassword'
100 | }
101 | }
102 | Standard = @{
103 | FormatCodePSM1 = @{
104 |
105 | }
106 | FormatCodePSD1 = @{
107 | Enabled = $true
108 | #RemoveComments = $true
109 | }
110 | }
111 | PowerShellGallery = @{
112 | ApiKey = 'C:\Support\Important\PowerShellGalleryAPI.txt'
113 | FromFile = $true
114 | }
115 | GitHub = @{
116 | ApiKey = 'C:\Support\Important\GithubAPI.txt'
117 | FromFile = $true
118 | UserName = 'EvotecIT'
119 | #RepositoryName = 'PSPublishModule' # not required, uses project name
120 | }
121 | Documentation = @{
122 | Path = 'Docs'
123 | PathReadme = 'Docs\Readme.md'
124 | }
125 | }
126 | Steps = @{
127 | BuildModule = @{ # requires Enable to be on to process all of that
128 | Enable = $true
129 | DeleteBefore = $false
130 | Merge = $true
131 | MergeMissing = $true
132 | SignMerged = $true
133 | Releases = $true
134 | ReleasesUnpacked = $false
135 | RefreshPSD1Only = $false
136 | }
137 | BuildDocumentation = $false
138 | ImportModules = @{
139 | Self = $true
140 | RequiredModules = $false
141 | Verbose = $false
142 | }
143 | PublishModule = @{ # requires Enable to be on to process all of that
144 | Enabled = $false
145 | Prerelease = ''
146 | RequireForce = $false
147 | GitHub = $false
148 | }
149 | }
150 | }
151 |
152 | New-PrepareModule -Configuration $Configuration -Verbose
--------------------------------------------------------------------------------
/README.MD:
--------------------------------------------------------------------------------
1 | # PSAutomator - PowerShell Module
2 |
3 | Overview of this module is available at: https://evotec.xyz/hub/scripts/psautomator-powershell-module/
4 |
5 | ### Description
6 |
7 | This PowerShell Module is new approach to onboarding, offboarding and business as usual processes running in companies infrastructure. Usually each company has different rules, different approaches on how processes should look like and this module takes an easy approach that's similar to what you can find in services like **IFTTT** or **Microsoft Flow**. Those services work in known schema such as Services, Triggers, Ingredients and Applets. For this PowerShell Module I've taken similar approach which is described below.
8 |
9 | While it's encouraged to keep correct order Service, Trigger, Ignore, Condition, Action it actually only requires Service, Trigger to be in correct order.
10 |
11 | - [x] **Service** – is kind of a wrapper for other blocks above. It has also ability to load configuration from file. Currently loading file doesn't do anything.
12 | - [x] **Trigger** – is first block in Service. Before an Action can be executed it needs a **Trigger**. **Trigger** can be membership in Group, Organizational Unit etc
13 | - [ ] User Based Triggers
14 | - [ ] Always,
15 | - [x] OrganizationalUnit,
16 | - [x] GroupMembership,
17 | - [ ] Filter
18 | - [x] **Ignore** – But Trigger can also have things that need to be ignored. For example lack of email address field.
19 | - [ ] User Based Ignore
20 | - [x] MatchingEmptyOrNull,
21 | - [ ] MatchingObjects,
22 | - [ ] MatchingFields
23 | - [x] **Condition** – It can also be conditioned for example Last User Modification Date should be more then 30 days.
24 | - [ ] User Based Conditions
25 | - [ ] RequireGroupMembership,
26 | - [ ] RequireLastModified
27 | - [x] **Action** – are essentially Tasks that are about to be executed. This can be adding a user to a group, disabling user etc. This is also final step to close Service.
28 | - [ ] User Based Actions
29 | - [x] AccountAddGroupsSpecific
30 | - [x] AccountDisable
31 | - [x] AccountEnable
32 | - [x] AccountHideInGAL
33 | - [x] AccountShowInGAL
34 | - [x] AccountRemoveGroupsAll
35 | - [x] AccountRemoveGroupsSecurity
36 | - [x] AccountRemoveGroupsDistribution
37 | - [x] AccountRemoveGroupsSpecific
38 | - [x] AccountRemoveGroupsDomainLocal
39 | - [x] AccountRemoveGroupsGlobal
40 | - [x] AccountRemoveGroupsUniversal
41 | - [ ] AccountRename,
42 | - [x] AccountSnapshot
43 |
44 | Keep in mind that following is true for Service:
45 | - [x] Can hold only 1 trigger
46 | - [x] Can have multiple Ignore blocks
47 | - [x] Can have multiple Condition blocks
48 | - [x] Can have multiple Action blocks
49 |
50 | **This is proof-of-concept. Heavy work in progres... Please take your time and leave feedback!**
51 |
52 | ## DO NOT USE IN **PRODUCTION** YET - UNLESS YOU LIKE FIRES!
53 |
54 | ### Sample offboarding
55 |
56 | 
57 |
58 | ```powershell
59 | Clear-Host
60 | Import-Module PSAutomator -Force #-Verbose
61 | Import-Module PSSharedGoods -Force
62 | Service -Name 'Active Directory Offboarding' -ConfigurationPath 'C:\Support\GitHub\PSAutomator\Examples\MyConfiguration.xml' {
63 | Trigger -Name 'OU Offboarded Users' -User OrganizationalUnit -Value 'OU=Users-Offboarded,OU=Production,DC=ad,DC=evotec,DC=xyz' |
64 | Condition -Name 'No conditions' |
65 | Ignore -Name 'Ignore Windows Email Address if Empty or null' -Ignore MatchingEmptyOrNull -Value EmailAddress |
66 | Action -Name 'Make User Snapshot' -ActiveDirectory AccountSnapshot -Value 'C:\Users\pklys\Desktop\MyExport' |
67 | Action -Name 'Disable AD Account' -ActiveDirectory AccountDisable |
68 | Action -Name 'Hide account in GAL' -ActiveDirectory AccountHideInGAL |
69 | Action -Name 'Remove all security groups' -ActiveDirectory AccountRemoveGroupsSecurity |
70 | Action -Name 'Rename Account' -ActiveDirectory AccountRename -Value @{ Action = 'AddText'; Where = 'After'; Text = ' (offboarded)'; }
71 | }
72 | ```
73 |
74 | ### Sample onboarding
75 |
76 | 
77 |
78 | ```powershell
79 | Clear-Host
80 | Import-Module PSAutomator -Force #-Verbose
81 | Import-Module PSSharedGoods -Force
82 | Service -Name 'Active Directory Enable Users in OU' {
83 | Trigger -Name 'Find Offboarded Users' -User OrganizationalUnit -Value 'OU=Users-Offboarded,OU=Production,DC=ad,DC=evotec,DC=xyz' |
84 | Ignore |
85 | Action -Name 'Enable Offboarded Users' -ActiveDirectory AccountEnable |
86 | Action -Name 'Add to group GDS-TestGroup5' -ActiveDirectory AccountAddGroupsSpecific -Value 'GDS-TestGroup5' |
87 | Action -Name 'Add to group GDS-TestGroup4' -ActiveDirectory AccountAddGroupsSpecific -Value 'GDS-TestGroup4' |
88 | Action -Name 'Remove Offboarded Tag' -ActiveDirectory AccountRename -Value @{ Action = 'RemoveText'; Fields = 'DisplayName', 'Name' ; Text = ' (offboarded)'; }
89 | }
90 | ```
91 |
92 | ## DO NOT USE IN **PRODUCTION** YET - UNLESS YOU LIKE FIRES!
--------------------------------------------------------------------------------