Terraform
Terraform
May 8, 2024

How to use the Bitbucket Terraform Provider

By
Ryan Fee

There are a couple of core components in any infrastructure as code pipelines: An IaC platform, such as Terraform or OpenTofu, and a version control system (VCS) such as Bitbucket. Terraform, a widely adopted IaC tool, allows users to define and provision infrastructure using a declarative configuration language. Integrating Terraform with Bitbucket adds an extra layer of control and collaboration. When talking about Bitbucket with Terraform, many think about pull request automation, which we will touch on in the second half of this blog, but we’ll also focus on how to use Terraform to manage your Bitbucket configuration as well as the integration Scalr has with Bitbucket

Understanding the Bitbucket Terraform Provider

What is the Bitbucket Terraform Provider?

Terraform uses the concept of providers to interact with endpoint APIs to create resources in the provider. The Bitbucket Terraform provider serves as a bridge between your infrastructure code and Bitbucket Cloud or Bitbucket Datacenter. It allows you to define and manage Bitbucket resources – such as repositories and projects – directly within your Terraform modules and code. This integration ensures that your repository configurations are codified, version-controlled, and can be easily reproduced across different environments.

An important aspect of managing Bitbucket with Terraform is to select the appropriate Terraform provider to use. While many other tools, like Okta and Gitlab, have officially supported providers, Bitbucket is community driven so it’s important to select the provider that is maintained and used the most. When searching in the standard Terraform registry, it was hard to figure out which provider to go with as there aren’t really many insights provided.

Instead, I used library.tf, a registry maintained by Scalr, which gave me the insights I needed to make the decision on which provider to use:

Screenshot of Providers from Library.tf

As seen above, there is only one provider that has been updated in the last year and has frequent commits, when clicking on the provider I can also see the number of contributors, open issues, and more to help me make my decision on using this Bitbucket provider.

Prerequisites

Before getting into the common use cases of using the Bitbucket Terraform provider, ensure that you have the following prerequisites in place:

  1. Terraform Installed: Make sure you have Terraform or OpenTofu installed on your machine. You can download the latest versions from Terraform or OpenTofu websites.
  2. Bitbucket Cloud Account: You'll need a Bitbucket account with the necessary permissions to manage Bitbucket resources. If you don't have a Bitbucket account, sign up for one on the Bitbucket website. Bitbucket server is also an option, but we’ll focus on Bitbucket cloud in this example.
  3. Bitbucket secret(optional): Bitbucket supports authentication through a username/password, OAuth client ID and secret, or token.
  4. Scalr Account: If you want to use Scalr as the remote backend, sign up for a free account here. Feel free to use this as a development environment while you explore Scalr.

Using the Bitbucket Provider: Examples

In the following steps, we’ll provide you with the methods to authenticate to the provider and then walk through some basic examples of using it.

Define Required Providers and Provider Configuration

Start by configuring the Bitbucket Terraform provider in your Terraform code. Open your Terraform configuration file (commonly named main.tf) and add the following block:

terraform {
  required_providers {
    bitbucket = {
      source = "DrFaust92/bitbucket"
      version = "2.40.1"
    }
  }
}

provider "bitbucket" {
  username = "your-username"
  password = "your-password"
}

Replace "your-username” with your Bitbucket username and "your-password” with the password you use for Bitbucket. The latest version of the Bitbucket Terraform provider documentation can be found here.

Manage Repos

Now, let's create a Bitbucket repository using the Bitbucket Terraform resource. This can all be viewed in detail in the Terraform registry here . Add the following code to your configuration:

resource "bitbucket_repository" "example_repo" {
  owner       = "user or team name"
  name        = "repo-name"
  is_private  = true
}

This Terraform code defines a resource "example_repo" that is set to be private.

Manage Groups

In this example we’ll manage the groups in Bitbucket and what permissions they have. In this case, we’ll also use a datasource to pull the workspace ID:

data "bitbucket_workspace" "example" {
  workspace = "example"
}

resource "bitbucket_group" "example_group" {
  workspace  = data.bitbucket_workspace.example.id
  name       = "example group"
  permission = "read"
}

This Terraform code defines a resource "example_group" and sets the groups permissions to read.

Run Terraform Commands

Once you've defined your Bitbucket resources through the Bitbucket Terraform provider, navigate to the directory containing your Terraform configuration file and run the following commands:

terraform init
terraform plan
terraform apply

If you are using OpenTofu, use the tofu commands instead:

tofu init
tofu plan
tofu apply

Terraform will initialize the Bitbucket provider and apply the changes to your Bitbucket account. Upon a successful Terraform run, the state file will be created.

Best Practices and Advanced Usage

Variables and Dynamic Configurations

Utilize Terraform variables to make your configurations more dynamic. Instead of hardcoding values, use variables to create reusable and flexible scripts.

variable "username" {
 description = "The username you authenticate to Bitbucket with"
}

variable "password" {
 description = "The password you authenticate to Bitbucket with"
}

provider "bitbucket" {
 org_name    = var.username
 api_token   = "var.password"
}

Remote State Management

Consider using remote state management to store your Terraform state files securely. Services like Scalr or AWS S3 can be configured as remote backends to store state files. Here is an example of connecting to Scalr:

terraform {
  backend "remote" {
    hostname = "<account-name>.scalr.io"
    organization = "<scalr-environment-name>"

    workspaces {
      name = "<workspace-name>"
    }
  }
}

Data Sources

To improve your Terraform code, we encourage you to review the option of using Bitbucket data sources in the code to be able to pull information from other resources or workspaces into the run.

Provider Summary

This guide covers the basic steps to configure the Bitbucket Terraform provider, create repositories, and groups, and introduce best practices for advanced usage. As you explore further, consider exploring additional Bitbucket resources supported by the Bitbucket provider, such as branches, deploy keys, and projects. The library.tf documentation for the Bitbucket Terraform provider is a valuable resource for in-depth information and examples.

By integrating Bitbucket into your Terraform workflows, you're not just managing infrastructure – you're managing your VCS provider with the efficiency and scalability that infrastructure as code brings.

Scalr’s Integration with Bitbucket

Now we’re going to switch gears a little and talk about how Bitbucket can be used as a vital integration in your overall Terraform pipeline and how it integrates with Scalr.

Bitbucket as a VCS Repo

When talking about Terraform and Bitbucket, the number one best practice is to make sure your Terraform files are stored in a VCS repository, like Bitbucket. By storing the Terraform configuration in a Bitbucket repository, you enable the following for your infrastructure teams:

  • Tracking Changes: A VCS keeps track of changes made to Terraform source code files within a Bitbucket repo. Each change is associated with a commit, which includes details such as who made the Terraform code changes, when it was made, and a description of the modifications.
  • Collaboration: VCS enables multiple developers to work on the same Bitbucket repository simultaneously. Each developer can make changes independently, and the VCS helps merge these changes seamlessly, preventing conflicts and ensuring a coherent Terraform codebase.
  • History and Rollback: VCS maintains a complete history of all changes made to the Terraform code. This allows developers to roll back to previous versions of the Terraform code in case of errors or to investigate when a specific change was introduced.
  • Branching and Merging: VCS allows developers to create branches, which are independent lines of Terraform code development. This feature is valuable for working on new features, bug fixes, or experimental changes without affecting the main Terraform codebase. By opening a merge request, you have the ability to automatically trigger a “Terraform dry run” in tools like Scalr or Terraform Cloud, which will execute a Terraform plan and send the results back into Bitbucket. Based on the results coming back successfully, developers can then merge the code allowing changes from one branch to be incorporated into another.
  • Code Review: VCS facilitates Terraform code reviews by providing a clear view of the changes made in a commit. Reviewers can easily assess the modifications, leave comments, and suggest improvements before changes are merged into the main branch.

Using Bitbucket with a TACO (Terraform Collaboration and Automation Platform)

If you are looking for a TACO, such as Scalr or Terraform Cloud, to help scale your Terraform operations, the integration with Bitbucket is a key feature. By integrating these tools with Bitbucket, you are not only able to pull in the Terraform code but also enable the following features:

  • Terraform Private Module Registry: On top of storing your Terraform code in Bitbucket for the reasons stated above, another best practice is to implement a Terraform Private Module Registry to store your Terraform modules. When doing this, you store your Terraform modules in Bitbucket repos, integrate Scalr or Terraform Cloud with Bitbucket and then pull the Terraform modules in for use by your DevOps teams. By doing this, Bitbucket is still the source of truth for the code, but you can now curate a list of approved modules for your teams to use.
  • GitOps Workflow: A GitOps workflow for Terraform is usually the goal for most DevOps teams. A GitOps workflow can leverage the Bitbucket branching and merging to automatically kick off Terraform dry runs as well as Terraform applies. The flow is typically as follows:
    • A branch, let’s call it dev, is created based on the main branch.
    • Terraform code is updated in the dev branch.
    • A merge request is opened up against the main branch from dev.
    • Based on the merge request being opened, the TACO will automatically execute a Terraform dry run and send the results back to Bitbucket pipelines.
    • Admins can optionally (considered a best practice though) set branch policies to only allow a merge request if all checks come back successfully from the TACO.
    • Once the merge request is approved the Terraform apply will execute in the TACO.
  • Open Policy Agent: Open Policy Agent (OPA) with Terraform enables declarative policy enforcement for the Terraform code, allowing admins to define and enforce fine-grained policies to govern the provisioning workflow. Typically, the OPA policies are stored in Bitbucket and then pulled into Scalr or Terraform Cloud to enforce them in the core workflow.

The TACO products have a full feature set dedicated to Terraform, including the ability to store Terraform state files. See more here.

Note: While this blog references Terraform, everything mentioned in here also applies to OpenTofu. New to OpenTofu? It is a fork of Terraform 1.5.7 as a result of the license change from MPL to BUSL by HashiCorp. OpenTofu is an open-source alternative to Terraform that is governed by the Linux Foundation. All features available in Terraform 1.5.7 or earlier are also available in OpenTofu. Find out the history of OpenTofu here.

Start using the Terraform platform of the future.

A screenshot of the modules page in the Scalr Platform