diff options
-rw-r--r-- | lib/leap_cli/commands/compile.rb | 13 | ||||
-rw-r--r-- | lib/leap_cli/commands/ssh.rb | 5 | ||||
-rw-r--r-- | lib/leap_cli/commands/vagrant.rb | 2 | ||||
-rw-r--r-- | lib/leap_cli/macros/provider.rb | 70 | ||||
-rw-r--r-- | provider_base/common.json | 3 | ||||
-rw-r--r-- | provider_base/services/webapp.json | 2 | ||||
-rw-r--r-- | provider_base/tags/development.json | 6 | ||||
-rw-r--r-- | puppet/lib/puppet/parser/functions/sorted_yaml.rb | 388 | ||||
-rw-r--r-- | puppet/modules/leap/manifests/cli/install.pp | 33 | ||||
-rw-r--r-- | puppet/modules/site_postfix/manifests/mx.pp | 14 | ||||
-rw-r--r-- | puppet/modules/site_postfix/manifests/mx/static_aliases.pp | 34 | ||||
-rw-r--r-- | puppet/modules/site_postfix/templates/custom-aliases.erb | 11 | ||||
-rw-r--r-- | puppet/modules/site_postfix/templates/virtual-aliases.erb | 22 | ||||
-rw-r--r-- | puppet/modules/site_sshd/manifests/init.pp | 18 | ||||
-rw-r--r-- | puppet/modules/site_webapp/templates/config.yml.erb | 67 | ||||
-rwxr-xr-x | vagrant/configure-leap.sh | 33 | ||||
-rwxr-xr-x | vagrant/install-platform.pp | 32 |
17 files changed, 622 insertions, 131 deletions
diff --git a/lib/leap_cli/commands/compile.rb b/lib/leap_cli/commands/compile.rb index f5895b8b..8f6c7769 100644 --- a/lib/leap_cli/commands/compile.rb +++ b/lib/leap_cli/commands/compile.rb @@ -256,7 +256,7 @@ remove this directory if you don't use it. ## ZONE FILE ## - def relative_hostname(fqdn) + def relative_hostname(fqdn, provider) @domain_regexp ||= /\.?#{Regexp.escape(provider.domain)}$/ fqdn.sub(@domain_regexp, '') end @@ -265,10 +265,11 @@ remove this directory if you don't use it. # serial is any number less than 2^32 (4294967296) # def compile_zone_file + provider = manager.env('default').provider hosts_seen = {} f = $stdout f.puts ZONE_HEADER % {:domain => provider.domain, :ns => provider.domain, :contact => provider.contacts.default.first.sub('@','.')} - max_width = manager.nodes.values.inject(0) {|max, node| [max, relative_hostname(node.domain.full).length].max } + max_width = manager.nodes.values.inject(0) {|max, node| [max, relative_hostname(node.domain.full, provider).length].max } put_line = lambda do |host, line| host = '@' if host == '' f.puts("%-#{max_width}s %s" % [host, line]) @@ -297,18 +298,18 @@ remove this directory if you don't use it. f.puts ENV_HEADER % (env.nil? ? 'default' : env) nodes.each_node do |node| if node.dns.public - hostname = relative_hostname(node.domain.full) - put_line.call relative_hostname(node.domain.full), "IN A #{node.ip_address}" + hostname = relative_hostname(node.domain.full, provider) + put_line.call relative_hostname(node.domain.full, provider), "IN A #{node.ip_address}" end if node.dns['aliases'] node.dns.aliases.each do |host_alias| if host_alias != node.domain.full && host_alias != provider.domain - put_line.call relative_hostname(host_alias), "IN A #{node.ip_address}" + put_line.call relative_hostname(host_alias, provider), "IN A #{node.ip_address}" end end end if node.services.include? 'mx' - put_line.call relative_hostname(node.domain.full_suffix), "IN MX 10 #{relative_hostname(node.domain.full)}" + put_line.call relative_hostname(node.domain.full_suffix, provider), "IN MX 10 #{relative_hostname(node.domain.full, provider)}" end end end diff --git a/lib/leap_cli/commands/ssh.rb b/lib/leap_cli/commands/ssh.rb index 1a81902c..3887618e 100644 --- a/lib/leap_cli/commands/ssh.rb +++ b/lib/leap_cli/commands/ssh.rb @@ -27,6 +27,11 @@ module LeapCli; module Commands c.flag 'port', :arg_name => 'SSH_PORT', :desc => 'Override default SSH port used when trying to connect to the server. Same as `--ssh "-p SSH_PORT"`.' c.action do |global_options,options,args| local_port, node, remote_port = parse_tunnel_arg(args.first) + unless node.ssh.config.AllowTcpForwarding == "yes" + log :warning, "It looks like TCP forwarding is not enabled. "+ + "The tunnel command requires that the node property ssh.config.AllowTcpForwarding "+ + "be set to 'yes'. Add this property to #{node.name}.json, deploy, and then try tunnel again." + end options[:ssh] = [options[:ssh], "-N -L 127.0.0.1:#{local_port}:0.0.0.0:#{remote_port}"].join(' ') log("Forward port localhost:#{local_port} to #{node.name}:#{remote_port}") if is_port_available?(local_port) diff --git a/lib/leap_cli/commands/vagrant.rb b/lib/leap_cli/commands/vagrant.rb index 1561a658..9e81b2f8 100644 --- a/lib/leap_cli/commands/vagrant.rb +++ b/lib/leap_cli/commands/vagrant.rb @@ -79,7 +79,7 @@ module LeapCli; module Commands # we need to make sure that it owned by us and not world readable. # def vagrant_ssh_key_file - file_path = Path.vagrant_ssh_key_file + file_path = Path.vagrant_ssh_pub_key_file Util.assert_files_exist! file_path uid = File.new(file_path).stat.uid if uid == 0 || uid == Process.euid diff --git a/lib/leap_cli/macros/provider.rb b/lib/leap_cli/macros/provider.rb index 84c4e1b8..4e74da01 100644 --- a/lib/leap_cli/macros/provider.rb +++ b/lib/leap_cli/macros/provider.rb @@ -16,5 +16,75 @@ module LeapCli } end + # + # The webapp will not work unless the service level configuration is precisely defined. + # Here, we take what the sysadmin has specified in provider.json and clean it up to + # ensure it is OK. + # + # It would be better to add support for JSON schema. + # + def service_levels() + levels = {} + provider.service.levels.each do |name, level| + if name =~ /^[0-9]+$/ + name = name.to_i + end + levels[name] = level_cleanup(name, level.clone) + end + levels + end + + private + + def print_warning(name, msg) + if self.environment + provider_str = "provider.json or %s" % ['provider', self.environment, 'json'].join('.') + else + provider_str = "provider.json" + end + LeapCli::log :warning, "In #{provider_str}, you have an incorrect definition for service level '#{name}':" do + LeapCli::log msg + end + end + + def level_cleanup(name, level) + unless level['name'] + print_warning(name, 'required field "name" is missing') + end + unless level['description'] + print_warning(name, 'required field "description" is missing') + end + unless level['bandwidth'].nil? || level['bandwidth'] == 'limited' + print_warning(name, 'field "bandwidth" must be nil or "limited"') + end + unless level['rate'].nil? || level['rate'].is_a?(Hash) + print_warning(name, 'field "rate" must be nil or a hash (e.g. {"USD":10, "EUR":10})') + end + possible_services = enabled_services + if level['services'] + level['services'].each do |service| + unless possible_services.include? service + print_warning(name, "the service '#{service}' does not exist or there are no nodes that provide this service.") + LeapCli::Util::bail! + end + end + else + level['services'] = possible_services + end + level['services'] = remap_services(level['services']) + level + end + + # + # the service names that the webapp uses and that leap_platform uses are different. ugh. + # + SERVICE_MAP = { + "mx" => "email", + "openvpn" => "eip" + } + def remap_services(services) + services.map {|srv| SERVICE_MAP[srv]} + end + end end diff --git a/provider_base/common.json b/provider_base/common.json index 3d2965d7..e968dd27 100644 --- a/provider_base/common.json +++ b/provider_base/common.json @@ -16,6 +16,9 @@ }, "ssh": { "authorized_keys": "= authorized_keys", + "config": { + "AllowTcpForwarding": "no" + }, "port": 22, "mosh": { "ports": "60000:61000", diff --git a/provider_base/services/webapp.json b/provider_base/services/webapp.json index dbcfe0a6..039b1c0b 100644 --- a/provider_base/services/webapp.json +++ b/provider_base/services/webapp.json @@ -20,7 +20,7 @@ "allow_anonymous_certs": "= provider.service.allow_anonymous", "allow_registration": "= provider.service.allow_registration", "default_service_level": "= provider.service.default_service_level", - "service_levels": "= provider.service.levels", + "service_levels": "= service_levels()", "secret_token": "= secret :webapp_secret_token", "api_version": 1, "secure": false, diff --git a/provider_base/tags/development.json b/provider_base/tags/development.json index d9c2c007..caf18e9d 100644 --- a/provider_base/tags/development.json +++ b/provider_base/tags/development.json @@ -1,7 +1,3 @@ { - "environment": "development", - "domain": { - "full_suffix": "= 'dev.' + provider.domain", - "internal_suffix": "= 'dev.' + provider.domain_internal" - } + "environment": "development" }
\ No newline at end of file diff --git a/puppet/lib/puppet/parser/functions/sorted_yaml.rb b/puppet/lib/puppet/parser/functions/sorted_yaml.rb new file mode 100644 index 00000000..fa0db4d2 --- /dev/null +++ b/puppet/lib/puppet/parser/functions/sorted_yaml.rb @@ -0,0 +1,388 @@ +# encoding: UTF-8 +# +# provides sorted_yaml() function, using Ya2YAML. +# see https://github.com/afunai/ya2yaml +# + +class Ya2YAML + # + # Author:: Akira FUNAI + # Copyright:: Copyright (c) 2006-2010 Akira FUNAI + # License:: MIT License + # + + def initialize(opts = {}) + options = opts.dup + options[:indent_size] = 2 if options[:indent_size].to_i <= 0 + options[:minimum_block_length] = 0 if options[:minimum_block_length].to_i <= 0 + options.update( + { + :printable_with_syck => true, + :escape_b_specific => true, + :escape_as_utf8 => true, + } + ) if options[:syck_compatible] + + @options = options + end + + def _ya2yaml(obj) + #raise 'set $KCODE to "UTF8".' if (RUBY_VERSION < '1.9.0') && ($KCODE != 'UTF8') + if (RUBY_VERSION < '1.9.0') + $KCODE = 'UTF8' + end + '--- ' + emit(obj, 1) + "\n" + rescue SystemStackError + raise ArgumentError, "ya2yaml can't handle circular references" + end + + private + + def emit(obj, level) + case obj + when Array + if (obj.length == 0) + '[]' + else + indent = "\n" + s_indent(level - 1) + ### + ### NOTE: a minor modification to normal Ya2YAML... + ### We want arrays to be output in sorted order, not just + ### Hashes. + ### + #obj.collect {|o| + # indent + '- ' + emit(o, level + 1) + #}.join('') + obj.sort {|a,b| a.to_s <=> b.to_s}.collect {|o| + indent + '- ' + emit(o, level + 1) + }.join('') + end + when Hash + if (obj.length == 0) + '{}' + else + indent = "\n" + s_indent(level - 1) + hash_order = @options[:hash_order] + if (hash_order && level == 1) + hash_keys = obj.keys.sort {|x, y| + x_order = hash_order.index(x) ? hash_order.index(x) : Float::MAX + y_order = hash_order.index(y) ? hash_order.index(y) : Float::MAX + o = (x_order <=> y_order) + (o != 0) ? o : (x.to_s <=> y.to_s) + } + elsif @options[:preserve_order] + hash_keys = obj.keys + else + hash_keys = obj.keys.sort {|x, y| x.to_s <=> y.to_s } + end + hash_keys.collect {|k| + key = emit(k, level + 1) + if ( + is_one_plain_line?(key) || + key =~ /\A(#{REX_BOOL}|#{REX_FLOAT}|#{REX_INT}|#{REX_NULL})\z/x + ) + indent + key + ': ' + emit(obj[k], level + 1) + else + indent + '? ' + key + + indent + ': ' + emit(obj[k], level + 1) + end + }.join('') + end + when NilClass + '~' + when String + emit_string(obj, level) + when TrueClass, FalseClass + obj.to_s + when Fixnum, Bignum, Float + obj.to_s + when Date + obj.to_s + when Time + offset = obj.gmtoff + off_hm = sprintf( + '%+.2d:%.2d', + (offset / 3600.0).to_i, + (offset % 3600.0) / 60 + ) + u_sec = (obj.usec != 0) ? sprintf(".%.6d", obj.usec) : '' + obj.strftime("%Y-%m-%d %H:%M:%S#{u_sec} #{off_hm}") + when Symbol + '!ruby/symbol ' + emit_string(obj.to_s, level) + when Range + '!ruby/range ' + obj.to_s + when Regexp + '!ruby/regexp ' + obj.inspect + else + case + when obj.is_a?(Struct) + struct_members = {} + obj.each_pair{|k, v| struct_members[k.to_s] = v } + '!ruby/struct:' + obj.class.to_s.sub(/^(Struct::(.+)|.*)$/, '\2') + ' ' + + emit(struct_members, level + 1) + else + # serialized as a generic object + object_members = {} + obj.instance_variables.each{|k, v| + object_members[k.to_s.sub(/^@/, '')] = obj.instance_variable_get(k) + } + '!ruby/object:' + obj.class.to_s + ' ' + + emit(object_members, level + 1) + end + end + end + + def emit_string(str, level) + (is_string, is_printable, is_one_line, is_one_plain_line) = string_type(str) + if is_string + if is_printable + if is_one_plain_line + emit_simple_string(str, level) + else + (is_one_line || str.length < @options[:minimum_block_length]) ? + emit_quoted_string(str, level) : + emit_block_string(str, level) + end + else + emit_quoted_string(str, level) + end + else + emit_base64_binary(str, level) + end + end + + def emit_simple_string(str, level) + str + end + + def emit_block_string(str, level) + str = normalize_line_break(str) + + indent = s_indent(level) + indentation_indicator = (str =~ /\A /) ? indent.size.to_s : '' + str =~ /(#{REX_NORMAL_LB}*)\z/ + chomping_indicator = case $1.length + when 0 + '-' + when 1 + '' + else + '+' + end + + str.chomp! + str.gsub!(/#{REX_NORMAL_LB}/) { + $1 + indent + } + '|' + indentation_indicator + chomping_indicator + "\n" + indent + str + end + + def emit_quoted_string(str, level) + str = yaml_escape(normalize_line_break(str)) + if (str.length < @options[:minimum_block_length]) + str.gsub!(/#{REX_NORMAL_LB}/) { ESCAPE_SEQ_LB[$1] } + else + str.gsub!(/#{REX_NORMAL_LB}$/) { ESCAPE_SEQ_LB[$1] } + str.gsub!(/(#{REX_NORMAL_LB}+)(.)/) { + trail_c = $3 + $1 + trail_c.sub(/([\t ])/) { ESCAPE_SEQ_WS[$1] } + } + indent = s_indent(level) + str.gsub!(/#{REX_NORMAL_LB}/) { + ESCAPE_SEQ_LB[$1] + "\\\n" + indent + } + end + '"' + str + '"' + end + + def emit_base64_binary(str, level) + indent = "\n" + s_indent(level) + base64 = [str].pack('m') + '!binary |' + indent + base64.gsub(/\n(?!\z)/, indent) + end + + def string_type(str) + if str.respond_to?(:encoding) && (!str.valid_encoding? || str.encoding == Encoding::ASCII_8BIT) + return false, false, false, false + end + (ucs_codes = str.unpack('U*')) rescue ( + # ArgumentError -> binary data + return false, false, false, false + ) + if ( + @options[:printable_with_syck] && + str =~ /\A#{REX_ANY_LB}* | #{REX_ANY_LB}*\z|#{REX_ANY_LB}{2}\z/ + ) + # detour Syck bug + return true, false, nil, false + end + ucs_codes.each {|ucs_code| + return true, false, nil, false unless is_printable?(ucs_code) + } + return true, true, is_one_line?(str), is_one_plain_line?(str) + end + + def is_printable?(ucs_code) + # YAML 1.1 / 4.1.1. + ( + [0x09, 0x0a, 0x0d, 0x85].include?(ucs_code) || + (ucs_code <= 0x7e && ucs_code >= 0x20) || + (ucs_code <= 0xd7ff && ucs_code >= 0xa0) || + (ucs_code <= 0xfffd && ucs_code >= 0xe000) || + (ucs_code <= 0x10ffff && ucs_code >= 0x10000) + ) && + !( + # treat LS/PS as non-printable characters + @options[:escape_b_specific] && + (ucs_code == 0x2028 || ucs_code == 0x2029) + ) + end + + def is_one_line?(str) + str !~ /#{REX_ANY_LB}(?!\z)/ + end + + def is_one_plain_line?(str) + # YAML 1.1 / 4.6.11. + str !~ /^([\-\?:,\[\]\{\}\#&\*!\|>'"%@`\s]|---|\.\.\.)/ && + str !~ /[:\#\s\[\]\{\},]/ && + str !~ /#{REX_ANY_LB}/ && + str !~ /^(#{REX_BOOL}|#{REX_FLOAT}|#{REX_INT}|#{REX_MERGE} + |#{REX_NULL}|#{REX_TIMESTAMP}|#{REX_VALUE})$/x + end + + def s_indent(level) + # YAML 1.1 / 4.2.2. + ' ' * (level * @options[:indent_size]) + end + + def normalize_line_break(str) + # YAML 1.1 / 4.1.4. + str.gsub(/(#{REX_CRLF}|#{REX_CR}|#{REX_NEL})/, "\n") + end + + def yaml_escape(str) + # YAML 1.1 / 4.1.6. + str.gsub(/[^a-zA-Z0-9]/u) {|c| + ucs_code, = (c.unpack('U') rescue [??]) + case + when ESCAPE_SEQ[c] + ESCAPE_SEQ[c] + when is_printable?(ucs_code) + c + when @options[:escape_as_utf8] + c.respond_to?(:bytes) ? + c.bytes.collect {|b| '\\x%.2x' % b }.join : + '\\x' + c.unpack('H2' * c.size).join('\\x') + when ucs_code == 0x2028 || ucs_code == 0x2029 + ESCAPE_SEQ_LB[c] + when ucs_code <= 0x7f + sprintf('\\x%.2x', ucs_code) + when ucs_code <= 0xffff + sprintf('\\u%.4x', ucs_code) + else + sprintf('\\U%.8x', ucs_code) + end + } + end + + module Constants + UCS_0X85 = [0x85].pack('U') # c285@UTF8 Unicode next line + UCS_0XA0 = [0xa0].pack('U') # c2a0@UTF8 Unicode non-breaking space + UCS_0X2028 = [0x2028].pack('U') # e280a8@UTF8 Unicode line separator + UCS_0X2029 = [0x2029].pack('U') # e280a9@UTF8 Unicode paragraph separator + + # non-break characters + ESCAPE_SEQ = { + "\x00" => '\\0', + "\x07" => '\\a', + "\x08" => '\\b', + "\x0b" => '\\v', + "\x0c" => '\\f', + "\x1b" => '\\e', + "\"" => '\\"', + "\\" => '\\\\', + } + + # non-breaking space + ESCAPE_SEQ_NS = { + UCS_0XA0 => '\\_', + } + + # white spaces + ESCAPE_SEQ_WS = { + "\x09" => '\\t', + " " => '\\x20', + } + + # line breaks + ESCAPE_SEQ_LB ={ + "\x0a" => '\\n', + "\x0d" => '\\r', + UCS_0X85 => '\\N', + UCS_0X2028 => '\\L', + UCS_0X2029 => '\\P', + } + + # regexps for line breaks + REX_LF = Regexp.escape("\x0a") + REX_CR = Regexp.escape("\x0d") + REX_CRLF = Regexp.escape("\x0d\x0a") + REX_NEL = Regexp.escape(UCS_0X85) + REX_LS = Regexp.escape(UCS_0X2028) + REX_PS = Regexp.escape(UCS_0X2029) + + REX_ANY_LB = /(#{REX_LF}|#{REX_CR}|#{REX_NEL}|#{REX_LS}|#{REX_PS})/ + REX_NORMAL_LB = /(#{REX_LF}|#{REX_LS}|#{REX_PS})/ + + # regexps for language-Independent types for YAML1.1 + REX_BOOL = / + y|Y|yes|Yes|YES|n|N|no|No|NO + |true|True|TRUE|false|False|FALSE + |on|On|ON|off|Off|OFF + /x + REX_FLOAT = / + [-+]?([0-9][0-9_]*)?\.[0-9.]*([eE][-+][0-9]+)? # (base 10) + |[-+]?[0-9][0-9_]*(:[0-5]?[0-9])+\.[0-9_]* # (base 60) + |[-+]?\.(inf|Inf|INF) # (infinity) + |\.(nan|NaN|NAN) # (not a number) + /x + REX_INT = / + [-+]?0b[0-1_]+ # (base 2) + |[-+]?0[0-7_]+ # (base 8) + |[-+]?(0|[1-9][0-9_]*) # (base 10) + |[-+]?0x[0-9a-fA-F_]+ # (base 16) + |[-+]?[1-9][0-9_]*(:[0-5]?[0-9])+ # (base 60) + /x + REX_MERGE = / + << + /x + REX_NULL = / + ~ # (canonical) + |null|Null|NULL # (English) + | # (Empty) + /x + REX_TIMESTAMP = / + [0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] # (ymd) + |[0-9][0-9][0-9][0-9] # (year) + -[0-9][0-9]? # (month) + -[0-9][0-9]? # (day) + ([Tt]|[ \t]+)[0-9][0-9]? # (hour) + :[0-9][0-9] # (minute) + :[0-9][0-9] # (second) + (\.[0-9]*)? # (fraction) + (([ \t]*)Z|[-+][0-9][0-9]?(:[0-9][0-9])?)? # (time zone) + /x + REX_VALUE = / + = + /x + end + + include Constants +end + +module Puppet::Parser::Functions + newfunction(:sorted_yaml, :type => :rvalue, :doc => "This function outputs yaml, but ensures the keys are sorted.") do |argument| + return Ya2YAML.new()._ya2yaml(argument) + end +end diff --git a/puppet/modules/leap/manifests/cli/install.pp b/puppet/modules/leap/manifests/cli/install.pp new file mode 100644 index 00000000..858bd7da --- /dev/null +++ b/puppet/modules/leap/manifests/cli/install.pp @@ -0,0 +1,33 @@ +# installs leap_cli on node +class leap::cli::install ( $source = false ) { + if $source { + # needed for building leap_cli from source + include ::git + include ::site_config::ruby::dev + + vcsrepo { '/srv/leap/cli': + ensure => present, + force => true, + revision => 'develop', + provider => 'git', + source => 'https://leap.se/git/leap_cli.git', + owner => 'root', + group => 'root', + notify => Exec['install_leap_cli'], + require => Package['git'] + } + + exec { 'install_leap_cli': + command => '/usr/bin/rake build && /usr/bin/rake install', + cwd => '/srv/leap/cli', + refreshonly => true, + require => [ Package['ruby-dev'], File['/etc/gemrc'], Package['rake'] ] + } + } + else { + package { 'leap_cli': + ensure => installed, + provider => gem + } + } +} diff --git a/puppet/modules/site_postfix/manifests/mx.pp b/puppet/modules/site_postfix/manifests/mx.pp index 2b311e06..42313d1a 100644 --- a/puppet/modules/site_postfix/manifests/mx.pp +++ b/puppet/modules/site_postfix/manifests/mx.pp @@ -7,8 +7,8 @@ class site_postfix::mx { $domain = $domain_hash['full_suffix'] $host_domain = $domain_hash['full'] $cert_name = hiera('name') - $mynetworks = join(hiera('mynetworks'), ' ') - $rbls = suffix(prefix(hiera('rbls'), 'reject_rbl_client '), ',') + $mynetworks = join(hiera('mynetworks', ''), ' ') + $rbls = suffix(prefix(hiera('rbls', []), 'reject_rbl_client '), ',') $root_mail_recipient = hiera('contacts') $postfix_smtp_listen = 'all' @@ -21,16 +21,20 @@ class site_postfix::mx { postfix::config { 'mynetworks': value => "127.0.0.0/8 [::1]/128 [fe80::]/64 ${mynetworks}"; + # Note: mydestination should not include @domain, because this is + # used in virtual alias maps. 'mydestination': - value => "\$myorigin, localhost, localhost.\$mydomain, ${domain}"; + value => "\$myorigin, localhost, localhost.\$mydomain"; 'myhostname': value => $host_domain; 'mailbox_size_limit': value => '0'; 'home_mailbox': value => 'Maildir/'; + # Note: virtual-aliases map will take precedence over leap_mx + # lookup (tcp:localhost) 'virtual_alias_maps': - value => 'tcp:localhost:4242'; + value => 'hash:/etc/postfix/virtual-aliases tcp:localhost:4242'; 'luser_relay': value => 'vmail'; 'smtpd_tls_received_header': @@ -69,13 +73,13 @@ class site_postfix::mx { preseed => true, root_mail_recipient => $root_mail_recipient, smtp_listen => 'all', - default_alias_maps => false, mastercf_tail => "smtps inet n - - - - smtpd -o smtpd_tls_wrappermode=yes -o smtpd_tls_security_level=encrypt -o smtpd_recipient_restrictions=\$smtps_recipient_restrictions -o smtpd_helo_restrictions=\$smtps_helo_restrictions + -o smtpd_client_restrictions= -o cleanup_service_name=clean_smtps clean_smtps unix n - n - 0 cleanup -o header_checks=pcre:/etc/postfix/checks/rewrite_openpgp_headers", diff --git a/puppet/modules/site_postfix/manifests/mx/static_aliases.pp b/puppet/modules/site_postfix/manifests/mx/static_aliases.pp index 786d74c1..e9118470 100644 --- a/puppet/modules/site_postfix/manifests/mx/static_aliases.pp +++ b/puppet/modules/site_postfix/manifests/mx/static_aliases.pp @@ -30,29 +30,21 @@ class site_postfix::mx::static_aliases { } # - # Custom aliases. - # - # This does not use the puppet mailalias resource because we want to be able - # to guarantee the contents of the alias file. This is needed so if you - # remove an alias from the node's config, it will get removed from the alias - # file. - # - - # both alias files must be listed under "alias_database", because once you - # specify one, then `newaliases` no longer will default to updating - # "/etc/aliases.db". - postfix::config { - 'alias_database': - value => "/etc/aliases, /etc/postfix/custom-aliases"; - 'alias_maps': - value => "hash:/etc/aliases, hash:/etc/postfix/custom-aliases"; + # Custom static virtual aliases. + # + exec { 'postmap_virtual_aliases': + command => '/usr/sbin/postmap /etc/postfix/virtual-aliases', + refreshonly => true, + user => root, + group => root, + require => Package['postfix'], + subscribe => File['/etc/postfix/virtual-aliases'] } - - file { '/etc/postfix/custom-aliases': - content => template('site_postfix/custom-aliases.erb'), + file { '/etc/postfix/virtual-aliases': + content => template('site_postfix/virtual-aliases.erb'), owner => root, group => root, - mode => 0600, - notify => Exec['newaliases'] + mode => '0600', + require => Package['postfix'] } } diff --git a/puppet/modules/site_postfix/templates/custom-aliases.erb b/puppet/modules/site_postfix/templates/custom-aliases.erb deleted file mode 100644 index f261514b..00000000 --- a/puppet/modules/site_postfix/templates/custom-aliases.erb +++ /dev/null @@ -1,11 +0,0 @@ -# -# This file is managed by puppet. -# -# This is a map of custom, non-standard aliases. The contents of this file -# are derived from the node property `mx.aliases`. -# - -<%- @aliases.keys.sort.each do |from| -%> -"<%= from %>": "<%= [@aliases[from]].flatten.join('", "') %>" -<%- end -%> - diff --git a/puppet/modules/site_postfix/templates/virtual-aliases.erb b/puppet/modules/site_postfix/templates/virtual-aliases.erb new file mode 100644 index 00000000..c474e734 --- /dev/null +++ b/puppet/modules/site_postfix/templates/virtual-aliases.erb @@ -0,0 +1,22 @@ +# +# This file is managed by puppet. +# +# This is a map of custom, non-standard aliases. The contents of this file +# are derived from the node property `mx.aliases`. +# + +# +# enable these virtual domains: +# +<%= @domain %> enabled +<%- @aliases.keys.map {|addr| addr.split('@')[1] }.compact.sort.uniq.each do |virt_domain| -%> +<%= virt_domain %> enabled +<%- end %> + +# +# virtual aliases: +# +<%- @aliases.keys.sort.each do |from| -%> +<%- full_address = from =~ /@/ ? from : from + "@" + @domain -%> +<%= full_address %> <%= [@aliases[from]].flatten.map{|a| a =~ /@/ ? a : a + "@" + @domain}.join(', ') %> +<%- end -%> diff --git a/puppet/modules/site_sshd/manifests/init.pp b/puppet/modules/site_sshd/manifests/init.pp index 1da2f1d5..170be32c 100644 --- a/puppet/modules/site_sshd/manifests/init.pp +++ b/puppet/modules/site_sshd/manifests/init.pp @@ -1,6 +1,7 @@ class site_sshd { - $ssh = hiera_hash('ssh') - $hosts = hiera('hosts', '') + $ssh = hiera_hash('ssh') + $ssh_config = $ssh['config'] + $hosts = hiera('hosts', '') ## ## SETUP AUTHORIZED KEYS @@ -52,11 +53,12 @@ class site_sshd { ## SSHD SERVER CONFIGURATION ## class { '::sshd': - manage_nagios => false, - ports => [ $ssh['port'] ], - use_pam => 'yes', - hardened_ssl => 'yes', - print_motd => 'no', - manage_client => false + manage_nagios => false, + ports => [ $ssh['port'] ], + use_pam => 'yes', + hardened_ssl => 'yes', + print_motd => 'no', + tcp_forwarding => $ssh_config['AllowTcpForwarding'], + manage_client => false } } diff --git a/puppet/modules/site_webapp/templates/config.yml.erb b/puppet/modules/site_webapp/templates/config.yml.erb index e8853ade..5cb436fc 100644 --- a/puppet/modules/site_webapp/templates/config.yml.erb +++ b/puppet/modules/site_webapp/templates/config.yml.erb @@ -1,33 +1,34 @@ -<%- require 'json' -%> -<%- cert_options = @webapp['client_certificates'] -%> -production: - admins: <%= @webapp['admins'].inspect %> - default_locale: :<%= @webapp['default_locale'] %> - available_locales: -<%- @webapp['locales'].each do |locale| -%> - - :<%= locale %> -<%- end -%> - domain: <%= @provider_domain %> - force_ssl: <%= @webapp['secure'] %> - client_ca_key: <%= scope.lookupvar('x509::variables::keys') %>/<%= scope.lookupvar('site_config::params::client_ca_name') %>.key - client_ca_cert: <%= scope.lookupvar('x509::variables::local_CAs') %>/<%= scope.lookupvar('site_config::params::client_ca_name') %>.crt - secret_token: "<%= @secret_token %>" - client_cert_lifespan: <%= cert_options['life_span'] %> - client_cert_bit_size: <%= cert_options['bit_size'].to_i %> - client_cert_hash: <%= cert_options['digest'] %> - allow_limited_certs: <%= @webapp['allow_limited_certs'].inspect %> - allow_unlimited_certs: <%= @webapp['allow_unlimited_certs'].inspect %> - allow_anonymous_certs: <%= @webapp['allow_anonymous_certs'].inspect %> - limited_cert_prefix: "<%= cert_options['limited_prefix'] %>" - unlimited_cert_prefix: "<%= cert_options['unlimited_prefix'] %>" - minimum_client_version: "<%= @webapp['client_version']['min'] %>" - default_service_level: "<%= @webapp['default_service_level'] %>" - service_levels: <%= scope.function_sorted_json([@webapp['service_levels']]) %> - allow_registration: <%= @webapp['allow_registration'].inspect %> - handle_blacklist: <%= @webapp['forbidden_usernames'].inspect %> -<%- if @webapp['engines'] && @webapp['engines'].any? -%> - engines: -<%- @webapp['engines'].each do |engine| -%> - - <%= engine %> -<%- end -%> -<%- end -%> +<%- +cert_options = @webapp['client_certificates'] +production = { + "admins" => @webapp['admins'], + "default_locale" => @webapp['default_locale'], + "available_locales" => @webapp['locales'], + "domain" => @provider_domain, + "force_ssl" => @webapp['secure'], + "client_ca_key" => "%s/%s.key" % [scope.lookupvar('x509::variables::keys'), scope.lookupvar('site_config::params::client_ca_name')], + "client_ca_cert" => "%s/%s.crt" % [scope.lookupvar('x509::variables::local_CAs'), scope.lookupvar('site_config::params::client_ca_name')], + "secret_token" => @secret_token, + "client_cert_lifespan" => cert_options['life_span'], + "client_cert_bit_size" => cert_options['bit_size'].to_i, + "client_cert_hash" => cert_options['digest'], + "allow_limited_certs" => @webapp['allow_limited_certs'], + "allow_unlimited_certs" => @webapp['allow_unlimited_certs'], + "allow_anonymous_certs" => @webapp['allow_anonymous_certs'], + "limited_cert_prefix" => cert_options['limited_prefix'], + "unlimited_cert_prefix" => cert_options['unlimited_prefix'], + "minimum_client_version" => @webapp['client_version']['min'], + "default_service_level" => @webapp['default_service_level'], + "service_levels" => @webapp['service_levels'], + "allow_registration" => @webapp['allow_registration'], + "handle_blacklist" => @webapp['forbidden_usernames'] +} + +if @webapp['engines'] && @webapp['engines'].any? + production["engines"] = @webapp['engines'] +end +-%> +# +# This file is generated by puppet. This file inherits from defaults.yml. +# +<%= scope.function_sorted_yaml({"production" => production}) %> diff --git a/vagrant/configure-leap.sh b/vagrant/configure-leap.sh index 9541e194..332bdddf 100755 --- a/vagrant/configure-leap.sh +++ b/vagrant/configure-leap.sh @@ -1,13 +1,15 @@ #!/bin/bash -. /vagrant/vagrant/vagrant.config +. /vagrant/vagrant/vagrant.config #OPTS='--no-color' OPTS='' -PROVIDERDIR='/srv/leap/configuration' +USER='vagrant' NODE='node1' -LEAP='/usr/local/bin/leap' +SUDO="sudo -u ${USER}" +PROVIDERDIR="/home/${USER}/leap/configuration" +LEAP="$SUDO /usr/local/bin/leap" echo '===============================================' echo 'configuring leap' @@ -15,19 +17,22 @@ echo '===============================================' # purge $PROVIDERDIR so this script can be run multiple times [ -e $PROVIDERDIR ] && rm -rf $PROVIDERDIR -mkdir $PROVIDERDIR + +mkdir -p $PROVIDERDIR +chown ${USER}:${USER} ${PROVIDERDIR} cd $PROVIDERDIR $LEAP $OPTS new --contacts "$contacts" --domain "$provider_domain" --name "$provider_name" --platform=/vagrant . -echo -e '\n@log = "/var/log/leap/deploy.log"' >> Leapfile +$SUDO echo -e '\n@log = "/var/log/leap/deploy.log"' >> Leapfile -if [ ! -e /root/.ssh/id_rsa ]; then - ssh-keygen -f /root/.ssh/id_rsa -P '' - cat /root/.ssh/id_rsa.pub >> /root/.ssh/authorized_keys +if [ ! -e /home/${USER}/.ssh/id_rsa ]; then + $SUDO ssh-keygen -f /home/${USER}/.ssh/id_rsa -P '' + cat /home/${USER}/.ssh/id_rsa.pub >> /root/.ssh/authorized_keys fi -mkdir -p $PROVIDERDIR/files/nodes/$NODE +$SUDO mkdir -p ${PROVIDERDIR}/files/nodes/${NODE} sh -c "cat /etc/ssh/ssh_host_rsa_key.pub | cut -d' ' -f1,2 >> $PROVIDERDIR/files/nodes/$NODE/${NODE}_ssh.pub" +chown ${USER}:${USER} ${PROVIDERDIR}/files/nodes/${NODE}/${NODE}_ssh.pub $LEAP $OPTS add-user --self $LEAP $OPTS cert ca @@ -41,17 +46,13 @@ git init git add . git commit -m'configured provider' -$LEAP $OPTS node init $NODE +$LEAP $OPTS node init $NODE if [ $? -eq 1 ]; then echo 'node init failed' exit 1 fi $LEAP $OPTS -v 2 deploy -if [ $? -eq 1 ]; then - echo 'deploy failed' - exit 1 -fi set +e git add . @@ -69,9 +70,6 @@ echo 'setting node to demo-mode' echo '===============================================' postconf -e default_transport='error: in demo mode' -sed -i 's/PasswordAuthentication no/PasswordAuthentication yes/g' /etc/ssh/sshd_config -/etc/init.d/ssh reload - # add users: testadmin and testuser with passwords "hallo123" curl -s -k https://localhost/1/users.json -d "user%5Blogin%5D=testuser&user%5Bpassword_salt%5D=7d4880237a038e0e&user%5Bpassword_verifier%5D=b98dc393afcd16e5a40fb57ce9cddfa6a978b84be326196627c111d426cada898cdaf3a6427e98b27daf4b0ed61d278bc856515aeceb2312e50c8f816659fcaa4460d839a1e2d7ffb867d32ac869962061368141c7571a53443d58dc84ca1fca34776894414c1090a93e296db6cef12c2cc3f7a991b05d49728ed358fd868286" curl -s -k https://localhost/1/users.json -d "user%5Blogin%5D=testadmin&user%5Bpassword_salt%5D=ece1c457014d8282&user%5Bpassword_verifier%5D=9654d93ab409edf4ff1543d07e08f321107c3fd00de05c646c637866a94f28b3eb263ea9129dacebb7291b3374cc6f0bf88eb3d231eb3a76eed330a0e8fd2a5c477ed2693694efc1cc23ae83c2ae351a21139701983dd595b6c3225a1bebd2a4e6122f83df87606f1a41152d9890e5a11ac3749b3bfcf4407fc83ef60b4ced68" @@ -80,4 +78,3 @@ echo -e '\n\n\n' echo 'You are now ready to use your provider. Please update your /etc/hosts with following dns overrides:' $LEAP list --print ip_address,domain.full,dns.aliases | sed 's/,//g' | cut -d' ' -f 2- - diff --git a/vagrant/install-platform.pp b/vagrant/install-platform.pp index 465ca78a..5ea834b1 100755 --- a/vagrant/install-platform.pp +++ b/vagrant/install-platform.pp @@ -3,34 +3,22 @@ File['/etc/apt/preferences'] -> Exec['refresh_apt'] -> Package <| ( title != 'lsb' ) |> -package { [ 'rsync', 'ruby-hiera-puppet', 'git', 'ruby1.9.1-dev', 'rake', 'jq' ]: - ensure => installed -} - -file { '/etc/gemrc': - content => "---\n:sources:\n - https://rubygems.org/" -} -vcsrepo { '/srv/leap/leap_cli': - ensure => present, - force => true, - revision => 'develop', - provider => 'git', - source => 'https://leap.se/git/leap_cli.git', - owner => 'root', - group => 'root', - notify => Exec['install_leap_cli'], - require => Package['git'] +if $::lsbdistcodename == 'wheezy' { + package { 'ruby-hiera-puppet': + ensure => installed + } } -exec { 'install_leap_cli': - command => '/usr/bin/rake build && /usr/bin/rake install', - cwd => '/srv/leap/leap_cli', - refreshonly => true, - require => [ Package['ruby1.9.1-dev'], File['/etc/gemrc'], Package['rake'] ] +# install leap_cli from source, so it will work with the develop +# branch of leap_platform +class { '::leap::cli::install': + source => true, } file { [ '/srv/leap', '/srv/leap/configuration', '/var/log/leap' ]: ensure => directory } +# install prerequisites for configuring the provider +include ::git |