I was at client location and online Microsoft PSGallery was blocked as per company security policy, They wanted to only allow to use local respository which will only have tested and verified PowerShell modules. For this we suggested to configure a solution local PowerShell repository. In the Microsoft Powershell there is a option to configure local central PSGallery for better collaboration and security. Once the automation team writes new PS modules or download/review the modules from online PSGallery and keep on local repo, Basically plan was Powershell designer will write code and host on local repository for Ops team/Administrators use.
Check other articles
Get-PSRepository WARNING Unable to find module repositories
Invoke-WebRequest : The underlying connection was closed: An unexpected error occurred on a send
How to sign PowerShell ps1 scripts
Download this script here or from github.com/kunaludapi.
PHASE 1
1 2 3 4 5 6 7 8 9 10 11 12 |
#Create PowerShell repository folder on server $localPath = 'C:\OnPremRepo' New-Item -Path $localPath -ItemType Directory #Share Powershell repository folder with everyone $smbShareParam = @{ Name = 'OnPremRepo' Path = $localPath Description = 'In House PS Repository' FullAccess = 'Everyone' } New-SmbShare @smbShareParam |
PHASE 2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
#Create PowerShell repository and configure it as trusted repo Get-NetIPAddress | Where-Object {$_.AddressFamily -eq 'IPv4'} | Select-Object IPAddress #Check which PSRepositories are configured Get-PSRepository $remotePath = '\\192.168.34.16\OnPremRepo' $localPsRepoParam = @{ Name = 'OnPremRepo' SourceLocation = $remotePath PublishLocation = $remotePath InstallationPolicy = 'Trusted' } Register-PSRepository @localPsRepoParam #Check again which PSRepositories are configured Get-PSRepository #Create a OSInfo module folder New-Item C:\OSInfo -ItemType Directory #Create a very simple module $moduleCode = @" Function Get-OsInfo { Get-CimInstance -ClassName win32_OperatingSystem | Select CSName, Caption, Version, OSArchitecture } Set-Alias OSInfo Get-OsInfo "@ $moduleCode | Out-File C:\OSInfo\OSInfo.psm1 #Load and test the OSInfo module Import-Module -Name C:\OSInfo #Run module cmdlets OSInfo #Create a powershell module manifest for OSInfo Module $moduleMetaDataParam = @{ Path = 'C:\OSInfo\OSInfo.psd1' RootModule = 'OSInfo.psm1' Description = 'CIM operating system information module' Author = '[email protected]' FunctionsToExport = 'Get-OsInfo' CompanyName = 'vcloud-lab.com' } New-ModuleManifest @moduleMetaDataParam #Check whats on OnPremRepo powershell repository Find-Module -Repository OnPremRepo #Do web request over TLS1.2 and Publish Module on local PSRepository [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 Publish-Module -Path C:\OSInfo -Repository OnPremRepo -Force #Look at what is in the C:\OnPremRepo folder Get-ChildItem -Path C:\OnPremRepo #View the result of OnPremRepo Find-Module -Repository OnPremRepo #Install and test module from local OnPremRepo Install-Module -Name OSInfo -Repository OnPremRepo -Scope CurrentUser OSInfo |
Above script is split into 2 phases, Both first and second phase can run on psserver, where it will be hosted modules centrally. Instead of below commands you can do the same on gui by creating a shared folder with everyone providing full controls (You can assign strict privileges to only required users, for simple demo purpose I am using everyone). After running first phase script it created a new directory and assigning permissions verify, I made sure share path is accessible over network.
Phase 1: Script lines 01 to 03: Create a new folder C:\OnPremRepo
Phase 1: Script lines 06 to 12: Share folder C:\OnPremRepo and provided full control access to everyone
I am running all the commands from psserver.
Phase 2: Script lines 01: On the psserver I will just grab the IPAddress, This is IP of share path and I will keep using it.
Phase 2: Script lines 04: Check the current list of registered PSrepositories, by default it will list online PSGallery with SourceLocation https://powershellgallery.com/api/v2.
Phase 2: Script lines 06 to 13: Register newly created local PSRepository.
Phase 2: Script lines 16: Reverify new local psrepository is added successful by fetching list
If you are planning to run below commands for other team members system, You will need to execute command numbers from Phase 2: 1 to 13, I am still on psserver and using it to execute commands.
Phase 2: Script Line 19: I will create new PowerShell module for testing, for this new folder is required, module name must equals folder name.
Phase 2: Script Line 22 to 29: I am creating very basic small module function and saving text contents to module folder with same file name, and extension is .psm1
Phase 2: Script Line 32: Import the newly created module.
Phase 2: Script Line 35: Test Imported module by running cmdlet, All looks good.
Phase 2: Script Line 38 to 46: Generate powershell module manifest, A module manifest is a PowerShell data file ( . psd1 ) that describes the contents of a module and determines how a module is processed.
Phase 2: Script Line 49: Modules are created but PSRepository is empty, verify the same using finding on local repo, it is empty as we haven't published any modules yet.
Phase 2: Script Line 52 to 53: While publishing module on local repository I faced few issues and I have written separate article to resolve Invoke-WebRequest : The underlying connection was closed: An unexpected error occurred on a send, Publishing file to local repo may take some time based on module folder size. New nupkg package is created.
Phase 2: Script Line 56: You will see new file package generated on local repo with version no, filename extension is .nupkg.
Phase 2: Script Line 59: Try finding module from local PSRepository, it will show the result now.
So far all the above commands where successful executed on PSserver and output was good, now I will test repo from another computer.
Get-ChildItem -Path \\SharePath\PSRepo: Check and verify if PSRepository share path is accessible over network
Phase 2: Script Line 6 to 13: Register the local repository on another computer.
Install-Module -Name ModuleName -Repository Localrepo -Scope CurrentUser : Test Installing the module to currently logged in users module folder, Additionally you can test cmdlets in the module, to verify all is fine.
Useful Articles
GUI - SETUP AND CONFIGURE POWERSHELL WEB ACCESS SERVER (GATEWAY)
USE POWERSHELL ON MOBILE - SETUP AND CONFIGURE POWERSHELL WEB ACCESS (PSWA)
Different ways to bypass Powershell execution policy :.ps1 cannot be loaded because running scripts is disabled
Powershell Trick : Execute or run any file as a script file
Set Powershell execution policy with Group Policy
Powershell execution policy setting is overridden by a policy defined at a more specific scope