NGINX Open Sourceで再起動せずにSSL/TLS証明書をローテーション

NGINX | 2023年9月26日

高性能Webサーバーの分野では、NGINXは軽量で効率的なアーキテクチャにより大量のトラフィックを処理できるため、広く採用されています。共有ディクショナリ機能がNGINX JavaScript module (njs)の一部として導入されたことで、NGINXのパフォーマンスはさらに向上します。

このブログ記事では、njs共有ディクショナリの機能とメリットを解説し、SSL/TLS証明書のローテーション時に再起動を必要としないNGINX Open Sourceの設定方法をご紹介します。

共有ディクショナリの基本とメリット

新しい「js_shared_dict_zone」ディレクティブにより、NGINX Open Sourceユーザーは共有メモリゾーンを有効にし、ワーカープロセス間で効率的にデータを交換できます。これらの共有メモリゾーンはキーバリューディクショナリとして機能し、リアルタイムでアクセスおよび変更できる動的な構成設定を保存します。

共有ディクショナリの主なメリットは次のとおりです。

  • オーバーヘッドを最小限に抑え、簡単に利用可能 — njsに直接組み込まれているため、直感的なAPIとシンプルな実装で、容易にプロビジョニングして利用できます。また、ワーカープロセス間でのデータの管理と共有も簡素化できます。
  • 軽量かつ効率的 – NGINXとシームレスに統合し、イベント駆動型のノンブロッキングI/Oモデルを活用します。このアプローチにより、メモリ使用量を削減し、同時実行性を向上させることで、NGINXは多数の同時接続を効率的に処理できます。
  • スケーラビリティ — NGINXの複数のワーカープロセスにわたる水平スケーリング機能を活用することで、複雑なプロセス間通信メカニズムを必要とせずに、プロセス間でデータを共有し、同期できます。存続時間(TTL)設定では、非アクティブになった共有ディクショナリエントリのレコードをゾーンから削除して管理できます。evictパラメーターは、新しいエントリ用の領域を確保するために、最も古いキーと値のペアを削除します。

共有ディクショナリを使用したSSLローテーション

共有ディクショナリの特に効果的なユースケースの1つが、SSL/TLSローテーションです。js_shared_dict_zoneを使用すると、SSL/TLS証明書または鍵を更新した場合でも、NGINXを再起動する必要はありません。さらに、NGINX上の証明書を管理するためのREST風APIも利用できます。

以下は、js_setディレクティブとssl_certificateディレクティブを使用してHTTPSサーバーを設定するNGINX構成ファイルの例です。JavaScriptハンドラーは、js_setを使用してファイルからSSL/TLS証明書または鍵を読み取ります。

この構成スニペットでは、共有ディクショナリを使用し、証明書とキーをキャッシュとして共有メモリに保存します。キーが存在しない場合は、証明書またはキーをディスクから読み取り、キャッシュに格納します。

キャッシュをクリアするlocationを公開することもできます。ディスク上のファイルが更新されると(証明書や鍵が更新された場合など)、共有ディクショナリによってディスクからの再読み込みが強制されます。この調整により、NGINXプロセスを再起動せずに証明書や鍵をローテーションできます。

http {     ...
    js_shared_dict_zone zone=kv:1m;
   
    server {
    …
     # Sets an njs function for the variable. Returns a value of cert/key
      js_set $dynamic_ssl_cert main.js_cert;
      js_set $dynamic_ssl_key main.js_key;
   
      # use variable's data
      ssl_certificate data:$dynamic_ssl_cert;
      ssl_certificate_key data:$dynamic_ssl_key;
     
     # a location to clear cache 
   location = /clear {
      js_content main.clear_cache;
      # allow 127.0.0.1;
      # deny all;
    }
  ...
  }

次に、js_shared_dict_zoneを使用してSSL/TLS証明書と鍵をローテーションするJavaScript実装を示します。

function js_cert(r) {  if (r.variables['ssl_server_name']) {
    return read_cert_or_key(r, '.cert.pem');
  } else {
    return '';
  }
}

function js_key(r) {
  if (r.variables['ssl_server_name']) {
    return read_cert_or_key(r, '.key.pem');
  } else {
    return '';
  }
}
/** 
   * Retrieves the key/cert value from Shared memory or fallback to disk
   */
  function read_cert_or_key(r, fileExtension) {
    let data = '';
    let path = '';
    const zone = 'kv';
    let certName = r.variables.ssl_server_name;
    let prefix =  '/etc/nginx/certs/';
    path = prefix + certName + fileExtension;
    r.log('Resolving ${path}');
    const key = ['certs', path].join(':');
    const cache = zone && ngx.shared && ngx.shared[zone];
   
    if (cache) {
    data = cache.get(key) || '';
    if (data) {
      r.log(`Read ${key} from cache`);
      return data;
    }
  }
  try {
    data = fs.readFileSync(path, 'utf8');
    r.log('Read from cache');
  } catch (e) {
    data = '';
    r.log(`Error reading from file:${path}. Error=${e}`);
  }
  if (cache && data) {
    try {
      cache.set(key, data);
      r.log('Persisted in cache');
    } catch (e) {
      const errMsg = `Error writing to shared dict zone: ${zone}. Error=${e}`;
      r.log(errMsg);
    }
  }
  return data
}

By sending the /clearリクエストを送信すると、キャッシュが無効化され、次回のSSL/TLSハンドシェイク時にNGINXがディスクからSSL/TLS証明書またはキーを読み込みます。また、リクエストからSSL/TLS証明書またはキーを取得し、キャッシュへの保存と更新も行うjs_contentを実装できます。

この例の完全なコードは、njs GitHubリポジトリで確認できます。

今すぐ始める

共有ディクショナリ機能は、アプリケーションのプログラマビリティを高め、効率化とスケーラビリティの面で大きなメリットをもたらす強力なツールです。js_shared_dict_zoneの機能を活用することで、新たな成長機会を引き出し、増大するトラフィック需要に効率的に対応できます。

NGINX環境をjs_shared_dict_zoneでさらに強化しませんか?NGINX環境をjs_shared_dict_zoneでアップグレードすることで、新たなユースケースに対応できます。この機能の詳細については、ドキュメントをご覧ください。また、最近公開されたnjs-acmeプロジェクトでは、共有ディクショナリ機能の完全な例を確認できます。このプロジェクトにより、njsモジュールのランタイムをACMEプロバイダーと連携させることができます。

NGINX Open Sourceを使い始めたい方や、ご質問がある方は、NGINX Community Slackにご参加ください。自己紹介をして、NGINXユーザーのコミュニティと交流しましょう。


共有
タグ: F5 NGINX, Tech

関連するブログ記事

チュートリアル:NGINXを使用してアプリケーション向けにOpenTelemetryを構成する
NGINX | 2024/01/18

チュートリアル:NGINXを使用してアプリケーション向けにOpenTelemetryを構成する

OpenTelemetryを使用してNGINXサーバーの状態と健全性をより明確に把握することで、問題のトラブルシューティングを行い、Webアプリケーションのパフォーマンスを向上できます。

AkitaのNGINX Plus認定モジュールでAPIエンドポイントの問題を特定・修正
NGINX | 2023/05/31

AkitaのNGINX Plus認定モジュールでAPIエンドポイントの問題を特定・修正

Akita SoftwareのAPIオブザーバビリティ向け新しいNGINX Plus Certified Moduleを活用して、APIエンドポイントの問題をより迅速に特定し、修正できます。

JavaプロジェクトをスキャフォールディングしてKubernetesネイティブアプリを構築する方法
NGINX | 2023/02/09

JavaプロジェクトをスキャフォールディングしてKubernetesネイティブアプリを構築する方法

Red HatのシニアプリンシパルデベロッパーアドボケイトであるDaniel Oh氏が、Javaプロジェクトをゼロから構築するためのひな形を作成し、Kubernetesネイティブアプリケーションとしてビルドする方法を解説します。

F5 NGINXaaS for Azureのご紹介:Microsoft Azureでネイティブに利用できるSaaS型ロードバランシング
NGINX | 2022/05/24

F5 NGINXaaS for Azureのご紹介:Microsoft Azureでネイティブに利用できるSaaS型ロードバランシング

NGINXaaS for Azureは、NGINX PlusをAzureネイティブのSaaSとして利用できるサービスです。NGINXの設定を容易にリフト&シフトできるため、クラウド導入とモダンアプリの展開を加速できます。

SELinuxでNGINXおよびNGINX Plusを使用する
NGINX | 2018/08/17

SELinuxでNGINXおよびNGINX Plusを使用する

Red Hat Enterprise Linux(RHEL)および関連ディストリビューションでSecurity-Enhanced Linux(SELinux)を有効にすると、デフォルト設定によりNGINXとNGINX Plusの一部の操作が制限されます。この記事では、すべての機能を利用できるようにSELinuxの設定を変更する方法について説明します。

NGINX PlusによるAWS Auto Scalingグループの負荷分散
NGINX | 2017/03/06

NGINX PlusによるAWS Auto Scalingグループの負荷分散

新しいnginx-asg-sync統合ソフトウェアにより、NGINX PlusはAWS Auto Scalingグループの負荷を直接分散できるため、クラウドでの負荷分散がさらに柔軟になります