Skip to main content
Skip table of contents

Configure Mend for GitHub Enterprise to resolve your private dependencies

Overview

In order to scan dependencies from private registries, Mend must be provided with credentials. These credentials must be added as encrypted secrets to the .whitesource file, either per-repository or in the shared global config if the secret scope is org-wide.

Use Case

Below is an example of applying private registry credentials in the hostRules block of a .whitesource file:

CODE
{
  "hostRules": [
    {
      "matchHost": "registry.npmjs.org",
      "hostType": "npm",
      "userName": "bot1",
      "encrypted": {
        "token": "3f832f2983yf89hsd98ahadsjfasdfjaslf............"
      }
    },
    {
      "matchHost": "https://custom.registry.company.com/maven/",
      "hostType": "maven",
      "userName": "bot1",
      "encrypted": {
        "password": "p278djfdsi9832jnfdshufwji2r389fdskj........."
      }
    }
  ]
}

Getting It Done

Mend for GitHub Enterprise supports private registries hosted on any platform that can be accessed with credentials (Nexus, GitHub, Artifactory, Azure Artifacts, GitLab, NPM).

In order to scan dependencies from private registries and authenticated repositories, Mend must be provided with credentials, such as an NPM token. These credentials must be added as encrypted secrets to the .whitesource file, either per-repository or in the shared global config, if the secret scope is org-wide.

Сreate the encrypted secrets. Each secret you encrypt must be scoped to a GitHub group or repository, and its use will be restricted to those within the app.

Note: Decryption is only available for 2048-bit gpg keys. Any other key size will result in an error.

  1. Use GPG to generate a PGP Key. Use the command gpg --full-generate-key and follow the prompts to generate a key. Please note that at this time we do not support using a passphrase for decryption, so it is best to generate the keys without a passphrase. Name and email are not important.

    1. Copy the key ID from the output or run gpg --list-secret-keys if you forgot to take a copy. This is your public key.

    2. Run gpg --armor --export-secret-keys YOUR_NEW_KEY_ID > ws-private-key.asc to generate an armored (text-based) private key file

    3. Run gpg --armor --export YOUR_NEW_KEY_ID > ws-public-key.asc to generate an armored (text-based) public key file

  2. Provide the private key to the Controller, Remediate, and Scanner with environmental variable (learn more about environmental variables in the Advanced Technical Information documentation). There are two options for how to do it, but only one option should be used.

    1. WS_HOST_RULES_PRIVATE_KEY - the value of the private key itself.

      1. Please note, that the private key should be formatted to work properly:

        1. Remove the beginning and end comments (as well as any extra lines).

        2. At the end of the key, there will be a buffer that looks like ==<some_text>. This needs to be removed.

        3. Remove all of the new lines in the key so it is all in one line (i.e. delete all \n characters).

    2. WS_HOST_RULES_PRIVATE_KEY_FILE_PATH - path to the file containing the private key. This file should be mapped to the running containers.

  3. Open wss-encryption/secret-encryption.html in your favorite editor.

  4. Find and replace the text "COPY_YOUR_PUBLIC_PGP_KEY_HERE" with your newly generated public key and save the file.
    const publicKeyString = `COPY_YOUR_PUBLIC_PGP_KEY_HERE`;

  5. Generate a secret. There are the following fields on the encryption page:

    1. Organization\Group - required, your GitHub group to which tokens secret be scoped.

    2. Repository - optional, your GitHub repository to which secret should be scoped.

    3. Raw value - required, confidential values/secrets such as tokens or passwords.

    4. Encrypted value - the result of the encryption to be used in the integration.

  6. After creating the secret, add the encrypted secret to the Private Registry Settings (hostRules) block of your .whitesource file.

index-enterprise.html

We use asymmetric public-key cryptography of the PGP methodology. There is a public key on the page we provided for encrypting secrets from passwords or tokens. This public key has a related private key secured by Mend.

The private key is used to decrypt secrets created with the public key. In this way, only the holder of the private key (Mend in this situation) can have access to the encrypted contents. Organization/Group, Repository, Raw Value - all information you provide on the encryption page is secured with this approach.

Automate Secret Encryption for Private Registries

You can encrypt secrets from the CLI, using the curl, echo, jq, gpg, grep and tr CLI programs.
Here is an example:

CODE
curl https://app.renovatebot.com/renovate.pgp --output renovate.pgp
echo -n '{"o":"your-organization", "r":"your-repository (optional)", "v":"your-secret-value"}' | jq . -c | gpg --encrypt -a --recipient-file renovate.pgp | grep -v '^----' | tr -d '\n'

The above script uses:

  • curl to download the Mend Renovate hosted app's public key

  • echo to echo a JSON object into jq

  • jq to validate the JSON and then compact it

  • gpg to encrypt the contents

  • grep and tr to extract the encrypted payload which we will use

The jq step is optional, you can leave it out if you wish. Its primary value is validating that the string you echo to gpg is valid JSON and compact.

Note: Encrypted secrets must have at least an org/group scope, and optionally a repository scope. This means that Renovate will check if a secret's scope matches the current repository before applying it, and warn/discard if there is a mismatch.

Encrypted secrets usually have a single organization. But you may encrypt a secret with more than one organization, for example, org1,org2. This way the secret can be used in both the org1 and org2 organizations.

For more information on how to use secrets for private packages, refer to the Private package support documentation.

Reference

Parameters

Private Registry Settings (hostRules)

Parameter

Type

Description

matchHost

String

Required. The URL of the private registry where the private dependencies are hosted. Here are a few examples:

hostType

String

Required. The type of private registry. Supported values:

  • npm (for both NPM and Yarn projects)

  • maven (for both Maven and Gradle projects)

  • pypi (for Pip and Pipenv)

  • go

  • nuget

  • ruby

  • sbt

Note: When using Renovate with a Ruby private registry, add a hostRules block with hostType=rubygems within the remediateSettings block.

userName

String

Optional. The value used when the private registry requires a username credential for resolution access to its private dependencies.

encrypted.password

String

Required. The value used when the private registry requires a password credential for resolution access to its private dependencies. The value first needs to be encrypted into a secret on this page section.

This encrypted secret will be applied as a credential to the set in the matchHost block and must be included inside the encrypted parameter:

CODE
      "encrypted": {
        "password": "3f832f2983yf89hsd98ahadsjfasdfjaslf............"
      }

encrypted.token

String

Required. The value used when the private registry requires a token credential for resolution access to its private dependencies. The value first needs to be encrypted into a secret on this page section.

This encrypted secret will be applied as a credential to the set in the matchHost block and must be included inside the encrypted parameter:

CODE
      "encrypted": {
        "token": "3f832f2983yf89hsd98ahadsjfasdfjaslf............"
      }

envVariablesMapping

Object

Use this parameter if you used environmental variables in the settings of your package manager to include username and password/token (e.g. for a specified package index). envVariablesMapping takes a value as an object with two literals: userName and password / token.
For example, if you have:

CODE
[[source]]
url = "https://${USER_PRIVATE_REPO}:{PASS_PRIVATE_REPO}:@pypi/PACKAGE_NAME/simple"
verify_ssl = true
name = "IndexName"

or

CODE
  {
    url 'https://private.jfrog.io/artifactory/dependencies'
    credentials {
      username System.getenv("USER_PRIVATE_REPO") ?: "${USER_PRIVATE_REPO}"
      password System.getenv("PASS_PRIVATE_REPO") ?: "${PASS_PRIVATE_REPO}"
    }
}

Then, set envVariablesMapping to:

CODE
"envVariablesMapping": {"userName": "USER_PRIVATE_REPO" ,"password":"PASS_PRIVATE_REPO"}

Below is an example of applying envVariablesMapping in the hostRules block of a .whitesource file:

CODE
{
  "hostRules": [
    {
      "matchHost": "https://custom.registry.company.com/maven/",
      "hostType": "maven",
      "userName": "bot1",
      "encrypted": {
        "token": "p278djfdsi9832jnfdshufwji2r389fdskj........."
      },
      "envVariablesMapping": {
        "userName": "GITHUB_ACTOR",
        "token": "GITHUB_TOKEN"
      }
    }
  ]
}

sourceName

String

Only for Pipenv private registries. Optional. Use this parameter if you don’t have a specified package index. In this case, Mend will create one for you based on other parameters of hostRules. The value of sourceName should be the index name used for your private dependencies.

For example, if you have packages with the following index:

CODE
[packages]
<package_name> = { version = "*", index = "IndexName" }

Then, set sourceName to:

CODE
"sourceName": "IndexName"

Mend for GitHub Enterprise private registry-supported languages

The following languages and their package managers are supported for scanning dependencies from private registries with Mend for GitHub Enterprise.

Language

Package Manager

Details

C#

NuGet

Configuration file(s): nuget.config

  • If the nuget.config preexists, it is appended with the hostRulesprovided.

  • If the nuget.config does not exist, it is temporarily created with the hostRules provided for scanning purposes.

Go

Modules

Configuration file(s): .netrc

  • If the .netrc preexists, it is appended with the hostRulesprovided.

  • If the .netrc does not exist, it is temporarily created with the hostRules provided for scanning purposes.

Specifications:

  • Only HTTPS is available for matchHost, HTTP is not supported.

  • If the private registry is hosted on GitHub, only token can be used in the encrypted parameter (password is not supported).

Java

Gradle

Configuration file(s): build.gradle, settings.gradle

  • If the build.gradle or settings.gradle preexists, it is appended with the hostRulesprovided.

  • If the build.gradle or settings.gradle does not exist, it is temporarily created with the hostRules provided for scanning purposes.

Specifications:

  • We also support the Kotlin format (KTS) of the Gradle configuration files.

  • The buildscript or pluginManagement blocks need to be at the beginning of the build.gradle or settings.gradle, respectively.

  • The matchHost parameter should contain the full path to the private registries, not just the domain.

  • Use the envVariablesMapping parameter if you used environmental variables in your Gradle settings to include the username and password/token.

Java

Maven

Configuration file(s): settings.xml

  • If the settings.xml preexists, it is appended with the hostRulesprovided.

  • If the settings.xml does not exist, it is temporarily created with the hostRules provided for scanning purposes.

JavaScript

NPM

Configuration file(s): .npmrc

  • If the .npmrc preexists, it is appended with the hostRulesprovided.

  • If the .npmrc does not exist, it is temporarily created with the hostRules provided for scanning purposes.

Specifications:

  • If .npmrc is missing and only one host is used in the project, it should be connected to the official public registry: http://npmjs.com. Otherwise, only private dependencies will be scanned and all public dependencies of this registry will be omitted.

  • If several hosts are used in the project, it is required that .npmrc file preexists in the project and contains information about these hosts.

JavaScript

Yarn

Configuration file(s): .npmrc (Yarn 1), .yarnrc (Yarn 2, 3)

  • If the .npmrc or .yarnrc preexists, it is appended with the hostRulesprovided.

  • If the .npmrc or .yarnrc does not exist, it is temporarily created with the hostRules provided for scanning purposes.

Specifications:

  • If .yarnrc is missing (or npmRegistryServer in it is not set) and only one host is used in the project - it will be set to the hostRules.matchHost from the config. In the same case, if several hosts are used, npmRegistryServer will be set to https://registry.yarnpkg.com.

Python

Pip

Specifications:

  • Certain special characters are not valid in the credential part of a URL. If the user or password part of the login credentials contains any of these special characters, then they must be percent-encoded.

Python

Pipenv

Specifications:

  • Use the envVariablesMapping parameter if you used environmental variables in your Pipenv settings to include the username and password/token.

  • Use the sourceName parameter if you don't have a specified package index.

Ruby

Bundler

N/A

Examples of hostRules with specific registries

As AWS Code Artifact tokens rotate every twelve hours, it is recommended to scan applications built using AWS Code Artifact using the Mend CLI. More information can be found at Scan with the Mend CLI.

JavaScript errors detected

Please note, these errors can depend on your browser setup.

If this problem persists, please contact our support.