passcore on Windows Server 2016

# passcore On Windows Server 2016

## passcoreとは

[passcore](https://github.com/unosquare/passcore)とは、WebベースのUIでActive Directoryユーザのパスワードが変更出来るソフトウェアです。
オープンソースで開発されており、プロジェクトサイトは次のURLです。

- https://github.com/unosquare/passcore

## 前提条件

- Active Directoryが構成済みであること
- ドメインに参加したコンピュータで動作させること
- Windows Server 2016でドメインを構成し、ドメインコントローラ上でpasscoreを動作させます。

## ポイント

- READMEに有るとおり、PowerShellを使う方法でさくっとインストール出来ますが、PowerShellスクリプトでは.NET Core Windows Server Hostingのバージョンが2.2.3を想定しており、READMEからリンクされている、2.1ではバージョンの差分があり、インストールに失敗します。

## 導入方法

1. 役割と機能の追加ウィザードで、「Webサーバ(IIS)」をインストールします。   
細かいオプションはとりあえず、デフォルトのままで動作します。
2. [.NET Core 2.2.3 Windows Server Hosting](https://dotnet.microsoft.com/download/thank-you/dotnet-runtime-2.2.3-windows-hosting-bundle-installer)をダウンロードし、インストールします。
2. PowerShellを管理者権限で開き、次のコマンドを実行します。   

    ```
    Set-ExecutionPolicy Bypass -Scope Process -Force; iex ((New-Object System.Net.WebClient).DownloadString('https://raw.githubusercontent.com/unosquare/passcore/master/Installer.ps1'))
    ```

3. 途中でメモ帳が出てきますが、とりあえず閉じるとインストール完了です。

## 動作確認

1. http://ホストのIPアドレス:8080/ でアクセスすると、passcoreのWebUIが表示されます。
2. 必要な項目を入力し、パスワードが更新できれば完了です。

## 各種設定

\passcore\appsettings.jsonが設定ファイルとなります。
日本語化もこのファイルで出来るので、こんな感じにしてみました。

```appsettings.json
{
  "Logging": {
    "IncludeScopes": false,
    "LogLevel": {
      "Default": "Debug",
      "System": "Information",
      "Microsoft": "Information"
    }
  },
  "WebSettings": {
    "EnableHttpsRedirect": true
  },
  "AppSettings": {
    // The following options for AD Provider (remove if you don't use this Provider)
    "UseAutomaticContext": true, // Set true to allow PassCore to reset password using the same credentials, or false if you will fill the credentials below
    "RestrictedADGroups": [
      "Administrators",
      "Domain Admins",
      "Enterprise Admins"
    ], // Set the AD groups to restrict the use of PassCore
    "AllowedADGroups": [], // Set the AD Groups to allow PassCore, if the array is empty all the groups no-restricted above are allowed
    "IdTypeForUser": "UPN", // Possible values are "DN", "GUID", "Name", "SAM", "SID" and "UPN" (Default UPN)
    "UpdateLastPassword": false, // Set true to allow PassCore to  update the last password timestamp
    // The following options are for LDAP Provider (remove if you don't use this Provider)
    "LdapSearchBase": "ou=people,dc=example,dc=com",
    "LdapSecureSocketLayer": false, // Default for AD is true when using LDAPS 636
    "LdapStartTls": false, // Default for AD is true when using LDAP 389
    "LdapChangePasswordWithDelAdd": true,
    "LdapSearchFilter": "(sAMAccountName={Username})", // Another value: "(&(objectClass=person)(cn={Username}))"
    // General options (valid for both providers)
    "LdapHostnames": [ "" ], // Set your hostname(s)
    "LdapPort": 389, // Default for AD is 389, for LDAPS 636
    "LdapUsername": "", // Set the username or distinguish name (DN) to bind the LDAP server
    "LdapPassword": "", // Set the password for the username
    // デフォルトドメイン
    "DefaultDomain": "" // Set your default AD domain here, or non "@" logins will not work! Use empty value to allow user to set the domain. This option is ONLY available with UPN.
  },
  "ClientSettings": {
    "ValidationRegex": {
      "EmailRegex": "^[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\\.[a-zA-Z0-9-]+)*$",
      "UsernameRegex": "^[a-zA-Z0-9._-]{3,20}$"
    },
    "ShowPasswordMeter": true,
    "Recaptcha": {
      "SiteKey": "", // ReCAPTCHA public key: replace this! or leave empty if you don't need ReCAPTCHA
      "PrivateKey": "", // ReCAPTCHA private key: replace this! or leave empty if you don't need ReCAPTCHA
      "LanguageCode": "en"
    },
    // 認証にメールアドレスを利用するか
    // 利用しない場合、アカウント名の末尾にDefaultDomainが補完される
    "UseEmail": "true",
    "ApplicationTitle": "パスワードの変更 | セルフサービスアカウントマネージメントツール",
    "ChangePasswordTitle":  "パスワードの変更",
    "ChangePasswordForm": {
      "HelpText": "このツールで問題が発生している場合は、IT担当者へ連絡してください。",
      "UsernameLabel": "ユーザ名",
      "UsernameHelpblock": "あなたの組織のメールアドレスを入力してください。",
      "UsernameDefaultDomainHelperBlock": "あなたの組織のユーザ名を入力してください。",
      "CurrentPasswordLabel": "現在のパスワード",
      "CurrentPasswordHelpblock": "あなたの現在のパスワードを入力してください。",
      "NewPasswordLabel": "新しいパスワード",
      "NewPasswordHelpblock": "新しいパスワードを入力してください。",
      "NewPasswordVerifyLabel": "新しいパスワード(確認)",
      "NewPasswordVerifyHelpblock": "再度、新しいパスワードを入力してください。",
      "ChangePasswordButtonLabel": "パスワードの変更"
    },
    "ErrorsPasswordForm": {
      "FieldRequired": "この項目は必須です。",
      "UsernamePattern": "有効なユーザ名を入力してください。",
      "UsernameEmailPattern": "有効なメールアドレスを入力してください。",
      "PasswordMatch": "パスワードが一致していません。"
    },
    "Alerts": {
      "SuccessAlertTitle": "あなたのパスワードは変更されました。",
      "SuccessAlertBody": "すべてのドメインコントローラに変更が反映されるまでに少し時間がかかる場合があります。",
      "ErrorPasswordChangeNotAllowed": "あなたはパスワードの変更が許可されていません。IT担当者に連絡してください。",
      "ErrorInvalidCredentials": "ユーザ名もしくは現在のパスワードに誤りがあります。",
      "ErrorInvalidDomain": "入力されたドメインではログインできませんでした。",
      "ErrorInvalidUser": "ユーザ名もしくは現在のパスワードに誤りがあります。",
      "ErrorCaptcha": "あなたがロボットではないことを確認します。",
      "ErrorFieldRequired": "Fulfill all the fields",
      "ErrorFieldMismatch": "入力された新しいパスワードが一致しません。"
    }
  }
}
```



## こんな時は

### 0X800708C5エラーで更新できない場合

パスワードの複雑さなどは満たしているのに、

> Failed to update password: パスワードはパスワード ポリシーの要件を満たしていません。
> パスワードの最短の長さ、パスワードの複雑性、およびパスワード履歴の要件を確認してください。
> (Exception from HRESULT: 0x800708C5)

と言われる場合は、次の操作を行うことで回避が出来ます。
ただ、理由は良くわかってないので、自己責任で。

- 参考サイト：http://blog.cionsystems.com/?p=907
    - 既定のドメインポリシーで、パスワードの変更禁止期間を0に設定します。

1. ファイル名を指定して実行で「gpmc.msc」(グループポリシーの管理)を開きます。
2. フォレスト → 「ドメイン」 → ドメイン名 → 「グループポリシーオブジェクト」 → 「Defaulte Domain Policy」を選択し、右クリックして編集を選びます。
3. 「コンピュータの構成] → 「ポリシー」→「Windowsの設定」→「セキュリティの設定」→「アカウントポリシー」→「パスワードのポリシー」→「パスワードの変更禁止期間」を「0」に設定します。
4. 管理者としてコマンドプロンプトを開き、「gpupdate /force」を実行します。