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 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 initialize(url)
16
- @url = 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
- @consumers ||= JSON.parse RestClient.get("#{@url}consumers", :content_type => :json, :accept => :json);
60
+ user["consumers"]
29
61
  end
30
62
 
31
63
  def providers
32
- @providers ||= JSON.parse RestClient.get("#{@url}providers", :content_type => :json, :accept => :json);
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
- "#{user["ip"]}:#{user["port"]}" if user["ip"]
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
@@ -1,16 +1,40 @@
1
1
  module Fenris
2
2
  module Command
3
- def self.run(command, arg=nil, name=nil)
3
+ def self.run(command, *args)
4
+ arg, name = args
4
5
  begin
5
- client = Fenris::Client.new(ENV['FENRIS_URL']);
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 serve BINDING\n",
12
- " fenris connect [ USER [ BINDING ] ]" ]
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["provider"]}) #{c["ip"]} #{c["port"]}" }
55
+ client.providers.each { |c| puts " #{c["binding"] || "unbound"} #{c["name"]} (#{c["description"]}) #{c["location"]}" }
32
56
  end
33
- when "serve"
34
- from = 10001
35
- to = arg
36
- Fenris::Base.serve(client, from, to)
37
- when "connect"
38
- Fenris::Base.connect(client, arg, name)
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
- def producer_server(client, from, to)
57
- return producer_server_stdio(client, from, to) if to == "--"
58
- EventMachine::__send__ *mkbinding(:start_server, from), Fenris::Connection do |consumer|
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, to), Fenris::Connection do |producer|
69
+ EventMachine::__send__ *mkbinding(:connect, internal), Fenris::Connection do |provider|
64
70
  client.log "start proxying"
65
- producer.proxy consumer; consumer.proxy producer
71
+ provider.proxy consumer; consumer.proxy provider
66
72
  end
67
73
  end
68
74
  end
69
75
  end
70
76
 
71
- def producer_server_stdio(client, from, to)
72
- EventMachine::__send__ *mkbinding(:connect, to), Fenris::Connection do |producer|
73
- EventMachine::__send__ *mkbinding(:start_server, from), Fenris::Connection do |consumer|
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
- producer.proxy consumer; consumer.proxy producer
84
+ provider.proxy consumer; consumer.proxy provider
79
85
  end
80
86
  end
81
87
  end
82
88
  end
83
89
 
84
- def serve(client, listen_port, to)
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
- client.update "0.0.0.0", listen_port
90
- from = "0.0.0.0:#{listen_port}"
91
- client.log "Serving port #{to} on #{from}"
92
- producer_server(client, from, to)
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 connect(client, overide_provider = nil, override_binding = nil)
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"], "#{p["ip"]}:#{p["port"]}")
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
-
@@ -1,3 +1,3 @@
1
1
  module Fenris
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
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.1
4
+ version: 0.0.2
5
5
  segments:
6
6
  - 0
7
7
  - 0
8
- - 1
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-18 00:00:00.000000000 -07:00
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: &2168813480 !ruby/object:Gem::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: *2168813480
33
+ version_requirements: *2155696200
34
34
  - !ruby/object:Gem::Dependency
35
35
  name: rest-client
36
- requirement: &2168811760 !ruby/object:Gem::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: *2168811760
48
+ version_requirements: *2155694060
49
49
  - !ruby/object:Gem::Dependency
50
50
  name: multi_json
51
- requirement: &2168810220 !ruby/object:Gem::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: *2168810220
63
+ version_requirements: *2155692380
64
64
  description: An authentication and service location service.
65
65
  email: orion.henry@gmail.com
66
66
  executables: