diff --git a/lib/travis/api/app/endpoint/authorization.rb b/lib/travis/api/app/endpoint/authorization.rb index 122aa8e8..41b06e75 100644 --- a/lib/travis/api/app/endpoint/authorization.rb +++ b/lib/travis/api/app/endpoint/authorization.rb @@ -78,6 +78,7 @@ class Travis::Api::App # # * **github_token**: GitHub token for checking authorization (required) post '/github' do + check_agent unless params[:github_token] halt 422, { "error" => "Must pass 'github_token' parameter" } end @@ -145,6 +146,16 @@ class Travis::Api::App private + def allowed_agents + @allowed_agents ||= redis.smembers('auth_agents') + end + + def check_agent + return if settings.test? or allowed_agents.empty? + return if allowed_agents.any? { |a| request.user_agent.to_s.start_with? a } + halt 403, "you are currently not allowed to perform this request. please contact support@travis-ci.com." + end + def serialize_user(user) rendered = Travis::Api.data(user, version: :v2) rendered['user'].merge('token' => user.tokens.first.try(:token).to_s) diff --git a/lib/travis/api/app/middleware/user_agent_tracker.rb b/lib/travis/api/app/middleware/user_agent_tracker.rb index d7d582fa..c758e0f4 100644 --- a/lib/travis/api/app/middleware/user_agent_tracker.rb +++ b/lib/travis/api/app/middleware/user_agent_tracker.rb @@ -37,7 +37,7 @@ class Travis::Api::App end def mark_travis(agent) - command = agent.application.comment.detect { |c| c.start_with? "command " } + command = agent.application.comment.detect { |c| c.start_with? "command " } if agent.application.comment if command mark(:cli, :version, agent.version) diff --git a/lib/travis/api/attack.rb b/lib/travis/api/attack.rb index 4d91ec31..dc0a247d 100644 --- a/lib/travis/api/attack.rb +++ b/lib/travis/api/attack.rb @@ -44,7 +44,7 @@ class Rack::Attack # Ban time: 5 hours # Ban after: 10 POST requests within five minutes to /auth/github blacklist('hammering /auth/github') do |request| - Rack::Attack::Allow2Ban.filter(request.identifier, maxretry: 10, findtime: 5.minutes, bantime: bantime(5.hours)) do + Rack::Attack::Allow2Ban.filter(request.identifier, maxretry: 2, findtime: 5.minutes, bantime: bantime(5.hours)) do request.post? and request.path == '/auth/github' end end @@ -59,6 +59,14 @@ class Rack::Attack end end + + ### + # Throttle: unauthenticated requests to /auth/github - 1 per minute + # Scoped by: IP address + throttle('req/ip/1min', limit: 1, period: 1.minute) do |request| + request.ip unless request.authenticated? and request.path == '/auth/github' + end + ### # Throttle: unauthenticated requests - 500 per minute # Scoped by: IP address diff --git a/lib/travis/api/v3/access_control/user.rb b/lib/travis/api/v3/access_control/user.rb index e48bb577..5b6460fe 100644 --- a/lib/travis/api/v3/access_control/user.rb +++ b/lib/travis/api/v3/access_control/user.rb @@ -8,6 +8,7 @@ module Travis::API::V3 user = Models::User.find(user.id) if user.is_a? ::User @user = user @access_permissions = user.permissions.where(user_id: user.id) + @got_request = false super() end @@ -20,6 +21,7 @@ module Travis::API::V3 end def visible_repositories(list) + load_permissions list.where('repositories.private = false OR repositories.id IN (?)'.freeze, access_permissions.map(&:repository_id)) end @@ -47,7 +49,19 @@ module Travis::API::V3 def permission?(type, id) id = id.id if id.is_a? ::Repository - access_permissions.where(type => true, :repository_id => id).any? + + load_permissions if @got_request + @got_request = true + + if access_permissions.respond_to? :where + access_permissions.where(type => true, :repository_id => id).any? + else + access_permissions.any? { |p| p[type] == true and p.repository_id == id } + end + end + + def load_permissions + @access_permissions = @access_permissions.to_a end end end