新着: プロジェクトの最新情報についてはTwitterMastodonでご確認ください。

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つのオプションがあります。

  1. (ベストプラクティス)一時的なセキュリティ認証情報を持つIAMロールを使用します。
  2. 長期的なアクセスキーを持つIAMユーザーを使用します。

一時的なセキュリティ認証情報を持つIAMロールを使用することがベストプラクティスとされている理由は次のとおりです。

  1. 長期的なアクセスキー(例:シークレット内)を保存する必要がありません。
  2. アクセスキーのローテーションを管理する必要がありません。

cert-managerがAWS外部にデプロイされているがDNSゾーンがRoute53上にある場合、長期的なアクセスキーを持つIAMユーザーを使用することは妥当な選択肢です。

cert-managerは、アクセスキーを取得するための複数の方法をサポートしており、それらは「アンビエント」または「ノンアンビエント」のいずれかに分類できます。

アンビエント認証情報

アンビエント認証情報は、次のいずれかのメカニズムによってcert-managerコントローラーPodで使用可能になる認証情報です。

アンビエント認証情報の利点は、設定が容易で、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/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
...
solvers:
- dns01:
route53: {}

ℹ️ 使用するアンビエントメカニズムに関係なく、route53セクションは空のままです。cert-managerは、cert-manager Podに追加される環境変数を調べることで、認証情報、ロール、リージョンを見つけることができます。

EKS Pod Identity

EKSでcert-managerをデプロイする場合、EKS Pod Identityはアンビエント認証情報を使用する最も簡単な方法です。これは4ステップのプロセスです。

  1. クラスタにEKS Pod Identityエージェントを設定します。

  2. cert-manager KubernetesサービスアカウントにIAMロールを割り当てます。.

  3. EKS Pod Identityエージェントが必要な環境変数をPodに注入できるように、cert-manager Deploymentを再起動します。

  4. ClusterIssuerリソースを作成します。

    apiVersion: cert-manager.io/v1
    kind: ClusterIssuer
    metadata:
    name: letsencrypt-prod
    spec:
    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にマウントされたサービスアカウントボリュームが自動的に設定されます。

  1. クラスタのIAM OIDCプロバイダーを作成します。

    cert-managerでIRSAを使用するには、最初にクラスタでその機能を有効にする必要があります。公式ドキュメントに従ってください。

  2. 信頼関係を作成します。

    この構成では、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ロールにアタッチされます。権限ポリシーは上記と同じです。

  3. cert-manager ServiceAccountにアノテーションを付与します。

    apiVersion: v1
    kind: ServiceAccount
    metadata:
    annotations:
    eks.amazonaws.com/role-arn: arn:aws:iam::XXXXXXXXXXX:role/cert-manager

    cert-manager Helmチャートは、cert-managerのServiceAccountにアノテーションを注入するための変数を次のように提供します。

    serviceAccount:
    annotations:
    eks.amazonaws.com/role-arn: arn:aws:iam::XXXXXXXXXXX:role/cert-manager

    ℹ️ 複数アカウントの例に従っている場合、アカウントYのロールを使用してClusterIssuerを変更します。

  4. (オプション) ファイルシステムの権限を更新します。

    📢 このドキュメントの改善にご協力ください

    このオプション手順が必要となる理由は、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 Needs runAsUser: 1001 を読んで、この手順がまだ必要かどうか、または廃止されたかどうかをお知らせください。

    異なるユーザーとグループを使用してcert-manager Deploymentを変更し、ServiceAccountトークンを読み取れるようにする必要がある場合もあります。

    spec:
    template:
    spec:
    securityContext:
    fsGroup: 1001
    runAsUser: 1001

    cert-manager Helmチャートは、cert-managerのDeploymentを変更するための変数を次のように提供します。

    securityContext:
    fsGroup: 1001
    runAsUser: 1001
  5. cert-manager Deploymentを再起動します。

    webhookが必要なvolumevolumemount、および環境変数をPodに注入できるように、cert-manager Deploymentを再起動します。

  6. ClusterIssuerリソースを作成します。

    apiVersion: cert-manager.io/v1
    kind: ClusterIssuer
    metadata:
    name: letsencrypt-prod
    spec:
    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チュートリアルを参照してください。

この構成では、独自のServiceAccountsIssuerまたはClusterIssuerで参照でき、cert-managerはKubernetes APIからServiceAccountトークンを取得し、AWSの一時的なクレデンシャルと交換するためにSTSに送信します。

このメカニズムの利点は次のとおりです。

  1. 各Issuerは異なるServiceAccountを参照できます。つまり、権限を制限して、各ServiceAccountが、必要なゾーンのみを更新できる権限を持つIAMロールにマップされるようにできます(Pod IdentityまたはIRSAとは異なります)。
  2. このメカニズムは、cert-managerがAWSの外側にデプロイされている場合でも機能します。

設定方法は次のとおりです。

  1. ServiceAccountを作成します。

    ServiceAccountを参照するには、最初に存在する必要があります。通常のIRSAとは異なり、eks.amazonaws.com/role-arnアノテーションは必要ありません。

    apiVersion: v1
    kind: ServiceAccount
    metadata:
    name: <service-account-name>
  2. 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オブジェクトの名前です。
  3. RBACロールとRoleBindingを作成します。

    cert-managerがServiceAccountを使用してトークンを発行できるようにするには、クラスタにいくつかのRBACをデプロイする必要があります。

    apiVersion: rbac.authorization.k8s.io/v1
    kind: Role
    metadata:
    name: <service-account-name>-tokenrequest
    namespace: <service-account-namespace>
    rules:
    - apiGroups: ['']
    resources: ['serviceaccounts/token']
    resourceNames: ['<service-account-name>']
    verbs: ['create']
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: RoleBinding
    metadata:
    name: cert-manager-<service-account-name>-tokenrequest
    namespace: <service-account-namespace>
    subjects:
    - kind: ServiceAccount
    name: <cert-manager-service-account-name>
    namespace: <cert-manager-namespace>
    roleRef:
    apiGroup: rbac.authorization.k8s.io
    kind: Role
    name: <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がデプロイされている名前空間です。
  4. IssuerまたはClusterIssuerを作成します。

    この時点で、新しいServiceAccountを使用するようにIssuerを構成する準備が整っているはずです。以下の例の設定を参照してください。

    apiVersion: cert-manager.io/v1
    kind: Issuer
    metadata:
    name: example
    spec:
    acme:
    ...
    solvers:
    - dns01:
    route53:
    region: us-east-1
    role: <iam-role-arn> # This must be set so cert-manager what role to attempt to authenticate with
    auth:
    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/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
...
solvers:
- dns01:
route53:
region: eu-central-1
accessKeyIDSecretRef:
name: prod-route53-credentials-secret
key: access-key-id
secretAccessKeySecretRef:
name: prod-route53-credentials-secret
key: secret-access-key
# (optional) you can also assume a role with these credentials
role: 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_REGIONAWS_DEFAULT_REGION環境変数からリージョンを取得します。

環境変数による認証情報を使用する場合、AWS_REGIONAWS_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リージョンエンドポイントをお読みください。