[submodule "external_modules/slack"]
path = external_modules/slack
url = git://git.immae.eu/github/cegeka/puppet-slack
+[submodule "external_modules/patch"]
+ path = external_modules/patch
+ url = git://git.immae.eu/github/tohuwabohu/puppet-patch.git
--- /dev/null
+---
+classes:
+ role::etherpad: ~
--- /dev/null
+Subproject commit fed3814e759347d72b919ebeb1b6837c5d13373f
branch="master"
if [ -n "$1" ]; then
branch="$1"
+ shift
fi
git reset --hard origin/$branch
git submodule update --init
-puppet_apply --test manifests/site.pp
+puppet_apply "$@" --test manifests/site.pp
--- /dev/null
+module Puppet::Parser::Functions
+ newfunction(:find_host, :type => :rvalue, :doc => <<-EOS
+This function searches through the hosts to find the one with matching cn
+ EOS
+ ) do |arguments|
+
+ if (arguments.size != 2) then
+ raise(Puppet::ParseError, "grep(): Wrong number of arguments given #{arguments.size} for 2")
+ end
+
+ hosts = arguments[0]
+ cn = arguments[1]
+
+ hosts.find { |host| host["cn"].any? { |cn_| cn_ == cn } }
+ end
+end
+
+# vim: set ts=2 sw=2 et :
<% unless @ips["v6"].nil? -%>ipHostNumber: <%= @ips["v6"]["ipAddress"] %>/<%= @ips["v6"]["mask"] %><%- end %>
<%- end -%>
environment: <%= @environment %>
+puppetVar: real_hostname=<%= @real_hostname %>
userpassword: {SSHA}<%= Base64.encode64(Digest::SHA1.digest(@ldap_password+@ssha_ldap_seed)+@ssha_ldap_seed).chomp! %>
EOF
\e[0;35m#### Or modify an existing entry:\e[0m
--- /dev/null
+auth required pam_ldap.so config=/etc/pam_ldap.d/postgresql.conf
+account required pam_ldap.so config=/etc/pam_ldap.d/postgresql.conf
+
--- /dev/null
+define profile::postgresql_master (
+ $letsencrypt_host = undef,
+ $backup_hosts = [],
+) {
+ $password_seed = lookup("base_installation::puppet_pass_seed")
+
+ ensure_resource("file", "/var/lib/postgres/data/certs", {
+ ensure => directory,
+ mode => "0700",
+ owner => $::profile::postgresql::pg_user,
+ group => $::profile::postgresql::pg_user,
+ require => File["/var/lib/postgres"],
+ })
+
+ ensure_resource("file", "/var/lib/postgres/data/certs/cert.pem", {
+ source => "file:///etc/letsencrypt/live/$letsencrypt_host/cert.pem",
+ mode => "0600",
+ links => "follow",
+ owner => $::profile::postgresql::pg_user,
+ group => $::profile::postgresql::pg_user,
+ require => [Letsencrypt::Certonly[$letsencrypt_host], File["/var/lib/postgres/data/certs"]]
+ })
+
+ ensure_resource("file", "/var/lib/postgres/data/certs/privkey.pem", {
+ source => "file:///etc/letsencrypt/live/$letsencrypt_host/privkey.pem",
+ mode => "0600",
+ links => "follow",
+ owner => $::profile::postgresql::pg_user,
+ group => $::profile::postgresql::pg_user,
+ require => [Letsencrypt::Certonly[$letsencrypt_host], File["/var/lib/postgres/data/certs"]]
+ })
+
+ ensure_resource("postgresql::server::config_entry", "wal_level", {
+ value => "logical",
+ })
+
+ ensure_resource("postgresql::server::config_entry", "ssl", {
+ value => "on",
+ require => Letsencrypt::Certonly[$letsencrypt_host],
+ })
+
+ ensure_resource("postgresql::server::config_entry", "ssl_cert_file", {
+ value => "/var/lib/postgres/data/certs/cert.pem",
+ require => Letsencrypt::Certonly[$letsencrypt_host],
+ })
+
+ ensure_resource("postgresql::server::config_entry", "ssl_key_file", {
+ value => "/var/lib/postgres/data/certs/privkey.pem",
+ require => Letsencrypt::Certonly[$letsencrypt_host],
+ })
+
+ $backup_hosts.each |$backup_host| {
+ ensure_packages(["pam_ldap"])
+
+ $host = find_host($facts["ldapvar"]["other"], $backup_host)
+ unless empty($host) {
+ $host["ipHostNumber"].each |$ip| {
+ $infos = split($ip, "/")
+ $ipaddress = $infos[0]
+ if (length($infos) == 1 and $ipaddress =~ /:/) {
+ $mask = "128"
+ } elsif (length($infos) == 1) {
+ $mask = "32"
+ } else {
+ $mask = $infos[1]
+ }
+
+ postgresql::server::pg_hba_rule { "allow TCP access to replication user from backup for replication from $ipaddress/$mask":
+ type => 'hostssl',
+ database => 'replication',
+ user => $backup_host,
+ address => "$ipaddress/$mask",
+ auth_method => 'pam',
+ order => "06-01",
+ }
+ }
+
+ postgresql::server::role { $backup_host:
+ replication => true,
+ }
+
+ postgresql_replication_slot { regsubst($backup_host, '-', "_", "G"):
+ ensure => present
+ }
+ }
+ }
+
+ $ldap_server = lookup("base_installation::ldap_server")
+ $ldap_base = lookup("base_installation::ldap_base")
+ $ldap_dn = lookup("base_installation::ldap_dn")
+ $ldap_cn = lookup("base_installation::ldap_cn")
+ $ldap_password = generate_password(24, $password_seed, "ldap")
+ $ldap_attribute = "cn"
+
+ # This is to be replicated to the backup
+ postgresql::server::role { $ldap_cn:
+ replication => true,
+ }
+
+ file { "/etc/pam_ldap.d":
+ ensure => directory,
+ mode => "0755",
+ owner => "root",
+ group => "root",
+ } ->
+ file { "/etc/pam_ldap.d/postgresql.conf":
+ ensure => "present",
+ mode => "0600",
+ owner => $::profile::postgresql::pg_user,
+ group => "root",
+ content => template("profile/postgresql_master/pam_ldap_postgresql.conf.erb"),
+ } ->
+ file { "/etc/pam.d/postgresql":
+ ensure => "present",
+ mode => "0644",
+ owner => "root",
+ group => "root",
+ source => "puppet:///modules/profile/postgresql_master/pam_postgresql"
+ }
+
+}
--- /dev/null
+host <%= @ldap_server %>
+
+base <%= @ldap_base %>
+binddn <%= @ldap_dn %>
+bindpw <%= @ldap_password %>
+pam_login_attribute <%= @ldap_attribute %>
--- /dev/null
+--- a/LibreOffice.js 2018-06-18 09:54:15.087161212 +0200
++++ b/LibreOffice.js 2018-06-18 10:33:27.534055021 +0200
+@@ -63,6 +63,7 @@
+ '--invisible',
+ '--nologo',
+ '--nolockcheck',
++ '-env:UserInstallation=file:///tmp/',
+ '--convert-to', task.type,
+ task.srcFile,
+ '--outdir', tmpDir
+
include "role::backup::postgresql"
+ ensure_packages(["python", "python-pip"])
+ package { "pylog2rotate":
+ source => "git+https://github.com/avian2/pylog2rotate",
+ ensure => present,
+ provider => "pip3",
+ require => Package["python-pip"],
+ }
+
ensure_packages(["rsync"])
ssh_keygen { $user:
$ldap_server = lookup("base_installation::ldap_server")
$ldap_base = lookup("base_installation::ldap_base")
$ldap_dn = lookup("base_installation::ldap_dn")
- $ldap_attribute = "uid"
+ $pgbouncer_ldap_attribute = "uid"
$pg_slot = regsubst($ldap_cn, '-', "_", "G")
],
}
- file { "/etc/pam_ldap.d":
- ensure => directory,
- mode => "0755",
- owner => "root",
- group => "root",
- } ->
file { "/etc/pam_ldap.d/pgbouncer.conf":
ensure => "present",
mode => "0600",
owner => $pg_user,
group => "root",
content => template("role/backup/pam_ldap_pgbouncer.conf.erb"),
+ require => File["/etc/pam_ldap.d"],
} ->
file { "/etc/pam.d/pgbouncer":
ensure => "present",
}
}
- $pg_backup_hosts.each |$pg_backup_host, $pg_infos| {
+ $ldap_attribute = "cn"
+
+ file { "/etc/pam_ldap.d":
+ ensure => directory,
+ mode => "0755",
+ owner => "root",
+ group => "root",
+ } ->
+ file { "/etc/pam_ldap.d/postgresql.conf":
+ ensure => "present",
+ mode => "0600",
+ owner => $pg_user,
+ group => "root",
+ content => template("profile/postgresql_master/pam_ldap_postgresql.conf.erb"),
+ } ->
+ file { "/etc/pam.d/postgresql":
+ ensure => "present",
+ mode => "0644",
+ owner => "root",
+ group => "root",
+ source => "puppet:///modules/profile/postgresql_master/pam_postgresql"
+ }
+
+ $pg_backup_hosts.each |$backup_host_cn, $pg_infos| {
+ $host = find_host($facts["ldapvar"]["other"], $backup_host_cn)
+ if empty($host) {
+ $pg_backup_host = $backup_host_cn
+ } elsif has_key($host["vars"], "host") {
+ $pg_backup_host = $host["vars"]["host"][0]
+ } else {
+ $pg_backup_host = $host["vars"]["real_hostname"][0]
+ }
+
$pg_path = "$mountpoint/$pg_backup_host/postgresql"
$pg_backup_path = "$mountpoint/$pg_backup_host/postgresql_backup"
$pg_host = "$pg_backup_host"
$pg_port = $pg_infos["dbport"]
+ if has_key($host["vars"], "postgresql_backup_port") {
+ $pg_listen_port = $host["vars"]["postgresql_backup_port"][0]
+ file { "$pg_path/certs":
+ ensure => directory,
+ mode => "0700",
+ owner => $pg_user,
+ group => $pg_group,
+ } ->
+ ssl::self_signed_certificate { $backup_host_cn:
+ common_name => $backup_host_cn,
+ country => "FR",
+ days => "3650",
+ organization => "Immae",
+ owner => $pg_user,
+ group => $pg_group,
+ directory => "$pg_path/certs",
+ before => File["$pg_path/postgresql.conf"],
+ }
+ $ssl_key = "$pg_path/certs/$backup_host_cn.key"
+ $ssl_cert = "$pg_path/certs/$backup_host_cn.crt"
+ } else {
+ $pg_listen_port = undef
+ $ssl_key = undef
+ $ssl_cert = undef
+ }
+
+
+ unless empty($host) {
+ $host["ipHostNumber"].each |$ip| {
+ $infos = split($ip, "/")
+ $ipaddress = $infos[0]
+ if (length($infos) == 1 and $ipaddress =~ /:/) {
+ $mask = "128"
+ } elsif (length($infos) == 1) {
+ $mask = "32"
+ } else {
+ $mask = $infos[1]
+ }
+
+ postgresql::server::pg_hba_rule { "allow TCP access for initial replication from $ipaddress/$mask":
+ type => 'hostssl',
+ database => 'replication',
+ user => $backup_host_cn,
+ address => "$ipaddress/$mask",
+ auth_method => 'pam',
+ order => "06-01",
+ target => "$pg_path/pg_hba.conf",
+ postgresql_version => "10",
+ }
+ }
+ }
+
if !empty($ldap_filter) and ($pg_infos["pgbouncer"]) {
+ if empty($pg_listen_port) {
+ $pg_listen_port_key = ""
+ } else {
+ $pg_listen_port_key = "port=$pg_listen_port"
+ }
+
concat::fragment { "pgbouncer_$pg_backup_host":
target => "/etc/pgbouncer/pgbouncer.ini",
order => 02,
- content => "${pg_infos[pgbouncer_dbname]} = host=$mountpoint/$pg_backup_host/postgresql user=${pg_infos[dbuser]} dbname=${pg_infos[dbname]}",
+ content => "${pg_infos[pgbouncer_dbname]} = host=$mountpoint/$pg_backup_host/postgresql $pg_listen_port_key user=${pg_infos[dbuser]} dbname=${pg_infos[dbname]}",
}
postgresql::server::pg_hba_rule { "$pg_backup_host - local access as ${pg_infos[dbuser]} user":
description => "Backup the database",
},
{
- command => "/usr/bin/rm -f $(ls -1 $pg_backup_path/*.sql | sort -r | sed -e '1,16d')",
+ command => "/usr/bin/rm -f $(ls -1 $pg_backup_path/*.sql | grep -v 'T22:' | sort -r | sed -e '1,12d')",
user => $pg_user,
hour => 3,
minute => 0,
description => "Cleanup the database backups",
},
+ {
+ command => "cd $pg_backup_path ; /usr/bin/rm -f $(ls -1 *T22*.sql | log2rotate --skip 7 --fuzz 7 --delete --format='%Y-%m-%dT%H:%M:%S+02:00.sql')",
+ user => $pg_user,
+ hour => 3,
+ minute => 1,
+ description => "Cleanup the database backups exponentially",
+ },
]
}
Concat["$pg_path/pg_hba.conf"],
Concat["$pg_path/recovery.conf"],
File["$pg_path/postgresql.conf"],
+ ],
+ subscribe => [
+ Concat["$pg_path/pg_hba.conf"],
+ Concat["$pg_path/recovery.conf"],
+ File["$pg_path/postgresql.conf"],
]
}
}
--- /dev/null
+class role::etherpad (
+) {
+ $password_seed = lookup("base_installation::puppet_pass_seed")
+ $web_host = lookup("base_installation::real_hostname")
+ $web_listen = "0.0.0.0"
+ $web_port = 18000
+ $pg_db = "etherpad-lite"
+ $pg_user = "etherpad-lite"
+ $pg_password = generate_password(24, $password_seed, "postgres_etherpad")
+
+ $ldap_server = lookup("base_installation::ldap_server")
+ $ldap_base = lookup("base_installation::ldap_base")
+ $ldap_dn = lookup("base_installation::ldap_dn")
+ $ldap_account_pattern = "(&(memberOf=cn=users,cn=etherpad,ou=services,dc=immae,dc=eu)(uid={{username}}))"
+ $ldap_group_pattern = "(memberOf=cn=groups,cn=etherpad,ou=services,dc=immae,dc=eu)"
+ $ldap_password = generate_password(24, $password_seed, "ldap")
+
+
+ include "base_installation"
+
+ include "profile::tools"
+ include "profile::postgresql"
+ include "profile::apache"
+
+ ensure_packages(["npm"])
+ ensure_packages(["abiword"])
+ ensure_packages(["libreoffice-fresh", "libreoffice-fresh-fr", "java-runtime-common", "jre8-openjdk"])
+ ensure_packages(["tidy"])
+ aur::package { "etherpad-lite": }
+ -> patch::file { "/usr/share/etherpad-lite/src/node/utils/LibreOffice.js":
+ diff_source => "puppet:///modules/role/etherpad/libreoffice_patch.diff",
+ }
+ -> file { "/etc/etherpad-lite/settings.json":
+ ensure => present,
+ owner => "etherpad-lite",
+ group => "etherpad-lite",
+ notify => Service["etherpad-lite"],
+ content => template("role/etherpad/settings.json.erb"),
+ }
+
+ $modules = [
+ "ep_aa_file_menu_toolbar",
+ "ep_adminpads",
+ "ep_align",
+ "ep_bookmark",
+ "ep_clear_formatting",
+ "ep_colors",
+ "ep_copy_paste_select_all",
+ "ep_cursortrace",
+ "ep_embedmedia",
+ "ep_font_family",
+ "ep_font_size",
+ "ep_headings2",
+ "ep_ldapauth",
+ "ep_line_height",
+ "ep_markdown",
+ "ep_previewimages",
+ "ep_ruler",
+ "ep_scrollto",
+ "ep_set_title_on_pad",
+ "ep_subscript_and_superscript",
+ "ep_timesliderdiff"
+ ]
+
+ $modules.each |$module| {
+ exec { "npm_install_$module":
+ command => "/usr/bin/npm install $module",
+ unless => "/usr/bin/test -d /usr/share/etherpad-lite/node_modules/$module",
+ cwd => "/usr/share/etherpad-lite/",
+ environment => "HOME=/root",
+ require => Aur::Package["etherpad-lite"],
+ before => Service["etherpad-lite"],
+ notify => Service["etherpad-lite"],
+ }
+ ->
+ file { "/usr/share/etherpad-lite/node_modules/$module/.ep_initialized":
+ ensure => present,
+ mode => "0644",
+ before => Service["etherpad-lite"],
+ }
+ }
+
+ service { "etherpad-lite":
+ enable => true,
+ ensure => "running",
+ require => Aur::Package["etherpad-lite"],
+ subscribe => Aur::Package["etherpad-lite"],
+ }
+
+ profile::postgresql_master { "postgresql master for etherpad":
+ letsencrypt_host => $web_host,
+ backup_hosts => ["backup-1"],
+ }
+
+ postgresql::server::db { $pg_db:
+ user => $pg_user,
+ password => postgresql_password($pg_user, $pg_password),
+ }
+
+ postgresql::server::pg_hba_rule { "allow local access to $pg_user user":
+ type => 'local',
+ database => $pg_db,
+ user => $pg_user,
+ auth_method => 'ident',
+ order => "05-01",
+ }
+
+}
base <%= @ldap_base %>
binddn <%= @ldap_dn %>
bindpw <%= @ldap_password %>
-pam_login_attribute <%= @ldap_attribute %>
+pam_login_attribute <%= @pgbouncer_ldap_attribute %>
pam_filter <%= @ldap_filter %>
+<%- if !@pg_listen_port.nil? -%>
+listen_addresses= '*'
+port = <%= @pg_listen_port %>
+ssl = on
+ssl_key_file = '<%= @ssl_key %>'
+ssl_cert_file = '<%= @ssl_cert %>'
+<%- else -%>
listen_addresses= ''
+<%- end %>
unix_socket_directories = '<%= @pg_path %>'
data_directory = '<%= @pg_path %>'
wal_level = logical
-
--- /dev/null
+{
+ "title": "Etherpad",
+ "favicon": "favicon.ico",
+
+ "ip": "<%= @web_listen %>",
+ "port" : <%= @web_port %>,
+ "showSettingsInAdminPage" : false,
+ "dbType" : "postgres",
+ "dbSettings" : {
+ "user" : "<%= @pg_user %>",
+ "host" : "/run/postgresql",
+ "password": "",
+ "database": "<%= @pg_db %>",
+ "charset" : "utf8mb4"
+ },
+
+ "defaultPadText" : "Welcome to Etherpad!\n\nThis pad text is synchronized as you type, so that everyone viewing this page sees the same text. This allows you to collaborate seamlessly on documents!\n\nGet involved with Etherpad at http:\/\/etherpad.org\n",
+ "padOptions": {
+ "noColors": false,
+ "showControls": true,
+ "showChat": true,
+ "showLineNumbers": true,
+ "useMonospaceFont": false,
+ "userName": false,
+ "userColor": false,
+ "rtl": false,
+ "alwaysShowChat": false,
+ "chatAndUsers": false,
+ "lang": "en-gb"
+ },
+
+ "suppressErrorsInPadText" : false,
+ "requireSession" : false,
+ "editOnly" : false,
+ "sessionNoPassword" : false,
+ "minify" : true,
+ "maxAge" : 21600,
+ "abiword" : "/usr/bin/abiword",
+ "soffice" : "/usr/bin/soffice",
+ "tidyHtml" : "/usr/bin/tidy",
+ "allowUnknownFileEnds" : true,
+ "requireAuthentication" : false,
+ "requireAuthorization" : false,
+ "trustProxy" : false,
+ "disableIPlogging" : false,
+ "automaticReconnectionTimeout" : 0,
+ "scrollWhenFocusLineIsOutOfViewport": {
+ "percentage": {
+ "editionAboveViewport": 0,
+ "editionBelowViewport": 0
+ },
+ "duration": 0,
+ "scrollWhenCaretIsInTheLastLineOfViewport": false,
+ "percentageToScrollWhenUserPressesArrowUp": 0
+ },
+ "users": {
+ "ldapauth": {
+ "url": "ldaps://<%= @ldap_server %>",
+ "accountBase": "<%= @ldap_base %>",
+ "accountPattern": "<%= @ldap_account_pattern %>",
+ "displayNameAttribute": "cn",
+ "searchDN": "<%= @ldap_dn %>",
+ "searchPWD": "<%= @ldap_password %>",
+ "groupSearchBase": "<%= @ldap_base %>",
+ "groupAttribute": "member",
+ "groupAttributeIsDN": true,
+ "searchScope": "sub",
+ "groupSearch": "<%= @ldap_group_pattern %>",
+ "anonymousReadonly": false
+ }
+ },
+ "socketTransportProtocols" : ["xhr-polling", "jsonp-polling", "htmlfile"],
+ "loadTest": false,
+ "indentationOnNewLine": false,
+ "toolbar": {
+ "left": [
+ ["bold", "italic", "underline", "strikethrough"],
+ ["orderedlist", "unorderedlist", "indent", "outdent"],
+ ["undo", "redo"],
+ ["clearauthorship"]
+ ],
+ "right": [
+ ["importexport", "timeslider", "savedrevision"],
+ ["settings", "embed"],
+ ["showusers"]
+ ],
+ "timeslider": [
+ ["timeslider_export", "timeslider_returnToPad"]
+ ]
+ },
+ "loglevel": "INFO",
+ "logconfig" : { "appenders": [ { "type": "console" } ] }
+}
result = client.post("/cloud/project/{}/instance/{}/rescueMode".format(project,
instance["id"]), imageId=instance["imageId"], rescue=(netboot_mode == "rescue"))
print(result)
+else:
+ result = client.post("/cloud/project/{}/instance/{}/reboot".format(project, instance["id"]), type="soft")
+ print(result)
# reboot normal:
#result = client.post("/cloud/project/{}/instance/{}/reboot".format(project, instance["id"]), type="soft")