🐶
Terraform

Terraform GCP Service Account Creation with Roles

By Filip on 10/08/2024

Learn how to streamline infrastructure management by securely creating GCP service accounts with specific roles using Terraform.

Terraform GCP Service Account Creation with Roles

Table of Contents

Introduction

This guide explains how to create a Google Cloud Platform (GCP) service account and assign it roles using Terraform. We'll cover defining the service account, specifying roles, and using the google_project_iam_member resource to grant the roles. The example code includes explanations and important considerations for managing service accounts and their permissions effectively.

Step-by-Step Guide

To create a GCP service account with roles using Terraform, you'll generally follow these steps:

  1. Define the service account:

    resource "google_service_account" "default" {
      account_id   = "your-service-account-id"
      display_name = "Your Service Account Name"
    }
    • Replace "your-service-account-id" with a unique identifier for your service account.
    • Replace "Your Service Account Name" with a descriptive name.
  2. Define the roles: You can either list roles directly or use variables for better organization:

    variable "roles" {
      type = list(string)
      default = [
        "roles/storage.objectViewer",
        "roles/pubsub.publisher",
      ]
    }
  3. Assign roles using google_project_iam_member:

    resource "google_project_iam_member" "service_account_roles" {
      for_each = toset(var.roles)
      role    = each.value
      member  = "serviceAccount:${google_service_account.default.email}"
    }
    • This iterates through the roles list and grants each role to the service account.

Explanation:

  • google_service_account: This resource creates the service account itself.
  • google_project_iam_member: This resource binds roles to members (in this case, your service account) at the project level.
  • for_each: This Terraform construct allows you to create multiple instances of a resource based on a collection. Here, it iterates through the roles list.
  • toset: This function converts the roles list into a set, which is required for for_each.
  • each.value: This refers to the current element (role) being processed within the loop.
  • "serviceAccount:${google_service_account.default.email}": This dynamically constructs the member string using the service account's email.

Important Considerations:

  • Permissions: Ensure your Terraform code has the necessary permissions (e.g., iam.serviceAccounts.create, iam.roles.list) to create service accounts and assign roles.
  • Resource hierarchy: Roles can be granted at different levels (project, organization, etc.). Adjust the resource type (e.g., google_organization_iam_member) accordingly.
  • Service account deletion: If you delete and recreate a service account with the same name, you might need to wait a short period for IAM bindings to propagate correctly.
  • Alternative approaches: You can also use loops with count or modules to manage roles for multiple service accounts.

This setup ensures that roles are added specifically to your new service account without affecting existing role assignments.

Code Example

This Terraform code defines variables for a Google Cloud service account, including its ID, display name, and roles. It then creates the service account and assigns the specified roles to it. Finally, it outputs the service account's email address.

# Define variables for service account and roles
variable "service_account_id" {
  type        = string
  description = "Unique ID for the service account"
  default     = "your-service-account-id"
}

variable "service_account_display_name" {
  type        = string
  description = "Display name for the service account"
  default     = "Your Service Account Name"
}

variable "roles" {
  type        = list(string)
  description = "List of roles to assign to the service account"
  default = [
    "roles/storage.objectViewer",
    "roles/pubsub.publisher",
  ]
}

# Create the service account
resource "google_service_account" "default" {
  account_id   = var.service_account_id
  display_name = var.service_account_display_name
}

# Assign roles to the service account
resource "google_project_iam_member" "service_account_roles" {
  for_each = toset(var.roles)
  role    = each.value
  member  = "serviceAccount:${google_service_account.default.email}"
}

# Output the service account email
output "service_account_email" {
  value = google_service_account.default.email
}

Explanation:

  1. Variables:

    • service_account_id: Stores the unique ID for your service account.
    • service_account_display_name: Stores the display name for your service account.
    • roles: Defines a list of roles to be assigned.
  2. Service Account Creation:

    • The google_service_account resource creates the service account using the provided ID and display name.
  3. Role Assignment:

    • The google_project_iam_member resource iterates through the roles list using for_each and toset.
    • For each role, it grants the role to the service account using its email address, which is dynamically retrieved using google_service_account.default.email.
  4. Output:

    • The output block displays the service account's email address, which can be useful for later reference.

To use this code:

  1. Save: Save the code as a .tf file (e.g., service_account.tf).
  2. Customize: Update the variables with your desired values.
  3. Run Terraform:
    • terraform init (initializes Terraform)
    • terraform plan (preview the changes)
    • terraform apply (create the resources)

This code will create a GCP service account with the specified roles, providing a clear and organized way to manage service account permissions in your Terraform infrastructure.

Additional Notes

Security:

  • Principle of Least Privilege: Assign only the minimum necessary roles to the service account. Avoid overly permissive roles like Project Editor or Owner whenever possible.
  • Key Management: If you need to interact with the service account outside of Google Cloud, generate and securely store its keys. Rotate keys regularly and consider using short-lived credentials when possible.
  • Auditing: Enable audit logging for services accessed by the service account to track its activity.

Best Practices:

  • Naming Conventions: Use clear and consistent naming conventions for service accounts and roles to improve readability and maintainability.
  • Modularization: For larger projects, consider organizing your Terraform code into modules to manage service accounts and their roles for different environments or components.
  • Documentation: Document the purpose of each service account and the roles assigned to it. This helps with troubleshooting and security audits.

Troubleshooting:

  • IAM Propagation Delays: Be aware that IAM changes might take a few minutes to propagate fully. If you encounter permission issues immediately after creating or modifying a service account, wait a short period and try again.
  • Error Messages: Pay close attention to Terraform error messages, as they often provide valuable clues for resolving issues related to service account creation or role assignment.

Alternatives:

  • Workload Identity Federation: For applications running outside of GCP, consider using Workload Identity Federation to grant them temporary credentials to access GCP resources without needing a service account key.
  • Terraform Google Provider Documentation: Refer to the official Terraform Google provider documentation for the most up-to-date information on resources and their usage: https://registry.terraform.io/providers/hashicorp/google/latest/docs

Summary

This table summarizes the key aspects of creating GCP service accounts and assigning them roles using Terraform:

Feature Description Terraform Resource Example
Service Account Creation Defines the service account with a unique ID and display name. google_service_account resource "google_service_account" "default" { account_id = "your-service-account-id" display_name = "Your Service Account Name" }
Role Definition Specifies the roles to be assigned, either directly or using variables for better organization. variable "roles" { type = list(string) default = [ "roles/storage.objectViewer", "roles/pubsub.publisher" ] }
Role Assignment Binds the defined roles to the service account at the project level. google_project_iam_member resource "google_project_iam_member" "service_account_roles" { for_each = toset(var.roles) role = each.value member = "serviceAccount:${google_service_account.default.email}" }
Dynamic Member String Constructs the member string dynamically using the service account's email. "serviceAccount:${google_service_account.default.email}"
Iteration through Roles Uses for_each to iterate through the list of roles and assign each one to the service account. for_each = toset(var.roles)

Key Considerations:

  • Permissions: Ensure your Terraform code has the necessary permissions to create service accounts and assign roles.
  • Resource Hierarchy: Adjust the resource type based on the desired level of role assignment (project, organization, etc.).
  • Service Account Deletion: Be aware of potential propagation delays when deleting and recreating service accounts with the same name.
  • Alternative Approaches: Explore using loops with count or modules for managing roles across multiple service accounts.

Conclusion

By combining the google_service_account and google_project_iam_member resources with Terraform's built-in functionalities like for_each, you can efficiently manage service accounts and their roles in your GCP projects. This approach enables infrastructure as code, ensuring that your service accounts have the correct permissions for your applications and workflows. Remember to follow security best practices, such as the principle of least privilege, and consult the Terraform Google provider documentation for the latest features and updates. By automating this process, you can minimize errors, improve consistency, and streamline your cloud infrastructure management.

References

Were You Able to Follow the Instructions?

😍Love it!
😊Yes
😐Meh-gical
😞No
🤮Clickbait