gitit icon indicating copy to clipboard operation
gitit copied to clipboard

Add systemd service

Open tensor5 opened this issue 8 years ago • 2 comments

It was proposed in https://github.com/tensor5/haskell-happstack/issues/11 to add systemd service file to the haskell-gitit Arch Linux package. We agreed that this issue should be discussed upstream.

We think that there should be two service files, one named gitit.service:

[Unit]
Description=Gitit wiki
After=network.target

[Service]
ExecStart=/usr/bin/gitit -f /etc/gitit/default.conf
WorkingDirectory=/srv/gitit/default
User=gitit
Group=gitit
#Restart=on-failure

[Install]
WantedBy=multi-user.target

and the other named [email protected]:

[Unit]
Description=Gitit wiki
After=network.target

[Service]
ExecStart=/usr/bin/gitit -f /etc/gitit/%I.conf
WorkingDirectory=/srv/gitit/%I
User=gitit
Group=gitit
#Restart=on-failure

[Install]
WantedBy=multi-user.target

with gitit user and group being created upon installation and %I being the unescaped instance name. User can enable mutliple instances by running e.g. systemctl start [email protected]. Depending on the configuration it could run on port 80 (the executable /usr/bin/gitit should be granted the capability CAP_NET_BIND_SERVICE), or proxied behind a web server. The use of the directory /srv/gitit as home of gitit data is still being debated.

tensor5 avatar Jul 23 '15 00:07 tensor5

This is more a packaging issue, and I don't have strong opinions about it.

jgm avatar Jul 23 '15 15:07 jgm

FYI here is a hardened gitit .service that I just wrote. It gets reverse-proxied by a nginx running on the same host (hence only localhost may talk to gitit directly). This is working for me at least enough that chromium can log in and make edits to a page, with

$ ssh heavy -N -M -D12345 -oLocalCommand='chromium --temp-profile --proxy-server=socks://localhost:12345 http://heavy:5001 &'   # NOTE: chromium won't allow "http://localhost:5001"

NOTE: For password resets: If you want gitit to use /usr/sbin/sendmail(8postfix) this is too aggressive (postfix needs set-gid maildrop!). If you want gitit to use /usr/sbin/sendmail(1msmtp) it will probably work because AF_INET6 and localhost are still unblocked.

NOTE: if your users don't "git push" changes to the gitit repo, you can ignore all the tmpfiles.d ACL crap, and you can turn on cache in gitit.conf. The CacheDirectory=%p means gitit will have write access to /var/cache/gitit implicitly, created and managed by systemd

  - name: Be our Knowledge Base (KB).
    tags: kb, gitit, wiki
    block:
    - ansible.builtin.package:
        name:
          - gitit
          # gitit Recommends
          - mime-support
          - libghc-filestore-data
          # Custom theme
          # https://github.com/trentbuck/gitit-bootstrap-theme/
          - gitit-bootstrap-theme
    - name: tell systemd to create system user 'gitit'
      ansible.builtin.copy:
        dest: /etc/sysusers.d/cyber-gitit.conf
        content: |
          u gitit - - -
        # FIXME: needs notify handler for "systemd-sysusers /etc/sysusers.d/cyber-gitit.conf"
    - name: tell systemd to create grant user 'gitit' write access to KB repo
      ansible.builtin.copy:
        dest: /etc/tmpfiles.d/cyber-gitit.conf
        content: |
          # FIXME: this is excessive.
          # FIXME: also needs "git config core.sharedRepository true", probably?
          A  /srv/vcs/kb - - - - default:user::rwx,user::rwx
          A+ /srv/vcs/kb - - - - default:user:gitit:rwx,user:gitit:rwx
          A+ /srv/vcs/kb - - - - default:group::rwx,group:gitit:rwx
          A+ /srv/vcs/kb - - - - default:group:cyber:rwx,group:cyber:rwx
          A+ /srv/vcs/kb - - - - default:other::---,other::---
    - ansible.builtin.copy:
        dest: /etc/systemd/system/gitit.service
        content: |
          [Service]
          ExecStart=gitit --config-file=/etc/gitit.conf
          [Install]
          WantedBy=multi-user.target

          # Hardening
          [Service]
          User=%p
          LogsDirectory=%p
          StateDirectory=%p
          RuntimeDirectory=%p
          WorkingDirectory=/run/%p
          CacheDirectory=%p
          ConfigurationDirectory=%p
          ReadWritePaths=/srv/vcs/kb

          # FIXME: gitit cannot listen on gitit.sock or systemd socket-activate yet.
          #          https://github.com/jgm/gitit/issues/675
          #        therefore we cannot do
          #          PrivateNetwork=yes
          #          RestrictAddressFamilies=~AF_INET
          #          RestrictAddressFamilies=~AF_INET6
          #          IPAddressDeny=any
          CapabilityBoundingSet=
          RestrictNamespaces=yes
          RestrictAddressFamilies=AF_UNIX AF_NETLINK AF_INET AF_INET6
          DevicePolicy=closed
          IPAddressDeny=all
          IPAddressAllow=localhost
          NoNewPrivileges=yes
          PrivateDevices=yes
          PrivateUsers=yes
          PrivateTmp=yes
          ProtectClock=yes
          ProtectControlGroups=yes
          ProtectHome=yes
          ProtectKernelLogs=yes
          ProtectKernelModules=yes
          ProtectKernelTunables=yes
          ProtectProc=invisible
          ProtectSystem=strict
          RestrictSUIDGUID=yes
          SystemCallArchitectures=native
          SystemCallFilter=@system-service
          SystemCallFilter=~@privileged
          SystemCallFilter=~@resources
          RestrictRealtime=yes
          LockPersonality=yes
          MemoryDenyWriteExecute=yes
          RemoveIPC=yes
          UMask=0077
          ProtectHostname=yes
          ProcSubset=pid
    - ansible.builtin.copy:
        dest: /etc/gitit.conf
        content: |
          # See gitit --print-default-config for documentation.
          default-page-type:              RST
          log-file:                       /var/log/gitit/gitit.log
          # Use this to log every GET request.
          # NOTE: if you do this, set up a logrotate rule for gitit!
          #log-level:                     INFO
          port:                           5001
          repository-path:                /srv/vcs/kb
          static-dir:                     /usr/share/javascript/gitit-bootstrap-theme/static
          templates-dir:                  /usr/share/javascript/gitit-bootstrap-theme/templates
          user-file:                      /var/lib/gitit/gitit-users
          wiki-title:                     Knowledge Base
          # FIXME: the cache doesn't know about updates made directly via git
          # (as opposed to via the web UI).  This could be fixed by having git
          # delete the cached version of a file when its source is updated.
          #use-cache:                     yes
          cache-dir:                      /var/cache/gitit
          # authentication-method:          form
          front-page: Knowledge Base
          no-delete:
          no-edit:
          # Disable mathjax -- IMO we do not need to hotlink to cdnjs.cloudflare.com.
          math: no
          # A security thing.  Probably on by default, but does not hurt to be explicit.
          xss-sanitize: yes
    - ansible.builtin.systemd:
        daemon_reload: true
        name: gitit.service
        state: started
        enabled: true

And here's systemd's assessment of systemd-provided hardening (anything below 4-5 is doing well; below 1 is nearly impossible):

  NAME                                                        DESCRIPTION                                                                    EXPOSURE
✗ PrivateNetwork=                                             Service has access to the host's network                                            0.5
✓ User=/DynamicUser=                                          Service runs under a static non-root user identity                             
✓ CapabilityBoundingSet=~CAP_SET(UID|GID|PCAP)                Service cannot change UID/GID identities/capabilities                          
✓ CapabilityBoundingSet=~CAP_SYS_ADMIN                        Service has no administrator privileges                                        
✓ CapabilityBoundingSet=~CAP_SYS_PTRACE                       Service has no ptrace() debugging abilities                                    
✗ RestrictAddressFamilies=~AF_(INET|INET6)                    Service may allocate Internet sockets                                               0.3
✓ RestrictNamespaces=~CLONE_NEWUSER                           Service cannot create user namespaces                                          
✓ RestrictAddressFamilies=~…                                  Service cannot allocate exotic sockets                                         
✓ CapabilityBoundingSet=~CAP_(CHOWN|FSETID|SETFCAP)           Service cannot change file ownership/access mode/capabilities                  
✓ CapabilityBoundingSet=~CAP_(DAC_*|FOWNER|IPC_OWNER)         Service cannot override UNIX file/IPC permission checks                        
✓ CapabilityBoundingSet=~CAP_NET_ADMIN                        Service has no network configuration privileges                                
✓ CapabilityBoundingSet=~CAP_SYS_MODULE                       Service cannot load kernel modules                                             
✓ CapabilityBoundingSet=~CAP_SYS_RAWIO                        Service has no raw I/O access                                                  
✓ CapabilityBoundingSet=~CAP_SYS_TIME                         Service processes cannot change the system clock                               
✗ DeviceAllow=                                                Service has a device ACL with some special devices                                  0.1
✗ IPAddressDeny=                                              Service does not define an IP address allow list                                    0.2
✓ KeyringMode=                                                Service doesn't share key material with other services                         
✓ NoNewPrivileges=                                            Service processes cannot acquire new privileges                                
✓ NotifyAccess=                                               Service child processes cannot alter service state                             
✓ PrivateDevices=                                             Service has no access to hardware devices                                      
✓ PrivateMounts=                                              Service cannot install system mounts                                           
✓ PrivateTmp=                                                 Service has no access to other software's temporary files                      
✓ PrivateUsers=                                               Service does not have access to other users                                    
✓ ProtectClock=                                               Service cannot write to the hardware clock or system clock                     
✓ ProtectControlGroups=                                       Service cannot modify the control group file system                            
✓ ProtectHome=                                                Service has no access to home directories                                      
✓ ProtectKernelLogs=                                          Service cannot read from or write to the kernel log ring buffer                
✓ ProtectKernelModules=                                       Service cannot load or read kernel modules                                     
✓ ProtectKernelTunables=                                      Service cannot alter kernel tunables (/proc/sys, …)                            
✓ ProtectProc=                                                Service has restricted access to process tree (/proc hidepid=)                 
✓ ProtectSystem=                                              Service has strict read-only access to the OS file hierarchy                   
✓ RestrictAddressFamilies=~AF_PACKET                          Service cannot allocate packet sockets                                         
✗ RestrictSUIDSGID=                                           Service may create SUID/SGID files                                                  0.2
✓ SystemCallArchitectures=                                    Service may execute system calls only with native ABI                          
✓ SystemCallFilter=~@clock                                    System call allow list defined for service, and @clock is not included         
✓ SystemCallFilter=~@debug                                    System call allow list defined for service, and @debug is not included         
✓ SystemCallFilter=~@module                                   System call allow list defined for service, and @module is not included        
✓ SystemCallFilter=~@mount                                    System call allow list defined for service, and @mount is not included         
✓ SystemCallFilter=~@raw-io                                   System call allow list defined for service, and @raw-io is not included        
✓ SystemCallFilter=~@reboot                                   System call allow list defined for service, and @reboot is not included        
✓ SystemCallFilter=~@swap                                     System call allow list defined for service, and @swap is not included          
✓ SystemCallFilter=~@privileged                               System call allow list defined for service, and @privileged is not included    
✓ SystemCallFilter=~@resources                                System call allow list defined for service, and @resources is not included     
✓ AmbientCapabilities=                                        Service process does not receive ambient capabilities                          
✓ CapabilityBoundingSet=~CAP_AUDIT_*                          Service has no audit subsystem access                                          
✓ CapabilityBoundingSet=~CAP_KILL                             Service cannot send UNIX signals to arbitrary processes                        
✓ CapabilityBoundingSet=~CAP_MKNOD                            Service cannot create device nodes                                             
✓ CapabilityBoundingSet=~CAP_NET_(BIND_SERVICE|BROADCAST|RAW) Service has no elevated networking privileges                                  
✓ CapabilityBoundingSet=~CAP_SYSLOG                           Service has no access to kernel logging                                        
✓ CapabilityBoundingSet=~CAP_SYS_(NICE|RESOURCE)              Service has no privileges to change resource use parameters                    
✓ RestrictNamespaces=~CLONE_NEWCGROUP                         Service cannot create cgroup namespaces                                        
✓ RestrictNamespaces=~CLONE_NEWIPC                            Service cannot create IPC namespaces                                           
✓ RestrictNamespaces=~CLONE_NEWNET                            Service cannot create network namespaces                                       
✓ RestrictNamespaces=~CLONE_NEWNS                             Service cannot create file system namespaces                                   
✓ RestrictNamespaces=~CLONE_NEWPID                            Service cannot create process namespaces                                       
✓ RestrictRealtime=                                           Service realtime scheduling access is restricted                               
✓ SystemCallFilter=~@cpu-emulation                            System call allow list defined for service, and @cpu-emulation is not included 
✓ SystemCallFilter=~@obsolete                                 System call allow list defined for service, and @obsolete is not included      
✗ RestrictAddressFamilies=~AF_NETLINK                         Service may allocate netlink sockets                                                0.1
✗ RootDirectory=/RootImage=                                   Service runs within the host's root directory                                       0.1
✓ SupplementaryGroups=                                        Service has no supplementary groups                                            
✓ CapabilityBoundingSet=~CAP_MAC_*                            Service cannot adjust SMACK MAC                                                
✓ CapabilityBoundingSet=~CAP_SYS_BOOT                         Service cannot issue reboot()                                                  
✓ Delegate=                                                   Service does not maintain its own delegated control group subtree              
✓ LockPersonality=                                            Service cannot change ABI personality                                          
✓ MemoryDenyWriteExecute=                                     Service cannot create writable executable memory mappings                      
✓ RemoveIPC=                                                  Service user cannot leave SysV IPC objects around                              
✓ RestrictNamespaces=~CLONE_NEWUTS                            Service cannot create hostname namespaces                                      
✓ UMask=                                                      Files created by service are accessible only by service's own user by default  
✓ CapabilityBoundingSet=~CAP_LINUX_IMMUTABLE                  Service cannot mark files immutable                                            
✓ CapabilityBoundingSet=~CAP_IPC_LOCK                         Service cannot lock memory into RAM                                            
✓ CapabilityBoundingSet=~CAP_SYS_CHROOT                       Service cannot issue chroot()                                                  
✓ ProtectHostname=                                            Service cannot change system host/domainname                                   
✓ CapabilityBoundingSet=~CAP_BLOCK_SUSPEND                    Service cannot establish wake locks                                            
✓ CapabilityBoundingSet=~CAP_LEASE                            Service cannot create file leases                                              
✓ CapabilityBoundingSet=~CAP_SYS_PACCT                        Service cannot use acct()                                                      
✓ CapabilityBoundingSet=~CAP_SYS_TTY_CONFIG                   Service cannot issue vhangup()                                                 
✓ CapabilityBoundingSet=~CAP_WAKE_ALARM                       Service cannot program timers that wake up the system                          
✗ RestrictAddressFamilies=~AF_UNIX                            Service may allocate local sockets                                                  0.1
✓ ProcSubset=                                                 Service has no access to non-process /proc files (/proc subset=)               

→ Overall exposure level for gitit.service: 1.3 OK 🙂

trentbuck avatar Sep 09 '22 14:09 trentbuck