A need has arisen to implement asset tagging on Linux objects in Active Directory. I have been testing with the module named in the subject line, but I keep getting this error:
“New-ADObject failed: An attempt was made to add an object to the directory with a name that is already in use.”
This network is isolated, so getting the full error output (-vvv) is a little difficult. The documentation suggests that editing an existing Active Directory computer object is possible.
microsoft.ad.object module – Manage Active Directory objects — Ansible Documentation
Does anyone have any experience with this particular module, or any suggestions to try for getting past this error?
Probably going to need more information. Can you share a snippet of the code you’re using? Are you running this module against a linux or a windows target (not the AD object)? Have you tried using microsoft.ad.computer module – Manage Active Directory computer objects — Ansible Documentation instead?
1 Like
Below is the code from my test playbook, with some fields sanitized. Previously we had a requirement to update just the description field, so we were using win_domain_computer, but that module is very limited in what it can do. The vars at the bottom are required for that module to work, so I assume they are needed for most microsoft.ad modules, which is why I left them in place. I did try using microsoft.ad.computer, but was not able to get it to work either. The hosts are Linux, which use adcli and sssd to domain-join and authenticate users against an Active Directory infrastructure.
**Please ignore any format issues, since I hand-typed this into this message.
- hosts: all
gather_facts: true
tasks:
- name: Test microsoft.ad module
microsoft.ad.object:
domain_server: ‘{{ ad_preferred_dc }}’
domain_username: ‘{{ domain_username }}’
domain_password: ‘{{ domain_password }}’
name: ‘{{ inventory_hostname }}’
identity: ‘{{ inventory_hostname }}’
path: ‘{{ ad_computer_ou }}’
attributes:
set:
ENVIRONMENT: ‘[env_name]’
PLATFORM: ‘Rocky8]’
BRANCH: ‘[branch_name]’
type: computer
state: present
delegate_to: ‘{{ ad_preferred_dc }}’
vars:
ansible_connection: winrm
ansible_winrm_server_cert_validation: ignore
ansible_winrm_transport: ntlm
ansible_port: [port]
ansible_become: no
ansible_become_method: runas
ansible_user: ‘{{ domain_username }}’
ansible_password: ‘{{ domain_password }}’
ansible_become_flags: logon_type=interactive logon_flags=with_profile
ignore_errors: yes
First, I don’t see any module argument that you’re using for microsoft.ad.object that isn’t in microsoft.ad.computer. I do however see that using both the name and identity arguments may attempt to name, rename, or move an object if the name does not match the property found by identity (if one is found at all, then we would try to create a new object by that name). The ‘name’ argument appends ‘$’ to the value to determine the sAMAccountName. Some other arguments, such as identity, don’t appear to do this. So, your name and identity will never both match “{{ inventory_hostname }}”, and thus trigger creating a New-ADObject using a name that already exists.
Assuming inventory_hostname is the short hostname and not the fqdn, try something like this:
- hosts: all
gather_facts: true
tasks:
- name: Test microsoft.ad module
microsoft.ad.object:
domain_server: "{{ ad_preferred_dc }}"
domain_username: "{{ domain_username }}"
domain_password: "{{ domain_password }}"
name: "{{ inventory_hostname }}"
identity: "{{ inventory_hostname }}$" # appending the '$' should force searching for sAMAccountName's
sam_account_name: "{{ inventory_hostname }}" # sam_account_name appends missing '$' automatically
path: "{{ ad_computer_ou }}"
attributes:
set:
ENVIRONMENT: "[env_name]"
PLATFORM: "[Rocky8]"
BRANCH: "[branch_name]"
type: computer
state: present
delegate_to: "{{ ad_preferred_dc }}"
vars:
ansible_connection: winrm
ansible_winrm_server_cert_validation: ignore
ansible_winrm_transport: ntlm
ansible_port: [port]
ansible_become: no
ansible_become_method: runas
ansible_user: "{{ domain_username }}"
ansible_password: "{{ domain_password }}"
ansible_become_flags: logon_type=interactive logon_flags=with_profile
ignore_errors: yes
The changes you suggested worked when I tested them, so thanks for that. However, when I changed the hard-coded key-pair values for variables it complains about undefined variables. For example:
POC-EMAIL: group-name@outlook.com
vs
POC-EMAIL: ‘{{ cm_poc_email }}’
That and other key-pair variables are defined in the group_vars for this particular set of workstations, so they are defined somewhere. Does this particular module require hard-coded key-pair values?
I think you might be using single quotes when you should be using double-quotes. Single quotes tell Ansible to use literal strings, so ‘{{ cm_poc_email }}’ is literally {{ cm_poc_email }}
, while “{{ cm_poc_email }}” expands to group-name@outlook.com
.
You might also be running into issues with how delegate_to
handles variables relating to the host. The vars you’re using may be undefined in this context. In this case, you may need to use "{{ hostvars[inventory_hostname]['cm_poc_email'] }}"
.