zas-client 0.0.8 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +27 -1
- data/lib/zas/client.rb +38 -11
- data/lib/zas/client_configuration.rb +23 -6
- data/lib/zas/credentials.rb +3 -3
- data/lib/zas/http_basic_credentials.rb +5 -3
- metadata +2 -2
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# Zero Authentication Service - Ruby Client
|
2
2
|
|
3
|
-
This is a ruby client libraty for the Zero Authentication Service.
|
3
|
+
This is a ruby client libraty for the Zero Authentication Service (https://github.com/zero-as/zas-service).
|
4
4
|
|
5
5
|
## Usage
|
6
6
|
|
@@ -22,6 +22,32 @@ In irb:
|
|
22
22
|
bundle exec irb -Ilib -rzas
|
23
23
|
=> # everything from general usage
|
24
24
|
|
25
|
+
## Adding Support for Other Credential Types
|
26
|
+
|
27
|
+
Any object that responds to `#to_wire` may be based to `Client#authenticate`. The wire format is JSON and
|
28
|
+
includes a strategy key/value pair and a credentials key/value pair. For example, here is what a simple
|
29
|
+
authentication wire representation looks like:
|
30
|
+
|
31
|
+
{
|
32
|
+
"strategy": "auth",
|
33
|
+
"credentials": {
|
34
|
+
"username": "jdoe",
|
35
|
+
"password": "password"
|
36
|
+
}
|
37
|
+
}
|
38
|
+
|
39
|
+
Here is an example of what a custom authentication type might look like:
|
40
|
+
|
41
|
+
{
|
42
|
+
"strategy": "my_auth",
|
43
|
+
"credentials": {
|
44
|
+
"id": "my_identifier",
|
45
|
+
"token": "123456gregergjerg"
|
46
|
+
}
|
47
|
+
}
|
48
|
+
|
49
|
+
In order to handle a custom strategy you will need to register an authenticator when starting up your
|
50
|
+
Zas service.
|
25
51
|
|
26
52
|
## Configuration
|
27
53
|
|
data/lib/zas/client.rb
CHANGED
@@ -4,32 +4,45 @@ require 'yajl'
|
|
4
4
|
require 'hashie'
|
5
5
|
|
6
6
|
module Zas
|
7
|
-
# A TimeoutError may be raised if the Zas authentication service fails to respond
|
7
|
+
# Public: A TimeoutError may be raised if the Zas authentication service fails to respond
|
8
8
|
# within a timeout limit.
|
9
9
|
class TimeoutError < RuntimeError
|
10
10
|
end
|
11
11
|
|
12
|
+
# Public: A client for the Zero Authentication Service.
|
12
13
|
class Client
|
13
14
|
require 'zas/client_configuration'
|
14
15
|
require 'zas/credentials'
|
15
16
|
require 'zas/http_basic_credentials'
|
16
17
|
|
17
|
-
# Initialize the client with the given configuration.
|
18
|
+
# Public: Initialize the client with the given configuration.
|
18
19
|
#
|
19
20
|
# config - Configuration spec for the client.
|
20
21
|
def initialize(config=ClientConfiguration.new)
|
21
22
|
self.host = config.host
|
22
23
|
self.port = config.port
|
23
24
|
self.timeout = config.timeout
|
25
|
+
self.logger = config.logger
|
24
26
|
self.context = ZMQ::Context.new
|
25
|
-
self.logger = Syslogger.new(config.name, Syslog::LOG_PID, Syslog::LOG_LOCAL0)
|
26
27
|
|
27
|
-
|
28
|
+
Signal.trap(:INT) {
|
29
|
+
begin
|
30
|
+
puts "Trapped INT in Zas client"
|
31
|
+
disconnect
|
32
|
+
close
|
33
|
+
rescue => e
|
34
|
+
puts "Error while trying to shut down zas client: #{e.message}"
|
35
|
+
end
|
36
|
+
}
|
28
37
|
end
|
29
38
|
|
30
39
|
# Public: Authenticate the given credentials.
|
31
40
|
#
|
32
|
-
# credentials - The credentials
|
41
|
+
# credentials - The credentials. The credentials may be any object that implements
|
42
|
+
# the #to_wire method. This method must construct a JSON data structure with
|
43
|
+
# at least the following two keys:
|
44
|
+
# strategy - The name of the strategy to use
|
45
|
+
# credentials - A data structure with the credentials
|
33
46
|
#
|
34
47
|
# Returns the results of the authentication.
|
35
48
|
#
|
@@ -38,9 +51,12 @@ module Zas
|
|
38
51
|
def authenticate(credentials)
|
39
52
|
begin
|
40
53
|
socket.send credentials.to_wire
|
54
|
+
logger.debug "Selecting on socket #{socket.inspect} with timeout #{timeout}"
|
41
55
|
if ZMQ.select([socket], nil, nil, timeout)
|
56
|
+
logger.debug("Receiving from socket #{socket.inspect}")
|
42
57
|
Hashie::Mash.new(Yajl::Parser.parse(socket.recv))
|
43
58
|
else
|
59
|
+
logger.debug("Failed to select on socket #{socket.inspect}")
|
44
60
|
disconnect
|
45
61
|
raise Zas::TimeoutError, "Response from authentication service not received in time"
|
46
62
|
end
|
@@ -51,13 +67,20 @@ module Zas
|
|
51
67
|
|
52
68
|
# Public: Disconnect the socket.
|
53
69
|
def disconnect
|
54
|
-
|
70
|
+
if socket
|
71
|
+
logger.debug "Closing socket #{socket.inspect}"
|
72
|
+
socket.close
|
73
|
+
end
|
55
74
|
@socket = nil
|
56
75
|
end
|
57
76
|
|
58
77
|
# Public: Close the context.
|
59
78
|
def close
|
60
|
-
|
79
|
+
if context
|
80
|
+
logger.debug "Closing context #{context.inspect}"
|
81
|
+
context.close
|
82
|
+
context = nil
|
83
|
+
end
|
61
84
|
end
|
62
85
|
|
63
86
|
private
|
@@ -72,10 +95,14 @@ module Zas
|
|
72
95
|
end
|
73
96
|
|
74
97
|
def build_socket
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
98
|
+
if context
|
99
|
+
logger.info "Building new socket for Zas Client, connecting to #{host}:#{port}"
|
100
|
+
socket = context.socket ZMQ::REQ
|
101
|
+
socket.connect "tcp://#{host}:#{port}"
|
102
|
+
socket
|
103
|
+
else
|
104
|
+
logger.info "Cannot build a new socket as there is no context"
|
105
|
+
end
|
79
106
|
end
|
80
107
|
end
|
81
108
|
end
|
@@ -1,27 +1,44 @@
|
|
1
1
|
module Zas
|
2
|
-
# Struct used to configure the Zas::Client.
|
2
|
+
# Public: Struct used to configure the Zas::Client. Configuration options are:
|
3
3
|
#
|
4
|
-
# host - The IP address of the service
|
5
|
-
# port - The port number for the service
|
6
|
-
# name - The name of the client for logging
|
7
|
-
# timeout - The timeout for
|
8
|
-
|
4
|
+
# host - The IP address of the service (default: 127.0.0.1)
|
5
|
+
# port - The port number for the service (default: 5555)
|
6
|
+
# name - The name of the client for logging (default: zas-client)
|
7
|
+
# timeout - The timeout, in seconds, to wait for a response from the service (default: 1 second)
|
8
|
+
# logger - The logger (default: syslog)
|
9
|
+
class ClientConfiguration < Struct.new(:host, :port, :name, :timeout, :logger)
|
10
|
+
# Public: Construct the ClientConfiguration.
|
11
|
+
#
|
12
|
+
# attributes - A Hash of attributes. All attributes are optional:
|
13
|
+
# host - The IP address of the service (default: 127.0.0.1)
|
14
|
+
# port - The port number for the service (default: 5555)
|
15
|
+
# name - The name of the client for logging (default: zas-client)
|
16
|
+
# timeout - The timeout, in seconds, to wait for a response from the service (default: 1 second)
|
17
|
+
# logger - The logger (default: syslog)
|
9
18
|
def initialize(attributes={})
|
10
19
|
attributes.each do |k, v|
|
11
20
|
self[k] = v
|
12
21
|
end
|
13
22
|
end
|
23
|
+
|
14
24
|
def host
|
15
25
|
self[:host] || '127.0.0.1'
|
16
26
|
end
|
27
|
+
|
17
28
|
def port
|
18
29
|
self[:port] || '5555'
|
19
30
|
end
|
31
|
+
|
20
32
|
def name
|
21
33
|
self[:name] || 'zas-client'
|
22
34
|
end
|
35
|
+
|
23
36
|
def timeout
|
24
37
|
self[:timeout] || 1
|
25
38
|
end
|
39
|
+
|
40
|
+
def logger
|
41
|
+
self[:logger] || Syslogger.new(config.name, Syslog::LOG_PID, Syslog::LOG_LOCAL0)
|
42
|
+
end
|
26
43
|
end
|
27
44
|
end
|
data/lib/zas/credentials.rb
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
module Zas
|
2
|
-
# Handle credentials as a Hash
|
2
|
+
# Public: Handle credentials as a Hash
|
3
3
|
class Credentials
|
4
|
-
# Initialize the credentials with the given Hash.
|
4
|
+
# Public: Initialize the credentials with the given Hash.
|
5
5
|
#
|
6
6
|
# credentials - A Hash with the keys :username and :password
|
7
7
|
def initialize(credentials)
|
8
8
|
self.credentials = credentials
|
9
9
|
end
|
10
10
|
|
11
|
-
# Construct a wire representation of the credentials
|
11
|
+
# Public: Construct a wire representation of the credentials
|
12
12
|
#
|
13
13
|
# Returns the encoded JSON
|
14
14
|
def to_wire
|
@@ -1,13 +1,15 @@
|
|
1
1
|
module Zas
|
2
|
-
# Credentials as taken from HTTP Basic Authentication.
|
2
|
+
# Public: Credentials as taken from HTTP Basic Authentication.
|
3
3
|
class HttpBasicCredentials
|
4
|
-
# Construct the credentials with the base64 encoded value
|
4
|
+
# Public: Construct the credentials with the base64 encoded value
|
5
5
|
# passed directly from an HTTP request.
|
6
|
+
#
|
7
|
+
# base64_encoded_credentials - The Base64 encoded HTTP Basic credentials
|
6
8
|
def initialize(base64_encoded_credentials)
|
7
9
|
self.base64_encoded_credentials = base64_encoded_credentials
|
8
10
|
end
|
9
11
|
|
10
|
-
# Construct a wire representation of the credentials.
|
12
|
+
# Public: Construct a wire representation of the credentials.
|
11
13
|
#
|
12
14
|
# Returns the encoded JSON
|
13
15
|
def to_wire
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: zas-client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-05-14 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: zmq
|