Commit 04094afc authored by Oswaldo Ferreira's avatar Oswaldo Ferreira

Allow only requests from DVCS connector for Github-like endpoints

parent 0b5f80b4
......@@ -52,8 +52,8 @@ module API
# Although the following endpoints are kept behind V3 namespace, they're not
# deprecated neither should be removed when V3 get removed.
# They're needed as a layer to integrate with Jira development panel.
mount ::API::V3::GithubRepos
# They're needed as a layer to integrate with Jira Development Panel.
mount ::API::V3::Github
end
before { header['X-Frame-Options'] = 'SAMEORIGIN' }
......
......@@ -1090,73 +1090,5 @@ module API
expose :failing_on_hosts
expose :total_failures
end
module Github
class Namespace < Grape::Entity
expose :path, as: :login
end
class Repository < Grape::Entity
expose :id
expose :namespace, as: :owner, using: Namespace
expose :name
end
class BranchCommit < Grape::Entity
expose :id, as: :sha
expose :type do |model|
'commit'
end
end
class RepoCommit < Grape::Entity
expose :id, as: :sha
expose :author do |commit|
{
login: commit.author&.username,
email: commit.author_email
}
end
expose :committer do |commit|
{
login: commit.author&.username,
email: commit.committer_email
}
end
expose :commit do |commit|
# TODO: export to entity
{
author: {
name: commit.author_name,
email: commit.author_email,
date: commit.authored_date.iso8601,
type: 'User'
},
committer: {
name: commit.committer_name,
email: commit.committer_email,
date: commit.committed_date.iso8601,
type: 'User'
},
message: commit.safe_message
}
end
expose :parents do |commit|
# TODO: export to entity
commit.parent_ids.map { |id| { sha: id } }
end
expose :files do |commit|
[]
end
end
class Branch < Grape::Entity
expose :name
expose :commit, using: BranchCommit do |repo_branch, options|
options[:project].repository.commit(repo_branch.dereferenced_target)
end
end
end
end
end
# Simplified version of Github API entities.
# It's mainly used to mimic Github API and integrate with Jira Development Panel.
#
module API
module Github
module Entities
class Namespace < Grape::Entity
expose :path, as: :login
end
class Repository < Grape::Entity
expose :id
expose :namespace, as: :owner, using: Namespace
expose :name
end
class BranchCommit < Grape::Entity
expose :id, as: :sha
expose :type do |model|
'commit'
end
end
class RepoCommit < Grape::Entity
expose :id, as: :sha
expose :author do |commit|
{
login: commit.author&.username,
email: commit.author_email
}
end
expose :committer do |commit|
{
login: commit.author&.username,
email: commit.committer_email
}
end
expose :commit do |commit|
# TODO: export to entity
{
author: {
name: commit.author_name,
email: commit.author_email,
date: commit.authored_date.iso8601,
type: 'User'
},
committer: {
name: commit.committer_name,
email: commit.committer_email,
date: commit.committed_date.iso8601,
type: 'User'
},
message: commit.safe_message
}
end
expose :parents do |commit|
# TODO: export to entity
commit.parent_ids.map { |id| { sha: id } }
end
expose :files do |commit|
[]
end
end
class Branch < Grape::Entity
expose :name
expose :commit, using: BranchCommit do |repo_branch, options|
options[:project].repository.commit(repo_branch.dereferenced_target)
end
end
end
end
end
module API
module V3
class GithubRepos < Grape::API
before { authenticate! }
class Github < Grape::API
before do
authenticate!
authorize_jira_user_agent!(request)
end
helpers do
params :project_full_path do
......@@ -9,6 +12,10 @@ module API
requires :project, type: String
end
def authorize_jira_user_agent!(request)
not_found! unless Gitlab::Jira::Middleware.jira_dvcs_connector?(request.env)
end
def find_project_with_access(full_path)
project = find_project!(full_path)
not_found! unless project.feature_available?(:jira_dev_panel_integration)
......@@ -32,7 +39,7 @@ module API
get ':namespace/repos' do
projects = current_user.authorized_projects.select { |project| project.feature_available?(:jira_dev_panel_integration) }
projects = ::Kaminari.paginate_array(projects)
present paginate(projects), with: ::API::Entities::Github::Repository
present paginate(projects), with: ::API::Github::Entities::Repository
end
end
......@@ -51,9 +58,7 @@ module API
branches = ::Kaminari.paginate_array(user_project.repository.branches.sort_by(&:name))
present paginate(branches),
with: ::API::Entities::Github::Branch,
project: user_project
present paginate(branches), with: ::API::Github::Entities::Branch, project: user_project
end
params do
......@@ -68,7 +73,7 @@ module API
not_found! 'Commit' unless commit
present commit, with: ::API::Entities::Github::RepoCommit
present commit, with: ::API::Github::Entities::RepoCommit
end
end
end
......
module Gitlab
module Jira
class Middleware
def self.jira_dvcs_connector?(env)
env['HTTP_USER_AGENT']&.start_with?('JIRA DVCS Connector')
end
def initialize(app)
@app = app
end
def call(env)
env['HTTP_AUTHORIZATION'].sub!('token', 'Bearer') if jira_dvcs_connector?(env)
env['HTTP_AUTHORIZATION'].sub!('token', 'Bearer') if self.class.jira_dvcs_connector?(env)
@app.call(env)
end
private
def jira_dvcs_connector?(env)
/JIRA DVCS Connector/.match(env['HTTP_USER_AGENT'])
end
end
end
end
......@@ -3,15 +3,24 @@ require 'spec_helper'
describe Gitlab::Jira::Middleware do
let(:app) { double(:app) }
let(:middleware) { described_class.new(app) }
let(:jira_user_agent) { 'JIRA DVCS Connector Vertigo/5.0.0-D20170810T012915' }
describe '.jira_dvcs_connector?' do
it 'returns true when DVCS connector' do
expect(described_class.jira_dvcs_connector?('HTTP_USER_AGENT' => jira_user_agent)).to eq(true)
end
it 'returns false when not DVCS connector' do
expect(described_class.jira_dvcs_connector?('HTTP_USER_AGENT' => 'pokemon')).to eq(false)
end
end
describe '#call' do
it 'adjusts HTTP_AUTHORIZATION env when request from JIRA DVCS user agent' do
user_agent = 'JIRA DVCS Connector Vertigo/5.0.0-D20170810T012915'
expect(app).to receive(:call).with('HTTP_USER_AGENT' => user_agent,
expect(app).to receive(:call).with('HTTP_USER_AGENT' => jira_user_agent,
'HTTP_AUTHORIZATION' => 'Bearer hash-123')
middleware.call('HTTP_USER_AGENT' => user_agent, 'HTTP_AUTHORIZATION' => 'token hash-123')
middleware.call('HTTP_USER_AGENT' => jira_user_agent, 'HTTP_AUTHORIZATION' => 'token hash-123')
end
it 'does not change HTTP_AUTHORIZATION env when request is not from JIRA DVCS user agent' do
......
require 'spec_helper'
describe API::V3::GithubRepos do
describe API::V3::Github do
let(:user) { create(:user) }
let!(:project) { create(:project, :repository, creator: user) }
before do
allow(Gitlab::Jira::Middleware).to receive(:jira_dvcs_connector?) { true }
project.add_master(user)
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