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¶
- 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"
- Initialize and 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:
- Group memberships must be removed first (handled automatically by Terraform)
- Users can be deleted after their memberships are removed
- 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 }
}