For some of my projects, I run a Dynamic DNS server service attached to one of the less-standard DNS Names I own, and use that to connect to the web pages I’m spinning up. In a recent demo, I noticed that the terraform “changes” log where it shows what things are being updated showed the credentials I was using, because I was using “simple” authentication, like this:
data "http" "ddns_web" {
url = "https://my.ddns.example.org/update?secret=${var.ddns_secret}&domain=web&addr=192.0.2.1"
}
variable "ddns_secret" {
default = "bob"
}
For context, that would ask the DDNS service running at ddns.example.org to create a DNS record for web.ddns.example.org with an A record of 192.0.2.1.
While this is fine for my personal projects, any time this goes past, anyone who spots that update line would see the credentials I use for this service. Not great.
I had a quick look at the other options I had for authentication, and noticed that the DDNS server I’m running also supports the DynDNS update mechanism. In that case, we need to construct things a little differently!
data "http" "ddns_web" {
url = "https://my.ddns.example.org/nic/update?hostname=web&myip=192.0.2.1"
request_headers = {
Authorization = "Basic ${base64encode("user:${var.ddns_secret}")}"
}
}
variable "ddns_secret" {
type = string
sensitive = true
default = "bob"
}
So now, we change the URL to include the /nic/ path fragment, we use different names for the variables and we’re using Basic Authentication which is a request header. It’s a little frustrating that the http data source doesn’t also have a query type or a path constructor we could have used, but…
In this context the request header of “Authorization” is a string starting “Basic” but then with a Base64 encoded value of the username (which for this DDNS service, can be anything, so I’ve set it as the word “user”), then a colon and then the password. By setting the ddns_secret
variable as being “sensitive”, if I use terraform console, and ask it for the value of data.http.ddns_web
I get
> data.http.ddns_web
{
"body" = <<-EOT
good 192.0.2.1
EOT
"id" = "https://my.ddns.example.org/nic/update?hostname=web&myip=192.0.2.1"
"request_headers" = tomap({
"Authorization" = (sensitive)
})
"response_body" = <<-EOT
good 192.0.2.1
EOT
"response_headers" = tomap({
"Content-Length" = "18"
"Content-Type" = "text/plain; charset=utf-8"
"Date" = "Thu, 01 Jan 1970 00:00:00 UTC"
"Server" = "nginx"
"Strict-Transport-Security" = "max-age=31536000; includeSubDomains"
"X-Content-Type-Options" = "nosniff"
"X-Xss-Protection" = "1; mode=block"
})
"url" = "https://my.ddns.example.org/nic/update?hostname=web&myip=192.0.2.1"
}
>
Note that if your DDNS service has a particular username requirement, this can also be entered, in the same way, by changing the string “user” to something like ${var.ddns_user}
.
Featured image is “Sensitive Species” by “Rennett Stowe” on Flickr and is released under a CC-BY license.