Webエンジニア向けプログラミング解説動画をYouTubeで配信中!
▶ チャンネル登録はこちら

【ITニュース解説】How Blocking Port 80 Made My Time API Project More Secure (And More Annoying)

2025年10月01日に「Dev.to」が公開したITニュース「How Blocking Port 80 Made My Time API Project More Secure (And More Annoying)」について初心者にもわかりやすく解説しています。

作成日: 更新日:

ITニュース概要

APIのセキュリティ向上のため、ポート80をブロックしHTTPSのみ許可した。これによりSSL証明書取得が複雑化したが、IngressとNSG、Cert-Managerのdns-01検証とTerraformを使い、安全な自動証明書発行システムを構築。手間はかかったが、安全なAPIアクセスを実現した。

ITニュース解説

今回のプロジェクトでは、Time APIという自作のAPIをインターネット上で公開し、安全かつアクセスしやすい形で提供することを目指した。その過程で、セキュリティを重視したある決定が、技術的な課題を生み出し、それを解決するために様々なクラウド技術を深く学ぶ機会となった。

まず、APIを外部からアクセス可能にするために「Ingress Controller(イングレスコントローラー)」という仕組みを導入した。これは、インターネットからの通信がサーバー群に到達する際の「交通整理役」のようなものだ。具体的には、ユーザーからのリクエストを複数のAPIインスタンスに振り分けたり(負荷分散)、ユーザーとサーバー間の通信を暗号化したり(SSL/TLS終端)、一つのウェブサイトドメイン内で異なるURLパス(例えばapi.mywonder.works/timeのような形)に基づいて異なるサービスにリクエストをルーティングしたりする。このプロジェクトでは、NginxをベースにしたIngress Controllerを「Terraform(テラフォーム)」というツールを使って自動的にデプロイし、api.mywonder.works/timeというURLでAPIにアクセスできるように設定した。

次に、ネットワークのセキュリティを強化するための重要な決定として、「ポート80」からのアクセスを全てブロックした。ポート80は通常、暗号化されていないHTTP通信に使われる。一方で、ポート443は暗号化されたHTTPS通信に使われる。Virtual Private Cloud Network(VPCネットワーク)という仮想的なネットワーク環境において、Network Security Group(NSG)というセキュリティルールを設定し、外部からの通信はポート443と、VPCネットワーク内部からの通信のみを許可した。これにより、APIへの不正なアクセス経路を減らし、暗号化されていない危険な通信を防ぐことで、全体のセキュリティレベルを大きく向上させることができた。

しかし、このポート80のブロックという決断は、その後の実装に一つの課題をもたらした。APIを安全に公開し、ユーザーに信頼してもらうためには、「SSL/TLS証明書」が不可欠だからだ。この証明書は、ウェブサイトやAPIが本物であることを証明し、ユーザーのブラウザとサーバー間の通信を暗号化する役割を持つ。これにより、通信内容が第三者に盗み見られたり改ざんされたりするのを防ぐことができる。多くの主要なブラウザは、この証明書が信頼できる「認証局(CA)」によって発行されたものであれば、アドレスバーに鍵アイコンを表示して接続が安全であることを示してくれる。Let's Encrypt(レッツエンクリプト)は、このようなSSL/TLS証明書を無料で発行してくれる広く利用されている認証局の一つだ。

SSL/TLS証明書を取得するには、自分がそのドメインの正当な所有者であることを認証局に証明する必要がある。この証明方法の一つに「HTTP-01認証」というものがある。これは、認証局が指定するファイルをウェブサイトの特定のパスに配置し、認証局がポート80経由でそのファイルにアクセスできるかを確認することでドメインの所有権を証明する方法だ。しかし、今回のプロジェクトではポート80をブロックしてしまったため、このHTTP-01認証を利用できなくなった。

そこで、代替手段として「DNS-01認証」という別の証明方法を採用することになった。DNS-01認証は、DNS(Domain Name System)プロバイダのDNSレコードに、認証局が指定する特殊な「TXTレコード」を一時的に追加することで、ドメインの所有権を証明する方法だ。この方法はポート80へのアクセスを必要としないため、ポート80をブロックした環境でも利用できるという利点があった。

DNS-01認証を実装するためには、いくつかの準備が必要だった。まず、ドメイン名とIPアドレスの対応付けを管理する「DNSプロバイダ」が必要だ。今回はName.comというプロバイダを利用した。Name.comはAPIを提供しており、プログラムからDNSレコードを自動で操作できる点が重要だった。次に、Cert-Manager(サートマネージャー)というツールがName.comのDNSレコードを自動的に変更できるように、「DNSレコード変更の権限」を与える必要があった。これは、Name.comのAPIにアクセスするための認証情報(APIトークンなど)を安全にKubernetesクラスタ内に保存し、Cert-Managerが利用できるように設定することで実現した。

さらに、Cert-Managerは全てのDNSプロバイダに標準で対応しているわけではないため、Name.comのような特定のプロバイダでDNS-01認証を行うには「Cert-Manager Webhook(サートマネージャーウェブフック)」というコンポーネントが必要だった。これは、Cert-Managerの機能を拡張し、特定のDNSプロバイダとの連携を可能にするためのもので、認証時にCert-ManagerとName.com APIの間でやり取りを仲介する役割を果たす。幸いにも、このWebhookは他の開発者が作成し、公開していたものがあったため、それを活用することができた。

これらの複雑なインフラストラクチャの構築と設定は、全て「Infrastructure as Code(インフラストラクチャ・アズ・コード、IaC)」の考え方に基づき、Terraformを使って自動化した。IaCでは、コード(設定ファイル)を使ってサーバー、ネットワーク、その他のクラウドサービスといったインフラストラクチャを定義し、それを自動的に構築・管理する。これにより、同じ環境を何度でも確実かつ迅速に再現できるようになった。

具体的なデプロイプロセスとしては、まずKubernetesクラスターやネットワーク、基本的な追加機能といった基盤となるインフラストラクチャをTerraformでプロビジョニングした。その後、アプリケーションのデプロイと証明書管理を別のTerraformコマンドで実行する、という段階的なアプローチを取った。この方法により、基盤が正しく構築されたことを確認してからアプリケーションを展開できるため、デプロイ時のエラーを最小限に抑えられた。

Cert-Managerの導入には、Kubernetesのパッケージマネージャーである「Helm(ヘルム)」を利用した。Helmを使うことで、Cert-Managerコントローラーと、証明書を発行するための設定(ClusterIssuerリソース)を簡単にクラスタ内にデプロイできた。このClusterIssuerでは、Let's EncryptのACMEサーバーと、カスタムで用意したName.com Webhookを利用するDNS-01認証の仕組みを設定した。これにより、Cert-Managerはクラスタ全体で証明書の発行と更新を自動的に管理できるようになった。

Name.com WebhookもHelmを使ってデプロイした。このWebhookは、Cert-ManagerがDNS-01認証を行う際に、Name.comのAPIを呼び出して一時的なTXTレコードを追加・削除する役割を担う。WebhookがName.com APIに安全にアクセスできるよう、APIトークンなどの認証情報は、Kubernetesの「Secret(シークレット)」という仕組みを使って暗号化して保存し、GitHub Actionsのワークフローから安全にTerraform変数経由で注入するようにした。

最終的に、APIのデプロイとIngressリソースの設定を行った。このIngressリソースには、api.mywonder.worksというホスト名に対して/timeパスが来た場合に、APIサービスにトラフィックをルーティングするというルールを定義した。さらに、このIngressリソースに特定の「アノテーション」を追加することで、Cert-ManagerがこのIngressを監視し、記載されたホスト名(api.mywonder.works)に対するSSL/TLS証明書を自動的に発行・更新するように設定した。

Cert-Managerがこのアノテーションを検知すると、まずLet's Encryptに対して証明書発行のリクエストを送信する。Let's Encryptはドメイン所有権を確認するため、Cert-Managerに一時的なTXTレコードの追加を要求する。Cert-Managerはこの要求をWebhook経由でName.com APIに伝え、DNSゾーンに特定のTXTレコードが追加される。Let's Encryptがそのレコードを検証し、ドメインの所有権が確認されると、証明書が発行される。発行された証明書はKubernetesのSecretとして安全に保存され、Ingressコントローラーによって利用されることでHTTPS通信が可能になる。この一連のプロセスは完全に自動化されており、証明書の有効期限が切れる前に、自動的に更新される仕組みとなっている。

これらの複雑な設定とデプロイのプロセスは、全て「GitHub Actions(ギットハブアクションズ)」というCI/CD(継続的インテグレーション/継続的デプロイ)ツールを使って自動化した。GitHub Actionsのワークフローでは、まずAPIのDockerイメージをビルドしてDocker Hubに公開し、その後Terraformを使ってインフラストラクチャをプロビジョニングする。この際、GitHub Secretsに保存された機密情報(ドメイン名やName.comの認証情報)をTerraformに安全に渡すようにしている。そして、基盤が整った後に、アプリケーションとIngressをデプロイするという、段階的かつ自動的なデプロイを実行する。

このプロジェクトを通して、ポート80のブロックというセキュリティを優先した決断が、結果的にSSL/TLS証明書の発行方法を深く探求するきっかけとなった。Ingressコントローラーによるルーティングの自動化、ネットワークセキュリティグループによる厳密なアクセス制限、Cert-ManagerとカスタムWebhookを組み合わせた証明書の自動管理、そしてTerraformとGitHub ActionsによるIaCとCI/CDの実現は、クラウドネイティブな環境でセキュアかつスケーラブルなAPIを構築するための実践的な知識と経験を与えてくれた。初期設定は少し複雑になったが、一度構築してしまえば、手作業なしで安全なAPIを運用できるメリットは非常に大きい。

関連コンテンツ

関連IT用語