From 6df811b81a8f40583ee9f14909f0ed2b2dbcf7c8 Mon Sep 17 00:00:00 2001 From: jtimberman Date: Tue, 17 Apr 2012 17:37:11 -0600 Subject: [PATCH] [COOK-880] - add client/server roles for search of relayhost --- README.md | 96 ++++++++++++++++++++++++++++++++--- attributes/default.rb | 33 ++++++------ recipes/client.rb | 42 +++++++++++++++ recipes/default.rb | 2 +- recipes/server.rb | 23 +++++++++ templates/default/main.cf.erb | 36 ++++++------- 6 files changed, 191 insertions(+), 41 deletions(-) create mode 100644 recipes/client.rb create mode 100644 recipes/server.rb diff --git a/README.md b/README.md index fd25be8..4f12d74 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ Requirements * Ubuntu 10.04+ * Debian 6.0+ * RHEL/CentOS/Scientific 5.7+, 6.2+ -* Amazon Linux (as of 4/9/2012) +* Amazon Linux (as of AMIs created after 4/9/2012) Attributes ========== @@ -23,7 +23,7 @@ See `attributes/default.rb` for default values. * `node['postfix']['mail_type']` - Sets the kind of mail configuration. `master` will set up a server (relayhost). -* `node['postfix']['myhostname']` - corresponds to the myhostname +* `node['postfix']['myhostname']` - corresponds to the myhostname option in `/etc/postfix/main.cf`. * `node['postfix']['mydomain']` - corresponds to the mydomain option in `/etc/postfix/main.cf`. @@ -31,6 +31,11 @@ See `attributes/default.rb` for default values. in `/etc/postfix/main.cf`. * `node['postfix']['relayhost']` - corresponds to the relayhost option in `/etc/postfix/main.cf`. +* `node['postfix']['relayhost_role']` - name of a role used for search + in the client recipe. +* `node['postfix']['multi_environment_relay']` - set to true if nodes + should not constrain search for the relayhost in their own + environment. * `node['postfix']['mail_relay_networks']` - corresponds to the mynetworks option in `/etc/postfix/main.cf`. * `node['postfix']['smtpd_use_tls']` - set to "yes" to use TLS for @@ -41,8 +46,8 @@ See `attributes/default.rb` for default values. `smtp_sasl_password_maps` option in `/etc/postfix/main.cf`. * `node['postfix']['smtp_sasl_security_options']` - corresponds to the `smtp_sasl_security_options` option in `/etc/postfix/main.cf`. -* `node['postfix']['smtp_tls_cafile']` - corresponds to the `smtp_tls_CAfile` - option in `/etc/postfix/main.cf`. +* `node['postfix']['smtp_tls_cafile']` - corresponds to the + `smtp_tls_CAfile` option in `/etc/postfix/main.cf`. * `node['postfix']['smtp_use_tls']` - corresponds to the `smtp_use_tls` option in `/etc/postfix/main.cf`. * `node['postfix']['smtp_sasl_user_name']` - mapped in the @@ -64,12 +69,38 @@ configuration files (`/etc/postfix/main.cf` and `/etc/postfix/master.cf`). See __Usage__ and __Examples__ to see how to affect behavior of this recipe through configuration. +For a more dynamic approach to discovery for the relayhost, see the +`client` and `server` recipes below. + +client +------ + +Use this recipe to have nodes automatically search for the mail relay +based which node has the `node['postfix']['relayhost']` role. Sets the +`node['postfix']['relayhost']` attribute to the first result from the +search. + +Includes the default recipe to install, configure and start postfix. + +Does not work with `chef-solo`. + sasl\_auth ---------- Sets up the system to authenticate with a remote mail relay using SASL authentication. +server +------ + +To use Chef Server search to automatically detect a node that is the +relayhost, use this recipe in a role that will be relayhost. By +default, the role should be "relayhost" but you can change the +attribute `node['postfix']['relayhost_role']` to modify this. + +**Note** This recipe will set the `node['postfix']['mail_type']` to +"master" with an override attribute. + aliases ------- @@ -91,7 +122,8 @@ the internet, use `recipe[postfix]` and modify the On systems that should be the MX for a domain, set the attributes accordingly and make sure the `node['postfix']['mail_type']` attribute -is `master`. +is `master`. See __Examples__ for information on how to use +`recipe[postfix::server]` to do this automatically. If you need to use SASL authentication to send mail through your ISP (such as on a home network), use `recipe[postfix::sasl_auth]` and set @@ -159,12 +191,64 @@ password, see the following blog post: * http://jtimberman.github.com/blog/2011/08/06/encrypted-data-bag-for-postfix-sasl-authentication/ +**Examples using the client & server recipes** + +If you'd like to use the more dynamic search based approach for discovery, use the server and client recipes. First, create a relayhost role. + + name "relayhost" + run_list("recipe[postfix::server]") + override_attributes( + "postfix" => { + "mail_relay_networks" => "10.3.3.0/24", + "mydomain" => "example.com", + "myorigin" => "example.com" + } + ) + +Then, add the `postfix::client` recipe to the run list of your `base` role or equivalent role for postfix clients. + + name "base" + run_list("recipe[postfix::client]") + override_attributes( + "postfix" => { + "mail_type" => "client", + "mydomain" => "example.com", + "myorigin" => "example.com" + } + ) + +If you wish to use a different role name for the relayhost, then also set the attribute in the `base` role. For example, `postfix_master` as the role name: + + name "postfix_master" + description "a role for postfix master that isn't relayhost" + run_list("recipe[postfix::server]") + override_attributes( + "postfix" => { + "mail_relay_networks" => "10.3.3.0/24", + "mydomain" => "example.com", + "myorigin" => "example.com" + } + ) + +The base role would look something like this: + + name "base" + run_list("recipe[postfix::client]") + override_attributes( + "postfix" => { + "relayhost_role" => "postfix_master", + "mail_type" => "client", + "mydomain" => "example.com", + "myorigin" => "example.com" + } + ) + License and Author ================== Author:: Joshua Timberman -Copyright:: 2009-2011, Opscode, Inc +Copyright:: 2009-2012, Opscode, Inc Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/attributes/default.rb b/attributes/default.rb index 2012b4e..bc2071b 100644 --- a/attributes/default.rb +++ b/attributes/default.rb @@ -15,21 +15,22 @@ # See the License for the specific language governing permissions and # limitations under the License. -default[:postfix][:mail_type] = "client" -default[:postfix][:myhostname] = fqdn -default[:postfix][:mydomain] = domain -default[:postfix][:myorigin] = "$myhostname" -default[:postfix][:relayhost] = "" -default[:postfix][:mail_relay_networks] = "127.0.0.0/8" +default['postfix']['mail_type'] = "client" +default['postfix']['myhostname'] = fqdn +default['postfix']['mydomain'] = domain +default['postfix']['myorigin'] = "$myhostname" +default['postfix']['relayhost'] = "" +default['postfix']['mail_relay_networks'] = "127.0.0.0/8" +default['postfix']['relayhost_role'] = "relayhost" +default['postfix']['multi_environment_relay'] = false -default[:postfix][:smtpd_use_tls] = "yes" +default['postfix']['smtpd_use_tls'] = "yes" +default['postfix']['smtp_sasl_auth_enable'] = "no" +default['postfix']['smtp_sasl_password_maps'] = "hash:/etc/postfix/sasl_passwd" +default['postfix']['smtp_sasl_security_options'] = "noanonymous" +default['postfix']['smtp_tls_cafile'] = "/etc/postfix/cacert.pem" +default['postfix']['smtp_use_tls'] = "yes" +default['postfix']['smtp_sasl_user_name'] = "" +default['postfix']['smtp_sasl_passwd'] = "" -default[:postfix][:smtp_sasl_auth_enable] = "no" -default[:postfix][:smtp_sasl_password_maps] = "hash:/etc/postfix/sasl_passwd" -default[:postfix][:smtp_sasl_security_options] = "noanonymous" -default[:postfix][:smtp_tls_cafile] = "/etc/postfix/cacert.pem" -default[:postfix][:smtp_use_tls] = "yes" -default[:postfix][:smtp_sasl_user_name] = "" -default[:postfix][:smtp_sasl_passwd] = "" - -default[:postfix][:aliases] = {} +default['postfix']['aliases'] = {} diff --git a/recipes/client.rb b/recipes/client.rb new file mode 100644 index 0000000..2c26c2d --- /dev/null +++ b/recipes/client.rb @@ -0,0 +1,42 @@ +# +# Author:: Joshua Timberman() +# Cookbook Name:: postfix +# Recipe:: client +# +# Copyright 2009-2012, 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. +# + +if Chef::Config[:solo] + Chef::Log.info("#{cookbook_name}::#{recipe_name} is intended for use with Chef Server, use #{cookbook_name}::default with Chef Solo.") + return +end + +query = "role:#{node['postfix']['relayhost_role']}" +relayhost = "" +results = [] + +if node.run_list.roles.include?(node['postfix']['relayhost_role']) + relayhost << node['ipaddress'] +elsif node['postfix']['multi_environment_relay'] + results = search(:node, query) + relayhost = results.map {|n| n['ipaddress']}.first +else + results = search(:node, "#{query} AND chef_environment:#{node.chef_environment}") + relayhost = results.map {|n| n['ipaddress']}.first +end + +node.set['postfix']['relayhost'] = "[#{relayhost}]" + +include_recipe "postfix" diff --git a/recipes/default.rb b/recipes/default.rb index ef00f91..cc479de 100644 --- a/recipes/default.rb +++ b/recipes/default.rb @@ -3,7 +3,7 @@ # Cookbook Name:: postfix # Recipe:: default # -# Copyright 2009, Opscode, Inc. +# Copyright 2009-2012, Opscode, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/recipes/server.rb b/recipes/server.rb new file mode 100644 index 0000000..db408fe --- /dev/null +++ b/recipes/server.rb @@ -0,0 +1,23 @@ +# +# Author:: Joshua Timberman() +# Cookbook Name:: postfix +# Recipe:: server +# +# Copyright 2009-2012, 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. +# + +node.override['postfix']['mail_type'] = 'master' + +include_recipe "postfix" diff --git a/templates/default/main.cf.erb b/templates/default/main.cf.erb index 935f22c..9083ec5 100644 --- a/templates/default/main.cf.erb +++ b/templates/default/main.cf.erb @@ -1,38 +1,38 @@ ### -# Generated by Chef for <%= node[:fqdn] %> -# Configured as <%= node[:postfix][:mail_type] %> +# Generated by Chef for <%= node['fqdn'] %> +# Configured as <%= node['postfix']['mail_type'] %> ### biff = no append_dot_mydomain = no -smtpd_use_tls = <%= node[:postfix][:smtpd_use_tls] %> -<% if node[:postfix][:smtpd_use_tls] == "yes" -%> +smtpd_use_tls = <%= node['postfix']['smtpd_use_tls'] %> +<% if node['postfix']['smtpd_use_tls'] == "yes" -%> smtpd_tls_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem smtpd_tls_key_file=/etc/ssl/private/ssl-cert-snakeoil.key smtpd_tls_session_cache_database = btree:${queue_directory}/smtpd_scache <% end -%> smtp_tls_session_cache_database = btree:${queue_directory}/smtp_scache -smtp_sasl_auth_enable = <%= node[:postfix][:smtp_sasl_auth_enable] %> -<% if node[:postfix][:smtp_sasl_auth_enable] == "yes" -%> -smtp_sasl_password_maps = <%= node[:postfix][:smtp_sasl_password_maps] %> -smtp_sasl_security_options = <%= node[:postfix][:smtp_sasl_security_options] %> -smtp_tls_CAfile = <%= node[:postfix][:smtp_tls_cafile] %> -smtp_use_tls = <%= node[:postfix][:smtp_use_tls] %> +smtp_sasl_auth_enable = <%= node['postfix']['smtp_sasl_auth_enable'] %> +<% if node['postfix']['smtp_sasl_auth_enable'] == "yes" -%> +smtp_sasl_password_maps = <%= node['postfix']['smtp_sasl_password_maps'] %> +smtp_sasl_security_options = <%= node['postfix']['smtp_sasl_security_options'] %> +smtp_tls_CAfile = <%= node['postfix']['smtp_tls_cafile'] %> +smtp_use_tls = <%= node['postfix']['smtp_use_tls'] %> <% end -%> -myhostname = <%= node[:postfix][:myhostname] %> -mydomain = <%= node[:postfix][:mydomain] %> -myorigin = <%= node[:postfix][:myorigin] %> +myhostname = <%= node['postfix']['myhostname'] %> +mydomain = <%= node['postfix']['mydomain'] %> +myorigin = <%= node['postfix']['myorigin'] %> smtpd_banner = $myhostname ESMTP $mail_name alias_maps = hash:/etc/aliases alias_database = hash:/etc/aliases -mydestination = <%= node[:postfix][:myhostname] %>, <%= node[:hostname] %>, localhost.localdomain, localhost -<% if node[:postfix][:mail_type] == "master" -%> +mydestination = <%= node['postfix']['myhostname'] %>, <%= node['hostname'] %>, localhost.localdomain, localhost +<% if node['postfix']['mail_type'] == "master" -%> relayhost = -mynetworks = <%= node[:postfix][:mail_relay_networks] %> +mynetworks = <%= node['postfix']['mail_relay_networks'] %> inet_interfaces = all <% else -%> -relayhost = <%= node[:postfix][:relayhost] %> -mynetworks = <%= node[:postfix][:mail_relay_networks] %> +relayhost = <%= node['postfix']['relayhost'] %> +mynetworks = <%= node['postfix']['mail_relay_networks'] %> inet_interfaces = loopback-only <% end -%> mailbox_size_limit = 0