TerraformでCisco ISEポリシー作成

# はじめに

:::note info
この記事は[Cisco Systems Japan Advent Calendar 2023]( https://qiita.com/advent-calendar/2023/cisco)の7日目の記事となります。
:::



- 2017年版: https://qiita.com/advent-calendar/2017/cisco
- 2018年版: https://qiita.com/advent-calendar/2018/cisco
- 2019年版: https://qiita.com/advent-calendar/2019/cisco
- 2020年版: https://qiita.com/advent-calendar/2020/cisco
- 2020年版(2枚目): https://qiita.com/advent-calendar/2020/cisco2
- 2021年版: https://qiita.com/advent-calendar/2021/cisco
- 2021年版(2枚目): https://qiita.com/advent-calendar/2021/cisco2
- 2022年版(1,2): https://qiita.com/advent-calendar/2022/cisco
- 2023年版: https://qiita.com/advent-calendar/2023/cisco <=== ここ

# Cisco Identy Services Engine (ISE)とは？
[Cisco Identy Services Engine (ISE)](https://www.cisco.com/c/ja_jp/products/security/identity-services-engine/index.html)とは、シスコシステムズが提供するセキュリティソフトウェアの１つで、ネットワーク上のデバイスやユーザの管理、制御を行うセキュリティポリシーサーバ

# Cisco ISEセキュリティポリシーの仕組み

セキュリティポリシーは以下の要素で構成される。

 - ポリシーセット：以下の２つのポリシーをまとめるコンポーネント
     - 認証ポリシー：アクセスしてきたユーザやデバイスの認証方式を定義
     - 認可ポリシー：アクセスしてきたユーザやデバイスに割り当てる権限を定義

 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3566506/b46fb7e3-96df-5c7e-d1ad-5f997e03c6ff.png)

# 実施すること

Terraformを使用して、ブラウザから効率的にCisco ISEに以下のポリシーを展開する。

- **<INS>ポリシーセットの作成</INS>**
    - ルール名：”Wired MAB”
    - 条件："WiredMAB"
    - 許可されたプロトコルサービス："Default Network Service"

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3566506/5e2bfbb1-4a81-68db-ffd1-add757b93387.png)


- **<INS>認証ポリシーの作成</INS>**
    - ルール名：MAB
    - 条件："WiredMAB"
    - アイデンティティ参照場所："Internal Endpoints"
    - 認証失敗時の処理
        - 接続に失敗した場合："REJECT"
        - ユーザが見つからない場合："REJECT"
        - プロセスが失敗した場合："DROP"

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3566506/168db73b-a685-488d-0683-a8d7cebb7031.png)

- **<INS>認可ポリシーの作成</INS>**
    - ルール名：MAB Endpoints
    - 条件："Endpoint Identity Groups:MAB-Endpoints"
    - 結果："PermitAccess"

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3566506/45054077-9f3e-ba04-e19b-08e12fe657fd.png)


# 自動化の流れ
![1205.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3566506/88d74e23-eeb0-2f85-637c-cefd3baf26c0.jpeg)



１．ローカルリポジトリからリモートリポジトリにコードをPUSH
２．Terraform CloudにWorkspaceを作成し、Githubとリポジトリの紐づけ
３．手動で実行をトリガーし、Agentにジョブを割り当てる
４．ジョブを実行し、Cisco ISEの設定変更を行う


## 環境
- GitHub
- Terraform v1.6.5
- providers.ciscoise Version0.6.22-beta
- WSL2(Ubuntu-22.04)
- tfc-agent_1.14.1

# 構築手順
１．Terraformコード
２．GitHubにコードをPUSH
３．Terraform Cloud設定
４．動作確認

## １．Terraformコード
Hashicorp社が提供しているCisco Identity Services Engine（ISE）の公式ドキュメントを参照

https://registry.terraform.io/providers/CiscoISE/ciscoise/latest/docs

Terraform実行の各ファイル構成、役割は以下の通り。


- `Policyset`：ポリシーセットの作成
- `Authentication`：認証ポリシーの作成
- `Authorization`：認可ポリシーの作成

```title:ディレクトリ構成
.
├── work
│   ├── Policyset
│   │   ├── main.tf
│   │   ├── providers.tf
│   │   ├── variables.tf
│   │   └── outputs.tf
│   │     
│   ├── Authentication
│   │   ├── main.tf
│   │   ├── providers.tf
│   │   └── variables.tf
│   │
│   ├── Authorization
│   │   ├── main.tf
│   │   ├── providers.tf
│   │   └── variables.tf  
```

## 1-1. Policyset(ポリシーセット作成)
- main.tf：リソースの定義、メインコード
- providers.tf：サービスプロバイダーの定義
- variables.tf：変数の定義
- output.tf：実行後に出力する内容の定義

## `main.tf`

```./work/Policyset/main.tf
## Cisco ISEのポリシーセットを管理するリソースを定義
resource "ciscoise_network_access_policy_set" "example" {
  provider = ciscoise
  parameters {
  　# ルール名
    name         = "Wired MAB"
    # 備考
    description  = "test policy set"
    # デフォルトポリシーかどうか
    default      = "false"
　　# ポリシーが適用された回数
    hit_counts   = 0
　　# ポリシーの優先度
    rank         = 0
    # ポリシーセットが適用されるプロトコルサービス名
    service_name = "Default Network Access"
    # ポリシーセットの状態
    state        = "enabled"

    condition {
    　# 条件タイプの指定
      condition_type = "ConditionAttributes"
      # 条件の属性名
      attribute_name  = "RadiusFlowType"
      # 条件の属性値
      attribute_value = "WiredMAB"
      # 条件の辞書名
      dictionary_name = "Normalised Radius"
      # 比較演算子
      operator        = "equals"
    }
  }
}
```
`resource "ciscoise_network_access_policy_set" "example" {}`：
Cisco ISEのポリシーセットを管理するリソースを定義
`parameter{}`：ポリシー名や優先度などポリシーセット自体の定義を行う
`condition{}`：ポリシーセットが適用される条件の指定を行う

**・ポイント**
　今回はcondition_typeとして、`ConditionAttributes`を指定し、属性の値に基づいた条件を作成しましたが、他の選択肢として以下のようなものがある。
 `ConditionReference`：既存の条件を参照
 `ConditionAndBlock/OrBlock`：複数の条件を組み合わせて論理的なANDまたはOR条件を作成

## `providers.tf`

```./work/Policyset/providers.tf
terraform {
  required_providers {
    ciscoise = {
      source = "CiscoISE/ciscoise"
      version = "0.6.22-beta"
    }
  }
}
provider "ciscoise" {
  ## 認証情報を外部から取得するための変数を定義
  username = var.ciscoise_username
  password = var.ciscoise_password
  base_url = var.ciscoise_base_url
  ## SSL証明書の検証
  ssl_verify = "false"
  ## リクエストのタイムアウト値
  single_request_timeout = 150
}
```

`terraform{}`：プロバイダ、バージョンの指定を行う
`provider{}`：認証情報やURLなどプロバイダに対する具体的な設定を行う

## `variables.tf`

```./work/Policyset/variables.tf
variable "ciscoise_username" {
　## 変数のデータ型を文字列型に指定
  type        = string
  description = "Username"
  ## デフォルト値の定義
  default     = "*****"
}

variable "ciscoise_password" {
　## 変数のデータ型を文字列型に指定
  type        = string
  description = "Password"
  ## デフォルト値の定義
  default     = "*****"
}

variable "ciscoise_base_url" {
　## 変数のデータ型を文字列型に指定
  type        = string
  ## デフォルト値の定義 
  default     = "https://*****"
}
```
`variable "ciscoise_username" {}`：変数の定義を行う

## `output.tf`

```./work/Policyset/output.tf
output "policy_set_id" {
  ## ポリシーセットIDの取得
  value = ciscoise_network_access_policy_set.example.id
}

output "policy_set_id_value" {
  ## ポリシーセットIDの一部を取得
  value = substr(ciscoise_network_access_policy_set.example.id, 4, 36)
}
```
`output "policy_set_id" {}`：実行結果から取得した情報の表示。または、別ディレクトリで利用できるようにする

- **ポイント**

`value = ciscoise_network_access_policy_set.example.id`で取得する値は以下の形式
```
policy_set_id = "id:=e20eeef6-****-****-****-************\\name:=test-policyset
```
1-2,1-3でポリシーセットIDを参照する必要があるため、substr()関数でUUIDのみ出力する
`value = substr(ciscoise_network_access_policy_set.example.id, 4, 36)`

```
policy_set_id_value = "e20eeef6****-****-****-************"
```

## 1-2. Authentication(認証ポリシー作成)
- main.tf
- providers.tf（1.1と同一ファイルのため説明省略）
- variables.tf（1.1と同一ファイルのため説明省略）

## `main.tf`

```./work/Authentication/main.tf

## リモートステートのデータを取得する
data "terraform_remote_state" "status" {
  ## リモートバックエンドを指定
  backend = "remote"

  config = {
    ## Terraform Cloudの組織名を指定
    organization = "Terraform-Cloud-ISE"
    workspaces = {
    ## Workspace名を指定
    name = "policyset_create"
    }
  }
}
## 認証ポリシーを管理するTerraformリソースを定義
resource "ciscoise_network_access_authentication_rules" "example" {
  provider = ciscoise
  parameters {
    ## アイデンティティ参照場所
    identity_source_name = "Internal Endpoints"
    ## 認証が失敗した場合の動作
    if_auth_fail         = "REJECT"
    ## ユーザが見つからなかった場合の動作
    if_user_not_found    = "REJECT"
    ## プロセスが失敗した場合の動作
    if_process_fail      = "DROP"

　　## リモートステートから取得した`policy_set_id_value`を参照しポリシーIDを指定
    policy_id = data.terraform_remote_state.status.outputs.policy_set_id_value
    rule {

      condition {
　　　　## 条件タイプの指定 
        condition_type  = "ConditionAttributes"
        ## 条件の属性名
        attribute_name  = "RadiusFlowType"
        ## 条件の属性値
        attribute_value = "WiredMAB"
        ## 条件の辞書名
        dictionary_name = "Normalised Radius"
        ## 比較演算子
        operator        = "equals"
      }
      ## デフォルトポリシーかどうか
      default    = "false"
      ## ポリシーが適用された回数
      hit_counts = 0
      ## ルール名
      name       = "MAB"
      ## ポリシーの優先度
      rank       = 0
      ## ポリシーの状態
      state      = "enabled"
    }
  }
}
```
`resource "ciscoise_network_access_authentication_rules" "example"{}`：
Cisco ISEの認証ポリシーを管理するリソース

`data "terraform_remote_state" "status{}`：
別フォルダの.tfstateファイルのoutputを参照する

`resource "ciscoise_network_access_authentication_rules" "example"{}`：
Cisco ISEのネットワークアクセス認証ルールを管理する

- **ポイント**

`policy_id = data.terraform_remote_state.status.outputs.policy_set_id_value`で
1-1のoutput.tfファイルで出力したポリシーIDを参照する

## 1.3. Authorization(認可ポリシー作成)
- main.tf
- providers.tf（1.1と同一ファイルのため説明省略）
- variables.tf（1.1と同一ファイルのため説明省略）

## `main.tf`

```./work/Authorization/main.tf
data "terraform_remote_state" "status" {
  ## リモートバックエンドを指定
  backend = "remote"

  config = {
    ## Terraform Cloudの組織名を指定
    organization = "Terraform-Cloud-ISE"
    workspaces = {
    ## Workspace名を指定
    name = "policyset_create"
    }
  }
}
## Cisco ISEの認可ポリシー管理するTerraformリソースを定義
resource "ciscoise_network_access_authorization_rules" "example" {
  provider = ciscoise
  parameters {
    ## リモートステートから取得した`policy_set_id_value`を使用してポリシーIDを指定
    policy_id = data.terraform_remote_state.status.outputs.policy_set_id_value
    ## 認可ルールの結果を指定
    profile   = ["PermitAccess"]
    rule {
    　## ルールの条件を指定
      condition {
        ## 条件タイプの指定 
        condition_type  = "ConditionAttributes"
        ## 条件の属性名
        attribute_name  = "Name"
        ## 条件の属性値
        attribute_value = "Endpoint Identity Groups:MAB-Endpoints"
        ## 条件の辞書名
        dictionary_name = "IdentityGroup"
        ## 比較演算子
        operator        = "equals"
      }
    ## デフォルトポリシーかどうか
    default    = "false"
    ## ポリシーが適用された回数
    hit_counts = 0
    ## ルール名
    name       = "MAB Endpoints"
    ## ポリシーの優先度
    rank       = 0
    ## ポリシーの状態
    state      = "enabled"
    }
  }
}
```

`resource "ciscoise_network_access_authorization_rules" "example" {}`：
Cisco ISEの認可ポリシー管理するリソース

## ２．GitHubにコードをPUSH
１．で作成したTerraformコードをリモートリポジトリにPUSHする
GitHubにPUSHする方法は省略します


## ３．Terraform Cloud設定

- Workspaceを３つ作成 
  - `policy_create`：ポリシーセット作成用
  - `authn_create`：認証ポリシー作成用
  - `authz_create`：認可ポリシー作成用


![terraform5.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3566506/0d460394-74aa-049d-be05-3d4e4b0aad47.jpeg)


## 3-1. Workspaceの作成

「Version Control Workflow」を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3566506/836e5677-e1e0-ca21-7b6a-cb60068abe43.png)

リポジトリを選択
選択したリポジトリがリポジトリルートとなり、コードを実行する作業ディレクトリになる
※作成する全てのワークスペースで`./work`を選択し、作成完了後に各ワークスペースの作業ディレクトリのPathを個別に設定する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3566506/9fd90870-7598-d431-d79a-147449eeb059.png)

Workspace Nameを入力し「Create」を押下
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3566506/db757f61-2b5f-6a08-af53-d81abb033566.png)

作成が完了！
![workspace6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3566506/2c6bf6d4-f5d3-e883-ed92-9e86cf1beee7.png)

残りのWorkspaceも作成し、全てのWorkspaceの作成が完了！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3566506/4618dbca-19c5-c24a-5672-d4f9aa03231a.png)


## 3-2. Workspaceの設定

### Working Directoryの設定
Terraformが実行されるディレクトリを設定する
現在のリポジトリルートは `./work` であるため、各ワークスペースの作業ディレクトリを相対パスで指定する
```
.
├── work
│   ├── Policyset
│   │   ├── main.tf
│   │   ├── providers.tf
│   │   ├── variables.tf
│   │   └── outputs.tf
│   │     
│   ├── Authentication
│   │   ├── main.tf
│   │   ├── providers.tf
│   │   └── variables.tf
│   │
│   ├── Authorization
│   │   ├── main.tf
│   │   ├── providers.tf
│   │   └── variables.tf  
```
　
**`policyset_create`** > **`Settings`** に遷移します
ポリシーセット作成用のワークスペースのため、`Policyset` ディレクトリを指定する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3566506/bbc26bbe-35d1-1df3-52ec-02f808f15aff.png)

**`authn_create`** > **`Settings`** に遷移します
認証ポリシー作成用のワークスペースのため、`Authentication` ディレクトリを指定する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3566506/8274d1a5-c3d0-e035-cfea-dea308a39841.png)

**`authz_create`** > **`Settings`** に遷移します
認可ポリシー作成用のワークスペースのため、`Authorization` ディレクトリを指定する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3566506/a5a292c3-dd9e-0bae-18ae-e5096bed7e1e.png)

### Auto-applyの設定
・Planが成功したらApplyも自動的に実行するように設定します。
・ワークスペースの適用が完了したら次のワークスペースを実行するための自動トリガーの設定も有効化します。

**`policyset_create`** > **`Settings`** に遷移します
※ **`authn_create`** , **`authz_create`** でも同様の設定を実施
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3566506/3719216f-6d1c-254e-a47d-ea14a92f32d4.png)

### 実行トリガーの設定
`policyset_create`（ポリシーセット作成）の適用をトリガーに、
`authn_create`（認証ポリシー作成）,`authz_create`（認可ポリシー作成）を自動的に実行するように設定します。

**`authn_create`** > **`Settings`** > **`Run Triggers`** に遷移し、Source Workspacesに **`policyset_create`** を選択する
※ **`authz_create`** でも同様の設定を実施
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3566506/58bdab4e-400e-4273-76ef-0c7cf90820b9.png)

### Remote state sharingの設定
terraform_remote_stateを他のワークスペースと共有するための設定を行います

**`policyset_create`** > **`Settings`** に遷移します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3566506/103b9914-1984-8e17-6882-b2f35e248764.png)

### Agentの設定
今回設定変更するCisco ISEがプライベートネットワークに存在するため、Agentを導入する。
Agentのインストール方法は省略します。

**`Settings`** > **`Agents`** > に遷移し、「Create agent pool」を押下
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3566506/7838fcb6-710c-e04d-09d7-d2d005d98648.png)

Agent Pool Nameを入力し、「Continue」を押下
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3566506/8aa68da5-1d72-aed1-69ca-34ec8354c573.png)

Descriptionを入力し、「Create token」を押下し、Tokenを作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3566506/767dce33-96db-f64e-6c5e-ae4d42a71182.png)

Toeknが表示されるので、コピーしておく
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3566506/28804e14-b285-11ce-86a6-9e6c85fef753.png)

Agentがインストールされたディレクトリに移動し、トークン、エージェント名を設定し、Agentを起動する。※Token生成時に記載されているコマンドを参照
```Ubuntu22.04
$ export TFC_AGENT_TOKEN= <token>
$ export TFC_AGENT_NAME=CiscoISE-Agent
$ ./tfc-agent
2023-12-06T17:40:30.410+0900 [INFO]  agent: Starting: agent_name=CiscoISE-Agent agent_version=1.14.1
2023-12-06T17:40:30.500+0900 [INFO]  core: Starting: version=1.14.1
2023-12-06T17:40:31.448+0900 [INFO]  core: Agent registered successfully with Terraform Cloud: agent_id=<agent id> agent_pool_id=<agent pool id>
2023-12-06T17:40:31.573+0900 [INFO]  agent: Core version is up to date: version=1.14.1
2023-12-06T17:40:31.573+0900 [INFO]  core: Waiting for next job
```

terraform cloud画面に戻り、**`Settings`** > **`General`** > に遷移します。
実行モードにAggentを選択し、Agent Poolに先ほど作成したCiscoISE-Agentを選択します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3566506/bfce8b7c-0f25-9ec1-3f6b-a5eba8331ce8.png)


## ４．動作確認
準備が整ったので、実際に実行してみる

## 4.1 Terraform Cloudからデプロイ
実行トリガーの設定より、`policyset_create` の実行が成功すると、
`authn_create` / `authz_create` が自動的に実行されるため、`policyset_create` のみ手動でrun

**`policyset_create`** > 「New run」 を押下
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3566506/c52f9f0a-2b20-c235-e719-cdaee0edfe99.png)

「Start run」を押下
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3566506/7287d0e0-ccd7-bf22-6923-f085dc26b72e.png)

## 4.2 実行結果（policyset_create）

Planが成功し、自動的にApplyが実行される。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3566506/61244399-7065-61aa-3033-240bf3f529bb.png)

Cisco ISEにログインし、ポリシーセットが作成されたことが確認できる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3566506/f88001f5-402c-28ca-7969-82dc45632050.png)



## 4.3 実行結果（authn_create/authz_create）

`policyset_create`の適用が完了したことにより、トリガー設定していた
`authn_create` , `authz_create`が自動的に実行され、Plan,Applyが成功している。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3566506/24072a8d-8e85-4edc-4bbc-c87227b9c3f6.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3566506/13900e40-5276-a52d-f3f4-069f9b34b0ea.png)


Cisco ISEにログインし、認証、認可ポリシーが作成されていることを確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3566506/09c48003-4834-b388-f04e-67f00a08702b.png)




# おわりに
今回、Terraformを使用してISEの設定をしてみましたが、コードの書き方が独特であったり、Terraformのバージョンによって動かないリソースがあったりと苦戦しました。
また、セキュリティポリシーだけでなく、設定頻度が高い項目や一般的なユースケースに沿った内容をテンプレートとして作成することで、より効率化が図れそうだと感じました。
今後もTerraformでできることを追求していきます。

# 免責事項
本サイトおよび対応するコメントにおいて表明される意見は、投稿者本人の個人的意見であり、シスコの意見ではありません。本サイトの内容は、情報の提供のみを目的として掲載されており、シスコや他の関係者による推奨や表明を目的としたものではありません。各利用者は、本Webサイトへの掲載により、投稿、リンクその他の方法でアップロードした全ての情報の内容に対して全責任を負い、本Web サイトの利用に関するあらゆる責任からシスコを免責することに同意したものとします。