Azure App Service で curl を使って SSL (https) でアクセスする際の注意点


こんにちは。

このところハンズオンをやるたびに説明しているので、改めて注記しておこうと思います。 (昨日の Twilio ハンズオン、今日の Azure AD ハンズオン、Office 365 API などなど)

Azure App Service の Web App (旧 Azure WebSite) で、PHP から curl を使って https (SSL) のサイトにアクセスする場合、下記の通り、証明書を明示的に指定する必要があります。(「とにかく、すぐ動かしたい」という方は、推奨はしませんが、下記コメントの通り CURLOPT_SSL_VERIFYPEER を false にしても OK です。検証目的などで暫定で動かす場合は、この方法で回避しても良いですね。)

<?php
$req = curl_init();
curl_setopt($req, CURLOPT_URL,
  'https://api.twilio.com');
curl_setopt($req, CURLOPT_RETURNTRANSFER, true);
curl_setopt($req, CURLOPT_CAINFO, dirname(__FILE__) . '\test.pem'); // recommended
//curl_setopt($req, CURLOPT_SSL_VERIFYPEER, false); // not recommended
$res = curl_exec($req);    
curl_close($req);
var_dump($res);
?>

この証明書は、例えば、Windows を使用している方は、以下の通り作成できます。

  • Internet Explorer で目的のサイトにアクセスして証明書の内容を確認します。下図の鍵 (Key) のアイコンをクリックして、[証明書の表示] をクリックします。
  • 証明書の Chain を確認します。例えば、下図では、thawte の Server CA の証明書が使用されています。
  • Windows のコマンドで certmgr と入力すると、皆さんのマシン (Windows) に登録されている証明書を確認できます。
    今回の例では、ルート証明機関の thawte の Server CA の証明書が使用されています。(Internet Explorer で閲覧した場合は、この証明書が使用されます。下図参照)
  • この証明書を表示して、下図の [ファイルにコピー] ボタンを押すと証明書をファイルに保存できます。
    Base64 Encode で「test.pem」などのファイル名で保存します。
  • あとは、この証明書をアップロードして、上記の通り、この証明書を指定して (CURLOPT_CAINFO オプションを使って) curl を実行します。

また、3rd party が提供する API (ベンダー提供の SDK やライブラリーなど) を使用する場合も、内部で curl を使用している場合があるので注意してください。
3rd party が提供する API では、多くの場合、設定 (コード) により証明書の明示的な指定が可能になっていると思いますので、この設定方法に従ってください。例えば、PHP の Twilio API (ライブラリー) を使用する場合は、以下の通り証明書を指定します。(提供されているライブラリーや SDK によって指定方法が異なります。)

///// hello.php

<?php
require "/vendor/twilio/sdk/Services/Twilio.php";
$xml = new Services_Twilio_Twiml();
$xml->say('こんにちは', array('language' => 'ja-jp'));
header('Content-type: text/xml; charset=utf-8');
print $xml;
?>
///// call.php

<?php
require "/vendor/twilio/sdk/Services/Twilio.php";
$http = new Services_Twilio_TinyHttp(
  'https://api.twilio.com',
  array('curlopts' => array(
    CURLOPT_CAINFO => dirname(__FILE__) . '\cacert.pem',
  )));
$client = new Services_Twilio(
  "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", // SID
  "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy", // Auth Token
  "2010-04-01",
  $http);
$xmlUrl = (empty($_SERVER["HTTPS"]) ? "http://" : "https://") . $_SERVER["HTTP_HOST"] . "/hello.php";
$message = $client->account->calls->create(
  "+xx-xx-xxxx-xxxx", // From
  "+xx-xx-xxxx-xxxx",  // To
  $xmlUrl);  
header('Content-type: text/plain; charset=utf-8');
echo "電話をかけました!";
?>

補足 : なお、あらかじめ、PHP 用の Twilio API を取得しておいてください。composer を使って取得する場合は、以下のコマンドを入力します。

curl http://getcomposer.org/installer | php
php composer.phar require twilio/sdk dev-master

Azure Web App (と ClearDB) で OpenVBX を動かす場合には、config/config.php に以下の通り指定します。

$config['twilio_use_certificate'] = true;

 

curl を使っているライブラリーが動かないというこの現象、結構よく出くわすので、おぼえておいてください。

 

※ 変更履歴

2015/03/26  Azure WebSite から Azure Web App に名称変更

 

 

Comments (3)

  1. 榧野正一 says:

    TwilioをAzure Web Siteで利用したいと考え、

    Call.phpを参考に発呼のテストを行っています。

    下記のエラーが消えず、困っています。

    SSL certificate problem: self signed certificate in certificate chain

    Certificate data from Mozilla as of: Wed Feb 25 04:12:04 2015の

    cacert.pemを取得して、call.phpと同じフォルダに配置しており、

    ファイルは読めていると思います。

    しかしながら、上記のエラーが消えず、困っています。

    なお、array('curlopts' => array(CURLOPT_SSL_VERIFYPEER => false))を指定して、$httpを作成すると

    通るので、証明書がうまく働いていないと認識しています。

    お手数ですが、回避方法がありましたら、お教えください。

  2. お世話になります。

    試しに、今、こちらで同じサンプルを作って Azure WebSites で動かしてみましたが、特に警告も出ず、問題なく動作しました。まずは、上記とまったく同じ手順で動作するかご確認いただけないでしょうか?

    例えば、上図の通り、信頼されたルート証明機関 (CA) の「Thawte Premium Server CA」をエクスポートされましたでしょうか?(他のものを選択されてませんよね?)

    また、エクスポート方法 (フォーマット) は、Base 64 エンコードされた X.509 証明書として保存してますでしょうか?(他のフォーマットになっていないでしょうか?)

    あと、別の箇所で証明書エラーになっている可能性もあるので、もし実行されているコードが異なるなら、まずは、上記とまったく同じサンプル コードで確認してみていただけないでしょうか?

    よろしくお願いします。

  3. 榧野 正一 says:

    ご連絡ありがとうございます。

    証明書を取得する時に、Thawte Premium Server CAと違うものをとっていました。

    申し訳ありません。

    取得したcacert.pemにもPremiumServerのCAがなかったため、

    エラーとなっていることを理解出来ました。

    何日もトライして出来なかったのでほんと助かりました。

Skip to main content