diff options
author | Douwe Maan <douwe@gitlab.com> | 2016-07-05 22:57:19 +0000 |
---|---|---|
committer | Douwe Maan <douwe@gitlab.com> | 2016-07-05 22:57:19 +0000 |
commit | cfd5870b62e9d76e564ffc64db1d1281b4a363bb (patch) | |
tree | 34adec49220b96c99aea7139cd0794405ecd7b8d | |
parent | 1141eaf5c83f927ccc064b6c5d162081fdd22894 (diff) | |
parent | 0bdf6fe4ba90f0a1dc7777d17651667776dfb91b (diff) | |
download | gitlab-ce-cfd5870b62e9d76e564ffc64db1d1281b4a363bb.tar.gz |
Merge branch 'allow-disabling-of-git-access-protocol' into 'master'
Add setting that allows admins to choose which Git access protocols are enabled.
## What does this MR do?
It allows admins to disable one of the two protocols for Git access. They can choose to enable just SSH, HTTP or allow both. If one of them is disabled, the clone URL in the project will show only the allowed protocol, and no dropdown to change protocols will be presented.
## What are the relevant issue numbers?
Full implementation on GitLab's side for #18601
GitLab Shell implementation: gitlab-org/gitlab-shell!62
GitLab Workhorse implementation: gitlab-org/gitlab-workhorse!51
## Screenshots (if relevant)
![Screen_Shot_2016-06-16_at_12.26.19_PM](/uploads/bad845142e9704a7385b2eaca51fd4eb/Screen_Shot_2016-06-16_at_12.26.19_PM.png)
![Screen_Shot_2016-06-20_at_4.24.54_PM](/uploads/6e452dd269e06f0be23841ce93866ed6/Screen_Shot_2016-06-20_at_4.24.54_PM.png)
/cc @jschatz1 this MR touches the UI. Please review.
See merge request !4696
29 files changed, 360 insertions, 37 deletions
diff --git a/CHANGELOG b/CHANGELOG index 3da5583d452..8ef934bf80d 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -23,6 +23,7 @@ v 8.10.0 (unreleased) - Add notification settings dropdown for groups - Allow importing from Github using Personal Access Tokens. (Eric K Idema) - API: Todos !3188 (Robert Schilling) + - Add "Enabled Git access protocols" to Application Settings - Fix user creation with stronger minimum password requirements !4054 (nathan-pmt) - PipelinesFinder uses git cache data - Check for conflicts with existing Project's wiki path when creating a new project. diff --git a/app/assets/stylesheets/framework/buttons.scss b/app/assets/stylesheets/framework/buttons.scss index 1e3083cce55..590b8f54363 100644 --- a/app/assets/stylesheets/framework/buttons.scss +++ b/app/assets/stylesheets/framework/buttons.scss @@ -281,3 +281,21 @@ color: $gl-icon-color; } } + +.clone-dropdown-btn a { + color: $dropdown-link-color; + &:hover { + text-decoration: none; + } +} + +.btn-static { + background-color: $background-color !important; + border: 1px solid lightgrey; + cursor: default; + &:active { + -moz-box-shadow: inset 0 0 0 white; + -webkit-box-shadow: inset 0 0 0 white; + box-shadow: inset 0 0 0 white; + } +} diff --git a/app/controllers/admin/application_settings_controller.rb b/app/controllers/admin/application_settings_controller.rb index 5f65dd3aff0..cbdf2859898 100644 --- a/app/controllers/admin/application_settings_controller.rb +++ b/app/controllers/admin/application_settings_controller.rb @@ -110,6 +110,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController :send_user_confirmation_email, :container_registry_token_expire_delay, :repository_storage, + :enabled_git_access_protocol, restricted_visibility_levels: [], import_sources: [], disabled_oauth_sign_in_sources: [] diff --git a/app/controllers/projects/git_http_controller.rb b/app/controllers/projects/git_http_controller.rb index 62c3fa8de53..40a8b7940d9 100644 --- a/app/controllers/projects/git_http_controller.rb +++ b/app/controllers/projects/git_http_controller.rb @@ -19,6 +19,8 @@ class Projects::GitHttpController < Projects::ApplicationController render_ok elsif receive_pack? && receive_pack_allowed? render_ok + elsif http_blocked? + render_not_allowed else render_not_found end @@ -154,6 +156,10 @@ class Projects::GitHttpController < Projects::ApplicationController render plain: 'Not Found', status: :not_found end + def render_not_allowed + render plain: download_access.message, status: :forbidden + end + def ci? @ci.present? end @@ -162,12 +168,28 @@ class Projects::GitHttpController < Projects::ApplicationController return false unless Gitlab.config.gitlab_shell.upload_pack if user - Gitlab::GitAccess.new(user, project).download_access_check.allowed? + download_access.allowed? else ci? || project.public? end end + def access + return @access if defined?(@access) + + @access = Gitlab::GitAccess.new(user, project, 'http') + end + + def download_access + return @download_access if defined?(@download_access) + + @download_access = access.check('git-upload-pack') + end + + def http_blocked? + !access.protocol_allowed? + end + def receive_pack_allowed? return false unless Gitlab.config.gitlab_shell.receive_pack diff --git a/app/helpers/application_settings_helper.rb b/app/helpers/application_settings_helper.rb index 6e580c62ccd..78c0b79d2bd 100644 --- a/app/helpers/application_settings_helper.rb +++ b/app/helpers/application_settings_helper.rb @@ -31,6 +31,28 @@ module ApplicationSettingsHelper current_application_settings.akismet_enabled? end + def allowed_protocols_present? + current_application_settings.enabled_git_access_protocol.present? + end + + def enabled_protocol + case current_application_settings.enabled_git_access_protocol + when 'http' + gitlab_config.protocol + when 'ssh' + 'ssh' + end + end + + def enabled_project_button(project, protocol) + case protocol + when 'ssh' + ssh_clone_button(project, 'bottom', append_link: false) + else + http_clone_button(project, 'bottom', append_link: false) + end + end + # Return a group of checkboxes that use Bootstrap's button plugin for a # toggle button effect. def restricted_level_checkboxes(help_block_id) diff --git a/app/helpers/branches_helper.rb b/app/helpers/branches_helper.rb index c533659b600..601df5c18df 100644 --- a/app/helpers/branches_helper.rb +++ b/app/helpers/branches_helper.rb @@ -12,7 +12,7 @@ module BranchesHelper def can_push_branch?(project, branch_name) return false unless project.repository.branch_exists?(branch_name) - ::Gitlab::GitAccess.new(current_user, project).can_push_to_branch?(branch_name) + ::Gitlab::GitAccess.new(current_user, project, 'web').can_push_to_branch?(branch_name) end def project_branches diff --git a/app/helpers/button_helper.rb b/app/helpers/button_helper.rb index 9051a493b9b..0f097f86816 100644 --- a/app/helpers/button_helper.rb +++ b/app/helpers/button_helper.rb @@ -40,33 +40,33 @@ module ButtonHelper type: :button end - def http_clone_button(project) + def http_clone_button(project, placement = 'right', append_link: true) klass = 'http-selector' klass << ' has-tooltip' if current_user.try(:require_password?) protocol = gitlab_config.protocol.upcase - content_tag :a, protocol, + content_tag (append_link ? :a : :span), protocol, class: klass, - href: project.http_url_to_repo, + href: (project.http_url_to_repo if append_link), data: { html: true, - placement: 'right', + placement: placement, container: 'body', title: "Set a password on your account<br>to pull or push via #{protocol}" } end - def ssh_clone_button(project) + def ssh_clone_button(project, placement = 'right', append_link: true) klass = 'ssh-selector' klass << ' has-tooltip' if current_user.try(:require_ssh_key?) - content_tag :a, 'SSH', + content_tag (append_link ? :a : :span), 'SSH', class: klass, - href: project.ssh_url_to_repo, + href: (project.ssh_url_to_repo if append_link), data: { html: true, - placement: 'right', + placement: placement, container: 'body', title: 'Add an SSH key to your profile<br>to pull or push via SSH.' } diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index f312a7ccca3..88787576dd3 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -206,10 +206,14 @@ module ProjectsHelper end def default_clone_protocol - if !current_user || current_user.require_ssh_key? - gitlab_config.protocol + if allowed_protocols_present? + enabled_protocol else - "ssh" + if !current_user || current_user.require_ssh_key? + gitlab_config.protocol + else + 'ssh' + end end end diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb index 5fa6eacd234..7bf618d60b9 100644 --- a/app/models/application_setting.rb +++ b/app/models/application_setting.rb @@ -59,6 +59,9 @@ class ApplicationSetting < ActiveRecord::Base presence: true, inclusion: { in: ->(_object) { Gitlab.config.repositories.storages.keys } } + validates :enabled_git_access_protocol, + inclusion: { in: %w(ssh http), allow_blank: true, allow_nil: true } + validates_each :restricted_visibility_levels do |record, attr, value| unless value.nil? value.each do |level| diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index cb0f871897a..4f7e1d2f302 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -481,7 +481,7 @@ class MergeRequest < ActiveRecord::Base end def can_be_merged_by?(user) - ::Gitlab::GitAccess.new(user, project).can_push_to_branch?(target_branch) + ::Gitlab::GitAccess.new(user, project, 'web').can_push_to_branch?(target_branch) end def mergeable_ci_state? diff --git a/app/services/commits/change_service.rb b/app/services/commits/change_service.rb index 6b69cb53b2c..c578097376a 100644 --- a/app/services/commits/change_service.rb +++ b/app/services/commits/change_service.rb @@ -23,7 +23,7 @@ module Commits private def check_push_permissions - allowed = ::Gitlab::GitAccess.new(current_user, project).can_push_to_branch?(@target_branch) + allowed = ::Gitlab::GitAccess.new(current_user, project, 'web').can_push_to_branch?(@target_branch) unless allowed raise ValidationError.new('You are not allowed to push into this branch') diff --git a/app/services/files/base_service.rb b/app/services/files/base_service.rb index 0326a8823e9..4bdb68a3698 100644 --- a/app/services/files/base_service.rb +++ b/app/services/files/base_service.rb @@ -43,7 +43,7 @@ module Files end def validate - allowed = ::Gitlab::GitAccess.new(current_user, project).can_push_to_branch?(@target_branch) + allowed = ::Gitlab::GitAccess.new(current_user, project, 'web').can_push_to_branch?(@target_branch) unless allowed raise_error("You are not allowed to push into this branch") diff --git a/app/views/admin/application_settings/_form.html.haml b/app/views/admin/application_settings/_form.html.haml index c1f70bc1866..eb325576e4f 100644 --- a/app/views/admin/application_settings/_form.html.haml +++ b/app/views/admin/application_settings/_form.html.haml @@ -44,6 +44,12 @@ and GitLab.com = link_to "(?)", help_page_path("integration", "gitlab") .form-group + %label.control-label.col-sm-2 Enabled Git access protocols + .col-sm-10 + = select(:application_setting, :enabled_git_access_protocol, [['Both SSH and HTTP(S)', nil], ['Only SSH', 'ssh'], ['Only HTTP(S)', 'http']], {}, class: 'form-control') + %span.help-block#clone-protocol-help + Allow only the selected protocols to be used for Git access. + .form-group .col-sm-offset-2.col-sm-10 .checkbox = f.label :version_check_enabled do diff --git a/app/views/shared/_clone_panel.html.haml b/app/views/shared/_clone_panel.html.haml index 84b3f44c0ad..3b82d8e686f 100644 --- a/app/views/shared/_clone_panel.html.haml +++ b/app/views/shared/_clone_panel.html.haml @@ -2,15 +2,20 @@ .git-clone-holder.input-group .input-group-btn - %a#clone-dropdown.clone-dropdown-btn.btn{href: '#', 'data-toggle' => 'dropdown'} - %span - = default_clone_protocol.upcase - = icon('caret-down') - %ul.dropdown-menu.dropdown-menu-right.clone-options-dropdown - %li - = ssh_clone_button(project) - %li - = http_clone_button(project) + -if allowed_protocols_present? + .clone-dropdown-btn.btn.btn-static + %span + = enabled_project_button(project, enabled_protocol) + - else + %a#clone-dropdown.clone-dropdown-btn.btn{href: '#', data: { toggle: 'dropdown' }} + %span + = default_clone_protocol.upcase + = icon('caret-down') + %ul.dropdown-menu.dropdown-menu-right.clone-options-dropdown + %li + = ssh_clone_button(project) + %li + = http_clone_button(project) = text_field_tag :project_clone, default_url_to_repo(project), class: "js-select-on-focus form-control", readonly: true .input-group-btn diff --git a/db/migrate/20160615173316_add_enabled_git_access_protocols_to_application_settings.rb b/db/migrate/20160615173316_add_enabled_git_access_protocols_to_application_settings.rb new file mode 100644 index 00000000000..013904b3f4f --- /dev/null +++ b/db/migrate/20160615173316_add_enabled_git_access_protocols_to_application_settings.rb @@ -0,0 +1,11 @@ +# See http://doc.gitlab.com/ce/development/migration_style_guide.html +# for more information on how to write migrations for GitLab. +# rubocop:disable all + +class AddEnabledGitAccessProtocolsToApplicationSettings < ActiveRecord::Migration + include Gitlab::Database::MigrationHelpers + + def change + add_column :application_settings, :enabled_git_access_protocol, :string + end +end diff --git a/db/schema.rb b/db/schema.rb index c1e88c1ed7e..f6465136e6a 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -86,6 +86,7 @@ ActiveRecord::Schema.define(version: 20160705163108) do t.integer "container_registry_token_expire_delay", default: 5 t.text "after_sign_up_text" t.string "repository_storage", default: "default" + t.string "enabled_git_access_protocol" end create_table "audit_events", force: :cascade do |t| diff --git a/doc/README.md b/doc/README.md index 53a12d2a455..cf7a828d91e 100644 --- a/doc/README.md +++ b/doc/README.md @@ -21,6 +21,7 @@ ## Administrator documentation +- [Access restrictions](administration/access_restrictions.md) Define which Git access protocols can be used to talk to GitLab - [Authentication/Authorization](administration/auth/README.md) Configure external authentication with LDAP, SAML, CAS and additional Omniauth providers. - [Custom Git hooks](administration/custom_hooks.md) Custom Git hooks (on the filesystem) for when webhooks aren't enough. diff --git a/doc/administration/access_restrictions.md b/doc/administration/access_restrictions.md new file mode 100644 index 00000000000..51d7996effd --- /dev/null +++ b/doc/administration/access_restrictions.md @@ -0,0 +1,38 @@ +# Access Restrictions + +> **Note:** This feature is only available on versions 8.10 and above. + +With GitLab's Access restrictions you can choose which Git access protocols you +want your users to use to communicate with GitLab. This feature can be enabled +via the `Application Settings` in the Admin interface. + +The setting is called `Enabled Git access protocols`, and it gives you the option +to choose between: + +- Both SSH and HTTP(S) +- Only SSH +- Only HTTP(s) + +![Settings Overview](img/access_restrictions.png) + +## Enabled Protocol + +When both SSH and HTTP(S) are enabled, GitLab will behave as usual, it will give +your users the option to choose which protocol they would like to use. + +When you choose to allow only one of the protocols, a couple of things will happen: + +- The project page will only show the allowed protocol's URL, with no option to + change it. +- A tooltip will be shown when you hover over the URL's protocol, if an action + on the user's part is required, e.g. adding an SSH key, or setting a password. + +![Project URL with SSH only access](img/restricted_url.png) + +On top of these UI restrictions, GitLab will deny all Git actions on the protocol +not selected. + +> **Note:** Please keep in mind that disabling an access protocol does not actually + block access to the server itself. The ports used for the protocol, be it SSH or + HTTP, will still be accessible. What GitLab does is restrict access on the + application level.
\ No newline at end of file diff --git a/doc/administration/img/access_restrictions.png b/doc/administration/img/access_restrictions.png Binary files differnew file mode 100644 index 00000000000..66fd9491e85 --- /dev/null +++ b/doc/administration/img/access_restrictions.png diff --git a/doc/administration/img/restricted_url.png b/doc/administration/img/restricted_url.png Binary files differnew file mode 100644 index 00000000000..0a677433dcf --- /dev/null +++ b/doc/administration/img/restricted_url.png diff --git a/doc/api/settings.md b/doc/api/settings.md index 741c5a29581..d9b68eaeadf 100644 --- a/doc/api/settings.md +++ b/doc/api/settings.md @@ -68,6 +68,7 @@ PUT /application/settings | `after_sign_out_path` | string | no | Where to redirect users after logout | | `container_registry_token_expire_delay` | integer | no | Container Registry token duration in minutes | | `repository_storage` | string | no | Storage path for new projects. The value should be the name of one of the repository storage paths defined in your gitlab.yml | +| `enabled_git_access_protocol` | string | no | Enabled protocols for Git access. Allowed values are: `ssh`, `http`, and `nil` to allow both protocols. ```bash curl -X PUT -H "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/application/settings?signup_enabled=false&default_project_visibility=1 diff --git a/lib/api/internal.rb b/lib/api/internal.rb index b32503e8516..d5dfba5e0cc 100644 --- a/lib/api/internal.rb +++ b/lib/api/internal.rb @@ -13,6 +13,7 @@ module API # action - git action (git-upload-pack or git-receive-pack) # ref - branch name # forced_push - forced_push + # protocol - Git access protocol being used, e.g. HTTP or SSH # helpers do @@ -46,11 +47,13 @@ module API User.find_by(id: params[:user_id]) end + protocol = params[:protocol] + access = if wiki? - Gitlab::GitAccessWiki.new(actor, project) + Gitlab::GitAccessWiki.new(actor, project, protocol) else - Gitlab::GitAccess.new(actor, project) + Gitlab::GitAccess.new(actor, project, protocol) end access_status = access.check(params[:action], params[:changes]) diff --git a/lib/gitlab/git/hook.rb b/lib/gitlab/git/hook.rb index 420c6883c45..57c41b41298 100644 --- a/lib/gitlab/git/hook.rb +++ b/lib/gitlab/git/hook.rb @@ -1,6 +1,7 @@ module Gitlab module Git class Hook + GL_PROTOCOL = 'web'.freeze attr_reader :name, :repo_path, :path def initialize(name, repo_path) @@ -34,7 +35,8 @@ module Gitlab vars = { 'GL_ID' => gl_id, - 'PWD' => repo_path + 'PWD' => repo_path, + 'GL_PROTOCOL' => GL_PROTOCOL } options = { diff --git a/lib/gitlab/git_access.rb b/lib/gitlab/git_access.rb index d2a0e316cbe..7679c7e4bb8 100644 --- a/lib/gitlab/git_access.rb +++ b/lib/gitlab/git_access.rb @@ -3,11 +3,12 @@ module Gitlab DOWNLOAD_COMMANDS = %w{ git-upload-pack git-upload-archive } PUSH_COMMANDS = %w{ git-receive-pack } - attr_reader :actor, :project + attr_reader :actor, :project, :protocol - def initialize(actor, project) + def initialize(actor, project, protocol) @actor = actor @project = project + @protocol = protocol end def user @@ -49,6 +50,8 @@ module Gitlab end def check(cmd, changes = nil) + return build_status_object(false, "Git access over #{protocol.upcase} is not allowed") unless protocol_allowed? + unless actor return build_status_object(false, "No user or key was provided.") end @@ -164,6 +167,10 @@ module Gitlab Gitlab::ForcePushCheck.force_push?(project, oldrev, newrev) end + def protocol_allowed? + Gitlab::ProtocolAccess.allowed?(protocol) + end + private def protected_branch_action(oldrev, newrev, branch_name) diff --git a/lib/gitlab/protocol_access.rb b/lib/gitlab/protocol_access.rb new file mode 100644 index 00000000000..21aefc884be --- /dev/null +++ b/lib/gitlab/protocol_access.rb @@ -0,0 +1,13 @@ +module Gitlab + module ProtocolAccess + def self.allowed?(protocol) + if protocol == 'web' + true + elsif current_application_settings.enabled_git_access_protocol.blank? + true + else + protocol == current_application_settings.enabled_git_access_protocol + end + end + end +end diff --git a/spec/features/admin/admin_disables_git_access_protocol_spec.rb b/spec/features/admin/admin_disables_git_access_protocol_spec.rb new file mode 100644 index 00000000000..5b1c0460274 --- /dev/null +++ b/spec/features/admin/admin_disables_git_access_protocol_spec.rb @@ -0,0 +1,66 @@ +require 'rails_helper' + +feature 'Admin disables Git access protocol', feature: true do + let(:project) { create(:empty_project, :empty_repo) } + let(:admin) { create(:admin) } + + background do + login_as(admin) + end + + context 'with HTTP disabled' do + background do + disable_http_protocol + end + + scenario 'shows only SSH url' do + visit_project + + expect(page).to have_content("git clone #{project.ssh_url_to_repo}") + expect(page).not_to have_selector('#clone-dropdown') + end + end + + context 'with SSH disabled' do + background do + disable_ssh_protocol + end + + scenario 'shows only HTTP url' do + visit_project + + expect(page).to have_content("git clone #{project.http_url_to_repo}") + expect(page).not_to have_selector('#clone-dropdown') + end + end + + context 'with nothing disabled' do + background do + create(:personal_key, user: admin) + end + + scenario 'shows default SSH url and protocol selection dropdown' do + visit_project + + expect(page).to have_content("git clone #{project.ssh_url_to_repo}") + expect(page).to have_selector('#clone-dropdown') + end + + end + + def visit_project + visit namespace_project_path(project.namespace, project) + end + + def disable_http_protocol + visit admin_application_settings_path + find('#application_setting_enabled_git_access_protocol').find(:xpath, 'option[2]').select_option + click_on 'Save' + end + + def disable_ssh_protocol + visit admin_application_settings_path + find('#application_setting_enabled_git_access_protocol').find(:xpath, 'option[3]').select_option + click_on 'Save' + end +end diff --git a/spec/lib/gitlab/git_access_spec.rb b/spec/lib/gitlab/git_access_spec.rb index 9b7986fa12d..c79ba11f782 100644 --- a/spec/lib/gitlab/git_access_spec.rb +++ b/spec/lib/gitlab/git_access_spec.rb @@ -1,7 +1,7 @@ require 'spec_helper' describe Gitlab::GitAccess, lib: true do - let(:access) { Gitlab::GitAccess.new(actor, project) } + let(:access) { Gitlab::GitAccess.new(actor, project, 'web') } let(:project) { create(:project) } let(:user) { create(:user) } let(:actor) { user } @@ -67,6 +67,43 @@ describe Gitlab::GitAccess, lib: true do end end + describe '#check with single protocols allowed' do + def disable_protocol(protocol) + settings = ::ApplicationSetting.create_from_defaults + settings.update_attribute(:enabled_git_access_protocol, protocol) + end + + context 'ssh disabled' do + before do + disable_protocol('ssh') + @acc = Gitlab::GitAccess.new(actor, project, 'ssh') + end + + it 'blocks ssh git push' do + expect(@acc.check('git-receive-pack').allowed?).to be_falsey + end + + it 'blocks ssh git pull' do + expect(@acc.check('git-upload-pack').allowed?).to be_falsey + end + end + + context 'http disabled' do + before do + disable_protocol('http') + @acc = Gitlab::GitAccess.new(actor, project, 'http') + end + + it 'blocks http push' do + expect(@acc.check('git-receive-pack').allowed?).to be_falsey + end + + it 'blocks http git pull' do + expect(@acc.check('git-upload-pack').allowed?).to be_falsey + end + end + end + describe 'download_access_check' do describe 'master permissions' do before { project.team << [user, :master] } diff --git a/spec/lib/gitlab/git_access_wiki_spec.rb b/spec/lib/gitlab/git_access_wiki_spec.rb index 77ecfce6f17..4244b807d41 100644 --- a/spec/lib/gitlab/git_access_wiki_spec.rb +++ b/spec/lib/gitlab/git_access_wiki_spec.rb @@ -1,7 +1,7 @@ require 'spec_helper' describe Gitlab::GitAccessWiki, lib: true do - let(:access) { Gitlab::GitAccessWiki.new(user, project) } + let(:access) { Gitlab::GitAccessWiki.new(user, project, 'web') } let(:project) { create(:project) } let(:user) { create(:user) } diff --git a/spec/requests/api/internal_spec.rb b/spec/requests/api/internal_spec.rb index fcea45f19ba..e567d36afa8 100644 --- a/spec/requests/api/internal_spec.rb +++ b/spec/requests/api/internal_spec.rb @@ -207,26 +207,86 @@ describe API::API, api: true do expect(json_response["status"]).to be_falsey end end + + context 'ssh access has been disabled' do + before do + settings = ::ApplicationSetting.create_from_defaults + settings.update_attribute(:enabled_git_access_protocol, 'http') + end + + it 'rejects the SSH push' do + push(key, project) + + expect(response.status).to eq(200) + expect(json_response['status']).to be_falsey + expect(json_response['message']).to eq 'Git access over SSH is not allowed' + end + + it 'rejects the SSH pull' do + pull(key, project) + + expect(response.status).to eq(200) + expect(json_response['status']).to be_falsey + expect(json_response['message']).to eq 'Git access over SSH is not allowed' + end + end + + context 'http access has been disabled' do + before do + settings = ::ApplicationSetting.create_from_defaults + settings.update_attribute(:enabled_git_access_protocol, 'ssh') + end + + it 'rejects the HTTP push' do + push(key, project, 'http') + + expect(response.status).to eq(200) + expect(json_response['status']).to be_falsey + expect(json_response['message']).to eq 'Git access over HTTP is not allowed' + end + + it 'rejects the HTTP pull' do + pull(key, project, 'http') + + expect(response.status).to eq(200) + expect(json_response['status']).to be_falsey + expect(json_response['message']).to eq 'Git access over HTTP is not allowed' + end + end + + context 'web actions are always allowed' do + it 'allows WEB push' do + settings = ::ApplicationSetting.create_from_defaults + settings.update_attribute(:enabled_git_access_protocol, 'ssh') + project.team << [user, :developer] + push(key, project, 'web') + + expect(response.status).to eq(200) + expect(json_response['status']).to be_truthy + end + end end - def pull(key, project) + def pull(key, project, protocol = 'ssh') post( api("/internal/allowed"), key_id: key.id, project: project.path_with_namespace, action: 'git-upload-pack', - secret_token: secret_token + secret_token: secret_token, + protocol: protocol ) end - def push(key, project) + def push(key, project, protocol = 'ssh') post( api("/internal/allowed"), changes: 'd14d6c0abdd253381df51a723d58691b2ee1ab08 570e7b2abdd848b95f2f578043fc23bd6f6fd24d refs/heads/master', key_id: key.id, project: project.path_with_namespace, action: 'git-receive-pack', - secret_token: secret_token + secret_token: secret_token, + protocol: protocol ) end @@ -237,7 +297,8 @@ describe API::API, api: true do key_id: key.id, project: project.path_with_namespace, action: 'git-upload-archive', - secret_token: secret_token + secret_token: secret_token, + protocol: 'ssh' ) end end |