Skip to content

Group Managed Service Account Playbook Usage Guide

Requirements

  1. The target host must be a Windows Server with the RSAT-AD-PowerShell feature available. The playbook will install it automatically if it is not already present.

Prerequisites

  1. A domain account with permissions to create security groups and service accounts in Active Directory must be available.
  2. The playbook must be run against a single Windows host using --limit. The host does not need to be a domain controller, but must be domain-joined.
  3. Define your gMSA definitions in extra_vars/gmsas.yml. See Sample Variables below.
  4. The following variables must be defined. The variables should be all uppercase when defined as environment variables, but all lowercase when defined in host_vars, group_vars, or an Ansible vault.
# REQUIRED VARIABLES
export DOMAIN_NAME='sapphire.dev'
export DOMAIN_ADMIN_USER='sapphire\adminuser'
export DOMAIN_ADMIN_PASSWORD='PASSWORD'
# REQUIRED VARIABLES
domain_name: 'sapphire.dev'
domain_admin_user: 'sapphire\adminuser'
domain_admin_password: 'PASSWORD'

Usage

  1. Define your gMSA definitions in extra_vars/gmsas.yml using the sample variables below.
  2. Run the playbooks/create-gmsa.yml playbook against a single domain-joined Windows host. The playbook will create the AD security group, add the specified members, and create the gMSA with the group as the allowed principal to retrieve the password.
    ansible-playbook --limit=epic-kpr-sapph1.sapphire.dev playbooks/create-gmsa.yml -e @extra_vars/gmsas.yml
    

Optional Variables

The following optional variables can be passed to override default AD paths and group ownership:

Variable Description
security_group_path OU path for the security group (e.g. OU=Groups,DC=sapphire,DC=dev)
service_account_path OU path for the gMSA (e.g. OU=Service Accounts,DC=sapphire,DC=dev)
managed_by AD identity to set as the group's Managed By attribute

Inventory Groups and the Constructed Plugin

When using members_group, the group name must match an Ansible inventory group. The ansible.builtin.constructed inventory plugin is the recommended way to create these groups from hostname naming conventions — no manual maintenance required as hosts are added or removed.

This repo includes inventory.constructed.yml as a ready-to-use example. It creates groups in two ways:

  • keyed_groups — auto-derives a group from the role segment of the hostname (e.g. epic-kpr-*role_kpr, epic-msql-*role_msql). Any new host matching the naming convention is grouped automatically.
  • groups — explicit named groups using Jinja2 hostname pattern matching (e.g. epic_kpr, epic_msql).
plugin: constructed

keyed_groups:
  - key: inventory_hostname.split('.')[0].split('-')[1] if inventory_hostname.split('.')[0].split('-') | length > 1 else 'ungrouped'
    prefix: "role"
    separator: "_"

groups:
  epic: "'epic-' in inventory_hostname"
  epic_kpr: "'epic-kpr' in inventory_hostname"
  epic_msql: "'epic-msql' in inventory_hostname"
  epic_cog: "'epic-cog' in inventory_hostname"
  epic_smtp: "'epic-smtp' in inventory_hostname"
  epic_sp: "'epic-sp' in inventory_hostname"

To verify the groups that will be available to use in members_group, run:

ansible-inventory --graph

Sample Variables

extra_vars/gmsas.yml defines the gMSAs to create. Each entry requires a name (the gMSA account name), a group (the AD security group that controls which hosts can retrieve the password), and at least one of members or members_group to populate that group.

Specifying Members

members and members_group can be used independently or combined — duplicates are automatically removed.

  • members_group — an Ansible inventory group; short hostnames are derived automatically (e.g. hosts in epic_kpr resolve to epic-kpr-sapph1, epic-kpr-sapph2)
  • members — an explicit list of short AD computer names (without the trailing $)
# gmsa_definitions supports two ways to specify members (combinable):
#   members:       explicit list of short AD computer names
#   members_group: an Ansible inventory group; short names are derived automatically
gmsa_definitions:
  - name: kuiper-gmsa
    group: KuiperAllowedHosts
    members_group: epic_kpr

  # Mix both: group provides the base, members adds extras not in inventory
  # - name: kuiper-gmsa
  #   group: KuiperAllowedHosts
  #   members_group: epic_kpr
  #   members:
  #     - some-extra-host

  # Manual-only
  # - name: wbs-gmsa
  #   group: WbsAllowedHosts
  #   members:
  #     - epic-msql-sapph