diff options
author | kwadronaut <kwadronaut@leap.se> | 2018-11-07 15:43:41 +0100 |
---|---|---|
committer | kwadronaut <kwadronaut@leap.se> | 2018-11-07 15:43:41 +0100 |
commit | e598088c2f9263e7682e399b65376d7a2c529ded (patch) | |
tree | aa628edf0ad55dc2adea8bc6f96bf516aaba0a30 | |
parent | d30831f7214da266ad943cf4013f0632e8b15d48 (diff) | |
parent | 77070c6bf97ecd6fc860cae6120dca86fa910e5a (diff) |
58 files changed, 1134 insertions, 665 deletions
@@ -1 +1,9 @@ +.tmp_*~ *.swp +.librarian +.tmp +spec/fixtures/modules +spec/fixtures/manifests +spec/tmp +!spec/tmp/.keep +*.lock diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 611058c..268210d 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,39 +1,21 @@ -image: ruby:2.1 -before_script: - - bundle install --jobs $(nproc) --without system_tests --path=/var/cache/gitlab-runner/ "${FLAGS[@]}" +image: ruby:2.3 -.job_template: &job_definition +# Test job template +.test_template: &test_definition + stage: test script: - # don't fail on lint warnings - - bundle exec rake lint || /bin/true - - bundle exec rake syntax - - bundle exec rake validate + - bundle install --jobs $(nproc) --without docs --path vendor + - bundle exec rake tests - bundle exec rake spec -# Default debian jessie versions -test:puppet37: - variables: - PUPPET_VERSION: "~> 3.7.2" - FACTER_VERSION: '~> 2.2.0' - <<: *job_definition - -test:puppet38_future_parser: - variables: - PUPPET_VERSION: '~> 3.8' - FACTER_VERSION: '~> 2.2.0' - FUTURE_PARSER: 'yes' - <<: *job_definition - -# Default debian stretch versions +# Test with version present on Debian stable test:puppet48: variables: PUPPET_VERSION: "~> 4.8.2" FACTER_VERSION: '~> 2.4.6' - <<: *job_definition + HIERA_VERSION: '~> 3.2.0' + <<: *test_definition -# Latest greatest -test:puppet4x: - variables: - PUPPET_VERSION: "> 4" - FACTER_VERSION: '> 2' - <<: *job_definition +# Test with latest Puppet release +test:puppetlatest: + <<: *test_definition @@ -1,23 +1,18 @@ -source "https://rubygems.org" +# vim:ft=ruby +source 'https://rubygems.org' -group :development, :unit_tests do - gem "rake" - gem "rspec-puppet", "~> 2.1", :require => false - gem "rspec-core" - gem "puppetlabs_spec_helper" - gem "semantic_puppet" - gem "metadata-json-lint" - gem "rspec-puppet-facts" - gem "mocha" -end - -group :system_tests do - gem 'beaker' - gem 'beaker-rspec' - gem 'beaker_spec_helper' - gem 'serverspec' -end +gem 'rake' +# 5.3.4 is currently broken +# https://github.com/rodjek/rspec-puppet/issues/647 +gem 'puppet', ENV['PUPPET_VERSION'] || '< 5.3.4' -gem "puppet", ENV['PUPPET_VERSION'] || ENV['GEM_PUPPET_VERSION'] || ENV['PUPPET_GEM_VERSION'] || '~> 3.7.0' -gem "facter", ENV['FACTER_VERSION'] || ENV['GEM_FACTER_VERSION'] || ENV['FACTER_GEM_VERSION'] || '~> 2.2.0' +gem 'base32' +group :tests do + gem 'facter', ENV['FACTER_VERSION'] + gem 'hiera', ENV['HIERA_VERSION'] + gem 'puppetlabs_spec_helper' + gem 'librarian-puppet' + gem 'metadata-json-lint' + gem 'semantic_puppet' +end @@ -11,17 +11,17 @@ * [Installing torsocks](#installing-torsocks) * [Configuring relays](#configuring-relays) * [Configuring the control](#configuring-control) - * [Configuring hidden services](#configuring-hidden-services) + * [Configuring onion services](#configuring-onion-services) * [Configuring directories](#configuring-directories) * [Configuring exit policies](#configuring-exit-policies) * [Configuring transport plugins](#configuring-transport-plugins) -* [Polipo](#polipo) +* [Functions](#functions) * [Munin](#munin) # Overview<a name="overview"></a> This module tries to manage tor, making sure it is installed, running, has -munin graphs if desired and allows for configuration of relays, hidden services, +munin graphs if desired and allows for configuration of relays, onion services, exit policies, etc. ## Upgrade Notice<a name="upgrade-notice"></a> @@ -71,8 +71,7 @@ To install tor, simply include the 'tor' class in your manifests: class { 'tor': } -You can specify the `$ensure_version` class parameter to get a specific -version installed. +You can specify the `$version` class parameter to get a specific version installed. However, if you want to make configuration changes to your tor daemon, you will want to instead include the `tor::daemon` class in your manifests, which will @@ -126,8 +125,7 @@ To install torsocks, simply include the `torsocks` class in your manifests: class { 'tor::torsocks': } -You can specify the `$ensure_version` class parameter to get a specific -version installed. +You can specify the `$version` class parameter to get a specific version installed. # Configuring relays<a name="configuring-relays"></a> @@ -175,24 +173,28 @@ To pass parameters to configure the `ControlPort` and the Note: you must pass a hashed password to the control port, if you are going to use it. -## Configuring hidden services<a name="configuring-hidden-services"></a> +## Configuring onion services<a name="configuring-onion-services"></a> -To configure a tor hidden service you can do something like the following: +To configure a tor onion service you can do something like the following: - tor::daemon::hidden_service { "hidden_ssh": + tor::daemon::onion_service { "onion_ssh": ports => 22; } The `HiddenServiceDir` is set to the `${data_dir}/${name}`, but you can override it with the parameter `datadir`. -If you wish to enable v3-style hidden services to correspond with the v2-style -hidden services (the same configuration will be applied to both), you can pass +If you wish to enable v3-style onion services to correspond with the v2-style +onion services (the same configuration will be applied to both), you can pass the parameter `v3 => true`. The default is `false`. If you wish to enable single-hop onion addresses, you can enable them by passing `single_hop => true`. The default is `false`. +Onion services used to be called hidden services, so an old interface +`tor::daemon::hidden_service` is still available, with the feature +set of that time. + ## Configuring directories<a name="configuring-directories"></a> An example directory configuration: @@ -229,15 +231,18 @@ default: $servertransport_listenaddr #Set a different address for the transport plugin mechanism $servertransport_options #Pass a k=v parameters to the transport proxy -# Polipo<a name="polipo"></a> +# Functions<a name="functions"></a> -Polipo support can be enabled by doing: +This module comes with 2 functions specific to tor support. They require the base32 gem to be installed on the master or wherever they are executed. - include tor::polipo +## onion_address + +This function takes a 1024bit RSA private key as an argument and returns the onion address for an onion service for that key. + +## generate_onion_key + +This function takes a path (on the puppetmaster!) and an identifier for a key and returns an array containing the matching onion address and the private key. The private key either exists under the supplied `path/key_identifier` or is being generated on the fly and stored under that path for the next execution. -This will inherit the `tor` class by default, remove `privoxy` if it's -installed, and install `polipo`, making sure it is running. - # Munin<a name="munin"></a> If you are using `munin`, and have the puppet munin module installed, you can @@ -1,19 +1,23 @@ +require 'rubygems' +# keep for compatibility for now require 'puppetlabs_spec_helper/rake_tasks' -require 'puppet-lint/tasks/puppet-lint' -PuppetLint.configuration.send('disable_80chars') -PuppetLint.configuration.ignore_paths = ["spec/**/*.pp", "pkg/**/*.pp"] +task :tests do + # run syntax checks on manifests, templates and hiera data + # also runs :metadata_lint + Rake::Task[:validate].invoke -desc "Validate manifests, templates, and ruby files" -task :validate do - Dir['manifests/**/*.pp'].each do |manifest| - sh "puppet parser validate --noop #{manifest}" - end - Dir['spec/**/*.rb','lib/**/*.rb'].each do |ruby_file| - sh "ruby -c #{ruby_file}" unless ruby_file =~ /spec\/fixtures/ - end - Dir['templates/**/*.erb'].each do |template| - sh "erb -P -x -T '-' #{template} | ruby -c" + # runs puppet-lint + Rake::Task[:lint].invoke +end + +# use librarian-puppet to manage fixtures instead of .fixtures.yml +# offers more possibilities like explicit version management, forge downloads,... +task :librarian_spec_prep do + sh "librarian-puppet install --path=spec/fixtures/modules/" + pwd = `pwd`.strip + unless File.directory?("#{pwd}/spec/fixtures/modules/tor") + sh "ln -s #{pwd} #{pwd}/spec/fixtures/modules/tor" end end -task :test => [:lint, :syntax , :validate, :spec] +task :spec_prep => :librarian_spec_prep diff --git a/files/munin/tor_connections b/files/munin/tor_connections deleted file mode 100755 index c1d0a92..0000000 --- a/files/munin/tor_connections +++ /dev/null @@ -1,162 +0,0 @@ -#!/usr/bin/perl -w -# -# Munin plugin to monitor Tor -# -# Author: Ge van Geldorp <ge@gse.nl> -# -# Parameters understood: -# -# host - Change which host to graph (default localhost) -# port - Change which port to connect to (default 9051) -# password - Plain-text control channel password (see torrc -# HashedControlPassword parameter) -# cookiefile - Name of the file containing the control channel cookie -# (see torrc CookieAuthentication parameter) -# -# Using HashedControlPassword authentication has the problem that you must -# include the plain-text password in the munin config file. To have any -# effect, that file shouldn't be world-readable. -# If you're using CookieAuthentication, you should run this plugin as a user -# which has read access to the tor datafiles. Also note that bugs in versions -# upto and including 0.1.1.20 prevent CookieAuthentication from working. -# -# Usage: place in /etc/munin/node.d/ (or link it there using ln -s) -# -# Parameters understood: -# config (required) -# autoconf (optional - used by munin-config) -# -# -# Magic markers - optional - used by installation scripts and -# munin-config: -# -#%# family=contrib -#%# capabilities=autoconf - -use strict; -use IO::Socket::INET; - -# Config -our $address = $ENV{host} || "localhost"; # Default: localhost -our $port = $ENV{port} || 9051; # Default: 9051 - -# Don't edit below this line - -sub Authenticate -{ - my ($socket) = @_; - my $authline = "AUTHENTICATE"; - if (defined($ENV{cookiefile})) { - if (open(COOKIE, "<$ENV{cookiefile}")) { - binmode COOKIE; - my $cookie; - $authline .= " "; - while (read(COOKIE, $cookie, 32)) { - foreach my $byte (unpack "C*", $cookie) { - $authline .= sprintf "%02x", $byte; - } - } - close COOKIE; - } - } elsif (defined($ENV{password})) { - $authline .= ' "' . $ENV{password} . '"'; - } - print $socket "$authline\r\n"; - my $replyline = <$socket>; - if (substr($replyline, 0, 1) != '2') { - $replyline =~ s/\s*$//; - return "Failed to authenticate: $replyline"; - } - - return; -} - -if ($ARGV[0] and $ARGV[0] eq "autoconf") { - # Try to connect to the daemon - my $socket = IO::Socket::INET->new("$address:$port") - or my $failed = 1; - - if ($failed) { - print "no (failed to connect to $address port $port)\n"; - exit 1; - } - - my $msg = Authenticate($socket); - if (defined($msg)) { - print $socket "QUIT\r\n"; - close($socket); - print "no ($msg)\n"; - exit 1; - } - - print $socket "QUIT\r\n"; - close($socket); - print "yes\n"; - exit 0; -} - -my %connections = ("new", 0, - "launched", 0, - "connected", 0, - "failed", 0, - "closed", 0); - -if ($ARGV[0] and $ARGV[0] eq "config") { - print "graph_title Connections\n"; - print "graph_args -l 0 --base 1000\n"; - print "graph_vlabel connections\n"; - print "graph_category Tor\n"; - print "graph_period second\n"; - print "graph_info This graph shows the number of Tor OR connections.\n"; - - foreach my $status (keys %connections) { - print "$status.label $status\n"; - print "$status.type GAUGE\n"; - print "$status.max 50000\n"; - print "$status.min 0\n"; - } - - exit 0; -} - -my $socket = IO::Socket::INET->new("$address:$port") - or die("Couldn't connect to $address port $port: $!"); - -my $msg = Authenticate($socket); -if (defined($msg)) { - print $socket "QUIT\r\n"; - close($socket); - die "$msg\n"; -} - -print $socket "GETINFO orconn-status\r\n"; -my $replyline = <$socket>; -if (substr($replyline, 0, 1) != '2') { - print $socket "QUIT\r\n"; - close($socket); - $replyline =~ s/\s*$//; - die "Failed to get orconn-status info: $replyline\n"; -} - -while (! (($replyline = <$socket>) =~ /^\.\s*$/)) { - my @reply = split(/\s+/, $replyline); - $connections{lc($reply[1])}++; -} -$replyline = <$socket>; -if (substr($replyline, 0, 1) != '2') { - print $socket "QUIT\r\n"; - close($socket); - $replyline =~ s/\s*$//; - die "Failed to authenticate: $replyline\n"; -} - -print $socket "QUIT\r\n"; -close($socket); - -while (my ($status, $count) = each(%connections)) { - print "$status.value $count\n"; -} - -exit 0; - -# vim:syntax=perl diff --git a/files/munin/tor_openfds b/files/munin/tor_openfds new file mode 100644 index 0000000..9c14852 --- /dev/null +++ b/files/munin/tor_openfds @@ -0,0 +1,38 @@ +#!/usr/bin/perl -w +# https://lists.torproject.org/pipermail/tor-talk/2006-June/010486.html + +use strict; + +# Script to monitor the amount of FDs used by +# the Tor process (var/run/tor/tor.pid) + +if ($ARGV[0] and $ARGV[0] =~ /^\s*config\s*$/i) +{ + print "graph_title Open file descriptors for Tor\n"; + print "graph_args --base 1000 -l 0\n"; + print "graph_vlabel open FDs\n"; + print "graph_category Tor\n"; + print "count.label TorFDs\n"; + exit 0; +} + +my $pidfile = "/var/run/tor/tor.pid"; +my $pid = ''; +if (-e $pidfile) { + open (PID, $pidfile) or exit 1; + $pid = <PID>; + close PID; +} else { + $pid = `pidof tor`; +} +chomp $pid; + +$pid =~ /^[0-9]+$/ or exit 1; + +opendir (FDS, "/proc/$pid/fd") or exit 1; +my @fds = readdir(FDS); +closedir FDS; + +my $count = scalar @fds - 2; + +print "count.value $count\n"; diff --git a/files/polipo/polipo.conf b/files/polipo/polipo.conf deleted file mode 100644 index 12b10c4..0000000 --- a/files/polipo/polipo.conf +++ /dev/null @@ -1,164 +0,0 @@ -# Polipo Configuration from https://svn.torproject.org/svn/torbrowser/trunk/build-scripts/config/polipo.conf -# Managed by puppet. - -### Basic configuration -### ******************* - -# Uncomment one of these if you want to allow remote clients to -# connect: - -# proxyAddress = "::0" # both IPv4 and IPv6 -# proxyAddress = "0.0.0.0" # IPv4 only - -proxyAddress = "127.0.0.1" -proxyPort = 8118 - -# If you do that, you'll want to restrict the set of hosts allowed to -# connect: - -# allowedClients = "127.0.0.1, 134.157.168.57" -# allowedClients = "127.0.0.1, 134.157.168.0/24" - -allowedClients = 127.0.0.1 -allowedPorts = 1-65535 - -# Uncomment this if you want your Polipo to identify itself by -# something else than the host name: - -proxyName = "localhost" - -# Uncomment this if there's only one user using this instance of Polipo: - -cacheIsShared = false - -# Uncomment this if you want to use a parent proxy: - -# parentProxy = "squid.example.org:3128" - -# Uncomment this if you want to use a parent SOCKS proxy: - -socksParentProxy = "localhost:9050" -socksProxyType = socks5 - - -### Memory -### ****** - -# Uncomment this if you want Polipo to use a ridiculously small amount -# of memory (a hundred C-64 worth or so): - -# chunkHighMark = 819200 -# objectHighMark = 128 - -# Uncomment this if you've got plenty of memory: - -# chunkHighMark = 50331648 -# objectHighMark = 16384 - -chunkHighMark = 67108864 - -### On-disk data -### ************ - -# Uncomment this if you want to disable the on-disk cache: - -diskCacheRoot = "" - -# Uncomment this if you want to put the on-disk cache in a -# non-standard location: - -# diskCacheRoot = "~/.polipo-cache/" - -# Uncomment this if you want to disable the local web server: - -localDocumentRoot = "" - -# Uncomment this if you want to enable the pages under /polipo/index? -# and /polipo/servers?. This is a serious privacy leak if your proxy -# is shared. - -# disableIndexing = false -# disableServersList = false - -disableLocalInterface = true -disableConfiguration = true - -### Domain Name System -### ****************** - -# Uncomment this if you want to contact IPv4 hosts only (and make DNS -# queries somewhat faster): -# -# dnsQueryIPv6 = no - -# Uncomment this if you want Polipo to prefer IPv4 to IPv6 for -# double-stack hosts: -# -# dnsQueryIPv6 = reluctantly - -# Uncomment this to disable Polipo's DNS resolver and use the system's -# default resolver instead. If you do that, Polipo will freeze during -# every DNS query: - -dnsUseGethostbyname = yes - - -### HTTP -### **** - -# Uncomment this if you want to enable detection of proxy loops. -# This will cause your hostname (or whatever you put into proxyName -# above) to be included in every request: - -disableVia = true - -# Uncomment this if you want to slightly reduce the amount of -# information that you leak about yourself: - -# censoredHeaders = from, accept-language -# censorReferer = maybe - -censoredHeaders = from,accept-language,x-pad,link -censorReferer = maybe - -# Uncomment this if you're paranoid. This will break a lot of sites, -# though: - -# censoredHeaders = set-cookie, cookie, cookie2, from, accept-language -# censorReferer = true - -# Uncomment this if you want to use Poor Man's Multiplexing; increase -# the sizes if you're on a fast line. They should each amount to a few -# seconds' worth of transfer; if pmmSize is small, you'll want -# pmmFirstSize to be larger. - -# Note that PMM is somewhat unreliable. - -# pmmFirstSize = 16384 -# pmmSize = 8192 - -# Uncomment this if your user-agent does something reasonable with -# Warning headers (most don't): - -# relaxTransparency = maybe - -# Uncomment this if you never want to revalidate instances for which -# data is available (this is not a good idea): - -# relaxTransparency = yes - -# Uncomment this if you have no network: - -# proxyOffline = yes - -# Uncomment this if you want to avoid revalidating instances with a -# Vary header (this is not a good idea): - -# mindlesslyCacheVary = true - -# Suggestions from Incognito configuration -maxConnectionAge = 5m -maxConnectionRequests = 120 -serverMaxSlots = 8 -serverSlots = 2 -tunnelAllowedPorts = 1-65535 diff --git a/lib/facter/tor_hidden_services.rb b/lib/facter/tor_hidden_services.rb new file mode 100644 index 0000000..c2a6cca --- /dev/null +++ b/lib/facter/tor_hidden_services.rb @@ -0,0 +1,19 @@ +Facter.add(:tor_hidden_services) do + confine :kernel => "Linux" + setcode do + config_file = '/etc/tor/torrc' + if File.exists?(config_file) + dirs = File.read(config_file).split("\n").select{|l| + l =~ /^HiddenServiceDir/ + }.collect{|l| l.sub(/^HiddenServiceDir /,'') } + dirs.inject({}) { |res,d| + if File.exists?(h=File.join(d,'hostname')) + res[File.basename(d)] = File.read(h).chomp + end + res + } + else + {} + end + end +end diff --git a/lib/puppet/parser/functions/generate_onion_key.rb b/lib/puppet/parser/functions/generate_onion_key.rb new file mode 100644 index 0000000..9ee5351 --- /dev/null +++ b/lib/puppet/parser/functions/generate_onion_key.rb @@ -0,0 +1,48 @@ +module Puppet::Parser::Functions + newfunction(:generate_onion_key, :type => :rvalue, :doc => <<-EOS +Generates or loads a rsa private key for an onion service, returns they onion +onion address and the private key content. + +Requires a location to load and store the private key, as well an identifier, which will be used as a filename in the location. + +Example: + + res = generate_onion_key('/tmp','my_secret_key') + notice "Onion Address: \${res[0]" + notice "Priavte Key: \${res[1]" + + +It will also store the onion address under /tmp/my_secret_key.hostname. +If /tmp/my_secret_key.key exists, but not the hostname file. Then the function will be loaded and the onion address will be generated from it. + + EOS + ) do |args| + location = args.shift + identifier = args.shift + + raise(Puppet::ParseError, "generate_onion_key(): requires 2 arguments") unless [location,identifier].all?{|i| !i.nil? } + + raise(Puppet::ParseError, "generate_onion_key(): requires location (#{location}) to be a directory") unless File.directory?(location) + path = File.join(location,identifier) + + private_key = if File.exists?(kf="#{path}.key") + pk = OpenSSL::PKey::RSA.new(File.read(kf)) + raise(Puppet::ParseError, "generate_onion_key(): key in path #{kf} must have a length of 1024bit") unless (pk.n.num_bytes * 8) == 1024 + pk + else + # 1024 is hardcoded by tor + pk = OpenSSL::PKey::RSA.generate(1024) + File.open(kf,'w'){|f| f << pk.to_s } + pk + end + onion_address = if File.exists?(hf="#{path}.hostname") + File.read(hf) + else + oa = function_onion_address([private_key]) + File.open(hf,'w'){|f| f << oa.to_s } + oa + end + + [ onion_address, private_key.to_s ] + end +end diff --git a/lib/puppet/parser/functions/onion_address.rb b/lib/puppet/parser/functions/onion_address.rb new file mode 100644 index 0000000..a6f9755 --- /dev/null +++ b/lib/puppet/parser/functions/onion_address.rb @@ -0,0 +1,30 @@ +require 'base32' +module Puppet::Parser::Functions + newfunction(:onion_address, :type => :rvalue, :doc => <<-EOS +Generates an onion address from a 1024-bit RSA private key. + +Example: + + onion_address("-----BEGIN RSA PRIVATE KEY----- +MII.... +-----END RSA PRIVATE KEY-----") + +Returns the onionadress for that key, *without* the .onion suffix. + EOS + ) do |args| + key = args.shift + raise(Puppet::ParseError, "onion_address(): requires 1 argument") unless key && args.empty? + private_key = key.is_a?(OpenSSL::PKey::RSA) ? key : OpenSSL::PKey::RSA.new(key) + + # the onion address are a base32 encoded string of the first half of the sha1 over the + # der format of the public key + # https://trac.torproject.org/projects/tor/wiki/doc/HiddenServiceNames#Howare.onionnamescreated + # We can skip the first 22 bits of the der format as they are ignored by tor + # https://timtaubert.de/blog/2014/11/using-the-webcrypto-api-to-generate-onion-names-for-tor-hidden-services/ + # https://gitweb.torproject.org/torspec.git/tree/rend-spec.txt#n525 + # Except for Ruby 1.8.7 where the first 22 are not present at all + start = RUBY_VERSION.to_f < 1.9 ? 0 : 22 + public_key_der = private_key.public_key.to_der + Base32.encode(Digest::SHA1.digest(public_key_der[start..-1]))[0..15].downcase + end +end diff --git a/manifests/arm.pp b/manifests/arm.pp index 44ddcbb..dfea7c8 100644 --- a/manifests/arm.pp +++ b/manifests/arm.pp @@ -1,9 +1,9 @@ # manage tor-arm class tor::arm ( - $ensure_version = 'installed' + $version = 'installed' ){ include ::tor package{'tor-arm': - ensure => $ensure_version, + ensure => $version, } } diff --git a/manifests/base.pp b/manifests/base.pp index b98451b..13d8507 100644 --- a/manifests/base.pp +++ b/manifests/base.pp @@ -1,7 +1,13 @@ # basic management of resources for tor class tor::base { - package { [ 'tor', 'tor-geoipdb' ]: - ensure => $tor::ensure_version, + package {'tor': + ensure => $tor::version, + } + if $facts['osfamily'] == 'Debian' { + package {'tor-geoipdb': + ensure => $tor::version, + before => Service['tor'], + } } service { 'tor': diff --git a/manifests/compact.pp b/manifests/compact.pp deleted file mode 100644 index c0f5919..0000000 --- a/manifests/compact.pp +++ /dev/null @@ -1,7 +0,0 @@ -# manage a complete tor -# installation with all the basics -class tor::compact { - include ::tor - include tor::polipo - include tor::torsocks -} diff --git a/manifests/daemon.pp b/manifests/daemon.pp index 2522b2c..55c881d 100644 --- a/manifests/daemon.pp +++ b/manifests/daemon.pp @@ -1,6 +1,5 @@ # manage a snippet based tor installation class tor::daemon ( - $ensure_version = 'installed', $use_munin = false, $data_dir = '/var/lib/tor', $config_file = '/etc/tor/torrc', @@ -10,13 +9,10 @@ class tor::daemon ( $safe_logging = 1, ) { - class{'tor': - ensure_version => $ensure_version, - } - - include tor::daemon::base + include ::tor + include ::tor::daemon::base if $use_munin { - include tor::munin + include ::tor::munin } } diff --git a/manifests/daemon/base.pp b/manifests/daemon/base.pp index f3bbc37..86156af 100644 --- a/manifests/daemon/base.pp +++ b/manifests/daemon/base.pp @@ -1,70 +1,62 @@ # extend basic tor things with a snippet based daemon configuration class tor::daemon::base inherits tor::base { - # packages, user, group - Service['tor'] { - subscribe => Concat[$tor::daemon::config_file], - } - Package[ 'tor' ] { - require => File[$tor::daemon::data_dir], - } + include ::tor::daemon::params - group { 'debian-tor': - ensure => present, - allowdupe => false, - } + if $tor::daemon::params::manage_user { + group { $tor::daemon::params::group: + ensure => present, + allowdupe => false, + } - user { 'debian-tor': - ensure => present, - allowdupe => false, - comment => 'tor user,,,', - home => $tor::daemon::data_dir, - shell => '/bin/false', - gid => 'debian-tor', - require => Group['debian-tor'], + user { $tor::daemon::params::user: + ensure => present, + allowdupe => false, + comment => 'tor user,,,', + home => $tor::daemon::data_dir, + shell => '/bin/false', + gid => $tor::daemon::params::group, + require => Group[$tor::daemon::params::group], + } } # directories file { $tor::daemon::data_dir: ensure => directory, - mode => '0700', - owner => 'debian-tor', - group => 'debian-tor', - require => User['debian-tor'], + mode => $tor::daemon::params::data_dir_mode, + owner => $tor::daemon::params::user, + group => 'root', + require => Package['tor'], } file { '/etc/tor': ensure => directory, mode => '0755', - owner => 'debian-tor', - group => 'debian-tor', - require => User['debian-tor'], - } - - file { '/var/lib/puppet/modules/tor': - ensure => absent, - recurse => true, - force => true, + owner => 'root', + group => 'root', + require => Package['tor'], } # tor configuration file concat { $tor::daemon::config_file: - mode => '0600', - owner => 'debian-tor', - group => 'debian-tor', + mode => '0640', + owner => 'root', + group => $tor::daemon::params::group, + require => Package['tor'], + notify => Service['tor'], } # config file headers concat::fragment { '00.header': content => template('tor/torrc.header.erb'), - order => 00, + order => '00', target => $tor::daemon::config_file, } # global configurations concat::fragment { '01.global': content => template('tor/torrc.global.erb'), - order => 01, + order => '01', target => $tor::daemon::config_file, } } diff --git a/manifests/daemon/bridge.pp b/manifests/daemon/bridge.pp index a448f82..e09f4f7 100644 --- a/manifests/daemon/bridge.pp +++ b/manifests/daemon/bridge.pp @@ -2,12 +2,15 @@ define tor::daemon::bridge( $ip, $port, - $fingerprint = false ) { - - concat::fragment { "10.bridge.${name}": - content => template('tor/torrc.bridge.erb'), - order => 10, - target => $tor::daemon::config_file, + $fingerprint = false, + $ensure = 'present', +) { + if $ensure == 'present' { + concat::fragment { "10.bridge.${name}": + content => template('tor/torrc.bridge.erb'), + order => '10', + target => $tor::daemon::config_file, + } } } diff --git a/manifests/daemon/control.pp b/manifests/daemon/control.pp index 4137c3e..ee4a1fd 100644 --- a/manifests/daemon/control.pp +++ b/manifests/daemon/control.pp @@ -1,26 +1,26 @@ # control definition define tor::daemon::control( + $ensure = 'present', $port = 0, $hashed_control_password = '', $cookie_authentication = 0, $cookie_auth_file = '', $cookie_auth_file_group_readable = '', - $ensure = present ) { +) { - if $cookie_authentication == '0' - and $hashed_control_password == '' - and $ensure != 'absent' { + if $ensure == 'present' { + if $cookie_authentication == '0' and $hashed_control_password == '' { fail('You need to define the tor control password') } - if $cookie_authentication == 0 - and ($cookie_auth_file != '' or $cookie_auth_file_group_readable != '') { + if $cookie_authentication == 0 and ($cookie_auth_file != '' or $cookie_auth_file_group_readable != '') { # lint:ignore:80chars notice('You set a tor cookie authentication option, but do not have cookie_authentication on') # lint:ignore:80chars } - concat::fragment { '04.control': - content => template('tor/torrc.control.erb'), - order => 04, - target => $tor::daemon::config_file, + concat::fragment { '04.control': + content => template('tor/torrc.control.erb'), + order => '04', + target => $tor::daemon::config_file, + } } } diff --git a/manifests/daemon/directory.pp b/manifests/daemon/directory.pp index 3eaef9f..b2f77fe 100644 --- a/manifests/daemon/directory.pp +++ b/manifests/daemon/directory.pp @@ -1,22 +1,24 @@ # directory advertising define tor::daemon::directory ( + $ensure = 'present', $port = 0, $port_front_page = '/etc/tor/tor-exit-notice.html', - $ensure = present ) { - - concat::fragment { '06.directory': - content => template('tor/torrc.directory.erb'), - order => 06, - target => $tor::daemon::config_file, +) { + if $ensure == 'present' { + concat::fragment { '06.directory': + content => template('tor/torrc.directory.erb'), + order => '06', + target => $tor::daemon::config_file, + } } + include ::tor::daemon::params file { '/etc/tor/tor-exit-notice.html': ensure => $ensure, source => 'puppet:///modules/tor/tor-exit-notice.html', require => File['/etc/tor'], - owner => 'debian-tor', - group => 'debian-tor', + owner => $tor::daemon::params::user, + group => $tor::daemon::params::group, mode => '0644', } } - diff --git a/manifests/daemon/dns.pp b/manifests/daemon/dns.pp index 599abd8..899f920 100644 --- a/manifests/daemon/dns.pp +++ b/manifests/daemon/dns.pp @@ -1,11 +1,14 @@ # DNS definition define tor::daemon::dns( - $port = 0 ) { - - concat::fragment { "08.dns.${name}": - content => template('tor/torrc.dns.erb'), - order => '08', - target => $tor::daemon::config_file, + $ensure = 'present', + $port = 0, +){ + if $ensure == 'present' { + concat::fragment { "08.dns.${name}": + content => template('tor/torrc.dns.erb'), + order => '08', + target => $tor::daemon::config_file, + } } } diff --git a/manifests/daemon/exit_policy.pp b/manifests/daemon/exit_policy.pp index c117d5d..62876c7 100644 --- a/manifests/daemon/exit_policy.pp +++ b/manifests/daemon/exit_policy.pp @@ -1,13 +1,16 @@ # exit policies define tor::daemon::exit_policy( + $ensure = 'present', $accept = [], $reject = [], - $reject_private = 1 ) { - - concat::fragment { "07.exit_policy.${name}": - content => template('tor/torrc.exit_policy.erb'), - order => 07, - target => $tor::daemon::config_file, + $reject_private = 1, +) { + if $ensure == 'present' { + concat::fragment { "07.exit_policy.${name}": + content => template('tor/torrc.exit_policy.erb'), + order => '07', + target => $tor::daemon::config_file, + } } } diff --git a/manifests/daemon/hidden_service.pp b/manifests/daemon/hidden_service.pp index 9e053cc..8a062c5 100644 --- a/manifests/daemon/hidden_service.pp +++ b/manifests/daemon/hidden_service.pp @@ -3,19 +3,14 @@ define tor::daemon::hidden_service( $ports = [], $single_hop = false, $v3 = false, - $data_dir = $tor::daemon::data_dir ) { - - - - if $single_hop { - file { "${$data_dir}/${$name}/onion_service_non_anonymous": - ensure => 'present', - } - } - - concat::fragment { "05.hidden_service.${name}": - content => template('tor/torrc.hidden_service.erb'), - order => 05, - target => $tor::daemon::config_file, + $data_dir = $tor::daemon::data_dir, +) { + info("Using tor::daemon::hidden_service is deprecated, please use tor::daemon::onion_service for ${name}") + tor::daemon::onion_service{ + $name: + ports => $ports, + single_hop => $single_hop, + v3 => $v3, + data_dir => $data_dir, } } diff --git a/manifests/daemon/map_address.pp b/manifests/daemon/map_address.pp index 1829eae..ca21ed9 100644 --- a/manifests/daemon/map_address.pp +++ b/manifests/daemon/map_address.pp @@ -1,12 +1,15 @@ # map address definition define tor::daemon::map_address( + $ensure = 'present', $address = '', - $newaddress = '' ) { - - concat::fragment { "08.map_address.${name}": - content => template('tor/torrc.map_address.erb'), - order => '08', - target => $tor::daemon::config_file, + $newaddress = '', +) { + if $ensure == 'present' { + concat::fragment { "08.map_address.${name}": + content => template('tor/torrc.map_address.erb'), + order => '08', + target => $tor::daemon::config_file, + } } } diff --git a/manifests/daemon/onion_service.pp b/manifests/daemon/onion_service.pp new file mode 100644 index 0000000..cb55d06 --- /dev/null +++ b/manifests/daemon/onion_service.pp @@ -0,0 +1,65 @@ +# onion services definition +define tor::daemon::onion_service( + $ensure = 'present', + $ports = [], + $data_dir = $tor::daemon::data_dir, + $v3 = false, + $single_hop = false, + $private_key = undef, + $private_key_name = $name, + $private_key_store_path = undef, +) { + + $data_dir_path = "${data_dir}/${name}" + if $ensure == 'present' { + include ::tor::daemon::params + concat::fragment { "05.onion_service.${name}": + content => template('tor/torrc.onion_service.erb'), + order => '05', + target => $tor::daemon::config_file, + } + if $single_hop { + file { "${$data_dir_path}/onion_service_non_anonymous": + ensure => 'present', + notify => Service['tor']; + } + } + } + if $private_key or ($private_key_name and $private_key_store_path) { + if $private_key and ($private_key_name and $private_key_store_path) { + fail('Either private_key OR (private_key_name AND private_key_store_path) must be set, but not all three of them') + } + if $private_key_store_path and $private_key_name { + $tmp = generate_onion_key($private_key_store_path,$private_key_name) + $os_hostname = $tmp[0] + $real_private_key = $tmp[1] + } else { + $os_hostname = onion_address($private_key) + $real_private_key = $private_key + } + file{ + $data_dir_path: + ensure => directory, + purge => true, + force => true, + recurse => true, + owner => $tor::daemon::params::user, + group => $tor::daemon::params::group, + mode => '0600', + require => Package['tor']; + "${data_dir_path}/private_key": + content => $real_private_key, + owner => $tor::daemon::params::user, + group => $tor::daemon::params::group, + mode => '0600', + notify => Service['tor']; + "${data_dir_path}/hostname": + content => "${os_hostname}.onion\n", + owner => $tor::daemon::params::user, + group => $tor::daemon::params::group, + mode => '0600', + notify => Service['tor']; + } + } +} + diff --git a/manifests/daemon/params.pp b/manifests/daemon/params.pp new file mode 100644 index 0000000..39126ee --- /dev/null +++ b/manifests/daemon/params.pp @@ -0,0 +1,19 @@ +# setup variables for different distributions +class tor::daemon::params { + case $facts['osfamily'] { + 'RedHat': { + $user = 'toranon' + $group = 'toranon' + $manage_user = false + $data_dir_mode = '0750' + } + 'Debian': { + $user = 'debian-tor' + $group = 'debian-tor' + $manage_user = true + $data_dir_mode = '0700' + } + default: { fail("No support for osfamily ${facts['osfamily']}") } + } + +} diff --git a/manifests/daemon/relay.pp b/manifests/daemon/relay.pp index fa908f5..bc72dd0 100644 --- a/manifests/daemon/relay.pp +++ b/manifests/daemon/relay.pp @@ -1,5 +1,6 @@ # relay definition define tor::daemon::relay( + $ensure = 'present', $port = 0, $outbound_bindaddresses = [], $portforwarding = 0, @@ -13,25 +14,27 @@ define tor::daemon::relay( $relay_bandwidth_burst = 0, # GB, 0 for no limit $accounting_max = 0, - $accounting_start = "month 1 0:00", + $accounting_start = 'month 1 0:00', $contact_info = '', # TODO: autofill with other relays $my_family = '', $address = "tor.${::domain}", $bridge_relay = 0, - $ensure = present ) { +) { - $nickname = $name + if $ensure == 'present' { + $nickname = $name - if $outbound_bindaddresses == [] { - $real_outbound_bindaddresses = [] - } else { - $real_outbound_bindaddresses = $outbound_bindaddresses - } + if $outbound_bindaddresses == [] { + $real_outbound_bindaddresses = [] + } else { + $real_outbound_bindaddresses = $outbound_bindaddresses + } - concat::fragment { '03.relay': - content => template('tor/torrc.relay.erb'), - order => 03, - target => $tor::daemon::config_file, + concat::fragment { '03.relay': + content => template('tor/torrc.relay.erb'), + order => '03', + target => $tor::daemon::config_file, + } } } diff --git a/manifests/daemon/snippet.pp b/manifests/daemon/snippet.pp index 5a4c091..195ed77 100644 --- a/manifests/daemon/snippet.pp +++ b/manifests/daemon/snippet.pp @@ -1,11 +1,15 @@ # Arbitrary torrc snippet definition define tor::daemon::snippet( - $content = '' ) { + $ensure = 'present', + $content = '', +) { - concat::fragment { "99.snippet.${name}": - content => $content, - order => 99, - target => $tor::daemon::config_file, + if $ensure == 'present' { + concat::fragment { "99.snippet.${name}": + content => $content, + order => '99', + target => $tor::daemon::config_file, + } } } diff --git a/manifests/daemon/socks.pp b/manifests/daemon/socks.pp index cb130d9..e36d91e 100644 --- a/manifests/daemon/socks.pp +++ b/manifests/daemon/socks.pp @@ -1,11 +1,14 @@ # socks definition define tor::daemon::socks( - $port = 0, - $policies = [] ) { - - concat::fragment { '02.socks': - content => template('tor/torrc.socks.erb'), - order => 02, - target => $tor::daemon::config_file, + $ensure = 'present', + $port = 0, + $policies = [], +) { + if $ensure == 'present' { + concat::fragment { '02.socks': + content => template('tor/torrc.socks.erb'), + order => '02', + target => $tor::daemon::config_file, + } } } diff --git a/manifests/daemon/transparent.pp b/manifests/daemon/transparent.pp index 90c0142..0d4620a 100644 --- a/manifests/daemon/transparent.pp +++ b/manifests/daemon/transparent.pp @@ -1,11 +1,14 @@ # Transparent proxy definition define tor::daemon::transparent( - $port = 0 ) { + $ensure = 'present', + $port = 0) { - concat::fragment { "09.transparent.${name}": - content => template('tor/torrc.transparent.erb'), - order => '09', - target => $tor::daemon::config_file, + if $ensure == 'present' { + concat::fragment { "09.transparent.${name}": + content => template('tor/torrc.transparent.erb'), + order => '09', + target => $tor::daemon::config_file, + } } } diff --git a/manifests/daemon/transport_plugin.pp b/manifests/daemon/transport_plugin.pp index 1921282..4f7bbf2 100644 --- a/manifests/daemon/transport_plugin.pp +++ b/manifests/daemon/transport_plugin.pp @@ -1,13 +1,16 @@ # transport plugin define tor::daemon::transport_plugin( + $ensure = 'present', $servertransport_plugin = '', $servertransport_listenaddr = '', $servertransport_options = '', - $ext_port = '' ) { - - concat::fragment { '11.transport_plugin': - content => template('tor/torrc.transport_plugin.erb'), - order => 11, - target => $tor::daemon::config_file, + $ext_port = '', +) { + if $ensure == 'present' { + concat::fragment { '11.transport_plugin': + content => template('tor/torrc.transport_plugin.erb'), + order => 11, + target => $tor::daemon::config_file, + } } } diff --git a/manifests/init.pp b/manifests/init.pp index 9c19c64..ad584aa 100644 --- a/manifests/init.pp +++ b/manifests/init.pp @@ -1,6 +1,6 @@ # manage a basic tor installation class tor ( - $ensure_version = 'installed' + $version = 'installed' ){ include tor::base } diff --git a/manifests/munin.pp b/manifests/munin.pp index 2a01175..f718c37 100644 --- a/manifests/munin.pp +++ b/manifests/munin.pp @@ -2,17 +2,19 @@ class tor::munin { tor::daemon::control{ 'control_port_for_munin': - port => 19051, + port => 9001, cookie_authentication => 1, cookie_auth_file => '/var/run/tor/control.authcookie', } + include ::tor::daemon::params Munin::Plugin::Deploy { - config => "user debian-tor\n env.cookiefile /var/run/tor/control.authcookie\n env.port 19051" # lint:ignore:80chars + config => "user ${tor::daemon::params::user}\n env.cookiefile /var/run/tor/control.authcookie\n env.port 9001" # lint:ignore:80chars } munin::plugin::deploy { - 'tor_connections': - source => 'tor/munin/tor_connections'; + 'tor_openfds': + config => 'user root', + source => 'tor/munin/tor_openfds'; 'tor_routers': source => 'tor/munin/tor_routers'; 'tor_traffic': diff --git a/manifests/onionbalance.pp b/manifests/onionbalance.pp new file mode 100644 index 0000000..1921754 --- /dev/null +++ b/manifests/onionbalance.pp @@ -0,0 +1,82 @@ +# manages an onionbalance installation +# +# Parameters: +# +# services: a hash of onionbalance service instances +# services => { +# keyname_of_service1 => { +# name1 => onionservice_addr_3, +# name2 => onionservice_addr_2, +# _key_content => content_of_key_of_onionbalanced_service1, +# }, +# } +# +class tor::onionbalance( + $services, +) { + + include ::tor + + case $facts['osfamily'] { + 'Debian': { + $pkg_name = 'onionbalance' + $instance_file = '/etc/tor/instances/onionbalance/torrc' + $instance_user = '_tor-onionbalance' + exec{'/usr/sbin/tor-instance-create onionbalance': + creates => '/etc/tor/instances/onionbalance', + require => Package['tor'], + before => File[$instance_file], + } -> augeas{"manage_onionbalance_in_group_${instance_user}": + context => '/files/etc/group', + changes => [ "set ${instance_user}/user[last()+1] onionbalance" ], + onlyif => "match ${instance_user}/*[../user='onionbalance'] size == 0", + require => Package['onionbalance'], + } + } + 'RedHat': { + $instance_file = '/etc/tor/onionbalance.torrc' + $instance_user = 'toranon' + $pkg_name = 'python2-onionbalance' + } + default: { + fail("OSFamily ${facts['osfamily']} not (yet) supported for onionbalance") + } + } + + package{$pkg_name: + ensure => 'installed', + tag => 'onionbalance', + } -> file{ + '/etc/onionbalance/config.yaml': + content => template('tor/onionbalance/config.yaml.erb'), + owner => root, + group => $instance_user, + mode => '0640', + notify => Service['onionbalance']; + $instance_file: + content => template("tor/onionbalance/${facts['osfamily']}.torrc.erb"), + owner => root, + group => 0, + mode => '0644', + require => Package['tor'], + notify => Service['tor@onionbalance'], + } + + $keys = keys($services) + tor::onionbalance::keys{ + $keys: + values => $services, + group => $instance_user, + } + + service{ + 'tor@onionbalance': + ensure => running, + enable => true; + 'onionbalance': + ensure => running, + enable => true, + subscribe => Service['tor@onionbalance']; + } + +} diff --git a/manifests/onionbalance/key.pp b/manifests/onionbalance/key.pp new file mode 100644 index 0000000..e0016fc --- /dev/null +++ b/manifests/onionbalance/key.pp @@ -0,0 +1,25 @@ +# manage onionbalance keys +# +# key_content will be treated as path +# to a file containing the key content +# if the value starts with a / +# +define tor::onionbalance::key( + $key_content, + $group, +){ + + if $key_content =~ /^\// { + $content = file($key_content) + } else { + $content = $key_content + } + Package<| tag == 'onionbalance' |> -> file{ + "/etc/onionbalance/${name}.key": + content => $content, + owner => root, + group => $group, + mode => '0640', + notify => Service['onionbalance']; + } +} diff --git a/manifests/onionbalance/keys.pp b/manifests/onionbalance/keys.pp new file mode 100644 index 0000000..e3040f5 --- /dev/null +++ b/manifests/onionbalance/keys.pp @@ -0,0 +1,11 @@ +# a wrapper to manage onionbalance keys +define tor::onionbalance::keys( + $values, + $group, +) { + tor::onionbalance::key{ + $name: + key_content => $values[$name]['_key_content'], + group => $group, + } +} diff --git a/manifests/polipo.pp b/manifests/polipo.pp deleted file mode 100644 index 73dc226..0000000 --- a/manifests/polipo.pp +++ /dev/null @@ -1,9 +0,0 @@ -# manage the polipo proxy service -class tor::polipo { - include ::tor - - case $::operatingsystem { - 'debian': { include tor::polipo::debian } - default: { include tor::polipo::base } - } -} diff --git a/manifests/polipo/base.pp b/manifests/polipo/base.pp deleted file mode 100644 index df2d6ea..0000000 --- a/manifests/polipo/base.pp +++ /dev/null @@ -1,22 +0,0 @@ -# manage polipo resources -class tor::polipo::base { - package{'polipo': - ensure => present, - } - - file { '/etc/polipo/config': - ensure => present, - owner => root, - group => root, - mode => '0644', - source => 'puppet:///modules/tor/polipo/polipo.conf', - require => Package['polipo'], - notify => Service['polipo'], - } - - service { 'polipo': - ensure => running, - enable => true, - require => [ Package['polipo'], Service['tor'] ], - } -} diff --git a/manifests/polipo/debian.pp b/manifests/polipo/debian.pp deleted file mode 100644 index 607b361..0000000 --- a/manifests/polipo/debian.pp +++ /dev/null @@ -1,7 +0,0 @@ -# manage polipo on debian -class tor::polipo::debian inherits tor::polipo::base { - Service['polipo'] { - hasstatus => false, - pattern => '/usr/bin/polipo', - } -} diff --git a/manifests/repo.pp b/manifests/repo.pp index 9549219..d9d43ec 100644 --- a/manifests/repo.pp +++ b/manifests/repo.pp @@ -1,4 +1,4 @@ -# setup repository for tor +# add upstream repositories of torproject class tor::repo ( $ensure = present, $source_name = 'torproject.org', @@ -10,6 +10,9 @@ class tor::repo ( $location = 'https://deb.torproject.org/torproject.org/' class { 'tor::repo::debian': } } + 'RedHat': { + # no need as EPEL is the relevant reference + } default: { fail("Unsupported managed repository for osfamily: ${::osfamily}, operatingsystem: ${::operatingsystem}, module ${module_name} currently only supports managing repos for osfamily Debian and Ubuntu") # lint:ignore:80chars } diff --git a/manifests/torsocks.pp b/manifests/torsocks.pp index e9fc75b..e1ba8a9 100644 --- a/manifests/torsocks.pp +++ b/manifests/torsocks.pp @@ -1,9 +1,9 @@ # manage torsocks class tor::torsocks ( - $ensure_version = 'installed' + $version = 'installed' ){ - include ::tor + include ::tor::daemon package{'torsocks': - ensure => $ensure_version, + ensure => $version, } } diff --git a/metadata.json b/metadata.json index 72e3701..b5a2d9f 100644 --- a/metadata.json +++ b/metadata.json @@ -1,6 +1,6 @@ { "name": "smash-tor", - "version": "1.0.0", + "version": "1.1.0", "author": "SMASH", "summary": "This project tracks the tor puppet module that manages the tor onion routing system.", "license": "GPL-3.0", @@ -17,12 +17,33 @@ "8", "9" ] + }, + { + "operatingsystem": "CentOS", + "operatingsystemrelease": [ + "7", + "6" + ] } ], "requirements": [ { "name": "puppet", - "version_requirement": "4.X" + "version_requirement": ">= 4.7.0 < 6.0.0" + } + ], + "dependencies": [ + { + "name": "puppetlabs/stdlib", + "version_requirement": ">= 4.24.0 < 5.0.0" + }, + { + "name": "puppetlabs/concat", + "version_requirement": ">= 4.2.0 < 5.0.0" + }, + { + "name": "puppetlabs/apt", + "version_requirement": ">= 4.5.1 < 5.0.0" } ], "description": "This module tries to manage tor, making sure it is installed, running, has munin graphs if desired and allows for configuration of relays, hidden services, exit policies, etc." diff --git a/spec/acceptance/nodesets/default.yml b/spec/acceptance/nodesets/default.yml deleted file mode 100644 index f09ad62..0000000 --- a/spec/acceptance/nodesets/default.yml +++ /dev/null @@ -1,19 +0,0 @@ -HOSTS: - debian-8-x64: - platform: debian-8-amd64 - image: debian:8 - hypervisor: docker - docker_preserve_image: true - docker_cmd: '["/sbin/init"]' - docker_image_commands: - - 'apt-get install -y wget locales-all puppet git' - - 'rm -f /usr/sbin/policy-rc.d' - -CONFIG: - type: foss - #log_level: verbose - #log_level: debug - -ssh: - password: root - auth_methods: ["password"] diff --git a/spec/classes/base_spec.rb b/spec/classes/base_spec.rb new file mode 100644 index 0000000..7f288ec --- /dev/null +++ b/spec/classes/base_spec.rb @@ -0,0 +1,44 @@ +require File.expand_path(File.join(File.dirname(__FILE__),'../spec_helper')) + +describe 'tor::base', :type => 'class' do + let(:default_facts) { + { + :osfamily => 'RedHat', + :operatingsystem => 'CentOS', + } + } + let(:facts){ default_facts } + let(:pre_condition){'include ::tor + Exec{path => "/bin"}' } + describe 'with standard' do + it { is_expected.to compile.with_all_deps } + + it { is_expected.to contain_package('tor').with_ensure('installed') } + it { is_expected.to_not contain_package('tor-geoipdb').with_ensure('installed') } + it { is_expected.to contain_service('tor').with( + :ensure => 'running', + :enable => 'true', + :hasrestart => 'true', + :hasstatus => 'true', + :require => 'Package[tor]', + ) } + context 'on Debian' do + let(:facts) { + { + :osfamily => 'Debian', + :operatingsystem => 'Debian', + } + } + it { is_expected.to compile.with_all_deps } + it { is_expected.to contain_package('tor').with_ensure('installed') } + it { is_expected.to contain_package('tor-geoipdb').with_ensure('installed') } + it { is_expected.to contain_service('tor').with( + :ensure => 'running', + :enable => 'true', + :hasrestart => 'true', + :hasstatus => 'true', + :require => 'Package[tor]', + ) } + end + end +end diff --git a/spec/classes/daemon_spec.rb b/spec/classes/daemon_spec.rb new file mode 100644 index 0000000..db5291d --- /dev/null +++ b/spec/classes/daemon_spec.rb @@ -0,0 +1,31 @@ +require File.expand_path(File.join(File.dirname(__FILE__),'../spec_helper')) + +describe 'tor::daemon', :type => 'class' do + let(:default_facts) { + { + :osfamily => 'RedHat', + :operatingsystem => 'CentOS', + } + } + let(:facts){ default_facts } + let(:pre_condition){'Exec{path => "/bin"}' } + describe 'with standard' do + it { is_expected.to compile.with_all_deps } + + it { is_expected.to contain_class('tor') } + it { is_expected.to contain_class('tor::daemon::base') } + it { is_expected.to_not contain_class('tor::munin') } + context 'on Debian' do + let(:facts) { + { + :osfamily => 'Debian', + :operatingsystem => 'Debian', + } + } + it { is_expected.to compile.with_all_deps } + it { is_expected.to contain_class('tor') } + it { is_expected.to contain_class('tor::daemon::base') } + it { is_expected.to_not contain_class('tor::munin') } + end + end +end diff --git a/spec/classes/init_spec.rb b/spec/classes/init_spec.rb new file mode 100644 index 0000000..be4f30b --- /dev/null +++ b/spec/classes/init_spec.rb @@ -0,0 +1,27 @@ +require File.expand_path(File.join(File.dirname(__FILE__),'../spec_helper')) + +describe 'tor', :type => 'class' do + let(:default_facts) { + { + :osfamily => 'RedHat', + :operatingsystem => 'CentOS', + } + } + let(:facts){ default_facts } + let(:pre_condition){'Exec{path => "/bin"}' } + describe 'with standard' do + it { is_expected.to compile.with_all_deps } + + it { is_expected.to contain_class('tor::base') } + context 'on Debian' do + let(:facts) { + { + :osfamily => 'Debian', + :operatingsystem => 'Debian', + } + } + it { is_expected.to compile.with_all_deps } + it { is_expected.to contain_class('tor::base') } + end + end +end diff --git a/spec/classes/onionbalance_spec.rb b/spec/classes/onionbalance_spec.rb new file mode 100644 index 0000000..ff9bb27 --- /dev/null +++ b/spec/classes/onionbalance_spec.rb @@ -0,0 +1,60 @@ +require File.expand_path(File.join(File.dirname(__FILE__),'../spec_helper')) + +describe 'tor::onionbalance', :type => 'class' do + let(:default_facts) { + { + :osfamily => 'RedHat', + :operatingsystem => 'CentOS', + } + } + let(:facts){ default_facts } + let(:pre_condition){'Exec{path => "/bin"}' } + let(:params){ + { + :services => { + 'keyname_of_service1' => { + 'name1' => 'onionservice_addr_3', + 'name2' => 'onionservice_addr_2', + '_key_content' => 'content_of_key_of_onionbalanced_service1', + }, + }, + } + } + describe 'with standard' do + it { is_expected.to compile.with_all_deps } + + it { is_expected.to contain_package('python2-onionbalance').with( + :ensure => 'installed', + ) } + it { is_expected.to contain_service('tor@onionbalance').with( + :ensure => 'running', + :enable => true, + ) } + it { is_expected.to contain_service('onionbalance').with( + :ensure => 'running', + :enable => true, + :subscribe => 'Service[tor@onionbalance]', + ) } + context 'on Debian' do + let(:facts) { + { + :osfamily => 'Debian', + :operatingsystem => 'Debian', + } + } + it { is_expected.to compile.with_all_deps } + it { is_expected.to contain_package('onionbalance').with( + :ensure => 'installed', + ) } + it { is_expected.to contain_service('tor@onionbalance').with( + :ensure => 'running', + :enable => true, + ) } + it { is_expected.to contain_service('onionbalance').with( + :ensure => 'running', + :enable => true, + :subscribe => 'Service[tor@onionbalance]', + ) } + end + end +end diff --git a/spec/defines/daemon_onion_service_spec.rb b/spec/defines/daemon_onion_service_spec.rb new file mode 100644 index 0000000..95be8c4 --- /dev/null +++ b/spec/defines/daemon_onion_service_spec.rb @@ -0,0 +1,120 @@ +require File.expand_path(File.join(File.dirname(__FILE__),'../spec_helper')) +require 'openssl' + +describe 'tor::daemon::onion_service', :type => 'define' do + let(:default_facts) { + { + :osfamily => 'RedHat', + :operatingsystem => 'CentOS', + } + } + let(:title){ 'test_os' } + let(:facts){ default_facts } + let(:pre_condition){'Exec{path => "/bin"} + include tor::daemon' } + describe 'with standard' do + it { is_expected.to compile.with_all_deps } + + it { is_expected.to contain_concat__fragment('05.onion_service.test_os').with( + :content => /HiddenServiceDir \/var\/lib\/tor\/test_os/, + :order => '05', + :target => '/etc/tor/torrc', + )} + it { is_expected.to_not contain_concat__fragment('05.onion_service.test_os').with_content(/^HiddenServicePort/) } + it { is_expected.to_not contain_file('/var/lib/tor/test_os') } + context 'on Debian' do + let(:facts) { + { + :osfamily => 'Debian', + :operatingsystem => 'Debian', + } + } + it { is_expected.to compile.with_all_deps } + it { is_expected.to contain_concat__fragment('05.onion_service.test_os').with( + :content => /HiddenServiceDir \/var\/lib\/tor\/test_os/, + :order => '05', + :target => '/etc/tor/torrc', + )} + it { is_expected.to_not contain_concat__fragment('05.onion_service.test_os').with_content(/^HiddenServicePort/) } + it { is_expected.to_not contain_file('/var/lib/tor/test_os') } + end + context 'with differt port params' do + let(:params){ + { + :ports => ['25','443 192.168.0.1:8443'] + } + } + it { is_expected.to compile.with_all_deps } + it { is_expected.to contain_concat__fragment('05.onion_service.test_os').with_content(/^HiddenServicePort 25 127.0.0.1:25/) } + it { is_expected.to contain_concat__fragment('05.onion_service.test_os').with_content(/^HiddenServicePort 443 192.168.0.1:8443/) } + it { is_expected.to_not contain_file('/var/lib/tor/test_os') } + end + context 'with private_key' do + let(:params){ + { + :ports => ['80'], + :private_key => OpenSSL::PKey::RSA.generate(1024).to_s, + } + } + it { is_expected.to compile.with_all_deps } + it { is_expected.to contain_concat__fragment('05.onion_service.test_os').with_content(/^HiddenServicePort 80 127.0.0.1:80/) } + it { is_expected.to contain_file('/var/lib/tor/test_os').with( + :ensure => 'directory', + :purge => true, + :force => true, + :recurse => true, + :owner => 'toranon', + :group => 'toranon', + :mode => '0600', + :require => 'Package[tor]', + )} + it { is_expected.to contain_file('/var/lib/tor/test_os/hostname').with( + :content => /^[a-z2-7]{16}\.onion\n/, + :owner => 'toranon', + :group => 'toranon', + :mode => '0600', + :notify => 'Service[tor]', + )} + it { is_expected.to contain_file('/var/lib/tor/test_os/private_key').with( + :owner => 'toranon', + :group => 'toranon', + :mode => '0600', + :notify => 'Service[tor]', + )} + end + context 'with private key to generate' do + let(:params){ + { + :ports => ['80'], + :private_key_name => 'test_os', + :private_key_store_path => File.expand_path(File.join(File.dirname(__FILE__),'..','tmp')), + } + } + it { is_expected.to compile.with_all_deps } + it { is_expected.to contain_concat__fragment('05.onion_service.test_os').with_content(/^HiddenServicePort 80 127.0.0.1:80/) } + it { is_expected.to contain_file('/var/lib/tor/test_os').with( + :ensure => 'directory', + :purge => true, + :force => true, + :recurse => true, + :owner => 'toranon', + :group => 'toranon', + :mode => '0600', + :require => 'Package[tor]', + )} + it { is_expected.to contain_file('/var/lib/tor/test_os/hostname').with( + :content => /^[a-z2-7]{16}\.onion\n/, + :owner => 'toranon', + :group => 'toranon', + :mode => '0600', + :notify => 'Service[tor]', + )} + it { is_expected.to contain_file('/var/lib/tor/test_os/private_key').with( + :owner => 'toranon', + :group => 'toranon', + :mode => '0600', + :notify => 'Service[tor]', + )} + end + end +end diff --git a/spec/functions/generate_onion_key_spec.rb b/spec/functions/generate_onion_key_spec.rb new file mode 100644 index 0000000..355f862 --- /dev/null +++ b/spec/functions/generate_onion_key_spec.rb @@ -0,0 +1,73 @@ +require 'spec_helper' +require 'fileutils' + +describe 'generate_onion_key' do + before(:all) do + @tmp_path = File.expand_path(File.join(File.dirname(__FILE__),'..','fixtures','tmp')) + @test_path = File.join(@tmp_path,'test.key') + @drpsyff5srkctr7h_str = "-----BEGIN RSA PRIVATE KEY----- +MIICXAIBAAKBgQC9OUBOkL73n43ogC/Jma54/ZZDEpoisqpkGJHgbcRGJIxcqqfL +PbnT3hD5SUCVXxLnzWDCTwTe2VOzIUlBXmslwVXnCJh/XGZg9NHiNU3EAZTwu1g9 +8gNmmG1bymaoEBkuC1osijOj+CN+gzLzApiMbDxddpxTn70LWaSqMDbfdQIDAQAB +An88nBn9EGAa8QCDeIvWB2PbXV7EHTFB6/ioFzairIYx8YMEK6WTdDIRqw/EybHm +Jo3nseFMXAMzXmlw9zh/t76ZzE7ooYocSPIEzpu4gDRsa5/mqRCGajs8A8ooiHN5 +Tc9cHzIfhjOYhu3VxF0G9LTAC8nKdWQkHm+h+J6A6+wBAkEA2E6GcIdPGTSfaNRS +BHOpKUUSvH7W0e5fyYe221EhESdTFjVkaO5YN9HvcqYh27nik0azKgNj6PiE01FC +0q4fgQJBAN/ycGS3dX5WRXEOpbQ04LKyxCFMVgS+tN5ueDgbv/SxWAxidLYcVfbg +CcUA+L2OaQ95S97CxYlCLda10vIPOfUCQQCUvQJzFIgOlAHdqsovJ3011Lp6hVmg +h6K0SK8zhkkPq5PVnKdMBEEDOUfG9XgoyFyF20LN7ADirSlgyesCRhuBAkEAmuCE +MmNecn0fkUzb9IENVQik85JjeuyZEau8oLEwU/3CMu50YO2/1fijSQee/xlaN0Vf +3zM8geyu3urodFdrcQJBAMBcecMvo4ddZ/GnwpKJuXEhKSwQfPOeb8lK12NvKuVE +znq+qT/KbJlwy/27X/auCAzD5rJ9VVzyWiu8nnwICS8= +-----END RSA PRIVATE KEY-----\n" + end + describe 'signature validation' do + it { is_expected.not_to eq(nil) } + it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /requires 2 arguments/) } + it { is_expected.to run.with_params(1).and_raise_error(Puppet::ParseError, /requires 2 arguments/) } + it { is_expected.to run.with_params('/etc/passwd','test').and_raise_error(Puppet::ParseError, /requires location \(\/etc\/passwd\) to be a directory/) } + describe 'with a key bigger than 1024' do + before(:each) do + FileUtils.mkdir_p(@tmp_path) unless File.directory?(@tmp_path) + File.open(@test_path,'w'){|f| f << OpenSSL::PKey::RSA.generate(2048) } + end + it { is_expected.to run.with_params(@tmp_path,'test').and_raise_error(Puppet::ParseError, /must have a length of 1024bit/) } + end + end + + describe 'normal operation' do + before(:all) do + FileUtils.rm_rf(@tmp_path) if File.exists?(@tmp_path) + FileUtils.mkdir_p(@tmp_path) + end + after(:all) do + FileUtils.rm_rf(@tmp_path) if File.exists?(@tmp_path) + end + let(:return_value) { + scope.function_generate_onion_key([@tmp_path,'test']) + } + context 'without an existing key' do + it 'returns an onion address and a key ' do + expect(return_value.size).to be(2) + end + it 'creates and stores the key' do + expect(return_value.last).to be_eql(File.read(File.join(@tmp_path,'test.key'))) + end + it 'returns a proper onion address' do + expect(return_value.first).to be_eql(scope.function_onion_address([File.read(File.join(@tmp_path,'test.key'))])) + end + it 'does not recreate a key once created' do + expect(scope.function_generate_onion_key([@tmp_path,'test'])).to be_eql(scope.function_generate_onion_key([@tmp_path,'test'])) + end + it 'creates to different keys for different names' do + expect(scope.function_generate_onion_key([@tmp_path,'test']).first).to_not be_eql(scope.function_generate_onion_key([@tmp_path,'test2'])) + end + end + context 'with an existing key' do + before(:all) do + File.open(File.join(@tmp_path,'test3.key'),'w'){|f| f << @drpsyff5srkctr7h_str } + end + it { is_expected.to run.with_params(@tmp_path,'test3').and_return(['drpsyff5srkctr7h',@drpsyff5srkctr7h_str]) } + end + end +end diff --git a/spec/functions/onion_address_spec.rb b/spec/functions/onion_address_spec.rb new file mode 100644 index 0000000..942d022 --- /dev/null +++ b/spec/functions/onion_address_spec.rb @@ -0,0 +1,48 @@ +require 'spec_helper' + +describe 'onion_address' do + describe 'signature validation' do + it { is_expected.not_to eq(nil) } + it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /requires 1 argument/) } + it { is_expected.to run.with_params(1,2).and_raise_error(Puppet::ParseError, /requires 1 argument/) } + end + + describe 'normal operation' do + it { is_expected.to run.with_params( +"-----BEGIN RSA PRIVATE KEY----- +MIICXAIBAAKBgQC9OUBOkL73n43ogC/Jma54/ZZDEpoisqpkGJHgbcRGJIxcqqfL +PbnT3hD5SUCVXxLnzWDCTwTe2VOzIUlBXmslwVXnCJh/XGZg9NHiNU3EAZTwu1g9 +8gNmmG1bymaoEBkuC1osijOj+CN+gzLzApiMbDxddpxTn70LWaSqMDbfdQIDAQAB +An88nBn9EGAa8QCDeIvWB2PbXV7EHTFB6/ioFzairIYx8YMEK6WTdDIRqw/EybHm +Jo3nseFMXAMzXmlw9zh/t76ZzE7ooYocSPIEzpu4gDRsa5/mqRCGajs8A8ooiHN5 +Tc9cHzIfhjOYhu3VxF0G9LTAC8nKdWQkHm+h+J6A6+wBAkEA2E6GcIdPGTSfaNRS +BHOpKUUSvH7W0e5fyYe221EhESdTFjVkaO5YN9HvcqYh27nik0azKgNj6PiE01FC +0q4fgQJBAN/ycGS3dX5WRXEOpbQ04LKyxCFMVgS+tN5ueDgbv/SxWAxidLYcVfbg +CcUA+L2OaQ95S97CxYlCLda10vIPOfUCQQCUvQJzFIgOlAHdqsovJ3011Lp6hVmg +h6K0SK8zhkkPq5PVnKdMBEEDOUfG9XgoyFyF20LN7ADirSlgyesCRhuBAkEAmuCE +MmNecn0fkUzb9IENVQik85JjeuyZEau8oLEwU/3CMu50YO2/1fijSQee/xlaN0Vf +3zM8geyu3urodFdrcQJBAMBcecMvo4ddZ/GnwpKJuXEhKSwQfPOeb8lK12NvKuVE +znq+qT/KbJlwy/27X/auCAzD5rJ9VVzyWiu8nnwICS8= +-----END RSA PRIVATE KEY-----" + ).and_return("drpsyff5srkctr7h")} + end + describe 'by getting an RSA key' do + it { is_expected.to run.with_params(OpenSSL::PKey::RSA.new( +"-----BEGIN RSA PRIVATE KEY----- +MIICXQIBAAKBgQDbvYjbtJB9vTnEygyq4Bzp0xxtTl3ZYKC6JbxgRzP8uLv1HoxX +20EmQUZ/LNBXHebc6frlObhtpKULFuBzAy5LpdKI9CUErkl3D3AigFgP3XP/PtdP +m11TuxdBoKL6Jbo54NpUVOGQ5SJJaNEOfhmgMSCtlyyI9DBni3PLO2P0sQIDAQAB +AoGAPTlt7Gk+6QnUErSJGwMeize67+mp1GtL3RGujtTH8141YHKGf+QjHtmJHt4J +nnxCWsMGmN+gN0xsf8578w+r0fvDjZ3e5lVUpR/8ds90a654Lr/pgqLc3H1EZ9Pr +GDFjPdaMtdTSX5hSAB2EDLfDUU19bdFRK+k71mglrMLpdQECQQDmJt3mmX67kAzH +w2I/BEbmOlonmn3c98VyawoNrk0fKAluoYWHxxk9SuCu2ZDQyyPKPQuZbgdPnUNp +kV3PuQ6ZAkEA9GtTjMfceX8ArLTmOMIMVP2t8yzbcK2uqukMG79JiPZbYKIstjho +XUpO/jZhTb9p8M4NV/09z091gMTOF6Fd2QJBAM1I7bS6ROhX3I5yIDfFQNgqRC// +BTULa/par2T0i6W2uHMNb2VkmYaqOy66sQkLqKjDOo1oLu08gNyw5NRbZEECQQCr +FDR25a28nNisCjLap3haRPXssAko5WjM2DJReaLO6yEqklkZcoIaSljgNtAEy2Yr +1w4f+HG7GbL1XsuiXqCBAkAeYljaIVhqGOOez0ORaCm0FCLoTJ6/fn7009os/qgr +n2xsVGUNm+E0pvAMT0LIx2KvpLxe2Y0Xx497/vyM6e7G +-----END RSA PRIVATE KEY-----") + ).and_return("d3ep6pcs4to4hbwo") } + end +end diff --git a/spec/puppetlabs_spec_helper_clone.rb b/spec/puppetlabs_spec_helper_clone.rb new file mode 100644 index 0000000..6a94a3b --- /dev/null +++ b/spec/puppetlabs_spec_helper_clone.rb @@ -0,0 +1,34 @@ +#This file pulls in only the minimum necessary to let unmigrated specs still work + +# Define the main module namespace for use by the helper modules +module PuppetlabsSpec + # FIXTURE_DIR represents the standard locations of all fixture data. Normally + # this represents <project>/spec/fixtures. This will be used by the fixtures + # library to find relative fixture data. + FIXTURE_DIR = File.join("spec", "fixtures") unless defined?(FIXTURE_DIR) +end + +# Require all necessary helper libraries so they can be used later +require 'puppetlabs_spec_helper/puppetlabs_spec/files' +require 'puppetlabs_spec_helper/puppetlabs_spec/fixtures' +#require 'puppetlabs_spec_helper/puppetlabs_spec/puppet_internals' +require 'puppetlabs_spec_helper/puppetlabs_spec/matchers' + +RSpec.configure do |config| + # Include PuppetlabsSpec helpers so they can be called at convenience + config.extend PuppetlabsSpec::Files + config.extend PuppetlabsSpec::Fixtures + config.include PuppetlabsSpec::Fixtures + + config.parser = 'future' if ENV['FUTURE_PARSER'] == 'yes' + config.strict_variables = true if ENV['STRICT_VARIABLES'] == 'yes' + config.stringify_facts = false if ENV['STRINGIFY_FACTS'] == 'no' + config.trusted_node_data = true if ENV['TRUSTED_NODE_DATA'] == 'yes' + config.ordering = ENV['ORDERING'] if ENV['ORDERING'] + + # This will cleanup any files that were created with tmpdir or tmpfile + config.after :each do + PuppetlabsSpec::Files.cleanup + end +end + diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 3cca63a..66cfb3b 100644..100755 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,12 +1,48 @@ -# https://puppetlabs.com/blog/testing-modules-in-the-puppet-forge +#! /usr/bin/env ruby -S rspec +dir = File.expand_path(File.dirname(__FILE__)) +$LOAD_PATH.unshift File.join(dir, 'lib') + +# So everyone else doesn't have to include this base constant. +module PuppetSpec + FIXTURE_DIR = File.join(dir = File.expand_path(File.dirname(__FILE__)), "fixtures") unless defined?(FIXTURE_DIR) +end + +require 'puppet' +require 'rspec-puppet' require 'puppetlabs_spec_helper/module_spec_helper' +require 'mocha/api' +#require 'puppetlabs_spec_helper/module_spec_helper' +require 'puppetlabs_spec_helper_clone' + +# hack to enable all the expect syntax (like allow_any_instance_of) in rspec-puppet examples +RSpec::Mocks::Syntax.enable_expect(RSpec::Puppet::ManifestMatchers) -fixture_path = File.expand_path(File.join(__FILE__, '..', 'fixtures')) +RSpec.configure do |config| + config.module_path = File.join(File.dirname(File.expand_path(__FILE__)), 'fixtures', 'modules') + config.manifest_dir = File.join(File.dirname(File.expand_path(__FILE__)), 'fixtures', 'manifests') + config.environmentpath = spec_path = File.expand_path(File.join(Dir.pwd, 'spec')) -RSpec.configure do |c| + config.add_setting :puppet_future + #config.puppet_future = (ENV['FUTURE_PARSER'] == 'yes' or Puppet.version.to_f >= 4.0) + config.puppet_future = Puppet.version.to_f >= 4.0 - c.manifest_dir = File.join(fixture_path, 'manifests') - c.module_path = File.join(fixture_path, 'modules') + config.before :each do + # Ensure that we don't accidentally cache facts and environment between + # test cases. This requires each example group to explicitly load the + # facts being exercised with something like + # Facter.collection.loader.load(:ipaddress) + Facter.clear + Facter.clear_messages + + RSpec::Mocks.setup + end + + config.after :each do + RSpec::Mocks.verify + RSpec::Mocks.teardown + end +end - c.color = true +# Helper class to test handling of arguments which are derived from string +class AlsoString < String end diff --git a/spec/spec_helper_acceptance.rb b/spec/spec_helper_acceptance.rb deleted file mode 100644 index e6a2cd8..0000000 --- a/spec/spec_helper_acceptance.rb +++ /dev/null @@ -1,18 +0,0 @@ -require 'beaker-rspec' - -RSpec.configure do |c| - module_root = File.expand_path(File.join(File.dirname(__FILE__), '..')) - module_name = module_root.split('-').last - - # Readable test descriptions - c.formatter = :documentation - - # Configure all nodes in nodeset - c.before :suite do - # Install module and dependencies - puppet_module_install(:source => module_root, :module_name => module_name) - hosts.each do |host| - shell('git clone https://github.com/puppetlabs/puppetlabs-concat.git /etc/puppet/modules/concat') - end - end -end diff --git a/spec/tmp/.keep b/spec/tmp/.keep new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/spec/tmp/.keep diff --git a/templates/onionbalance/Debian.torrc.erb b/templates/onionbalance/Debian.torrc.erb new file mode 100644 index 0000000..4b1afc4 --- /dev/null +++ b/templates/onionbalance/Debian.torrc.erb @@ -0,0 +1,5 @@ +# Tor config for the onionbalance management server +# --- +# The onionbalance service must be able to access the Tor control port. +ControlPort 9051 +SocksPort 0 diff --git a/templates/onionbalance/RedHat.torrc.erb b/templates/onionbalance/RedHat.torrc.erb new file mode 100644 index 0000000..023748b --- /dev/null +++ b/templates/onionbalance/RedHat.torrc.erb @@ -0,0 +1,13 @@ +# Tor config for the onionbalance management server +# --- +# The onionbalance service must be able to access the Tor control port. + +DataDirectory /var/lib/tor/onionbalance-data + +ControlPort 9051 +CookieAuthentication 1 +SocksPort 0 + +CookieAuthFileGroupReadable 1 +CookieAuthFile /run/tor/onionbalance.control.authcookie + diff --git a/templates/onionbalance/config.yaml.erb b/templates/onionbalance/config.yaml.erb new file mode 100644 index 0000000..b1d4d80 --- /dev/null +++ b/templates/onionbalance/config.yaml.erb @@ -0,0 +1,10 @@ +# OnionBalance Config File +services: +<% @services.keys.sort.each do |key| -%> + - key: /etc/onionbalance/<%= key %>.key + instances: +<% (@services[key].keys - ['_key_content']).sort.each do |inst| -%> + - address: <%= @services[key][inst] %> + name: <%= inst %> +<% end -%> +<% end -%> diff --git a/templates/torrc.global.erb b/templates/torrc.global.erb index c29b76b..763e63f 100644 --- a/templates/torrc.global.erb +++ b/templates/torrc.global.erb @@ -1,24 +1,24 @@ # runtime RunAsDaemon 1 -<% if (v=scope.lookupvar('tor::daemon::data_dir')) != '/var/lib/tor' -%> +<% if (v=scope['tor::daemon::data_dir']) != '/var/lib/tor' -%> DataDirectory <%= v %> <% end -%> # log -<% if (rules=scope.lookupvar('tor::daemon::log_rules')).empty? -%> +<% if (rules=scope['tor::daemon::log_rules']).empty? -%> Log notice syslog <% else -%> <% Array(rules).each do |log_rule| -%> Log <%= log_rule %> -<% end -%> -<% end -%> -<%- if (v=scope.lookupvar('tor::daemon::safe_logging')) != '1' then -%> +<% end +end -%> +<% if (v=scope['tor::daemon::safe_logging']) != 1 -%> SafeLogging <%= v %> -<%- end -%> +<% end -%> -<% if (v=scope.lookupvar('tor::daemon::automap_hosts_on_resolve')) != '0' -%> +<% if (v=scope['tor::daemon::automap_hosts_on_resolve']) != 0 -%> AutomapHostsOnResolve <%= v %> -<% end -%> -<% if (v=scope.lookupvar('tor::daemon::use_bridges')) != '0' -%> +<% end -%> +<% if (v=scope['tor::daemon::use_bridges']) != 0 -%> UseBridges <%= v %> -<%- end -%> +<% end -%> diff --git a/templates/torrc.hidden_service.erb b/templates/torrc.onion_service.erb index c7dbe9e..9b05c43 100644 --- a/templates/torrc.hidden_service.erb +++ b/templates/torrc.onion_service.erb @@ -1,20 +1,20 @@ -<% if @single_hop != false %> +<% if @single_hop != false -%> HiddenServiceSingleHopMode 1 HiddenServiceNonAnonymousMode 1 SOCKSPort 0 -<% end %> +<% end -%> # hidden service <%= @name %> -HiddenServiceDir <%= @data_dir %>/<%= @name %> +HiddenServiceDir <%= @data_dir_path %> <% Array(@ports).each do |port| -%> -HiddenServicePort <%= port %> +HiddenServicePort <%= port =~ /^\d+$/ ? "#{port} 127.0.0.1:#{port}" : port %> <% end -%> -<% if @v3 != false %> +<% if @v3 != false -%> # hidden service v3 static -HiddenServiceDir <%= @data_dir %>/<%= @name -%>3 +HiddenServiceDir <%= @data_dir_path %>3 HiddenServiceVersion 3 <% Array(@ports).each do |port| -%> HiddenServicePort <%= port %> -<% end -%> -<% end -%> +<% end +end -%> |