From 8bb1931ef2d25ee5dfc5352a3932b948656ddf94 Mon Sep 17 00:00:00 2001 From: Patricio Cano Date: Wed, 10 Aug 2016 19:04:25 -0500 Subject: [PATCH] Deny Git over HTTP access to users that have 2FA enabled, unless they use a Personal Access Token. --- .../personal_access_tokens/index.html.haml | 4 ++ spec/requests/git_http_spec.rb | 41 +++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/app/views/profiles/personal_access_tokens/index.html.haml b/app/views/profiles/personal_access_tokens/index.html.haml index 71ac367830d..03ee682b343 100644 --- a/app/views/profiles/personal_access_tokens/index.html.haml +++ b/app/views/profiles/personal_access_tokens/index.html.haml @@ -7,6 +7,10 @@ = page_title %p You can generate a personal access token for each application you use that needs access to the GitLab API. + %p + You can also use personal access tokens to authenticate against Git over HTTP. Use them specially when you + have 2FA enabled. + .col-lg-9 - if flash[:personal_access_token] diff --git a/spec/requests/git_http_spec.rb b/spec/requests/git_http_spec.rb index 8537c252b58..37c2586bbe2 100644 --- a/spec/requests/git_http_spec.rb +++ b/spec/requests/git_http_spec.rb @@ -198,6 +198,47 @@ describe 'Git HTTP requests', lib: true do end end + context 'when user has 2FA enabled' do + before do + @user = create(:user, :two_factor) + project.team << [@user, :master] + end + + context 'when username and password are provided' do + it 'rejects the clone attempt' do + download("#{project.path_with_namespace}.git", user: @user.username, password: @user.password) do |response| + expect(response).to have_http_status(401) + expect(response.body).to include('You have 2FA enabled, please use a personal access token for Git over HTTP') + end + end + + it 'rejects the push attempt' do + upload("#{project.path_with_namespace}.git", user: @user.username, password: @user.password) do |response| + expect(response).to have_http_status(401) + expect(response.body).to include('You have 2FA enabled, please use a personal access token for Git over HTTP') + end + end + end + + context 'when username and personal access token are provided' do + before do + @token = create(:personal_access_token, user: @user) + end + + it 'allows clones' do + download("#{project.path_with_namespace}.git", user: @user.username, password: @token.token) do |response| + expect(response).to have_http_status(200) + end + end + + it 'allows pushes' do + upload("#{project.path_with_namespace}.git", user: @user.username, password: @token.token) do |response| + expect(response).to have_http_status(200) + end + end + end + end + context "when blank password attempts follow a valid login" do def attempt_login(include_password) password = include_password ? user.password : ""