fenris 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- 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:
|