menu
Webを活用してお客様のビジネス課題を解決します。札幌・東京を拠点にWebコンサルティングをコアにした、Web制作・システム開発・サーバ構築会社です。

時刻テストのためにLinuxのシステム時刻を変更したらアプリケーションが動かなくなった原因と対策

シェア
ツイート
シェア
ブックマーク
タイトルとURLをコピー

最終更新日:2024/10/08   公開日:2024/10/07

はじめに

ウェブアプリケーションには、現在時刻に応じて異なる出力を行う機能が組み込まれている場合があります。たとえば、食事処のウェブサイトのトップページで、現在時刻に応じたメニュー表を表示する(朝~昼はランチメニュー、夕方~はディナーメニューを表示する)といった機能がその例です。

今回、この機能のテストのために単体テストを用意しましたが、サーバー上での動作確認を求める声があったため、NTPサービスを一時的に無効化してLinuxのシステム時刻を変更しました。その結果、アプリケーションが予期せず動作しなくなりました。この記事では、このような問題が発生する原因と、回避策について解説します。

 

発生していた問題の原因

調査の結果、問題の原因はTLS証明書の検証に失敗していたことでした。

このアプリケーションは外部サービスとHTTPS通信を行っており、その際、証明書の有効性をクライアント側の現在時刻で確認します。システム時刻が大幅にずれていると、証明書が有効期限外と判断され、接続に失敗してしまうのです。この結果、アプリケーションは外部サービスからレスポンスを受け取れず、正常に動作しなくなりました。

システム時刻のずれが原因でアプリケーションが正常に動作しない問題は他にもあります。例えば、AWS CLIやAWS SDKを使用してAPIを呼び出す際、現在時刻を基にシグネチャ計算が行われます。AWSはSignature Version 4を使ってリクエストに署名しますが、セキュリティ上、リクエストに含まれるタイムスタンプとAWSサーバーのタイムスタンプが5分以上ずれると、リクエストが拒否される仕様となっています。

現在、VPC内のインスタンスはAmazon TimeSync Serviceによって自動的に時刻が同期されますが、このサービスがなかった頃は、EC2上でAPIコールを行っていると毎日少しずつ時刻がずれていき、ある日突然スクリプトが動かなくなる、と言った問題が発生することがありました。

 

本問題の回避策

問題の原因は「システム全体の時刻が変更されていること」にあるため、アプリケーション内で特定部分のみの時刻を変更できるよう実装することが根本的な解決策です。

具体的には、現在時刻を直接ライブラリから取得するのではなく、時刻取得を一元管理するサービスや独自関数を経由して取得する方法を採用することです。たとえば、PHPであればCarbon::now を使って直接現在時刻を取得する代わりに、その関数を経由して取得するようにします。この関数にはモックを適用したり、テスト時には設定に基づいた固定時刻を返すようにすることで、必要な部分のみ時刻を変更して検証可能な環境を整えることができます。

 

おわりに

システム時刻の変更を伴うテストには、ここで挙げた問題に加えて、予期しない問題が発生する可能性があります。そのため、システム全体の時刻変更を伴うテストは注意して行う必要があります。

時刻依存のテストを行う効果的な方法は、アプリケーションの時刻依存部分を共通化し、テスト時にのみダミーの時間を使用できる仕組みを導入することです。この手法を導入することで、システム全体に影響を与えず、安心してテストを行うことができます。