diff options
Diffstat (limited to 'provider_base/services')
-rw-r--r-- | provider_base/services/_api_tester.json | 13 | ||||
-rw-r--r-- | provider_base/services/_couchdb_mirror.json | 22 | ||||
-rw-r--r-- | provider_base/services/_couchdb_multimaster.json | 24 | ||||
-rw-r--r-- | provider_base/services/couchdb.json | 49 | ||||
-rw-r--r-- | provider_base/services/couchdb.rb | 27 | ||||
-rw-r--r-- | provider_base/services/dns.json | 14 | ||||
-rw-r--r-- | provider_base/services/monitor.json | 29 | ||||
-rw-r--r-- | provider_base/services/monitor.rb | 3 | ||||
-rw-r--r-- | provider_base/services/mx.json | 53 | ||||
-rw-r--r-- | provider_base/services/mx.rb | 1 | ||||
-rw-r--r-- | provider_base/services/obfsproxy.json | 9 | ||||
-rw-r--r-- | provider_base/services/openvpn.json | 45 | ||||
-rw-r--r-- | provider_base/services/soledad.json | 21 | ||||
-rw-r--r-- | provider_base/services/soledad.rb | 3 | ||||
-rw-r--r-- | provider_base/services/static.json | 20 | ||||
-rw-r--r-- | provider_base/services/tor.json | 15 | ||||
-rw-r--r-- | provider_base/services/webapp.json | 93 |
17 files changed, 441 insertions, 0 deletions
diff --git a/provider_base/services/_api_tester.json b/provider_base/services/_api_tester.json new file mode 100644 index 00000000..790aa7d8 --- /dev/null +++ b/provider_base/services/_api_tester.json @@ -0,0 +1,13 @@ +// +// This partial should be added to any service that runs tests that rely on +// accessing the bonafide webapp API. +// +{ + "testing": { + "monitor_auth_token": "= secret :api_monitor_auth_token", + "api_uri": "= global.services[:webapp].api.uri", + // api_hosts is not used directly, but calling hostnames() will ensure + // that the hostnames are added to /etc/hosts + "api_hosts": "= hostnames(nodes_like_me[:services => 'webapp'])" + } +}
\ No newline at end of file diff --git a/provider_base/services/_couchdb_mirror.json b/provider_base/services/_couchdb_mirror.json new file mode 100644 index 00000000..da496bae --- /dev/null +++ b/provider_base/services/_couchdb_mirror.json @@ -0,0 +1,22 @@ +// +// Applied to all non-master couchdb nodes +// NOT CURRENTLY SUPPORTED +// +{ + "stunnel": { + "clients": { + "couch_client": "= stunnel_client(nodes[couch.replication.masters.keys], couch.port)" + } + }, + "couch": { + "mode": "mirror", + "replication": { + // for now, pick the first close one, or the first one. + // in the future, maybe use haproxy to balance among all the masters + "masters": "= try{pick_node(:couch_master,nodes_near_me['services' => 'couchdb']['couch.master' => true]).pick_fields('domain.internal', 'couch.port')} || try{pick_node(:couch_master,nodes_like_me['services' => 'couchdb']['couch.master' => true]).pick_fields('domain.internal', 'couch.port')}", + "username": "replication", + "password": "= secret :couch_replication_password", + "role": "replication" + } + } +} diff --git a/provider_base/services/_couchdb_multimaster.json b/provider_base/services/_couchdb_multimaster.json new file mode 100644 index 00000000..803a9416 --- /dev/null +++ b/provider_base/services/_couchdb_multimaster.json @@ -0,0 +1,24 @@ +// +// Only applied to master couchdb nodes when there are multiple masters +// NOT CURRENTLY USED. +{ + "stunnel": { + "servers": { + "epmd_server": "= stunnel_server(couch.bigcouch.epmd_port)", + "ednp_server": "= stunnel_server(couch.bigcouch.ednp_port)" + }, + "clients": { + "epmd_clients": "= stunnel_client(nodes_like_me['services' => 'couchdb']['couch.mode' => 'multimaster'], couch.bigcouch.epmd_port)", + "ednp_clients": "= stunnel_client(nodes_like_me['services' => 'couchdb']['couch.mode' => 'multimaster'], couch.bigcouch.ednp_port)" + } + }, + "couch": { + "mode": "multimaster", + "bigcouch": { + "epmd_port": 4369, + "ednp_port": 9002, + "cookie": "= secret :bigcouch_cookie", + "neighbors": "= nodes_like_me['services' => 'couchdb']['couch.mode' => 'multimaster'].exclude(self).field('domain.full')" + } + } +} diff --git a/provider_base/services/couchdb.json b/provider_base/services/couchdb.json new file mode 100644 index 00000000..30cb53d1 --- /dev/null +++ b/provider_base/services/couchdb.json @@ -0,0 +1,49 @@ +{ + "x509": { + "use": true + }, + "stunnel": { + "servers": { + "couch_server": "= stunnel_server(couch.port)" + } + }, + "couch": { + "port": 5984, + "mode": "plain", + "users": { + "admin": { + "username": "admin", + "password": "= secret :couch_admin_password", + "salt": "= hex_secret :couch_admin_password_salt, 128" + }, + "leap_mx": { + "username": "leap_mx", + "password": "= secret :couch_leap_mx_password", + "salt": "= hex_secret :couch_leap_mx_password_salt, 128" + }, + "nickserver": { + "username": "nickserver", + "password": "= secret :couch_nickserver_password", + "salt": "= hex_secret :couch_nickserver_password_salt, 128" + }, + "soledad": { + "username": "soledad", + "password": "= secret :couch_soledad_password", + "salt": "= hex_secret :couch_soledad_password_salt, 128" + }, + "webapp": { + "username": "webapp", + "password": "= secret :couch_webapp_password", + "salt": "= hex_secret :couch_webapp_password_salt, 128" + }, + "replication": { + "username": "replication", + "password": "= secret :couch_replication_password", + "salt": "= hex_secret :couch_replication_password_salt, 128" + } + }, + "webapp": { + "nagios_test_pw": "= secret :nagios_test_password" + } + } +} diff --git a/provider_base/services/couchdb.rb b/provider_base/services/couchdb.rb new file mode 100644 index 00000000..ba7e5ae5 --- /dev/null +++ b/provider_base/services/couchdb.rb @@ -0,0 +1,27 @@ +# +# custom logic for couchdb json resolution +# ============================================ +# +# bigcouch is no longer maintained, so now couchdb is required... +# no matter what! +# + +if self.couch['master'] + LeapCli::log :warning, %("The node property {couch.master:true} is deprecated.\n) + + %( Only {couch.mode:plain} is supported. (node #{self.name})) +end + +couchdb_nodes = nodes_like_me['services' => 'couchdb'] + +if couchdb_nodes.size > 1 + LeapCli::log :error, "Having multiple nodes with {services:couchdb} is no longer supported (nodes #{couchdb_nodes.keys.join(', ')})." +elsif self.couch.mode == "multimaster" + LeapCli::log :error, "Nodes with {couch.mode:multimaster} are no longer supported (node #{self.name})." +end + +# +# This is needed for the "test" that creates and removes the storage db +# for test_user_email. If that test is removed, then this is no longer +# necessary: +# +apply_partial('_api_tester')
\ No newline at end of file diff --git a/provider_base/services/dns.json b/provider_base/services/dns.json new file mode 100644 index 00000000..67948ef8 --- /dev/null +++ b/provider_base/services/dns.json @@ -0,0 +1,14 @@ +{ + "hosts": { + "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", + "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 new file mode 100644 index 00000000..9ddc0ec7 --- /dev/null +++ b/provider_base/services/monitor.json @@ -0,0 +1,29 @@ +{ + "nagios": { + "nagiosadmin_pw": "= secret :nagios_admin_password", + "domains_internal": "= nagios.hosts.values.map{|h|h['domain_internal_suffix']}.uniq", + "environments": "= Hash[ nagios.hosts.values.map{|h|h['environment']}.uniq.map{|e| [e||'default',{'contact_emails'=>manager.env(e).provider.contacts.default}]} ]", + "hosts": "= (self.environment == 'local' ? nodes_like_me : nodes[:environment => '!local']).pick_fields('environment', 'domain.internal', 'domain.internal_suffix', 'domain.full_suffix', 'ip_address', 'services', 'openvpn.gateway_address', 'ssh.port')" + }, + "hosts": "= self.environment == 'local' ? hosts_file(nodes_like_me) : hosts_file(nodes[:environment => '!local'])", + "ssh": { + "monitor": { + "username": "= Leap::Platform.monitor_username", + "private_key": "= file(:monitor_priv_key)" + } + }, + "x509": { + "use": true, + "use_commercial": true, + "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/monitor.rb b/provider_base/services/monitor.rb new file mode 100644 index 00000000..01590d5c --- /dev/null +++ b/provider_base/services/monitor.rb @@ -0,0 +1,3 @@ +unless self.services.include? "webapp" + LeapCli.log :error, "service `monitor` requires service `webapp` on the same node (node #{self.name})." +end diff --git a/provider_base/services/mx.json b/provider_base/services/mx.json new file mode 100644 index 00000000..c7e99d85 --- /dev/null +++ b/provider_base/services/mx.json @@ -0,0 +1,53 @@ +{ + "mx": { + // provider should define their own custom aliases. + // these are in *addition* to the standard reserved aliases for root and postmaster, etc. + "aliases": {}, + // this is the domain that is used for the OpenPGP header + "key_lookup_domain": "= global.services[:webapp].webapp.domain", + "dkim": { + // bit sizes larger than 2048 are not necessarily supported + "bit_size": 2048, + "public_key": "= remote_file_path(:dkim_pub_key) { generate_dkim_key(mx.dkim.bit_size) }", + "private_key": "= remote_file_path(:dkim_priv_key) { generate_dkim_key(mx.dkim.bit_size) }", + // generate selector based on first ten digits of pub key fingerprint: + "selector": "= fingerprint(local_file_path(:dkim_pub_key) { generate_dkim_key(mx.dkim.bit_size) }, :mode => :rsa).slice(0,10)" + } + }, + "stunnel": { + "clients": { + "couch_client": "= stunnel_client(nodes_like_me[:services => :couchdb], global.services[:couchdb].couch.port)" + } + }, + "haproxy": { + "couch": { + "listen_port": 4096, + "servers": "= haproxy_servers(nodes_like_me[:services => :couchdb], stunnel.clients.couch_client, global.services[:couchdb].couch.port)" + } + }, + "couchdb_leap_mx_user": { + "username": "= global.services[:couchdb].couch.users[:leap_mx].username", + "password": "= secret :couch_leap_mx_password", + "salt": "= hex_secret :couch_leap_mx_password_salt, 128" + }, + "mynetworks": "= host_ips(nodes)", + "rbls": ["zen.spamhaus.org"], + "clamav": { + "whitelisted_addresses": [] + }, + "x509": { + "use": true, + "use_commercial": true, + "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`'" + }, + "service_type": "user_service", + "firewall": { + "mx": { + "from": "*", + "to": "= ip_address", + "port": [25, 465] + } + } +} diff --git a/provider_base/services/mx.rb b/provider_base/services/mx.rb new file mode 100644 index 00000000..03ee561f --- /dev/null +++ b/provider_base/services/mx.rb @@ -0,0 +1 @@ +apply_partial('_api_tester') diff --git a/provider_base/services/obfsproxy.json b/provider_base/services/obfsproxy.json new file mode 100644 index 00000000..979d0ef9 --- /dev/null +++ b/provider_base/services/obfsproxy.json @@ -0,0 +1,9 @@ +{ + "obfsproxy": { + "scramblesuit": { + "password": "= base32_secret('scramblesuit_password_'+name)", + "port" : "= rand_range('scramblesuit_port_'+name, 18000..32000)" + }, + "gateway_address": "= try{pick_node(:obfs_gateway,nodes_near_me['services' => 'openvpn']).pick_fields('openvpn.gateway_address')} || try{pick_node(:obfs_gateway,nodes_like_me['services' => 'openvpn']).pick_fields('openvpn.gateway_address')}" + } +} diff --git a/provider_base/services/openvpn.json b/provider_base/services/openvpn.json new file mode 100644 index 00000000..6f73e31c --- /dev/null +++ b/provider_base/services/openvpn.json @@ -0,0 +1,45 @@ +{ + "service_type": "user_service", + "x509": { + "use": true, + "client_ca_cert": "= file :client_ca_cert, :missing => 'Certificate Authority. Run `leap cert ca`'", + "dh": "= file :dh_params, :missing => 'Diffie-Hellman parameters. Run `leap cert dh`'" + }, + "location": null, + "openvpn": { + "gateway_address": "REQUIRED", + "second_gateway_address": "= openvpn.allow_limited && openvpn.allow_unlimited ? 'REQUIRED' : nil", + "ports": ["80", "443", "53", "1194"], + "protocols": ["tcp", "udp"], + "filter_dns": false, + "adblock": false, + "user_ips": false, + "allow_limited": "= provider.service.allow_limited_bandwidth", + "allow_unlimited": "= provider.service.allow_unlimited_bandwidth", + "limited_prefix": "= provider.ca.client_certificates.limited_prefix", + "unlimited_prefix": "= provider.ca.client_certificates.unlimited_prefix", + "rate_limit": "= openvpn.allow_limited ? provider.service.bandwidth_limit : nil", + "configuration": { + "tls-cipher": "DHE-RSA-AES128-SHA", + "auth": "SHA1", + "cipher": "AES-128-CBC", + "keepalive": "10 30", + "tun-ipv6": true, + "fragment": 1500 + } + }, + "obfsproxy": { + "scramblesuit": { + "password": "= base32_secret('scramblesuit_password_'+name)", + "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 new file mode 100644 index 00000000..169588c8 --- /dev/null +++ b/provider_base/services/soledad.json @@ -0,0 +1,21 @@ +{ + "soledad": { + "port": 2323, + "couchdb_soledad_user": { + "username": "= global.services[:couchdb].couch.users[:soledad].username", + "password": "= secret :couch_soledad_password", + "salt": "= hex_secret :couch_soledad_password_salt, 128" + }, + "couchdb_leap_mx_user": { + "username": "= global.services[:couchdb].couch.users[:leap_mx].username" + } + }, + "service_type": "public_service", + "firewall": { + "soledad": { + "from": "*", + "to": "= ip_address", + "port": "= soledad.port" + } + } +} diff --git a/provider_base/services/soledad.rb b/provider_base/services/soledad.rb new file mode 100644 index 00000000..9b220c39 --- /dev/null +++ b/provider_base/services/soledad.rb @@ -0,0 +1,3 @@ +unless self.services.include? "couchdb" + LeapCli.log :error, "service `soledad` requires service `couchdb` on the same node (node #{self.name})." +end diff --git a/provider_base/services/static.json b/provider_base/services/static.json new file mode 100644 index 00000000..2f408ec1 --- /dev/null +++ b/provider_base/services/static.json @@ -0,0 +1,20 @@ +{ + "static": { + "formats": "=> try{static.domains.values.collect{|d| try{d.locations.values.collect{|l|l.format}} }.flatten.compact.uniq} || []", + // include a copy of provider.json in case any of the configured domains happens to match provider.domain + "bootstrap_files": { + "domain": "= provider.domain", + "enabled": "= !! try{static.domains[provider.domain]}", + "provider_json": "=> static.bootstrap_files.enabled ? try{nodes_like_me[:services => 'webapp'].values.first.definition_files['provider']} : nil", + "client_version": "= static.bootstrap_files.enabled ? provider.client_version : nil" + } + }, + "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/tor.json b/provider_base/services/tor.json new file mode 100644 index 00000000..55d3d2ee --- /dev/null +++ b/provider_base/services/tor.json @@ -0,0 +1,15 @@ +{ + "tor": { + "bandwidth_rate": 6550, + "contacts": "= [provider.contacts['tor'] || provider.contacts.default].flatten", + "nickname": "= (self.name + secret(:tor_family)).sub('_','')[0..18]", + "family": "= nodes[:services => 'tor'][:environment => '!local'].field('tor.nickname').join(',')", + "hidden_service": { + "active": null, + "key_type": "RSA", + "public_key": "= tor_public_key_path(:node_tor_pub_key, tor.hidden_service.key_type) if tor.hidden_service.active", + "private_key": "= tor_private_key_path(:node_tor_priv_key, tor.hidden_service.key_type) if tor.hidden_service.active", + "address": "= onion_address(:node_tor_pub_key) if tor.hidden_service.active" + } + } +} diff --git a/provider_base/services/webapp.json b/provider_base/services/webapp.json new file mode 100644 index 00000000..b1d2ca59 --- /dev/null +++ b/provider_base/services/webapp.json @@ -0,0 +1,93 @@ +{ + "webapp": { + "admins": [], + "forbidden_usernames": [ + "admin", "admins", "administrator", "administrators", "arin-admin", + "certmaster", "contact", "email", "help", "help-desk", "help-ticket", + "help-tickets", "help_desk", "help_ticket", "help_tickets", "helpdesk", + "helpticket", "helptickets", "info", "mail", "maildrop", "noreply", + "owner", "owners", "postmaster", "reply", "robot", "ssladmin", "staff", + "support", "tech-support", "tech_support", "techsupport", "ticket", + "tickets", "vmail", "www-data"], + "domain": "= provider.domain", + "modules": ["user", "billing", "help"], + "couchdb_webapp_user": "= global.services[:couchdb].couch.users[:webapp]", + "couchdb_admin_user": "= global.services[:couchdb].couch.users[:admin]", + "customization_dir": "= file_path 'webapp'", + "client_certificates": "= provider.ca.client_certificates", + "allow_limited_certs": "= provider.service.allow_limited_bandwidth", + "allow_unlimited_certs": "= provider.service.allow_unlimited_bandwidth", + "allow_anonymous_certs": "= provider.service.allow_anonymous", + "allow_registration": "= provider.service.allow_registration", + "default_service_level": "= provider.service.default_service_level", + "service_levels": "= service_levels()", + "secret_token": "= secret :webapp_secret_token", + "api_version": 1, + "secure": false, + "client_version": "= provider.client_version", + "nagios_test_user": { + "username": "nagios_test", + "password": "= secret :nagios_test_password" + }, + "engines": [ + "support" + ], + "locales": "= provider.languages", + "default_locale": "= provider.default_language", + "api_tokens": { + "monitor": "= secret :api_monitor_auth_token", + "allowed_ips": "= host_ips(nodes_like_me)" + } + }, + "stunnel": { + "clients": { + "couch_client": "= stunnel_client(nodes_like_me[:services => :couchdb], global.services[:couchdb].couch.port)" + } + }, + "haproxy": { + "couch": { + "listen_port": 4096, + "servers": "= haproxy_servers(nodes_like_me[:services => :couchdb], stunnel.clients.couch_client, global.services[:couchdb].couch.port)" + } + }, + "definition_files": { + "provider": "= file :provider_json_template", + "eip_service": "= file [:eip_service_json_template, 'v'+webapp.api_version.to_s]", + "soledad_service": "= file [:soledad_service_json_template, 'v'+webapp.api_version.to_s]", + "smtp_service": "= file [:smtp_service_json_template, 'v'+webapp.api_version.to_s]" + }, + "service_type": "public_service", + "api": { + "domain": "= 'api.' + webapp.domain", + "version": 1, + "port": 4430, + "ca_cert_uri": "= 'https://' + webapp.domain + '/ca.crt'", + "uri": "= %(https://#{api.domain}:#{api.port}/#{api.version})" + }, + "nickserver": { + "domain": "= 'nicknym.' + domain.full_suffix", + "couchdb_nickserver_user": { + "username": "= global.services[:couchdb].couch.users[:nickserver].username", + "password": "= secret :couch_nickserver_password", + "salt": "= hex_secret :couch_nickserver_password_salt, 128" + }, + "port": 6425 + }, + "dns": { + "aliases": "= [domain.full, webapp.domain, api.domain, nickserver.domain]" + }, + "x509": { + "use": true, + "use_commercial": true, + "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]" + } + } +} |