Commit 753a1829 authored by GitLab Bot's avatar GitLab Bot

Automatic merge of gitlab-org/gitlab master

parents f9c447c0 f8c90100
import $ from 'jquery';
import { refreshCurrentPage } from '../../lib/utils/url_utility';
function showBlacklistType() {
if ($('input[name="blacklist_type"]:checked').val() === 'file') {
$('.blacklist-file').show();
$('.blacklist-raw').hide();
function showDenylistType() {
if ($('input[name="denylist_type"]:checked').val() === 'file') {
$('.js-denylist-file').show();
$('.js-denylist-raw').hide();
} else {
$('.blacklist-file').hide();
$('.blacklist-raw').show();
$('.js-denylist-file').hide();
$('.js-denylist-raw').show();
}
}
......@@ -60,6 +60,6 @@ export default function adminInit() {
$('li.project_member, li.group_member').on('ajax:success', refreshCurrentPage);
$("input[name='blacklist_type']").on('click', showBlacklistType);
showBlacklistType();
$("input[name='denylist_type']").on('click', showDenylistType);
showDenylistType();
}
......@@ -216,10 +216,10 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
remove_blank_params_for!(:elasticsearch_aws_secret_access_key, :eks_secret_access_key)
# TODO Remove domain_blacklist_raw in APIv5 (See https://gitlab.com/gitlab-org/gitlab-foss/issues/67204)
params.delete(:domain_blacklist_raw) if params[:domain_blacklist_file]
params.delete(:domain_blacklist_raw) if params[:domain_blacklist]
params.delete(:domain_whitelist_raw) if params[:domain_whitelist]
# TODO Remove domain_denylist_raw in APIv5 (See https://gitlab.com/gitlab-org/gitlab-foss/issues/67204)
params.delete(:domain_denylist_raw) if params[:domain_denylist_file]
params.delete(:domain_denylist_raw) if params[:domain_blacklist]
params.delete(:domain_allowlist_raw) if params[:domain_whitelist]
params.require(:application_setting).permit(
visible_application_setting_attributes
......@@ -240,7 +240,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
*ApplicationSetting.repository_storages_weighted_attributes,
:lets_encrypt_notification_email,
:lets_encrypt_terms_of_service_accepted,
:domain_blacklist_file,
:domain_denylist_file,
:raw_blob_request_limit,
:issues_create_limit,
:default_branch_name,
......
......@@ -201,12 +201,12 @@ module ApplicationSettingsHelper
:disabled_oauth_sign_in_sources,
:domain_blacklist,
:domain_blacklist_enabled,
# TODO Remove domain_blacklist_raw in APIv5 (See https://gitlab.com/gitlab-org/gitlab-foss/issues/67204)
:domain_blacklist_raw,
# TODO Remove domain_denylist_raw in APIv5 (See https://gitlab.com/gitlab-org/gitlab-foss/issues/67204)
:domain_denylist_raw,
:domain_whitelist,
# TODO Remove domain_whitelist_raw in APIv5 (See https://gitlab.com/gitlab-org/gitlab-foss/issues/67204)
:domain_whitelist_raw,
:outbound_local_requests_whitelist_raw,
# TODO Remove domain_allowlist_raw in APIv5 (See https://gitlab.com/gitlab-org/gitlab-foss/issues/67204)
:domain_allowlist_raw,
:outbound_local_requests_allowlist_raw,
:dsa_key_restriction,
:ecdsa_key_restriction,
:ed25519_key_restriction,
......
......@@ -202,38 +202,38 @@ module ApplicationSettingImplementation
super(sources)
end
def domain_whitelist_raw
def domain_allowlist_raw
array_to_string(self.domain_whitelist)
end
def domain_blacklist_raw
def domain_denylist_raw
array_to_string(self.domain_blacklist)
end
def domain_whitelist_raw=(values)
def domain_allowlist_raw=(values)
self.domain_whitelist = strings_to_array(values)
end
def domain_blacklist_raw=(values)
def domain_denylist_raw=(values)
self.domain_blacklist = strings_to_array(values)
end
def domain_blacklist_file=(file)
self.domain_blacklist_raw = file.read
def domain_denylist_file=(file)
self.domain_denylist_raw = file.read
end
def outbound_local_requests_whitelist_raw
def outbound_local_requests_allowlist_raw
array_to_string(self.outbound_local_requests_whitelist)
end
def outbound_local_requests_whitelist_raw=(values)
clear_memoization(:outbound_local_requests_whitelist_arrays)
def outbound_local_requests_allowlist_raw=(values)
clear_memoization(:outbound_local_requests_allowlist_arrays)
self.outbound_local_requests_whitelist = strings_to_array(values)
end
def add_to_outbound_local_requests_whitelist(values_array)
clear_memoization(:outbound_local_requests_whitelist_arrays)
clear_memoization(:outbound_local_requests_allowlist_arrays)
self.outbound_local_requests_whitelist ||= []
self.outbound_local_requests_whitelist += values_array
......@@ -242,16 +242,16 @@ module ApplicationSettingImplementation
end
# This method separates out the strings stored in the
# application_setting.outbound_local_requests_whitelist array into 2 arrays;
# application_setting.outbound_local_requests_allowlist array into 2 arrays;
# an array of IPAddr objects (`[IPAddr.new('127.0.0.1')]`), and an array of
# domain strings (`['www.example.com']`).
def outbound_local_requests_whitelist_arrays
strong_memoize(:outbound_local_requests_whitelist_arrays) do
def outbound_local_requests_allowlist_arrays
strong_memoize(:outbound_local_requests_allowlist_arrays) do
next [[], []] unless self.outbound_local_requests_whitelist
ip_whitelist, domain_whitelist = separate_whitelists(self.outbound_local_requests_whitelist)
ip_allowlist, domain_allowlist = separate_allowlists(self.outbound_local_requests_whitelist)
[ip_whitelist, domain_whitelist]
[ip_allowlist, domain_allowlist]
end
end
......@@ -396,19 +396,19 @@ module ApplicationSettingImplementation
private
def separate_whitelists(string_array)
string_array.reduce([[], []]) do |(ip_whitelist, domain_whitelist), string|
def separate_allowlists(string_array)
string_array.reduce([[], []]) do |(ip_allowlist, domain_allowlist), string|
address, port = parse_addr_and_port(string)
ip_obj = Gitlab::Utils.string_to_ip_object(address)
if ip_obj
ip_whitelist << Gitlab::UrlBlockers::IpWhitelistEntry.new(ip_obj, port: port)
ip_allowlist << Gitlab::UrlBlockers::IpAllowlistEntry.new(ip_obj, port: port)
else
domain_whitelist << Gitlab::UrlBlockers::DomainWhitelistEntry.new(address, port: port)
domain_allowlist << Gitlab::UrlBlockers::DomainAllowlistEntry.new(address, port: port)
end
[ip_whitelist, domain_whitelist]
[ip_allowlist, domain_allowlist]
end
end
......
......@@ -13,9 +13,9 @@
= _('Allow requests to the local network from system hooks')
.form-group
= f.label :outbound_local_requests_whitelist_raw, class: 'label-bold' do
= f.label :outbound_local_requests_allowlist_raw, class: 'label-bold' do
= _('Local IP addresses and domain names that hooks and services may access.')
= f.text_area :outbound_local_requests_whitelist_raw, placeholder: "example.com, 192.168.1.1", class: 'form-control', rows: 8
= f.text_area :outbound_local_requests_allowlist_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 not allowed. 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. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com.')
......
......@@ -28,33 +28,33 @@
.form-text.text-muted
= _("See GitLab's %{password_policy_guidelines}").html_safe % { password_policy_guidelines: password_policy_guidelines_link }
.form-group
= f.label :domain_whitelist, 'Whitelisted domains for sign-ups', class: 'label-bold'
= f.text_area :domain_whitelist_raw, placeholder: 'domain.com', class: 'form-control', rows: 8
= f.label :domain_whitelist, _('Allowed domains for sign-ups'), class: 'label-bold'
= f.text_area :domain_allowlist_raw, placeholder: 'domain.com', class: 'form-control', rows: 8
.form-text.text-muted ONLY users with e-mail addresses that match these domain(s) will be able to sign-up. Wildcards allowed. Use separate lines for multiple entries. Ex: domain.com, *.domain.com
.form-group
= f.label :domain_blacklist_enabled, 'Domain Blacklist', class: 'label-bold'
= f.label :domain_blacklist_enabled, _('Domain denylist'), class: 'label-bold'
.form-check
= f.check_box :domain_blacklist_enabled, class: 'form-check-input'
= f.label :domain_blacklist_enabled, class: 'form-check-label' do
Enable domain blacklist for sign ups
Enable domain denylist for sign ups
.form-group
.form-check
= radio_button_tag :blacklist_type, :file, false, class: 'form-check-input'
= label_tag :blacklist_type_file, class: 'form-check-label' do
= radio_button_tag :denylist_type, :file, false, class: 'form-check-input'
= label_tag :denylist_type_file, class: 'form-check-label' do
.option-title
Upload blacklist file
Upload denylist file
.form-check
= radio_button_tag :blacklist_type, :raw, @application_setting.domain_blacklist.present? || @application_setting.domain_blacklist.blank?, class: 'form-check-input'
= label_tag :blacklist_type_raw, class: 'form-check-label' do
= radio_button_tag :denylist_type, :raw, @application_setting.domain_blacklist.present? || @application_setting.domain_blacklist.blank?, class: 'form-check-input'
= label_tag :denylist_type_raw, class: 'form-check-label' do
.option-title
Enter blacklist manually
.form-group.blacklist-file
= f.label :domain_blacklist_file, 'Blacklist file', class: 'label-bold'
= f.file_field :domain_blacklist_file, class: 'form-control', accept: '.txt,.conf'
Enter denylist manually
.form-group.js-denylist-file
= f.label :domain_denylist_file, _('Denylist file'), class: 'label-bold'
= f.file_field :domain_denylist_file, class: 'form-control', accept: '.txt,.conf'
.form-text.text-muted Users with e-mail addresses that match these domain(s) will NOT be able to sign-up. Wildcards allowed. Use separate lines or commas for multiple entries.
.form-group.blacklist-raw
= f.label :domain_blacklist, 'Blacklisted domains for sign-ups', class: 'label-bold'
= f.text_area :domain_blacklist_raw, placeholder: 'domain.com', class: 'form-control', rows: 8
.form-group.js-denylist-raw
= f.label :domain_blacklist, _('Denied domains for sign-ups'), class: 'label-bold'
= f.text_area :domain_denylist_raw, placeholder: 'domain.com', class: 'form-control', rows: 8
.form-text.text-muted 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
.form-group
= f.label :email_restrictions_enabled, _('Email restrictions'), class: 'label-bold'
......
---
title: Update whitelist/blacklist to allowlist/denylist in Signup restrictions window
merge_request: 46168
author:
type: changed
......@@ -42,6 +42,8 @@ a mail server feature where any email to `user+arbitrary_tag@example.com` will e
in the mailbox for `user@example.com` . It is supported by providers such as
Gmail, Google Apps, Yahoo! Mail, Outlook.com, and iCloud, as well as the
[Postfix mail server](reply_by_email_postfix_setup.md), which you can run on-premises.
Microsoft Exchange Server [does not support sub-addressing](#microsoft-exchange-server),
and Microsoft Office 365 [does not support sub-addressing by default](#microsoft-office-365)
TIP: **Tip:**
If your provider or server supports email sub-addressing, we recommend using it.
......@@ -326,11 +328,11 @@ incoming_email:
#### Microsoft Exchange Server
Example configurations for Microsoft Exchange Server with IMAP enabled. Since
Example configurations for Microsoft Exchange Server with IMAP enabled. Because
Exchange does not support sub-addressing, only two options exist:
- Catch-all mailbox (recommended for Exchange-only)
- Dedicated email address (supports Reply by Email only)
- [Catch-all mailbox](#catch-all-mailbox) (recommended for Exchange-only)
- [Dedicated email address](#dedicated-email-address) (supports Reply by Email only)
##### Catch-all mailbox
......@@ -417,7 +419,8 @@ Example for source installs:
incoming_email:
enabled: true
# Exchange does not support sub-addressing, and we're not using a catch-all mailbox so %{key} is not used here
# Exchange does not support sub-addressing,
# and we're not using a catch-all mailbox so %{key} is not used here
address: "incoming@exchange.example.com"
# Email account username
......@@ -433,3 +436,180 @@ incoming_email:
# Whether the IMAP server uses SSL
ssl: true
```
#### Microsoft Office 365
Example configurations for Microsoft Office 365 with IMAP enabled.
##### Sub-addressing mailbox
NOTE: **Note:**
As of September 2020 sub-addressing support
[has been added to Office 365](https://office365.uservoice.com/forums/273493-office-365-admin/suggestions/18612754-support-for-dynamic-email-aliases-in-office-36). This feature is not
enabled by default, and must be enabled through PowerShell.
This series of PowerShell commands enables [sub-addressing](#email-sub-addressing)
at the organization level in Office 365. This allows all mailboxes in the organization
to receive sub-addressed mail:
NOTE: **Note:**
This series of commands will enable sub-addressing at the organization
level in Office 365. This will allow all mailboxes in the organization
to receive sub-addressed mail.
```powershell
Set-ExecutionPolicy RemoteSigned -Scope CurrentUser
$UserCredential = Get-Credential
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/ -Credential $UserCredential -Authentication Basic -AllowRedirection
Import-PSSession $Session -DisableNameChecking
Set-OrganizationConfig -AllowPlusAddressInRecipients $true
```
This example for Omnibus GitLab assumes the mailbox `incoming@office365.example.com`:
```ruby
gitlab_rails['incoming_email_enabled'] = true
# The email address including the `%{key}` placeholder that will be replaced
# to reference the item being replied to. The placeholder can be omitted, but if
# present, it must appear in the "user" part of the address (before the `@`).
gitlab_rails['incoming_email_address'] = "incoming+%{key}@office365.example.com"
# Email account username
# Typically this is the userPrincipalName (UPN)
gitlab_rails['incoming_email_email'] = "incoming@office365.example.com"
# Email account password
gitlab_rails['incoming_email_password'] = "[REDACTED]"
# IMAP server host
gitlab_rails['incoming_email_host'] = "outlook.office365.com"
# IMAP server port
gitlab_rails['incoming_email_port'] = 993
# Whether the IMAP server uses SSL
gitlab_rails['incoming_email_ssl'] = true
```
This example for source installs assumes the mailbox `incoming@office365.example.com`:
```yaml
incoming_email:
enabled: true
# The email address including the `%{key}` placeholder that will be replaced
# to reference the item being replied to. The placeholder can be omitted, but
# if present, it must appear in the "user" part of the address (before the `@`).
address: "incoming+%{key}@office365.example.comm"
# Email account username
# Typically this is the userPrincipalName (UPN)
user: "incoming@office365.example.comm"
# Email account password
password: "[REDACTED]"
# IMAP server host
host: "outlook.office365.com"
# IMAP server port
port: 993
# Whether the IMAP server uses SSL
ssl: true
```
##### Catch-all mailbox
This example for Omnibus installs assumes the catch-all mailbox `incoming@office365.example.com`:
```ruby
gitlab_rails['incoming_email_enabled'] = true
# The email address including the `%{key}` placeholder that will be replaced to
# reference the item being replied to. The placeholder can be omitted, but if present,
# it must appear in the "user" part of the address (before the `@`).
gitlab_rails['incoming_email_address'] = "incoming-%{key}@office365.example.com"
# Email account username
# Typically this is the userPrincipalName (UPN)
gitlab_rails['incoming_email_email'] = "incoming@office365.example.com"
# Email account password
gitlab_rails['incoming_email_password'] = "[REDACTED]"
# IMAP server host
gitlab_rails['incoming_email_host'] = "outlook.office365.com"
# IMAP server port
gitlab_rails['incoming_email_port'] = 993
# Whether the IMAP server uses SSL
gitlab_rails['incoming_email_ssl'] = true
```
This example for source installs assumes the catch-all mailbox `incoming@office365.example.com`:
```yaml
incoming_email:
enabled: true
# The email address including the `%{key}` placeholder that will be replaced
# to reference the item being replied to. The placeholder can be omitted, but
# if present, it must appear in the "user" part of the address (before the `@`).
address: "incoming-%{key}@office365.example.com"
# Email account username
# Typically this is the userPrincipalName (UPN)
user: "incoming@ad-domain.example.com"
# Email account password
password: "[REDACTED]"
# IMAP server host
host: "outlook.office365.com"
# IMAP server port
port: 993
# Whether the IMAP server uses SSL
ssl: true
```
##### Dedicated email address
This example for Omnibus installs assumes the dedicated email address `incoming@office365.example.com`:
```ruby
gitlab_rails['incoming_email_enabled'] = true
gitlab_rails['incoming_email_address'] = "incoming@office365.example.com"
# Email account username
# Typically this is the userPrincipalName (UPN)
gitlab_rails['incoming_email_email'] = "incoming@office365.example.com"
# Email account password
gitlab_rails['incoming_email_password'] = "[REDACTED]"
# IMAP server host
gitlab_rails['incoming_email_host'] = "outlook.office365.com"
# IMAP server port
gitlab_rails['incoming_email_port'] = 993
# Whether the IMAP server uses SSL
gitlab_rails['incoming_email_ssl'] = true
```
This example for source installs assumes the dedicated email address `incoming@office365.example.com`:
```yaml
incoming_email:
enabled: true
address: "incoming@office365.example.com"
# Email account username
# Typically this is the userPrincipalName (UPN)
user: "incoming@office365.example.com"
# Email account password
password: "[REDACTED]"
# IMAP server host
host: "outlook.office365.com"
# IMAP server port
port: 993
# Whether the IMAP server uses SSL
ssl: true
```
......@@ -423,7 +423,51 @@ A URL scan allows you to specify which parts of a website are scanned by DAST.
#### Define the URLs to scan
To specify the paths to scan, add a comma-separated list of the paths to the `DAST_PATHS`
URLs to scan can be specified by either of the following methods:
- Use `DAST_PATHS_FILE` environment variable to specify the name of a file containing the paths.
- Use `DAST_PATHS` environment variable to list the paths.
##### Use DAST_PATHS_FILE environment variable
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/258825) in GitLab 13.6.
To define the URLs to scan in a file, create a plain text file with one path per line.
```txt
page1.html
/page2.html
category/shoes/page1.html
```
To scan the URLs in that file, set the environment variable `DAST_PATHS_FILE` to the path of that file.
```yaml
include:
- template: DAST.gitlab-ci.yml
variables:
DAST_PATHS_FILE: url_file.txt
```
By default, DAST scans do not clone the project repository. If the file is checked in to the project, instruct the DAST job to clone the project by setting GIT_STRATEGY to fetch. The file is expected to be in the `/zap/wrk` directory.
```yaml
dast:
script:
- mkdir -p /zap/wrk
- cp url_file.txt /zap/wrk/url_file.txt
- /analyze -t $DAST_WEBSITE
variables:
GIT_STRATEGY: fetch
DAST_PATHS_FILE: url_file.txt
```
##### Use DAST_PATHS environment variable
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/214120) in GitLab 13.4.
To specify the paths to scan in an environment variable, add a comma-separated list of the paths to the `DAST_PATHS`
environment variable. Note that you can only scan paths of a single host.
```yaml
......@@ -434,10 +478,13 @@ variables:
DAST_PATHS=/page1.html,/category1/page1.html,/page3.html
```
When using `DAST_PATHS`, note the following:
When using `DAST_PATHS` and `DAST_PATHS_FILE`, note the following:
- `DAST_WEBSITE` must be defined when using either `DAST_PATHS_FILE` or `DAST_PATHS`. The paths listed in either will use `DAST_WEBSITE` to build the URLs to scan
- Spidering is disabed when `DAST_PATHS` or `DAST_PATHS_FILE` are defined
- `DAST_PATHS_FILE` and `DAST_PATHS` can not be used together
- The `DAST_PATHS` environment variable has a limit of about 130kb. If you have a list or paths
greater than this, you should create multiple DAST jobs and split the paths over each job.
greater than this, use `DAST_PATHS_FILE`.
#### Full Scan
......@@ -498,6 +545,7 @@ DAST can be [configured](#customizing-the-dast-settings) using environment varia
| `DAST_INCLUDE_ALPHA_VULNERABILITIES` | boolean | Set to `true` to include alpha passive and active scan rules. Default: `false`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12652) in GitLab 13.1. |
| `DAST_USE_AJAX_SPIDER` | boolean | Set to `true` to use the AJAX spider in addition to the traditional spider, useful for crawling sites that require JavaScript. Default: `false`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12652) in GitLab 13.1. |
| `DAST_PATHS` | string | Set to a comma-separated list of URLs for DAST to scan. For example, `/page1.html,/category1/page3.html,/page2.html`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/214120) in GitLab 13.4. |
| `DAST_PATHS_FILE` | string | The file path containing the paths within `DAST_WEBSITE` to scan. The file must be plain text with one path per line and be within `/zap/wrk`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/258825) in GitLab 13.6. |
| `DAST_ZAP_CLI_OPTIONS` | string | ZAP server command-line options. For example, `-Xmx3072m` would set the Java maximum memory allocation pool size. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12652) in GitLab 13.1. |
| `DAST_ZAP_LOG_CONFIGURATION` | string | Set to a semicolon-separated list of additional log4j properties for the ZAP Server. For example, `log4j.logger.org.parosproxy.paros.network.HttpSender=DEBUG;log4j.logger.com.crawljax=DEBUG` |
......
......@@ -49,7 +49,7 @@ module Gitlab
return [uri, nil] unless address_info
ip_address = ip_address(address_info)
return [uri, nil] if domain_whitelisted?(uri) || ip_whitelisted?(ip_address, port: get_port(uri))
return [uri, nil] if domain_allowed?(uri) || ip_allowed?(ip_address, port: get_port(uri))
protected_uri_with_hostname = enforce_uri_hostname(ip_address, uri, dns_rebind_protection)
......@@ -114,7 +114,7 @@ module Gitlab
rescue SocketError
# If the dns rebinding protection is not enabled or the domain
# is whitelisted we avoid the dns rebinding checks
return if domain_whitelisted?(uri) || !dns_rebind_protection
return if domain_allowed?(uri) || !dns_rebind_protection
# In the test suite we use a lot of mocked urls that are either invalid or
# don't exist. In order to avoid modifying a ton of tests and factories
......@@ -253,12 +253,12 @@ module Gitlab
(uri.port.blank? || uri.port == config.gitlab_shell.ssh_port)
end
def domain_whitelisted?(uri)
Gitlab::UrlBlockers::UrlWhitelist.domain_whitelisted?(uri.normalized_host, port: get_port(uri))
def domain_allowed?(uri)
Gitlab::UrlBlockers::UrlAllowlist.domain_allowed?(uri.normalized_host, port: get_port(uri))
end
def ip_whitelisted?(ip_address, port: nil)
Gitlab::UrlBlockers::UrlWhitelist.ip_whitelisted?(ip_address, port: port)
def ip_allowed?(ip_address, port: nil)
Gitlab::UrlBlockers::UrlAllowlist.ip_allowed?(ip_address, port: port)
end
def config
......
......@@ -2,7 +2,7 @@
module Gitlab
module UrlBlockers
class DomainWhitelistEntry
class DomainAllowlistEntry
attr_reader :domain, :port
def initialize(domain, port: nil)
......
......@@ -2,7 +2,7 @@
module Gitlab
module UrlBlockers
class IpWhitelistEntry
class IpAllowlistEntry
attr_reader :ip, :port
# Argument ip should be an IPAddr object
......
......@@ -2,43 +2,41 @@
module Gitlab
module UrlBlockers
class UrlWhitelist
class UrlAllowlist
class << self
def ip_whitelisted?(ip_string, port: nil)
def ip_allowed?(ip_string, port: nil)
return false if ip_string.blank?
ip_whitelist, _ = outbound_local_requests_whitelist_arrays
ip_allowlist, _ = outbound_local_requests_allowlist_arrays
ip_obj = Gitlab::Utils.string_to_ip_object(ip_string)
ip_whitelist.any? do |ip_whitelist_entry|
ip_whitelist_entry.match?(ip_obj, port)
ip_allowlist.any? do |ip_allowlist_entry|
ip_allowlist_entry.match?(ip_obj, port)
end
end
def domain_whitelisted?(domain_string, port: nil)
def domain_allowed?(domain_string, port: nil)
return false if domain_string.blank?
_, domain_whitelist = outbound_local_requests_whitelist_arrays
_, domain_allowlist = outbound_local_requests_allowlist_arrays
domain_whitelist.any? do |domain_whitelist_entry|
domain_whitelist_entry.match?(domain_string, port)
domain_allowlist.any? do |domain_allowlist_entry|
domain_allowlist_entry.match?(domain_string, port)
end
end
private
attr_reader :ip_whitelist, :domain_whitelist
# We cannot use Gitlab::CurrentSettings as ApplicationSetting itself
# calls this class. This ends up in a cycle where
# Gitlab::CurrentSettings creates an ApplicationSetting which then
# calls this method.
#
# See https://gitlab.com/gitlab-org/gitlab/issues/9833
def outbound_local_requests_whitelist_arrays
def outbound_local_requests_allowlist_arrays
return [[], []] unless ApplicationSetting.current
ApplicationSetting.current.outbound_local_requests_whitelist_arrays
ApplicationSetting.current.outbound_local_requests_allowlist_arrays
end
end
end
......
......@@ -2753,6 +2753,9 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
msgid "Allowed domains for sign-ups"
msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
......@@ -8698,12 +8701,18 @@ msgstr ""
msgid "Denied authorization of chat nickname %{user_name}."
msgstr ""
msgid "Denied domains for sign-ups"
msgstr ""
msgid "Deny"
msgstr ""
msgid "Deny access request"
msgstr ""
msgid "Denylist file"
msgstr ""
msgid "Dependencies"
msgstr ""
......@@ -9462,6 +9471,9 @@ msgstr ""
msgid "Domain cannot be deleted while associated to one or more clusters."
msgstr ""
msgid "Domain denylist"
msgstr ""
msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
msgstr ""
......
......@@ -2,57 +2,57 @@
require 'spec_helper'
RSpec.describe Gitlab::UrlBlockers::DomainWhitelistEntry do
RSpec.describe Gitlab::UrlBlockers::DomainAllowlistEntry do
let(:domain) { 'www.example.com' }
describe '#initialize' do
it 'initializes without port' do
domain_whitelist_entry = described_class.new(domain)
domain_allowlist_entry = described_class.new(domain)
expect(domain_whitelist_entry.domain).to eq(domain)
expect(domain_whitelist_entry.port).to be(nil)
expect(domain_allowlist_entry.domain).to eq(domain)
expect(domain_allowlist_entry.port).to be(nil)
end
it 'initializes with port' do
port = 8080
domain_whitelist_entry = described_class.new(domain, port: port)
domain_allowlist_entry = described_class.new(domain, port: port)
expect(domain_whitelist_entry.domain).to eq(domain)
expect(domain_whitelist_entry.port).to eq(port)
expect(domain_allowlist_entry.domain).to eq(domain)
expect(domain_allowlist_entry.port).to eq(port)
end
end
describe '#match?' do
it 'matches when domain and port are equal' do
port = 8080
domain_whitelist_entry = described_class.new(domain, port: port)
domain_allowlist_entry = described_class.new(domain, port: port)
expect(domain_whitelist_entry).to be_match(domain, port)
expect(domain_allowlist_entry).to be_match(domain, port)
end
it 'matches any port when port is nil' do
domain_whitelist_entry = described_class.new(domain)
domain_allowlist_entry = described_class.new(domain)
expect(domain_whitelist_entry).to be_match(domain, 8080)
expect(domain_whitelist_entry).to be_match(domain, 9090)
expect(domain_allowlist_entry).to be_match(domain, 8080)
expect(domain_allowlist_entry).to be_match(domain, 9090)
end
it 'does not match when port is present but requested_port is nil' do
domain_whitelist_entry = described_class.new(domain, port: 8080)
domain_allowlist_entry = described_class.new(domain, port: 8080)
expect(domain_whitelist_entry).not_to be_match(domain, nil)
expect(domain_allowlist_entry).not_to be_match(domain, nil)
end
it 'matches when port and requested_port are nil' do
domain_whitelist_entry = described_class.new(domain)
domain_allowlist_entry = described_class.new(domain)
expect(domain_whitelist_entry).to be_match(domain)
expect(domain_allowlist_entry).to be_match(domain)
end
it 'does not match if domain is not equal' do
domain_whitelist_entry = described_class.new(domain)
domain_allowlist_entry = described_class.new(domain)
expect(domain_whitelist_entry).not_to be_match('www.gitlab.com', 8080)
expect(domain_allowlist_entry).not_to be_match('www.gitlab.com', 8080)
end
end
end
......@@ -2,74 +2,74 @@
require 'spec_helper'
RSpec.describe Gitlab::UrlBlockers::IpWhitelistEntry do
RSpec.describe Gitlab::UrlBlockers::IpAllowlistEntry do
let(:ipv4) { IPAddr.new('192.168.1.1') }
describe '#initialize' do
it 'initializes without port' do
ip_whitelist_entry = described_class.new(ipv4)
ip_allowlist_entry = described_class.new(ipv4)
expect(ip_whitelist_entry.ip).to eq(ipv4)
expect(ip_whitelist_entry.port).to be(nil)
expect(ip_allowlist_entry.ip).to eq(ipv4)
expect(ip_allowlist_entry.port).to be(nil)
end
it 'initializes with port' do
port = 8080
ip_whitelist_entry = described_class.new(ipv4, port: port)
ip_allowlist_entry = described_class.new(ipv4, port: port)
expect(ip_whitelist_entry.ip).to eq(ipv4)
expect(ip_whitelist_entry.port).to eq(port)
expect(ip_allowlist_entry.ip).to eq(ipv4)
expect(ip_allowlist_entry.port).to eq(port)
end
end
describe '#match?' do
it 'matches with equivalent IP and port' do
port = 8080
ip_whitelist_entry = described_class.new(ipv4, port: port)
ip_allowlist_entry = described_class.new(ipv4, port: port)
expect(ip_whitelist_entry).to be_match(ipv4.to_s, port)
expect(ip_allowlist_entry).to be_match(ipv4.to_s, port)
end
it 'matches any port when port is nil' do
ip_whitelist_entry = described_class.new(ipv4)
ip_allowlist_entry = described_class.new(ipv4)
expect(ip_whitelist_entry).to be_match(ipv4.to_s, 8080)
expect(ip_whitelist_entry).to be_match(ipv4.to_s, 9090)
expect(ip_allowlist_entry).to be_match(ipv4.to_s, 8080)
expect(ip_allowlist_entry).to be_match(ipv4.to_s, 9090)
end
it 'does not match when port is present but requested_port is nil' do
ip_whitelist_entry = described_class.new(ipv4, port: 8080)
ip_allowlist_entry = described_class.new(ipv4, port: 8080)
expect(ip_whitelist_entry).not_to be_match(ipv4.to_s, nil)
expect(ip_allowlist_entry).not_to be_match(ipv4.to_s, nil)
end
it 'matches when port and requested_port are nil' do
ip_whitelist_entry = described_class.new(ipv4)
ip_allowlist_entry = described_class.new(ipv4)
expect(ip_whitelist_entry).to be_match(ipv4.to_s)
expect(ip_allowlist_entry).to be_match(ipv4.to_s)
end
it 'works with ipv6' do
ipv6 = IPAddr.new('fe80::c800:eff:fe74:8')
ip_whitelist_entry = described_class.new(ipv6)
ip_allowlist_entry = described_class.new(ipv6)
expect(ip_whitelist_entry).to be_match(ipv6.to_s, 8080)
expect(ip_allowlist_entry).to be_match(ipv6.to_s, 8080)
end
it 'matches ipv4 within IPv4 range' do
ipv4_range = IPAddr.new('127.0.0.0/28')
ip_whitelist_entry = described_class.new(ipv4_range)
ip_allowlist_entry = described_class.new(ipv4_range)
expect(ip_whitelist_entry).to be_match(ipv4_range.to_range.last.to_s, 8080)
expect(ip_whitelist_entry).not_to be_match('127.0.1.1', 8080)
expect(ip_allowlist_entry).to be_match(ipv4_range.to_range.last.to_s, 8080)
expect(ip_allowlist_entry).not_to be_match('127.0.1.1', 8080)
end
it 'matches IPv6 within IPv6 range' do
ipv6_range = IPAddr.new('fd84:6d02:f6d8:c89e::/124')
ip_whitelist_entry = described_class.new(ipv6_range)
ip_allowlist_entry = described_class.new(ipv6_range)
expect(ip_whitelist_entry).to be_match(ipv6_range.to_range.last.to_s, 8080)
expect(ip_whitelist_entry).not_to be_match('fd84:6d02:f6d8:f::f', 8080)
expect(ip_allowlist_entry).to be_match(ipv6_range.to_range.last.to_s, 8080)
expect(ip_allowlist_entry).not_to be_match('fd84:6d02:f6d8:f::f', 8080)
end
end
end
......@@ -2,62 +2,62 @@
require 'spec_helper'
RSpec.describe Gitlab::UrlBlockers::UrlWhitelist do
RSpec.describe Gitlab::UrlBlockers::UrlAllowlist do
include StubRequests
let(:whitelist) { [] }
let(:allowlist) { [] }
before do
allow(ApplicationSetting).to receive(:current).and_return(ApplicationSetting.new)
stub_application_setting(outbound_local_requests_whitelist: whitelist)
stub_application_setting(outbound_local_requests_whitelist: allowlist)
end
describe '#domain_whitelisted?' do
let(:whitelist) { ['www.example.com', 'example.com'] }
describe '#domain_allowed?' do
let(:allowlist) { %w[www.example.com example.com] }
it 'returns true if domains present in whitelist' do
not_whitelisted = ['subdomain.example.com', 'example.org']
it 'returns true if domains present in allowlist' do
not_allowed = %w[subdomain.example.com example.org]
aggregate_failures do
whitelist.each do |domain|
expect(described_class).to be_domain_whitelisted(domain)
allowlist.each do |domain|
expect(described_class).to be_domain_allowed(domain)
end
not_whitelisted.each do |domain|
expect(described_class).not_to be_domain_whitelisted(domain)
not_allowed.each do |domain|
expect(described_class).not_to be_domain_allowed(domain)
end
end
end
it 'returns false when domain is blank' do
expect(described_class).not_to be_domain_whitelisted(nil)
expect(described_class).not_to be_domain_allowed(nil)
end
context 'with ports' do
let(:whitelist) { ['example.io:3000'] }
let(:allowlist) { ['example.io:3000'] }
it 'returns true if domain and ports present in whitelist' do
parsed_whitelist = [['example.io', { port: 3000 }]]
not_whitelisted = [
it 'returns true if domain and ports present in allowlist' do
parsed_allowlist = [['example.io', { port: 3000 }]]
not_allowed = [
'example.io',
['example.io', { port: 3001 }]
]
aggregate_failures do
parsed_whitelist.each do |domain_and_port|
expect(described_class).to be_domain_whitelisted(*domain_and_port)
parsed_allowlist.each do |domain_and_port|
expect(described_class).to be_domain_allowed(*domain_and_port)
end
not_whitelisted.each do |domain_and_port|
expect(described_class).not_to be_domain_whitelisted(*domain_and_port)
not_allowed.each do |domain_and_port|
expect(described_class).not_to be_domain_allowed(*domain_and_port)
end
end
end
end
end
describe '#ip_whitelisted?' do
let(:whitelist) do
describe '#ip_allowed?' do
let(:allowlist) do
[
'0.0.0.0',
'127.0.0.1',
......@@ -72,77 +72,77 @@ RSpec.describe Gitlab::UrlBlockers::UrlWhitelist do
]
end
it 'returns true if ips present in whitelist' do
it 'returns true if ips present in allowlist' do
aggregate_failures do
whitelist.each do |ip_address|
expect(described_class).to be_ip_whitelisted(ip_address)
allowlist.each do |ip_address|
expect(described_class).to be_ip_allowed(ip_address)
end
['172.16.2.2', '127.0.0.2', 'fe80::c800:eff:fe74:9'].each do |ip_address|
expect(described_class).not_to be_ip_whitelisted(ip_address)
%w[172.16.2.2 127.0.0.2 fe80::c800:eff:fe74:9].each do |ip_address|
expect(described_class).not_to be_ip_allowed(ip_address)
end
end
end
it 'returns false when ip is blank' do
expect(described_class).not_to be_ip_whitelisted(nil)
expect(described_class).not_to be_ip_allowed(nil)
end
context 'with ip ranges in whitelist' do
context 'with ip ranges in allowlist' do
let(:ipv4_range) { '127.0.0.0/28' }
let(:ipv6_range) { 'fd84:6d02:f6d8:c89e::/124' }
let(:whitelist) do
let(:allowlist) do
[
ipv4_range,
ipv6_range
]
end
it 'does not whitelist ipv4 range when not in whitelist' do
it 'does not allowlist ipv4 range when not in allowlist' do
stub_application_setting(outbound_local_requests_whitelist: [])
IPAddr.new(ipv4_range).to_range.to_a.each do |ip|
expect(described_class).not_to be_ip_whitelisted(ip.to_s)
expect(described_class).not_to be_ip_allowed(ip.to_s)
end
end
it 'whitelists all ipv4s in the range when in whitelist' do
it 'allowlists all ipv4s in the range when in allowlist' do
IPAddr.new(ipv4_range).to_range.to_a.each do |ip|
expect(described_class).to be_ip_whitelisted(ip.to_s)
expect(described_class).to be_ip_allowed(ip.to_s)
end
end
it 'does not whitelist ipv6 range when not in whitelist' do
it 'does not allowlist ipv6 range when not in allowlist' do
stub_application_setting(outbound_local_requests_whitelist: [])
IPAddr.new(ipv6_range).to_range.to_a.each do |ip|
expect(described_class).not_to be_ip_whitelisted(ip.to_s)
expect(described_class).not_to be_ip_allowed(ip.to_s)
end
end
it 'whitelists all ipv6s in the range when in whitelist' do
it 'allowlists all ipv6s in the range when in allowlist' do
IPAddr.new(ipv6_range).to_range.to_a.each do |ip|
expect(described_class).to be_ip_whitelisted(ip.to_s)
expect(described_class).to be_ip_allowed(ip.to_s)
end
end
it 'does not whitelist IPs outside the range' do
expect(described_class).not_to be_ip_whitelisted("fd84:6d02:f6d8:c89e:0:0:1:f")
it 'does not allowlist IPs outside the range' do
expect(described_class).not_to be_ip_allowed("fd84:6d02:f6d8:c89e:0:0:1:f")
expect(described_class).not_to be_ip_whitelisted("127.0.1.15")
expect(described_class).not_to be_ip_allowed("127.0.1.15")
end
end
context 'with ports' do
let(:whitelist) { ['127.0.0.9:3000', '[2001:db8:85a3:8d3:1319:8a2e:370:7348]:443'] }
let(:allowlist) { %w[127.0.0.9:3000 [2001:db8:85a3:8d3:1319:8a2e:370:7348]:443] }
it 'returns true if ip and ports present in whitelist' do
parsed_whitelist = [
it 'returns true if ip and ports present in allowlist' do
parsed_allowlist = [
['127.0.0.9', { port: 3000 }],
['[2001:db8:85a3:8d3:1319:8a2e:370:7348]', { port: 443 }]
]
not_whitelisted = [
not_allowed = [
'127.0.0.9',
['127.0.0.9', { port: 3001 }],
'[2001:db8:85a3:8d3:1319:8a2e:370:7348]',
......@@ -150,12 +150,12 @@ RSpec.describe Gitlab::UrlBlockers::UrlWhitelist do
]
aggregate_failures do
parsed_whitelist.each do |ip_and_port|
expect(described_class).to be_ip_whitelisted(*ip_and_port)
parsed_allowlist.each do |ip_and_port|
expect(described_class).to be_ip_allowed(*ip_and_port)
end
not_whitelisted.each do |ip_and_port|
expect(described_class).not_to be_ip_whitelisted(*ip_and_port)
not_allowed.each do |ip_and_port|
expect(described_class).not_to be_ip_allowed(*ip_and_port)
end
end
end
......
......@@ -91,12 +91,12 @@ RSpec.describe ApplicationSettings::UpdateService do
end
end
context 'when param outbound_local_requests_whitelist_raw is passed' do
context 'when param outbound_local_requests_allowlist_raw is passed' do
before do
application_settings.outbound_local_requests_whitelist = ['127.0.0.1']
end
let(:params) { { outbound_local_requests_whitelist_raw: 'example.com;gitlab.com' } }
let(:params) { { outbound_local_requests_allowlist_raw: 'example.com;gitlab.com' } }
it 'overwrites the existing whitelist' do
expect { subject.execute }.to change {
......
# frozen_string_literal: true
RSpec.shared_examples 'string of domains' do |attribute|
RSpec.shared_examples 'string of domains' do |mapped_name, attribute|
it 'sets single domain' do
setting.method("#{attribute}_raw=").call('example.com')
setting.method("#{mapped_name}_raw=").call('example.com')
expect(setting.method(attribute).call).to eq(['example.com'])
end
it 'sets multiple domains with spaces' do
setting.method("#{attribute}_raw=").call('example.com *.example.com')
setting.method("#{mapped_name}_raw=").call('example.com *.example.com')
expect(setting.method(attribute).call).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")
setting.method("#{mapped_name}_raw=").call("example.com\n *.example.com")
expect(setting.method(attribute).call).to eq(['example.com', '*.example.com'])
end
it 'sets multiple domains with commas' do
setting.method("#{attribute}_raw=").call("example.com, *.example.com")
setting.method("#{mapped_name}_raw=").call("example.com, *.example.com")
expect(setting.method(attribute).call).to eq(['example.com', '*.example.com'])
end
it 'sets multiple domains with semicolon' do
setting.method("#{attribute}_raw=").call("example.com; *.example.com")
setting.method("#{mapped_name}_raw=").call("example.com; *.example.com")
expect(setting.method(attribute).call).to contain_exactly('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")
setting.method("#{mapped_name}_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
it 'removes duplicates' do
setting.method("#{attribute}_raw=").call("example.com; example.com; 127.0.0.1; 127.0.0.1")
setting.method("#{mapped_name}_raw=").call("example.com; example.com; 127.0.0.1; 127.0.0.1")
expect(setting.method(attribute).call).to contain_exactly('example.com', '127.0.0.1')
end
it 'does not fail with garbage values' do
setting.method("#{attribute}_raw=").call("example;34543:garbage:fdh5654;")
setting.method("#{mapped_name}_raw=").call("example;34543:garbage:fdh5654;")
expect(setting.method(attribute).call).to contain_exactly('example', '34543:garbage:fdh5654')
end
it 'does not raise error with nil' do
setting.method("#{attribute}_raw=").call(nil)
setting.method("#{mapped_name}_raw=").call(nil)
expect(setting.method(attribute).call).to eq([])
end
end
RSpec.shared_examples 'application settings examples' do
context 'restricted signup domains' do
it_behaves_like 'string of domains', :domain_whitelist
it_behaves_like 'string of domains', :domain_allowlist, :domain_whitelist
end
context 'blacklisted signup domains' do
it_behaves_like 'string of domains', :domain_blacklist
it_behaves_like 'string of domains', :domain_denylist, :domain_blacklist
it 'sets multiple domain with file' do
setting.domain_blacklist_file = File.open(Rails.root.join('spec/fixtures/', 'domain_blacklist.txt'))
setting.domain_denylist_file = File.open(Rails.root.join('spec/fixtures/', 'domain_denylist.txt'))
expect(setting.domain_blacklist).to contain_exactly('example.com', 'test.com', 'foo.bar')
end
end
context 'outbound_local_requests_whitelist' do
it_behaves_like 'string of domains', :outbound_local_requests_whitelist
it_behaves_like 'string of domains', :outbound_local_requests_allowlist, :outbound_local_requests_whitelist
it 'clears outbound_local_requests_whitelist_arrays memoization' do
setting.outbound_local_requests_whitelist_raw = 'example.com'
it 'clears outbound_local_requests_allowlist_arrays memoization' do
setting.outbound_local_requests_allowlist_raw = 'example.com'
expect(setting.outbound_local_requests_whitelist_arrays).to contain_exactly(
expect(setting.outbound_local_requests_allowlist_arrays).to contain_exactly(
[], [an_object_having_attributes(domain: 'example.com')]
)
setting.outbound_local_requests_whitelist_raw = 'gitlab.com'
expect(setting.outbound_local_requests_whitelist_arrays).to contain_exactly(
setting.outbound_local_requests_allowlist_raw = 'gitlab.com'
expect(setting.outbound_local_requests_allowlist_arrays).to contain_exactly(
[], [an_object_having_attributes(domain: 'gitlab.com')]
)
end
end
context 'outbound_local_requests_whitelist_arrays' do
context 'outbound_local_requests_allowlist_arrays' do
it 'separates the IPs and domains' do
setting.outbound_local_requests_whitelist = [
'192.168.1.1',
......@@ -118,7 +118,7 @@ RSpec.shared_examples 'application settings examples' do
an_object_having_attributes(domain: 'example.com', port: 8080)
]
expect(setting.outbound_local_requests_whitelist_arrays).to contain_exactly(
expect(setting.outbound_local_requests_allowlist_arrays).to contain_exactly(
ip_whitelist, domain_whitelist
)
end
......@@ -139,10 +139,10 @@ RSpec.shared_examples 'application settings examples' do
)
end
it 'clears outbound_local_requests_whitelist_arrays memoization' do
it 'clears outbound_local_requests_allowlist_arrays memoization' do
setting.outbound_local_requests_whitelist = ['example.com']
expect(setting.outbound_local_requests_whitelist_arrays).to contain_exactly(
expect(setting.outbound_local_requests_allowlist_arrays).to contain_exactly(
[],
[an_object_having_attributes(domain: 'example.com')]
)
......@@ -151,7 +151,7 @@ RSpec.shared_examples 'application settings examples' do
['example.com', 'gitlab.com']
)
expect(setting.outbound_local_requests_whitelist_arrays).to contain_exactly(
expect(setting.outbound_local_requests_allowlist_arrays).to contain_exactly(
[],
[an_object_having_attributes(domain: 'example.com'), an_object_having_attributes(domain: 'gitlab.com')]
)
......@@ -163,7 +163,7 @@ RSpec.shared_examples 'application settings examples' do
setting.add_to_outbound_local_requests_whitelist(['gitlab.com'])
expect(setting.outbound_local_requests_whitelist).to contain_exactly('gitlab.com')
expect(setting.outbound_local_requests_whitelist_arrays).to contain_exactly(
expect(setting.outbound_local_requests_allowlist_arrays).to contain_exactly(
[], [an_object_having_attributes(domain: 'gitlab.com')]
)
end
......@@ -171,7 +171,7 @@ RSpec.shared_examples 'application settings examples' do
it 'does not raise error with nil' do
setting.outbound_local_requests_whitelist = nil
expect(setting.outbound_local_requests_whitelist_arrays).to contain_exactly([], [])
expect(setting.outbound_local_requests_allowlist_arrays).to contain_exactly([], [])
end
end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment