π§ Terraform
Create a Lumos requestable permission linked to a specified security group and application
This Terraform configuration example, using the Lumos Terraform Provider, enables teams to automate the provisioning of access permissions in the Lumos AppStore by integrating with Okta security groups. It allows infrastructure and security engineers to define access requests declaratively, ensuring that only validated applications and groups are used.
By automatically configuring request approvals and fulfillment based on existing Okta groups, the configuration streamlines access managementβeliminating manual steps, reducing misconfiguration risk, and supporting compliance with organizational policies.
It empowers teams to programmatically manage who can request access, who approves it, and how itβs fulfilledβall through version-controlled infrastructure as code.
The example configuration:
- Authenticates the Lumos provider using a bearer token from an environment variable or Terraform variable.
- Accepts inputs for the Lumos application name and the Okta security group name via variables.
- Uses data sources to look up the Okta security group and Lumos application by name, ensuring exact matches.
- Conditionally creates a lumos_requestable_permission resource only if both the group and application are found.
- Configures request approval to require the identified group as an approver, while disabling manager approval.
- Configures request fulfillment by assigning the same group as the provisioning target.
- Outputs the IDs of the security group, application, and requestable permission (if created) to aid in validation and debugging.
# terraform.tfvars
lumos_api_token = "lsk_" # Replace with your actual token
okta_security_group_name = "Contractor"
app_name = "Okta (Democorp1)"
# main.tf
###############################################################################
# Terraform & provider versions
###############################################################################
terraform {
required_version = ">= 1.5"
required_providers {
lumos = {
source = "teamlumos/lumos"
version = "0.8.0"
}
}
}
###############################################################################
# Provider β token comes from env var LUMOS_HTTP_BEARER
###############################################################################
provider "lumos" {
# If you want to use the variable from terraform.tfvars, uncomment the line below:
http_bearer = var.lumos_api_token
# Otherwise, ensure LUMOS_HTTP_BEARER environment variable is set.
}
###############################################################################
# Variables β supply them via terraform.tfvars or -var flags
###############################################################################
variable "lumos_api_token" {
type = string
sensitive = true
}
variable "okta_security_group_name" { # Name of the Okta Security Group
type = string
description = "The name of the Okta security group to be used as an approver and provisioning target."
}
variable "app_name" { # Name of the Lumos Application
type = string
description = "The name of the Lumos application for which the requestable permission is being configured."
}
###############################################################################
# Data source β fetch the Security group by name
###############################################################################
data "lumos_groups" "security_group_by_name" {
name = var.okta_security_group_name
exact_match = true # Recommended to ensure you find the specific group
}
###############################################################################
# Data source β fetch the Application by name
###############################################################################
data "lumos_apps" "application_by_name" {
name_search = var.app_name
exact_match = true # Recommended for precise matching
}
#locals {
# This local variable makes it easier to access the group ID and provides a check.
# It assumes the group name is unique and will be found.
# security_group_id = can(data.lumos_groups.security_group_by_name.items[0].id) ? data.lumos_groups.security_group_by_name.items[0].id : tostring(null)
# application_id = can(data.lumos_apps.application_by_name.items[0].id) ? data.lumos_apps.application_by_name.items[0].id : tostring(null)
#}
#lifecycle {
# pre shabbycondition {
# condition = local.security_group_id != null && local.application_id != null
# error_message = "The Okta security group named '${var.okta_security_group_name}' or the Application named '${var.app_name}' was not found or the data source returned no items."
#}
#}
###############################################################################
# Resource β create / update the requestable permission
###############################################################################
resource "lumos_requestable_permission" "secure_app_store" {
# Create this resource only if both the group and the app are found
count = length(data.lumos_groups.security_group_by_name.items) > 0 && length(data.lumos_apps.application_by_name.items) > 0 ? 1 : 0
app_id = data.lumos_apps.application_by_name.items[0].id # Use ID from app lookup
label = "Access to Secure App Store"
request_config = {
request_approval_config = {
request_approval_config_override = true
approvers = {
groups = [
{ id = data.lumos_groups.security_group_by_name.items[0].id }
]
}
manager_approval = "NONE" # or "INITIAL_APPROVAL" if you need the manager gate
}
request_fulfillment_config = {
provisioning_group = {
id = data.lumos_groups.security_group_by_name.items[0].id # Lumos adds requester here
}
# auto-provision is implied when a provisioning_group is supplied
}
}
}
###############################################################################
# Handy outputs
###############################################################################
output "security_group_id_from_name_lookup" {
value = length(data.lumos_groups.security_group_by_name.items) > 0 ? data.lumos_groups.security_group_by_name.items[0].id : "Okta security group not found by name."
description = "The ID of the Okta security group found by its name."
}
output "application_id_from_name_lookup" {
value = length(data.lumos_apps.application_by_name.items) > 0 ? data.lumos_apps.application_by_name.items[0].id : "Application not found by name."
description = "The ID of the Application found by its name."
}
output "requestable_permission_id" {
value = length(lumos_requestable_permission.secure_app_store) > 0 ? lumos_requestable_permission.secure_app_store[0].id : "Requestable permission not created (likely because the group or app was not found)."
description = "The ID of the created requestable permission."
}
Here are the Terraform commands you can use to run and test this configuration:
π οΈ Terraform Commands to Run/Test
-
Initialize the Terraform configuration:
terraform init
-
(Optional) Validate the configuration:
terraform validate
-
(Optional) Preview what changes will be made:
terraform plan -var="lumos_api_token=<your_token>" -var="okta_security_group_name=<your_group>" -var="app_name=<your_app>"
-
Apply the configuration to create resources:
terraform apply -var="lumos_api_token=<your_token>" -var="okta_security_group_name=<your_group>" -var="app_name=<your_app>"
-
(Optional) View the output values after apply:
terraform output
-
Destroy the resources when you're done testing:
terraform destroy -var="lumos_api_token=<your_token>" -var="okta_security_group_name=<your_group>" -var="app_name=<your_app>"
Tip: You can use terraform.tfvars
file to supply values for lumos_api_token
, okta_security_group_name
, and app_name
to avoid repeating them in each command.
Updated 20 days ago