Menu

Virtual Geek

Tales from real IT system administrators world and non-production environment

Creating an internal PowerShell module repository

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 = 'kunaludapi@gmail.com'
	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

Microsoft Powershell repository new-item itemtype directory path new-smbshare fullaccess everyone description path configure local remote powershell repo module scopename.png

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

Powershell get-NetIPaddress where-object get-repository powershellgallary publishlocation installationpolicy sourcelocation setup configure powershell internal repository powershellget.png

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.

microsoft windows powershell module psm1 new-item -itemtype directory function get-ciminstance -classname win32_operatingsystem select-object import-module local psrepository psgallary fileshare cmdlet.png

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.

microsoft windows Powershell automation location module manifest module functionstoexport new-modulemanifest find-module repository psd1 psm1 metadata module data file rootmodule parameters.png

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.

Microsoft Powershell collobration tool psrepository local remote net.servicepointmanager securityprotocol get-childitem find-module net.securityprotocoltype tls12 nupkg cim operting system psgallery remote repo.png

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.

Microsoft Windows Powershell get-childitem remotepath publishlocation sourcelocation installationpolicy trusted register-PSrepository get-psrepository install-module -scope currentuser psgallery.png

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

Go Back

Comment

Blog Search

Page Views

4127819

Follow me on Blogarama