Continuous improvement is better than delayed perfection. Mark Twain
In this short article, you will learn how you can leverage the Terraform provider alias to setup multiple provider configurations with multiple credentials. The main reason to use an alias is usually to support multiple regions or projects for a cloud platform. Here we will focus on using multiple sets of credentials, why use this approach and how it could benefit your Terraform configuration and the security of your infrastructure.
Typically, you would not use a single set of credentials to manage your entire infrastructure. You would also most likely not rely on a single Terraform configuration to manage your entire infrastructure, because it would take time to refresh and update the state when managing a lot of resources. The best practice is to split your infrastructure into multiple Terraform configurations (called root modules), which usually use provider configurations with different credentials.
However, a root module can benefit from using multiple credentials for the same Terraform provider configuration.
The main reason to use a Terraform configuration with multiple credentials is to apply the principle of least privilege. This allows your configuration to rely on different credentials with specific permissions, and limit the risk of compromising your infrastructure managed by the same Terraform configuration.
A Terraform provider usually requires some credentials to perform some actions on protected resources. By using aliases, we can use one provider to create some credentials which are then used by a second provider within the same configuration.
Let’s have a look at a simple example. The code for this example is fully available in GitLab. In this scenario, we want to create using Terraform a new Google Cloud project (p1) that will contain some BigQuery resources. Prior to this, we have manually created a Google Cloud Project (ops) which hosts the service account that will be used by Terraform and granted the necessary permissions to create projects in a specific location.
In this ops project, we don’t have the BigQuery API service enabled because the ops project is not related to any BigQuery resources.
In the Terraform code without alias, we create the resources for the new project, the BigQuery API and a bigQuery dataset. Running the Terraform code will fail because we configure the provider with the service account from the ops project. Even with the specific access rights, the project hosting the service account used by the provider to create the BigQuery resources doesn't have access to the BigQuery API.
│ Error: Error creating Dataset: googleapi: Error 403: BigQuery API has not been used in project 934740185609 before or it is disabled. Enable it by visiting https://console.developers.google.com/apis/api/bigquery.googleapis.com/overview?project=934740185609 then retry. If you enabled this API recently, wait a few minutes for the action to propagate to our systems and retry.
What can we do?
Enabling the Google BigQuery API in the ops project will fix the problem, but what if you have many resources to create, requiring many APIs ? Suddenly, you will enable many APIs in a single project so that your Terraform code can manage all different types of resources in many projects.
Using an alias
Instead, a better approach is to use an alias to clearly define the scope of each service account. In this case, we first have to enable the IAM API in the ops project manually to be able to create IAM resources.
Then, we add a definition for a new service account in the target project (p1) and grant it ownership of the project. We then use the credentials of that service account to create an alias for the provider. Finally, we use the alias to create the resources within the project.
With this approach, the scope of each Terraform provider is clearly defined.
- Each projects has it own set of credentials
- Resources can only be created within the authorized project
- Specific APIs are only enabled within the corresponding projects
Apply complete! Resources: 7 added, 0 changed, 0 destroyed.
We have seen how using an alias to use different credentials within a Terraform root module can limit the risks of compromising your infrastructure. It helps you to reduce coupling between your resources by clearly defining the scope of your credentials.