Commit 19a5e7c9 authored by Jacob Vosmaer's avatar Jacob Vosmaer

Test Grack::Auth via a request spec

parent 7124e5a4
require "spec_helper" require "spec_helper"
describe Grack::Auth, lib: true do describe 'Git HTTP requests', lib: true do
let(:user) { create(:user) } let(:user) { create(:user) }
let(:project) { create(:project) } let(:project) { create(:project) }
let(:app) { lambda { |env| [200, {}, "Success!"] } }
let!(:auth) { Grack::Auth.new(app) }
let(:env) do
{
'rack.input' => '',
'REQUEST_METHOD' => 'GET',
'QUERY_STRING' => 'service=git-upload-pack'
}
end
let(:status) { auth.call(env).first }
describe "#call" do describe "#call" do
context "when the project doesn't exist" do context "when the project doesn't exist" do
before do
env["PATH_INFO"] = "doesnt/exist.git"
end
context "when no authentication is provided" do context "when no authentication is provided" do
it "responds with status 401" do it "responds with status 401" do
expect(status).to eq(401) clone_get '/doesnt/exist.git/info/refs'
expect(response.status).to eq(401)
end end
end end
context "when username and password are provided" do context "when username and password are provided" do
context "when authentication fails" do context "when authentication fails" do
before do
env["HTTP_AUTHORIZATION"] = ActionController::HttpAuthentication::Basic.encode_credentials(user.username, "nope")
end
it "responds with status 401" do it "responds with status 401" do
expect(status).to eq(401) clone_get '/doesnt/exist.git/info/refs', user: user.username, password: "nope"
expect(response.status).to eq(401)
end end
end end
context "when authentication succeeds" do context "when authentication succeeds" do
before do
env["HTTP_AUTHORIZATION"] = ActionController::HttpAuthentication::Basic.encode_credentials(user.username, user.password)
end
it "responds with status 404" do it "responds with status 404" do
expect(status).to eq(404) clone_get '/doesnt/exist.git/info/refs', user: user.username, password: user.password
expect(response.status).to eq(404)
end end
end end
end end
end end
context "when the Wiki for a project exists" do context "when the Wiki for a project exists" do
before do it "responds with the right project" do
@wiki = ProjectWiki.new(project) wiki = ProjectWiki.new(project)
env["PATH_INFO"] = "#{@wiki.repository.path_with_namespace}.git/info/refs"
project.update_attribute(:visibility_level, Project::PUBLIC) project.update_attribute(:visibility_level, Project::PUBLIC)
end
it "responds with the right project" do clone_get "/#{wiki.repository.path_with_namespace}.git/info/refs"
response = auth.call(env) json_body = ActiveSupport::JSON.decode(response.body)
json_body = ActiveSupport::JSON.decode(response[2][0])
expect(response.first).to eq(200) expect(response.status).to eq(200)
expect(json_body['RepoPath']).to include(@wiki.repository.path_with_namespace) expect(json_body['RepoPath']).to include(wiki.repository.path_with_namespace)
end end
end end
context "when the project exists" do context "when the project exists" do
before do let(:path) { clone_path(project) }
env["PATH_INFO"] = project.path_with_namespace + ".git"
end
context "when the project is public" do context "when the project is public" do
before do it "responds with status 200" do
project.update_attribute(:visibility_level, Project::PUBLIC) project.update_attribute(:visibility_level, Project::PUBLIC)
end clone_get path
it "responds with status 200" do expect(response.status).to eq(200)
expect(status).to eq(200)
end end
end end
...@@ -88,85 +65,74 @@ describe Grack::Auth, lib: true do ...@@ -88,85 +65,74 @@ describe Grack::Auth, lib: true do
context "when no authentication is provided" do context "when no authentication is provided" do
it "responds with status 401" do it "responds with status 401" do
expect(status).to eq(401) clone_get path
expect(response.status).to eq(401)
end end
end end
context "when username and password are provided" do context "when username and password are provided" do
context "when authentication fails" do context "when authentication fails" do
before do
env["HTTP_AUTHORIZATION"] = ActionController::HttpAuthentication::Basic.encode_credentials(user.username, "nope")
end
it "responds with status 401" do it "responds with status 401" do
expect(status).to eq(401) clone_get path, user: user.username, password: 'nope'
expect(response.status).to eq(401)
end end
context "when the user is IP banned" do context "when the user is IP banned" do
before do it "responds with status 401" do
expect(Rack::Attack::Allow2Ban).to receive(:filter).and_return(true) expect(Rack::Attack::Allow2Ban).to receive(:filter).and_return(true)
allow_any_instance_of(Rack::Request).to receive(:ip).and_return('1.2.3.4') allow_any_instance_of(Rack::Request).to receive(:ip).and_return('1.2.3.4')
end
it "responds with status 401" do clone_get path, user: user.username, password: 'nope'
expect(status).to eq(401)
expect(response.status).to eq(401)
end end
end end
end end
context "when authentication succeeds" do context "when authentication succeeds" do
before do
env["HTTP_AUTHORIZATION"] = ActionController::HttpAuthentication::Basic.encode_credentials(user.username, user.password)
end
context "when the user has access to the project" do context "when the user has access to the project" do
before do before do
project.team << [user, :master] project.team << [user, :master]
end end
context "when the user is blocked" do context "when the user is blocked" do
before do it "responds with status 404" do
user.block user.block
project.team << [user, :master] project.team << [user, :master]
end
it "responds with status 404" do clone_get path, user: user.username, password: user.password
expect(status).to eq(404)
expect(response.status).to eq(404)
end end
end end
context "when the user isn't blocked" do context "when the user isn't blocked" do
before do
expect(Rack::Attack::Allow2Ban).to receive(:reset)
end
it "responds with status 200" do it "responds with status 200" do
expect(status).to eq(200) expect(Rack::Attack::Allow2Ban).to receive(:reset)
end
end
context "when blank password attempts follow a valid login" do clone_get path, user: user.username, password: user.password
let(:options) { Gitlab.config.rack_attack.git_basic_auth }
let(:maxretry) { options[:maxretry] - 1 }
let(:ip) { '1.2.3.4' }
before do expect(response.status).to eq(200)
allow_any_instance_of(Rack::Request).to receive(:ip).and_return(ip)
Rack::Attack::Allow2Ban.reset(ip, options)
end end
after do
Rack::Attack::Allow2Ban.reset(ip, options)
end end
context "when blank password attempts follow a valid login" do
def attempt_login(include_password) def attempt_login(include_password)
password = include_password ? user.password : "" password = include_password ? user.password : ""
env["HTTP_AUTHORIZATION"] = ActionController::HttpAuthentication::Basic.encode_credentials(user.username, password) clone_get path, user: user.username, password: password
Grack::Auth.new(app) response.status
auth.call(env).first
end end
it "repeated attempts followed by successful attempt" do it "repeated attempts followed by successful attempt" do
options = Gitlab.config.rack_attack.git_basic_auth
maxretry = options[:maxretry] - 1
ip = '1.2.3.4'
allow_any_instance_of(Rack::Request).to receive(:ip).and_return(ip)
Rack::Attack::Allow2Ban.reset(ip, options)
maxretry.times.each do maxretry.times.each do
expect(attempt_login(false)).to eq(401) expect(attempt_login(false)).to eq(401)
end end
...@@ -177,33 +143,48 @@ describe Grack::Auth, lib: true do ...@@ -177,33 +143,48 @@ describe Grack::Auth, lib: true do
maxretry.times.each do maxretry.times.each do
expect(attempt_login(false)).to eq(401) expect(attempt_login(false)).to eq(401)
end end
Rack::Attack::Allow2Ban.reset(ip, options)
end end
end end
end end
context "when the user doesn't have access to the project" do context "when the user doesn't have access to the project" do
it "responds with status 404" do it "responds with status 404" do
expect(status).to eq(404) clone_get path, user: user.username, password: user.password
expect(response.status).to eq(404)
end end
end end
end end
end end
context "when a gitlab ci token is provided" do context "when a gitlab ci token is provided" do
let(:token) { "123" } it "responds with status 200" do
let(:project) { FactoryGirl.create :empty_project } token = "123"
project = FactoryGirl.create :empty_project
before do
project.update_attributes(runners_token: token, builds_enabled: true) project.update_attributes(runners_token: token, builds_enabled: true)
env["HTTP_AUTHORIZATION"] = ActionController::HttpAuthentication::Basic.encode_credentials("gitlab-ci-token", token) clone_get clone_path(project), user: 'gitlab-ci-token', password: token
end
it "responds with status 200" do expect(response.status).to eq(200)
expect(status).to eq(200)
end end
end end
end end
end end
end end
def clone_get(url, user: nil, password: nil)
if user && password
env = { 'HTTP_AUTHORIZATION' => ActionController::HttpAuthentication::Basic.encode_credentials(user, password) }
else
env = {}
end
get url, { 'service' => 'git-upload-pack' }, env
end
def clone_path(project)
"/#{project.path_with_namespace}.git/info/refs"
end
end end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment