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 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: