ふらふらエンジニアのメモ帳

セキュリティおべんきょちゅ( ˘ω˘ )スヤァ…

Check Point IPSにSnort Ruleを適用する

Check Point次世代ファイアウォールのIPSに、カスタマイズしたシグネチャを適用した時のメモ。

f:id:tsukino_netwkr:20190729232317p:plain

Check Point IPSシグネチャ

Ruleファイルの作成

以下のガイドを参考に作成。

sc1.checkpoint.com

完成したRuleファイル。

alert tcp any any -> any 23 (msg:"Telnet Hello1"; content:"|68 65 6c 6c 6f|"; )
alert tcp any any -> any 23 (msg:"Telnet Hello2"; content:"hello"; )
  • Check PointにTelnetログインしたユーザが、helloを含む文字列を入力した場合、IPS検知ログが上がるようにした。
  • 動作確認のため、文字列のマッチ条件を2種類作成。Telnet Hello1はバイナリ、Telnet Hello2はASCII形式。

ちょっとハマったところ。

  • ファイル拡張子は.ruleとする。
  • 指定できるプロトコルは、tcpudpall(TCP+UDP)。icmpipは非サポート。
  • 宛先ポート番号をanyにすると反映されなかった。
  • msgキーワードはシグネチャの名前として使われるため必須。contentキーワードも必須。
  • 最後はセミコロン;を付ける必要あり。
  • Performance ImpactはHigh、SeverityはHigh、Confidence LevelはLow。プロファイル設定によってはActionがInactive(無効)になるため、DetectもしくはPreventへ変更。

Ruleファイルの適用

  • SmartConsoleからSecurity Management Serverへ接続
  • SECURITY POLICIES > Threat Prevention > Policyをクリック
  • IPS Protectionsをクリック
  • Actions > Snort protections > Import Snort rulesをクリック
  • Snort Ruleファイルを選択してインポート
  • IPSポリシーのAction変更
  • セッションの公開
  • Threat Prevention(IPS)ポリシーをSecurity GatewayもしくはSecurity Clusterへインストール

f:id:tsukino_netwkr:20210413023359p:plain ※ガイドより抜粋

設定後のIPS Protection設定。

f:id:tsukino_netwkr:20210413021207p:plain
IPS Protection設定

ログ確認

Telnetクライアントから入力した文字は、基本的に1文字ずつ送信されるため、helloをコピペして頑張って1パケットで送信。 IPSログを見ると、両方のパターンで検知出来た。

f:id:tsukino_netwkr:20210413024859p:plain

Ansible cli_commandモジュールのprompt/answerオプション動作確認

Ansibleのcli_commandモジュールは、ネットワーク機器でshowコマンド等を実行できるマルチOS対応のモジュールです。

docs.ansible.com

本モジュールは、Cisco IOS、NX-OS、Juniper等、OSの違いを意識せずに使えるのが最大のメリットですが、他にも、コマンド実行後に "複数の" 確認メッセージが出る場合に、あらかじめ指定した回答を返すことが出来ます。
後者については、Red HatのAnsibleブログでも、Ciscoルータの再起動(reload)の例が紹介されています。

www.ansible.com

今回は、Ansibleブログと同じくCisco IOSで、様々な確認メッセージ(promptオプション)と回答(answerオプション)のパターンで動作確認してみました。
Ansibleは2.8.4、NW機器はCatalyst3560、12.2台を使用しました。

CLIで再起動した時の確認メッセージ

Cisco IOSの場合、前回の設定保存以降に一度でもグローバルコンフィグレーションモードに移行した場合、設定変更していなくても保存するか聞かれます。

Router#reload

System configuration has been modified. Save? [yes/no]:

②その後、本当に再起動して問題ないか聞かれます。

Proceed with reload? [confirm]

OKパターン1:promptオプションを①Save?、②confirmの順番で定義

Playbook

promptオプションに、メッセージの表示順通り、リスト形式で①Save\?、②confirmを定義しました。(①は?正規表現として扱われないよう、\エスケープ処理しています。)
各メッセージに対する回答は、いずれもyにしています。
check_allオプションはデフォルトでFalseが採用され、①②いずれかに回答したタイミングでそれ以降のメッセージ確認/回答は行いません。そのため今回はTrueを指定し、①②両方に回答するようにしています。Trueの場合、設定保存済みで①が表示されないケースでは、①のプロンプトを待ち続け、コマンドタイムアウトでエラー終了となってしまうので注意が必要です。

---

- hosts: cisco
  gather_facts: no
  connection: network_cli

  tasks:
    - name: reboot ios device
      cli_command:
        command: reload
        check_all: True
        prompt:
          - 'Save\?'
          - 'confirm'
        answer:
          - 'y'
          - 'y'

実行結果

問題なく再起動できました。

$ ansible-playbook -i inventory_3560 playbook_cli_command1.yml

PLAY [cisco] *******************************************************************************

TASK [reboot ios device] *******************************************************************
ok: [Router]

PLAY RECAP *********************************************************************************
Router                    : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

OKパターン2:promptオプションを②confirm、①Save?の順番で定義

Playbook

OKパターン1のpromptオプションのリストデータを逆にした場合に、再起動できるか確認してみました。

---

- hosts: cisco
  gather_facts: no
  connection: network_cli

  tasks:
    - name: reboot ios device
      cli_command:
        command: reload
        check_all: True
        prompt:
          - 'confirm'
          - 'Save\?'
        answer:
          - 'y'
          - 'y'

実行結果

出力内容は割愛しますが、問題なく再起動できました。定義の順番は関係なさそうです。

NGパターン1:Save?に対しシングルクォーテーションなしのyesで回答

Playbook

設定保存するかSave? [yes/no]:で聞かれた時、シングルクォーテーションなしのyesで回答してみました。yesnoで答えてくれと言われているので、このパターンは一見問題なさそうです。

---

- hosts: cisco
  gather_facts: no
  connection: network_cli

  tasks:
    - name: reboot ios device
      cli_command:
        command: reload
        check_all: True
        prompt:
          - 'Save\?'
          - 'confirm'
        answer:
          - yes   # yからyesに変更。かつシングルクォーテーションを外す。
          - 'y'

実行結果

コマンドタイムアウトでエラー終了してしまいました。デバッグモードの途中結果を見ると、yestrueに変換されています。別の方法でも確認したところ、どうやらyesの代わりにTrueで回答し、そこで止まってしまったようです。

$ ansible-playbook -i inventory_3560 playbook_cli_command1.yml -vvv
(省略)
fatal: [Router]: FAILED! => {
    "changed": false,
    "invocation": {
        "module_args": {
            "answer": [
                true,
                "y"
            ],
            "check_all": true,
            "command": "reload",
            "prompt": [
                "Save\\?",
                "confirm"
            ],
            "sendonly": false
        }
    },
    "msg": "command timeout triggered, timeout value is 30 secs.\nSee the timeout setting options in the Network Debug and Troubleshooting Guide."
}

PLAY RECAP *********************************************************************************
Router                    : ok=0    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0

NGパターン2:Save?をダブルクォーテーションで定義

Playbook

これまでのPlaybookはすべての値をシングルクォーテーションで囲っていましたが、代わりにSave?をダブルクォーテーションで囲ってみます。多くのケースでは、どちらで囲っても問題なく、何となく選んでいるケースが多いと思います。

---

- hosts: cisco
  gather_facts: no
  connection: network_cli

  tasks:
    - name: reboot ios device
      cli_command:
        command: reload
        check_all: True
        prompt:
          - "Save\?"   # シングルクォーテーションからダブルクォーテーションに変更
          - 'confirm'
        answer:
          - 'y'
          - 'y'

実行結果

シンタックスエラーとなってしまいました。ダブルクォーテーション内でエスケープ処理する場合、"Save\\?"とすれば問題なさそうです。(使い分けがややこしいですね!)

$ ansible-playbook -i inventory_3560 playbook_cli_command1.yml -vvv
(省略)
ERROR! Syntax Error while loading YAML.
  found unknown escape character '?'

The error appears to be in '/home/centos/venv/ansible/playbook_cli_command1.yml': line 13, column 19, but may
be elsewhere in the file depending on the exact syntax problem.

The offending line appears to be:

        prompt:
          - "Save\?"
                  ^ here

そもそもの話になってしまいますが、再起動は、直前に設定保存すればプロンプト処理は1回で済むため、わざわざcli_commandモジュールを使う必要はないかもしれません。
他の応用例として、拡張Tracerouteの実行例もメモしておきます。

おまけ:拡張Tracerouteの実行例

CLIで実行した時のメッセージ

Router#traceroute
Protocol [ip]: ip
Target IP address: 192.168.100.1
Source address: 192.168.100.24
Numeric display [n]: n
Timeout in seconds [3]: 3
Probe count [3]: 3
Minimum Time to Live [1]: 1
Maximum Time to Live [30]: 10
Port Number [33434]: 33434
Loose, Strict, Record, Timestamp, Verbose[none]:
Type escape sequence to abort.
Tracing the route to 192.168.100.1

  1 192.168.100.1 0 msec 0 msec 0 msec

Playbook

---

- hosts: cisco
  gather_facts: no
  connection: network_cli

  tasks:
    - name: issue extended traceroute command
      cli_command:
        command: traceroute
        check_all: True
        prompt:
          - 'Protocol'
          - 'Target'
          - 'Source'
          - 'Numeric'
          - 'Timeout'
          - 'Probe'
          - 'Minimum'
          - 'Maximum'
          - 'Port'
          - 'Loose'
        answer:
          - 'ip'
          - '192.168.100.1'
          - '192.168.100.24'
          - 'n'
          - '3'
          - '3'
          - '1'
          - '10'
          - '33434'
          - ''
      register: result

    - name: debug
      debug:
        msg: "{{ result }}"

実行結果

$ ansible-playbook -i inventory_3560 playbook_cli_traceroute.yml

PLAY [cisco] *******************************************************************************

TASK [issue extended traceroute command] *******************************************************************
ok: [Router]

TASK [debug] *******************************************************************************
ok: [Router] => {
    "msg": {
        "changed": false,
        "failed": false,
        "stdout": "Protocol [ip]: ip\nTarget IP address: 192.168.100.1\nSource address: 192.168.100.24\nNumeric display [n]: n\nTimeout in seconds [3]: 3\nProbe count [3]: 3\nMinimum Time to Live [1]: 1\nMaximum Time to Live [30]: 10\nPort Number [33434]: 33434\nLoose, Strict, Record, Timestamp, Verbose[none]: \nType escape sequence to abort.\nTracing the route to 192.168.100.1\n\n  1 192.168.100.1 0 msec 0 msec 0 msec",
        "stdout_lines": [
            "Protocol [ip]: ip",
            "Target IP address: 192.168.100.1",
            "Source address: 192.168.100.24",
            "Numeric display [n]: n",
            "Timeout in seconds [3]: 3",
            "Probe count [3]: 3",
            "Minimum Time to Live [1]: 1",
            "Maximum Time to Live [30]: 10",
            "Port Number [33434]: 33434",
            "Loose, Strict, Record, Timestamp, Verbose[none]: ",
            "Type escape sequence to abort.",
            "Tracing the route to 192.168.100.1",
            "",
            "  1 192.168.100.1 0 msec 0 msec 0 msec"
        ]
    }
}

PLAY RECAP *********************************************************************************
Router                    : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

AnsibleでCisco FTDを操作する

Ciscoが提供する次世代ファイアウォール Firepower Threat Defence(FTD)を操作するためのAnsibleモジュールftd_configurationを使って、REST API経由でネットワークオブジェクトやアクセスルールの追加を行ってみました。

FTD API概要

FTDの設定変更方法としては、CLIやWeb GUIに加え、バージョン6.2.3からREST APIもサポートされています。GUIREST APIの場合は、管理ツール経由で操作する形になります。

FTDの管理ツールは以下の3種類があります。
1. Firepower Management Center (FMC)
複数のデバイスを一括管理可能。大規模環境向き。(ただし2や3との共存は不可。)
2. Firepower Device Manager (FDM)
単一のデバイスを”On Box(同一筐体上)”で管理。中~小規模環境向き。
3. Cisco Defense Orchestrator (CDO)
クラウドベースで複数のデバイスを管理。

これらの内、ftd_xxxモジュールは、2つめのFDM経由で操作するモジュールになります。
(1や3のAnsibleモジュールは、2019年11月時点でリリースされていません。)

f:id:tsukino_netwkr:20191117001155p:plain
FDM画面

API経由で操作できる項目は以下の通りです。

  • Interface Configuration (incl. BVI, Sub-interfaces)
  • Routing (static routing only)
  • VPN (Site-to-site and Remote Access)
  • System Settings (Interface, NTP, Hostname, etc.)
  • Policy Objects, such as Networks, Ports, Security Zones, Applications, URLs, Geolocation
  • Policies (SSL, Identity, Security Intel, Blacklists, NAT, Access, Intrusion)
  • Talos updates
  • Smart Licensing
  • Backup Restore
  • Troubleshooting

参考URL: DevNet Learning Labs - Firepower Threat Defense API

FTD Ansibleモジュール概要

FTD用のモジュールは、執筆時点で以下の4つがあります。

  1. ftd_configuration
    REST API経由でFTDを操作するモジュール
  2. ftd_file_download
    HTTP(S)経由でFTDから各種ファイル(pending changes, disk files, certificates, troubleshoot reports, and backup)をダウンロードするモジュール
  3. ftd_file_upload
    HTTP(S)経由でFTDへ各種ファイルをアップロードするモジュール
  4. ftd_install
    ROMMONイメージやFTD pkgイメージをインストールするモジュール

一見少なく見えますが、1つ目のftd_configurationモジュールで、利用可能なAPIをすべてAnsibleから実行できるようです。具体的には、operationオプションで、各設定項目名の頭に以下を付けることで、CRUDに近い形で操作できます。

  • get - fetches a object by its ID (e.g., getNetworkObject);
  • getList - fetches a list of objects matching given criteria (e.g., getNetworkObjectList). For example, it can be used to find an object by name or other attribute when its ID is not known;
  • add - creates a new object (e.g., addNetworkObject);
  • edit - updates an existing object (e.g., editNetworkObject). ID of the existing object is a mandatory attribute for this operation type;
  • delete - deletes an existing object by its ID (e.g., deleteNetworkObject);
  • upsert - creates a new object if it does not exist, or updates it when the object already exists (e.g., upsertNetworkObject). By default, upsert operation looks for an object by its name, but the filtering criteria can be adjusted. See Upsert operation for more details;

この中でupsertは、存在しない場合新規作成(Create)したり、既に存在する場合に更新(Update)できるもので、メンテナンス時は使い勝手が良さそうです。 詳細は、Cisco DevNet - FTD AnsibleのUser GuideやOperationsを参照願います。

その他、Playbookを作る上で参考になりそうなサイトを記載しておきます。

  1. Ansible Network modules - Ftd
    Ansibleの公式ドキュメント。まず初めに目を通す。
  2. GitHub - FTD Ansible / samples
    Playbookサンプルが豊富。どのバージョンで動くかもまとめられていて便利。
  3. FDM - API Explorer https://<FDMのIPアドレス>/#/api-explorer
    REST APIの詳細を確認可能。

用意した環境

  • FTD:FTDv 6.4.0 VMware install package
    VMware Workstation Player 15.5.0上に構築
    ※ URLベースのアクセスルールを設定する場合は、URL Licenseの有効化が必要
  • Ansible:2.9.0

Cisco DevNet Sandbox「FirePower Threat Defense REST API (6.5)」だと、ネットワークオブジェクトの作成は出来るものの、アクセスルールの作成がエラーで出来ませんでした。

Inventoryファイル

以下の通り作成しました。

  • inventory_ftd_vm
[ftd]
firepower ansible_host=192.168.100.45

[ftd:vars]
ansible_network_os=ftd
ansible_user=admin
ansible_password=<FDMのパスワード>
ansible_httpapi_use_ssl=yes
ansible_httpapi_validate_certs=no

Playbook① ポリシー作成

  1. ホストオブジェクトの作成
    1つ目のタスクで、operationオプションupsertNetworkObjectを指定し、IPアドレス192.168.2.1に紐づくネットワークオブジェクトAnsible-network-hostを作成しています。
    2つ目のタスクで、operationオプションgetNetworkObjectを指定し、objId(オブジェクトID)をキーに情報取得を行い、3つ目のタスクで結果を表示しています。
  2. アクセスルールの作成
    後半は、operationオプションupsertAccessRuleで、Ansible-network-hostからの通信を許可するアクセスルールを設定し、同様に結果を表示しています。

playbook_ftd_acl_add2.yml

---

- hosts: ftd
  gather_facts: no
  connection: httpapi

  tasks:
    - name: Create a network object
      ftd_configuration:
        operation: upsertNetworkObject
        data:
          name: Ansible-network-host
          description: From Ansible with love
          subType: HOST
          value: 192.168.2.1
          dnsResolution: IPV4_AND_IPV6
          type: networkobject
        register_as: hostNetwork

    - name: Get network object
      ftd_configuration:
        operation: getNetworkObject
        path_params:
          objId: "{{ hostNetwork['id'] }}"
        register_as: network_obj

    - name: Display network object
      debug:
        msg: "{{ network_obj }}"

    - name: Create an access rule allowing traffic from Ansible-network-host
      ftd_configuration:
        operation: upsertAccessRule
        data:
          name: Allow_Ansible_Traffic
          type: accessrule
          sourceNetworks:
            - "{{ hostNetwork }}"
          ruleAction: PERMIT
          eventLogAction: LOG_BOTH
        path_params:
          parentId: default
        register_as: accessRule

    - name: Get access rule
      ftd_configuration:
        operation: getAccessRule
        path_params:
          parentId: default
          objId: "{{ accessRule['id'] }}"
        register_as: access_rule

    - name: Display access rule
      debug:
        msg: "{{ access_rule }}"

実行結果① ポリシー作成

changed=2となり、問題なくオブジェクトとアクセスルールが設定されました。
ちなみに、同じPlaybookをもう一回実行すると、changed=0になりました。また、operationaddNetworkObjectaddAccessRuleとした場合も同様の結果だったため、冪等性は担保されているようです。

$ ansible-playbook -i inventory_ftd_vm playbook_ftd_acl_add2.yml

PLAY [ftd] **********************************************************************************************************************************

TASK [Create a network object] **************************************************************************************************************
changed: [firepower]

TASK [Get network object] *******************************************************************************************************************
ok: [firepower]

TASK [Display network object] ***************************************************************************************************************
ok: [firepower] => {
    "msg": {
        "description": "From Ansible with love",
        "dnsResolution": "IPV4_AND_IPV6",
        "id": "c9b4138b-087c-11ea-948b-9bbf3850c347",
        "isSystemDefined": false,
        "links": {
            "self": "https://192.168.100.45/api/fdm/v3/object/networks/c9b4138b-087c-11ea-948b-9bbf3850c347"
        },
        "name": "Ansible-network-host",
        "subType": "HOST",
        "type": "networkobject",
        "value": "192.168.2.1",
        "version": "hs4yv7xe7yk34"
    }
}

TASK [Create an access rule allowing traffic from Ansible-network-host] *********************************************************************
changed: [firepower]

TASK [Get access rule] **********************************************************************************************************************
ok: [firepower]

TASK [Display access rule] ******************************************************************************************************************
ok: [firepower] => {
    "msg": {
        "destinationNetworks": [],
        "destinationPorts": [],
        "destinationZones": [],
        "embeddedAppFilter": null,
        "eventLogAction": "LOG_BOTH",
        "filePolicy": null,
        "id": "cc1ef90e-087c-11ea-948b-5f82967c1861",
        "identitySources": [],
        "intrusionPolicy": null,
        "links": {
            "self": "https://192.168.100.45/api/fdm/v3/policy/accesspolicies/default/accessrules/cc1ef90e-087c-11ea-948b-5f82967c1861"
        },
        "logFiles": false,
        "name": "Allow_Ansible_Traffic",
        "ruleAction": "PERMIT",
        "ruleId": 268435462,
        "sourceNetworks": [
            {
                "id": "c9b4138b-087c-11ea-948b-9bbf3850c347",
                "name": "Ansible-network-host",
                "type": "networkobject",
                "version": "hs4yv7xe7yk34"
            }
        ],
        "sourcePorts": [],
        "sourceZones": [],
        "syslogServer": null,
        "type": "accessrule",
        "urlFilter": null,
        "users": [],
        "version": "jk3l2ohh5ku2v"
    }
}

PLAY RECAP **********************************************************************************************************************************
firepower                  : ok=6    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

FDMのWeb GUI画面でも、問題なく設定されている事が分かります。

f:id:tsukino_netwkr:20191116234720p:plain
FDM画面(ネットワークオブジェクト設定)
f:id:tsukino_netwkr:20191116234817p:plain
FDM画面(ポリシー設定)

Playbook② デプロイ

この段階では、設定がFTDに反映されておらず、反映するにはデプロイが必要です。

f:id:tsukino_netwkr:20191116233805p:plain
FDM画面(Deploy前)

以下のPlaybookでデプロイを行います。

  • inventory_ftd_deploy.yml
---

- hosts: ftd
  gather_facts: no
  connection: httpapi

  tasks:
    - name: Fetch pending changes
      ftd_configuration:
        operation: getBaseEntityDiffList
        register_as: pending_changes

    - name: Complete playbook when nothing to deploy
      meta: end_play
      when: pending_changes | length == 0

    - name: Start deployment
      ftd_configuration:
        operation: addDeployment
        register_as: deployment_job

    - name: Poll deployment status until the job is finished
      ftd_configuration:
        operation: getDeployment
        path_params:
          objId: '{{ deployment_job.id }}'
        register_as: deployment_status
      until: deployment_status.endTime != -1
      retries: 100
      delay: 3

    - name: Stop the playbook if the deployment failed
      fail:
        msg: 'Deployment failed. Status: {{ deployment_status.statusMessages }}'
      when: deployment_status.state != 'DEPLOYED'

出力結果② デプロイ

$ ansible-playbook -i inventory_ftd_vm playbook_ftd_deploy.yml

PLAY [ftd] **********************************************************************************************************************************

TASK [Fetch pending changes] ****************************************************************************************************************
ok: [firepower]

TASK [Start deployment] *********************************************************************************************************************
changed: [firepower]

TASK [Poll deployment status until the job is finished] *************************************************************************************
FAILED - RETRYING: Poll deployment status until the job is finished (100 retries left).
FAILED - RETRYING: Poll deployment status until the job is finished (99 retries left).
FAILED - RETRYING: Poll deployment status until the job is finished (98 retries left).
FAILED - RETRYING: Poll deployment status until the job is finished (97 retries left).
FAILED - RETRYING: Poll deployment status until the job is finished (96 retries left).
FAILED - RETRYING: Poll deployment status until the job is finished (95 retries left).
FAILED - RETRYING: Poll deployment status until the job is finished (94 retries left).
FAILED - RETRYING: Poll deployment status until the job is finished (93 retries left).
ok: [firepower]

TASK [Stop the playbook if the deployment failed] *******************************************************************************************
skipping: [firepower]

PLAY RECAP **********************************************************************************************************************************
firepower                  : ok=3    changed=1    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0  

FDM画面でも、デプロイに成功し、保留中の変更がない事が確認できます。

f:id:tsukino_netwkr:20191116234611p:plain
FDM画面(Deploy後)

最後にFTDのCLI画面で、設定が反映されたことを確認します。

> show running-config
: Saved

:
: Serial Number: XXXXXXXX
: Hardware:   NGFWv, 8192 MB RAM, CPU Lynnfield 1991 MHz, 1 CPU (4 cores)
:
NGFW Version 6.4.0
!
hostname firepower
enable password ***** encrypted
strong-encryption-disable
names
no mac-address auto

!
interface GigabitEthernet0/0
 nameif outside
 cts manual
  propagate sgt preserve-untag
  policy static sgt disabled trusted
 security-level 0
 ip address 192.168.100.46 255.255.255.0
!
interface GigabitEthernet0/1
 nameif inside
 cts manual
  propagate sgt preserve-untag
  policy static sgt disabled trusted
 security-level 0
 ip address 10.1.1.2 255.255.255.0
!
(中略)
object network any-ipv4
 subnet 0.0.0.0 0.0.0.0
object network any-ipv6
 subnet ::/0
object network OutsideIPv4Gateway
 host 192.168.100.1
object network OutsideIPv4DefaultRoute
 subnet 0.0.0.0 0.0.0.0
object network Ansible-network-host
 host 192.168.2.1
object-group service |acSvcg-268435457
 service-object ip
object-group service |acSvcg-268435462
 service-object ip
access-list NGFW_ONBOX_ACL remark rule-id 268435457: ACCESS POLICY: NGFW_Access_Policy
access-list NGFW_ONBOX_ACL remark rule-id 268435457: L5 RULE: Inside_Outside_Rule
access-list NGFW_ONBOX_ACL advanced trust object-group |acSvcg-268435457 ifc inside any ifc outside any rule-id 268435457 event-log both
access-list NGFW_ONBOX_ACL remark rule-id 268435462: ACCESS POLICY: NGFW_Access_Policy
access-list NGFW_ONBOX_ACL remark rule-id 268435462: L5 RULE: Allow_Ansible_Traffic
access-list NGFW_ONBOX_ACL advanced permit object-group |acSvcg-268435462 object Ansible-network-host any rule-id 268435462 event-log both
access-list NGFW_ONBOX_ACL remark rule-id 1: ACCESS POLICY: NGFW_Access_Policy
access-list NGFW_ONBOX_ACL remark rule-id 1: L5 RULE: DefaultActionRule
access-list NGFW_ONBOX_ACL advanced deny ip any any rule-id 1
(中略)

最後に

今回試した範囲では、FTD 6.4.0では正しく設定が行われ、冪等性も問題ありませんでした。
まだ触り始めたばかりで不明点が多いので、引き続き勉強していきたいと思います。

AnsibleでCheck Pointを操作する(2.9.0版) ②ポリシー設定変更編

前回に続き、Ansible2.9.0でリリースされたCheck Pointモジュールを使って、ポリシー設定変更を行っていきます。

f:id:tsukino_netwkr:20190729232317p:plain

設定変更内容

下図の、④User PCからL3SW(hqdist1A)へのSSH version2、ICMPアクセス許可設定を行ってみます。

f:id:tsukino_netwkr:20191110135021p:plain
テスト環境構成

Inventoryファイル

以下の通り作成しました。

  • inventory_cp_vm
[checkpoint]
smart1 ansible_host=192.168.100.70

[checkpoint:vars]
ansible_network_os=checkpoint
ansible_user=admin
ansible_password=<管理サーバのパスワード>
ansible_httpapi_use_ssl=yes
ansible_httpapi_validate_certs=no

Playbook① ホストオブジェクトの作成

User_PCとhqdist1Aのホストオブジェクトを作成します。モジュールは「cp_mgmt_host」を使用します。設定後、モジュール「cp_mgmt_host_facts」で内容を確認します。
その後、モジュール「cp_mgmt_publish」でポリシーの公開、モジュール「cp_mgmt_install_policy」でポリシーのインストールを行います。 この時、インストール対象機器と内容(Access ControlとTheat Prevention)も指定可能です。
簡単のため、変数はすべてPlaybook内に記載していますが、可用性を考慮するとInventoryファイルや変数定義ファイルに記載すべきかと思います。

  • playbook_cp_host_add.yml
---

- hosts: checkpoint
  gather_facts: no
  connection: httpapi

  tasks:
    - name: Create host object1
      cp_mgmt_host:
        name: User_PC   # ホストオブジェクト名1
        ip_address: 10.1.1.100

    - name: Get host object facts1
      cp_mgmt_host_facts:
        name: User_PC
      register: result_host1

    - name: debug1
      debug:
        msg: "{{ result_host1 }}"

    - name: Create host object2
      cp_mgmt_host:
        name: hqdist1A   # ホストオブジェクト名2
        ip_address: 192.168.100.24

    - name: Get host object facts2
      cp_mgmt_host_facts:
        name: hqdist1A
      register: result_host2

    - name: debug2
      debug:
        msg: "{{ result_host2 }}"

    - name: Publish policy
      cp_mgmt_publish:

    - name: Install policy
      cp_mgmt_install_policy:
        access: true
        threat_prevention: true
        policy_package: standard
        targets:
           - gw-2fd599

実行結果① ホストオブジェクトの作成

2つとも問題なく作成されました。

$ ansible-playbook -i inventory_cp_vm playbook_cp_host_add.yml

PLAY [checkpoint] ***************************************************************************************************************************

TASK [Create host object1] ******************************************************************************************************************
changed: [smart1]

TASK [Get host object facts1] ***************************************************************************************************************
ok: [smart1]

TASK [debug1] *******************************************************************************************************************************
ok: [smart1] => {
    "msg": {
        "ansible_facts": {
            "host": {
                "color": "black",
                "comments": "",
                "domain": {
                    "domain-type": "domain",
                    "name": "SMC User",
                    "uid": "41e821a0-3720-11e3-aa6e-0800200c9fde"
                },
                "groups": [],
                "icon": "Objects/host",
                "interfaces": [],
                "ipv4-address": "10.1.1.100",
                "meta-info": {
                    "creation-time": {
                        "iso-8601": "2019-11-10T15:31+0900",
                        "posix": 1573367516326
                    },
                    "creator": "admin",
                    "last-modifier": "admin",
                    "last-modify-time": {
                        "iso-8601": "2019-11-10T15:31+0900",
                        "posix": 1573367516326
                    },
                    "lock": "locked by current session",
                    "validation-state": "ok"
                },
                "name": "User_PC",
                "nat-settings": {
                    "auto-rule": false
                },
                "read-only": false,
                "tags": [],
                "type": "host",
                "uid": "9c5afc3c-aa27-4714-871f-ea6b012b8ec4"
            }
        },
        "changed": false,
        "failed": false
    }
}

TASK [Create host object2] ******************************************************************************************************************
changed: [smart1]

TASK [Get host object facts2] ***************************************************************************************************************
ok: [smart1]

TASK [debug2] *******************************************************************************************************************************
ok: [smart1] => {
    "msg": {
        "ansible_facts": {
            "host": {
                "color": "black",
                "comments": "",
                "domain": {
                    "domain-type": "domain",
                    "name": "SMC User",
                    "uid": "41e821a0-3720-11e3-aa6e-0800200c9fde"
                },
                "groups": [],
                "icon": "Objects/host",
                "interfaces": [],
                "ipv4-address": "192.168.100.24",
                "meta-info": {
                    "creation-time": {
                        "iso-8601": "2019-11-10T15:32+0900",
                        "posix": 1573367524244
                    },
                    "creator": "admin",
                    "last-modifier": "admin",
                    "last-modify-time": {
                        "iso-8601": "2019-11-10T15:32+0900",
                        "posix": 1573367524244
                    },
                    "lock": "locked by current session",
                    "validation-state": "ok"
                },
                "name": "hqdist1A",
                "nat-settings": {
                    "auto-rule": false
                },
                "read-only": false,
                "tags": [],
                "type": "host",
                "uid": "77c34958-751e-425f-9e57-d78a5407c635"
            }
        },
        "changed": false,
        "failed": false
    }
}

TASK [Publish policy] ***********************************************************************************************************************
changed: [smart1]

TASK [Install policy] ***********************************************************************************************************************
changed: [smart1]

PLAY RECAP **********************************************************************************************************************************
smart1                     : ok=8    changed=4    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0  

Smart Console画面右のObjects barにも、2つのオブジェクトが表示されている事が分かります。

f:id:tsukino_netwkr:20191110153903p:plain
ホストオブジェクト作成後の画面

Playbook② ポリシーの作成

User_PCからhqdist1A向けのSSH version2およびICMP通信を許可する設定を行います。モジュールは「cp_mgmt_access_rule」を使用します。アクセスルール名は「Switch_access」とし、一番上にルールを挿入します。今回はオプション「position」で「1(文字列)」を指定していますが、「top」でも同じ結果になりました。またtrackオプションで、通信のログ取得を行うようにしています。
設定後、モジュール「cp_mgmt_access_rule_facts」で内容を確認しています。その後、先ほどと同様、ポリシーの公開とインストールを行っています。

  • playbook_cp_policy_add.yml
---

- hosts: checkpoint
  gather_facts: no
  connection: httpapi

  tasks:
    - name: Create access rule
      cp_mgmt_access_rule:
        layer: Network
        name: Switch_access   # アクセスルール名
        position: "1"   # ルールの挿入位置
        source: User_PC   # オブジェクト名 or any
        destination: hqdist1A   # オブジェクト名 or any
        service:
          - ssh_version_2
          - echo-request
        action: accept   # acceptで許可、dropで拒否
        track:
          type: Log

    - name: Get access rule facts
      cp_mgmt_access_rule_facts:
        layer: Network
        name: Switch_access   # アクセスルール名
      register: result_access_rule

    - name: debug
      debug:
        msg: "{{ result_access_rule }}"

    - name: Publish policy
      cp_mgmt_publish:

    - name: Install policy
      cp_mgmt_install_policy:
        access: true
        threat_prevention: true
        policy_package: standard
        targets:
           - gw-2fd599

実行結果② ポリシーの作成

こちらも問題なく作成されました。

$ ansible-playbook -i inventory_cp_vm playbook_cp_policy_add.yml

PLAY [checkpoint] ***************************************************************************************************************************

TASK [Create access rule] *******************************************************************************************************************
changed: [smart1]

TASK [Get access rule facts] ****************************************************************************************************************
ok: [smart1]

TASK [debug] ********************************************************************************************************************************
ok: [smart1] => {
    "msg": {
        "ansible_facts": {
            "access-rule": {
                "action": {
                    "domain": {
                        "domain-type": "data domain",
                        "name": "Check Point Data",
                        "uid": "a0bbbc99-adef-4ef8-bb6d-defdefdefdef"
                    },
                    "name": "Accept",
                    "type": "RulebaseAction",
                    "uid": "6c488338-8eec-4103-ad21-cd461ac2c472"
                },
                "action-settings": {
                    "enable-identity-captive-portal": false
                },
                "comments": "",
                "content": [
                    {
                        "domain": {
                            "domain-type": "data domain",
                            "name": "Check Point Data",
                            "uid": "a0bbbc99-adef-4ef8-bb6d-defdefdefdef"
                        },
                        "name": "Any",
                        "type": "CpmiAnyObject",
                        "uid": "97aeb369-9aea-11d5-bd16-0090272ccb30"
                    }
                ],
                "content-direction": "any",
                "content-negate": false,
                "custom-fields": {
                    "field-1": "",
                    "field-2": "",
                    "field-3": ""
                },
                "destination": [
                    {
                        "domain": {
                            "domain-type": "domain",
                            "name": "SMC User",
                            "uid": "41e821a0-3720-11e3-aa6e-0800200c9fde"
                        },
                        "ipv4-address": "192.168.100.24",
                        "name": "hqdist1A",
                        "type": "host",
                        "uid": "77c34958-751e-425f-9e57-d78a5407c635"
                    }
                ],
                "destination-negate": false,
                "domain": {
                    "domain-type": "domain",
                    "name": "SMC User",
                    "uid": "41e821a0-3720-11e3-aa6e-0800200c9fde"
                },
                "enabled": true,
                "install-on": [
                    {
                        "domain": {
                            "domain-type": "data domain",
                            "name": "Check Point Data",
                            "uid": "a0bbbc99-adef-4ef8-bb6d-defdefdefdef"
                        },
                        "name": "Policy Targets",
                        "type": "Global",
                        "uid": "6c488338-8eec-4103-ad21-cd461ac2c476"
                    }
                ],
                "layer": "8a5e96fb-c793-457f-b78f-c667074223a5",
                "meta-info": {
                    "creation-time": {
                        "iso-8601": "2019-11-10T15:48+0900",
                        "posix": 1573368497300
                    },
                    "creator": "admin",
                    "last-modifier": "admin",
                    "last-modify-time": {
                        "iso-8601": "2019-11-10T15:48+0900",
                        "posix": 1573368498132
                    },
                    "lock": "locked by current session",
                    "validation-state": "ok"
                },
                "name": "Switch_access",
                "service": [
                    {
                        "domain": {
                            "domain-type": "data domain",
                            "name": "Check Point Data",
                            "uid": "a0bbbc99-adef-4ef8-bb6d-defdefdefdef"
                        },
                        "name": "ssh_version_2",
                        "port": "22",
                        "type": "service-tcp",
                        "uid": "cd082d9a-44a6-4cef-a17d-5541029adfb3"
                    },
                    {
                        "domain": {
                            "domain-type": "data domain",
                            "name": "Check Point Data",
                            "uid": "a0bbbc99-adef-4ef8-bb6d-defdefdefdef"
                        },
                        "name": "echo-request",
                        "type": "service-icmp",
                        "uid": "97aeb40a-9aea-11d5-bd16-0090272ccb30"
                    }
                ],
                "service-negate": false,
                "source": [
                    {
                        "domain": {
                            "domain-type": "domain",
                            "name": "SMC User",
                            "uid": "41e821a0-3720-11e3-aa6e-0800200c9fde"
                        },
                        "ipv4-address": "10.1.1.100",
                        "name": "User_PC",
                        "type": "host",
                        "uid": "9c5afc3c-aa27-4714-871f-ea6b012b8ec4"
                    }
                ],
                "source-negate": false,
                "time": [
                    {
                        "domain": {
                            "domain-type": "data domain",
                            "name": "Check Point Data",
                            "uid": "a0bbbc99-adef-4ef8-bb6d-defdefdefdef"
                        },
                        "name": "Any",
                        "type": "CpmiAnyObject",
                        "uid": "97aeb369-9aea-11d5-bd16-0090272ccb30"
                    }
                ],
                "track": {
                    "accounting": false,
                    "alert": "none",
                    "per-connection": true,
                    "per-session": false,
                    "type": {
                        "domain": {
                            "domain-type": "data domain",
                            "name": "Check Point Data",
                            "uid": "a0bbbc99-adef-4ef8-bb6d-defdefdefdef"
                        },
                        "name": "Log",
                        "type": "Track",
                        "uid": "598ead32-aa42-4615-90ed-f51a5928d41d"
                    }
                },
                "type": "access-rule",
                "uid": "7ef33013-15ba-4fa6-94c5-08c4a17bc890",
                "vpn": [
                    {
                        "domain": {
                            "domain-type": "data domain",
                            "name": "Check Point Data",
                            "uid": "a0bbbc99-adef-4ef8-bb6d-defdefdefdef"
                        },
                        "name": "Any",
                        "type": "CpmiAnyObject",
                        "uid": "97aeb369-9aea-11d5-bd16-0090272ccb30"
                    }
                ]
            }
        },
        "changed": false,
        "failed": false
    }
}

TASK [Publish policy] ***********************************************************************************************************************
changed: [smart1]

TASK [Install policy] ***********************************************************************************************************************
changed: [smart1]

PLAY RECAP **********************************************************************************************************************************
smart1                     : ok=5    changed=3    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0 

Smart Console画面でも、作成したポリシーが一番上に表示されている事が分かります。

f:id:tsukino_netwkr:20191110155742p:plain
ポリシー作成後の画面

ちなみに、同じPlaybookをもう1回実行すると、エラーメッセージが表示されFailとなってしまいます。(ホストオブジェクトの場合も同じ。)設定済みの場合、「ok=1、changed=0」で次のタスクに進んでくれることを期待していたのですが、ここは改善の余地ありかもしれません。

$ ansible-playbook -i inventory_cp_vm playbook_cp_policy_add.yml

PLAY [checkpoint] ***************************************************************************************************************************

TASK [Create access rule] *******************************************************************************************************************
fatal: [smart1]: FAILED! => {"changed": false, "msg": {"code": "generic_internal_error", "message": "Internal error. For more info search for incident [f50b84fa-f190-41bf-88f6-1b31bb0f5f52] in log file"}}

PLAY RECAP **********************************************************************************************************************************
smart1                     : ok=0    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0  

Playbook③ ポリシーの削除

作成したポリシー「Switch_access」を削除します。以下のURLのExamplesを見る限り、モジュール「cp_mgmt_access_rule」のオプション「layer」と「name」で削除したいものを指定し、「state」を「absent」とすれば削除できるはずですが、なぜかオプション「destination」に適当な文字列「dummy」を入れないと削除できませんでした。 docs.ansible.com

  • playbook_cp_policy_del.yml
---

- hosts: checkpoint
  gather_facts: no
  connection: httpapi

  tasks:
    - name: Delete access rule
      cp_mgmt_access_rule:
        layer: Network
        name: Switch_access   # アクセスルール名
        destination: dummy   # オブジェクト名 or any
        state: absent

    - name: Publish
      cp_mgmt_publish:

    - name: Install policy
      cp_mgmt_install_policy:
        access: true
        threat_prevention: true
        policy_package: standard
        targets:
           - gw-2fd599

実行結果③ ポリシーの削除

$ ansible-playbook -i inventory_cp_vm playbook_cp_policy_del.yml

PLAY [checkpoint] ***************************************************************************************************************************

TASK [Delete access rule] *******************************************************************************************************************
changed: [smart1]

TASK [Publish] ******************************************************************************************************************************
changed: [smart1]

TASK [Install policy] ***********************************************************************************************************************
changed: [smart1]

PLAY RECAP **********************************************************************************************************************************
smart1                     : ok=3    changed=3    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

f:id:tsukino_netwkr:20191110174608p:plain
ポリシー削除後の画面

Playbook④ ホストオブジェクトの削除

最後に、作成したホストオブジェクト「User_PC」と「hqdist1A」を削除します。以下のURLのExamplesを見る限り、モジュール「cp_mgmt_host」のオプション「name」で削除したいものを指定し、「state」を「absent」とすれば削除できるはずですが、こちらもなぜかオプション「ip_address」に適当な文字列「dummy」を入れないと削除できませんでした。 docs.ansible.com

  • playbook_cp_host_del.yml
---
- hosts: checkpoint
  gather_facts: no
  connection: httpapi

  tasks:
    - name: Delete host object1
      cp_mgmt_host:
        name: User_PC   # ホストオブジェクト名
        ip_address: dummy
        state: absent

    - name: Delete host object2
      cp_mgmt_host:
        name: hqdist1A   # ホストオブジェクト名
        ip_address: dummy
        state: absent

    - name: Publish
      cp_mgmt_publish:

    - name: Install policy
      cp_mgmt_install_policy:
        access: true
        threat_prevention: true
        policy_package: standard
        targets:
           - gw-2fd599

実行結果④ ホストオブジェクトの削除

$ ansible-playbook -i inventory_cp_vm playbook_cp_host_del.yml

PLAY [checkpoint] ***************************************************************************************************************************

TASK [Delete host object1] ******************************************************************************************************************
changed: [smart1]

TASK [Delete host object2] ******************************************************************************************************************
changed: [smart1]

TASK [Publish] ******************************************************************************************************************************
changed: [smart1]

TASK [Install policy] ***********************************************************************************************************************
changed: [smart1]

PLAY RECAP **********************************************************************************************************************************
smart1                     : ok=4    changed=4    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

f:id:tsukino_netwkr:20191110175050p:plain
ホストオブジェクト削除後の画面

最後に

今回試した限りでは、Playbookを2回以上実行した場合や、削除時の動作に怪しい点がありました。コードを読んでみて、もし原因が分かったらアップデートしたいと思います。また、今後他のモジュールも試してみたいと思います。

AnsibleでCheck Pointを操作する(2.9.0版) ①セットアップ編

前回の記事で、Ansible2.8.0を使ってCheck Pointのポリシー設定変更を行いました。

AnsibleでCheck Pointを操作する

f:id:tsukino_netwkr:20190729232317p:plain

2019年10月末にリリースされたAnsible2.9.0では、これまでの9つのモジュール(checkpoint_xxx)に加え、90のモジュール(cp_xxx)が追加され、合計で99のモジュールが揃いました。
本記事では、新しいモジュールを使ってみる前に、環境のセットアップ手順を備忘録としてメモしておきます。

用意した環境

今回はAWS上ではなく、Windows10のVMware Workstation上にSecurity Gateway(ファイアウォール)とSecurity Management(管理サーバ)を兼ねたVM1を立てました(下図)。
合わせて、Workstation上にAnsible用のVM2とUser PC用のVM3を準備しました。VM3はポリシーテスト用に作ったVMで、なくてもAnsibleを使った操作確認は可能です。

f:id:tsukino_netwkr:20191110135021p:plain
テスト環境構成
OSイメージは、Check Pointサイトからダウンロードできる無償評価版(R80.10)を利用しました。トライアル期間は1ヶ月です。 supportcenter.checkpoint.com

セットアップ手順

手順1. 仮想マシンの作成

  1. VMware Workstationの新規仮想マシン作成ウィザードを開きます。イメージファイルは、ダウンロードしたisoファイル「Check_Point_R80.10_T462_Gaia.iso」を指定します。
  2. ゲストOSの選択で、ゲストOSを「その他」、バージョンを「その他」に指定。
  3. 任意の仮想マシン名を指定。今回は「Check_Point_test」としています。
  4. ディスク容量を100GBに指定。(テスト用なので、もっと少なくて良いかも知れません。)
  5. ハードウェアをカスタマイズをクリックし、プロセッサのコア数を2、メモリを6GBにカスタマイズ。Release Notes R80.10を見ると、推奨リソースは以下の通りのようです。 f:id:tsukino_netwkr:20191110005555p:plain
  6. ネットワークアダプタをブリッジ接続に変更。さらにネットワークアダプタ2を追加し、LANセグメントを指定。
  7. 設定が終わったら、完了をクリック。
    f:id:tsukino_netwkr:20191110111546p:plain
    仮想マシン設定画面

※AnsibleやUser PCの仮想マシン作成手順は割愛します。

手順2. Check Pointのインストール

  1. VMware Workstationで、手順1で作成した仮想マシンを再生します。
  2. インストール開始画面が出てきたら、「Install Gaia on a system listed in sk77660」を選択。
    f:id:tsukino_netwkr:20191110022750p:plain
    インストール開始画面
  3. 続く画面でインストールを開始して問題ないか聞かれるので、OKをクリックします。
    f:id:tsukino_netwkr:20191110025735p:plain
    インストール開始画面2
  4. キーボード設定をJapaneseに指定。
    f:id:tsukino_netwkr:20191110025843p:plain
    キーボード選択画面
  5. パーティション設定は、今回はSystem-rootを22GB、Logsを20GBに設定しました。
    f:id:tsukino_netwkr:20191110030008p:plain
    パーティション設定画面
  6. adminアカウントのパスワードを設定します。
    f:id:tsukino_netwkr:20191110030108p:plain
    アカウント設定画面
  7. マネジメントポートを、eth0(外部セグメント)に指定します。
    f:id:tsukino_netwkr:20191110030220p:plain
    マネジメントポート設定画面
  8. マネジメントポートのIPアドレスを指定します。今回は固定IPにしました。
    f:id:tsukino_netwkr:20191110030347p:plain
    マネジメントインターフェース(eth0)設定
  9. 最後に、インストールして問題ないか聞かれるので、OKをクリックします。
    f:id:tsukino_netwkr:20191110030506p:plain
    確認画面
  10. インストール完了後、リブートを行います。
    f:id:tsukino_netwkr:20191110030829p:plain
    インストール完了画面
  11. リブート後、ログイン画面が出てきたら、インストール成功です。
    f:id:tsukino_netwkr:20191110031115p:plain
    初期ログイン画面

手順3. Gaiaポータルの初回設定

  1. Gaiaポータル(https://[マネジメントIPアドレス])にログインします。※自分の環境では、ChromeFireFoxの場合ログイン後に何も表示されなくなったため、Edgeを使いました。
    f:id:tsukino_netwkr:20191110031319p:plain
    Gaiaログイン画面
  2. Nextを選択。
    f:id:tsukino_netwkr:20191110031452p:plain
    Gaia初回設定開始画面
  3. そのままNextを選択。
    f:id:tsukino_netwkr:20191110031837p:plain
    デプロイメントオプション画面
  4. 指定したIPアドレスがセットされている事を確認し、そのままNextを選択。
    f:id:tsukino_netwkr:20191110032009p:plain
    マネジメント接続
  5. eth1のIPアドレスを設定します。
    f:id:tsukino_netwkr:20191110032150p:plain
    インターフェース設定画面
  6. DNSサーバを設定します。必要に応じて、プロキシサーバも設定します。
    f:id:tsukino_netwkr:20191110032316p:plain
    DNS/プロキシ設定画面
  7. 日本時間になっている事を確認し、Nextを選択。
    f:id:tsukino_netwkr:20191110032421p:plain
    日時設定画面
  8. Security Gateway and/or Security Managementを選択。
    f:id:tsukino_netwkr:20191110032521p:plain
    インストールタイプ設定画面
  9. Security GatewayとSecurity Management両方にチェックが入っている事を確認し、Nextを選択。
  10. Security Managementの管理パスワードを設定します。今回は、手順2で設定したadminパスワードを使います。
    f:id:tsukino_netwkr:20191110032742p:plain
    Security Management 管理パスワード設定画面
  11. Security ManagementへログインできるGUIクライアントを設定します。今回はテスト環境なので、すべてのIPアドレスにしました。
    f:id:tsukino_netwkr:20191110033001p:plain
    Security Management GUIクライアント設定画面
  12. 最後にFinishボタンを選択します。
    f:id:tsukino_netwkr:20191110033140p:plain
    初回設定ウィザードサマリ画面
  13. 設定とリブートが完了するまで待ちます。
    f:id:tsukino_netwkr:20191110033733p:plain
    設定中の画面
  14. リブート後、adminアカウントで再ログインします。Security GatewayがPlatform: VMwareにインストールされた事が確認できます。
    f:id:tsukino_netwkr:20191110033847p:plain
    初回設定後のログイン後画面

手順4. Smart Consoleのインストール、Security Managementへのアクセス

  1. 先ほどの画面の上にある「Management Software Blades using SmartConsole ↓ Download Now!」をクリックします。
  2. ダウンロードしたSmart Consoleのexeファイルをインストールします。
  3. インストール後、アイコンをクリックし、adminアカウントでSecurity Managementにアクセスします。
    f:id:tsukino_netwkr:20191110035213p:plain
    Smart Consoleログイン画面

手順5. Security Gatewayのポリシー設定変更

初期状態では、Firewallポリシーがデフォルトで拒否となっています。そのため、冒頭のテスト環境構成で記載した通信の内、①の自身から外部向けの通信は可能ですが、②③のCheck Point向けや④のCheck Pointを通過する通信はできません。
以降で②③の通信許可設定を行います。

  1. ホストグループの作成
    • Smart Console画面右のObjects Barから、New→Hostをクリックします。
    • 以下の通り、オブジェクト名を「Ansible」とし、AnsibleのIPアドレスを指定します。
      f:id:tsukino_netwkr:20191110113907p:plain
      ホストグループの作成
    • 加えて、ホストOS(Windows10)からもSSH/HTTPSアクセスできるよう、オブジェクト名「Console_PC」を作成しておきます。
  2. ポリシーの作成
    • 画面上のAdd rule aboveをクリックし、以下のNo.1,2の通り設定を行います。(No.3はデフォルトの拒否設定です。)
      f:id:tsukino_netwkr:20191110120050p:plain
      ポリシー設定画面
  3. セッションの公開
    • 画面一番上のPublishをクリックし、他のユーザが編集内容を閲覧できる状態にします。
      f:id:tsukino_netwkr:20191110114858p:plain
      セッション公開画面
  4. ポリシーのインストール
    • 画面一番上のInstall Policyをクリックし、上記の設定を確定します。(公開とインストールを同時に行うことも可能です。)
      f:id:tsukino_netwkr:20191110115103p:plain
      ポリシーインストール画面

手順6. Security ManagementへのHotfix適用

Ansible2.9.0でリリースされたCheck Pointモジュールを使うには、以下のHotfixの適用が必要なため、インストール作業を行います。

supportcenter.checkpoint.com

  1. Gaiaポータル(https://[マネジメントIPアドレス])にログインし、Software Updatesの右側のリンクをクリックします。
  2. [重要!] AnsibleのHotfix適用前に、これまでのHotfixをまとめたパッケージ「R80.10 Jumbo Hotfix Accumulator GA (Take 225)」をインストールしないと、後続の手順でAPIの有効化に失敗してしまいます。「Install Update」をクリックし、必ず先にインストールしておきます。
    f:id:tsukino_netwkr:20191110122512p:plain
    推奨パッケージ一覧画面
  3. 自動でダウンロード、インストール、リブートが行われますので、完了まで待ちます。
  4. 再度ログインし、先ほどのパッケージ一覧画面右の「Add Hotfixes from the Cloud」をクリックし、検索バーに「Check Point R80.10 JHF T245 Ansible Hotfix for sk114661」と入力して検索を行います。
    f:id:tsukino_netwkr:20191110120839p:plain
    Hotfix追加画面
  5. 出てきた候補をクリックし、パッケージが追加された後、「Install Update」をクリックします。
  6. リブート完了まで待ちます。

手順7. API設定

AnsibleからAPIを叩けるよう、Check PointにSSHログインの上、Expertモードで設定を行います。

1.Expertパスワードを設定の上、Expertモードに移行します。

gw-2fd599> lock database override
gw-2fd599> set expert-password
Enter new expert password:
Enter new expert password (again):
gw-2fd599> expert
Enter expert password:


Warning! All configurations should be done through clish
You are in expert mode now.

[Expert@gw-2fd599:0]#

2.APIサービスはデフォルトで停止しているため、コマンド「api start」で開始します。

[Expert@gw-2fd599:0]# api start
2019-Nov-10 12:22:02 - Starting API...
. . . . . . .
2019-Nov-10 12:22:38 - API started successfully.

3.コマンド「mgmt_cli ~」ですべてのIPアドレスからのAPIコール許可設定を行います。

[Expert@gw-2fd599:0]# mgmt_cli -r true set api-settings accepted-api-calls-from "All IP addresses" --domain 'System Data'


---------------------------------------------
Time: [13:16:58] 10/11/2019
---------------------------------------------
"Publish operation"  in progress  (60%)


---------------------------------------------
Time: [13:17:08] 10/11/2019
---------------------------------------------
"Publish operation"  succeeded  (100%)

4.コマンド「api restart」でAPIサービス再起動します。

[Expert@gw-2fd599:0]# api restart
2019-Nov-10 13:17:14 - Stopping API...
2019-Nov-10 13:17:16 - API stopped successfully.
2019-Nov-10 13:17:16 - Starting API...
. . . . . . . . . . . . . .
2019-Nov-10 13:18:35 - API started successfully.

5.コマンド「api status」で、APIプロセスがStartedとなり、「API readiness test SUCCESSFUL.」と表示されれば成功です。

[Expert@gw-2fd599:0]# api status

API Settings:
---------------------
Accessibility:                      Require all granted
Automatic Start:                    Disabled

Processes:

Name      State     PID       More Information
-------------------------------------------------
API       Started   3302
CPM       Started   5741      Check Point Security Management Server is running and ready
FWM       Started   5525
APACHE    Started   4876

Port Details:
-------------------
JETTY Internal Port:      50277
APACHE Gaia Port:         443
                          Apache port retrieved from: httpd-ssl.conf


--------------------------------------------
Overall API Status: Started
--------------------------------------------

API readiness test SUCCESSFUL. The server is up and ready to receive connections

Notes:
------------
To collect troubleshooting data, please run 'api status -s <comment>'

最後に

ここまでで、AnsibleからCheck Pointを操作するための事前準備ができました。次の記事で、実際に操作を行ってみたいと思います。

AnsibleでCheck Pointを操作する

AnsibleからAPI経由で、Check Pointの情報取得や設定変更した時のメモです。

用意した環境

Check Point

AWS上のCloudGuard IaaS All-In-Oneを使いました。

f:id:tsukino_netwkr:20190729232317p:plain
f:id:tsukino_netwkr:20190729232337p:plain

バージョンは最新のR80.10を利用しています。 30日の無料トライアルがあり、この期間はソフトウェアの利用料はかかりません。 ※ただし、AWSのEC2(m4.xlarge)利用料はかかるのでご注意を。

All-In-Oneと書いてある通り、Firewall、IPS、Application Control、IPsec VPN、Antivirus、Anti-Bot、Data Loss Prevention等のセキュリティ機能に対応しています。 さらに、機器のステータス、ポリシー(ACL/NAT)設定変更、ログ閲覧・監視などをGUIで行える、管理サーバとしての機能も備えています。

複数拠点に導入する場合は、セキュリティ機能と管理サーバは個別に構築すべきですが、今回は簡易的に、1つの仮想マシン上で両機能を有効化しました。

Ansible

AnsibleのCheck Pointモジュールは2.8でリリースされています。今回は2.8.0で試しています。

Check Pointモジュール

Check Pointは管理サーバ経由のGUI設定、CLI設定、API経由での設定をサポートしていますが、AnsibleモジュールはすべてAPI経由で動作します。
2019年7月時点でサポートしているモジュールは以下の通りです。

Network modules -Checkpoint

  1. checkpoint_access_layer_facts – Get access layer facts on Check Point over Web Services API
  2. checkpoint_access_rule – Manages access rules on Checkpoint over Web Services API
  3. checkpoint_access_rule_facts – Get access rules objects facts on Checkpoint over Web Services API
  4. checkpoint_host – Manages host objects on Checkpoint over Web Services API
  5. checkpoint_host_facts – Get host objects facts on Checkpoint over Web Services API
  6. checkpoint_object_facts – Get object facts on Check Point over Web Services API
  7. checkpoint_run_script – Run scripts on Checkpoint devices over Web Services API
  8. checkpoint_session – Manages session objects on Check Point over Web Services API
  9. checkpoint_task_facts – Get task objects facts on Checkpoint over Web Services API

Check Pointでポリシーを設定する際は、IPアドレスではなく、ネットワークオブジェクトを指定する必要があります。 具体的には、あらかじめホスト(IPアドレス)と、それに紐付くNATアドレスをセットにしてオブジェクト名を付けたり、ネットワークセグメントとNATにオブジェクト名を付けたりしておいて、それをポリシー設定時に指定するイメージです。

上記モジュールの内、checkpoint_hostでホストのオブジェクト設定、checkpoint_host_factsで設定したオブジェクトを閲覧できます。 また、checkpoint_access_ruleでポリシー設定、checkpoint_access_rule_factsで設定したポリシーを閲覧できます。
Ansible2.9からは ネットワークのオブジェクト設定ができるcp_networkモジュールもリリースされる予定です。

セットアップ

AWS R77.30 セットアップガイドを参考にしました。

加えて、AnsibleからAPIを叩けるよう、管理サーバにSSHログインの上、Expertモードで以下コマンドを実行しています。 詳細はこちら

[Expert@xxxx:0]# mgmt_cli -r true set api-settings accepted-api-calls-from "All IP addresses" --domain 'System Data'
[Expert@xxxx:0]# api restart

今回は全アドレスからのAPIコールを許可していますが、 本番環境で使う場合は制限すべきですね。

Ansible Inventory

以下の通り作成しました。

  • inventory_cp
[checkpoint]
smart1 ansible_host=<管理サーバのIPアドレス>

[checkpoint:vars]
ansible_network_os=checkpoint
ansible_user=<管理サーバのユーザ名>
ansible_password=<管理サーバのパスワード>
ansible_httpapi_use_ssl=yes
ansible_httpapi_validate_certs=no 

Ansible Playbook

ホストオブジェクトとアクセスルールの設定、確認、削除を行うPlaybookを作成しました。

  • playbook_cp.yml
---

- hosts: checkpoint
  gather_facts: no
  connection: httpapi

  tasks:
    # ホストオブジェクトの設定
    - name: Create host object
      checkpoint_host:
        name: test_sv   # ホストオブジェクト名
        ip_address: 192.168.0.15   # IP address

    # ホストオブジェクトの確認
    - name: Get host object facts
      checkpoint_host_facts:
        name: test_sv   # ホストオブジェクト名
      register: result_host

    - name: debug
      debug:
        msg: "{{ result_host }}"

    # アクセスルールの設定
    - name: Create access rule
      checkpoint_access_rule:
        layer: Network
        name: "acl_test"   # アクセスルール名
        position: top   # ルールの挿入位置
        source: any   # オブジェクト名 or any
        destination: test_sv   # オブジェクト名 or any
        action: accept   # acceptで許可、dropで拒否

    # アクセスルールの確認
    - name: Get access rule facts
      checkpoint_access_rule_facts:
        layer: Network
        name: "acl_test"   # アクセスルール名
      register: result_access_rule

    - name: debug
      debug:
        msg: "{{ result_access_rule }}"

    # 設定したアクセスルールの削除
    - name: Delete access rule
      checkpoint_access_rule:
        layer: Network
        name: "acl_test"   # アクセスルール名
        state: absent

    # 設定したホストの削除
    - name: Delete host object
      checkpoint_host:
        name: test_sv   # ホストオブジェクト名
        state: absent

実行結果

だいぶ長いですが、ご参考までに載せておきます。

$ ansible-playbook -i inventory_cp playbook1_cp.yml

PLAY [checkpoint] *******************************************************************************************************

TASK [Create host object] ***********************************************************************************************
changed: [smart1]

TASK [Get host object facts] ********************************************************************************************
ok: [smart1]

TASK [debug] ************************************************************************************************************
ok: [smart1] => {
    "msg": {
        "ansible_facts": {
            "checkpoint_hosts": {
                "color": "black",
                "comments": "",
                "domain": {
                    "domain-type": "domain",
                    "name": "SMC User",
                    "uid": "xxx"
                },
                "groups": [],
                "icon": "Objects/host",
                "interfaces": [],
                "ipv4-address": "192.168.0.15",
                "meta-info": {
                    "creation-time": {
                        "iso-8601": "2019-07-29T22:29+0900",
                        "posix": xxx
                    },
                    "creator": "admin",
                    "last-modifier": "admin",
                    "last-modify-time": {
                        "iso-8601": "2019-07-29T22:29+0900",
                        "posix": xxx
                    },
                    "lock": "unlocked",
                    "validation-state": "ok"
                },
                "name": "test_sv",
                "nat-settings": {
                    "auto-rule": false
                },
                "read-only": false,
                "tags": [],
                "type": "host",
                "uid": "xxx"
            }
        },
        "changed": false,
        "failed": false
    }
}

TASK [Create access rule] ***********************************************************************************************
changed: [smart1]

TASK [Get access rule facts] ********************************************************************************************
ok: [smart1]

TASK [debug] ************************************************************************************************************
ok: [smart1] => {
    "msg": {
        "ansible_facts": {
            "checkpoint_access_rules": {
                "action": {
                    "domain": {
                        "domain-type": "data domain",
                        "name": "Check Point Data",
                        "uid": "xxx"
                    },
                    "name": "Accept",
                    "type": "RulebaseAction",
                    "uid": "xxx"
                },
                "action-settings": {
                    "enable-identity-captive-portal": false
                },
                "comments": "",
                "content": [
                    {
                        "domain": {
                            "domain-type": "data domain",
                            "name": "Check Point Data",
                            "uid": "xxx"
                        },
                        "name": "Any",
                        "type": "CpmiAnyObject",
                        "uid": "xxx"
                    }
                ],
                "content-direction": "any",
                "content-negate": false,
                "custom-fields": {
                    "field-1": "",
                    "field-2": "",
                    "field-3": ""
                },
                "destination": [
                    {
                        "domain": {
                            "domain-type": "domain",
                            "name": "SMC User",
                            "uid": "xxx"
                        },
                        "ipv4-address": "192.168.0.15",
                        "name": "test_sv",
                        "type": "host",
                        "uid": "xxx"
                    }
                ],
                "destination-negate": false,
                "domain": {
                    "domain-type": "domain",
                    "name": "SMC User",
                    "uid": "xxx"
                },
                "enabled": true,
                "install-on": [
                    {
                        "domain": {
                            "domain-type": "data domain",
                            "name": "Check Point Data",
                            "uid": "xxx"
                        },
                        "name": "Policy Targets",
                        "type": "Global",
                        "uid": "xxx"
                    }
                ],
                "layer": "xxx",
                "meta-info": {
                    "creation-time": {
                        "iso-8601": "2019-07-29T22:29+0900",
                        "posix": xxx
                    },
                    "creator": "admin",
                    "last-modifier": "admin",
                    "last-modify-time": {
                        "iso-8601": "2019-07-29T22:29+0900",
                        "posix": xxx
                    },
                    "lock": "unlocked",
                    "validation-state": "ok"
                },
                "name": "acl_test",
                "service": [
                    {
                        "domain": {
                            "domain-type": "data domain",
                            "name": "Check Point Data",
                            "uid": "xxx"
                        },
                        "name": "Any",
                        "type": "CpmiAnyObject",
                        "uid": "xxx"
                    }
                ],
                "service-negate": false,
                "source": [
                    {
                        "domain": {
                            "domain-type": "data domain",
                            "name": "Check Point Data",
                            "uid": "xxx"
                        },
                        "name": "Any",
                        "type": "CpmiAnyObject",
                        "uid": "xxx"
                    }
                ],
                "source-negate": false,
                "time": [
                    {
                        "domain": {
                            "domain-type": "data domain",
                            "name": "Check Point Data",
                            "uid": "xxx"
                        },
                        "name": "Any",
                        "type": "CpmiAnyObject",
                        "uid": "xxx"
                    }
                ],
                "track": {
                    "accounting": false,
                    "alert": "none",
                    "per-connection": false,
                    "per-session": false,
                    "type": {
                        "domain": {
                            "domain-type": "data domain",
                            "name": "Check Point Data",
                            "uid": "xxx"
                        },
                        "name": "None",
                        "type": "Track",
                        "uid": "xxx"
                    }
                },
                "type": "access-rule",
                "uid": "xxx",
                "vpn": [
                    {
                        "domain": {
                            "domain-type": "data domain",
                            "name": "Check Point Data",
                            "uid": "xxx"
                        },
                        "name": "Any",
                        "type": "CpmiAnyObject",
                        "uid": "xxx"
                    }
                ]
            }
        },
        "changed": false,
        "failed": false
    }
}

TASK [Delete access rule] ***********************************************************************************************
changed: [smart1]

TASK [Delete host object] ***********************************************************************************************
changed: [smart1]

PLAY RECAP **************************************************************************************************************
smart1                     : ok=8    changed=4    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

(参考) GUI画面

管理サーバにHTTPSアクセスすると、専用のクライアントソフト「スマートコンソール」をダウンロードできます。 これをインストールし、管理サーバへアクセスしました。
以下は、Ansibleで最後に削除を行う前の結果です。いずれも設定内容が問題なく反映されている事が分かります。

  • ホストオブジェクトの設定画面 f:id:tsukino_netwkr:20190729225611p:plain

  • アクセスルールの設定画面 f:id:tsukino_netwkr:20190729225508p:plain