Because We Love Happy Coding

フリーライターからエンジニア × 講師。発信力だけあり余ってる感じ

kintone REST APIへクライアント証明書付きでアクセスする

今日もまたコーディング。だって僕らはHappy Codingが大好きだから。

あんまり詳しいドキュメントがみつからなかったので、拙いながらも参考まで。

環境

  • kintone

クライアント認証

PHP-cURLを使ったSSLクライアント認証手順 - Qiita

file_get_contentについて。

PHPでクライアント証明書が必要なWebサイトにアクセスする at softelメモ

pfx形式、PKCS#12形式の証明書は、opensslコマンドでPEM形式に変換できる。

contextの中のoptionで'http'を'https'する必要があるかと思ったけれど、SSL通信の場合でもここはhttpコンテキストということでいいらしい。

php - https for stream_context_create - Stack Overflow

IPアドレス制限時のクライアント証明書を利用したREST APIの利用 – cybozu developer network

PHP: SSL context options - Manual

local_pk string Path to local private key file on filesystem in case of separate files for certificate (local_cert) and private key.

どうもpemファイルの運用に2パターンあるらしい。

  • pemファイルとpassphraseをstream_context_set_optionに設定する
  • pemファイルとkeyファイルをstream_context_set_optionに設定する

pfxファイルを変換する際のオプションによって、おそらくどちらのパターンになるかが決まるというわけか。

この辺り、opensslコマンドやSSL関連の理解が足りていない。

pfxファイルをpemファイルとkeyファイルに変換する

  1. foo@bar.co.jp.pfx と foo@bar.co.jp.txt を cybozu 共通設定からダウンロード
  2. foo@bar.co.jp.txtからパスワードを確認しておく
  3. PowerShellを起動。ファイルのディレクトリまでcdで移動してコマンド
    openssl pkcs12 -nodes -in foo@bar.co.jp.pfx -clcerts -nokeys -out some_name.pem
    //パスワード入力
    openssl pkcs12 -nodes -in foo@bar.co.jp.pfx -nocerts -out some_name.key
    //パスワード入力

これでpfxファイルとkeyファイルが生成される。

  • nokeys ……pemファイル内にkeyを書き込まない
  • nocerts ……keyファイル内に証明情報を書き込まない

サンプル関数

symfony2(というかECCUBE3)のControllerの中で使っていた関数だが参考まで。

    public function testKintone(Application $app, Request $request)
    {
      $loginName = 'hoge@hoge';
      $password = 'randompassword';
      
      // リクエストヘッダ
      $header = array(
        "Host: subdomain.s.cybozu.com:443",
        "X-Cybozu-Authorization: " . base64_encode($loginName . ':' . $password),
      );
      
      // HTTPコンテキスト
      $context_array = array(
        "http" => array(
          "method" => 'GET',
          "header" => implode("\r\n", $header),
        ),
        'ssl' => array(
          'local_cert' => __DIR__ . '/certificatefile.pem',//starts with slush
          'local_pk' => __DIR__ . '/secretkey.key',//starts with slush
          // 'passphrase' => 'in_case_you_use_passphrase_instead_of_secretkey',
        )
      );

      $context = stream_context_create($context_array);

      try {
            $result_json = file_get_contents(
                'https://subdomain.cybozu.com/k/v1/record.json?app='.'1'.'&id='.'2', 
                false,
                $context
            );
            return $result_json;
          } catch (Exception $exception) {
            throw $exception;
        }
    }

画像のダウンロードサンプルはこちら。

    public function testKintonePictDownload(Application $app, Request $request)
    {
      $loginName = 'hoge@hoge';
      $password = 'some_password';
      
      // リクエストヘッダ
      $header = array(
        "Host: subdomain.s.cybozu.com:443",
        "X-Cybozu-Authorization: " . base64_encode($loginName . ':' . $password),
      );
      
      // HTTPコンテキスト
      $context_array = array(
        "http" => array(
          "method" => 'GET',
          "header" => implode("\r\n", $header),
        ),
        'ssl' => array(
          'local_cert' => __DIR__ . '/certificatefile.pem',//starts with slush
          'local_pk' => __DIR__ . '/secretkey.key',//starts with slush
          // 'passphrase' => 'in_case_you_use_passphrase_instead_of_secretkey',
        )
      );

      $context = stream_context_create($context_array);// コンテキストの生成

      try {
          $result_json = file_get_contents(
                'https://subdomain.s.cybozu.com/k/v1/record.json?app='.'1'.'&id='.'2', // URI
                false, // use_include_pathはfalse
                $context // コンテキストの生成
            );

          $result_array = json_decode($result_json,true);
          $fileKey = $result_array['record']['添付ファイル']['value'][0]['fileKey'];
          $add_images = file_get_contents('https://subdomain.s.cybozu.com/k/v1/file.json?fileKey=' . $fileKey, false, $context);
          return 'OK';

          } catch (Exception $exception) {
            throw $exception;
        }
      
    }

kintoneは公式ドキュメントのエンドポイントURLに「セキュアアクセスの場合はsubdomain.s.cybozu.com にアクセスする」ってことを明記すべきだと思うんだが違うかな。

参考記事