Entitle Terraform provider | Entitle

What is Terraform?

Terraform is an infrastructure orchestrator written in HashiCorp Configuration Language (HCL). It is a widely adopted Infrastructure-as-Code (IaC) tool that eliminates the need for manual configuration by enabling declarative management of infrastructure resources.

How is the Entitle Terraform provider useful?

The Entitle Terraform provider enables you to manage Entitle resources and configurations using Terraform. It supports the automated management of integrations, workflows, and access policies within your Entitle environment, allowing for consistent and repeatable infrastructure management.

For additional examples beyond those provided in this guide, refer to Entitle's Terraform registry.

ℹ️

This guide assumes familiarity with HashiCorp Terraform. If you're new to Terraform, refer to the official Terraform guides and tutorials for foundational knowledge.

Supported API endpoints

The Entitle Terraform provider currently supports the following:

Prerequisites

Before using the Entitle Terraform provider, ensure the following:

Install the Entitle Terraform provider

Copy and paste this code into your Terraform configuration to install the latest Entitle provider.

terraform {
  required_providers {
    entitle = {
      source = "entitleio/entitle"
    }
  }
}

Configure the provider

The provider accepts the following optional arguments:

  • endpoint (String) - Entitle API server address, set by default to https://api.entitle.io.
  • api_key (String, sensitive) - Entitle API bearer authorizations (http, Bearer).
Configure the Entitle provider

This example shows the Entitle provider configuration, including the optional arguments:

terraform {
  required_providers {
    entitle = {
      source = "entitleio/entitle"
    }
  }
}

provider "entitle" {
  endpoint = "https://api.entitle.io"
  api_key  = "PUT_YOUR_TOKEN"
}

In case optional arguments are not used, the provider will use environment variables instead:

  • ENTITLE_API_KEY
  • ENTITLE_API_ENDPOINT

The configuration would look like this:

terraform {
  required_providers {
    entitle = {
      source = "entitleio/entitle"
    }
  }
}

provider "entitle" {}
Create a workflow and integration

This example shows how to define a workflow and then create an integration using this workflow:

terraform {
  required_providers {
    entitle = {
      source = "entitleio/entitle"
    }
  }
}

provider "entitle" {
  endpoint = "https://api.entitle.io"
  api_key  = var.entitle_api_key
}

data "entitle_user" "my_user" {
  email = "[email protected]"
}

resource "entitle_workflow" "my_workflow" {
  name = "example workflow name"
  rules = [
    {
      any_schedule = true
      approval_flow = {
        steps = [
          {
            approval_entities = [
              {
                type = "Automatic"
              }
            ]
            notified_entities = []
            operator          = "or"
            sort_order        = 1
          }
        ]
      }

      in_groups      = []
      in_schedules   = []
      sort_order     = 1
      under_duration = 3600
    }
  ]
}

resource "entitle_integration" "my_gitlab" {
  name                   = var.integration_name
  requestable            = true
  requestable_by_default = true
  application = {
    name = "Gitlab"
  }
  allowed_durations = [-1]
  auto_assign_recommended_maintainers = false
  auto_assign_recommended_owners      = false
  allow_creating_accounts             = false
  connection_json = jsonencode({
    domain                  = "https://gitlab.com"
    private_token           = var.gitlab_access_token
    configurationSchemaName = "Configuration "
  })
  notify_about_external_permission_changes = true
  readonly = false
  workflow = {
    id = entitle_workflow.my_workflow.id
  }
  maintainers = []
  owner = {
    id = data.entitle_user.my_user.id
  }
}
Keep integration credentials out of Terraform state

By default, Terraform stores the connection_json argument in your state, even though the provider marks it as sensitive. To keep credentials such as LDAP bind passwords, service account keys, and API tokens out of state and plan files, use the write-only connection_json_wo argument with an ephemeral source.

  • connection_json_wo: A write-only argument. Terraform sends it to Entitle when you create the integration and whenever connection_json_wo_version changes. Terraform never stores it in state or plan files.
  • connection_json_wo_version: Change this value to re-send the credentials, for example after you rotate a secret.

Use either connection_json or connection_json_wo in a resource, not both.

ephemeral "vault_kv_secret_v2" "gitlab" {
  mount = "secret"
  name  = "entitle/gitlab"
}

resource "entitle_integration" "my_gitlab" {
  name = "My Gitlab Integration"
  application = {
    name = "gitlab"
  }
  connection_json_wo = jsonencode({
    domain                  = "https://gitlab.com"
    private_token           = ephemeral.vault_kv_secret_v2.gitlab.data["token"]
    configurationSchemaName = "Configuration "
  })
  connection_json_wo_version = "1" # Change to re-send rotated credentials
  allowed_durations = [-1]
  owner    = { id = var.entitle_owner_id }
  workflow = { id = var.entitle_workflow_id }
}

Migrate an existing integration

  1. Replace connection_json with connection_json_wo, and set connection_json_wo_version to a starting value such as "1".
  2. Run terraform apply. Terraform updates the integration in place and removes connection_json from state.
  3. Rotate the credentials in the source system, update them in your secret store, then change connection_json_wo_version.
⚠️

Important

Rotate credentials after migrating. Older state snapshots, such as backend versions and backups, still contain the old connection_json value.

Create a virtual integration from an existing integration

This example shows how to create a GitLab integration, retrieve its role IDs, and use those roles to build a virtual integration with associated resources and roles.

The same approach can also be used with integrations created through the Entitle UI or API.

This example uses three files:

  • main.tf
  • variables.tf
  • terraform.tfvars

Define the variables

The variables.tf file contains the variables used in this example:

variable "entitle_api_key" {
  type      = string
  sensitive = true
}

variable "entitle_workflow_id" {
  type = string
}

variable "entitle_role_id" {
  type = string
}

variable "entitle_role2_id" {
  type = string
}

variable "entitle_owner_id" {
  type = string
}

variable "gitlab_access_token" {
  type      = string
  sensitive = true
}

Set the variable values

Use the terraform.tfvars file to provide values for the required variables:

# Can be created by using Entitle Web UI
# https://docs.beyondtrust.com/entitle/docs/org-settings#view-and-manage-tokens
entitle_api_key = ""

# Can be created from terraform using entitle_workflow resource,
# but if already exists can be get from web UI, API or by using entitle_workflow data source
entitle_workflow_id = ""

# Can be fetched by using API or terraform entitle_users data source
entitle_owner_id = ""

# Create gitlab account, create dummy repo, then get token
# https://docs.beyondtrust.com/entitle/docs/entitle-integration-gitlab
gitlab_access_token = ""

# These we will get on STEP2
entitle_role_id  = ""
entitle_role2_id = ""

Define the Terraform configuration

Use the main.tf file as the base configuration:

# STEP 1
terraform {
  required_providers {
    entitle = {
      source = "entitleio/entitle"
    }
  }
}

provider "entitle" {
  endpoint = "https://api.entitle.io"
  api_key  = var.entitle_api_key
}

# GitLab Integration

resource "entitle_integration" "my_gitlab" {
  name = "My Gitlab Integration"
  application = {
    name = "gitlab"
  }
  allowed_durations = [-1]
  auto_assign_recommended_maintainers = false
  auto_assign_recommended_owners      = false
  allow_creating_accounts             = false
  connection_json = jsonencode({
    domain                  = "https://gitlab.com"
    private_token           = var.gitlab_access_token
    configurationSchemaName = "Configuration "
  })
  notify_about_external_permission_changes = true
  owner = {
    id = var.entitle_owner_id
  }
  readonly = false
  workflow = {
    id = var.entitle_workflow_id
  }
  requestable            = true
  requestable_by_default = true
}

# # STEP 2
# # Get Roles
# data "entitle_resources" "my_gitlab_resources" {
#   integration_id = entitle_integration.my_gitlab.id
# }
#
# output "first_gitlab_resource" {
#   value = data.entitle_resources.my_gitlab_resources.resources.0.id
# }
#
# data "entitle_roles" "my_gitlab_roles" {
#   resource_id = data.entitle_resources.my_gitlab_resources.resources.0.id
# }
#
# output "first_gitlab_role" {
#   value = data.entitle_roles.my_gitlab_roles.roles.0.id
# }
#
# output "second_gitlab_role" {
#   value = data.entitle_roles.my_gitlab_roles.roles.1.id
# }

# # STEP 3
# # Virtual Application
#
# resource "entitle_integration" "test_integration" {
#   name = "Test Example Virtual Integration"
#   application = {
#     name = "virtual application"
#   }
#   allowed_durations = [1800, 3600]
#   connection_json = jsonencode({})
#   owner = {
#     id = var.entitle_owner_id
#   }
#   workflow = {
#     id = var.entitle_workflow_id
#   }
#   allow_changing_account_permissions       = false
#   allow_creating_accounts                  = false
#   auto_assign_recommended_owners           = false
#   auto_assign_recommended_maintainers      = false
#   notify_about_external_permission_changes = false
# }
#
# resource "entitle_resource" "my_resource" {
#   name                     = "My Virtual Resource - TEST"
#   user_defined_description = "test description"
#   requestable              = true
#   allowed_durations = [-1]
#   owner = {
#     id = var.entitle_owner_id
#   }
#   workflow = {
#     id = var.entitle_workflow_id
#   }
#   integration = {
#     id = entitle_integration.test_integration.id
#   }
#   maintainers = []
#   user_defined_tags = [
#     "test1",
#     "test2"
#   ]
# }
#
# resource "entitle_role" "mr_role" {
#   allowed_durations = [-1]
#   name        = "ROLE1"
#   requestable = true
#   resource = {
#     id = entitle_resource.my_resource.id
#   }
#   virtualized_role = {
#     id = var.entitle_role_id
#   }
# }
#
# resource "entitle_role" "mr_role2" {
#   allowed_durations = [-1]
#   name        = "ROLE2"
#   requestable = true
#   resource = {
#     id = entitle_resource.my_resource.id
#   }
#   virtualized_role = {
#     id = var.entitle_role2_id
#   }
# }
#
# resource "entitle_resource" "my_resource2" {
#   name                     = "My Resource - TEST2"
#   user_defined_description = "test description"
#   requestable              = true
#   allowed_durations = [-1]
#   owner = {
#     id = var.entitle_owner_id
#   }
#   workflow = {
#     id = var.entitle_workflow_id
#   }
#   integration = {
#     id = entitle_integration.test_integration.id
#   }
#   maintainers = []
#   user_defined_tags = [
#     "test1",
#     "test2"
#   ]
# }
#
#
# resource "entitle_role" "mr2_role" {
#   allowed_durations = [-1]
#   name        = "ROLE1"
#   requestable = true
#   resource = {
#     id = entitle_resource.my_resource2.id
#   }
#   virtualized_role = {
#     id = var.entitle_role_id
#   }
# }
#
# resource "entitle_role" "mr2_role2" {
#   allowed_durations = [-1]
#   name        = "ROLE2"
#   requestable = true
#   resource = {
#     id = entitle_resource.my_resource2.id
#   }
#   virtualized_role = {
#     id = var.entitle_role_id
#   }
# }
#
# data "entitle_roles" "my_list" {
#   resource_id = entitle_resource.my_resource.id
# }
#
# output "roles" {
#   value = data.entitle_roles.my_list
# }
#
# data "entitle_roles" "my_list2" {
#   resource_id = entitle_resource.my_resource2.id
# }
#
# output "roles2" {
#   value = data.entitle_roles.my_list2
# }

Create the integration

  1. Save all three files in the same directory.
  2. Open terraform.tfvars and provide the required values.
  3. Run:
    terraform init
    terraform plan
    terraform apply
    This completes STEP 1 and creates the GitLab integration.

Retrieve role IDs

  1. In main.tf, uncomment all lines in STEP 2.
  2. Run:
    terraform apply
  3. Copy the returned role IDs from the output and add them to terraform.tfvars:
    entitle_role_id  = "ROLE_ID_1"  
    entitle_role2_id = "ROLE_ID_2"
  4. After saving the values, comment out all lines in STEP 2.

Create the virtual integration, resources, and roles

  1. In main.tf, uncomment all lines in STEP 3.
  2. Run
    terraform apply

This creates:

  • a virtual integration
  • virtual resources
  • virtual roles mapped to the original GitLab roles

The created roles are printed in the Terraform output.

Delete a virtual role

To delete a virtual role, remove its entitle_role block from main.tf, then run:

terraform apply

Did this page help you?

©2003-2026 BeyondTrust Corporation. All Rights Reserved. Other trademarks identified on this page are owned by their respective owners. BeyondTrust is not a chartered bank or trust company, or depository institution. It is not authorized to accept deposits or trust accounts and is not licensed or regulated by any state or federal banking authority.