Class: Pantry::Communication::Security::Authentication

Inherits:
Object
  • Object
show all
Includes:
Celluloid::ZMQ
Defined in:
lib/pantry/communication/security/authentication.rb

Overview

This class implements and manages the ZAP handler. For any connecting client, this handler receives a request to authenticate the Client. If the Client is allowed in, all proceeds as normal. If a Client is not allowed in then the connection is dropped.

For Pantry, this is a very strict authentication mechanism that only allows Clients in whos public keys are in the server_keys.yml keystore. It also rejects any attempts to authenticate with a mechanism other than CURVE.

ZAP: ZeroMQ Authentication Protocol

rfc.zeromq.org/spec:27

Instance Method Summary collapse

Constructor Details

#initialize(key_store) ⇒ Authentication

Returns a new instance of Authentication.



19
20
21
22
23
24
# File 'lib/pantry/communication/security/authentication.rb', line 19

def initialize(key_store)
  @key_store = key_store

  @socket = Celluloid::ZMQ::RepSocket.new
  @socket.linger = 0
end

Instance Method Details

#authenticate_client(client_key) ⇒ Object



76
77
78
79
80
81
82
# File 'lib/pantry/communication/security/authentication.rb', line 76

def authenticate_client(client_key)
  if @key_store.known_client?(client_key)
    ["200", "OK"]
  else
    ["400", "Unknown Client"]
  end
end

#authenticate_request(request) ⇒ Object



65
66
67
68
69
70
71
72
73
74
# File 'lib/pantry/communication/security/authentication.rb', line 65

def authenticate_request(request)
  mechanism  = request[5]
  client_key = request[6]

  if mechanism != "CURVE"
    ["400", "Invalid Mechanism"]
  else
    authenticate_client(client_key)
  end
end

#openObject



26
27
28
29
30
# File 'lib/pantry/communication/security/authentication.rb', line 26

def open
  @socket.bind("inproc://zeromq.zap.01")
  @running = true
  self.async.process_requests
end

#process_next_requestObject



43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/pantry/communication/security/authentication.rb', line 43

def process_next_request
  request = read_next_request

  response_code, response_text = authenticate_request(request)

  if response_code == "200"
    Pantry.logger.debug("[AUTH] Client authentication successful")
  else
    Pantry.logger.debug("[AUTH] Client authentication rejected: #{response_text}")
  end

  write_response(request, response_code, response_text)
end

#process_requestsObject



37
38
39
40
41
# File 'lib/pantry/communication/security/authentication.rb', line 37

def process_requests
  while @running
    process_next_request
  end
end

#read_next_requestObject



57
58
59
60
61
62
63
# File 'lib/pantry/communication/security/authentication.rb', line 57

def read_next_request
  request = []
  begin
    request << @socket.read
  end while @socket.more_parts?
  request
end

#shutdownObject



32
33
34
35
# File 'lib/pantry/communication/security/authentication.rb', line 32

def shutdown
  @socket.close
  @running = false
end

#write_response(request, response_code, response_text) ⇒ Object



84
85
86
87
88
89
90
91
92
93
# File 'lib/pantry/communication/security/authentication.rb', line 84

def write_response(request, response_code, response_text)
  @socket.write([
    request[0],    # Version
    request[1],    # Sequence / Request id
    response_code,
    response_text,
    "",            # username
    ""             # metadata
  ])
end