Class: Fenris::Client
- Inherits:
-
Object
- Object
- Fenris::Client
- Defined in:
- lib/fenris/client.rb
Constant Summary collapse
- UPDATE_INTERVAL =
10
Instance Method Summary collapse
- #add(name) ⇒ Object
- #bind(name, binding) ⇒ Object
- #bind_location ⇒ Object
- #cert(name) ⇒ Object
- #cert_path(name) ⇒ Object
- #config_dir ⇒ Object
- #consume(arg = nil, &blk) ⇒ Object
- #consumers ⇒ Object
- #debug(message) ⇒ Object
- #digest(obj) ⇒ Object
- #exec(*args) ⇒ Object
- #generate_csr(cn) ⇒ Object
- #get_authkey_from_stdin ⇒ Object
- #get_cn(cert) ⇒ Object
-
#initialize(url, options = OpenStruct.new) ⇒ Client
constructor
A new instance of Client.
- #key ⇒ Object
- #location ⇒ Object
- #location_of(provider) ⇒ Object
- #log(message) ⇒ Object
- #my_cert ⇒ Object
- #my_cert_path ⇒ Object
- #my_key ⇒ Object
- #my_key_path ⇒ Object
- #options ⇒ Object
- #post_location ⇒ Object
- #provide(local_binding) ⇒ Object
- #provider_map ⇒ Object
- #providers ⇒ Object
- #read_cert(cn) ⇒ Object
- #read_config_file(name) ⇒ Object
- #rekey ⇒ Object
- #remove(name) ⇒ Object
- #root ⇒ Object
- #ssl? ⇒ Boolean
- #update_config(verbose = true) ⇒ Object
- #update_user_config ⇒ Object
- #url ⇒ Object
- #user ⇒ Object
- #user_name ⇒ Object
- #useradd(name) ⇒ Object
- #userdel(name) ⇒ Object
- #users ⇒ Object
- #validate_peer(pem, peer_connection = nil, peer_name = nil) ⇒ Object
- #verify_cert(cn) ⇒ Object
- #verify_private_key ⇒ Object
- #write(object) ⇒ Object
- #write_cert(cert) ⇒ Object
- #write_config_file(name, data) ⇒ Object
Constructor Details
#initialize(url, options = OpenStruct.new) ⇒ Client
Returns a new instance of Client.
13 14 15 16 17 18 19 |
# File 'lib/fenris/client.rb', line 13 def initialize(url, = OpenStruct.new) @url = url @url = URI.parse(url) unless url.is_a? URI = OpenStruct.new if .is_a? Hash @options = @verbose = false end |
Instance Method Details
#add(name) ⇒ Object
214 215 216 217 |
# File 'lib/fenris/client.rb', line 214 def add(name) update_user_config RestClient.post("#{url}consumers", { :name => name }, :content_type => :json, :accept => :json); end |
#bind(name, binding) ⇒ Object
242 243 244 245 |
# File 'lib/fenris/client.rb', line 242 def bind(name, binding) update_user_config RestClient.put("#{url}providers/#{name}", { :binding => binding }, :content_type => :json, :accept => :json); end |
#bind_location ⇒ Object
193 194 195 |
# File 'lib/fenris/client.rb', line 193 def bind_location "0.0.0.0:#{.port}" end |
#cert(name) ⇒ Object
86 87 88 |
# File 'lib/fenris/client.rb', line 86 def cert(name) read_config_file "#{user_name}:#{name}.crt" end |
#cert_path(name) ⇒ Object
90 91 92 |
# File 'lib/fenris/client.rb', line 90 def cert_path(name) "#{config_dir}/#{user_name}:#{name}.crt" end |
#config_dir ⇒ Object
43 44 45 |
# File 'lib/fenris/client.rb', line 43 def config_dir .config end |
#consume(arg = nil, &blk) ⇒ Object
306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 |
# File 'lib/fenris/client.rb', line 306 def consume(arg = nil, &blk) update_config map = arg if arg.is_a? Hash map = { arg => provider_map[arg] } if arg.is_a? String map ||= provider_map EventMachine::run do EventMachine::PeriodicTimer.new(UPDATE_INTERVAL) { update_config(false) } if .autosync map.each do |provider, binding| ConsumerLocal.begin(self, location_of(provider), provider, binding) end blk.call if blk end end |
#consumers ⇒ Object
197 198 199 |
# File 'lib/fenris/client.rb', line 197 def consumers user["consumers"] end |
#debug(message) ⇒ Object
137 138 139 |
# File 'lib/fenris/client.rb', line 137 def debug() puts "DEBUG: #{}" if .debug and not .quiet end |
#digest(obj) ⇒ Object
247 248 249 |
# File 'lib/fenris/client.rb', line 247 def digest obj OpenSSL::Digest::SHA1.new(obj.to_der).to_s end |
#exec(*args) ⇒ Object
322 323 324 325 326 327 328 329 330 |
# File 'lib/fenris/client.rb', line 322 def exec(*args) command = args.join(' ') consume do Thread.new do system command EventMachine::stop end end end |
#generate_csr(cn) ⇒ Object
251 252 253 254 255 256 257 258 259 260 261 |
# File 'lib/fenris/client.rb', line 251 def generate_csr(cn) subject = OpenSSL::X509::Name.parse "/DC=org/DC=fenris/CN=#{cn}" digest = OpenSSL::Digest::SHA1.new req = OpenSSL::X509::Request.new req.version = 0 req.subject = subject req.public_key = key.public_key req.sign(key, digest) log "generating csr #{digest req} #{subject}" req end |
#get_authkey_from_stdin ⇒ Object
33 34 35 36 37 38 39 40 41 |
# File 'lib/fenris/client.rb', line 33 def get_authkey_from_stdin begin system "stty -echo" print "Authkey: " $stdin.gets.chomp ensure system "stty echo" end end |
#get_cn(cert) ⇒ Object
263 264 265 |
# File 'lib/fenris/client.rb', line 263 def get_cn(cert) cert.subject.to_a.detect { |a,b,c| a == "CN" }[1] rescue nil end |
#key ⇒ Object
291 292 293 |
# File 'lib/fenris/client.rb', line 291 def key read_config_file "#{user_name}.key" end |
#location ⇒ Object
189 190 191 |
# File 'lib/fenris/client.rb', line 189 def location "#{.host}:#{.port}" end |
#location_of(provider) ⇒ Object
181 182 183 184 185 186 187 |
# File 'lib/fenris/client.rb', line 181 def location_of(provider) if p = providers.detect { |p| p["name"] == provider } p["locations"].first else raise NoSuchProvider, provider end end |
#log(message) ⇒ Object
141 142 143 |
# File 'lib/fenris/client.rb', line 141 def log() puts "LOG: #{}" if not .quiet end |
#my_cert ⇒ Object
78 79 80 |
# File 'lib/fenris/client.rb', line 78 def my_cert read_config_file "#{user_name}.crt" end |
#my_cert_path ⇒ Object
94 95 96 |
# File 'lib/fenris/client.rb', line 94 def my_cert_path "#{config_dir}/#{user_name}.crt" end |
#my_key ⇒ Object
82 83 84 |
# File 'lib/fenris/client.rb', line 82 def my_key read_config_file "#{user_name}.key" end |
#my_key_path ⇒ Object
98 99 100 |
# File 'lib/fenris/client.rb', line 98 def my_key_path "#{config_dir}/#{user_name}.key" end |
#options ⇒ Object
21 22 23 |
# File 'lib/fenris/client.rb', line 21 def @options end |
#post_location ⇒ Object
145 146 147 |
# File 'lib/fenris/client.rb', line 145 def post_location RestClient.put("#{url}", { :location => location }, :content_type => :json, :accept => :json) end |
#provide(local_binding) ⇒ Object
297 298 299 300 301 302 303 304 |
# File 'lib/fenris/client.rb', line 297 def provide(local_binding) update_config EventMachine::run do EventMachine::PeriodicTimer.new(UPDATE_INTERVAL) { Thread.new { update_config(false) } } if .autosync post_location ProviderServer.begin(self, bind_location, local_binding) end end |
#provider_map ⇒ Object
177 178 179 |
# File 'lib/fenris/client.rb', line 177 def provider_map Hash[ * providers.map { |p| [ p["name"], p["binding"] ] }.flatten ] end |
#providers ⇒ Object
201 202 203 |
# File 'lib/fenris/client.rb', line 201 def providers user["providers"] end |
#read_cert(cn) ⇒ Object
67 68 69 70 71 72 73 74 75 76 |
# File 'lib/fenris/client.rb', line 67 def read_cert cn if cert = read_config_file("#{cn}.crt") if cert.not_after > Time.now cert else log "cert expired #{digest cert} :: #{cert.not_after} :: #{cn}" nil end end end |
#read_config_file(name) ⇒ Object
112 113 114 115 116 117 118 119 120 121 122 123 124 125 |
# File 'lib/fenris/client.rb', line 112 def read_config_file name path = "#{config_dir}/#{name}" if not File.exists? path nil elsif name =~ /[.]json$/ JSON.parse File.read(path) elsif name =~ /[.]crt$/ OpenSSL::X509::Certificate.new File.read(path) elsif name =~ /[.]key$/ OpenSSL::PKey::RSA.new File.read(path) else File.read path end end |
#rekey ⇒ Object
226 227 228 229 230 231 |
# File 'lib/fenris/client.rb', line 226 def rekey update_user_config newkey = RestClient.post("#{url}authkeys", { }, :content_type => :json, :accept => :json); write_config_file "#{user_name}.authkey", newkey newkey end |
#remove(name) ⇒ Object
209 210 211 212 |
# File 'lib/fenris/client.rb', line 209 def remove(name) update_user_config RestClient.delete("#{url}consumers/#{name}"); end |
#root ⇒ Object
287 288 289 |
# File 'lib/fenris/client.rb', line 287 def root read_config_file "root.crt" end |
#ssl? ⇒ Boolean
153 154 155 |
# File 'lib/fenris/client.rb', line 153 def ssl? @url.scheme == "https" end |
#update_config(verbose = true) ⇒ Object
163 164 165 166 167 168 169 170 171 172 173 174 175 |
# File 'lib/fenris/client.rb', line 163 def update_config(verbose = true) @verbose = verbose log "updating config in #{config_dir}" if @verbose update_user_config log "have update user config" if @verbose write_config_file "root.crt", RestClient.get("#{url}cert") ## TODO find a way to get this out of the connection info verify_private_key verify_cert user_name providers.each do |p| verify_cert "#{user_name}:#{p["name"]}" end @verbose = false end |
#update_user_config ⇒ Object
157 158 159 160 161 |
# File 'lib/fenris/client.rb', line 157 def update_user_config @user = JSON.parse RestClient.get("#{url}", :content_type => :json, :accept => :json) write_config_file "#{user_name}.authkey", @url.password write user end |
#url ⇒ Object
25 26 27 28 29 30 31 |
# File 'lib/fenris/client.rb', line 25 def url @url.user = .user @url.password = read_config_file("#{user_name}.authkey") @url.password ||= .password @url.password ||= get_authkey_from_stdin @url end |
#user ⇒ Object
149 150 151 |
# File 'lib/fenris/client.rb', line 149 def user @user ||= read_config_file "config.json" end |
#user_name ⇒ Object
205 206 207 |
# File 'lib/fenris/client.rb', line 205 def user_name .user end |
#useradd(name) ⇒ Object
219 220 221 222 223 224 |
# File 'lib/fenris/client.rb', line 219 def useradd(name) update_user_config newuser = JSON.parse RestClient.post("#{url}users", { :name => name }, :content_type => :json, :accept => :json); write_config_file "#{newuser["name"]}.authkey", newuser["authkey"] newuser end |
#userdel(name) ⇒ Object
237 238 239 240 |
# File 'lib/fenris/client.rb', line 237 def userdel(name) update_user_config RestClient.delete("#{url}users/#{name}", :content_type => :json, :accept => :json); end |
#users ⇒ Object
233 234 235 |
# File 'lib/fenris/client.rb', line 233 def users user["subusers"] end |
#validate_peer(pem, peer_connection = nil, peer_name = nil) ⇒ Object
267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 |
# File 'lib/fenris/client.rb', line 267 def validate_peer(pem, peer_connection = nil, peer_name = nil) consumer_cert = OpenSSL::X509::Certificate.new(pem) cert_cn = get_cn(consumer_cert) valid_peer_names = [ peer_name ] if peer_name valid_peer_names ||= consumers.map { |c| c["name"] } consumer_cn,provider_cn = cert_cn.split ":" provider_cn_ok = !!user_name consumer_cn_ok = !!valid_peer_names.detect { |name| name == consumer_cn } cert_ok = !!consumer_cert.verify(root.public_key) log "Consumer Cert CN '#{cert_cn}' displays correct provider? #{provider_cn_ok}" log "Consumer Cert CN '#{cert_cn}' in allowed_list? #{consumer_cn_ok}" log "Consumer Cert Signed By Broker? '#{cert_ok}'" result = consumer_cn_ok and provider_cn_ok and cert_ok unless result log "Certificate verification failed. connection closed [#{consumer_cn_ok}] [#{provider_cn_ok}] [#{cert_ok}]" peer_connection.close_connection if peer_connection end result end |
#verify_cert(cn) ⇒ Object
57 58 59 60 61 62 63 64 65 |
# File 'lib/fenris/client.rb', line 57 def verify_cert(cn) if cert = read_cert(cn) log "existing cert #{digest cert} :: #{cert.not_after} :: #{cn}" if @verbose else cert = OpenSSL::X509::Certificate.new(RestClient.post("#{url}cert", :csr => generate_csr(cn))) write cert log "new cert received #{digest cert} :: #{cert.not_after} :: #{cn}" end end |
#verify_private_key ⇒ Object
47 48 49 50 51 52 53 54 55 |
# File 'lib/fenris/client.rb', line 47 def verify_private_key if key = read_config_file("#{user_name}.key") log "using existing key #{digest key}" if @verbose else key = OpenSSL::PKey::RSA.new(2048) write key log "new rsa key generated #{digest key}" end end |
#write(object) ⇒ Object
127 128 129 130 131 132 133 134 135 |
# File 'lib/fenris/client.rb', line 127 def write object if object.is_a? OpenSSL::X509::Certificate write_config_file "#{get_cn(object)}.crt", object.to_pem elsif object.is_a? OpenSSL::PKey::RSA write_config_file "#{user_name}.key", object.to_pem else write_config_file "#{user_name}.json", object.to_json end end |
#write_cert(cert) ⇒ Object
102 103 104 |
# File 'lib/fenris/client.rb', line 102 def write_cert(cert) write_config_file "#{get_cn(cert)}.crt", cert end |
#write_config_file(name, data) ⇒ Object
106 107 108 109 110 |
# File 'lib/fenris/client.rb', line 106 def write_config_file name, data File.umask 0077 Dir.mkdir config_dir unless Dir.exists? config_dir File.open("#{config_dir}/#{name}","w") { |f| f.write(data) } end |