From 76ba67a2528279e3e542bdf36db749667eb80c6f Mon Sep 17 00:00:00 2001 From: =?utf8?q?Felix=20D=C3=B6rre?= Date: Sat, 22 Dec 2018 13:19:16 +0100 Subject: [PATCH] add: motion system from source Change-Id: I3d69d1c6d8870df39699f079642100b7b1201654 --- commands | 1 + environments/production/manifests/ip.pp | 2 + environments/production/manifests/motion.pp | 8 ++ environments/production/manifests/nginx.pp | 4 +- manager/admin-manage-certificates | 3 + modules/motion/.gitignore | 4 + modules/motion/README | 3 + modules/motion/files/.gitignore | 1 + modules/motion/files/motion.ini | 6 ++ modules/motion/files/motion.service | 20 +++++ modules/motion/files/user_map.template.epp | 6 ++ modules/motion/manifests/container.pp | 82 +++++++++++++++++++++ modules/motion/manifests/virtual.pp | 48 ++++++++++++ modules/motion/templates/config.py.epp | 4 + modules/motion/templates/nginx.epp | 62 ++++++++++++++++ 15 files changed, 252 insertions(+), 2 deletions(-) create mode 100644 environments/production/manifests/motion.pp create mode 100644 modules/motion/.gitignore create mode 100644 modules/motion/README create mode 100644 modules/motion/files/.gitignore create mode 100644 modules/motion/files/motion.ini create mode 100644 modules/motion/files/motion.service create mode 100644 modules/motion/files/user_map.template.epp create mode 100644 modules/motion/manifests/container.pp create mode 100644 modules/motion/manifests/virtual.pp create mode 100644 modules/motion/templates/config.py.epp create mode 100644 modules/motion/templates/nginx.epp diff --git a/commands b/commands index 531e973..aa2f808 100755 --- a/commands +++ b/commands @@ -50,6 +50,7 @@ if [[ $com == "update certs" || $com == "force update certs" ]]; then update_cert "modules/gigi/files/gigi" update_cert "modules/gigi/files/client" update_cert "modules/gitweb/files/web" + update_cert "modules/motion/files/motion" echo "DONE" [[ -f $folder/web.crt ]] && rm $folder/web.crt [[ -f $folder/web.req ]] && rm $folder/web.req diff --git a/environments/production/manifests/ip.pp b/environments/production/manifests/ip.pp index 944a6fc..dd510b1 100644 --- a/environments/production/manifests/ip.pp +++ b/environments/production/manifests/ip.pp @@ -6,6 +6,7 @@ $ips = { hop => '10.0.3.18', quiz => '10.0.3.19', postgres => '10.0.3.14', + motion => '10.0.3.22', gitweb => '10.0.3.20'} $ipsv6 = { @@ -17,6 +18,7 @@ $ipsv6 = { exim => 'fc00:1::11', hop => 'fc00:1::12', quiz => 'fc00:1::13', + motion => 'fc00:1::16', gitweb => 'fc00:1::14'} $passwords = { diff --git a/environments/production/manifests/motion.pp b/environments/production/manifests/motion.pp new file mode 100644 index 0000000..307b870 --- /dev/null +++ b/environments/production/manifests/motion.pp @@ -0,0 +1,8 @@ +motion::virtual{'motion': +} + +node motion{ + class{'motion::container': + container => 'motion' + } +} diff --git a/environments/production/manifests/nginx.pp b/environments/production/manifests/nginx.pp index 9b9c561..db81cc5 100644 --- a/environments/production/manifests/nginx.pp +++ b/environments/production/manifests/nginx.pp @@ -1,4 +1,4 @@ -define front_vhost($source, $crt = undefined){ +define front_vhost($source, $crt = undefined, $args = {}){ if $crt { file{"/etc/ssl/private/$name.crt": ensure => 'file', @@ -16,7 +16,7 @@ define front_vhost($source, $crt = undefined){ } file {"/etc/nginx/sites-available/$name.conf": ensure => 'file', - content => epp($source), + content => epp($source, $args), require => Package['nginx-light'], }-> file {"/etc/nginx/sites-enabled/$name.conf": diff --git a/manager/admin-manage-certificates b/manager/admin-manage-certificates index 2a6c4c0..634aa7f 100755 --- a/manager/admin-manage-certificates +++ b/manager/admin-manage-certificates @@ -98,6 +98,9 @@ while true; do "modules/quiz/files/client") options="profile=client-orga&CN=Quiz+Api+User&SANs=quiz@$domain" ;; + "modules/motion/files/motion") + options="profile=server-orga&CN=&SANs=motion.$domain" + ;; *) echo "Unknown certificate in $line, rejecting" echo "FAIL" >&${COPROC[1]} diff --git a/modules/motion/.gitignore b/modules/motion/.gitignore new file mode 100644 index 0000000..5c9671b --- /dev/null +++ b/modules/motion/.gitignore @@ -0,0 +1,4 @@ +/files/motion-roots.pem +/files/web.crt +/files/web.key +/templates/user_map.epp diff --git a/modules/motion/README b/modules/motion/README new file mode 100644 index 0000000..d4987f4 --- /dev/null +++ b/modules/motion/README @@ -0,0 +1,3 @@ +Usage: +- Put list of allowed root-pem files in "files/motion-roots.pem" +- Add allowed certificates with usernames and privileges to "templates/user_map.epp" which can be initialized with a copy of "templates/user_map.template.epp" diff --git a/modules/motion/files/.gitignore b/modules/motion/files/.gitignore new file mode 100644 index 0000000..41b8c56 --- /dev/null +++ b/modules/motion/files/.gitignore @@ -0,0 +1 @@ +user_map.epp diff --git a/modules/motion/files/motion.ini b/modules/motion/files/motion.ini new file mode 100644 index 0000000..20fead5 --- /dev/null +++ b/modules/motion/files/motion.ini @@ -0,0 +1,6 @@ +[uwsgi] +fastcgi-socket=/motion-socket/motion.fcgi +chmod-socket=666 +virtualenv=/home/motion/motion +master=True +mount=/=motion:app diff --git a/modules/motion/files/motion.service b/modules/motion/files/motion.service new file mode 100644 index 0000000..e4ed3b4 --- /dev/null +++ b/modules/motion/files/motion.service @@ -0,0 +1,20 @@ +[Unit] +Description=Motion uWSGI app +After=syslog.target + +[Service] +ExecStart=/home/motion/motion/bin/uwsgi --ini ../motion.ini +User=motion +Group=motion +Restart=on-failure +KillSignal=SIGQUIT +Type=notify +StandardError=journal +NotifyAccess=all +WorkingDirectory=/home/motion/motion +PrivateTmp=yes +PrivateDevices=yes +ProtectSystem=strict +ProtectHome=no +ReadOnlyPaths=/home +ReadWritePaths=/home/motion/motion/__pycache__/ /motion-socket diff --git a/modules/motion/files/user_map.template.epp b/modules/motion/files/user_map.template.epp new file mode 100644 index 0000000..064f5be --- /dev/null +++ b/modules/motion/files/user_map.template.epp @@ -0,0 +1,6 @@ +map_hash_bucket_size 128; + +# user map +map "$ssl_client_serial:$ssl_client_i_dn" $<%=$container%>_user_role { + default "/"; +} diff --git a/modules/motion/manifests/container.pp b/modules/motion/manifests/container.pp new file mode 100644 index 0000000..86ecc38 --- /dev/null +++ b/modules/motion/manifests/container.pp @@ -0,0 +1,82 @@ +class motion::container($container){ + include container::contained; + include container::no_ssh; + + package{ ['python3', 'python3-pip', 'virtualenv', 'libpq-dev']: + ensure => 'installed' + } + user{'motion': + ensure => present, + home => '/home/motion', + system => 'yes' + } -> + file{'/home/motion': + ensure => 'directory', + owner => 'motion', + group => 'motion' + } + file{'/motion-socket': + owner => 'motion', + group => 'motion' + } + package{'git': + } -> + exec{'clone motion': + command => '/usr/bin/git clone https://code.wpia.club/motion.git', + cwd => '/home/motion', + creates => '/home/motion/motion/.git', + user => 'motion' + } -> + file{'/home/motion/motion/__pycache__': + ensure => directory, + owner => motion, + group => motion + } -> + file{'/home/motion/motion/config.py': + content => epp("motion/config.py", {user => $container, password => 'motion'}), + owner => motion, + group => motion + } -> + exec {'motion-virtualenv': + command => '/usr/bin/virtualenv -p python3 motion', + cwd => '/home/motion', + creates => '/home/motion/motion/bin/activate', + user => 'motion', + require => [Package['virtualenv'], Package['python3-pip'], Exec['clone motion']], + before =>  Service['motion.service'], + } -> + exec{'pip dependencies': + command => '/bin/bash -c "source motion/bin/activate; /home/motion/motion/bin/pip install -r motion/requirements.txt"', + require => [Exec['motion-virtualenv'],Package['python3-pip']], + cwd => '/home/motion', + timeout => 0, + user => 'motion', + creates => '/home/motion/motion/bin/flask' + } + + exec{'install uwsgi': + command => '/bin/bash -c "source motion/bin/activate; /home/motion/motion/bin/pip install uwsgi"', + require => Exec['motion-virtualenv'], + cwd => '/home/motion', + timeout => 0, + user => 'motion', + creates => '/home/motion/motion/bin/uwsgi' + } + + file{'/home/motion/motion.ini': + source => 'puppet:///modules/motion/motion.ini' + } -> + systemd::unit_file {'motion.service': + ensure => 'file', + source => 'puppet:///modules/motion/motion.service', + notify => Service['motion.service'], + require => Exec['install uwsgi'] + } + service{'motion.service': + ensure => 'running', + provider => 'systemd', + enable => true, + require => [Exec['pip dependencies'],Exec['systemctl-daemon-reload']], + } + +} diff --git a/modules/motion/manifests/virtual.pp b/modules/motion/manifests/virtual.pp new file mode 100644 index 0000000..ccc379d --- /dev/null +++ b/modules/motion/manifests/virtual.pp @@ -0,0 +1,48 @@ +define motion::virtual ($domain = "motion.${systemDomain}", $container = $name) { + @file{"/run/${container}-socket": + ensure => 'directory', + tag => [root] + } -> + @lxc::container { $container: + contname => $container, + ip => $ips[$container], + dir => ['/motion-socket'], + bind => { + "/run/${container}-socket" => { 'target' => "motion-socket"}, + }, + tag => [root] + } + @lxc::container_bind{ "/run/${container}-socket": + container => 'front-nginx', + target => "${container}-socket", + tag => [root] + } + + @file{"/etc/ssl/${container}-roots.pem": + ensure => 'file', + source => ['puppet:///modules/motion/motion-roots.pem', 'puppet:///modules/nre/config/ca/root.crt'], + tag => [nginx] + } + @front_vhost{$container: + source => 'motion/nginx.epp', + args => {container => $container, cert_stem => "/etc/ssl/private/${container}", domain => $domain, socket => "unix:/${container}-socket/motion.fcgi"}, + crt => "motion/${container}", + tag => [nginx] + } + + + @postgresql::server::db { $container: + user => $container, + password => postgresql_password($container, 'motion'), + tag => [primary] + } + @postgresql::server::pg_hba_rule { "allow ${container} to access its database": + description => "Open up PostgreSQL for access from motion-user to its database", + type => 'host', + database => $container, + user => $container, + address => "${ips[$container]}/32", + auth_method => 'md5', + tag => [primary] + } +} diff --git a/modules/motion/templates/config.py.epp b/modules/motion/templates/config.py.epp new file mode 100644 index 0000000..27274f2 --- /dev/null +++ b/modules/motion/templates/config.py.epp @@ -0,0 +1,4 @@ +DATABASE="pq://<%=$ips[postgres]%>/motion" +USER="<%=$user%>" +PASSWORD="<%=$password%>" +GROUP_PREFIX={"motion.<%=$systemDomain%>":{"fellowship": "f", "board": "m"}} diff --git a/modules/motion/templates/nginx.epp b/modules/motion/templates/nginx.epp new file mode 100644 index 0000000..36dbfa6 --- /dev/null +++ b/modules/motion/templates/nginx.epp @@ -0,0 +1,62 @@ +server { + listen 0.0.0.0:80; + server_name <%=$domain%>; + gzip on; + + location / { + fastcgi_param QUERY_STRING $query_string; + fastcgi_param REQUEST_METHOD $request_method; + fastcgi_param CONTENT_TYPE $content_type; + fastcgi_param CONTENT_LENGTH $content_length; + fastcgi_param REQUEST_URI $request_uri; + fastcgi_param PATH_INFO $document_uri; + fastcgi_param REMOTE_ADDR $remote_addr; + fastcgi_param REMOTE_PORT $remote_port; + fastcgi_param SERVER_NAME $host; + fastcgi_param SERVER_PORT '80'; + fastcgi_param SERVER_PROTOCOL 'http'; + fastcgi_param USER_ROLES 'anonymous/void:*'; + fastcgi_pass <%=$socket%>; + } + location ~* /.well-known/someca-challenge/.* { + root /data/challenge; + } +} +<%=inline_epp(file('motion/user_map.epp', 'motion/user_map.template.epp'), {container => $container})%> +log_format <%=$container%>-cert '$date_gmt $ssl_client_serial:$ssl_client_i_dn;$<%=$container%>_user_role'; +server { + listen 0.0.0.0:443 ssl; + server_name <%=$domain%>; + gzip on; + ssl_certificate <%=$cert_stem%>.crt; + ssl_certificate_key <%=$cert_stem%>.key; + + ssl_client_certificate /etc/ssl/<%=$container%>-roots.pem; + ssl_verify_client on; + ssl_verify_depth 4; + access_log /tmp/<%=$container%>-certs.log <%=$container%>-cert; + + location / { + fastcgi_param QUERY_STRING $query_string; + fastcgi_param REQUEST_METHOD $request_method; + fastcgi_param CONTENT_TYPE $content_type; + fastcgi_param CONTENT_LENGTH $content_length; + fastcgi_param REQUEST_URI $request_uri; + fastcgi_param PATH_INFO $document_uri; + fastcgi_param REMOTE_ADDR $remote_addr; + fastcgi_param REMOTE_PORT $remote_port; + fastcgi_param SERVER_NAME $host; + fastcgi_param SERVER_PORT '443'; + fastcgi_param SERVER_PROTOCOL 'https'; + fastcgi_param USER_ROLES $<%=$container%>_user_role; + fastcgi_pass <%=$socket%>; + + <% if($protected != 'no') { %> + auth_basic "closed site"; + auth_basic_user_file /etc/nginx/access.txt; + <% } %> + } + location ~* /.well-known/someca-challenge/.* { + root /data/challenge; + } +} -- 2.39.2