Code Monkey home page Code Monkey logo

puppet-opnsense's Introduction

ci codecov Puppet Forge Puppet Forge Downloads

opnsense

Table of Contents

Module description

The opnsense module configures OPNsense firewalls.

It allows administrators to manage an OPNsense firewall directly via the sysutils/puppet-agent opnsense plugin and/or manage multiple firewalls from a bastion host running a puppet-agent with opn-cli installed.

The main target of module is to enable GitOps for your network security policies. Developers could submit pull request for new firewall rules and loadbalancer configurations and the network or ops team could review it and deploy it to a pre production environment for testing and verification. If everything passes, you could deploy it to production.

You can automate the following with the module:

  • plugins
  • firewall aliases
  • firewall rules
  • haproxy servers
  • haproxy backends
  • haproxy frontends
  • prometheus nodeexporter
  • syslog destinations
  • static routes

Setup

OPNsense firewall

If you want to manage your firewall directly with a puppet-agent running on the device.

Requirements

OPNsense plugins:

Install requirements

Menu->Firmware->Plugins

Install plugin: sysutils/puppet-agent

Bastion host

If you want a bastion hosts running a puppet-agent which could manage multiple firewalls via https API calls.

Requirements

Install requirements

$packages = [
    'python3',
    'python3-pip',
]
$pip_packages = [
    'opn-cli',
]
package { $packages:
    ensure => present,
}
-> package { $pip_packages:
    ensure   => latest,
    provider => 'pip3',
}

Access to the OPNsense api

If you want to manage an OPNsense firewall, you need to supply credentials and connection information for the device.

To create an api_key and api_secret see: https://docs.opnsense.org/development/how-tos/api.html#creating-keys.

If you want to use ssl verification (recommended):`

To download the default self-signed cert, open the OPNsense web gui and go to System->Trust->Certificates. Search for the name: "Web GUI SSL certificate" and press the "export user cert" button.

If you use a ca signed certificate, go to System->Trust->Authorities and press the "export CA cert" button to download the ca.

Save the cert or ca and make sure the puppet agent is able to read it.

Usage

Install and enable opnsense

include opnsense

Configure OPNsense firewall(s)

You can manage multiple opnsense firewalls with this module.

In the following example a single OPNsense firewall running a puppet agent is manged which allows clients to export configuration via exported resources (manage_resources => true):

# node: opnsense.example.com

class { 'opnsense':
  manage_resources => true,
  devices => {
    'opnsense.example.com' => {
      'url'        => 'https://127.0.0.1/api',
      'api_key'    => 'your_api_key',
      'api_secret' => 'your_api_secret',
      'ssl_verify' => true,
      'timeout'    => 60,
      'ca'         => '~/.opn-cli/ca.pem',
      'plugins'    => {
        'os-helloworld' => {}
      },
      nodeexporter => {
        enabled        => true,
        listen_address => '192.168.1.1',
        listen_port    => '9200',
        cpu            => false,
        exec           => false,
        filesystem     => false,
        loadavg        => false,
        meminfo        => false,
        netdev         => false,
        time           => false,
        devstat        => false,
        interrupts     => true,
        ntp            => true,
        zfs            => true,
      },
      "ensure"      => "present"      
    }
  },
  firewall => {
    aliases => {
      'my_http_ports_local' => {
        'devices'     => ['opnsense.example.com'],
        'type'        => 'port',
        'content'     => ['80', '443'],
        'description' => 'example local http ports',
        'enabled'     => true,
        'ensure'      => present
      },
    },
    rules => {
      'allow all from lan' => {
        'devices'   => ['opnsense.example.com'],
        'sequence'  => '1',
        'action'    => 'pass',
        'interface' => ['lan']
      }
    }
  },
  syslog => {
    destinations => {
      'syslogger 1' => {
        devices     => ['opnsense.example.com'],
        enabled     => true,
        transport   => 'tcp4',
        program     => 'ntp,ntpdate',
        level       => ['crit', 'alert', 'emerg'],
        facility    => ['ntp'],
        hostname    => 'syslog.example.com',
        certificate => '',
        port        => '10514',
        rfc5424     => true,
        ensure      => present,
      },
    },
  },
  route => {
    static => {
      'static route 1' => {
        devices    => ['opnsense.example.com'],
        network    => '10.0.0.98/24',
        gateway    => 'WAN_DHCP',
        disabled   => false,
        ensure     => 'present',
      },
    },
  },
  haproxy => {
    servers => {
      "server1" => {
        "devices"     => ["opnsense.example.com"],
        "description" => "first local server",
        "address"     => "127.0.0.1",
        "port"        => "8091",
      },
      "server2" => {
        "devices"   => ["opnsense.example.com"],
        "description" => "second local server",
        "address"     => "127.0.0.1",
        "port"        => "8092",
      },
    },
    backends => {
      "localhost_backend" => {
        "devices"        => ["opnsense.example.com"],
        "description"    => "local server backend",
        "mode"           => "http",
        "linked_servers" => ["server1", "server2"],
      }
    },
    frontends => {
      "localhost_frontend" => {
        "devices"           => ["opnsense.example.com"],
        "description"       => "local frontend",
        "bind"              => "127.0.0.1:8090",
        "ssl_enabled"       => false,
        "default_backend"   => "localhost_backend",
      }
    },
  },
}

Configure a client to export firewall aliases and rules

This feature use exported resources. You need to enable catalog storage and searching (storeconfigs) on your primary puppet server.

Here the client (client1.example.com) is exporting it´s security configuration to the firewall (opnsense.example.com) defined above:

# node: client1.example.com

class { 'opnsense::client::firewall':
  aliases => {
    'client1_example_com' => {
      'devices'     => ['opnsense.example.com'],
      'type'        => 'host',
      'content'     => ['client1.example.com'],
      'description' => 'client.example.com alias',
      'enabled'     => true,
      'ensure'      => present
    },
  },
  rules => {
    'allow https from lan to client1.example.com' => {
      'devices'          => ['opnsense.example.com'],
      'sequence'         => '100',
      'action'           => 'pass',
      'interface'        => ['lan'],
      'protocol'         => 'TCP',
      'destination_net'  => 'client1_example_com',
      'destination_port' => 'https',
      'ensure'           => present
    },
  }
}

Configure a client to export haproxy server, backends and frontends

This feature use exported resources. You need to enable catalog storage and searching (storeconfigs) on your primary puppet server.

Here the client (client1.example.com) is exporting it´s haproxy configuration to the firewall (opnsense.example.com) defined above:

# node: client1.example.com

class { 'opnsense::client::haproxy':
  servers  => {
    "client1.example.com" => {
      "devices"     => ["opnsense.example.com"],
      "description" => "client test server",
      "address"     => "client1.example.com",
      "port"        => "443",
      "enabled"     => ture,
    },
  },
  backends => {
    "web_backend" => {
      "devices"        => ["opnsense.example.com"],
      "description"    => "test backend",
      "mode"           => "http",
      "linked_servers" => ["server1", "server2"],
      "enabled"        => false,
    }
  },
  frontends => {
    "web_frontend" => {
      "devices"           => ["opnsense.example.com"],
      "description"       => "test frontend",
      "bind"              => "127.0.0.1:9000",
      "ssl_enabled"       => false,
      "default_backend"   => "localhost_backend",
      "enabled"           => true,
    }
  },
}

Dealing with self-signed certificates

When connecting to the OPNsense API, this module will tell opn-cli to use the system-wide installed CA certificates to verify the SSL connection. However, this will only work when using a valid certificate for the OPNsense WebUI.

If the OPNsense WebUI still uses the pre-installed self-signed certificate, then it is possible to use the OPNsense CA certificate for SSL verification:

class { 'opnsense':
  use_system_ca => false,
  ca_file       => '/root/.opn-cli/ca.pem',
  ca_content    => '-----BEGIN CERTIFICATE-----
AAAAAABBBBBBBBBCCCCCCCCCCDDDDDDDDDDDEEEEEEEEEEEFFFFFFFFFGGGGGGGG
-----END CERTIFICATE-----'
}

The OPNsense CA certificate can be downloaded from System: Trust: Authorities on the OPNsense firewall.

More examples

You find more examples in the examples folder.

Reference

Types and providers are documented in REFERENCE.md.

Limitations

For an extensive list of supported operating systems, see metadata.json

CI/CD

CI/CD is done via Github Actions.

Development

You need to install the following requirements to setup the local development environment:

Create the local development environment

scripts/create_test_env 

Running unit tests

Unit testing uses pdk

scripts/unit_tests

Running acceptance tests

Acceptance testing uses puppet litmus.

scripts/acceptance_tests

Teardown

scripts/remove_test_env

Release module to Puppet Forge

Prepare

First prepare the release with:

./scripts/release_prep

This will set the version in metadata.json, create REFERENCE.md and CHANGELOG.md.

Commit and push

Then commit the changes and push them to the repository.

configure github actions secrets

https://github.com/andeman/puppet-opnsense/settings/secrets/actions

Ensure that the following secrets are set in the github repository:

  • FORGE_API_KEY (your puppet forge api key)

Contributing

Please use the GitHub issues functionality to report any bugs or requests for new features. Feel free to fork and submit pull requests for potential contributions.

All contributions must pass all existing tests, new features should provide additional unit/acceptance tests.

Release Notes

See Changelog.

puppet-opnsense's People

Contributors

andeman avatar fraenki avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

Forkers

markt-de

puppet-opnsense's Issues

I would like to sponsor your project

Hello @andeman! I was looking for an opnsense automation tool found your repo, it looks really good!

Are you interested in extending its functionality? I would like to sponsor you.

The features I'm most interested in are:

  • Manage OpenVPN server, client and client specific overrides
  • Manage opnsense users (Create user, update password, manage group membership)
  • Manage IPsec tunnels
  • Manage static routes
  • Manage syslog and prometheus node exporter settings

Should not perform a "filter reload" for every single alias

I've noticed that when adding multiple new aliases in the same Puppet run...

Notice: /Stage[main]/Opnsense/Opnsense_firewall_alias[alias1]/ensure: defined 'ensure' as 'present'
Notice: opnsense_firewall_alias[alias1]: Creating: Finished in 3.91 seconds
Notice: /Stage[main]/Opnsense/Opnsense_firewall_alias[alias2]/ensure: defined 'ensure' as 'present'
Notice: opnsense_firewall_alias[alias2]: Creating: Finished in 4.16 seconds
Notice: /Stage[main]/Opnsense/Opnsense_firewall_alias[alias3]/ensure: defined 'ensure' as 'present'
Notice: opnsense_firewall_alias[alias3]: Creating: Finished in 4.47 seconds
...
Notice: Applied catalog in 1684.30 seconds

...the provider will trigger a reload of the firewall for every single alias:

root@opnsense:~ # grep 'Reloading filter' /var/log/configd/latest.log | wc -l
     332

This lead to a partial service disruption on this device.

Of course, there won't be too many cases where so many aliases are created or updated at the same time. But maybe there is a way to "tune" the provider to only perform the "filter reload" once during every Puppet run.

This would benefit the stability of the firewall when using this provider. Besides that it would probably also speedup the process.

Alias provider reports false errors after first error

This is just nitpicking... :)

If the creation of an alias fails for some reason...

Notice: /Stage[main]/Opnsense/Opnsense_firewall_alias[test_alias]/ensure: defined 'ensure' as 'present'
Error: opnsense_firewall_alias[test_alias]: Creating: Failed after 1.74 seconds: Execution of 'opn-cli -c /root/.puppet-opnsense/opnsense-config.yaml firewall alias create test_alias -t network -d opnsense api manager - test -C test_alias1,test_alias2 -p  -u 0.0 --no-counters --enabled' returned 1: Error: {'result': 'failed', 'validations': {'alias.content': ['Entry "test_alias1" is not a network.', 'Entry "test_alias2" is not a network.']}}

...then for ALL other alias creations (in the same Puppet run) an error is reported too:

Error: /Stage[main]/Opnsense/Opnsense_firewall_alias[test_alias3]: Could not evaluate: Execution encountered an error
Notice: /Stage[main]/Opnsense/Opnsense_firewall_alias[test_alias3]/ensure: defined 'ensure' as 'present'
Notice: opnsense_firewall_alias[test_alias3]: Creating: Finished in 4.85 seconds

Error: /Stage[main]/Opnsense/Opnsense_firewall_alias[test_alias4]: Could not evaluate: Execution encountered an error
Notice: /Stage[main]/Opnsense/Opnsense_firewall_alias[test_alias4]/ensure: defined 'ensure' as 'present'
Notice: opnsense_firewall_alias[net_dc1_dmz1]: Creating: test_alias4 in 4.70 seconds

The creation of these aliases actually succeeds, so the error is pretty misleading. Maybe there is a way to suppress this error somehow.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.