NexusManagement.psm1

<#
.SYNOPSIS
Gets a list of the available Nexus repositories.
 
.DESCRIPTION
Gets a list of the available Nexus repositories.
 
.EXAMPLE
$creds = Get-Credential
Get-NexusRepository -Uri 'http://localhost:8081' -Credential $creds
 
Returns a list of the repositories available ont he Nexus repository server at http://localhost:8081 using the
credentials $creds.
 
.NOTES
The basic code of this function was borrowed from the chocolatey-nexus-repo package
(https://chocolatey.org/packages/chocolatey-nexus-repo). Credit to Stephen Valdinger and Paul Broadwith.
 
For a list of the repository API calls see
https://github.com/sonatype/nexus-public/blob/master/plugins/nexus-script-plugin/src/main/java/org/sonatype/nexus/script/plugin/RepositoryApi.java
 
Nexus 3 REST and API reference https://help.sonatype.com/repomanager3/rest-and-integration-api
 
.LINK
https://github.com/pauby/NexusManagement/blob/master/docs/en-US/Get-NexusRepository.md
#>


function Get-NexusRepository {
    [CmdletBinding()]
    Param (
        # Uri of the Nexus repository server (for example https://nexus.myorg.local).
        [Parameter(Mandatory)]
        [String]
        $Uri,

        # User credentials that have permission to request a list of repositories.
        [Parameter(Mandatory)]
        [PSCredential]
        $Credential
    )

    $params = @{
        Uri     = "{0}/service/rest/v1/repositories" -f $Uri.Trim('\/')
        Method  = 'Get'
        Headers = New-NexusApiHeader -Credential $Credential
    }
    Invoke-RestMethod @params
}
<#
.SYNOPSIS
Invokes a Nexus script.
 
.DESCRIPTION
Invokes a Nexus script.
 
.EXAMPLE
$creds = Get-Credential
$script = @"
import org.sonatype.nexus.repository.Repository;
repository.createNugetHosted("myRepo","default");
"@
Invoke-NexusScript -Uri 'http://localhost:8081' -Credential $creds -Script $script
 
Invokes the contents of $script on the Nexus repository server 'http://localhost:8081' using the credential $creds.
.NOTES
The basic code of this function was borrowed from the chocolatey-nexus-repo package
(https://chocolatey.org/packages/chocolatey-nexus-repo). Credit to Stephen Valdinger and Paul Broadwith.
 
For a list of the repository API calls see
https://github.com/sonatype/nexus-public/blob/master/plugins/nexus-script-plugin/src/main/java/org/sonatype/nexus/script/plugin/RepositoryApi.java
 
Nexus 3 REST and API reference https://help.sonatype.com/repomanager3/rest-and-integration-api
 
.LINK
https://github.com/pauby/NexusManagement/blob/master/docs/en-US/Invoke-NexusScript.md
#>


function Invoke-NexusScript {
    [CmdletBinding()]
    Param (
        # Uri of the Nexus repository server (for example https://nexus.myorg.local).
        [Parameter(Mandatory)]
        [String]
        $Uri,

        # User credentials that have permission to execute the script.
        [Parameter(Mandatory)]
        [PSCredential]
        $Credential,

        # The Groovy script to execute.
        [Parameter(Mandatory)]
        [String]
        $Script
    )

    $header = New-NexusApiHeader -Credential $Credential

    # create a random name for the script so that it does not conflict with any other script stored in Nexus
    $scriptName = [GUID]::NewGuid().ToString()
    $body = @{
        name    = $scriptName
        type    = 'groovy'
        content = $Script
    }

    # TODO Check for trailing slash in $Uri
    $baseApiUri = "$Uri/service/rest/v1/script"

    # Store the Script
    $params = @{
        Uri         = $baseApiUri
        ContentType = 'application/json'
        Body        = $($body | ConvertTo-Json)
        Header      = $header
        Method      = 'Post'
    }
    Invoke-RestMethod @params

    # Run the script
    $params = @{
        Uri         = "{0}/{1}/run" -f $baseApiUri, $scriptName
        ContentType = 'text/plain'
        Header      = $header
        Method      = 'Post'
    }
    $result = Invoke-RestMethod @params

    # Delete the Script
    $params = @{
        Uri         = "{0}/{1}" -f $baseApiUri, $scriptName
        Header      = $header
        Method      = 'Delete'
    }
    Invoke-RestMethod @params

    $result
}
<#
.SYNOPSIS
Creates the web request header to access the Nexus Api.
 
.DESCRIPTION
Creates the web request header to access the Nexus Api.
 
.EXAMPLE
$creds = Get-Credential
New-Nexus-ApiHeader -Credential $creds
 
Creates a new header with the credential $creds to access the Nexus Api.
 
.NOTES
The basic code of this function was borrowed from the chocolatey-nexus-repo package
(https://chocolatey.org/packages/chocolatey-nexus-repo). Credit to Stephen Valdinger and Paul Broadwith.
 
.LINK
https://github.com/pauby/NexusManagement/blob/master/docs/en-US/New-NexusApiHeader.md
#>


function New-NexusApiHeader {
    [CmdletBinding()]
    Param (
        # Credentials used to access Nexus.
        [Parameter(Mandatory)]
        [PSCredential]
        $Credential
    )

    # Create the Api header
    $credPair = ("{0}:{1}" -f $Credential.Username, $Credential.GetNetworkCredential().Password)
    $encodedCreds = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($credPair))
    return @{
        Authorization = "Basic $encodedCreds"
    }
}
<#
.SYNOPSIS
Creates a new Nexus Nuget Hosted repository.
 
.DESCRIPTION
Creates a new Nexus Nuget Hosted repository.
 
.EXAMPLE
$creds = Get-Credential
Get-NexusNugetHostedRepository -Uri 'http://localhost:8081' -Credential $creds ` -Name 'myRepo'
    -NoStrictContentTypeValidation
 
Creates a new Nuget hosted Nexus repository called myRepo on the default blob store with no strict content type
validation and with a deployment policy of allow at the Nexus repository server 'http://localhost:8081# using the
credentials $creds
 
.NOTES
The basic code of this function was borrowed from the chocolatey-nexus-repo package
(https://chocolatey.org/packages/chocolatey-nexus-repo). Credit to Stephen Valdinger and Paul Broadwith.
 
For a list of the repository API calls see
https://github.com/sonatype/nexus-public/blob/master/plugins/nexus-script-plugin/src/main/java/org/sonatype/nexus/script/plugin/RepositoryApi.java
 
For the valid WritePolicy see
https://github.com/sonatype/nexus-public/blob/master/components/nexus-repository/src/main/java/org/sonatype/nexus/repository/storage/WritePolicy.java
 
Nexus 3 REST and API reference https://help.sonatype.com/repomanager3/rest-and-integration-api
 
.LINK
https://github.com/pauby/NexusManagement/blob/master/docs/en-US/New-NexusNugetHostedRepository.md
#>


function New-NexusNugetHostedRepository {
    [CmdletBinding()]
    Param (
        # Uri of the Nexus repository server (for example https://nexus.myorg.local).
        [Parameter(Mandatory)]
        [String]
        $Uri,

        # User credentials that have permission to request a list of repositories.
        [Parameter(Mandatory)]
        [PSCredential]
        $Credential,

        # Name of the repository to create.
        [Parameter(Mandatory)]
        [String]
        $Name,

        # Blob store name to use to store the repository. By default is 'default'.
        [String]
        $BlobStoreName = 'default',

        # Turns off strict content type validation (turned on by default)
        [Switch]
        $NoStrictContentTypeValidation,

        # Specifies the Deployment Policy for the repository
        [ValidateSet('Allow Redeploy', 'Disable Redeploy', 'Read-only')]
        [String]
        $DeploymentPolicy = 'Allow Redeploy'
    )

    # translate our nice deployment policy types into Nexus WritePolicy (see
    # https://github.com/sonatype/nexus-public/blob/master/components/nexus-repository/src/main/java/org/sonatype/nexus/repository/storage/WritePolicy.java)
    # Make sure the script has 'import org.sonatype.nexus.repository.storage.WritePolicy;' otherwise you will need to
    # specify the full 'org.sonatype.nexus.repository.storage.WritePolicy' namespace
    switch ($DeploymentPolicy) {
        'Allow Redeploy' {
            $writePolicy = 'WritePolicy.ALLOW'
            break
        }
        'Read-only' {
            $writePolicy = 'WritePolicy.DENY'
            break
        }
        'Disable Redeploy' {
            $writePolicy = 'WritePolicy.ALLOW_ONCE'
            break
        }
        default {
            # we should never get here
            throw "Something has gone wrong. We hit the default switch statement for Deployment Policy whose value is '$DeploymentPolicy'"
        }
    } # /switch

    # by default strict content type validation is $true - set it to false if the switch NoStrictContentTypeValidation
    # is passed
    # The Nexus API needs a boolean to be lower case
    $strictContentTypeValidation = (-not $NoStrictContentTypeValidation.IsPresent).ToString().ToLower()

    $params = @{
        Uri        = $Uri
        Credential = $Credential
        Script     = @"
import org.sonatype.nexus.repository.Repository;
import org.sonatype.nexus.repository.storage.WritePolicy;
repository.createNugetHosted("$Name","$BlobStoreName", $strictContentTypeValidation, $writePolicy);
"@

    }

    Invoke-NexusScript @params
}

<#
.SYNOPSIS
Creates a new Nexus Nuget Hosted repository.
 
.DESCRIPTION
Creates a new Nexus Nuget Hosted repository.
 
.EXAMPLE
$creds = Get-Credential
Get-NexusNugetHostedRepository -Uri 'http://localhost:8081' -Credential $creds ` -Name 'myRepo'
    -NoStrictContentTypeValidation
 
Creates a new Nuget hosted Nexus repository called myRepo on the default blob store with no strict content type
validation and with a deployment policy of allow at the Nexus repository server 'http://localhost:8081# using the
credentials $creds
 
.NOTES
The basic code of this function was borrowed from the chocolatey-nexus-repo package
(https://chocolatey.org/packages/chocolatey-nexus-repo). Credit to Stephen Valdinger and Paul Broadwith.
 
For a list of the repository API calls see
https://github.com/sonatype/nexus-public/blob/master/plugins/nexus-script-plugin/src/main/java/org/sonatype/nexus/script/plugin/RepositoryApi.java
 
For the valid WritePolicy see
https://github.com/sonatype/nexus-public/blob/master/components/nexus-repository/src/main/java/org/sonatype/nexus/repository/storage/WritePolicy.java
 
Nexus 3 REST and API reference https://help.sonatype.com/repomanager3/rest-and-integration-api
 
.LINK
https://github.com/pauby/NexusManagement/blob/master/docs/en-US/New-NexusNugetHostedRepository.md
#>


function Remove-NexusRepository {
    [CmdletBinding()]
    Param (
        # Uri of the Nexus repository server (for example https://nexus.myorg.local).
        [Parameter(Mandatory)]
        [String]
        $Uri,

        # User credentials that have permission to request a list of repositories.
        [Parameter(Mandatory)]
        [PSCredential]
        $Credential,

        # Name of the repository to remove.
        [Parameter(Mandatory)]
        [String]
        $Name
    )

    $params = @{
        Uri        = $Uri
        Credential = $Credential
        Script     = @"
import org.sonatype.nexus.repository.Repository;
repository.getRepositoryManager().delete("$Name");
"@

    }

    Invoke-NexusScript @params
}

<#
.SYNOPSIS
    Gets the Nexus Api Key for the user.
 
.DESCRIPTION
    Gets the Nexus Api Key for the user.
 
.EXAMPLE
    $creds = Get-Credential
    Remove-NexusRepository -Uri 'http://localhost:8081' -Credential $creds ` -Name 'myRepo'
 
    Removes a repository called 'myRepo' from the Nexus repository server 'http://localhost:8081# using the credentials
    $creds
 
.NOTES
    The basic code of this function was borrowed from Stephen Valdinger (@steviecoaster).
 
    For a list of the repository API calls see
    https://github.com/sonatype/nexus-public/blob/master/plugins/nexus-script-plugin/src/main/java/org/sonatype/nexus/script/plugin/RepositoryApi.java
 
    The code for the groovy script to delete the repository was borrowed from ansible-nexus3:
    https://github.com/savoirfairelinux/ansible-nexus3-oss/blob/master/files/groovy/delete_repo.groovy
 
    Nexus 3 REST and API reference https://help.sonatype.com/repomanager3/rest-and-integration-api
 
.LINK
    https://github.com/pauby/NexusManagement/blob/master/docs/en-US/Remove-NexusRepository.md
#>


function Get-NexusApiKey {
    [CmdletBinding()]
    Param (
        # Uri of the Nexus repository server (for example https://nexus.myorg.local).
        [Parameter(Mandatory)]
        [String]
        $Uri,

        # User credentials that have permission to request a list of repositories.
        [Parameter(Mandatory)]
        [PSCredential]
        $Credential,

        # Name of the repository to remove.
        [Parameter(Mandatory)]
        [String]
        $Username
    )

    $params = @{
        Uri        = $Uri
        Credential = $Credential
        Script     = @"
import org.sonatype.nexus.security.authc.apikey.ApiKeyStore
import org.sonatype.nexus.security.realm.RealmManager
import org.apache.shiro.subject.SimplePrincipalCollection
 
def getOrCreateNuGetApiKey(String userName) {
    realmName = "NexusAuthenticatingRealm"
    apiKeyDomain = "NuGetApiKey"
    principal = new SimplePrincipalCollection(userName, realmName)
    keyStore = container.lookup(ApiKeyStore.class.getName())
    apiKey = keyStore.getApiKey(apiKeyDomain, principal)
    if (apiKey == null) {
        apiKey = keyStore.createApiKey(apiKeyDomain, principal)
    }
    return apiKey.toString()
}
 
getOrCreateNuGetApiKey("$Username")
"@

    }

    Invoke-NexusScript @params
}

<#
.SYNOPSIS
    Remove an asset from a Nexus repository.
 
.DESCRIPTION
    Remove an asset from a Nexus repository.
 
.EXAMPLE
    $creds = Get-Credential
    Remove-NexusRepositoryAsset -Uri 'http://localhost:8081' -Credential $creds -Id 'abc123'
 
    Removes the asset with Id 'abc123' from the Nexus repository server 'http://localhost:8081' using the credentials
    $creds
 
.NOTES
    For the specifics about the API this function uses, see
    https://help.sonatype.com/repomanager3/rest-and-integration-api/assets-api#AssetsAPI-DeleteAsset
 
    Nexus 3 REST and API reference https://help.sonatype.com/repomanager3/rest-and-integration-api
 
.LINK
    https://github.com/pauby/NexusManagement/blob/master/docs/en-US/Get-NexusRepositoryAsset.md
#>


function Remove-NexusRepositoryAsset {
    [CmdletBinding()]
    Param (
        # Uri of the Nexus repository server (for example https://nexus.myorg.local).
        [Parameter(Mandatory)]
        [String]
        $Uri,

        # User credentials that have permission to request a list of repositories.
        [Parameter(Mandatory)]
        [PSCredential]
        $Credential,

        # Id of the asset to return.
        [Parameter(Mandatory)]
        [ValidateNotNullOrEmpty()]
        [String]
        $Id
    )

    $apiUri = 'service/rest/v1/assets'
    if ($Uri.EndsWith('/')) {
        $Uri += $apiUri
    }
    else {
        $Uri += "/$apiUri"
    }

    $Uri += "/$Id"

    $params = @{
        Uri        = $Uri
        Header = New-NexusApiHeader -Credential $Credential
        Method      = 'Delete'
    }

    Invoke-RestMethod @params
}


<#
.SYNOPSIS
  Gets assets from a Nexus repository.
 
.DESCRIPTION
  Gets assets from the Nexus repository.
 
  If a repository name is provided then all assets from that repository are returned.
 
  If an asset id is provided then that asset is returned.
 
.EXAMPLE
    $creds = Get-Credential
    Get-NexusRepositoryAsset -Uri 'http://localhost:8081' -Credential $creds -RepositoryName 'myRepo'
 
    Gets all of the assets from the repository named 'myRepo' from the Nexus repository server 'http://localhost:8081'
    using the credentials $creds
 
.NOTES
  For the specifics about the API this function uses, see
  https://help.sonatype.com/repomanager3/rest-and-integration-api/assets-api and
  https://help.sonatype.com/repomanager3/rest-and-integration-api/pagination for details of pagination.
 
  Nexus 3 REST and API reference https://help.sonatype.com/repomanager3/rest-and-integration-api
 
.LINK
  https://github.com/pauby/NexusManagement/blob/master/docs/en-US/Get-NexusRepositoryAsset.md
#>


<#
.SYNOPSIS
  Gets assets from a Nexus repository.
 
.DESCRIPTION
  Gets assets from the Nexus repository.
 
  If a repository name is provided then all assets from that repository are returned.
 
  If an asset id is provided then that asset is returned.
 
.EXAMPLE
    $creds = Get-Credential
    Get-NexusRepositoryAsset -Uri 'http://localhost:8081' -Credential $creds -RepositoryName 'myRepo'
 
    Gets all of the assets from the repository named 'myRepo' from the Nexus repository server 'http://localhost:8081'
    using the credentials $creds
 
.NOTES
  For the specifics about the API this function uses, see
  https://help.sonatype.com/repomanager3/rest-and-integration-api/assets-api and
  https://help.sonatype.com/repomanager3/rest-and-integration-api/pagination for details of pagination.
 
  Nexus 3 REST and API reference https://help.sonatype.com/repomanager3/rest-and-integration-api
 
.LINK
  https://github.com/pauby/NexusManagement/blob/master/docs/en-US/Get-NexusRepositoryAsset.md
#>


function Get-NexusRepositoryAsset {
    [CmdletBinding(DefaultParameterSetName = 'Repository')]
    Param (
        # Uri of the Nexus repository server (for example https://nexus.myorg.local).
        [Parameter(Mandatory)]
        [String]
        $Uri,

        # User credentials that have permission to request a list of repositories.
        [Parameter(Mandatory)]
        [PSCredential]
        $Credential,

        # Name of the repository to return all assets from.
        [Parameter(Mandatory, ParameterSetName = 'Repository')]
        [ValidateNotNullOrEmpty()]
        [String]
        $RepositoryName,

        # Id of the asset to return.
        [Parameter(Mandatory, ParameterSetName = 'Id')]
        [ValidateNotNullOrEmpty()]
        [String]
        $Id
    )

    $apiUri = 'service/rest/v1/assets'
    if ($Uri.EndsWith('/')) {
        $Uri += $apiUri
    }
    else {
        $Uri += "/$apiUri"
    }

    if ($PSBoundParameters.ContainsKey('RepositoryName')) {
        $Uri += "?repository=$RepositoryName"

        $params = @{
            Uri    = $Uri
            Header = New-NexusApiHeader -Credential $Credential
            Method = 'Get'
        }

        $items = @()
        do {
            $result = Invoke-RestMethod @params
            $items += $result.items
            if ($result.continuationToken) {
                $params.Uri = "{0}&continuationToken={1}" -f $Uri, $result.continuationToken
            }
        } while ($result.continuationToken)

        $items

    }
    elseif ($PSBoundParameters.ContainsKey('Id')) {
        $Uri += "/$Id"

        $params = @{
            Uri    = $Uri
            Header = New-NexusApiHeader -Credential $Credential
            Method = 'Get'
        }

        Invoke-RestMethod @params
    }
    else {
        # we should never actually get here
        throw "We have reached the else clause in Get-NexusRepositoryAsset which should not be possible!"
    }
}