class soc::intelmq(
  Optional[String]    $tls_cert   = undef,
  Optional[String]    $tls_chain  = undef,
  Optional[String]    $tls_key    = undef,
  String              $servername = $facts['networking']['fqdn'],
  Boolean             $use_snakeoil = false,
) {
  include sunet::systemd_reload

  # Set some global variables
  $api_user = lookup('intelmq_api_user.username', undef, undef, 'test')
  $api_pass = lookup('intelmq_api_user.password', undef, undef, 'pass')
  $db_user = lookup('intelmq_db_user.username', undef, undef, 'test')
  $db_pass = lookup('intelmq_db_user.password', undef, undef, 'pass')

  group { 'intelmq':
    ensure => present,
  }

  user { 'intelmq':
    ensure     => present,
    gid        => 'intelmq',
    groups     => 'www-data',
    home       => '/opt/intelmq',
    managehome => true,
    shell      => '/bin/bash',
  }

  file {
    '/etc/intelmq':
      ensure => directory,
      owner  => 'intelmq',
      group  => 'intelmq',
      ;
    '/etc/intelmq/mailgen':
      ensure => directory,
      owner  => 'intelmq',
      group  => 'intelmq',
      ;
    '/etc/intelmq/mailgen/formats':
      ensure => directory,
      owner  => 'intelmq',
      group  => 'intelmq',
      ;
    '/etc/intelmq/mailgen/gnupghome':
      ensure => directory,
      owner  => 'intelmq',
      group  => 'intelmq',
      ;
    '/etc/intelmq/mailgen/templates':
      ensure => directory,
      owner  => 'intelmq',
      group  => 'intelmq',
      ;
  }

  file { '/etc/intelmq/api':
    ensure => directory,
    owner  => 'intelmq',
    group  => 'www-data',
    mode   => '0770',
  }

  file { '/etc/intelmq/fody':
    ensure => directory,
    owner  => 'intelmq',
    group  => 'www-data',
    mode   => '0770',
  }

  package { 'apache2':
    ensure => 'latest',
  }

  package { 'libapache2-mod-wsgi-py3':
    ensure => 'latest',
  }

  file { '/opt/intelmq/install':
    ensure => directory,
    owner  => 'intelmq',
    group  => 'intelmq',
    mode   => '0755',
  }

  file {
    '/opt/intelmq/www':
      ensure => directory,
      owner  => 'intelmq',
      group  => 'intelmq',
      mode   => '0755',
      ;
    '/opt/intelmq/www/intelmq-manager':
      ensure => directory,
      owner  => 'intelmq',
      group  => 'www-data',
      mode   => '0750',
      ;
    '/opt/intelmq/www/fody':
      ensure => directory,
      owner  => 'intelmq',
      group  => 'www-data',
      mode   => '0750',
      ;
  }

  file { '/opt/intelmq/install/setup-nodesource.sh':
    ensure  => file,
    content => file('soc/intelmq/setup-nodesource.sh'),
    mode    => '0540',
  }

  exec { 'Add nodesource repo':
    command => '/opt/intelmq/install/setup-nodesource.sh',
    creates => '/etc/apt/sources.list.d/nodesource.list',
  }

  package { ['postgresql', 'python3-venv', 'python3-pip', 'python3-gpg', 'python3-psycopg2', 'redict', 'nodejs', ]:
    ensure => 'latest',
  }

  package { ['cmdtest', ]:
    ensure => 'absent',
  }

  exec { 'Install yarn from npm':
    command => 'npm install --global yarn',
    creates => '/usr/bin/yarn',
  }

  exec { 'Install IntelMQ venv':
    command => 'sudo -u intelmq /usr/bin/python3 -m venv --system-site-packages /opt/intelmq/venv',
    creates => '/opt/intelmq/venv',
  }

  exec { 'Always active venv for IntelMQ':
    command => 'echo ". venv/bin/activate" >> /opt/intelmq/.profile',
    unless  => 'grep -q activate /opt/intelmq/.profile 2> /dev/null',
  }

  file { '/opt/intelmq/install/eventdb-notifications.sql':
    ensure  => file,
    content => file('soc/intelmq/eventdb-notifications.sql'),
  }

  file { '/opt/intelmq/install/install-intelmq.sh':
    ensure  => file,
    content => file('soc/intelmq/install-intelmq.sh'),
    mode    => '0555',
  }

  exec { 'Install IntelMQ':
    command => 'sudo -u intelmq /opt/intelmq/install/install-intelmq.sh',
    creates => '/opt/intelmq/.installed'
  }

  exec { 'Run IntelMQ setup script':
    command => '/opt/intelmq/venv/bin/intelmqsetup',
    creates => '/opt/intelmq/var/lib/state.json',
    returns => ['0', '1',],
  }

  file { '/usr/bin/intelmqctl':
    ensure  => file,
    mode    => '0555',
    content => file('soc/intelmq/usr-bin-intelmqctl'),
  }

  file { '/opt/intelmq/install/setup-pgsql.sh':
    ensure  => file,
    content => template('soc/intelmq/setup-pgsql.sh'),
    mode    => '0500',
  }

  exec { 'Setup IntelMQ eventdb':
    command => '/opt/intelmq/install/setup-pgsql.sh',
    creates => '/opt/intelmq/.pgsql-installed',
  }

  file { '/etc/sudoers.d/01_intelmq-api':
    ensure  => file,
    content => file('soc/intelmq/sudoers-01-intelmq-api'),
    mode    => '0440',
  }

  service { 'apache2':
    ensure  => 'running',
    enable  => true,
    require => Package['apache2'],
  }

  $apache_modules = ['ssl', 'proxy', 'proxy_http', 'headers', 'rewrite',]
  $apache_modules.each |String $module| {
    exec { "a2enmod ${module}":
      notify  => Service['apache2'],
      unless  => "test -f /etc/apache2/mods-enabled/${module}.load",
    }
  }

  exec { 'Enable mod_wsgi':
    command => 'a2enmod wsgi',
    require => Package['libapache2-mod-wsgi-py3'],
    notify  => Service['apache2'],
    creates => '/etc/apache2/mods-enabled/wsgi.load',
  }

  file { '/etc/apache2/conf-available/wsgi-venv.conf':
    ensure  => file,
    content => file('soc/intelmq/apache/wsgi-venv.conf'),
  }

  exec { 'Enable wsgi-venv conf':
    command => 'a2enconf wsgi-venv',
    creates => '/etc/apache2/conf-enabled/wsgi-venv.conf',
    notify  => Service['apache2'],
  }

  file { '/etc/apache2/sites-available/intelmq-vhost.conf':
    ensure  => file,
    content => template('soc/intelmq/intelmq-vhost.conf.erb'),
    notify  => Service['apache2'],
  }

  file { '/etc/intelmq/api-config.json':
    ensure  => file,
    owner   => 'intelmq',
    group   => 'intelmq',
    mode    => '0444',
    content => file('soc/intelmq/api-config.json'),
  }

  file { '/etc/intelmq/fody-session.conf':
    ensure  => file,
    owner   => 'intelmq',
    group   => 'intelmq',
    mode    => '0444',
    content => file('soc/intelmq/fody-session.conf'),
  }

  exec { 'Setup intelmq-api user':
    command => "sudo -u intelmq /opt/intelmq/venv/bin/intelmq-api-adduser --user ${api_user} --password ${api_pass}",
    creates => '/etc/intelmq/api/api-session.sqlite',
  }

  file { '/etc/intelmq/api/api-session.sqlite':
    ensure  => 'present',
    replace => 'no',
    owner   => 'intelmq',
    group   => 'www-data',
    mode    => '0660'
  }

  file { '/etc/intelmq/fody/fody-session.sqlite':
    ensure  => 'present',
    replace => 'no',
    owner   => 'intelmq',
    group   => 'www-data',
    mode    => '0660'
  }

  exec { 'Setup fody-api user':
    command => "sudo -u intelmq /opt/intelmq/venv/bin/fody-adduser --user ${api_user} --password ${api_pass}",
    unless  => "sqlite3 /etc/intelmq/fody/fody-session.sqlite \"SELECT username FROM user WHERE username ='${api_user}'\" | grep -q ${api_user}",
  }

  file {
    '/etc/intelmq/contactdb-serve.conf':
      ensure  => file,
      owner   => 'intelmq',
      group   => 'www-data',
      mode    => '0440',
      content => template('soc/intelmq/contactdb-serve.conf.erb'),
    ;
    '/etc/intelmq/eventdb-serve.conf':
      ensure  => file,
      owner   => 'intelmq',
      group   => 'www-data',
      mode    => '0440',
      content => template('soc/intelmq/eventdb-serve.conf.erb'),
    ;
    '/etc/intelmq/tickets-serve.conf':
      ensure  => file,
      owner   => 'intelmq',
      group   => 'www-data',
      mode    => '0440',
      content => template('soc/intelmq/tickets-serve.conf.erb'),
    ;
    '/etc/intelmq/intelmq-mailgen.conf':
      ensure  => file,
      owner   => 'intelmq',
      group   => 'www-data',
      mode    => '0440',
      content => template('soc/intelmq/intelmq-mailgen.conf.erb'),
    ;

  }

  file { '/etc/systemd/system/intelmq-api.service':
    ensure  => file,
    content => file('soc/intelmq/intelmq-api.service'),
    notify  => [Class['sunet::systemd_reload'], Service['intelmq-api.service'],],
  }

  file { '/etc/systemd/system/intelmq-api.socket':
    ensure  => file,
    content => file('soc/intelmq/intelmq-api.socket'),
    notify  => [Class['sunet::systemd_reload'], Service['intelmq-api.socket'],],
  }

  file { '/opt/intelmq/etc/runtime.yaml':
    ensure  => 'present',
    replace => 'no',
    owner   => 'intelmq',
    group   => 'www-data',
    mode    => '0660',
  }

  file { '/opt/intelmq/etc/runtime.yaml.bak':
    ensure  => 'present',
    replace => 'no',
    owner   => 'www-data',
    group   => 'www-data',
    mode    => '0660',
    content => '',
  }

  file { '/opt/intelmq/etc/manager':
    ensure => directory,
    owner  => 'www-data',
    group  => 'www-data',
    mode   => '0775',
  }

  service { 'intelmq-api.service':
    ensure     => running,
    name       => 'intelmq-api.service',
    enable     => true,
    hasrestart => true,
  }

  service { 'intelmq-api.socket':
    ensure     => running,
    name       => 'intelmq-api.socket',
    enable     => true,
    hasrestart => true,
  }

  exec { 'Disable default apache conf':
    command => 'a2dissite 000-default',
    onlyif  => 'test -f /etc/apache2/sites-enabled/000-default.conf',
    notify  => Service['apache2'],
  }

  exec { 'Enable intelmq apache conf':
    command => 'a2ensite intelmq-vhost',
    creates => '/etc/apache2/sites-enabled/intelmq-vhost.conf',
    notify  => Service['apache2'],
  }

  sunet::nftables::allow { 'allow_http':
    from => any,
    port => 80,
  }

  sunet::nftables::allow { 'allow_https':
    from => any,
    port => 443,
  }
}