summaryrefslogtreecommitdiff
path: root/provider_base
diff options
context:
space:
mode:
authorelijah <elijah@riseup.net>2014-10-31 00:01:57 -0700
committerelijah <elijah@riseup.net>2014-10-31 00:01:57 -0700
commit1d4670f8b9b4c1f3d4cd8017a3f6145ccdd41312 (patch)
treed3272ca05c567219d1f9a476b56f2a8cb808cb19 /provider_base
parentd3e24760b33d6ae20f153d3c144d7d443fb0b69e (diff)
add support for property tor.key
Diffstat (limited to 'provider_base')
-rw-r--r--provider_base/lib/macros.rb1
-rw-r--r--provider_base/lib/macros/files.rb14
-rw-r--r--provider_base/lib/macros/keys.rb78
-rw-r--r--provider_base/services/tor.json9
4 files changed, 99 insertions, 3 deletions
diff --git a/provider_base/lib/macros.rb b/provider_base/lib/macros.rb
index 854b92b5..ecc3e6ba 100644
--- a/provider_base/lib/macros.rb
+++ b/provider_base/lib/macros.rb
@@ -9,6 +9,7 @@ require_relative 'macros/core'
require_relative 'macros/files'
require_relative 'macros/haproxy'
require_relative 'macros/hosts'
+require_relative 'macros/keys'
require_relative 'macros/nodes'
require_relative 'macros/secrets'
require_relative 'macros/stunnel'
diff --git a/provider_base/lib/macros/files.rb b/provider_base/lib/macros/files.rb
index b3ba4a06..958958bc 100644
--- a/provider_base/lib/macros/files.rb
+++ b/provider_base/lib/macros/files.rb
@@ -48,13 +48,22 @@ module LeapCli
# * if the path does not exist locally, but exists in provider_base, then the default file from
# provider_base is copied locally. this is required for rsync to work correctly.
#
- def file_path(path)
+ def file_path(path, options={})
if path.is_a? Symbol
path = [path, @node.name]
+ elsif path.is_a? String
+ # ensure it prefixed with files/
+ unless path =~ /^files\//
+ path = "files/" + path
+ end
end
actual_path = Path.find_file(path)
if actual_path.nil?
- Util::log 2, :skipping, "file_path(\"#{path}\") because there is no such file."
+ if options[:missing]
+ raise FileMissing.new(Path.named_path(path), options)
+ else
+ Util::log 2, :skipping, "file_path(\"#{path}\") because there is no such file."
+ end
nil
else
if actual_path =~ /^#{Regexp.escape(Path.provider_base)}/
@@ -70,6 +79,7 @@ module LeapCli
actual_path += '/' # ensure directories end with /, important for building rsync command
end
relative_path = Path.relative_path(actual_path)
+ relative_path.sub!(/^files\//, '') # remove "files/" prefix
@node.file_paths << relative_path
File.join(Leap::Platform.files_dir, relative_path)
end
diff --git a/provider_base/lib/macros/keys.rb b/provider_base/lib/macros/keys.rb
new file mode 100644
index 00000000..0d46acb5
--- /dev/null
+++ b/provider_base/lib/macros/keys.rb
@@ -0,0 +1,78 @@
+# encoding: utf-8
+
+#
+# Macro for dealing with cryptographic keys
+#
+
+module LeapCli
+ module Macro
+
+ #
+ # return the path to the tor public key
+ # generating key if it is missing
+ #
+ def tor_public_key_path(path_name, key_type)
+ path = file_path(path_name)
+ if path.nil?
+ generate_tor_key(key_type)
+ end
+ return path
+ end
+
+ #
+ # return the path to the tor private key
+ # generating key if it is missing
+ #
+ def tor_private_key_path(path_name, key_type)
+ path = file_path(path_name)
+ if path.nil?
+ generate_tor_key(key_type)
+ end
+ return path
+ end
+
+ #
+ # on the command line an onion address can be created
+ # from an rsa public key using this:
+ #
+ # base64 -d < ./pubkey | sha1sum | awk '{print $1}' |
+ # perl -e '$l=<>; chomp $l; print pack("H*", $l)' |
+ # python -c 'import base64, sys; t=sys.stdin.read(); print base64.b32encode(t[:10]).lower()'
+ #
+ # path_name is the named path of the tor public key.
+ #
+ def onion_address(path_name)
+ require 'base32'
+ require 'base64'
+ require 'openssl'
+ path = Path.find_file([path_name, self.name])
+ if path && File.exists?(path)
+ public_key_str = File.readlines(path).grep(/^[^-]/).join
+ public_key = Base64.decode64(public_key_str)
+ sha1sum_string = Digest::SHA1.new.hexdigest(public_key)
+ sha1sum_binary = [sha1sum_string].pack('H*')
+ Base32.encode(sha1sum_binary.slice(0,10)).downcase
+ else
+ LeapCli.log :warning, 'Tor public key file "%s" does not exist' % tor_public_key_path
+ end
+ end
+
+ private
+
+ def generate_tor_key(key_type)
+ if key_type == 'RSA'
+ require 'certificate_authority'
+ keypair = CertificateAuthority::MemoryKeyMaterial.new
+ bit_size = 1024
+ LeapCli.log :generating, "%s bit RSA Tor key" % bit_size do
+ keypair.generate_key(bit_size)
+ LeapCli::Util.write_file! [:node_tor_priv_key, self.name], keypair.private_key.to_pem
+ LeapCli::Util.write_file! [:node_tor_pub_key, self.name], keypair.public_key.to_pem
+ end
+ else
+ LeapCli.bail! 'tor.key.type of %s is not yet supported' % key_type
+ end
+ end
+
+ end
+end
diff --git a/provider_base/services/tor.json b/provider_base/services/tor.json
index fc365a19..87fb9682 100644
--- a/provider_base/services/tor.json
+++ b/provider_base/services/tor.json
@@ -3,6 +3,13 @@
"bandwidth_rate": 6550,
"contacts": "= [provider.contacts['tor'] || provider.contacts.default].flatten",
"nickname": "= (self.name + secret(:tor_family)).sub('_','')[0..18]",
- "family": "= nodes[:services => 'tor'][:environment => '!local'].field('tor.nickname').join(',')"
+ "family": "= nodes[:services => 'tor'][:environment => '!local'].field('tor.nickname').join(',')",
+ "hidden_service": null,
+ "key": {
+ "type": "RSA",
+ "public": "= tor_public_key_path(:node_tor_pub_key, tor.key.type) if tor.hidden_service",
+ "private": "= tor_private_key_path(:node_tor_priv_key, tor.key.type) if tor.hidden_service",
+ "address": "= onion_address(:node_tor_pub_key) if tor.hidden_service"
+ }
}
}