A Look at OpenTofu 👁️ (with a GenAI Twist 🤖)
In this blog I wanted to take a look at OpenTofu, an open-source infrastructure as code tool, in response to some recent drama with HashiCorp and Terraform. For those who do not know, Terraform was open-sourced in 2014 and it has built up quite the community ever since. On August 10th, 2023, HashiCorp decided to change the licensing to a non-open source license, causing an uproar in the community.
This decision seems to have shaken the confidence in the Terraform community, and as a result, OpenTofu was created. OpenTofu has a manifesto detailing their motives and goals that I recommend everyone read.
The long story short of all this is the Linux Foundation created a fork of Terraform and plan to maintain it going forward. On April 3rd, 2024, OpenTofu received a Cease and Desist letter from HashiCorp, claiming copyright infringement. OpenTofu responded and the OpenTofu team ‘vehemently disagrees with any suggestion that it misappropriated, mis-sourced, or otherwise misused HashiCorp’s BSL code’. On top of all this, IBM is purchasing HashiCorp for $6.4B. While this is all very interesting, the point of this article is not to cover the legality and the drama behind all of this.
What I wanted to cover was OpenTofu from a technical standpoint and pit it against Terraform to see how it works. I will also put a ‘GenAI Twist’ on this blog and generate the OpenTofu code using GPT Vision.
Let’s dive in!
NOTE: In this blog, I will be deploying an Azure VM via OpenTofu. I will be creating a VM that leverages a username and password for authentication to demonstrate OpenTofu’s state encryption feature. In an actual environment, it is not advisable to use username and password authentication for a VM. Instead, SSH keys are generally a more secure option. Additionally, credentials should not be checked into source control.
OpenTofu Setup ⚙️
If you have set up Terraform before, you will be right at home with OpenTofu. For those who haven’t set up tools like Terraform before, allow me to step you through how to set it up
The easiest way to get the OpenTofu binary is to navigate to the OpenTofu releases page and download the latest stable version.
Note the highlighted assets section above. You will need to download the binary for your distribution. In my case, I am running windows so I will download the tofu_1.7.1_windows_amd64.zip file. Once you have downloaded the zip file, you will notice a few items inside. The file that is important in this case is the tofu.exe file:
Move that tofu.exe to a location you can remember and copy the file path to the exe and create a new PATH environment variable.
Open up a PowerShell terminal and type tofu.
You will notice right away, it looks almost identical to Terraform.
Leveraging GPT Vision to Generate the Code 🤖
Let’s ask GPT Vision to generate OpenTofu code for the below architecture:
Please keep in mind that we need to ask for Terraform code generation because GPT isn’t familiar with OpenTofu yet, as it’s a relatively new tool. However, this isn’t a big issue currently, as the feature sets of the two tools haven’t differed much. Below, you’ll find a snippet of the code we used to prompt GPT to generate the code for us based on the diagram we created:
response = client.chat.completions.create(
model=deployment_name,
messages=[
{ "role": "system", "content": "You are a helpful assistant that analyzes azure architectures" },
{ "role": "user", "content": [
{
"type": "text",
"text": "Describe this architecture and generate terraform code to deploy it:"
},
{
"type": "image_url",
"image_url": {
"url": data_url
}
}
] }
],
extra_body={
"dataSources": [
{
"type": "AzureComputerVision",
"parameters": {
"endpoint": os.environ.get("COMPUTER_VISION_ENDPOINT"),
"key": os.environ.get("COMPUTER_VISION_KEY")
}
}],
"enhancements": {
"ocr": {
"enabled": True
},
"grounding": {
"enabled": True
}
}
},
max_tokens=2000
)
print(response)
The code for this can be found here if you want to try using GPT vision to generate the code yourself. Having a look at the output and parsing out just the code, we get the following:
provider "azurerm" {
features {}
}
resource "azurerm_resource_group" "example" {
name = "example-resources"
location = "East US"
}
resource "azurerm_virtual_network" "example" {
name = "example-network"
address_space = ["10.0.0.0/16"]
location = azurerm_resource_group.example.location
resource_group_name = azurerm_resource_group.example.name
}
resource "azurerm_subnet" "example" {
name = "example-subnet"
resource_group_name = azurerm_resource_group.example.name
virtual_network_name = azurerm_virtual_network.example.name
address_prefixes = ["10.0.2.0/24"]
}
resource "azurerm_network_interface" "example" {
name = "example-nic"
location = azurerm_resource_group.example.location
resource_group_name = azurerm_resource_group.example.name
ip_configuration {
name = "internal"
subnet_id = azurerm_subnet.example.id
private_ip_address_allocation = "Dynamic"
}
}
resource "azurerm_linux_virtual_machine" "example" {
name = "example-vm"
resource_group_name = azurerm_resource_group.example.name
location = azurerm_resource_group.example.location
size = "Standard_F2"
admin_username = "adminuser"
admin_password = "P@ssword1234"
disable_password_authentication = false
network_interface_ids = [
azurerm_network_interface.example.id,
]
os_disk {
caching = "ReadWrite"
storage_account_type = "Standard_LRS"
}
source_image_reference {
publisher = "Canonical"
offer = "UbuntuServer"
sku = "18.04-LTS"
version = "latest"
}
}
Looks pretty good. Let’s run this code in the next section.
Running OpenTofu 🏃♂️
Let’s bring that code into a terraform file so we can execute it. The steps to do this are exactly the same as Terraform. Open up a PowerShell terminal and run tofu init:
And then, tofu plan:
Notice the plan file looks the same to what Terraform does. Let’s run a tofu apply and deploy those resources to Azure.
Awesome! Our resources are deployed. With OpenTofu being a fork of Terraform, we can also run Terraform commands on the code for the time being. For example, terraform init, plan, and apply all work the same.
terraform init:
terraform plan:
And a terraform apply creates the resources exactly the same. With this all being said, while Terraform and OpenTofu are very similar now, I expect them to diverge over time, and as we will see in the next section, already have to an extent. We are already seeing this with OpenTofu releasing features like state encryption which encrypts the state files at rest.
To demonstrate state encryption, you will notice I have deployed a VM with a username and password. This password is sensitive and since OpenTofu leverages an external state file (similar to terraform) to manage the infrastructure, this password is stored in plain text by default:
Let’s have a look at how we can encrypt that state file.
State Encryption 🔒
Following the OpenTofu example we can see we have to add a few lines of code to our main.tf file that will enable us to encrypt the state file at rest.
terraform {
encryption {
key_provider "pbkdf2" "my_passphrase" {
passphrase = "RnndN6kcHf7fgQca"
}
method "aes_gcm" "my_method" {
keys = key_provider.pbkdf2.my_passphrase
}
state {
method = method.aes_gcm.my_method
fallback {}
}
}
}
Rerunning our Tofu Apply, we can now see the state file is now encrypted and we can no longer see the VM password.
OpenTofu also provides a mechanism to decrypt the state file.
To demonstrate how OpenTofu and Terraform have started to diverge, trying to run this same code in Terraform gives us an error:
This is to be expected since Terraform does not have the same functionality around encrypting state files at rest.
Conclusion
In conclusion, OpenTofu emerges as a promising technology for deploying infrastructure through code. With its innovative features like state encryption, OpenTofu is already differentiating itself in the market. While it shares similarities with Terraform, its unique capabilities and potential for future development make it an exciting prospect for DevOps teams and infrastructure engineers. As the landscape of infrastructure as code continues to evolve, OpenTofu’s trajectory warrants close attention, offering the potential to streamline and enhance the process of managing infrastructure.