DEV Community

Drakos
Drakos

Posted on • Edited on

Publish private NPM packages securely with scopes on CodeArtifact

NPM is a package manager configured by default to use the public registry but what if your code is proprietary and you want full disclosure? The easiest way is to use any cloud services (that support private registries) like Github, Amazon Web Services, or Google Cloud.
With just a few clicks you can setup a private registry for free. In this example, I'll be using CodeArtifact, I'm not affiliated in any way with Amazon Web Services, I had an account and didn't want to waste time trying other services.

Disclaimer: I realize that people are dangerously messing up their environments and the most accurate way to prevent your modules from pushing to wrong servers is using NPM's scope packages. https://docs.npmjs.com/cli/v7/using-npm/scope

Install AWS CLI Version 2

Pushing packages to CodeArtifact requires AWS authentication using the official CLI from Amazon, just run the following 3 commands to install it.

Linux

  1. curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
  2. unzip awscliv2.zip
  3. ./aws/install # as root

macOS

  1. curl "https://awscli.amazonaws.com/AWSCLIV2.pkg" -o "AWSCLIV2.pkg"
  2. sudo installer -pkg AWSCLIV2.pkg -target /

Output:

# /usr/local/bin/aws --version
aws-cli/2.2.47 Python/3.8.8 Linux/5.10.0-8-amd64 exe/x86_64.debian prompt/off

Enter fullscreen mode Exit fullscreen mode

Setup an IAM user (API Keys)

  1. Go to IAM https://console.aws.amazon.com/iamv2/home#/users
  2. Click Add users
  3. Select Access Key as credential type
  4. Create new group and give AWSCodeArtifactAdminAccess permissions.
  5. Write down the generated Access key ID & Secret access key.

Login using the generated keys

Running aws configure will setup the AWS (needed for generating the NPM token later).

**Don't forget to choose the default region. In this example I'm using Ireland EU.

Output:

aws configure

AWS Access Key ID [None]: ----------------
AWS Secret Access Key [None]: ------------
Default region name [None]: eu-west-1
Default output format [None]: json
Enter fullscreen mode Exit fullscreen mode

Create a new NPM scope repo

  1. Login to the AWS dashboard.
  2. Go to CodeArtifact and click Create repository. To avoid collisions give the scope repo a unique name like ca-priv-repo-01
  3. Follow the instructions from AWS.

Publish & Pull the modules

Here comes the hard part. The most valid & secure way to configure any project, is using scopes (namespaces).
Publishing and pulling packages securely without messing up with global configuration files which can lead to massive data leaks & terrible headaches. Thank to NPM's scopes, AWS will play fair with the package manager.

Tip: Check the dummy project here https://github.com/crafter999/private-npm-package

Publish

  1. Create a fresh package using the AWS repository name as an NPM scope. For example @ca-priv-repo-01/mypackage. Example package.json: "name": "@ca-priv-repo-01/private-npm-package"
  2. Go to the CodeArtifact panel.
  3. Click on the target repository & then View connection instructions.
  4. From there, select the npm package manager.
  5. Choose Manual Setup. (Skip Recommended setup for the obvious reasons)
  6. Run the first generated command on a terminal to export the CodeArtifact token.

    Example: 
    
    export CODEARTIFACT_AUTH_TOKEN=`aws codeartifact get-authorization-token --domain mydomain --domain-owner 00000000 --query authorizationToken --output text`
    
  7. Copy paste the 3 lines to the .npmrc replacing registry= with @myscope:registry

    Example: 
    @ca-priv-repo-01:registry=https://-----------.amazonaws.com/npm/ca-priv-repo-01/
    //-----------.amazonaws.com/npm/ca-priv-repo-01/:always-auth=true
    //-----------.amazonaws.com/npm/ca-priv-repo-01/:_authToken=${CODEARTIFACT_AUTH_TOKEN}
    
  8. Add the following lines to the package.json replacing ---id--- with te registry name.

      "publishConfig": {
        "registry": "https://---id---.codeartifact.eu-west-1.amazonaws.com/npm/ca-priv-repo-01/"
      },
    
  9. Lastly, upload any package using npm publish.

NOTE 1: If you're getting authentication errors like the following one, make sure you successfully exported the CODEARTIFACT_AUTH_TOKEN.

npm ERR! code E401
npm ERR! Unable to authenticate, your authentication token seems to be invalid.
npm ERR! To correct this please trying logging in again with:
npm ERR! npm login
Enter fullscreen mode Exit fullscreen mode

NOTE 2: If you're getting domain errors like the following, make sure you are on the right region.

An error occurred (ResourceNotFoundException) when calling the GetAuthorizationToken operation: Domain not found. Domain 'example' owned by account '0000000000' does not exist.
Enter fullscreen mode Exit fullscreen mode

Pull

  1. Create a new project.
  2. Copy paste the .npmrc from the previous step to root folder of your project.
  3. Export the token. Use the generated command from Connection Instructions (Manual Setup).
  4. Install using npm install @myscope/mypackage.

Example Code

You can find a dummy project here. https://github.com/crafter999/private-npm-package

Support

If you liked this article please follow me on Twitter, it's free. https://twitter.com/devcrafter91

Top comments (0)