upbound / provider-terraform

A @crossplane provider for Terraform
Apache License 2.0
124 stars 55 forks source link

Import regular k8s secrets #251

Open prog76 opened 3 months ago

prog76 commented 3 months ago

What problem are you facing?

When one Workspace object writes connection data, it does that as a regular k8s secret. I think it could be a good improvement to make it possible to use this secret as a varFile for the second Workspace objects.

How could Official Terraform Provider help solve your problem?

probably when Key is omitted, provider could load all keys from the secret as variables:

    varFiles:
    - source: SecretKey
      secretKeyRef:
        namespace: default
        name: terraform
bobh66 commented 6 days ago

@prog76 can you provide some more details about the scenario? Maybe a sample Composition or Workspace that shows the workflow you have in mind? Thanks

prog76 commented 6 days ago

Here it is. I'm configuring a user in the first Workspace and I need to use it's credentials in the second one

apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
  name: xreplications.minio.company.io
spec:
  compositeTypeRef:
    apiVersion: minio.company.io/v1alpha1
    kind: Xreplication
  mode: Pipeline
  writeConnectionSecretsToNamespace: crossplane-system
  pipeline:
  - step: render-templates
    functionRef:
      name: function-go-templating
    input:
      apiVersion: gotemplating.fn.crossplane.io/v1beta1
      kind: GoTemplate
      source: Inline
      inline:
        template: |
          ---
          {{ $resource := .observed.composite.resource }}
          {{ $source := $resource.spec.source }}
          {{ $target := $resource.spec.target }}
          {{ $srcRef := printf "%s-replica-src-%s" $source.provider $source.bucket }}
          {{ $tgtRef := printf "%s-replica-tgt-%s" $target.provider $target.bucket }}

          apiVersion: tf.upbound.io/v1beta1
          kind: Workspace
          metadata:
            name: {{ $tgtRef }}
            annotations:
              gotemplating.fn.crossplane.io/composition-resource-name: {{ $tgtRef }}
          spec:
            providerConfigRef:
              name: {{ $target.provider }}
            forProvider:
              source: Inline
              module: |
                resource "minio_iam_policy" "policy" {
                  name = "replica-{{ $target.bucket }}"
                  policy= <<EOF
                {
                 //some policy
                }
                EOF
                }

                resource "minio_iam_user" "user" {
                  name = "replica-user-{{ $target.bucket }}"
                } 

                resource "minio_iam_user_policy_attachment" "attachment" ...

                resource "minio_iam_service_account" "replication" {
                  target_user = minio_iam_user.user.id
                  depends_on = [
                    minio_iam_user_policy_attachment.attachment
                  ]
                }

                output "access_key" {
                  value = minio_iam_service_account.replication.access_key
                  sensitive = true
                }

                output "secret_key" {
                  value = minio_iam_service_account.replication.secret_key
                  sensitive = true
                }

                output "endpoint" {
                  value = var.minio_server
                }

            writeConnectionSecretToRef:
              name: {{ $tgtRef }}
              namespace: crossplane-system
          ---
          apiVersion: tf.upbound.io/v1beta1
          kind: Workspace
          metadata:
            name: {{ $srcRef }}
            annotations:
              gotemplating.fn.crossplane.io/composition-resource-name: {{ $srcRef }}
          spec:
            providerConfigRef:
              name: {{ $source.provider }}
          {{ if $.observed.resources }}

here I need minio_iam_service_account.replication.access_key and minio_iam_service_account.replication.secret_key. they exists in connectionDetails secret

          {{ $secret := (index $.observed.resources $tgtRef).connectionDetails }}
          {{ if and $secret (index $secret "access_key") }}
            forProvider:
              source: Inline
              module: |
                resource "minio_s3_bucket_replication" "replication" {
                  bucket     = "{{ $source.bucket }}"

                  rule {
                    delete_replication = true
                    delete_marker_replication = true
                    existing_object_replication = true
                    metadata_sync = true

                    target {
                      bucket = "{{ $target.bucket }}"
                      host = "{{ $secret.endpoint | b64dec }}"
                      secure = false

unfortunately this way I have to expose values. and that's what I want to avoid.

                      access_key = "{{ $secret.access_key | b64dec }}"
                      secret_key ="{{ $secret.secret_key | b64dec }}"
                    }
                  }
                }
          {{ end }}
          {{ end }}
  - step: ready
    functionRef:
      name: function-auto-ready