106 lines
3.8 KiB
Python
106 lines
3.8 KiB
Python
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
# not use this file except in compliance with the License. You may obtain
|
|
# a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing permissions and limitations
|
|
# under the License.
|
|
|
|
from subprocess import call
|
|
from subprocess import PIPE
|
|
from subprocess import Popen
|
|
import sys
|
|
|
|
from oslo_log._i18n import _LE
|
|
from oslo_log._i18n import _LI
|
|
from oslo_log import log as logging
|
|
from oslo_serialization import jsonutils
|
|
|
|
LOG = logging.getLogger(__name__)
|
|
|
|
|
|
class ConfigureIPtables(object):
|
|
|
|
def __init__(self, json_blob):
|
|
ps = Popen(["sysctl", "net.ipv4.ip_forward"], stdout=PIPE)
|
|
output = ps.communicate()[0]
|
|
if "0" in output:
|
|
LOG.info(_LI("Enabling IP forwarding ..."))
|
|
call(["sysctl", "-w", "net.ipv4.ip_forward=1"])
|
|
else:
|
|
LOG.info(_LI("IP forwarding already enabled"))
|
|
try:
|
|
self.rules_json = jsonutils.loads(json_blob)
|
|
except ValueError:
|
|
sys.exit('Given json_blob is not a valid json')
|
|
|
|
def update_chain(self):
|
|
ps = Popen(["iptables", "-L"], stdout=PIPE)
|
|
output = ps.communicate()[0]
|
|
|
|
# check if chain is present if not create new chain
|
|
if "testchain" not in output:
|
|
LOG.info(_LI("Creating new chain ..."))
|
|
call(["iptables", "-F"])
|
|
call(["iptables", "-N", "testchain"])
|
|
call(
|
|
["iptables", "-t", "filter",
|
|
"-A", "FORWARD", "-j", "testchain"])
|
|
call(["iptables", "-A", "FORWARD", "-j", "DROP"])
|
|
|
|
# flush chain of existing rules
|
|
call(["iptables", "-F", "testchain"])
|
|
# return
|
|
|
|
# Update chain with new rules
|
|
LOG.info(_LI("Updating chain with new rules ..."))
|
|
count = 0
|
|
for rule in self.rules_json.get('rules'):
|
|
LOG.info(_LI("adding rule %(count)d"), {'count': count})
|
|
try:
|
|
action_values = ["LOG", "ACCEPT"]
|
|
action = rule['action'].upper()
|
|
if action not in action_values:
|
|
sys.exit(
|
|
"Action %s is not valid action! Please enter "
|
|
"valid action (LOG or ACCEPT)" % (action))
|
|
service = rule['service'].split('/')
|
|
except KeyError as e:
|
|
sys.exit('KeyError: Rule does not have key %s' % (e))
|
|
|
|
if len(service) > 1:
|
|
ps = Popen(["iptables", "-A", "testchain", "-p", service[
|
|
0], "--dport", service[1], "-j", action],
|
|
stdout=PIPE)
|
|
else:
|
|
ps = Popen(
|
|
["iptables", "-A", "testchain", "-p", service[0],
|
|
"-j", action], stdout=PIPE)
|
|
output = ps.communicate()[0]
|
|
if output:
|
|
LOG.error(_LE("Unable to add rule to chain due to: %(msg)s"),
|
|
{'msg': output})
|
|
count = count + 1
|
|
ps = Popen(["iptables", "-A", "testchain", "-m", "state", "--state",
|
|
"ESTABLISHED,RELATED", "-j", "ACCEPT"], stdout=PIPE)
|
|
output = ps.communicate()[0]
|
|
if output:
|
|
LOG.error(_LE("Unable to add rule to chain due to: %(output)s"),
|
|
{'output': output})
|
|
|
|
|
|
def main():
|
|
if len(sys.argv) < 2:
|
|
sys.exit('Usage: %s json-blob' % sys.argv[0])
|
|
else:
|
|
json_blob = sys.argv[1]
|
|
test = ConfigureIPtables(json_blob)
|
|
test.update_chain()
|
|
|
|
if __name__ == "__main__":
|
|
main()
|