Route53
このガイドでは、Amazon Route53 を使用して DNS01 ACME チャレンジを解決するためのIssuer
またはClusterIssuer
の設定方法について説明します。cert-manager が DNS01 チャレンジをどのように処理するかについてのより一般的な理解を得るために、最初にDNS01 チャレンジプロバイダーのページを読むことをお勧めします。
ℹ️ このガイドでは、Route53 に既にホストゾーンがあることを前提としています。
📖 cert-manager と AWS を初めて使用する方は、AWS + LoadBalancer + Let's Encryptチュートリアルをお読みください。エンドツーエンドの手順が記載されています。
IAMポリシーの設定
cert-managerは、DNS01チャレンジを解決するためにRoute53にレコードを追加できる必要があります。そのためには、次の権限を持つIAMポリシーを作成します。
{"Version": "2012-10-17","Statement": [{"Effect": "Allow","Action": "route53:GetChange","Resource": "arn:aws:route53:::change/*"},{"Effect": "Allow","Action": ["route53:ChangeResourceRecordSets","route53:ListResourceRecordSets"],"Resource": "arn:aws:route53:::hostedzone/*"},{"Effect": "Allow","Action": "route53:ListHostedZonesByName","Resource": "*"}]}
ℹ️
route53:ListHostedZonesByName
ステートメントは、(オプションの)hostedZoneID
を指定する場合は削除できます。さらに、cert-managerがアクセスできるホストゾーンを制限することで(例:arn:aws:route53:::hostedzone/DIKER8JEXAMPLE
)、ポリシーをより厳しくすることができます。📖 Amazon Route 53でサポートされているアクションについては、Amazon Route 53 APIリファレンスのAmazon Route 53 APIリファレンスをご覧ください。
📖 EKSを使用している場合は、
eksctl
がcert-manager IAMポリシーを自動的に作成する方法について学習してください。
認証情報
cert-managerは、Route53 APIに対して認証するためにAWSアクセスキーを必要とします。アクセスキーは、AWSで次のように定義されています。
アクセスキー:アクセスキーID(例:
AKIAIOSFODNN7EXAMPLE
)とシークレットアクセスキー(例:wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
)の組み合わせです。アクセスキーを使用して、AWSに対して行うAPIリクエストに署名します。
2つのオプションがあります。
- (ベストプラクティス)一時的なセキュリティ認証情報を持つIAMロールを使用します。
- 長期的なアクセスキーを持つIAMユーザーを使用します。
一時的なセキュリティ認証情報を持つIAMロールを使用することがベストプラクティスとされている理由は次のとおりです。
- 長期的なアクセスキー(例:シークレット内)を保存する必要がありません。
- アクセスキーのローテーションを管理する必要がありません。
cert-managerがAWS外部にデプロイされているがDNSゾーンがRoute53上にある場合、長期的なアクセスキーを持つIAMユーザーを使用することは妥当な選択肢です。
cert-managerは、アクセスキーを取得するための複数の方法をサポートしており、それらは「アンビエント」または「ノンアンビエント」のいずれかに分類できます。
アンビエント認証情報
アンビエント認証情報は、次のいずれかのメカニズムによってcert-managerコントローラーPodで使用可能になる認証情報です。
- EKS Pod Identity:
cert-managerが、すべてのKubernetesノードで実行されるEKS認証APIから認証情報を受け取ります。 - EKS IAM Roles for Service Accounts (IRSA):
cert-managerは、cert-managerコントローラーPodにマウントされるKubernetes ServiceAccountトークンを使用します。 - EC2インスタンスメタデータサービス(IMDS):
cert-managerは、IMDSのiam/security-credentials/<role-name>
エンドポイントから認証情報を受け取ります。 - 環境変数:
cert-managerは、それらの変数が存在する場合、cert-managerコントローラーPod内のAWS_ACCESS_KEY_ID
とAWS_SECRET_ACCESS_KEY
環境変数から認証情報を読み込みます。 - 共有設定ファイルと認証情報ファイル:
cert-managerは、cert-managerコントローラーPodにマウントされているファイル(~/.aws/config
と~/.aws/credentials
)から認証情報を読み込みます。
アンビエント認証情報の利点は、設定が容易で、Amazon AWSによって広範に文書化されていることです。アンビエント認証情報の欠点は、すべてのClusterIssuerリソースとすべてのIssuerリソースでグローバルに使用できるため、マルチテナント環境では、IssuerまたはClusterIssuerを作成する権限を持つテナントは、そのアカウントに付与された権限を取得してアンビエント認証情報を使用できる可能性があることです。
📖 cert-managerがこれらのすべてのアンビエント認証情報ソースをサポートする方法については、AWS SDKおよびツール標準化された認証情報プロバイダーをお読みください。
⚠️ デフォルトでは、cert-managerは
Issuer
リソースではなくClusterIssuer
リソースに対してのみアンビエント認証情報を使用します。これは、Issuerリソースを作成する権限を持つ特権のないユーザーが、cert-managerが偶然アクセスできる認証情報を使用して証明書を発行することを防ぐためです。ClusterIssuerリソースはクラスタスコープ(名前空間なし)であり、プラットフォーム管理者だけがそれらを作成する権限を付与されるべきです。
⚠️
Issuer
リソースに対してアンビエント認証メカニズムを有効にすることは可能ですが(推奨されません)、cert-managerコントローラーで--issuer-ambient-credentials
フラグをtrueに設定することで行えます。
Route53アンビエント認証情報を使用するためのClusterIssuer
の例を次に示します。
apiVersion: cert-manager.io/v1kind: ClusterIssuermetadata:name: letsencrypt-prodspec:acme:...solvers:- dns01:route53: {}
ℹ️ 使用するアンビエントメカニズムに関係なく、
route53
セクションは空のままです。cert-managerは、cert-manager Podに追加される環境変数を調べることで、認証情報、ロール、リージョンを見つけることができます。
EKS Pod Identity
EKSでcert-managerをデプロイする場合、EKS Pod Identityはアンビエント認証情報を使用する最も簡単な方法です。これは4ステップのプロセスです。
-
クラスタにEKS Pod Identityエージェントを設定します。
-
EKS Pod Identityエージェントが必要な環境変数をPodに注入できるように、cert-manager Deploymentを再起動します。
-
ClusterIssuer
リソースを作成します。apiVersion: cert-manager.io/v1kind: ClusterIssuermetadata:name: letsencrypt-prodspec:acme:solvers:- dns01:route53: {}
EKS IAM Roles for Service Accounts (IRSA)
EKSでcert-managerをデプロイする場合、IAM Roles for Service Accounts (IRSA)はアンビエント認証情報を使用するもう1つの方法です。Pod Identityよりも複雑で、Kubernetesクラスタ管理者とAWSアカウント管理者間の調整が必要です。これには、Kubernetesのcert-manager
ServiceAccountに注釈を付け、AWSでIAMロール、信頼ポリシー、信頼関係を設定する必要があります。ミューテーションWebhookによって、cert-manager Podにマウントされたサービスアカウントボリュームが自動的に設定されます。
-
クラスタのIAM OIDCプロバイダーを作成します。
cert-managerでIRSAを使用するには、最初にクラスタでその機能を有効にする必要があります。公式ドキュメントに従ってください。
-
信頼関係を作成します。
この構成では、IAMロールがcert-manager
ServiceAccount
にマップされ、AWSで認証できるようになります。ServiceAccount
にマップするIAMロールには、cert-managerが使用するすべてのRoute53ゾーンに対する権限が必要です。次の信頼ポリシーをIAMロールに追加して、信頼関係を作成します。{"Version": "2012-10-17","Statement": [{"Effect": "Allow","Action": "sts:AssumeRoleWithWebIdentity","Principal": {"Federated": "arn:aws:iam::<aws-account-id>:oidc-provider/oidc.eks.<aws-region>.amazonaws.com/id/<eks-hash>"},"Condition": {"StringEquals": {"oidc.eks.<aws-region>.amazonaws.com/id/<eks-hash>:sub": "system:serviceaccount:<namespace>:<service-account-name>"}}}]}次のものを置き換えます。
-
<aws-account-id>
をEKSクラスタのAWSアカウントIDに置き換えます。 -
<aws-region>
をEKSクラスタが存在するリージョンに置き換えます。 -
<eks-hash>
をEKS API URLのハッシュに置き換えます。これはランダムな32文字の16進数文字列になります(例:45DABD88EEE3A227AF0FA468BE4EF0B5
)。 -
<namespace>
をcert-managerが実行されている名前空間に置き換えます。 -
<service-account-name>
をcert-managerによって作成されたServiceAccount
オブジェクトの名前に置き換えます。
ℹ️ 複数アカウントの例に従っている場合、この信頼ポリシーは、ARN
arn:aws:iam::XXXXXXXXXXX:role/cert-manager
を持つアカウントXのcert-managerロールにアタッチされます。権限ポリシーは上記と同じです。 -
-
cert-manager
ServiceAccount
にアノテーションを付与します。apiVersion: v1kind: ServiceAccountmetadata:annotations:eks.amazonaws.com/role-arn: arn:aws:iam::XXXXXXXXXXX:role/cert-managercert-manager Helmチャートは、cert-managerの
ServiceAccount
にアノテーションを注入するための変数を次のように提供します。serviceAccount:annotations:eks.amazonaws.com/role-arn: arn:aws:iam::XXXXXXXXXXX:role/cert-managerℹ️ 複数アカウントの例に従っている場合、アカウントYのロールを使用して
ClusterIssuer
を変更します。 -
(オプション) ファイルシステムの権限を更新します。
📢 このドキュメントの改善にご協力ください
このオプション手順が必要となる理由は、EKS Fargateと一部の古いバージョンのEKSでは、次のようなエラーが発生する可能性があるためです。
/var/run/secrets/eks.amazonaws.com/serviceaccount/token のファイルを読み取れません
open /var/run/secrets/eks.amazonaws.com/serviceaccount/token: permission denied
この場合、cert-managerプロセスのユーザーとグループを変更して、マウントされたServiceAccountトークンを読み取れるようにすることができます。
cert-manager/website#697
: IRSA NeedsrunAsUser: 1001
を読んで、この手順がまだ必要かどうか、または廃止されたかどうかをお知らせください。異なるユーザーとグループを使用してcert-manager
Deployment
を変更し、ServiceAccount
トークンを読み取れるようにする必要がある場合もあります。spec:template:spec:securityContext:fsGroup: 1001runAsUser: 1001cert-manager Helmチャートは、cert-managerの
Deployment
を変更するための変数を次のように提供します。securityContext:fsGroup: 1001runAsUser: 1001 -
cert-manager Deploymentを再起動します。
webhookが必要な
volume
、volumemount
、および環境変数をPodに注入できるように、cert-manager Deploymentを再起動します。 -
ClusterIssuer
リソースを作成します。apiVersion: cert-manager.io/v1kind: ClusterIssuermetadata:name: letsencrypt-prodspec:acme:solvers:- dns01:route53: {}
非環境クレデンシャル
非環境クレデンシャルとは、IssuerまたはClusterIssuerリソースで明示的に設定されたクレデンシャルです。例えば、
- アクセスキーシークレット参照:
cert-managerがKubernetes Secretリソースから長期的なアクセスキーを読み込む場合。 - ServiceAccount参照:
cert-managerがKubernetes APIサーバーからServiceAccountトークン(署名付きJWT)を取得し、STS AssumeRoleWithWebIdentityエンドポイントを使用して一時的なAWSクレデンシャルと交換する場合。
非環境クレデンシャルの利点は、cert-managerがマルチテナント環境でRoute53操作を実行できることです。各テナントは、自分の名前空間にIssuerリソースを作成および更新する権限を付与され、自分の名前空間に独自のAWSクレデンシャルを提供できます。
専用のKubernetes ServiceAccountを持つIAMロール
📖 EKSにcert-managerをデプロイし、この認証メカニズムを使用する方法については、AWS + LoadBalancer + Let's Encryptチュートリアルを参照してください。
この構成では、独自のServiceAccounts
をIssuer
またはClusterIssuer
で参照でき、cert-managerはKubernetes APIからServiceAccountトークンを取得し、AWSの一時的なクレデンシャルと交換するためにSTSに送信します。
このメカニズムの利点は次のとおりです。
- 各Issuerは異なる
ServiceAccount
を参照できます。つまり、権限を制限して、各ServiceAccount
が、必要なゾーンのみを更新できる権限を持つIAMロールにマップされるようにできます(Pod IdentityまたはIRSAとは異なります)。 - このメカニズムは、cert-managerがAWSの外側にデプロイされている場合でも機能します。
設定方法は次のとおりです。
-
ServiceAccountを作成します。
ServiceAccount
を参照するには、最初に存在する必要があります。通常のIRSAとは異なり、eks.amazonaws.com/role-arn
アノテーションは必要ありません。apiVersion: v1kind: ServiceAccountmetadata:name: <service-account-name> -
IAMロールの信頼ポリシーを作成します。
AWS認証に使用する
ServiceAccount
ごとに、最初に信頼ポリシーを設定する必要があります。{"Version": "2012-10-17","Statement": [{"Effect": "Allow","Action": "sts:AssumeRoleWithWebIdentity","Principal": {"Federated": "arn:aws:iam::<aws-account-id>:oidc-provider/oidc.eks.<aws-region>.amazonaws.com/id/<eks-hash>"},"Condition": {"StringEquals": {"oidc.eks.<aws-region>.amazonaws.com/id/<eks-hash>:sub": "system:serviceaccount:<namespace>:<service-account-name>"}}}]}次のものを置き換えます。
<aws-account-id>
をEKSクラスタのAWSアカウントIDに置き換えます。<aws-region>
をEKSクラスタが存在するリージョンに置き換えます。<eks-hash>
をEKS API URLのハッシュに置き換えます。これはランダムな32文字の16進数文字列になります(例:45DABD88EEE3A227AF0FA468BE4EF0B5
)。<namespace>
はServiceAccount
オブジェクトの名前空間です。<service-account-name>
はServiceAccount
オブジェクトの名前です。
-
RBACロールとRoleBindingを作成します。
cert-managerが
ServiceAccount
を使用してトークンを発行できるようにするには、クラスタにいくつかのRBACをデプロイする必要があります。apiVersion: rbac.authorization.k8s.io/v1kind: Rolemetadata:name: <service-account-name>-tokenrequestnamespace: <service-account-namespace>rules:- apiGroups: ['']resources: ['serviceaccounts/token']resourceNames: ['<service-account-name>']verbs: ['create']---apiVersion: rbac.authorization.k8s.io/v1kind: RoleBindingmetadata:name: cert-manager-<service-account-name>-tokenrequestnamespace: <service-account-namespace>subjects:- kind: ServiceAccountname: <cert-manager-service-account-name>namespace: <cert-manager-namespace>roleRef:apiGroup: rbac.authorization.k8s.iokind: Rolename: <service-account-name>-tokenrequest次のものを置き換えます。
<service-account-name>
はServiceAccount
オブジェクトの名前です。<service-account-namespace>
はServiceAccount
オブジェクトの名前空間です。<cert-manager-service-account-name>
は、cert-managerのインストール時に作成されたServiceAccount
オブジェクトの名前です。<cert-manager-namespace>
は、cert-managerがデプロイされている名前空間です。
-
IssuerまたはClusterIssuerを作成します。
この時点で、新しい
ServiceAccount
を使用するようにIssuerを構成する準備が整っているはずです。以下の例の設定を参照してください。apiVersion: cert-manager.io/v1kind: Issuermetadata:name: examplespec:acme:...solvers:- dns01:route53:region: us-east-1role: <iam-role-arn> # This must be set so cert-manager what role to attempt to authenticate withauth:kubernetes:serviceAccountRef:name: <service-account-name> # The name of the service account created
長期的なアクセスキーを持つIAMユーザー
このメカニズムでは、cert-managerはSecretリソースからクレデンシャルを読み込みます。Issuer
リソースを使用する場合、SecretはIssuerと同じ名前空間にある必要があります。ClusterIssuer
リソースを使用する場合、Secretはcert-manager
名前空間、または--cluster-resource-namespace
cert-managerコンポーネントのオプションで指定された値にある必要があります。
このメカニズムの利点は、シンプルで、cert-managerがAWSの外側にデプロイされている場合でも機能することです。
ClusterIssuer
の例の設定を次に示します。
apiVersion: cert-manager.io/v1kind: ClusterIssuermetadata:name: letsencrypt-prodspec:acme:...solvers:- dns01:route53:region: eu-central-1accessKeyIDSecretRef:name: prod-route53-credentials-secretkey: access-key-idsecretAccessKeySecretRef:name: prod-route53-credentials-secretkey: secret-access-key# (optional) you can also assume a role with these credentialsrole: arn:aws:iam::YYYYYYYYYYYY:role/dns-manager
複数アカウントアクセス
例:アカウントYがRoute53 DNSゾーンを管理しています。アカウントX(または他の多くのアカウント)で実行されているcert-managerが、アカウントYでホストされているRoute53ゾーンのレコードを管理できるようにします。
最初に、上記の権限ポリシーを持つロール(ロール名をdns-manager
とします)をアカウントYに作成し、以下の信頼関係をアタッチします。
{"Version": "2012-10-17","Statement": [{"Effect": "Allow","Principal": {"AWS": "arn:aws:iam::XXXXXXXXXXX:role/cert-manager"},"Action": "sts:AssumeRole"}]}
アカウントYでcert-manager
ロールが作成されるまでは、このポリシーを定義できません。構成言語を使用して設定している場合は、プリンシパルを次のように定義することをお勧めします。
"Principal": {"AWS": "XXXXXXXXXXX"}
そして、すべてのロールが作成された後で、次の手順で制限します。
これにより、アカウントXのcert-manager
ロールがアカウントYのdns-manager
ロールを想定して、アカウントYのRoute53 DNSゾーンを管理できます。詳細については、公式ドキュメントを参照してください。
次に、アカウントXにcert-managerロールを作成します。これは、アカウントXで実行されているcert-manager Podのクレデンシャルソースとして使用されます。次の**権限**ポリシーをロールにアタッチします。
{"Version": "2012-10-17","Statement": [{"Effect": "Allow","Resource": "arn:aws:iam::YYYYYYYYYYYY:role/dns-manager","Action": "sts:AssumeRole"}]}
そして、以下の信頼関係(必要に応じてAWS サービス
を追加)
{"Version": "2012-10-17","Statement": [{"Effect": "Allow","Principal": {"Service": "ec2.amazonaws.com"},"Action": "sts:AssumeRole"}]}
リージョン
.spec.acme.solvers.dns01.route53.region
フィールドを省略した場合、cert-managerは、cert-managerコントローラーPod内で設定されている場合、AWS_REGION
とAWS_DEFAULT_REGION
環境変数からリージョンを取得します。
環境変数による認証情報を使用する場合、AWS_REGION
とAWS_DEFAULT_REGION
環境変数は優先度が高く、環境変数が設定されていない場合のみ.spec.acme.solvers.dns01.route53.region
フィールドが使用されます。
EKS Pod Identitiesを使用する場合は、AWS_REGION
環境変数がAmazon EKS Pod Identity Agentによってcert-managerコントローラーPodに追加されるため、.spec.acme.solvers.dns01.route53.region
フィールドは無視されます。
IAM Roles for Service Accounts (IRSA)を使用する場合は、AWS_REGION
環境変数がAmazon EKS Pod Identity Webhookによってcert-managerコントローラーPodに追加されるため、.spec.acme.solvers.dns01.route53.region
フィールドは無視されます。
ℹ️ Route53はグローバルサービスであり、リージョンエンドポイントはありませんが、リージョンはRoute53に接続するときの正しいAWS認証情報のスコープとパーティションを計算するためのヒントとして使用されます。
📖 詳細については、Amazon Route 53 エンドポイントとクォータおよびグローバルサービスをお読みください。
ℹ️ STSはリージョンサービスであり、cert-managerは
region
フィールドまたは環境変数から計算されたリージョンSTSエンドポイントURLを使用します。STSはIRSA認証情報、専用のServiceAccount認証情報、およびクロスアカウントアクセスに使用されます。📖 どのリージョンがSTSをサポートしているかについては、AWSリージョンでのAWS STSの管理をお読みください。
📖 環境変数を使用してリージョンSTSエンドポイントの使用を構成する方法については、AWS STSリージョンエンドポイントをお読みください。