Exemple #1
0
def initialize_ufw():
    """Initialize the UFW firewall

    Ensure critical ports have explicit allows

    :return: None
    """

    if not config('enable-firewall'):
        log("Firewall has been administratively disabled", "DEBUG")
        return

    # this charm will monitor exclusively the ports used, using 'allow' as
    # default policy enables sharing the machine with other services
    ufw.default_policy('allow', 'incoming')
    ufw.default_policy('allow', 'outgoing')
    ufw.default_policy('allow', 'routed')
    # Rsync manages its own ACLs
    ufw.service('rsync', 'open')
    # Guarantee SSH access
    ufw.service('ssh', 'open')
    # Enable
    ufw.enable(soft_fail=config('allow-ufw-ip6-softfail'))

    # Allow GRE traffic
    add_ufw_gre_rule(os.path.join(UFW_DIR, 'before.rules'))
    ufw.reload()
Exemple #2
0
    def test_with_ipv6(self, modprobe, check_output, isdir, is_enabled, log):
        def c(*args, **kwargs):
            if args[0] == ['lsmod']:
                return LSMOD_IP6
            else:
                return 'Firewall is active and enabled on system startup\n'

        check_output.side_effect = c
        is_enabled.return_value = False
        isdir.return_value = True
        ufw.enable()
Exemple #3
0
    def test_no_ipv6(self, check_output, call, isdir, log, is_enabled):
        check_output.return_value = ('Firewall is active and enabled '
                                     'on system startup\n')
        isdir.return_value = False
        call.return_value = 0
        is_enabled.return_value = False
        ufw.enable()

        call.assert_called_with(['sed', '-i', 's/IPV6=.*/IPV6=no/g',
                                 '/etc/default/ufw'])
        log.assert_any_call('IPv6 support in ufw disabled', level='INFO')
def initialize_ufw():
    """Initialize the UFW firewall

    Ensure critical ports have explicit allows

    :return: None
    """
    # this charm will monitor exclusively the ports used, using 'allow' as
    # default policy enables sharing the machine with other services
    ufw.default_policy('allow', 'incoming')
    # Rsync manages its own ACLs
    ufw.service('rsync', 'open')
    # Guarantee SSH access
    ufw.service('ssh', 'open')
    # Enable
    ufw.enable(soft_fail=config('allow-ufw-ip6-softfail'))
Exemple #5
0
    def test_enable_fail(self, modprobe, check_output, log):
        msg = 'neneene\n'
        check_output.return_value = msg
        self.assertFalse(ufw.enable())

        check_output.assert_any_call(['ufw', 'enable'],
                                     universal_newlines=True,
                                     env={'LANG': 'en_US',
                                          'PATH': os.environ['PATH']})
        log.assert_any_call(msg, level='DEBUG')
        log.assert_any_call("ufw couldn't be enabled", level='WARN')
Exemple #6
0
    def test_enable_ok(self, modprobe, check_output, log):
        msg = 'Firewall is active and enabled on system startup\n'
        check_output.return_value = msg
        self.assertTrue(ufw.enable())

        check_output.assert_any_call(['ufw', 'enable'],
                                     universal_newlines=True,
                                     env={'LANG': 'en_US',
                                          'PATH': os.environ['PATH']})
        log.assert_any_call(msg, level='DEBUG')
        log.assert_any_call('ufw enabled', level='INFO')
Exemple #7
0
    def test_no_ip6_tables(self, modprobe, check_output, call, isdir, log,
                           is_enabled):
        def c(*args, **kwargs):
            if args[0] == ['lsmod']:
                return LSMOD_NO_IP6
            elif args[0] == ['modprobe', 'ip6_tables']:
                return ""
            else:
                return 'Firewall is active and enabled on system startup\n'

        check_output.side_effect = c
        isdir.return_value = True
        call.return_value = 0

        is_enabled.return_value = False
        self.assertTrue(ufw.enable())
Exemple #8
0
    def test_no_ip6_tables_fail_to_load_soft_fail(self, check_output, call,
                                                  is_module_loaded, modprobe,
                                                  isdir, log, is_enabled):
        is_module_loaded.return_value = False

        def c(m):
            raise subprocess.CalledProcessError(1, ['modprobe', 'ip6_tables'],
                                                "fail to load ip6_tables")

        modprobe.side_effect = c
        isdir.return_value = True
        call.return_value = 0
        check_output.return_value = ("Firewall is active and enabled on "
                                     "system startup\n")
        is_enabled.return_value = False
        self.assertTrue(ufw.enable(soft_fail=True))
        call.assert_called_with(
            ['sed', '-i', 's/IPV6=.*/IPV6=no/g', '/etc/default/ufw'])
        log.assert_any_call('IPv6 support in ufw disabled', level='INFO')
Exemple #9
0
def configure_firewall():
    '''Configure firewall rules using ufw.

    This is primarily to block access to the replication and JMX ports,
    as juju's default port access controls are not strict enough and
    allow access to the entire environment.
    '''
    config = hookenv.config()
    ufw.enable(soft_fail=True)

    # Enable SSH from anywhere, relying on Juju and external firewalls
    # to control access.
    ufw.service('ssh', 'open')
    ufw.service('nrpe', 'open')  # Also NRPE for nagios checks.

    # Clients need client access. These protocols are configured to
    # require authentication.
    client_keys = ['native_transport_port', 'rpc_port']
    client_ports = [config[key] for key in client_keys]

    # Peers need replication access. This protocols does not
    # require authentication, so firewall it from other nodes.
    peer_ports = [config['storage_port'], config['ssl_storage_port']]

    # Enable client access from anywhere. Juju and external firewalls
    # can still restrict this further of course (ie. 'juju expose').
    for key in client_keys:
        if config.changed(key) and config.previous(key) is not None:
            # First close old ports. We use this order in the unlikely case
            # someone is trying to swap the native and Thrift ports.
            ufw.service(config.previous(key), 'close')
    for port in client_ports:
        # Then open or close the configured ports.
        ufw.service(port, 'open')

    desired_rules = set()  # ufw.grant_access/remove_access commands.

    # Rules for peers
    for relinfo in hookenv.relations_of_type('cluster'):
        if relinfo['private-address']:
            for port in peer_ports:
                desired_rules.add((relinfo['private-address'], 'any', port))
    # Rules for admin connections. We allow database-admin relations access
    # to the cluster communication ports so that tools like sstableloader
    # can run.
    for relinfo in hookenv.relations_of_type('database-admin'):
        if relinfo['private-address']:
            for port in peer_ports:
                desired_rules.add((relinfo['private-address'], 'any', port))

    previous_rules = set(tuple(rule) for rule in config.get('ufw_rules', []))

    # Close any rules previously opened that are no longer desired.
    for rule in sorted(list(previous_rules - desired_rules)):
        ufw.revoke_access(*rule)

    # Open all the desired rules.
    for rule in sorted(list(desired_rules)):
        ufw.grant_access(*rule)

    # Store our rules for next time. Note that this is inherantly racy -
    # this value is only persisted if the hook exits cleanly. If the
    # hook fails, then someone changes port configuration or IP
    # addresses change, then the failed hook retried, we can lose track
    # of previously granted rules and they will never be revoked. It is
    # impossible to remove this race entirely, so we stick with this
    # simple approach.
    config['ufw_rules'] = list(desired_rules)  # A list because JSON.
def configure_firewall():
    '''Configure firewall rules using ufw.

    This is primarily to block access to the replication and JMX ports,
    as juju's default port access controls are not strict enough and
    allow access to the entire environment.
    '''
    config = hookenv.config()
    ufw.enable(soft_fail=True)

    # Enable SSH from anywhere, relying on Juju and external firewalls
    # to control access.
    ufw.service('ssh', 'open')
    ufw.service('nrpe', 'open')  # Also NRPE for nagios checks.

    # Clients need client access. These protocols are configured to
    # require authentication.
    client_keys = ['native_transport_port', 'rpc_port']
    client_ports = [config[key] for key in client_keys]

    # Peers need replication access. This protocols does not
    # require authentication, so firewall it from other nodes.
    peer_ports = [config['storage_port'], config['ssl_storage_port']]

    # Enable client access from anywhere. Juju and external firewalls
    # can still restrict this further of course (ie. 'juju expose').
    for key in client_keys:
        if config.changed(key) and config.previous(key) is not None:
            # First close old ports. We use this order in the unlikely case
            # someone is trying to swap the native and Thrift ports.
            ufw.service(config.previous(key), 'close')
    for port in client_ports:
        # Then open or close the configured ports.
        ufw.service(port, 'open')

    desired_rules = set()  # ufw.grant_access/remove_access commands.

    # Rules for peers
    for relinfo in hookenv.relations_of_type('cluster'):
        if relinfo['private-address']:
            for port in peer_ports:
                desired_rules.add((relinfo['private-address'], 'any', port))
    # Rules for admin connections. We allow database-admin relations access
    # to the cluster communication ports so that tools like sstableloader
    # can run.
    for relinfo in hookenv.relations_of_type('database-admin'):
        if relinfo['private-address']:
            for port in peer_ports:
                desired_rules.add((relinfo['private-address'], 'any', port))

    previous_rules = set(tuple(rule) for rule in config.get('ufw_rules', []))

    # Close any rules previously opened that are no longer desired.
    for rule in sorted(list(previous_rules - desired_rules)):
        ufw.revoke_access(*rule)

    # Open all the desired rules.
    for rule in sorted(list(desired_rules)):
        ufw.grant_access(*rule)

    # Store our rules for next time. Note that this is inherantly racy -
    # this value is only persisted if the hook exits cleanly. If the
    # hook fails, then someone changes port configuration or IP
    # addresses change, then the failed hook retried, we can lose track
    # of previously granted rules and they will never be revoked. It is
    # impossible to remove this race entirely, so we stick with this
    # simple approach.
    config['ufw_rules'] = list(desired_rules)  # A list because JSON.