summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrpereira2 <rpereira@gitlab.com>2019-07-09 16:42:24 +0530
committerrpereira2 <rpereira@gitlab.com>2019-07-24 12:43:07 +0530
commitcc0ea991edfcf1ba0a159230bbc102e1d6bb718f (patch)
tree4f2bfedfa920f2c3dfe6c5496eb711ce9c719569
parentcfcde04d9eb43eea2bbf7cef09cd3caff2df7c05 (diff)
downloadgitlab-ce-cc0ea991edfcf1ba0a159230bbc102e1d6bb718f.tar.gz
Allow ip ranges in local requests whitelist
- Use IPAddr to test if ips belong to a whitelisted ip or range.
-rw-r--r--app/helpers/application_settings_helper.rb1
-rw-r--r--app/models/application_setting.rb6
-rw-r--r--app/models/application_setting_implementation.rb66
-rw-r--r--app/views/admin/application_settings/_outbound.html.haml9
-rw-r--r--changelogs/unreleased/add-outbound-requests-whitelist-for-local-networks.yml3
-rw-r--r--config/initializers/1_settings.rb1
-rw-r--r--db/migrate/20180824202952_add_outbound_requests_whitelist_to_application_settings.rb6
-rw-r--r--doc/api/settings.md6
-rw-r--r--lib/gitlab/url_blocker.rb21
-rw-r--r--lib/gitlab/utils.rb7
-rw-r--r--locale/gitlab.pot3
-rw-r--r--spec/lib/gitlab/url_blocker_spec.rb145
-rw-r--r--spec/lib/gitlab/utils_spec.rb19
-rw-r--r--spec/support/shared_examples/application_setting_examples.rb111
14 files changed, 264 insertions, 140 deletions
diff --git a/app/helpers/application_settings_helper.rb b/app/helpers/application_settings_helper.rb
index 4bf9b708401..3847a35fbab 100644
--- a/app/helpers/application_settings_helper.rb
+++ b/app/helpers/application_settings_helper.rb
@@ -177,6 +177,7 @@ module ApplicationSettingsHelper
:domain_blacklist_enabled,
:domain_blacklist_raw,
:domain_whitelist_raw,
+ :outbound_local_requests_whitelist_raw,
:dsa_key_restriction,
:ecdsa_key_restriction,
:ed25519_key_restriction,
diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb
index 9347d82e9e5..af55f86aa0b 100644
--- a/app/models/application_setting.rb
+++ b/app/models/application_setting.rb
@@ -19,7 +19,7 @@ class ApplicationSetting < ApplicationRecord
serialize :restricted_visibility_levels # rubocop:disable Cop/ActiveRecordSerialize
serialize :import_sources # rubocop:disable Cop/ActiveRecordSerialize
serialize :disabled_oauth_sign_in_sources, Array # rubocop:disable Cop/ActiveRecordSerialize
- serialize :outbound_requests_whitelist, Array # rubocop:disable Cop/ActiveRecordSerialize
+ serialize :outbound_local_requests_whitelist, Array # rubocop:disable Cop/ActiveRecordSerialize
serialize :domain_whitelist, Array # rubocop:disable Cop/ActiveRecordSerialize
serialize :domain_blacklist, Array # rubocop:disable Cop/ActiveRecordSerialize
serialize :repository_storages # rubocop:disable Cop/ActiveRecordSerialize
@@ -118,10 +118,6 @@ class ApplicationSetting < ApplicationRecord
validates :enabled_git_access_protocol,
inclusion: { in: %w(ssh http), allow_blank: true, allow_nil: true }
- validates :outbound_requests_whitelist,
- presence: { message: 'Outbound requests whitelist cannot be activated if local requests from hooks and services is enabled.' },
- if: :allow_local_requests_from_hooks_and_services?
-
validates :domain_blacklist,
presence: { message: 'Domain blacklist cannot be empty if Blacklist is enabled.' },
if: :domain_blacklist_enabled?
diff --git a/app/models/application_setting_implementation.rb b/app/models/application_setting_implementation.rb
index d80777fba0f..1fec62c5cd2 100644
--- a/app/models/application_setting_implementation.rb
+++ b/app/models/application_setting_implementation.rb
@@ -2,6 +2,7 @@
module ApplicationSettingImplementation
extend ActiveSupport::Concern
+ include Gitlab::Utils::StrongMemoize
DOMAIN_LIST_SEPARATOR = %r{\s*[,;]\s* # comma or semicolon, optionally surrounded by whitespace
| # or
@@ -97,7 +98,7 @@ module ApplicationSettingImplementation
commit_email_hostname: default_commit_email_hostname,
protected_ci_variables: false,
local_markdown_version: 0,
- outbound_requests_whitelist: Settings.gitlab['outbound_requests_whitelist']
+ outbound_local_requests_whitelist: []
}
end
@@ -131,52 +132,51 @@ module ApplicationSettingImplementation
super(sources)
end
- def outbound_requests_whitelist_raw
- self.outbound_requests_whitelist&.join("\n")
- end
-
- def outbound_requests_whitelist_raw=(values)
- self.outbound_requests_whitelist = []
- self.outbound_requests_whitelist = values.split(DOMAIN_LIST_SEPARATOR)
- self.outbound_requests_whitelist.reject! { |d| d.empty? }
- self.outbound_requests_whitelist
- end
-
def domain_whitelist_raw
- self.domain_whitelist&.join("\n")
+ array_to_string(self.domain_whitelist)
end
def domain_blacklist_raw
- self.domain_blacklist&.join("\n")
+ array_to_string(self.domain_blacklist)
end
def domain_whitelist_raw=(values)
- self.domain_whitelist = []
- self.domain_whitelist = values.split(DOMAIN_LIST_SEPARATOR)
- self.domain_whitelist.reject! { |d| d.empty? }
- self.domain_whitelist
+ self.domain_whitelist = domain_strings_to_array(values)
end
def domain_blacklist_raw=(values)
- self.domain_blacklist = []
- self.domain_blacklist = values.split(DOMAIN_LIST_SEPARATOR)
- self.domain_blacklist.reject! { |d| d.empty? }
- self.domain_blacklist
+ self.domain_blacklist = domain_strings_to_array(values)
end
def domain_blacklist_file=(file)
self.domain_blacklist_raw = file.read
end
- def outbound_requests_whitelist_raw
- self.outbound_requests_whitelist = string_to_array(values)
+ def outbound_local_requests_whitelist_raw
+ array_to_string(self.outbound_local_requests_whitelist)
end
- def outbound_requests_whitelist_raw=(values)
- self.outbound_requests_whitelist = []
- self.outbound_requests_whitelist = values.split(DOMAIN_LIST_SEPARATOR)
- self.outbound_requests_whitelist.reject! { |d| d.empty? }
- self.outbound_requests_whitelist
+ def outbound_local_requests_whitelist_raw=(values)
+ self.outbound_local_requests_whitelist = domain_strings_to_array(values)
+ end
+
+ def outbound_local_requests_whitelist_arrays
+ strong_memoize(:outbound_local_requests_whitelist_arrays) do
+ ip_whitelist = []
+ domain_whitelist = []
+
+ self.outbound_local_requests_whitelist.each do |str|
+ ip_obj = Gitlab::Utils.string_to_ip_object(str)
+
+ if ip_obj
+ ip_whitelist << ip_obj
+ else
+ domain_whitelist << str
+ end
+ end
+
+ [ip_whitelist, domain_whitelist]
+ end
end
def repository_storages
@@ -278,6 +278,14 @@ module ApplicationSettingImplementation
private
+ def array_to_string(arr)
+ arr&.join("\n")
+ end
+
+ def domain_strings_to_array(values)
+ values.split(DOMAIN_LIST_SEPARATOR).reject(&:empty?)
+ end
+
def ensure_uuid!
return if uuid?
diff --git a/app/views/admin/application_settings/_outbound.html.haml b/app/views/admin/application_settings/_outbound.html.haml
index c302b042a95..255c2803cad 100644
--- a/app/views/admin/application_settings/_outbound.html.haml
+++ b/app/views/admin/application_settings/_outbound.html.haml
@@ -8,9 +8,12 @@
= f.label :allow_local_requests_from_hooks_and_services, class: 'form-check-label' do
Allow requests to the local network from hooks and services
- = f.label :web_hook_uri_whitelist, class: 'label-bold' do
- URI of trusted services for web hook integrations
- = f.text_field :web_hook_uri_whitelist, placeholder: "example.com,192.168.1.1", class: 'form-control'
+ .form-group
+ = f.label :outbound_local_requests_whitelist_raw, class: 'label-bold' do
+ Whitelist to allow requests to the local network from hooks and services
+ = f.text_area :outbound_local_requests_whitelist_raw, placeholder: "example.com, 192.168.1.1", class: 'form-control', rows: 8
+ %span.form-text.text-muted
+ = _('Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are disabled. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. Ex: domain.com, 192.168.1.1, 127.0.0.0/28')
.form-group
.form-check
diff --git a/changelogs/unreleased/add-outbound-requests-whitelist-for-local-networks.yml b/changelogs/unreleased/add-outbound-requests-whitelist-for-local-networks.yml
index 41305aa160e..9b50175f536 100644
--- a/changelogs/unreleased/add-outbound-requests-whitelist-for-local-networks.yml
+++ b/changelogs/unreleased/add-outbound-requests-whitelist-for-local-networks.yml
@@ -1,6 +1,5 @@
---
title: Add Outbound requests whitelist for local networks
-merge_request: 21377
+merge_request: 30350
author: Istvan Szalai
type: added
-
diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb
index 64a004ac620..494c4dd1f93 100644
--- a/config/initializers/1_settings.rb
+++ b/config/initializers/1_settings.rb
@@ -197,7 +197,6 @@ Settings.gitlab.default_projects_features['snippets'] = true if Settin
Settings.gitlab.default_projects_features['builds'] = true if Settings.gitlab.default_projects_features['builds'].nil?
Settings.gitlab.default_projects_features['container_registry'] = true if Settings.gitlab.default_projects_features['container_registry'].nil?
Settings.gitlab.default_projects_features['visibility_level'] = Settings.__send__(:verify_constant, Gitlab::VisibilityLevel, Settings.gitlab.default_projects_features['visibility_level'], Gitlab::VisibilityLevel::PRIVATE)
-Settings.gitlab['outbound_requests_whitelist'] ||= []
Settings.gitlab['domain_whitelist'] ||= []
Settings.gitlab['import_sources'] ||= Gitlab::ImportSources.values
Settings.gitlab['trusted_proxies'] ||= []
diff --git a/db/migrate/20180824202952_add_outbound_requests_whitelist_to_application_settings.rb b/db/migrate/20180824202952_add_outbound_requests_whitelist_to_application_settings.rb
index f43a9c19048..c0c1bde0a1e 100644
--- a/db/migrate/20180824202952_add_outbound_requests_whitelist_to_application_settings.rb
+++ b/db/migrate/20180824202952_add_outbound_requests_whitelist_to_application_settings.rb
@@ -1,9 +1,9 @@
-class AddOutboundRequestsWhitelistToApplicationSettings < ActiveRecord::Migration
+# frozen_string_literal: true
- # Set this constant to true if this migration requires downtime.
+class AddOutboundRequestsWhitelistToApplicationSettings < ActiveRecord::Migration[5.1]
DOWNTIME = false
def change
- add_column :application_settings, :outbound_requests_whitelist, :text
+ add_column :application_settings, :outbound_local_requests_whitelist, :text
end
end
diff --git a/doc/api/settings.md b/doc/api/settings.md
index 695eff1dad0..68da88af698 100644
--- a/doc/api/settings.md
+++ b/doc/api/settings.md
@@ -39,7 +39,7 @@ Example response:
"session_expire_delay" : 10080,
"home_page_url" : null,
"default_snippet_visibility" : "private",
- "outbound_requests_whitelist": [],
+ "outbound_local_requests_whitelist": [],
"domain_whitelist" : [],
"domain_blacklist_enabled" : false,
"domain_blacklist" : [],
@@ -114,7 +114,7 @@ Example response:
"default_project_visibility": "internal",
"default_snippet_visibility": "private",
"default_group_visibility": "private",
- "outbound_requests_whitelist": [],
+ "outbound_local_requests_whitelist": [],
"domain_whitelist": [],
"domain_blacklist_enabled" : false,
"domain_blacklist" : [],
@@ -195,7 +195,7 @@ are listed in the descriptions of the relevant settings.
| `domain_blacklist` | array of strings | required by: `domain_blacklist_enabled` | Users with e-mail addresses that match these domain(s) will NOT be able to sign-up. Wildcards allowed. Use separate lines for multiple entries. Ex: `domain.com`, `*.domain.com`. |
| `domain_blacklist_enabled` | boolean | no | (**If enabled, requires:** `domain_blacklist`) Allows blocking sign-ups from emails from specific domains. |
| `domain_whitelist` | array of strings | no | Force people to use only corporate emails for sign-up. Default is `null`, meaning there is no restriction. |
-| `outbound_requests_whitelist` | array of strings | no | Define a list of trusted domains or ip addresses for outbound requests.
+| `outbound_local_requests_whitelist` | array of strings | no | Define a list of trusted domains or ip addresses to which local requests are allowed when local requests for hooks and services are disabled.
| `dsa_key_restriction` | integer | no | The minimum allowed bit length of an uploaded DSA key. Default is `0` (no restriction). `-1` disables DSA keys. |
| `ecdsa_key_restriction` | integer | no | The minimum allowed curve size (in bits) of an uploaded ECDSA key. Default is `0` (no restriction). `-1` disables ECDSA keys. |
| `ed25519_key_restriction` | integer | no | The minimum allowed curve size (in bits) of an uploaded ED25519 key. Default is `0` (no restriction). `-1` disables ED25519 keys. |
diff --git a/lib/gitlab/url_blocker.rb b/lib/gitlab/url_blocker.rb
index 8732e5dec09..174abfb9415 100644
--- a/lib/gitlab/url_blocker.rb
+++ b/lib/gitlab/url_blocker.rb
@@ -57,6 +57,8 @@ module Gitlab
return protected_uri_with_hostname if internal?(uri)
validate_local_request(
+ uri: protected_uri_with_hostname[0],
+ hostname: protected_uri_with_hostname[1],
address_info: address_info,
allow_localhost: allow_localhost,
allow_local_network: allow_local_network
@@ -113,9 +115,12 @@ module Gitlab
rescue SocketError
end
- def validate_local_request(address_info:, allow_localhost:, allow_local_network:)
+ def validate_local_request(uri:, hostname:, address_info:, allow_localhost:, allow_local_network:)
return if allow_local_network && allow_localhost
+ return if local_request_whitelisted?(uri.host) ||
+ local_request_whitelisted?(hostname)
+
unless allow_localhost
validate_localhost(address_info)
validate_loopback(address_info)
@@ -231,8 +236,18 @@ module Gitlab
(uri.port.blank? || uri.port == config.gitlab_shell.ssh_port)
end
- def whitelisted?(uri)
- config.gitlab.outbound_requests_whitelist.include?(uri)
+ def local_request_whitelisted?(str)
+ ip_obj = Gitlab::Utils.string_to_ip_object(str)
+
+ ip_whitelist, domain_whitelist = Gitlab::CurrentSettings.outbound_local_requests_whitelist_arrays
+
+ if ip_obj
+ return true if ip_whitelist.any? { |ip| ip.include?(ip_obj) }
+ else
+ return true if domain_whitelist.include?(str)
+ end
+
+ false
end
def config
diff --git a/lib/gitlab/utils.rb b/lib/gitlab/utils.rb
index 16ec8a8bb28..31c9e18c996 100644
--- a/lib/gitlab/utils.rb
+++ b/lib/gitlab/utils.rb
@@ -131,5 +131,12 @@ module Gitlab
data
end
end
+
+ def string_to_ip_object(str)
+ return unless str
+
+ IPAddr.new(str)
+ rescue IPAddr::InvalidAddressError
+ end
end
end
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 833c8c9fe11..60d7e3865f9 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -8994,6 +8994,9 @@ msgstr ""
msgid "Requests Profiles"
msgstr ""
+msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are disabled. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. Ex: domain.com, 192.168.1.1, 127.0.0.0/28"
+msgstr ""
+
msgid "Require all users in this group to setup Two-factor authentication"
msgstr ""
diff --git a/spec/lib/gitlab/url_blocker_spec.rb b/spec/lib/gitlab/url_blocker_spec.rb
index f8b0cbfb6f6..fb83b9510f5 100644
--- a/spec/lib/gitlab/url_blocker_spec.rb
+++ b/spec/lib/gitlab/url_blocker_spec.rb
@@ -220,53 +220,53 @@ describe Gitlab::UrlBlocker do
end
let(:fake_domain) { 'www.fakedomain.fake' }
- context 'true (default)' do
+ shared_examples 'allows local requests' do |url_blocker_attributes|
it 'does not block urls from private networks' do
local_ips.each do |ip|
- stub_domain_resolv(fake_domain, ip)
-
- expect(described_class).not_to be_blocked_url("http://#{fake_domain}")
-
- unstub_domain_resolv
+ stub_domain_resolv(fake_domain, ip) do
+ expect(described_class).not_to be_blocked_url("http://#{fake_domain}", url_blocker_attributes)
+ end
- expect(described_class).not_to be_blocked_url("http://#{ip}")
+ expect(described_class).not_to be_blocked_url("http://#{ip}", url_blocker_attributes)
end
end
it 'allows localhost endpoints' do
- expect(described_class).not_to be_blocked_url('http://0.0.0.0', allow_localhost: true)
- expect(described_class).not_to be_blocked_url('http://localhost', allow_localhost: true)
- expect(described_class).not_to be_blocked_url('http://127.0.0.1', allow_localhost: true)
+ expect(described_class).not_to be_blocked_url('http://0.0.0.0', url_blocker_attributes)
+ expect(described_class).not_to be_blocked_url('http://localhost', url_blocker_attributes)
+ expect(described_class).not_to be_blocked_url('http://127.0.0.1', url_blocker_attributes)
end
it 'allows loopback endpoints' do
- expect(described_class).not_to be_blocked_url('http://127.0.0.2', allow_localhost: true)
+ expect(described_class).not_to be_blocked_url('http://127.0.0.2', url_blocker_attributes)
end
it 'allows IPv4 link-local endpoints' do
- expect(described_class).not_to be_blocked_url('http://169.254.169.254')
- expect(described_class).not_to be_blocked_url('http://169.254.168.100')
+ expect(described_class).not_to be_blocked_url('http://169.254.169.254', url_blocker_attributes)
+ expect(described_class).not_to be_blocked_url('http://169.254.168.100', url_blocker_attributes)
end
it 'allows IPv6 link-local endpoints' do
- expect(described_class).not_to be_blocked_url('http://[0:0:0:0:0:ffff:169.254.169.254]')
- expect(described_class).not_to be_blocked_url('http://[::ffff:169.254.169.254]')
- expect(described_class).not_to be_blocked_url('http://[::ffff:a9fe:a9fe]')
- expect(described_class).not_to be_blocked_url('http://[0:0:0:0:0:ffff:169.254.168.100]')
- expect(described_class).not_to be_blocked_url('http://[::ffff:169.254.168.100]')
- expect(described_class).not_to be_blocked_url('http://[::ffff:a9fe:a864]')
- expect(described_class).not_to be_blocked_url('http://[fe80::c800:eff:fe74:8]')
+ expect(described_class).not_to be_blocked_url('http://[0:0:0:0:0:ffff:169.254.169.254]', url_blocker_attributes)
+ expect(described_class).not_to be_blocked_url('http://[::ffff:169.254.169.254]', url_blocker_attributes)
+ expect(described_class).not_to be_blocked_url('http://[::ffff:a9fe:a9fe]', url_blocker_attributes)
+ expect(described_class).not_to be_blocked_url('http://[0:0:0:0:0:ffff:169.254.168.100]', url_blocker_attributes)
+ expect(described_class).not_to be_blocked_url('http://[::ffff:169.254.168.100]', url_blocker_attributes)
+ expect(described_class).not_to be_blocked_url('http://[::ffff:a9fe:a864]', url_blocker_attributes)
+ expect(described_class).not_to be_blocked_url('http://[fe80::c800:eff:fe74:8]', url_blocker_attributes)
end
end
+ context 'true (default)' do
+ it_behaves_like 'allows local requests', { allow_localhost: true, allow_local_network: true }
+ end
+
context 'false' do
it 'blocks urls from private networks' do
local_ips.each do |ip|
- stub_domain_resolv(fake_domain, ip)
-
- expect(described_class).to be_blocked_url("http://#{fake_domain}", allow_local_network: false)
-
- unstub_domain_resolv
+ stub_domain_resolv(fake_domain, ip) do
+ expect(described_class).to be_blocked_url("http://#{fake_domain}", allow_local_network: false)
+ end
expect(described_class).to be_blocked_url("http://#{ip}", allow_local_network: false)
end
@@ -286,15 +286,104 @@ describe Gitlab::UrlBlocker do
expect(described_class).to be_blocked_url('http://[::ffff:a9fe:a864]', allow_local_network: false)
expect(described_class).to be_blocked_url('http://[fe80::c800:eff:fe74:8]', allow_local_network: false)
end
+
+ context 'when local url/ip is whitelisted' do
+ before do
+ Gitlab::CurrentSettings.outbound_local_requests_whitelist = whitelist
+ end
+
+ context 'with IPs in whitelist' do
+ let(:whitelist) do
+ [
+ '0.0.0.0',
+ '127.0.0.1',
+ '127.0.0.2',
+ '192.168.1.2',
+ '0:0:0:0:0:ffff:192.168.1.2',
+ '::ffff:c0a8:102',
+ '10.0.0.2',
+ '0:0:0:0:0:ffff:10.0.0.2',
+ '::ffff:a00:2',
+ '172.16.0.2',
+ '0:0:0:0:0:ffff:172.16.0.2',
+ '::ffff:ac10:20',
+ 'feef::1',
+ 'fee2::',
+ 'fc00:bf8b:e62c:abcd:abcd:aaaa:aaaa:aaaa',
+ '0:0:0:0:0:ffff:169.254.169.254',
+ '::ffff:a9fe:a9fe',
+ '::ffff:169.254.168.100',
+ '::ffff:a9fe:a864',
+ 'fe80::c800:eff:fe74:8'
+ ]
+ end
+
+ it_behaves_like 'allows local requests', { allow_localhost: false, allow_local_network: false }
+ end
+
+ context 'with domains in whitelist' do
+ let(:whitelist) do
+ [
+ 'www.example.com',
+ 'example.com'
+ ]
+ end
+
+ it 'allows domains present in whitelist' do
+ domain = 'example.com'
+ subdomain1 = 'www.example.com'
+ subdomain2 = 'subdomain.example.com'
+
+ stub_domain_resolv(domain, '192.168.1.1') do
+ expect(described_class).not_to be_blocked_url("http://#{domain}",
+ { allow_localhost: false, allow_local_network: false })
+ end
+
+ stub_domain_resolv(subdomain1, '192.168.1.1') do
+ expect(described_class).not_to be_blocked_url("http://#{subdomain1}",
+ { allow_localhost: false, allow_local_network: false })
+ end
+
+ # subdomain2 is not part of the whitelist so it should be blocked
+ stub_domain_resolv(subdomain2, '192.168.1.1') do
+ expect(described_class).to be_blocked_url("http://#{subdomain2}",
+ { allow_localhost: false, allow_local_network: false })
+ end
+ end
+ end
+
+ context 'with ip ranges in whitelist' do
+ let(:whitelist) do
+ [
+ '127.0.0.0/28',
+ '1:0:0:0:0:0:0:0/124'
+ ]
+ end
+
+ it 'allows all ipv4s in the range' do
+ IPAddr.new("127.0.0.0/28").to_range.to_a.each do |ip|
+ expect(described_class).not_to be_blocked_url("http://#{ip}",
+ { allow_localhost: false, allow_local_network: false })
+ end
+ end
+
+ it 'allows all ipv6s in the range' do
+ IPAddr.new("1:0:0:0:0:0:0:0/124").to_range.to_a.each do |ip|
+ expect(described_class).not_to be_blocked_url("http://[#{ip}]",
+ { allow_localhost: false, allow_local_network: false })
+ end
+ end
+ end
+ end
end
- def stub_domain_resolv(domain, ip)
+ def stub_domain_resolv(domain, ip, &block)
address = double(ip_address: ip, ipv4_private?: true, ipv6_link_local?: false, ipv4_loopback?: false, ipv6_loopback?: false, ipv4?: false)
allow(Addrinfo).to receive(:getaddrinfo).with(domain, any_args).and_return([address])
allow(address).to receive(:ipv6_v4mapped?).and_return(false)
- end
- def unstub_domain_resolv
+ yield
+
allow(Addrinfo).to receive(:getaddrinfo).and_call_original
end
end
diff --git a/spec/lib/gitlab/utils_spec.rb b/spec/lib/gitlab/utils_spec.rb
index 4645339f439..0c20b3aa4c8 100644
--- a/spec/lib/gitlab/utils_spec.rb
+++ b/spec/lib/gitlab/utils_spec.rb
@@ -231,4 +231,23 @@ describe Gitlab::Utils do
end
end
end
+
+ describe '.string_to_ip_object' do
+ it 'returns nil when string is nil' do
+ expect(described_class.string_to_ip_object(nil)).to eq(nil)
+ end
+
+ it 'returns nil when string is invalid IP' do
+ expect(described_class.string_to_ip_object('invalid ip')).to eq(nil)
+ expect(described_class.string_to_ip_object('')).to eq(nil)
+ end
+
+ it 'returns IP object when string is valid IP' do
+ expect(described_class.string_to_ip_object('192.168.1.1')).to eq(IPAddr.new('192.168.1.1'))
+ expect(described_class.string_to_ip_object('::ffff:a9fe:a864')).to eq(IPAddr.new('::ffff:a9fe:a864'))
+ expect(described_class.string_to_ip_object('[::ffff:a9fe:a864]')).to eq(IPAddr.new('::ffff:a9fe:a864'))
+ expect(described_class.string_to_ip_object('127.0.0.0/28')).to eq(IPAddr.new('127.0.0.0/28'))
+ expect(described_class.string_to_ip_object('1:0:0:0:0:0:0:0/124')).to eq(IPAddr.new('1:0:0:0:0:0:0:0/124'))
+ end
+ end
end
diff --git a/spec/support/shared_examples/application_setting_examples.rb b/spec/support/shared_examples/application_setting_examples.rb
index 1fcc304e941..cdc4774645a 100644
--- a/spec/support/shared_examples/application_setting_examples.rb
+++ b/spec/support/shared_examples/application_setting_examples.rb
@@ -1,84 +1,69 @@
# frozen_string_literal: true
-RSpec.shared_examples 'application settings examples' do
- context 'restricted signup domains' do
- it 'sets single domain' do
- setting.domain_whitelist_raw = 'example.com'
- expect(setting.domain_whitelist).to eq(['example.com'])
- end
-
- it 'sets multiple domains with spaces' do
- setting.domain_whitelist_raw = 'example.com *.example.com'
- expect(setting.domain_whitelist).to eq(['example.com', '*.example.com'])
- end
+RSpec.shared_examples 'string of domains' do |attribute|
+ it 'sets single domain' do
+ setting.method("#{attribute}_raw=").call('example.com')
+ expect(setting.method(attribute).call).to eq(['example.com'])
+ end
- it 'sets multiple domains with newlines and a space' do
- setting.domain_whitelist_raw = "example.com\n *.example.com"
- expect(setting.domain_whitelist).to eq(['example.com', '*.example.com'])
- end
+ it 'sets multiple domains with spaces' do
+ setting.method("#{attribute}_raw=").call('example.com *.example.com')
+ expect(setting.method(attribute).call).to eq(['example.com', '*.example.com'])
+ end
- it 'sets multiple domains with commas' do
- setting.domain_whitelist_raw = "example.com, *.example.com"
- expect(setting.domain_whitelist).to eq(['example.com', '*.example.com'])
- end
+ it 'sets multiple domains with newlines and a space' do
+ setting.method("#{attribute}_raw=").call("example.com\n *.example.com")
+ expect(setting.method(attribute).call).to eq(['example.com', '*.example.com'])
end
- context 'restricted outbound requests domain' do
- it 'sets outbound requests domain' do
- setting.outbound_requests_whitelist_raw = 'example.com'
- expect(setting.outbound_requests_whitelist).to eq(['example.com'])
- end
+ it 'sets multiple domains with commas' do
+ setting.method("#{attribute}_raw=").call("example.com, *.example.com")
+ expect(setting.method(attribute).call).to eq(['example.com', '*.example.com'])
+ end
- it 'sets multiple outbound requests domain with spaces' do
- setting.outbound_requests_whitelist_raw = 'example.com *.example.com'
- expect(setting.outbound_requests_whitelist).to eq(['example.com', '*.example.com'])
- end
+ it 'sets multiple domains with semicolon' do
+ setting.method("#{attribute}_raw=").call("example.com; *.example.com")
+ expect(setting.method(attribute).call).to contain_exactly('example.com', '*.example.com')
+ end
- it 'sets multiple outbound requests domains with newlines and a space' do
- setting.outbound_requests_whitelist_raw = "example.com\n *.example.com"
- expect(setting.outbound_requests_whitelist).to eq(['example.com', '*.example.com'])
- end
+ it 'sets multiple domains with mixture of everything' do
+ setting.method("#{attribute}_raw=").call("example.com; *.example.com\n test.com\sblock.com yes.com")
+ expect(setting.method(attribute).call).to contain_exactly('example.com', '*.example.com', 'test.com', 'block.com', 'yes.com')
+ end
+end
- it 'sets multiple outbound requests domains with commas' do
- setting.outbound_requests_whitelist_raw = "example.com, *.example.com"
- expect(setting.outbound_requests_whitelist).to eq(['example.com', '*.example.com'])
- end
+RSpec.shared_examples 'application settings examples' do
+ context 'restricted signup domains' do
+ it_behaves_like 'string of domains', :domain_whitelist
end
context 'blacklisted signup domains' do
- it 'sets single domain' do
- setting.domain_blacklist_raw = 'example.com'
- expect(setting.domain_blacklist).to contain_exactly('example.com')
- end
-
- it 'sets multiple domains with spaces' do
- setting.domain_blacklist_raw = 'example.com *.example.com'
- expect(setting.domain_blacklist).to contain_exactly('example.com', '*.example.com')
- end
+ it_behaves_like 'string of domains', :domain_blacklist
- it 'sets multiple domains with newlines and a space' do
- setting.domain_blacklist_raw = "example.com\n *.example.com"
- expect(setting.domain_blacklist).to contain_exactly('example.com', '*.example.com')
+ it 'sets multiple domain with file' do
+ setting.domain_blacklist_file = File.open(Rails.root.join('spec/fixtures/', 'domain_blacklist.txt'))
+ expect(setting.domain_blacklist).to contain_exactly('example.com', 'test.com', 'foo.bar')
end
+ end
- it 'sets multiple domains with commas' do
- setting.domain_blacklist_raw = "example.com, *.example.com"
- expect(setting.domain_blacklist).to contain_exactly('example.com', '*.example.com')
- end
+ context 'outbound_local_requests_whitelist' do
+ it_behaves_like 'string of domains', :outbound_local_requests_whitelist
+ end
- it 'sets multiple domains with semicolon' do
- setting.domain_blacklist_raw = "example.com; *.example.com"
- expect(setting.domain_blacklist).to contain_exactly('example.com', '*.example.com')
- end
+ context 'outbound_local_requests_whitelist_arrays' do
+ it 'separates the IPs and domains' do
+ setting.outbound_local_requests_whitelist = [
+ '192.168.1.1', '127.0.0.0/28', 'www.example.com', 'example.com',
+ '::ffff:a00:2', '1:0:0:0:0:0:0:0/124', 'subdomain.example.com'
+ ]
- it 'sets multiple domains with mixture of everything' do
- setting.domain_blacklist_raw = "example.com; *.example.com\n test.com\sblock.com yes.com"
- expect(setting.domain_blacklist).to contain_exactly('example.com', '*.example.com', 'test.com', 'block.com', 'yes.com')
- end
+ ip_whitelist = [
+ IPAddr.new('192.168.1.1'), IPAddr.new('127.0.0.0/8'),
+ IPAddr.new('::ffff:a00:2'), IPAddr.new('1:0:0:0:0:0:0:0/124')
+ ]
+ domain_whitelist = ['www.example.com', 'example.com', 'subdomain.example.com']
- it 'sets multiple domain with file' do
- setting.domain_blacklist_file = File.open(Rails.root.join('spec/fixtures/', 'domain_blacklist.txt'))
- expect(setting.domain_blacklist).to contain_exactly('example.com', 'test.com', 'foo.bar')
+ expect(setting.outbound_local_requests_whitelist_arrays).to contain_exactly(ip_whitelist, domain_whitelist)
end
end