Skip to content

Terraform External Provider and Datasource

Step-01: Introduction

Step-02: Pre-requisite Installs

  • ssh-keygen
  • jq
    # ssh-keygen
    which ssh-keygen
    
    # jq
    which jq
    brew install jq
    

Step-03: ssh_key_generator.sh

  • File Location: terraform-manifests/shell-scripts
    function error_exit() {
      echo "$1" 1>&2
      exit 1
    }
    
    function check_deps() {
      test -f $(which ssh-keygen) || error_exit "ssh-keygen command not found in path, please install it"
      test -f $(which jq) || error_exit "jq command not found in path, please install it"
    }
    
    function parse_input() {
      # jq reads from stdin so we don't have to set up any inputs, but let's validate the outputs
      eval "$(jq -r '@sh "export KEY_NAME=\(.key_name) KEY_ENVIRONMENT=\(.key_environment)"')"
      if [[ -z "${KEY_NAME}" ]]; then export KEY_NAME=none; fi
      if [[ -z "${KEY_ENVIRONMENT}" ]]; then export KEY_ENVIRONMENT=none; fi
    }
    
    function create_ssh_key() {
      script_dir=$(dirname $0)
      export ssh_key_file="${script_dir}/${KEY_NAME}-${KEY_ENVIRONMENT}"
      # echo "DEBUG: ssh_key_file = ${ssh_key_file}" 1>&2
      if [[ ! -f "${ssh_key_file}" ]]; then
        #ssh-keygen -m PEM -t rsa -b 4096 -N '' -f $ssh_key_file
        ssh-keygen -q -m PEM -t rsa -b 4096 -N '' -f $ssh_key_file
      fi
    }
    
    function produce_output() {
      public_key_contents=$(cat ${ssh_key_file}.pub)
      # echo "DEBUG: public_key_contents ${public_key_contents}" 1>&2
      private_key_contents=$(cat ${ssh_key_file} | awk '$1=$1' ORS='  \n')
      # echo "DEBUG: private_key_contents ${private_key_contents}" 1>&2
      # echo "DEBUG: private_key_file ${ssh_key_file}" 1>&2
      jq -n \
        --arg public_key "$public_key_contents" \
        --arg private_key "$private_key_contents" \
        --arg private_key_file "$ssh_key_file" \
        '{"public_key":$public_key,"private_key":$private_key,"private_key_file":$private_key_file}'
    }
    
    # main()
    check_deps
    # echo "DEBUG: received: $INPUT" 1>&2
    parse_input
    create_ssh_key
    produce_output
    

Step-04: Test Shell Script

# Test Shell Script
echo '{"key_name": "terraformdemo", "key_environment": "dev"}' | ./ssh_key_generator.sh

# Verify the files created
File Location: terraform-manifests/shell-scripts/
1. terraformdemodev: Private key file created
2. terraformdemodev.pub: Public Key file created

Step-05: c1-versions.tf

# Terraform Block
terraform {
  required_version = ">= 1.0.0"
  required_providers {
    azurerm = {
      source = "hashicorp/azurerm"
      version = ">= 2.0" 
    }
    external = {
      source = "hashicorp/external"
      version = ">= 2.0"
    }       
  }
}

# Provider Block
provider "azurerm" {
 features {}          
}

Step-06: c2-external-datasource.tf

# External Datasource
data "external" "ssh_key_generator" {
  program = ["bash", "${path.module}/shell-scripts/ssh_key_generator.sh"]

  query = {
    key_name = "terraformdemo"
    key_environment = "dev"
  }
}

Step-07: c2-external-datasource.tf - Outputs

  • Terraform Outputs for the External Datasource.
    # Outputs
    output "public_key" {
      description = "public_key"
      value = data.external.ssh_key_generator.result.public_key
    }
    
    output "private_key" {
      description = "private_key"
      value = data.external.ssh_key_generator.result.private_key
    }
    
    output "private_key_file" {
      description = "private_key_file"
      value = data.external.ssh_key_generator.result.private_key_file 
    }
    

Step-08: Execute Terraform Commands

# Terraform Initialize
terraform init

# Terraform Validate
terraform validate

# Terraform Plan
terraform plan

# Observation
1. Its just datasource, so either we execute terraform plan or apply, shell script "ssh_key_generator.sh" will be triggered  and Public and Private Keys are generated

# Terraform Apply (Optional)
terraform apply 

Step-09: Clean-Up

# Destroy Resources (Optional if terraform apply not executed)
terraform destroy -auto-approve 

# Delete Files
rm -rf .terraform* 
rm -rf terraform.tfstate*
🎉 New Course
Ultimate DevOps Real-World Project Implementation on AWS
$15.99 $84.99 81% OFF
MARCH2026
Enroll Now on Udemy →
🎉 Offer