summaryrefslogtreecommitdiff
path: root/provider_base/services
diff options
context:
space:
mode:
Diffstat (limited to 'provider_base/services')
-rw-r--r--provider_base/services/_api_tester.json13
-rw-r--r--provider_base/services/_couchdb_mirror.json22
-rw-r--r--provider_base/services/_couchdb_multimaster.json24
-rw-r--r--provider_base/services/couchdb.json49
-rw-r--r--provider_base/services/couchdb.rb27
-rw-r--r--provider_base/services/dns.json14
-rw-r--r--provider_base/services/monitor.json29
-rw-r--r--provider_base/services/monitor.rb3
-rw-r--r--provider_base/services/mx.json53
-rw-r--r--provider_base/services/mx.rb1
-rw-r--r--provider_base/services/obfsproxy.json9
-rw-r--r--provider_base/services/openvpn.json45
-rw-r--r--provider_base/services/soledad.json21
-rw-r--r--provider_base/services/soledad.rb3
-rw-r--r--provider_base/services/static.json20
-rw-r--r--provider_base/services/tor.json15
-rw-r--r--provider_base/services/webapp.json93
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]"
+ }
+ }
+}