fenris 0.0.1 → 0.0.2
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/lib/fenris/client.rb +57 -9
- data/lib/fenris/command.rb +41 -11
- data/lib/fenris/em.rb +39 -18
- data/lib/fenris/version.rb +1 -1
- metadata +9 -9
data/lib/fenris/client.rb
CHANGED
@@ -1,9 +1,16 @@
|
|
1
1
|
require 'restclient'
|
2
2
|
require 'json'
|
3
3
|
require 'openssl'
|
4
|
+
require 'uri'
|
5
|
+
require 'eventmachine'
|
4
6
|
|
5
7
|
module Fenris
|
6
8
|
class Client
|
9
|
+
def initialize(url)
|
10
|
+
@url = url
|
11
|
+
@url = URI.parse(url) unless url.is_a? URI
|
12
|
+
end
|
13
|
+
|
7
14
|
def debug(message)
|
8
15
|
puts "DEBUG: #{message}" if ENV['DEBUG']
|
9
16
|
end
|
@@ -12,24 +19,49 @@ module Fenris
|
|
12
19
|
puts "LOG: #{message}"
|
13
20
|
end
|
14
21
|
|
15
|
-
def
|
16
|
-
@url
|
17
|
-
end
|
18
|
-
|
19
|
-
def update(ip, port)
|
20
|
-
RestClient.put("#{@url}", { :ip => ip, :port => port }, :content_type => :json, :accept => :json)
|
22
|
+
def update(location)
|
23
|
+
RestClient.put("#{@url}", { :location => location }, :content_type => :json, :accept => :json)
|
21
24
|
end
|
22
25
|
|
23
26
|
def user
|
24
27
|
@user ||= JSON.parse RestClient.get("#{@url}", :content_type => :json, :accept => :json)
|
25
28
|
end
|
26
29
|
|
30
|
+
def ssl?
|
31
|
+
@url.scheme == "https"
|
32
|
+
end
|
33
|
+
|
34
|
+
def async_connection
|
35
|
+
@async_connection = nil if @async_connection && @async_connection.error?
|
36
|
+
@async_connection ||= EM::Protocols::HttpClient2.connect :host => @url.host, :port => @url.port, :ssl => ssl?
|
37
|
+
end
|
38
|
+
|
39
|
+
def auth_string
|
40
|
+
"Basic " + ["#{@url.user}:#{@url.password}"].pack('m').strip.gsub(/\n/,'')
|
41
|
+
end
|
42
|
+
|
43
|
+
def async_update(&blk)
|
44
|
+
request = async_connection.get(:uri => "/", :authorization => auth_string )
|
45
|
+
request.callback do |response|
|
46
|
+
if response.status == 200
|
47
|
+
# TODO - output if something has changed
|
48
|
+
@broker ||= OpenSSL::X509::Certificate.new(async_connection.get_peer_cert) if ssl?
|
49
|
+
@user = JSON.parse response.content
|
50
|
+
else
|
51
|
+
log "Error updating user info"
|
52
|
+
debug response.status
|
53
|
+
@async_connection = nil
|
54
|
+
end
|
55
|
+
blk.call if blk
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
27
59
|
def consumers
|
28
|
-
|
60
|
+
user["consumers"]
|
29
61
|
end
|
30
62
|
|
31
63
|
def providers
|
32
|
-
|
64
|
+
user["providers"]
|
33
65
|
end
|
34
66
|
|
35
67
|
def user_name
|
@@ -37,7 +69,7 @@ module Fenris
|
|
37
69
|
end
|
38
70
|
|
39
71
|
def route
|
40
|
-
|
72
|
+
user["location"]
|
41
73
|
end
|
42
74
|
|
43
75
|
def remove(name)
|
@@ -48,6 +80,22 @@ module Fenris
|
|
48
80
|
RestClient.post("#{@url}consumers", { :name => name }, :content_type => :json, :accept => :json);
|
49
81
|
end
|
50
82
|
|
83
|
+
def useradd(name)
|
84
|
+
JSON.parse RestClient.post("#{@url}users", { :name => name }, :content_type => :json, :accept => :json);
|
85
|
+
end
|
86
|
+
|
87
|
+
def rekey
|
88
|
+
RestClient.post("#{@url}authkeys", { }, :content_type => :json, :accept => :json);
|
89
|
+
end
|
90
|
+
|
91
|
+
def users
|
92
|
+
JSON.parse RestClient.get("#{@url}users", :content_type => :json, :accept => :json)
|
93
|
+
end
|
94
|
+
|
95
|
+
def userdel(name)
|
96
|
+
RestClient.delete("#{@url}users/#{name}", :content_type => :json, :accept => :json);
|
97
|
+
end
|
98
|
+
|
51
99
|
def bind(name, binding)
|
52
100
|
RestClient.put("#{@url}providers/#{name}", { :binding => binding }, :content_type => :json, :accept => :json);
|
53
101
|
end
|
data/lib/fenris/command.rb
CHANGED
@@ -1,16 +1,40 @@
|
|
1
1
|
module Fenris
|
2
2
|
module Command
|
3
|
-
def self.run(command,
|
3
|
+
def self.run(command, *args)
|
4
|
+
arg, name = args
|
4
5
|
begin
|
5
|
-
|
6
|
+
url = URI.parse(ENV['FENRIS_URL'] || 'https://broker.fenris.cc')
|
7
|
+
url.user ||= ENV['FENRIS_USER']
|
8
|
+
url.password ||= ENV['FENRIS_AUTHKEY']
|
9
|
+
client = Fenris::Client.new url
|
6
10
|
help = [ "Usage: fenris help\n",
|
7
11
|
" fenris info\n",
|
8
12
|
" fenris bind PROVIDER BINDING\n",
|
13
|
+
" fenris useradd NAME\n",
|
14
|
+
" fenris userdel NAME\n",
|
15
|
+
" fenris users\n",
|
16
|
+
" fenris rekey\n",
|
9
17
|
" fenris add CONSUMER\n",
|
10
18
|
" fenris remove CONSUMER\n",
|
11
|
-
" fenris
|
12
|
-
" fenris
|
19
|
+
" fenris exec COMMAND\n",
|
20
|
+
" fenris provide BINDING\n",
|
21
|
+
" fenris consume [ USER [ BINDING ] ]" ]
|
13
22
|
case command
|
23
|
+
when "users"
|
24
|
+
client.users.each do |u|
|
25
|
+
puts u["name"]
|
26
|
+
end
|
27
|
+
when "userdel"
|
28
|
+
client.userdel(arg)
|
29
|
+
when "useradd"
|
30
|
+
new_user = client.useradd(arg)
|
31
|
+
puts "New user created"
|
32
|
+
puts "export FENRIS_USER='#{new_user["name"]}'"
|
33
|
+
puts "export FENRIS_AUTHKEY='#{new_user["authkey"]}'"
|
34
|
+
when "rekey"
|
35
|
+
newkey = client.rekey
|
36
|
+
puts "New Key Assigned:"
|
37
|
+
puts "export FENRIS_AUTHKEY='#{newkey}'"
|
14
38
|
when "cert"
|
15
39
|
puts client.cert.to_text
|
16
40
|
when "bind"
|
@@ -28,14 +52,16 @@ module Fenris
|
|
28
52
|
end
|
29
53
|
unless client.providers.empty?
|
30
54
|
puts "SERVICES:"
|
31
|
-
client.providers.each { |c| puts " #{c["binding"] || "unbound"} #{c["name"]} (#{c["
|
55
|
+
client.providers.each { |c| puts " #{c["binding"] || "unbound"} #{c["name"]} (#{c["description"]}) #{c["location"]}" }
|
32
56
|
end
|
33
|
-
when "
|
34
|
-
|
35
|
-
|
36
|
-
Fenris::Base.
|
37
|
-
when "
|
38
|
-
Fenris::Base.
|
57
|
+
when "provide"
|
58
|
+
external = "#{Socket.gethostname}:#{10001}"
|
59
|
+
internal = arg
|
60
|
+
Fenris::Base.provide(client, external, internal)
|
61
|
+
when "consume"
|
62
|
+
Fenris::Base.consume(client, arg, name)
|
63
|
+
when "exec"
|
64
|
+
Fenris::Base.exec(client, *args)
|
39
65
|
else
|
40
66
|
puts command.inspect
|
41
67
|
puts help
|
@@ -43,6 +69,10 @@ module Fenris
|
|
43
69
|
exit
|
44
70
|
end
|
45
71
|
rescue SystemExit
|
72
|
+
rescue RestClient::Conflict
|
73
|
+
puts "Duplicate"
|
74
|
+
rescue RestClient::Unauthorized
|
75
|
+
puts "Unauthorized"
|
46
76
|
rescue RestClient::ResourceNotFound
|
47
77
|
puts "Resource Not Found"
|
48
78
|
exit
|
data/lib/fenris/em.rb
CHANGED
@@ -23,13 +23,17 @@ module Fenris
|
|
23
23
|
@validator = blk;
|
24
24
|
end
|
25
25
|
|
26
|
+
def on_unbind(&blk)
|
27
|
+
@on_unbind = blk
|
28
|
+
end
|
29
|
+
|
26
30
|
def ssl_verify_peer(pem)
|
27
31
|
@verify ||= @validator.call(pem)
|
28
32
|
end
|
29
33
|
|
30
34
|
def unbind
|
35
|
+
@on_unbind.call(self) if @on_unbind
|
31
36
|
@unbound = true
|
32
|
-
puts "DEBUG: unbind #{@signature}"
|
33
37
|
EM::stop if @signature < 3 ## this is for attach($stdin)
|
34
38
|
@peer.close_connection_after_writing rescue nil
|
35
39
|
close_connection
|
@@ -53,43 +57,45 @@ module Fenris
|
|
53
57
|
module Base
|
54
58
|
extend self
|
55
59
|
|
56
|
-
|
57
|
-
|
58
|
-
|
60
|
+
UPDATE_INTERVAL = 2
|
61
|
+
|
62
|
+
def listen(client, external, internal)
|
63
|
+
return listen_stdio(client, external, internal) if internal == "--"
|
64
|
+
EventMachine::__send__ *mkbinding(:start_server, external), Fenris::Connection do |consumer|
|
59
65
|
client.log "New connection - begin ssl handshake"
|
60
66
|
consumer.validate_peer { |pem| client.validate_peer pem }
|
61
67
|
consumer.begin_ssl :key_file => client.key_path , :cert_file => client.cert_path do
|
62
68
|
client.log "SSL complete - open local connection"
|
63
|
-
EventMachine::__send__ *mkbinding(:connect,
|
69
|
+
EventMachine::__send__ *mkbinding(:connect, internal), Fenris::Connection do |provider|
|
64
70
|
client.log "start proxying"
|
65
|
-
|
71
|
+
provider.proxy consumer; consumer.proxy provider
|
66
72
|
end
|
67
73
|
end
|
68
74
|
end
|
69
75
|
end
|
70
76
|
|
71
|
-
def
|
72
|
-
EventMachine::__send__ *mkbinding(:connect,
|
73
|
-
EventMachine::__send__ *mkbinding(:start_server,
|
77
|
+
def listen_stdio(client, external, internal)
|
78
|
+
EventMachine::__send__ *mkbinding(:connect, internal), Fenris::Connection do |provider|
|
79
|
+
EventMachine::__send__ *mkbinding(:start_server, external), Fenris::Connection do |consumer|
|
74
80
|
client.log "stdio connection - begin ssl handshake"
|
75
81
|
consumer.validate_peer { |pem| client.validate_peer pem }
|
76
82
|
consumer.begin_ssl :key_file => client.key_path , :cert_file => client.cert_path do
|
77
83
|
client.log "SSL complete - start proxying"
|
78
|
-
|
84
|
+
provider.proxy consumer; consumer.proxy provider
|
79
85
|
end
|
80
86
|
end
|
81
87
|
end
|
82
88
|
end
|
83
89
|
|
84
|
-
def
|
90
|
+
def provide(client, external, internal)
|
85
91
|
at_exit { client.cleanup }
|
86
92
|
|
87
93
|
EventMachine::run do
|
88
94
|
client.save_keys
|
89
|
-
|
90
|
-
|
91
|
-
client.log "Serving port #{
|
92
|
-
|
95
|
+
EventMachine::PeriodicTimer.new(UPDATE_INTERVAL) { client.async_update }
|
96
|
+
client.update external
|
97
|
+
client.log "Serving port #{internal} on #{external}"
|
98
|
+
listen client, external, internal
|
93
99
|
end
|
94
100
|
end
|
95
101
|
|
@@ -107,6 +113,7 @@ module Fenris
|
|
107
113
|
|
108
114
|
## really want to unify all these :(
|
109
115
|
def consumer_connect(client, consumer, provider_name, provider)
|
116
|
+
client.log "COMSUMER CONNECT #{consumer.inspect} #{provider_name.inspect} #{provider.inspect}"
|
110
117
|
EventMachine::__send__ *mkbinding(:start_server, consumer), Fenris::Connection do |consumer|
|
111
118
|
client.log "New connection: opening connection to the server"
|
112
119
|
EventMachine::__send__ *mkbinding(:connect, provider), Fenris::Connection do |provider|
|
@@ -120,7 +127,7 @@ module Fenris
|
|
120
127
|
end
|
121
128
|
end
|
122
129
|
|
123
|
-
def
|
130
|
+
def consume(client, overide_provider = nil, override_binding = nil)
|
124
131
|
at_exit { client.cleanup }
|
125
132
|
|
126
133
|
client.save_keys
|
@@ -133,13 +140,27 @@ module Fenris
|
|
133
140
|
abort "Can only pass a binding for a single provider" if override_binding && providers.length != 1
|
134
141
|
|
135
142
|
EventMachine::run do
|
143
|
+
EventMachine::PeriodicTimer.new(UPDATE_INTERVAL) { client.async_update }
|
136
144
|
providers.each do |p|
|
137
145
|
binding = override_binding || p["binding"]
|
138
|
-
consumer_connect(client, binding, p["name"],
|
146
|
+
consumer_connect(client, binding, p["name"], p["location"])
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
def exec(client, *args)
|
152
|
+
command = args.join(' ')
|
153
|
+
EventMachine::run do
|
154
|
+
consume(client)
|
155
|
+
stdin = EventMachine.attach $stdin, Connection
|
156
|
+
EventMachine::popen command, Connection do |ps|
|
157
|
+
puts "execing command '#{command}'"
|
158
|
+
ps.on_unbind { EventMachine::stop }
|
159
|
+
stdin.on_unbind { EventMachine::stop }
|
160
|
+
ps.proxy stdin; stdin.proxy ps
|
139
161
|
end
|
140
162
|
end
|
141
163
|
end
|
142
164
|
end
|
143
165
|
end
|
144
166
|
|
145
|
-
|
data/lib/fenris/version.rb
CHANGED
metadata
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fenris
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 0
|
8
|
-
-
|
8
|
+
- 2
|
9
9
|
prerelease: false
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
@@ -13,12 +13,12 @@ authors:
|
|
13
13
|
autorequire:
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
|
-
date: 2011-10-
|
16
|
+
date: 2011-10-24 00:00:00.000000000 -07:00
|
17
17
|
default_executable:
|
18
18
|
dependencies:
|
19
19
|
- !ruby/object:Gem::Dependency
|
20
20
|
name: eventmachine
|
21
|
-
requirement: &
|
21
|
+
requirement: &2155696200 !ruby/object:Gem::Requirement
|
22
22
|
none: false
|
23
23
|
requirements:
|
24
24
|
- - ! '>='
|
@@ -30,10 +30,10 @@ dependencies:
|
|
30
30
|
- 10
|
31
31
|
type: :runtime
|
32
32
|
prerelease: false
|
33
|
-
version_requirements: *
|
33
|
+
version_requirements: *2155696200
|
34
34
|
- !ruby/object:Gem::Dependency
|
35
35
|
name: rest-client
|
36
|
-
requirement: &
|
36
|
+
requirement: &2155694060 !ruby/object:Gem::Requirement
|
37
37
|
none: false
|
38
38
|
requirements:
|
39
39
|
- - ! '>='
|
@@ -45,10 +45,10 @@ dependencies:
|
|
45
45
|
- 7
|
46
46
|
type: :runtime
|
47
47
|
prerelease: false
|
48
|
-
version_requirements: *
|
48
|
+
version_requirements: *2155694060
|
49
49
|
- !ruby/object:Gem::Dependency
|
50
50
|
name: multi_json
|
51
|
-
requirement: &
|
51
|
+
requirement: &2155692380 !ruby/object:Gem::Requirement
|
52
52
|
none: false
|
53
53
|
requirements:
|
54
54
|
- - ! '>='
|
@@ -60,7 +60,7 @@ dependencies:
|
|
60
60
|
- 3
|
61
61
|
type: :runtime
|
62
62
|
prerelease: false
|
63
|
-
version_requirements: *
|
63
|
+
version_requirements: *2155692380
|
64
64
|
description: An authentication and service location service.
|
65
65
|
email: orion.henry@gmail.com
|
66
66
|
executables:
|