summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--platform.rb12
-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
5 files changed, 106 insertions, 8 deletions
diff --git a/platform.rb b/platform.rb
index 06a49b7e..c37b6d29 100644
--- a/platform.rb
+++ b/platform.rb
@@ -5,7 +5,7 @@
Leap::Platform.define do
self.version = "0.6"
- self.compatible_cli = "1.6.0".."1.99"
+ self.compatible_cli = "1.6.1".."1.99"
#
# the facter facts that should be gathered
@@ -77,10 +77,12 @@ Leap::Platform.define do
:vagrantfile => 'test/Vagrantfile',
# node output files
- :hiera => 'hiera/#{arg}.yaml',
- :node_ssh_pub_key => 'files/nodes/#{arg}/#{arg}_ssh.pub',
- :node_x509_key => 'files/nodes/#{arg}/#{arg}.key',
- :node_x509_cert => 'files/nodes/#{arg}/#{arg}.crt',
+ :hiera => 'hiera/#{arg}.yaml',
+ :node_ssh_pub_key => 'files/nodes/#{arg}/#{arg}_ssh.pub',
+ :node_x509_key => 'files/nodes/#{arg}/#{arg}.key',
+ :node_x509_cert => 'files/nodes/#{arg}/#{arg}.crt',
+ :node_tor_priv_key => 'files/nodes/#{arg}/tor.key',
+ :node_tor_pub_key => 'files/nodes/#{arg}/tor.pub',
# testing files
:test_client_key => 'test/cert/client.key',
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"
+ }
}
}