diff options
author | Jenny Shen <jenny.shen@shopify.com> | 2023-02-15 23:36:15 -0500 |
---|---|---|
committer | Hiroshi SHIBATA <hsbt@ruby-lang.org> | 2023-04-12 11:51:05 +0900 |
commit | 353f9adcccc9928eb6fc0a7b581d31a1f5ca2d7b (patch) | |
tree | a791ad1579dc6007211c0a09431e6409ef935b78 | |
parent | 6e7bf0677d74a721e3be95e7e60d3033228bb73d (diff) | |
download | ruby-353f9adcccc9928eb6fc0a7b581d31a1f5ca2d7b.tar.gz |
[rubygems/rubygems] Add otp command tests
https://github.com/rubygems/rubygems/commit/c494112063
-rw-r--r-- | lib/rubygems/commands/owner_command.rb | 2 | ||||
-rw-r--r-- | test/rubygems/test_gem_commands_owner_command.rb | 57 | ||||
-rw-r--r-- | test/rubygems/test_gem_commands_push_command.rb | 59 | ||||
-rw-r--r-- | test/rubygems/test_gem_commands_yank_command.rb | 66 |
4 files changed, 158 insertions, 26 deletions
diff --git a/lib/rubygems/commands/owner_command.rb b/lib/rubygems/commands/owner_command.rb index 80620d98ca..eb66c510a9 100644 --- a/lib/rubygems/commands/owner_command.rb +++ b/lib/rubygems/commands/owner_command.rb @@ -98,6 +98,8 @@ permission to. action = method == :delete ? "Removing" : "Adding" with_response response, "#{action} #{owner}" + rescue Gem::WebauthnVerificationError => e + raise e rescue StandardError # ignore end diff --git a/test/rubygems/test_gem_commands_owner_command.rb b/test/rubygems/test_gem_commands_owner_command.rb index 8774862070..fc8c8cb1bd 100644 --- a/test/rubygems/test_gem_commands_owner_command.rb +++ b/test/rubygems/test_gem_commands_owner_command.rb @@ -362,10 +362,12 @@ EOF assert_equal "111111", @stub_fetcher.last_request["OTP"] end - def test_webauthn_otp_verified_success + def test_with_webauthn_enabled_success webauthn_verification_url = "rubygems.org/api/v1/webauthn_verification/odow34b93t6aPCdY" response_fail = "You have enabled multifactor authentication but your request doesn't have the correct OTP code. Please check it and retry." response_success = "Owner added successfully." + port = 5678 + server = TCPServer.new(port) @stub_fetcher.data["#{Gem.host}/api/v1/webauthn_verification"] = HTTPResponseFactory.create(body: webauthn_verification_url, code: 200, msg: "OK") @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = [ @@ -373,15 +375,54 @@ EOF HTTPResponseFactory.create(body: response_success, code: 200, msg: "OK"), ] - @otp_ui = Gem::MockGemUi.new "111111\n" - use_ui @otp_ui do - @cmd.add_owners("freewill", ["user-new1@example.com"]) + TCPServer.stub(:new, server) do + Gem::WebauthnListener.stub(:wait_for_otp_code, "Uvh6T57tkWuUnWYo") do + use_ui @stub_ui do + @cmd.add_owners("freewill", ["user-new1@example.com"]) + end + end + ensure + server.close end - assert_match "You have enabled multi-factor authentication. Please enter OTP code from your security device by visiting #{webauthn_verification_url}", @otp_ui.output - assert_match "Code: ", @otp_ui.output - assert_match response_success, @otp_ui.output - assert_equal "111111", @stub_fetcher.last_request["OTP"] + url_with_port = "#{webauthn_verification_url}?port=#{port}" + assert_match "You have enabled multi-factor authentication. Please visit #{url_with_port} to authenticate via security device.", @stub_ui.output + assert_match "You are verified with a security device. You may close the browser window.", @stub_ui.output + assert_equal "Uvh6T57tkWuUnWYo", @stub_fetcher.last_request["OTP"] + assert_match response_success, @stub_ui.output + end + + def test_with_webauthn_enabled_failure + webauthn_verification_url = "rubygems.org/api/v1/webauthn_verification/odow34b93t6aPCdY" + response_fail = "You have enabled multifactor authentication but your request doesn't have the correct OTP code. Please check it and retry." + response_success = "Owner added successfully." + port = 5678 + server = TCPServer.new(port) + raise_error = ->(*_args) { raise Gem::WebauthnVerificationError, "Something went wrong" } + + @stub_fetcher.data["#{Gem.host}/api/v1/webauthn_verification"] = HTTPResponseFactory.create(body: webauthn_verification_url, code: 200, msg: "OK") + @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = [ + HTTPResponseFactory.create(body: response_fail, code: 401, msg: "Unauthorized"), + HTTPResponseFactory.create(body: response_success, code: 200, msg: "OK"), + ] + + error = assert_raise Gem::WebauthnVerificationError do + TCPServer.stub(:new, server) do + Gem::WebauthnListener.stub(:wait_for_otp_code, raise_error) do + use_ui @stub_ui do + @cmd.add_owners("freewill", ["user-new1@example.com"]) + end + end + ensure + server.close + end + end + assert_equal "Security device verification failed: Something went wrong", error.message + + url_with_port = "#{webauthn_verification_url}?port=#{port}" + assert_match "You have enabled multi-factor authentication. Please visit #{url_with_port} to authenticate via security device.", @stub_ui.output + refute_match "You are verified with a security device. You may close the browser window.", @stub_ui.output + refute_match response_success, @stub_ui.output end def test_remove_owners_unathorized_api_key diff --git a/test/rubygems/test_gem_commands_push_command.rb b/test/rubygems/test_gem_commands_push_command.rb index 2a45853513..9463e50a53 100644 --- a/test/rubygems/test_gem_commands_push_command.rb +++ b/test/rubygems/test_gem_commands_push_command.rb @@ -425,10 +425,12 @@ class TestGemCommandsPushCommand < Gem::TestCase assert_equal "111111", @fetcher.last_request["OTP"] end - def test_webauthn_otp_verified_success - webauthn_verification_url = "#{Gem.host}/api/v1/webauthn_verification/odow34b93t6aPCdY" + def test_with_webauthn_enabled_success + webauthn_verification_url = "rubygems.org/api/v1/webauthn_verification/odow34b93t6aPCdY" response_fail = "You have enabled multifactor authentication but your request doesn't have the correct OTP code. Please check it and retry." response_success = "Successfully registered gem: freewill (1.0.0)" + port = 5678 + server = TCPServer.new(port) @fetcher.data["#{Gem.host}/api/v1/gems"] = [ HTTPResponseFactory.create(body: response_fail, code: 401, msg: "Unauthorized"), @@ -436,15 +438,54 @@ class TestGemCommandsPushCommand < Gem::TestCase ] @fetcher.data["#{Gem.host}/api/v1/webauthn_verification"] = HTTPResponseFactory.create(body: webauthn_verification_url, code: 200, msg: "OK") - @otp_ui = Gem::MockGemUi.new "111111\n" - use_ui @otp_ui do - @cmd.send_gem(@path) + TCPServer.stub(:new, server) do + Gem::WebauthnListener.stub(:wait_for_otp_code, "Uvh6T57tkWuUnWYo") do + use_ui @ui do + @cmd.send_gem(@path) + end + end + ensure + server.close end - assert_match "You have enabled multi-factor authentication. Please enter OTP code from your security device by visiting #{webauthn_verification_url}", @otp_ui.output - assert_match "Code: ", @otp_ui.output - assert_match response_success, @otp_ui.output - assert_equal "111111", @fetcher.last_request["OTP"] + url_with_port = "#{webauthn_verification_url}?port=#{port}" + assert_match "You have enabled multi-factor authentication. Please visit #{url_with_port} to authenticate via security device.", @ui.output + assert_match "You are verified with a security device. You may close the browser window.", @ui.output + assert_equal "Uvh6T57tkWuUnWYo", @fetcher.last_request["OTP"] + assert_match response_success, @ui.output + end + + def test_with_webauthn_enabled_failure + webauthn_verification_url = "rubygems.org/api/v1/webauthn_verification/odow34b93t6aPCdY" + response_fail = "You have enabled multifactor authentication but your request doesn't have the correct OTP code. Please check it and retry." + response_success = "Successfully registered gem: freewill (1.0.0)" + port = 5678 + server = TCPServer.new(port) + raise_error = ->(*_args) { raise Gem::WebauthnVerificationError, "Something went wrong" } + + @fetcher.data["#{Gem.host}/api/v1/gems"] = [ + HTTPResponseFactory.create(body: response_fail, code: 401, msg: "Unauthorized"), + HTTPResponseFactory.create(body: response_success, code: 200, msg: "OK"), + ] + @fetcher.data["#{Gem.host}/api/v1/webauthn_verification"] = HTTPResponseFactory.create(body: webauthn_verification_url, code: 200, msg: "OK") + + error = assert_raise Gem::WebauthnVerificationError do + TCPServer.stub(:new, server) do + Gem::WebauthnListener.stub(:wait_for_otp_code, raise_error) do + use_ui @ui do + @cmd.send_gem(@path) + end + end + ensure + server.close + end + end + assert_equal "Security device verification failed: Something went wrong", error.message + + url_with_port = "#{webauthn_verification_url}?port=#{port}" + assert_match "You have enabled multi-factor authentication. Please visit #{url_with_port} to authenticate via security device.", @ui.output + refute_match "You are verified with a security device. You may close the browser window.", @ui.output + refute_match response_success, @ui.output end def test_sending_gem_unathorized_api_key_with_mfa_enabled diff --git a/test/rubygems/test_gem_commands_yank_command.rb b/test/rubygems/test_gem_commands_yank_command.rb index 1ded1146b1..860f445a95 100644 --- a/test/rubygems/test_gem_commands_yank_command.rb +++ b/test/rubygems/test_gem_commands_yank_command.rb @@ -116,11 +116,14 @@ class TestGemCommandsYankCommand < Gem::TestCase assert_equal "111111", @fetcher.last_request["OTP"] end - def test_execute_with_webauthn_otp_success + def test_with_webauthn_enabled_success webauthn_verification_url = "http://example/api/v1/webauthn_verification/odow34b93t6aPCdY" response_fail = "You have enabled multifactor authentication but your request doesn't have the correct OTP code. Please check it and retry." yank_uri = "http://example/api/v1/gems/yank" webauthn_uri = "http://example/api/v1/webauthn_verification" + port = 5678 + server = TCPServer.new(port) + @fetcher.data[webauthn_uri] = HTTPResponseFactory.create(body: webauthn_verification_url, code: 200, msg: "OK") @fetcher.data[yank_uri] = [ HTTPResponseFactory.create(body: response_fail, code: 401, msg: "Unauthorized"), @@ -131,16 +134,61 @@ class TestGemCommandsYankCommand < Gem::TestCase @cmd.options[:added_platform] = true @cmd.options[:version] = req("= 1.0") - @otp_ui = Gem::MockGemUi.new "111111\n" - use_ui @otp_ui do - @cmd.execute + TCPServer.stub(:new, server) do + Gem::WebauthnListener.stub(:wait_for_otp_code, "Uvh6T57tkWuUnWYo") do + use_ui @ui do + @cmd.execute + end + end + ensure + server.close end - assert_match "You have enabled multi-factor authentication. Please enter OTP code from your security device by visiting #{webauthn_verification_url}", @otp_ui.output - assert_match "Code: ", @otp_ui.output - assert_match %r{Yanking gem from http://example}, @otp_ui.output - assert_match %r{Successfully yanked}, @otp_ui.output - assert_equal "111111", @fetcher.last_request["OTP"] + url_with_port = "#{webauthn_verification_url}?port=#{port}" + assert_match %r{Yanking gem from http://example}, @ui.output + assert_match "You have enabled multi-factor authentication. Please visit #{url_with_port} to authenticate via security device.", @ui.output + assert_match "You are verified with a security device. You may close the browser window.", @ui.output + assert_equal "Uvh6T57tkWuUnWYo", @fetcher.last_request["OTP"] + assert_match "Successfully yanked", @ui.output + end + + def test_with_webauthn_enabled_failure + webauthn_verification_url = "http://example/api/v1/webauthn_verification/odow34b93t6aPCdY" + response_fail = "You have enabled multifactor authentication but your request doesn't have the correct OTP code. Please check it and retry." + yank_uri = "http://example/api/v1/gems/yank" + webauthn_uri = "http://example/api/v1/webauthn_verification" + port = 5678 + server = TCPServer.new(port) + raise_error = ->(*_args) { raise Gem::WebauthnVerificationError, "Something went wrong" } + + @fetcher.data[webauthn_uri] = HTTPResponseFactory.create(body: webauthn_verification_url, code: 200, msg: "OK") + @fetcher.data[yank_uri] = [ + HTTPResponseFactory.create(body: response_fail, code: 401, msg: "Unauthorized"), + HTTPResponseFactory.create(body: "Successfully yanked", code: 200, msg: "OK"), + ] + + @cmd.options[:args] = %w[a] + @cmd.options[:added_platform] = true + @cmd.options[:version] = req("= 1.0") + + error = assert_raise Gem::WebauthnVerificationError do + TCPServer.stub(:new, server) do + Gem::WebauthnListener.stub(:wait_for_otp_code, raise_error) do + use_ui @ui do + @cmd.execute + end + end + ensure + server.close + end + end + assert_equal "Security device verification failed: Something went wrong", error.message + + url_with_port = "#{webauthn_verification_url}?port=#{port}" + assert_match %r{Yanking gem from http://example}, @ui.output + assert_match "You have enabled multi-factor authentication. Please visit #{url_with_port} to authenticate via security device.", @ui.output + refute_match "You are verified with a security device. You may close the browser window.", @ui.output + refute_match "Successfully yanked", @ui.output end def test_execute_key |