Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
gitlab-ce
Commits
f02e89a9
Commit
f02e89a9
authored
Apr 05, 2019
by
GitLab Bot
Browse files
Options
Browse Files
Download
Plain Diff
Automatic merge of gitlab-org/gitlab-ce master
parents
9ab34362
3962b00b
Changes
99
Hide whitespace changes
Inline
Side-by-side
Showing
99 changed files
with
2973 additions
and
35 deletions
+2973
-35
app/assets/stylesheets/pages/projects.scss
app/assets/stylesheets/pages/projects.scss
+4
-0
app/controllers/admin/application_settings_controller.rb
app/controllers/admin/application_settings_controller.rb
+3
-1
app/controllers/concerns/project_unauthorized.rb
app/controllers/concerns/project_unauthorized.rb
+15
-4
app/controllers/projects_controller.rb
app/controllers/projects_controller.rb
+1
-0
app/helpers/application_settings_helper.rb
app/helpers/application_settings_helper.rb
+45
-0
app/helpers/projects_helper.rb
app/helpers/projects_helper.rb
+10
-0
app/models/application_setting.rb
app/models/application_setting.rb
+34
-0
app/models/issue.rb
app/models/issue.rb
+8
-2
app/models/project.rb
app/models/project.rb
+5
-0
app/policies/base_policy.rb
app/policies/base_policy.rb
+8
-1
app/policies/project_policy.rb
app/policies/project_policy.rb
+28
-0
app/services/application_settings/update_service.rb
app/services/application_settings/update_service.rb
+8
-0
app/services/concerns/validates_classification_label.rb
app/services/concerns/validates_classification_label.rb
+27
-0
app/services/projects/create_service.rb
app/services/projects/create_service.rb
+4
-0
app/services/projects/update_service.rb
app/services/projects/update_service.rb
+3
-0
app/validators/x509_certificate_credentials_validator.rb
app/validators/x509_certificate_credentials_validator.rb
+86
-0
app/views/admin/application_settings/_external_authorization_service_form.html.haml
...n_settings/_external_authorization_service_form.html.haml
+51
-0
app/views/admin/application_settings/show.html.haml
app/views/admin/application_settings/show.html.haml
+1
-1
app/views/layouts/nav/_classification_level_banner.html.haml
app/views/layouts/nav/_classification_level_banner.html.haml
+5
-0
app/views/projects/_classification_policy_settings.html.haml
app/views/projects/_classification_policy_settings.html.haml
+8
-0
app/views/projects/edit.html.haml
app/views/projects/edit.html.haml
+1
-1
changelogs/unreleased/57131-external_auth_to_core.yml
changelogs/unreleased/57131-external_auth_to_core.yml
+5
-0
db/migrate/20171211131502_add_external_classification_authorization_settings_to_appliction_settings.rb
...fication_authorization_settings_to_appliction_settings.rb
+29
-0
db/migrate/20171218140451_add_external_authorization_service_classification_label_to_projects.rb
...authorization_service_classification_label_to_projects.rb
+11
-0
db/migrate/20180314100728_add_external_authorization_service_timeout_to_application_settings.rb
..._authorization_service_timeout_to_application_settings.rb
+18
-0
db/migrate/20180315160435_add_external_auth_mutual_tls_fields_to_project_settings.rb
...dd_external_auth_mutual_tls_fields_to_project_settings.rb
+16
-0
lib/api/entities.rb
lib/api/entities.rb
+3
-0
lib/api/helpers/projects_helpers.rb
lib/api/helpers/projects_helpers.rb
+3
-2
lib/api/settings.rb
lib/api/settings.rb
+3
-1
lib/gitlab/external_authorization.rb
lib/gitlab/external_authorization.rb
+40
-0
lib/gitlab/external_authorization/access.rb
lib/gitlab/external_authorization/access.rb
+55
-0
lib/gitlab/external_authorization/cache.rb
lib/gitlab/external_authorization/cache.rb
+62
-0
lib/gitlab/external_authorization/client.rb
lib/gitlab/external_authorization/client.rb
+63
-0
lib/gitlab/external_authorization/config.rb
lib/gitlab/external_authorization/config.rb
+47
-0
lib/gitlab/external_authorization/logger.rb
lib/gitlab/external_authorization/logger.rb
+21
-0
lib/gitlab/external_authorization/response.rb
lib/gitlab/external_authorization/response.rb
+38
-0
spec/controllers/admin/application_settings_controller_spec.rb
...controllers/admin/application_settings_controller_spec.rb
+22
-0
spec/controllers/boards/issues_controller_spec.rb
spec/controllers/boards/issues_controller_spec.rb
+26
-0
spec/controllers/concerns/project_unauthorized_spec.rb
spec/controllers/concerns/project_unauthorized_spec.rb
+51
-0
spec/controllers/dashboard/groups_controller_spec.rb
spec/controllers/dashboard/groups_controller_spec.rb
+31
-19
spec/controllers/dashboard/labels_controller_spec.rb
spec/controllers/dashboard/labels_controller_spec.rb
+5
-1
spec/controllers/dashboard/milestones_controller_spec.rb
spec/controllers/dashboard/milestones_controller_spec.rb
+6
-0
spec/controllers/dashboard/projects_controller_spec.rb
spec/controllers/dashboard/projects_controller_spec.rb
+23
-1
spec/controllers/dashboard/todos_controller_spec.rb
spec/controllers/dashboard/todos_controller_spec.rb
+6
-0
spec/controllers/groups/avatars_controller_spec.rb
spec/controllers/groups/avatars_controller_spec.rb
+10
-0
spec/controllers/groups/boards_controller_spec.rb
spec/controllers/groups/boards_controller_spec.rb
+8
-0
spec/controllers/groups/children_controller_spec.rb
spec/controllers/groups/children_controller_spec.rb
+12
-0
spec/controllers/groups/group_members_controller_spec.rb
spec/controllers/groups/group_members_controller_spec.rb
+86
-0
spec/controllers/groups/labels_controller_spec.rb
spec/controllers/groups/labels_controller_spec.rb
+6
-0
spec/controllers/groups/milestones_controller_spec.rb
spec/controllers/groups/milestones_controller_spec.rb
+6
-0
spec/controllers/groups/settings/ci_cd_controller_spec.rb
spec/controllers/groups/settings/ci_cd_controller_spec.rb
+15
-0
spec/controllers/groups/variables_controller_spec.rb
spec/controllers/groups/variables_controller_spec.rb
+34
-0
spec/controllers/groups_controller_spec.rb
spec/controllers/groups_controller_spec.rb
+96
-0
spec/controllers/projects/boards_controller_spec.rb
spec/controllers/projects/boards_controller_spec.rb
+4
-0
spec/controllers/projects/issues_controller_spec.rb
spec/controllers/projects/issues_controller_spec.rb
+11
-0
spec/controllers/projects_controller_spec.rb
spec/controllers/projects_controller_spec.rb
+32
-0
spec/controllers/search_controller_spec.rb
spec/controllers/search_controller_spec.rb
+39
-0
spec/controllers/users_controller_spec.rb
spec/controllers/users_controller_spec.rb
+12
-0
spec/features/dashboard/group_dashboard_with_external_authorization_service_spec.rb
...oup_dashboard_with_external_authorization_service_spec.rb
+38
-0
spec/features/groups/group_page_with_external_authorization_service_spec.rb
...ps/group_page_with_external_authorization_service_spec.rb
+58
-0
spec/features/projects/classification_label_on_project_pages_spec.rb
...es/projects/classification_label_on_project_pages_spec.rb
+22
-0
spec/features/projects/forks/fork_list_spec.rb
spec/features/projects/forks/fork_list_spec.rb
+35
-0
spec/features/projects/issues/viewing_issues_with_external_authorization_enabled_spec.rb
...iewing_issues_with_external_authorization_enabled_spec.rb
+128
-0
spec/features/projects/settings/external_authorization_service_settings_spec.rb
.../settings/external_authorization_service_settings_spec.rb
+21
-0
spec/features/users/show_spec.rb
spec/features/users/show_spec.rb
+22
-0
spec/finders/issues_finder_spec.rb
spec/finders/issues_finder_spec.rb
+7
-0
spec/finders/labels_finder_spec.rb
spec/finders/labels_finder_spec.rb
+7
-0
spec/finders/merge_requests_finder_spec.rb
spec/finders/merge_requests_finder_spec.rb
+7
-0
spec/finders/snippets_finder_spec.rb
spec/finders/snippets_finder_spec.rb
+32
-0
spec/finders/todos_finder_spec.rb
spec/finders/todos_finder_spec.rb
+7
-0
spec/fixtures/passphrase_x509_certificate.crt
spec/fixtures/passphrase_x509_certificate.crt
+27
-0
spec/fixtures/passphrase_x509_certificate_pk.key
spec/fixtures/passphrase_x509_certificate_pk.key
+54
-0
spec/fixtures/x509_certificate.crt
spec/fixtures/x509_certificate.crt
+27
-0
spec/fixtures/x509_certificate_pk.key
spec/fixtures/x509_certificate_pk.key
+51
-0
spec/lib/gitlab/external_authorization/access_spec.rb
spec/lib/gitlab/external_authorization/access_spec.rb
+142
-0
spec/lib/gitlab/external_authorization/cache_spec.rb
spec/lib/gitlab/external_authorization/cache_spec.rb
+48
-0
spec/lib/gitlab/external_authorization/client_spec.rb
spec/lib/gitlab/external_authorization/client_spec.rb
+97
-0
spec/lib/gitlab/external_authorization/logger_spec.rb
spec/lib/gitlab/external_authorization/logger_spec.rb
+45
-0
spec/lib/gitlab/external_authorization/response_spec.rb
spec/lib/gitlab/external_authorization/response_spec.rb
+52
-0
spec/lib/gitlab/external_authorization_spec.rb
spec/lib/gitlab/external_authorization_spec.rb
+54
-0
spec/models/application_setting_spec.rb
spec/models/application_setting_spec.rb
+47
-1
spec/models/concerns/protected_ref_access_spec.rb
spec/models/concerns/protected_ref_access_spec.rb
+12
-0
spec/models/issue_spec.rb
spec/models/issue_spec.rb
+45
-0
spec/models/project_spec.rb
spec/models/project_spec.rb
+20
-0
spec/policies/base_policy_spec.rb
spec/policies/base_policy_spec.rb
+23
-0
spec/policies/issue_policy_spec.rb
spec/policies/issue_policy_spec.rb
+19
-0
spec/policies/merge_request_policy_spec.rb
spec/policies/merge_request_policy_spec.rb
+19
-0
spec/policies/project_policy_spec.rb
spec/policies/project_policy_spec.rb
+53
-0
spec/requests/api/projects_spec.rb
spec/requests/api/projects_spec.rb
+49
-0
spec/requests/api/settings_spec.rb
spec/requests/api/settings_spec.rb
+33
-0
spec/serializers/group_child_entity_spec.rb
spec/serializers/group_child_entity_spec.rb
+19
-0
spec/services/application_settings/update_service_spec.rb
spec/services/application_settings/update_service_spec.rb
+35
-0
spec/services/notification_service_spec.rb
spec/services/notification_service_spec.rb
+41
-0
spec/services/projects/create_service_spec.rb
spec/services/projects/create_service_spec.rb
+37
-0
spec/services/projects/update_service_spec.rb
spec/services/projects/update_service_spec.rb
+40
-0
spec/support/external_authorization_service_helpers.rb
spec/support/external_authorization_service_helpers.rb
+33
-0
spec/support/shared_examples/controllers/external_authorization_service_shared_examples.rb
...rollers/external_authorization_service_shared_examples.rb
+40
-0
spec/support/shared_examples/finders/finder_with_external_authorization_enabled.rb
...les/finders/finder_with_external_authorization_enabled.rb
+30
-0
spec/validators/x509_certificate_credentials_validator_spec.rb
...validators/x509_certificate_credentials_validator_spec.rb
+87
-0
No files found.
app/assets/stylesheets/pages/projects.scss
View file @
f02e89a9
...
...
@@ -67,6 +67,10 @@
}
}
.classification-label
{
background-color
:
$red-500
;
}
.toggle-wrapper
{
margin-top
:
5px
;
}
...
...
app/controllers/admin/application_settings_controller.rb
View file @
f02e89a9
...
...
@@ -124,7 +124,9 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
end
def
visible_application_setting_attributes
ApplicationSettingsHelper
.
visible_attributes
+
[
[
*::
ApplicationSettingsHelper
.
visible_attributes
,
*::
ApplicationSettingsHelper
.
external_authorization_service_attributes
,
:domain_blacklist_file
,
disabled_oauth_sign_in_sources:
[],
import_sources:
[],
...
...
app/controllers/concerns/project_unauthorized.rb
View file @
f02e89a9
# frozen_string_literal: true
module
ProjectUnauthorized
extend
ActiveSupport
::
Concern
# EE would override this
def
project_unauthorized_proc
# no-op
lambda
do
|
project
|
if
project
label
=
project
.
external_authorization_classification_label
rejection_reason
=
nil
unless
::
Gitlab
::
ExternalAuthorization
.
access_allowed?
(
current_user
,
label
)
rejection_reason
=
::
Gitlab
::
ExternalAuthorization
.
rejection_reason
(
current_user
,
label
)
rejection_reason
||=
_
(
'External authorization denied access to this project'
)
end
if
rejection_reason
access_denied!
(
rejection_reason
)
end
end
end
end
end
...
...
app/controllers/projects_controller.rb
View file @
f02e89a9
...
...
@@ -343,6 +343,7 @@ class ProjectsController < Projects::ApplicationController
:container_registry_enabled
,
:default_branch
,
:description
,
:external_authorization_classification_label
,
:import_url
,
:issues_tracker
,
:issues_tracker_id
,
...
...
app/helpers/application_settings_helper.rb
View file @
f02e89a9
...
...
@@ -119,6 +119,39 @@ module ApplicationSettingsHelper
options_for_select
(
options
,
selected
)
end
def
external_authorization_description
_
(
"If enabled, access to projects will be validated on an external service"
\
" using their classification label."
)
end
def
external_authorization_timeout_help_text
_
(
"Time in seconds GitLab will wait for a response from the external "
\
"service. When the service does not respond in time, access will be "
\
"denied."
)
end
def
external_authorization_url_help_text
_
(
"When leaving the URL blank, classification labels can still be "
\
"specified without disabling cross project features or performing "
\
"external authorization checks."
)
end
def
external_authorization_client_certificate_help_text
_
(
"The X509 Certificate to use when mutual TLS is required to communicate "
\
"with the external authorization service. If left blank, the server "
\
"certificate is still validated when accessing over HTTPS."
)
end
def
external_authorization_client_key_help_text
_
(
"The private key to use when a client certificate is provided. This value "
\
"is encrypted at rest."
)
end
def
external_authorization_client_pass_help_text
_
(
"The passphrase required to decrypt the private key. This is optional "
\
"and the value is encrypted at rest."
)
end
def
visible_attributes
[
:admin_notification_email
,
...
...
@@ -237,6 +270,18 @@ module ApplicationSettingsHelper
]
end
def
external_authorization_service_attributes
[
:external_auth_client_cert
,
:external_auth_client_key
,
:external_auth_client_key_pass
,
:external_authorization_service_default_label
,
:external_authorization_service_enabled
,
:external_authorization_service_timeout
,
:external_authorization_service_url
]
end
def
expanded_by_default?
Rails
.
env
.
test?
end
...
...
app/helpers/projects_helper.rb
View file @
f02e89a9
...
...
@@ -305,6 +305,16 @@ module ProjectsHelper
@path
.
present?
end
def
external_classification_label_help_message
default_label
=
::
Gitlab
::
CurrentSettings
.
current_application_settings
.
external_authorization_service_default_label
s_
(
"ExternalAuthorizationService|When no classification label is set the "
\
"default label `%{default_label}` will be used."
)
%
{
default_label:
default_label
}
end
private
def
get_project_nav_tabs
(
project
,
current_user
)
...
...
app/models/application_setting.rb
View file @
f02e89a9
...
...
@@ -213,6 +213,40 @@ class ApplicationSetting < ApplicationRecord
validate
:terms_exist
,
if: :enforce_terms?
validates
:external_authorization_service_default_label
,
presence:
true
,
if: :external_authorization_service_enabled
validates
:external_authorization_service_url
,
url:
true
,
allow_blank:
true
,
if: :external_authorization_service_enabled
validates
:external_authorization_service_timeout
,
numericality:
{
greater_than:
0
,
less_than_or_equal_to:
10
},
if: :external_authorization_service_enabled
validates
:external_auth_client_key
,
presence:
true
,
if:
->
(
setting
)
{
setting
.
external_auth_client_cert
.
present?
}
validates_with
X509CertificateCredentialsValidator
,
certificate: :external_auth_client_cert
,
pkey: :external_auth_client_key
,
pass: :external_auth_client_key_pass
,
if:
->
(
setting
)
{
setting
.
external_auth_client_cert
.
present?
}
attr_encrypted
:external_auth_client_key
,
mode: :per_attribute_iv
,
key:
Settings
.
attr_encrypted_db_key_base_truncated
,
algorithm:
'aes-256-gcm'
,
encode:
true
attr_encrypted
:external_auth_client_key_pass
,
mode: :per_attribute_iv
,
key:
Settings
.
attr_encrypted_db_key_base_truncated
,
algorithm:
'aes-256-gcm'
,
encode:
true
before_validation
:ensure_uuid!
before_validation
:strip_sentry_values
...
...
app/models/issue.rb
View file @
f02e89a9
...
...
@@ -230,7 +230,13 @@ class Issue < ApplicationRecord
def
visible_to_user?
(
user
=
nil
)
return
false
unless
project
&&
project
.
feature_available?
(
:issues
,
user
)
user
?
readable_by?
(
user
)
:
publicly_visible?
return
publicly_visible?
unless
user
return
false
unless
readable_by?
(
user
)
user
.
full_private_access?
||
::
Gitlab
::
ExternalAuthorization
.
access_allowed?
(
user
,
project
.
external_authorization_classification_label
)
end
def
check_for_spam?
...
...
@@ -298,7 +304,7 @@ class Issue < ApplicationRecord
# Returns `true` if this Issue is visible to everybody.
def
publicly_visible?
project
.
public?
&&
!
confidential?
project
.
public?
&&
!
confidential?
&&
!::
Gitlab
::
ExternalAuthorization
.
enabled?
end
def
expire_etag_cache
...
...
app/models/project.rb
View file @
f02e89a9
...
...
@@ -2062,6 +2062,11 @@ class Project < ApplicationRecord
fetch_branch_allows_collaboration
(
user
,
branch_name
)
end
def
external_authorization_classification_label
super
||
::
Gitlab
::
CurrentSettings
.
current_application_settings
.
external_authorization_service_default_label
end
def
licensed_features
[]
end
...
...
app/policies/base_policy.rb
View file @
f02e89a9
...
...
@@ -22,7 +22,14 @@ class BasePolicy < DeclarativePolicy::Base
Gitlab
::
CurrentSettings
.
current_application_settings
.
restricted_visibility_levels
.
include?
(
Gitlab
::
VisibilityLevel
::
PUBLIC
)
end
# This is prevented in some cases in `gitlab-ee`
condition
(
:external_authorization_enabled
,
scope: :global
,
score:
0
)
do
::
Gitlab
::
ExternalAuthorization
.
perform_check?
end
rule
{
external_authorization_enabled
&
~
full_private_access
}.
policy
do
prevent
:read_cross_project
end
rule
{
default
}.
enable
:read_cross_project
end
...
...
app/policies/project_policy.rb
View file @
f02e89a9
...
...
@@ -89,6 +89,15 @@ class ProjectPolicy < BasePolicy
::
Gitlab
::
CurrentSettings
.
current_application_settings
.
mirror_available
end
with_scope
:subject
condition
(
:classification_label_authorized
,
score:
32
)
do
::
Gitlab
::
ExternalAuthorization
.
access_allowed?
(
@user
,
@subject
.
external_authorization_classification_label
,
@subject
.
full_path
)
end
# We aren't checking `:read_issue` or `:read_merge_request` in this case
# because it could be possible for a user to see an issuable-iid
# (`:read_issue_iid` or `:read_merge_request_iid`) but then wouldn't be
...
...
@@ -417,6 +426,25 @@ class ProjectPolicy < BasePolicy
rule
{
~
can_have_multiple_clusters
&
has_clusters
}.
prevent
:add_cluster
rule
{
~
can?
(
:read_cross_project
)
&
~
classification_label_authorized
}.
policy
do
# Preventing access here still allows the projects to be listed. Listing
# projects doesn't check the `:read_project` ability. But instead counts
# on the `project_authorizations` table.
#
# All other actions should explicitly check read project, which would
# trigger the `classification_label_authorized` condition.
#
# `:read_project_for_iids` is not prevented by this condition, as it is
# used for cross-project reference checks.
prevent
:guest_access
prevent
:public_access
prevent
:public_user_access
prevent
:reporter_access
prevent
:developer_access
prevent
:maintainer_access
prevent
:owner_access
end
private
def
team_member?
...
...
app/services/application_settings/update_service.rb
View file @
f02e89a9
...
...
@@ -2,9 +2,17 @@
module
ApplicationSettings
class
UpdateService
<
ApplicationSettings
::
BaseService
include
ValidatesClassificationLabel
attr_reader
:params
,
:application_setting
def
execute
validate_classification_label
(
application_setting
,
:external_authorization_service_default_label
)
if
application_setting
.
errors
.
any?
return
false
end
update_terms
(
@params
.
delete
(
:terms
))
if
params
.
key?
(
:performance_bar_allowed_group_path
)
...
...
app/services/concerns/validates_classification_label.rb
0 → 100644
View file @
f02e89a9
# frozen_string_literal: true
module
ValidatesClassificationLabel
def
validate_classification_label
(
record
,
attribute_name
)
return
unless
::
Gitlab
::
ExternalAuthorization
.
enabled?
return
unless
classification_label_change?
(
record
,
attribute_name
)
new_label
=
params
[
attribute_name
].
presence
new_label
||=
::
Gitlab
::
CurrentSettings
.
current_application_settings
.
external_authorization_service_default_label
unless
::
Gitlab
::
ExternalAuthorization
.
access_allowed?
(
current_user
,
new_label
)
reason
=
rejection_reason_for_label
(
new_label
)
message
=
s_
(
'ClassificationLabelUnavailable|is unavailable: %{reason}'
)
%
{
reason:
reason
}
record
.
errors
.
add
(
attribute_name
,
message
)
end
end
def
rejection_reason_for_label
(
label
)
reason_from_service
=
::
Gitlab
::
ExternalAuthorization
.
rejection_reason
(
current_user
,
label
).
presence
reason_from_service
||
_
(
"Access to '%{classification_label}' not allowed"
)
%
{
classification_label:
label
}
end
def
classification_label_change?
(
record
,
attribute_name
)
params
.
key?
(
attribute_name
)
||
record
.
new_record?
end
end
app/services/projects/create_service.rb
View file @
f02e89a9
...
...
@@ -2,6 +2,8 @@
module
Projects
class
CreateService
<
BaseService
include
ValidatesClassificationLabel
def
initialize
(
user
,
params
)
@current_user
,
@params
=
user
,
params
.
dup
@skip_wiki
=
@params
.
delete
(
:skip_wiki
)
...
...
@@ -45,6 +47,8 @@ module Projects
relations_block
&
.
call
(
@project
)
yield
(
@project
)
if
block_given?
validate_classification_label
(
@project
,
:external_authorization_classification_label
)
# If the block added errors, don't try to save the project
return
@project
if
@project
.
errors
.
any?
...
...
app/services/projects/update_service.rb
View file @
f02e89a9
...
...
@@ -3,6 +3,7 @@
module
Projects
class
UpdateService
<
BaseService
include
UpdateVisibilityLevel
include
ValidatesClassificationLabel
ValidationError
=
Class
.
new
(
StandardError
)
...
...
@@ -14,6 +15,8 @@ module Projects
yield
if
block_given?
validate_classification_label
(
project
,
:external_authorization_classification_label
)
# If the block added errors, don't try to save the project
return
update_failed!
if
project
.
errors
.
any?
...
...
app/validators/x509_certificate_credentials_validator.rb
0 → 100644
View file @
f02e89a9
# frozen_string_literal: true
# X509CertificateCredentialsValidator
#
# Custom validator to check if certificate-attribute was signed using the
# private key stored in an attrebute.
#
# This can be used as an `ActiveModel::Validator` as follows:
#
# validates_with X509CertificateCredentialsValidator,
# certificate: :client_certificate,
# pkey: :decrypted_private_key,
# pass: :decrypted_passphrase
#
#
# Required attributes:
# - certificate: The name of the accessor that returns the certificate to check
# - pkey: The name of the accessor that returns the private key
# Optional:
# - pass: The name of the accessor that returns the passphrase to decrypt the
# private key
class
X509CertificateCredentialsValidator
<
ActiveModel
::
Validator
def
initialize
(
*
args
)
super
# We can't validate if we don't have a private key or certificate attributes
# in which case this validator is useless.
if
options
[
:pkey
].
nil?
||
options
[
:certificate
].
nil?
raise
'Provide at least `certificate` and `pkey` attribute names'
end
end
def
validate
(
record
)
unless
certificate
=
read_certificate
(
record
)
record
.
errors
.
add
(
options
[
:certificate
],
_
(
'is not a valid X509 certificate.'
))
end
unless
private_key
=
read_private_key
(
record
)
record
.
errors
.
add
(
options
[
:pkey
],
_
(
'could not read private key, is the passphrase correct?'
))
end
return
if
private_key
.
nil?
||
certificate
.
nil?
unless
certificate
.
public_key
.
fingerprint
==
private_key
.
public_key
.
fingerprint
record
.
errors
.
add
(
options
[
:pkey
],
_
(
'private key does not match certificate.'
))
end
end
private
def
read_private_key
(
record
)
OpenSSL
::
PKey
.
read
(
pkey
(
record
).
to_s
,
pass
(
record
).
to_s
)
rescue
OpenSSL
::
PKey
::
PKeyError
,
ArgumentError
# When the primary key could not be read, an ArgumentError is raised.
# This hapens when the passed key is not valid or the passphrase is incorrect
nil
end
def
read_certificate
(
record
)
OpenSSL
::
X509
::
Certificate
.
new
(
certificate
(
record
).
to_s
)
rescue
OpenSSL
::
X509
::
CertificateError
nil
end
# rubocop:disable GitlabSecurity/PublicSend
#
# Allowing `#public_send` here because we don't want the validator to really
# care about the names of the attributes or where they come from.
#
# The credentials are mostly stored encrypted so we need to go through the
# accessors to get the values, `read_attribute` bypasses those.
def
certificate
(
record
)
record
.
public_send
(
options
[
:certificate
])
end
def
pkey
(
record
)
record
.
public_send
(
options
[
:pkey
])
end
def
pass
(
record
)
return
unless
options
[
:pass
]
record
.
public_send
(
options
[
:pass
])
end
# rubocop:enable GitlabSecurity/PublicSend
end
app/views/admin/application_settings/_external_authorization_service_form.html.haml
0 → 100644
View file @
f02e89a9
%section
.settings.as-external-auth.no-animate
#js-external-auth-settings
{
class:
(
'expanded'
if
expanded
)
}
.settings-header
%h4
=
_
(
'External authentication'
)
%button
.btn.js-settings-toggle
{
type:
'button'
}
=
expanded
?
'Collapse'
:
'Expand'
%p
=
_
(
'External Classification Policy Authorization'
)
.settings-content
=
form_for
@application_setting
,
url:
admin_application_settings_path
(
anchor:
'js-external-auth-settings'
),
html:
{
class:
'fieldset-form'
}
do
|
f
|
=
form_errors
(
@application_setting
)
%fieldset
.form-group
.form-check
=
f
.
check_box
:external_authorization_service_enabled
,
class:
'form-check-input'
=
f
.
label
:external_authorization_service_enabled
,
class:
'form-check-label'
do
=
_
(
'Enable classification control using an external service'
)
%span
.form-text.text-muted
=
external_authorization_description
=
link_to
icon
(
'question-circle'
),
help_page_path
(
'user/admin_area/settings/external_authorization'
)
.form-group
=
f
.
label
:external_authorization_service_url
,
_
(
'Service URL'
),
class:
'label-bold'
=
f
.
text_field
:external_authorization_service_url
,
class:
'form-control'
%span
.form-text.text-muted
=
external_authorization_url_help_text
.form-group
=
f
.
label
:external_authorization_service_timeout
,
_
(
'External authorization request timeout'
),
class:
'label-bold'
=
f
.
number_field
:external_authorization_service_timeout
,
class:
'form-control'
,
min:
0.001
,
max:
10
,
step:
0.001
%span
.form-text.text-muted
=
external_authorization_timeout_help_text
=
f
.
label
:external_auth_client_cert
,
_
(
'Client authentication certificate'
),
class:
'label-bold'
=
f
.
text_area
:external_auth_client_cert
,
class:
'form-control'
%span
.form-text.text-muted
=
external_authorization_client_certificate_help_text
.form-group
=
f
.
label
:external_auth_client_key
,
_
(
'Client authentication key'
),
class:
'label-bold'
=
f
.
text_area
:external_auth_client_key
,
class:
'form-control'
%span
.form-text.text-muted
=
external_authorization_client_key_help_text
.form-group
=
f
.
label
:external_auth_client_key_pass
,
_
(
'Client authentication key password'
),
class:
'label-bold'
=
f
.
password_field
:external_auth_client_key_pass
,
class:
'form-control'
%span
.form-text.text-muted
=
external_authorization_client_pass_help_text
.form-group
=
f
.
label
:external_authorization_service_default_label
,
_
(
'Default classification label'
),
class:
'label-bold'
=
f
.
text_field
:external_authorization_service_default_label
,
class:
'form-control'
=
f
.
submit
'Save changes'
,
class:
"btn btn-success"
app/views/admin/application_settings/show.html.haml
View file @
f02e89a9
...
...
@@ -68,7 +68,7 @@
.settings-content
=
render
'terms'
=
render
_if_exists
'admin/application_settings/external_authorization_service_form'
,
expanded:
expanded_by_default?
=
render
'admin/application_settings/external_authorization_service_form'
,
expanded:
expanded_by_default?
%section
.settings.as-terminal.no-animate
#js-terminal-settings
{
class:
(
'expanded'
if
expanded_by_default?
)
}
.settings-header
...
...
app/views/layouts/nav/_classification_level_banner.html.haml
0 → 100644
View file @
f02e89a9
-
if
::
Gitlab
::
ExternalAuthorization
.
enabled?
&&
@project
=
content_for
:header_content
do
%span
.badge.color-label.classification-label.has-tooltip
{
title:
s_
(
'ExternalAuthorizationService|Classification label'
)
}
=
sprite_icon
(
'lock-open'
,
size:
8
,
css_class:
'inline'
)
=
@project
.
external_authorization_classification_label
app/views/projects/_classification_policy_settings.html.haml
0 → 100644
View file @
f02e89a9
-
if
::
Gitlab
::
ExternalAuthorization
.
enabled?
.form-group
=
f
.
label
:external_authorization_classification_label
,
class:
'label-bold'
do
=
s_
(
'ExternalAuthorizationService|Classification Label'
)
%span
.light
(optional)
=
f
.
text_field
:external_authorization_classification_label
,
class:
"form-control"
%span
.form-text.text-muted
=
external_classification_label_help_message
app/views/projects/edit.html.haml
View file @
f02e89a9
...
...
@@ -32,7 +32,7 @@
%span
.light
(optional)
=
f
.
text_area
:description
,
class:
"form-control"
,
rows:
3
,
maxlength:
250
=
render
_if_exists
'projects/classification_policy_settings'
,
f:
f
=
render
'projects/classification_policy_settings'
,
f:
f
=
render_if_exists
'shared/repository_size_limit_setting'
,
form:
f
,
type: :project
...
...
changelogs/unreleased/57131-external_auth_to_core.yml
0 → 100644
View file @
f02e89a9
---
title
:
Move "Authorize project access with external service" to Core
merge_request
:
26823
author
:
type
:
changed
db/migrate/20171211131502_add_external_classification_authorization_settings_to_appliction_settings.rb
0 → 100644
View file @
f02e89a9
class
AddExternalClassificationAuthorizationSettingsToApplictionSettings
<
ActiveRecord
::
Migration
[
4.2
]
include
Gitlab
::
Database
::
MigrationHelpers
DOWNTIME
=
false
disable_ddl_transaction!
def
up
add_column_with_default
:application_settings
,
:external_authorization_service_enabled
,
:boolean
,
default:
false
add_column
:application_settings
,
:external_authorization_service_url
,
:string
add_column
:application_settings
,
:external_authorization_service_default_label
,
:string
end
def
down
remove_column
:application_settings
,
:external_authorization_service_default_label
remove_column
:application_settings
,
:external_authorization_service_url
remove_column
:application_settings
,
:external_authorization_service_enabled
end
end
db/migrate/20171218140451_add_external_authorization_service_classification_label_to_projects.rb
0 → 100644
View file @
f02e89a9
class
AddExternalAuthorizationServiceClassificationLabelToProjects
<
ActiveRecord
::
Migration
[
4.2
]
include
Gitlab
::
Database
::
MigrationHelpers
DOWNTIME
=
false
def
change
add_column
:projects
,
:external_authorization_classification_label
,
:string
end
end
db/migrate/20180314100728_add_external_authorization_service_timeout_to_application_settings.rb
0 → 100644
View file @
f02e89a9
class
AddExternalAuthorizationServiceTimeoutToApplicationSettings
<
ActiveRecord
::
Migration
[
4.2
]
include
Gitlab
::
Database
::
MigrationHelpers
DOWNTIME
=
false
def
up
# We can use the regular `add_column` with a default since `application_settings`
# is a small table.
add_column
:application_settings
,
:external_authorization_service_timeout
,
:float
,
default:
0.5
end
def
down
remove_column
:application_settings
,
:external_authorization_service_timeout
end
end
db/migrate/20180315160435_add_external_auth_mutual_tls_fields_to_project_settings.rb
0 → 100644
View file @
f02e89a9
class
AddExternalAuthMutualTlsFieldsToProjectSettings
<
ActiveRecord
::
Migration
[
4.2
]
DOWNTIME
=
false
def
change
add_column
:application_settings
,
:external_auth_client_cert
,
:text
add_column
:application_settings
,
:encrypted_external_auth_client_key
,
:text
add_column
:application_settings
,
:encrypted_external_auth_client_key_iv
,
:string
add_column
:application_settings
,
:encrypted_external_auth_client_key_pass
,
:string
add_column
:application_settings
,
:encrypted_external_auth_client_key_pass_iv
,
:string
end
end
lib/api/entities.rb
View file @
f02e89a9
...
...
@@ -277,6 +277,7 @@ module API
expose
:statistics
,
using:
'API::Entities::ProjectStatistics'
,
if:
->
(
project
,
options
)
{
options
[
:statistics
]
&&
Ability
.
allowed?
(
options
[
:current_user
],
:read_statistics
,
project
)
}
expose
:external_authorization_classification_label
# rubocop: disable CodeReuse/ActiveRecord
def
self
.
preload_relation
(
projects_relation
,
options
=
{})
...
...
@@ -1116,6 +1117,8 @@ module API
expose
(
:default_snippet_visibility
)
{
|
setting
,
_options
|
Gitlab
::
VisibilityLevel
.
string_level
(
setting
.
default_snippet_visibility
)
}
expose
(
:default_group_visibility
)
{
|
setting
,
_options
|
Gitlab
::
VisibilityLevel
.
string_level
(
setting
.
default_group_visibility
)
}
expose
(
*::
ApplicationSettingsHelper
.
external_authorization_service_attributes
)
# support legacy names, can be removed in v5
expose
:password_authentication_enabled_for_web
,
as: :password_authentication_enabled
expose
:password_authentication_enabled_for_web
,
as: :signin_enabled
...
...
lib/api/helpers/projects_helpers.rb
View file @
f02e89a9
...
...
@@ -29,13 +29,13 @@ module API
optional
:printing_merge_request_link_enabled
,
type:
Boolean
,
desc:
'Show link to create/view merge request when pushing from the command line'
optional
:merge_method
,
type:
String
,
values:
%w(ff rebase_merge merge)
,
desc:
'The merge method used when merging merge requests'
optional
:initialize_with_readme
,
type:
Boolean
,
desc:
"Initialize a project with a README.md"
optional
:external_authorization_classification_label
,
type:
String
,
desc:
'The classification label for the project'
end
if
Gitlab
.
ee?
params
:optional_project_params_ee
do
optional
:repository_storage
,
type:
String
,
desc:
'Which storage shard the repository is on. Available only to admins'
optional
:approvals_before_merge
,
type:
Integer
,
desc:
'How many approvers should approve merge request by default'
optional
:external_authorization_classification_label
,
type:
String
,
desc:
'The classification label for the project'
optional
:mirror
,
type:
Boolean
,
desc:
'Enables pull mirroring in a project'
optional
:mirror_trigger_builds
,
type:
Boolean
,
desc:
'Pull mirroring triggers builds'
end
...
...
@@ -72,7 +72,8 @@ module API
:tag_list
,
:visibility
,
:wiki_enabled
,
:avatar
:avatar
,
:external_authorization_classification_label
]
end
end
...
...
lib/api/settings.rb
View file @
f02e89a9
...
...
@@ -167,7 +167,9 @@ module API
optional
:usage_ping_enabled
,
type:
Boolean
,
desc:
'Every week GitLab will report license usage back to GitLab, Inc.'
end
optional_attributes
=
::
ApplicationSettingsHelper
.
visible_attributes
<<
:performance_bar_allowed_group_id
optional_attributes
=
[
*::
ApplicationSettingsHelper
.
visible_attributes
,
*::
ApplicationSettingsHelper
.
external_authorization_service_attributes
,
:performance_bar_allowed_group_id
]
if
Gitlab
.
ee?
optional_attributes
+=
EE
::
ApplicationSettingsHelper
.
possible_licensed_attributes
...
...
lib/gitlab/external_authorization.rb
0 → 100644
View file @
f02e89a9
# frozen_string_literal: true
module
Gitlab
module
ExternalAuthorization
extend
ExternalAuthorization
::
Config
RequestFailed
=
Class
.
new
(
StandardError
)
def
self
.
access_allowed?
(
user
,
label
,
project_path
=
nil
)
return
true
unless
perform_check?
return
false
unless
user
access_for_user_to_label
(
user
,
label
,
project_path
).
has_access?
end
def
self
.
rejection_reason
(
user
,
label
)
return
unless
enabled?
return
unless
user
access_for_user_to_label
(
user
,
label
,
nil
).
reason
end
def
self
.
access_for_user_to_label
(
user
,
label
,
project_path
)
if
RequestStore
.
active?
RequestStore
.
fetch
(
"external_authorisation:user-
#{
user
.
id
}
:label-
#{
label
}
"
)
do
load_access
(
user
,
label
,
project_path
)
end
else
load_access
(
user
,
label
,
project_path
)
end
end
def
self
.
load_access
(
user
,
label
,
project_path
)
access
=
::
Gitlab
::
ExternalAuthorization
::
Access
.
new
(
user
,
label
).
load!
::
Gitlab
::
ExternalAuthorization
::
Logger
.
log_access
(
access
,
project_path
)
access
end
end
end
lib/gitlab/external_authorization/access.rb
0 → 100644
View file @
f02e89a9
# frozen_string_literal: true
module
Gitlab
module
ExternalAuthorization
class
Access
attr_reader
:user
,
:reason
,
:loaded_at
,
:label
,
:load_type
def
initialize
(
user
,
label
)
@user
,
@label
=
user
,
label
end
def
loaded?
loaded_at
&&
(
loaded_at
>
ExternalAuthorization
::
Cache
::
VALIDITY_TIME
.
ago
)
end
def
has_access?
@access
end
def
load!
load_from_cache
load_from_service
unless
loaded?
self
end
private
def
load_from_cache
@load_type
=
:cache
@access
,
@reason
,
@loaded_at
=
cache
.
load
end
def
load_from_service
@load_type
=
:request
response
=
Client
.
new
(
@user
,
@label
).
request_access
@access
=
response
.
successful?
@reason
=
response
.
reason
@loaded_at
=
Time
.
now
cache
.
store
(
@access
,
@reason
,
@loaded_at
)
if
response
.
valid?
rescue
::
Gitlab
::
ExternalAuthorization
::
RequestFailed
=>
e
@access
=
false
@reason
=
e
.
message
@loaded_at
=
Time
.
now
end
def
cache
@cache
||=
ExternalAuthorization
::
Cache
.
new
(
@user
,
@label
)
end
end
end
end
lib/gitlab/external_authorization/cache.rb
0 → 100644
View file @
f02e89a9
# frozen_string_literal: true
module
Gitlab
module
ExternalAuthorization
class
Cache
VALIDITY_TIME
=
6
.
hours
def
initialize
(
user
,
label
)
@user
,
@label
=
user
,
label
end
def
load
@access
,
@reason
,
@refreshed_at
=
::
Gitlab
::
Redis
::
Cache
.
with
do
|
redis
|
redis
.
hmget
(
cache_key
,
:access
,
:reason
,
:refreshed_at
)
end
[
access
,
reason
,
refreshed_at
]
end
def
store
(
new_access
,
new_reason
,
new_refreshed_at
)
::
Gitlab
::
Redis
::
Cache
.
with
do
|
redis
|
redis
.
pipelined
do
redis
.
mapped_hmset
(
cache_key
,
{
access:
new_access
.
to_s
,
reason:
new_reason
.
to_s
,
refreshed_at:
new_refreshed_at
.
to_s
}
)
redis
.
expire
(
cache_key
,
VALIDITY_TIME
)
end
end
end
private
def
access
::
Gitlab
::
Utils
.
to_boolean
(
@access
)
end
def
reason
# `nil` if the cached value was an empty string
return
unless
@reason
.
present?
@reason
end
def
refreshed_at
# Don't try to parse a time if there was no cache
return
unless
@refreshed_at
.
present?
Time
.
parse
(
@refreshed_at
)
end
def
cache_key
"external_authorization:user-
#{
@user
.
id
}
:label-
#{
@label
}
"
end
end
end
end
lib/gitlab/external_authorization/client.rb
0 → 100644
View file @
f02e89a9
# frozen_string_literal: true
Excon
.
defaults
[
:ssl_verify_peer
]
=
false
module
Gitlab
module
ExternalAuthorization
class
Client
include
ExternalAuthorization
::
Config
REQUEST_HEADERS
=
{
'Content-Type'
=>
'application/json'
,
'Accept'
=>
'application/json'
}.
freeze
def
initialize
(
user
,
label
)
@user
,
@label
=
user
,
label
end
def
request_access
response
=
Excon
.
post
(
service_url
,
post_params
)
::
Gitlab
::
ExternalAuthorization
::
Response
.
new
(
response
)
rescue
Excon
::
Error
=>
e
raise
::
Gitlab
::
ExternalAuthorization
::
RequestFailed
.
new
(
e
)
end
private
def
post_params
params
=
{
headers:
REQUEST_HEADERS
,
body:
body
.
to_json
,
connect_timeout:
timeout
,
read_timeout:
timeout
,
write_timeout:
timeout
}
if
has_tls?
params
[
:client_cert_data
]
=
client_cert
params
[
:client_key_data
]
=
client_key
params
[
:client_key_pass
]
=
client_key_pass
end
params
end
def
body
@body
||=
begin
body
=
{
user_identifier:
@user
.
email
,
project_classification_label:
@label
}
if
@user
.
ldap_identity
body
[
:user_ldap_dn
]
=
@user
.
ldap_identity
.
extern_uid
end
body
end
end
end
end
end
lib/gitlab/external_authorization/config.rb
0 → 100644
View file @
f02e89a9
# frozen_string_literal: true
module
Gitlab
module
ExternalAuthorization
module
Config
extend
self
def
timeout
application_settings
.
external_authorization_service_timeout
end
def
service_url
application_settings
.
external_authorization_service_url
end
def
enabled?
application_settings
.
external_authorization_service_enabled
end
def
perform_check?
enabled?
&&
service_url
.
present?
end
def
client_cert
application_settings
.
external_auth_client_cert
end
def
client_key
application_settings
.
external_auth_client_key
end
def
client_key_pass
application_settings
.
external_auth_client_key_pass
end
def
has_tls?
client_cert
.
present?
&&
client_key
.
present?
end
private
def
application_settings
::
Gitlab
::
CurrentSettings
.
current_application_settings
end
end
end
end
lib/gitlab/external_authorization/logger.rb
0 → 100644
View file @
f02e89a9
# frozen_string_literal: true
module
Gitlab
module
ExternalAuthorization
class
Logger
<
::
Gitlab
::
Logger
def
self
.
log_access
(
access
,
project_path
)
status
=
access
.
has_access?
?
"GRANTED"
:
"DENIED"
message
=
[
"
#{
status
}
#{
access
.
user
.
email
}
access to '
#{
access
.
label
}
'"
]
message
<<
"(
#{
project_path
}
)"
if
project_path
.
present?
message
<<
"-
#{
access
.
load_type
}
#{
access
.
loaded_at
}
"
if
access
.
load_type
==
:cache
info
(
message
.
join
(
' '
))
end
def
self
.
file_name_noext
'external-policy-access-control'
end
end
end
end
lib/gitlab/external_authorization/response.rb
0 → 100644
View file @
f02e89a9
# frozen_string_literal: true
module
Gitlab
module
ExternalAuthorization
class
Response
include
::
Gitlab
::
Utils
::
StrongMemoize
def
initialize
(
excon_response
)
@excon_response
=
excon_response
end
def
valid?
@excon_response
&&
[
200
,
401
,
403
].
include?
(
@excon_response
.
status
)
end
def
successful?
valid?
&&
@excon_response
.
status
==
200
end
def
reason
parsed_response
[
'reason'
]
if
parsed_response
end
private
def
parsed_response
strong_memoize
(
:parsed_response
)
{
parse_response!
}
end
def
parse_response!
JSON
.
parse
(
@excon_response
.
body
)
rescue
JSON
::
JSONError
# The JSON response is optional, so don't fail when it's missing
nil
end
end
end
end
spec/controllers/admin/application_settings_controller_spec.rb
View file @
f02e89a9
...
...
@@ -85,6 +85,28 @@ describe Admin::ApplicationSettingsController do
expect
(
response
).
to
redirect_to
(
admin_application_settings_path
)
expect
(
ApplicationSetting
.
current
.
receive_max_input_size
).
to
eq
(
1024
)
end
context
'external policy classification settings'
do
let
(
:settings
)
do
{
external_authorization_service_enabled:
true
,
external_authorization_service_url:
'https://custom.service/'
,
external_authorization_service_default_label:
'default'
,
external_authorization_service_timeout:
3
,
external_auth_client_cert:
File
.
read
(
'spec/fixtures/passphrase_x509_certificate.crt'
),
external_auth_client_key:
File
.
read
(
'spec/fixtures/passphrase_x509_certificate_pk.key'
),
external_auth_client_key_pass:
"5iveL!fe"
}
end
it
'updates settings when the feature is available'
do
put
:update
,
params:
{
application_setting:
settings
}
settings
.
each
do
|
attribute
,
value
|
expect
(
ApplicationSetting
.
current
.
public_send
(
attribute
)).
to
eq
(
value
)
end
end
end
end
describe
'PUT #reset_registration_token'
do
...
...
spec/controllers/boards/issues_controller_spec.rb
View file @
f02e89a9
require
'spec_helper'
describe
Boards
::
IssuesController
do
include
ExternalAuthorizationServiceHelpers
let
(
:project
)
{
create
(
:project
,
:private
)
}
let
(
:board
)
{
create
(
:board
,
project:
project
)
}
let
(
:user
)
{
create
(
:user
)
}
...
...
@@ -136,6 +138,30 @@ describe Boards::IssuesController do
end
end
context
'with external authorization'
do
before
do
sign_in
(
user
)
enable_external_authorization_service_check
end
it
'returns a 403 for group boards'
do
group
=
create
(
:group
)
group_board
=
create
(
:board
,
group:
group
)
list_issues
(
user:
user
,
board:
group_board
)
expect
(
response
).
to
have_gitlab_http_status
(
403
)
end
it
'is successful for project boards'
do
project_board
=
create
(
:board
,
project:
project
)
list_issues
(
user:
user
,
board:
project_board
)
expect
(
response
).
to
have_gitlab_http_status
(
200
)
end
end
def
list_issues
(
user
:,
board
:,
list:
nil
)
sign_in
(
user
)
...
...
spec/controllers/concerns/project_unauthorized_spec.rb
0 → 100644
View file @
f02e89a9
require
'spec_helper'
describe
ProjectUnauthorized
do
include
ExternalAuthorizationServiceHelpers
let
(
:user
)
{
create
(
:user
)
}
before
do
sign_in
user
end
render_views
describe
'#project_unauthorized_proc'
do
controller
(
::
Projects
::
ApplicationController
)
do
def
show
head
:ok
end
end
let
(
:project
)
{
create
(
:project
)
}
before
do
project
.
add_developer
(
user
)
end
it
'renders a 200 when the service allows access to the project'
do
external_service_allow_access
(
user
,
project
)
get
:show
,
params:
{
namespace_id:
project
.
namespace
.
to_param
,
id:
project
.
to_param
}
expect
(
response
).
to
have_gitlab_http_status
(
200
)
end
it
'renders a 403 when the service denies access to the project'
do
external_service_deny_access
(
user
,
project
)
get
:show
,
params:
{
namespace_id:
project
.
namespace
.
to_param
,
id:
project
.
to_param
}
expect
(
response
).
to
have_gitlab_http_status
(
403
)
expect
(
response
.
body
).
to
match
(
"External authorization denied access to this project"
)
end
it
'renders a 404 when the user cannot see the project at all'
do
other_project
=
create
(
:project
,
:private
)
get
:show
,
params:
{
namespace_id:
other_project
.
namespace
.
to_param
,
id:
other_project
.
to_param
}
expect
(
response
).
to
have_gitlab_http_status
(
404
)
end
end
end
spec/controllers/dashboard/groups_controller_spec.rb
View file @
f02e89a9
require
'spec_helper'
describe
Dashboard
::
GroupsController
do
include
ExternalAuthorizationServiceHelpers
let
(
:user
)
{
create
(
:user
)
}
before
do
...
...
@@ -11,33 +13,43 @@ describe Dashboard::GroupsController do
expect
(
described_class
).
to
include
(
GroupTree
)
end
it
'only includes projects the user is a member of'
do
member_of_group
=
create
(
:group
)
member_of_group
.
add_developer
(
user
)
create
(
:group
,
:public
)
describe
'#index'
do
it
'only includes projects the user is a member of'
do
member_of_group
=
create
(
:group
)
member_of_group
.
add_developer
(
user
)
create
(
:group
,
:public
)
get
:index
get
:index
expect
(
assigns
(
:groups
)).
to
contain_exactly
(
member_of_group
)
end
expect
(
assigns
(
:groups
)).
to
contain_exactly
(
member_of_group
)
end
context
'when rendering an expanded hierarchy with public groups you are not a member of'
,
:nested_groups
do
let!
(
:top_level_result
)
{
create
(
:group
,
name:
'chef-top'
)
}
let!
(
:top_level_a
)
{
create
(
:group
,
name:
'top-a'
)
}
let!
(
:sub_level_result_a
)
{
create
(
:group
,
name:
'chef-sub-a'
,
parent:
top_level_a
)
}
let!
(
:other_group
)
{
create
(
:group
,
name:
'other'
)
}
context
'when rendering an expanded hierarchy with public groups you are not a member of'
,
:nested_groups
do
let!
(
:top_level_result
)
{
create
(
:group
,
name:
'chef-top'
)
}
let!
(
:top_level_a
)
{
create
(
:group
,
name:
'top-a'
)
}
let!
(
:sub_level_result_a
)
{
create
(
:group
,
name:
'chef-sub-a'
,
parent:
top_level_a
)
}
let!
(
:other_group
)
{
create
(
:group
,
name:
'other'
)
}
before
do
top_level_result
.
add_maintainer
(
user
)
top_level_a
.
add_maintainer
(
user
)
before
do
top_level_result
.
add_maintainer
(
user
)
top_level_a
.
add_maintainer
(
user
)
end
it
'renders only groups the user is a member of when searching hierarchy correctly'
do
get
:index
,
params:
{
filter:
'chef'
},
format: :json
expect
(
response
).
to
have_gitlab_http_status
(
200
)
all_groups
=
[
top_level_result
,
top_level_a
,
sub_level_result_a
]
expect
(
assigns
(
:groups
)).
to
contain_exactly
(
*
all_groups
)
end
end
it
'renders only groups the user is a member of when searching hierarchy correctly'
do
get
:index
,
params:
{
filter:
'chef'
},
format: :json
it
'works when the external authorization service is enabled'
do
enable_external_authorization_service_check
get
:index
expect
(
response
).
to
have_gitlab_http_status
(
200
)
all_groups
=
[
top_level_result
,
top_level_a
,
sub_level_result_a
]
expect
(
assigns
(
:groups
)).
to
contain_exactly
(
*
all_groups
)
end
end
end
spec/controllers/dashboard/labels_controller_spec.rb
View file @
f02e89a9
...
...
@@ -13,13 +13,17 @@ describe Dashboard::LabelsController do
describe
"#index"
do
let!
(
:unrelated_label
)
{
create
(
:label
,
project:
create
(
:project
,
:public
))
}
subject
{
get
:index
,
format: :json
}
it
'returns global labels for projects the user has a relationship with'
do
get
:index
,
format: :json
subject
expect
(
json_response
).
to
be_kind_of
(
Array
)
expect
(
json_response
.
size
).
to
eq
(
1
)
expect
(
json_response
[
0
][
"id"
]).
to
be_nil
expect
(
json_response
[
0
][
"title"
]).
to
eq
(
label
.
title
)
end
it_behaves_like
'disabled when using an external authorization service'
end
end
spec/controllers/dashboard/milestones_controller_spec.rb
View file @
f02e89a9
...
...
@@ -81,5 +81,11 @@ describe Dashboard::MilestonesController do
expect
(
response
.
body
).
to
include
(
"Open
\n
<span class=
\"
badge badge-pill
\"
>2</span>"
)
expect
(
response
.
body
).
to
include
(
"Closed
\n
<span class=
\"
badge badge-pill
\"
>0</span>"
)
end
context
'external authorization'
do
subject
{
get
:index
}
it_behaves_like
'disabled when using an external authorization service'
end
end
end
spec/controllers/dashboard/projects_controller_spec.rb
View file @
f02e89a9
require
'spec_helper'
describe
Dashboard
::
ProjectsController
do
it_behaves_like
'authenticates sessionless user'
,
:index
,
:atom
include
ExternalAuthorizationServiceHelpers
describe
'#index'
do
context
'user not logged in'
do
it_behaves_like
'authenticates sessionless user'
,
:index
,
:atom
end
context
'user logged in'
do
before
do
sign_in
create
(
:user
)
end
context
'external authorization'
do
it
'works when the external authorization service is enabled'
do
enable_external_authorization_service_check
get
:index
expect
(
response
).
to
have_gitlab_http_status
(
200
)
end
end
end
end
context
'json requests'
do
render_views
...
...
spec/controllers/dashboard/todos_controller_spec.rb
View file @
f02e89a9
...
...
@@ -105,6 +105,12 @@ describe Dashboard::TodosController do
end
end
end
context
'external authorization'
do
subject
{
get
:index
}
it_behaves_like
'disabled when using an external authorization service'
end
end
describe
'PATCH #restore'
do
...
...
spec/controllers/groups/avatars_controller_spec.rb
View file @
f02e89a9
require
'spec_helper'
describe
Groups
::
AvatarsController
do
include
ExternalAuthorizationServiceHelpers
let
(
:user
)
{
create
(
:user
)
}
let
(
:group
)
{
create
(
:group
,
avatar:
fixture_file_upload
(
"spec/fixtures/dk.png"
,
"image/png"
))
}
...
...
@@ -15,4 +17,12 @@ describe Groups::AvatarsController do
expect
(
@group
.
avatar
.
present?
).
to
be_falsey
expect
(
@group
).
to
be_valid
end
it
'works when external authorization service is enabled'
do
enable_external_authorization_service_check
delete
:destroy
,
params:
{
group_id:
group
}
expect
(
response
).
to
have_gitlab_http_status
(
302
)
end
end
spec/controllers/groups/boards_controller_spec.rb
View file @
f02e89a9
...
...
@@ -82,6 +82,10 @@ describe Groups::BoardsController do
end
end
it_behaves_like
'disabled when using an external authorization service'
do
subject
{
list_boards
}
end
def
list_boards
(
format: :html
)
get
:index
,
params:
{
group_id:
group
},
format:
format
end
...
...
@@ -160,6 +164,10 @@ describe Groups::BoardsController do
end
end
it_behaves_like
'disabled when using an external authorization service'
do
subject
{
read_board
board:
board
}
end
def
read_board
(
board
:,
format: :html
)
get
:show
,
params:
{
group_id:
group
,
...
...
spec/controllers/groups/children_controller_spec.rb
View file @
f02e89a9
require
'spec_helper'
describe
Groups
::
ChildrenController
do
include
ExternalAuthorizationServiceHelpers
let
(
:group
)
{
create
(
:group
,
:public
)
}
let
(
:user
)
{
create
(
:user
)
}
let!
(
:group_member
)
{
create
(
:group_member
,
group:
group
,
user:
user
)
}
...
...
@@ -317,5 +319,15 @@ describe Groups::ChildrenController do
end
end
end
context
'external authorization'
do
it
'works when external authorization service is enabled'
do
enable_external_authorization_service_check
get
:index
,
params:
{
group_id:
group
},
format: :json
expect
(
response
).
to
have_gitlab_http_status
(
200
)
end
end
end
end
spec/controllers/groups/group_members_controller_spec.rb
View file @
f02e89a9
require
'spec_helper'
describe
Groups
::
GroupMembersController
do
include
ExternalAuthorizationServiceHelpers
let
(
:user
)
{
create
(
:user
)
}
let
(
:group
)
{
create
(
:group
,
:public
,
:access_requestable
)
}
let
(
:membership
)
{
create
(
:group_member
,
group:
group
)
}
describe
'GET index'
do
it
'renders index with 200 status code'
do
...
...
@@ -283,4 +286,87 @@ describe Groups::GroupMembersController do
end
end
end
context
'with external authorization enabled'
do
before
do
enable_external_authorization_service_check
group
.
add_owner
(
user
)
sign_in
(
user
)
end
describe
'GET #index'
do
it
'is successful'
do
get
:index
,
params:
{
group_id:
group
}
expect
(
response
).
to
have_gitlab_http_status
(
200
)
end
end
describe
'POST #create'
do
it
'is successful'
do
post
:create
,
params:
{
group_id:
group
,
users:
user
,
access_level:
Gitlab
::
Access
::
GUEST
}
expect
(
response
).
to
have_gitlab_http_status
(
302
)
end
end
describe
'PUT #update'
do
it
'is successful'
do
put
:update
,
params:
{
group_member:
{
access_level:
Gitlab
::
Access
::
GUEST
},
group_id:
group
,
id:
membership
},
format: :js
expect
(
response
).
to
have_gitlab_http_status
(
200
)
end
end
describe
'DELETE #destroy'
do
it
'is successful'
do
delete
:destroy
,
params:
{
group_id:
group
,
id:
membership
}
expect
(
response
).
to
have_gitlab_http_status
(
302
)
end
end
describe
'POST #destroy'
do
it
'is successful'
do
sign_in
(
create
(
:user
))
post
:request_access
,
params:
{
group_id:
group
}
expect
(
response
).
to
have_gitlab_http_status
(
302
)
end
end
describe
'POST #approve_request_access'
do
it
'is successful'
do
access_request
=
create
(
:group_member
,
:access_request
,
group:
group
)
post
:approve_access_request
,
params:
{
group_id:
group
,
id:
access_request
}
expect
(
response
).
to
have_gitlab_http_status
(
302
)
end
end
describe
'DELETE #leave'
do
it
'is successful'
do
group
.
add_owner
(
create
(
:user
))
delete
:leave
,
params:
{
group_id:
group
}
expect
(
response
).
to
have_gitlab_http_status
(
302
)
end
end
describe
'POST #resend_invite'
do
it
'is successful'
do
post
:resend_invite
,
params:
{
group_id:
group
,
id:
membership
}
expect
(
response
).
to
have_gitlab_http_status
(
302
)
end
end
end
end
spec/controllers/groups/labels_controller_spec.rb
View file @
f02e89a9
...
...
@@ -37,6 +37,12 @@ describe Groups::LabelsController do
expect
(
label_ids
).
to
match_array
([
group_label_1
.
title
,
subgroup_label_1
.
title
])
end
end
context
'external authorization'
do
subject
{
get
:index
,
params:
{
group_id:
group
.
to_param
}
}
it_behaves_like
'disabled when using an external authorization service'
end
end
describe
'POST #toggle_subscription'
do
...
...
spec/controllers/groups/milestones_controller_spec.rb
View file @
f02e89a9
...
...
@@ -80,6 +80,12 @@ describe Groups::MilestonesController do
expect
(
response
.
content_type
).
to
eq
'application/json'
end
end
context
'external authorization'
do
subject
{
get
:index
,
params:
{
group_id:
group
.
to_param
}
}
it_behaves_like
'disabled when using an external authorization service'
end
end
describe
'#show'
do
...
...
spec/controllers/groups/settings/ci_cd_controller_spec.rb
View file @
f02e89a9
require
'spec_helper'
describe
Groups
::
Settings
::
CiCdController
do
include
ExternalAuthorizationServiceHelpers
let
(
:group
)
{
create
(
:group
)
}
let
(
:user
)
{
create
(
:user
)
}
...
...
@@ -33,6 +35,19 @@ describe Groups::Settings::CiCdController do
expect
(
response
).
to
have_gitlab_http_status
(
404
)
end
end
context
'external authorization'
do
before
do
enable_external_authorization_service_check
group
.
add_owner
(
user
)
end
it
'renders show with 200 status code'
do
get
:show
,
params:
{
group_id:
group
}
expect
(
response
).
to
have_gitlab_http_status
(
200
)
end
end
end
describe
'PUT #reset_registration_token'
do
...
...
spec/controllers/groups/variables_controller_spec.rb
View file @
f02e89a9
require
'spec_helper'
describe
Groups
::
VariablesController
do
include
ExternalAuthorizationServiceHelpers
let
(
:group
)
{
create
(
:group
)
}
let
(
:user
)
{
create
(
:user
)
}
...
...
@@ -34,4 +36,36 @@ describe Groups::VariablesController do
include_examples
'PATCH #update updates variables'
end
context
'with external authorization enabled'
do
before
do
enable_external_authorization_service_check
end
describe
'GET #show'
do
let!
(
:variable
)
{
create
(
:ci_group_variable
,
group:
group
)
}
it
'is successful'
do
get
:show
,
params:
{
group_id:
group
},
format: :json
expect
(
response
).
to
have_gitlab_http_status
(
200
)
end
end
describe
'PATCH #update'
do
let!
(
:variable
)
{
create
(
:ci_group_variable
,
group:
group
)
}
let
(
:owner
)
{
group
}
it
'is successful'
do
patch
:update
,
params:
{
group_id:
group
,
variables_attributes:
[{
id:
variable
.
id
,
key:
'hello'
}]
},
format: :json
expect
(
response
).
to
have_gitlab_http_status
(
200
)
end
end
end
end
spec/controllers/groups_controller_spec.rb
View file @
f02e89a9
require
'spec_helper'
describe
GroupsController
do
include
ExternalAuthorizationServiceHelpers
let
(
:user
)
{
create
(
:user
)
}
let
(
:admin
)
{
create
(
:admin
)
}
let
(
:group
)
{
create
(
:group
,
:public
)
}
...
...
@@ -697,4 +699,98 @@ describe GroupsController do
end
end
end
describe
'external authorization'
do
before
do
group
.
add_owner
(
user
)
sign_in
(
user
)
end
context
'with external authorization service enabled'
do
before
do
enable_external_authorization_service_check
end
describe
'GET #show'
do
it
'is successful'
do
get
:show
,
params:
{
id:
group
.
to_param
}
expect
(
response
).
to
have_gitlab_http_status
(
200
)
end
it
'does not allow other formats'
do
get
:show
,
params:
{
id:
group
.
to_param
},
format: :atom
expect
(
response
).
to
have_gitlab_http_status
(
403
)
end
end
describe
'GET #edit'
do
it
'is successful'
do
get
:edit
,
params:
{
id:
group
.
to_param
}
expect
(
response
).
to
have_gitlab_http_status
(
200
)
end
end
describe
'GET #new'
do
it
'is successful'
do
get
:new
expect
(
response
).
to
have_gitlab_http_status
(
200
)
end
end
describe
'GET #index'
do
it
'is successful'
do
get
:index
# Redirects to the dashboard
expect
(
response
).
to
have_gitlab_http_status
(
302
)
end
end
describe
'POST #create'
do
it
'creates a group'
do
expect
do
post
:create
,
params:
{
group:
{
name:
'a name'
,
path:
'a-name'
}
}
end
.
to
change
{
Group
.
count
}.
by
(
1
)
end
end
describe
'PUT #update'
do
it
'updates a group'
do
expect
do
put
:update
,
params:
{
id:
group
.
to_param
,
group:
{
name:
'world'
}
}
end
.
to
change
{
group
.
reload
.
name
}
end
end
describe
'DELETE #destroy'
do
it
'deletes the group'
do
delete
:destroy
,
params:
{
id:
group
.
to_param
}
expect
(
response
).
to
have_gitlab_http_status
(
302
)
end
end
end
describe
'GET #activity'
do
subject
{
get
:activity
,
params:
{
id:
group
.
to_param
}
}
it_behaves_like
'disabled when using an external authorization service'
end
describe
'GET #issues'
do
subject
{
get
:issues
,
params:
{
id:
group
.
to_param
}
}
it_behaves_like
'disabled when using an external authorization service'
end
describe
'GET #merge_requests'
do
subject
{
get
:merge_requests
,
params:
{
id:
group
.
to_param
}
}
it_behaves_like
'disabled when using an external authorization service'
end
end
end
spec/controllers/projects/boards_controller_spec.rb
View file @
f02e89a9
...
...
@@ -98,6 +98,10 @@ describe Projects::BoardsController do
end
end
it_behaves_like
'unauthorized when external service denies access'
do
subject
{
list_boards
}
end
def
list_boards
(
format: :html
)
get
:index
,
params:
{
namespace_id:
project
.
namespace
,
...
...
spec/controllers/projects/issues_controller_spec.rb
View file @
f02e89a9
...
...
@@ -127,6 +127,17 @@ describe Projects::IssuesController do
expect
(
assigns
(
:issues
).
size
).
to
eq
(
2
)
end
end
context
'external authorization'
do
before
do
sign_in
user
project
.
add_developer
(
user
)
end
it_behaves_like
'unauthorized when external service denies access'
do
subject
{
get
:index
,
params:
{
namespace_id:
project
.
namespace
,
project_id:
project
}
}
end
end
end
describe
'GET #new'
do
...
...
spec/controllers/projects_controller_spec.rb
View file @
f02e89a9
require
(
'spec_helper'
)
describe
ProjectsController
do
include
ExternalAuthorizationServiceHelpers
include
ProjectForksHelper
let
(
:project
)
{
create
(
:project
)
}
...
...
@@ -430,6 +431,37 @@ describe ProjectsController do
it_behaves_like
'updating a project'
end
context
'as maintainer'
do
before
do
project
.
add_maintainer
(
user
)
sign_in
(
user
)
end
it_behaves_like
'unauthorized when external service denies access'
do
subject
do
put
:update
,
params:
{
namespace_id:
project
.
namespace
,
id:
project
,
project:
{
description:
'Hello world'
}
}
project
.
reload
end
it
'updates when the service allows access'
do
external_service_allow_access
(
user
,
project
)
expect
{
subject
}.
to
change
(
project
,
:description
)
end
it
'does not update when the service rejects access'
do
external_service_deny_access
(
user
,
project
)
expect
{
subject
}.
not_to
change
(
project
,
:description
)
end
end
end
end
describe
'#transfer'
do
...
...
spec/controllers/search_controller_spec.rb
View file @
f02e89a9
require
'spec_helper'
describe
SearchController
do
include
ExternalAuthorizationServiceHelpers
let
(
:user
)
{
create
(
:user
)
}
before
do
...
...
@@ -76,4 +78,41 @@ describe SearchController do
expect
(
assigns
[
:search_objects
].
count
).
to
eq
(
0
)
end
end
context
'with external authorization service enabled'
do
let
(
:project
)
{
create
(
:project
,
namespace:
user
.
namespace
)
}
let
(
:note
)
{
create
(
:note_on_issue
,
project:
project
)
}
before
do
enable_external_authorization_service_check
end
describe
'GET #show'
do
it
'renders a 403 when no project is given'
do
get
:show
,
params:
{
scope:
'notes'
,
search:
note
.
note
}
expect
(
response
).
to
have_gitlab_http_status
(
403
)
end
it
'renders a 200 when a project was set'
do
get
:show
,
params:
{
project_id:
project
.
id
,
scope:
'notes'
,
search:
note
.
note
}
expect
(
response
).
to
have_gitlab_http_status
(
200
)
end
end
describe
'GET #autocomplete'
do
it
'renders a 403 when no project is given'
do
get
:autocomplete
,
params:
{
term:
'hello'
}
expect
(
response
).
to
have_gitlab_http_status
(
403
)
end
it
'renders a 200 when a project was set'
do
get
:autocomplete
,
params:
{
project_id:
project
.
id
,
term:
'hello'
}
expect
(
response
).
to
have_gitlab_http_status
(
200
)
end
end
end
end
spec/controllers/users_controller_spec.rb
View file @
f02e89a9
...
...
@@ -223,6 +223,12 @@ describe UsersController do
end
end
context
'external authorization'
do
subject
{
get
:calendar_activities
,
params:
{
username:
user
.
username
}
}
it_behaves_like
'disabled when using an external authorization service'
end
def
create_push_event
push_data
=
Gitlab
::
DataBuilder
::
Push
.
build_sample
(
project
,
public_user
)
EventCreateService
.
new
.
push
(
project
,
public_user
,
push_data
)
...
...
@@ -286,6 +292,12 @@ describe UsersController do
expect
(
JSON
.
parse
(
response
.
body
)).
to
have_key
(
'html'
)
end
end
context
'external authorization'
do
subject
{
get
:snippets
,
params:
{
username:
user
.
username
}
}
it_behaves_like
'disabled when using an external authorization service'
end
end
describe
'GET #exists'
do
...
...
spec/features/dashboard/group_dashboard_with_external_authorization_service_spec.rb
0 → 100644
View file @
f02e89a9
require
'spec_helper'
describe
'The group dashboard'
do
include
ExternalAuthorizationServiceHelpers
let
(
:user
)
{
create
(
:user
)
}
before
do
sign_in
user
end
describe
'The top navigation'
do
it
'has all the expected links'
do
visit
dashboard_groups_path
within
(
'.navbar'
)
do
expect
(
page
).
to
have_button
(
'Projects'
)
expect
(
page
).
to
have_button
(
'Groups'
)
expect
(
page
).
to
have_link
(
'Activity'
)
expect
(
page
).
to
have_link
(
'Milestones'
)
expect
(
page
).
to
have_link
(
'Snippets'
)
end
end
it
'hides some links when an external authorization service is enabled'
do
enable_external_authorization_service_check
visit
dashboard_groups_path
within
(
'.navbar'
)
do
expect
(
page
).
to
have_button
(
'Projects'
)
expect
(
page
).
to
have_button
(
'Groups'
)
expect
(
page
).
not_to
have_link
(
'Activity'
)
expect
(
page
).
not_to
have_link
(
'Milestones'
)
expect
(
page
).
to
have_link
(
'Snippets'
)
end
end
end
end
spec/features/groups/group_page_with_external_authorization_service_spec.rb
0 → 100644
View file @
f02e89a9
# frozen_string_literal: true
require
'spec_helper'
describe
'The group page'
do
include
ExternalAuthorizationServiceHelpers
let
(
:user
)
{
create
(
:user
)
}
let
(
:group
)
{
create
(
:group
)
}
before
do
sign_in
user
group
.
add_owner
(
user
)
end
def
expect_all_sidebar_links
within
(
'.nav-sidebar'
)
do
expect
(
page
).
to
have_link
(
'Overview'
)
expect
(
page
).
to
have_link
(
'Details'
)
expect
(
page
).
to
have_link
(
'Activity'
)
expect
(
page
).
to
have_link
(
'Issues'
)
expect
(
page
).
to
have_link
(
'Merge Requests'
)
expect
(
page
).
to
have_link
(
'Members'
)
end
end
describe
'The sidebar'
do
it
'has all the expected links'
do
visit
group_path
(
group
)
expect_all_sidebar_links
end
it
'shows all project features when policy control is enabled'
do
stub_application_setting
(
external_authorization_service_enabled:
true
)
visit
group_path
(
group
)
expect_all_sidebar_links
end
it
'hides some links when an external authorization service configured with an url'
do
enable_external_authorization_service_check
visit
group_path
(
group
)
within
(
'.nav-sidebar'
)
do
expect
(
page
).
to
have_link
(
'Overview'
)
expect
(
page
).
to
have_link
(
'Details'
)
expect
(
page
).
not_to
have_link
(
'Activity'
)
expect
(
page
).
not_to
have_link
(
'Contribution Analytics'
)
expect
(
page
).
not_to
have_link
(
'Issues'
)
expect
(
page
).
not_to
have_link
(
'Merge Requests'
)
expect
(
page
).
to
have_link
(
'Members'
)
end
end
end
end
spec/features/projects/classification_label_on_project_pages_spec.rb
0 → 100644
View file @
f02e89a9
# frozen_string_literal: true
require
'spec_helper'
describe
'Classification label on project pages'
do
let
(
:project
)
do
create
(
:project
,
external_authorization_classification_label:
'authorized label'
)
end
let
(
:user
)
{
create
(
:user
)
}
before
do
stub_application_setting
(
external_authorization_service_enabled:
true
)
project
.
add_maintainer
(
user
)
sign_in
(
user
)
end
it
'shows the classification label on the project page'
do
visit
project_path
(
project
)
expect
(
page
).
to
have_content
(
'authorized label'
)
end
end
spec/features/projects/forks/fork_list_spec.rb
0 → 100644
View file @
f02e89a9
require
'spec_helper'
describe
'listing forks of a project'
do
include
ProjectForksHelper
include
ExternalAuthorizationServiceHelpers
let
(
:source
)
{
create
(
:project
,
:public
,
:repository
)
}
let!
(
:fork
)
{
fork_project
(
source
,
nil
,
repository:
true
)
}
let
(
:user
)
{
create
(
:user
)
}
before
do
source
.
add_maintainer
(
user
)
sign_in
(
user
)
end
it
'shows the forked project in the list with commit as description'
do
visit
project_forks_path
(
source
)
page
.
within
(
'li.project-row'
)
do
expect
(
page
).
to
have_content
(
fork
.
full_name
)
expect
(
page
).
to
have_css
(
'a.commit-row-message'
)
end
end
it
'does not show the commit message when an external authorization service is used'
do
enable_external_authorization_service_check
visit
project_forks_path
(
source
)
page
.
within
(
'li.project-row'
)
do
expect
(
page
).
to
have_content
(
fork
.
full_name
)
expect
(
page
).
not_to
have_css
(
'a.commit-row-message'
)
end
end
end
spec/features/projects/issues/viewing_issues_with_external_authorization_enabled_spec.rb
0 → 100644
View file @
f02e89a9
require
'spec_helper'
describe
'viewing an issue with cross project references'
do
include
ExternalAuthorizationServiceHelpers
include
Gitlab
::
Routing
.
url_helpers
let
(
:user
)
{
create
(
:user
)
}
let
(
:other_project
)
do
create
(
:project
,
:public
,
external_authorization_classification_label:
'other_label'
)
end
let
(
:other_issue
)
do
create
(
:issue
,
:closed
,
title:
'I am in another project'
,
project:
other_project
)
end
let
(
:other_confidential_issue
)
do
create
(
:issue
,
:confidential
,
:closed
,
title:
'I am in another project and confidential'
,
project:
other_project
)
end
let
(
:other_merge_request
)
do
create
(
:merge_request
,
:closed
,
title:
'I am a merge request in another project'
,
source_project:
other_project
)
end
let
(
:description_referencing_other_issue
)
do
"Referencing:
#{
other_issue
.
to_reference
(
project
)
}
, "
\
"a confidential issue
#{
confidential_issue
.
to_reference
}
, "
\
"a cross project confidential issue
#{
other_confidential_issue
.
to_reference
(
project
)
}
, and "
\
"a cross project merge request
#{
other_merge_request
.
to_reference
(
project
)
}
"
end
let
(
:project
)
{
create
(
:project
)
}
let
(
:issue
)
do
create
(
:issue
,
project:
project
,
description:
description_referencing_other_issue
)
end
let
(
:confidential_issue
)
do
create
(
:issue
,
:confidential
,
:closed
,
title:
"I am in the same project and confidential"
,
project:
project
)
end
before
do
project
.
add_developer
(
user
)
sign_in
(
user
)
end
it
'shows all information related to the cross project reference'
do
visit
project_issue_path
(
project
,
issue
)
expect
(
page
).
to
have_link
(
"
#{
other_issue
.
to_reference
(
project
)
}
(
#{
other_issue
.
state
}
)"
)
expect
(
page
).
to
have_xpath
(
"//a[@title='
#{
other_issue
.
title
}
']"
)
end
it
'shows a link to the confidential issue in the same project'
do
visit
project_issue_path
(
project
,
issue
)
expect
(
page
).
to
have_link
(
"
#{
confidential_issue
.
to_reference
(
project
)
}
(
#{
confidential_issue
.
state
}
)"
)
expect
(
page
).
to
have_xpath
(
"//a[@title='
#{
confidential_issue
.
title
}
']"
)
end
it
'does not show the link to a cross project confidential issue when the user does not have access'
do
visit
project_issue_path
(
project
,
issue
)
expect
(
page
).
not_to
have_link
(
"
#{
other_confidential_issue
.
to_reference
(
project
)
}
(
#{
other_confidential_issue
.
state
}
)"
)
expect
(
page
).
not_to
have_xpath
(
"//a[@title='
#{
other_confidential_issue
.
title
}
']"
)
end
it
'shows the link to a cross project confidential issue when the user has access'
do
other_project
.
add_developer
(
user
)
visit
project_issue_path
(
project
,
issue
)
expect
(
page
).
to
have_link
(
"
#{
other_confidential_issue
.
to_reference
(
project
)
}
(
#{
other_confidential_issue
.
state
}
)"
)
expect
(
page
).
to
have_xpath
(
"//a[@title='
#{
other_confidential_issue
.
title
}
']"
)
end
context
'when an external authorization service is enabled'
do
before
do
enable_external_authorization_service_check
end
it
'only hits the external service for the project the user is viewing'
do
expect
(
::
Gitlab
::
ExternalAuthorization
)
.
to
receive
(
:access_allowed?
).
with
(
user
,
'default_label'
,
any_args
).
at_least
(
1
).
and_return
(
true
)
expect
(
::
Gitlab
::
ExternalAuthorization
)
.
not_to
receive
(
:access_allowed?
).
with
(
user
,
'other_label'
,
any_args
)
visit
project_issue_path
(
project
,
issue
)
end
it
'shows only the link to the cross project references'
do
visit
project_issue_path
(
project
,
issue
)
expect
(
page
).
to
have_link
(
"
#{
other_issue
.
to_reference
(
project
)
}
"
)
expect
(
page
).
to
have_link
(
"
#{
other_merge_request
.
to_reference
(
project
)
}
"
)
expect
(
page
).
not_to
have_content
(
"
#{
other_issue
.
to_reference
(
project
)
}
(
#{
other_issue
.
state
}
)"
)
expect
(
page
).
not_to
have_xpath
(
"//a[@title='
#{
other_issue
.
title
}
']"
)
expect
(
page
).
not_to
have_content
(
"
#{
other_merge_request
.
to_reference
(
project
)
}
(
#{
other_merge_request
.
state
}
)"
)
expect
(
page
).
not_to
have_xpath
(
"//a[@title='
#{
other_merge_request
.
title
}
']"
)
end
it
'does not link a cross project confidential issue if the user does not have access'
do
visit
project_issue_path
(
project
,
issue
)
expect
(
page
).
not_to
have_link
(
"
#{
other_confidential_issue
.
to_reference
(
project
)
}
"
)
expect
(
page
).
not_to
have_xpath
(
"//a[@title='
#{
other_confidential_issue
.
title
}
']"
)
end
it
'links a cross project confidential issue without exposing information when the user has access'
do
other_project
.
add_developer
(
user
)
visit
project_issue_path
(
project
,
issue
)
expect
(
page
).
to
have_link
(
"
#{
other_confidential_issue
.
to_reference
(
project
)
}
"
)
expect
(
page
).
not_to
have_xpath
(
"//a[@title='
#{
other_confidential_issue
.
title
}
']"
)
end
it
'shows a link to the confidential issue in the same project'
do
visit
project_issue_path
(
project
,
issue
)
expect
(
page
).
to
have_link
(
"
#{
confidential_issue
.
to_reference
(
project
)
}
(
#{
confidential_issue
.
state
}
)"
)
expect
(
page
).
to
have_xpath
(
"//a[@title='
#{
confidential_issue
.
title
}
']"
)
end
end
end
spec/features/projects/settings/external_authorization_service_settings_spec.rb
0 → 100644
View file @
f02e89a9
# frozen_string_literal: true
require
'spec_helper'
describe
'Projects > Settings > External Authorization Classification Label setting'
do
let
(
:user
)
{
create
(
:user
)
}
let
(
:project
)
{
create
(
:project_empty_repo
)
}
before
do
project
.
add_maintainer
(
user
)
sign_in
(
user
)
end
it
'shows the field to set a classification label'
do
stub_application_setting
(
external_authorization_service_enabled:
true
)
visit
edit_project_path
(
project
)
expect
(
page
).
to
have_selector
(
'#project_external_authorization_classification_label'
)
end
end
spec/features/users/show_spec.rb
View file @
f02e89a9
require
'spec_helper'
describe
'User page'
do
include
ExternalAuthorizationServiceHelpers
let
(
:user
)
{
create
(
:user
)
}
context
'with public profile'
do
...
...
@@ -86,4 +88,24 @@ describe 'User page' do
end
end
end
context
'most recent activity'
do
it
'shows the most recent activity'
do
visit
(
user_path
(
user
))
expect
(
page
).
to
have_content
(
'Most Recent Activity'
)
end
context
'when external authorization is enabled'
do
before
do
enable_external_authorization_service_check
end
it
'hides the most recent activity'
do
visit
(
user_path
(
user
))
expect
(
page
).
not_to
have_content
(
'Most Recent Activity'
)
end
end
end
end
spec/finders/issues_finder_spec.rb
View file @
f02e89a9
...
...
@@ -559,6 +559,13 @@ describe IssuesFinder do
expect
(
issues
.
count
).
to
eq
0
end
end
context
'external authorization'
do
it_behaves_like
'a finder with external authorization service'
do
let!
(
:subject
)
{
create
(
:issue
,
project:
project
)
}
let
(
:project_params
)
{
{
project_id:
project
.
id
}
}
end
end
end
describe
'#row_count'
,
:request_store
do
...
...
spec/finders/labels_finder_spec.rb
View file @
f02e89a9
...
...
@@ -226,5 +226,12 @@ describe LabelsFinder do
expect
(
finder
.
execute
).
to
eq
[
project_label_1
]
end
end
context
'external authorization'
do
it_behaves_like
'a finder with external authorization service'
do
let!
(
:subject
)
{
create
(
:label
,
project:
project
)
}
let
(
:project_params
)
{
{
project_id:
project
.
id
}
}
end
end
end
end
spec/finders/merge_requests_finder_spec.rb
View file @
f02e89a9
...
...
@@ -253,6 +253,13 @@ describe MergeRequestsFinder do
expect
(
finder
.
row_count
).
to
eq
(
1
)
end
end
context
'external authorization'
do
it_behaves_like
'a finder with external authorization service'
do
let!
(
:subject
)
{
create
(
:merge_request
,
source_project:
project
)
}
let
(
:project_params
)
{
{
project_id:
project
.
id
}
}
end
end
end
context
'when projects require different access levels for merge requests'
do
...
...
spec/finders/snippets_finder_spec.rb
View file @
f02e89a9
require
'spec_helper'
describe
SnippetsFinder
do
include
ExternalAuthorizationServiceHelpers
include
Gitlab
::
Allowable
describe
'#initialize'
do
...
...
@@ -164,4 +165,35 @@ describe SnippetsFinder do
end
it_behaves_like
'snippet visibility'
context
'external authorization'
do
let
(
:user
)
{
create
(
:user
)
}
let
(
:project
)
{
create
(
:project
)
}
let!
(
:snippet
)
{
create
(
:project_snippet
,
:public
,
project:
project
)
}
before
do
project
.
add_maintainer
(
user
)
end
it_behaves_like
'a finder with external authorization service'
do
let!
(
:subject
)
{
create
(
:project_snippet
,
project:
project
)
}
let
(
:project_params
)
{
{
project:
project
}
}
end
it
'includes the result if the external service allows access'
do
external_service_allow_access
(
user
,
project
)
results
=
described_class
.
new
(
user
,
project:
project
).
execute
expect
(
results
).
to
contain_exactly
(
snippet
)
end
it
'does not include any results if the external service denies access'
do
external_service_deny_access
(
user
,
project
)
results
=
described_class
.
new
(
user
,
project:
project
).
execute
expect
(
results
).
to
be_empty
end
end
end
spec/finders/todos_finder_spec.rb
View file @
f02e89a9
...
...
@@ -47,6 +47,13 @@ describe TodosFinder do
end
end
end
context
'external authorization'
do
it_behaves_like
'a finder with external authorization service'
do
let!
(
:subject
)
{
create
(
:todo
,
project:
project
,
user:
user
)
}
let
(
:project_params
)
{
{
project_id:
project
.
id
}
}
end
end
end
describe
'#sort'
do
...
...
spec/fixtures/passphrase_x509_certificate.crt
0 → 100644
View file @
f02e89a9
-----BEGIN CERTIFICATE-----
MIIEpTCCAo0CAQEwDQYJKoZIhvcNAQEFBQAwFDESMBAGA1UEAwwJYXV0aG9yaXR5
MB4XDTE4MDMyMzE0MDIwOFoXDTE5MDMyMzE0MDIwOFowHTEbMBkGA1UEAwwSZ2l0
bGFiLXBhc3NwaHJhc2VkMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA
zpsWHOewP/khfDsLUWxaRCinrBzVJm2C01bVahKVR3g/JD4vEH901Wod9Pvbh/9e
PEfE+YZmgSUUopbL3JUheMnyW416F43HKE/fPW4+QeuIEceuhCXg20eOXmvnWWNM
0hXZh4hq69rwvMPREC/LkZy/QkTDKhJNLNAqAQu2AJ3C7Yga8hFQYEhx1hpfGtwD
z/Nf3efat9WN/d6yW9hfJ98NCmImTm5l9Pc0YPNWCAf96vsqsNHBrTkFy6CQwkhH
K1ynVYuqnHYxSc4FPCT5SAleD9gR/xFBAHb7pPy4yGxMSEmiWaMjjZCVPsghj1jM
Ej77MTDL3U9LeDfiILhvZ+EeQxqPiFwwG2eaIn3ZEs2Ujvw7Z2VpG9VMcPTnB4jK
ot6qPM1YXnkGWQ6iT0DTPS3h7zg1xIJXI5N2sI6GXuKrXXwZ1wPqzFLKPv+xBjp8
P6dih+EImfReFi9zIO1LqGMY+XmRcqodsb6jzsmBimJkqBtatJM7FuUUUN56wiaj
q9+BWbm+ZdQ2lvqndMljjUjTh6pNERfGAJgkNuLn3X9hXVE0TSpmn0nOgaL5izP3
7FWUt0PTyGgK2zq9SEhZmK2TKckLkKMk/ZBBBVM/nrnjs72IlbsqdcVoTnApytZr
xVYTj1hV7QlAfaU3w/M534qXDiy8+HfX5ksWQMtSklECAwEAATANBgkqhkiG9w0B
AQUFAAOCAgEAMMhzSRq9PqCpui74nwjhmn8Dm2ky7A+MmoXNtk70cS/HWrjzaacb
B/rxsAUp7f0pj4QMMM0ETMFpbNs8+NPd2FRY0PfWE4yyDpvZO2Oj1HZKLHX72Gjn
K5KB9DYlVsXhGPfuFWXpxGWF2Az9hDWnj58M3DOAps+6tHuAtudQUuwf5ENQZWwE
ySpr7yoHm1ykgl0Tsb9ZHi9qLrWRRMNYXRT+gvwP1bba8j9jOtjO/xYiIskwMPLM
W8SFmQxbg0Cvi8Q89PB6zoTNOhPQyoyeSlw9meeZJHAMK2zxeglEm8C4EQ+I9Y6/
yylM5/Sc55TjWAvRFgbsq+OozgMvffk/Q2fzcGF44J9DEQ7nrhmJxJ+X4enLknR5
Hw4+WhdYA+bwjx3YZBNTh9/YMgNPYwQhf5gtcZGTd6X4j6qZfJ6CXBmhkC1Cbfyl
yM7B7i4JAqPWMeDP50pXCgyKlwgw1JuFW+xkbkYQAj7wtggQ6z1Vjb5W8R8kYn9q
LXClVtThEeSV5KkVwNX21aFcUs8qeQ+zsgKqpEyM5oILQQ1gDSxLTtrr2KuN+WJN
wM0acwD45X7gA/aZYpCGkIgHIBq0zIDP1s6IqeebFJjW8lWofhRxOEWomWdRweJG
N7qQ1WCTQxAPGAkDI8QPjaspvnAhFKmpBG/mR5IXLFKDbttu7WNdYDo=
-----END CERTIFICATE-----
spec/fixtures/passphrase_x509_certificate_pk.key
0 → 100644
View file @
f02e89a9
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-128-CBC,79CCB506B0FD42A6F1BAE6D72E1CB20C
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
-----END RSA PRIVATE KEY-----
spec/fixtures/x509_certificate.crt
0 → 100644
View file @
f02e89a9
-----BEGIN CERTIFICATE-----
MIIEnDCCAoQCAQEwDQYJKoZIhvcNAQEFBQAwFDESMBAGA1UEAwwJYXV0aG9yaXR5
MB4XDTE4MDMxOTE1MjYzMloXDTE5MDMxOTE1MjYzMlowFDESMBAGA1UEAwwJbG9j
YWxob3N0MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA+tcM7iphsLlR
ccUph2ixabRYnw1HeLCiA4O9a4O31oVUBuzAn/eVU4jyVWkaBym6MHa8CiDOro9H
OXodITMw+3G1sG/yQZ8Y/5dsOP2hEoSfs63/2FAgFWzrB2HnYSShiN8tBeeDI5cJ
ii4JVMfpfi9cvXZUXFR8+P0XR1HDxx6or6UTK37k2kbDQZ41rv1ng2w0AUZt0LRA
NWVE48zvUWIU0y+2JLP1yhrKj85RRjQc5cMK88zzWSZBcSjDGGeJ4C8B5Zh2gFlQ
+1aJkyyklORR3v/RyYO9prTeXPqQ3x/nNsNkI+cyv0Gle6tk+CkOfE1m0CvNWlNg
b8LdQ0XZsOYLZvxfpHk3gHA5GrHXvn5StkM5xMXpdUCsh22CZZHe/4SeFE64amkf
1/LuqY0LYc5UdG2SeJ0SDauPRAIuAr4OV7+Q/nLdY8haMC6KOtpbAWvKX/Jqq0z1
nUXzQn1JWCNw1QMdq9Uz8wiWOjLTr2D/mIVrVef0pb2mfdtzjzUrYCP0PtnQExPB
rocP6BDXN7Ragcdis5/IfLuCOD6pAkmzy6o8RSvAoEUs9VbPiUfN7WAyU1K1rTYH
KV+zPfWF254nZ2SBeReN9CMKbMJE+TX2chRlq07Q5LDz33h9KXw1LZT8MWRinVJf
RePsQiyHpRBWRG0AhbD+YpiGKHzsat0CAwEAATANBgkqhkiG9w0BAQUFAAOCAgEA
Skp0tbvVsg3RG2pX0GP25j0ix+f78zG0+BJ6LiKGMoCIBtGKitfUjBg83ru/ILpa
fpgrQpNQVUnGQ9tmpnqV605ZBBRUC1CRDsvUnyN6p7+yQAq6Fl+2ZKONHpPk+Bl4
CIewgdkHjTwTpvIM/1DFVCz4R1FxNjY3uqOVcNDczMYEk2Pn2GZNNN35hUHHxWh4
89ZvI+XKuRFZq3cDPA60PySeJJpCRScWGgnkdEX1gTtWH3WUlq9llxIvRexyNyzZ
Yqvcfx5UT75/Pp+JPh9lpUCcKLHeUiadjkiLxu3IcrYa4gYx4lA8jgm7adNEahd0
oMAHoO9DU6XMo7o6tnQH3xQv9RAbQanjuyJR9N7mwmc59bQ6mW+pxCk843GwT73F
slseJ1nE1fQQQD7mn/KGjmeWtxY2ElUjTay9ff9/AgJeQYRW+oH0cSdo8WCpc2+G
+LZtLWfBgFLHseRlmarSe2pP8KmbaTd3q7Bu0GekVQOxYcNX59Pj4muQZDVLh8aX
mSQ+Ifts/ljT649MISHn2AZMR4+BUx63tFcatQhbAGGH5LeFdbaGcaVdsUVyZ9a2
HBmFWNsgEPtcC+WmNzCXbv7jQsLAJXufKG5MnurJgNf/n5uKCmpGsEJDT/KF1k/3
x9YnqM7zTyV6un+LS3HjEJvwQmqPWe+vFAeXWGCoWxE=
-----END CERTIFICATE-----
spec/fixtures/x509_certificate_pk.key
0 → 100644
View file @
f02e89a9
-----BEGIN RSA PRIVATE KEY-----
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
-----END RSA PRIVATE KEY-----
spec/lib/gitlab/external_authorization/access_spec.rb
0 → 100644
View file @
f02e89a9
require
'spec_helper'
describe
Gitlab
::
ExternalAuthorization
::
Access
,
:clean_gitlab_redis_cache
do
subject
(
:access
)
{
described_class
.
new
(
build
(
:user
),
'dummy_label'
)
}
describe
'#loaded?'
do
it
'is `true` when it was loaded recently'
do
Timecop
.
freeze
do
allow
(
access
).
to
receive
(
:loaded_at
).
and_return
(
5
.
minutes
.
ago
)
expect
(
access
).
to
be_loaded
end
end
it
'is `false` when there is no loading time'
do
expect
(
access
).
not_to
be_loaded
end
it
'is `false` when there the result was loaded a long time ago'
do
Timecop
.
freeze
do
allow
(
access
).
to
receive
(
:loaded_at
).
and_return
(
2
.
weeks
.
ago
)
expect
(
access
).
not_to
be_loaded
end
end
end
describe
'load!'
do
let
(
:fake_client
)
{
double
(
'ExternalAuthorization::Client'
)
}
let
(
:fake_response
)
do
double
(
'Response'
,
'successful?'
=>
true
,
'valid?'
=>
true
,
'reason'
=>
nil
)
end
before
do
allow
(
access
).
to
receive
(
:load_from_cache
)
allow
(
fake_client
).
to
receive
(
:request_access
).
and_return
(
fake_response
)
allow
(
Gitlab
::
ExternalAuthorization
::
Client
).
to
receive
(
:new
)
{
fake_client
}
end
context
'when loading from the webservice'
do
it
'loads from the webservice it the cache was empty'
do
expect
(
access
).
to
receive
(
:load_from_cache
)
expect
(
access
).
to
receive
(
:load_from_service
).
and_call_original
access
.
load!
expect
(
access
).
to
be_loaded
end
it
'assigns the accessibility, reason and loaded_at'
do
allow
(
fake_response
).
to
receive
(
:successful?
).
and_return
(
false
)
allow
(
fake_response
).
to
receive
(
:reason
).
and_return
(
'Inaccessible label'
)
access
.
load!
expect
(
access
.
reason
).
to
eq
(
'Inaccessible label'
)
expect
(
access
).
not_to
have_access
expect
(
access
.
loaded_at
).
not_to
be_nil
end
it
'returns itself'
do
expect
(
access
.
load!
).
to
eq
(
access
)
end
it
'stores the result in redis'
do
Timecop
.
freeze
do
fake_cache
=
double
expect
(
fake_cache
).
to
receive
(
:store
).
with
(
true
,
nil
,
Time
.
now
)
expect
(
access
).
to
receive
(
:cache
).
and_return
(
fake_cache
)
access
.
load!
end
end
context
'when the request fails'
do
before
do
allow
(
fake_client
).
to
receive
(
:request_access
)
do
raise
::
Gitlab
::
ExternalAuthorization
::
RequestFailed
.
new
(
'Service unavailable'
)
end
end
it
'is loaded'
do
access
.
load!
expect
(
access
).
to
be_loaded
end
it
'assigns the correct accessibility, reason and loaded_at'
do
access
.
load!
expect
(
access
.
reason
).
to
eq
(
'Service unavailable'
)
expect
(
access
).
not_to
have_access
expect
(
access
.
loaded_at
).
not_to
be_nil
end
it
'does not store the result in redis'
do
fake_cache
=
double
expect
(
fake_cache
).
not_to
receive
(
:store
)
allow
(
access
).
to
receive
(
:cache
).
and_return
(
fake_cache
)
access
.
load!
end
end
end
context
'When loading from cache'
do
let
(
:fake_cache
)
{
double
(
'ExternalAuthorization::Cache'
)
}
before
do
allow
(
access
).
to
receive
(
:cache
).
and_return
(
fake_cache
)
end
it
'does not load from the webservice'
do
Timecop
.
freeze
do
expect
(
fake_cache
).
to
receive
(
:load
).
and_return
([
true
,
nil
,
Time
.
now
])
expect
(
access
).
to
receive
(
:load_from_cache
).
and_call_original
expect
(
access
).
not_to
receive
(
:load_from_service
)
access
.
load!
end
end
it
'loads from the webservice when the cached result was too old'
do
Timecop
.
freeze
do
expect
(
fake_cache
).
to
receive
(
:load
).
and_return
([
true
,
nil
,
2
.
days
.
ago
])
expect
(
access
).
to
receive
(
:load_from_cache
).
and_call_original
expect
(
access
).
to
receive
(
:load_from_service
).
and_call_original
allow
(
fake_cache
).
to
receive
(
:store
)
access
.
load!
end
end
end
end
end
spec/lib/gitlab/external_authorization/cache_spec.rb
0 → 100644
View file @
f02e89a9
require
'spec_helper'
describe
Gitlab
::
ExternalAuthorization
::
Cache
,
:clean_gitlab_redis_cache
do
let
(
:user
)
{
build_stubbed
(
:user
)
}
let
(
:cache_key
)
{
"external_authorization:user-
#{
user
.
id
}
:label-dummy_label"
}
subject
(
:cache
)
{
described_class
.
new
(
user
,
'dummy_label'
)
}
def
read_from_redis
(
key
)
Gitlab
::
Redis
::
Cache
.
with
do
|
redis
|
redis
.
hget
(
cache_key
,
key
)
end
end
def
set_in_redis
(
key
,
value
)
Gitlab
::
Redis
::
Cache
.
with
do
|
redis
|
redis
.
hmset
(
cache_key
,
key
,
value
)
end
end
describe
'#load'
do
it
'reads stored info from redis'
do
Timecop
.
freeze
do
set_in_redis
(
:access
,
false
)
set_in_redis
(
:reason
,
'Access denied for now'
)
set_in_redis
(
:refreshed_at
,
Time
.
now
)
access
,
reason
,
refreshed_at
=
cache
.
load
expect
(
access
).
to
eq
(
false
)
expect
(
reason
).
to
eq
(
'Access denied for now'
)
expect
(
refreshed_at
).
to
be_within
(
1
.
second
).
of
(
Time
.
now
)
end
end
end
describe
'#store'
do
it
'sets the values in redis'
do
Timecop
.
freeze
do
cache
.
store
(
true
,
'the reason'
,
Time
.
now
)
expect
(
read_from_redis
(
:access
)).
to
eq
(
'true'
)
expect
(
read_from_redis
(
:reason
)).
to
eq
(
'the reason'
)
expect
(
read_from_redis
(
:refreshed_at
)).
to
eq
(
Time
.
now
.
to_s
)
end
end
end
end
spec/lib/gitlab/external_authorization/client_spec.rb
0 → 100644
View file @
f02e89a9
require
'spec_helper'
describe
Gitlab
::
ExternalAuthorization
::
Client
do
let
(
:user
)
{
build
(
:user
,
email:
'dummy_user@example.com'
)
}
let
(
:dummy_url
)
{
'https://dummy.net/'
}
subject
(
:client
)
{
described_class
.
new
(
user
,
'dummy_label'
)
}
before
do
stub_application_setting
(
external_authorization_service_url:
dummy_url
)
end
describe
'#request_access'
do
it
'performs requests to the configured endpoint'
do
expect
(
Excon
).
to
receive
(
:post
).
with
(
dummy_url
,
any_args
)
client
.
request_access
end
it
'adds the correct params for the user to the body of the request'
do
expected_body
=
{
user_identifier:
'dummy_user@example.com'
,
project_classification_label:
'dummy_label'
}.
to_json
expect
(
Excon
).
to
receive
(
:post
)
.
with
(
dummy_url
,
hash_including
(
body:
expected_body
))
client
.
request_access
end
it
'respects the the timeout'
do
stub_application_setting
(
external_authorization_service_timeout:
3
)
expect
(
Excon
).
to
receive
(
:post
).
with
(
dummy_url
,
hash_including
(
connect_timeout:
3
,
read_timeout:
3
,
write_timeout:
3
))
client
.
request_access
end
it
'adds the mutual tls params when they are present'
do
stub_application_setting
(
external_auth_client_cert:
'the certificate data'
,
external_auth_client_key:
'the key data'
,
external_auth_client_key_pass:
'open sesame'
)
expected_params
=
{
client_cert_data:
'the certificate data'
,
client_key_data:
'the key data'
,
client_key_pass:
'open sesame'
}
expect
(
Excon
).
to
receive
(
:post
).
with
(
dummy_url
,
hash_including
(
expected_params
))
client
.
request_access
end
it
'returns an expected response'
do
expect
(
Excon
).
to
receive
(
:post
)
expect
(
client
.
request_access
)
.
to
be_kind_of
(
::
Gitlab
::
ExternalAuthorization
::
Response
)
end
it
'wraps exceptions if the request fails'
do
expect
(
Excon
).
to
receive
(
:post
)
{
raise
Excon
::
Error
.
new
(
'the request broke'
)
}
expect
{
client
.
request_access
}
.
to
raise_error
(
::
Gitlab
::
ExternalAuthorization
::
RequestFailed
)
end
describe
'for ldap users'
do
let
(
:user
)
do
create
(
:omniauth_user
,
email:
'dummy_user@example.com'
,
extern_uid:
'external id'
,
provider:
'ldapprovider'
)
end
it
'includes the ldap dn for ldap users'
do
expected_body
=
{
user_identifier:
'dummy_user@example.com'
,
project_classification_label:
'dummy_label'
,
user_ldap_dn:
'external id'
}.
to_json
expect
(
Excon
).
to
receive
(
:post
)
.
with
(
dummy_url
,
hash_including
(
body:
expected_body
))
client
.
request_access
end
end
end
end
spec/lib/gitlab/external_authorization/logger_spec.rb
0 → 100644
View file @
f02e89a9
require
'spec_helper'
describe
Gitlab
::
ExternalAuthorization
::
Logger
do
let
(
:request_time
)
{
Time
.
parse
(
'2018-03-26 20:22:15'
)
}
def
fake_access
(
has_access
,
user
,
load_type
=
:request
)
access
=
double
(
'access'
)
allow
(
access
).
to
receive_messages
(
user:
user
,
has_access?:
has_access
,
loaded_at:
request_time
,
label:
'dummy_label'
,
load_type:
load_type
)
access
end
describe
'.log_access'
do
it
'logs a nice message for an access request'
do
expected_message
=
"GRANTED admin@example.com access to 'dummy_label' (the/project/path)"
fake_access
=
fake_access
(
true
,
build
(
:user
,
email:
'admin@example.com'
))
expect
(
described_class
).
to
receive
(
:info
).
with
(
expected_message
)
described_class
.
log_access
(
fake_access
,
'the/project/path'
)
end
it
'does not trip without a project path'
do
expected_message
=
"DENIED admin@example.com access to 'dummy_label'"
fake_access
=
fake_access
(
false
,
build
(
:user
,
email:
'admin@example.com'
))
expect
(
described_class
).
to
receive
(
:info
).
with
(
expected_message
)
described_class
.
log_access
(
fake_access
,
nil
)
end
it
'adds the load time for cached accesses'
do
expected_message
=
"DENIED admin@example.com access to 'dummy_label' - cache
#{
request_time
}
"
fake_access
=
fake_access
(
false
,
build
(
:user
,
email:
'admin@example.com'
),
:cache
)
expect
(
described_class
).
to
receive
(
:info
).
with
(
expected_message
)
described_class
.
log_access
(
fake_access
,
nil
)
end
end
end
spec/lib/gitlab/external_authorization/response_spec.rb
0 → 100644
View file @
f02e89a9
require
'spec_helper'
describe
Gitlab
::
ExternalAuthorization
::
Response
do
let
(
:excon_response
)
{
double
}
subject
(
:response
)
{
described_class
.
new
(
excon_response
)
}
describe
'#valid?'
do
it
'is valid for 200, 401, and 403 responses'
do
[
200
,
401
,
403
].
each
do
|
status
|
allow
(
excon_response
).
to
receive
(
:status
).
and_return
(
status
)
expect
(
response
).
to
be_valid
end
end
it
"is invalid for other statuses"
do
expect
(
excon_response
).
to
receive
(
:status
).
and_return
(
500
)
expect
(
response
).
not_to
be_valid
end
end
describe
'#reason'
do
it
'returns a reason if it was included in the response body'
do
expect
(
excon_response
).
to
receive
(
:body
).
and_return
({
reason:
'Not authorized'
}.
to_json
)
expect
(
response
.
reason
).
to
eq
(
'Not authorized'
)
end
it
'returns nil when there was no body'
do
expect
(
excon_response
).
to
receive
(
:body
).
and_return
(
''
)
expect
(
response
.
reason
).
to
eq
(
nil
)
end
end
describe
'#successful?'
do
it
'is `true` if the status is 200'
do
allow
(
excon_response
).
to
receive
(
:status
).
and_return
(
200
)
expect
(
response
).
to
be_successful
end
it
'is `false` if the status is 401 or 403'
do
[
401
,
403
].
each
do
|
status
|
allow
(
excon_response
).
to
receive
(
:status
).
and_return
(
status
)
expect
(
response
).
not_to
be_successful
end
end
end
end
spec/lib/gitlab/external_authorization_spec.rb
0 → 100644
View file @
f02e89a9
require
'spec_helper'
describe
Gitlab
::
ExternalAuthorization
,
:request_store
do
include
ExternalAuthorizationServiceHelpers
let
(
:user
)
{
build
(
:user
)
}
let
(
:label
)
{
'dummy_label'
}
describe
'#access_allowed?'
do
it
'is always true when the feature is disabled'
do
# Not using `stub_application_setting` because the method is prepended in
# `EE::ApplicationSetting` which breaks when using `any_instance`
# https://gitlab.com/gitlab-org/gitlab-ce/issues/33587
expect
(
::
Gitlab
::
CurrentSettings
.
current_application_settings
)
.
to
receive
(
:external_authorization_service_enabled
)
{
false
}
expect
(
described_class
).
not_to
receive
(
:access_for_user_to_label
)
expect
(
described_class
.
access_allowed?
(
user
,
label
)).
to
be_truthy
end
end
describe
'#rejection_reason'
do
it
'is always nil when the feature is disabled'
do
expect
(
::
Gitlab
::
CurrentSettings
.
current_application_settings
)
.
to
receive
(
:external_authorization_service_enabled
)
{
false
}
expect
(
described_class
).
not_to
receive
(
:access_for_user_to_label
)
expect
(
described_class
.
rejection_reason
(
user
,
label
)).
to
be_nil
end
end
describe
'#access_for_user_to_label'
do
it
'only loads the access once per request'
do
enable_external_authorization_service_check
expect
(
::
Gitlab
::
ExternalAuthorization
::
Access
)
.
to
receive
(
:new
).
with
(
user
,
label
).
once
.
and_call_original
2
.
times
{
described_class
.
access_for_user_to_label
(
user
,
label
,
nil
)
}
end
it
'logs the access request once per request'
do
expect
(
::
Gitlab
::
ExternalAuthorization
::
Logger
)
.
to
receive
(
:log_access
)
.
with
(
an_instance_of
(
::
Gitlab
::
ExternalAuthorization
::
Access
),
'the/project/path'
)
.
once
2
.
times
{
described_class
.
access_for_user_to_label
(
user
,
label
,
'the/project/path'
)
}
end
end
end
spec/models/application_setting_spec.rb
View file @
f02e89a9
...
...
@@ -3,7 +3,7 @@
require
'spec_helper'
describe
ApplicationSetting
do
le
t
(
:setting
)
{
described_class
.
create_from_defaults
}
subjec
t
(
:setting
)
{
described_class
.
create_from_defaults
}
it
{
include
(
CacheableAttributes
)
}
it
{
include
(
ApplicationSettingImplementation
)
}
...
...
@@ -284,6 +284,52 @@ describe ApplicationSetting do
expect
(
subject
).
to
be_valid
end
end
describe
'when external authorization service is enabled'
do
before
do
setting
.
external_authorization_service_enabled
=
true
end
it
{
is_expected
.
not_to
allow_value
(
'not a URL'
).
for
(
:external_authorization_service_url
)
}
it
{
is_expected
.
to
allow_value
(
'https://example.com'
).
for
(
:external_authorization_service_url
)
}
it
{
is_expected
.
to
allow_value
(
''
).
for
(
:external_authorization_service_url
)
}
it
{
is_expected
.
not_to
allow_value
(
nil
).
for
(
:external_authorization_service_default_label
)
}
it
{
is_expected
.
not_to
allow_value
(
11
).
for
(
:external_authorization_service_timeout
)
}
it
{
is_expected
.
not_to
allow_value
(
0
).
for
(
:external_authorization_service_timeout
)
}
it
{
is_expected
.
not_to
allow_value
(
'not a certificate'
).
for
(
:external_auth_client_cert
)
}
it
{
is_expected
.
to
allow_value
(
''
).
for
(
:external_auth_client_cert
)
}
it
{
is_expected
.
to
allow_value
(
''
).
for
(
:external_auth_client_key
)
}
context
'when setting a valid client certificate for external authorization'
do
let
(
:certificate_data
)
{
File
.
read
(
'spec/fixtures/passphrase_x509_certificate.crt'
)
}
before
do
setting
.
external_auth_client_cert
=
certificate_data
end
it
'requires a valid client key when a certificate is set'
do
expect
(
setting
).
not_to
allow_value
(
'fefefe'
).
for
(
:external_auth_client_key
)
end
it
'requires a matching certificate'
do
other_private_key
=
File
.
read
(
'spec/fixtures/x509_certificate_pk.key'
)
expect
(
setting
).
not_to
allow_value
(
other_private_key
).
for
(
:external_auth_client_key
)
end
it
'the credentials are valid when the private key can be read and matches the certificate'
do
tls_attributes
=
[
:external_auth_client_key_pass
,
:external_auth_client_key
,
:external_auth_client_cert
]
setting
.
external_auth_client_key
=
File
.
read
(
'spec/fixtures/passphrase_x509_certificate_pk.key'
)
setting
.
external_auth_client_key_pass
=
'5iveL!fe'
setting
.
validate
expect
(
setting
.
errors
).
not_to
include
(
*
tls_attributes
)
end
end
end
end
context
'restrict creating duplicates'
do
...
...
spec/models/concerns/protected_ref_access_spec.rb
View file @
f02e89a9
...
...
@@ -3,6 +3,8 @@
require
'spec_helper'
describe
ProtectedRefAccess
do
include
ExternalAuthorizationServiceHelpers
subject
(
:protected_ref_access
)
do
create
(
:protected_branch
,
:maintainers_can_push
).
push_access_levels
.
first
end
...
...
@@ -29,5 +31,15 @@ describe ProtectedRefAccess do
expect
(
protected_ref_access
.
check_access
(
developer
)).
to
be_falsy
end
context
'external authorization'
do
it
'is false if external authorization denies access'
do
maintainer
=
create
(
:user
)
project
.
add_maintainer
(
maintainer
)
external_service_deny_access
(
maintainer
,
project
)
expect
(
protected_ref_access
.
check_access
(
maintainer
)).
to
be_falsey
end
end
end
end
spec/models/issue_spec.rb
View file @
f02e89a9
...
...
@@ -3,6 +3,8 @@
require
'spec_helper'
describe
Issue
do
include
ExternalAuthorizationServiceHelpers
describe
"Associations"
do
it
{
is_expected
.
to
belong_to
(
:milestone
)
}
it
{
is_expected
.
to
have_many
(
:assignees
)
}
...
...
@@ -779,4 +781,47 @@ describe Issue do
it_behaves_like
'throttled touch'
do
subject
{
create
(
:issue
,
updated_at:
1
.
hour
.
ago
)
}
end
context
'when an external authentication service'
do
before
do
enable_external_authorization_service_check
end
describe
'#visible_to_user?'
do
it
'is `false` when an external authorization service is enabled'
do
issue
=
build
(
:issue
,
project:
build
(
:project
,
:public
))
expect
(
issue
).
not_to
be_visible_to_user
end
it
'checks the external service to determine if an issue is readable by a user'
do
project
=
build
(
:project
,
:public
,
external_authorization_classification_label:
'a-label'
)
issue
=
build
(
:issue
,
project:
project
)
user
=
build
(
:user
)
expect
(
::
Gitlab
::
ExternalAuthorization
).
to
receive
(
:access_allowed?
).
with
(
user
,
'a-label'
)
{
false
}
expect
(
issue
.
visible_to_user?
(
user
)).
to
be_falsy
end
it
'does not check the external service if a user does not have access to the project'
do
project
=
build
(
:project
,
:private
,
external_authorization_classification_label:
'a-label'
)
issue
=
build
(
:issue
,
project:
project
)
user
=
build
(
:user
)
expect
(
::
Gitlab
::
ExternalAuthorization
).
not_to
receive
(
:access_allowed?
)
expect
(
issue
.
visible_to_user?
(
user
)).
to
be_falsy
end
it
'does not check the external webservice for admins'
do
issue
=
build
(
:issue
)
user
=
build
(
:admin
)
expect
(
::
Gitlab
::
ExternalAuthorization
).
not_to
receive
(
:access_allowed?
)
issue
.
visible_to_user?
(
user
)
end
end
end
end
spec/models/project_spec.rb
View file @
f02e89a9
...
...
@@ -5,6 +5,7 @@ require 'spec_helper'
describe
Project
do
include
ProjectForksHelper
include
GitHelpers
include
ExternalAuthorizationServiceHelpers
it_behaves_like
'having unique enum values'
...
...
@@ -4417,6 +4418,25 @@ describe Project do
end
end
describe
'#external_authorization_classification_label'
do
it
'falls back to the default when none is configured'
do
enable_external_authorization_service_check
expect
(
build
(
:project
).
external_authorization_classification_label
)
.
to
eq
(
'default_label'
)
end
it
'returns the classification label if it was configured on the project'
do
enable_external_authorization_service_check
project
=
build
(
:project
,
external_authorization_classification_label:
'hello'
)
expect
(
project
.
external_authorization_classification_label
)
.
to
eq
(
'hello'
)
end
end
describe
"#pages_https_only?"
do
subject
{
build
(
:project
)
}
...
...
spec/policies/base_policy_spec.rb
View file @
f02e89a9
require
'spec_helper'
describe
BasePolicy
do
include
ExternalAuthorizationServiceHelpers
describe
'.class_for'
do
it
'detects policy class based on the subject ancestors'
do
expect
(
DeclarativePolicy
.
class_for
(
GenericCommitStatus
.
new
)).
to
eq
(
CommitStatusPolicy
)
...
...
@@ -16,4 +18,25 @@ describe BasePolicy do
expect
(
DeclarativePolicy
.
class_for
(
:global
)).
to
eq
(
GlobalPolicy
)
end
end
describe
'read cross project'
do
let
(
:current_user
)
{
create
(
:user
)
}
let
(
:user
)
{
create
(
:user
)
}
subject
{
described_class
.
new
(
current_user
,
[
user
])
}
it
{
is_expected
.
to
be_allowed
(
:read_cross_project
)
}
context
'when an external authorization service is enabled'
do
before
do
enable_external_authorization_service_check
end
it
{
is_expected
.
not_to
be_allowed
(
:read_cross_project
)
}
it
'allows admins'
do
expect
(
described_class
.
new
(
build
(
:admin
),
nil
)).
to
be_allowed
(
:read_cross_project
)
end
end
end
end
spec/policies/issue_policy_spec.rb
View file @
f02e89a9
require
'spec_helper'
describe
IssuePolicy
do
include
ExternalAuthorizationServiceHelpers
let
(
:guest
)
{
create
(
:user
)
}
let
(
:author
)
{
create
(
:user
)
}
let
(
:assignee
)
{
create
(
:user
)
}
...
...
@@ -204,4 +206,21 @@ describe IssuePolicy do
end
end
end
context
'with external authorization enabled'
do
let
(
:user
)
{
create
(
:user
)
}
let
(
:project
)
{
create
(
:project
,
:public
)
}
let
(
:issue
)
{
create
(
:issue
,
project:
project
)
}
let
(
:policies
)
{
described_class
.
new
(
user
,
issue
)
}
before
do
enable_external_authorization_service_check
end
it
'can read the issue iid without accessing the external service'
do
expect
(
::
Gitlab
::
ExternalAuthorization
).
not_to
receive
(
:access_allowed?
)
expect
(
policies
).
to
be_allowed
(
:read_issue_iid
)
end
end
end
spec/policies/merge_request_policy_spec.rb
View file @
f02e89a9
require
'spec_helper'
describe
MergeRequestPolicy
do
include
ExternalAuthorizationServiceHelpers
let
(
:guest
)
{
create
(
:user
)
}
let
(
:author
)
{
create
(
:user
)
}
let
(
:developer
)
{
create
(
:user
)
}
...
...
@@ -47,4 +49,21 @@ describe MergeRequestPolicy do
expect
(
permissions
(
guest
,
merge_request_locked
)).
to
be_disallowed
(
:reopen_merge_request
)
end
end
context
'with external authorization enabled'
do
let
(
:user
)
{
create
(
:user
)
}
let
(
:project
)
{
create
(
:project
,
:public
)
}
let
(
:merge_request
)
{
create
(
:merge_request
,
source_project:
project
)
}
let
(
:policies
)
{
described_class
.
new
(
user
,
merge_request
)
}
before
do
enable_external_authorization_service_check
end
it
'can read the issue iid without accessing the external service'
do
expect
(
::
Gitlab
::
ExternalAuthorization
).
not_to
receive
(
:access_allowed?
)
expect
(
policies
).
to
be_allowed
(
:read_merge_request_iid
)
end
end
end
spec/policies/project_policy_spec.rb
View file @
f02e89a9
require
'spec_helper'
describe
ProjectPolicy
do
include
ExternalAuthorizationServiceHelpers
include_context
'ProjectPolicy context'
set
(
:guest
)
{
create
(
:user
)
}
set
(
:reporter
)
{
create
(
:user
)
}
...
...
@@ -292,4 +293,56 @@ describe ProjectPolicy do
projects:
[
clusterable
])
end
end
context
'reading a project'
do
it
'allows access when a user has read access to the repo'
do
expect
(
described_class
.
new
(
owner
,
project
)).
to
be_allowed
(
:read_project
)
expect
(
described_class
.
new
(
developer
,
project
)).
to
be_allowed
(
:read_project
)
expect
(
described_class
.
new
(
admin
,
project
)).
to
be_allowed
(
:read_project
)
end
it
'never checks the external service'
do
expect
(
::
Gitlab
::
ExternalAuthorization
).
not_to
receive
(
:access_allowed?
)
expect
(
described_class
.
new
(
owner
,
project
)).
to
be_allowed
(
:read_project
)
end
context
'with an external authorization service'
do
before
do
enable_external_authorization_service_check
end
it
'allows access when the external service allows it'
do
external_service_allow_access
(
owner
,
project
)
external_service_allow_access
(
developer
,
project
)
expect
(
described_class
.
new
(
owner
,
project
)).
to
be_allowed
(
:read_project
)
expect
(
described_class
.
new
(
developer
,
project
)).
to
be_allowed
(
:read_project
)
end
it
'does not check the external service for admins and allows access'
do
expect
(
::
Gitlab
::
ExternalAuthorization
).
not_to
receive
(
:access_allowed?
)
expect
(
described_class
.
new
(
admin
,
project
)).
to
be_allowed
(
:read_project
)
end
it
'prevents all but seeing a public project in a list when access is denied'
do
[
developer
,
owner
,
build
(
:user
),
nil
].
each
do
|
user
|
external_service_deny_access
(
user
,
project
)
policy
=
described_class
.
new
(
user
,
project
)
expect
(
policy
).
not_to
be_allowed
(
:read_project
)
expect
(
policy
).
not_to
be_allowed
(
:owner_access
)
expect
(
policy
).
not_to
be_allowed
(
:change_namespace
)
end
end
it
'passes the full path to external authorization for logging purposes'
do
expect
(
::
Gitlab
::
ExternalAuthorization
)
.
to
receive
(
:access_allowed?
).
with
(
owner
,
'default_label'
,
project
.
full_path
).
and_call_original
described_class
.
new
(
owner
,
project
).
allowed?
(
:read_project
)
end
end
end
end
spec/requests/api/projects_spec.rb
View file @
f02e89a9
...
...
@@ -46,6 +46,8 @@ shared_examples 'languages and percentages JSON response' do
end
describe
API
::
Projects
do
include
ExternalAuthorizationServiceHelpers
let
(
:user
)
{
create
(
:user
)
}
let
(
:user2
)
{
create
(
:user
)
}
let
(
:user3
)
{
create
(
:user
)
}
...
...
@@ -1386,6 +1388,39 @@ describe API::Projects do
end
end
end
context
'with external authorization'
do
let
(
:project
)
do
create
(
:project
,
namespace:
user
.
namespace
,
external_authorization_classification_label:
'the-label'
)
end
context
'when the user has access to the project'
do
before
do
external_service_allow_access
(
user
,
project
)
end
it
'includes the label in the response'
do
get
api
(
"/projects/
#{
project
.
id
}
"
,
user
)
expect
(
response
).
to
have_gitlab_http_status
(
200
)
expect
(
json_response
[
'external_authorization_classification_label'
]).
to
eq
(
'the-label'
)
end
end
context
'when the external service denies access'
do
before
do
external_service_deny_access
(
user
,
project
)
end
it
'returns a 404'
do
get
api
(
"/projects/
#{
project
.
id
}
"
,
user
)
expect
(
response
).
to
have_gitlab_http_status
(
404
)
end
end
end
end
describe
'GET /projects/:id/users'
do
...
...
@@ -1956,6 +1991,20 @@ describe API::Projects do
expect
(
response
).
to
have_gitlab_http_status
(
403
)
end
end
context
'when updating external classification'
do
before
do
enable_external_authorization_service_check
end
it
'updates the classification label'
do
put
(
api
(
"/projects/
#{
project
.
id
}
"
,
user
),
params:
{
external_authorization_classification_label:
'new label'
})
expect
(
response
).
to
have_gitlab_http_status
(
200
)
expect
(
project
.
reload
.
external_authorization_classification_label
).
to
eq
(
'new label'
)
end
end
end
describe
'POST /projects/:id/archive'
do
...
...
spec/requests/api/settings_spec.rb
View file @
f02e89a9
...
...
@@ -115,6 +115,39 @@ describe API::Settings, 'Settings' do
expect
(
json_response
[
'performance_bar_allowed_group_id'
]).
to
be_nil
end
context
'external policy classification settings'
do
let
(
:settings
)
do
{
external_authorization_service_enabled:
true
,
external_authorization_service_url:
'https://custom.service/'
,
external_authorization_service_default_label:
'default'
,
external_authorization_service_timeout:
9.99
,
external_auth_client_cert:
File
.
read
(
'spec/fixtures/passphrase_x509_certificate.crt'
),
external_auth_client_key:
File
.
read
(
'spec/fixtures/passphrase_x509_certificate_pk.key'
),
external_auth_client_key_pass:
"5iveL!fe"
}
end
let
(
:attribute_names
)
{
settings
.
keys
.
map
(
&
:to_s
)
}
it
'includes the attributes in the API'
do
get
api
(
"/application/settings"
,
admin
)
expect
(
response
).
to
have_gitlab_http_status
(
200
)
attribute_names
.
each
do
|
attribute
|
expect
(
json_response
.
keys
).
to
include
(
attribute
)
end
end
it
'allows updating the settings'
do
put
api
(
"/application/settings"
,
admin
),
params:
settings
expect
(
response
).
to
have_gitlab_http_status
(
200
)
settings
.
each
do
|
attribute
,
value
|
expect
(
ApplicationSetting
.
current
.
public_send
(
attribute
)).
to
eq
(
value
)
end
end
end
context
"missing plantuml_url value when plantuml_enabled is true"
do
it
"returns a blank parameter error message"
do
put
api
(
"/application/settings"
,
admin
),
params:
{
plantuml_enabled:
true
}
...
...
spec/serializers/group_child_entity_spec.rb
View file @
f02e89a9
require
'spec_helper'
describe
GroupChildEntity
do
include
ExternalAuthorizationServiceHelpers
include
Gitlab
::
Routing
.
url_helpers
let
(
:user
)
{
create
(
:user
)
}
...
...
@@ -109,4 +110,22 @@ describe GroupChildEntity do
it_behaves_like
'group child json'
end
describe
'for a project with external authorization enabled'
do
let
(
:object
)
do
create
(
:project
,
:with_avatar
,
description:
'Awesomeness'
)
end
before
do
enable_external_authorization_service_check
object
.
add_maintainer
(
user
)
end
it
'does not hit the external authorization service'
do
expect
(
::
Gitlab
::
ExternalAuthorization
).
not_to
receive
(
:access_allowed?
)
expect
(
json
[
:can_edit
]).
to
eq
(
false
)
end
end
end
spec/services/application_settings/update_service_spec.rb
View file @
f02e89a9
require
'spec_helper'
describe
ApplicationSettings
::
UpdateService
do
include
ExternalAuthorizationServiceHelpers
let
(
:application_settings
)
{
create
(
:application_setting
)
}
let
(
:admin
)
{
create
(
:user
,
:admin
)
}
let
(
:params
)
{
{}
}
...
...
@@ -143,4 +145,37 @@ describe ApplicationSettings::UpdateService do
end
end
end
context
'when external authorization is enabled'
do
before
do
enable_external_authorization_service_check
end
it
'does not save the settings with an error if the service denies access'
do
expect
(
::
Gitlab
::
ExternalAuthorization
)
.
to
receive
(
:access_allowed?
).
with
(
admin
,
'new-label'
)
{
false
}
described_class
.
new
(
application_settings
,
admin
,
{
external_authorization_service_default_label:
'new-label'
}).
execute
expect
(
application_settings
.
errors
[
:external_authorization_service_default_label
]).
to
be_present
end
it
'saves the setting when the user has access to the label'
do
expect
(
::
Gitlab
::
ExternalAuthorization
)
.
to
receive
(
:access_allowed?
).
with
(
admin
,
'new-label'
)
{
true
}
described_class
.
new
(
application_settings
,
admin
,
{
external_authorization_service_default_label:
'new-label'
}).
execute
# Read the attribute directly to avoid the stub from
# `enable_external_authorization_service_check`
expect
(
application_settings
[
:external_authorization_service_default_label
]).
to
eq
(
'new-label'
)
end
it
'does not validate the label if it was not passed'
do
expect
(
::
Gitlab
::
ExternalAuthorization
)
.
not_to
receive
(
:access_allowed?
)
described_class
.
new
(
application_settings
,
admin
,
{
home_page_url:
'http://foo.bar'
}).
execute
end
end
end
spec/services/notification_service_spec.rb
View file @
f02e89a9
...
...
@@ -2,6 +2,7 @@ require 'spec_helper'
describe
NotificationService
,
:mailer
do
include
EmailSpec
::
Matchers
include
ExternalAuthorizationServiceHelpers
include
NotificationHelpers
let
(
:notification
)
{
described_class
.
new
}
...
...
@@ -2217,6 +2218,46 @@ describe NotificationService, :mailer do
end
end
context
'with external authorization service'
do
let
(
:issue
)
{
create
(
:issue
)
}
let
(
:project
)
{
issue
.
project
}
let
(
:note
)
{
create
(
:note
,
noteable:
issue
,
project:
project
)
}
let
(
:member
)
{
create
(
:user
)
}
subject
{
NotificationService
.
new
}
before
do
project
.
add_maintainer
(
member
)
member
.
global_notification_setting
.
update!
(
level: :watch
)
end
it
'sends email when the service is not enabled'
do
expect
(
Notify
).
to
receive
(
:new_issue_email
).
at_least
(
:once
).
with
(
member
.
id
,
issue
.
id
,
nil
).
and_call_original
subject
.
new_issue
(
issue
,
member
)
end
context
'when the service is enabled'
do
before
do
enable_external_authorization_service_check
end
it
'does not send an email'
do
expect
(
Notify
).
not_to
receive
(
:new_issue_email
)
subject
.
new_issue
(
issue
,
member
)
end
it
'still delivers email to admins'
do
member
.
update!
(
admin:
true
)
expect
(
Notify
).
to
receive
(
:new_issue_email
).
at_least
(
:once
).
with
(
member
.
id
,
issue
.
id
,
nil
).
and_call_original
subject
.
new_issue
(
issue
,
member
)
end
end
end
def
build_team
(
project
)
@u_watcher
=
create_global_setting_for
(
create
(
:user
),
:watch
)
@u_participating
=
create_global_setting_for
(
create
(
:user
),
:participating
)
...
...
spec/services/projects/create_service_spec.rb
View file @
f02e89a9
require
'spec_helper'
describe
Projects
::
CreateService
,
'#execute'
do
include
ExternalAuthorizationServiceHelpers
include
GitHelpers
let
(
:gitlab_shell
)
{
Gitlab
::
Shell
.
new
}
...
...
@@ -344,6 +345,42 @@ describe Projects::CreateService, '#execute' do
expect
(
rugged
.
config
[
'gitlab.fullpath'
]).
to
eq
project
.
full_path
end
context
'with external authorization enabled'
do
before
do
enable_external_authorization_service_check
end
it
'does not save the project with an error if the service denies access'
do
expect
(
::
Gitlab
::
ExternalAuthorization
)
.
to
receive
(
:access_allowed?
).
with
(
user
,
'new-label'
,
any_args
)
{
false
}
project
=
create_project
(
user
,
opts
.
merge
({
external_authorization_classification_label:
'new-label'
}))
expect
(
project
.
errors
[
:external_authorization_classification_label
]).
to
be_present
expect
(
project
).
not_to
be_persisted
end
it
'saves the project when the user has access to the label'
do
expect
(
::
Gitlab
::
ExternalAuthorization
)
.
to
receive
(
:access_allowed?
).
with
(
user
,
'new-label'
,
any_args
)
{
true
}
project
=
create_project
(
user
,
opts
.
merge
({
external_authorization_classification_label:
'new-label'
}))
expect
(
project
).
to
be_persisted
expect
(
project
.
external_authorization_classification_label
).
to
eq
(
'new-label'
)
end
it
'does not save the project when the user has no access to the default label and no label is provided'
do
expect
(
::
Gitlab
::
ExternalAuthorization
)
.
to
receive
(
:access_allowed?
).
with
(
user
,
'default_label'
,
any_args
)
{
false
}
project
=
create_project
(
user
,
opts
)
expect
(
project
.
errors
[
:external_authorization_classification_label
]).
to
be_present
expect
(
project
).
not_to
be_persisted
end
end
def
create_project
(
user
,
opts
)
Projects
::
CreateService
.
new
(
user
,
opts
).
execute
end
...
...
spec/services/projects/update_service_spec.rb
View file @
f02e89a9
...
...
@@ -362,6 +362,46 @@ describe Projects::UpdateService, '#execute' do
call_service
end
end
context
'with external authorization enabled'
do
before
do
enable_external_authorization_service_check
end
it
'does not save the project with an error if the service denies access'
do
expect
(
::
Gitlab
::
ExternalAuthorization
)
.
to
receive
(
:access_allowed?
).
with
(
user
,
'new-label'
)
{
false
}
result
=
update_project
(
project
,
user
,
{
external_authorization_classification_label:
'new-label'
})
expect
(
result
[
:message
]).
to
be_present
expect
(
result
[
:status
]).
to
eq
(
:error
)
end
it
'saves the new label if the service allows access'
do
expect
(
::
Gitlab
::
ExternalAuthorization
)
.
to
receive
(
:access_allowed?
).
with
(
user
,
'new-label'
)
{
true
}
result
=
update_project
(
project
,
user
,
{
external_authorization_classification_label:
'new-label'
})
expect
(
result
[
:status
]).
to
eq
(
:success
)
expect
(
project
.
reload
.
external_authorization_classification_label
).
to
eq
(
'new-label'
)
end
it
'checks the default label when the classification label was cleared'
do
expect
(
::
Gitlab
::
ExternalAuthorization
)
.
to
receive
(
:access_allowed?
).
with
(
user
,
'default_label'
)
{
true
}
update_project
(
project
,
user
,
{
external_authorization_classification_label:
''
})
end
it
'does not check the label when it does not change'
do
expect
(
::
Gitlab
::
ExternalAuthorization
)
.
not_to
receive
(
:access_allowed?
)
update_project
(
project
,
user
,
{
name:
'New name'
})
end
end
end
describe
'#run_auto_devops_pipeline?'
do
...
...
spec/support/external_authorization_service_helpers.rb
0 → 100644
View file @
f02e89a9
module
ExternalAuthorizationServiceHelpers
def
enable_external_authorization_service_check
stub_application_setting
(
external_authorization_service_enabled:
true
)
stub_application_setting
(
external_authorization_service_url:
'https://authorize.me'
)
stub_application_setting
(
external_authorization_service_default_label:
'default_label'
)
stub_request
(
:post
,
"https://authorize.me"
).
to_return
(
status:
200
)
end
def
external_service_set_access
(
allowed
,
user
,
project
)
enable_external_authorization_service_check
classification_label
=
::
Gitlab
::
CurrentSettings
.
current_application_settings
.
external_authorization_service_default_label
# Reload the project so cached licensed features are reloaded
if
project
classification_label
=
Project
.
find
(
project
.
id
).
external_authorization_classification_label
end
allow
(
::
Gitlab
::
ExternalAuthorization
)
.
to
receive
(
:access_allowed?
)
.
with
(
user
,
classification_label
,
any_args
)
.
and_return
(
allowed
)
end
def
external_service_allow_access
(
user
,
project
=
nil
)
external_service_set_access
(
true
,
user
,
project
)
end
def
external_service_deny_access
(
user
,
project
=
nil
)
external_service_set_access
(
false
,
user
,
project
)
end
end
spec/support/shared_examples/controllers/external_authorization_service_shared_examples.rb
0 → 100644
View file @
f02e89a9
require
'spec_helper'
shared_examples
'disabled when using an external authorization service'
do
include
ExternalAuthorizationServiceHelpers
it
'works when the feature is not enabled'
do
subject
expect
(
response
).
to
be_success
end
it
'renders a 404 with a message when the feature is enabled'
do
enable_external_authorization_service_check
subject
expect
(
response
).
to
have_gitlab_http_status
(
403
)
end
end
shared_examples
'unauthorized when external service denies access'
do
include
ExternalAuthorizationServiceHelpers
it
'allows access when the authorization service allows it'
do
external_service_allow_access
(
user
,
project
)
subject
# Account for redirects after updates
expect
(
response
.
status
).
to
be_between
(
200
,
302
)
end
it
'allows access when the authorization service denies it'
do
external_service_deny_access
(
user
,
project
)
subject
expect
(
response
).
to
have_gitlab_http_status
(
403
)
end
end
spec/support/shared_examples/finders/finder_with_external_authorization_enabled.rb
0 → 100644
View file @
f02e89a9
require
'spec_helper'
shared_examples
'a finder with external authorization service'
do
include
ExternalAuthorizationServiceHelpers
let
(
:user
)
{
create
(
:user
)
}
let
(
:project
)
{
create
(
:project
)
}
before
do
project
.
add_maintainer
(
user
)
end
it
'finds the subject'
do
expect
(
described_class
.
new
(
user
).
execute
).
to
include
(
subject
)
end
context
'with an external authorization service'
do
before
do
enable_external_authorization_service_check
end
it
'does not include the subject when no project was given'
do
expect
(
described_class
.
new
(
user
).
execute
).
not_to
include
(
subject
)
end
it
'includes the subject when a project id was given'
do
expect
(
described_class
.
new
(
user
,
project_params
).
execute
).
to
include
(
subject
)
end
end
end
spec/validators/x509_certificate_credentials_validator_spec.rb
0 → 100644
View file @
f02e89a9
require
'spec_helper'
describe
X509CertificateCredentialsValidator
do
let
(
:certificate_data
)
{
File
.
read
(
'spec/fixtures/x509_certificate.crt'
)
}
let
(
:pkey_data
)
{
File
.
read
(
'spec/fixtures/x509_certificate_pk.key'
)
}
let
(
:validatable
)
do
Class
.
new
do
include
ActiveModel
::
Validations
attr_accessor
:certificate
,
:private_key
,
:passphrase
def
initialize
(
certificate
,
private_key
,
passphrase
=
nil
)
@certificate
,
@private_key
,
@passphrase
=
certificate
,
private_key
,
passphrase
end
end
end
subject
(
:validator
)
do
described_class
.
new
(
certificate: :certificate
,
pkey: :private_key
)
end
it
'is not valid when the certificate is not valid'
do
record
=
validatable
.
new
(
'not a certificate'
,
nil
)
validator
.
validate
(
record
)
expect
(
record
.
errors
[
:certificate
]).
to
include
(
'is not a valid X509 certificate.'
)
end
it
'is not valid without a certificate'
do
record
=
validatable
.
new
(
nil
,
nil
)
validator
.
validate
(
record
)
expect
(
record
.
errors
[
:certificate
]).
not_to
be_empty
end
context
'when a valid certificate is passed'
do
let
(
:record
)
{
validatable
.
new
(
certificate_data
,
nil
)
}
it
'does not track an error for the certificate'
do
validator
.
validate
(
record
)
expect
(
record
.
errors
[
:certificate
]).
to
be_empty
end
it
'adds an error when not passing a correct private key'
do
validator
.
validate
(
record
)
expect
(
record
.
errors
[
:private_key
]).
to
include
(
'could not read private key, is the passphrase correct?'
)
end
it
'has no error when the private key is correct'
do
record
.
private_key
=
pkey_data
validator
.
validate
(
record
)
expect
(
record
.
errors
).
to
be_empty
end
end
context
'when using a passphrase'
do
let
(
:passphrase_certificate_data
)
{
File
.
read
(
'spec/fixtures/passphrase_x509_certificate.crt'
)
}
let
(
:passphrase_pkey_data
)
{
File
.
read
(
'spec/fixtures/passphrase_x509_certificate_pk.key'
)
}
let
(
:record
)
{
validatable
.
new
(
passphrase_certificate_data
,
passphrase_pkey_data
,
'5iveL!fe'
)
}
subject
(
:validator
)
do
described_class
.
new
(
certificate: :certificate
,
pkey: :private_key
,
pass: :passphrase
)
end
it
'is valid with the correct data'
do
validator
.
validate
(
record
)
expect
(
record
.
errors
).
to
be_empty
end
it
'adds an error when the passphrase is wrong'
do
record
.
passphrase
=
'wrong'
validator
.
validate
(
record
)
expect
(
record
.
errors
[
:private_key
]).
not_to
be_empty
end
end
end
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment