web-dev-qa-db-ja.com

stdinからの入力を読み取らずに「npm login」でnpmクレデンシャルを設定します

Dockerコンテナ内でnpm publishを自動化しようとしていますが、npm loginコマンドがプロンプトからユーザー名とメールを読み取ろうとすると問題が発生します。

npm login << EOF
username
password
email
EOF

Bashターミナルでは動作しますが、stdinが開いていないコンテナでは動作せず、次のエラーメッセージが表示されます。

Username: Password: npm ERR! cb() never called!
npm ERR! not ok code 0

npm-adduser によると:

ユーザー名、パスワード、および電子メールは、プロンプトから読み込まれます。

では、stdinを開かずにnpm loginを実行するにはどうすればよいですか?

34
shawmzhu

TL; DR:HTTP要求をレジストリに直接送信します。

TOKEN=$(curl -s \
  -H "Accept: application/json" \
  -H "Content-Type:application/json" \
  -X PUT --data '{"name": "username_here", "password": "password_here"}' \
  http://your_registry/-/user/org.couchdb.user:username_here 2>&1 | grep -Po \
  '(?<="token": ")[^"]*')

npm set registry "http://your_registry"
npm set //your_registry/:_authToken $TOKEN

根拠

舞台裏npm adduserは、レジストリにHTTPリクエストを送信します。 adduserを強制的に希望どおりに動作させる代わりに、cliを経由せずにレジストリに直接リクエストを行い、npm setで認証トークンを設定できます。

ソースコードが示唆する 次のペイロードでhttp://your_registry/-/user/org.couchdb.user:your-usernameにPUTリクエストを行うことができる

{
  name: username,
  password: password
}

それにより、レジストリに新しいユーザーが作成されます。

問題を解決するためのよりクリーンなアプローチを見つけてくれた@shawnzhuに感謝します。

31
danielepolencic

期待されるスクリプトが私のために働いた。 expectがインストールされていることを確認する必要があります。このコマンドは、ubuntuに対して実行する必要があります。

apt-get install expect-dev

スクリプトは次のようになります(npm_login_expect):

#!/usr/bin/expect -f

# set our args into variables
set i 0; foreach n $argv {set "p[incr i]" $n}

set timeout 60
#npm login command, add whatever command-line args are necessary
spawn npm login
match_max 100000

expect "Username"    
send "$p1\r"

expect "Password"
send "$p2\r" 

expect "Email"
send "$p3\r"

expect {
   timeout      exit 1
   eof
}

そして、次のように呼び出します:

expect -f npm_login_expect myuser mypassword "[email protected]"
9
Ted Elliott

私はまだうまくいくように見える少し異なるアプローチを取りました。まず、認証トークンが必要になります。これは、npm adduserをローカルで実行し、ユーザーフォルダーにある~/.npmrcから生成されたトークンを取得することで簡単に取得できます。 CIサーバーで認証されるためには、この認証トークンは、レポジトリにある.npmrcではなく、ユーザーの.npmrc(ローカルと同様)のレジストリURLに追加する必要があります。これらは、私のCI構成のスクリプトステップとしてうまく機能しました

- echo "//<npm-registry>:8080/:_authToken=$AUTH_TOKEN" > ~/.npmrc
- npm publish

aUTH_TOKENは、設定の秘密変数として保存されます。これをテストする良い方法は、npm publishnpm whoamiに置き換えてテストし、正常にログインしたことを確認することです。

ここに私の全体の設定があります

publish:
  stage: deploy
  only:
    - tags
  script:
    - yarn run build
    - echo "//<npm-registry>:8080/:_authToken=$NPME_AUTH_TOKEN" > ~/.npmrc
    - npm publish
    - echo 'Congrats on your publication!'

私はgitlab-ciを使用していますが、これがどのciアプリケーションにも当てはまらないのかわかりません。

7
Bryson Reynolds

これは、Alexander Fの答えの上に構築されています。これは、彼が提供したコードの単純化されたバージョンであり、 npm-registry-client で提供されたサンプルコードとマッシュアップされています。

"use strict";

var RegClient = require('npm-registry-client')
var client = new RegClient()
var uri = "https://registry.npmjs.org/npm"
var params = {timeout: 1000}

var username = 'my.npm.username'
var password = 'myPassword'
var email = '[email protected]'

var params = {
  auth: {
    username,
    password,
    email
  }
};

client.adduser(uri, params, function (error, data, raw, res) {
  if(error) {
    console.error(error);
    return;
  }
  console.log(`Login succeeded`);
  console.log(`data: ${JSON.stringify(data,null,2)}`);
  console.log(`NPM access token: ${data.token}`);
});
3
Chris Troutner

npm-cli-loginを使用すると、STDINなしでNPMにログインできます。

実行をインストールするには

npm install -g npm-cli-login

使用例:-

npm-cli-login -uユーザー名-pパスワード-e [email protected] -r https:// your-private-registry-link

3
Arun Dhiman

結局のところ、npmログインの解決策はまだないとは信じられません。一度トークンを取得して、CIのすべてのニーズに使用できますが、期限切れにならないトークンのセキュリティへの影響についてはどうでしょうか?そして、ある日管理者がトークンの有効期限を決定するとどうなりますか?

以下は、npm-registry-clientパッケージを使用した私のハッキングJavaScriptソリューションです。 json文字列引数を渡すと、ログインして.npmrcファイルが現在のディレクトリに書き込まれます。ログアウトするには、通常どおりnpm logoutを使用します。

var client = new (require('npm-registry-client'))({});
var std_in = JSON.parse(process.argv[2]);

if (std_in.uri === undefined) {
    console.error('Must input registry uri!');
    return;
}

// fix annoying trailing '/' thing in registry uri
if (std_in.uri[std_in.uri.length - 1] !== '/') {
    std_in.uri = std_in.uri + '/';
}

if (std_in.scope === undefined) {
    console.error('Must input scope!');
    return;
    //std_in.scope = '@my-scope'; // or add default scope of your own
}

if (std_in.scope[0] !== '@') {
    std_in.scope = '@' + std_in.scope;
}

client.adduser(std_in.uri, std_in.params, function(err, data, raw, res) {
    if (err) {
        console.error(err);
        return;
    } 
    require('fs').writeFileSync('.npmrc', `${std_in.scope}:registry=${std_in.uri}\n//${(std_in.uri.split('//'))[1]}:_authToken=${data.token}`);
});

入力例:

{ 
    "uri": "https://my-nmp.reg",
    "scope": "@my-scope",
    "params": {
        "auth": {
            "username": "secret-agent",
            "password": "12345",
            "email": "[email protected]"
        }
    }
}
2
Alexander F.

1つの解決策は、トークンを取得して〜/ .npmrcを更新することです

export ARTIFACTORY_TOKEN=`curl --silent --show-error --fail -u $ARTIFACTORY_USERNAME:$ARTIFACTORY_API_KEY https://artifactory.my.io/artifactory/api/npm/auth | \
grep -oP '_auth[\s?]=[\s?]\K(.*)$'`

echo "@my:registry=https://artifactory.my.io/artifactory/api/npm/npm-release-local/" > ~/.npmrc
echo "//artifactory.my.io/artifactory/api/npm/npm-release-local/:_auth=${ARTIFACTORY_TOKEN}" >> ~/.npmrc
echo "//artifactory.my.io/artifactory/api/npm/npm-release-local/:email=${ARTIFACTORY_USERNAME}" >> ~/.npmrc
echo "//artifactory.my.io/artifactory/api/npm/npm-release-local/:always-auth=true" >> ~/.npmrc

これにより、npmjsからの@scopeパッケージの取得に関する問題が防止されます。

2
dres

代わりにexpectスクリプトを使用するか、 pty.js を使用するノードスクリプトを記述できます。

0
mscdex

ke_wa で公開されたソリューション2の場合 duplicated post は機能しています。

マッシュアップ:

export NPM_USERNAME=mUs34
export NPM_PASSWORD=mypassW0rD
export [email protected]
npm adduser<<!
$NPM_USERNAME
$NPM_PASSWORD
$NPM_EMAIL
!
0
l.cotonea