You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

升级CDKTF至0.16.3后OIDC Provider URL解析异常问题

问题描述

将cdktf从0.12.3版本升级至0.16.3版本后,AWS OIDC URL在生成IAM策略时出现异常:原本通过replace方法去除https://前缀的逻辑失效,生成的策略中出现资源引用字符串而非实际URL。

相关代码

const oidcProvider = new aws.iam.IamOpenidConnectProvider(
  this,
  "oidc_provider",
  {
    clientIdList: ["sts.amazonaws.com"],
    thumbprintList: [
      dataTlsCertificateCertificate.certificates.get(0).sha1Fingerprint,
    ],
    url,
    dependsOn: [dataTlsCertificateCertificate],
  }
);

const dataAwsIamPolicyDocumentElbAssumeRolePolicy =
  new aws.iam.DataAwsIamPolicyDocument(this, "elb_assume_role_policy", {
    statement: [
      {
        actions: ["sts:AssumeRoleWithWebIdentity"],
        condition: [
          {
            test: "StringEquals",
            values: [
              "system:serviceaccount:kube-system:aws-load-balancer-controller",
            ],
            variable: `\${replace("${oidcProvider.url}", "https://", "")}:sub`,
          },
        ],
        effect: "Allow",
        principals: [
          {
            identifiers: [
              `arn:aws:iam::${dataCallerIdentity.id}:oidc-provider/\${replace("${oidcProvider.url}", "https://", "")}`,
            ],
            type: "Federated",
          },
        ],
      },
    ],
    dependsOn: [dataCallerIdentity],
  });

执行diff后的异常输出

goldsky-infra-prod    # aws_iam_role.eks_lb_controller (eks_lb_controller) will be updated in-place
                      ~ resource "aws_iam_role" "eks_lb_controller" {
                          ~ assume_role_policy    = jsonencode(
                              ~ {
                                  ~ Statement = [
                                      ~ {
                                          ~ Condition = {
                                              ~ StringEquals = {
                                                  + "aws_iam_openid_connect_provider.oidc_provider (oidc_provider).url:sub"                    = "system:serviceaccount:kube-system:aws-load-balancer-controller"
                                                  - "oidc.eks.us-west-2.amazonaws.com/id/78FBBFA50C5182DF54CBF222699F1025:sub" = "system:serviceaccount:kube-system:aws-load-balancer-controller" -> null
                                                }
                                            }
                                          ~ Principal = {
                                              ~ Federated = "arn:aws:iam::301417190815:oidc-provider/oidc.eks.us-west-2.amazonaws.com/id/78FBBFA50C5182DF54CBF222699F1025" -> "arn:aws:iam::301417190815:oidc-provider/aws_iam_openid_connect_provider.oidc_provider (oidc_provider).url"
                                            }
                                            # (3 unchanged elements hidden)
                                        },
                                    ]
                                    # (1 unchanged element hidden)
                                }
                            )
                            id                    = "AmazonEKSLoadBalancerControllerRole"
                            name                  = "AmazonEKSLoadBalancerControllerRole"
                            tags                  = {}
                            # (9 unchanged attributes hidden)

尝试过给url添加.toString()方法,无效果。

原因分析

cdktf 0.13+版本对Terraform资源属性的处理逻辑发生了变化:oidcProvider.url不再直接返回字符串值,而是返回一个Terraform引用对象。之前的字符串插值方式会将这个引用对象直接转为其资源标识符字符串,而非实际的URL值。

解决方案

使用cdktf内置的Fn工具类处理URL操作,避免字符串插值导致的引用对象暴露:

修正后的代码

const oidcProvider = new aws.iam.IamOpenidConnectProvider(
  this,
  "oidc_provider",
  {
    clientIdList: ["sts.amazonaws.com"],
    thumbprintList: [
      dataTlsCertificateCertificate.certificates.get(0).sha1Fingerprint,
    ],
    url,
    dependsOn: [dataTlsCertificateCertificate],
  }
);

// 用cdktf内置Fn处理URL前缀移除
const strippedOidcUrl = Fn.replace(oidcProvider.url, "https://", "");

const dataAwsIamPolicyDocumentElbAssumeRolePolicy =
  new aws.iam.DataAwsIamPolicyDocument(this, "elb_assume_role_policy", {
    statement: [
      {
        actions: ["sts:AssumeRoleWithWebIdentity"],
        condition: [
          {
            test: "StringEquals",
            values: [
              "system:serviceaccount:kube-system:aws-load-balancer-controller",
            ],
            variable: Fn.concat(strippedOidcUrl, ":sub"),
          },
        ],
        effect: "Allow",
        principals: [
          {
            identifiers: [
              Fn.concat(`arn:aws:iam::${dataCallerIdentity.id}:oidc-provider/`, strippedOidcUrl),
            ],
            type: "Federated",
          },
        ],
      },
    ],
    dependsOn: [dataCallerIdentity],
  });

关键改动说明

  1. 用Fn.replace替代字符串插值中的replace函数,确保操作的是Terraform属性的实际值而非引用对象。
  2. 用Fn.concat完成字符串拼接,避免直接在模板字符串中嵌入资源引用。
  3. 提前将处理后的URL存入变量,提升代码复用性和可读性。

修改后,Terraform会正确解析OIDC URL的实际值,生成符合预期的IAM策略文档。

内容的提问来源于stack exchange,提问作者Paymahn Moghadasian

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 23:52:54