Search code examples
azureterraformdockerhubterraform-provider-kubernetes

How to properly use the access token to authenticate to Docker Hub using Terraform?


I'm just starting out using Terraform and I'm deploying my infrastructure on Azure AKS and I'm stuck at creating a secret to authenticate with Docker Hub and pull the image from I intend to use for my Deployment from my private repository.

In my first try I did the procedure to create a secret described here https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ using user name, password and email.

  1. create the secret with kubectl create secret docker-registry regcred --docker-server=<your-registry-server> --docker-username=<your-name> --docker-password=<your-pword> --docker-email=<your-email>

  2. then read it decoded, as terraform secrets seem to want non encoded values with kubectl get secret regcred --output="jsonpath={.data.\.dockerconfigjson}" | base64 --decode

  3. then wrote the Terraform kubernetes_secret as

resource "kubernetes_secret" "user-credentials" {
data = {
".dockerconfigjson" = jsonencode({
  "auths":{
    "${var.docker_registry_server}":{
      "username":  var.docker_user,
      "password": var.docker_password,
      "email": var.docker_email,
      "auth": var.docker_auth
      }}})
}
metadata { 
  name = "docker-registry"
  namespace =  "default"
}
type = "kubernetes.io/dockerconfigjson"
  
}

Using the credential (either hardcoded or stored in variables) works and I'm able to authenticate and use the image for the deployment. I then created an Access Token on Docker Hub and tried using it in the secret instead of my user credentials but I'm not finding the correct way to structure the json as I did for the user credentials and the deployment fails after the create timeout.

Can you spot what I'm doing wrong setting the secret to use the access token? Many thanks for your time and help.

#variables

variable "docker_registry_server" {
  default = "https://index.docker.io/v1/"
}
variable "docker_user" {
  default = "vinnytwice"
  
}
variable "docker_email" {
  default = "****"
}
variable "docker_password" {
  default = "****"
}
variable "docker_auth" {
  default = "****"
}

variable "docker_token" {
  default = "****"
}

#Secret using access token

resource "kubernetes_secret" "access-token" {
  metadata {
    name = "docker-registry"
    namespace = "default"
  }
  type = "kubernetes.io/dockerconfigjson"
  data = {
    ".dockerconfigjson" = jsonencode({
      
      //not working
      "auths":{
        "${var.docker_registry_server}":{
          "auth":"${var.docker_user}:${var.docker_token}"
        }
      }
      //not working 
      # "auths":{
      #   "${var.docker_registry_server}":{
      #     "auth":"${var.docker_token}"
      #   }
      # }
      //not working
      # "auths":{
      #   "https://index.docker.io/v1/":{
      #     "auth":"***:***"
      #   }
      # }
    })
  }
}

#Deployment

resource "kubernetes_deployment" "fixit-server" {
  timeouts {
    create = "1m"
  }
  metadata {
    name = "fixit-server"
  }
  spec {
    replicas = 1
    revision_history_limit = 10
    selector {
      match_labels = {
        app = "fixit-server-pod"
      }
    }
    template {
      metadata {
        labels = {
          app = "fixit-server-pod"
        }
      }
      spec {
        image_pull_secrets {
          name = "docker-registry"
        }
        container {
          name  = "fixit-server-container"
          image = "vinnytwice/fixit-server:dev"
          image_pull_policy = "IfNotPresent"
          }
        }
      }
    }
}

Solution

  • Finally! Well as in another post here on SO, access tokens are just passwords and so should they be treated.. in fact, after this reading I noticed that in the procedure is specified that at docker login you can use either a token or your password..

    When prompted, enter your Docker ID, and then the credential you want to use (access token, or the password for your Docker ID).

    so I did the procedure login in with the token and the json auths would in fact be identical, just with the token value for password, and a different value for auth. Modified the secret with those values and it does work.

    resource "kubernetes_secret" "access-token" {
      metadata {
        name = "docker-registry"
        namespace = "default"
      }
      type = "kubernetes.io/dockerconfigjson"
      data = {
        ".dockerconfigjson" = jsonencode({
          "auths":{
        "${var.docker_registry_server}":{
          "username":  var.docker_user,
          "password": var.docker_token,
          "email": var.docker_email,
          "auth": var.docker_auth_token
          }}
        })
      }
    }
    
    

    Hope it can be useful to others. Cheers.