Add a load more cookbooks
authorTom Hughes <tom@compton.nu>
Fri, 31 May 2013 19:01:21 +0000 (20:01 +0100)
committerTom Hughes <tom@compton.nu>
Fri, 31 May 2013 19:01:21 +0000 (20:01 +0100)
139 files changed:
cookbooks/clamav/README.rdoc [new file with mode: 0644]
cookbooks/clamav/metadata.rb [new file with mode: 0644]
cookbooks/clamav/recipes/default.rb [new file with mode: 0644]
cookbooks/dhcpd/README.md [new file with mode: 0644]
cookbooks/dhcpd/attributes/default.rb [new file with mode: 0644]
cookbooks/dhcpd/metadata.rb [new file with mode: 0644]
cookbooks/dhcpd/recipes/default.rb [new file with mode: 0644]
cookbooks/dhcpd/templates/default/dhcpd.conf.erb [new file with mode: 0644]
cookbooks/exim/README.rdoc [new file with mode: 0644]
cookbooks/exim/attributes/default.rb [new file with mode: 0644]
cookbooks/exim/files/default/noreply/gpx [new file with mode: 0644]
cookbooks/exim/files/default/noreply/help [new file with mode: 0644]
cookbooks/exim/files/default/noreply/trac [new file with mode: 0644]
cookbooks/exim/files/default/noreply/web [new file with mode: 0644]
cookbooks/exim/metadata.rb [new file with mode: 0644]
cookbooks/exim/recipes/default.rb [new file with mode: 0644]
cookbooks/exim/templates/default/aliases.erb [new file with mode: 0644]
cookbooks/exim/templates/default/exim4.conf.erb [new file with mode: 0644]
cookbooks/foundation/README.rdoc [new file with mode: 0644]
cookbooks/foundation/metadata.rb [new file with mode: 0644]
cookbooks/foundation/recipes/default.rb [new file with mode: 0644]
cookbooks/git/README.rdoc [new file with mode: 0644]
cookbooks/git/metadata.rb [new file with mode: 0644]
cookbooks/git/recipes/default.rb [new file with mode: 0644]
cookbooks/git/recipes/server.rb [new file with mode: 0644]
cookbooks/git/templates/default/apache.erb [new file with mode: 0644]
cookbooks/git/templates/default/gitweb.conf.erb [new file with mode: 0644]
cookbooks/git/templates/default/post-receive.erb [new file with mode: 0644]
cookbooks/git/templates/default/post-update.erb [new file with mode: 0644]
cookbooks/mailman/README.rdoc [new file with mode: 0644]
cookbooks/mailman/metadata.rb [new file with mode: 0644]
cookbooks/mailman/recipes/default.rb [new file with mode: 0644]
cookbooks/mailman/templates/default/apache.erb [new file with mode: 0644]
cookbooks/mysql/README.rdoc [new file with mode: 0644]
cookbooks/mysql/attributes/default.rb [new file with mode: 0644]
cookbooks/mysql/libraries/mysql.rb [new file with mode: 0644]
cookbooks/mysql/metadata.rb [new file with mode: 0644]
cookbooks/mysql/providers/database.rb [new file with mode: 0644]
cookbooks/mysql/providers/user.rb [new file with mode: 0644]
cookbooks/mysql/recipes/default.rb [new file with mode: 0644]
cookbooks/mysql/resources/database.rb [new file with mode: 0644]
cookbooks/mysql/resources/user.rb [new file with mode: 0644]
cookbooks/mysql/templates/default/my.cnf.erb [new file with mode: 0644]
cookbooks/networking/README.md [new file with mode: 0644]
cookbooks/networking/attributes/default.rb [new file with mode: 0644]
cookbooks/networking/definitions/firewall_rule.rb [new file with mode: 0644]
cookbooks/networking/libraries/interfaces.rb [new file with mode: 0644]
cookbooks/networking/libraries/ipaddresses.rb [new file with mode: 0644]
cookbooks/networking/metadata.rb [new file with mode: 0644]
cookbooks/networking/recipes/default.rb [new file with mode: 0644]
cookbooks/networking/templates/default/hostname.erb [new file with mode: 0644]
cookbooks/networking/templates/default/hosts.erb [new file with mode: 0644]
cookbooks/networking/templates/default/interfaces.erb [new file with mode: 0644]
cookbooks/networking/templates/default/resolv.conf.erb [new file with mode: 0644]
cookbooks/networking/templates/default/shorewall-default.erb [new file with mode: 0644]
cookbooks/networking/templates/default/shorewall-hosts.erb [new file with mode: 0644]
cookbooks/networking/templates/default/shorewall-interfaces.erb [new file with mode: 0644]
cookbooks/networking/templates/default/shorewall-masq.erb [new file with mode: 0644]
cookbooks/networking/templates/default/shorewall-policy.erb [new file with mode: 0644]
cookbooks/networking/templates/default/shorewall-rules.erb [new file with mode: 0644]
cookbooks/networking/templates/default/shorewall-zones.erb [new file with mode: 0644]
cookbooks/networking/templates/default/shorewall.conf.erb [new file with mode: 0644]
cookbooks/networking/templates/default/shorewall6-hosts.erb [new file with mode: 0644]
cookbooks/networking/templates/default/shorewall6-interfaces.erb [new file with mode: 0644]
cookbooks/networking/templates/default/shorewall6.conf.erb [new file with mode: 0644]
cookbooks/nfs/README.rdoc [new file with mode: 0644]
cookbooks/nfs/metadata.rb [new file with mode: 0644]
cookbooks/nfs/recipes/default.rb [new file with mode: 0644]
cookbooks/nfs/recipes/server.rb [new file with mode: 0644]
cookbooks/nfs/templates/default/exports.erb [new file with mode: 0644]
cookbooks/openvpn/README.rdoc [new file with mode: 0644]
cookbooks/openvpn/attributes/default.rb [new file with mode: 0644]
cookbooks/openvpn/metadata.rb [new file with mode: 0644]
cookbooks/openvpn/recipes/default.rb [new file with mode: 0644]
cookbooks/openvpn/templates/default/tunnel.conf.erb [new file with mode: 0644]
cookbooks/osqa/README.rdoc [new file with mode: 0644]
cookbooks/osqa/attributes/default.rb [new file with mode: 0644]
cookbooks/osqa/files/default/osmauth/__init__.py [new file with mode: 0644]
cookbooks/osqa/files/default/osmauth/authentication.py [new file with mode: 0644]
cookbooks/osqa/files/default/osmauth/forms.py [new file with mode: 0644]
cookbooks/osqa/files/default/osmauth/osm.py [new file with mode: 0644]
cookbooks/osqa/files/default/osmauth/templates/loginform.html [new file with mode: 0644]
cookbooks/osqa/files/default/osmauth/urls.py [new file with mode: 0644]
cookbooks/osqa/metadata.rb [new file with mode: 0644]
cookbooks/osqa/recipes/default.rb [new file with mode: 0644]
cookbooks/osqa/templates/default/apache.erb [new file with mode: 0644]
cookbooks/osqa/templates/default/osqa.wsgi.erb [new file with mode: 0644]
cookbooks/otrs/README.rdoc [new file with mode: 0644]
cookbooks/otrs/attributes/default.rb [new file with mode: 0644]
cookbooks/otrs/metadata.rb [new file with mode: 0644]
cookbooks/otrs/recipes/default.rb [new file with mode: 0644]
cookbooks/otrs/templates/default/apache.erb [new file with mode: 0644]
cookbooks/otrs/templates/default/sudoers.erb [new file with mode: 0644]
cookbooks/piwik/README.rdoc [new file with mode: 0644]
cookbooks/piwik/metadata.rb [new file with mode: 0644]
cookbooks/piwik/recipes/default.rb [new file with mode: 0644]
cookbooks/piwik/templates/default/apache.erb [new file with mode: 0644]
cookbooks/piwik/templates/default/cron.erb [new file with mode: 0644]
cookbooks/postgresql/README.rdoc [new file with mode: 0644]
cookbooks/postgresql/attributes/default.rb [new file with mode: 0644]
cookbooks/postgresql/definitions/postgresql_munin.rb [new file with mode: 0644]
cookbooks/postgresql/libraries/postgresql.rb [new file with mode: 0644]
cookbooks/postgresql/metadata.rb [new file with mode: 0644]
cookbooks/postgresql/providers/database.rb [new file with mode: 0644]
cookbooks/postgresql/providers/execute.rb [new file with mode: 0644]
cookbooks/postgresql/providers/extension.rb [new file with mode: 0644]
cookbooks/postgresql/providers/table.rb [new file with mode: 0644]
cookbooks/postgresql/providers/user.rb [new file with mode: 0644]
cookbooks/postgresql/recipes/default.rb [new file with mode: 0644]
cookbooks/postgresql/resources/database.rb [new file with mode: 0644]
cookbooks/postgresql/resources/execute.rb [new file with mode: 0644]
cookbooks/postgresql/resources/extension.rb [new file with mode: 0644]
cookbooks/postgresql/resources/table.rb [new file with mode: 0644]
cookbooks/postgresql/resources/user.rb [new file with mode: 0644]
cookbooks/postgresql/templates/default/munin.erb [new file with mode: 0644]
cookbooks/postgresql/templates/default/ohai.rb.erb [new file with mode: 0644]
cookbooks/postgresql/templates/default/pg_hba.conf.erb [new file with mode: 0644]
cookbooks/postgresql/templates/default/pg_ident.conf.erb [new file with mode: 0644]
cookbooks/postgresql/templates/default/postgresql.conf.erb [new file with mode: 0644]
cookbooks/postgresql/templates/default/recovery.conf.erb [new file with mode: 0644]
cookbooks/rsyncd/README.md [new file with mode: 0644]
cookbooks/rsyncd/attributes/default.rb [new file with mode: 0644]
cookbooks/rsyncd/metadata.rb [new file with mode: 0644]
cookbooks/rsyncd/recipes/default.rb [new file with mode: 0644]
cookbooks/rsyncd/templates/default/rsync.erb [new file with mode: 0644]
cookbooks/rsyncd/templates/default/rsyncd.conf.erb [new file with mode: 0644]
cookbooks/spamassassin/README.rdoc [new file with mode: 0644]
cookbooks/spamassassin/metadata.rb [new file with mode: 0644]
cookbooks/spamassassin/recipes/default.rb [new file with mode: 0644]
cookbooks/spamassassin/templates/default/local.cf.erb [new file with mode: 0644]
cookbooks/spamassassin/templates/default/spamassassin.erb [new file with mode: 0644]
cookbooks/switch2osm/README.rdoc [new file with mode: 0644]
cookbooks/switch2osm/metadata.rb [new file with mode: 0644]
cookbooks/switch2osm/recipes/default.rb [new file with mode: 0644]
cookbooks/thinkup/README.rdoc [new file with mode: 0644]
cookbooks/thinkup/metadata.rb [new file with mode: 0644]
cookbooks/thinkup/recipes/default.rb [new file with mode: 0644]
cookbooks/thinkup/templates/default/apache.erb [new file with mode: 0644]
cookbooks/thinkup/templates/default/cron.erb [new file with mode: 0644]

diff --git a/cookbooks/clamav/README.rdoc b/cookbooks/clamav/README.rdoc
new file mode 100644 (file)
index 0000000..3de2ec7
--- /dev/null
@@ -0,0 +1,8 @@
+= DESCRIPTION:
+
+= REQUIREMENTS:
+
+= ATTRIBUTES:
+
+= USAGE:
+
diff --git a/cookbooks/clamav/metadata.rb b/cookbooks/clamav/metadata.rb
new file mode 100644 (file)
index 0000000..1675e56
--- /dev/null
@@ -0,0 +1,6 @@
+maintainer        "OpenStreetMap Administrators"
+maintainer_email  "admins@openstreetmap.org"
+license           "Apache 2.0"
+description       "Installs and configures clamav"
+long_description  IO.read(File.join(File.dirname(__FILE__), 'README.rdoc'))
+version           "1.0.0"
diff --git a/cookbooks/clamav/recipes/default.rb b/cookbooks/clamav/recipes/default.rb
new file mode 100644 (file)
index 0000000..ff34b85
--- /dev/null
@@ -0,0 +1,31 @@
+#
+# Cookbook Name:: clamav
+# Recipe:: default
+#
+# Copyright 2011, OpenStreetMap Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+package "clamav-daemon"
+package "clamav-freshclam"
+
+service "clamav-daemon" do
+  action [ :enable, :start ]
+  supports :status => true, :restart => true
+end
+
+service "clamav-freshclam" do
+  action [ :enable, :start ]
+  supports :status => true, :restart => true
+end
diff --git a/cookbooks/dhcpd/README.md b/cookbooks/dhcpd/README.md
new file mode 100644 (file)
index 0000000..6b08769
--- /dev/null
@@ -0,0 +1,57 @@
+DESCRIPTION
+===========
+
+Configures networking.
+
+USAGE
+=====
+
+Set the networking attributes in a role, for example from my base.rb:
+
+    :networking => {
+      :nameservers => [ "10.13.37.120", "10.13.37.40" ],
+      :search => [ "int.example.org". "example.org" ]
+    }
+
+The resulting /etc/resolv.conf will look like:
+
+    search int.example.org example.org
+    nameserver 10.13.37.120
+    nameserver 10.13.37.40
+
+LICENSE AND AUTHOR
+==================
+
+Author:: OpenStreetMap Administrators (<admins@openstreetmap.org>)
+
+Copyright 2010, OpenStreetMap Foundation.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+Based on resolver cookbook:
+
+Author:: Joshua Timberman (<joshua@opscode.com>)
+
+Copyright 2009, Opscode, Inc.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff --git a/cookbooks/dhcpd/attributes/default.rb b/cookbooks/dhcpd/attributes/default.rb
new file mode 100644 (file)
index 0000000..0844369
--- /dev/null
@@ -0,0 +1,2 @@
+default[:dhcpd][:first_address] = nil
+default[:dhcpd][:last_address] = nil
diff --git a/cookbooks/dhcpd/metadata.rb b/cookbooks/dhcpd/metadata.rb
new file mode 100644 (file)
index 0000000..656d877
--- /dev/null
@@ -0,0 +1,12 @@
+maintainer        "OpenStreetMap Administrators"
+maintainer_email  "admins@openstreetmap.org"
+license           "Apache 2.0"
+description       "Configures dhcpd"
+long_description  IO.read(File.join(File.dirname(__FILE__), 'README.md'))
+version           "1.0.0"
+depends           "networking"
+
+attribute "dhcpd",
+  :display_name => "dhcpd",
+  :description => "Hash of dhcpd attributes",
+  :type => "hash"
diff --git a/cookbooks/dhcpd/recipes/default.rb b/cookbooks/dhcpd/recipes/default.rb
new file mode 100644 (file)
index 0000000..0bdba6a
--- /dev/null
@@ -0,0 +1,46 @@
+#
+# Cookbook Name:: dhcpd
+# Recipe:: default
+#
+# Copyright 2011, OpenStreetMap Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+include_recipe "networking"
+
+if node[:lsb][:release].to_f < 12.04
+  package_name = "dhcp3-server"
+  config_file = "/etc/dhcp3/dhcpd.conf"
+else
+  package_name = "isc-dhcp-server"
+  config_file = "/etc/dhcp/dhcpd.conf"
+end
+
+package package_name
+
+domain = "#{node[:networking][:roles][:external][:zone]}.openstreetmap.org"
+
+template config_file do
+  source "dhcpd.conf.erb"
+  owner "root"
+  group "root"
+  mode 0644
+  variables :domain => domain
+end
+
+service package_name do
+  action [ :enable, :start ]
+  supports :status => true, :restart => true
+  subscribes :restart, resources(:template => config_file)
+end
diff --git a/cookbooks/dhcpd/templates/default/dhcpd.conf.erb b/cookbooks/dhcpd/templates/default/dhcpd.conf.erb
new file mode 100644 (file)
index 0000000..1872158
--- /dev/null
@@ -0,0 +1,165 @@
+# DO NOT EDIT - This file is being maintained by Chef
+
+default-lease-time 600;
+max-lease-time 7200;
+<% node.interfaces(:role => :internal).each do |interface| -%>
+
+subnet <%= interface[:network] %> netmask <%= interface[:netmask] %> {
+  range dynamic-bootp <%= node[:dhcpd][:first_address] %> <%= node[:dhcpd][:last_address] %>;
+#  option broadcast-address <%= interface[:broadcast] %>;
+  option routers <%= interface[:gateway] %>;
+  option domain-name "<%= @domain %>";
+  option domain-name-servers <%= interface[:gateway] %>;
+  option ntp-servers <%= node[:ntp][:servers].join(", ") %>;
+}
+<% end -%>
+
+host apc1.<%= @domain %> {
+  hardware ethernet 00:c0:b7:77:f3:d8;
+  server-name "apc1.<%= @domain %>";
+  fixed-address apc1.<%= @domain %>;
+}
+
+host apc2.<%= @domain %> {
+  hardware ethernet 00:c0:b7:52:b7:d2;
+  server-name "apc2.<%= @domain %>";
+  fixed-address apc2.<%= @domain %>;
+}
+
+host apc3.<%= @domain %> {
+  hardware ethernet 00:c0:b7:52:b9:1e;
+  server-name "apc3.<%= @domain %>";
+  fixed-address apc3.<%= @domain %>;
+}
+
+host bowser.oob.openstreetmap.org {
+  hardware ethernet 00:16:35:c5:dd:9e;
+  server-name "bowser.oob.openstreetmap.org";
+  fixed-address bowser.oob.openstreetmap.org;
+}
+
+host draco.oob.openstreetmap.org {
+  hardware ethernet 00:1c:c4:7a:da:dc;
+  server-name "draco.oob.openstreetmap.org";
+  fixed-address draco.oob.openstreetmap.org;
+}
+
+host errol.oob.openstreetmap.org {
+  hardware ethernet 00:e0:81:c0:8d:01;
+  server-name "errol.oob.openstreetmap.org";
+  fixed-address errol.oob.openstreetmap.org;
+}
+
+host eustace.oob.openstreetmap.org {
+  hardware ethernet 00:17:a4:3c:fb:9c;
+  server-name "eustace.oob.openstreetmap.org";
+  fixed-address eustace.oob.openstreetmap.org;
+}
+
+host faffy.oob.openstreetmap.org {
+  hardware ethernet 00:17:a4:37:cc:d0;
+  server-name "faffy.oob.openstreetmap.org";
+  fixed-address faffy.oob.openstreetmap.org;
+}
+
+host fiddlestick.oob.openstreetmap.org {
+  hardware ethernet 00:17:a4:0f:22:c6;
+  server-name "fiddlestick.oob.openstreetmap.org";
+  fixed-address fiddlestick.oob.openstreetmap.org;
+}
+
+host horntail.oob.openstreetmap.org {
+  hardware ethernet 00:e0:81:46:95:6e;
+  server-name "horntail.oob.openstreetmap.org";
+  fixed-address horntail.oob.openstreetmap.org;
+}
+
+host idris.oob.openstreetmap.org {
+  hardware ethernet 00:1f:29:68:bd:b6;
+  server-name "idris.oob.openstreetmap.org";
+  fixed-address idris.oob.openstreetmap.org;
+}
+
+host norbert.oob.openstreetmap.org {
+  hardware ethernet 00:1c:c4:7c:14:f6;
+  server-name "norbert.oob.openstreetmap.org";
+  fixed-address norbert.oob.openstreetmap.org;
+}
+
+host poldi.oob.openstreetmap.org {
+  hardware ethernet 00:e0:81:c5:2b:b7;
+  server-name "poldi.oob.openstreetmap.org";
+  fixed-address poldi.oob.openstreetmap.org;
+}
+
+host ridley.oob.openstreetmap.org {
+  hardware ethernet 00:17:a4:39:99:54;
+  server-name "ridley.oob.openstreetmap.org";
+  fixed-address ridley.oob.openstreetmap.org;
+}
+
+host sarel.oob.openstreetmap.org {
+  hardware ethernet 00:1c:c4:7c:d2:be;
+  server-name "sarel.oob.openstreetmap.org";
+  fixed-address sarel.oob.openstreetmap.org;
+}
+
+host smaug.oob.openstreetmap.org {
+  hardware ethernet 00:30:48:9d:57:ff;
+  server-name "smaug.oob.openstreetmap.org";
+  fixed-address smaug.oob.openstreetmap.org;
+}
+
+host soup.oob.openstreetmap.org {
+  hardware ethernet 00:17:a4:37:ec:88;
+  server-name "soup.oob.openstreetmap.org";
+  fixed-address soup.oob.openstreetmap.org;
+}
+
+host spike-01.oob.openstreetmap.org {
+  hardware ethernet 00:1a:4b:a5:bd:2a;
+  server-name "spike-01.oob.openstreetmap.org";
+  fixed-address spike-01.oob.openstreetmap.org;
+}
+
+host spike-02.oob.openstreetmap.org {
+  hardware ethernet 00:1b:78:04:37:de;
+  server-name "spike-02.oob.openstreetmap.org";
+  fixed-address spike-02.oob.openstreetmap.org;
+}
+
+host spike-03.oob.openstreetmap.org {
+  hardware ethernet 00:19:bb:39:3c:64;
+  server-name "spike-03.oob.openstreetmap.org";
+  fixed-address spike-03.oob.openstreetmap.org;
+}
+
+host thorn-01.oob.openstreetmap.org {
+  hardware ethernet 00:19:bb:35:87:94;
+  server-name "thorn-01.oob.openstreetmap.org";
+  fixed-address thorn-01.oob.openstreetmap.org;
+}
+
+host thorn-02.oob.openstreetmap.org {
+  hardware ethernet 00:19:bb:39:9b:a6;
+  server-name "thorn-02.oob.openstreetmap.org";
+  fixed-address thorn-02.oob.openstreetmap.org;
+}
+
+host thorn-03.oob.openstreetmap.org {
+  hardware ethernet 00:19:bb:37:f3:ce;
+  server-name "thorn-03.oob.openstreetmap.org";
+  fixed-address thorn-03.oob.openstreetmap.org;
+}
+
+host urmel.oob.openstreetmap.org {
+  hardware ethernet 00:19:bb:39:1b:e6;
+  server-name "urmel.oob.openstreetmap.org";
+  fixed-address urmel.oob.openstreetmap.org;
+}
+
+host yevaud.oob.openstreetmap.org {
+  hardware ethernet 00:e0:81:c0:8d:02;
+  server-name "yevaud.oob.openstreetmap.org";
+  fixed-address yevaud.oob.openstreetmap.org;
+}
diff --git a/cookbooks/exim/README.rdoc b/cookbooks/exim/README.rdoc
new file mode 100644 (file)
index 0000000..3de2ec7
--- /dev/null
@@ -0,0 +1,8 @@
+= DESCRIPTION:
+
+= REQUIREMENTS:
+
+= ATTRIBUTES:
+
+= USAGE:
+
diff --git a/cookbooks/exim/attributes/default.rb b/cookbooks/exim/attributes/default.rb
new file mode 100644 (file)
index 0000000..e6e7fff
--- /dev/null
@@ -0,0 +1,9 @@
+default[:exim][:local_domains] = [ "localhost", "@" ]
+default[:exim][:relay_to_domains] = [ ]
+default[:exim][:relay_from_hosts] = [ "127.0.0.1", "::1" ]
+default[:exim][:daemon_smtp_ports] = [ 25 ]
+default[:exim][:trusted_users] = [ ]
+default[:exim][:smarthost_name] = nil
+default[:exim][:smarthost_via] = "mail.openstreetmap.org:26"
+default[:exim][:routes] = { }
+default[:exim][:aliases][:root] = "tomh"
diff --git a/cookbooks/exim/files/default/noreply/gpx b/cookbooks/exim/files/default/noreply/gpx
new file mode 100644 (file)
index 0000000..6c8a45a
--- /dev/null
@@ -0,0 +1,18 @@
+This is an automated response to your email, which was sent to an
+unattended address.
+
+The message you replied to was notifying you of the status of your
+recent openstreetmap.org GPS trace upload, and you do not generally
+need to reply to this message.
+
+If your trace failed to upload, please start by consulting the
+information on our wiki about import failures:
+
+  http://wiki.openstreetmap.org/index.php/GPX_Import_Failures
+
+If you have encountered a technical problem withe upload service
+then please contact support@openstreetmap.org for assistance.
+
+Thank you,
+
+OpenStreetMap Administrators
diff --git a/cookbooks/exim/files/default/noreply/help b/cookbooks/exim/files/default/noreply/help
new file mode 100644 (file)
index 0000000..8dfbc31
--- /dev/null
@@ -0,0 +1,13 @@
+This is an automated response to your email, which was sent to an
+unattended address.
+
+If you were trying to reply to a question, answer or comment on
+the help.openstreetmap.org web site then you should do so using
+the web site as it is not possible to reply by email.
+
+If you are having problems with the help.openstreetmap.org site
+then please contact support@openstreetmap.org for assistance.
+
+Thank you,
+
+OpenStreetMap Administrators
diff --git a/cookbooks/exim/files/default/noreply/trac b/cookbooks/exim/files/default/noreply/trac
new file mode 100644 (file)
index 0000000..2628aa8
--- /dev/null
@@ -0,0 +1,13 @@
+This is an automated response to your email, which was sent to an
+unattended address.
+
+If you were trying to reply to a comment on a bug report on
+the trac.openstreetmap.org web site then you should do so using
+the web site as it is not possible to reply by email.
+
+If you are having problems with the trac.openstreetmap.org site
+then please contact support@openstreetmap.org for assistance.
+
+Thank you,
+
+OpenStreetMap Administrators
diff --git a/cookbooks/exim/files/default/noreply/web b/cookbooks/exim/files/default/noreply/web
new file mode 100644 (file)
index 0000000..51eab34
--- /dev/null
@@ -0,0 +1,18 @@
+This is an automated response to your email, which was sent to an
+unattended address.
+
+If you were trying to confirm your email address after signing
+up for an account, or after changing your email address, then you 
+should click on the link in the original email you received.
+
+If you need help using OpenStreetMap then you should try our
+question and answer site:
+
+  http://help.openstreetmap.org/
+
+If you are having technical problems with the web site then please
+contact support@openstreetmap.org for assistance.
+
+Thank you,
+
+OpenStreetMap Administrators
diff --git a/cookbooks/exim/metadata.rb b/cookbooks/exim/metadata.rb
new file mode 100644 (file)
index 0000000..861ce09
--- /dev/null
@@ -0,0 +1,58 @@
+maintainer        "OpenStreetMap Administrators"
+maintainer_email  "admins@openstreetmap.org"
+license           "Apache 2.0"
+description       "Installs and configures exim"
+long_description  IO.read(File.join(File.dirname(__FILE__), 'README.rdoc'))
+version           "1.0.0"
+depends           "networking"
+depends           "ssl"
+
+attribute "exim",
+  :display_name => "Exim",
+  :description => "Hash of exim attributes",
+  :type => "hash"
+
+attribute "exim/local_domains",
+  :display_name => "Domains to Handle Locally",
+  :description => "List of domains we are prepared to accept mail for",
+  :default => [ "@" ]
+
+attribute "exim/relay_to_domains",
+  :display_name => "Domains to Relay To",
+  :description => "List of domains we are prepared to relay to",
+  :default => [ ]
+
+attribute "exim/relay_from_hosts",
+  :display_name => "Hosts to Relay From",
+  :description => "List of hosts we are prepared to relay from",
+  :default => [ "127.0.0.1", "::1" ]
+
+attribute "exim/daemon_smtp_ports",
+  :display_name => "Ports to Listen On",
+  :description => "List of ports we will listen on",
+  :default => [ 25 ]
+
+attribute "exim/trusted_users",
+  :display_name => "Trusted Users",
+  :description => "List of users we will trust",
+  :default => [ ]
+
+attribute "exim/smarthost_name",
+  :display_name => "Smarthost Name",
+  :description => "Name of this smarthost",
+  :default => nil
+
+attribute "exim/smarthost_via",
+  :display_name => "Smarthost Via",
+  :description => "Smarthost to use for sending mail",
+  :default => "mail.openstreetmap.org:26"
+
+attribute "exim/routes",
+  :display_name => "Custom Routes",
+  :description => "Custom routes for handling local mail",
+  :default => { }
+
+attribute "exim/aliases",
+  :display_name => "Mail Aliases",
+  :description => "Mail aliases",
+  :default => { }
diff --git a/cookbooks/exim/recipes/default.rb b/cookbooks/exim/recipes/default.rb
new file mode 100644 (file)
index 0000000..ff38860
--- /dev/null
@@ -0,0 +1,108 @@
+#
+# Cookbook Name:: exim
+# Recipe:: default
+#
+# Copyright 2011, OpenStreetMap Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+include_recipe "networking"
+include_recipe "ssl"
+
+package "exim4"
+
+if File.exist?("/var/run/clamav/clamd.ctl")
+  package "exim4-daemon-heavy"
+end
+
+group "ssl-cert" do
+  action :modify
+  members "Debian-exim"
+  append true
+end
+
+service "exim4" do
+  action [ :enable, :start ]
+  supports :status => true, :restart => true, :reload => true
+  subscribes :restart, resources(:cookbook_file => "/etc/ssl/certs/openstreetmap.pem")
+  subscribes :restart, resources(:file => "/etc/ssl/private/openstreetmap.key")
+end
+
+relay_to_domains = node[:exim][:relay_to_domains]
+
+node[:exim][:routes].each_value do |route|
+  relay_to_domains = relay_to_domains | route[:domains]
+end
+
+relay_from_hosts = node[:exim][:relay_from_hosts]
+
+if node[:exim][:smarthost_name]
+  search(:node, "exim_smarthost_via:#{node[:exim][:smarthost_name]}\\:*").each do |host|
+    relay_from_hosts = relay_from_hosts | host.ipaddresses(:role => :external)
+  end
+end
+
+template "/etc/exim4/exim4.conf" do
+  source "exim4.conf.erb"
+  owner "root"
+  group "Debian-exim"
+  mode 0644
+  variables :relay_to_domains => relay_to_domains.sort,
+            :relay_from_hosts => relay_from_hosts.sort
+  notifies :restart, resources(:service => "exim4")
+end
+
+template "/etc/aliases" do
+  source "aliases.erb"
+  owner "root"
+  group "root"
+  mode 0644
+end
+
+remote_directory "/etc/exim4/noreply" do
+  source "noreply"
+  owner "root"
+  group "Debian-exim"
+  mode 0755
+  files_owner "root"
+  files_group "Debian-exim"
+  files_mode 0755
+  purge true
+end
+
+munin_plugin "exim_mailqueue"
+munin_plugin "exim_mailstats"
+
+if not relay_to_domains.empty? or not node[:exim][:local_domains].empty?
+  node[:exim][:daemon_smtp_ports].each do |port|
+    firewall_rule "accept-inbound-smtp-#{port}" do
+      action :accept
+      source "net"
+      dest "fw"
+      proto "tcp:syn"
+      dest_ports port
+      source_ports "1024:"
+    end
+  end
+end
+
+if node[:exim][:smarthost_via]
+  firewall_rule "deny-outbound-smtp" do
+    action :reject
+    source "fw"
+    dest "net"
+    proto "tcp:syn"
+    dest_ports "smtp"
+  end
+end
diff --git a/cookbooks/exim/templates/default/aliases.erb b/cookbooks/exim/templates/default/aliases.erb
new file mode 100644 (file)
index 0000000..52a7f35
--- /dev/null
@@ -0,0 +1,11 @@
+# DO NOT EDIT - This file is being maintained by Chef
+
+<% node[:exim][:aliases].keys.sort.each do |a| -%>
+<%= a -%>: <%= node[:exim][:aliases][a] %>
+<% end -%>
+
+<% node[:accounts][:users].keys.sort.each do |u| -%>
+<% if node[:accounts][:users][u][:status] and node[:accounts][:users][u][:email] -%>
+<%= u -%>: <%= node[:accounts][:users][u][:email] %>
+<% end -%>
+<% end -%>
diff --git a/cookbooks/exim/templates/default/exim4.conf.erb b/cookbooks/exim/templates/default/exim4.conf.erb
new file mode 100644 (file)
index 0000000..c1a842c
--- /dev/null
@@ -0,0 +1,810 @@
+# $Cambridge: exim/exim-src/src/configure.default,v 1.14 2009/10/16 07:46:13 tom Exp $
+
+######################################################################
+#                  Runtime configuration file for Exim               #
+######################################################################
+
+
+# This is a default configuration file which will operate correctly in
+# uncomplicated installations. Please see the manual for a complete list
+# of all the runtime configuration options that can be included in a
+# configuration file. There are many more than are mentioned here. The
+# manual is in the file doc/spec.txt in the Exim distribution as a plain
+# ASCII file. Other formats (PostScript, Texinfo, HTML, PDF) are available
+# from the Exim ftp sites. The manual is also online at the Exim web sites.
+
+
+# This file is divided into several parts, all but the first of which are
+# headed by a line starting with the word "begin". Only those parts that
+# are required need to be present. Blank lines, and lines starting with #
+# are ignored.
+
+
+########### IMPORTANT ########## IMPORTANT ########### IMPORTANT ###########
+#                                                                          #
+# Whenever you change Exim's configuration file, you *must* remember to    #
+# HUP the Exim daemon, because it will not pick up the new configuration   #
+# until you do. However, any other Exim processes that are started, for    #
+# example, a process started by an MUA in order to send a message, will    #
+# see the new configuration as soon as it is in place.                     #
+#                                                                          #
+# You do not need to HUP the daemon for changes in auxiliary files that    #
+# are referenced from this file. They are read every time they are used.   #
+#                                                                          #
+# It is usually a good idea to test a new configuration for syntactic      #
+# correctness before installing it (for example, by running the command    #
+# "exim -C /config/file.new -bV").                                         #
+#                                                                          #
+########### IMPORTANT ########## IMPORTANT ########### IMPORTANT ###########
+
+
+
+######################################################################
+#                    MAIN CONFIGURATION SETTINGS                     #
+######################################################################
+
+# Specify your host's canonical name here. This should normally be the fully
+# qualified "official" name of your host. If this option is not set, the
+# uname() function is called to obtain the name. In many cases this does
+# the right thing and you need not set anything explicitly.
+
+primary_hostname = <%= node[:fqdn] %>
+
+
+# The next three settings create two lists of domains and one list of hosts.
+# These lists are referred to later in this configuration using the syntax
+# +local_domains, +relay_to_domains, and +relay_from_hosts, respectively. They
+# are all colon-separated lists:
+
+domainlist local_domains = <%= node[:exim][:local_domains].join(" : ") %>
+domainlist relay_to_domains = <%= @relay_to_domains.join(" : ") %>
+hostlist   relay_from_hosts = <; <%= @relay_from_hosts.join(" ; ") %>
+
+# Most straightforward access control requirements can be obtained by
+# appropriate settings of the above options. In more complicated situations,
+# you may need to modify the Access Control Lists (ACLs) which appear later in
+# this file.
+
+# The first setting specifies your local domains, for example:
+#
+#   domainlist local_domains = my.first.domain : my.second.domain
+#
+# You can use "@" to mean "the name of the local host", as in the default
+# setting above. This is the name that is specified by primary_hostname,
+# as specified above (or defaulted). If you do not want to do any local
+# deliveries, remove the "@" from the setting above. If you want to accept mail
+# addressed to your host's literal IP address, for example, mail addressed to
+# "user@[192.168.23.44]", you can add "@[]" as an item in the local domains
+# list. You also need to uncomment "allow_domain_literals" below. This is not
+# recommended for today's Internet.
+
+# The second setting specifies domains for which your host is an incoming relay.
+# If you are not doing any relaying, you should leave the list empty. However,
+# if your host is an MX backup or gateway of some kind for some domains, you
+# must set relay_to_domains to match those domains. For example:
+#
+# domainlist relay_to_domains = *.myco.com : my.friend.org
+#
+# This will allow any host to relay through your host to those domains.
+# See the section of the manual entitled "Control of relaying" for more
+# information.
+
+# The third setting specifies hosts that can use your host as an outgoing relay
+# to any other host on the Internet. Such a setting commonly refers to a
+# complete local network as well as the localhost. For example:
+#
+# hostlist relay_from_hosts = 127.0.0.1 : 192.168.0.0/16
+#
+# The "/16" is a bit mask (CIDR notation), not a number of hosts. Note that you
+# have to include 127.0.0.1 if you want to allow processes on your host to send
+# SMTP mail by using the loopback address. A number of MUAs use this method of
+# sending mail.
+
+# All three of these lists may contain many different kinds of item, including
+# wildcarded names, regular expressions, and file lookups. See the reference
+# manual for details. The lists above are used in the access control lists for
+# checking incoming messages. The names of these ACLs are defined here:
+
+acl_smtp_rcpt = acl_check_rcpt
+acl_smtp_data = acl_check_data
+
+# You should not change those settings until you understand how ACLs work.
+
+
+<% if File.exist?("/var/run/clamav/clamd.ctl") -%>
+# If you are running a version of Exim that was compiled with the content-
+# scanning extension, you can cause incoming messages to be automatically
+# scanned for viruses. You have to modify the configuration in two places to
+# set this up. The first of them is here, where you define the interface to
+# your scanner. This example is typical for ClamAV; see the manual for details
+# of what to set for other virus scanners. The second modification is in the
+# acl_check_data access control list (see below).
+
+av_scanner = clamd:/var/run/clamav/clamd.ctl
+
+
+<% end -%>
+<% if File.exist?("/var/run/spamd.pid") -%>
+# For spam scanning, there is a similar option that defines the interface to
+# SpamAssassin. You do not need to set this if you are using the default, which
+# is shown in this commented example. As for virus scanning, you must also
+# modify the acl_check_data access control list to enable spam scanning.
+
+spamd_address = 127.0.0.1 783
+
+
+<% end -%>
+# If Exim is compiled with support for TLS, you may want to enable the
+# following options so that Exim allows clients to make encrypted
+# connections. In the authenticators section below, there are template
+# configurations for plaintext username/password authentication. This kind
+# of authentication is only safe when used within a TLS connection, so the
+# authenticators will only work if the following TLS settings are turned on
+# as well.
+
+# Allow any client to use TLS.
+
+tls_advertise_hosts = <; !127.0.0.1 ; !::1
+
+# Specify the location of the Exim server's TLS certificate and private key.
+# The private key must not be encrypted (password protected). You can put
+# the certificate and private key in the same file, in which case you only
+# need the first setting, or in separate files, in which case you need both
+# options.
+
+tls_certificate = /etc/ssl/certs/openstreetmap.pem
+tls_privatekey = /etc/ssl/private/openstreetmap.key
+
+# In order to support roaming users who wish to send email from anywhere,
+# you may want to make Exim listen on other ports as well as port 25, in
+# case these users need to send email from a network that blocks port 25.
+# The standard port for this purpose is port 587, the "message submission"
+# port. See RFC 4409 for details. Microsoft MUAs cannot be configured to
+# talk the message submission protocol correctly, so if you need to support
+# them you should also allow TLS-on-connect on the traditional but
+# non-standard port 465.
+
+daemon_smtp_ports = <%= node[:exim][:daemon_smtp_ports].join(" : ") %>
+# tls_on_connect_ports = 465
+
+
+# Specify the domain you want to be added to all unqualified addresses
+# here. An unqualified address is one that does not contain an "@" character
+# followed by a domain. For example, "caesar@rome.example" is a fully qualified
+# address, but the string "caesar" (i.e. just a login name) is an unqualified
+# email address. Unqualified addresses are accepted only from local callers by
+# default. See the recipient_unqualified_hosts option if you want to permit
+# unqualified addresses from remote sources. If this option is not set, the
+# primary_hostname value is used for qualification.
+
+qualify_domain = openstreetmap.org
+
+
+# If you want unqualified recipient addresses to be qualified with a different
+# domain to unqualified sender addresses, specify the recipient domain here.
+# If this option is not set, the qualify_domain value is used.
+
+qualify_recipient = <%= node[:fqdn] %>
+
+
+# The following line must be uncommented if you want Exim to recognize
+# addresses of the form "user@[10.11.12.13]" that is, with a "domain literal"
+# (an IP address) instead of a named domain. The RFCs still require this form,
+# but it makes little sense to permit mail to be sent to specific hosts by
+# their IP address in the modern Internet. This ancient format has been used
+# by those seeking to abuse hosts by using them for unwanted relaying. If you
+# really do want to support domain literals, uncomment the following line, and
+# see also the "domain_literal" router below.
+
+# allow_domain_literals
+
+
+# No deliveries will ever be run under the uids of users specified by
+# never_users (a colon-separated list). An attempt to do so causes a panic
+# error to be logged, and the delivery to be deferred. This is a paranoic
+# safety catch. There is an even stronger safety catch in the form of the
+# FIXED_NEVER_USERS setting in the configuration for building Exim. The list of
+# users that it specifies is built into the binary, and cannot be changed. The
+# option below just adds additional users to the list. The default for
+# FIXED_NEVER_USERS is "root", but just to be absolutely sure, the default here
+# is also "root".
+
+# Note that the default setting means you cannot deliver mail addressed to root
+# as if it were a normal user. This isn't usually a problem, as most sites have
+# an alias for root that redirects such mail to a human administrator.
+
+never_users = root
+
+
+# The setting below causes Exim to do a reverse DNS lookup on all incoming
+# IP calls, in order to get the true host name. If you feel this is too
+# expensive, you can specify the networks for which a lookup is done, or
+# remove the setting entirely.
+
+host_lookup = *
+
+
+# The settings below, which are actually the same as the defaults in the
+# code, cause Exim to make RFC 1413 (ident) callbacks for all incoming SMTP
+# calls. You can limit the hosts to which these calls are made, and/or change
+# the timeout that is used. If you set the timeout to zero, all RFC 1413 calls
+# are disabled. RFC 1413 calls are cheap and can provide useful information
+# for tracing problem messages, but some hosts and firewalls have problems
+# with them. This can result in a timeout instead of an immediate refused
+# connection, leading to delays on starting up SMTP sessions. (The default was
+# reduced from 30s to 5s for release 4.61.)
+
+rfc1413_hosts = *
+rfc1413_query_timeout = 5s
+
+
+# By default, Exim expects all envelope addresses to be fully qualified, that
+# is, they must contain both a local part and a domain. If you want to accept
+# unqualified addresses (just a local part) from certain hosts, you can specify
+# these hosts by setting one or both of
+#
+# sender_unqualified_hosts =
+# recipient_unqualified_hosts =
+#
+# to control sender and recipient addresses, respectively. When this is done,
+# unqualified addresses are qualified using the settings of qualify_domain
+# and/or qualify_recipient (see above).
+
+
+# If you want Exim to support the "percent hack" for certain domains,
+# uncomment the following line and provide a list of domains. The "percent
+# hack" is the feature by which mail addressed to x%y@z (where z is one of
+# the domains listed) is locally rerouted to x@y and sent on. If z is not one
+# of the "percent hack" domains, x%y is treated as an ordinary local part. This
+# hack is rarely needed nowadays; you should not enable it unless you are sure
+# that you really need it.
+#
+# percent_hack_domains =
+#
+# As well as setting this option you will also need to remove the test
+# for local parts containing % in the ACL definition below.
+
+
+# When Exim can neither deliver a message nor return it to sender, it "freezes"
+# the delivery error message (aka "bounce message"). There are also other
+# circumstances in which messages get frozen. They will stay on the queue for
+# ever unless one of the following options is set.
+
+# This option unfreezes frozen bounce messages after two days, tries
+# once more to deliver them, and ignores any delivery failures.
+
+ignore_bounce_errors_after = 2d
+
+# This option cancels (removes) frozen messages that are older than a week.
+
+timeout_frozen_after = 7d
+
+
+# By default, messages that are waiting on Exim's queue are all held in a
+# single directory called "input" which it itself within Exim's spool
+# directory. (The default spool directory is specified when Exim is built, and
+# is often /var/spool/exim/.) Exim works best when its queue is kept short, but
+# there are circumstances where this is not always possible. If you uncomment
+# the setting below, messages on the queue are held in 62 subdirectories of
+# "input" instead of all in the same directory. The subdirectories are called
+# 0, 1, ... A, B, ... a, b, ... z. This has two benefits: (1) If your file
+# system degrades with many files in one directory, this is less likely to
+# happen; (2) Exim can process the queue one subdirectory at a time instead of
+# all at once, which can give better performance with large queues.
+
+# split_spool_directory = true
+
+
+# Log just about everything we can log so that we have the best
+# possible chance of knowing what's going on.
+
+log_selector = +all -skip_delivery
+
+
+# Define trusted users.
+
+trusted_users = <%= node[:exim][:trusted_users].join(" : ") %>
+
+
+
+######################################################################
+#                       ACL CONFIGURATION                            #
+#         Specifies access control lists for incoming SMTP mail      #
+######################################################################
+
+begin acl
+
+# This access control list is used for every RCPT command in an incoming
+# SMTP message. The tests are run in order until the address is either
+# accepted or denied.
+
+acl_check_rcpt:
+
+  # Accept if the source is local SMTP (i.e. not over TCP/IP). We do this by
+  # testing for an empty sending host field.
+
+  accept  hosts = :
+<% if node[:lsb][:release].to_i >= 10.04 -%>
+          control = dkim_disable_verify
+<% end -%>
+
+  #############################################################################
+  # The following section of the ACL is concerned with local parts that contain
+  # @ or % or ! or / or | or dots in unusual places.
+  #
+  # The characters other than dots are rarely found in genuine local parts, but
+  # are often tried by people looking to circumvent relaying restrictions.
+  # Therefore, although they are valid in local parts, these rules lock them
+  # out, as a precaution.
+  #
+  # Empty components (two dots in a row) are not valid in RFC 2822, but Exim
+  # allows them because they have been encountered. (Consider local parts
+  # constructed as "firstinitial.secondinitial.familyname" when applied to
+  # someone like me, who has no second initial.) However, a local part starting
+  # with a dot or containing /../ can cause trouble if it is used as part of a
+  # file name (e.g. for a mailing list). This is also true for local parts that
+  # contain slashes. A pipe symbol can also be troublesome if the local part is
+  # incorporated unthinkingly into a shell command line.
+  #
+  # Two different rules are used. The first one is stricter, and is applied to
+  # messages that are addressed to one of the local domains handled by this
+  # host. The line "domains = +local_domains" restricts it to domains that are
+  # defined by the "domainlist local_domains" setting above. The rule  blocks
+  # local parts that begin with a dot or contain @ % ! / or |. If you have
+  # local accounts that include these characters, you will have to modify this
+  # rule.
+
+  deny    message       = Restricted characters in address
+          domains       = +local_domains
+          local_parts   = ^[.] : ^.*[@%!/|]
+
+  # The second rule applies to all other domains, and is less strict. The line
+  # "domains = !+local_domains" restricts it to domains that are NOT defined by
+  # the "domainlist local_domains" setting above. The exclamation mark is a
+  # negating operator. This rule allows your own users to send outgoing
+  # messages to sites that use slashes and vertical bars in their local parts.
+  # It blocks local parts that begin with a dot, slash, or vertical bar, but
+  # allows these characters within the local part. However, the sequence /../
+  # is barred. The use of @ % and ! is blocked, as before. The motivation here
+  # is to prevent your users (or your users' viruses) from mounting certain
+  # kinds of attack on remote sites.
+
+  deny    message       = Restricted characters in address
+          domains       = !+local_domains
+          local_parts   = ^[./|] : ^.*[@%!] : ^.*/\\.\\./
+  #############################################################################
+
+  # Accept mail to postmaster in any local domain, regardless of the source,
+  # and without verifying the sender.
+
+  accept  local_parts   = postmaster
+          domains       = +local_domains
+
+  # Deny incoming mail unless the sender address can be verified.
+
+  deny   !hosts         = +relay_from_hosts
+         !verify        = sender/callout/defer_ok
+
+  # Accept if the message comes from one of the hosts for which we are an
+  # outgoing relay. It is assumed that such hosts are most likely to be MUAs,
+  # so we set control=submission to make Exim treat the message as a
+  # submission. It will fix up various errors in the message, for example, the
+  # lack of a Date: header line. If you are actually relaying out out from
+  # MTAs, you may want to disable this. If you are handling both relaying from
+  # MTAs and submissions from MUAs you should probably split them into two
+  # lists, and handle them differently.
+
+  # Recipient verification is omitted here, because in many cases the clients
+  # are dumb MUAs that don't cope well with SMTP error responses. If you are
+  # actually relaying out from MTAs, you should probably add recipient
+  # verification here.
+
+  # Note that, by putting this test before any DNS black list checks, you will
+  # always accept from these hosts, even if they end up on a black list. The
+  # assumption is that they are your friends, and if they get onto a black
+  # list, it is a mistake.
+
+  accept  hosts         = +relay_from_hosts
+          control       = submission
+<% if node[:lsb][:release].to_i >= 10.04 -%>
+          control       = dkim_disable_verify
+<% end -%>
+
+  # Accept if the message arrived over an authenticated connection, from
+  # any host. Again, these messages are usually from MUAs, so recipient
+  # verification is omitted, and submission mode is set. And again, we do this
+  # check before any black list tests.
+
+  accept  authenticated = *
+          control       = submission
+<% if node[:lsb][:release].to_i >= 10.04 -%>
+          control       = dkim_disable_verify
+<% end -%>
+
+  # Insist that any other recipient address that we accept is either in one of
+  # our local domains, or is in a domain for which we explicitly allow
+  # relaying. Any other domain is rejected as being unacceptable for relaying.
+
+  require message = relay not permitted
+          domains = +local_domains : +relay_to_domains
+
+  # We also require all accepted addresses to be verifiable. This check will
+  # do local part verification for local domains, but only check the domain
+  # for remote domains. The only way to check local parts for the remote
+  # relay domains is to use a callout (add /callout), but please read the
+  # documentation about callouts before doing this.
+
+  require verify = recipient
+
+<% if node[:exim][:dns_blacklists] -%>
+  # Deny any messages from hosts in certain blacklists.
+
+  deny    message       = Rejected because $sender_host_address is in a black list at $dnslist_domain\n$dnslist_text
+          dnslists      = <%= node[:exim][:dns_blacklists].join(" : ") %>
+
+<% end -%>
+  #############################################################################
+  # This check is commented out because it is recognized that not every
+  # sysadmin will want to do it. If you enable it, the check performs
+  # Client SMTP Authorization (csa) checks on the sending host. These checks
+  # do DNS lookups for SRV records. The CSA proposal is currently (May 2005)
+  # an Internet draft. You can, of course, add additional conditions to this
+  # ACL statement to restrict the CSA checks to certain hosts only.
+  #
+  # require verify = csa
+  #############################################################################
+
+  # At this point, the address has passed all the checks that have been
+  # configured, so we accept it unconditionally.
+
+  accept
+
+
+# This ACL is used after the contents of a message have been received. This
+# is the ACL in which you can test a message's headers or body, and in
+# particular, this is where you can invoke external virus or spam scanners.
+# Some suggested ways of configuring these tests are shown below, commented
+# out. Without any tests, this ACL accepts all messages. If you want to use
+# such tests, you must ensure that Exim is compiled with the content-scanning
+# extension (WITH_CONTENT_SCAN=yes in Local/Makefile).
+
+acl_check_data:
+
+<% if File.exist?("/var/run/clamav/clamd.ctl") -%>
+  # Deny if the message contains a virus. Before enabling this check, you
+  # must install a virus scanner and set the av_scanner option above.
+  #
+  deny    demime     = *
+          malware    = *
+          message    = This message contains a virus ($malware_name).
+
+<% end -%>
+<% if File.exist?("/var/run/spamd.pid") -%>
+  # Deny if the message looks like spam. Before enabling this check, you
+  # must install spamassassin and set the spamd_address option above.
+  #
+  deny    spam       = nobody/deferok
+          message    = This message scored $spam_score SpamAssassin points.
+
+<% end -%>
+  # Accept the message.
+
+  accept
+
+
+
+######################################################################
+#                      ROUTERS CONFIGURATION                         #
+#               Specifies how addresses are handled                  #
+######################################################################
+#     THE ORDER IN WHICH THE ROUTERS ARE DEFINED IS IMPORTANT!       #
+# An address is passed to each router in turn until it is accepted.  #
+######################################################################
+
+begin routers
+
+# This router handles aliasing using a linearly searched alias file with the
+# name /etc/aliases. When this configuration is installed automatically,
+# the name gets inserted into this file from whatever is set in Exim's
+# build-time configuration. The default path is the traditional /etc/aliases.
+# If you install this configuration by hand, you need to specify the correct
+# path in the "data" setting below.
+#
+##### NB  You must ensure that the alias file exists. It used to be the case
+##### NB  that every Unix had that file, because it was the Sendmail default.
+##### NB  These days, there are systems that don't have it. Your aliases
+##### NB  file should at least contain an alias for "postmaster".
+#
+# If any of your aliases expand to pipes or files, you will need to set
+# up a user and a group for these deliveries to run under. You can do
+# this by uncommenting the "user" option below (changing the user name
+# as appropriate) and adding a "group" option if necessary. Alternatively, you
+# can specify "user" on the transports that are used. Note that the transports
+# listed below are the same as are used for .forward files; you might want
+# to set up different ones for pipe and file deliveries from aliases.
+
+system_aliases:
+  driver = redirect
+  domains = +local_domains
+  allow_fail
+  allow_defer
+  data = ${lookup{$local_part}lsearch{/etc/aliases}}
+# user = exim
+  file_transport = address_file
+  pipe_transport = address_pipe
+
+<% if File.directory?("/var/lib/mailman") -%>
+# This router handles mail for mailman mailing lists.
+
+mailman:
+  driver = accept
+  domains = +local_domains
+  condition = ${lookup{$local_part@$domain}lsearch{/var/lib/mailman/data/virtual-mailman}{1}{0}}
+  require_files = /var/lib/mailman/lists/$local_part/config.pck
+  local_part_suffix = -bounces : -bounces+* : \
+                      -confirm+* : -join : -leave : \
+                      -subscribe : -unsubscribe : \
+                      -owner : -request : -admin 
+  local_part_suffix_optional
+  transport = mailman
+
+<% end -%>
+# This router handles mail for noreply.openstreetmap.org
+
+noreply:
+  driver = accept
+  domains = noreply.openstreetmap.org
+  require_files = /etc/exim4/noreply/$local_part
+  transport = noreply
+
+<% node[:exim][:routes].each do |name,details| -%>
+# This router handles mail for <%= details[:comment] -%>.
+
+<%= name -%>:
+<% if details[:host] -%>
+  driver = manualroute
+<% else -%>
+  driver = accept
+<% end -%>
+<% if details[:domains] -%>
+  domains = <%= details[:domains].join(" : ") %>
+<% end -%>
+<% if details[:local_parts] -%>
+  local_parts = <%= details[:local_parts].join(" : ") %>
+<% end -%>
+<% if details[:host] -%>
+<% if details[:host].kind_of?(Array) -%>
+  route_data = <%= details[:host].join(":") %> byname
+<% else -%>
+  route_data = <%= details[:host] %> byname
+<% end -%>
+  transport = remote_smtp
+<% else -%>
+  transport = <%= name %>
+<% end -%>
+
+<% end -%>
+
+<% if node[:exim][:smarthost_via] -%>
+# This router routes addresses that are not in local domains by
+# forwarding them to a smarthost.
+
+smarthost:
+  driver = manualroute
+  domains = ! +local_domains
+  transport = remote_smtp
+  route_data = <%= node[:exim][:smarthost_via].gsub(":", "::") -%> byname
+  same_domain_copy_routing = yes
+  no_more
+<% else -%>
+# This router routes addresses that are not in local domains by doing a DNS
+# lookup on the domain name. The exclamation mark that appears in "domains = !
+# +local_domains" is a negating operator, that is, it can be read as "not". The
+# recipient's domain must not be one of those defined by "domainlist
+# local_domains" above for this router to be used.
+#
+# If the router is used, any domain that resolves to 0.0.0.0 or to a loopback
+# interface address (127.0.0.0/8) is treated as if it had no DNS entry. Note
+# that 0.0.0.0 is the same as 0.0.0.0/32, which is commonly treated as the
+# local host inside the network stack. It is not 0.0.0.0/0, the default route.
+# If the DNS lookup fails, no further routers are tried because of the no_more
+# setting, and consequently the address is unrouteable.
+
+dnslookup:
+  driver = dnslookup
+  domains = ! +local_domains
+  transport = remote_smtp
+  same_domain_copy_routing = yes
+  ignore_target_hosts = 0.0.0.0 : 127.0.0.0/8
+  no_more
+<% end -%>
+
+
+######################################################################
+#                      TRANSPORTS CONFIGURATION                      #
+######################################################################
+#                       ORDER DOES NOT MATTER                        #
+#     Only one appropriate transport is called for each delivery.    #
+######################################################################
+
+# A transport is used only when referenced from a router that successfully
+# handles an address.
+
+begin transports
+
+
+# This transport is used for delivering messages over SMTP connections.
+
+remote_smtp:
+  driver = smtp
+
+
+# This transport is used for handling pipe deliveries generated by alias or
+# .forward files. If the pipe generates any standard output, it is returned
+# to the sender of the message as a delivery error. Set return_fail_output
+# instead of return_output if you want this to happen only when the pipe fails
+# to complete normally. You can set different transports for aliases and
+# forwards if you want to - see the references to address_pipe in the routers
+# section above.
+
+address_pipe:
+  driver = pipe
+  return_output
+
+
+# This transport is used for handling deliveries directly to files that are
+# generated by aliasing or forwarding.
+
+address_file:
+  driver = appendfile
+  delivery_date_add
+  envelope_to_add
+  return_path_add
+
+
+<% if File.directory?("/var/lib/mailman") -%>
+# This transport is used for handling deliveries to mailman mailing lists.
+
+mailman:
+  driver = pipe
+  command = /var/lib/mailman/mail/mailman \
+            '${if def:local_part_suffix \
+                  {${sg{$local_part_suffix}{-(\\w+)(\\+.*)?}{\$1}}} \
+                  {post}}' \
+            $local_part
+  current_directory = /var/lib/mailman
+  home_directory = /var/lib/mailman
+  user = list
+  group = daemon
+  freeze_exec_fail = true
+
+
+<% end -%>
+# This transport handles mail for noreply.openstreetmap.org
+
+noreply:
+  driver = autoreply
+  from = OpenStreetMap <noreply@openstreetmap.org>
+  to = $sender_address
+  subject = Re: $header_subject:
+  headers = MIME-Version: 1.0\nContent-Type: text/plain; charset=utf-8
+  file = /etc/exim4/noreply/$local_part
+  user = Debian-exim
+  group = Debian-exim
+
+<% node[:exim][:routes].each do |name,details| -%>
+<% if details[:command] -%>
+# This transport handles mail for <%= details[:comment] -%>.
+
+<%= name -%>:
+  driver = pipe
+  command = <%= details[:command] %>
+  user = <%= details[:user] %>
+<% if details[:group] -%>
+  group = <%= details[:group] %>
+<% end -%>
+  home_directory = <%= details[:home_directory] %>
+  return_output
+
+
+<% end -%>
+<% end -%>
+
+######################################################################
+#                      RETRY CONFIGURATION                           #
+######################################################################
+
+begin retry
+
+# This single retry rule applies to all domains and all errors. It specifies
+# retries every 15 minutes for 2 hours, then increasing retry intervals,
+# starting at 1 hour and increasing each time by a factor of 1.5, up to 16
+# hours, then retries every 6 hours until 4 days have passed since the first
+# failed delivery.
+
+# WARNING: If you do not have any retry rules at all (this section of the
+# configuration is non-existent or empty), Exim will not do any retries of
+# messages that fail to get delivered at the first attempt. The effect will
+# be to treat temporary errors as permanent. Therefore, DO NOT remove this
+# retry rule unless you really don't want any retries.
+
+# Address or Domain    Error       Retries
+# -----------------    -----       -------
+
+*                      *           F,2h,15m; G,16h,1h,1.5; F,4d,6h
+
+
+
+######################################################################
+#                      REWRITE CONFIGURATION                         #
+######################################################################
+
+# There are no rewriting specifications in this default configuration file.
+
+begin rewrite
+
+
+
+######################################################################
+#                   AUTHENTICATION CONFIGURATION                     #
+######################################################################
+
+# The following authenticators support plaintext username/password
+# authentication using the standard PLAIN mechanism and the traditional
+# but non-standard LOGIN mechanism, with Exim acting as the server.
+# PLAIN and LOGIN are enough to support most MUA software.
+#
+# These authenticators are not complete: you need to change the
+# server_condition settings to specify how passwords are verified.
+# They are set up to offer authentication to the client only if the
+# connection is encrypted with TLS, so you also need to add support
+# for TLS. See the global configuration options section at the start
+# of this file for more about TLS.
+#
+# The default RCPT ACL checks for successful authentication, and will accept
+# messages from authenticated users from anywhere on the Internet.
+
+begin authenticators
+
+# PLAIN authentication has no server prompts. The client sends its
+# credentials in one lump, containing an authorization ID (which we do not
+# use), an authentication ID, and a password. The latter two appear as
+# $auth2 and $auth3 in the configuration and should be checked against a
+# valid username and password. In a real configuration you would typically
+# use $auth2 as a lookup key, and compare $auth3 against the result of the
+# lookup, perhaps using the crypteq{}{} condition.
+
+#PLAIN:
+#  driver                     = plaintext
+#  server_set_id              = $auth2
+#  server_prompts             = :
+#  server_condition           = Authentication is not yet configured
+#  server_advertise_condition = ${if def:tls_cipher }
+
+# LOGIN authentication has traditional prompts and responses. There is no
+# authorization ID in this mechanism, so unlike PLAIN the username and
+# password are $auth1 and $auth2. Apart from that you can use the same
+# server_condition setting for both authenticators.
+
+#LOGIN:
+#  driver                     = plaintext
+#  server_set_id              = $auth1
+#  server_prompts             = <| Username: | Password:
+#  server_condition           = Authentication is not yet configured
+#  server_advertise_condition = ${if def:tls_cipher }
+
+
+######################################################################
+#                   CONFIGURATION FOR local_scan()                   #
+######################################################################
+
+# If you have built Exim to include a local_scan() function that contains
+# tables for private options, you can define those options here. Remember to
+# uncomment the "begin" line. It is commented by default because it provokes
+# an error with Exim binaries that are not built with LOCAL_SCAN_HAS_OPTIONS
+# set in the Local/Makefile.
+
+# begin local_scan
+
+
+# End of Exim configuration file
diff --git a/cookbooks/foundation/README.rdoc b/cookbooks/foundation/README.rdoc
new file mode 100644 (file)
index 0000000..3de2ec7
--- /dev/null
@@ -0,0 +1,8 @@
+= DESCRIPTION:
+
+= REQUIREMENTS:
+
+= ATTRIBUTES:
+
+= USAGE:
+
diff --git a/cookbooks/foundation/metadata.rb b/cookbooks/foundation/metadata.rb
new file mode 100644 (file)
index 0000000..90a2dea
--- /dev/null
@@ -0,0 +1,7 @@
+maintainer        "OpenStreetMap Administrators"
+maintainer_email  "admins@openstreetmap.org"
+license           "Apache 2.0"
+description       "Installs and configures Foundation services"
+long_description  IO.read(File.join(File.dirname(__FILE__), 'README.rdoc'))
+version           "1.0.0"
+depends           "wordpress"
diff --git a/cookbooks/foundation/recipes/default.rb b/cookbooks/foundation/recipes/default.rb
new file mode 100644 (file)
index 0000000..7b1fa1d
--- /dev/null
@@ -0,0 +1,50 @@
+#
+# Cookbook Name:: foundation
+# Recipe:: default
+#
+# Copyright 2013, OpenStreetMap Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+include_recipe "wordpress"
+
+passwords = data_bag_item("foundation", "passwords")
+
+wordpress_site "blog.osmfoundation.org" do
+  database_name "osmf-blog"
+  database_user "osmf-blog-user"
+  database_password passwords["osmf-blog-user"]
+end
+
+wordpress_theme "osmf-blog-theme" do
+  site "blog.osmfoundation.org"
+  repository "http://svn.openstreetmap.org/extensions/wordpress/osmf-blog-theme"
+end
+
+wordpress_plugin "google-analytics-for-wordpress" do
+  site "blog.osmfoundation.org"
+end
+
+wordpress_plugin "google-sitemap-generator" do
+  site "blog.osmfoundation.org"
+end
+
+wordpress_plugin "shareadraft" do
+  site "blog.osmfoundation.org"
+end
+
+wordpress_plugin "sitepress-multilingual-cms" do
+  site "blog.osmfoundation.org"
+  source "plugins/sitepress-multilingual-cms"
+end
diff --git a/cookbooks/git/README.rdoc b/cookbooks/git/README.rdoc
new file mode 100644 (file)
index 0000000..3de2ec7
--- /dev/null
@@ -0,0 +1,8 @@
+= DESCRIPTION:
+
+= REQUIREMENTS:
+
+= ATTRIBUTES:
+
+= USAGE:
+
diff --git a/cookbooks/git/metadata.rb b/cookbooks/git/metadata.rb
new file mode 100644 (file)
index 0000000..1b30312
--- /dev/null
@@ -0,0 +1,21 @@
+maintainer        "OpenStreetMap Administrators"
+maintainer_email  "admins@openstreetmap.org"
+license           "Apache 2.0"
+description       "Installs and configures git"
+long_description  IO.read(File.join(File.dirname(__FILE__), 'README.rdoc'))
+version           "1.0.0"
+depends           "networking"
+depends           "apache"
+
+attribute "git",
+  :display_name => "Git",
+  :description => "Hash of Git attributes",
+  :type => "hash"
+
+attribute "git/host",
+  :display_name => "Server Hostname",
+  :description => "Hostname to use for Git server"
+
+attribute "git/directory",
+  :display_name => "Repository Directory",
+  :description => "Directory to use for Git server repositories"
diff --git a/cookbooks/git/recipes/default.rb b/cookbooks/git/recipes/default.rb
new file mode 100644 (file)
index 0000000..63dea75
--- /dev/null
@@ -0,0 +1,20 @@
+#
+# Cookbook Name:: git
+# Recipe:: default
+#
+# Copyright 2011, OpenStreetMap Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+package "git-core"
diff --git a/cookbooks/git/recipes/server.rb b/cookbooks/git/recipes/server.rb
new file mode 100644 (file)
index 0000000..c3382a2
--- /dev/null
@@ -0,0 +1,73 @@
+#
+# Cookbook Name:: git
+# Recipe:: server
+#
+# Copyright 2011, OpenStreetMap Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+include_recipe "apache"
+include_recipe "networking"
+
+package "gitweb"
+
+apache_module "rewrite"
+
+git_directory = node[:git][:directory]
+
+directory git_directory do
+  owner "git"
+  group "git"
+  mode 02775
+end
+
+template "/etc/gitweb.conf" do
+  source "gitweb.conf.erb"
+  owner "root"
+  group "root"
+  mode 0644
+end
+
+apache_site node[:git][:host] do
+  template "apache.erb"
+  directory git_directory
+end
+
+firewall_rule "accept-git" do
+  action :accept
+  source "net"
+  dest "fw"
+  proto "tcp:syn"
+  dest_ports "git"
+  source_ports "1024:"
+end
+
+Dir.new(git_directory).select { |name| name =~ /\.git$/ }.each do |repository|
+  template "#{git_directory}/#{repository}/hooks/post-update" do
+    source "post-update.erb"
+    owner "root"
+    group "git"
+    mode 0755
+  end
+
+  if repository != "dns.git"
+    template "#{git_directory}/#{repository}/hooks/post-receive" do
+      source "post-receive.erb"
+      owner "root"
+      group "git"
+      mode 0755
+      variables :repository => "#{git_directory}/#{repository}"
+    end
+  end
+end
diff --git a/cookbooks/git/templates/default/apache.erb b/cookbooks/git/templates/default/apache.erb
new file mode 100644 (file)
index 0000000..e9cb8b7
--- /dev/null
@@ -0,0 +1,18 @@
+# DO NOT EDIT - This file is being maintained by Chef
+
+<VirtualHost *:80>
+       ServerName <%= @name %>
+
+       CustomLog /var/log/apache2/<%= @name %>-access.log combined
+       ErrorLog /var/log/apache2/<%= @name %>-error.log
+
+       DocumentRoot <%= @directory %>
+       HeaderName HEADER
+       Alias /gitweb /usr/share/gitweb
+       Alias /git /var/cache/git
+       ScriptAlias /gitweb.cgi /usr/lib/cgi-bin/gitweb.cgi
+
+       RewriteEngine On
+       RewriteRule ^/$ /gitweb.cgi%{REQUEST_URI} [L,PT]
+       RewriteRule ^/(.*\.git/(?!/?(HEAD|info|objects|refs)).*)?$ /gitweb.cgi%{REQUEST_URI} [L,PT]
+</VirtualHost>
diff --git a/cookbooks/git/templates/default/gitweb.conf.erb b/cookbooks/git/templates/default/gitweb.conf.erb
new file mode 100644 (file)
index 0000000..b98c15a
--- /dev/null
@@ -0,0 +1,34 @@
+# DO NOT EDIT - This file is being maintained by Chef
+
+# path to git projects (<project>.git)
+$projectroot = "<%= node[:git][:directory] %>";
+
+# directory to use for temp files
+$git_temp = "/tmp";
+
+# target of the home link on top of all pages
+#$home_link = $my_uri || "/";
+
+# html text to include at home page
+$home_text = "indextext.html";
+
+# file with project list; by default, simply scan the projectroot dir.
+$projects_list = $projectroot;
+
+# stylesheet to use
+$stylesheet = "/gitweb/static/gitweb.css";
+
+# logo to use
+$logo = "/gitweb/static/git-logo.png";
+
+# the 'favicon'
+$favicon = "/gitweb/static/git-favicon.png";
+
+# URI of gitweb.js (JavaScript code for gitweb)
+our $javascript = "/gitweb/static/gitweb.js";
+
+# use pretty urls
+$feature{'pathinfo'}{'default'} = [1];
+
+# define roots for cloning
+@git_base_url_list = qw(git://<%= node[:git][:host] %>);
diff --git a/cookbooks/git/templates/default/post-receive.erb b/cookbooks/git/templates/default/post-receive.erb
new file mode 100644 (file)
index 0000000..52075a0
--- /dev/null
@@ -0,0 +1,14 @@
+#!/bin/zsh
+
+# DO NOT EDIT - This file is being maintained by Chef
+
+while read oldrev newrev refname
+do
+  if [[ "$refname" = "refs/heads/master" ]]
+  then
+    for rev in $(git rev-list ${newrev} ^${oldrev})
+    do
+      sudo -u trac /usr/bin/trac-admin /var/lib/trac changeset added "<%= @repository %>" "${rev}"
+    done
+  fi
+done
diff --git a/cookbooks/git/templates/default/post-update.erb b/cookbooks/git/templates/default/post-update.erb
new file mode 100644 (file)
index 0000000..40ebafa
--- /dev/null
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+# DO NOT EDIT - This file is being maintained by Chef
+
+exec git-update-server-info
diff --git a/cookbooks/mailman/README.rdoc b/cookbooks/mailman/README.rdoc
new file mode 100644 (file)
index 0000000..3de2ec7
--- /dev/null
@@ -0,0 +1,8 @@
+= DESCRIPTION:
+
+= REQUIREMENTS:
+
+= ATTRIBUTES:
+
+= USAGE:
+
diff --git a/cookbooks/mailman/metadata.rb b/cookbooks/mailman/metadata.rb
new file mode 100644 (file)
index 0000000..2cee98b
--- /dev/null
@@ -0,0 +1,7 @@
+maintainer        "OpenStreetMap Administrators"
+maintainer_email  "admins@openstreetmap.org"
+license           "Apache 2.0"
+description       "Installs and configures mailman"
+long_description  IO.read(File.join(File.dirname(__FILE__), 'README.rdoc'))
+version           "1.0.0"
+depends           "apache"
diff --git a/cookbooks/mailman/recipes/default.rb b/cookbooks/mailman/recipes/default.rb
new file mode 100644 (file)
index 0000000..05f1997
--- /dev/null
@@ -0,0 +1,34 @@
+#
+# Cookbook Name:: mailman
+# Recipe:: default
+#
+# Copyright 2011, OpenStreetMap Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+include_recipe "apache"
+
+package "mailman"
+
+service "mailman" do
+  action [ :enable, :start ]
+  supports :restart => true, :reload => true
+end
+
+apache_module "expires"
+apache_module "rewrite"
+
+apache_site "lists.openstreetmap.org" do
+  template "apache.erb"
+end
diff --git a/cookbooks/mailman/templates/default/apache.erb b/cookbooks/mailman/templates/default/apache.erb
new file mode 100644 (file)
index 0000000..396bcd5
--- /dev/null
@@ -0,0 +1,49 @@
+# DO NOT EDIT - This file is being maintained by Chef
+
+<VirtualHost *:80>
+       ServerName <%= @name %>
+       ServerAdmin postmaster@openstreetmap.org
+       ServerSignature On
+
+       CustomLog /var/log/apache2/<%= @name %>-access.log combined
+       ErrorLog /var/log/apache2/<%= @name %>-error.log
+       LogLevel warn
+
+        AddDefaultCharset off
+
+       DocumentRoot <%= @directory %>
+
+       RewriteEngine on
+
+       RewriteCond %{HTTP_REFERER} www\.mailbait\.info
+       RewriteRule . - [F,L]
+
+       RedirectMatch ^/$ /listinfo
+       RedirectMatch ^/cgi-bin/mailman/(.*)$ /$1
+
+       <Directory /var/lib/mailman/archives/>
+               Options Indexes FollowSymLinks
+               AllowOverride None
+       </Directory>
+
+       Alias /pipermail/ /var/lib/mailman/archives/public/
+       Alias /images/ /usr/share/images/mailman/
+
+       ScriptAlias /admin /usr/lib/cgi-bin/mailman/admin
+       ScriptAlias /admindb /usr/lib/cgi-bin/mailman/admindb
+       ScriptAlias /confirm /usr/lib/cgi-bin/mailman/confirm
+       ScriptAlias /create /usr/lib/cgi-bin/mailman/create
+       ScriptAlias /edithtml /usr/lib/cgi-bin/mailman/edithtml
+       ScriptAlias /listinfo /usr/lib/cgi-bin/mailman/listinfo
+       ScriptAlias /options /usr/lib/cgi-bin/mailman/options
+       ScriptAlias /private /usr/lib/cgi-bin/mailman/private
+       ScriptAlias /rmlist /usr/lib/cgi-bin/mailman/rmlist
+       ScriptAlias /roster /usr/lib/cgi-bin/mailman/roster
+       ScriptAlias /subscribe /usr/lib/cgi-bin/mailman/subscribe
+       ScriptAlias /mailman/ /usr/lib/cgi-bin/mailman/
+
+       <Location ~ "/pipermail/([^/]+)/(2004|2005|2006|2007|2008|2009)">
+               ExpiresActive On
+               ExpiresDefault "access plus 180 days"
+       </Location>
+</VirtualHost>
diff --git a/cookbooks/mysql/README.rdoc b/cookbooks/mysql/README.rdoc
new file mode 100644 (file)
index 0000000..3de2ec7
--- /dev/null
@@ -0,0 +1,8 @@
+= DESCRIPTION:
+
+= REQUIREMENTS:
+
+= ATTRIBUTES:
+
+= USAGE:
+
diff --git a/cookbooks/mysql/attributes/default.rb b/cookbooks/mysql/attributes/default.rb
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/cookbooks/mysql/libraries/mysql.rb b/cookbooks/mysql/libraries/mysql.rb
new file mode 100644 (file)
index 0000000..c0da28f
--- /dev/null
@@ -0,0 +1,146 @@
+require "chef/mixin/command"
+require "rexml/document"
+
+class Chef
+  class MySQL
+    include Chef::Mixin::Command
+
+    USER_PRIVILEGES = [
+      :select, :insert, :update, :delete, :create, :drop, :reload,
+      :shutdown, :process, :file, :grant, :references, :index, :alter,
+      :show_db, :super, :create_tmp_table, :lock_tables, :execute,
+      :repl_slave, :repl_client, :create_view, :show_view, :create_routine,
+      :alter_routine, :create_user, :event, :trigger, :create_tablespace
+    ]
+
+    DATABASE_PRIVILEGES = [
+      :select, :insert, :update, :delete, :create, :drop, :grant,
+      :references, :index, :alter, :create_tmp_table, :lock_tables,
+      :create_view, :show_view, :create_routine, :alter_routine,
+      :execute, :event, :trigger
+    ]
+
+    def execute(options)
+      # Create argument array
+      args = []
+
+      # Work out how to authenticate
+      if options[:user]
+        args.push("--username=#{options[:user]}")
+        args.push("--password=#{options[:password]}") if options[:password]
+      else
+        args.push("--defaults-file=/etc/mysql/debian.cnf")
+      end
+
+      # Build the other arguments
+      args.push("--execute=\"#{options[:command]}\"") if options[:command]
+
+      # Get the database to use
+      database = options[:database] || "mysql"
+
+      # Build the command to run
+      command = "/usr/bin/mysql #{args.join(' ')} #{database}"
+
+      # Escape backticks in the command
+      command.gsub!(/`/, "\\\\`")
+
+      # Run the command
+      run_command(:command => command, :user => "root", :group => "root")
+    end
+
+    def query(sql, options = {})
+      # Get the database to use
+      database = options[:database] || "mysql"
+
+      # Construct the command string
+      command = "/usr/bin/mysql --defaults-file=/etc/mysql/debian.cnf --xml --execute='#{sql}' #{database}"
+
+      # Run the query
+      status, stdout, stderr = output_of_command(command, :user => "root", :group => "root")
+      handle_command_failures(status, "STDOUT: #{stdout}\nSTDERR: #{stderr}", :output_on_failure => true)
+
+      # Parse the output
+      document = REXML::Document.new(stdout)
+
+      # Create
+      records = []
+
+      # Loop over the rows in the result set
+      document.root.each_element("/resultset/row") do |row|
+        # Create a record
+        record = {}
+
+        # Loop over the fields, adding them to the record
+        row.each_element("field") do |field|
+          name = field.attributes["name"].downcase
+          value = field.text
+
+          record[name.to_sym] = value
+        end
+
+        # Add the record to the record list
+        records << record
+      end
+
+      # Return the record list
+      records
+    end
+
+    def users
+      @users ||= query("SELECT * FROM user").inject({}) do |users,user|
+        name = "'#{user[:user]}'@'#{user[:host]}'"
+
+        users[name] = USER_PRIVILEGES.inject({}) do |privileges,privilege|
+          privileges[privilege] = user["#{privilege}_priv".to_sym] == "Y"
+          privileges
+        end
+
+        users
+      end
+    end
+
+    def databases
+      @databases ||= query("SHOW databases").inject({}) do |databases,database|
+        databases[database[:database]] = {
+          :permissions => {}
+        }
+        databases
+      end
+
+      query("SELECT * FROM db").each do |record|
+        if database = @databases[record[:db]]
+          user = "'#{record[:user]}'@'#{record[:host]}'"
+
+          database[:permissions][user] = DATABASE_PRIVILEGES.inject([]) do |privileges,privilege|
+            privileges << privilege if record["#{privilege}_priv".to_sym] == "Y"
+            privileges
+          end
+        end
+      end
+
+      @databases
+    end
+
+    def canonicalise_user(user)
+      local, host = user.split("@")
+
+      host = "%" unless host
+
+      local = "'#{local}'" unless local =~ /^'.*'$/
+      host = "'#{host}'" unless host =~ /^'.*'$/
+
+      "#{local}@#{host}"
+    end
+
+    def privilege_name(privilege)
+      case privilege
+      when :grant
+        "GRANT OPTION"
+      when :create_tmp_table
+        "CREATE TEMPORARY TABLES"
+      else
+        privilege.to_s.upcase.tr("_", " ")
+      end
+    end
+  end
+end
diff --git a/cookbooks/mysql/metadata.rb b/cookbooks/mysql/metadata.rb
new file mode 100644 (file)
index 0000000..f77dbf8
--- /dev/null
@@ -0,0 +1,11 @@
+maintainer        "OpenStreetMap Administrators"
+maintainer_email  "admins@openstreetmap.org"
+license           "Apache 2.0"
+description       "Installs and configures mysql"
+long_description  IO.read(File.join(File.dirname(__FILE__), 'README.rdoc'))
+version           "1.0.0"
+
+attribute "mysql",
+  :display_name => "MySQL",
+  :description => "Hash of MySQL configuration details",
+  :type => "hash"
diff --git a/cookbooks/mysql/providers/database.rb b/cookbooks/mysql/providers/database.rb
new file mode 100644 (file)
index 0000000..29b38f7
--- /dev/null
@@ -0,0 +1,87 @@
+#
+# Cookbook Name:: mysql
+# Provider:: mysql_database
+#
+# Copyright 2013, OpenStreetMap Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+def load_current_resource
+  @mysql = Chef::MySQL.new
+
+  @current_resource = Chef::Resource::MysqlDatabase.new(new_resource.name)
+  @current_resource.database(new_resource.database)
+  if mysql_database = @mysql.databases[@current_resource.database]
+    @current_resource.permissions(mysql_database[:permissions])
+  end
+  @current_resource
+end
+
+action :create do
+  unless @mysql.databases.include?(new_resource.database)
+    converge_by("create #{new_resource}") do
+      Chef::Log.info("Creating #{new_resource}")
+      @mysql.execute(:command => "CREATE DATABASE `#{new_resource.database}`")
+    end
+  end
+
+  new_permissions = Hash[new_resource.permissions.collect do |user,privileges|
+    [@mysql.canonicalise_user(user), privileges]
+  end]
+
+  @current_resource.permissions.each do |user,privileges|
+    unless new_permissions[user]
+      converge_by("revoke all for #{user} on #{new_resource}") do
+        Chef::Log.info("Revoking all for #{user} on #{new_resource}")
+        @mysql.execute(:command => "REVOKE ALL ON `#{new_resource.database}`.* FROM #{user}")
+      end
+    end
+  end
+
+  new_permissions.each do |user,new_privileges|
+    current_privileges = @current_resource.permissions[user] || {}
+    new_privileges = Array(new_privileges)
+
+    if new_privileges.include?(:all)
+      new_privileges |= (Chef::MySQL::DATABASE_PRIVILEGES - [:grant])
+    end
+
+    Chef::MySQL::DATABASE_PRIVILEGES.each do |privilege|
+      if new_privileges.include?(privilege)
+        unless current_privileges.include?(privilege)
+          converge_by("grant #{privilege} for #{user} on mysql database #{new_resource}") do
+            Chef::Log.info("Granting #{privilege} for #{user} on mysql database #{new_resource}")
+            @mysql.execute(:command => "GRANT #{@mysql.privilege_name(privilege)} ON `#{new_resource.database}`.* TO #{user}")
+          end
+        end
+      else
+        if current_privileges.include?(privilege)
+          converge_by("revoke #{privilege} for #{user} on #{new_resource}") do
+            Chef::Log.info("Revoking #{privilege} for #{user} on #{new_resource}")
+            @mysql.execute(:command => "REVOKE #{@mysql.privilege_name(privilege)} ON `#{new_resource.database}`.* FROM #{user}")
+          end
+        end
+      end
+    end
+  end
+end
+
+action :drop do
+  if @mysql.databases.include?(new_resource.database)
+    converge_by("drop #{new_resource}") do
+      Chef::Log.info("Dropping #{new_resource}")
+      @mysql.execute(:command => "DROP DATABASE `#{new_resource.database}`")
+    end
+  end
+end
diff --git a/cookbooks/mysql/providers/user.rb b/cookbooks/mysql/providers/user.rb
new file mode 100644 (file)
index 0000000..e027b4f
--- /dev/null
@@ -0,0 +1,70 @@
+#
+# Cookbook Name:: mysql
+# Provider:: mysql_user
+#
+# Copyright 2013, OpenStreetMap Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+def load_current_resource
+  @mysql = Chef::MySQL.new
+
+  @current_resource = Chef::Resource::MysqlUser.new(new_resource.name)
+  @current_resource.user(new_resource.user)
+  if mysql_user = @mysql.users[@current_resource.user]
+    Chef::MySQL::USER_PRIVILEGES.each do |privilege|
+      @current_resource.send(privilege, mysql_user[privilege])
+    end
+  end
+  @current_resource
+end
+
+action :create do
+  user = @mysql.canonicalise_user(new_resource.user)
+  password = new_resource.password ? "IDENTIFIED BY '#{new_resource.password}'" : ""
+
+  unless @mysql.users.include?(user)
+    converge_by("create #{new_resource}") do
+      Chef::Log.info("Creating #{new_resource}")
+      @mysql.execute(:command => "CREATE USER #{user} #{password}")
+    end
+  end
+
+  Chef::MySQL::USER_PRIVILEGES.each do |privilege|
+    if new_resource.send(privilege) != @current_resource.send(privilege)
+      if new_resource.send(privilege)
+        converge_by("grant #{privilege} for #{new_resource}") do
+          Chef::Log.info("Granting #{privilege} for #{new_resource}")
+          @mysql.execute(:command => "GRANT #{@mysql.privilege_name(privilege)} ON *.* TO #{user}")
+        end
+      else
+        converge_by("revoke #{privilege} for #{new_resource}") do
+          Chef::Log.info("Revoking #{privilege} for #{new_resource}")
+          @mysql.execute(:command => "REVOKE #{@mysql.privilege_name(privilege)} ON *.* FROM #{user}")
+        end
+      end
+    end
+  end
+end
+
+action :drop do
+  user = @mysql.canonicalise_user(new_resource.user)
+
+  if @mysql.users.include?(user)
+    converge_by("drop #{new_resource}") do
+      Chef::Log.info("Dropping #{new_resource}")
+      @mysql.execute(:command => "DROP USER #{user}")
+    end
+  end
+end
diff --git a/cookbooks/mysql/recipes/default.rb b/cookbooks/mysql/recipes/default.rb
new file mode 100644 (file)
index 0000000..d56fbdc
--- /dev/null
@@ -0,0 +1,129 @@
+#
+# Cookbook Name:: mysql
+# Recipe:: default
+#
+# Copyright 2013, OpenStreetMap Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+package "mysql-server"
+package "mysql-client"
+
+service "mysql" do
+  action [ :enable, :start ]
+  supports :status => true, :restart => true, :reload => true
+end
+
+template "/etc/mysql/conf.d/chef.cnf" do
+  source "my.cnf.erb"
+  owner "root"
+  group "root"
+  mode 0644
+  notifies :reload, resources(:service => "mysql")
+end
+
+package "libdbd-mysql-perl"
+package "libcache-cache-perl"
+
+munin_plugin "mysql_bin_relay_log" do
+  target "mysql_"
+end
+
+munin_plugin "mysql_commands" do
+  target "mysql_"
+end
+
+munin_plugin "mysql_connections" do
+  target "mysql_"
+end
+
+munin_plugin "mysql_files_tables" do
+  target "mysql_"
+end
+
+munin_plugin "mysql_innodb_bpool" do
+  target "mysql_"
+end
+
+munin_plugin "mysql_innodb_bpool_act" do
+  target "mysql_"
+end
+
+munin_plugin "mysql_innodb_insert_buf" do
+  target "mysql_"
+end
+
+munin_plugin "mysql_innodb_io" do
+  target "mysql_"
+end
+
+munin_plugin "mysql_innodb_io_pend" do
+  target "mysql_"
+end
+
+munin_plugin "mysql_innodb_log" do
+  target "mysql_"
+end
+
+munin_plugin "mysql_innodb_rows" do
+  target "mysql_"
+end
+
+munin_plugin "mysql_innodb_semaphores" do
+  target "mysql_"
+end
+
+munin_plugin "mysql_innodb_tnx" do
+  target "mysql_"
+end
+
+munin_plugin "mysql_myisam_indexes" do
+  target "mysql_"
+end
+
+munin_plugin "mysql_network_traffic" do
+  target "mysql_"
+end
+
+munin_plugin "mysql_qcache" do
+  target "mysql_"
+end
+
+munin_plugin "mysql_qcache_mem" do
+  target "mysql_"
+end
+
+munin_plugin "mysql_replication" do
+  target "mysql_"
+end
+
+munin_plugin "mysql_select_types" do
+  target "mysql_"
+end
+
+munin_plugin "mysql_slow" do
+  target "mysql_"
+end
+
+munin_plugin "mysql_sorts" do
+  target "mysql_"
+end
+
+munin_plugin "mysql_table_locks" do
+  target "mysql_"
+end
+
+munin_plugin "mysql_tmp_tables" do
+  target "mysql_"
+end
diff --git a/cookbooks/mysql/resources/database.rb b/cookbooks/mysql/resources/database.rb
new file mode 100644 (file)
index 0000000..60236d8
--- /dev/null
@@ -0,0 +1,24 @@
+#
+# Cookbook Name:: mysql
+# Resource:: mysql_database
+#
+# Copyright 2013, OpenStreetMap Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+actions :create, :drop
+default_action :create
+
+attribute :database, :kind_of => String, :name_attribute => true
+attribute :permissions, :kind_of => Hash, :default => {}
diff --git a/cookbooks/mysql/resources/user.rb b/cookbooks/mysql/resources/user.rb
new file mode 100644 (file)
index 0000000..45436c7
--- /dev/null
@@ -0,0 +1,28 @@
+#
+# Cookbook Name:: mysql
+# Resource:: mysql_user
+#
+# Copyright 2012, OpenStreetMap Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+actions :create, :drop
+default_action :create
+
+attribute :user, :kind_of => String, :name_attribute => true
+attribute :password, :kind_of => String
+
+Chef::MySQL::USER_PRIVILEGES.each do |privilege|
+  attribute privilege, :default => false
+end
diff --git a/cookbooks/mysql/templates/default/my.cnf.erb b/cookbooks/mysql/templates/default/my.cnf.erb
new file mode 100644 (file)
index 0000000..a03aebc
--- /dev/null
@@ -0,0 +1 @@
+# DO NOT EDIT - This file is being maintained by Chef
diff --git a/cookbooks/networking/README.md b/cookbooks/networking/README.md
new file mode 100644 (file)
index 0000000..6b08769
--- /dev/null
@@ -0,0 +1,57 @@
+DESCRIPTION
+===========
+
+Configures networking.
+
+USAGE
+=====
+
+Set the networking attributes in a role, for example from my base.rb:
+
+    :networking => {
+      :nameservers => [ "10.13.37.120", "10.13.37.40" ],
+      :search => [ "int.example.org". "example.org" ]
+    }
+
+The resulting /etc/resolv.conf will look like:
+
+    search int.example.org example.org
+    nameserver 10.13.37.120
+    nameserver 10.13.37.40
+
+LICENSE AND AUTHOR
+==================
+
+Author:: OpenStreetMap Administrators (<admins@openstreetmap.org>)
+
+Copyright 2010, OpenStreetMap Foundation.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+Based on resolver cookbook:
+
+Author:: Joshua Timberman (<joshua@opscode.com>)
+
+Copyright 2009, Opscode, Inc.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff --git a/cookbooks/networking/attributes/default.rb b/cookbooks/networking/attributes/default.rb
new file mode 100644 (file)
index 0000000..9a03eb3
--- /dev/null
@@ -0,0 +1,3 @@
+default[:networking][:interfaces] = { }
+default[:networking][:nameservers] = [ ]
+default[:networking][:search] = [ ]
diff --git a/cookbooks/networking/definitions/firewall_rule.rb b/cookbooks/networking/definitions/firewall_rule.rb
new file mode 100644 (file)
index 0000000..44d1418
--- /dev/null
@@ -0,0 +1,52 @@
+#
+# Cookbook Name:: networking
+# Definition:: firewall_rule
+#
+# Copyright 2011, OpenStreetMap Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+define :firewall_rule, :action => :accept do
+  inet = nil
+  inet6 = nil
+
+  begin
+    inet = resources(:template => "/etc/shorewall/rules")
+    inet6 = resources(:template => "/etc/shorewall6/rules")
+  rescue
+  end
+
+  rule = Hash[
+    :action => params[:action].to_s.upcase,
+    :source => params[:source],
+    :dest => params[:dest],
+    :proto => params[:proto],
+    :dest_ports => params[:dest_ports] || "-",
+    :source_ports => params[:source_ports] || "-",
+    :rate_limit => params[:rate_limit] || "-"
+  ]
+
+  if params[:family].nil?
+    inet.variables[:rules] << rule unless inet.nil?
+    inet6.variables[:rules] << rule unless inet6.nil?
+  elsif params[:family].to_s == "inet"
+    inet.variables[:rules] << rule unless inet.nil?
+  elsif params[:family].to_s == "inet6"
+    inet6.variables[:rules] << rule unless inet6.nil?
+  else
+    log "Unsupported network family" do
+      level :error
+    end
+  end
+end
diff --git a/cookbooks/networking/libraries/interfaces.rb b/cookbooks/networking/libraries/interfaces.rb
new file mode 100644 (file)
index 0000000..cc9c11a
--- /dev/null
@@ -0,0 +1,24 @@
+class Chef
+  class Node
+    def interfaces(options = {}, &block)
+      interfaces = []
+
+      networking = construct_attributes[:networking] || {}
+      networking_interfaces = networking[:interfaces] || []
+
+      networking_interfaces.each do |name,interface|
+        if options[:role].nil? or interface[:role].to_s == options[:role].to_s
+          if options[:family].nil? or interface[:family].to_s == options[:family].to_s
+            if block.nil?
+              interfaces << interface
+            else
+              block.call(interface)
+            end
+          end
+        end
+      end
+
+      interfaces
+    end
+  end
+end
diff --git a/cookbooks/networking/libraries/ipaddresses.rb b/cookbooks/networking/libraries/ipaddresses.rb
new file mode 100644 (file)
index 0000000..811c818
--- /dev/null
@@ -0,0 +1,25 @@
+class Chef
+  class Node
+    def ipaddresses(options = {}, &block)
+      addresses = []
+
+      interfaces(options).each do |interface|
+        if block.nil?
+          addresses << interface[:address]
+        else
+          block.call(interface[:address])
+        end
+      end
+
+      addresses
+    end
+
+    def internal_ipaddress
+      return ipaddresses(:role => :internal).first
+    end
+
+    def external_ipaddress
+      return ipaddresses(:role => :external).first
+    end
+  end
+end
diff --git a/cookbooks/networking/metadata.rb b/cookbooks/networking/metadata.rb
new file mode 100644 (file)
index 0000000..df97c45
--- /dev/null
@@ -0,0 +1,25 @@
+maintainer        "OpenStreetMap Administrators"
+maintainer_email  "admins@openstreetmap.org"
+license           "Apache 2.0"
+description       "Configures networking"
+long_description  IO.read(File.join(File.dirname(__FILE__), 'README.md'))
+version           "1.0.0"
+recipe            "networking", "Configures networking via attributes"
+supports          "ubuntu"
+
+attribute "networking",
+  :display_name => "Networking",
+  :description => "Hash of networking attributes",
+  :type => "hash"
+
+attribute "networking/search",
+  :display_name => "Resolver Search Path",
+  :description => "List of domains to search",
+  :default => "domain"
+
+attribute "networking/nameservers",
+  :display_name => "Nameservers",
+  :description => "List of nameservers to use",
+  :type => "array",
+  :default => [""]
+
diff --git a/cookbooks/networking/recipes/default.rb b/cookbooks/networking/recipes/default.rb
new file mode 100644 (file)
index 0000000..f68522b
--- /dev/null
@@ -0,0 +1,330 @@
+#
+# Cookbook Name:: networking
+# Recipe:: default
+#
+# Copyright 2010, OpenStreetMap Foundation.
+# Copyright 2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# = Requires
+# * node[:networking][:nameservers]
+
+require "ipaddr"
+
+node[:networking][:interfaces].each do |name,interface|
+  if interface[:role] and role = node[:networking][:roles][interface[:role]]
+    if role[interface[:family]]
+      node.default[:networking][:interfaces][name][:prefix] = role[interface[:family]][:prefix]
+      node.default[:networking][:interfaces][name][:gateway] = role[interface[:family]][:gateway]
+    end
+
+    node.default[:networking][:interfaces][name][:metric] = role[:metric]
+    node.default[:networking][:interfaces][name][:zone] = role[:zone]
+  end
+
+  prefix = node[:networking][:interfaces][name][:prefix]
+
+  node.default[:networking][:interfaces][name][:netmask] = (~IPAddr.new(interface[:address]).mask(0)).mask(prefix)
+  node.default[:networking][:interfaces][name][:network] = IPAddr.new(interface[:address]).mask(prefix)
+end
+
+template "/etc/network/interfaces" do
+  source "interfaces.erb"
+  owner "root"
+  group "root"
+  mode 0644
+end
+
+execute "hostname" do
+  action :nothing
+  command "/bin/hostname -F /etc/hostname"
+end
+
+template "/etc/hostname" do
+  source "hostname.erb"
+  owner "root"
+  group "root"
+  mode 0644
+  notifies :run, resources(:execute => "hostname")
+end
+
+template "/etc/hosts" do
+  source "hosts.erb"
+  owner "root"
+  group "root"
+  mode 0644
+end
+
+link "/etc/resolv.conf" do
+  action :delete
+  link_type :symbolic
+  to "/run/resolvconf/resolv.conf"
+  only_if { File.symlink?("/etc/resolv.conf") }
+end
+
+template "/etc/resolv.conf" do
+  source "resolv.conf.erb"
+  owner "root"
+  group "root"
+  mode 0644
+end
+
+node.interfaces(:role => :internal) do |interface|
+  if interface[:gateway] and interface[:gateway] != interface[:address]
+    search(:node, "networking_interfaces*address:#{interface[:gateway]}") do |gateway|
+      if gateway[:openvpn]
+        gateway[:openvpn][:tunnels].each_value do |tunnel|
+          if tunnel[:peer][:address]
+            route tunnel[:peer][:address] do
+              netmask "255.255.255.255"
+              gateway interface[:gateway]
+              device interface[:interface]
+            end
+          end
+
+          if tunnel[:peer][:networks]
+            tunnel[:peer][:networks].each do |network|
+              route network[:address] do
+                netmask network[:netmask]
+                gateway interface[:gateway]
+                device interface[:interface]
+              end
+            end
+          end
+        end
+      end
+    end
+  end
+end
+
+zones = Hash.new
+
+search(:node, "networking:interfaces").collect do |n|
+  if n[:fqdn] != node[:fqdn]
+    n.interfaces.each do |interface|
+      if interface[:role] == "external" and interface[:zone]
+        zones[interface[:zone]] ||= Hash.new
+        zones[interface[:zone]][interface[:family]] ||= Array.new
+        zones[interface[:zone]][interface[:family]] << interface[:address]
+      end
+    end
+  end
+end
+
+package "shorewall"
+
+service "shorewall" do
+  action [ :enable, :start ]
+  supports :restart => true
+  status_command "shorewall status"
+end
+
+template "/etc/default/shorewall" do
+  source "shorewall-default.erb"
+  owner "root"
+  group "root"
+  mode 0644
+  notifies :restart, resources(:service => "shorewall")
+end
+
+template "/etc/shorewall/shorewall.conf" do
+  source "shorewall.conf.erb"
+  owner "root"
+  group "root"
+  mode 0644
+  notifies :restart, resources(:service => "shorewall")
+end
+
+template "/etc/shorewall/zones" do
+  source "shorewall-zones.erb"
+  owner "root"
+  group "root"
+  mode 0644
+  variables :type => "ipv4"
+  notifies :restart, resources(:service => "shorewall")
+end
+
+template "/etc/shorewall/interfaces" do
+  source "shorewall-interfaces.erb"
+  owner "root"
+  group "root"
+  mode 0644
+  notifies :restart, resources(:service => "shorewall")
+end
+
+template "/etc/shorewall/hosts" do
+  source "shorewall-hosts.erb"
+  owner "root"
+  group "root"
+  mode 0644
+  variables :zones => zones
+  notifies :restart, resources(:service => "shorewall")
+end
+
+template "/etc/shorewall/policy" do
+  source "shorewall-policy.erb"
+  owner "root"
+  group "root"
+  mode 0644
+  notifies :restart, resources(:service => "shorewall")
+end
+
+template "/etc/shorewall/rules" do
+  source "shorewall-rules.erb"
+  owner "root"
+  group "root"
+  mode 0644
+  variables :family => "inet", :rules => []
+  notifies :restart, resources(:service => "shorewall")
+end
+
+firewall_rule "limit-icmp-echo" do
+  action :accept
+  family :inet
+  source "net"
+  dest "fw"
+  proto "icmp"
+  dest_ports "echo-request"
+  if node[:lsb][:release].to_f >= 10.04
+    rate_limit "s:1/sec:5"
+  else
+    rate_limit "1/sec:5"
+  end
+end
+
+[ "ucl", "ic", "bm" ].each do |zone|
+  firewall_rule "accept-openvpn-#{zone}" do
+    action :accept
+    family :inet
+    source zone
+    dest "fw"
+    proto "udp"
+    dest_ports "1194:1196"
+    source_ports "1194:1196"
+  end
+end
+
+if node[:roles].include?("gateway")
+  template "/etc/shorewall/masq" do
+    source "shorewall-masq.erb"
+    owner "root"
+    group "root"
+    mode 0644
+    notifies :restart, resources(:service => "shorewall")
+  end
+else
+  file "/etc/shorewall/masq" do
+    action :delete
+    notifies :restart, resources(:service => "shorewall")
+  end
+end
+
+if not node.interfaces(:family => :inet6).empty?
+  package "shorewall6"
+
+  service "shorewall6" do
+    action [ :enable, :start ]
+    supports :restart => true
+    status_command "shorewall6 status"
+  end
+
+  template "/etc/default/shorewall6" do
+    source "shorewall-default.erb"
+    owner "root"
+    group "root"
+    mode 0644
+    notifies :restart, resources(:service => "shorewall6")
+  end
+
+  template "/etc/shorewall6/shorewall6.conf" do
+    source "shorewall6.conf.erb"
+    owner "root"
+    group "root"
+    mode 0644
+    notifies :restart, resources(:service => "shorewall6")
+  end
+
+  template "/etc/shorewall6/zones" do
+    source "shorewall-zones.erb"
+    owner "root"
+    group "root"
+    mode 0644
+    variables :type => "ipv6"
+    notifies :restart, resources(:service => "shorewall6")
+  end
+
+  template "/etc/shorewall6/interfaces" do
+    source "shorewall6-interfaces.erb"
+    owner "root"
+    group "root"
+    mode 0644
+    notifies :restart, resources(:service => "shorewall6")
+  end
+
+  template "/etc/shorewall6/hosts" do
+    source "shorewall6-hosts.erb"
+    owner "root"
+    group "root"
+    mode 0644
+    variables :zones => zones
+    notifies :restart, resources(:service => "shorewall6")
+  end
+
+  template "/etc/shorewall6/policy" do
+    source "shorewall-policy.erb"
+    owner "root"
+    group "root"
+    mode 0644
+    notifies :restart, resources(:service => "shorewall6")
+  end
+
+  template "/etc/shorewall6/rules" do
+    source "shorewall-rules.erb"
+    owner "root"
+    group "root"
+    mode 0644
+    variables :family => "inet6", :rules => []
+    notifies :restart, resources(:service => "shorewall6")
+  end
+
+  firewall_rule "limit-icmp6-echo" do
+    action :accept
+    family :inet6
+    source "net"
+    dest "fw"
+    proto "ipv6-icmp"
+    dest_ports "echo-request"
+    if node[:lsb][:release].to_f >= 10.04
+      rate_limit "s:1/sec:5"
+    else
+      rate_limit "1/sec:5"
+    end
+  end
+end
+
+firewall_rule "accept-http" do
+  action :accept
+  source "net"
+  dest "fw"
+  proto "tcp:syn"
+  dest_ports "http"
+end
+
+firewall_rule "accept-https" do
+  action :accept
+  source "net"
+  dest "fw"
+  proto "tcp:syn"
+  dest_ports "https"
+end
diff --git a/cookbooks/networking/templates/default/hostname.erb b/cookbooks/networking/templates/default/hostname.erb
new file mode 100644 (file)
index 0000000..1e80c0c
--- /dev/null
@@ -0,0 +1 @@
+<%= node[:hostname] %>.openstreetmap.org
diff --git a/cookbooks/networking/templates/default/hosts.erb b/cookbooks/networking/templates/default/hosts.erb
new file mode 100644 (file)
index 0000000..decae86
--- /dev/null
@@ -0,0 +1,16 @@
+# DO NOT EDIT - This file is being maintained by Chef
+
+# This machine
+127.0.1.1       <%= node[:hostname] -%>.openstreetmap.org <%= node[:hostname] %>
+
+# IPv4 loopback address
+127.0.0.1       localhost ip4-localhost ip4-loopback
+
+# IPv6 loopback address
+::1             localhost ip6-localhost ip6-loopback
+
+# Other useful IPv6 addresses
+fe00::0         ip6-localnet
+ff00::0         ip6-mcastprefix
+ff02::1         ip6-allnodes
+ff02::2         ip6-allrouters
diff --git a/cookbooks/networking/templates/default/interfaces.erb b/cookbooks/networking/templates/default/interfaces.erb
new file mode 100644 (file)
index 0000000..89fc316
--- /dev/null
@@ -0,0 +1,35 @@
+# DO NOT EDIT - This file is being maintained by Chef
+
+iface lo inet loopback
+<% node[:networking][:interfaces].each do |name,interface| -%>
+
+iface <%= interface[:interface] %> <%= interface[:family] %> static
+      address   <%= interface[:address] %>
+<% if interface[:family] == "inet" -%>
+      netmask   <%= interface[:netmask] %>
+<% elsif interface[:family] == "inet6" -%>
+      netmask   <%= interface[:prefix] %>
+<% end -%>
+<% if interface[:hwaddress] -%>
+      hwaddress <%= interface[:hwaddress] %>
+<% end -%>
+<% if interface[:gateway] -%>
+<% if interface[:network].include?(interface[:gateway]) or IPAddr.new("fe80::/64").include?(interface[:gateway]) -%>
+      gateway   <%= interface[:gateway] %>
+      metric    <%= interface[:metric] %>
+<% else -%>
+      post-up   /sbin/ip -f <%= interface[:family] %> route add <%= interface[:gateway] %> dev <%= interface[:interface] %>
+      post-up   /sbin/ip -f <%= interface[:family] %> route add default metric <%= interface[:metric] %> via <%= interface[:gateway] %>
+      pre-down  /sbin/ip -f <%= interface[:family] %> route del default metric <%= interface[:metric] %> via <%= interface[:gateway] %>
+      pre-down  /sbin/ip -f <%= interface[:family] %> route del <%= interface[:gateway] %> dev <%= interface[:interface] %>
+<% end -%>
+<% end -%>
+<% if interface[:mtu] -%>
+      mtu       <%= interface[:mtu] %>
+<% end -%>
+<% if interface[:family] == "inet6" -%>
+      autoconf  0
+<% end -%>
+<% end -%>
+
+auto lo <%= node[:networking][:interfaces].collect { |n,i| i[:interface] }.sort.uniq.join(" ") %>
diff --git a/cookbooks/networking/templates/default/resolv.conf.erb b/cookbooks/networking/templates/default/resolv.conf.erb
new file mode 100644 (file)
index 0000000..c857ff8
--- /dev/null
@@ -0,0 +1,7 @@
+# DO NOT EDIT - This file is being maintained by Chef
+<% unless node[:networking][:search].empty? -%>
+search <%= node[:networking][:search].join(" ") %>
+<% end -%>
+<% node[:networking][:nameservers].each do |nameserver| -%>
+nameserver <%= nameserver %>
+<% end -%>
diff --git a/cookbooks/networking/templates/default/shorewall-default.erb b/cookbooks/networking/templates/default/shorewall-default.erb
new file mode 100644 (file)
index 0000000..03f3ffc
--- /dev/null
@@ -0,0 +1,7 @@
+# DO NOT EDIT - This file is being maintained by Chef
+
+# Allow shorewall to start
+startup=1
+
+# Program options
+OPTIONS=""
diff --git a/cookbooks/networking/templates/default/shorewall-hosts.erb b/cookbooks/networking/templates/default/shorewall-hosts.erb
new file mode 100644 (file)
index 0000000..76160b0
--- /dev/null
@@ -0,0 +1,12 @@
+# DO NOT EDIT - This file is being maintained by Chef
+
+# ZONE HOST                    OPTIONS
+<% node.interfaces(:family => :inet, :role => :external).each do |interface| -%>
+<% @zones.keys.sort.each do |zone| -%>
+<% if @zones[zone]["inet"] -%>
+<% @zones[zone]["inet"].sort.each do |ra| -%>
+<%= zone %>    <%= interface[:interface] %>:<%= ra %>
+<% end -%>
+<% end -%>
+<% end -%>
+<% end -%>
diff --git a/cookbooks/networking/templates/default/shorewall-interfaces.erb b/cookbooks/networking/templates/default/shorewall-interfaces.erb
new file mode 100644 (file)
index 0000000..89d8a2d
--- /dev/null
@@ -0,0 +1,13 @@
+# DO NOT EDIT - This file is being maintained by Chef
+
+# ZONE INTERFACE       BROADCAST       OPTIONS
+<% node[:networking][:interfaces].each do |name,interface| -%>
+<% if interface[:family] == "inet" -%>
+<% if interface[:role] == "internal" -%>
+loc    <%= interface[:interface] %>            detect          nosmurfs,tcpflags
+<% elsif interface[:role] == "external" -%>
+net    <%= interface[:interface] %>            detect          nosmurfs,tcpflags
+<% end -%>
+<% end -%>
+<% end -%>
+loc    tun+            detect          nosmurfs,tcpflags
diff --git a/cookbooks/networking/templates/default/shorewall-masq.erb b/cookbooks/networking/templates/default/shorewall-masq.erb
new file mode 100644 (file)
index 0000000..856f60e
--- /dev/null
@@ -0,0 +1,8 @@
+# DO NOT EDIT - This file is being maintained by Chef
+
+# INTERFACE    SOURCE          ADDRESS
+<% node.interfaces(:role => :external).each do |external| -%>
+<% node.interfaces(:role => :internal).each do |internal| -%>
+<%= external[:interface] %>            <%= internal[:network] %>/<%= internal[:prefix] %>      detect
+<% end -%>
+<% end -%>
diff --git a/cookbooks/networking/templates/default/shorewall-policy.erb b/cookbooks/networking/templates/default/shorewall-policy.erb
new file mode 100644 (file)
index 0000000..4f29377
--- /dev/null
@@ -0,0 +1,5 @@
+# DO NOT EDIT - This file is being maintained by Chef
+
+# FROM         TO              POLICY          LOG LEVEL       BURST:LIMIT
+net            all             DROP
+all            all             ACCEPT
diff --git a/cookbooks/networking/templates/default/shorewall-rules.erb b/cookbooks/networking/templates/default/shorewall-rules.erb
new file mode 100644 (file)
index 0000000..ffa55a9
--- /dev/null
@@ -0,0 +1,9 @@
+# DO NOT EDIT - This file is being maintained by Chef
+
+SECTION NEW
+
+# ACTION       SOURCE  DEST    PROTO           DEST            SOURCE  ORIGINAL        RATE
+#                                              PORTS           PORTS   DEST            LIMIT
+<% @rules.each do |r| -%>
+<%= r[:action] %>              <%= r[:source] %>       <%= r[:dest] %> <%= r[:proto] %>                <%= r[:dest_ports] %>   <%= r[:source_ports] %> -       <%= r[:rate_limit] %>
+<% end -%>
diff --git a/cookbooks/networking/templates/default/shorewall-zones.erb b/cookbooks/networking/templates/default/shorewall-zones.erb
new file mode 100644 (file)
index 0000000..0af666a
--- /dev/null
@@ -0,0 +1,20 @@
+# DO NOT EDIT - This file is being maintained by Chef
+
+# ZONE         TYPE            OPTIONS         IN OPTIONS      OUT OPTIONS
+fw             firewall
+loc            <%= @type %>
+net            <%= @type %>
+osm:net                <%= @type %>
+ucl:osm                <%= @type %>
+ic:osm         <%= @type %>
+bm:osm         <%= @type %>
+ts:osm         <%= @type %>
+yx:osm         <%= @type %>
+ra:osm         <%= @type %>
+pa:osm         <%= @type %>
+bx:osm         <%= @type %>
+ff:osm         <%= @type %>
+pr:osm         <%= @type %>
+ly:osm         <%= @type %>
+ov:osm         <%= @type %>
+hz:osm         <%= @type %>
diff --git a/cookbooks/networking/templates/default/shorewall.conf.erb b/cookbooks/networking/templates/default/shorewall.conf.erb
new file mode 100644 (file)
index 0000000..14e0779
--- /dev/null
@@ -0,0 +1,192 @@
+# DO NOT EDIT - This file is being maintained by Chef
+
+###############################################################################
+#                     S T A R T U P   E N A B L E D
+###############################################################################
+
+STARTUP_ENABLED=Yes
+
+###############################################################################
+#                            V E R B O S I T Y
+###############################################################################
+
+VERBOSITY=1
+
+###############################################################################
+#                             L O G G I N G
+###############################################################################
+
+LOGFILE=/var/log/messages
+
+STARTUP_LOG=/var/log/shorewall-init.log
+
+LOG_VERBOSITY=2
+
+LOGFORMAT="Shorewall:%s:%s:"
+
+LOGTAGONLY=No
+
+LOGRATE=
+
+LOGBURST=
+
+LOGALLNEW=
+
+BLACKLIST_LOGLEVEL=
+
+MACLIST_LOG_LEVEL=info
+
+TCP_FLAGS_LOG_LEVEL=info
+
+SMURF_LOG_LEVEL=info
+
+LOG_MARTIANS=Yes
+
+###############################################################################
+#      L O C A T I O N   O F   F I L E S   A N D   D I R E C T O R I E S
+###############################################################################
+
+IPTABLES=
+
+IP=
+
+TC=
+
+IPSET=
+
+PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin:/usr/local/sbin
+
+SHOREWALL_SHELL=/bin/sh
+
+SUBSYSLOCK=""
+
+MODULESDIR=
+
+CONFIG_PATH=/etc/shorewall:/usr/share/shorewall
+
+RESTOREFILE=
+
+IPSECFILE=zones
+
+LOCKFILE=
+
+###############################################################################
+#              D E F A U L T   A C T I O N S / M A C R O S
+###############################################################################
+
+DROP_DEFAULT="Drop"
+REJECT_DEFAULT="Reject"
+ACCEPT_DEFAULT="none"
+QUEUE_DEFAULT="none"
+NFQUEUE_DEFAULT="none"
+
+###############################################################################
+#                        R S H / R C P  C O M M A N D S
+###############################################################################
+
+RSH_COMMAND='ssh ${root}@${system} ${command}'
+RCP_COMMAND='scp ${files} ${root}@${system}:${destination}'
+
+###############################################################################
+#                      F I R E W A L L   O P T I O N S
+###############################################################################
+
+IP_FORWARDING=Keep
+
+ADD_IP_ALIASES=Yes
+
+ADD_SNAT_ALIASES=No
+
+RETAIN_ALIASES=No
+
+TC_ENABLED=Internal
+
+TC_EXPERT=No
+
+CLEAR_TC=Yes
+
+MARK_IN_FORWARD_CHAIN=No
+
+CLAMPMSS=No
+
+ROUTE_FILTER=Yes
+
+DETECT_DNAT_IPADDRS=No
+
+MUTEX_TIMEOUT=60
+
+ADMINISABSENTMINDED=Yes
+
+BLACKLISTNEWONLY=Yes
+
+DELAYBLACKLISTLOAD=No
+
+MODULE_SUFFIX=ko
+
+DISABLE_IPV6=No
+
+BRIDGING=No
+
+DYNAMIC_ZONES=No
+
+PKTTYPE=Yes
+
+NULL_ROUTE_RFC1918=No
+
+MACLIST_TABLE=filter
+
+MACLIST_TTL=
+
+SAVE_IPSETS=No
+
+MAPOLDACTIONS=No
+
+FASTACCEPT=No
+
+IMPLICIT_CONTINUE=Yes
+
+HIGH_ROUTE_MARKS=No
+
+USE_ACTIONS=Yes
+
+OPTIMIZE=1
+
+EXPORTPARAMS=Yes
+
+EXPAND_POLICIES=Yes
+
+KEEP_RT_TABLES=No
+
+DELETE_THEN_ADD=Yes
+
+MULTICAST=No
+
+DONT_LOAD=
+
+AUTO_COMMENT=Yes
+
+MANGLE_ENABLED=Yes
+
+USE_DEFAULT_RT=No
+
+RESTORE_DEFAULT_ROUTE=Yes
+
+AUTOMAKE=No
+
+WIDE_TC_MARKS=No
+
+TRACK_PROVIDERS=No
+
+ZONE2ZONE=2
+
+###############################################################################
+#                      P A C K E T   D I S P O S I T I O N
+###############################################################################
+
+BLACKLIST_DISPOSITION=DROP
+
+MACLIST_DISPOSITION=REJECT
+
+TCP_FLAGS_DISPOSITION=DROP
+
+#LAST LINE -- DO NOT REMOVE
diff --git a/cookbooks/networking/templates/default/shorewall6-hosts.erb b/cookbooks/networking/templates/default/shorewall6-hosts.erb
new file mode 100644 (file)
index 0000000..c2ac663
--- /dev/null
@@ -0,0 +1,12 @@
+# DO NOT EDIT - This file is being maintained by Chef
+
+# ZONE HOST                                            OPTIONS
+<% node.interfaces(:family => :inet6, :role => :external).each do |interface| -%>
+<% @zones.keys.sort.each do |zone| -%>
+<% if @zones[zone]["inet6"] -%>
+<% @zones[zone]["inet6"].sort.each do |ra| -%>
+<%= zone %>    <%= interface[:interface] %>:[<%= ra %>]
+<% end -%>
+<% end -%>
+<% end -%>
+<% end -%>
diff --git a/cookbooks/networking/templates/default/shorewall6-interfaces.erb b/cookbooks/networking/templates/default/shorewall6-interfaces.erb
new file mode 100644 (file)
index 0000000..d2b4a3d
--- /dev/null
@@ -0,0 +1,12 @@
+# DO NOT EDIT - This file is being maintained by Chef
+
+# ZONE INTERFACE       UNICAST         OPTIONS
+<% node[:networking][:interfaces].each do |name,interface| -%>
+<% if interface[:family] == "inet6" -%>
+<% if interface[:role] == "internal" -%>
+loc    <%= interface[:interface] %>            -
+<% elsif interface[:role] == "external" -%>
+net    <%= interface[:interface] %>            -
+<% end -%>
+<% end -%>
+<% end -%>
diff --git a/cookbooks/networking/templates/default/shorewall6.conf.erb b/cookbooks/networking/templates/default/shorewall6.conf.erb
new file mode 100644 (file)
index 0000000..008fc6a
--- /dev/null
@@ -0,0 +1,146 @@
+# DO NOT EDIT - This file is being maintained by Chef
+
+###############################################################################
+#                     S T A R T U P   E N A B L E D
+###############################################################################
+
+STARTUP_ENABLED=Yes
+
+###############################################################################
+#                            V E R B O S I T Y
+###############################################################################
+
+VERBOSITY=1
+
+###############################################################################
+#                             L O G G I N G
+###############################################################################
+
+LOGFILE=/var/log/messages
+
+STARTUP_LOG=/var/log/shorewall6-init.log
+
+LOG_VERBOSITY=2
+
+LOGFORMAT="Shorewall:%s:%s:"
+
+LOGTAGONLY=No
+
+LOGRATE=
+
+LOGBURST=
+
+LOGALLNEW=
+
+BLACKLIST_LOGLEVEL=
+
+TCP_FLAGS_LOG_LEVEL=info
+
+SMURF_LOG_LEVEL=info
+
+###############################################################################
+#      L O C A T I O N   O F   F I L E S   A N D   D I R E C T O R I E S
+###############################################################################
+
+IP6TABLES=
+
+IP=
+
+TC=
+
+IPSET=
+
+PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin:/usr/local/sbin
+
+SHOREWALL_SHELL=/bin/sh
+
+SUBSYSLOCK=""
+
+MODULESDIR=
+
+CONFIG_PATH=/etc/shorewall6:/usr/share/shorewall6:/usr/share/shorewall
+
+RESTOREFILE=
+
+LOCKFILE=
+
+###############################################################################
+#              D E F A U L T   A C T I O N S / M A C R O S
+###############################################################################
+
+DROP_DEFAULT="Drop"
+REJECT_DEFAULT="Reject"
+ACCEPT_DEFAULT="none"
+QUEUE_DEFAULT="none"
+NFQUEUE_DEFAULT="none"
+
+###############################################################################
+#                        R S H / R C P  C O M M A N D S
+###############################################################################
+
+RSH_COMMAND='ssh ${root}@${system} ${command}'
+RCP_COMMAND='scp ${files} ${root}@${system}:${destination}'
+
+###############################################################################
+#                      F I R E W A L L   O P T I O N S
+###############################################################################
+
+IP_FORWARDING=Off
+
+TC_ENABLED=No
+
+TC_EXPERT=No
+
+CLEAR_TC=No
+
+MARK_IN_FORWARD_CHAIN=No
+
+CLAMPMSS=No
+
+MUTEX_TIMEOUT=60
+
+ADMINISABSENTMINDED=Yes
+
+BLACKLISTNEWONLY=Yes
+
+MODULE_SUFFIX=ko
+
+FASTACCEPT=No
+
+IMPLICIT_CONTINUE=Yes
+
+HIGH_ROUTE_MARKS=No
+
+OPTIMIZE=1
+
+EXPORTPARAMS=Yes
+
+EXPAND_POLICIES=Yes
+
+KEEP_RT_TABLES=Yes
+
+DELETE_THEN_ADD=Yes
+
+DONT_LOAD=
+
+AUTO_COMMENT=Yes
+
+MANGLE_ENABLED=Yes
+
+AUTOMAKE=No
+
+WIDE_TC_MARKS=No
+
+TRACK_PROVIDERS=No
+
+ZONE2ZONE=2
+
+###############################################################################
+#                      P A C K E T   D I S P O S I T I O N
+###############################################################################
+
+BLACKLIST_DISPOSITION=DROP
+
+TCP_FLAGS_DISPOSITION=DROP
+
+#LAST LINE -- DO NOT REMOVE
diff --git a/cookbooks/nfs/README.rdoc b/cookbooks/nfs/README.rdoc
new file mode 100644 (file)
index 0000000..3de2ec7
--- /dev/null
@@ -0,0 +1,8 @@
+= DESCRIPTION:
+
+= REQUIREMENTS:
+
+= ATTRIBUTES:
+
+= USAGE:
+
diff --git a/cookbooks/nfs/metadata.rb b/cookbooks/nfs/metadata.rb
new file mode 100644 (file)
index 0000000..7deebd5
--- /dev/null
@@ -0,0 +1,6 @@
+maintainer        "OpenStreetMap Administrators"
+maintainer_email  "admins@openstreetmap.org"
+license           "Apache 2.0"
+description       "Installs and configures nfs"
+long_description  IO.read(File.join(File.dirname(__FILE__), 'README.rdoc'))
+version           "1.0.0"
diff --git a/cookbooks/nfs/recipes/default.rb b/cookbooks/nfs/recipes/default.rb
new file mode 100644 (file)
index 0000000..0b4c9ff
--- /dev/null
@@ -0,0 +1,44 @@
+#
+# Cookbook Name:: nfs
+# Recipe:: default
+#
+# Copyright 2010, OpenStreetMap Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+package "nfs-common"
+
+node[:nfs].each do |mountpoint,details|
+  if details[:readonly]
+    mount_options = "ro,bg,soft,udp,rsize=8192,wsize=8192,nfsvers=3"
+  else
+    mount_options = "rw,bg,udp,rsize=8192,wsize=8192,nfsvers=3"
+  end
+
+  directory mountpoint do
+    owner "root"
+    group "root"
+    mode 0755
+    recursive true
+    not_if { File.exists?(mountpoint) }
+  end
+
+  mount mountpoint do
+    action [ :mount, :enable ]
+    device "#{details[:host]}:#{details[:path]}"
+    fstype "nfs"
+    options mount_options
+    ignore_failure true
+  end
+end
diff --git a/cookbooks/nfs/recipes/server.rb b/cookbooks/nfs/recipes/server.rb
new file mode 100644 (file)
index 0000000..3e13507
--- /dev/null
@@ -0,0 +1,64 @@
+#
+# Cookbook Name:: nfs
+# Recipe:: server
+#
+# Copyright 2010, OpenStreetMap Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+package "nfs-kernel-server"
+
+service "portmap" do
+  action [ :enable, :start ]
+  supports :status => true, :restart => true, :reload => true
+end
+
+#service "nfs-kernel-server" do
+#  action [ :enable, :start ]
+#  supports :status => true, :restart => true, :reload => true
+#end
+
+exports = {}
+
+search(:node, "*:*") do |client|
+  if client[:nfs]
+    client[:nfs].each_value do |mount|
+      if mount[:host] == node[:hostname]
+        client.ipaddresses do |address|
+          exports[mount[:path]] ||= {}
+
+          if mount[:readonly]
+            exports[mount[:path]][address] = "ro"
+          else
+            exports[mount[:path]][address] = "rw"
+          end
+        end
+      end
+    end
+  end
+end
+
+execute "exportfs" do
+  action :nothing
+  command "/usr/sbin/exportfs -ra"
+end
+
+template "/etc/exports" do
+  source "exports.erb"
+  owner "root"
+  group "root"
+  mode 0644
+  variables :exports => exports
+  notifies :run, resources(:execute => "exportfs")
+end
diff --git a/cookbooks/nfs/templates/default/exports.erb b/cookbooks/nfs/templates/default/exports.erb
new file mode 100644 (file)
index 0000000..ba812c7
--- /dev/null
@@ -0,0 +1,6 @@
+# DO NOT EDIT - This file is being maintained by Chef
+
+<% @exports.each do |directory,clients| -%>
+<%= directory -%> -sync,subtree_check<% clients.each do |address,options| -%> <%= address -%>(<%= options -%>)<% end %>
+<% end -%>
+/store/planet -sync,subtree_check 146.179.159.168(rw) 146.179.159.170(rw) 128.40.168.104(ro) 128.40.168.103(ro) 128.40.168.100(ro)
diff --git a/cookbooks/openvpn/README.rdoc b/cookbooks/openvpn/README.rdoc
new file mode 100644 (file)
index 0000000..3de2ec7
--- /dev/null
@@ -0,0 +1,8 @@
+= DESCRIPTION:
+
+= REQUIREMENTS:
+
+= ATTRIBUTES:
+
+= USAGE:
+
diff --git a/cookbooks/openvpn/attributes/default.rb b/cookbooks/openvpn/attributes/default.rb
new file mode 100644 (file)
index 0000000..af20e4e
--- /dev/null
@@ -0,0 +1,2 @@
+default[:openvpn][:tunnels] = {}
+default[:openvpn][:keys] = {}
diff --git a/cookbooks/openvpn/metadata.rb b/cookbooks/openvpn/metadata.rb
new file mode 100644 (file)
index 0000000..9197554
--- /dev/null
@@ -0,0 +1,6 @@
+maintainer        "OpenStreetMap Administrators"
+maintainer_email  "admins@openstreetmap.org"
+license           "Apache 2.0"
+description       "Installs and configures OpenVPN"
+long_description  IO.read(File.join(File.dirname(__FILE__), 'README.rdoc'))
+version           "1.0.0"
diff --git a/cookbooks/openvpn/recipes/default.rb b/cookbooks/openvpn/recipes/default.rb
new file mode 100644 (file)
index 0000000..cbd45ee
--- /dev/null
@@ -0,0 +1,79 @@
+#
+# Cookbook Name:: openvpn
+# Recipe:: default
+#
+# Copyright 2012, OpenStreetMap Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+package "openvpn"
+
+service "openvpn" do
+  action [ :enable, :start ]
+  supports :status => true, :restart => true, :reload => true
+  ignore_failure true
+end
+
+node[:openvpn][:tunnels].each do |name,details|
+  if peer = search(:node, "fqdn:#{details[:peer][:host]}").first
+    if peer[:openvpn] and not details[:peer][:address]
+      node.default[:openvpn][:tunnels][name][:peer][:address] = peer[:openvpn][:address]
+    end
+
+    node.default[:openvpn][:tunnels][name][:peer][:networks] = peer.interfaces(:role => :internal).collect do |interface|
+      { :address => interface[:network], :netmask => interface[:netmask] }
+    end
+  else
+    node.default[:openvpn][:tunnels][name][:peer][:networks] = []
+  end
+
+  if details[:mode] == "client"
+    execute "openvpn-genkey-#{name}" do
+      command "openvpn --genkey --secret /etc/openvpn/#{name}.key"
+      user "root"
+      group "root"
+      creates "/etc/openvpn/#{name}.key"
+    end
+
+    if File.exists?("/etc/openvpn/#{name}.key")
+      node.set[:openvpn][:keys][name] = IO.read("/etc/openvpn/#{name}.key")
+    end
+  elsif peer and peer[:openvpn]
+    file "/etc/openvpn/#{name}.key" do
+      owner "root"
+      group "root"
+      mode 0600
+      content peer[:openvpn][:keys][name]
+    end
+  end
+
+  if node[:openvpn][:tunnels][name][:peer][:address]
+    template "/etc/openvpn/#{name}.conf" do
+      source "tunnel.conf.erb"
+      owner "root"
+      group "root"
+      mode 0644
+      variables :name => name,
+      :address => node[:openvpn][:address],
+      :port => node[:openvpn][:tunnels][name][:port],
+      :mode => node[:openvpn][:tunnels][name][:mode],
+      :peer => node[:openvpn][:tunnels][name][:peer]
+      notifies :restart, resources(:service => "openvpn")
+    end
+  else
+    file "/etc/openvpn/#{name}.conf" do
+      action :delete
+    end
+  end
+end
diff --git a/cookbooks/openvpn/templates/default/tunnel.conf.erb b/cookbooks/openvpn/templates/default/tunnel.conf.erb
new file mode 100644 (file)
index 0000000..748f969
--- /dev/null
@@ -0,0 +1,47 @@
+# DO NOT EDIT - This file is being maintained by Chef
+
+# Set the local port to use
+port <%= @port %>
+
+# Use UDP
+proto udp
+
+# Use routed IP tunnels
+dev tun
+
+# Use shared secret authentication
+secret <%= @name %>.key
+
+# Run in peer-to-peer mode
+mode p2p
+<% if @mode == "client" -%>
+
+# Connect to the remote machine
+remote <%= @peer[:host] %> <%= @peer[:port] %>
+<% end -%>
+
+# Configure interface and routing
+ifconfig <%= @address %> <%= @peer[:address] %>
+<% @peer[:networks].each do |network| -%>
+route <%= network[:address] %> <%= network[:netmask] %>
+<% end -%>
+
+# Keepalive - check every 10 seconds and reset after 2 minutes
+keepalive 10 120
+
+# Use AES-128 as the cipher
+cipher AES-128-CBC
+
+# Enable compression
+comp-lzo
+
+# Run unprivileged
+user nobody
+group nogroup
+
+# Reuse resources on restart to avoid privilege problems
+persist-key
+persist-tun
+
+# Set log verbosity
+verb 3
diff --git a/cookbooks/osqa/README.rdoc b/cookbooks/osqa/README.rdoc
new file mode 100644 (file)
index 0000000..3de2ec7
--- /dev/null
@@ -0,0 +1,8 @@
+= DESCRIPTION:
+
+= REQUIREMENTS:
+
+= ATTRIBUTES:
+
+= USAGE:
+
diff --git a/cookbooks/osqa/attributes/default.rb b/cookbooks/osqa/attributes/default.rb
new file mode 100644 (file)
index 0000000..fb20a4d
--- /dev/null
@@ -0,0 +1,7 @@
+default[:osqa][:revision] = "1284"
+default[:osqa][:user] = "osqa"
+default[:osqa][:group] = nil
+default[:osqa][:database_name] = "osqa"
+default[:osqa][:database_user] = "osqa"
+default[:osqa][:database_password] = ""
+default[:osqa][:sites] = []
diff --git a/cookbooks/osqa/files/default/osmauth/__init__.py b/cookbooks/osqa/files/default/osmauth/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/cookbooks/osqa/files/default/osmauth/authentication.py b/cookbooks/osqa/files/default/osmauth/authentication.py
new file mode 100644 (file)
index 0000000..7c8e702
--- /dev/null
@@ -0,0 +1,21 @@
+from forum.authentication.base import AuthenticationConsumer, ConsumerTemplateContext, InvalidAuthentication
+from forms import OpenStreetMapLoginForm
+
+class OpenStreetMapAuthConsumer(AuthenticationConsumer):
+    def process_authentication_request(self, request):
+        form_auth = OpenStreetMapLoginForm(request.POST)
+
+        if form_auth.is_valid():
+            request.session["auth_consumer_data"] = form_auth.get_user_data()
+            return form_auth.get_user()
+        else:
+            raise InvalidAuthentication(" ".join(form_auth.errors.values()[0]))
+
+    def get_user_data(self, key):
+        return {}
+
+class OpenStreetMapAuthContext(ConsumerTemplateContext):
+    mode = 'TOP_STACK_ITEM'
+    weight = 0
+    human_name = 'OpenStreetMap Login'
+    stack_item_template = 'modules/osmauth/loginform.html'
diff --git a/cookbooks/osqa/files/default/osmauth/forms.py b/cookbooks/osqa/files/default/osmauth/forms.py
new file mode 100644 (file)
index 0000000..c59475e
--- /dev/null
@@ -0,0 +1,72 @@
+from osm import OpenStreetMapAPI
+from forum.forms import NextUrlField, UserNameField, SetPasswordForm
+from django.utils.translation import ugettext as _
+from django import forms
+
+class OpenStreetMapLoginForm(forms.Form):
+    """ osm account signin form """
+    next = NextUrlField()
+    username = UserNameField(required=False, skip_clean=True)
+    password = forms.CharField(max_length=128,
+                               widget=forms.widgets.PasswordInput(attrs={'class':'required login'}),
+                               required=False)
+
+    def __init__(self, data=None, files=None, auto_id='id_%s',
+                 prefix=None, initial=None):
+        super(OpenStreetMapLoginForm, self).__init__(data, files, auto_id,
+                                                     prefix, initial)
+        self.user_details = None
+
+    def _clean_nonempty_field(self, field):
+        value = None
+        if field in self.cleaned_data:
+            value = self.cleaned_data[field].strip()
+            if value == '':
+                value = None
+        self.cleaned_data[field] = value
+        return value
+
+    def clean_username(self):
+        return self._clean_nonempty_field('username')
+
+    def clean_password(self):
+        return self._clean_nonempty_field('password')
+
+    def clean(self):
+        error_list = []
+        username = self.cleaned_data['username']
+        password = self.cleaned_data['password']
+
+        self.user_details = None
+        if username and password:
+            api = OpenStreetMapAPI(username, password)
+
+            try:
+                self.user_details = api.user_details()
+            except:
+                del self.cleaned_data['username']
+                del self.cleaned_data['password']
+                error_list.insert(0, (_("Please enter valid username and password "
+                "(both are case-sensitive).")))
+                error_list.insert(0, _('Login failed.'))
+
+        elif password == None and username == None:
+            error_list.append(_('Please enter username and password'))
+        elif password == None:
+            error_list.append(_('Please enter your password'))
+        elif username == None:
+            error_list.append(_('Please enter user name'))
+        if len(error_list) > 0:
+            self._errors['__all__'] = forms.util.ErrorList(error_list)
+
+        return self.cleaned_data
+
+    def get_user(self):
+        """ get authenticated user """
+        return "http://www.openstreetmap.org/user/%s" % self.user_details["id"]
+
+    def get_user_data(self):
+        """ get user data for authenticated user """
+        return {
+            "username": self.user_details["display_name"]
+        }
diff --git a/cookbooks/osqa/files/default/osmauth/osm.py b/cookbooks/osqa/files/default/osmauth/osm.py
new file mode 100644 (file)
index 0000000..94dcd13
--- /dev/null
@@ -0,0 +1,19 @@
+from xml.etree.ElementTree import ElementTree
+import urllib2
+
+class OpenStreetMapAPI:
+    def __init__(self, username, password):
+        passman = urllib2.HTTPPasswordMgr()
+        passman.add_password("Web Password", "https://api.openstreetmap.org/api/0.6", username, password)
+        authhandler =  urllib2.HTTPBasicAuthHandler(passman)
+        self.opener = urllib2.build_opener(authhandler)
+
+    def user_details(self):
+        response = self.opener.open("https://api.openstreetmap.org/api/0.6/user/details")
+        tree = ElementTree()
+        root = tree.parse(response)
+        user = root.find("user")
+        return {
+            "id": user.attrib["id"],
+            "display_name": user.attrib["display_name"]
+        }
diff --git a/cookbooks/osqa/files/default/osmauth/templates/loginform.html b/cookbooks/osqa/files/default/osmauth/templates/loginform.html
new file mode 100644 (file)
index 0000000..5091dfa
--- /dev/null
@@ -0,0 +1,31 @@
+{% load i18n %}
+
+<fieldset id='openstreetmap_login_fs'>
+  <p><span class='big strong'>{% trans 'Enter your OpenStreetMap username and password' %}</span><br/><span class='grey'>({% trans 'or select your external provider below' %})</span></p>
+  <table>
+    <tr>
+        <td>
+             <label for="id_osm_username">{% trans 'Username' %}</label>
+        </td>
+        <td>
+             <input id="id_osm_username" type="text" class="required login" name="username" maxlength="255" />
+        </td>
+    </tr>
+    <tr>
+        <td>
+              <label for="id_osm_password">{% trans 'Password' %}</label>
+        </td>
+        <td>
+             <input id="id_osm_password" type="password" class="required login" name="password" maxlength="255" />
+        </td>
+    </tr>
+    <tr>
+        <td>
+            <input id="blogin" name="blogin" type="submit" value="{% trans 'Login' %}" />
+        </td>
+        <td>
+              <a href="https://www.openstreetmap.org/user/new">{% trans 'Create account' %}</a><span>&nbsp;|&nbsp;</span><a href="http://www.openstreetmap.org/user/forgot-password">{% trans 'Forgot your password?' %}</a>
+        </td>
+    </tr>
+  </table>
+</fieldset>
diff --git a/cookbooks/osqa/files/default/osmauth/urls.py b/cookbooks/osqa/files/default/osmauth/urls.py
new file mode 100644 (file)
index 0000000..62581f0
--- /dev/null
@@ -0,0 +1,8 @@
+from django.conf.urls.defaults import *
+from django.views.generic.simple import direct_to_template
+from django.utils.translation import ugettext as _
+import views as app
+
+urlpatterns = patterns('',
+    url(r'^%s%s%s$' % (_('account/'), _('openstreetmap/'),  _('register/')), app.register, name='auth_openstreetmap_register'),
+)
diff --git a/cookbooks/osqa/metadata.rb b/cookbooks/osqa/metadata.rb
new file mode 100644 (file)
index 0000000..da3014e
--- /dev/null
@@ -0,0 +1,48 @@
+maintainer        "OpenStreetMap Administrators"
+maintainer_email  "admins@openstreetmap.org"
+license           "Apache 2.0"
+description       "Installs and configures OSQA"
+long_description  IO.read(File.join(File.dirname(__FILE__), 'README.rdoc'))
+version           "1.0.0"
+depends           "apache"
+depends           "memcached"
+
+attribute "osqa",
+  :display_name => "OSQA",
+  :description => "Hash of OSQA attributes",
+  :type => "hash"
+
+attribute "osqa/revision",
+  :display_name => "OSQA Revision",
+  :description => "Default revision of OSQA to use",
+  :default => "703"
+
+attribute "osqa/user",
+  :display_name => "User",
+  :description => "Default user to run OSQA as",
+  :default => "osqa"
+
+attribute "osqa/group",
+  :display_name => "Group",
+  :description => "Default group to run OSQA ad",
+  :default => nil
+
+attribute "osqa/database_name",
+  :display_name => "Database Name",
+  :description => "Default database to run OSQA against",
+  :default => "osqa"
+
+attribute "osqa/database_user",
+  :display_name => "Database User",
+  :description => "Default user for OSQA to connect to the database as",
+  :default => "osqa"
+
+attribute "osqa/database_password",
+  :display_name => "Database Password",
+  :description => "Default password for OSQA to authenticate to the database with",
+  :default => ""
+
+attribute "osqa/sites",
+  :display_name => "Sites",
+  :description => "Array of OSQA sites to setup",
+  :default => []
diff --git a/cookbooks/osqa/recipes/default.rb b/cookbooks/osqa/recipes/default.rb
new file mode 100644 (file)
index 0000000..2ed82d2
--- /dev/null
@@ -0,0 +1,113 @@
+#
+# Cookbook Name:: osqa
+# Recipe:: default
+#
+# Copyright 2011, OpenStreetMap Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+include_recipe "tools"
+include_recipe "apache::ssl"
+include_recipe "memcached"
+
+package "python-django"
+package "python-html5lib"
+package "python-markdown"
+package "python-memcache"
+package "python-openid"
+package "python-mysqldb"
+package "python-psycopg2"
+package "python-setuptools"
+
+easy_install_package "South" do
+  package_name "south"
+end
+
+apache_module "rewrite"
+apache_module "wsgi"
+
+node[:osqa][:sites].each do |site|
+  name = site[:name]
+  directory = site[:directory] || "/var/www/#{name}"
+  osqa_revision = site[:revision] || node[:osqa][:revision]
+  site_user = site[:user] || node[:osqa][:user]
+  site_user = Etc.getpwuid(site_user).name if site_user.is_a?(Integer)
+  site_group = site[:group] || node[:osqa][:group] || Etc.getpwnam(site_user).gid
+  site_group = Etc.getgrgid(site_group).name if site_group.is_a?(Integer)
+  database_name = site[:database_name] || node[:osqa][:database_name]
+  database_user = site[:database_user] || node[:osqa][:database_user]
+  database_password = site[:database_user] || node[:osqa][:database_password]
+
+  apache_site name do
+    template "apache.erb"
+    directory "#{directory}/osqa"
+    variables :user => site_user, :group => site_group
+  end
+
+  execute "osqa-migrate" do
+    action :nothing
+    command "python manage.py migrate forum"
+    cwd "#{directory}/osqa"
+    user site_user
+    group site_group
+    notifies :reload, resources(:service => "apache2")
+  end
+
+  subversion "#{directory}/osqa" do
+    action :sync
+    repository "http://svn.osqa.net/svnroot/osqa/trunk"
+    revision osqa_revision
+    user site_user
+    group site_group
+    notifies :run, resources(:execute => "osqa-migrate")
+  end
+
+  remote_directory "#{directory}/osqa/forum_modules/osmauth" do
+    source "osmauth"
+    owner site_user
+    group site_group
+    mode 0755
+    files_owner site_user
+    files_group site_group
+    files_mode 0644
+  end
+
+  template "#{directory}/osqa/osqa.wsgi" do
+    source "osqa.wsgi.erb"
+    owner site_user
+    group site_group
+    mode 0644
+    variables :directory => directory
+    notifies :reload, resources(:service => "apache2")
+  end
+
+  file "#{directory}/osqa/settings_local.py" do
+    owner site_user
+    group site_group
+    mode 0644
+    content_from_file "#{directory}/osqa/settings_local.py.dist" do |line|
+      line.gsub!(/^( *)'ENGINE': '.*',/, "\\1'ENGINE': 'django.db.backends.postgresql_psycopg2',")
+      line.gsub!(/^( *)'NAME': '.*',/, "\\1'NAME': '#{database_name}',")
+      line.gsub!(/^( *)'USER': '.*',/, "\\1'USER': '#{database_user}',")
+      line.gsub!(/^( *)'PASSWORD': '.*',/, "\\1'PASSWORD': '#{database_password}',")
+      line.gsub!(/^CACHE_BACKEND = .*/, "CACHE_BACKEND = 'memcached://127.0.0.1:11211/'")
+      line.gsub!(/^APP_URL = 'http:\/\/'/, "APP_URL = 'http://#{name}'")
+      line.gsub!(/^TIME_ZONE = 'America\/New_York'/, "TIME_ZONE = 'Europe/London'")
+      line.gsub!(/^DISABLED_MODULES = \[([^\]]+)\]/, "DISABLED_MODULES = [\\1, 'localauth', 'facebookauth', 'oauthauth']")
+
+      line
+    end
+    notifies :reload, resources(:service => "apache2")
+  end
+end
diff --git a/cookbooks/osqa/templates/default/apache.erb b/cookbooks/osqa/templates/default/apache.erb
new file mode 100644 (file)
index 0000000..ad98501
--- /dev/null
@@ -0,0 +1,31 @@
+# DO NOT EDIT - This file is being maintained by Chef
+
+WSGIDaemonProcess <%= @name %> user=<%= @user %> group=<%= @group %> processes=4 threads=4
+
+<VirtualHost *:80>
+        ServerName <%= @name %>
+        ServerAdmin webmaster@openstreetmap.org
+
+        CustomLog /var/log/apache2/<%= @name %>-access.log combined
+        ErrorLog /var/log/apache2/<%= @name %>-error.log
+
+        RedirectPermanent / https://<%= @name %>/
+</VirtualHost>
+
+<VirtualHost *:443>
+        ServerName <%= @name %>
+        ServerAdmin webmaster@openstreetmap.org
+
+        CustomLog /var/log/apache2/<%= @name %>-access.log combined
+        ErrorLog /var/log/apache2/<%= @name %>-error.log
+
+        DocumentRoot <%= @directory %>
+        Alias /m/ <%= @directory %>/forum/skins/
+        Alias /upfiles/ <%= @directory %>/forum/upfiles/
+        Alias /admin_media/ /usr/share/pyshared/django/contrib/admin/media/
+        WSGIScriptAlias / <%= @directory %>/osqa.wsgi
+
+        WSGIProcessGroup <%= @name %>
+
+        SSLEngine on
+</VirtualHost>
diff --git a/cookbooks/osqa/templates/default/osqa.wsgi.erb b/cookbooks/osqa/templates/default/osqa.wsgi.erb
new file mode 100644 (file)
index 0000000..04487d5
--- /dev/null
@@ -0,0 +1,11 @@
+# DO NOT EDIT - This file is being maintained by Chef
+
+import os
+import sys
+import django.core.handlers.wsgi
+
+sys.path.append('<%= @directory %>')
+sys.path.append('<%= @directory %>/osqa')
+os.environ['DJANGO_SETTINGS_MODULE'] = 'osqa.settings'
+
+application = django.core.handlers.wsgi.WSGIHandler()
diff --git a/cookbooks/otrs/README.rdoc b/cookbooks/otrs/README.rdoc
new file mode 100644 (file)
index 0000000..3de2ec7
--- /dev/null
@@ -0,0 +1,8 @@
+= DESCRIPTION:
+
+= REQUIREMENTS:
+
+= ATTRIBUTES:
+
+= USAGE:
+
diff --git a/cookbooks/otrs/attributes/default.rb b/cookbooks/otrs/attributes/default.rb
new file mode 100644 (file)
index 0000000..b6edde2
--- /dev/null
@@ -0,0 +1,8 @@
+default[:otrs][:version] = "3.1.5"
+default[:otrs][:user] = "otrs"
+default[:otrs][:group] = nil
+default[:otrs][:database_cluster] = "9.1/main"
+default[:otrs][:database_name] = "otrs"
+default[:otrs][:database_user] = "otrs"
+default[:otrs][:database_password] = ""
+default[:otrs][:site] = nil
diff --git a/cookbooks/otrs/metadata.rb b/cookbooks/otrs/metadata.rb
new file mode 100644 (file)
index 0000000..5627836
--- /dev/null
@@ -0,0 +1,53 @@
+maintainer        "OpenStreetMap Administrators"
+maintainer_email  "admins@openstreetmap.org"
+license           "Apache 2.0"
+description       "Installs and configures OTRS"
+long_description  IO.read(File.join(File.dirname(__FILE__), 'README.rdoc'))
+version           "1.0.0"
+depends           "apache"
+depends           "postgresql"
+
+attribute "otrs",
+  :display_name => "OTRS",
+  :description => "Hash of OTRS attributes",
+  :type => "hash"
+
+attribute "otrs/version",
+  :display_name => "OTRS Version",
+  :description => "Version of OTRS to use",
+  :default => "3.1.5"
+
+attribute "otrs/user",
+  :display_name => "User",
+  :description => "Iser to run OTRS as",
+  :default => "otrs"
+
+attribute "otrs/group",
+  :display_name => "Group",
+  :description => "Group to run OTRS as",
+  :default => nil
+
+attribute "otrs/database_cluster",
+  :display_name => "Database Cluster",
+  :description => "Database cluster to run OTRS against",
+  :default => "8.4/main"
+
+attribute "otrs/database_name",
+  :display_name => "Database Name",
+  :description => "Database to run OTRS against",
+  :default => "otrs"
+
+attribute "otrs/database_user",
+  :display_name => "Database User",
+  :description => "User for OTRS to connect to the database as",
+  :default => "otrs"
+
+attribute "otrs/database_password",
+  :display_name => "Database Password",
+  :description => "Password for OTRS to authenticate to the database with",
+  :default => ""
+
+attribute "otrs/site",
+  :display_name => "Site",
+  :description => "Name of OTRS site",
+  :default => nil
diff --git a/cookbooks/otrs/recipes/default.rb b/cookbooks/otrs/recipes/default.rb
new file mode 100644 (file)
index 0000000..731bdf2
--- /dev/null
@@ -0,0 +1,144 @@
+#
+# Cookbook Name:: otrs
+# Recipe:: default
+#
+# Copyright 2012, OpenStreetMap Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+include_recipe "tools"
+include_recipe "apache::ssl"
+
+package "libapache2-mod-perl2"
+package "libapache2-reload-perl"
+
+package "libgd-gd2-perl"
+package "libgd-graph-perl"
+package "libgd-text-perl"
+package "libjson-xs-perl"
+package "libmail-imapclient-perl"
+package "libnet-ldap-perl"
+package "libpdf-api2-perl"
+package "libsoap-lite-perl"
+
+apache_module "headers"
+
+version = node[:otrs][:version]
+user = node[:otrs][:user]
+group = node[:otrs][:group]
+database_cluster = node[:otrs][:database_cluster]
+database_name = node[:otrs][:database_name]
+database_user = node[:otrs][:database_user]
+database_password = node[:otrs][:database_password]
+site = node[:otrs][:site]
+
+remote_file "/tmp/otrs-#{version}.tar.bz2" do
+  source "http://ftp.otrs.org/pub/otrs/otrs-#{version}.tar.bz2"
+  not_if { File.exist?("/opt/otrs-#{version}") }
+end
+
+execute "untar-otrs-#{version}" do
+  command "tar jxf /tmp/otrs-#{version}.tar.bz2"
+  cwd "/opt"
+  user "root"
+  group "root"
+  not_if { File.exist?("/opt/otrs-#{version}") }
+end
+
+file "/opt/otrs-#{version}/Kernel/Config.pm" do
+  owner user
+  group "www-data"
+  mode 0664
+  content_from_file "/opt/otrs-#{version}/Kernel/Config.pm.dist" do |line|
+    line.gsub!(/^( *)\$Self->{Database} = 'otrs'/, "\\1$Self->{Database} = '#{database_name}'")
+    line.gsub!(/^( *)\$Self->{DatabaseUser} = 'otrs'/, "\\1$Self->{DatabaseUser} = '#{database_user}'")
+    line.gsub!(/^( *)\$Self->{DatabasePw} = 'some-pass'/, "\\1$Self->{DatabasePw} = '#{database_password}'")
+    line.gsub!(/^( *)\$Self->{Database} = 'otrs'/, "\\1$Self->{Database} = '#{database_name}'")
+    line.gsub!(/^( *\$Self->{DatabaseDSN} = "DBI:mysql:)/, "#\\1")
+    line.gsub!(/^#( *\$Self->{DatabaseDSN} = "DBI:Pg:.*;host=)/, "\\1")
+
+    line
+  end
+end
+
+file "/opt/otrs-#{version}/Kernel/Config/GenericAgent.pm" do
+  owner user
+  group "www-data"
+  mode 0664
+  content_from_file "/opt/otrs-#{version}/Kernel/Config/GenericAgent.pm.dist" do |line|
+    line
+  end
+end
+
+link "/opt/otrs" do
+  to "/opt/otrs-#{version}"
+end
+
+execute "/opt/otrs/bin/otrs.SetPermissions.pl" do
+  action :run
+  command "/opt/otrs/bin/otrs.SetPermissions.pl --otrs-user=#{user} --web-user=www-data --otrs-group=www-data --web-group=www-data /opt/otrs-#{version}"
+  user "root"
+  group "root"
+  not_if { File.stat("/opt/otrs/README").uid != Etc.getpwnam("otrs").uid }
+end
+
+execute "/opt/otrs/bin/otrs.RebuildConfig.pl" do
+  action :run
+  command "/opt/otrs/bin/otrs.RebuildConfig.pl"
+  user "root"
+  group "root"
+  not_if { File.exist?("/opt/otrs/Kernel/Config/Files/ZZZAAuto.pm") }
+end
+
+if node[:postgresql][:clusters][database_cluster]
+  postgresql_user database_user do
+    cluster database_cluster
+    password database_password
+  end
+
+  postgresql_database database_name do
+    cluster database_cluster
+    owner database_user
+  end
+end
+
+execute "/opt/otrs/bin/Cron.sh" do
+  action :nothing
+  command "/opt/otrs/bin/Cron.sh restart"
+  user "otrs"
+  group "otrs"
+end
+
+Dir.glob("/opt/otrs/var/cron/*.dist") do |distname|
+  name = distname.sub(".dist", "")
+
+  file name do
+    owner "otrs"
+    group "www-data"
+    mode 0664
+    content IO.read(distname)
+    notifies :run, resources(:execute => "/opt/otrs/bin/Cron.sh")
+  end
+end
+
+apache_site site do
+  template "apache.erb"
+end
+
+template "/etc/sudoers.d/otrs" do
+  source "sudoers.erb"
+  owner "root"
+  group "root"
+  mode 0440
+end
diff --git a/cookbooks/otrs/templates/default/apache.erb b/cookbooks/otrs/templates/default/apache.erb
new file mode 100644 (file)
index 0000000..da5a60d
--- /dev/null
@@ -0,0 +1,72 @@
+# DO NOT EDIT - This file is being maintained by Chef
+
+<VirtualHost *:80>
+        ServerName <%= @name %>
+        ServerAdmin webmaster@openstreetmap.org
+
+        CustomLog /var/log/apache2/<%= @name %>-access.log combined
+        ErrorLog /var/log/apache2/<%= @name %>-error.log
+
+        RedirectPermanent / https://otrs.openstreetmap.org/
+</VirtualHost>
+
+<VirtualHost *:443>
+        ServerName <%= @name %>
+        ServerAdmin webmaster@openstreetmap.org
+
+        CustomLog /var/log/apache2/<%= @name %>-access.log combined
+        ErrorLog /var/log/apache2/<%= @name %>-error.log
+
+        SSLEngine on
+
+        ScriptAlias /otrs/ /opt/otrs/bin/cgi-bin/
+        Alias /otrs-web/ /opt/otrs/var/httpd/htdocs/
+        RedirectMatch ^/$ /otrs/index.pl
+
+        PerlRequire /opt/otrs/scripts/apache2-perl-startup.pl
+
+        PerlModule Apache2::Reload
+        PerlInitHandler Apache2::Reload
+        PerlModule Apache2::RequestRec
+
+        <Location /otrs>
+                ErrorDocument 403 /otrs/index.pl
+                ErrorDocument 404 /otrs/index.pl
+                SetHandler  perl-script
+                PerlResponseHandler ModPerl::Registry
+                Options +ExecCGI
+                PerlOptions +ParseHeaders
+                PerlOptions +SetupEnv
+                Order allow,deny
+                Allow from all
+        </Location>
+
+        <Location /otrs/nph-genericinterface.pl>
+                PerlOptions -ParseHeaders
+        </Location>
+</VirtualHost>
+
+<Directory /opt/otrs/bin/cgi-bin>
+        AllowOverride None
+        Options +ExecCGI -Includes
+        Order allow,deny
+        Allow from all
+</Directory>
+
+<Directory /opt/otrs/var/httpd/htdocs>
+        AllowOverride None
+        Order allow,deny
+        Allow from all
+</Directory>
+
+<Directory /opt/otrs/var/httpd/htdocs/skins/*/*/css-cache>
+        <FilesMatch "\.(css|CSS)$">
+                Header set Cache-Control "max-age=2592000 must-revalidate"
+        </FilesMatch>
+</Directory>
+
+<Directory /opt/otrs/var/httpd/htdocs/js/js-cache>
+        <FilesMatch "\.(js|JS)$">
+                Header set Cache-Control "max-age=2592000 must-revalidate"
+        </FilesMatch>
+</Directory>
diff --git a/cookbooks/otrs/templates/default/sudoers.erb b/cookbooks/otrs/templates/default/sudoers.erb
new file mode 100644 (file)
index 0000000..91c73e9
--- /dev/null
@@ -0,0 +1,4 @@
+# DO NOT EDIT - This file is being maintained by Chef
+
+# Allow exim to deliver mail into OTRS
+Debian-exim ALL=(otrs) NOPASSWD: /usr/share/otrs/bin/PostMaster.pl
diff --git a/cookbooks/piwik/README.rdoc b/cookbooks/piwik/README.rdoc
new file mode 100644 (file)
index 0000000..3de2ec7
--- /dev/null
@@ -0,0 +1,8 @@
+= DESCRIPTION:
+
+= REQUIREMENTS:
+
+= ATTRIBUTES:
+
+= USAGE:
+
diff --git a/cookbooks/piwik/metadata.rb b/cookbooks/piwik/metadata.rb
new file mode 100644 (file)
index 0000000..31d80ce
--- /dev/null
@@ -0,0 +1,8 @@
+maintainer        "OpenStreetMap Administrators"
+maintainer_email  "admins@openstreetmap.org"
+license           "Apache 2.0"
+description       "Installs and configures Piwik"
+long_description  IO.read(File.join(File.dirname(__FILE__), 'README.rdoc'))
+version           "1.0.0"
+depends           "apache"
+depends           "mysql"
diff --git a/cookbooks/piwik/recipes/default.rb b/cookbooks/piwik/recipes/default.rb
new file mode 100644 (file)
index 0000000..02fb7a8
--- /dev/null
@@ -0,0 +1,73 @@
+#
+# Cookbook Name:: piwik
+# Recipe:: default
+#
+# Copyright 2011, OpenStreetMap Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+include_recipe "apache::ssl"
+include_recipe "mysql"
+
+passwords = data_bag_item("piwik", "passwords")
+
+package "php5"
+package "php5-cli"
+package "php5-curl"
+package "php5-mysql"
+package "php5-gd"
+
+package "php-apc"
+
+package "geoip-database-contrib"
+
+apache_module "php5"
+apache_module "geoip"
+
+apache_site "piwik.openstreetmap.org" do
+  template "apache.erb"
+end
+
+directory "/srv/piwik.openstreetmap.org" do
+  owner "root"
+  group "root"
+  mode "0755"
+end
+
+directory "/srv/piwik.openstreetmap.org/config" do
+  owner "www-data"
+  group "www-data"
+  mode "0755"
+end
+
+directory "/srv/piwik.openstreetmap.org/tmp" do
+  owner "www-data"
+  group "www-data"
+  mode "0755"
+end
+
+template "/etc/cron.d/piwiki" do
+  source "cron.erb"
+  owner "root"
+  group "root"
+  mode "0644"
+end
+
+mysql_user "piwik@localhost" do
+  password passwords["database"]
+end
+
+mysql_database "piwik" do
+  permissions "piwik@localhost" => :all
+end
diff --git a/cookbooks/piwik/templates/default/apache.erb b/cookbooks/piwik/templates/default/apache.erb
new file mode 100644 (file)
index 0000000..5229358
--- /dev/null
@@ -0,0 +1,28 @@
+# DO NOT EDIT - This file is being maintained by Chef
+
+<VirtualHost *:80>
+       ServerName piwik.openstreetmap.org
+       ServerAlias piwik.osm.org
+       ServerAdmin webmaster@openstreetmap.org
+
+       CustomLog /var/log/apache2/piwik.openstreetmap.org-access.log combined
+       ErrorLog /var/log/apache2/piwik.openstreetmap.org-error.log
+
+       DocumentRoot /srv/piwik.openstreetmap.org
+</VirtualHost>
+
+<VirtualHost *:443>
+       ServerName piwik.openstreetmap.org
+       ServerAdmin webmaster@openstreetmap.org
+
+       SSLEngine on
+       SSLProtocol all -SSLv2
+       SSLCipherSuite ALL:!ADH:!EXPORT:!SSLv2:RC4+RSA:+HIGH:+MEDIUM:+LOW
+       SSLCertificateFile /etc/ssl/certs/openstreetmap.pem
+       SSLCertificateKeyFile /etc/ssl/private/openstreetmap.key
+
+       CustomLog /var/log/apache2/piwik.openstreetmap.org-access.log combined
+       ErrorLog /var/log/apache2/piwik.openstreetmap.org-error.log
+
+       DocumentRoot /srv/piwik.openstreetmap.org
+</VirtualHost>
diff --git a/cookbooks/piwik/templates/default/cron.erb b/cookbooks/piwik/templates/default/cron.erb
new file mode 100644 (file)
index 0000000..7bf5484
--- /dev/null
@@ -0,0 +1 @@
+5 * * * * www-data /usr/bin/php5 /srv/piwik.openstreetmap.org/misc/cron/archive.php --url=http://piwik.openstreetmap.org/ > /dev/null
diff --git a/cookbooks/postgresql/README.rdoc b/cookbooks/postgresql/README.rdoc
new file mode 100644 (file)
index 0000000..3de2ec7
--- /dev/null
@@ -0,0 +1,8 @@
+= DESCRIPTION:
+
+= REQUIREMENTS:
+
+= ATTRIBUTES:
+
+= USAGE:
+
diff --git a/cookbooks/postgresql/attributes/default.rb b/cookbooks/postgresql/attributes/default.rb
new file mode 100644 (file)
index 0000000..1bfdb83
--- /dev/null
@@ -0,0 +1,30 @@
+default[:postgresql][:versions] = []
+default[:postgresql][:clusters] = {}
+default[:postgresql][:settings][:defaults][:port] = "5432"
+default[:postgresql][:settings][:defaults][:max_connections] = "100"
+default[:postgresql][:settings][:defaults][:shared_buffers] = "32MB"
+default[:postgresql][:settings][:defaults][:temp_buffers] = "8MB"
+default[:postgresql][:settings][:defaults][:work_mem] = "1MB"
+default[:postgresql][:settings][:defaults][:maintenance_work_mem] = "16MB"
+default[:postgresql][:settings][:defaults][:max_stack_depth] = "2MB"
+default[:postgresql][:settings][:defaults][:wal_level] = "minimal"
+default[:postgresql][:settings][:defaults][:fsync] = "on"
+default[:postgresql][:settings][:defaults][:synchronous_commit] = "on"
+default[:postgresql][:settings][:defaults][:wal_buffers] = "-1"
+default[:postgresql][:settings][:defaults][:wal_writer_delay] = "200ms"
+default[:postgresql][:settings][:defaults][:commit_delay] = "0"
+default[:postgresql][:settings][:defaults][:checkpoint_segments] = "3"
+default[:postgresql][:settings][:defaults][:checkpoint_timeout] = "5min"
+default[:postgresql][:settings][:defaults][:checkpoint_completion_target] = "0.5"
+default[:postgresql][:settings][:defaults][:archive_mode] = "off"
+default[:postgresql][:settings][:defaults][:max_wal_senders] = "0"
+default[:postgresql][:settings][:defaults][:hot_standby] = "off"
+default[:postgresql][:settings][:defaults][:hot_standby_feedback] = "off"
+default[:postgresql][:settings][:defaults][:random_page_cost] = "4.0"
+default[:postgresql][:settings][:defaults][:effective_cache_size] = "128MB"
+default[:postgresql][:settings][:defaults][:log_min_duration_statement] = "-1"
+default[:postgresql][:settings][:defaults][:autovacuum_max_workers] = "3"
+default[:postgresql][:settings][:defaults][:user_name_maps] = {}
+default[:postgresql][:settings][:defaults][:early_authentication_rules] = []
+default[:postgresql][:settings][:defaults][:late_authentication_rules] = []
+default[:postgresql][:settings][:defaults][:standby_mode] = "off"
diff --git a/cookbooks/postgresql/definitions/postgresql_munin.rb b/cookbooks/postgresql/definitions/postgresql_munin.rb
new file mode 100644 (file)
index 0000000..8062044
--- /dev/null
@@ -0,0 +1,94 @@
+#
+# Cookbook Name:: postgresql
+# Definition:: postgresql_munin
+#
+# Copyright 2012, OpenStreetMap Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+define :postgresql_munin, :action => :create do
+  cluster = params[:cluster]
+  suffix = cluster.tr("/", ":")
+  database = params[:database]
+
+  if node[:postgresql][:clusters] and node[:postgresql][:clusters][cluster]
+    munin_plugin "postgres_cache_#{database}:#{suffix}" do
+      action params[:action]
+      target "postgres_cache_"
+      conf "munin.erb"
+      conf_cookbook "postgresql"
+      conf_variables :port => node[:postgresql][:clusters][cluster][:port]
+    end
+
+    munin_plugin "postgres_connections_#{database}:#{suffix}" do
+      action params[:action]
+      target "postgres_connections_"
+      conf "munin.erb"
+      conf_cookbook "postgresql"
+      conf_variables :port => node[:postgresql][:clusters][cluster][:port]
+    end
+
+    munin_plugin "postgres_locks_#{database}:#{suffix}" do
+      action params[:action]
+      target "postgres_locks_"
+      conf "munin.erb"
+      conf_cookbook "postgresql"
+      conf_variables :port => node[:postgresql][:clusters][cluster][:port]
+    end
+
+    munin_plugin "postgres_querylength_#{database}:#{suffix}" do
+      action params[:action]
+      target "postgres_querylength_"
+      conf "munin.erb"
+      conf_cookbook "postgresql"
+      conf_variables :port => node[:postgresql][:clusters][cluster][:port]
+    end
+
+    munin_plugin "postgres_scans_#{database}:#{suffix}" do
+      action params[:action]
+      target "postgres_scans_"
+      conf "munin.erb"
+      conf_cookbook "postgresql"
+      conf_variables :port => node[:postgresql][:clusters][cluster][:port]
+    end
+
+    munin_plugin "postgres_size_#{database}:#{suffix}" do
+      action params[:action]
+      target "postgres_size_"
+      conf "munin.erb"
+      conf_cookbook "postgresql"
+      conf_variables :port => node[:postgresql][:clusters][cluster][:port]
+    end
+
+    munin_plugin "postgres_transactions_#{database}:#{suffix}" do
+      action params[:action]
+      target "postgres_transactions_"
+      conf "munin.erb"
+      conf_cookbook "postgresql"
+      conf_variables :port => node[:postgresql][:clusters][cluster][:port]
+    end
+
+    munin_plugin "postgres_tuples_#{database}:#{suffix}" do
+      action params[:action]
+      target "postgres_tuples_"
+      conf "munin.erb"
+      conf_cookbook "postgresql"
+      conf_variables :port => node[:postgresql][:clusters][cluster][:port]
+    end
+  else
+    log "Postgres cluster #{cluster} not found" do
+      level :warn
+    end
+  end
+end
diff --git a/cookbooks/postgresql/libraries/postgresql.rb b/cookbooks/postgresql/libraries/postgresql.rb
new file mode 100644 (file)
index 0000000..bd10a02
--- /dev/null
@@ -0,0 +1,130 @@
+require 'chef/mixin/command'
+
+class Chef
+  class PostgreSQL
+    include Chef::Mixin::Command
+
+    TABLE_PRIVILEGES = [
+      :select, :insert, :update, :delete, :truncate, :references, :trigger
+    ]
+
+    def initialize(cluster)
+      @cluster = cluster
+    end
+
+    def execute(options)
+      # Create argument array
+      args = []
+
+      # Build the arguments
+      args.push("--command=\"#{options[:command].gsub('"', '\\"')}\"") if options[:command]
+      args.push("--file=#{options[:file]}") if options[:file]
+
+      # Get the database to use
+      database = options[:database] || "template1"
+
+      # Build the command to run
+      command = "/usr/bin/psql --cluster #{@cluster} #{args.join(' ')} #{database}"
+
+      # Get the user and group to run as
+      user = options[:user] || "postgres"
+      group = options[:group] || "postgres"
+
+      # Run the command
+      run_command(:command => command, :user => user, :group => group)
+    end
+
+    def query(sql, options = {})
+      # Get the database to use
+      database = options[:database] || "template1"
+
+      # Construct the command string
+      command = "/usr/bin/psql --cluster #{@cluster} --no-align --command='#{sql}' #{database}"
+
+      # Run the query
+      status, stdout, stderr = output_of_command(command, :user => "postgres", :group => "postgres")
+      handle_command_failures(status, "STDOUT: #{stdout}\nSTDERR: #{stderr}", :output_on_failure => true)
+
+      # Split the output into lines
+      lines = stdout.split("\n")
+
+      # Remove the "(N rows)" line from the end
+      lines.pop
+
+      # Get the field names
+      fields = lines.shift.split("|")
+
+      # Extract the record data
+      lines.collect do |line|
+        record = {}
+        fields.zip(line.split("|")) { |name,value| record[name.to_sym] = value }
+        record
+      end
+    end
+
+    def users
+      @users ||= query("SELECT * FROM pg_user").inject({}) do |users,user|
+        users[user[:usename]] = {
+          :superuser => user[:usesuper] == "t",
+          :createdb => user[:usercreatedb] == "t",
+          :createrole => user[:usecatupd] == "t",
+          :replication => user[:userepl] == "t"
+        }
+        users
+      end
+    end
+
+    def databases
+      @databases ||= query("SELECT d.datname, u.usename, d.encoding FROM pg_database AS d INNER JOIN pg_user AS u ON d.datdba = u.usesysid").inject({}) do |databases,database|
+        databases[database[:datname]] = {
+          :owner => database[:usename],
+          :encoding => database[:encoding]
+        }
+        databases
+      end
+    end
+
+    def extensions(database)
+      @extensions ||= {}
+      @extensions[database] ||= query("SELECT extname, extversion FROM pg_extension", :database => database).inject({}) do |extensions,extension|
+        extensions[extension[:extname]] = {
+          :version => extension[:extversion]
+        }
+        databases
+      end
+    end
+
+    def tables(database)
+      @tables ||= {}
+      @tables[database] ||= query("SELECT n.nspname, c.relname, u.usename, c.relacl FROM pg_class AS c INNER JOIN pg_user AS u ON c.relowner = u.usesysid INNER JOIN pg_namespace AS n ON c.relnamespace = n.oid", :database => database).inject({}) do |tables,table|
+        name = "#{table[:nspname]}.#{table[:relname]}"
+
+        tables[name] = {
+          :owner => table[:usename],
+          :permissions => parse_acl(table[:relacl] || "{}")
+        }
+
+        tables
+      end
+    end
+
+  private
+
+    def parse_acl(acl)
+      acl.sub(/^\{(.*)\}$/, "\\1").split(",").inject({}) do |permissions, entry|
+        entry = entry.sub(/^"(.*)"$/) { $1.gsub(/\\"/, '"') }.sub(/\/.*$/, "")
+        user, privileges = entry.split("=")
+
+        user = user.sub(/^"(.*)"$/, "\\1")
+        user = "public" if user == ""
+
+        permissions[user] = {
+          "a" => :insert, "r" => :select, "w" => :update, "d" => :delete,
+          "D" => :truncate, "x" => :references, "t" => :trigger
+        }.values_at(*(privileges.chars)).compact
+
+        permissions
+      end
+    end
+  end
+end
diff --git a/cookbooks/postgresql/metadata.rb b/cookbooks/postgresql/metadata.rb
new file mode 100644 (file)
index 0000000..f2ad194
--- /dev/null
@@ -0,0 +1,18 @@
+maintainer        "OpenStreetMap Administrators"
+maintainer_email  "admins@openstreetmap.org"
+license           "Apache 2.0"
+description       "Installs and configures postgresql"
+long_description  IO.read(File.join(File.dirname(__FILE__), 'README.rdoc'))
+version           "1.0.0"
+depends           "chef"
+
+attribute "postgresql",
+  :display_name => "PostgreSQL",
+  :description => "Hash of PostgreSQL configuration details",
+  :type => "hash"
+
+attribute "postgresql/versions",
+  :display_name => "Versions",
+  :description => "List of versions to install",
+  :type => "array",
+  :default => []
diff --git a/cookbooks/postgresql/providers/database.rb b/cookbooks/postgresql/providers/database.rb
new file mode 100644 (file)
index 0000000..eee7903
--- /dev/null
@@ -0,0 +1,50 @@
+#
+# Cookbook Name:: postgresql
+# Provider:: postgresql_database
+#
+# Copyright 2012, OpenStreetMap Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+def load_current_resource
+  @pg = Chef::PostgreSQL.new(new_resource.cluster)
+
+  @current_resource = Chef::Resource::PostgresqlDatabase.new(new_resource.name)
+  @current_resource.database(new_resource.database)
+  @current_resource.cluster(new_resource.cluster)
+  if pg_database = @pg.databases[@current_resource.database]
+    @current_resource.owner(pg_database[:owner])
+    @current_resource.encoding(pg_database[:encoding])
+  end
+  @current_resource
+end
+
+action :create do
+  unless @pg.databases.include?(new_resource.database)
+    @pg.execute(:command => "CREATE DATABASE #{new_resource.database} OWNER #{new_resource.owner} ENCODING '#{new_resource.encoding}'")
+    new_resource.updated_by_last_action(true)
+  else
+    if new_resource.owner != @current_resource.owner
+      @pg.execute(:command => "ALTER DATABASE #{new_resource.database} OWNER TO #{new_resource.owner}")
+      new_resource.updated_by_last_action(true)
+    end
+  end
+end
+
+action :drop do
+  if @pg.databases.include?(new_resource.database)
+    @pg.execute(:command => "DROP DATABASE #{new_resource.database}")
+    new_resource.updated_by_last_action(true)
+  end
+end
diff --git a/cookbooks/postgresql/providers/execute.rb b/cookbooks/postgresql/providers/execute.rb
new file mode 100644 (file)
index 0000000..2b7bd5f
--- /dev/null
@@ -0,0 +1,42 @@
+#
+# Cookbook Name:: postgresql
+# Provider:: postgresql_execute
+#
+# Copyright 2012, OpenStreetMap Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+def load_current_resource
+  @pg = Chef::PostgreSQL.new(new_resource.cluster)
+
+  @current_resource = Chef::Resource::PostgresqlExecute.new(new_resource.name)
+  @current_resource.cluster(new_resource.cluster)
+  @current_resource.database(new_resource.database)
+  @current_resource
+end
+
+action :nothing do
+end
+
+action :run do
+  options = { :database => new_resource.database, :user => new_resource.user, :group => new_resource.group }
+
+  if ::File.exist?(new_resource.command)
+    @pg.execute(options.merge(:file => new_resource.command))
+  else
+    @pg.execute(options.merge(:command => new_resource.command))
+  end
+
+  new_resource.updated_by_last_action(true)
+end
diff --git a/cookbooks/postgresql/providers/extension.rb b/cookbooks/postgresql/providers/extension.rb
new file mode 100644 (file)
index 0000000..81a9760
--- /dev/null
@@ -0,0 +1,42 @@
+#
+# Cookbook Name:: postgresql
+# Provider:: postgresql_extension
+#
+# Copyright 2012, OpenStreetMap Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+def load_current_resource
+  @pg = Chef::PostgreSQL.new(new_resource.cluster)
+
+  @current_resource = Chef::Resource::PostgresqlExtension.new(new_resource.name)
+  @current_resource.extension(new_resource.extension)
+  @current_resource.cluster(new_resource.cluster)
+  @current_resource.database(new_resource.database)
+  @current_resource
+end
+
+action :create do
+  unless @pg.extensions(new_resource.database).include?(new_resource.extension)
+    @pg.execute(:command => "CREATE EXTENSION #{new_resource.extension}", :database => new_resource.database)
+    new_resource.updated_by_last_action(true)
+  end
+end
+
+action :drop do
+  if @pg.extensions(new_resource.database).include?(new_resource.extension)
+    @pg.execute(:command => "DROP EXTENSION #{new_resource.extension}", :database => new_resource.database)
+    new_resource.updated_by_last_action(true)
+  end
+end
diff --git a/cookbooks/postgresql/providers/table.rb b/cookbooks/postgresql/providers/table.rb
new file mode 100644 (file)
index 0000000..4a2b43f
--- /dev/null
@@ -0,0 +1,90 @@
+#
+# Cookbook Name:: postgresql
+# Provider:: postgresql_table
+#
+# Copyright 2013, OpenStreetMap Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+def load_current_resource
+  @pg = Chef::PostgreSQL.new(new_resource.cluster)
+  @tables = @pg.tables(new_resource.database)
+  @name = "#{new_resource.schema}.#{new_resource.name}"
+
+  @current_resource = Chef::Resource::PostgresqlTable.new(new_resource.name)
+  @current_resource.cluster(new_resource.cluster)
+  @current_resource.database(new_resource.database)
+  @current_resource.schema(new_resource.schema)
+  if pg_table = @tables[@name]
+    @current_resource.owner(pg_table[:owner])
+    @current_resource.permissions(pg_table[:permissions])
+  end
+  @current_resource
+end
+
+action :create do
+  if @tables.include?(@name)
+    if new_resource.owner != @current_resource.owner
+      converge_by("set owner for #{new_resource} to #{new_resource.owner}") do
+        Chef::Log.info("Setting owner for #{new_resource} to #{new_resource.owner}")
+        @pg.execute(:command => "ALTER TABLE #{@name} OWNER TO \"#{new_resource.owner}\"", :database => new_resource.database)
+      end
+    end
+
+    @current_resource.permissions.each do |user,privileges|
+      unless new_resource.permissions[user]
+        converge_by("revoke all for #{user} on #{new_resource}") do
+          Chef::Log.info("Revoking all for #{user} on #{new_resource}")
+          @pg.execute(:command => "REVOKE ALL ON #{@name} FROM \"#{user}\"", :database => new_resource.database)
+        end
+      end
+    end
+
+    new_resource.permissions.each do |user,new_privileges|
+      current_privileges = @current_resource.permissions[user] || {}
+      new_privileges = Array(new_privileges)
+      
+      if new_privileges.include?(:all)
+        new_privileges |= Chef::PostgreSQL::TABLE_PRIVILEGES
+      end
+
+      Chef::PostgreSQL::TABLE_PRIVILEGES.each do |privilege|
+        if new_privileges.include?(privilege)
+          unless current_privileges.include?(privilege)
+            converge_by("grant #{privilege} for #{user} on #{new_resource}") do
+              Chef::Log.info("Granting #{privilege} for #{user} on #{new_resource}")
+              @pg.execute(:command => "GRANT #{privilege.to_s.upcase} ON #{@name} TO \"#{user}\"", :database => new_resource.database)
+            end
+          end
+        else
+          if current_privileges.include?(privilege)
+            converge_by("revoke #{privilege} for #{user} on #{new_resource}") do
+              Chef::Log.info("Revoking #{privilege} for #{user} on #{new_resource}")
+              @pg.execute(:command => "REVOKE #{privilege.to_s.upcase} ON #{@name} FROM \"#{user}\"", :database => new_resource.database)
+            end
+          end
+        end
+      end
+    end
+  end
+end
+
+action :drop do
+  if @tables.include?(@name)
+    converge_by("drop #{new_resource}") do
+      Chef::Log.info("Dropping #{new_resource}")
+      @pg.execute(:command => "DROP TABLE #{@name}", :database => new_resource.database)
+    end
+  end
+end
diff --git a/cookbooks/postgresql/providers/user.rb b/cookbooks/postgresql/providers/user.rb
new file mode 100644 (file)
index 0000000..11c783e
--- /dev/null
@@ -0,0 +1,75 @@
+#
+# Cookbook Name:: postgresql
+# Provider:: postgresql_user
+#
+# Copyright 2012, OpenStreetMap Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+def load_current_resource
+  @pg = Chef::PostgreSQL.new(new_resource.cluster)
+
+  @current_resource = Chef::Resource::PostgresqlUser.new(new_resource.name)
+  @current_resource.user(new_resource.user)
+  @current_resource.cluster(new_resource.cluster)
+  if pg_user = @pg.users[@current_resource.user]
+    @current_resource.superuser(pg_user[:superuser])
+    @current_resource.createdb(pg_user[:createdb])
+    @current_resource.createrole(pg_user[:createrole])
+    @current_resource.replication(pg_user[:replication])
+  end
+  @current_resource
+end
+
+action :create do
+  password = new_resource.password ? "ENCRYPTED PASSWORD '#{new_resource.password}'" : ""
+  superuser = new_resource.superuser ? "SUPERUSER" : "NOSUPERUSER"
+  createdb = new_resource.createdb ? "CREATEDB" : "NOCREATEDB"
+  createrole = new_resource.createrole ? "CREATEROLE" : "NOCREATEROLE"
+  replication = new_resource.replication ? "REPLICATION" : "NOREPLICATION"
+
+  unless @pg.users.include?(new_resource.user)
+    @pg.execute(:command => "CREATE ROLE \"#{new_resource.user}\" LOGIN #{password} #{superuser} #{createdb} #{createrole}")
+    new_resource.updated_by_last_action(true)
+  else
+    if new_resource.superuser != @current_resource.superuser
+      @pg.execute(:command => "ALTER ROLE \"#{new_resource.user}\" #{superuser}")
+      new_resource.updated_by_last_action(true)
+    end
+
+    unless new_resource.superuser
+      if new_resource.createdb != @current_resource.createdb
+        @pg.execute(:command => "ALTER ROLE \"#{new_resource.user}\" #{createdb}")
+        new_resource.updated_by_last_action(true)
+      end
+
+      if new_resource.createrole != @current_resource.createrole
+        @pg.execute(:command => "ALTER ROLE \"#{new_resource.user}\" #{createrole}")
+        new_resource.updated_by_last_action(true)
+      end
+
+      if new_resource.replication != @current_resource.replication
+        @pg.execute(:command => "ALTER ROLE \"#{new_resource.user}\" #{replication}")
+        new_resource.updated_by_last_action(true)
+      end
+    end
+  end
+end
+
+action :drop do
+  if @pg.users.include?(new_resource.user)
+    @pg.execute(:command => "DROP ROLE \"#{new_resource.user}\"")
+    new_resource.updated_by_last_action(true)
+  end
+end
diff --git a/cookbooks/postgresql/recipes/default.rb b/cookbooks/postgresql/recipes/default.rb
new file mode 100644 (file)
index 0000000..c054a13
--- /dev/null
@@ -0,0 +1,168 @@
+#
+# Cookbook Name:: postgresql
+# Recipe:: default
+#
+# Copyright 2012, OpenStreetMap Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+if File.exists?("/etc/init.d/postgresql")
+  service "postgresql" do
+    action [ :enable, :start ]
+    supports :status => true, :restart => true, :reload => true
+  end
+end
+
+node[:postgresql][:versions].each do |version|
+  package "postgresql-#{version}"
+  package "postgresql-client-#{version}"
+  package "postgresql-contrib-#{version}"
+  package "postgresql-server-dev-#{version}"
+
+  if File.exists?("/etc/init.d/postgresql-#{version}")
+    service "postgresql-#{version}" do
+      action [ :enable, :start ]
+      supports :status => true, :restart => true, :reload => true
+    end
+  end
+
+  defaults = node[:postgresql][:settings][:defaults] || {}
+  settings = node[:postgresql][:settings][version] || {}
+
+  template "/etc/postgresql/#{version}/main/postgresql.conf" do
+    source "postgresql.conf.erb"
+    owner "postgres"
+    group "postgres"
+    mode 0644
+    variables :version => version, :defaults => defaults, :settings => settings
+    if File.exists?("/etc/init.d/postgresql-#{version}")
+      notifies :reload, resources(:service => "postgresql-#{version}")
+    else
+      notifies :reload, resources(:service => "postgresql")
+    end
+  end
+
+  template "/etc/postgresql/#{version}/main/pg_hba.conf" do
+    source "pg_hba.conf.erb"
+    owner "postgres"
+    group "postgres"
+    mode 0640
+    variables :early_rules => settings[:early_authentication_rules] || defaults[:early_authentication_rules],
+              :late_rules => settings[:late_authentication_rules] || defaults[:late_authentication_rules]
+    if File.exists?("/etc/init.d/postgresql-#{version}")
+      notifies :reload, resources(:service => "postgresql-#{version}")
+    else
+      notifies :reload, resources(:service => "postgresql")
+    end
+  end
+
+  template "/etc/postgresql/#{version}/main/pg_ident.conf" do
+    source "pg_ident.conf.erb"
+    owner "postgres"
+    group "postgres"
+    mode 0640
+    variables :maps => settings[:user_name_maps] || defaults[:user_name_maps]
+    if File.exists?("/etc/init.d/postgresql-#{version}")
+      notifies :reload, resources(:service => "postgresql-#{version}")
+    else
+      notifies :reload, resources(:service => "postgresql")
+    end
+  end
+
+  link "/var/lib/postgresql/#{version}/main/server.crt" do
+    to "/etc/ssl/certs/ssl-cert-snakeoil.pem"
+  end
+
+  link "/var/lib/postgresql/#{version}/main/server.key" do
+    to "/etc/ssl/private/ssl-cert-snakeoil.key"
+  end
+
+  restore_command = settings[:restore_command] || defaults[:restore_command]
+  standby_mode = settings[:standby_mode] || defaults[:standby_mode]
+
+  if restore_command || standby_mode == "on"
+    template "/var/lib/postgresql/#{version}/main/recovery.conf" do
+      source "recovery.conf.erb"
+      owner "postgres"
+      group "postgres"
+      mode 0640
+      variables :defaults => defaults, :settings => settings
+      if File.exists?("/etc/init.d/postgresql-#{version}")
+        notifies :reload, resources(:service => "postgresql-#{version}")
+      else
+        notifies :reload, resources(:service => "postgresql")
+      end
+    end
+  else
+    template "/var/lib/postgresql/#{version}/main/recovery.conf" do
+      action :delete
+      if File.exists?("/etc/init.d/postgresql-#{version}")
+        notifies :reload, resources(:service => "postgresql-#{version}")
+      else
+        notifies :reload, resources(:service => "postgresql")
+      end
+    end
+  end
+end
+
+ohai_plugin "postgresql" do
+  template "ohai.rb.erb"
+end
+
+package "ptop"
+package "libdbd-pg-perl"
+
+clusters = node[:postgresql][:clusters] || []
+
+clusters.each do |name,details|
+  suffix = name.tr("/", ":")
+
+  munin_plugin "postgres_bgwriter_#{suffix}" do
+    target "postgres_bgwriter"
+    conf "munin.erb"
+    conf_variables :port => details[:port]
+  end
+
+  munin_plugin "postgres_checkpoints_#{suffix}" do
+    target "postgres_checkpoints"
+    conf "munin.erb"
+    conf_variables :port => details[:port]
+  end
+
+  munin_plugin "postgres_connections_db_#{suffix}" do
+    target "postgres_connections_db"
+    conf "munin.erb"
+    conf_variables :port => details[:port]
+  end
+
+  munin_plugin "postgres_users_#{suffix}" do
+    target "postgres_users"
+    conf "munin.erb"
+    conf_variables :port => details[:port]
+  end
+
+  munin_plugin "postgres_xlog_#{suffix}" do
+    target "postgres_xlog"
+    conf "munin.erb"
+    conf_variables :port => details[:port]
+  end
+
+  if File.exist?("/var/lib/postgresql/#{details[:version]}/main/recovery.conf")
+    munin_plugin "postgres_replication_#{suffix}" do
+      target "postgres_replication"
+      conf "munin.erb"
+      conf_variables :port => details[:port]
+    end
+  end
+end
diff --git a/cookbooks/postgresql/resources/database.rb b/cookbooks/postgresql/resources/database.rb
new file mode 100644 (file)
index 0000000..039c124
--- /dev/null
@@ -0,0 +1,30 @@
+#
+# Cookbook Name:: postgresql
+# Resource:: postgresql_database
+#
+# Copyright 2012, OpenStreetMap Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+actions :create, :drop
+
+attribute :database, :kind_of => String, :name_attribute => true
+attribute :cluster, :kind_of => String, :required => true
+attribute :owner, :kind_of => String, :required => true
+attribute :encoding, :kind_of => String, :default => "UTF8"
+
+def initialize(*args)
+  super
+  @action = :create
+end
diff --git a/cookbooks/postgresql/resources/execute.rb b/cookbooks/postgresql/resources/execute.rb
new file mode 100644 (file)
index 0000000..49ff80e
--- /dev/null
@@ -0,0 +1,31 @@
+#
+# Cookbook Name:: postgresql
+# Resource:: postgresql_execute
+#
+# Copyright 2012, OpenStreetMap Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+actions :nothing, :run
+
+attribute :command, :kind_of => String, :name_attribute => true
+attribute :cluster, :kind_of => String, :required => true
+attribute :database, :kind_of => String, :required => true
+attribute :user, :default => "postgres"
+attribute :group, :default => "postgres"
+
+def initialize(*args)
+  super
+  @action = :run
+end
diff --git a/cookbooks/postgresql/resources/extension.rb b/cookbooks/postgresql/resources/extension.rb
new file mode 100644 (file)
index 0000000..8c876f4
--- /dev/null
@@ -0,0 +1,29 @@
+#
+# Cookbook Name:: postgresql
+# Resource:: postgresql_extension
+#
+# Copyright 2012, OpenStreetMap Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+actions :create, :drop
+
+attribute :extension, :kind_of => String, :name_attribute => true
+attribute :cluster, :kind_of => String, :required => true
+attribute :database, :kind_of => String, :required => true
+
+def initialize(*args)
+  super
+  @action = :create
+end
diff --git a/cookbooks/postgresql/resources/table.rb b/cookbooks/postgresql/resources/table.rb
new file mode 100644 (file)
index 0000000..9bf1fe1
--- /dev/null
@@ -0,0 +1,28 @@
+#
+# Cookbook Name:: postgresql
+# Resource:: postgresql_table
+#
+# Copyright 2013, OpenStreetMap Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+actions :create, :drop
+default_action :create
+
+attribute :table, :kind_of => String, :name_attribute => true
+attribute :cluster, :kind_of => String, :required => true
+attribute :database, :kind_of => String, :required => true
+attribute :schema, :kind_of => String, :default => "public"
+attribute :owner, :kind_of => String, :required => true
+attribute :permissions, :kind_of => Hash, :default => {}
diff --git a/cookbooks/postgresql/resources/user.rb b/cookbooks/postgresql/resources/user.rb
new file mode 100644 (file)
index 0000000..f5fefa3
--- /dev/null
@@ -0,0 +1,33 @@
+#
+# Cookbook Name:: postgresql
+# Resource:: postgresql_user
+#
+# Copyright 2012, OpenStreetMap Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+actions :create, :drop
+
+attribute :user, :kind_of => String, :name_attribute => true
+attribute :cluster, :kind_of => String, :required => true
+attribute :password, :kind_of => String
+attribute :superuser, :default => false
+attribute :createdb, :default => false
+attribute :createrole, :default => false
+attribute :replication, :default => false
+
+def initialize(*args)
+  super
+  @action = :create
+end
diff --git a/cookbooks/postgresql/templates/default/munin.erb b/cookbooks/postgresql/templates/default/munin.erb
new file mode 100644 (file)
index 0000000..fd08870
--- /dev/null
@@ -0,0 +1,6 @@
+# DO NOT EDIT - This file is being maintained by Chef
+
+[<%= @name %>]
+user postgres
+env.PGUSER postgres
+env.PGPORT <%= @port %>
diff --git a/cookbooks/postgresql/templates/default/ohai.rb.erb b/cookbooks/postgresql/templates/default/ohai.rb.erb
new file mode 100644 (file)
index 0000000..e3eca3a
--- /dev/null
@@ -0,0 +1,17 @@
+provides "postgresql"
+
+postgresql Mash.new
+
+Dir.glob("/etc/postgresql/*/*/postgresql.conf").each do |conf|
+  cluster = conf.sub("/etc/postgresql/", "").sub("/postgresql.conf", "")
+
+  postgresql[:clusters] = Mash.new unless postgresql[:clusters]
+  postgresql[:clusters][cluster] = Mash.new unless postgresql[:clusters][cluster]
+  postgresql[:clusters][cluster][:version] = cluster.split("/").first.to_f
+
+  IO.foreach(conf) do |line|
+    if line =~ /^ *port *= *([0-9]+)\s+/
+      postgresql[:clusters][cluster][:port] = $1
+    end
+  end
+end
diff --git a/cookbooks/postgresql/templates/default/pg_hba.conf.erb b/cookbooks/postgresql/templates/default/pg_hba.conf.erb
new file mode 100644 (file)
index 0000000..18b490c
--- /dev/null
@@ -0,0 +1,12 @@
+# DO NOT EDIT - This file is being maintained by Chef
+
+# TYPE DATABASE        USER            ADDRESS                 METHOD
+<% @early_rules.each do |rule| -%>
+<%= rule[:type] || "host" %>   <%= rule[:database] || "all" %>         <%= rule[:user] || "all" %>             <%= rule[:address] %>           <%= rule[:method] || "md5" %> <%= (rule[:options] || {}).collect { |k,v| "#{k}=#{v}" }.join(" ") %>
+<% end -%>
+local  all             all                                     peer
+host   all             all             127.0.0.1/32            md5
+host   all             all             ::1/128                 md5
+<% @late_rules.each do |rule| -%>
+<%= rule[:type] || "host" %>   <%= rule[:database] || "all" %>         <%= rule[:user] || "all" %>             <%= rule[:address] %>           <%= rule[:method] || "md5" %> <%= (rule[:options] || {}).collect { |k,v| "#{k}=#{v}" }.join(" ") %>
+<% end -%>
diff --git a/cookbooks/postgresql/templates/default/pg_ident.conf.erb b/cookbooks/postgresql/templates/default/pg_ident.conf.erb
new file mode 100644 (file)
index 0000000..d46a05f
--- /dev/null
@@ -0,0 +1,8 @@
+# DO NOT EDIT - This file is being maintained by Chef
+
+# MAPNAME      SYSTEM-USERNAME         PG-USERNAME
+<% @maps.keys.each do |name| -%>
+<% @maps[name].each do |user| -%>
+<%= name %>    <%= user[:system] %>    <%= user[:postgres] %>
+<% end -%>
+<% end -%>
diff --git a/cookbooks/postgresql/templates/default/postgresql.conf.erb b/cookbooks/postgresql/templates/default/postgresql.conf.erb
new file mode 100644 (file)
index 0000000..01b7968
--- /dev/null
@@ -0,0 +1,119 @@
+# DO NOT EDIT - This file is being maintained by Chef
+
+#------------------------------------------------------------------------------
+# FILE LOCATIONS
+#------------------------------------------------------------------------------
+
+data_directory = '/var/lib/postgresql/<%= @version %>/main'
+hba_file = '/etc/postgresql/<%= @version %>/main/pg_hba.conf'
+ident_file = '/etc/postgresql/<%= @version %>/main/pg_ident.conf'
+external_pid_file = '/var/run/postgresql/<%= @version %>-main.pid'
+
+#------------------------------------------------------------------------------
+# CONNECTIONS AND AUTHENTICATION
+#------------------------------------------------------------------------------
+
+# - Connection Settings -
+
+<% if @settings[:listen_addresses] || @defaults[:listen_addresses] -%>
+listen_addresses = '<%= @settings[:listen_addresses] || @defaults[:listen_addresses] %>'
+<% end -%>
+port = <%= @settings[:port] || @defaults[:port] %>
+max_connections = <%= @settings[:max_connections] || @defaults[:max_connections] %>
+unix_socket_directory = '/var/run/postgresql'
+
+# - Security and Authentication -
+
+ssl = true
+ssl_renegotiation_limit = 0
+
+#------------------------------------------------------------------------------
+# RESOURCE USAGE (except WAL)
+#------------------------------------------------------------------------------
+
+# - Memory -
+
+shared_buffers = <%= @settings[:shared_buffers] || @defaults[:shared_buffers] %>
+temp_buffers = <%= @settings[:temp_buffers] || @defaults[:temp_buffers] %>
+work_mem = <%= @settings[:work_mem] || @defaults[:work_mem] %>
+maintenance_work_mem = <%= @settings[:maintenance_work_mem] || @defaults[:maintenance_work_mem] %>
+max_stack_depth = <%= @settings[:max_stack_depth] || @defaults[:max_stack_depth] %>
+
+#------------------------------------------------------------------------------
+# WRITE AHEAD LOG
+#------------------------------------------------------------------------------
+
+# - Settings -
+
+wal_level = <%= @settings[:wal_level] || @defaults[:wal_level] %>
+fsync = <%= @settings[:fsync] || @defaults[:fsync] %>
+synchronous_commit = <%= @settings[:synchronous_commit] || @defaults[:synchronous_commit] %>
+wal_buffers = <%= @settings[:wal_buffers] || @defaults[:wal_buffers] %>
+wal_writer_delay = <%= @settings[:wal_writer_delay] || @defaults[:wal_writer_delay] %>
+commit_delay = <%= @settings[:commit_delay] || @defaults[:commit_delay] %>
+
+# - Checkpoints -
+
+checkpoint_segments = <%= @settings[:checkpoint_segments] || @defaults[:checkpoint_segments] %>
+checkpoint_timeout = <%= @settings[:checkpoint_timeout] || @defaults[:checkpoint_timeout] %>
+checkpoint_completion_target = <%= @settings[:checkpoint_completion_target] || @defaults[:checkpoint_completion_target] %>
+
+# - Archiving -
+
+archive_mode = <%= @settings[:archive_mode] || @defaults[:archive_mode] %>
+<% if @settings[:archive_command] || @defaults[:archive_command] -%>
+archive_command = '<%= @settings[:archive_command] || @defaults[:archive_command] %>'
+<% end -%>
+
+#------------------------------------------------------------------------------
+# REPLICATION
+#------------------------------------------------------------------------------
+
+# - Sending Server(s) -
+
+max_wal_senders = <%= @settings[:max_wal_senders] || @defaults[:max_wal_senders] %>
+
+# - Standby Servers -
+
+hot_standby = <%= @settings[:hot_standby] || @defaults[:hot_standby] %>
+hot_standby_feedback = <%= @settings[:hot_standby_feedback] || @defaults[:hot_standby_feedback] %>
+
+#------------------------------------------------------------------------------
+# QUERY TUNING
+#------------------------------------------------------------------------------
+
+# - Planner Cost Constants -
+
+random_page_cost = <%= @settings[:random_page_cost] || @defaults[:random_page_cost] %>
+effective_cache_size = <%= @settings[:effective_cache_size] || @defaults[:effective_cache_size] %>
+
+#------------------------------------------------------------------------------
+# ERROR REPORTING AND LOGGING
+#------------------------------------------------------------------------------
+
+# - When to Log -
+
+log_min_duration_statement = <%= @settings[:log_min_duration_statement] || @defaults[:log_min_duration_statement] %>
+
+# - What to Log -
+
+log_line_prefix = '%t '
+
+#------------------------------------------------------------------------------
+# AUTOVACUUM PARAMETERS
+#------------------------------------------------------------------------------
+
+autovacuum_max_workers = <%= @settings[:autovacuum_max_workers] || @defaults[:autovacuum_max_workers] %>
+
+#------------------------------------------------------------------------------
+# CLIENT CONNECTION DEFAULTS
+#------------------------------------------------------------------------------
+
+# - Locale and Formatting -
+
+datestyle = 'iso, dmy'
+lc_messages = 'en_GB.UTF-8'
+lc_monetary = 'en_GB.UTF-8'
+lc_numeric = 'en_GB.UTF-8'
+lc_time = 'en_GB.UTF-8'
+default_text_search_config = 'pg_catalog.english'
diff --git a/cookbooks/postgresql/templates/default/recovery.conf.erb b/cookbooks/postgresql/templates/default/recovery.conf.erb
new file mode 100644 (file)
index 0000000..f762890
--- /dev/null
@@ -0,0 +1,9 @@
+# DO NOT EDIT - This file is being maintained by Chef
+
+standby_mode = <%= @settings[:standby_mode] || @defaults[:standby_mode] %>
+<% if @settings[:primary_conninfo] || @defaults[:primary_conninfo] -%>
+primary_conninfo = '<%= @settings[:primary_conninfo] || @defaults[:primary_conninfo] %>'
+<% end -%>
+<% if @settings[:restore_command] || @defaults[:restore_command] -%>
+restore_command = '<%= @settings[:restore_command] || @defaults[:restore_command] %>'
+<% end -%>
diff --git a/cookbooks/rsyncd/README.md b/cookbooks/rsyncd/README.md
new file mode 100644 (file)
index 0000000..6b08769
--- /dev/null
@@ -0,0 +1,57 @@
+DESCRIPTION
+===========
+
+Configures networking.
+
+USAGE
+=====
+
+Set the networking attributes in a role, for example from my base.rb:
+
+    :networking => {
+      :nameservers => [ "10.13.37.120", "10.13.37.40" ],
+      :search => [ "int.example.org". "example.org" ]
+    }
+
+The resulting /etc/resolv.conf will look like:
+
+    search int.example.org example.org
+    nameserver 10.13.37.120
+    nameserver 10.13.37.40
+
+LICENSE AND AUTHOR
+==================
+
+Author:: OpenStreetMap Administrators (<admins@openstreetmap.org>)
+
+Copyright 2010, OpenStreetMap Foundation.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+Based on resolver cookbook:
+
+Author:: Joshua Timberman (<joshua@opscode.com>)
+
+Copyright 2009, Opscode, Inc.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff --git a/cookbooks/rsyncd/attributes/default.rb b/cookbooks/rsyncd/attributes/default.rb
new file mode 100644 (file)
index 0000000..55bd9a7
--- /dev/null
@@ -0,0 +1 @@
+default[:rsyncd][:modules] = [ ]
diff --git a/cookbooks/rsyncd/metadata.rb b/cookbooks/rsyncd/metadata.rb
new file mode 100644 (file)
index 0000000..790d946
--- /dev/null
@@ -0,0 +1,17 @@
+maintainer        "OpenStreetMap Administrators"
+maintainer_email  "admins@openstreetmap.org"
+license           "Apache 2.0"
+description       "Configures rsyncd"
+long_description  IO.read(File.join(File.dirname(__FILE__), 'README.md'))
+version           "1.0.0"
+depends           "networking"
+
+attribute "rsyncd",
+  :display_name => "rsyncd",
+  :description => "Hash of rsyncd attributes",
+  :type => "hash"
+
+attribute "rsyncd/modules",
+  :display_name => "rsyncd",
+  :description => "Hash of rsyncd modules to configure",
+  :type => "hash"
diff --git a/cookbooks/rsyncd/recipes/default.rb b/cookbooks/rsyncd/recipes/default.rb
new file mode 100644 (file)
index 0000000..5f090d1
--- /dev/null
@@ -0,0 +1,51 @@
+#
+# Cookbook Name:: rsyncd
+# Recipe:: default
+#
+# Copyright 2011, OpenStreetMap Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+include_recipe "networking"
+
+package "rsync"
+
+service "rsync" do
+  action [ :enable, :start ]
+  supports :status => true, :restart => true
+end
+
+template "/etc/default/rsync" do
+  source "rsync.erb"
+  owner "root"
+  group "root"
+  mode 0644
+  notifies :restart, resources(:service => "rsync")
+end
+
+template "/etc/rsyncd.conf" do
+  source "rsyncd.conf.erb"
+  owner "root"
+  group "root"
+  mode 0644
+end
+
+firewall_rule "accept-rsync" do
+  action :accept
+  source "net"
+  dest "fw"
+  proto "tcp:syn"
+  dest_ports "rsync"
+  source_ports "1024:"
+end
diff --git a/cookbooks/rsyncd/templates/default/rsync.erb b/cookbooks/rsyncd/templates/default/rsync.erb
new file mode 100644 (file)
index 0000000..013f029
--- /dev/null
@@ -0,0 +1,43 @@
+# DO NOT EDIT - This file is being maintained by Chef
+
+# defaults file for rsync daemon mode
+
+# start rsync in daemon mode from init.d script?
+#  only allowed values are "true", "false", and "inetd"
+#  Use "inetd" if you want to start the rsyncd from inetd,
+#  all this does is prevent the init.d script from printing a message
+#  about not starting rsyncd (you still need to modify inetd's config yourself).
+RSYNC_ENABLE=true
+
+# which file should be used as the configuration file for rsync.
+# This file is used instead of the default /etc/rsyncd.conf
+# Warning: This option has no effect if the daemon is accessed
+#          using a remote shell. When using a different file for
+#          rsync you might want to symlink /etc/rsyncd.conf to
+#          that file.
+# RSYNC_CONFIG_FILE=
+
+# what extra options to give rsync --daemon?
+#  that excludes the --daemon; that's always done in the init.d script
+#  Possibilities are:
+#   --address=123.45.67.89             (bind to a specific IP address)
+#   --port=8730                                (bind to specified port; default 873)
+RSYNC_OPTS=''
+
+# run rsyncd at a nice level?
+#  the rsync daemon can impact performance due to much I/O and CPU usage,
+#  so you may want to run it at a nicer priority than the default priority.
+#  Allowed values are 0 - 19 inclusive; 10 is a reasonable value.
+RSYNC_NICE='10'
+
+# run rsyncd with ionice?
+#  "ionice" does for IO load what "nice" does for CPU load.
+#  As rsync is often used for backups which aren't all that time-critical,
+#  reducing the rsync IO priority will benefit the rest of the system.
+#  See the manpage for ionice for allowed options.
+#  -c3 is recommended, this will run rsync IO at "idle" priority. Uncomment
+#  the next line to activate this.
+RSYNC_IONICE='-c3'
+
+# Don't forget to create an appropriate config file,
+# else the daemon will not start.
diff --git a/cookbooks/rsyncd/templates/default/rsyncd.conf.erb b/cookbooks/rsyncd/templates/default/rsyncd.conf.erb
new file mode 100644 (file)
index 0000000..adc04a8
--- /dev/null
@@ -0,0 +1,43 @@
+# DO NOT EDIT - This file is being maintained by Chef
+<% node[:rsyncd][:modules].each do |name,details| -%>
+
+[<%= name %>]
+     comment = <%= details[:comment] %>
+     path = <%= details[:path] %>
+     use chroot = yes
+     read only = <%= details[:read_only] %>
+     write only = <%= details[:write_only] %>
+     list = <%= details[:list] %>
+     uid = <%= details[:uid] %>
+     gid = <%= details[:gid] %>
+     transfer logging = <%= details[:transfer_logging] %>
+<% if details[:include] -%>
+     include = <%= details[:include].join(" ") %>
+<% end -%>
+<% if details[:exclude] -%>
+     exclude = <%= details[:exclude].join(" ") %>
+<% end -%>
+<% if details[:max_connections] -%>
+     max connections = <%= details[:max_connections] %>
+     lock file = /var/run/rsyncd.<%= name %>.lock
+<% end -%>
+<% if details[:ignore_errors] -%>
+     ignore errors = true
+<% end -%>
+<% if details[:ignore_nonreadable] -%>
+     ignore nonreadable = true
+<% end -%>
+<% if details[:timeout] -%>
+     timeout = <%= details[:timeout] %>
+<% end -%>
+<% if details[:refuse_options] -%>
+     refuse options = <%= details[:refuse_options].join(" ") %>
+<% end -%>
+<% if details[:hosts_allow] -%>
+     hosts allow = <%= details[:hosts_allow].join(",") %>
+<% end -%>
+<% if details[:hosts_deny] -%>
+     hosts deny = <%= details[:hosts_deny].join(",") %>
+<% end -%>
+     dont compress = *.gz *.tgz *.zip *.z *.rpm *.deb *.iso *.bz2 *.tbz *.7z
+<% end -%>
diff --git a/cookbooks/spamassassin/README.rdoc b/cookbooks/spamassassin/README.rdoc
new file mode 100644 (file)
index 0000000..3de2ec7
--- /dev/null
@@ -0,0 +1,8 @@
+= DESCRIPTION:
+
+= REQUIREMENTS:
+
+= ATTRIBUTES:
+
+= USAGE:
+
diff --git a/cookbooks/spamassassin/metadata.rb b/cookbooks/spamassassin/metadata.rb
new file mode 100644 (file)
index 0000000..d662a92
--- /dev/null
@@ -0,0 +1,6 @@
+maintainer        "OpenStreetMap Administrators"
+maintainer_email  "admins@openstreetmap.org"
+license           "Apache 2.0"
+description       "Installs and configures spamassassin"
+long_description  IO.read(File.join(File.dirname(__FILE__), 'README.rdoc'))
+version           "1.0.0"
diff --git a/cookbooks/spamassassin/recipes/default.rb b/cookbooks/spamassassin/recipes/default.rb
new file mode 100644 (file)
index 0000000..ec1109c
--- /dev/null
@@ -0,0 +1,52 @@
+#
+# Cookbook Name:: spamassassin
+# Recipe:: default
+#
+# Copyright 2011, OpenStreetMap Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+package "spamassassin"
+
+service "spamassassin" do
+  action [ :enable, :start ]
+  supports :status => true, :restart => true, :reload => true
+end
+
+template "/etc/default/spamassassin" do
+  source "spamassassin.erb"
+  owner "root"
+  group "root"
+  mode 0644
+  notifies :restart, resources(:service => "spamassassin")
+end
+
+trusted_networks = node[:exim][:relay_from_hosts]
+
+if node[:exim][:smarthost_name]
+  search(:node, "exim_smarthost_via:#{node[:exim][:smarthost_name]}\\:*").each do |host|
+    trusted_networks = trusted_networks | host.ipaddresses(:role => :external)
+  end
+end
+
+trusted_networks = trusted_networks - [ "127.0.0.1", "::1" ]
+
+template "/etc/spamassassin/local.cf" do
+  source "local.cf.erb"
+  owner "root"
+  group "root"
+  mode 0644
+  variables :trusted_networks => trusted_networks.sort
+  notifies :restart, resources(:service => "spamassassin")
+end
diff --git a/cookbooks/spamassassin/templates/default/local.cf.erb b/cookbooks/spamassassin/templates/default/local.cf.erb
new file mode 100644 (file)
index 0000000..be8b773
--- /dev/null
@@ -0,0 +1,7 @@
+# DO NOT EDIT - This file is being maintained by Chef
+
+# Set the threshold at which a message is considered spam
+required_score 5.0
+
+# Set which networks or hosts are considered 'trusted'
+trusted_networks <%= @trusted_networks.join(" ") %>
diff --git a/cookbooks/spamassassin/templates/default/spamassassin.erb b/cookbooks/spamassassin/templates/default/spamassassin.erb
new file mode 100644 (file)
index 0000000..e64c19b
--- /dev/null
@@ -0,0 +1,27 @@
+# DO NOT EDIT - This file is being maintained by Chef
+
+# Change to one to enable spamd
+ENABLED=1
+
+# Options
+# See man spamd for possible options. The -d option is automatically added.
+
+# SpamAssassin uses a preforking model, so be careful! You need to
+# make sure --max-children is not set to anything higher than 5,
+# unless you know what you're doing.
+
+OPTIONS="--username mail --nouser-config"
+
+# Pid file
+# Where should spamd write its PID to file? If you use the -u or
+# --username option above, this needs to be writable by that user.
+# Otherwise, the init script will not be able to shut spamd down.
+PIDFILE="/var/run/spamd.pid"
+
+# Set nice level of spamd
+#NICE="--nicelevel 15"
+
+# Cronjob
+# Set to anything but 0 to enable the cron job to automatically update
+# spamassassin's rules on a nightly basis
+CRON=1
diff --git a/cookbooks/switch2osm/README.rdoc b/cookbooks/switch2osm/README.rdoc
new file mode 100644 (file)
index 0000000..3de2ec7
--- /dev/null
@@ -0,0 +1,8 @@
+= DESCRIPTION:
+
+= REQUIREMENTS:
+
+= ATTRIBUTES:
+
+= USAGE:
+
diff --git a/cookbooks/switch2osm/metadata.rb b/cookbooks/switch2osm/metadata.rb
new file mode 100644 (file)
index 0000000..a73dbb8
--- /dev/null
@@ -0,0 +1,7 @@
+maintainer        "OpenStreetMap Administrators"
+maintainer_email  "admins@openstreetmap.org"
+license           "Apache 2.0"
+description       "Installs and configures servers for switch2osm"
+long_description  IO.read(File.join(File.dirname(__FILE__), 'README.rdoc'))
+version           "1.0.0"
+depends           "wordpress"
diff --git a/cookbooks/switch2osm/recipes/default.rb b/cookbooks/switch2osm/recipes/default.rb
new file mode 100644 (file)
index 0000000..d394d7e
--- /dev/null
@@ -0,0 +1,36 @@
+#
+# Cookbook Name:: switch2osm
+# Recipe:: default
+#
+# Copyright 2013, OpenStreetMap Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+include_recipe "wordpress"
+
+passwords = data_bag_item("switch2osm", "passwords")
+
+wordpress_site "switch2osm.org" do
+  aliases "www.switch2osm.org", "switch2osm.com", "www.switch2osm.com"
+  directory "/srv/switch2osm.org"
+  database_name "switch2osm-blog"
+  database_user "switch2osm-user"
+  database_password passwords["switch2osm-user"]
+end
+
+wordpress_theme "picolight" do
+  site "switch2osm.org"
+  repository "git://github.com/Firefishy/picolight-s2o.git"
+  revision "master"
+end
diff --git a/cookbooks/thinkup/README.rdoc b/cookbooks/thinkup/README.rdoc
new file mode 100644 (file)
index 0000000..3de2ec7
--- /dev/null
@@ -0,0 +1,8 @@
+= DESCRIPTION:
+
+= REQUIREMENTS:
+
+= ATTRIBUTES:
+
+= USAGE:
+
diff --git a/cookbooks/thinkup/metadata.rb b/cookbooks/thinkup/metadata.rb
new file mode 100644 (file)
index 0000000..1ef9c8c
--- /dev/null
@@ -0,0 +1,8 @@
+maintainer        "OpenStreetMap Administrators"
+maintainer_email  "admins@openstreetmap.org"
+license           "Apache 2.0"
+description       "Installs and configures ThinkUp"
+long_description  IO.read(File.join(File.dirname(__FILE__), 'README.rdoc'))
+version           "1.0.0"
+depends           "apache"
+depends           "mysql"
diff --git a/cookbooks/thinkup/recipes/default.rb b/cookbooks/thinkup/recipes/default.rb
new file mode 100644 (file)
index 0000000..ab85e64
--- /dev/null
@@ -0,0 +1,116 @@
+#
+# Cookbook Name:: thinkup
+# Recipe:: default
+#
+# Copyright 2011, OpenStreetMap Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+include_recipe "apache"
+include_recipe "mysql"
+
+passwords = data_bag_item("thinkup", "passwords")
+
+package "php5"
+package "php5-cli"
+package "php5-curl"
+package "php5-mysql"
+package "php5-gd"
+
+package "php-apc"
+
+apache_module "php5"
+
+apache_site "thinkup.openstreetmap.org" do
+  template "apache.erb"
+end
+
+mysql_user "thinkup@localhost" do
+  password passwords["database"]
+end
+
+mysql_database "thinkup" do
+  permissions "thinkup@localhost" => :all
+end
+
+git "/srv/thinkup.openstreetmap.org" do
+  action :sync
+  repository "git://github.com/ginatrapani/ThinkUp.git"
+  revision "v1.2.1"
+  user "root"
+  group "root"
+  notifies :reload, resources(:service => "apache2")
+end
+
+directory "/srv/thinkup.openstreetmap.org/logs" do
+  owner "thinkup"
+  group "thinkup"
+  mode "0755"
+end
+
+directory "/srv/thinkup.openstreetmap.org/logs/archive" do
+  owner "thinkup"
+  group "thinkup"
+  mode "0755"
+end
+
+directory "/srv/thinkup.openstreetmap.org/webapp/data" do
+  owner "www-data"
+  group "www-data"
+  mode "0755"
+end
+
+directory "/srv/thinkup.openstreetmap.org/webapp/_lib/view/compiled_view" do
+  owner "www-data"
+  group "www-data"
+  mode "0755"
+end
+
+file "/srv/thinkup.openstreetmap.org/webapp/config.inc.php" do
+  owner "root"
+  group "root"
+  mode 0644
+  content_from_file "/srv/thinkup.openstreetmap.org/webapp/config.sample.inc.php" do |line|
+    line.gsub!(/^(\$THINKUP_CFG\['site_root_path'\] *=) '[^']*';$/, "\\1 '/';")
+    line.gsub!(/^(\$THINKUP_CFG\['timezone'\] *=) '[^']*';$/, "\\1 'Europe/London';")
+    line.gsub!(/^(\$THINKUP_CFG\['db_user'\] *=) '[^']*';$/, "\\1 'thinkup';")
+    line.gsub!(/^(\$THINKUP_CFG\['db_password'\] *=) '[^']*';$/, "\\1 '#{passwords["database"]}';")
+    line.gsub!(/^(\$THINKUP_CFG\['db_name'\] *=) '[^']*';$/, "\\1 'thinkup';")
+
+    line
+  end
+  notifies :reload, resources(:service => "apache2")
+end
+
+file "/srv/thinkup.openstreetmap.org/extras/cron/config" do
+  owner "root"
+  group "thinkup"
+  mode 0640
+  content_from_file "/srv/thinkup.openstreetmap.org/extras/cron/config.sample" do |line|
+    line.gsub!(/^thinkup="[^"]*"$/, "thinkup=\"/srv/thinkup.openstreetmap.org\"")
+    line.gsub!(/^thinkup_username="[^"]*"$/, "thinkup_username=\"openstreetmap@jonno.cix.co.uk\"")
+    line.gsub!(/^thinkup_password="[^"]*"$/, "thinkup_password=\"#{passwords["admin"]}\"")
+    line.gsub!(/^php="[^"]*"$/, "php=\"/usr/bin/php\"")
+    line.gsub!(/^#crawl_interval=[0-9]+$/, "crawl_interval=30")
+
+    line
+  end
+end
+
+template "/etc/cron.d/thinkup" do
+  source "cron.erb"
+  owner "root"
+  group "root"
+  mode "0644"
+end
diff --git a/cookbooks/thinkup/templates/default/apache.erb b/cookbooks/thinkup/templates/default/apache.erb
new file mode 100644 (file)
index 0000000..fa40d7f
--- /dev/null
@@ -0,0 +1,12 @@
+# DO NOT EDIT - This file is being maintained by Chef
+
+<VirtualHost *:80>
+       ServerName thinkup.openstreetmap.org
+       ServerAlias thinkup.osm.org
+       ServerAdmin webmaster@openstreetmap.org
+
+       CustomLog /var/log/apache2/thinkup.openstreetmap.org-access.log combined
+       ErrorLog /var/log/apache2/thinkup.openstreetmap.org-error.log
+
+       DocumentRoot /srv/thinkup.openstreetmap.org/webapp
+</VirtualHost>
diff --git a/cookbooks/thinkup/templates/default/cron.erb b/cookbooks/thinkup/templates/default/cron.erb
new file mode 100644 (file)
index 0000000..b0b4d09
--- /dev/null
@@ -0,0 +1 @@
+0 * * * * thinkup /srv/thinkup.openstreetmap.org/extras/cron/cron > /srv/thinkup.openstreetmap.org/logs/crawler-$(date +\%Y\%m\%d\%H\%M\%S).log 2>&1