diff options
-rw-r--r-- | app/workers/irker_worker.rb | 18 | ||||
-rw-r--r-- | doc/api/status_checks.md | 1 | ||||
-rw-r--r-- | spec/models/integrations/irker_spec.rb | 18 | ||||
-rw-r--r-- | spec/support/helpers/dns_helpers.rb | 10 | ||||
-rw-r--r-- | spec/workers/irker_worker_spec.rb | 15 |
5 files changed, 52 insertions, 10 deletions
diff --git a/app/workers/irker_worker.rb b/app/workers/irker_worker.rb index 3097a9fbc03..4f51bb69b8c 100644 --- a/app/workers/irker_worker.rb +++ b/app/workers/irker_worker.rb @@ -2,6 +2,7 @@ require 'json' require 'socket' +require 'resolv' class IrkerWorker # rubocop:disable Scalability/IdempotentWorker include ApplicationWorker @@ -43,9 +44,18 @@ class IrkerWorker # rubocop:disable Scalability/IdempotentWorker private def start_connection(irker_server, irker_port) + ip_address = Resolv.getaddress(irker_server) + # handle IP6 addresses + domain = Resolv::IPv6::Regex.match?(ip_address) ? "[#{ip_address}]" : ip_address + begin - @socket = TCPSocket.new irker_server, irker_port - rescue Errno::ECONNREFUSED => e + Gitlab::UrlBlocker.validate!( + "irc://#{domain}", + allow_localhost: allow_local_requests?, + allow_local_network: allow_local_requests?, + schemes: ['irc']) + @socket = TCPSocket.new ip_address, irker_port + rescue Errno::ECONNREFUSED, Gitlab::UrlBlocker::BlockedUrlError => e logger.fatal "Can't connect to Irker daemon: #{e}" return false end @@ -53,6 +63,10 @@ class IrkerWorker # rubocop:disable Scalability/IdempotentWorker true end + def allow_local_requests? + Gitlab::CurrentSettings.allow_local_requests_from_web_hooks_and_services? + end + def send_to_irker(privmsg) to_send = { to: @channels, privmsg: privmsg } diff --git a/doc/api/status_checks.md b/doc/api/status_checks.md index c0dba71bdc5..7de188ad185 100644 --- a/doc/api/status_checks.md +++ b/doc/api/status_checks.md @@ -45,6 +45,7 @@ GET /projects/:id/merge_requests/:merge_request_iid/status_checks ## Set status of an external status check For a single merge request, use the API to inform GitLab that a merge request has passed a check by an external service. +To set the status of an external check, the personal access token used must belong to a user with at least the developer role on the target project of the merge request. ```plaintext POST /projects/:id/merge_requests/:merge_request_iid/status_check_responses diff --git a/spec/models/integrations/irker_spec.rb b/spec/models/integrations/irker_spec.rb index 8b207e8b43e..8aea2c26dc5 100644 --- a/spec/models/integrations/irker_spec.rb +++ b/spec/models/integrations/irker_spec.rb @@ -2,6 +2,7 @@ require 'spec_helper' require 'socket' +require 'timeout' require 'json' RSpec.describe Integrations::Irker do @@ -37,6 +38,7 @@ RSpec.describe Integrations::Irker do before do @irker_server = TCPServer.new 'localhost', 0 + allow(Gitlab::CurrentSettings).to receive(:allow_local_requests_from_web_hooks_and_services?).and_return(true) allow(irker).to receive_messages( active: true, project: project, @@ -58,13 +60,17 @@ RSpec.describe Integrations::Irker do irker.execute(sample_data) conn = @irker_server.accept - conn.each_line do |line| - msg = Gitlab::Json.parse(line.chomp("\n")) - expect(msg.keys).to match_array(%w(to privmsg)) - expect(msg['to']).to match_array(["irc://chat.freenode.net/#commits", - "irc://test.net/#test"]) + + Timeout.timeout(5) do + conn.each_line do |line| + msg = Gitlab::Json.parse(line.chomp("\n")) + expect(msg.keys).to match_array(%w(to privmsg)) + expect(msg['to']).to match_array(["irc://chat.freenode.net/#commits", + "irc://test.net/#test"]) + end end - conn.close + ensure + conn.close if conn end end end diff --git a/spec/support/helpers/dns_helpers.rb b/spec/support/helpers/dns_helpers.rb index ba32ccbb6f1..b941e7c4808 100644 --- a/spec/support/helpers/dns_helpers.rb +++ b/spec/support/helpers/dns_helpers.rb @@ -23,7 +23,15 @@ module DnsHelpers end def permit_local_dns! - local_addresses = /\A(127|10)\.0\.0\.\d{1,3}|(192\.168|172\.16)\.\d{1,3}\.\d{1,3}|0\.0\.0\.0|localhost\z/i + local_addresses = %r{ + \A + ::1? | # IPV6 + (127|10)\.0\.0\.\d{1,3} | # 127.0.0.x or 10.0.0.x local network + (192\.168|172\.16)\.\d{1,3}\.\d{1,3} | # 192.168.x.x or 172.16.x.x local network + 0\.0\.0\.0 | # loopback + localhost + \z + }xi allow(Addrinfo).to receive(:getaddrinfo).with(local_addresses, anything, nil, :STREAM).and_call_original allow(Addrinfo).to receive(:getaddrinfo).with(local_addresses, anything, nil, :STREAM, anything, anything, any_args).and_call_original end diff --git a/spec/workers/irker_worker_spec.rb b/spec/workers/irker_worker_spec.rb index aa1f1d2fe1d..c3d40ad2783 100644 --- a/spec/workers/irker_worker_spec.rb +++ b/spec/workers/irker_worker_spec.rb @@ -21,7 +21,7 @@ RSpec.describe IrkerWorker, '#perform' do channels, false, push_data, - server_settings + HashWithIndifferentAccess.new(server_settings) ] end @@ -35,6 +35,14 @@ RSpec.describe IrkerWorker, '#perform' do allow(tcp_socket).to receive(:close).and_return(true) end + context 'local requests are not allowed' do + before do + allow(Gitlab::CurrentSettings).to receive(:allow_local_requests_from_web_hooks_and_services?).and_return(false) + end + + it { expect(worker.perform(*arguments)).to be_falsey } + end + context 'connection fails' do before do allow(TCPSocket).to receive(:new).and_raise(Errno::ECONNREFUSED.new('test')) @@ -44,6 +52,11 @@ RSpec.describe IrkerWorker, '#perform' do end context 'connection successful' do + before do + allow(Gitlab::CurrentSettings) + .to receive(:allow_local_requests_from_web_hooks_and_services?).and_return(true) + end + it { expect(subject.perform(*arguments)).to be_truthy } context 'new branch' do |