keyringパッケージで認証情報を管理する


ソースコード中にユーザー名やパスワード、書きたくないですよね？

[Securing Credentials](https://db.rstudio.com/best-practices/managing-credentials/)では、データベース接続時の認証情報管理方法がいくつか紹介されていますが、その中で`keyring`（ https://github.com/r-lib/keyring )というパッケージが紹介されています。

このパッケージは、macOSならキーチェーン、WindowsならCredential StoreといったOS側の仕組みを使って認証情報を管理する方法を提供してくれます。

## パッケージのインストール

### macOS / Windows

macOSとWindowsなら、単にパッケージをインストールするだけで機能します。

``` r
install.packages("keyring")
```

### Linux

Linuxの場合は、いくつかのライブラリを先にインストールしておく必要があるかもしれません。手元（Ubuntu 18.04）で試したところ、パッケージのビルド自体に`libssl`と`libsodium`が必要でした。また、認証情報の管理に`libsecret`を使用するので、これもインストールしておいたほうが良いでしょう。`libsecret`は無くとも一応動作しますが、その場合は単に環境変数に情報が保存されます。なお、RStudio serverからRを起動すると`libsecret`が使用できないため、この場合も環境変数に情報が保存されるようになります（cf.  https://github.com/r-lib/keyring/issues/53 ）。

まず、ターミナルから必要なライブラリをインストールします。ディストリビューションにより多少違いますが、Ubuntuなら以下のようにします。`keyring`のREADME（ https://github.com/r-lib/keyring#readme ）も確認してください。

```
sudo apt install libssl-dev libsodium-dev libsecret-1-dev
```

その後でパッケージをインストールします。

``` r
install.packages("keyring")
```

## 使い方

### 認証情報の保存

`key_set()`で情報を保存します。関数を実行するとパスワードの入力欄が表示されるので、そこにパスワードを入力します。

``` r
keyring::key_set(
  service = "my-database",
  username = "myusername"
)
```

インタラクティブな操作をしたくない場合は、`key_set_with_value()`を使えばパスワードを引数として指定することもできます。

``` r
keyring::key_set_with_value(
  service = "my-database",
  username = "myusername2",
  password = "mypassword2"
)
```

### 認証情報の確認

`key_list()`でサービス名とユーザー名を一覧で取得します。サービス名を指定しなければ、すべての認証情報が表示されます。

``` r
keyring::key_list(service = "my-database")
```

    ##       service    username
    ## 1 my-database  myusername
    ## 2 my-database myusername2

`key_get()`でパスワードを取得します。

``` r
keyring::key_get(
  service = "my-database", 
  username = "myusername"
)
```

    ## [1] "mypassword"

取得しようとしている情報の種類や取得方法によっては、ここでパスワードの入力を求められる場合があります（例えば`knit`すると都度求められるようです）。

なお、macOSの場合はusernameの指定を省略できますが（`keyring::key_list()`で取得されるリストの一番上のパスワードが取得されます）、WindowsとLinuxでは省略できませんでした。

### 認証情報の削除

削除は`key_delete()`で行います。

``` r
keyring::key_delete("my-database", "myusername2")
keyring::key_list("my-database")
```

    ##       service   username
    ## 1 my-database myusername

## もうちょっと細かい使い方

一般的には上記の機能で十分だと思いますが、他にも機能があります。

### バックエンドの変更

macOSかWindowsかLinuxを使用している場合は、OSに適した適当なバックエンドが自動で選択されますが、これを任意に変更することもできます。`options(keyring_backend=)`または環境変数`R_KEYRING_BACKEND`に文字列でバックエンドを指定します。例えば`options(keyring_backend= "env")`とすれば、認証情報を環境変数に保存するようになります。詳しくは`?keyring::backends`を確認してみて下さい。

なお、現在設定されているバックエンドの簡単なマニュアルが`keyring::default_backend()`で確認できます。

``` r
keyring::default_backend()
```

    ## <keyring backend: 'macos'>
    ## Store secrets in the macOS Keychain.
    ## 
    ##  $get                  query a key from the keyring
    ##  $set                  set a key in the keyring (interactive)
    ##  $set_with_value       set a key in the keyring
    ##  $delete               delete a key
    ##  $list                 list keys in a keyring
    ##  $has_keyring_support  TRUE if multiple keyrings are supported
    ##  $keyring_create       create new keyring
    ##  $keyring_list         list all keyrings
    ##  $keyring_delete       delete a keyring
    ##  $keyring_lock         lock a keyring
    ##  $keyring_unlock       unlock a keyring
    ##  $keyring_is_locked    check if a keyring is locked
    ##  $keyring_default      query the default keyring
    ##  $keyring_set_default  set the default keyring

バックエンドとしては以下のようなものが指定可能です。

  - “wincred”…Windows Credential Store
  - “macos”…macOS Keychain
  - “secret\_service”…Secret Service API
(Linux)
  - “file”…暗号化したテキストファイルに保存
  - “env”…環境変数に保存

### キーリングの管理

指定しているバックエンドがサポートしている場合は、キーリングを新たに作成したり、削除したり、ロックしたりできます。キーリングを操作する関数としては以下のようなものが用意されています。

  - `has_keyring_support()`…バックエンドが複数のキーリングをサポートしていればTRUE（“env”以外はすべてTRUEのようです）。
  - `keyring_list()`…キーリング一覧を表示。
  - `keyring_create()`…キーリングの新規作成。
  - `keyring_delete()`…キーリングの削除。
  - `keyring_lock()`…キーリングのロック（デフォルトのキーリングは通常、最初からロックが解除されています）。
  - `keyring_unlock()`…キーリングのアンロック。
  - `keyring_is_locked()`…キーリングがロックされていればTRUE。

詳しくは`?keyring::has_keyring_support`を確認して下さい。