class OpenShift::Auth::BrokerKey

Service instance to generate and verify broker keys. Instance is thread safe, reuse to avoid reloading the priv/pub keys.

Public Class Methods

new(auth_info = nil) click to toggle source
# File lib/openshift/auth/broker_key.rb, line 9
def initialize(auth_info = nil)
  @auth_info = auth_info || Rails.application.config.auth
end

Public Instance Methods

authenticate_request(controller) click to toggle source

Return a hash with :username if a broker auth key was correctly provided, raise if authentication was not valid, or return nil if no authentication was present.

# File lib/openshift/auth/broker_key.rb, line 18
def authenticate_request(controller)
  req = controller.request
  key, iv = req.request_parameters.values_at('broker_auth_key', 'broker_auth_iv')
  key, iv = req.headers['broker_auth_key'], req.headers['broker_auth_iv'] unless key && iv
  validate_broker_key(iv, key) if key && iv
end
generate_broker_key(app) click to toggle source

Generate a broker key from an application

# File lib/openshift/auth/broker_key.rb, line 28
def generate_broker_key(app)
  cipher = OpenSSL::Cipher::Cipher.new("aes-256-cbc")
  cipher.encrypt
  cipher.key = cipher_key
  cipher.iv = iv = cipher.random_iv
  token = {:app_id => app._id,
           :creation_time => app.created_at}
  encrypted_token = cipher.update(token.to_json)
  encrypted_token << cipher.final
  encrypted_iv = public_key.public_encrypt(iv)

  # Base64 encode the iv and token
  encoded_iv = Base64::encode64(encrypted_iv)
  encoded_token = Base64::encode64(encrypted_token)

  [encoded_iv, encoded_token]
end
validate_broker_key(iv, key) click to toggle source
# File lib/openshift/auth/broker_key.rb, line 46
def validate_broker_key(iv, key)
  key = key.gsub(" ", "+")
  iv = iv.gsub(" ", "+")
  begin
    encrypted_token = Base64::decode64(key)
    cipher = OpenSSL::Cipher::Cipher.new("aes-256-cbc")
    cipher.decrypt
    cipher.key = cipher_key
    cipher.iv = private_key.private_decrypt(Base64::decode64(iv))
    json_token = cipher.update(encrypted_token)
    json_token << cipher.final
  rescue => e
    Rails.logger.error "Broker key authentication failed. #{e.message}\n  #{e.backtrace.join("\n  ")}"
    raise OpenShift::AccessDeniedException, "Broker key authentication failed: #{e.message}"
  end

  token = JSON.parse(json_token)
  user_login = token[token_login_key.to_s]
  creation_time = token['creation_time']

  if app_name = token['app_name']
    # DEPRECATED, kept for backwards compatibility
    user = begin
             CloudUser.find_by_identity(nil, user_login)
           rescue Mongoid::Errors::DocumentNotFound
             raise OpenShift::AccessDeniedException, "No such user exists with login #{user_login}"
           end
    app = Application.find_by_user(user, app_name)
  elsif app_id = token['app_id']
    app = Application.find(app_id)
    user = begin
             app.owner
           rescue Mongoid::Errors::DocumentNotFound
             raise OpenShift::AccessDeniedException, "The owner #{app.owner_id} does not exist"
           end
  end

  raise OpenShift::AccessDeniedException, "No such application exists #{app_name || app_id} or invalid token time" if app.nil? or (Time.parse(creation_time) - app.created_at).abs > 1.0

  scopes = [Scope::Application.new(:id => app._id.to_s, :app_scope => :scale), Scope::Application.new(:id => app._id.to_s, :app_scope => :report_deployments)]
  if app.requires(true).any?{ |feature| (c = CartridgeCache.find_cartridge(feature, app)) && c.is_ci_server? }
    scopes << Scope::DomainBuilder.new(app)
  end

  {:user => user, :auth_method => :broker_auth, :scopes => Scope::Scopes(scopes)}
end

Private Instance Methods

cipher_key() click to toggle source
# File lib/openshift/auth/broker_key.rb, line 101
def cipher_key
  @cipher_key ||= OpenSSL::Digest::SHA512.new(salt).digest
end
private_key() click to toggle source
# File lib/openshift/auth/broker_key.rb, line 94
def private_key
  @private_key ||= OpenSSL::PKey::RSA.new(File.read(privkeyfile), privkeypass)
end
privkeyfile() click to toggle source
# File lib/openshift/auth/broker_key.rb, line 107
def privkeyfile
  @auth_info[:privkeyfile]
end
privkeypass() click to toggle source
# File lib/openshift/auth/broker_key.rb, line 110
def privkeypass
  @auth_info[:privkeypass]
end
pubkeyfile() click to toggle source
# File lib/openshift/auth/broker_key.rb, line 113
def pubkeyfile
  @auth_info[:pubkeyfile]
end
public_key() click to toggle source
# File lib/openshift/auth/broker_key.rb, line 97
def public_key
  @public_key ||= OpenSSL::PKey::RSA.new(File.read(pubkeyfile), privkeypass)
end
salt() click to toggle source
# File lib/openshift/auth/broker_key.rb, line 104
def salt
  @auth_info[:salt]
end
token_login_key() click to toggle source
# File lib/openshift/auth/broker_key.rb, line 116
def token_login_key
  @auth_info[:token_login_key] || :login
end