[rubygems/rubygems] Move Webauthn listener thread to WebauthnListener class
https://github.com/rubygems/rubygems/commit/6ec474975e
This commit is contained in:
parent
fce04f9a6c
commit
24913e3dda
@ -18,8 +18,10 @@ require_relative "webauthn_listener/response"
|
|||||||
#
|
#
|
||||||
# Example usage:
|
# Example usage:
|
||||||
#
|
#
|
||||||
# server = TCPServer.new(0)
|
# thread = Gem::WebauthnListener.listener_thread("https://rubygems.example", server)
|
||||||
# otp = Gem::WebauthnListener.wait_for_otp_code("https://rubygems.example", server)
|
# thread.join
|
||||||
|
# otp = thread[:otp]
|
||||||
|
# error = thread[:error]
|
||||||
#
|
#
|
||||||
|
|
||||||
module Gem::GemcutterUtilities
|
module Gem::GemcutterUtilities
|
||||||
@ -32,7 +34,7 @@ module Gem::GemcutterUtilities
|
|||||||
|
|
||||||
def self.listener_thread(host, server)
|
def self.listener_thread(host, server)
|
||||||
thread = Thread.new do
|
thread = Thread.new do
|
||||||
Thread.current[:otp] = wait_for_otp_code(host, server)
|
Thread.current[:otp] = new(host).wait_for_otp_code(server)
|
||||||
rescue Gem::WebauthnVerificationError => e
|
rescue Gem::WebauthnVerificationError => e
|
||||||
Thread.current[:error] = e
|
Thread.current[:error] = e
|
||||||
ensure
|
ensure
|
||||||
@ -44,11 +46,7 @@ module Gem::GemcutterUtilities
|
|||||||
thread
|
thread
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.wait_for_otp_code(host, server)
|
def wait_for_otp_code(server)
|
||||||
new(host).fetch_otp_from_connection(server)
|
|
||||||
end
|
|
||||||
|
|
||||||
def fetch_otp_from_connection(server)
|
|
||||||
loop do
|
loop do
|
||||||
socket = server.accept
|
socket = server.accept
|
||||||
request_line = socket.gets
|
request_line = socket.gets
|
||||||
|
@ -381,7 +381,7 @@ EOF
|
|||||||
)
|
)
|
||||||
|
|
||||||
TCPServer.stub(:new, server) do
|
TCPServer.stub(:new, server) do
|
||||||
Gem::GemcutterUtilities::WebauthnListener.stub(:wait_for_otp_code, "Uvh6T57tkWuUnWYo") do
|
Gem::GemcutterUtilities::WebauthnListener.stub(:listener_thread, Thread.new { Thread.current[:otp] = "Uvh6T57tkWuUnWYo" }) do
|
||||||
use_ui @stub_ui do
|
use_ui @stub_ui do
|
||||||
@cmd.add_owners("freewill", ["user-new1@example.com"])
|
@cmd.add_owners("freewill", ["user-new1@example.com"])
|
||||||
end
|
end
|
||||||
@ -403,7 +403,7 @@ EOF
|
|||||||
response_success = "Owner added successfully."
|
response_success = "Owner added successfully."
|
||||||
port = 5678
|
port = 5678
|
||||||
server = TCPServer.new(port)
|
server = TCPServer.new(port)
|
||||||
raise_error = ->(*_args) { raise Gem::WebauthnVerificationError, "Something went wrong" }
|
error = Gem::WebauthnVerificationError.new("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/webauthn_verification"] = HTTPResponseFactory.create(body: webauthn_verification_url, code: 200, msg: "OK")
|
||||||
@stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = [
|
@stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = [
|
||||||
@ -417,7 +417,7 @@ EOF
|
|||||||
)
|
)
|
||||||
|
|
||||||
TCPServer.stub(:new, server) do
|
TCPServer.stub(:new, server) do
|
||||||
Gem::GemcutterUtilities::WebauthnListener.stub(:wait_for_otp_code, raise_error) do
|
Gem::GemcutterUtilities::WebauthnListener.stub(:listener_thread, Thread.new { Thread.current[:error] = error }) do
|
||||||
use_ui @stub_ui do
|
use_ui @stub_ui do
|
||||||
@cmd.add_owners("freewill", ["user-new1@example.com"])
|
@cmd.add_owners("freewill", ["user-new1@example.com"])
|
||||||
end
|
end
|
||||||
|
@ -445,7 +445,7 @@ class TestGemCommandsPushCommand < Gem::TestCase
|
|||||||
)
|
)
|
||||||
|
|
||||||
TCPServer.stub(:new, server) do
|
TCPServer.stub(:new, server) do
|
||||||
Gem::GemcutterUtilities::WebauthnListener.stub(:wait_for_otp_code, "Uvh6T57tkWuUnWYo") do
|
Gem::GemcutterUtilities::WebauthnListener.stub(:listener_thread, Thread.new { Thread.current[:otp] = "Uvh6T57tkWuUnWYo" }) do
|
||||||
use_ui @ui do
|
use_ui @ui do
|
||||||
@cmd.send_gem(@path)
|
@cmd.send_gem(@path)
|
||||||
end
|
end
|
||||||
@ -467,7 +467,7 @@ class TestGemCommandsPushCommand < Gem::TestCase
|
|||||||
response_success = "Successfully registered gem: freewill (1.0.0)"
|
response_success = "Successfully registered gem: freewill (1.0.0)"
|
||||||
port = 5678
|
port = 5678
|
||||||
server = TCPServer.new(port)
|
server = TCPServer.new(port)
|
||||||
raise_error = ->(*_args) { raise Gem::WebauthnVerificationError, "Something went wrong" }
|
error = Gem::WebauthnVerificationError.new("Something went wrong")
|
||||||
|
|
||||||
@fetcher.data["#{Gem.host}/api/v1/gems"] = [
|
@fetcher.data["#{Gem.host}/api/v1/gems"] = [
|
||||||
HTTPResponseFactory.create(body: response_fail, code: 401, msg: "Unauthorized"),
|
HTTPResponseFactory.create(body: response_fail, code: 401, msg: "Unauthorized"),
|
||||||
@ -482,7 +482,7 @@ class TestGemCommandsPushCommand < Gem::TestCase
|
|||||||
|
|
||||||
error = assert_raise Gem::MockGemUi::TermError do
|
error = assert_raise Gem::MockGemUi::TermError do
|
||||||
TCPServer.stub(:new, server) do
|
TCPServer.stub(:new, server) do
|
||||||
Gem::GemcutterUtilities::WebauthnListener.stub(:wait_for_otp_code, raise_error) do
|
Gem::GemcutterUtilities::WebauthnListener.stub(:listener_thread, Thread.new { Thread.current[:error] = error }) do
|
||||||
use_ui @ui do
|
use_ui @ui do
|
||||||
@cmd.send_gem(@path)
|
@cmd.send_gem(@path)
|
||||||
end
|
end
|
||||||
|
@ -141,7 +141,7 @@ class TestGemCommandsYankCommand < Gem::TestCase
|
|||||||
@cmd.options[:version] = req("= 1.0")
|
@cmd.options[:version] = req("= 1.0")
|
||||||
|
|
||||||
TCPServer.stub(:new, server) do
|
TCPServer.stub(:new, server) do
|
||||||
Gem::GemcutterUtilities::WebauthnListener.stub(:wait_for_otp_code, "Uvh6T57tkWuUnWYo") do
|
Gem::GemcutterUtilities::WebauthnListener.stub(:listener_thread, Thread.new { Thread.current[:otp] = "Uvh6T57tkWuUnWYo" }) do
|
||||||
use_ui @ui do
|
use_ui @ui do
|
||||||
@cmd.execute
|
@cmd.execute
|
||||||
end
|
end
|
||||||
@ -166,7 +166,7 @@ class TestGemCommandsYankCommand < Gem::TestCase
|
|||||||
status_uri = "http://example/api/v1/webauthn_verification/odow34b93t6aPCdY/status.json"
|
status_uri = "http://example/api/v1/webauthn_verification/odow34b93t6aPCdY/status.json"
|
||||||
port = 5678
|
port = 5678
|
||||||
server = TCPServer.new(port)
|
server = TCPServer.new(port)
|
||||||
raise_error = ->(*_args) { raise Gem::WebauthnVerificationError, "Something went wrong" }
|
error = Gem::WebauthnVerificationError.new("Something went wrong")
|
||||||
|
|
||||||
@fetcher.data[webauthn_uri] = HTTPResponseFactory.create(body: webauthn_verification_url, code: 200, msg: "OK")
|
@fetcher.data[webauthn_uri] = HTTPResponseFactory.create(body: webauthn_verification_url, code: 200, msg: "OK")
|
||||||
@fetcher.data[yank_uri] = [
|
@fetcher.data[yank_uri] = [
|
||||||
@ -185,7 +185,7 @@ class TestGemCommandsYankCommand < Gem::TestCase
|
|||||||
|
|
||||||
error = assert_raise Gem::MockGemUi::TermError do
|
error = assert_raise Gem::MockGemUi::TermError do
|
||||||
TCPServer.stub(:new, server) do
|
TCPServer.stub(:new, server) do
|
||||||
Gem::GemcutterUtilities::WebauthnListener.stub(:wait_for_otp_code, raise_error) do
|
Gem::GemcutterUtilities::WebauthnListener.stub(:listener_thread, Thread.new { Thread.current[:error] = error }) do
|
||||||
use_ui @ui do
|
use_ui @ui do
|
||||||
@cmd.execute
|
@cmd.execute
|
||||||
end
|
end
|
||||||
|
@ -229,7 +229,7 @@ class TestGemGemcutterUtilities < Gem::TestCase
|
|||||||
@fetcher.respond_with_require_otp
|
@fetcher.respond_with_require_otp
|
||||||
@fetcher.respond_with_webauthn_url(webauthn_verification_url)
|
@fetcher.respond_with_webauthn_url(webauthn_verification_url)
|
||||||
TCPServer.stub(:new, server) do
|
TCPServer.stub(:new, server) do
|
||||||
Gem::GemcutterUtilities::WebauthnListener.stub(:wait_for_otp_code, "Uvh6T57tkWuUnWYo") do
|
Gem::GemcutterUtilities::WebauthnListener.stub(:listener_thread, Thread.new { Thread.current[:otp] = "Uvh6T57tkWuUnWYo" }) do
|
||||||
util_sign_in
|
util_sign_in
|
||||||
end
|
end
|
||||||
ensure
|
ensure
|
||||||
@ -246,13 +246,13 @@ class TestGemGemcutterUtilities < Gem::TestCase
|
|||||||
webauthn_verification_url = "rubygems.org/api/v1/webauthn_verification/odow34b93t6aPCdY"
|
webauthn_verification_url = "rubygems.org/api/v1/webauthn_verification/odow34b93t6aPCdY"
|
||||||
port = 5678
|
port = 5678
|
||||||
server = TCPServer.new(port)
|
server = TCPServer.new(port)
|
||||||
raise_error = ->(*_args) { raise Gem::WebauthnVerificationError, "Something went wrong" }
|
error = Gem::WebauthnVerificationError.new("Something went wrong")
|
||||||
|
|
||||||
@fetcher.respond_with_require_otp
|
@fetcher.respond_with_require_otp
|
||||||
@fetcher.respond_with_webauthn_url(webauthn_verification_url)
|
@fetcher.respond_with_webauthn_url(webauthn_verification_url)
|
||||||
error = assert_raise Gem::MockGemUi::TermError do
|
error = assert_raise Gem::MockGemUi::TermError do
|
||||||
TCPServer.stub(:new, server) do
|
TCPServer.stub(:new, server) do
|
||||||
Gem::GemcutterUtilities::WebauthnListener.stub(:wait_for_otp_code, raise_error) do
|
Gem::GemcutterUtilities::WebauthnListener.stub(:listener_thread, Thread.new { Thread.current[:error] = error }) do
|
||||||
util_sign_in
|
util_sign_in
|
||||||
end
|
end
|
||||||
ensure
|
ensure
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require_relative "helper"
|
require_relative "helper"
|
||||||
require "rubygems/webauthn_listener"
|
require "rubygems/gemcutter_utilities/webauthn_listener"
|
||||||
|
require "rubygems/gemcutter_utilities"
|
||||||
|
|
||||||
class WebauthnListenerTest < Gem::TestCase
|
class WebauthnListenerTest < Gem::TestCase
|
||||||
def setup
|
def setup
|
||||||
@ -16,6 +17,22 @@ class WebauthnListenerTest < Gem::TestCase
|
|||||||
super
|
super
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_listener_thread_retreives_otp_code
|
||||||
|
thread = Gem::GemcutterUtilities::WebauthnListener.listener_thread(Gem.host, @server)
|
||||||
|
Gem::MockBrowser.get URI("http://localhost:#{@port}?code=xyz")
|
||||||
|
|
||||||
|
thread.join
|
||||||
|
assert_equal "xyz", thread[:otp]
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_listener_thread_sets_error
|
||||||
|
thread = Gem::GemcutterUtilities::WebauthnListener.listener_thread(Gem.host, @server)
|
||||||
|
Gem::MockBrowser.post URI("http://localhost:#{@port}?code=xyz")
|
||||||
|
|
||||||
|
thread.join
|
||||||
|
assert_equal "Security device verification failed: Invalid HTTP method POST received.", thread[:error].message
|
||||||
|
end
|
||||||
|
|
||||||
def test_wait_for_otp_code_get_follows_options
|
def test_wait_for_otp_code_get_follows_options
|
||||||
wait_for_otp_code
|
wait_for_otp_code
|
||||||
assert Gem::MockBrowser.options(URI("http://localhost:#{@port}?code=xyz")).is_a? Net::HTTPNoContent
|
assert Gem::MockBrowser.options(URI("http://localhost:#{@port}?code=xyz")).is_a? Net::HTTPNoContent
|
||||||
@ -106,7 +123,7 @@ class WebauthnListenerTest < Gem::TestCase
|
|||||||
|
|
||||||
def wait_for_otp_code
|
def wait_for_otp_code
|
||||||
@thread = Thread.new do
|
@thread = Thread.new do
|
||||||
Thread.current[:otp] = Gem::GemcutterUtilities::WebauthnListener.wait_for_otp_code(Gem.host, @server)
|
Thread.current[:otp] = Gem::GemcutterUtilities::WebauthnListener.new(Gem.host).wait_for_otp_code(@server)
|
||||||
end
|
end
|
||||||
@thread.abort_on_exception = true
|
@thread.abort_on_exception = true
|
||||||
@thread.report_on_exception = false
|
@thread.report_on_exception = false
|
||||||
@ -115,7 +132,7 @@ class WebauthnListenerTest < Gem::TestCase
|
|||||||
def wait_for_otp_code_expect_error_with_message(message)
|
def wait_for_otp_code_expect_error_with_message(message)
|
||||||
@thread = Thread.new do
|
@thread = Thread.new do
|
||||||
error = assert_raise Gem::WebauthnVerificationError do
|
error = assert_raise Gem::WebauthnVerificationError do
|
||||||
Thread.current[:otp] = Gem::GemcutterUtilities::WebauthnListener.wait_for_otp_code(Gem.host, @server)
|
Thread.current[:otp] = Gem::GemcutterUtilities::WebauthnListener.new(Gem.host).wait_for_otp_code(@server)
|
||||||
end
|
end
|
||||||
|
|
||||||
assert_equal message, error.message
|
assert_equal message, error.message
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require_relative "helper"
|
require_relative "helper"
|
||||||
require "rubygems/webauthn_listener/response"
|
require "rubygems/gemcutter_utilities/webauthn_listener/response"
|
||||||
|
|
||||||
class WebauthnListenerResponseTest < Gem::TestCase
|
class WebauthnListenerResponseTest < Gem::TestCase
|
||||||
def setup
|
def setup
|
||||||
|
Loading…
x
Reference in New Issue
Block a user