diff options
38 files changed, 362 insertions, 395 deletions
| diff --git a/Vagrantfile b/Vagrantfile index c9c68284..ba5451aa 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -9,6 +9,11 @@ Vagrant.configure("2") do |vagrant_config|      config.vm.box = "LEAP/wheezy"      #config.vm.network :private_network, ip: "10.5.5.102" + +    # forward leap_web ports +    config.vm.network "forwarded_port", guest: 80,  host:8080 +    config.vm.network "forwarded_port", guest: 443, host:4443 +      config.vm.provider "virtualbox" do |v|        v.memory = 1024        v.customize ["modifyvm", :id, "--natdnshostresolver1", "on"] diff --git a/lib/leap_cli/commands/compile.rb b/lib/leap_cli/commands/compile.rb index 8f6c7769..c388e5c3 100644 --- a/lib/leap_cli/commands/compile.rb +++ b/lib/leap_cli/commands/compile.rb @@ -265,56 +265,86 @@ 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 +      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, provider).length].max } -      put_line = lambda do |host, line| -        host = '@' if host == '' -        f.puts("%-#{max_width}s %s" % [host, line]) -      end +      lines      = [] + +      # +      # header +      # +      lines << ZONE_HEADER % {:domain => provider.domain, :ns => provider.domain, :contact => provider.contacts.default.first.sub('@','.')} -      f.puts ORIGIN_HEADER +      # +      # common records +      # +      lines << ORIGIN_HEADER        # 'A' records for primary domain        manager.nodes[:environment => '!local'].each_node do |node|          if node.dns['aliases'] && node.dns.aliases.include?(provider.domain) -          put_line.call "", "IN A      #{node.ip_address}" +          lines << ["@", "IN A      #{node.ip_address}"]          end        end -        # NS records        if provider['dns'] && provider.dns['nameservers']          provider.dns.nameservers.each do |ns| -          put_line.call "", "IN NS #{ns}." +          lines << ["@", "IN NS #{ns}."]          end        end -      # all other records +      # environment records        manager.environment_names.each do |env|          next if env == 'local'          nodes = manager.nodes[:environment => env]          next unless nodes.any? -        f.puts ENV_HEADER % (env.nil? ? 'default' : env) +        spf = nil +        lines << ENV_HEADER % (env.nil? ? 'default' : env)          nodes.each_node do |node|            if node.dns.public -            hostname = relative_hostname(node.domain.full, provider) -            put_line.call relative_hostname(node.domain.full, provider), "IN A      #{node.ip_address}" +            lines << [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, provider), "IN A      #{node.ip_address}" +                lines << [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, provider), "IN MX 10  #{relative_hostname(node.domain.full, provider)}" +            mx_domain = relative_hostname(node.domain.full_suffix, provider) +            lines << [mx_domain, "IN MX 10  #{relative_hostname(node.domain.full, provider)}"] +            spf ||= [mx_domain, spf_record(node)]            end          end +        lines << spf if spf +      end + +      # print the lines +      max_width = lines.inject(0) {|max, line| line.is_a?(Array) ? [max, line[0].length].max : max} +      lines.each do |host, line| +        if line.nil? +          puts(host) +        else +          host = '@' if host == '' +          puts("%-#{max_width}s %s" % [host, line]) +        end        end      end +    # +    # allow mail from any mx node, plus the webapp nodes. +    # +    # TODO: ipv6 +    # +    def spf_record(node) +      ips = node.nodes_like_me['services' => 'webapp'].values.collect {|n| +        "ip4:" + n.ip_address +      } +      # TXT strings may not be longer than 255 characters, although +      # you can chain multiple strings together. +      strings = "v=spf1 MX #{ips.join(' ')} -all".scan(/.{1,255}/).join('" "') +      %(IN TXT    "#{strings}") +    end +      ENV_HEADER = %[  ;;  ;; ENVIRONMENT %s diff --git a/lib/leap_cli/commands/db.rb b/lib/leap_cli/commands/db.rb index e4fd3858..5703e4bd 100644 --- a/lib/leap_cli/commands/db.rb +++ b/lib/leap_cli/commands/db.rb @@ -40,7 +40,6 @@ module LeapCli; module Commands    def destroy_all_dbs(nodes)      ssh_connect(nodes) do |ssh|        ssh.run('/etc/init.d/bigcouch stop && test ! -z "$(ls /opt/bigcouch/var/lib/ 2> /dev/null)" && rm -r /opt/bigcouch/var/lib/* && echo "db destroyed" || echo "db already destroyed"') -      ssh.run('grep ^seq_dir /etc/leap/tapicero.yaml | cut -f2 -d\" | xargs rm -rv')      end    end diff --git a/lib/leap_cli/macros/stunnel.rb b/lib/leap_cli/macros/stunnel.rb index f16308c7..821bda38 100644 --- a/lib/leap_cli/macros/stunnel.rb +++ b/lib/leap_cli/macros/stunnel.rb @@ -49,12 +49,14 @@ module LeapCli        result = Config::ObjectList.new        node_list.each_node do |node|          if node.name != self.name || options[:include_self] +          s_port = stunnel_port(port)            result["#{node.name}_#{port}"] = Config::Object[              'accept_port', @next_stunnel_port,              'connect', node.domain.internal, -            'connect_port', stunnel_port(port), +            'connect_port', s_port,              'original_port', port            ] +          manager.connections.add(:from => @node.ip_address, :to => node.ip_address, :port => s_port)            @next_stunnel_port += 1          end        end @@ -76,6 +78,15 @@ module LeapCli        }      end +    # +    # lists the ips that connect to this node, on particular ports. +    # +    def stunnel_firewall +      manager.connections.select {|connection| +        connection['to'] == @node.ip_address +      } +    end +      private      # diff --git a/provider_base/common.json b/provider_base/common.json index e968dd27..5821789b 100644 --- a/provider_base/common.json +++ b/provider_base/common.json @@ -50,6 +50,14 @@      "clients": {},      "servers": {}    }, +  "firewall": { +    "ssh": { +      "from": "sysadmin", +      "to": "= ip_address", +      "port": "= ssh.port" +    }, +    "stunnel": "=> stunnel_firewall" +  },    "platform": {      "version": "= Leap::Platform.version.to_s",      "major_version": "= Leap::Platform.major_version" @@ -75,11 +83,6 @@        "package": "soledad-server",        "revision": "latest"      }, -    "tapicero": { -      "type": "git", -      "source": "https://leap.se/git/tapicero", -      "revision": "origin/version/0.7" -    },      "webapp": {        "type": "git",        "source": "https://leap.se/git/leap_web", diff --git a/provider_base/services/couchdb.json b/provider_base/services/couchdb.json index 8b1386f8..5e65b2ec 100644 --- a/provider_base/services/couchdb.json +++ b/provider_base/services/couchdb.json @@ -31,11 +31,6 @@                  "password": "= secret :couch_soledad_password",                  "salt": "= hex_secret :couch_soledad_password_salt, 128"              }, -            "tapicero": { -                "username": "tapicero", -                "password": "= secret :couch_tapicero_password", -                "salt": "= hex_secret :couch_tapicero_password_salt, 128" -            },              "webapp": {                  "username": "webapp",                  "password": "= secret :couch_webapp_password", diff --git a/provider_base/services/dns.json b/provider_base/services/dns.json index 677d9b2c..67948ef8 100644 --- a/provider_base/services/dns.json +++ b/provider_base/services/dns.json @@ -3,5 +3,12 @@      "public":  "= nodes['dns.public' => true].fields('domain.name', 'dns.aliases', 'ip_address')",      "private": "= nodes['dns.public' => false].fields('domain.name', 'dns.aliases', 'ip_address')"    }, -  "service_type": "public_service" +  "service_type": "public_service", +  "firewall": { +    "dns": { +      "from": "*", +      "to": "= ip_address", +      "port": "53" +    } +  }  }
\ No newline at end of file diff --git a/provider_base/services/monitor.json b/provider_base/services/monitor.json index 10d5ac81..28fb837c 100644 --- a/provider_base/services/monitor.json +++ b/provider_base/services/monitor.json @@ -18,5 +18,12 @@      "ca_cert": "= file :ca_cert, :missing => 'provider CA. Run `leap cert ca`'",      "client_ca_cert": "= file :client_ca_cert, :missing => 'Certificate Authority. Run `leap cert ca`'",      "client_ca_key": "= file :client_ca_key, :missing => 'Certificate Authority. Run `leap cert ca`'" +  }, +  "firewall": { +    "monitor": { +      "from": "sysadmin", +      "to": "= ip_address", +      "port": [443, 80] +    }    }  } diff --git a/provider_base/services/mx.json b/provider_base/services/mx.json index 4d1b3dad..d6e9fff9 100644 --- a/provider_base/services/mx.json +++ b/provider_base/services/mx.json @@ -31,5 +31,12 @@      "client_ca_cert": "= file :client_ca_cert, :missing => 'Certificate Authority. Run `leap cert ca`'",      "client_ca_key": "= file :client_ca_key, :missing => 'Certificate Authority. Run `leap cert ca`'"    }, -  "service_type": "user_service" +  "service_type": "user_service", +  "firewall": { +    "mx": { +      "from": "*", +      "to": "= ip_address", +      "port": [25, 465] +    } +  }  } diff --git a/provider_base/services/openvpn.json b/provider_base/services/openvpn.json index 11cb0dc2..6f73e31c 100644 --- a/provider_base/services/openvpn.json +++ b/provider_base/services/openvpn.json @@ -34,5 +34,12 @@        "port" : "= rand_range('scramblesuit_port_'+name, 18000..32000)"      },      "gateway_address": "= openvpn.gateway_address" +  }, +  "firewall": { +    "vpn": { +      "from": "*", +      "to": "= openvpn.gateway_address", +      "port": "= openvpn.ports + [obfsproxy.scramblesuit.port]" +    }    }  } diff --git a/provider_base/services/soledad.json b/provider_base/services/soledad.json index ed6fbc9f..76f7155f 100644 --- a/provider_base/services/soledad.json +++ b/provider_base/services/soledad.json @@ -8,5 +8,12 @@        "salt": "= hex_secret :couch_soledad_password_salt, 128"      }    }, -  "service_type": "public_service" +  "service_type": "public_service", +  "firewall": { +    "soledad": { +      "from": "*", +      "to": "= ip_address", +      "port": "= soledad.port" +    } +  }  } diff --git a/provider_base/services/static.json b/provider_base/services/static.json index d9f52b36..2f408ec1 100644 --- a/provider_base/services/static.json +++ b/provider_base/services/static.json @@ -9,5 +9,12 @@        "client_version": "= static.bootstrap_files.enabled ? provider.client_version : nil"      }    }, -  "service_type": "public_service" +  "service_type": "public_service", +  "firewall": { +    "static": { +      "from": "*", +      "to": "= ip_address", +      "port": [80, 443] +    } +  }  }
\ No newline at end of file diff --git a/provider_base/services/webapp.json b/provider_base/services/webapp.json index 039b1c0b..9e3d751b 100644 --- a/provider_base/services/webapp.json +++ b/provider_base/services/webapp.json @@ -76,5 +76,12 @@      "ca_cert": "= file :ca_cert, :missing => 'provider CA. Run `leap cert ca`'",      "client_ca_cert": "= file :client_ca_cert, :missing => 'Certificate Authority. Run `leap cert ca`.'",      "client_ca_key": "= file :client_ca_key, :missing => 'Certificate Authority. Run `leap cert ca`.'" +  }, +  "firewall": { +    "webapp": { +      "from": "*", +      "to": "= ip_address", +      "port": "= [api.port, 443, 80, nickserver.port]" +    }    }  } diff --git a/puppet/manifests/site.pp b/puppet/manifests/site.pp index 912234ac..91dd2d3c 100644 --- a/puppet/manifests/site.pp +++ b/puppet/manifests/site.pp @@ -20,7 +20,6 @@ if member($services, 'openvpn') {  if member($services, 'couchdb') {    include site_couchdb -  include tapicero  }  if member($services, 'webapp') { diff --git a/puppet/modules/site_check_mk/files/agent/logwatch/bigcouch.cfg b/puppet/modules/site_check_mk/files/agent/logwatch/bigcouch.cfg index 95ddd2ca..0f378a5a 100644 --- a/puppet/modules/site_check_mk/files/agent/logwatch/bigcouch.cfg +++ b/puppet/modules/site_check_mk/files/agent/logwatch/bigcouch.cfg @@ -6,7 +6,7 @@   I 127.0.0.1 localhost:5984 .* ok   # https://leap.se/code/issues/5246   I Shutting down group server - # ignore bigcouch conflict errors, mainly coming from tapicero creating new users + # ignore bigcouch conflict errors   I Error in process.*{{nocatch,conflict}   # ignore "Uncaught error in HTTP request: {exit, normal}" error   # it's suppressed in later versions of bigcouch anhow diff --git a/puppet/modules/site_check_mk/files/agent/logwatch/tapicero.cfg b/puppet/modules/site_check_mk/files/agent/logwatch/tapicero.cfg deleted file mode 100644 index d98f5094..00000000 --- a/puppet/modules/site_check_mk/files/agent/logwatch/tapicero.cfg +++ /dev/null @@ -1,11 +0,0 @@ -/var/log/leap/tapicero.log -# Ignore transient Tapicero errors when creating a db (#6511) - I tapicero.*(Creating database|Checking security of|Writing security to|Uploading design doc to) user-.* failed (\(trying again soon\)|(twice )?due to): (RestClient::ResourceNotFound|RestClient::InternalServerError): (404 Resource Not Found|500 Internal Server Error) - C tapicero.*RestClient::InternalServerError: -# possible race condition between multiple tapicero -# instances, so we ignore it -# see https://leap.se/code/issues/5168 - I tapicero.*RestClient::PreconditionFailed: - C tapicero.*Creating database.*failed due to: - C tapicero.*failed - W tapicero.*Couch stream ended unexpectedly. diff --git a/puppet/modules/site_check_mk/manifests/agent/tapicero.pp b/puppet/modules/site_check_mk/manifests/agent/tapicero.pp deleted file mode 100644 index 8505b34a..00000000 --- a/puppet/modules/site_check_mk/manifests/agent/tapicero.pp +++ /dev/null @@ -1,26 +0,0 @@ -# sets up tapicero monitoring -class site_check_mk::agent::tapicero { - -  include ::site_nagios::plugins - -  # watch logs -  file { '/etc/check_mk/logwatch.d/tapicero.cfg': -    source => 'puppet:///modules/site_check_mk/agent/logwatch/tapicero.cfg', -  } - -  # local nagios plugin checks via mrpe -  augeas { -    'Tapicero_Procs': -      incl    => '/etc/check_mk/mrpe.cfg', -      lens    => 'Spacevars.lns', -      changes => [ -        'rm /files/etc/check_mk/mrpe.cfg/Tapicero_Procs', -        "set Tapicero_Procs \"/usr/lib/nagios/plugins/check_procs -w 1:1 -c 1:1 --ereg-argument-array='^tapicero$'\"" ], -      require => File['/etc/check_mk/mrpe.cfg']; -    'Tapicero_Heartbeat': -      incl    => '/etc/check_mk/mrpe.cfg', -      lens    => 'Spacevars.lns', -      changes => 'set Tapicero_Heartbeat \'/usr/local/lib/nagios/plugins/check_last_regex_in_log -f /var/log/leap/tapicero.log -r "tapicero" -w 1200 -c 2400\'', -      require => File['/etc/check_mk/mrpe.cfg']; -  } -} diff --git a/puppet/modules/site_config/manifests/default.pp b/puppet/modules/site_config/manifests/default.pp index e69e4b7b..6b10dc19 100644 --- a/puppet/modules/site_config/manifests/default.pp +++ b/puppet/modules/site_config/manifests/default.pp @@ -1,3 +1,4 @@ +# common things to set up on every node  class site_config::default {    tag 'leap_base' @@ -29,7 +30,7 @@ class site_config::default {    # i.e. openstack/aws nodes, vagrant nodes    # fix dhclient from changing resolver information -   if $::dhcp_enabled == 'true' { +  if $::dhcp_enabled == 'true' {      include site_config::dhclient    } @@ -58,7 +59,9 @@ class site_config::default {    # set up core leap files and directories    include site_config::files -  include site_config::remove_files + +  # remove leftovers from previous deploys +  include site_config::remove    if ! member($services, 'mx') {      include site_postfix::satellite diff --git a/puppet/modules/site_config/manifests/remove.pp b/puppet/modules/site_config/manifests/remove.pp new file mode 100644 index 00000000..00502c0a --- /dev/null +++ b/puppet/modules/site_config/manifests/remove.pp @@ -0,0 +1,5 @@ +# remove leftovers from previous deploys +class site_config::remove { +  include site_config::remove::files +  include site_config::remove::tapicero +} diff --git a/puppet/modules/site_config/manifests/remove_files.pp b/puppet/modules/site_config/manifests/remove/files.pp index 51d1ea88..66647d31 100644 --- a/puppet/modules/site_config/manifests/remove_files.pp +++ b/puppet/modules/site_config/manifests/remove/files.pp @@ -9,7 +9,17 @@  # release.  # -class site_config::remove_files { +class site_config::remove::files { + +  # +  # Platform 0.8 removals +  # + +  tidy { +    '/etc/apache/sites-enabled/leap_webapp.conf': +      notify => Service['apache']; +  } +    #    # Platform 0.7 removals @@ -27,14 +37,11 @@ class site_config::remove_files {        path => '/var/log/',        recurse => true,        matches => 'leap_mx*'; -    'leap_mx_rotate': -      path => '/var/log/leap/', -      recurse => true, -      matches => [ 'mx.log.[0-9]', 'mx.log.[0-9]?', 'mx.log.[6-9]?gz'];      '/srv/leap/webapp/public/provider.json':;      '/srv/leap/couchdb/designs/tmp_users':        recurse => true,        rmdirs => true; +    '/etc/leap/soledad-server.conf':;    }    if member($::services, 'webapp') { diff --git a/puppet/modules/site_config/manifests/remove/tapicero.pp b/puppet/modules/site_config/manifests/remove/tapicero.pp new file mode 100644 index 00000000..497cf8b2 --- /dev/null +++ b/puppet/modules/site_config/manifests/remove/tapicero.pp @@ -0,0 +1,61 @@ +# remove tapicero leftovers from previous deploys +class site_config::remove::tapicero { + +  exec { 'kill_tapicero': +    onlyif  => '/usr/bin/test -s /var/run/tapicero.pid', +    command => '/usr/bin/pkill --pidfile /var/run/tapicero.pid' +  } + +  user { 'tapicero': +    ensure  => absent; +  } + +  group { 'tapicero': +    ensure => absent, +    require => User['tapicero']; +  } + +  tidy { +    '/srv/leap/tapicero': +      recurse => true, +      require   => [ Exec['kill_tapicero'] ]; +    '/var/lib/leap/tapicero': +      require   => [ Exec['kill_tapicero'] ]; +    '/var/run/tapicero': +      require   => [ Exec['kill_tapicero'] ]; +    '/etc/leap/tapicero.yaml': +      require   => [ Exec['kill_tapicero'] ]; +    '/etc/init.d/tapicero': +      require   => [ Exec['kill_tapicero'] ]; +    'tapicero_logs': +      path    => '/var/log/leap', +      recurse => true, +      matches => 'tapicero*', +      require   => [ Exec['kill_tapicero'] ]; +    '/etc/check_mk/logwatch.d/tapicero.cfg': +      notify => Exec['check_mk-refresh']; +    'checkmk_logwatch_spool': +      path    => '/var/lib/check_mk/logwatch', +      recurse => true, +      matches => '*tapicero.log', +      require => Exec['kill_tapicero'], +      notify  => Exec['check_mk-refresh']; +  } + +  # remove local nagios plugin checks via mrpe +  augeas { +    'Tapicero_Procs': +      incl    => '/etc/check_mk/mrpe.cfg', +      lens    => 'Spacevars.lns', +      changes => 'rm /files/etc/check_mk/mrpe.cfg/Tapicero_Procs', +      require => File['/etc/check_mk/mrpe.cfg'], +      notify  => Exec['check_mk-refresh']; +    'Tapicero_Heartbeat': +      incl    => '/etc/check_mk/mrpe.cfg', +      lens    => 'Spacevars.lns', +      changes => 'rm Tapicero_Heartbeat', +      require => File['/etc/check_mk/mrpe.cfg'], +      notify  => Exec['check_mk-refresh']; +  } + +} diff --git a/puppet/modules/site_couchdb/files/designs/invite_codes/InviteCode.json b/puppet/modules/site_couchdb/files/designs/invite_codes/InviteCode.json new file mode 100644 index 00000000..006c1ea1 --- /dev/null +++ b/puppet/modules/site_couchdb/files/designs/invite_codes/InviteCode.json @@ -0,0 +1,22 @@ +{ +   "_id": "_design/InviteCode", +   "language": "javascript", +   "views": { +       "by__id": { +           "map": "                function(doc) {\n                  if ((doc['type'] == 'InviteCode') && (doc['_id'] != null)) {\n                    emit(doc['_id'], 1);\n                  }\n                }\n", +           "reduce": "_sum" +       }, +       "by_invite_code": { +           "map": "                function(doc) {\n                  if ((doc['type'] == 'InviteCode') && (doc['invite_code'] != null)) {\n                    emit(doc['invite_code'], 1);\n                  }\n                }\n", +           "reduce": "_sum" +       }, +       "by_invite_count": { +           "map": "                function(doc) {\n                  if ((doc['type'] == 'InviteCode') && (doc['invite_count'] != null)) {\n                    emit(doc['invite_count'], 1);\n                  }\n                }\n", +           "reduce": "_sum" +       }, +       "all": { +           "map": "                function(doc) {\n                  if (doc['type'] == 'InviteCode') {\n                    emit(doc._id, null);\n                  }\n                }\n" +       } +   }, +   "couchrest-hash": "83fb8f504520b4a9c7ddbb7928cd0ce3" +}
\ No newline at end of file diff --git a/puppet/modules/site_couchdb/manifests/add_users.pp b/puppet/modules/site_couchdb/manifests/add_users.pp index 2f734ed4..c905316b 100644 --- a/puppet/modules/site_couchdb/manifests/add_users.pp +++ b/puppet/modules/site_couchdb/manifests/add_users.pp @@ -1,3 +1,4 @@ +# add couchdb users for all services  class site_couchdb::add_users {    Class['site_couchdb::create_dbs'] @@ -35,16 +36,6 @@ class site_couchdb::add_users {      require => Couchdb::Query::Setup['localhost']    } -  ### tapicero couchdb user -  ### admin: needs to be able to create user-<uuid> databases -  ### read: users -  couchdb::add_user { $site_couchdb::couchdb_tapicero_user: -    roles   => '["users"]', -    pw      => $site_couchdb::couchdb_tapicero_pw, -    salt    => $site_couchdb::couchdb_tapicero_salt, -    require => Couchdb::Query::Setup['localhost'] -  } -    ## webapp couchdb user    ## read/write: users, tokens, sessions, tickets, identities, customer    couchdb::add_user { $site_couchdb::couchdb_webapp_user: diff --git a/puppet/modules/site_couchdb/manifests/create_dbs.pp b/puppet/modules/site_couchdb/manifests/create_dbs.pp index eea4bbf5..a2d1c655 100644 --- a/puppet/modules/site_couchdb/manifests/create_dbs.pp +++ b/puppet/modules/site_couchdb/manifests/create_dbs.pp @@ -90,4 +90,13 @@ class site_couchdb::create_dbs {      members => "{ \"names\": [\"${site_couchdb::couchdb_webapp_user}\"], \"roles\": [\"replication\"] }",      require => Couchdb::Query::Setup['localhost']    } + +  ## invite_codes db +  ## store invite codes for new signups +  ## r/w: webapp +  couchdb::create_db { 'invite_codes': +    members => "{ \"names\": [\"${site_couchdb::couchdb_webapp_user}\"], \"roles\": [\"replication\"] }", +    require => Couchdb::Query::Setup['localhost'] +  } +  } diff --git a/puppet/modules/site_couchdb/manifests/designs.pp b/puppet/modules/site_couchdb/manifests/designs.pp index 1ab1c6a1..e5fd94c6 100644 --- a/puppet/modules/site_couchdb/manifests/designs.pp +++ b/puppet/modules/site_couchdb/manifests/designs.pp @@ -12,12 +12,13 @@ class site_couchdb::designs {    }    site_couchdb::upload_design { -    'customers':   design => 'customers/Customer.json'; -    'identities':  design => 'identities/Identity.json'; -    'tickets':     design => 'tickets/Ticket.json'; -    'messages':    design => 'messages/Message.json'; -    'users':       design => 'users/User.json'; -    'tmp_users':   design => 'users/User.json'; +    'customers':    design => 'customers/Customer.json'; +    'identities':   design => 'identities/Identity.json'; +    'tickets':      design => 'tickets/Ticket.json'; +    'messages':     design => 'messages/Message.json'; +    'users':        design => 'users/User.json'; +    'tmp_users':    design => 'users/User.json'; +    'invite_codes': design => 'invite_codes/InviteCode.json';      'shared_docs':        db => 'shared',        design => 'shared/docs.json'; diff --git a/puppet/modules/site_couchdb/manifests/init.pp b/puppet/modules/site_couchdb/manifests/init.pp index 6b6ddd3a..1ec15f00 100644 --- a/puppet/modules/site_couchdb/manifests/init.pp +++ b/puppet/modules/site_couchdb/manifests/init.pp @@ -26,11 +26,6 @@ class site_couchdb {    $couchdb_soledad_pw       = $couchdb_soledad['password']    $couchdb_soledad_salt     = $couchdb_soledad['salt'] -  $couchdb_tapicero         = $couchdb_users['tapicero'] -  $couchdb_tapicero_user    = $couchdb_tapicero['username'] -  $couchdb_tapicero_pw      = $couchdb_tapicero['password'] -  $couchdb_tapicero_salt    = $couchdb_tapicero['salt'] -    $couchdb_webapp           = $couchdb_users['webapp']    $couchdb_webapp_user      = $couchdb_webapp['username']    $couchdb_webapp_pw        = $couchdb_webapp['password'] @@ -66,6 +61,5 @@ class site_couchdb {    if $couchdb_backup   { include site_couchdb::backup }    include site_check_mk::agent::couchdb -  include site_check_mk::agent::tapicero  } diff --git a/puppet/modules/site_couchdb/manifests/setup.pp b/puppet/modules/site_couchdb/manifests/setup.pp index 69bd1c6a..fef48505 100644 --- a/puppet/modules/site_couchdb/manifests/setup.pp +++ b/puppet/modules/site_couchdb/manifests/setup.pp @@ -12,27 +12,40 @@ class site_couchdb::setup {    $user = $site_couchdb::couchdb_admin_user -  # /etc/couchdb/couchdb-admin.netrc is deployed by couchdb::query::setup -  # we symlink to couchdb.netrc for puppet commands. -  # we symlink this to /root/.netrc for couchdb_scripts (eg. backup) -  # and makes life easier for the admin (i.e. using curl/wget without -  # passing credentials) +  # setup /etc/couchdb/couchdb-admin.netrc for couchdb admin access +  couchdb::query::setup { 'localhost': +    user => $user, +    pw   => $site_couchdb::couchdb_admin_pw +  } + +  # We symlink /etc/couchdb/couchdb-admin.netrc to /etc/couchdb/couchdb.netrc +  # for puppet commands, and to to /root/.netrc for couchdb_scripts +  # (eg. backup) and to makes life easier for the admin on the command line +  # (i.e. using curl/wget without passing credentials)    file {      '/etc/couchdb/couchdb.netrc':        ensure  => link,        target  => "/etc/couchdb/couchdb-${user}.netrc"; -      '/root/.netrc':        ensure  => link,        target  => '/etc/couchdb/couchdb.netrc'; +  } -    '/srv/leap/couchdb': -      ensure => directory +  # setup /etc/couchdb/couchdb-soledad-admin.netrc file for couchdb admin +  # access, accessible only for the soledad-admin user to create soledad +  # userdbs +  file { '/etc/couchdb/couchdb-soledad-admin.netrc': +    content => "machine localhost login ${user} password ${site_couchdb::couchdb_admin_pw}", +    mode    => '0400', +    owner   => 'soledad-admin', +    group   => 'root', +    require => [ Package['couchdb'], User['soledad-admin'] ];    } -  couchdb::query::setup { 'localhost': -    user  => $user, -    pw    => $site_couchdb::couchdb_admin_pw, +  # Checkout couchdb_scripts repo +  file { +    '/srv/leap/couchdb': +      ensure => directory    }    vcsrepo { '/srv/leap/couchdb/scripts': diff --git a/puppet/modules/site_postfix/manifests/mx/static_aliases.pp b/puppet/modules/site_postfix/manifests/mx/static_aliases.pp index e9118470..71c0555a 100644 --- a/puppet/modules/site_postfix/manifests/mx/static_aliases.pp +++ b/puppet/modules/site_postfix/manifests/mx/static_aliases.pp @@ -1,37 +1,75 @@  #  # Defines static, hard coded aliases that are not in the database. +# These aliases take precedence over the database aliases. +# +# There are three classes of reserved names: +# +# (1) forbidden_usernames: +#     Some usernames are forbidden and cannot be registered. +#     this is defined in node property webapp.forbidden_usernames +#     This is enforced by the webapp. +# +# (2) public aliases: +#     Some aliases for root, and are publicly exposed so that anyone +#     can deliver mail to them. For example, postmaster. +#     These are implemented in the virtual alias map, which takes +#     precedence over the local alias map. +# +# (3) local aliases: +#     Some aliases are only available locally: mail can be delivered +#     to the alias if the mail originates from the local host, or is +#     hostname qualified, but otherwise it will be rejected. +#     These are implemented in the local alias map. +# +# The alias for local 'root' is defined elsewhere. In this file, we +# define the virtual 'root@domain' (which can be overwritten by +# defining an entry for root in node property mx.aliases).  #  class site_postfix::mx::static_aliases {    $mx = hiera('mx') -  $aliases = $mx['aliases'] +  $root_recipients = hiera('contacts')    # -  # Predefined aliases. -  # -  # Defines which mail addresses shouldn't be available and where they should -  # fwd -  # -  # TODO: reconcile this with the node property webapp.forbidden_usernames +  # LOCAL ALIASES    # +    # NOTE: if you remove one of these, they will still appear in the    # /etc/aliases file -  # +  $local_aliases = [ +    'admin', 'administrator', 'bin', 'cron', 'games', 'ftp', 'lp', 'maildrop', +    'mysql', 'news', 'nobody', 'noc', 'postgresql', 'ssladmin', 'sys', +    'usenet', 'uucp', 'www', 'www-data' +  ] +    postfix::mailalias { -    [ 'abuse', 'admin', 'arin-admin', 'administrator', 'bin', 'cron', -      'certmaster', 'domainadmin', 'games', 'ftp', 'hostmaster', 'lp', -      'maildrop', 'mysql', 'news', 'nobody', 'noc', 'postmaster', 'postgresql', -      'security', 'ssladmin', 'sys', 'usenet', 'uucp', 'webmaster', 'www', -      'www-data', -    ]: +    $local_aliases:        ensure    => present,        recipient => 'root'    }    # -  # Custom static virtual aliases. +  # PUBLIC ALIASES    # + +  $public_aliases = $mx['aliases'] + +  $default_public_aliases = { +    'root'          => $root_recipients, +    'abuse'         => 'postmaster', +    'arin-admin'    => 'root', +    'certmaster'    => 'hostmaster', +    'domainadmin'   => 'hostmaster', +    'hostmaster'    => 'root', +    'mailer-daemon' => 'postmaster', +    'postmaster'    => 'root', +    'security'      => 'root', +    'webmaster'     => 'hostmaster', +  } + +  $aliases = merge($default_public_aliases, $public_aliases) +    exec { 'postmap_virtual_aliases':      command     => '/usr/sbin/postmap /etc/postfix/virtual-aliases',      refreshonly => true, diff --git a/puppet/modules/site_postfix/templates/virtual-aliases.erb b/puppet/modules/site_postfix/templates/virtual-aliases.erb index c474e734..8373de97 100644 --- a/puppet/modules/site_postfix/templates/virtual-aliases.erb +++ b/puppet/modules/site_postfix/templates/virtual-aliases.erb @@ -1,8 +1,7 @@  #  # 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`. +# These virtual aliases take precedence over all other aliases.  #  # diff --git a/puppet/modules/site_webapp/templates/config.yml.erb b/puppet/modules/site_webapp/templates/config.yml.erb index 5cb436fc..19ed6b7b 100644 --- a/puppet/modules/site_webapp/templates/config.yml.erb +++ b/puppet/modules/site_webapp/templates/config.yml.erb @@ -21,7 +21,8 @@ production = {    "default_service_level" => @webapp['default_service_level'],    "service_levels" => @webapp['service_levels'],    "allow_registration" => @webapp['allow_registration'], -  "handle_blacklist" => @webapp['forbidden_usernames'] +  "handle_blacklist" => @webapp['forbidden_usernames'], +  "invite_required" => @webapp['invite_required']  }  if @webapp['engines'] && @webapp['engines'].any? diff --git a/puppet/modules/soledad/manifests/init.pp b/puppet/modules/soledad/manifests/init.pp index 7cf0b729..6a2c328e 100644 --- a/puppet/modules/soledad/manifests/init.pp +++ b/puppet/modules/soledad/manifests/init.pp @@ -1,18 +1,29 @@ +# set up users, group and directories for soledad-server +# although the soledad users are already created by the +# soledad-server package  class soledad {    group { 'soledad': -    ensure    => present, -    allowdupe => false; +    ensure => present, +    system => true,    }    user { 'soledad':      ensure    => present, -    allowdupe => false, +    system    => true,      gid       => 'soledad',      home      => '/srv/leap/soledad',      require   => Group['soledad'];    } +  user { 'soledad-admin': +    ensure  => present, +    system  => true, +    gid     => 'soledad', +    home    => '/srv/leap/soledad', +    require => Group['soledad']; +  } +    file {      '/srv/leap/soledad':        ensure  => directory, diff --git a/puppet/modules/soledad/manifests/server.pp b/puppet/modules/soledad/manifests/server.pp index b71fab69..e437c8f2 100644 --- a/puppet/modules/soledad/manifests/server.pp +++ b/puppet/modules/soledad/manifests/server.pp @@ -1,3 +1,4 @@ +# setup soledad-server  class soledad::server {    tag 'leap_service'    include soledad @@ -22,13 +23,19 @@ class soledad::server {    # SOLEDAD CONFIG    # -  file { '/etc/leap/soledad-server.conf': -    content => template('soledad/soledad-server.conf.erb'), -    owner   => 'soledad', -    group   => 'soledad', -    mode    => '0600', -    notify  => Service['soledad-server'], -    require => Class['soledad']; +  file { +    '/etc/soledad': +      ensure => directory, +      owner  => 'root', +      group  => 'root', +      mode   => '0755'; +    '/etc/soledad/soledad-server.conf': +      content => template('soledad/soledad-server.conf.erb'), +      owner   => 'soledad', +      group   => 'soledad', +      mode    => '0640', +      notify  => Service['soledad-server'], +      require => Class['soledad'];    }    package { $sources['soledad']['package']: diff --git a/puppet/modules/soledad/templates/soledad-server.conf.erb b/puppet/modules/soledad/templates/soledad-server.conf.erb index 47d1f6e4..42cf44d8 100644 --- a/puppet/modules/soledad/templates/soledad-server.conf.erb +++ b/puppet/modules/soledad/templates/soledad-server.conf.erb @@ -1,3 +1,4 @@  [soledad-server] -couch_url = http://<%= @couchdb_user %>:<%= @couchdb_password %>@<%= @couchdb_host %>:<%= @couchdb_port %> - +couch_url   = http://<%= @couchdb_user %>:<%= @couchdb_password %>@<%= @couchdb_host %>:<%= @couchdb_port %> +create_cmd  = sudo -u soledad-admin /usr/bin/create-user-db +admin_netrc = /etc/couchdb/couchdb-soledad-admin.netrc diff --git a/puppet/modules/tapicero/files/tapicero.init b/puppet/modules/tapicero/files/tapicero.init deleted file mode 100755 index 7a9af45f..00000000 --- a/puppet/modules/tapicero/files/tapicero.init +++ /dev/null @@ -1,60 +0,0 @@ -#!/bin/sh - -### BEGIN INIT INFO -# Provides:          tapicero -# Required-Start:    $remote_fs $syslog -# Required-Stop:     $remote_fs $syslog -# Default-Start:     2 3 4 5 -# Default-Stop:      0 1 6 -# Short-Description: tapicero initscript -# Description:       Controls tapicero daemon -### END INIT INFO - -PATH=/sbin:/usr/sbin:/bin:/usr/bin -BUNDLER=/usr/bin/bundle -NAME=tapicero -HOME="/srv/leap" -DAEMON="${HOME}/${NAME}/bin/${NAME}" -BUNDLE_GEMFILE="${HOME}/${NAME}/Gemfile" - -export BUNDLE_GEMFILE - -# exit if the daemon doesn't exist -[ -x "$DAEMON" ] || exit 0 - -. /lib/init/vars.sh -. /lib/lsb/init-functions - -if [ "$VERBOSE" != no ]; then -    OPTIONS="--verbose" -else -    OPTIONS="" -fi - -case "$1" in -    start) -        $BUNDLER exec $DAEMON start $OPTIONS -        exit $? -        ;; -    stop) -        $BUNDLER exec $DAEMON stop $OPTIONS -        exit $? -        ;; -    restart) -        $BUNDLER exec $DAEMON restart $OPTIONS -        exit $? -        ;; -    reload) -        $BUNDLER exec $DAEMON reload $OPTIONS -        exit $? -        ;; -    status) -        $BUNDLER exec $DAEMON status $OPTIONS -        exit $? -        ;; -    *) -        echo "Usage: /etc/init.d/$NAME {start|stop|reload|restart|status}" -        exit 1 -esac - -exit 0 diff --git a/puppet/modules/tapicero/manifests/init.pp b/puppet/modules/tapicero/manifests/init.pp deleted file mode 100644 index ca8488c8..00000000 --- a/puppet/modules/tapicero/manifests/init.pp +++ /dev/null @@ -1,137 +0,0 @@ -class tapicero { -  tag 'leap_service' - -  $couchdb                 = hiera('couch') -  $couchdb_port            = $couchdb['port'] - -  $couchdb_users           = $couchdb['users'] - -  $couchdb_admin_user      = $couchdb_users['admin']['username'] -  $couchdb_admin_password  = $couchdb_users['admin']['password'] - -  $couchdb_soledad_user    = $couchdb_users['soledad']['username'] -  $couchdb_leap_mx_user    = $couchdb_users['leap_mx']['username'] - -  $couchdb_mode            = $couchdb['mode'] -  $couchdb_replication     = $couchdb['replication'] - -  $sources                 = hiera('sources') - -  Class['site_config::default'] -> Class['tapicero'] - -  include site_config::ruby::dev - -  # -  # USER AND GROUP -  # - -  group { 'tapicero': -    ensure    => present, -    allowdupe => false; -  } - -  user { 'tapicero': -    ensure    => present, -    allowdupe => false, -    gid       => 'tapicero', -    home      => '/srv/leap/tapicero', -    require   => Group['tapicero']; -  } - -  # -  # TAPICERO FILES -  # - -  file { - -    # -    # TAPICERO DIRECTORIES -    # - -    '/srv/leap/tapicero': -      ensure  => directory, -      owner   => 'tapicero', -      group   => 'tapicero', -      require => User['tapicero']; - -    '/var/lib/leap/tapicero': -      ensure  => directory, -      owner   => 'tapicero', -      group   => 'tapicero', -      require => User['tapicero']; - -    # for pid file -    '/var/run/tapicero': -      ensure  => directory, -      owner   => 'tapicero', -      group   => 'tapicero', -      require => User['tapicero']; - -    # -    # TAPICERO CONFIG -    # - -    '/etc/leap/tapicero.yaml': -      content => template('tapicero/tapicero.yaml.erb'), -      owner   => 'tapicero', -      group   => 'tapicero', -      mode    => '0600', -      notify  => Service['tapicero']; - -    # -    # TAPICERO INIT -    # - -    '/etc/init.d/tapicero': -      source  => 'puppet:///modules/tapicero/tapicero.init', -      owner   => root, -      group   => 0, -      mode    => '0755', -      require => Vcsrepo['/srv/leap/tapicero']; -  } - -  # -  # TAPICERO CODE -  # - -  vcsrepo { '/srv/leap/tapicero': -    ensure   => present, -    force    => true, -    revision => $sources['tapicero']['revision'], -    provider => $sources['tapicero']['type'], -    source   => $sources['tapicero']['source'], -    owner    => 'tapicero', -    group    => 'tapicero', -    require  => [ User['tapicero'], Group['tapicero'] ], -    notify   => Exec['tapicero_bundler_update'] -  } - -  exec { 'tapicero_bundler_update': -    cwd     => '/srv/leap/tapicero', -    command => '/bin/bash -c "/usr/bin/bundle check || /usr/bin/bundle install --path vendor/bundle --without test development"', -    unless  => '/usr/bin/bundle check', -    user    => 'tapicero', -    timeout => 600, -    require => [ -                Class['bundler::install'], -                Vcsrepo['/srv/leap/tapicero'], -                Class['site_config::ruby::dev'] ], -    notify  => Service['tapicero']; -  } - -  # -  # TAPICERO DAEMON -  # - -  service { 'tapicero': -    ensure     => running, -    enable     => true, -    hasstatus  => false, -    hasrestart => true, -    require    => [ File['/etc/init.d/tapicero'], -                    File['/var/run/tapicero'], -                    Couchdb::Add_user[$::site_couchdb::couchdb_tapicero_user] ]; -  } - -  leap::logfile { 'tapicero': } -} diff --git a/puppet/modules/tapicero/templates/tapicero.yaml.erb b/puppet/modules/tapicero/templates/tapicero.yaml.erb deleted file mode 100644 index 8b08b49c..00000000 --- a/puppet/modules/tapicero/templates/tapicero.yaml.erb +++ /dev/null @@ -1,52 +0,0 @@ -<%- require 'json' -%> - -# -# Default configuration options for Tapicero -# - -# couch connection configuration -connection: -  protocol: "http" -  host: "localhost" -  port: <%= @couchdb_port %> -  username: <%= @couchdb_admin_user %> -  password: <%= @couchdb_admin_password %> -  prefix : "" -  suffix : "" -  netrc: "/etc/couchdb/couchdb.netrc" - -# file to store the last processed user record in so we can resume after -# a restart: -seq_dir: "/var/lib/leap/tapicero/" - -# Configure log_file like this if you want to log to a file instead of syslog: -#log_file: "/var/log/leap/tapicero.log" -#log_level: debug -log_level: info - -# tapicero specific options -options: -  # prefix for per user databases: -  db_prefix: "user-" -  mode: <%= @couchdb_mode %> -<%- if @couchdb_replication %> -  replication: <%= @couchdb_replication.to_json %> -<%- end -%> - -  # security settings to be used for the per user databases -  security: -    admins: -      names: -        # We explicitly allow the admin user to access per user databases, even -        # though admin access ignores per database security we just do this to be -        # explicit about this -        - <%= @couchdb_admin_user %> -      roles: [] -    members: -      names: -        - <%= @couchdb_soledad_user %> -        - <%= @couchdb_leap_mx_user %> -      roles: -        - replication - - diff --git a/tests/white-box/couchdb.rb b/tests/white-box/couchdb.rb index 5ee12ff3..edb28eac 100644 --- a/tests/white-box/couchdb.rb +++ b/tests/white-box/couchdb.rb @@ -9,7 +9,6 @@ class CouchDB < LeapTest    end    def test_00_Are_daemons_running? -    assert_running '^tapicero', :single => true      if multimaster?        assert_running 'bin/beam'        assert_running 'bin/epmd' @@ -70,7 +69,7 @@ class CouchDB < LeapTest    end    def test_04_Do_ACL_users_exist? -    acl_users = ['_design/_auth', 'leap_mx', 'nickserver', 'soledad', 'tapicero', 'webapp', 'replication'] +    acl_users = ['_design/_auth', 'leap_mx', 'nickserver', 'soledad', 'webapp', 'replication']      url = couchdb_backend_url("/_users/_all_docs", :username => 'admin')      assert_get(url) do |body|        response = JSON.parse(body) diff --git a/tests/white-box/webapp.rb b/tests/white-box/webapp.rb index 9956eb35..8be6bde2 100644 --- a/tests/white-box/webapp.rb +++ b/tests/white-box/webapp.rb @@ -95,7 +95,7 @@ class Webapp < LeapTest    end    # -  # returns true if the per-user db created by tapicero exists. +  # returns true if the per-user db created by soledad-server exists.    # we try three times, and give up after that.    #    def assert_user_db_exists(user) | 
