class oci::controller_iptables(
  $api_use_ipv6 = false,
  $vip_ipaddr = undef,
  $vip6_ipaddr = undef,
  $vip_netmask = undef,
  $vip6_netmask = undef,
  $api_disable_rate_limit = undef,
  $api_iptables_rate_limit = undef,
  $api_rate_limit_whitelist = undef,
  $no_api_rate_limit_networks = [],

  $api_rate_limit_whitelist2 = undef,
  $net_whitelist2 = undef,
  $net_whitelist = undef,

  $whitelist_all_ports = undef,

  $all_sql_allowed_ips = [],
  $rabbit_allowed_ips  = [],
){
  $whitelist_all_ports.each |Integer $index, String $value| {
    $val1 = sprintf("%03i", $index+80)
    firewall { "${val1} Allow ${value} to access everything":
      proto       => tcp,
      action      => accept,
      source      => "${value}",
    }
  }

  $all_sql_allowed_ips.each |Integer $index, String $value| {
    $val1 = $index+100
    firewall { "${val1} Allow ${value} to access MySQL VIP":
      proto       => tcp,
      action      => accept,
      source      => "${value}",
      dport       => [3306, 4567],
    }
  }

  $rabbit_allowed_ips.each |Integer $index, String $value| {
    $val1 = $index+200
    firewall { "${val1} Allow ${value} to access rabbit":
      proto       => tcp,
      action      => accept,
      source      => "${value}",
      dport       => [4369, 5671, 5672, 15671, 25672],
    }
  }

  if $api_disable_rate_limit {
    firewall { "791 rate limit to ${api_iptables_rate_limit} queries/s marked new":
      ensure          => absent,
      chain           => 'INPUT',
      dport           => 443,
      proto           => tcp,
      connlimit_above => $api_iptables_rate_limit,
      connlimit_mask  => 24,
      jump            => 'LOGDROP',
    }

    firewall { "791 rate limit to ${api_iptables_rate_limit} queries/s marked new (v6)":
      ensure          => absent,
      chain           => 'INPUT',
      dport           => 443,
      proto           => tcp,
      connlimit_above => $api_iptables_rate_limit,
      connlimit_mask  => 24,
      jump            => 'LOGDROP6',
      provider        => 'ip6tables',
    }
  } else {
    $net_whitelist.each |Integer $index, String $value| {
      $val1 = $index+700
      firewall { "${val1} Allow ${value} to access OpenStack API without rate limit":
        proto       => tcp,
        action      => accept,
        source      => "${value}",
        dport       => [443],
      }
    }
    if $api_use_ipv6 {
      firewall { "704 Allow ${vip6_ipaddr} to access OpenStack API without rate limit":
        proto       => tcp,
        action      => accept,
        source      => "${vip6_ipaddr}",
        dport       => [443],
        provider    => 'ip6tables',
      }
    }
  }

  # Add an IPv4 LOGDROP chain
  firewallchain { 'LOGDROP:filter:IPv4':
    ensure  => present,
  }->
  # LOG dropped packets
  firewall { '901 LOG rule for dropped packets':
    chain       => 'LOGDROP',
    proto       => tcp,
    jump        => 'LOG',
    log_level   => '6',
    log_prefix  => 'IPTables API rate limit:',
    limit       => '1/sec',
  }->
  # DROP packets
  firewall { "902 Deny access to OpenStack API":
    chain       => 'LOGDROP',
    proto       => tcp,
    action      => drop,
    dport       => '443',
  }->
  firewall { "903 Deny access to OpenStack HTTP":
    chain       => 'LOGDROP',
    proto       => tcp,
    action      => drop,
    dport       => '443',
  }->
  firewall { "904 Deny access to MySQL":
    chain       => 'LOGDROP',
    proto       => tcp,
    action      => drop,
    dport       => [3306, 4567],
  }->
  firewall { "905 Deny access to OpenStack FRR":
    chain       => 'LOGDROP',
    proto       => tcp,
    action      => drop,
    dport       => '179',
  }->
  firewall { "906 Deny access to OpenStack rabbit":
    chain       => 'LOGDROP',
    proto       => tcp,
    action      => drop,
    dport       => [4369, 5671, 5672, 15671, 25672],
  }->
  firewall { "907 Deny access to SMTP":
    chain       => 'LOGDROP',
    proto       => tcp,
    action      => drop,
    dport       => [25],
  }->
  firewall { "908 Deny access to RPCBIND":
    chain       => 'LOGDROP',
    proto       => tcp,
    action      => drop,
    dport       => [111],
  }->
  firewall { "909 Deny access to RPCBIND UDP":
    chain       => 'LOGDROP',
    proto       => udp,
    action      => reject,
    dport       => [111],
  }->
  firewall { "910 Deny access to xinetd":
    chain       => 'LOGDROP',
    proto       => tcp,
    action      => drop,
    dport       => [9200],
  }->
  firewall { "911 Deny access to Horizon without proxy":
    chain       => 'LOGDROP',
    proto       => tcp,
    action      => drop,
    dport       => [7080, 7443],
  }->
  firewall { "911 Deny access to half 1 of OpenStack services without proxy":
    chain       => 'LOGDROP',
    proto       => tcp,
    action      => drop,
    dport       => [5000, 6083, 8000, 8004, 8042, 8774, 8775, 8778,],
  }->
  firewall { "912 Deny access to half 2 of OpenStack services without proxy":
    chain       => 'LOGDROP',
    proto       => tcp,
    action      => drop,
    dport       => [8786, 9001, 9311, 9292, 9293, 9511, 9696, 9876, 10050],
  }

  # Add an IPv6 LOGDROP chain
  if $api_use_ipv6 {
    # Add an IPv6 LOGDROP chain
    firewallchain { 'LOGDROP6:filter:IPv6':
      ensure  => present,
    }->
    # LOG dropped packets
    firewall { '901 LOG rule for dropped packets (v6)':
      chain       => 'LOGDROP6',
      proto       => tcp,
      jump        => 'LOG',
      log_level   => '6',
      log_prefix  => 'IPTables API rate limit:',
      limit       => '1/sec',
      provider    => 'ip6tables',
    }->
    # DROP packets
    firewall { "902 Deny access to OpenStack API (v6)":
      chain       => 'LOGDROP6',
      proto       => tcp,
      action      => drop,
      dport       => '443',
      provider    => 'ip6tables',
    }->
    firewall { "903 Deny access to OpenStack HTTP (v6)":
      chain       => 'LOGDROP6',
      proto       => tcp,
      action      => drop,
      dport       => '443',
      provider    => 'ip6tables',
    }->
    firewall { "904 Deny access to MySQL (v6)":
      chain       => 'LOGDROP6',
      proto       => tcp,
      action      => drop,
      dport       => [3306, 4567],
      provider    => 'ip6tables',
    }->
    firewall { "905 Deny access to OpenStack FRR (v6)":
      chain       => 'LOGDROP6',
      proto       => tcp,
      action      => drop,
      dport       => '179',
      provider    => 'ip6tables',
    }->
    firewall { "906 Deny access to OpenStack rabbit (v6)":
      chain       => 'LOGDROP6',
      proto       => tcp,
      action      => drop,
      dport       => [4369, 5671, 5672, 15671, 25672],
      provider    => 'ip6tables',
    }->
    firewall { "907 Deny access to SMTP (v6)":
      chain       => 'LOGDROP6',
      proto       => tcp,
      action      => drop,
      dport       => [25],
      provider    => 'ip6tables',
    }->
    firewall { "908 Deny access to RPCBIND (v6)":
      chain       => 'LOGDROP6',
      proto       => tcp,
      action      => drop,
      dport       => [111],
      provider    => 'ip6tables',
    }->
    firewall { "909 Deny access to RPCBIND UDP (v6)":
      chain       => 'LOGDROP6',
      proto       => udp,
      action      => reject,
      dport       => [111],
      provider    => 'ip6tables',
    }->
    firewall { "910 Deny access to xinetd (v6)":
      chain       => 'LOGDROP6',
      proto       => tcp,
      action      => drop,
      dport       => [9200],
      provider    => 'ip6tables',
    }->
    firewall { "911 Deny access to Horizon without proxy (v6)":
      chain       => 'LOGDROP6',
      proto       => tcp,
      action      => drop,
      dport       => [7080, 7443],
      provider    => 'ip6tables',
    }->
    firewall { "911 Deny access to half 1 of OpenStack services without proxy (v6)":
      chain       => 'LOGDROP6',
      proto       => tcp,
      action      => drop,
      dport       => [5000, 6083, 8000, 8004, 8042, 8774, 8775, 8778,],
      provider    => 'ip6tables',
    }->
    firewall { "912 Deny access to half 2 of OpenStack services without proxy (v6)":
      chain       => 'LOGDROP6',
      proto       => tcp,
      action      => drop,
      dport       => [8786, 9001, 9311, 9292, 9293, 9511, 9696, 9876, 10050],
      provider    => 'ip6tables',
    }
  }

  # Define firewall rules v4
  firewall { '801 deny public access to http':
    proto       => tcp,
    jump        => 'LOGDROP',
    destination => "${vip_ipaddr}/${vip_netmask}",
    dport       => 80,
  }->
  firewall { '802 deny public access to mysql':
    proto       => tcp,
    jump        => 'LOGDROP',
    destination => "${vip_ipaddr}/${vip_netmask}",
    dport       => [3306, 4567],
  }->
  firewall { '803 deny public access to bgpd':
    proto       => tcp,
    jump        => 'LOGDROP',
    destination => "${vip_ipaddr}/${vip_netmask}",
    dport       => 179,
  }->
  firewall { '804 deny public access to epmd and rabbitmq':
    proto       => tcp,
    jump        => 'LOGDROP',
    destination => "${vip_ipaddr}/${vip_netmask}",
    dport       => [4369, 5671, 5672, 15671, 25672],
  }->
  firewall { '805 Jump to LOGDROP for SMTP':
    proto       => tcp,
    jump        => 'LOGDROP',
    destination => "${vip_ipaddr}/${vip_netmask}",
    dport       => '25',
  }->
  firewall { '806 deny public access to rpcbind':
    proto       => tcp,
    jump        => 'LOGDROP',
    destination => "${vip_ipaddr}/${vip_netmask}",
    dport       => [111],
  }->
  firewall { '807 deny public access to xinetd':
    proto       => tcp,
    jump        => 'LOGDROP',
    destination => "${vip_ipaddr}/${vip_netmask}",
    dport       => [9200],
  }->
  firewall { '808 deny public access to horizon without haproxy':
    proto       => tcp,
    jump        => 'LOGDROP',
    destination => "${vip_ipaddr}/${vip_netmask}",
    dport       => [7080, 7443],
  }->
  firewall { '809 deny public access to octavia API without haproxy':
    proto       => tcp,
    action      => drop,
    destination => "${vip_ipaddr}/${vip_netmask}",
    dport       => [9876],
  }->
  firewall { '810 deny public access to magnum API without haproxy':
    proto       => tcp,
    jump        => 'LOGDROP',
    destination => "${vip_ipaddr}/${vip_netmask}",
    dport       => [9511],
  }->
  firewall { '811 deny public access to designate API without haproxy':
    proto       => tcp,
    jump        => 'LOGDROP',
    destination => "${vip_ipaddr}/${vip_netmask}",
    dport       => [9001],
  }->
  firewall { '812 deny public access to keystone API without haproxy':
    proto       => tcp,
    jump        => 'LOGDROP',
    destination => "${vip_ipaddr}/${vip_netmask}",
    dport       => [5000],
  }->
  firewall { '813 deny public access to SMTP':
    proto       => tcp,
    jump        => 'LOGDROP',
    destination => "${vip_ipaddr}/${vip_netmask}",
    dport       => [25],
  }->
  firewall { '814 deny public access to Heat CFN API without haproxy':
    proto       => tcp,
    jump        => 'LOGDROP',
    destination => "${vip_ipaddr}/${vip_netmask}",
    dport       => [8000],
  }->
  firewall { '815 deny public access to Aodh API without haproxy':
    proto       => tcp,
    jump        => 'LOGDROP',
    destination => "${vip_ipaddr}/${vip_netmask}",
    dport       => [8042],
  }->
  firewall { '816 deny public access to manila API without haproxy':
    proto       => tcp,
    jump        => 'LOGDROP',
    destination => "${vip_ipaddr}/${vip_netmask}",
    dport       => [8786],
  }->
  firewall { '817 deny public access to Ironic API without haproxy':
    proto       => tcp,
    jump        => 'LOGDROP',
    destination => "${vip_ipaddr}/${vip_netmask}",
    dport       => [6385],
  }->
  firewall { '818 deny public access to Ironic Inspector API without haproxy':
    proto       => tcp,
    jump        => 'LOGDROP',
    destination => "${vip_ipaddr}/${vip_netmask}",
    dport       => [5050],
  }

  # Define firewall rules v6
  if $api_use_ipv6 {
    firewall { '801 deny public access to http (v6)':
      proto       => tcp,
      jump        => 'LOGDROP6',
      destination => "${vip6_ipaddr}/${vip6_netmask}",
      dport       => 80,
      provider    => 'ip6tables',
    }->
    firewall { '802 deny public access to mysql (v6)':
      proto       => tcp,
      jump        => 'LOGDROP6',
      destination => "${vip6_ipaddr}/${vip6_netmask}",
      dport       => [3306, 4567],
      provider    => 'ip6tables',
    }->
    firewall { '803 deny public access to bgpd (v6)':
      proto       => tcp,
      jump        => 'LOGDROP6',
      destination => "${vip6_ipaddr}/${vip6_netmask}",
      dport       => 179,
      provider    => 'ip6tables',
    }->
    firewall { '804 deny public access to epmd and rabbitmq (v6)':
      proto       => tcp,
      jump        => 'LOGDROP6',
      destination => "${vip6_ipaddr}/${vip6_netmask}",
      dport       => [4369, 5671, 5672, 15671, 25672],
      provider    => 'ip6tables',
    }->
    firewall { '805 Jump to LOGDROP for SMTP (v6)':
      proto       => tcp,
      jump        => 'LOGDROP6',
      destination => "${vip6_ipaddr}/${vip6_netmask}",
      dport       => '25',
      provider    => 'ip6tables',
    }->
    firewall { '806 deny public access to rpcbind (v6)':
      proto       => tcp,
      jump        => 'LOGDROP6',
      destination => "${vip6_ipaddr}/${vip6_netmask}",
      dport       => [111],
      provider    => 'ip6tables',
    }->
    firewall { '807 deny public access to xinetd (v6)':
      proto       => tcp,
      jump        => 'LOGDROP6',
      destination => "${vip6_ipaddr}/${vip6_netmask}",
      dport       => [9200],
      provider    => 'ip6tables',
    }->
    firewall { '808 deny public access to horizon without haproxy (v6)':
      proto       => tcp,
      jump        => 'LOGDROP6',
      destination => "${vip6_ipaddr}/${vip6_netmask}",
      dport       => [7080, 7443],
      provider    => 'ip6tables',
    }->
    firewall { '809 deny public access to octavia API without haproxy (v6)':
      proto       => tcp,
      action      => drop,
      destination => "${vip6_ipaddr}/${vip6_netmask}",
      dport       => [9876],
      provider    => 'ip6tables',
    }->
    firewall { '810 deny public access to magnum API without haproxy (v6)':
      proto       => tcp,
      jump        => 'LOGDROP6',
      destination => "${vip6_ipaddr}/${vip6_netmask}",
      dport       => [9511],
      provider    => 'ip6tables',
    }->
    firewall { '811 deny public access to designate API without haproxy (v6)':
      proto       => tcp,
      jump        => 'LOGDROP6',
      destination => "${vip6_ipaddr}/${vip6_netmask}",
      dport       => [9001],
      provider    => 'ip6tables',
    }->
    firewall { '812 deny public access to keystone API without haproxy (v6)':
      proto       => tcp,
      jump        => 'LOGDROP6',
      destination => "${vip6_ipaddr}/${vip6_netmask}",
      dport       => [5000],
      provider    => 'ip6tables',
    }->
    firewall { '813 deny public access to SMTP (v6)':
      proto       => tcp,
      jump        => 'LOGDROP6',
      destination => "${vip6_ipaddr}/${vip6_netmask}",
      dport       => [25],
      provider    => 'ip6tables',
    }->
    firewall { '814 deny public access to Heat CFN API without haproxy (v6)':
      proto       => tcp,
      jump        => 'LOGDROP6',
      destination => "${vip6_ipaddr}/${vip6_netmask}",
      dport       => [8000],
      provider    => 'ip6tables',
    }->
    firewall { '815 deny public access to Aodh API without haproxy (v6)':
      proto       => tcp,
      jump        => 'LOGDROP6',
      destination => "${vip6_ipaddr}/${vip6_netmask}",
      dport       => [8042],
      provider    => 'ip6tables',
    }->
    firewall { '816 deny public access to manila API without haproxy (v6)':
      proto       => tcp,
      jump        => 'LOGDROP6',
      destination => "${vip6_ipaddr}/${vip6_netmask}",
      dport       => [8786],
      provider    => 'ip6tables',
    }->
    firewall { '817 deny public access to Ironic API without haproxy (v6)':
      proto       => tcp,
      jump        => 'LOGDROP6',
      destination => "${vip6_ipaddr}/${vip6_netmask}",
      dport       => [6385],
      provider    => 'ip6tables',
    }->
    firewall { '818 deny public access to Ironic Inspector API without haproxy (v6)':
      proto       => tcp,
      jump        => 'LOGDROP6',
      destination => "${vip6_ipaddr}/${vip6_netmask}",
      dport       => [5050],
      provider    => 'ip6tables',
    }
  }
}
