1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

実践ServiceNow - ルータでIPアドレス/ポート開放の申請

Posted at

概要

本記事はルータでIPアドレス/ポートを開放するための申請処理を作成します。
既に稼働しているPythonで作成したサービスをServiceNowに移植します。

仕様

IPアドレス/ポート開放サービスの仕様は次の通りです:

  • 既存サービスは決められたIPアドレスの範囲のIPアドレスであればユーザが何時でも申請を行い、自動でIPアドレス/ポートを開放するACLをルータに追加します。また、既存サービスではルータに接続する前に既にIP/ポートが開放されているかを確認する。
  • 一つの申請は1IPアドレスに限りますが、10ポートまで受け付けます。複数のポートはコンマ区切り又は「-」を利用して範囲指定が可能(例:80,85,8080-8085)。
  • 複数の人が同時に申請を行えるため、ルータ接続は非同期にする。
  • ユーザは自分が申請した申請一覧を表示することができます。
  • 管理者はすべての申請を確認することができる。
  • 全員は開放されているIP/ポート一覧を表示できる。
  • IPアドレス/ポートを制御しているルータは東京と大阪にある。
  • ルータのACLを処理する申請の内容(申請者、申請日時、IPアドレス/ポート)をSlackチャネルに投稿する。
  • 管理者は決められたIPアドレス以外のIPアドレスの申請も行える。
  • 管理者は代理申請を行うことができる。
  • 申請者は自分が申請したIP/ポートを取消すことがでる。
  • 管理者は指定したIPアドレス、ACL、ルータのACL設定を確認することがでる。
  • 管理者はWebブラウザからACL行(ACL番号を指定、ACL一覧の最後からの行数)を一覧表示することができる。
  • 管理者は東京と大阪のACLに差があるか確認できる。
  • 管理者はWebブラウザから直接ルータのACLを挿入、削除することができる
  • 定期的に利用されていない(該当パケットが適用されていない)ACLを削除する
  • 監査用にユーザ及び管理者の処理をログに書き出す。

今回はServiceNowでIPアドレス/ポート開放の申請フォームのみを作成する。

ロールの作成

IPアドレス/ポート管理用のロールを作成します。ここれはロール名を「infra_itiservice_admin」を作成します。

  1. アプリケーション・ナビゲータから「role」を検索して、「User Administration」下の「Roles」を選択します。
    itiservice_role_1.png
    2.新しいロールを作成するので「New」ボタンを押下します。
    itiservice_role_2.png
    3.Nameに「infra_itiservice_admin」を入力して「Submit」ボタンを押下します。これでロール「infra_itiservice_admin」は作成されました。
    itiservice_role_3.png

フォームの作成

次に申請フォームを作成します。
1.アプリケーションナビゲータから「maintain」を検索して、Service Catalog下の「Maintain items」を選択します。
itiservice_form_1.png
2.新しいフォームを作成するので「New」ボタンを押下します。
itiservice_form_2.png
3.次の値を入力します。

No. 項目 値(英語) 値(日本語)
1. Name IP Port Open Request IPアドレス/ポート開放申請
2. Short description Open ip port on router request 外部からアクセスできるようにIPアドレス/ポートを開放する

itiservice_form_3.png
4.ポータルページで価格などを非表示にする。
「Portal Settings」タグを選択して次のように設定する。

No. 項目 設定
1. Request method Request
2. Hide 'Add to Card' チャック
3. Hide Quantity チャック
4. Hide Delivery time チャック
5. Hide 'Add to Wish List' チャック
6. Hide Attachment チャック
itiservice_form_4.png
5.入力して設定を保存します。入力フィールドとスクリプトも作成するのでヘッダ領域を右クリックして「Save」を選択します。
itiservice_form_5.png

フェールドの作成

フォームの入力フィールドを定義します。
1.フォームを保存するとページの下部分にタグが表示します。「Variables」タブを選択して「New」ボタンを押下します。
itiservice_variable_1.png
2.IPアドレスの検証をスキップするかのチェックボックスを作成します。
次のように設定した後に「Submit」ボタンを押下します。

No. 項目 値(英語) 値(日本語)
1. Type Label ラベル
2. Order 10 10
3. Question Validation IPアドレスチェック
4. Name infra_ipo_validation infra_ipo_validation
itiservice_variable_2.png
3.次のフィールドを定義します。「New」ボタンを押下します。
itiservice_variable_3.png
4.次のように設定します。
No. 項目 値(英語) 値(日本語)
1. Type CheckBox チェックボックス
2. Order 20 20
3. Question Skip スキップ
4. Name infra_ipo_skip_validation infra_ipo_skip_validation
itiservice_variable_4.png
5.デフォルトでは検証を行うようにします。
「Default Value」タブを選択してDefault valueの値に「false」を入力します。
入力した後に「Submit」ボタンを押下します。
itiservice_variable_5.png
6.IPアドレス入力フィールドを定義します。
「New」ボタンを押下します。
itiservice_variable_6.png
7.次のように設定します。
No. 項目 値(英語) 値(日本語)
1. Type Single Line Text 1行テキスト
2. Mandatory チェック チェック
3. Order 30 30
4. Question IP Address IPアドレス
5. Name infra_ipo_ip_address infra_ipo_ip_address
itiservice_variable_7.png
8.ヘルプテキストを設定します。
「Annotation」タグを選択して次のように設定します。
No. 項目 値(英語) 値(日本語)
1. Show help チェック チェック
2. Always Expanded チェック チェック
3. Help tag 空白 空白
4. Help text Please enter internal server IP address. Do not enter external IP address. 内部サーバのIPアドレスを入力してください。エンドユーザパソコンのIPアドレスを入力しないでください。
itiservice_variable_8.png
9.フィールドの幅を短くします。
「Type Specification」タブを選択してVariable Widthを「25%」に設定した後に「Submit」ボタンを押下します。
itiservice_variable_9.png
10.ポート番号入力フィールドを定義します。
「New」ボタンを押下します。
itiservice_variable_10.png
11.次のように設定します。
No. 項目 値(英語) 値(日本語)
1. Type Single Line Text 1行テキスト
2. Mandatory チェック チェック
3. Order 40 40
4. Question Port(s) ポート番号
5. Name infra_ipo_ports infra_ipo_ports
6. Example Text e.g. 80,82,8080-8085 例: 80,82,8080-8085
itiservice_variable_11.png
12.ヘルプテキストを設定します。
「Annotation」タグを選択して次のように設定します。
No. 項目 値(英語) 値(日本語)
1. Show help チェック チェック
2. Always Expanded チェック チェック
3. Help tag 空白 空白
4. Help text Several ports may be specified by separated by comma. Range may be specified by using hyphen. Maximum of 10 ports. 10ポートまで指定することが可能です。コンマ区切りでポートを指定します。範囲で指定する場合はハイフンを使います。
itiservice_variable_12.png
13.フィールドの幅を短くします。
「Type Specification」タブを選択してVariable Widthを「25%」に設定した後に「Submit」ボタンを押下します。
itiservice_variable_13.png
14.プロジェクト名フィールドを定義します。
「New」ボタンを押下します。
itiservice_variable_14.png
15.次のように設定します。
No. 項目 値(英語) 値(日本語)
1. Type Single Line Text 1行テキスト
2. Order 50 50
3. Question Project name プロジェクト名
4. Name infra_ipo_project_name infra_ipo_project_name
itiservice_variable_15.png
16.フィールドの幅を短くします。設定した後に「Submit」ボタンを押下して保存します。
「Type Specification」タブを選択してVariable Widthを「25%」に設定した後に「Submit」ボタンを押下します。
itiservice_variable_16.png
17.サービス内容フィールドを定義します。
「New」ボタンを押下します。
itiservice_variable_17.png
18.次のように設定します。
No. 項目 値(英語) 値(日本語)
1. Type Single Line Text 1行テキスト
2. Order 60 60
3. Question Service description 開放理由
4. Name infra_ipo_service_description infra_ipo_service_description
itiservice_variable_18.png
19.フィールドの幅を短くします。設定した後に「Submit」ボタンを押下して保存します。
「Type Specification」タブを選択してVariable Widthを「25%」に設定した後に「Submit」ボタンを押下します。
itiservice_variable_19.png
20.ルータ選定チェックボックスを定義します。
「New」ボタンを押下します。
itiservice_variable_20.png
21.次のように設定します。設定後に「Submit」ボタンを押下します。
No. 項目 値(英語) 値(日本語)
1. Type Label ラベル
2. Order 70 70
3. Question Routers ルータ
4. Name infra_ipo_routers infra_ipo_routers
itiservice_variable_21.png
22.東京ルータ用のチェックボックスを定義します。
「New」ボタンを押下します。
itiservice_variable_22.png
23.次のように設定します。
No. 項目 値(英語) 値(日本語)
1. Type Label ラベル
2. Selection Required チェック
3. Order 80 80
4. Question Tokyo 東京
5. Name infra_ipo_tokyo infra_ipo_tokyo
itiservice_variable_23.png
24.デフォルトで東京ルータを設定します。
「Default Value」タブを選択してDefault valueの値に「true」を入力します。設定後は「Submit」ボタンを押下します。
itiservice_variable_24.png
25.大阪ルータ用のチェックボックスを定義します。
「New」ボタンを押下します。
itiservice_variable_25.png
26.次のように設定します。
No. 項目 値(英語) 値(日本語)
1. Type Label ラベル
2. Order 90 90
4. Question Osaka 大阪
5. Name infra_ipo_osaka infra_ipo_osaka
itiservice_variable_26.png
27.デフォルトで大阪ルータを設定します。
「Default Value」タブを選択してDefault valueの値に「true」を入力します。設定後は「Submit」ボタンを押下します。
itiservice_variable_27.png
すべてのフィールドを定義すると次のようになります。
itiservice_variable_28.png

クライアントスクリプトの作成

表示するフィールドと入力チェックを行うためにクライアントスクリプトを作成します。
今回は4つのスクリプトを作成します。
itiservice_client_script_9.png

表示フィールドの制御

IPアドレスの検証のスキップとルータの選択は管理者の場合のみ表示します。一般ユーザでは非表示にします。
1.「Catalog Client Scripts」タブを選択します。新しいスクリプトを作成するため「New」ボタンを押下します。
itiservice_client_script_1.png
2.次のように設定します。

No. 項目
1. Name infra_ipo_cs_initialization
2. UI Type All
3. Type onLoad
スクリプト
function onLoad() {
    var itiserviceAdmin = g_user.hasRole('infra_itiservice_admin'); // ログインしているユーザが管理者か確認
    g_form.setDisplay('infra_ipo_routers', itiserviceAdmin); // ルータフィールを表示/非表示
    g_form.setDisplay('infra_ipo_validation', itiserviceAdmin); // IPアドレスチェックを表示/非表示
}

itiservice_client_script_2.png

IPアドレスチェック・スキップフィールドのチェック

1.「New」ボタンを押下します。
itiservice_client_script_3.png
2.次のように設定します。

No. 項目
1. Name infra_ipo_cs_skip_validation
2. UI Type All
3. Type onChange
4. Variable name infra_ipo_skip_validation
スクリプト
function onChange(control, oldValue, newValue, isLoading) {
    if (isLoading || newValue == '') {
        return;
    }
    try {
		g_form.hideFieldMsg('infra_ipo_ip_address');
        var ajax = new GlideAjax('infraIpoSIValidateIpPorts');
        ajax.addParam('sysparm_name', 'validateIp');
        ajax.addParam('sysparm_ip_address', g_form.getValue('infra_ipo_ip_address'));
        ajax.addParam('sysparam_ports', g_form.getValue('infra_ipo_ports'));
        ajax.addParam('sysparm_skip_validation', newValue);
        ajax.getXMLAnswer(function(answer) {
            if (answer && answer.length > 0) {
				g_form.setValue('infra_ipo_ip_address', '');
                g_form.showFieldMsg('infra_ipo_ip_address', answer, 'error');
            }
        });
    } catch (e) {}
}

itiservice_client_script_4.png

IPアドレスフィールドのチェック

1.「New」ボタンを押下します。
itiservice_client_script_5.png
2.次のように設定します。

No. 項目
1. Name infra_ipo_cs_validate_ip
2. UI Type All
3. Type onChange
4. Variable name infra_ipo_ip_address
スクリプト
function onChange(control, oldValue, newValue, isLoading) {
    if (isLoading || newValue == '') {
        return;
    }
    try {
        var ajax = new GlideAjax('infraIpoSIValidateIpPorts');
        ajax.addParam('sysparm_name', 'validateIp');
        ajax.addParam('sysparm_ip_address', newValue);
        ajax.addParam('sysparam_ports', g_form.getValue('infra_ipo_ports'));
        ajax.addParam('sysparm_skip_validation', g_form.getValue('infra_ipo_skip_validation'));
        ajax.getXMLAnswer(function(answer) {
            if (answer && answer.length > 0) {
				g_form.setValue('infra_ipo_ip_address', '');
                g_form.showFieldMsg('infra_ipo_ip_address', answer, 'error');
            }
        });
    } catch (e) {}
}

itiservice_client_script_6.png

ポート番号フィールをチェックします。

1.「New」ボタンを押下します。
itiservice_client_script_7.png
2.次のように設定します。

No. 項目
1. Name infra_ipo_cs_validatePorts
2. UI Type All
3. Type onChange
4. Variable name infra_ipo_ports
スクリプト
function onChange(control, oldValue, newValue, isLoading) {
    if (isLoading || newValue == '') {
        return;
    }
    try {
        var ajax = new GlideAjax('infraIpoSIValidateIpPorts');
        ajax.addParam('sysparm_name', 'validatePort');
        ajax.addParam('sysparm_ip_address', g_form.getValue('infra_ipo_ip_address'));
        ajax.addParam('sysparam_ports', newValue);
        ajax.addParam('sysparm_skip_validation', g_form.getValue('infra_ipo_skip_validation'));
        ajax.getXMLAnswer(function(answer) {
            if (answer && answer.length > 0) {
				g_form.setValue('infra_ipo_ports', '');
                g_form.showFieldMsg('infra_ipo_ports', answer, 'error');
            }
        });
    } catch (e) {}
}

itiservice_client_script_8.png

スクリプトインクルードの作成

クライアントスクリプトから呼び出されるサーバ側スクリプトを作成します。
今回は2つのサーバ側スクリプトを定義します。
itiservice_script_include_6.png
1.アプリケーションナビゲータから「script include」を検索してSystem Definition下のScript Includesを選択します。
itiservice_script_include_1.png
2.新しいスクリプトインクルードを作成するので「New」ボタンを押下します。
itiservice_script_include_2.png
3.次のように設定します。設定した後に「Submit」ボタンを押下します。

No. 項目
1. Name infraIpoSIValidateIpPorts
2. Client callable チェック
スクリプト
var IPv4_PTN = new RegExp('^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$');
var PORT_RANGE_PTN = new RegExp('^[0-9]{1,5}([,|-][0-9]{1,5})*$');
var PORT_MIN = 1;
var PORT_MAX = 65535;

var infraIpoSIValidateIpPorts = Class.create();
infraIpoSIValidateIpPorts.prototype = Object.extendsObject(AbstractAjaxProcessor, {
    validateIp: function() {
        var ipAddress = this.getParameter('sysparm_ip_address');
        var portString = this.getParameter('sysparam_ports');
        var skipValidation = this.getParameter('sysparm_skip_validation');
        if (!ipAddress) {
            return '';
        }
        ipAddress = String(ipAddress).trim();
        portString = String(portString).trim();
        if (!IPv4_PTN.test(ipAddress)) {
            return 'Please enter IP v4 address in xxx.xxx.xxx.xxx format.';
        }
		return new infraIpoSIValidateIpPortsUtils().validateIpPorts(ipAddress, portString, skipValidation);
    },
    validatePort: function() {
        var ipAddress = this.getParameter('sysparm_ip_address');
        var portString = this.getParameter('sysparam_ports');
        var skipValidation = this.getParameter('sysparm_skip_validation');
        if (!portString) {
            return '';
        }
        ipAddress = String(ipAddress).trim();
        portString = String(portString).trim();
        if (!PORT_RANGE_PTN.test(portString)) {
            return 'Please enter port number delimited by comma. Port number should be an integer value between ' + PORT_MIN + ' and ' + PORT_MAX + '.';
        }
        if (ipAddress == '' && portString == '') {
            return '';
        }
        return new infraIpoSIValidateIpPortsUtils().validateIpPorts(ipAddress, portString, 'true');
    },
    type: 'infraIpoSIValidateIpPorts'
});

itiservice_script_include_3.png
4.共有ユーティリティクラスを作成します。
「New」ボタンを押下します。
itiservice_script_include_4.png
5.次のように設定します。設定した後に「Submit」ボタンを押下します。

No. 項目
1. Name infraIpoSIValidateIpPortsUtils
2. Client callable チェック
スクリプト
var infraIpoSIValidateIpPortsUtils = Class.create();
infraIpoSIValidateIpPortsUtils.prototype = {
    initialize: function() {},
    validateIpPorts: function(ipAddress, portString, skipValidation) {
		// check if ip address is valid
        if (ipAddress && skipValidation != "true") {
            var isIpAddressOK = isOKIpAddress(ipAddress); // check if allowed ip address
            if (isIpAddressOK.length > 0) {
                return isIpAddressOK;
            }
        }

		// check if port numbers is valid and convert it into an array
		var portArray;
        if (portString) {
			if (portString.length > 0) {
                portArray = portString2PortArray(portString);
				if (!Array.isArray(portArray)) {
					return portArray;
				}
            }
        }
		// check if ip:port already is open
		if (ipAddress && portArray && portArray.length > 0) {
			var existResult = existsIpPort(ipAddress, portArray);
			if (existResult.length > 0) {
				return existResult;
			}
		}
		return '';

        // check if ip address is within allowed network
        function isOKIpAddress(ipAddress) {
            for (var i = 0; i < SERVER_ADDRESS_PATTERN_LIST.length; i++) {
                if (SERVER_ADDRESS_PATTERN_LIST[i].test(ipAddress)) {
                    return '';
                }
            }
            return 'IP ' + ipAddress + ' is not in allowed network';
        }

        // convert input port string to array of ports
        function portString2PortArray(portString) {
            var portArray = [];
            var portFinalArray = [];
            if (portString && portString.length > 0) {
                portArray = portString.split(',');
                for (var i = 0; i < portArray.length; i++) {
                    var portRange = portArray[i].split('-');
                    if (portRange.length > 2) {
                        return 'Please separate range with a comma';
                    } else if (portRange.length == 2) {
                        var startPort = parseInt(portRange[0]);
                        var endPort = parseInt(portRange[1]);
                        var validatePortResult = validatePortRange(startPort, endPort);
                        if (validatePortResult.length > 0) {
                            return validatePortResult;
                        }
                        if ((endPort - startPort) > 10) {
                            return 'Only 10 ports may be specified at once.';
                        }
                        for (var j = 0; j <= endPort - startPort; j++) {
                            portFinalArray.push(startPort + j);
                        }
                    } else {
                        var validateResult = validatePort(portArray[i]);
                        if (validateResult.length > 0) {
                            return validateResult;
                        } else {
                            portFinalArray.push(portArray[i]);
                        }
                    }
                }
				if (portFinalArray.length > 10) {
					return 'Only 10 ports may be specified at once.';
				}
				return portFinalArray;
            }
            return '';
        }

        function validatePortRange(startPort, endPort) {
            var validateResult = validatePort(startPort);
            if (validateResult.length > 0) {
                return validateResult;
            }
            validateResult = validatePort(endPort);
            if (validateResult.length > 0) {
                return validateResult;
            }
            if (startPort > endPort) {
                return 'Invalid range. Start range value should be less than end range value.';
            }
            return '';
        }

        function validatePort(port) {
            if (isNaN(port)) {
                return 'Invalid port number. Please enter port number between ' + PORT_MIN + ' and ' + PORT_MAX;
            }
            if (port < PORT_MIN) {
                return 'Port number should be greater than ' + PORT_MIN;
            }
            if (port > PORT_MAX) {
                return 'Port number should be less than ' + PORT_MAX;
            }
            return '';
        }
		
        // check if ip/port is already opened
        function existsIpPort(ipAddress, portString) {
            return '';
        }
    },
    type: 'infraIpoSIValidateIpPortsUtils'
};

// 許可するIPアドレスすの正規表現
var SERVER_ADDRESS_PATTERN_LIST = [
    new RegExp("^192.168.0.([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-4])$"),
];

var PORT_MIN = 1;
var PORT_MAX = 65535;

itiservice_script_include_5.png

テスト

正しく動作するか確認します。
確認する必要があるのは次の点になります。

  1. すべての項目が正しく表示するか
  2. 管理者ユーザ以外の場合はIPアドレスチェックスキップとルータ項目は非表示
  3. IPアドレス及びポート番号がチェックされるか
  4. IPアドレス制限が正しくチェックされるか
  5. サービスポータルページでも正しく動作するか

UI環境

UI環境で正しく表示され、動作するか確認します。
1.アプリケーションナビゲータから「maintain ite」を検索してService Catalog > Catalog Definitions > Maintain Itemsを選択します。
itiservice_test_1.png
2.一覧から今回作成した「IP Port Open Request」を選択します。
itiservice_test_2.png
3.「Try It」ボタンを押下します。
itiservice_test_3.png
4.正しく作成された場合は次のようなページが表示されます。
itiservice_test_4.png
5.IPアドレス及びポート番号フィールドに値を入力して正しくチェックされるか確認します。
itiservice_test_5.png
6.間違えた値を入力した場合は入力した値が初期化されてエラーメッセージが表示します。色々な値を入力してテストを行います。
itiservice_test_6.png
7.IPアドレスフィールド及びポート番号フィールドのテストの後は管理者以外でのテストを行います。
管理者以外のユーザを作成します。既に管理者以外のユーザがいる場合は手順11までスキップします。
アプリケーションナビゲータから「users」を検索して、User Administration下のUsersを選択します。
itiservice_test_10.png
8.「New」ボタンを押下します。
itiservice_test_11.png
9.User IDフィールドとPasswordフィールドに値を入力します。
itiservice_test_12.png
10.ヘッダ領域を右クリックしたSaveを選択します。それでユーザは作成されました。
itiservice_test_13.png
11.ページ右上のユーザ名をクリックして「Impersonate User」を選択します。
itiservice_test_20.png
12.作成したユーザ名を入力します。
itiservice_test_21.png
13.ユーザが変更されたことを確認します。
itiservice_test_22.png
14.再び作成したフォームを開きます。
IPアドレス検証フィールドとルータフィールドが表示されていないことを確認します。
itiservice_test_23.png
15.ログインユーザ名をクリックして「End Impersonation」を選択します。
itiservice_test_24.png
16.元の管理ユーザに戻されたことを確認します。
itiservice_test_25.png
17.infra_itiservice_adminロールのテストを行います。
上で作成したユーザを開き、Rolesタブを選択して「Edit」ボタンを押下します。
itiservice_test_role_3.png
18.「infra_itiservice_admin」ロールを付与します。
「infra」を検索して「infra_itiservice_admin」を選択した後に「>」ボタンを押下します。
itiservice_test_role_1.png
19.右側に表示されます。「Save」ボタンを押下します。再びフォームを表示してIPアドレス検証フィールとルータフィールドが表示されていることを確認します。
itiservice_test_role_2.png

サービスポータル

サービスポータルでも正しく表示されるか確認します。
先ずはサービスポータルにフォームを登録します。
1.アプリケーションナビゲータから「maintain ite」を検索してService Catalog > Catalog Definitions > Maintain Itemsを選択します。
itiservice_test_sp_1.png
2.一覧から作成した「IP Port Open Request」を選択します。
itiservice_test_sp_2.png
3.Catalogsフィールド右の南京錠アイコンをクリックします。
itiservice_test_sp_3.png
4.虫眼鏡アイコンをクリックします。
itiservice_test_sp_4.png
5.「Service Catalog」を選択します。
itiservice_test_sp_5.png
6.Categoryフィールドの右にある虫眼鏡アイコンをクリックします。
itiservice_test_sp_6.png
7.「Services」を選択します。
itiservice_test_sp_7.png
8.Catalogsの右に「Service Catalog」が表示され、Categoryの値は「Services」になります。
itiservice_test_sp_8.png
9.設定を保存します。
「Update」ボタンを押下します。
itiservice_test_sp_9.png
10.サービスポータルを開き、「Request Something」を選択します。
itiservice_test_sp_100.png
11.Office > Serviceを選択して「IP Port Open Request」を選択します。
itiservice_test_sp_101.png
12.次のようなページが表示されます。このページからの入力チェックやロールのチェックを行います。
itiservice_test_sp_102.png

以上

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?