travis-api/lib/travis/api/v3/access_control/signature.rb
2015-01-21 16:38:25 +01:00

59 lines
1.9 KiB
Ruby

require 'travis/api/v3/access_control/generic'
require 'travis/api/app/access_token'
require 'digest/sha1'
require 'openssl'
module Travis::API::V3
# Support signed requests to not expose the secret to an untrusted environment.
class AccessControl::Signature < AccessControl::Generic
auth_type('signature')
def self.for_request(type, payload, env)
*args, signature = payload
options = Hash[args.map { |a| a.split(?=.freeze, 2) }]
challenge = ""
if github_id = options[?u.freeze]
return unless user = ::User.find_by_github_id(github_id)
end
if application = options[?a.freeze]
return unless Travis.config.applications and app_config = Travis.config.applications[application]
end
if c = options[?c.freeze]
challenge << env['REQUEST_METHOD'.freeze] << "\n".freeze if c.include?(?m.freeze)
challenge << env['SCRIPT_NAME'.freeze] << env['PATH_INFO'.freeze] << "\n" if c.include?(?p.freeze)
end
challenge << app_config[:secret] if app_config and user
challenge << args.join(?:.freeze)
if app_config
control = AccessControl::Application.new(application, user: user)
secrets = user ? secrets_for(user) : [app_config[:secret]]
else
control = AccessControl::User.new(user)
secrets = secrets_for(user)
end
if scope = options[?s.freeze]
control &&= AccessControl::Scoped.new(scope, control)
end
control if secrets.any? { |secret| signed(challenge, secret) == signature }
end
def self.secrets_for(user)
[
Travis::Api::App::AccessToken.new(user: user, app_id: 1), # generated from github token
Travis::Api::App::AccessToken.new(user: user, app_id: 0) # used by web
]
end
def self.signed(challenge, secret)
OpenSSL::HMAC.hexdigest('sha256'.freeze, secret, challenge)
end
end
end