From 091a46e9728ed5594e6fa1025581532e52ae924d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Greg=20Kar=C3=A9kinian?= Date: Wed, 10 Jun 2020 18:37:36 +0200 Subject: [PATCH 1/6] Do not pass the pgsql_password variable to ejabberd.yml The password is only used in the config files for the vhosts --- site-cookbooks/kosmos-ejabberd/recipes/default.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/site-cookbooks/kosmos-ejabberd/recipes/default.rb b/site-cookbooks/kosmos-ejabberd/recipes/default.rb index 1572727..c43f2f0 100644 --- a/site-cookbooks/kosmos-ejabberd/recipes/default.rb +++ b/site-cookbooks/kosmos-ejabberd/recipes/default.rb @@ -152,8 +152,7 @@ template "/opt/ejabberd/conf/ejabberd.yml" do source "ejabberd.yml.erb" mode 0640 sensitive true - variables pgsql_password: postgresql_data_bag_item['ejabberd_user_password'], - hosts: hosts, + variables hosts: hosts, admin_users: admin_users, stun_auth_realm: "kosmos.org", turn_ip_address: node['ipaddress'], From 2c21d6255b7fb20b92ad06e9050e4ca9a3b0e457 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Greg=20Kar=C3=A9kinian?= Date: Wed, 10 Jun 2020 18:38:40 +0200 Subject: [PATCH 2/6] Add PostgreSQL primary support to the kosmos-ejabberd cookbook * Move the PostgreSQL user and database creation to a pg_db recipe * Generate access rights for the ejabberd servers in the pg_db recipe * Connect to the PostgreSQL primary instead of localhost Refs #180 --- .../kosmos-ejabberd/recipes/default.rb | 28 ++----- .../kosmos-ejabberd/recipes/pg_db.rb | 76 +++++++++++++++++++ .../kosmos-ejabberd/templates/vhost.yml.erb | 2 +- 3 files changed, 83 insertions(+), 23 deletions(-) create mode 100644 site-cookbooks/kosmos-ejabberd/recipes/pg_db.rb diff --git a/site-cookbooks/kosmos-ejabberd/recipes/default.rb b/site-cookbooks/kosmos-ejabberd/recipes/default.rb index c43f2f0..6e60685 100644 --- a/site-cookbooks/kosmos-ejabberd/recipes/default.rb +++ b/site-cookbooks/kosmos-ejabberd/recipes/default.rb @@ -28,11 +28,6 @@ include_recipe "kosmos-postgresql" ejabberd_credentials = data_bag_item("credentials", "ejabberd") -cookbook_file "#{Chef::Config[:file_cache_path]}/pg.sql" do - source "pg.sql" - mode "0664" -end - ejabberd_version = node["kosmos-ejabberd"]["version"] package_checksum = node["kosmos-ejabberd"]["checksum"] package_path = "#{Chef::Config['file_cache_path']}/ejabberd_#{ejabberd_version}-0_amd64.deb" @@ -52,11 +47,6 @@ end postgresql_data_bag_item = data_bag_item('credentials', 'postgresql') -postgresql_user 'ejabberd' do - action :create - password postgresql_data_bag_item['ejabberd_user_password'] -end - hosts = [ { name: "kosmos.org", @@ -111,21 +101,14 @@ ldap_base = "cn=users,dc=kosmos,dc=org" admin_users = ejabberd_credentials['admins'] +postgresql_primary_node = postgresql_primary +postgresql_server = postgresql_primary_node[:ipaddress] +# PostgreSQL is on the same server, connect through localhost +postgresql_server = "localhost" if postgresql_primary_node[:hostname] == node[:hostname] + hosts.each do |host| ldap_rootdn = "uid=xmpp,ou=#{host[:name]},cn=applications,dc=kosmos,dc=org" - postgresql_database host[:sql_database] do - owner 'ejabberd' - action :create - notifies :run, "execute[create db schema #{host[:sql_database]}]", :delayed - end - - execute "create db schema #{host[:sql_database]}" do - user "ejabberd" - command "psql #{host[:sql_database]} < #{Chef::Config[:file_cache_path]}/pg.sql" - action :nothing - end - template "/opt/ejabberd/conf/#{host[:name]}.yml" do source "vhost.yml.erb" mode 0640 @@ -133,6 +116,7 @@ hosts.each do |host| group 'ejabberd' sensitive true variables pgsql_password: postgresql_data_bag_item['ejabberd_user_password'], + sql_server: postgresql_server, host: host, ldap_base: ldap_base, ldap_server: ldap_domain, diff --git a/site-cookbooks/kosmos-ejabberd/recipes/pg_db.rb b/site-cookbooks/kosmos-ejabberd/recipes/pg_db.rb new file mode 100644 index 0000000..326ffda --- /dev/null +++ b/site-cookbooks/kosmos-ejabberd/recipes/pg_db.rb @@ -0,0 +1,76 @@ +# +# Cookbook:: kosmos-ejabberd +# Recipe:: pg_db +# +# The MIT License (MIT) +# +# Copyright:: 2020, Kosmos Developers +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +# + +postgresql_data_bag_item = data_bag_item('credentials', 'postgresql') + +postgresql_service = "service[#{postgresql_service_name}]" + +service postgresql_service do + supports restart: true, status: true, reload: true +end + +postgresql_user 'ejabberd' do + action :create + password postgresql_data_bag_item['ejabberd_user_password'] +end + +databases = ["ejabberd", "ejabberd_5apps"] + +ejabberd_servers = search(:node, "role:ejabberd AND chef_environment:#{node.chef_environment}") + +databases.each do |database| + postgresql_database database do + owner 'ejabberd' + action :create + notifies :run, "execute[create db schema #{database}]", :delayed + end + + cookbook_file "#{Chef::Config[:file_cache_path]}/pg.sql" do + source "pg.sql" + mode "0664" + end + + execute "create db schema #{database}" do + user "postgres" + command "psql #{database} < #{Chef::Config[:file_cache_path]}/pg.sql" + action :nothing + end + + ejabberd_servers.each do |ejabberd_server| + ip = ip_for(ejabberd_server) + hostname = ejabberd_server[:hostname] + + postgresql_access "ejabberd #{hostname}" do + access_type "host" + access_db "ejabberd" + access_user "ejabberd" + access_addr "#{ip}/32" + access_method "md5" + notifies :reload, postgresql_service, :delayed + end + end +end diff --git a/site-cookbooks/kosmos-ejabberd/templates/vhost.yml.erb b/site-cookbooks/kosmos-ejabberd/templates/vhost.yml.erb index 32c064d..eb6c943 100644 --- a/site-cookbooks/kosmos-ejabberd/templates/vhost.yml.erb +++ b/site-cookbooks/kosmos-ejabberd/templates/vhost.yml.erb @@ -7,7 +7,7 @@ certfiles: host_config: "<%= @host[:name] %>": sql_type: pgsql - sql_server: "localhost" + sql_server: "<%= @sql_server %>" sql_database: "<%= @host[:sql_database] %>" sql_username: "ejabberd" sql_password: "<%= @pgsql_password %>" From 1a6ce44758bedb59b6020d45937af27c4f8467ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Greg=20Kar=C3=A9kinian?= Date: Wed, 10 Jun 2020 18:43:34 +0200 Subject: [PATCH 3/6] Create a minimalist ejabberd role for development No Let's Encrypt, no backups --- roles/ejabberd.rb | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/roles/ejabberd.rb b/roles/ejabberd.rb index e126017..4034261 100644 --- a/roles/ejabberd.rb +++ b/roles/ejabberd.rb @@ -1,7 +1,16 @@ name "ejabberd" -run_list %w( +default_run_list = %w( + kosmos-ejabberd::default +) + +production_run_list = %w( kosmos-ejabberd::default kosmos-ejabberd::letsencrypt kosmos-ejabberd::backup ) +env_run_lists( + 'production' => production_run_list, + 'development' => default_run_list, + '_default' => default_run_list +) From 26097a7584c81451b7a4947b9584032b249d0b0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Greg=20Kar=C3=A9kinian?= Date: Thu, 11 Jun 2020 09:00:50 +0200 Subject: [PATCH 4/6] Use the correct database name for the access rights --- site-cookbooks/kosmos-ejabberd/recipes/pg_db.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/site-cookbooks/kosmos-ejabberd/recipes/pg_db.rb b/site-cookbooks/kosmos-ejabberd/recipes/pg_db.rb index 326ffda..4304ed5 100644 --- a/site-cookbooks/kosmos-ejabberd/recipes/pg_db.rb +++ b/site-cookbooks/kosmos-ejabberd/recipes/pg_db.rb @@ -64,9 +64,9 @@ databases.each do |database| ip = ip_for(ejabberd_server) hostname = ejabberd_server[:hostname] - postgresql_access "ejabberd #{hostname}" do + postgresql_access "#{database} #{hostname}" do access_type "host" - access_db "ejabberd" + access_db database access_user "ejabberd" access_addr "#{ip}/32" access_method "md5" From 6f696d7634bb78d3698c0677067923de0f44c291 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Greg=20Kar=C3=A9kinian?= Date: Thu, 11 Jun 2020 18:20:04 +0200 Subject: [PATCH 5/6] Define access rules in the PostgreSQL primary recipe Access is done for the IP of a server for all users and all databases for ejabberd and gitea --- .../kosmos-ejabberd/recipes/pg_db.rb | 21 ----------------- .../kosmos-postgresql/recipes/default.rb | 23 +++++++++++++++++++ site-cookbooks/kosmos_gitea/recipes/pg_db.rb | 20 ---------------- 3 files changed, 23 insertions(+), 41 deletions(-) diff --git a/site-cookbooks/kosmos-ejabberd/recipes/pg_db.rb b/site-cookbooks/kosmos-ejabberd/recipes/pg_db.rb index 4304ed5..85fba8c 100644 --- a/site-cookbooks/kosmos-ejabberd/recipes/pg_db.rb +++ b/site-cookbooks/kosmos-ejabberd/recipes/pg_db.rb @@ -27,12 +27,6 @@ postgresql_data_bag_item = data_bag_item('credentials', 'postgresql') -postgresql_service = "service[#{postgresql_service_name}]" - -service postgresql_service do - supports restart: true, status: true, reload: true -end - postgresql_user 'ejabberd' do action :create password postgresql_data_bag_item['ejabberd_user_password'] @@ -40,8 +34,6 @@ end databases = ["ejabberd", "ejabberd_5apps"] -ejabberd_servers = search(:node, "role:ejabberd AND chef_environment:#{node.chef_environment}") - databases.each do |database| postgresql_database database do owner 'ejabberd' @@ -60,17 +52,4 @@ databases.each do |database| action :nothing end - ejabberd_servers.each do |ejabberd_server| - ip = ip_for(ejabberd_server) - hostname = ejabberd_server[:hostname] - - postgresql_access "#{database} #{hostname}" do - access_type "host" - access_db database - access_user "ejabberd" - access_addr "#{ip}/32" - access_method "md5" - notifies :reload, postgresql_service, :delayed - end - end end diff --git a/site-cookbooks/kosmos-postgresql/recipes/default.rb b/site-cookbooks/kosmos-postgresql/recipes/default.rb index 53ec336..5fe7ba0 100644 --- a/site-cookbooks/kosmos-postgresql/recipes/default.rb +++ b/site-cookbooks/kosmos-postgresql/recipes/default.rb @@ -27,6 +27,10 @@ postgresql_version = "12" postgresql_service = "postgresql@#{postgresql_version}-main" +service postgresql_service do + supports restart: true, status: true, reload: true +end + postgresql_custom_server postgresql_version do role "primary" end @@ -54,6 +58,25 @@ postgresql_replicas.each do |replica| notifies :reload, "service[#{postgresql_service}]", :immediately end + gitea_servers = search(:node, "role:gitea AND chef_environment:#{node.chef_environment}") || [] + ejabberd_servers = search(:node, "role:ejabberd AND chef_environment:#{node.chef_environment}") || [] + + servers = (gitea_servers + ejabberd_servers).uniq + + servers.each do |server| + ip = ip_for(server) + hostname = server[:hostname] + + postgresql_access "#{hostname} all" do + access_type "host" + access_db "all" + access_user "all" + access_addr "#{ip}/32" + access_method "md5" + notifies :reload, "service[#{postgresql_service}]", :immediately + end + end + unless node.chef_environment == "development" include_recipe "firewall" diff --git a/site-cookbooks/kosmos_gitea/recipes/pg_db.rb b/site-cookbooks/kosmos_gitea/recipes/pg_db.rb index b4577e6..2cf4d19 100644 --- a/site-cookbooks/kosmos_gitea/recipes/pg_db.rb +++ b/site-cookbooks/kosmos_gitea/recipes/pg_db.rb @@ -6,12 +6,6 @@ gitea_data_bag_item = data_bag_item("credentials", "gitea") -postgresql_service = "service[#{postgresql_service_name}]" - -service postgresql_service do - supports restart: true, status: true, reload: true -end - postgresql_user "gitea" do action :create password gitea_data_bag_item["postgresql_password"] @@ -21,17 +15,3 @@ postgresql_database "gitea" do owner "gitea" action :create end - -search(:node, "role:gitea AND chef_environment:#{node.chef_environment}").each do |gitea_server| - ip = ip_for(gitea_server) - hostname = gitea_server[:hostname] - - postgresql_access "gitea #{hostname}" do - access_type "host" - access_db "gitea" - access_user "gitea" - access_addr "#{ip}/32" - access_method "md5" - notifies :reload, postgresql_service, :delayed - end -end From ee9c241a4d0f958b5c2b856779d997c94500924a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Greg=20Kar=C3=A9kinian?= Date: Fri, 12 Jun 2020 16:54:58 +0200 Subject: [PATCH 6/6] Add a postgresql_client role The role is empty but is used to explicitly define servers that have access rights to all PostgreSQL databases and users --- roles/ejabberd.rb | 2 + roles/gitea.rb | 1 + roles/postgresql_client.rb | 5 +++ .../kosmos-postgresql/recipes/default.rb | 37 +++++++++---------- 4 files changed, 26 insertions(+), 19 deletions(-) create mode 100644 roles/postgresql_client.rb diff --git a/roles/ejabberd.rb b/roles/ejabberd.rb index 4034261..561ca33 100644 --- a/roles/ejabberd.rb +++ b/roles/ejabberd.rb @@ -1,10 +1,12 @@ name "ejabberd" default_run_list = %w( + role[postgresql_client] kosmos-ejabberd::default ) production_run_list = %w( + role[postgresql_client] kosmos-ejabberd::default kosmos-ejabberd::letsencrypt kosmos-ejabberd::backup diff --git a/roles/gitea.rb b/roles/gitea.rb index b6f5069..5f7fd2a 100644 --- a/roles/gitea.rb +++ b/roles/gitea.rb @@ -1,6 +1,7 @@ name "gitea" run_list %w( + role[postgresql_client] kosmos_gitea::default kosmos_gitea::backup ) diff --git a/roles/postgresql_client.rb b/roles/postgresql_client.rb new file mode 100644 index 0000000..18771f2 --- /dev/null +++ b/roles/postgresql_client.rb @@ -0,0 +1,5 @@ +# This role is used by the kosmos-postgresql::default recipe to add access +# rules to every server that is a PostgreSQL client +name "postgresql_client" + +run_list [] diff --git a/site-cookbooks/kosmos-postgresql/recipes/default.rb b/site-cookbooks/kosmos-postgresql/recipes/default.rb index 5fe7ba0..c7d289b 100644 --- a/site-cookbooks/kosmos-postgresql/recipes/default.rb +++ b/site-cookbooks/kosmos-postgresql/recipes/default.rb @@ -48,6 +48,24 @@ systemctl start postgresql@12-main only_if { ::File.exist? "/var/lib/postgresql/10/main" } end +# Services that connect to PostgreSQL need to have the postgresql_client role +# as part of their run list. See the gitea and ejabberd roles. +postgresql_clients = search(:node, "roles:postgresql_client AND chef_environment:#{node.chef_environment}") || [] + +postgresql_clients.each do |client| + ip = ip_for(client) + hostname = client[:hostname] + + postgresql_access "#{hostname} all" do + access_type "host" + access_db "all" + access_user "all" + access_addr "#{ip}/32" + access_method "md5" + notifies :reload, "service[#{postgresql_service}]", :immediately + end +end + postgresql_replicas.each do |replica| postgresql_access "#{replica[:hostname]} replication" do access_type "host" @@ -58,25 +76,6 @@ postgresql_replicas.each do |replica| notifies :reload, "service[#{postgresql_service}]", :immediately end - gitea_servers = search(:node, "role:gitea AND chef_environment:#{node.chef_environment}") || [] - ejabberd_servers = search(:node, "role:ejabberd AND chef_environment:#{node.chef_environment}") || [] - - servers = (gitea_servers + ejabberd_servers).uniq - - servers.each do |server| - ip = ip_for(server) - hostname = server[:hostname] - - postgresql_access "#{hostname} all" do - access_type "host" - access_db "all" - access_user "all" - access_addr "#{ip}/32" - access_method "md5" - notifies :reload, "service[#{postgresql_service}]", :immediately - end - end - unless node.chef_environment == "development" include_recipe "firewall"