Uploaded image for project: 'Jenkins'
  1. Jenkins
  2. JENKINS-45854

Authentication for registry within declarative pipeline fails

    Details

    • Type: Bug
    • Status: Closed (View Workflow)
    • Priority: Major
    • Resolution: Not A Defect
    • Component/s: nodejs-plugin
    • Labels:
      None
    • Environment:
      Jenkins ver 2.44
      Nodejs Plugin 1.2.2
    • Similar Issues:

      Description

      I have a multi-branch pipeline for a private NPM package. 

      Within my Jenkinsfile I have a defined a "Publish" stage within my pipeline script for automatically deploying after a successful CI build. This stage looks like:

          stage('Publish') {
            if (env.BRANCH_NAME == "master" || env.BRANCH_NAME == "develop" || env.BRANCH_NAME.startsWith("release/") || env.BRANCH_NAME.startsWith('hotfix/')) {
              nodejs(nodeJSInstallationName: 'NodeJS 6.x', configId: 'abcdefgh-1234-5678-9999-0987654321') {
                sh 'npm login'
                sh 'npm publish'
              }
            }
            else if (env.BRANCH_NAME.startsWith('feature/')) {
              echo "On A feature branch. Not publishing!"
            }
            else {
              echo "Skipping publish - This build is not ocurring on a publish-able branch!"
            }
          }
      

       When the script for npm login fires I get an error:
      [Pipeline] sh
      [workspace] Running shell script
      + npm adduser
      Username: (jenkins) npm ERR! cb() never called!
      I could put the credentials in the script, but man does that suck. I spent a good amount of time setting up the credentials repository in Jenkins so that slick developers wouldn't be able to hold me hostage!

      How can I get authentication to work?

      Other notes:

      We're internally using Sonatype Nexus for our internal hosted NPM registry. I have two configuration files stored, one for accessing the proxy repository (combo of public npmjs and our hosted) and our hosted.

        Attachments

          Activity

          Hide
          nfalco Nikolas Falco added a comment -

          In our organisation we use artifactory. We use it to download and publish npm package.

          The generated .npmrc has credentials to perform the npm publish command, I do not if there is other settings to add for npm login and I do not know why you need to perform login when you publish.

          Anyway please post the generated .npmrc and take care to hide the personal informations.
          For more information have a look to the issue JENKINS-40364

          Show
          nfalco Nikolas Falco added a comment - In our organisation we use artifactory. We use it to download and publish npm package. The generated .npmrc has credentials to perform the npm publish command, I do not if there is other settings to add for npm login and I do not know why you need to perform login when you publish. Anyway please post the generated .npmrc and take care to hide the personal informations. For more information have a look to the issue JENKINS-40364
          Hide
          mikejr83 Michael Gardner added a comment -

          Hey Nikolas Falco

          Thanks for a quick reply.

          So, if I'm understanding correctly the credentials that I select when I build the configuration file and which I pass to the nodejs command should generate a .npmrc file which contains the necessary information to allow me to connect to my internal registry.

          My first attempt went like this:

          nodejs(nodeJSInstallationName: 'NodeJS 6.x', configId: 'abcdefgh-1234-5678-9999-0987654321') {
            sh 'npm publish'
          }
          

          I got an error along the lines that I needed to run `npm adduser` first.

          Should I just run:

          nodejs(nodeJSInstallationName: 'NodeJS 6.x', configId: 'abcdefgh-1234-5678-9999-0987654321') {
            sh 'cat .npmrc'
          }
          

          to get the contents of the file?

          Show
          mikejr83 Michael Gardner added a comment - Hey Nikolas Falco ,  Thanks for a quick reply. So, if I'm understanding correctly the credentials that I select when I build the configuration file and which I pass to the  nodejs command should generate a .npmrc file which contains the necessary information to allow me to connect to my internal registry. My first attempt went like this: nodejs(nodeJSInstallationName: 'NodeJS 6.x' , configId: 'abcdefgh-1234-5678-9999-0987654321' ) { sh 'npm publish' } I got an error along the lines that I needed to run `npm adduser` first. Should I just run: nodejs(nodeJSInstallationName: 'NodeJS 6.x' , configId: 'abcdefgh-1234-5678-9999-0987654321' ) { sh 'cat .npmrc' } to get the contents of the file?
          Hide
          nfalco Nikolas Falco added a comment -

          The credential you put are used to create the entries:

          • registry
          • _auth
          • always-auth

          in the .npmrc file as described here (https://docs.npmjs.com/misc/config)

          Run `npm config ls` to see the set of configuration parameters a shell step.
          Are you sure you can use `npm login` command in non interactive mode?

          Anyway my last question is why you perform a

          sh 'npm login'
          sh 'npm publish'
          

          to publish when a `npm publish` is enough?

          Show
          nfalco Nikolas Falco added a comment - The credential you put are used to create the entries: registry _auth always-auth in the .npmrc file as described here ( https://docs.npmjs.com/misc/config ) Run `npm config ls` to see the set of configuration parameters a shell step. Are you sure you can use `npm login` command in non interactive mode? Anyway my last question is why you perform a sh 'npm login' sh 'npm publish' to publish when a `npm publish` is enough?
          Hide
          nfalco Nikolas Falco added a comment - - edited

          Reading the documentation (google docet) around seems that the npm login add to the .npmrc the entry:

          //myregistryurl.com/npm-repository:_authToken=XYZ

          that permits to make the following HTTP PUT and DELETE requests to registry in authenticated way (always-auth=true if you want also perform GET/download in authenticated manner). The token is valid until you change the password.

          The npm login does not takes username/password CLI parameters due vulnerability issues (according to that the npm developers says).
          If you already have the token in the npmrc file and you perform again a npm login, it asks interactively user, password and email again.

          I can conclude that the step sh 'npm login' could be considered a wrong use case when you already provide credentials and registry URL in the NPM Config because the genereted file already provide all needed settings (expect for the required email entry) to perform the download and publish operations that requires authentication (also in case of scoped registry).
          In the case you do not (or want) use any NPM config file, than you have create a script to perform the npm login (there are a lot of example to do that).

          Show
          nfalco Nikolas Falco added a comment - - edited Reading the documentation (google docet) around seems that the npm login add to the .npmrc the entry: //myregistryurl.com/npm-repository:_authToken=XYZ that permits to make the following HTTP PUT and DELETE requests to registry in authenticated way ( always-auth=true if you want also perform GET/download in authenticated manner). The token is valid until you change the password. The npm login does not takes username/password CLI parameters due vulnerability issues (according to that the npm developers says). If you already have the token in the npmrc file and you perform again a npm login, it asks interactively user, password and email again. I can conclude that the step sh 'npm login' could be considered a wrong use case when you already provide credentials and registry URL in the NPM Config because the genereted file already provide all needed settings ( expect for the required email entry ) to perform the download and publish operations that requires authentication (also in case of scoped registry). In the case you do not (or want) use any NPM config file, than you have create a script to perform the npm login (there are a lot of example to do that). http://blog.npmjs.org/post/118393368555/deploying-with-npm-private-modules https://github.com/npm/npm/issues/12111#issuecomment-202497588 https://remysharp.com/2015/10/26/using-travis-with-private-npm-deps https://github.com/npm/npm/issues/9325 https://github.com/npm/npm/issues/1300
          Hide
          mikejr83 Michael Gardner added a comment -

          Nikolas Falco,

          I was able to hit the VPN and grab some more logs.

          Here's the command I'm running

           

            stage('Publish') {
              if (env.BRANCH_NAME == "master" || env.BRANCH_NAME == "develop" || env.BRANCH_NAME.startsWith("release/") || env.BRANCH_NAME.startsWith('hotfix/')) {
                nodejs(nodeJSInstallationName: 'NodeJS 6.x', configId: '9ba99862-7808-458d-86da-d8983b88fb05') {
                  sh 'npm publish'
                }
              }
              else if (env.BRANCH_NAME.startsWith('feature/')) {
                echo "On A feature branch. Not publishing!"
              }
              else {
                echo "Skipping publish - This build is not ocurring on a publish-able branch!"
              }
            }
          

          Here's the output from the console.

          [Pipeline] stage
           [Pipeline] { (Publish)
           [Pipeline] nodejs
           Adding all registry entries
           copy managed file [Internal NPM Hosted Registry] to file:/var/lib/jenkins/jobs/node-project-framework/branches/master/workspace@tmp/config2618819554631951328tmp
           [Pipeline] {
           [Pipeline] sh
           [workspace] Running shell script
           + npm publish
           npm ERR! Linux 3.19.0-80-generic
           npm ERR! argv "/var/lib/jenkins/tools/jenkins.plugins.nodejs.tools.NodeJSInstallation/NodeJS_6.x/bin/node" "/var/lib/jenkins/tools/jenkins.plugins.nodejs.tools.NodeJSInstallation/NodeJS_6.x/bin/npm" "publish"
           npm ERR! node v6.11.1
           npm ERR! npm v3.10.10
           npm ERR! code ENEEDAUTH
          npm ERR! need auth auth required for publishing
           npm ERR! need auth You need to authorize this machine using `npm adduser`
          npm ERR! Please include the following file with any support request:
           npm ERR! /var/lib/jenkins/jobs/node-project-framework/branches/master/workspace/npm-debug.log
           [Pipeline] }
           [Pipeline] // nodejs
           [Pipeline] }
           [Pipeline] // stage
          
          

            I did a npm config ls -l

          Adding all registry entries
          copy managed file [Internal NPM Hosted Registry] to file:/var/lib/jenkins/jobs/node-project-framework/branches/master/workspace@tmp/config8818317979924342001tmp
          [Pipeline] {
          [Pipeline] sh
          [workspace] Running shell script
          + npm config ls -l
          ; cli configs
          long = true
          user-agent = "npm/3.10.10 node/v6.11.1 linux x64"
          
          ; environment configs
          userconfig = "/var/lib/jenkins/jobs/node-project-framework/branches/master/workspace@tmp/config8818317979924342001tmp"
          
          ; userconfig /var/lib/jenkins/jobs/node-project-framework/branches/master/workspace@tmp/config8818317979924342001tmp
          always-auth = true
          registry = "http://team.mycompany.com:8080/repository/npm-hosted/"
          
          ; default values
          access = null
          also = null
          ; always-auth = false (overridden)
          bin-links = true
          browser = null
          ca = null
          cache = "/var/lib/jenkins/.npm"
          cache-lock-retries = 10
          cache-lock-stale = 60000
          cache-lock-wait = 10000
          cache-max = null
          cache-min = 10
          cafile = undefined
          cert = null
          color = true
          depth = null
          description = true
          dev = false
          dry-run = false
          editor = "vi"
          engine-strict = false
          fetch-retries = 2
          fetch-retry-factor = 10
          fetch-retry-maxtimeout = 60000
          fetch-retry-mintimeout = 10000
          force = false
          git = "git"
          git-tag-version = true
          global = false
          global-style = false
          globalconfig = "/var/lib/jenkins/tools/jenkins.plugins.nodejs.tools.NodeJSInstallation/NodeJS_6.x/etc/npmrc"
          globalignorefile = "/var/lib/jenkins/tools/jenkins.plugins.nodejs.tools.NodeJSInstallation/NodeJS_6.x/etc/npmignore"
          group = 114
          heading = "npm"
          https-proxy = null
          if-present = false
          ignore-scripts = false
          init-author-email = ""
          init-author-name = ""
          init-author-url = ""
          init-license = "ISC"
          init-module = "/var/lib/jenkins/.npm-init.js"
          init-version = "1.0.0"
          json = false
          key = null
          legacy-bundling = false
          link = false
          local-address = undefined
          loglevel = "warn"
          ; long = false (overridden)
          maxsockets = 50
          message = "%s"
          node-version = "6.11.1"
          npat = false
          onload-script = null
          only = null
          optional = true
          parseable = false
          prefix = "/var/lib/jenkins/tools/jenkins.plugins.nodejs.tools.NodeJSInstallation/NodeJS_6.x"
          production = false
          progress = true
          proprietary-attribs = true
          proxy = null
          rebuild-bundle = true
          ; registry = "https://registry.npmjs.org/" (overridden)
          rollback = true
          save = false
          save-bundle = false
          save-dev = false
          save-exact = false
          save-optional = false
          save-prefix = "^"
          scope = ""
          searchexclude = null
          searchopts = ""
          searchsort = "name"
          shell = "/bin/bash"
          shrinkwrap = true
          sign-git-tag = false
          strict-ssl = true
          tag = "latest"
          tag-version-prefix = "v"
          tmp = "/tmp"
          umask = 18
          unicode = true
          unsafe-perm = true
          usage = false
          user = 106
          ; user-agent = "npm/{npm-version} node/{node-version} {platform} {arch}" (overridden)
          ; userconfig = "/var/lib/jenkins/.npmrc" (overridden)
          version = false
          versions = false
          viewer = "man"
          

          Here's the contents of config8818317979924342001tmp

          jenkins@jenkins:~/jobs/node-project-framework/branches/master/workspace@tmp$ cat config8818317979924342001tmp
          ; Force npm to always require authentication when accessing the registry, even for GET requests.
          ; always-auth = false
          ; The location of npm's cache directory. See npm-cache (https://docs.npmjs.com/cli/cache)
          ; Default: Windows: %AppData%\npm-cache, Posix: ~/.npm
          ; cache =
          ; What level of logs to report. On failure, all logs are written to npm-debug.log in the current working directory.
          ; Any logs of a higher level than the setting are shown. The default is "warn", which shows warn and error output.
          ; Default: "warn"
          ; Values: "silent", "error", "warn", "http", "info", "verbose", "silly"
          ; loglevel =
          ; The config file to read for global config options.
          ; Default: {prefix}/etc/npmrc
          ; globalconfig =
          ; The location to install global items. If set on the command line, then it forces non-global commands to run in the specified folder.
          ; Default: see npm-folders (https://docs.npmjs.com/files/folders)
          ; prefix =
          ; The base URL of the npm package registry.
          ; Default: https://registry.npmjs.org/
          ; registry =
          ; If set to false, then ignore npm-shrinkwrap.json files when installing.
          ; Default: true
          ; shrinkwrap =
          registry = http://team.mycompany.com:8080/repository/npm-hosted/
          always-auth = true
          _auth = xxxxxxxxxxxxxxxx
          

          Could this be an issue with the Sonatype Nexus server (not publishing to npmjs)

          Show
          mikejr83 Michael Gardner added a comment - Nikolas Falco , I was able to hit the VPN and grab some more logs. Here's the command I'm running   stage( 'Publish' ) { if (env.BRANCH_NAME == "master" || env.BRANCH_NAME == "develop" || env.BRANCH_NAME.startsWith( "release/" ) || env.BRANCH_NAME.startsWith( 'hotfix/' )) { nodejs(nodeJSInstallationName: 'NodeJS 6.x' , configId: '9ba99862-7808-458d-86da-d8983b88fb05' ) { sh 'npm publish' } } else if (env.BRANCH_NAME.startsWith( 'feature/' )) { echo "On A feature branch. Not publishing!" } else { echo "Skipping publish - This build is not ocurring on a publish-able branch!" } } Here's the output from the console. [Pipeline] stage [Pipeline] { (Publish) [Pipeline] nodejs Adding all registry entries copy managed file [Internal NPM Hosted Registry] to file:/var/lib/jenkins/jobs/node-project-framework/branches/master/workspace@tmp/config2618819554631951328tmp [Pipeline] { [Pipeline] sh [workspace] Running shell script + npm publish npm ERR! Linux 3.19.0-80-generic npm ERR! argv "/var/lib/jenkins/tools/jenkins.plugins.nodejs.tools.NodeJSInstallation/NodeJS_6.x/bin/node" "/var/lib/jenkins/tools/jenkins.plugins.nodejs.tools.NodeJSInstallation/NodeJS_6.x/bin/npm" "publish" npm ERR! node v6.11.1 npm ERR! npm v3.10.10 npm ERR! code ENEEDAUTH npm ERR! need auth auth required for publishing npm ERR! need auth You need to authorize this machine using `npm adduser` npm ERR! Please include the following file with any support request: npm ERR! /var/lib/jenkins/jobs/node-project-framework/branches/master/workspace/npm-debug.log [Pipeline] } [Pipeline] // nodejs [Pipeline] } [Pipeline] // stage   I did a npm config ls -l Adding all registry entries copy managed file [Internal NPM Hosted Registry] to file:/var/lib/jenkins/jobs/node-project-framework/branches/master/workspace@tmp/config8818317979924342001tmp [Pipeline] { [Pipeline] sh [workspace] Running shell script + npm config ls -l ; cli configs long = true user-agent = "npm/3.10.10 node/v6.11.1 linux x64" ; environment configs userconfig = "/var/lib/jenkins/jobs/node-project-framework/branches/master/workspace@tmp/config8818317979924342001tmp" ; userconfig /var/lib/jenkins/jobs/node-project-framework/branches/master/workspace@tmp/config8818317979924342001tmp always-auth = true registry = "http://team.mycompany.com:8080/repository/npm-hosted/" ; default values access = null also = null ; always-auth = false (overridden) bin-links = true browser = null ca = null cache = "/var/lib/jenkins/.npm" cache-lock-retries = 10 cache-lock-stale = 60000 cache-lock-wait = 10000 cache-max = null cache-min = 10 cafile = undefined cert = null color = true depth = null description = true dev = false dry-run = false editor = "vi" engine-strict = false fetch-retries = 2 fetch-retry-factor = 10 fetch-retry-maxtimeout = 60000 fetch-retry-mintimeout = 10000 force = false git = "git" git-tag-version = true global = false global-style = false globalconfig = "/var/lib/jenkins/tools/jenkins.plugins.nodejs.tools.NodeJSInstallation/NodeJS_6.x/etc/npmrc" globalignorefile = "/var/lib/jenkins/tools/jenkins.plugins.nodejs.tools.NodeJSInstallation/NodeJS_6.x/etc/npmignore" group = 114 heading = "npm" https-proxy = null if-present = false ignore-scripts = false init-author-email = "" init-author-name = "" init-author-url = "" init-license = "ISC" init-module = "/var/lib/jenkins/.npm-init.js" init-version = "1.0.0" json = false key = null legacy-bundling = false link = false local-address = undefined loglevel = "warn" ; long = false (overridden) maxsockets = 50 message = "%s" node-version = "6.11.1" npat = false onload-script = null only = null optional = true parseable = false prefix = "/var/lib/jenkins/tools/jenkins.plugins.nodejs.tools.NodeJSInstallation/NodeJS_6.x" production = false progress = true proprietary-attribs = true proxy = null rebuild-bundle = true ; registry = "https://registry.npmjs.org/" (overridden) rollback = true save = false save-bundle = false save-dev = false save-exact = false save-optional = false save-prefix = "^" scope = "" searchexclude = null searchopts = "" searchsort = "name" shell = "/bin/bash" shrinkwrap = true sign-git-tag = false strict-ssl = true tag = "latest" tag-version-prefix = "v" tmp = "/tmp" umask = 18 unicode = true unsafe-perm = true usage = false user = 106 ; user-agent = "npm/{npm-version} node/{node-version} {platform} {arch}" (overridden) ; userconfig = "/var/lib/jenkins/.npmrc" (overridden) version = false versions = false viewer = "man" Here's the contents of config8818317979924342001tmp jenkins@jenkins:~/jobs/node-project-framework/branches/master/workspace@tmp$ cat config8818317979924342001tmp ; Force npm to always require authentication when accessing the registry, even for GET requests. ; always-auth = false ; The location of npm's cache directory. See npm-cache (https://docs.npmjs.com/cli/cache) ; Default: Windows: %AppData%\npm-cache, Posix: ~/.npm ; cache = ; What level of logs to report. On failure, all logs are written to npm-debug.log in the current working directory. ; Any logs of a higher level than the setting are shown. The default is "warn", which shows warn and error output. ; Default: "warn" ; Values: "silent", "error", "warn", "http", "info", "verbose", "silly" ; loglevel = ; The config file to read for global config options. ; Default: {prefix}/etc/npmrc ; globalconfig = ; The location to install global items. If set on the command line, then it forces non-global commands to run in the specified folder. ; Default: see npm-folders (https://docs.npmjs.com/files/folders) ; prefix = ; The base URL of the npm package registry. ; Default: https://registry.npmjs.org/ ; registry = ; If set to false, then ignore npm-shrinkwrap.json files when installing. ; Default: true ; shrinkwrap = registry = http://team.mycompany.com:8080/repository/npm-hosted/ always-auth = true _auth = xxxxxxxxxxxxxxxx Could this be an issue with the Sonatype Nexus server (not publishing to npmjs)
          Hide
          nfalco Nikolas Falco added a comment -

          I do not see the required email field needed for authentication

          Show
          nfalco Nikolas Falco added a comment - I do not see the required email field needed for authentication

            People

            • Assignee:
              nfalco Nikolas Falco
              Reporter:
              mikejr83 Michael Gardner
            • Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: