├── .dockerignore ├── .gitignore ├── README.md ├── app.py ├── configs └── .keep ├── dockerfile ├── docs ├── Makefile ├── image │ └── main.png ├── make.bat └── source │ ├── _static │ ├── Other_configs.png │ ├── Policy.png │ ├── chpoint │ │ ├── ch_policy.png │ │ └── configs.png │ ├── palo │ │ └── config_correction.png │ └── srx │ │ ├── Netconf.png │ │ └── SRX_XML_Format.png │ ├── chpoint.rst │ ├── conf.py │ ├── final.rst │ ├── index.rst │ ├── installation.rst │ ├── palo.rst │ └── srx.rst ├── exported └── .keep ├── logs └── .keep ├── requirements.txt └── resources ├── __init__.py ├── dst_vendor ├── __init__.py ├── dst_asa.py ├── dst_chpoint.py ├── dst_forti.py ├── dst_palo.py └── dst_srx.py ├── ip_address_converter └── netmask_convereter.py ├── parser.py ├── protocols └── nc_conn.py ├── src_vendor ├── chpoint │ ├── __init__.py │ ├── chpoint_config_parser.py │ └── chpoint_policy_parser.py ├── palo │ ├── palo_config_coverter.py │ └── palo_policy_convert.py └── srx │ ├── __init__.py │ ├── srx_config_converter.py │ └── srx_policy_convert.py └── web ├── static ├── files.css ├── script.js └── style.css └── templates ├── exported_vendor.html ├── files.html └── home.html /.dockerignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | *.log 3 | __pycache__ 4 | test.py 5 | .gitignore 6 | .dockerignore -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | share/python-wheels/ 24 | *.egg-info/ 25 | .installed.cfg 26 | *.egg 27 | MANIFEST 28 | 29 | # PyInstaller 30 | # Usually these files are written by a python script from a template 31 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 32 | *.manifest 33 | *.spec 34 | 35 | # Installer logs 36 | pip-log.txt 37 | pip-delete-this-directory.txt 38 | 39 | # Unit test / coverage reports 40 | htmlcov/ 41 | .tox/ 42 | .nox/ 43 | .coverage 44 | .coverage.* 45 | .cache 46 | nosetests.xml 47 | coverage.xml 48 | *.cover 49 | *.py,cover 50 | .hypothesis/ 51 | .pytest_cache/ 52 | cover/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | .pybuilder/ 76 | target/ 77 | 78 | # Jupyter Notebook 79 | .ipynb_checkpoints 80 | 81 | # IPython 82 | profile_default/ 83 | ipython_config.py 84 | 85 | # pyenv 86 | # For a library or package, you might want to ignore these files since the code is 87 | # intended to run in multiple environments; otherwise, check them in: 88 | # .python-version 89 | 90 | # pipenv 91 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 92 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 93 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 94 | # install all needed dependencies. 95 | #Pipfile.lock 96 | 97 | # poetry 98 | # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. 99 | # This is especially recommended for binary packages to ensure reproducibility, and is more 100 | # commonly ignored for libraries. 101 | # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control 102 | #poetry.lock 103 | 104 | # pdm 105 | # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. 106 | #pdm.lock 107 | # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it 108 | # in version control. 109 | # https://pdm.fming.dev/#use-with-ide 110 | .pdm.toml 111 | 112 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm 113 | __pypackages__/ 114 | 115 | # Celery stuff 116 | celerybeat-schedule 117 | celerybeat.pid 118 | 119 | # SageMath parsed files 120 | *.sage.py 121 | 122 | # Environments 123 | .env 124 | env/ 125 | venv/ 126 | ENV/ 127 | env.bak/ 128 | venv.bak/ 129 | .venv* 130 | 131 | # Spyder project settings 132 | .spyderproject 133 | .spyproject 134 | 135 | # Rope project settings 136 | .ropeproject 137 | 138 | # mkdocs documentation 139 | /site 140 | 141 | # mypy 142 | .mypy_cache/ 143 | .dmypy.json 144 | dmypy.json 145 | 146 | # Pyre type checker 147 | .pyre/ 148 | 149 | # pytype static type analyzer 150 | .pytype/ 151 | 152 | # Cython debug symbols 153 | cython_debug/ 154 | 155 | # PyCharm 156 | # JetBrains specific template is maintained in a separate JetBrains.gitignore that can 157 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore 158 | # and can be added to the global gitignore or merged into this file. For a more nuclear 159 | # option (not recommended) you can uncomment the following to ignore the entire idea folder. 160 | #.idea/ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Firewall Migration Tool 2 | 3 | fwmig tool helps you to migrate from one existing firewall to another one with simple copy/past steps. 4 | 5 | - It supports most well-known vendors. 6 | - This Tool is based on Flask and JS to provide Web UI for conversion of firewall objects and policies. 7 | - There is no online dependencies after you run the app. 8 | - Dockerfile is available for container implementaions. 9 | - Logging for troubleshoot is implemented. 10 | - Tested on python 3.8 and 3.9, and 3.10 11 | 12 | ---- 13 | ## Run the code: 14 | 15 | ```sh 16 | python3.10 -m venv venv 17 | source venv/bin/activate 18 | pip install -r requirements.txt 19 | python app.py 20 | ``` 21 | Or use Docker: 22 | 23 | ```sh 24 | docker build -t fwmig . 25 | docker run -p 8080:5000 --name=fwmig -d -v $(pwd)/logs:/code/logs/ -ti fwmig:latest 26 | ``` 27 | 28 | ----- 29 | 30 | ## Supported Matrix: 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 |
Source VendorDestination Vendor
Juniper SRXFortigateCisco ASACheckpointPalo Alto
Juniper SRXN/AYesYesYesYes
FortigateNoN/ANoNoNo
Cisco ASANoNoN/ANoNo
CheckpointYesYesYesN/AYes
Palo AltoYesYesYesYesN/A
86 | 87 |
88 | 89 | ![fwmig](https://github.com/VahidTa/firewall_migration_tool/blob/main/docs/image/main.png?raw=true) 90 | 91 | # Documentation 92 | 93 | Firewall Migration Tool (fwmig) documentation lives at [fwmig.readthedocs.io](https://fwmig.readthedocs.io/en/latest/?) 94 | 95 | 96 | # Feedback 97 | 98 | Please share your experience with me about Firewall Migration Tool through [@tavajjohi](https://twitter.com/tavajjohi) on twitter. 99 | -------------------------------------------------------------------------------- /app.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from flask import Flask, flash, request, redirect, url_for, send_from_directory 4 | from flask.templating import render_template 5 | from werkzeug.utils import secure_filename 6 | 7 | from resources.parser import main_parser 8 | from resources import app_logger 9 | 10 | logger = app_logger() 11 | 12 | UPLOAD_FOLDER = 'configs/' 13 | ALLOWED_EXTENSIONS = {'txt', 'log', 'csv'} 14 | 15 | app = Flask(__name__, template_folder='resources/web/templates', static_folder='resources/web/static') 16 | app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER 17 | app.secret_key = b'_5#y2L"F4Q8z\n\xec]/' 18 | 19 | 20 | def allowed_file(filename): 21 | return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS 22 | 23 | @app.route('/', methods=['GET', 'POST']) 24 | def main(): 25 | if request.method == 'POST': 26 | # check if the post request has the file part 27 | src_vendor = request.form.get('src_vendor') 28 | if request.form.get('type') == 'netconf': 29 | if src_vendor == 'srx': 30 | from resources.protocols.nc_conn import NcMGR 31 | acts = request.form.getlist('acts') 32 | action = request.form.get('action') 33 | nc_client = NcMGR() 34 | host = request.form.get('host') 35 | username = request.form.get('username') 36 | password = request.form.get('password') 37 | port = request.form.get('port') 38 | dst_vendor = request.form.get('dst_vendor') 39 | logger.info(f'Netconf started for {host} on port {port} ...') 40 | cfg = nc_client.junos_nc_conn(action, host, username, password, port, 'junos') 41 | if not cfg: 42 | flash('Authentication error') 43 | return redirect(request.url) 44 | elif cfg == 'other': 45 | flash('Connection problem, please check network and info.') 46 | return redirect(request.url) 47 | else: 48 | logger.info('Conversion started ...') 49 | main_parser(action, cfg, src_vendor, dst_vendor, acts) 50 | logger.info(f'Creating files and links for {dst_vendor}') 51 | return redirect(url_for('get_file', dirname=str(dst_vendor))) 52 | else: 53 | flash(f'Not supported for {src_vendor}!') 54 | return redirect(request.url) 55 | file = request.files['file'] 56 | # if user does not select file, browser also 57 | # submit an empty part without filename 58 | if file.filename == '': 59 | flash('No selected file') 60 | return redirect(request.url) 61 | if file and allowed_file(file.filename): 62 | filename = secure_filename(file.filename) 63 | file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename)) 64 | if src_vendor not in ['asa', 'forti']: 65 | acts = request.form.getlist('acts') 66 | action = request.form.get('action') 67 | if action == 'config' and not acts: 68 | flash('Please select one checkbox!') 69 | return redirect(request.url) 70 | 71 | dst_vendor = request.form.get('dst_vendor') 72 | 73 | logger.info('Conversion started ...') 74 | result = main_parser(action, filename, src_vendor, dst_vendor, acts) 75 | 76 | if not result: 77 | flash('Something is wrong! check again') 78 | return redirect(request.url) 79 | if result == 'no': 80 | flash('The operation is not supported for this vendor!') 81 | return redirect(request.url) 82 | logger.info(f'Creating files and links for {dst_vendor}') 83 | logger.info(50*'=') 84 | return redirect(url_for('get_file', dirname=str(dst_vendor))) 85 | else: 86 | flash('This conversion not supported yet.') 87 | return redirect(request.url) 88 | 89 | else: 90 | flash('File not supported. (txt, log, csv)') 91 | return redirect(request.url) 92 | return render_template('home.html') 93 | 94 | @app.route('/exported//') # this is a job for GET, not POST 95 | def get_file(dirname): 96 | dloads_dir = f'exported/{dirname}' 97 | dloads = os.listdir(dloads_dir) 98 | dloads_src = [f'/exported/{dirname}/{format(i)}' for i in dloads] 99 | return render_template('files.html', dloads=dloads, dloads_src=dloads_src, dirname=dirname) 100 | 101 | 102 | @app.route('/exported//') 103 | def download(dirname, filename): 104 | return send_from_directory(f'exported/{dirname}', filename) 105 | 106 | 107 | @app.route('/exported/') 108 | def exported(): 109 | dloads_dir = 'exported/' 110 | dloads = os.listdir(dloads_dir) 111 | dloads_src = [f'/exported/{format(i)}' for i in dloads] 112 | return render_template('exported_vendor.html', dloads=dloads, dloads_src=dloads_src) 113 | 114 | 115 | if __name__ == "__main__": 116 | app.run(host='0.0.0.0') -------------------------------------------------------------------------------- /configs/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VahidTa/firewall_migration_tool/06f0ff0d0714f9563fe21b83d69711e66a8f0b1c/configs/.keep -------------------------------------------------------------------------------- /dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.10-bullseye 2 | 3 | WORKDIR /code 4 | 5 | COPY requirements.txt requirements.txt 6 | 7 | RUN apt-get -y update 8 | RUN pip install -r requirements.txt 9 | 10 | EXPOSE 5000 11 | 12 | COPY . . 13 | 14 | CMD python app.py -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line, and also 5 | # from the environment for the first two. 6 | SPHINXOPTS ?= 7 | SPHINXBUILD ?= sphinx-build 8 | SOURCEDIR = source 9 | BUILDDIR = build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Catch-all target: route all unknown targets to Sphinx using the new 18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 19 | %: Makefile 20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 21 | -------------------------------------------------------------------------------- /docs/image/main.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VahidTa/firewall_migration_tool/06f0ff0d0714f9563fe21b83d69711e66a8f0b1c/docs/image/main.png -------------------------------------------------------------------------------- /docs/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | pushd %~dp0 4 | 5 | REM Command file for Sphinx documentation 6 | 7 | if "%SPHINXBUILD%" == "" ( 8 | set SPHINXBUILD=sphinx-build 9 | ) 10 | set SOURCEDIR=source 11 | set BUILDDIR=build 12 | 13 | if "%1" == "" goto help 14 | 15 | %SPHINXBUILD% >NUL 2>NUL 16 | if errorlevel 9009 ( 17 | echo. 18 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 19 | echo.installed, then set the SPHINXBUILD environment variable to point 20 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 21 | echo.may add the Sphinx directory to PATH. 22 | echo. 23 | echo.If you don't have Sphinx installed, grab it from 24 | echo.http://sphinx-doc.org/ 25 | exit /b 1 26 | ) 27 | 28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 29 | goto end 30 | 31 | :help 32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 33 | 34 | :end 35 | popd 36 | -------------------------------------------------------------------------------- /docs/source/_static/Other_configs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VahidTa/firewall_migration_tool/06f0ff0d0714f9563fe21b83d69711e66a8f0b1c/docs/source/_static/Other_configs.png -------------------------------------------------------------------------------- /docs/source/_static/Policy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VahidTa/firewall_migration_tool/06f0ff0d0714f9563fe21b83d69711e66a8f0b1c/docs/source/_static/Policy.png -------------------------------------------------------------------------------- /docs/source/_static/chpoint/ch_policy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VahidTa/firewall_migration_tool/06f0ff0d0714f9563fe21b83d69711e66a8f0b1c/docs/source/_static/chpoint/ch_policy.png -------------------------------------------------------------------------------- /docs/source/_static/chpoint/configs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VahidTa/firewall_migration_tool/06f0ff0d0714f9563fe21b83d69711e66a8f0b1c/docs/source/_static/chpoint/configs.png -------------------------------------------------------------------------------- /docs/source/_static/palo/config_correction.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VahidTa/firewall_migration_tool/06f0ff0d0714f9563fe21b83d69711e66a8f0b1c/docs/source/_static/palo/config_correction.png -------------------------------------------------------------------------------- /docs/source/_static/srx/Netconf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VahidTa/firewall_migration_tool/06f0ff0d0714f9563fe21b83d69711e66a8f0b1c/docs/source/_static/srx/Netconf.png -------------------------------------------------------------------------------- /docs/source/_static/srx/SRX_XML_Format.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VahidTa/firewall_migration_tool/06f0ff0d0714f9563fe21b83d69711e66a8f0b1c/docs/source/_static/srx/SRX_XML_Format.png -------------------------------------------------------------------------------- /docs/source/chpoint.rst: -------------------------------------------------------------------------------- 1 | Checkpoint conversion 2 | ###################### 3 | 4 | It is tested on SmartConsle **CSV** policy and address object exporting format. 5 | Because of insufficient information on csv output, Service part does not have protocol part to understand wheter it is TCP/UDP and Service conversion not implemented yet. 6 | 7 | | 8 | 9 | File Base 10 | ********* 11 | 12 | Here are steps to provide correct output file from Check Point: 13 | 14 | **Policy**: 15 | 16 | - Login to SmartConsole, go to **Security Policies**. 17 | - Click on actions and select export. 18 | 19 | .. image:: _static/chpoint/ch_policy.png 20 | :align: center 21 | 22 | | 23 | 24 | **Objects**: 25 | 26 | - Login to SmartConsole, on the right panel find 3 dots on toolbar and click. 27 | - Select Networks and Hosts section from left selection part 28 | - Click actions and select export. 29 | 30 | .. image:: _static/chpoint/configs.png 31 | :align: center 32 | 33 | | 34 | 35 | Final step 36 | ********** 37 | 38 | Got to `After conversion `_ -------------------------------------------------------------------------------- /docs/source/conf.py: -------------------------------------------------------------------------------- 1 | # Configuration file for the Sphinx documentation builder. 2 | # 3 | # This file only contains a selection of the most common options. For a full 4 | # list see the documentation: 5 | # https://www.sphinx-doc.org/en/master/usage/configuration.html 6 | 7 | # -- Path setup -------------------------------------------------------------- 8 | 9 | # If extensions (or modules to document with autodoc) are in another directory, 10 | # add these directories to sys.path here. If the directory is relative to the 11 | # documentation root, use os.path.abspath to make it absolute, like shown here. 12 | # 13 | # import os 14 | # import sys 15 | # sys.path.insert(0, os.path.abspath('.')) 16 | 17 | 18 | # -- Project information ----------------------------------------------------- 19 | 20 | project = 'Firewall Migration Tool (fwmig)' 21 | copyright = '2021, Vahid Tavajjohi' 22 | author = 'Vahid Tavajjohi' 23 | 24 | # The full version, including alpha/beta/rc tags 25 | release = '0.2.0' 26 | 27 | 28 | # -- General configuration --------------------------------------------------- 29 | 30 | # Add any Sphinx extension module names here, as strings. They can be 31 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 32 | # ones. 33 | extensions = [ 34 | ] 35 | 36 | # Add any paths that contain templates here, relative to this directory. 37 | templates_path = ['_templates'] 38 | 39 | # List of patterns, relative to source directory, that match files and 40 | # directories to ignore when looking for source files. 41 | # This pattern also affects html_static_path and html_extra_path. 42 | exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] 43 | 44 | 45 | # -- Options for HTML output ------------------------------------------------- 46 | 47 | # The theme to use for HTML and HTML Help pages. See the documentation for 48 | # a list of builtin themes. 49 | # 50 | html_theme = 'alabaster' 51 | 52 | # Add any paths that contain custom static files (such as style sheets) here, 53 | # relative to this directory. They are copied after the builtin static files, 54 | # so a file named "default.css" will overwrite the builtin "default.css". 55 | html_static_path = ['_static'] 56 | 57 | html_theme_options = { 58 | "show_powered_by": False, 59 | "github_user": "vahidta", 60 | "github_repo": "firewall_migration_tool", 61 | "github_banner": True, 62 | "github_button": True, 63 | "github_type": "star", 64 | "show_related": False, 65 | } -------------------------------------------------------------------------------- /docs/source/final.rst: -------------------------------------------------------------------------------- 1 | After Conversion 2 | ################ 3 | 4 | After successfull conversion of source config, based on destination vendor you were selected you must follow reagarding steps. 5 | 6 | 7 | Cisco ASA 8 | ********* 9 | 10 | Cisco ASA policy works only for global policy. 11 | 12 | - Login to the device 13 | - Enter to global config mode 14 | - You must copy/paste configuration first and then configuration. 15 | - Each .txt file contains related configuration. 16 | 17 | 18 | Checkpoint 19 | ********** 20 | 21 | * It supports from release R80 and later. 22 | * API must be enabled. Please refer to Checkpoint documentation. 23 | * Network and Service Objects will force to replace if there is existing object with the same name. 24 | * For objects, login to the device and go to expert mode 25 | * Use these steps: 26 | 27 | .. code-block:: bash 28 | :linenos: 29 | 30 | mgmt_cli add host --batch network_objects_host.csv #Host objects 31 | mgmt_cli add network --batch network_objects_network.csv #Network with subnets 32 | mgmt_cli add group --batch network_groups.csv #Object group objects 33 | mgmt_cli set group --batch network_group_members.csv #Object group members 34 | mgmt_cli add service-group --batch service_groups.csv #Service group members 35 | mgmt_cli set service-group --batch service_groups_members.csv #Service group members 36 | 37 | * For Policies: 38 | * Set ``username`` and ``password`` inside the ``policies.txt``. 39 | * Login to the decvice and go to expert mode. Then paste output policy. 40 | * This method is using `sid` for authentication. 41 | * Because of the platform limitations, you must paste rules by grouping 3 or 4 rules for each copy. 42 | * Please note that about per 100 lines there is a ``publish`` action. 43 | 44 | 45 | Fortigate 46 | ********* 47 | 48 | Because of the platform limitations, Policy names will be support upto 35 charachters. So, if there is a policy name with more than 35 charachter length will be convert to only first 35 characters. 49 | 50 | * Login to the device 51 | * You must copy/paste configuration first and then configuration. 52 | 53 | Palo Alto 54 | ********* 55 | 56 | May not allow more than 30 inputs in one copy/paste. So partition the output in clipboard. 57 | 58 | * Login to the device 59 | * Enter to config mode 60 | * You must copy/paste configuration first and then configuration 61 | * Commit the configuration at the end 62 | 63 | 64 | Juniper SRX 65 | *********** 66 | 67 | For SRX, output file is "set" based. 68 | 69 | * Login to the device 70 | * Enter to config mode 71 | * You must copy/paste configuration first and then configuration 72 | * Commit the configuration at the end -------------------------------------------------------------------------------- /docs/source/index.rst: -------------------------------------------------------------------------------- 1 | Firewall Migration Tool (fwmig) 2 | ############################### 3 | 4 | fwmig tool helps you to migrate from one existing firewall to another one with simple copy/past steps. 5 | 6 | - It supports most well-known vendors. 7 | - This tool is based on Flask and JS to provide Web UI for conversion of firewall objects and policies. 8 | - There is no online dependencies after you run the app. 9 | - Dockerfile is available for container implementaions. 10 | - Logging for troubleshoot is implemented. 11 | - Tested on python 3.8, 3.9, and 3.10 12 | 13 | | 14 | 15 | Supported Matrix table: 16 | 17 | ================ ====== ========== ========== =========== =========== 18 | Source Vendor Destination Vendor 19 | ---------------- -------------------------------------------------------- 20 | .. SRX Fortigate Cisco ASA Checkpoint Palo Alto 21 | ================ ====== ========== ========== =========== =========== 22 | **SRX** N/A Yes Yes Yes Yes 23 | ---------------- ------ ---------- ---------- ----------- ----------- 24 | **Fortigate** No N/A No No No 25 | ---------------- ------ ---------- ---------- ----------- ----------- 26 | **Cisco ASA** No No N/A No No 27 | ---------------- ------ ---------- ---------- ----------- ----------- 28 | **Checkpoint** Yes Yes Yes N/A Yes 29 | ---------------- ------ ---------- ---------- ----------- ----------- 30 | **Palo Alto** Yes Yes Yes Yes N/A 31 | ================ ====== ========== ========== =========== =========== 32 | 33 | | 34 | 35 | Any predefined services that are not included in fwmig or are not defined on the destination vendor (e.g., Palo Alto) will remain the same as on the source platform. For example, if there is an object called ``junos-who`` that this tool cannot convert, you will find an ``Error`` in the description of the policy it uses. 36 | 37 | | 38 | 39 | .. warning:: 40 | This tool **does not** support Zone, Interfaces, and NAT conversion yet. Please note that you **must** create interfaces and Zones before using policy output. 41 | 42 | Getting Start: 43 | ============== 44 | .. toctree:: 45 | :maxdepth: 2 46 | 47 | installation 48 | srx 49 | palo 50 | chpoint 51 | final 52 | 53 | 54 | Feedback 55 | ******** 56 | 57 | Please share your experience with me about Firewall Migration Tool through `@tavajjohi `_ on twitter. -------------------------------------------------------------------------------- /docs/source/installation.rst: -------------------------------------------------------------------------------- 1 | Installation 2 | ############ 3 | 4 | Here are two option for using firewall migration tool: 5 | 6 | Bash 7 | **** 8 | 9 | - Make a clone from the `Firewall Migration Tool `_ link 10 | - Use ``pip install -r requirements.txt`` to install required packages 11 | - Start the app using ``python3 app.py`` 12 | - Connect to ``http://localhost:5000`` on browser. 13 | 14 | Container 15 | ********* 16 | 17 | - Make a clone from the `Firewall Migration Tool `_ link 18 | - To build and run container use: 19 | 20 | .. code-block:: bash 21 | :linenos: 22 | 23 | docker build -t fwmig:latest 24 | docker run -p 8080:5000 --name=fwmig -d -v $(pwd)/logs:/code/logs/ -ti fwmig:latest 25 | 26 | - Connect to ``http://127.0.0.1:8080`` on browser. -------------------------------------------------------------------------------- /docs/source/palo.rst: -------------------------------------------------------------------------------- 1 | Palo Alto conversion 2 | #################### 3 | 4 | As Palo alto supports XML output format, here is the steps for getting config and policy fro PAN-OS: 5 | 6 | File Base 7 | ********* 8 | 9 | **Policy and Config** 10 | 11 | - Login to PAN-OS through cli or console. 12 | - Execute ``set cli config-output-format xml`` command 13 | - Enter to config mode with ``configure`` 14 | - Execute ``show`` command 15 | - Copy the output into file 16 | - Supported file extensions is .log and .txt 17 | - Because of Palo Alto XML formatted that is not standard, it is important to wrap up entire output with and tag. 18 | 19 | .. image:: _static/palo/config_correction.png 20 | :align: center 21 | 22 | | 23 | 24 | Final step 25 | ********** 26 | 27 | Got to `After conversion `_ -------------------------------------------------------------------------------- /docs/source/srx.rst: -------------------------------------------------------------------------------- 1 | SRX conversion 2 | ############## 3 | 4 | It is tested on Junos 12.x , 15.x , 18.x and it uses XML format to convert configs and policies. 5 | Policies can not be extracted from SRX configuration output, because it does not provide **rule order** . So, from ``show security policies`` it can find out rule/policy orders. 6 | 7 | Features 8 | ======== 9 | - Address books (Global and Policy based) 10 | - Name 11 | - Description 12 | 13 | - Services and Service Groups 14 | - Name 15 | - Description 16 | - Source and Destination port 17 | - Session timeout 18 | 19 | | 20 | 21 | File Base 22 | ********* 23 | 24 | If you want to get the SRX device configs and policies manually, you need to select ``file`` under ``Type of conversion`` section and you can follow below steps to do conversion without any error. 25 | 26 | SRX config and policy 27 | ===================== 28 | 29 | Here are steps to provide correct output file from SRX devices: 30 | 31 | **Policy**: 32 | 33 | - Login to SRX and execute :code:`show security policies | display xml` 34 | - Copy the output into file 35 | - Make sure only XML output is in the file 36 | - Supported file extensions is .log and .txt 37 | 38 | **General configs**: 39 | 40 | - Login to SRX and execute :code:`show configuration | display xml` 41 | - Copy the output into file 42 | - Make sure only XML output is in the file 43 | - Supported file extensions is .log and .txt 44 | 45 | 46 | For example if file starts or ends with some not xml lines please remove them. In below figure you can see first line is not xml formatted: 47 | 48 | .. image:: _static/srx/SRX_XML_Format.png 49 | :align: center 50 | 51 | It is important to note that after conversion steps, you must paste output files of configuration first. Because, policies uses network/service objects and if they are not available on destination device, policies will be failed. 52 | 53 | 54 | Using conversion 55 | ================ 56 | 57 | After `SRX Config and policy`_ steps, you can upload file through web UI. For policy conversion you should choose ``policy`` option under ``Action`` on web UI and upload policy XML formatted file to upload. However, if you choose ``other configs``, new options will be available for Address Books, Services and Service-groups to provide better result. You can see below figure for both options. 58 | 59 | .. image:: _static/Policy.png 60 | :width: 48 % 61 | .. image:: _static/Other_configs.png 62 | :width: 48 % 63 | 64 | 65 | | 66 | 67 | Netconf 68 | ******* 69 | 70 | You can use Netconf for conversion in fwmig. It will connect to the srx device and read configs or policies and then it will converts to destination vendor. You need to provide access for fwmig on Netconf port (TCP/22 or TCP/830) on SRX device. Below figure is example of Netconf conversion: 71 | 72 | .. image:: _static/srx/Netconf.png 73 | :align: center 74 | 75 | | 76 | 77 | Final step 78 | ********** 79 | 80 | Go to `After conversion `_ -------------------------------------------------------------------------------- /exported/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VahidTa/firewall_migration_tool/06f0ff0d0714f9563fe21b83d69711e66a8f0b1c/exported/.keep -------------------------------------------------------------------------------- /logs/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VahidTa/firewall_migration_tool/06f0ff0d0714f9563fe21b83d69711e66a8f0b1c/logs/.keep -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | Flask==2.2.5 2 | ncclient==0.6.9 3 | pandas==1.3.4 4 | paramiko==2.7.2 5 | requests==2.25.1 6 | xmltodict==0.12.0 7 | -------------------------------------------------------------------------------- /resources/__init__.py: -------------------------------------------------------------------------------- 1 | import logging 2 | 3 | from logging.handlers import RotatingFileHandler 4 | 5 | def app_logger(): 6 | 7 | log_date = '%Y-%m-%d %H:%M:%S' 8 | log_format = '%(asctime)s %(levelname)-8s [%(filename)s:%(lineno)d] %(message)s' 9 | handler = RotatingFileHandler('logs/app.log', maxBytes=100000, backupCount=1) 10 | formatter = logging.Formatter(log_format, log_date) 11 | handler.setFormatter(formatter) 12 | handler.suffix = f'%Y-%m-%d.log' 13 | handler.setLevel(logging.INFO) 14 | 15 | logger = logging.getLogger('fwmig') 16 | logger.setLevel(logging.INFO) 17 | logger.addHandler(handler) 18 | 19 | return logger 20 | -------------------------------------------------------------------------------- /resources/dst_vendor/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VahidTa/firewall_migration_tool/06f0ff0d0714f9563fe21b83d69711e66a8f0b1c/resources/dst_vendor/__init__.py -------------------------------------------------------------------------------- /resources/dst_vendor/dst_asa.py: -------------------------------------------------------------------------------- 1 | from resources.ip_address_converter.netmask_convereter import netmasker, nethost 2 | 3 | class ASA_DST: 4 | 5 | def service(*args): 6 | application_name = args[1] 7 | destination_port = args[2] 8 | source_port = args[3] 9 | application_protocol = args[4] 10 | application_desc = args[5] 11 | 12 | with open('exported/asa/service_objects.txt', 'a') as f: 13 | f.write(f'object service {application_name}\n') 14 | if destination_port: 15 | if '-' in destination_port: 16 | destination_port = destination_port.replace('-', ' ') 17 | f.write(f'service {application_protocol} destination range {destination_port}\n') 18 | else: 19 | f.write(f'service {application_protocol} destination eq {destination_port}\n') 20 | elif source_port: 21 | if '-' in source_port: 22 | source_port = source_port.replace('-', ' ') 23 | f.write(f'service {application_protocol} source range {source_port}\n') 24 | else: 25 | f.write(f'service {application_protocol} source eq {source_port}\n') 26 | if application_desc: 27 | f.write(f'description {application_desc} \n') 28 | f.write('exit\n\n') 29 | 30 | def service_set(*args): 31 | app_set_name = args[1] 32 | app_list = args[2] 33 | app_set_desc = args[3] 34 | 35 | with open('exported/asa/service_object_group.txt', 'a') as f: 36 | f.write(f'object-group service {app_set_name}\n') 37 | for object in app_list: 38 | if isinstance(object, (list)): 39 | if object[0] == 'icmp': 40 | f.write(f'service-object {object[0]} {object[1]}\n') 41 | else: 42 | f.write(f'service-object {object[0]} destination eq {object[1]}\n') 43 | else: 44 | f.write(f'service-object object {object} \n') 45 | if app_set_desc: 46 | f.write(f'description "{app_set_desc}" \n') 47 | f.write('exit\n\n') 48 | 49 | def address(*args): 50 | address_name = args[1] 51 | address_ip = args[2] 52 | address_desc = args[3] 53 | 54 | with open('exported/asa/object_network.txt', 'a') as f: 55 | if '-' in address_ip: 56 | start_ip = address_ip.split('-')[0].replace(' ', '') 57 | end_ip = address_ip.split('-')[1].replace(' ', '') 58 | address_netmask = f'range {start_ip} {end_ip}' 59 | elif '/32' in address_ip: 60 | address_netmask = 'host ' + nethost(address_ip) 61 | else: 62 | address_netmask = 'subnet ' + netmasker(address_ip) 63 | if '/' in address_name: 64 | address_name = address_name.replace('/', '-') 65 | f.write(f'object network {address_name}\n') 66 | if address_desc: 67 | f.write(f'description {address_desc}\n') 68 | f.write(f'{address_netmask}\n') 69 | f.write('exit\n\n') 70 | 71 | 72 | def address_set(*args): 73 | address_set_name = args[1] 74 | address_name_list = args[2] 75 | address_set_desc = args[3] 76 | 77 | with open('exported/asa/object_group_network.txt', 'a') as f: 78 | f.write(f'object-group network {address_set_name}\n') 79 | if address_set_desc: 80 | f.write(f'description {address_set_desc}\n') 81 | for address_name in address_name_list: 82 | f.write(f'network-object object {address_name}\n') 83 | f.write('exit\n\n') 84 | 85 | def policy(*args): 86 | """Not Implemented""" 87 | policy_name = args[1] 88 | source_zone = args[2] 89 | destination_zone = args[3] 90 | policy_src_address = args[4] 91 | policy_dst_address = args[5] 92 | policy_app = args[6] 93 | policy_log = args[7] 94 | policy_state = args[8] 95 | policy_action = args[9] 96 | policy_id = args[10] 97 | 98 | the_path = 'exported/asa/policies.txt' 99 | if policy_state != 'inactive': 100 | policy_state = '' 101 | if policy_log: 102 | policy_log = 'log' 103 | else: 104 | policy_log = '' 105 | if ' ' in policy_src_address: 106 | src_group_name = f'DM_INLINE_NETWORK_111{policy_id}' 107 | with open(the_path, 'a') as output: 108 | output.write(f'object-group network {src_group_name}\n') 109 | for src in policy_src_address.split(' '): 110 | output.write(f' network-object object {src}\n') 111 | output.write(' exit\n\n') 112 | policy_src_address = f'object-group {src_group_name}' 113 | else: 114 | policy_src_address = f'object {policy_src_address}' 115 | if ' ' in policy_dst_address: 116 | dst_group_name = f'DM_INLINE_NETWORK_222{policy_id}' 117 | with open(the_path, 'a') as output: 118 | output.write(f'object-group network {dst_group_name}\n') 119 | for dst in policy_dst_address.split(' '): 120 | output.write(f' network-object object {dst}\n') 121 | output.write(' exit\n\n') 122 | policy_dst_address = f'object-group {dst_group_name}' 123 | else: 124 | policy_dst_address = f'object {policy_dst_address}' 125 | 126 | if ' ' in policy_app: 127 | app_group_name = f'DM_INLINE_SERVICE_333{policy_id}' 128 | with open(the_path, 'a') as output: 129 | output.write(f'object-group service {app_group_name}\n') 130 | for dst in policy_app.split(' '): 131 | if isinstance(dst, (list)): 132 | if dst[1] == 'na': 133 | output.write(f' service-object {dst[0]}\n') 134 | else: 135 | dst = f'{dst[0]} destionation eq {dst[1]}' 136 | output.write(f' service-object {dst}\n') 137 | else: 138 | output.write(f' service-object object {dst}\n') 139 | policy_app = f'object-group {app_group_name}' 140 | elif isinstance(policy_app, (list)): 141 | app_group_name = f'DM_INLINE_SERVICE_333{policy_id}' 142 | with open(the_path, 'a') as output: 143 | output.write(f'object-group service {app_group_name}\n') 144 | for dst in policy_app: 145 | if isinstance(dst, (list)): 146 | if dst[1] == 'na': 147 | output.write(f' service-object {dst[0]}\n') 148 | else: 149 | dst = f'{dst[0]} destionation eq {dst[1]}' 150 | output.write(f' service-object {dst}\n') 151 | else: 152 | output.write(f' service-object object {dst}\n') 153 | policy_app = f'object-group {app_group_name}' 154 | 155 | if (isinstance(policy_app, (list)) == False) and ('DM_INLINE_SERVICE_' in policy_app) == False: 156 | policy_app = f'object {policy_app}' 157 | # if ('DM_INLINE_SERVICE_' in policy_app) == False: 158 | # policy_app = f'object {policy_app}' 159 | 160 | if isinstance(policy_app, (list)): 161 | with open('exported/asa/policies.txt', 'a') as output: 162 | output.write(f'access-list global_access line {policy_id} extended {policy_action} {policy_app[0]} {policy_src_address} {policy_dst_address} eq {policy_app[1]} {policy_log} {policy_state}\n\n') 163 | else: 164 | with open('exported/asa/policies.txt', 'a') as output: 165 | output.write(f'access-list global_access line {policy_id} extended {policy_action} {policy_app} {policy_src_address} {policy_dst_address} {policy_log} {policy_state}\n\n') 166 | 167 | 168 | 169 | -------------------------------------------------------------------------------- /resources/dst_vendor/dst_chpoint.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from resources.ip_address_converter.netmask_convereter import nethost, sub_mask 4 | 5 | 6 | class CHPoint_DST: 7 | 8 | def service(*args): 9 | application_name = args[1] 10 | destination_port = args[2] 11 | source_port = args[3] 12 | application_protocol = args[4] 13 | application_desc = args[5] 14 | app_session_ttl = args[6] 15 | 16 | the_path = f'exported/chpoint/service-{application_protocol}.csv' 17 | with open(the_path, 'a') as f: 18 | if os.path.getsize(the_path) == 0: 19 | f.write('name,port,source-port,session-timeout,set-if-exists,ignore-warnings,ignore-errors,comments\n') 20 | if application_desc and destination_port: 21 | f.write(f'{application_name},{destination_port},{source_port},{app_session_ttl},true,true,true,"{application_desc}"\n') 22 | elif destination_port: 23 | f.write(f'{application_name},{destination_port},{source_port},{app_session_ttl},true,true,true,\n') 24 | 25 | def service_set(*args): 26 | app_set_name = args[1] 27 | app_list = args[2] 28 | app_set_desc = args[3] 29 | 30 | the_path = 'exported/chpoint/service_groups.csv' 31 | with open(the_path, 'a') as f: 32 | if os.path.getsize(the_path) == 0: 33 | f.write('name,ignore-warnings,ignore-errors,comments\n') 34 | if app_set_desc: 35 | f.write(f'{app_set_name},true,true,"{app_set_desc}"\n') 36 | else: 37 | f.write(f'{app_set_name},true,true,\n') 38 | the_path = 'exported/chpoint/service_groups_members.csv' 39 | with open(the_path, 'a') as f: 40 | if os.path.getsize(the_path) == 0: 41 | f.write('name,members.add,ignore-warnings,ignore-errors\n') 42 | for object in app_list: 43 | if object[:1].isdigit(): 44 | object = 'custom_' + object 45 | f.write(f'{app_set_name},{object},true,true\n') 46 | 47 | def address(*args): 48 | address_name = args[1] 49 | address_ip = args[2] 50 | address_desc = args[3] 51 | 52 | if '/32' in address_ip: 53 | address_netmask = nethost(address_ip) 54 | the_path = 'exported/chpoint/network_objects_host.csv' 55 | with open(the_path, 'a') as f: 56 | if os.path.getsize(the_path) == 0: 57 | f.write(f'name,ip-address,set-if-exists,ignore-warnings,ignore-errors,comments\n') 58 | if address_desc: 59 | f.write(f'{address_name},{address_netmask},true,true,true,"{address_desc}"\n') 60 | else: 61 | f.write(f'{address_name},{address_netmask},true,true,true,\n') 62 | else: 63 | add_subnet = nethost(address_ip) 64 | add_mask = sub_mask(address_ip) 65 | the_path = 'exported/chpoint/network_objects_network.csv' 66 | with open(the_path, 'a') as f: 67 | if os.path.getsize(the_path) == 0: 68 | f.write(f'name,subnet,subnet-mask,set-if-exists,ignore-warnings,ignore-errors,comments\n') 69 | if address_desc: 70 | f.write(f'{address_name},{add_subnet},{add_mask},true,true,true,"{address_desc}"\n') 71 | else: 72 | f.write(f'{address_name},{add_subnet},{add_mask},true,true,true,\n') 73 | 74 | 75 | def address_set(*args): 76 | address_set_name = args[1] 77 | address_name_list = args[2] 78 | address_set_desc = args[3] 79 | 80 | the_path = 'exported/chpoint/network_groups.csv' 81 | with open(the_path, 'a') as f: 82 | if os.path.getsize(the_path) == 0: 83 | f.write(f'name,ignore-warnings,ignore-errors,comments\n') 84 | if address_set_desc: 85 | f.write(f'{address_set_name},true,true,"{address_set_desc}"\n') 86 | else: 87 | f.write(f'{address_set_name},true,true,\n') 88 | 89 | the_path = 'exported/chpoint/network_group_members.csv' 90 | with open(the_path, 'a') as f: 91 | if os.path.getsize(the_path) == 0: 92 | f.write(f'name,members.add,ignore-warnings,ignore-errors\n') 93 | for address_name in address_name_list: 94 | f.write(f'{address_set_name},{address_name},true,true\n') 95 | 96 | def policy(*args): 97 | policy_name = args[1] 98 | source_zone = args[2] 99 | destination_zone = args[3] 100 | policy_src_address = args[4] 101 | policy_dst_address = args[5] 102 | policy_app = args[6] 103 | policy_log = args[7] 104 | policy_state = args[8] 105 | policy_action = args[9] 106 | policy_id = args[10] 107 | position = args[11] 108 | 109 | the_path = 'exported/chpoint/policies.txt' 110 | with open(the_path, 'a') as output: 111 | if os.path.getsize(the_path) == 0: 112 | output.write('mgmt_cli login -u "your username" -p "your password" > "sid.txt"\n\n') 113 | 114 | if policy_log: 115 | output.write(f'mgmt_cli add access-rule layer "Network" position "{position}" name "{policy_name}" action "{policy_action}" {policy_src_address} {policy_dst_address} {policy_app} enabled {policy_state} comments "original rule order {policy_id}" track Log -s "sid.txt"\n\n') 116 | 117 | else: 118 | output.write(f'mgmt_cli add access-rule layer "Network" position "{position}" name "{policy_name}" action "{policy_action}" {policy_src_address} {policy_dst_address} {policy_app} enabled {policy_state} comments "original rule order{policy_id}" -s "sid.txt"\n\n') 119 | 120 | if position != 0 and position % 53 == 0: 121 | output.write('mgmt_cli publish -s "sid.txt"\n\n') -------------------------------------------------------------------------------- /resources/dst_vendor/dst_forti.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | class Forti_DST: 4 | 5 | def service(*args): 6 | application_name = args[1] 7 | destination_port = args[2] 8 | source_port = args[3] 9 | application_protocol = args[4] 10 | application_desc = args[5] 11 | app_session_ttl = args[6] 12 | 13 | 14 | the_path = 'exported/forti/services.txt' 15 | with open(the_path, 'a') as f: 16 | if os.path.getsize(the_path) == 0: 17 | f.write(f'config firewall service custom\n\n') 18 | 19 | f.write(f'edit {application_name}\n') 20 | if destination_port and not source_port: 21 | f.write(f'set {application_protocol}-portrange {destination_port}\n') 22 | elif source_port and not destination_port: 23 | f.write(f'set {application_protocol}-portrange {source_port}\n') 24 | elif source_port and destination_port: 25 | f.write(f'set {application_protocol}-portrange {destination_port}:{source_port}\n') 26 | if app_session_ttl: 27 | f.write(f'set session-ttl {app_session_ttl}\n') 28 | if application_desc: 29 | f.write(f'set comment "{application_desc}"\n') 30 | 31 | f.write('next\n\n') 32 | 33 | def service_set(*args): 34 | app_set_name = args[1] 35 | app_name = args[2] 36 | app_set_desc = args[3] 37 | 38 | the_path = 'exported/forti/service_group.txt' 39 | with open(the_path, 'a') as f: 40 | if os.path.getsize(the_path) == 0: 41 | f.write(f'config firewall service group\n\n') 42 | f.write(f'edit {app_set_name}\n') 43 | f.write(f'set member {app_name}\n') 44 | if app_set_desc: 45 | f.write(f'set comment "{app_set_desc}"\n') 46 | f.write('next\n\n') 47 | 48 | def address(*args): 49 | address_name = args[1] 50 | address_ip = args[2] 51 | address_desc = args[3] 52 | 53 | the_path = 'exported/forti/addresses.txt' 54 | with open(the_path, 'a') as f: 55 | if os.path.getsize(the_path) == 0: 56 | f.write('config firewall address\n\n') 57 | f.write(f'edit {address_name}\n') 58 | if address_desc: 59 | f.write(f'set comment "{address_desc}"\n') 60 | if '-' in address_ip: 61 | f.write(f'set type iprange\n') 62 | start_ip = address_ip.split('-')[0].replace(' ', '') 63 | end_ip = address_ip.split('-')[1].replace(' ', '') 64 | f.write(f'set start-ip {start_ip}\n') 65 | f.write(f'set end-ip {end_ip}\n') 66 | else: 67 | f.write(f'set subnet {address_ip}\n') 68 | f.write('next\n\n') 69 | 70 | 71 | def address_set(*args): 72 | address_set_name = args[1] 73 | address_name = args[2] 74 | address_set_desc = args[3] 75 | 76 | the_path = 'exported/forti/address_group.txt' 77 | with open(the_path, 'a') as f: 78 | if os.path.getsize(the_path) == 0: 79 | f.write('config firewall addrgrp\n\n') 80 | f.write(f'edit {address_set_name}\n') 81 | f.write(f'set member {address_name}\n') 82 | if address_set_desc: 83 | f.write(f'set comment "{address_set_desc}"\n') 84 | f.write('next\n\n') 85 | 86 | def policy(*args): 87 | policy_name = args[1] 88 | source_zone = args[2] 89 | destination_zone = args[3] 90 | policy_src_address = args[4] 91 | policy_dst_address = args[5] 92 | policy_app = args[6] 93 | policy_log = args[7] 94 | policy_state = args[8] 95 | policy_action = args[9] 96 | policy_id = args[10] 97 | 98 | the_path = 'exported/forti/policies.txt' 99 | with open(the_path, 'a') as output: 100 | if os.path.getsize(the_path) == 0: 101 | output.write('config firewall policy\n\n') 102 | output.write(f'edit {policy_id}\n') 103 | output.write(f'set name {policy_name}\n') 104 | output.write(f'set srcintf {source_zone}\n') 105 | output.write(f'set dstintf {destination_zone}\n') 106 | output.write(f'set srcaddr {policy_src_address}\n') 107 | output.write(f'set dstaddr {policy_dst_address}\n') 108 | output.write(f'set action {policy_action}\n') 109 | output.write(f'set service {policy_app}\n') 110 | if policy_log: 111 | output.write(f'set logtraffic all\n') 112 | if 'junos' in policy_app: 113 | output.write(f'set comments "Error, please check service for correction!"\n') 114 | output.write(f'set status {policy_state}\n') 115 | output.write('set schedule always\n') 116 | output.write('next\n\n') -------------------------------------------------------------------------------- /resources/dst_vendor/dst_palo.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | class Palo_DST: 4 | 5 | def service(*args): 6 | application_name = args[1] 7 | destination_port = args[2] 8 | source_port = args[3] 9 | application_protocol = args[4] 10 | application_desc = args[5] 11 | app_session_ttl = args[6] 12 | 13 | with open('exported/palo/services.txt', 'a') as f: 14 | if destination_port: 15 | f.write(f'set service {application_name} protocol {application_protocol} port {destination_port}\n\n') 16 | elif source_port: 17 | f.write(f'set service {application_name} protocol {application_protocol} source-port {source_port}\n\n') 18 | if application_desc: 19 | f.write(f'set service {application_name} description "{application_desc}"\n\n') 20 | if app_session_ttl: 21 | f.write(f'set service {application_name} protocol {application_protocol} override yes timeout {app_session_ttl}\n\n') 22 | 23 | 24 | 25 | def service_set(*args): 26 | app_set_name = args[1] 27 | app_name = args[2] 28 | 29 | with open('exported/palo/service_group.txt', 'a') as f: 30 | f.write(f'set service-group {app_set_name} members [ {app_name} ]\n\n') 31 | 32 | def address(*args): 33 | address_name = args[1] 34 | address_ip = args[2] 35 | address_desc = args[3] 36 | 37 | with open('exported/palo/addresses.txt', 'a') as f: 38 | if '-' in address_ip: 39 | address_ip = address_ip.replace(' ', '') 40 | f.write(f'set address {address_name} ip-range {address_ip}\n\n') 41 | else: 42 | f.write(f'set address {address_name} ip-netmask {address_ip}\n\n') 43 | if address_desc: 44 | f.write(f'set address {address_name} description "{address_desc}"\n\n') 45 | 46 | def address_set(*args): 47 | address_set_name = args[1] 48 | address_name = args[2] 49 | address_set_desc = args[3] 50 | 51 | with open('exported/palo/address_group.txt', 'a') as f: 52 | f.write(f'set address-group {address_set_name} static [ {address_name} ]\n\n') 53 | if address_set_desc: 54 | f.write(f'set address-group {address_set_name} description "{address_set_desc}"\n\n') 55 | 56 | def policy(*args): 57 | policy_name = args[1] 58 | source_zone = args[2] 59 | destination_zone = args[3] 60 | policy_src_address = args[4] 61 | policy_dst_address = args[5] 62 | policy_app = args[6] 63 | policy_log = args[7] 64 | policy_state = args[8] 65 | policy_action = args[9] 66 | 67 | the_path = 'exported/palo/policies.txt' 68 | with open(the_path, 'a') as output: 69 | if os.path.getsize(the_path) == 0: 70 | output.write('edit rulebase security\n\n') 71 | output.write(f'set rules {policy_name} from {source_zone}\n') 72 | output.write(f'set rules {policy_name} to {destination_zone}\n') 73 | output.write(f'set rules {policy_name} source [ {policy_src_address} ]\n') 74 | output.write(f'set rules {policy_name} destination [ {policy_dst_address} ]\n') 75 | output.write(f'set rules {policy_name} service [ {policy_app} ]\n') 76 | output.write(f'set rules {policy_name} application any\n') 77 | if source_zone == destination_zone: 78 | output.write(f'set rules {policy_name} rule-type intrazone\n') 79 | else: 80 | output.write(f'set rules {policy_name} rule-type interzone\n') 81 | if policy_log: 82 | output.write(f'set rules {policy_name} log-start yes\n') 83 | if policy_state == 'disabled': 84 | output.write(f'set rules {policy_name} disabled yes\n') 85 | output.write(f'set rules {policy_name} action {policy_action}\n\n') 86 | -------------------------------------------------------------------------------- /resources/dst_vendor/dst_srx.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | class SRX_DST: 4 | 5 | def service(*args): 6 | application_name = args[1] 7 | destination_port = args[2] 8 | source_port = args[3] 9 | application_protocol = args[4] 10 | application_desc = args[5] 11 | app_session_ttl = args[6] 12 | 13 | with open('exported/srx/services.txt', 'a') as f: 14 | if destination_port: 15 | f.write(f'set service {application_name} protocol {application_protocol} port {destination_port}\n\n') 16 | elif source_port: 17 | f.write(f'set service {application_name} protocol {application_protocol} source-port {source_port}\n\n') 18 | if application_desc: 19 | f.write(f'set service {application_name} description "{application_desc}"\n\n') 20 | 21 | def service_set(*args): 22 | app_set_name = args[1] 23 | app_name = args[2] 24 | 25 | with open('exported/srx/service_group.txt', 'a') as f: 26 | f.write(f'set service-group {app_set_name} members [ {app_name} ]\n\n') 27 | 28 | def address(*args): 29 | address_name = args[1] 30 | address_ip = args[2] 31 | address_desc = args[3] 32 | 33 | the_path = 'exported/srx/addresses.txt' 34 | with open(the_path, 'a') as f: 35 | if os.path.getsize(the_path) == 0: 36 | f.write(f'edit security address-book global\n\n') 37 | if '-' in address_ip: 38 | start_ip = address_ip.split('-')[0].replace(' ', '') 39 | end_ip = address_ip.split('-')[1].replace(' ', '') 40 | f.write(f'set address {address_name} range-address {start_ip} to {end_ip}\n\n') 41 | else: 42 | f.write(f'set address {address_name} ip-netmask {address_ip}\n\n') 43 | if address_desc: 44 | f.write(f'set address {address_name} description "{address_desc}"\n\n') 45 | 46 | def address_set(*args): 47 | address_set_name = args[1] 48 | address_name = args[2] 49 | address_set_desc = args[3] 50 | 51 | with open('exported/srx/address_group.txt', 'a') as f: 52 | f.write(f'set address-group {address_set_name} static [ {address_name} ]\n\n') 53 | if address_set_desc: 54 | f.write(f'set address-group {address_set_name} description "{address_set_desc}"\n\n') 55 | 56 | def policy(*args): 57 | policy_name = args[1] 58 | source_zone = args[2] 59 | destination_zone = args[3] 60 | policy_src_address = args[4] 61 | policy_dst_address = args[5] 62 | policy_app = args[6] 63 | policy_log = args[7] 64 | policy_state = args[8] 65 | policy_action = args[9] 66 | 67 | the_path = 'exported/srx/policies.txt' 68 | with open(the_path, 'a') as output: 69 | if os.path.getsize(the_path) == 0: 70 | output.write('edit security policies\n\n') 71 | if source_zone == 'global' and destination_zone == 'global': 72 | output.write(f'set global policy {policy_name} match source-address [ {policy_src_address} ]\n') 73 | output.write(f'set global policy {policy_name} match destination-address [ {policy_src_address} ]\n') 74 | output.write(f'set global policy {policy_name} match application [ {policy_src_address} ]\n') 75 | if policy_log: 76 | output.write(f'set global policy {policy_name} then log session-close session-init \n') 77 | output.write(f'set global policy {policy_name} then {policy_action} \n\n') 78 | else: 79 | output.write(f'set from-zone {source_zone} to-zone {destination_zone} policy {policy_name} match source-address [ {policy_src_address} ]\n') 80 | output.write(f'set from-zone {source_zone} to-zone {destination_zone} policy {policy_name} match destination-address [ {policy_dst_address} ]\n') 81 | output.write(f'set from-zone {source_zone} to-zone {destination_zone} policy {policy_name} match application [ {policy_app} ]\n') 82 | if policy_log: 83 | output.write(f'set from-zone {source_zone} to-zone {destination_zone} policy {policy_name} then log session-close session-init \n') 84 | output.write(f'set from-zone {source_zone} to-zone {destination_zone} policy {policy_name} then {policy_action}\n\n') 85 | 86 | -------------------------------------------------------------------------------- /resources/ip_address_converter/netmask_convereter.py: -------------------------------------------------------------------------------- 1 | from ipaddress import IPv4Network 2 | 3 | def netmasker(prefix): 4 | return str(IPv4Network(prefix).network_address) + ' ' + str(IPv4Network(prefix).netmask) 5 | 6 | def nethost(prefix): 7 | return str(IPv4Network(prefix).network_address) 8 | 9 | def sub_mask(prefix): 10 | return str(IPv4Network(prefix).netmask) 11 | 12 | def prefixer(prefix): 13 | return str(IPv4Network(prefix).network_address) + '/' +str(IPv4Network(prefix).prefixlen) 14 | 15 | 16 | -------------------------------------------------------------------------------- /resources/parser.py: -------------------------------------------------------------------------------- 1 | import os 2 | import logging 3 | 4 | from typing import List 5 | 6 | logger = logging.getLogger('fwmig.parser') 7 | 8 | def main_parser(action: str, cfg: str, src_vendor: str, dst_vendor: str, acts: List[str]) -> bool: 9 | if src_vendor == 'srx': 10 | from resources.src_vendor.srx.srx_config_converter import SRX_Cfg 11 | output = SRX_Cfg(cfg, dst_vendor) 12 | elif src_vendor == 'chpoint': 13 | from resources.src_vendor.chpoint.chpoint_config_parser import CHP_CFG 14 | output = CHP_CFG(cfg, dst_vendor) 15 | elif src_vendor == 'palo': 16 | from resources.src_vendor.palo.palo_config_coverter import PALO_Cfg 17 | output = PALO_Cfg(cfg, dst_vendor) 18 | # elif src_vendor == 'asa': 19 | # from resources.src_vendor.asa.asa_config_converter import ASA_CFG 20 | # output = ASA_CFG(cfg, dst_vendor) 21 | 22 | try: 23 | if action == 'policy': 24 | logger.info('Policy conversion started ...') 25 | output.policy 26 | 27 | elif action == 'config': 28 | output.cleaner 29 | if 'address' in acts: 30 | logger.info('Address and Address_set conversion started ...') 31 | output.address 32 | 33 | if 'service' in acts: 34 | if src_vendor == 'chpoint': 35 | return 'no' 36 | logger.info('Service conversion started ...') 37 | output.service 38 | 39 | if 'service_set' in acts: 40 | if src_vendor == 'chpoint': 41 | return 'no' 42 | logger.info('Service_set conversion started ...') 43 | output.service_set 44 | 45 | # if 'zone' in acts: 46 | # output.zone 47 | 48 | output.delete 49 | logger.info('Conversion finished successfully!') 50 | return True 51 | except Exception as err: 52 | logger.warning('Conversion Failed! Please re-check file content or Source vendor.') 53 | logger.error(err) 54 | logger.info(50*'=') 55 | try: 56 | os.remove(f'configs/{cfg}') 57 | except: 58 | pass 59 | return False -------------------------------------------------------------------------------- /resources/protocols/nc_conn.py: -------------------------------------------------------------------------------- 1 | import logging 2 | 3 | from ncclient import manager 4 | from ncclient import transport 5 | 6 | 7 | logger = logging.getLogger('fwmig.nc') 8 | 9 | class NcMGR: 10 | 11 | def _conn_mgr(self, host: str, username: str, password: str, port: str, device_params: str): 12 | return manager.connect( 13 | host=f'{host}', 14 | username = f'{username}', 15 | password = f'{password}', 16 | port = f'{port}', 17 | hostkey_verify = False, 18 | device_params = {'name': f'{device_params}'} 19 | ) 20 | 21 | 22 | # def junos_nc_conn(self, host: str, port: str, device_params: str, ): 23 | def junos_nc_conn(self, action: str, host: str, username: str, password: str, port: str, device_params: str): 24 | if action == 'policy': 25 | action = 'security policies | display xml' 26 | elif action == 'config': 27 | action = 'configuration | display xml' 28 | try: 29 | with self._conn_mgr(host, username, password, port, device_params) as m: 30 | result = m.command(f'show {action}') 31 | except transport.AuthenticationError: 32 | logger.warning(f'Authentication error for {username} on {host}:{port}') 33 | return False 34 | except: 35 | logger.warning('Something went wrong with connection or receiving data.') 36 | return 'other' 37 | with open('configs/nc_fw_result.log', 'w') as f: 38 | logger.info('Writing result to the file ...') 39 | f.write(str(result)) 40 | return 'nc_fw_result.log' -------------------------------------------------------------------------------- /resources/src_vendor/chpoint/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VahidTa/firewall_migration_tool/06f0ff0d0714f9563fe21b83d69711e66a8f0b1c/resources/src_vendor/chpoint/__init__.py -------------------------------------------------------------------------------- /resources/src_vendor/chpoint/chpoint_config_parser.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import os 3 | 4 | from resources.dst_vendor.dst_forti import Forti_DST 5 | from resources.dst_vendor.dst_asa import ASA_DST 6 | from resources.dst_vendor.dst_palo import Palo_DST 7 | from resources.dst_vendor.dst_srx import SRX_DST 8 | from resources.src_vendor.chpoint.chpoint_policy_parser import chpoint_policy 9 | from resources.ip_address_converter.netmask_convereter import prefixer 10 | 11 | 12 | forti = Forti_DST() 13 | asa = ASA_DST() 14 | palo = Palo_DST() 15 | srx = SRX_DST() 16 | 17 | class CHP_CFG: 18 | def __init__(self, cfg_file: str, vendor: str) -> None: 19 | self.cfg_file = cfg_file 20 | self.vendor = vendor 21 | 22 | @property 23 | def _job(self): 24 | names = ['Name', 'IPv4 address', 'Mask', 'IPv6 address', 'Mask 6', 'Port','Comments'] 25 | with open(f'configs/{self.cfg_file}', 'r') as imp_file: 26 | imported = pd.read_csv(imp_file, usecols=names, skiprows=1, names=names, keep_default_na=False, skipinitialspace=True) 27 | parsed = imported[names] 28 | return parsed 29 | 30 | @property 31 | def address(self): 32 | raw_objects = self._job 33 | for _ , row in raw_objects.iterrows(): 34 | address_name = row["Name"] 35 | if row["Comments"]: 36 | address_description = row["Comments"] 37 | else: 38 | address_description = '' 39 | 40 | if row["IPv4 address"] and '-' not in row["IPv4 address"]: 41 | ip_address = row["IPv4 address"] 42 | 43 | mask = row["Mask"] 44 | if mask: 45 | address_ip = prefixer(f'{ip_address}/{mask}') 46 | else: 47 | address_ip = prefixer(f'{ip_address}') 48 | # elif row["IPv6 address"]: 49 | # ip_address = row["IPv6 address"] 50 | # mask = row["Mask 6"] 51 | elif '-' in row["IPv4 address"]: 52 | address_ip = row["IPv4 address"] 53 | else: 54 | continue 55 | 56 | if self.vendor == 'forti': 57 | forti.address(address_name, address_ip, address_description) 58 | elif self.vendor == 'asa': 59 | asa.address(address_name, address_ip, address_description) 60 | elif self.vendor == 'palo': 61 | palo.address(address_name, address_ip, address_description) 62 | elif self.vendor == 'srx': 63 | srx.address(address_name, address_ip, address_description) 64 | 65 | @property 66 | def policy(self): 67 | chpoint_policy(self.cfg_file, self.vendor) 68 | 69 | @property 70 | def delete(self): 71 | os.remove(f'configs/{self.cfg_file}') 72 | 73 | @property 74 | def cleaner(self): 75 | if not os.path.exists(f'exported/{self.vendor}'): 76 | os.makedirs(f'exported/{self.vendor}') 77 | else: 78 | for f in os.listdir(f'exported/{self.vendor}/'): 79 | if f != 'policies.txt': 80 | os.remove(os.path.join(f'exported/{self.vendor}/', f)) 81 | 82 | -------------------------------------------------------------------------------- /resources/src_vendor/chpoint/chpoint_policy_parser.py: -------------------------------------------------------------------------------- 1 | import os 2 | import pandas as pd 3 | 4 | from resources.dst_vendor.dst_palo import Palo_DST 5 | from resources.dst_vendor.dst_forti import Forti_DST 6 | from resources.dst_vendor.dst_srx import SRX_DST 7 | from resources.dst_vendor.dst_asa import ASA_DST 8 | 9 | forti_translation = { 10 | 'Accept': 'accept', 11 | 'enabled': 'enable', 12 | 'disabled': 'disable', 13 | 'ftp': 'FTP', 14 | 'tftp': 'TFTP', 15 | 'rtsp': 'RTSP', 16 | 'ssh': 'SSH', 17 | 'telnet': 'TELNET', 18 | 'echo-request': 'PING', 19 | 'ntp-udp': 'NTP', 20 | 'nntp': 'NNTP', 21 | 'http': 'HTTP', 22 | 'https': 'HTTPS', 23 | 'smtp': 'SMTP', 24 | 'syslog': 'SYSLOG', 25 | 'domain-udp': 'DNS', 26 | 'domain-tcp': 'DNS', 27 | 'MS-SQL-Server': 'MS-SQL', 28 | 'smb': 'SMB', 29 | 'nbsession': 'SAMBA', 30 | 'NEW-RADIUS': 'RADIUS', 31 | 'pptp-tcp': 'PPTP', 32 | 'ldap': 'LDAP', 33 | 'ALL_DCE_RPC': 'DCE-RPC', 34 | 'H323': 'H323', 35 | 'ospf': 'OSPF', 36 | 'unknown-protocol-tcp': 'ALL_TCP', 37 | 'unknown-protocol-udp': 'ALL_UDP', 38 | } 39 | palo_translation = { 40 | 'Allow': 'allow', 41 | 'http': 'service-http', 42 | 'https': 'service-https', 43 | } 44 | 45 | srx_translation = { 46 | 'Accept': 'permit', 47 | 'Drop': 'deny', 48 | 'false': 'disabled', 49 | 'true': 'enabled', 50 | 'ftp': 'junos-ftp', 51 | 'tftp': 'junos-tftp', 52 | 'rtsp': 'junos-rtsp', 53 | 'ssh': 'junos-ssh', 54 | 'telnet': 'junos-telnet', 55 | 'echo-request': 'junos-ping', 56 | 'echo-request': 'junos-icmp-ping', 57 | 'ntp-udp': 'junos-ntp', 58 | 'nntp': 'junos-nntp', 59 | 'http': 'junos-http', 60 | 'https': 'junos-https', 61 | 'smtp': 'junos-smtp', 62 | 'syslog': 'junos-syslog', 63 | 'domain-udp': 'junos-dns-udp', 64 | 'domain-tcp': 'junos-dns-tcp', 65 | 'MS-SQL-Server': 'junos-ms-sql', 66 | 'MS-SQL-Monitor_UDP': 'junos-sql-monitor', 67 | 'smb': 'junos-smb-session', 68 | 'nbsession': 'junos-smb', 69 | 'NEW-RADIUS': 'junos-radius', 70 | 'NEW-RADIUS-ACCOUNTING': 'junos-radacct', 71 | 'TACACSplus': 'junos-tacacs', 72 | 'pptp-tcp': 'junos-pptp', 73 | 'ldap': 'junos-ldap', 74 | 'ALL_DCE_RPC': 'junos-ms-rpc-any', 75 | 'who': 'junos-who', 76 | 'CIFS': 'junos-cifs', 77 | 'ospf': 'junos-ospf', 78 | 'unknown_protocol_tcp': 'junos-tcp-any', 79 | 'unknown_protocol_udp': 'junos-udp-any', 80 | } 81 | 82 | asa_translation = { 83 | 'Accept': 'permit', 84 | 'disabled': 'inactive', 85 | 'ftp': ['tcp', 'ftp'], 86 | 'tftp': ['udp', 'tftp'], 87 | 'rtsp': ['tcp', 'rtsp'], 88 | 'ssh': ['tcp', 'ssh'], 89 | 'telnet': ['tcp', 'telnet'], 90 | 'echo-request': ['icmp', 'na'], 91 | 'ntp': ['udp', 'ntp'], 92 | 'nntp': ['tcp','nntp'], 93 | 'http': ['tcp', 'http'], 94 | 'https': ['tcp', 'https'], 95 | 'smtp': ['tcp', 'smtp'], 96 | 'syslog': ['udp', 'syslog'], 97 | 'echo-request': ['icmp', 'echo'], 98 | 'domain-udp': ['udp', 'domain'], 99 | 'domain-tcp': ['tcp', 'domain'], 100 | 'smb': ['tcp', 'netbios-ssn'], 101 | 'NEW-RADIUS': ['udp', 'radius'], 102 | 'NEW-RADIUS-ACCOUNTING': ['udp', 'radius-acct'], 103 | 'TACACSplus': ['tcp', 'tacacs'], 104 | 'pptp-tcp': ['tcp', 'pptp'], 105 | 'ldap': ['tcp', 'ldap'], 106 | 'who': ['udp', 'who'], 107 | 'CIFS': ['tcp-udp', 'cifs'], 108 | 'ospf': ['ospf', 'na'], 109 | 'unknown_protocol_tcp': ['tcp', 'na'], 110 | 'unknown_protocol_udp': ['udp', 'na'], 111 | } 112 | 113 | def chpoint_policy(file: str, vendor: str): 114 | """Uses to provide rule order!""" 115 | if not os.path.exists(f'exported/{vendor}'): 116 | os.makedirs(f'exported/{vendor}') 117 | else: 118 | try: 119 | os.remove(os.path.join(f'exported/{vendor}/', 'policies.txt')) 120 | except: 121 | pass 122 | 123 | names = ["No.", "Name", "Source", "Destination", "Services & Applications", "Action", "Track"] 124 | cols = [0, 2, 3, 4, 6, 8, 9] 125 | with open(f'configs/{file}', 'r') as f: 126 | imported = pd.read_csv(f, usecols=cols, names=names, skiprows=1, keep_default_na=False, skipinitialspace=True) 127 | os.remove(f'configs/{file}') 128 | 129 | for _, row in imported.iterrows(): 130 | policy_id = row["No."] 131 | policy_name = row["Name"] 132 | policy_src_address = row["Source"] 133 | policy_dst_address = row["Destination"] 134 | policy_action = row["Action"] 135 | policy_log = row["Track"] 136 | policy_app = row["Services & Applications"] 137 | source_zone = 'global' 138 | destination_zone = 'global' 139 | policy_state = '' 140 | 141 | try: 142 | app_list = policy_app.split(';') 143 | new_list = [] 144 | for app in app_list: 145 | if vendor == 'forti': 146 | policy_app = forti_translation.get(app, app) 147 | elif vendor == 'palo': 148 | policy_app = palo_translation.get(app, app) 149 | elif vendor == 'srx': 150 | policy_app = srx_translation.get(app, app) 151 | elif vendor == 'asa': 152 | policy_app = asa_translation.get(app, app) 153 | new_list.append(policy_app) 154 | policy_app = ' '.join(new_list) 155 | except: 156 | pass 157 | try: 158 | src_list = policy_src_address.split(';') 159 | policy_src_address = ' '.join(src_list) 160 | except: 161 | pass 162 | 163 | try: 164 | dst_list = policy_dst_address.split(';') 165 | policy_dst_address = ' '.join(dst_list) 166 | except: 167 | pass 168 | 169 | if vendor == 'forti': 170 | policy_action = forti_translation.get(policy_action, policy_action) 171 | if 'Any' in policy_src_address: 172 | policy_src_address = 'all' 173 | if 'Any' in policy_dst_address: 174 | policy_dst_address == 'all' 175 | if policy_app == 'Any': 176 | policy_app = 'ALL' 177 | 178 | forti = Forti_DST() 179 | forti.policy( 180 | policy_name, 181 | source_zone, 182 | destination_zone, 183 | policy_src_address, 184 | policy_dst_address, 185 | policy_app, 186 | policy_log, 187 | policy_state, 188 | policy_action, 189 | policy_id 190 | ) 191 | 192 | elif vendor == 'asa': 193 | policy_action = asa_translation.get(policy_action, policy_action) 194 | if 'Any' in policy_src_address: 195 | policy_src_address = 'any' 196 | if 'Any' in policy_dst_address: 197 | policy_dst_address == 'any' 198 | if policy_app == 'Any': 199 | policy_app = 'any' 200 | asa = ASA_DST() 201 | asa.policy( 202 | policy_name, 203 | source_zone, 204 | destination_zone, 205 | policy_src_address, 206 | policy_dst_address, 207 | policy_app, 208 | policy_log, 209 | policy_state, 210 | policy_action, 211 | policy_id 212 | ) 213 | elif vendor == 'palo': 214 | policy_action = palo_translation.get(policy_action, policy_action) 215 | palo = Palo_DST() 216 | palo.policy( 217 | policy_name, 218 | source_zone, 219 | destination_zone, 220 | policy_src_address, 221 | policy_dst_address, 222 | policy_app, 223 | policy_log, 224 | policy_state, 225 | policy_action 226 | ) 227 | elif vendor == 'srx': 228 | policy_action = srx_translation.get(policy_action, policy_action) 229 | if 'Any' in policy_src_address: 230 | policy_src_address = 'any' 231 | if 'Any' in policy_dst_address: 232 | policy_dst_address == 'any' 233 | if policy_app == 'Any': 234 | policy_app = 'any' 235 | srx = SRX_DST() 236 | srx.policy( 237 | policy_name, 238 | source_zone, 239 | destination_zone, 240 | policy_src_address, 241 | policy_dst_address, 242 | policy_app, 243 | policy_log, 244 | policy_state, 245 | policy_action 246 | ) 247 | -------------------------------------------------------------------------------- /resources/src_vendor/palo/palo_config_coverter.py: -------------------------------------------------------------------------------- 1 | import json 2 | import xmltodict 3 | import os 4 | import logging 5 | 6 | 7 | from resources.dst_vendor.dst_srx import SRX_DST 8 | from resources.dst_vendor.dst_forti import Forti_DST 9 | from resources.dst_vendor.dst_asa import ASA_DST 10 | from resources.dst_vendor.dst_chpoint import CHPoint_DST 11 | from resources.src_vendor.palo.palo_policy_convert import palo_policy 12 | from ipaddress import ip_network 13 | 14 | srx = SRX_DST() 15 | forti = Forti_DST() 16 | asa = ASA_DST() 17 | chpoint = CHPoint_DST() 18 | logger = logging.getLogger('fwmig.palo.config') 19 | 20 | 21 | class PALO_Cfg: 22 | """Converts PA -> Fortigate, ASA, Forti, Palo Alto (except zone and interfaces) """ 23 | def __init__(self, cfg_file: str, vendor: str) -> None: 24 | self.cfg_file = cfg_file 25 | self.vendor = vendor 26 | 27 | @property 28 | def _job(self): 29 | with open(f'configs/{self.cfg_file}', 'r') as imp_file: 30 | xml_dict = xmltodict.parse(imp_file.read()) 31 | json_formatted = json.dumps(xml_dict) 32 | dict_formatted = json.loads(json_formatted) 33 | try: 34 | return dict_formatted['root']['response'] 35 | except: 36 | logger.error(' or are not exists on the config. Conversion failed!') 37 | return False 38 | 39 | @property 40 | def service(self): 41 | """Exports custom application created on PaloAlto""" 42 | logger.info('Service process started ...') 43 | 44 | dict_formatted = self._job 45 | if not dict_formatted: 46 | return False 47 | for i in range(len(dict_formatted)): 48 | try: 49 | if 'service' in dict_formatted[i]['result']: 50 | applications_list = dict_formatted[i]['result']['service']['entry'] 51 | except: 52 | continue 53 | 54 | for index in range(len(applications_list)): 55 | application_name = applications_list[index].get('@name', 'None') 56 | application_desc = applications_list[index].get('description') 57 | application_protocol = applications_list[index]['protocol'].keys() 58 | application_protocol = list(application_protocol)[0] 59 | destination_port = applications_list[index]['protocol'][application_protocol]['port'] 60 | source_port = '' 61 | session_ttl = '' 62 | 63 | 64 | if self.vendor == 'forti': 65 | forti.service(application_name, destination_port, source_port, application_protocol, application_desc, session_ttl) 66 | elif self.vendor == 'asa': 67 | asa.service(application_name, destination_port, source_port, application_protocol, application_desc) 68 | 69 | elif self.vendor == 'srx': 70 | srx.service(application_name, destination_port, source_port, application_protocol, application_desc, session_ttl) 71 | 72 | elif self.vendor == 'chpoint': 73 | if not source_port: 74 | source_port = '' 75 | # Because the platform does not support name start with Digits! 76 | if application_name[:1].isdigit(): 77 | application_name = 'custom_' + application_name 78 | if "," in destination_port: 79 | # instead of skipping, creating single services and than a group would make more sense in the future 80 | logger.warn(f"Skipping Service {application_name} since it has multiple ports set, which checkpoint can't handle. Please add it manually afterwards") 81 | continue 82 | chpoint.service(application_name, destination_port, source_port, application_protocol, application_desc, session_ttl) 83 | 84 | 85 | 86 | @property 87 | def service_set(self): 88 | """Exports custome application-set created on SRX""" 89 | logger.info('Service-set process started ...') 90 | 91 | dict_formatted = self._job 92 | if not dict_formatted: 93 | return False 94 | 95 | for i in range(len(dict_formatted)): 96 | try: 97 | if 'service-group' in dict_formatted[i]['result']: 98 | applications_list = dict_formatted[i]['result']['service-group']['entry'] 99 | logger.info('Service-group exists in policy') 100 | except: 101 | logger.info('Service-group is not in policy') 102 | continue 103 | if not isinstance(applications_list,list): 104 | # if only one applications_list exists 105 | applications_list = [applications_list] 106 | for index in range(len(applications_list)): 107 | app_list = [] 108 | app_set_name = applications_list[index].get('@name', 'None') 109 | app_set_desc = applications_list[index].get('description') 110 | app_set_main = applications_list[index]['members']['member'] 111 | for sub_index in range(len(app_set_main)): 112 | app_name = app_set_main[sub_index] 113 | 114 | 115 | app_list.append(app_name) 116 | if not self.vendor == 'asa': 117 | app_name = ' '.join(app_list) 118 | 119 | if self.vendor == 'forti': 120 | forti.service_set(app_set_name, app_name, app_set_desc) 121 | elif self.vendor == 'asa': 122 | asa.service_set(app_set_name, app_list, app_set_desc) 123 | elif self.vendor == 'srx': 124 | srx.service_set(app_set_name, app_name) 125 | elif self.vendor == 'chpoint': 126 | chpoint.service_set(app_set_name, app_list, app_set_desc) 127 | 128 | 129 | @property 130 | def address(self): 131 | """Converts address books""" 132 | logger.info('Address and address-group process started ...') 133 | 134 | dict_formatted = self._job 135 | if not dict_formatted: 136 | return False 137 | 138 | for i in range(len(dict_formatted)): 139 | try: 140 | if 'address' in dict_formatted[i]['result']: 141 | address_list = dict_formatted[i]['result']['address']['entry'] 142 | elif 'address-group' in dict_formatted[i]['result']: 143 | address_set_books = dict_formatted[i]['result']['address-group']['entry'] 144 | except: 145 | logger.info('Address-group or address is not in policy') 146 | continue 147 | 148 | for index in range(len(address_list)): 149 | address_name = address_list[index].get('@name', 'None') 150 | address_description = address_list[index].get('description') 151 | address_ip = address_list[index].get('ip-netmask', 'None') 152 | if address_ip == 'None' or address_name == 'None': 153 | continue 154 | 155 | 156 | if self.vendor == 'forti': 157 | forti.address(address_name, address_ip, address_description) 158 | 159 | elif self.vendor == 'asa': 160 | asa.address(address_name, address_ip, address_description) 161 | 162 | elif self.vendor == 'srx': 163 | srx.address(address_name, address_ip, address_description) 164 | 165 | elif self.vendor == 'chpoint': 166 | if "/" not in address_ip: 167 | address_ip = address_ip+"/32" 168 | try: 169 | ip_network(address_ip, strict=True) 170 | # address_ip is a valid network address (or a valid host with /32 mask) -->nothing to do 171 | except ValueError: 172 | # address_ip is a palo specific host address that also has a network mask 173 | # --> convert to Host 174 | address_ip = address_ip.split("/")[0]+"/32" 175 | chpoint.address(address_name, address_ip, address_description) 176 | 177 | 178 | 179 | if address_set_books: 180 | if not isinstance(address_set_books,list): 181 | # if only one address-group exists 182 | address_set_books = [address_set_books] 183 | for index in range(len(address_set_books)): 184 | address_name_list = [] 185 | address_set_name = address_set_books[index].get('@name', 'None') 186 | address_set_desc = address_set_books[index].get('description') 187 | 188 | address_set_main = address_set_books[index]['static']['member'] 189 | for sub_index in range(len(address_set_main)): 190 | address_name = address_set_main[sub_index] 191 | address_name_list.append(address_name) 192 | address_name = ' '.join(address_name_list) 193 | 194 | if self.vendor == 'forti': 195 | forti.address_set(address_set_name, address_name, address_set_desc) 196 | elif self.vendor == 'asa': 197 | asa.address_set(address_set_name, address_name_list, address_set_desc) 198 | elif self.vendor == 'srx': 199 | srx.address_set(address_set_name, address_name, address_set_desc) 200 | elif self.vendor == 'chpoint': 201 | chpoint.address_set(address_set_name, address_name_list, address_set_desc) 202 | 203 | @property 204 | def policy(self): 205 | logger.info('Policy process started ...') 206 | palo_policy(self.cfg_file, self.vendor) 207 | 208 | @property 209 | def delete(self): 210 | os.remove(f'configs/{self.cfg_file}') 211 | 212 | @property 213 | def cleaner(self): 214 | if not os.path.exists(f'exported/{self.vendor}'): 215 | os.makedirs(f'exported/{self.vendor}') 216 | else: 217 | for f in os.listdir(f'exported/{self.vendor}/'): 218 | if f != 'policies.txt': 219 | os.remove(os.path.join(f'exported/{self.vendor}/', f)) 220 | 221 | -------------------------------------------------------------------------------- /resources/src_vendor/palo/palo_policy_convert.py: -------------------------------------------------------------------------------- 1 | import xmltodict 2 | import json 3 | import os 4 | import logging 5 | 6 | from resources.dst_vendor.dst_srx import SRX_DST 7 | from resources.dst_vendor.dst_forti import Forti_DST 8 | from resources.dst_vendor.dst_chpoint import CHPoint_DST 9 | from resources.dst_vendor.dst_asa import ASA_DST 10 | 11 | forti_translation = { 12 | 'allow': 'accept', 13 | 'no': 'enable', 14 | 'yes': 'disable', 15 | 'service-http': 'HTTP', 16 | 'service-https': 'HTTPS', 17 | } 18 | srx_translation = { 19 | 'allow': 'permit', 20 | 'no': 'enabled', 21 | 'yes': 'disabled', 22 | 'service-http': 'junos-http', 23 | 'service-https': 'junos-https', 24 | } 25 | 26 | chpoint_translation = { 27 | 'allow': 'accept', 28 | 'deny': 'drop', 29 | 'yes': 'false', 30 | 'no': 'true', 31 | 'service-http': 'http', 32 | 'service-https': 'https', 33 | } 34 | 35 | asa_translation = { 36 | 'yes': 'inactive', 37 | 'service-http': ['tcp', 'http'], 38 | 'service-https': ['tcp', 'https'], 39 | } 40 | 41 | logger = logging.getLogger('fwmig.palo.policy') 42 | 43 | def palo_policy(file: str, vendor: str): 44 | """Uses to provide rule order!""" 45 | if not os.path.exists(f'exported/{vendor}'): 46 | os.makedirs(f'exported/{vendor}') 47 | else: 48 | try: 49 | os.remove(os.path.join(f'exported/{vendor}/', 'policies.txt')) 50 | except: 51 | pass 52 | 53 | try: 54 | with open(f'configs/{file}', 'r') as f: 55 | my_text = xmltodict.parse(f.read()) 56 | except Exception as err: 57 | logger.error(f'Check file format. Maybe tag is not exists!') 58 | raise ValueError(err) 59 | 60 | os.remove(f'configs/{file}') 61 | 62 | try: 63 | json_formatted = json.dumps(my_text) 64 | dict_formatted = json.loads(json_formatted)['root']['response'] 65 | except: 66 | logger.error(' or are not exists on the config. Conversion failed!') 67 | 68 | for i in range(len(dict_formatted)): 69 | try: 70 | if 'rulebase' in dict_formatted[i]['result']: 71 | security_cfg = dict_formatted[i]['result']['rulebase']['security']['rules']['entry'] 72 | except: 73 | continue 74 | position = 1 75 | 76 | try: 77 | len(security_cfg) 78 | except: 79 | raise ValueError("This tool can't work for one rule!") 80 | 81 | for main_index in range(len(security_cfg)): 82 | policy_src_list = [] 83 | policy_dst_list = [] 84 | policy_app_list = [] 85 | 86 | policy_name = security_cfg[main_index]['@name'] 87 | source_zone = security_cfg[main_index]['from']['member'] 88 | destination_zone = security_cfg[main_index]['to']['member'] 89 | source_address_list = security_cfg[main_index]['source']['member'] 90 | destination_address_list = security_cfg[main_index]['destination']['member'] 91 | service_address_list = security_cfg[main_index]['service']['member'] 92 | # application_address_list = security_cfg[main_index]['application'] 93 | try: 94 | policy_state = security_cfg[main_index]['disabled'] 95 | except: 96 | policy_state = 'no' 97 | policy_action = security_cfg[main_index]['action'] 98 | try: 99 | policy_log = security_cfg[main_index]['log-start'] 100 | except: 101 | policy_log = False 102 | policy_id = position 103 | 104 | if isinstance(source_address_list, (list)): 105 | for sub_index in range(len(source_address_list)): 106 | policy_src_address = source_address_list[sub_index] 107 | policy_src_list.append(policy_src_address) 108 | else: 109 | policy_src_address = source_address_list 110 | 111 | if isinstance(destination_address_list, (list)): 112 | for sub_index in range(len(destination_address_list)): 113 | policy_dst_address = destination_address_list[sub_index] 114 | policy_dst_list.append(policy_dst_address) 115 | else: 116 | policy_dst_address = destination_address_list 117 | 118 | if isinstance(service_address_list, (list)): 119 | for sub_index in range(len(service_address_list)): 120 | policy_app = service_address_list[sub_index] 121 | policy_app_list.append(policy_app) 122 | else: 123 | policy_app = service_address_list 124 | 125 | if policy_log: 126 | policy_log = True 127 | else: 128 | policy_log = False 129 | if policy_src_list: 130 | policy_src_address = ' '.join(policy_src_list) 131 | if policy_dst_list: 132 | policy_dst_address = ' '.join(policy_dst_list) 133 | if policy_app_list: 134 | try: 135 | policy_app = ' '.join(policy_app_list) 136 | except: 137 | policy_app = policy_app_list 138 | 139 | if vendor == 'forti': 140 | policy_state = forti_translation.get(policy_state, policy_state) 141 | policy_action = forti_translation.get(policy_action, policy_action) 142 | if 'any' in policy_src_address: 143 | policy_src_address = 'all' 144 | if 'any' in policy_dst_address: 145 | policy_dst_address = 'all' 146 | if policy_app == 'any': 147 | policy_app = 'ALL' 148 | if len(policy_name) > 34: 149 | policy_name = policy_name[:34] 150 | 151 | forti = Forti_DST() 152 | forti.policy( 153 | policy_name, 154 | source_zone, 155 | destination_zone, 156 | policy_src_address, 157 | policy_dst_address, 158 | policy_app, 159 | policy_log, 160 | policy_state, 161 | policy_action, 162 | policy_id 163 | ) 164 | 165 | elif vendor == 'asa': 166 | policy_action = asa_translation.get(policy_action, policy_action) 167 | asa = ASA_DST() 168 | asa.policy( 169 | policy_name, 170 | source_zone, 171 | destination_zone, 172 | policy_src_address, 173 | policy_dst_address, 174 | policy_app, 175 | policy_log, 176 | policy_state, 177 | policy_action, 178 | policy_id 179 | ) 180 | elif vendor == 'srx': 181 | policy_action = srx_translation.get(policy_action, policy_action) 182 | srx = SRX_DST() 183 | srx.policy( 184 | policy_name, 185 | source_zone, 186 | destination_zone, 187 | policy_src_address, 188 | policy_dst_address, 189 | policy_app, 190 | policy_log, 191 | policy_state, 192 | policy_action 193 | ) 194 | 195 | elif vendor == 'chpoint': 196 | policy_action = chpoint_translation.get(policy_action, policy_action) 197 | policy_state = chpoint_translation.get(policy_state, policy_state) 198 | 199 | if policy_dst_list: 200 | dst_list = [] 201 | for i in range(len(policy_dst_list)): 202 | dst_list.append(f'destination.{i+1} "{policy_dst_list[i]}"') 203 | policy_dst_address = ' '.join(dst_list) 204 | else: 205 | policy_dst_address = f'destination "{"Any" if str(policy_dst_address).strip().lower() == "any" else policy_dst_address}"' #checkpoint need to have "Any" as string not "any" (Case is important) 206 | 207 | if policy_src_list: 208 | src_list = [] 209 | for i in range(len(policy_src_list)): 210 | src_list.append(f'source.{i+1} "{policy_src_list[i]}"') 211 | policy_src_address = ' '.join(src_list) 212 | else: 213 | policy_src_address = f'source "{"Any" if str(policy_src_address).strip().lower() == "any" else policy_src_address}"' #checkpoint need to have "Any" as string not "any" (Case is important) 214 | if policy_app_list: 215 | app_list = [] 216 | for i in range(len(policy_app_list)): 217 | if policy_app_list[i][:1].isdigit(): 218 | policy_app = 'custom_' + policy_app_list[i] 219 | else: 220 | policy_app = policy_app_list[i] 221 | app_list.append(f'service.{i+1} "{policy_app}"') 222 | policy_app = ' '.join(app_list) 223 | else: 224 | if policy_app[:1].isdigit(): 225 | policy_app = 'custom_' + policy_app 226 | elif str(policy_app).strip().lower() == "any" : 227 | policy_app = "Any" #checkpoint need to have "Any" as string not "any" (Case is important) 228 | elif str(policy_app).strip().lower() == "application-default": 229 | policy_app = "Any" #application-default concept does not exist in checkpoint (see https://knowledgebase.paloaltonetworks.com/KCSArticleDetail?id=kA10g000000ClVwCAK) 230 | policy_app = f'service {policy_app}' 231 | 232 | 233 | chpoint = CHPoint_DST() 234 | chpoint.policy( 235 | policy_name, 236 | source_zone, 237 | destination_zone, 238 | policy_src_address, 239 | policy_dst_address, 240 | policy_app, 241 | policy_log, 242 | policy_state, 243 | policy_action, 244 | policy_id, 245 | position 246 | ) 247 | 248 | 249 | position += 1 250 | -------------------------------------------------------------------------------- /resources/src_vendor/srx/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VahidTa/firewall_migration_tool/06f0ff0d0714f9563fe21b83d69711e66a8f0b1c/resources/src_vendor/srx/__init__.py -------------------------------------------------------------------------------- /resources/src_vendor/srx/srx_config_converter.py: -------------------------------------------------------------------------------- 1 | import json 2 | import xmltodict 3 | import os 4 | import logging 5 | 6 | from resources.src_vendor.srx.srx_policy_convert import forti_translation,\ 7 | palo_translation,\ 8 | chpoint_translation,\ 9 | asa_translation 10 | 11 | from resources.dst_vendor.dst_palo import Palo_DST 12 | from resources.dst_vendor.dst_forti import Forti_DST 13 | from resources.dst_vendor.dst_asa import ASA_DST 14 | from resources.dst_vendor.dst_chpoint import CHPoint_DST 15 | from resources.src_vendor.srx.srx_policy_convert import srx_policy 16 | 17 | 18 | 19 | palo = Palo_DST() 20 | forti = Forti_DST() 21 | asa = ASA_DST() 22 | chpoint = CHPoint_DST() 23 | logger = logging.getLogger('fwmig.srx.config') 24 | 25 | class SRX_Cfg: 26 | """Converts SRX -> Fortigate, ASA, Forti, Palo Alto (except zone and interfaces) """ 27 | def __init__(self, cfg_file: str, vendor: str) -> None: 28 | self.cfg_file = cfg_file 29 | self.vendor = vendor 30 | 31 | @property 32 | def _job(self): 33 | with open(f'configs/{self.cfg_file}', 'r') as imp_file: 34 | xml_dict = xmltodict.parse(imp_file.read()) 35 | json_formatted = json.dumps(xml_dict) 36 | dict_formatted = json.loads(json_formatted) 37 | return dict_formatted['rpc-reply']['configuration'] 38 | 39 | @property 40 | def service(self): 41 | """Exports custom application created on SRX""" 42 | 43 | dict_formatted = self._job 44 | 45 | applications_list = dict_formatted['applications'] 46 | apps= applications_list['application'] 47 | 48 | for index in range(len(apps)): 49 | application_name = apps[index].get('name', 'None') 50 | application_desc = apps[index].get('description') 51 | application_protocol = apps[index].get('protocol', 'None') 52 | destination_port = apps[index].get('destination-port') 53 | source_port = apps[index].get('source-port') 54 | session_ttl = apps[index].get('inactivity-timeout') 55 | 56 | if self.vendor == 'forti': 57 | forti.service(application_name, destination_port, source_port, application_protocol, application_desc, session_ttl) 58 | elif self.vendor == 'asa': 59 | asa.service(application_name, destination_port, source_port, application_protocol, application_desc) 60 | 61 | elif self.vendor == 'palo': 62 | if session_ttl == 'never': 63 | session_ttl = False 64 | palo.service(application_name, destination_port, source_port, application_protocol, application_desc, session_ttl) 65 | 66 | elif self.vendor == 'chpoint': 67 | if not source_port: 68 | source_port = '' 69 | if (not session_ttl) or (session_ttl == 'never'): 70 | session_ttl = '' 71 | # Because the platform does not support name start with Digits! 72 | if application_name[:1].isdigit(): 73 | application_name = 'custom_' + application_name 74 | 75 | chpoint.service(application_name, destination_port, source_port, application_protocol, application_desc, session_ttl) 76 | 77 | 78 | 79 | @property 80 | def service_set(self): 81 | """Exports custome application-set created on SRX""" 82 | 83 | dict_formatted = self._job 84 | 85 | applications_list = dict_formatted['applications'] 86 | apps_set = applications_list['application-set'] 87 | 88 | for index in range(len(apps_set)): 89 | app_list = [] 90 | app_set_name = apps_set[index].get('name', 'None') 91 | app_set_desc = apps_set[index].get('description') 92 | app_set_main = apps_set[index]['application'] 93 | for sub_index in range(len(app_set_main)): 94 | app_name = app_set_main[sub_index].get('name', 'None') 95 | 96 | if self.vendor == 'forti' and 'junos' in app_name: 97 | app_name = forti_translation.get(app_name, app_name) 98 | elif self.vendor == 'palo' and 'junos' in app_name: 99 | app_name = palo_translation.get(app_name, app_name) 100 | elif self.vendor == 'chpoint' and 'junos' in app_name: 101 | app_name = chpoint_translation.get(app_name, app_name) 102 | elif self.vendor == 'asa' and 'junos' in app_name: 103 | app_name = asa_translation.get(app_name, app_name) 104 | 105 | app_list.append(app_name) 106 | if not self.vendor == 'asa': 107 | app_name = ' '.join(app_list) 108 | 109 | if self.vendor == 'forti': 110 | forti.service_set(app_set_name, app_name, app_set_desc) 111 | elif self.vendor == 'asa': 112 | asa.service_set(app_set_name, app_list, app_set_desc) 113 | elif self.vendor == 'palo': 114 | palo.service_set(app_set_name, app_name) 115 | elif self.vendor == 'chpoint': 116 | chpoint.address_set(app_set_name, app_list, app_set_desc) 117 | 118 | 119 | @property 120 | def address(self): 121 | """Converts address books""" 122 | 123 | security_cfg = self._job 124 | try: 125 | address_books = security_cfg['security']['address-book']['address'] 126 | address_set_books = security_cfg['security']['address-book']['address-set'] 127 | check = True 128 | except: 129 | address_books = security_cfg['security']['zones']['security-zone'] 130 | address_set_books = security_cfg['security']['zones']['security-zone'] 131 | check = False 132 | 133 | for index in range(len(address_books)): 134 | address_list = [] 135 | if check: 136 | address_name = address_books[index].get('name', 'None') 137 | address_description = address_books[index].get('description') 138 | address_ip = address_books[index].get('ip-prefix', 'None') 139 | else: 140 | try: 141 | address_b = address_books[index]['address-book']['address'] 142 | except: 143 | continue 144 | for sub_index in range(len(address_b)): 145 | if isinstance(address_b, (list)): 146 | address_name = address_b[sub_index].get('name', 'None') 147 | address_description = address_b[sub_index].get('description') 148 | address_ip = address_b[sub_index].get('ip-prefix', 'None') 149 | address_list.append([address_name, address_description, address_ip]) 150 | else: 151 | address_name = address_b.get('name', 'None') 152 | address_description = address_b.get('description') 153 | address_ip = address_b.get('ip-prefix', 'None') 154 | 155 | 156 | if self.vendor == 'forti': 157 | if address_list: 158 | for i in range(len(address_list)): 159 | address_name = address_list[i][0] 160 | address_description = address_list[i][1] 161 | address_ip = address_list[i][2] 162 | forti.address(address_name, address_ip, address_description) 163 | else: 164 | forti.address(address_name, address_ip, address_description) 165 | 166 | elif self.vendor == 'asa': 167 | if address_list: 168 | for i in range(len(address_list)): 169 | address_name = address_list[i][0] 170 | address_description = address_list[i][1] 171 | address_ip = address_list[i][2] 172 | asa.address(address_name, address_ip, address_description) 173 | else: 174 | asa.address(address_name, address_ip, address_description) 175 | 176 | elif self.vendor == 'palo': 177 | if address_list: 178 | for i in range(len(address_list)): 179 | address_name = address_list[i][0] 180 | address_description = address_list[i][1] 181 | address_ip = address_list[i][2] 182 | palo.address(address_name, address_ip, address_description) 183 | else: 184 | palo.address(address_name, address_ip, address_description) 185 | 186 | elif self.vendor == 'chpoint': 187 | if address_list: 188 | for i in range(len(address_list)): 189 | address_name = address_list[i][0] 190 | address_description = address_list[i][1] 191 | address_ip = address_list[i][2] 192 | chpoint.address(address_name, address_ip, address_description) 193 | else: 194 | chpoint.address(address_name, address_ip, address_description) 195 | 196 | 197 | 198 | if address_set_books: 199 | for index in range(len(address_set_books)): 200 | address_name_list = [] 201 | if not check: 202 | try: 203 | address_b = address_set_books[index]['address-book']['address-set'] 204 | except: 205 | continue 206 | address_set_name = address_b.get('name', 'None') 207 | address_set_desc = address_b.get('description') 208 | address_set_main = address_b.get('address', 'None') 209 | else: 210 | address_set_name = address_set_books[index].get('name', 'None') 211 | address_set_desc = address_set_books[index].get('description') 212 | address_set_main = address_set_books[index].get('address', 'None') 213 | for sub_index in range(len(address_set_main)): 214 | address_name = address_set_main[sub_index].get('name', 'None') 215 | address_name_list.append(address_name) 216 | address_name = ' '.join(address_name_list) 217 | 218 | if self.vendor == 'forti': 219 | forti.address_set(address_set_name, address_name, address_set_desc) 220 | elif self.vendor == 'asa': 221 | asa.address_set(address_set_name, address_name_list, address_set_desc) 222 | elif self.vendor == 'palo': 223 | palo.address_set(address_set_name, address_name, address_set_desc) 224 | elif self.vendor == 'chpoint': 225 | chpoint.address_set(address_set_name, address_name_list, address_set_desc) 226 | 227 | @property 228 | def policy(self): 229 | srx_policy(self.cfg_file, self.vendor) 230 | 231 | @property 232 | def zone(self): 233 | """Not Implemented""" 234 | return 235 | # item = SRX_Int('test', '10.10.10.10/24') 236 | # item.save_to_db() 237 | 238 | security_cfg = self._job 239 | # zones = security_cfg['security']['zones']['security-zone'] 240 | 241 | # for main_index in range(len(zones)): 242 | # service_list = [] 243 | # zone_int_list = [] 244 | 245 | # zone_name = zones[main_index].get('name', 'None') 246 | # zone_service = zones[main_index]['host-inbound-traffic']['system-services'] 247 | # zone_ints = zones[main_index]['interfaces'] 248 | # if isinstance(zone_service, (list)): 249 | # for sub_index in range(len(zone_service)): 250 | # service = zone_service[sub_index].get('name', 'None') 251 | # service_list.append(service) 252 | # else: 253 | # service = zone_service.get('name', 'None') 254 | # service_list.append(service) 255 | # service = ' '.join(service_list) 256 | 257 | # if isinstance(zone_ints, (list)): 258 | # for sub_index in range(len(zone_ints)): 259 | # zone_int = zone_ints[sub_index].get('name', 'None') 260 | # zone_int_list.append(zone_int) 261 | # else: 262 | # zone_int = zone_ints.get('name', 'None') 263 | # zone_int_list.append(zone_int) 264 | # zone_int = ' '.join(zone_int_list) 265 | # if self.vendor == 'forti': 266 | # with open('exported/forti/zones.txt', 'a') as f: 267 | # f.write(f'zone {zone_name} ') 268 | 269 | 270 | interfaces = security_cfg['interfaces']['interface'] 271 | 272 | for main_index in range(len(interfaces)): 273 | # name_list = [] 274 | # vlan_list = [] 275 | # ip_list = [] 276 | int_name = interfaces[main_index].get('name') 277 | int_units = interfaces[main_index].get('unit') 278 | 279 | if int_units: 280 | if isinstance(int_units, (list)): 281 | for sub_index in range(len(int_units)): 282 | unit_name = int_units[sub_index].get('name') 283 | # name_list.append(unit_name) 284 | vlan_id = int_units[sub_index].get('vlan-id') 285 | # vlan_list.append(vlan_id) 286 | try: 287 | ip_addr = int_units[sub_index]['family']['inet']['address'].get('name', 'None') 288 | # ip_list.append(ip_addr) 289 | print(int_name+'.'+unit_name, vlan_id) 290 | item = SRX_Int(int_name+'.'+unit_name, vlan_id, ip_addr) 291 | logger.info(f'{item} created!') 292 | item.save_to_db() 293 | except: 294 | pass 295 | 296 | else: 297 | unit_name = int_units.get('name') 298 | vlan_id = int_units.get('vlan-id') 299 | try: 300 | ip_addr = int_units['family']['inet']['address'].get('name', 'None') 301 | item = SRX_Int(int_name+'.'+unit_name, vlan_id, ip_addr) 302 | logger.info(f'{item} created!') 303 | item.save_to_db() 304 | except: 305 | pass 306 | test = SRX_Int.findby_interface('10') 307 | print(test) 308 | 309 | # with open('exported/vahid.txt', 'a') as f: 310 | # f.write(test) 311 | # unit_name = ' '.join(name_list) 312 | # if vlan_list: 313 | # vlan_id = ' '.join(vlan_list) 314 | # else: 315 | # vlan_id = 0 316 | # if ip_list: 317 | # ip_addr = ' '.join(ip_list) 318 | # else: 319 | # ip_addr = "n/a" 320 | 321 | 322 | # print(int_name, unit_name, ip_addr) 323 | 324 | @property 325 | def delete(self): 326 | os.remove(f'configs/{self.cfg_file}') 327 | 328 | @property 329 | def cleaner(self): 330 | if not os.path.exists(f'exported/{self.vendor}'): 331 | os.makedirs(f'exported/{self.vendor}') 332 | else: 333 | for f in os.listdir(f'exported/{self.vendor}/'): 334 | if f != 'policies.txt': 335 | os.remove(os.path.join(f'exported/{self.vendor}/', f)) 336 | -------------------------------------------------------------------------------- /resources/src_vendor/srx/srx_policy_convert.py: -------------------------------------------------------------------------------- 1 | import xmltodict 2 | import json 3 | import os 4 | 5 | from resources.dst_vendor.dst_palo import Palo_DST 6 | from resources.dst_vendor.dst_forti import Forti_DST 7 | from resources.dst_vendor.dst_chpoint import CHPoint_DST 8 | from resources.dst_vendor.dst_asa import ASA_DST 9 | 10 | forti_translation = { 11 | 'permit': 'accept', 12 | 'enabled': 'enable', 13 | 'disabled': 'disable', 14 | 'junos-ftp': 'FTP', 15 | 'junos-tftp': 'TFTP', 16 | 'junos-rtsp': 'RTSP', 17 | 'junos-ssh': 'SSH', 18 | 'junos-telnet': 'TELNET', 19 | 'junos-ping': 'PING', 20 | 'junos-ntp': 'NTP', 21 | 'junos-nntp': 'NNTP', 22 | 'junos-http': 'HTTP', 23 | 'junos-https': 'HTTPS', 24 | 'junos-smtp': 'SMTP', 25 | 'junos-syslog': 'SYSLOG', 26 | 'junos-icmp-ping': 'PING', 27 | 'junos-icmp-all': 'ALL_ICMP', 28 | 'junos-dns-udp': 'DNS', 29 | 'junos-dns-tcp': 'DNS', 30 | 'junos-ms-sql': 'MS-SQL', 31 | 'junos-sql-monitor': 'MS-SQL', 32 | 'junos-vnc': 'VNC', 33 | 'junos-smb-session': 'SMB', 34 | 'junos-smb': 'SAMBA', 35 | 'junos-radius': 'RADIUS', 36 | 'junos-pptp': 'PPTP', 37 | 'junos-ldap': 'LDAP', 38 | 'junos-internet-locator-service': 'LDAP', 39 | 'junos-ms-rpc-any': 'DCE-RPC', 40 | 'junos-h323': 'H323', 41 | 'junos-ospf': 'OSPF', 42 | 'junos-tcp-any': 'ALL_TCP', 43 | 'junos-udp-any': 'ALL_UDP', 44 | } 45 | palo_translation = { 46 | 'permit': 'allow', 47 | 'junos-http': 'service-http', 48 | 'junos-https': 'service-https', 49 | } 50 | 51 | chpoint_translation = { 52 | 'permit': 'accept', 53 | 'deny': 'drop', 54 | 'disabled': 'false', 55 | 'enabled': 'true', 56 | 'junos-ftp': 'ftp', 57 | 'junos-tftp': 'tftp', 58 | 'junos-rtsp': 'rtsp', 59 | 'junos-ssh': 'ssh', 60 | 'junos-telnet': 'telnet', 61 | 'junos-ping': 'echo-request', 62 | 'junos-ntp': 'ntp-udp', 63 | 'junos-nntp': 'nntp', 64 | 'junos-http': 'http', 65 | 'junos-https': 'https', 66 | 'junos-smtp': 'smtp', 67 | 'junos-syslog': 'syslog', 68 | 'junos-icmp-ping': 'echo-request', 69 | 'junos-dns-udp': 'domain-udp', 70 | 'junos-dns-tcp': 'domain-tcp', 71 | 'junos-ms-sql': 'MS-SQL-Server', 72 | 'junos-sql-monitor': 'MS-SQL-Monitor_UDP', 73 | 'junos-smb-session': 'smb', 74 | 'junos-smb': 'nbsession', 75 | 'junos-radius': 'NEW-RADIUS', 76 | 'junos-radacct': 'NEW-RADIUS-ACCOUNTING', 77 | 'junos-tacacs': 'TACACSplus', 78 | 'junos-pptp': 'pptp-tcp', 79 | 'junos-ldap': 'ldap', 80 | 'junos-internet-locator-service': 'ldap', 81 | 'junos-ms-rpc-any': 'ALL_DCE_RPC', 82 | 'junos-who': 'who', 83 | 'junos-cifs': 'CIFS', 84 | 'junos-ospf': 'ospf', 85 | 'junos-tcp-any': 'unknown_protocol_tcp', 86 | 'junos-udp-any': 'unknown_protocol_udp', 87 | } 88 | 89 | asa_translation = { 90 | 'disabled': 'inactive', 91 | 'junos-ftp': ['tcp', 'ftp'], 92 | 'junos-tftp': ['udp', 'tftp'], 93 | 'junos-rtsp': ['tcp', 'rtsp'], 94 | 'junos-ssh': ['tcp', 'ssh'], 95 | 'junos-telnet': ['tcp', 'telnet'], 96 | 'junos-ping': ['icmp', 'na'], 97 | 'junos-ntp': ['udp', 'ntp'], 98 | 'junos-nntp': ['tcp','nntp'], 99 | 'junos-http': ['tcp', 'http'], 100 | 'junos-https': ['tcp', 'https'], 101 | 'junos-smtp': ['tcp', 'smtp'], 102 | 'junos-syslog': ['udp', 'syslog'], 103 | 'junos-icmp-ping': ['icmp', 'echo'], 104 | 'junos-dns-udp': ['udp', 'domain'], 105 | 'junos-dns-tcp': ['tcp', 'domain'], 106 | 'junos-smb': ['tcp', 'netbios-ssn'], 107 | 'junos-radius': ['udp', 'radius'], 108 | 'junos-radacct': ['udp', 'radius-acct'], 109 | 'junos-tacacs': ['tcp', 'tacacs'], 110 | 'junos-pptp': ['tcp', 'pptp'], 111 | 'junos-ldap': ['tcp', 'ldap'], 112 | 'junos-internet-locator-service': ['tcp', 'ldap'], 113 | 'junos-who': ['udp', 'who'], 114 | 'junos-cifs': ['tcp-udp', 'cifs'], 115 | 'junos-ospf': ['ospf', 'na'], 116 | 'junos-tcp-any': ['tcp', 'na'], 117 | 'junos-udp-any': ['udp', 'na'], 118 | } 119 | 120 | def srx_policy(file: str, vendor: str): 121 | """Uses to provide rule order!""" 122 | if not os.path.exists(f'exported/{vendor}'): 123 | os.makedirs(f'exported/{vendor}') 124 | else: 125 | try: 126 | os.remove(os.path.join(f'exported/{vendor}/', 'policies.txt')) 127 | except: 128 | pass 129 | 130 | with open(f'configs/{file}', 'r') as f: 131 | my_text = xmltodict.parse(f.read()) 132 | 133 | os.remove(f'configs/{file}') 134 | 135 | json_formatted = json.dumps(my_text) 136 | dict_formatted = json.loads(json_formatted) 137 | try: 138 | security_cfg = dict_formatted['rpc-reply']['multi-routing-engine-results']['multi-routing-engine-item']['security-policies']['security-context'] 139 | except: 140 | security_cfg = dict_formatted['rpc-reply']['security-policies']['security-context'] 141 | 142 | position = 1 143 | for main_index in range(len(security_cfg)): 144 | source_zone = security_cfg[main_index]['context-information'].get('source-zone-name', 'None') 145 | destination_zone = security_cfg[main_index]['context-information'].get('destination-zone-name', 'None') 146 | policy = security_cfg[main_index]['policies'] 147 | 148 | 149 | for sub_index in range(len(policy)): 150 | policy_src_list = [] 151 | policy_dst_list = [] 152 | policy_app_list = [] 153 | 154 | if isinstance(policy, (list)): 155 | policy_name = policy[sub_index]['policy-information'].get('policy-name', 'None') 156 | policy_state = policy[sub_index]['policy-information'].get('policy-state', 'None') 157 | policy_id = policy[sub_index]['policy-information'].get('policy-identifier', 'None') 158 | policy_seq = policy[sub_index]['policy-information'].get('policy-sequence-number', 'None') 159 | policy_source_address = policy[sub_index]['policy-information']['source-addresses']['source-address'] 160 | policy_destination_address = policy[sub_index]['policy-information']['destination-addresses']['destination-address'] 161 | policy_application = policy[sub_index]['policy-information']['applications']['application'] 162 | if isinstance(policy_source_address, (list)): 163 | for inc_index in range(len(policy_source_address)): 164 | policy_src_address = policy_source_address[inc_index].get('address-name', 'None') 165 | policy_src_list.append(policy_src_address) 166 | else: 167 | policy_src_address = policy_source_address.get('address-name', 'None') 168 | if isinstance(policy_destination_address, (list)): 169 | for inc_index in range(len(policy_destination_address)): 170 | policy_dst_address = policy_destination_address[inc_index].get('address-name', 'None') 171 | policy_dst_list.append(policy_dst_address) 172 | else: 173 | policy_dst_address = policy_destination_address.get('address-name', 'None') 174 | if isinstance(policy_application, (list)): 175 | for inc_index in range(len(policy_application)): 176 | policy_app = policy_application[inc_index].get('application-name', 'None') 177 | if vendor == 'forti' and 'junos' in policy_app: 178 | policy_app = forti_translation.get(policy_app, policy_app) 179 | elif vendor == 'palo' and 'junos' in policy_app: 180 | policy_app = palo_translation.get(policy_app, policy_app) 181 | elif vendor == 'chpoint' and 'junos' in policy_app: 182 | policy_app = chpoint_translation.get(policy_app, policy_app) 183 | elif vendor == 'asa' and 'junos' in policy_app: 184 | policy_app = asa_translation.get(policy_app, policy_app) 185 | 186 | policy_app_list.append(policy_app) 187 | else: 188 | policy_app = policy_application.get('application-name', 'None') 189 | if vendor == 'forti' and 'junos' in policy_app: 190 | policy_app = forti_translation.get(policy_app, policy_app) 191 | elif vendor == 'palo' and 'junos' in policy_app: 192 | policy_app == palo_translation.get(policy_app, policy_app) 193 | elif vendor == 'chpoint' and 'junos' in policy_app: 194 | policy_app = chpoint_translation.get(policy_app, policy_app) 195 | elif vendor == 'asa' and 'junos' in policy_app: 196 | policy_app = asa_translation.get(policy_app, policy_app) 197 | 198 | policy_action = policy[sub_index]['policy-information']['policy-action'].get('action-type', 'None') 199 | 200 | if 'log' in list(policy[sub_index]['policy-information']['policy-action'].keys()): 201 | policy_log = True 202 | else: 203 | policy_log = False 204 | else: 205 | policy_name = policy['policy-information'].get('policy-name', 'None') 206 | policy_state = policy['policy-information'].get('policy-state', 'None') 207 | policy_id = policy['policy-information'].get('policy-identifier', 'None') 208 | # policy_seq = policy['policy-information'].get('policy-sequence-number', 'None') 209 | policy_source_address = policy['policy-information']['source-addresses']['source-address'] 210 | policy_destination_address = policy['policy-information']['destination-addresses']['destination-address'] 211 | policy_application = policy['policy-information']['applications']['application'] 212 | 213 | if isinstance(policy_source_address, (list)): 214 | for inc_index in range(len(policy_source_address)): 215 | policy_src_address = policy_source_address[inc_index].get('address-name', 'None') 216 | policy_src_list.append(policy_src_address) 217 | else: 218 | policy_src_address = policy_source_address.get('address-name', 'None') 219 | if isinstance(policy_destination_address, (list)): 220 | for inc_index in range(len(policy_destination_address)): 221 | policy_dst_address = policy_destination_address[inc_index].get('address-name', 'None') 222 | policy_dst_list.append(policy_dst_address) 223 | else: 224 | policy_dst_address = policy_destination_address.get('address-name', 'None') 225 | if isinstance(policy_application, (list)): 226 | for inc_index in range(len(policy_application)): 227 | policy_app = policy_application[inc_index].get('application-name', 'None') 228 | if vendor == 'forti' and 'junos' in policy_app: 229 | policy_app = forti_translation.get(policy_app, policy_app) 230 | elif vendor == 'palo' and 'junos' in policy_app: 231 | policy_app = palo_translation.get(policy_app, policy_app) 232 | elif vendor == 'chpoint' and 'junos' in policy_app: 233 | policy_app = chpoint_translation.get(policy_app, policy_app) 234 | elif vendor == 'asa' and 'junos' in policy_app: 235 | policy_app = asa_translation.get(policy_app, policy_app) 236 | 237 | if vendor == 'chpoint': 238 | if policy_app[:1].isdigit(): 239 | policy_app = 'custom_' + policy_app 240 | policy_app_list.append(policy_app) 241 | else: 242 | policy_app = policy_application.get('application-name', 'None') 243 | if vendor == 'forti' and 'junos' in policy_app: 244 | policy_app = forti_translation.get(policy_app, policy_app) 245 | elif vendor == 'palo' and 'junos' in policy_app: 246 | policy_app = palo_translation.get(policy_app, policy_app) 247 | elif vendor == 'chpoint' and 'junos' in policy_app: 248 | policy_app = chpoint_translation.get(policy_app, policy_app) 249 | elif vendor == 'asa' and 'junos' in policy_app: 250 | policy_app = asa_translation.get(policy_app, policy_app) 251 | 252 | if vendor == 'chpoint': 253 | if policy_app[:1].isdigit(): 254 | policy_app = 'custom_' + policy_app 255 | 256 | 257 | policy_action = policy['policy-information']['policy-action'].get('action-type', 'None') 258 | 259 | if 'log' in list(policy['policy-information']['policy-action'].keys()): 260 | policy_log = True 261 | else: 262 | policy_log = False 263 | if policy_src_list: 264 | policy_src_address = ' '.join(policy_src_list) 265 | if policy_dst_list: 266 | policy_dst_address = ' '.join(policy_dst_list) 267 | if policy_app_list: 268 | try: 269 | policy_app = ' '.join(policy_app_list) 270 | except: 271 | policy_app = policy_app_list 272 | 273 | if vendor == 'forti': 274 | policy_state = forti_translation.get(policy_state, policy_state) 275 | policy_action = forti_translation.get(policy_action, policy_action) 276 | if 'any' in policy_src_address: 277 | policy_src_address = 'all' 278 | if 'any' in policy_dst_address: 279 | policy_dst_address = 'all' 280 | if policy_app == 'any': 281 | policy_app = 'ALL' 282 | if len(policy_name) > 34: 283 | policy_name = policy_name[:34] 284 | 285 | forti = Forti_DST() 286 | forti.policy( 287 | policy_name, 288 | source_zone, 289 | destination_zone, 290 | policy_src_address, 291 | policy_dst_address, 292 | policy_app, 293 | policy_log, 294 | policy_state, 295 | policy_action, 296 | policy_id 297 | ) 298 | 299 | elif vendor == 'asa': 300 | policy_action = asa_translation.get(policy_action, policy_action) 301 | asa = ASA_DST() 302 | asa.policy( 303 | policy_name, 304 | source_zone, 305 | destination_zone, 306 | policy_src_address, 307 | policy_dst_address, 308 | policy_app, 309 | policy_log, 310 | policy_state, 311 | policy_action, 312 | policy_id 313 | ) 314 | elif vendor == 'palo': 315 | policy_action = palo_translation.get(policy_action, policy_action) 316 | palo = Palo_DST() 317 | palo.policy( 318 | policy_name, 319 | source_zone, 320 | destination_zone, 321 | policy_src_address, 322 | policy_dst_address, 323 | policy_app, 324 | policy_log, 325 | policy_state, 326 | policy_action 327 | ) 328 | 329 | elif vendor == 'chpoint': 330 | policy_action = chpoint_translation.get(policy_action, policy_action) 331 | policy_state = chpoint_translation.get(policy_state, policy_state) 332 | 333 | if policy_dst_list: 334 | dst_list = [] 335 | for i in range(len(policy_dst_list)): 336 | dst_list.append(f'destination.{i+1} "{policy_dst_list[i]}"') 337 | policy_dst_address = ' '.join(dst_list) 338 | else: 339 | policy_dst_address = f'destination "{policy_dst_address}"' 340 | 341 | if policy_src_list: 342 | src_list = [] 343 | for i in range(len(policy_src_list)): 344 | src_list.append(f'source.{i+1} "{policy_src_list[i]}"') 345 | policy_src_address = ' '.join(src_list) 346 | else: 347 | policy_src_address = f'source "{policy_src_address}"' 348 | if policy_app_list: 349 | app_list = [] 350 | for i in range(len(policy_app_list)): 351 | if policy_app_list[i][:1].isdigit(): 352 | policy_app = 'custom_' + policy_app_list[i] 353 | else: 354 | policy_app = policy_app_list[i] 355 | app_list.append(f'service.{i+1} "{policy_app}"') 356 | policy_app = ' '.join(app_list) 357 | else: 358 | if policy_app[:1].isdigit(): 359 | policy_app = 'custom_' + policy_app 360 | 361 | policy_app = f'service "{policy_app}"' 362 | 363 | chpoint = CHPoint_DST() 364 | chpoint.policy( 365 | policy_name, 366 | source_zone, 367 | destination_zone, 368 | policy_src_address, 369 | policy_dst_address, 370 | policy_app, 371 | policy_log, 372 | policy_state, 373 | policy_action, 374 | policy_id, 375 | position 376 | ) 377 | 378 | 379 | position += 1 380 | -------------------------------------------------------------------------------- /resources/web/static/files.css: -------------------------------------------------------------------------------- 1 | *{ 2 | padding: 0; 3 | margin: 0; 4 | box-sizing: border-box; 5 | } 6 | 7 | body{ 8 | background-color: #bbb; 9 | color: orange; 10 | font-weight: bolder; 11 | } 12 | 13 | #container { 14 | margin: 30px auto; 15 | max-width: 450px; 16 | padding: 20px; 17 | background-color: white; 18 | border: solid black 2px; 19 | border-radius: 5px; 20 | } 21 | 22 | p { 23 | margin-bottom: 20px; 24 | font-size: larger; 25 | font-weight: bolder; 26 | color: #111; 27 | text-align: center; 28 | } 29 | 30 | a{ 31 | text-decoration: none; 32 | font-size: large; 33 | color: #111; 34 | text-decoration: underline; 35 | } 36 | 37 | nav { 38 | max-width: 100%; 39 | background-color: #444; 40 | height: 50px; 41 | display: flex; 42 | justify-content: space-between; 43 | } 44 | 45 | nav p { 46 | margin: 15px; 47 | color: orange; 48 | font-weight: bold; 49 | text-decoration: none; 50 | display: flex; 51 | align-items: center; 52 | } 53 | 54 | nav a { 55 | margin: 15px; 56 | color: orange; 57 | font-weight: bold; 58 | text-decoration: none; 59 | display: flex; 60 | align-items: center; 61 | } 62 | 63 | nav .linked { 64 | display: flex; 65 | 66 | } -------------------------------------------------------------------------------- /resources/web/static/script.js: -------------------------------------------------------------------------------- 1 | function ChangeDropdowns(value){ 2 | if(value=="netconf" || value=="rest"){ 3 | document.getElementById('file').style.display='none'; 4 | for (i = 0; i < 4; i++){ 5 | document.getElementsByClassName('remote')[i].style.display='block'; 6 | } 7 | document.getElementById('host').setAttribute('required', true); 8 | document.getElementById('username').setAttribute('required', true); 9 | document.getElementById('password').setAttribute('required', true); 10 | document.getElementById('port').setAttribute('required', true); 11 | if(value=="rest"){ 12 | document.getElementById('protocol').setAttribute('required', true); 13 | document.getElementsByClassName('protocol')[0].style.display='block'; 14 | } 15 | if(value=="netconf"){ 16 | document.getElementById('protocol').removeAttribute('required'); 17 | document.getElementsByClassName('protocol')[0].style.display='none'; 18 | } 19 | }else if(value=="file"){ 20 | document.getElementById('file').style.display='block'; 21 | for (i = 0; i < 4; i++) { 22 | document.getElementsByClassName('remote')[i].style.display='none'; 23 | } 24 | document.getElementsByClassName('protocol')[0].style.display='none'; 25 | document.getElementById('host').removeAttribute('required'); 26 | document.getElementById('username').removeAttribute('required'); 27 | document.getElementById('password').removeAttribute('required'); 28 | document.getElementById('protocol').removeAttribute('required'); 29 | document.getElementById('port').removeAttribute('required'); 30 | document.getElementById('protocol').removeAttribute('required'); 31 | } 32 | } 33 | 34 | function configOptions(value) { 35 | if(value=='config'){ 36 | document.getElementById('config-box').style.display='block'; 37 | } 38 | else if(value=='policy'){ 39 | document.getElementById('config-box').style.display='none'; 40 | } 41 | } 42 | 43 | 44 | function updateSelect(changedSelect, selectId) { 45 | var otherSelect = document.getElementById(selectId); 46 | for (var i = 0; i < otherSelect.options.length; ++i) { 47 | otherSelect.options[i].disabled = false; 48 | } 49 | if (changedSelect.selectedIndex == 0) { 50 | return; 51 | } 52 | otherSelect.options[changedSelect.selectedIndex].disabled = true; 53 | } 54 | 55 | 56 | -------------------------------------------------------------------------------- /resources/web/static/style.css: -------------------------------------------------------------------------------- 1 | * { 2 | padding: 0; 3 | margin: 0; 4 | box-sizing: border-box; 5 | } 6 | 7 | body{ 8 | background-color: #bbb; 9 | } 10 | 11 | #container { 12 | margin: 30px auto; 13 | max-width: 450px; 14 | padding: 20px; 15 | } 16 | 17 | .form-wrap { 18 | background-color: white; 19 | padding: 15px 25px; 20 | color: #333; 21 | border: solid 2px black; 22 | border-radius: 5px; 23 | } 24 | 25 | p { 26 | text-align: center; 27 | font-size: larger; 28 | font-weight: bolder; 29 | } 30 | 31 | .form-wrap .form-group { 32 | margin-top: 15px; 33 | } 34 | 35 | 36 | .form-wrap .form-group label{ 37 | display: block; 38 | color: #111; 39 | margin-bottom: 5px; 40 | font-weight: bold; 41 | } 42 | .form-wrap .remote, .form-wrap .protocol { 43 | display: none; 44 | } 45 | 46 | .form-wrap .config-box{ 47 | display: none; 48 | } 49 | 50 | .form-wrap .form-group input, select{ 51 | width: 100%; 52 | padding: 10px; 53 | border: #ddd 1px solid; 54 | border-radius: 5px; 55 | } 56 | 57 | .form-wrap button{ 58 | display: block; 59 | width: 100%; 60 | padding: 10px; 61 | margin-top: 10px; 62 | background-color: orange; 63 | color: black; 64 | font-weight: bold; 65 | } 66 | 67 | nav { 68 | max-width: 100%; 69 | background-color: #444; 70 | height: 50px; 71 | display: flex; 72 | justify-content: space-between; 73 | } 74 | 75 | nav p { 76 | margin: 15px; 77 | color: orange; 78 | font-weight: bold; 79 | text-decoration: none; 80 | display: flex; 81 | align-items: center; 82 | } 83 | 84 | nav a { 85 | margin: 15px; 86 | color: orange; 87 | font-weight: bold; 88 | text-decoration: none; 89 | display: flex; 90 | align-items: center; 91 | font-size: large; 92 | } 93 | 94 | nav .linked { 95 | display: flex; 96 | 97 | } 98 | 99 | .form-wrap .config-box label, .form-wrap .config-box input{ 100 | width:auto; 101 | display: unset; 102 | } 103 | -------------------------------------------------------------------------------- /resources/web/templates/exported_vendor.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Download Output 8 | 9 | 10 | 19 |
20 |

Output files

21 | {% for file in dloads %} 22 | {% if 'keep' not in file %} 23 | -> {{ file }}
24 | {% endif %} 25 | {% endfor %} 26 |
27 | 28 | -------------------------------------------------------------------------------- /resources/web/templates/files.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Download Output 8 | 9 | 10 | 19 |
20 |

Output files

21 | {% for file in dloads %} 22 | {% if 'keep' not in file %} 23 | -> {{ file }}
24 | {% endif %} 25 | {% endfor %} 26 |
27 | 28 | -------------------------------------------------------------------------------- /resources/web/templates/home.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | FW Migration Tool 9 | 10 | 11 | 20 |
21 |
22 |

Fill the form

23 |
24 |
25 | 26 | 36 |
37 |
38 | 39 | 49 |
50 |
51 | 52 | 57 |
58 |
59 | 60 | 61 | 62 | 63 |
64 |
65 | 66 | 67 |
68 |
69 | 70 | 71 |
72 | 73 |
74 | 75 | 80 |
81 |
82 | 83 | 84 |
85 |
86 | 87 | 91 |
92 |
93 |
94 | 95 | 96 |
97 |
98 | 99 | 100 |
101 |
102 | 103 | 104 |
105 | 109 |
110 |
111 | 112 | {% for mesg in get_flashed_messages() %} 113 |

{{ mesg }}

114 | {% endfor %} 115 |
116 | 117 |
118 |
119 |
120 | 128 | 129 | --------------------------------------------------------------------------------