ArcGIS Serverにサーバー証明書をインポートして適用する処理を自動化した


以下の処理を自動化した.

- ArcGIS Serverにサーバー証明書をインポートする
- ArcGIS Serverでインポートしたサーバー証明書を適用する
- ArcGIS ServerでHTTPS接続のみを有効にする

## 構成

```text
ImportSvrCert
┣Certificate
┃┗certificate.pfx
┣Python
┃┣import_svr_cert.py
┃┗config.py
┗Import-SvrCert.ps1
```

## 実行方法

C直下にモジュール置いたらスクリプト叩くだけ.

```powershell
cd C:\ImportSvrCert
.\Import-SvrCert.ps1
```

## なかみ

ArcGIS REST APIをPythonで叩くだけ.
API叩く際にtokenを別途取得してPOSTする必要がある.

```powershell
Start-Process -FilePath "C:\Python27\ArcGISx6410.6\python.exe" -ArgumentList "-B .\Python\import_svr_cert.py" -Verb runas
```

```python:import_svr_cert.py
# coding:utf-8
import json
import sys
import os
import getpass
import config as c
import traceback
import requests

#-------------------------------------------------------------------
def get_token(username, password, serverName, serverPort):
    # URL
    tokenURL = 'http://{0}:{1}/arcgis/admin/generateToken'.format(serverName, serverPort)
    # POST data
    data = {'username': username, 'password': password, 'client': 'requestip', 'f': 'json'}
    # send request
    res = requests.post(tokenURL, data=data)
    if res.status_code is 200:
        print(u'tokenの取得に成功しました. ')
        print(u'token: {0}'.format(res.json()['token']))
        return res.json()['token']
    else:
        print(u'tokenの取得に失敗しました.')
        print('response data: {0}'.format(res.text))
        raise Exception()
#-------------------------------------------------------------------
def import_server_certificate(serverName, serverPort, token, certAlias, certPassword, certFile):
    # URL
    svcURL = 'http://{0}:{1}/arcgis/admin/machines/{0}/sslcertificates/importExistingServerCertificate'.format(serverName, serverPort)
    # 証明書ファイル
    files = {'certFile': open(certFile, 'rb').read()}
    # POST data
    data = {'alias': certAlias, 'certPassword': certPassword, 'certFile': certFile, 'token': token, 'f':'json'}
    # send request
    res = requests.post(svcURL, files=files, data=data)
    if (res.status_code is 200) and (res.json()['status'] == 'success'):
        print(u'サーバー証明書のインポートに成功しました. ')
    else:
        print(u'サーバー証明書をインポートする際にエラーが発生しました.')
        print('response data: {0}'.format(res.text))
        raise Exception()
    return
#-------------------------------------------------------------------
def applly_imported_server_certificate(serverName, certAlias, machineConfigFile):
    f = open(machineConfigFile, 'r')
    data = json.load(f)
    # サーバー証明書を指定する
    data["webServerCertificateAlias"] = certAlias
    # JSON書き込み
    f = open(machineConfigFile, 'w')
    json.dump(data, f)
    print(u'インポートした証明書をArcGIS Serverに適用しました.')
    return
#-------------------------------------------------------------------
def enable_only_https(serverName, serverPort, token):
    # URL
    svcURL = 'http://{0}:{1}/arcgis/admin/security/config/update'.format(serverName, serverPort)
    cf.print_log('import server certificate URL: {0}'.format(svcURL))
    # POST data
    data = {'Protocol': 'HTTPS','authenticationTier': 'GIS_SERVER','allowDirectAccess': 'false','virtualDirsSecurityEnabled': 'false','allowedAdminAccessIPs': [],
        'cipherSuites': 'TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, TLS_DHE_RSA_WITH_AES_256_CBC_SHA, TLS_RSA_WITH_AES_256_GCM_SHA384, TLS_RSA_WITH_AES_256_CBC_SHA256, TLS_RSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_128_GCM_SHA256, TLS_RSA_WITH_AES_128_CBC_SHA256, TLS_RSA_WITH_AES_128_CBC_SHA',
        'token': token, 'f': 'json'}
    # send request
    res = requests.post(svcURL, data=data)
    if (res.status_code is 200) and (res.json()['status'] == 'success'):
        print(u'HTTPS通信のみ有効にしました.')
    else:
        print(u'HTTPS通信のみ有効にする際にエラーが発生しました.')
        print('response data: {0}'.format(res.text))
        raise Exception()
    return
#-------------------------------------------------------------------
try:
    token = get_token(c.username, c.password, c.server_name, c.server_port)
    import_server_certificate(c.server_name, c.server_port, token, c.cert_alias, c.cert_password, c.cert_file)
    applly_imported_server_certificate(c.server_name, c.cert_alias, c.machine_config_file)
    enable_only_https(c.server_name, c.server_port, token)
except Exception as e:
    print(traceback.format_exec())
```

```python:config.py
# coding:utf-8

import os
import shutil

# プライマリサイトの管理者ユーザー名
username = "testuser"
# プライマリサイトの管理者パスワード
password = "pAsSW0rd"
# ルートサーバー名
server_name  = "testsvr"
# ルートサーバーのポート番号
server_port = 6080
# 証明書のエイリアス
cert_alias = "SAMPLE_CERT"
# 証明書をエクスポートした際に指定したパスワード
cert_password = "sAmPlEcErT"
# 証明書のファイルパス
cert_file = os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'Certificate', 'certificate.pfx')
# マシン設定ファイルパス
machine_config_file = r'C:\arcgisserver\config-store\machines\{0}.json'.format(server_name)
```