Skip to content
This repository has been archived by the owner on Apr 14, 2021. It is now read-only.

Enabling TOTP on rubygems.org breaks rake release #6854

Closed
fnando opened this issue Dec 27, 2018 · 3 comments · Fixed by #7199
Closed

Enabling TOTP on rubygems.org breaks rake release #6854

fnando opened this issue Dec 27, 2018 · 3 comments · Fixed by #7199

Comments

@fnando
Copy link

fnando commented Dec 27, 2018

If you enable 2FA for both UI and API, you can't release new gems with rake release. AFAICT, there's no way one can inform a TOTP code when issuing a gem push. Upgrading to latest rubygems with gem update --system makes --otp available to gem push.

$ gem -v     
3.0.1

$ gem push -h
Usage: gem push GEM [options]

  Options:
    -k, --key KEYNAME                Use the given API key
                                     from ~/.gem/credentials
        --otp CODE                   Digit code for multifactor authentication
        --host HOST                  Push to another gemcutter-compatible host
                                       (e.g. https://rubygems.org)


  Local/Remote Options:
    -p, --[no-]http-proxy [URL]      Use HTTP proxy for remote operations


  Common Options:
    -h, --help                       Get help on this command
    -V, --[no-]verbose               Set the verbose level of output
    -q, --quiet                      Silence command progress meter
        --silent                     Silence RubyGems output
        --config-file FILE           Use this config file instead of default
        --backtrace                  Show stack backtrace on errors
        --debug                      Turn on Ruby debugging
        --norc                       Avoid loading any .gemrc file


  Arguments:
    GEM       built gem to push up

  Summary:
    Push a gem up to the gem server

  Description:
    The push command uploads a gem to the push server (the default is
    https://rubygems.org) and adds it to the index.
    
    The gem can be removed from the index and deleted from the server using the
    yank
    command.  For further discussion see the help for the yank command.
@sonalkr132
Copy link
Member

Thanks for reporting this. Looks like we need to add an argument to rake release:rubygem_push.
Even without --otp, gem push command is suppose to give you a prompt asking for OTP, I guess that is not working because of sh (?)
https://github.com/bundler/bundler/blob/45c7667cd79c6b9e886f75a4980a8921c2adf5c4/lib/bundler/gem_helper.rb#L107

Guides for using MFA with gem command are here. Please let us know your suggestions if we can improve it (PR for MFA guide).
We will update bundler docs after we fix this.

cc: @ecnelises

@segiddins
Copy link
Member

sh calls system, which should indeed be passing through STDIN to the subprocess, so gem push should be able to ask for the TOPT code

@deivid-rodriguez
Copy link
Member

Will be fixed by #7005, I think.

ghost pushed a commit that referenced this issue Jun 12, 2019
7199: Allow `rake release` to ask for input (3rd take) r=colby-swandale a=deivid-rodriguez

This PR supersedes #7108 and #7005.

It fixes #6854.

### What was the end-user problem that led to this PR?

The problem was that if users has 2FA authentication on their rubygems account, `rake release` doesn't really work at the moment, since it hangs asking for the OTP code, but without letting the user know.

### What was your diagnosis of the problem?

My diagnosis was that we need to allow the `rake release` helper that shells out to `gem push` to read `gem push` output and show it to the user, so that she can introduce the requested information.

### What is your fix for the problem, implemented in this PR?

My fix is inspired by @segiddins's comment in #6854 (comment). `Kernel#system` works like we would expect in this situation. 

### Why did you choose this fix out of the possible options?

I chose this fix because #7108 had a few problems:

* It would update the `sh` helper, which is used in many different places. This was unnecessary since most of the times we shell out to the `gem` CLI we don't need to ask for input, and it also produced a very verbose output in those cases, since everything the `gem` CLI prints to the screen would be printed by the bundler helpers too. This PR does not change the current output, other than for `rake release`.

* It would print _duplicate_ output. This is a `rake release` test using #7108:

    ```
    $ RUBYOPT="-I../bundler/lib" ../bundler/exe/bundle exec rake release
      Successfully built RubyGem
      Name: rake_release_tester
      Version: 0.1.0
      File: rake_release_tester-0.1.0.gem
    rake_release_tester 0.1.0 built to pkg/rake_release_tester-0.1.0.gem.
    v0.1.0
    Tag v0.1.0 has already been created.
    Pushing gem to https://rubygems.org...
    You have enabled multi-factor authentication. Please enter OTP code.
    Code:   asd
    Your OTP code is incorrect. Please check it and retry.
    rake aborted!
    Pushing gem to https://rubygems.org...
    You have enabled multi-factor authentication. Please enter OTP code.
    Code:   Your OTP code is incorrect. Please check it and retry.
    /home/deivid/Code/bundler/lib/bundler/gem_helper.rb:187:in `sh'
    /home/deivid/Code/bundler/lib/bundler/gem_helper.rb:109:in `rubygem_push'
    /home/deivid/Code/bundler/lib/bundler/gem_helper.rb:70:in `block in install'
    /home/deivid/Code/bundler/lib/bundler/cli/exec.rb:69:in `load'
    /home/deivid/Code/bundler/lib/bundler/cli/exec.rb:69:in `kernel_load'
    /home/deivid/Code/bundler/lib/bundler/cli/exec.rb:28:in `run'
    /home/deivid/Code/bundler/lib/bundler/cli.rb:468:in `exec'
    /home/deivid/Code/bundler/lib/bundler/vendor/thor/lib/thor/command.rb:27:in `run'
    /home/deivid/Code/bundler/lib/bundler/vendor/thor/lib/thor/invocation.rb:126:in `invoke_command'
    /home/deivid/Code/bundler/lib/bundler/vendor/thor/lib/thor.rb:387:in `dispatch'
    /home/deivid/Code/bundler/lib/bundler/cli.rb:26:in `dispatch'
    /home/deivid/Code/bundler/lib/bundler/vendor/thor/lib/thor/base.rb:466:in `start'
    /home/deivid/Code/bundler/lib/bundler/cli.rb:17:in `start'
    ../bundler/exe/bundle:30:in `block in <main>'
    /home/deivid/Code/bundler/lib/bundler/friendly_errors.rb:123:in `with_friendly_errors'
    ../bundler/exe/bundle:22:in `<main>'
    Tasks: TOP => release => release:rubygem_push
    (See full trace by running task with --trace)
    ```

    This is the same test using this PR:

    ```
    $ RUBYOPT="-I../bundler/lib" ../bundler/exe/bundle exec rake release
    rake_release_tester 0.1.0 built to pkg/rake_release_tester-0.1.0.gem.
    Tag v0.1.0 has already been created.
    Pushing gem to https://rubygems.org...
    You have enabled multi-factor authentication. Please enter OTP code.
    Code:   asdfasdf
    Your OTP code is incorrect. Please check it and retry.
    ```

* Previous approach was hard to test. The test included here might not be great but it's something...

Co-authored-by: David Rodríguez <[email protected]>
@ghost ghost closed this as completed in #7199 Jun 12, 2019
colby-swandale pushed a commit that referenced this issue Jun 12, 2019
7199: Allow `rake release` to ask for input (3rd take) r=colby-swandale a=deivid-rodriguez

This PR supersedes #7108 and #7005.

It fixes #6854.

### What was the end-user problem that led to this PR?

The problem was that if users has 2FA authentication on their rubygems account, `rake release` doesn't really work at the moment, since it hangs asking for the OTP code, but without letting the user know.

### What was your diagnosis of the problem?

My diagnosis was that we need to allow the `rake release` helper that shells out to `gem push` to read `gem push` output and show it to the user, so that she can introduce the requested information.

### What is your fix for the problem, implemented in this PR?

My fix is inspired by @segiddins's comment in #6854 (comment). `Kernel#system` works like we would expect in this situation.

### Why did you choose this fix out of the possible options?

I chose this fix because #7108 had a few problems:

* It would update the `sh` helper, which is used in many different places. This was unnecessary since most of the times we shell out to the `gem` CLI we don't need to ask for input, and it also produced a very verbose output in those cases, since everything the `gem` CLI prints to the screen would be printed by the bundler helpers too. This PR does not change the current output, other than for `rake release`.

* It would print _duplicate_ output. This is a `rake release` test using #7108:

    ```
    $ RUBYOPT="-I../bundler/lib" ../bundler/exe/bundle exec rake release
      Successfully built RubyGem
      Name: rake_release_tester
      Version: 0.1.0
      File: rake_release_tester-0.1.0.gem
    rake_release_tester 0.1.0 built to pkg/rake_release_tester-0.1.0.gem.
    v0.1.0
    Tag v0.1.0 has already been created.
    Pushing gem to https://rubygems.org...
    You have enabled multi-factor authentication. Please enter OTP code.
    Code:   asd
    Your OTP code is incorrect. Please check it and retry.
    rake aborted!
    Pushing gem to https://rubygems.org...
    You have enabled multi-factor authentication. Please enter OTP code.
    Code:   Your OTP code is incorrect. Please check it and retry.
    /home/deivid/Code/bundler/lib/bundler/gem_helper.rb:187:in `sh'
    /home/deivid/Code/bundler/lib/bundler/gem_helper.rb:109:in `rubygem_push'
    /home/deivid/Code/bundler/lib/bundler/gem_helper.rb:70:in `block in install'
    /home/deivid/Code/bundler/lib/bundler/cli/exec.rb:69:in `load'
    /home/deivid/Code/bundler/lib/bundler/cli/exec.rb:69:in `kernel_load'
    /home/deivid/Code/bundler/lib/bundler/cli/exec.rb:28:in `run'
    /home/deivid/Code/bundler/lib/bundler/cli.rb:468:in `exec'
    /home/deivid/Code/bundler/lib/bundler/vendor/thor/lib/thor/command.rb:27:in `run'
    /home/deivid/Code/bundler/lib/bundler/vendor/thor/lib/thor/invocation.rb:126:in `invoke_command'
    /home/deivid/Code/bundler/lib/bundler/vendor/thor/lib/thor.rb:387:in `dispatch'
    /home/deivid/Code/bundler/lib/bundler/cli.rb:26:in `dispatch'
    /home/deivid/Code/bundler/lib/bundler/vendor/thor/lib/thor/base.rb:466:in `start'
    /home/deivid/Code/bundler/lib/bundler/cli.rb:17:in `start'
    ../bundler/exe/bundle:30:in `block in <main>'
    /home/deivid/Code/bundler/lib/bundler/friendly_errors.rb:123:in `with_friendly_errors'
    ../bundler/exe/bundle:22:in `<main>'
    Tasks: TOP => release => release:rubygem_push
    (See full trace by running task with --trace)
    ```

    This is the same test using this PR:

    ```
    $ RUBYOPT="-I../bundler/lib" ../bundler/exe/bundle exec rake release
    rake_release_tester 0.1.0 built to pkg/rake_release_tester-0.1.0.gem.
    Tag v0.1.0 has already been created.
    Pushing gem to https://rubygems.org...
    You have enabled multi-factor authentication. Please enter OTP code.
    Code:   asdfasdf
    Your OTP code is incorrect. Please check it and retry.
    ```

* Previous approach was hard to test. The test included here might not be great but it's something...

Co-authored-by: David Rodríguez <[email protected]>
(cherry picked from commit cd05f13)
ghost pushed a commit to rubygems/rubygems that referenced this issue Mar 11, 2020
7199: Allow `rake release` to ask for input (3rd take) r=colby-swandale a=deivid-rodriguez

This PR supersedes #7108 and #7005.

It fixes #6854.

### What was the end-user problem that led to this PR?

The problem was that if users has 2FA authentication on their rubygems account, `rake release` doesn't really work at the moment, since it hangs asking for the OTP code, but without letting the user know.

### What was your diagnosis of the problem?

My diagnosis was that we need to allow the `rake release` helper that shells out to `gem push` to read `gem push` output and show it to the user, so that she can introduce the requested information.

### What is your fix for the problem, implemented in this PR?

My fix is inspired by @segiddins's comment in rubygems/bundler#6854 (comment). `Kernel#system` works like we would expect in this situation. 

### Why did you choose this fix out of the possible options?

I chose this fix because #7108 had a few problems:

* It would update the `sh` helper, which is used in many different places. This was unnecessary since most of the times we shell out to the `gem` CLI we don't need to ask for input, and it also produced a very verbose output in those cases, since everything the `gem` CLI prints to the screen would be printed by the bundler helpers too. This PR does not change the current output, other than for `rake release`.

* It would print _duplicate_ output. This is a `rake release` test using #7108:

    ```
    $ RUBYOPT="-I../bundler/lib" ../bundler/exe/bundle exec rake release
      Successfully built RubyGem
      Name: rake_release_tester
      Version: 0.1.0
      File: rake_release_tester-0.1.0.gem
    rake_release_tester 0.1.0 built to pkg/rake_release_tester-0.1.0.gem.
    v0.1.0
    Tag v0.1.0 has already been created.
    Pushing gem to https://rubygems.org...
    You have enabled multi-factor authentication. Please enter OTP code.
    Code:   asd
    Your OTP code is incorrect. Please check it and retry.
    rake aborted!
    Pushing gem to https://rubygems.org...
    You have enabled multi-factor authentication. Please enter OTP code.
    Code:   Your OTP code is incorrect. Please check it and retry.
    /home/deivid/Code/bundler/lib/bundler/gem_helper.rb:187:in `sh'
    /home/deivid/Code/bundler/lib/bundler/gem_helper.rb:109:in `rubygem_push'
    /home/deivid/Code/bundler/lib/bundler/gem_helper.rb:70:in `block in install'
    /home/deivid/Code/bundler/lib/bundler/cli/exec.rb:69:in `load'
    /home/deivid/Code/bundler/lib/bundler/cli/exec.rb:69:in `kernel_load'
    /home/deivid/Code/bundler/lib/bundler/cli/exec.rb:28:in `run'
    /home/deivid/Code/bundler/lib/bundler/cli.rb:468:in `exec'
    /home/deivid/Code/bundler/lib/bundler/vendor/thor/lib/thor/command.rb:27:in `run'
    /home/deivid/Code/bundler/lib/bundler/vendor/thor/lib/thor/invocation.rb:126:in `invoke_command'
    /home/deivid/Code/bundler/lib/bundler/vendor/thor/lib/thor.rb:387:in `dispatch'
    /home/deivid/Code/bundler/lib/bundler/cli.rb:26:in `dispatch'
    /home/deivid/Code/bundler/lib/bundler/vendor/thor/lib/thor/base.rb:466:in `start'
    /home/deivid/Code/bundler/lib/bundler/cli.rb:17:in `start'
    ../bundler/exe/bundle:30:in `block in <main>'
    /home/deivid/Code/bundler/lib/bundler/friendly_errors.rb:123:in `with_friendly_errors'
    ../bundler/exe/bundle:22:in `<main>'
    Tasks: TOP => release => release:rubygem_push
    (See full trace by running task with --trace)
    ```

    This is the same test using this PR:

    ```
    $ RUBYOPT="-I../bundler/lib" ../bundler/exe/bundle exec rake release
    rake_release_tester 0.1.0 built to pkg/rake_release_tester-0.1.0.gem.
    Tag v0.1.0 has already been created.
    Pushing gem to https://rubygems.org...
    You have enabled multi-factor authentication. Please enter OTP code.
    Code:   asdfasdf
    Your OTP code is incorrect. Please check it and retry.
    ```

* Previous approach was hard to test. The test included here might not be great but it's something...

Co-authored-by: David Rodríguez <[email protected]>
ghost pushed a commit to rubygems/rubygems that referenced this issue Mar 11, 2020
7199: Allow `rake release` to ask for input (3rd take) r=colby-swandale a=deivid-rodriguez

This PR supersedes #7108 and #7005.

It fixes #6854.

### What was the end-user problem that led to this PR?

The problem was that if users has 2FA authentication on their rubygems account, `rake release` doesn't really work at the moment, since it hangs asking for the OTP code, but without letting the user know.

### What was your diagnosis of the problem?

My diagnosis was that we need to allow the `rake release` helper that shells out to `gem push` to read `gem push` output and show it to the user, so that she can introduce the requested information.

### What is your fix for the problem, implemented in this PR?

My fix is inspired by @segiddins's comment in rubygems/bundler#6854 (comment). `Kernel#system` works like we would expect in this situation.

### Why did you choose this fix out of the possible options?

I chose this fix because #7108 had a few problems:

* It would update the `sh` helper, which is used in many different places. This was unnecessary since most of the times we shell out to the `gem` CLI we don't need to ask for input, and it also produced a very verbose output in those cases, since everything the `gem` CLI prints to the screen would be printed by the bundler helpers too. This PR does not change the current output, other than for `rake release`.

* It would print _duplicate_ output. This is a `rake release` test using #7108:

    ```
    $ RUBYOPT="-I../bundler/lib" ../bundler/exe/bundle exec rake release
      Successfully built RubyGem
      Name: rake_release_tester
      Version: 0.1.0
      File: rake_release_tester-0.1.0.gem
    rake_release_tester 0.1.0 built to pkg/rake_release_tester-0.1.0.gem.
    v0.1.0
    Tag v0.1.0 has already been created.
    Pushing gem to https://rubygems.org...
    You have enabled multi-factor authentication. Please enter OTP code.
    Code:   asd
    Your OTP code is incorrect. Please check it and retry.
    rake aborted!
    Pushing gem to https://rubygems.org...
    You have enabled multi-factor authentication. Please enter OTP code.
    Code:   Your OTP code is incorrect. Please check it and retry.
    /home/deivid/Code/bundler/lib/bundler/gem_helper.rb:187:in `sh'
    /home/deivid/Code/bundler/lib/bundler/gem_helper.rb:109:in `rubygem_push'
    /home/deivid/Code/bundler/lib/bundler/gem_helper.rb:70:in `block in install'
    /home/deivid/Code/bundler/lib/bundler/cli/exec.rb:69:in `load'
    /home/deivid/Code/bundler/lib/bundler/cli/exec.rb:69:in `kernel_load'
    /home/deivid/Code/bundler/lib/bundler/cli/exec.rb:28:in `run'
    /home/deivid/Code/bundler/lib/bundler/cli.rb:468:in `exec'
    /home/deivid/Code/bundler/lib/bundler/vendor/thor/lib/thor/command.rb:27:in `run'
    /home/deivid/Code/bundler/lib/bundler/vendor/thor/lib/thor/invocation.rb:126:in `invoke_command'
    /home/deivid/Code/bundler/lib/bundler/vendor/thor/lib/thor.rb:387:in `dispatch'
    /home/deivid/Code/bundler/lib/bundler/cli.rb:26:in `dispatch'
    /home/deivid/Code/bundler/lib/bundler/vendor/thor/lib/thor/base.rb:466:in `start'
    /home/deivid/Code/bundler/lib/bundler/cli.rb:17:in `start'
    ../bundler/exe/bundle:30:in `block in <main>'
    /home/deivid/Code/bundler/lib/bundler/friendly_errors.rb:123:in `with_friendly_errors'
    ../bundler/exe/bundle:22:in `<main>'
    Tasks: TOP => release => release:rubygem_push
    (See full trace by running task with --trace)
    ```

    This is the same test using this PR:

    ```
    $ RUBYOPT="-I../bundler/lib" ../bundler/exe/bundle exec rake release
    rake_release_tester 0.1.0 built to pkg/rake_release_tester-0.1.0.gem.
    Tag v0.1.0 has already been created.
    Pushing gem to https://rubygems.org...
    You have enabled multi-factor authentication. Please enter OTP code.
    Code:   asdfasdf
    Your OTP code is incorrect. Please check it and retry.
    ```

* Previous approach was hard to test. The test included here might not be great but it's something...

Co-authored-by: David Rodríguez <[email protected]>
(cherry picked from commit cd05f13)
This issue was closed.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
4 participants