class ChefPlugin::Authentication

Public Instance Methods

authenticated(request, &block) click to toggle source
# File lib/smart_proxy_chef_plugin/authentication.rb, line 29
def authenticated(request, &block)
  content     = request.env["rack.input"].read

  auth = true
  if ChefPlugin::Plugin.settings.chef_authenticate_nodes
    client_name = request.env['HTTP_X_FOREMAN_CLIENT']
    signature   = request.env['HTTP_X_FOREMAN_SIGNATURE']

    raise Proxy::Error::Unauthorized, "Failed to authenticate node #{client_name}. Missing some headers" if client_name.nil? or signature.nil?
    auth = verify_signature_request(client_name,signature,content)
  end

  if auth
    raise Proxy::Error::BadRequest, "Body is empty for node #{client_name}" if content.nil?
    block.call(content)
  else
    raise Proxy::Error::Unauthorized, "Failed to authenticate node #{client_name}"
  end
end
verify_signature_request(client_name,signature,body) click to toggle source
# File lib/smart_proxy_chef_plugin/authentication.rb, line 8
def verify_signature_request(client_name,signature,body)
  #We need to retrieve node public key
  #to verify signature
  chefurl = ChefPlugin::Plugin.settings.chef_server_url
  chef_smartproxy_clientname = ChefPlugin::Plugin.settings.chef_smartproxy_clientname
  key = ChefPlugin::Plugin.settings.chef_smartproxy_privatekey
  rest = ::Chef::REST.new(chefurl,chef_smartproxy_clientname,key)
  begin
    public_key = OpenSSL::PKey::RSA.new(rest.get_rest("/clients/#{client_name}").public_key)
  rescue Timeout::Error, Errno::EINVAL, Errno::ECONNRESET, EOFError,
    Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError,
    Errno::ECONNREFUSED, OpenSSL::SSL::SSLError => e
    raise Proxy::Error::Unauthorized, "Failed to authenticate node : "+e.message
  end

  #signature is base64 encoded
  decoded_signature = Base64.decode64(signature)
  hash_body = Digest::SHA256.hexdigest(body)
  public_key.verify(OpenSSL::Digest::SHA256.new,decoded_signature,hash_body)
end