Skip to content

Example: Local Groups and Users

This example demonstrates how to manage local groups, users, and group memberships on a Qumulo cluster.

Overview

Local groups and users are the foundation for access control on Qumulo clusters. They can be:

  • Referenced in SMB share permissions
  • Mapped to NFS identities
  • Used for quota management

Resources Created

  • Local Groups: users, developers, readers
  • Local Users: alice, bob, svc-backup, plus dynamic team members
  • Group Memberships: Users added to secondary groups

Usage

  1. Set up your variables:
export TF_VAR_cluster_endpoint="https://your-cluster:8000"
export TF_VAR_cluster_username="admin"
export TF_VAR_cluster_password="your-cluster-password"
export TF_VAR_user_password="password-for-new-users"
  1. Initialize and apply:
terraform init -upgrade
terraform plan
terraform apply

Key Concepts

Primary vs Secondary Groups

Each user has exactly one primary group (set on the user resource). Users can also belong to multiple secondary groups via the qumulo_local_group_member resource.

# Primary group is set on the user
resource "qumulo_local_user" "alice" {
  name          = "alice"
  primary_group = qumulo_local_group.users.id  # Primary
}

# Secondary group membership is a separate resource
resource "qumulo_local_group_member" "alice_developers" {
  group_id = qumulo_local_group.developers.id  # Secondary
  user_id  = qumulo_local_user.alice.id
}

Auto-Assigned IDs

If you don't specify gid (for groups) or uid (for users), the cluster will auto-assign values:

# GID will be auto-assigned
resource "qumulo_local_group" "users" {
  name = "users"
}

# UID will be auto-assigned
resource "qumulo_local_user" "alice" {
  name          = "alice"
  primary_group = qumulo_local_group.users.id
}

Write-Only Password

The password attribute on users is write-only. The cluster never returns passwords, so:

  • Terraform cannot detect if someone changed a password out-of-band
  • After import, passwords will not be managed unless you set them in config
resource "qumulo_local_user" "bob" {
  name          = "bob"
  primary_group = qumulo_local_group.users.id
  password      = var.user_password  # Sensitive, write-only
}

Dynamic User Creation

Use for_each to create multiple users and group memberships dynamically:

variable "team_members" {
  type    = set(string)
  default = ["charlie", "david", "eve"]
}

resource "qumulo_local_user" "team" {
  for_each      = var.team_members
  name          = each.value
  primary_group = qumulo_local_group.users.id
}

resource "qumulo_local_group_member" "team_developers" {
  for_each = var.team_members
  group_id = qumulo_local_group.developers.id
  user_id  = qumulo_local_user.team[each.value].id
}

Deletion Order

When destroying resources, be aware of dependencies:

  1. Group memberships must be removed first (handled automatically by Terraform)
  2. Users can be deleted after their memberships are removed
  3. Groups cannot be deleted if any user has them as primary_group

If you need to delete a group that's a primary group for users, first change those users' primary groups to a different group.

Import

Existing resources can be imported:

# Import a group (format: connection_profile,group_id)
terraform import 'qumulo_local_group.users' 'prod,500'

# Import a user (format: connection_profile,user_id)
terraform import 'qumulo_local_user.alice' 'prod,1001'

# Import a group membership (format: connection_profile,group_id,member_id)
terraform import 'qumulo_local_group_member.alice_developers' 'prod,501,1001'

Full Configuration

# Example: Managing Local Groups and Users on a Qumulo Cluster
#
# This example demonstrates how to create and manage local groups,
# users, and group memberships on a Qumulo cluster.

terraform {
  required_providers {
    qumulo = {
      source  = "qumulo-terraform-registry.s3.us-east-1.amazonaws.com/qumulo/qumulo"
      version = "~> 1.0"
    }
  }
}

variable "cluster_endpoint" {
  description = "Qumulo cluster REST API endpoint (e.g., https://cluster:8000)"
  type        = string
}

variable "cluster_username" {
  description = "Qumulo cluster admin username"
  type        = string
  default     = "admin"
}

variable "cluster_password" {
  description = "Qumulo cluster admin password"
  type        = string
  sensitive   = true
}

variable "user_password" {
  description = "Password for created local users"
  type        = string
  sensitive   = true
  default     = ""
}

# Define connection profile for the cluster
provider "qumulo" {
  connection_profiles = [
    {
      name                 = "cluster1"
      endpoint             = var.cluster_endpoint
      username             = var.cluster_username
      password             = var.cluster_password
      insecure_skip_verify = true # Required for clusters with self-signed certificates
    }
  ]
}

# =============================================================================
# Local Groups
# =============================================================================

# Primary group for regular users
resource "qumulo_local_group" "users" {
  connection_profile = "cluster1"

  name = "users"
}

# Group for developers with custom GID
resource "qumulo_local_group" "developers" {
  connection_profile = "cluster1"

  name = "developers"
  gid  = "2000"
}

# Group for read-only access
resource "qumulo_local_group" "readers" {
  connection_profile = "cluster1"

  name = "readers"
}

# =============================================================================
# Local Users
# =============================================================================

# Basic user with minimal configuration
resource "qumulo_local_user" "alice" {
  connection_profile = "cluster1"

  name          = "alice"
  primary_group = qumulo_local_group.users.id
}

# User with all options specified
resource "qumulo_local_user" "bob" {
  connection_profile = "cluster1"

  name           = "bob"
  primary_group  = qumulo_local_group.users.id
  uid            = "3001"
  home_directory = "/home/bob"
  password       = var.user_password
}

# Service account user
resource "qumulo_local_user" "svc_backup" {
  connection_profile = "cluster1"

  name          = "svc-backup"
  primary_group = qumulo_local_group.users.id
}

# =============================================================================
# Group Memberships (Secondary Groups)
# =============================================================================

# Add alice to developers group
resource "qumulo_local_group_member" "alice_developers" {
  connection_profile = "cluster1"

  group_id = qumulo_local_group.developers.id
  user_id  = qumulo_local_user.alice.id
}

# Add bob to developers group
resource "qumulo_local_group_member" "bob_developers" {
  connection_profile = "cluster1"

  group_id = qumulo_local_group.developers.id
  user_id  = qumulo_local_user.bob.id
}

# Add alice to readers group (she can be in multiple secondary groups)
resource "qumulo_local_group_member" "alice_readers" {
  connection_profile = "cluster1"

  group_id = qumulo_local_group.readers.id
  user_id  = qumulo_local_user.alice.id
}

# =============================================================================
# Dynamic Group Membership Using for_each
# =============================================================================

# Create multiple users dynamically
variable "team_members" {
  description = "Map of team member names"
  type        = set(string)
  default     = ["charlie", "david", "eve"]
}

resource "qumulo_local_user" "team" {
  for_each = var.team_members

  connection_profile = "cluster1"

  name          = each.value
  primary_group = qumulo_local_group.users.id
}

# Add all team members to developers group
resource "qumulo_local_group_member" "team_developers" {
  for_each = var.team_members

  connection_profile = "cluster1"

  group_id = qumulo_local_group.developers.id
  user_id  = qumulo_local_user.team[each.value].id
}

# =============================================================================
# Outputs
# =============================================================================

output "users_group_id" {
  description = "ID of the users group"
  value       = qumulo_local_group.users.id
}

output "developers_group_id" {
  description = "ID of the developers group"
  value       = qumulo_local_group.developers.id
}

output "alice_user_id" {
  description = "ID of the alice user"
  value       = qumulo_local_user.alice.id
}

output "alice_sid" {
  description = "Windows SID of the alice user"
  value       = qumulo_local_user.alice.sid
}

output "team_user_ids" {
  description = "Map of team member names to user IDs"
  value       = { for name, user in qumulo_local_user.team : name => user.id }
}