Leveraging built-in Terraform Functions in CDKTF

Hi everyone,

I’ve recently begun using cdktf and am loving it so far, however I’m finding a potential gap in functionality or haven’t found relevant documentation.

I’m leveraging the terraform-aws-modules/eks/aws module to create an EKS cluster with cdktf and am trying to access the base64 encoded certificate authority data to apply the AWS Authentication configmap thats leveraged as part of the module.

To do this I’m initializing the KubernetesProvider as such:

    KubernetesProvider(self, 'k8s', host=eks_cluster.cluster_endpoint_output,
                       cluster_ca_certificate=
                       eks_cluster.cluster_certificate_authority_data_output,
                       token=eks_cluster_auth.token, load_config_file=False),

However the output of eks_cluster.cluster_certificate_authority_data_output is ${module.eks_clusterName_SomeId.cluster_certificate_authority_data}

Since this data is natively base64 encoded I would simply call base64decode() in Terraform to decode it, but I’m not seeing that functionality in the CDK.

I’ve worked around it by stripping the ${} from the output string and using a custom formatted string as such:

        cluster_ca_lookup_string = ''.join(c for c in eks_cluster.cluster_certificate_authority_data_output
                                       if c not in '{}$')
    KubernetesProvider(self, 'k8s', host=eks_cluster.cluster_endpoint_output,
                       cluster_ca_certificate=
                       f'${{base64decode({cluster_ca_lookup_string})}}',
                       token=eks_cluster_auth.token, load_config_file=False),

This seems to work but is a bit messy. Is there a recommended way to perform these types of functions natively in the CDK or is it something that is still not developed/supported yet?

Cheers!

Using terraform functions in cdktf isn’t natively supported at this point in time. Adding support isn’t immediately on the roadmap, but I hope it can be added in the future.

1 Like

Ah that’s unfortunate. There’s a definite need I think for this to be added as certain modules and resources need things like base64decode/encode so I may open a Feature request.

Thanks for the info!

any updates on this? I’m trying to use a GCP service account json, but noticing that I’ll need rune-time access to base64decoding an object to be able to do what I planned to do.

There has been a little bit of early design, but I’m not aware of any concrete timeline.

Found out that we can use add_override for this. Not pretty, but it works:

    datadog_project.add_override('private_key_id', generate_decode_func(f'datadog-sa-key-{project_id}', 'private_key_id'))


def generate_decode_func(resource_id, attribute_name):
    return '${jsondecode(base64decode(google_service_account_key.' + resource_id + '.private_key)).' + attribute_name + '}'

Hello,
I ran into the same struggle while working with the aws-eks module.
Sadly @bikescholl s workaround didn’t work for me. But i managed to get it to work by comparing what .hcl expects and how to get into the cdk.tf.json.
To create a Kuberentes provider in hcl you define something like that.

data "aws_eks_cluster" "default" {
  name = local.cluster_name
}

data "aws_eks_cluster_auth" "default" {
  name = local.cluster_name
}

provider "kubernetes" {
  host                   = data.aws_eks_cluster.default.endpoint
  cluster_ca_certificate = base64decode(data.aws_eks_cluster.default.certificate_authority[0].data)
  token                  = data.aws_eks_cluster_auth.default.token
}

as by @bikescholl described that’s not possible since cluster_certificate_authority_data_output has the ${} syntax and you cannot use TF functions.
My workaround is to create the “string” by myself.

 cluster = Eks(
            self,
            "Eks",
            cluster_name=f"{env.prefix}-cluster",
           ... 
)
        cluster_auth_data = eks.DataAwsEksClusterAuth(
            self,
            "DataAwsEksClusterAuth",
            name=cluster.cluster_name,
        )


        k8s_provider = KubernetesProvider(
            self,
            "k8s",
            host=cluster.cluster_endpoint_output,
            # INFO Terraform methods not available
            # https://discuss.hashicorp.com/t/leveraging-built-in-terraform-functions-in-cdktf/17118/3
            cluster_ca_certificate=f"${{base64decode(module.{cluster.node.id}.cluster_certificate_authority_data)}}",
            token=cluster_auth_data.token,
        )

this generates the following cdk.tf.json

    "kubernetes": [
      {
        "cluster_ca_certificate": "${base64decode(module.Eks.cluster_certificate_authority_data)}",
        "host": "${module.Eks.cluster_endpoint}",
        "token": "${data.aws_eks_cluster_auth.DataAwsEksClusterAuth.token}"
      }
    ]

which is exactly what hcl does.

You should be able to use Fn.base64decode like we do it in the eks-kubernetes example.

1 Like