2
\$\begingroup\$

My goal for this script was to:

  • Create new folder
  • Create AD group FS-TESTSHARE-R
  • Create AD group FS-TESTSHARE-RW
  • Apply both groups to the new share folder
  • Set full read permissions to FS-TESTSHARE-R
  • Set full read/Rights permissions to FS-TESTSHARE-RW
  • Set full access permissions for local machine admins and domain admins

I've had a ton of help here and I really appreciate it. I've made some recommended changes based off Matt's answer here. So far I've decided to use read-host question and answer structure, but might eventually (after I've had some more practice) create parameters instead. I've also added some validation write-host statements to make sure my user can check their own writing. I've also done a lot of syntax cleanup and general structure change.

BTW, this script has come a long ways. THIS is what I started with... haha

Let me know what you think of this so far! Any other suggestions?

# File share server name
$Server = Read-Host -prompt "Verify Server Server Name (ie ECCOFS01)" 
If ([string]::IsNullOrWhiteSpace($Server)) { 
    Write-Host "You entered $Server which is an incorrect value: This Script is now Exiting. `r`n" -Foreground "White" -Background "Red"
    Exit
   }
else {
    Write-Host "You Entered $Server `r`n" -Foreground "Black" -Background "Yellow"
   }

    # Parent folder setup
$Parent = Read-Host -prompt "Enter full parent path that will contain the new folder (ie. \Groups\ECCO IT). Please use correct spelling and capitalization (ie. Parent Folder Name). Do not use local drive letters." 
If ([string]::IsNullOrWhiteSpace($Parent) -or ($Parent -like '*:*')) { 
    Write-Host "You entered $Parent which is an incorrect value: This Script is now Exiting. `r`n" -Foreground "White" -Background "Red"
     Exit
   }
else {
    Write-Host "You Entered $Parent `r`n" -Foreground "Black" -Background "Yellow"
   }

    # Set additional variables 
    # $Parent removes any extra backslashes if the user adds one in the front of the answer to $Parent
$Parent = $Parent -replace '^\\',''
$ServerParentShare = "\\"+[IO.Path]::Combine($Server,$Parent)

    # New Folder Name
$Name = Read-Host -prompt "Enter New Folder Name. Please use correct spelling and capitalization (ie. New Test Folder)" 
If ([string]::IsNullOrWhiteSpace($Name)) { 
    Write-Host "You entered $Name which is an incorrect value: This Script is now Exiting. `r`n" -Foreground "White" -Background "Red"
    Exit
   }
else {
    Write-Host "You Entered $Name. `r`n" -Foreground "Black" -Background "Yellow"
   }

$Path = [IO.Path]::Combine($ServerParentShare,$Name)
    Write-Host "New Folder Path = $Path `r`n" -Foreground "Black" -Background "Yellow"

    # Choose Parent OU  
$Country = Read-Host -prompt "Enter the location where the AD Group needs to be added (i.e. Global, Americas, Europe, Asia Pacific)" 
If ([string]::IsNullOrWhiteSpace($Country)) { 
    Write-Host "You entered $Country which is an incorrect value: This Script is now Exiting. `r`n" -Foreground "White" -Background "Red"
    Exit
   }
else {
    Write-Host "---------------------VERIFY ENTRY---------------------" -Foreground "Black" -Background "Yellow"
    Write-Host "OU = $Country, New share location = $Path `r`n" -Foreground "Black" -Background "Yellow"
   }



    # Option to continue or cancel the script
$Continue = Read-Host -prompt "Does this look correct? Y or N?"
If (($Continue -eq "N") -or ($Continue -eq "No")) { 
    Write-Host "Please Start over. This Script is now Exiting. `r`n" -Foreground "White" -Background "Red"
    Exit
   }
else {
    Write-Host "Make sure to verify all folders and and AD Groups once complete. `r`n" -Foreground "Yellow" -Background "Black"
   }


    #Ensure ActiveDirectory module is imported
Import-Module ActiveDirectory

    #Set additional values based off of answers to the previous questions. This allows the correct formatting to be used.
$FileShareFull = $Server -replace '\s'
$NameFull = $NAME -replace '[\s_\\]+'
$ADNameRO = "FS-$FileShareFull-$NameFull-RO".toupper()
$ADNameRW = "FS-$FileShareFull-$NameFull-RW".toupper()
$ADGroupPath = $Path.toupper()

    # Create Security Groups =
    # Creates the parameters for the new groups
    # Capitalizes and removes spaces from the answer to $Name
    # Adds a description to each AD Group
    # Creates the Security Groups in the appropriate Active Directory OU based off of the answser to $Country
$GroupParams1= @{
    'Name' = $ADNameRW
    'SamAccountName' = $ADNameRW
    'GroupCategory' = "Security"
    'GroupScope' = "Global"
    'DisplayName' = "$NAME Read-Write Access"
    'Path' = "OU=$Country,OU=FILE SHARE GROUPS,OU=Security Groups,DC=esg,DC=intl"
    'Description' = "Members of this group have read-write access to $ADGroupPath"
}

New-ADGroup @GroupParams1

$GroupParams2= @{
    'Name' = $ADNameRO
    'SamAccountName' = $ADNameRO
    'GroupCategory' = "Security"
    'GroupScope' = "Global"
    'DisplayName' = "$NAME Read-Write Access"
    'Path' = "OU=$Country,OU=FILE SHARE GROUPS,OU=Security Groups,DC=esg,DC=intl"
    'Description' = "Members of this group have read access to $ADGroupPath"
}

New-ADGroup @GroupParams2

    # Create New Share Folder
New-Item -Path $Path -ItemType Directory | Out-Null

    # Create initial ACE
    # Create the initial Object
    # Set domain - This could also be changed to prompt for domain if we decide it is needed
    # Define local Administrators group by Well Known SID
    # Set additional ACEs for the new AD File Share Groups
    # Set ACLs on the new folder
function New-Ace {
  [CmdletBinding()]
  Param(
    [Parameter(Mandatory=$true, Position=0)]
    [Security.Principal.NTAccount]$Account,
    [Parameter(Mandatory=$false, Position=1)]
    [Security.AccessControl.FileSystemRights]$Permissions = 'ReadAndExecute',
    [Parameter(Mandatory=$false, Position=2)]
    [Security.AccessControl.InheritanceFlags]$InheritanceFlags = 'ContainerInherit,ObjectInherit',
    [Parameter(Mandatory=$false, Position=3)]
    [Security.AccessControl.PropagationFlags]$PropagationFlags = 'NoPropagateInherit',
    [Parameter(Mandatory=$false, Position=4)]
    [Security.AccessControl.AccessControlType]$Type = 'Allow'
  )

  New-Object Security.AccessControl.FileSystemAccessRule(
    $Account, $Permissions, $InheritanceFlags, $PropagationFlags, $Type
  )
}

$domain = 'ESG.INTL'
$administrators = ([wmi]"Win32_Sid.Sid='S-1-5-32-544'").AccountName
$ADDomainUsers = "$domain\Domain Users"

$acl = Get-Acl $path

$administrators, "$domain\Domain Admins" | ForEach-Object {
  $acl.AddAccessRule((New-Ace $_ 'FullControl'))
}
$acl.AddAccessRule((New-Ace $ADNameRW 'Modify'))
$acl.AddAccessRule((New-Ace $ADNameRO 'ReadAndExecute'))
$acl.AddAccessRule((New-Ace $ADDomainUsers 'ReadAndExecute'))

$acl.SetAccessRuleProtection($True, $False)

Set-Acl $path $acl
\$\endgroup\$
1
\$\begingroup\$

How is this script called? It looks like a great candidate for a cmdlet.

Parameters

Validating

Because it exits when a value is incorrect (instead of looping until data is valid) you could use Parameters with validation scripts. For example:

Param (
   [ValidateScript({![String]::IsNullOrWhiteSpace($_)})]
   [String]$Server
)

Help Messages

There is also the option to add the help message, but the behavior is quite different:

Param (
   [Parameter(Mandatory=$true,HelpMessage="Enter a Server Name (ie ECCOFS01).")]
   [ValidateScript({![String]::IsNullOrWhiteSpace($_)})]
   [String]$Server
)

Results in:

PS D:\> .\Create-Share.ps1
cmdlet test.ps1 at command pipeline position 1
Supply values for the following parameters:
(Type !? for Help.)
Server: !?
Enter a Server Name (ie ECCOFS01).
Server:

Continue Prompt

Being a cmdlet, you can now use built in confirmations as well. For example:

[CmdletBinding(SupportsShouldProcess=$true,ConfirmImpact="High")]
...
If (!$PSCmdlet.ShouldProcess("$Path","Creating share")) {
   Write-Host "Please Start over. This Script is now Exiting." -Foreground "White" -Background "Red"
   Return
}
...

Before the prompt, it would be good to advise the full set of information that will be used (including the AD groups to be created).


Splats

Your splats are fine, but I personally don't like declaring variables I only use once (and on the very next line). This is a simple alternative which also uses splatting:

@{
   Name = $ADNameRW
   SamAccountName = $ADNameRW
   GroupCategory = "Security"
   GroupScope = "Global"
   DisplayName = "$NAME Read-Write Access"
   Path = "OU=$Country,OU=FILE SHARE GROUPS,OU=Security Groups,DC=esg,DC=intl"
   Description = "Members of this group have read-write access to $($Path.toupper())"
} | % { New-ADGroup @_ }

And the rest I would leave exactly as it is.

Nice work!

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Thanks! I've also been playing around with the idea of using a text file with all of the variables for multiple share folder creation. \$\endgroup\$ – Shane Johnson Jun 1 '16 at 22:19
  • \$\begingroup\$ I see your point on the splats as well. It does save a little bit of repetition and is quite a bit cleaner! I'm still really new to this and l'm trying to understand setting parameters. To use it in the way you are recommending would I just replace the "If" "else" section? \$\endgroup\$ – Shane Johnson Jun 2 '16 at 15:11
  • \$\begingroup\$ Yes, use the $Server, $Parent,$Name and $Country as parameters. It looks like everything else is derived from those inputs. \$\endgroup\$ – xXhRQ8sD2L7Z Jun 2 '16 at 19:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.