1#!/usr/local/bin/python3.8
2# -*- coding: utf-8 -*-
3
4# Copyright: (c) 2020, Brian Scholer (@briantist)
5# Copyright: (c) 2017, AMTEGA - Xunta de Galicia
6# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
7
8DOCUMENTATION = r'''
9---
10module: win_domain_computer
11short_description: Manage computers in Active Directory
12description:
13  - Create, read, update and delete computers in Active Directory using a
14    windows bridge computer to launch New-ADComputer, Get-ADComputer,
15    Set-ADComputer, Remove-ADComputer and Move-ADObject powershell commands.
16options:
17  name:
18    description:
19      - Specifies the name of the object.
20      - This parameter sets the Name property of the Active Directory object.
21      - The LDAP display name (ldapDisplayName) of this property is name.
22    type: str
23    required: true
24  sam_account_name:
25    description:
26      - Specifies the Security Account Manager (SAM) account name of the
27        computer.
28      - It maximum is 256 characters, 15 is advised for older
29        operating systems compatibility.
30      - The LDAP display name (ldapDisplayName) for this property is sAMAccountName.
31      - If ommitted the value is the same as C(name).
32      - Note that all computer SAMAccountNames need to end with a C($).
33      - If C($) is omitted, it will be added to the end.
34    type: str
35  enabled:
36    description:
37      - Specifies if an account is enabled.
38      - An enabled account requires a password.
39      - This parameter sets the Enabled property for an account object.
40      - This parameter also sets the ADS_UF_ACCOUNTDISABLE flag of the
41        Active Directory User Account Control (UAC) attribute.
42    type: bool
43    default: yes
44  ou:
45    description:
46      - Specifies the X.500 path of the Organizational Unit (OU) or container
47        where the new object is created. Required when I(state=present).
48      - "Special characters must be escaped,
49        see L(Distinguished Names,https://docs.microsoft.com/en-us/previous-versions/windows/desktop/ldap/distinguished-names) for details."
50    type: str
51  description:
52    description:
53      - Specifies a description of the object.
54      - This parameter sets the value of the Description property for the object.
55      - The LDAP display name (ldapDisplayName) for this property is description.
56    type: str
57    default: ''
58  dns_hostname:
59    description:
60      - Specifies the fully qualified domain name (FQDN) of the computer.
61      - This parameter sets the DNSHostName property for a computer object.
62      - The LDAP display name for this property is dNSHostName.
63      - Required when I(state=present).
64    type: str
65  domain_username:
66    description:
67    - The username to use when interacting with AD.
68    - If this is not set then the user Ansible used to log in with will be
69      used instead when using CredSSP or Kerberos with credential delegation.
70    type: str
71  domain_password:
72    description:
73    - The password for I(username).
74    type: str
75  domain_server:
76    description:
77    - Specifies the Active Directory Domain Services instance to connect to.
78    - Can be in the form of an FQDN or NetBIOS name.
79    - If not specified then the value is based on the domain of the computer
80      running PowerShell.
81    type: str
82  state:
83    description:
84      - Specified whether the computer should be C(present) or C(absent) in
85        Active Directory.
86    type: str
87    choices: [ absent, present ]
88    default: present
89  managed_by:
90    description:
91    - The value to be assigned to the LDAP C(managedBy) attribute.
92    - This value can be in the forms C(Distinguished Name), C(objectGUID),
93      C(objectSid) or C(sAMAccountName), see examples for more details.
94    type: str
95    version_added: '1.3.0'
96  offline_domain_join:
97    description:
98      - Provisions a computer in the directory and provides a BLOB file that can be used on the target computer/image to join it to the domain while offline.
99      - The C(none) value doesn't do any offline join operations.
100      - C(output) returns the BLOB in output. The BLOB should be treated as secret (it contains the machine password) so use C(no_log) when using this option.
101      - C(path) preserves the offline domain join BLOB file on the target machine for later use. The path will be returned.
102      - If the computer already exists, no BLOB will be created/returned, and the module will operate as it would have without offline domain join.
103    type: str
104    choices:
105      - none
106      - output
107      - path
108    default: none
109  odj_blob_path:
110    description:
111      - The path to the file where the BLOB will be saved. If omitted, a temporary file will be used.
112      - If I(offline_domain_join=output) the file will be deleted after its contents are returned.
113      - The parent directory for the BLOB file must exist; intermediate directories will not be created.
114notes:
115  - "For more information on Offline Domain Join
116    see L(the step-by-step guide,https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2008-R2-and-2008/dd392267%28v=ws.10%29)."
117  - When using the ODJ BLOB to join a computer to the domain, it must be written out to a file.
118  - The file must be UTF-16 encoded (in PowerShell this encoding is called C(Unicode)), and it must end in a null character. See examples.
119  - The C(djoin.exe) part of the offline domain join process will not use I(domain_server), I(domain_username), or I(domain_password).
120seealso:
121- module: ansible.windows.win_domain
122- module: ansible.windows.win_domain_controller
123- module: community.windows.win_domain_group
124- module: ansible.windows.win_domain_membership
125- module: community.windows.win_domain_user
126author:
127- Daniel Sánchez Fábregas (@Daniel-Sanchez-Fabregas)
128- Brian Scholer (@briantist)
129'''
130
131EXAMPLES = r'''
132  - name: Add linux computer to Active Directory OU using a windows machine
133    community.windows.win_domain_computer:
134      name: one_linux_server
135      sam_account_name: linux_server$
136      dns_hostname: one_linux_server.my_org.local
137      ou: "OU=servers,DC=my_org,DC=local"
138      description: Example of linux server
139      enabled: yes
140      state: present
141    delegate_to: my_windows_bridge.my_org.local
142
143  - name: Remove linux computer from Active Directory using a windows machine
144    community.windows.win_domain_computer:
145      name: one_linux_server
146      state: absent
147    delegate_to: my_windows_bridge.my_org.local
148
149  - name: Provision a computer for offline domain join
150    community.windows.win_domain_computer:
151      name: newhost
152      dns_hostname: newhost.ansible.local
153      ou: 'OU=A great\, big organizational unit name,DC=ansible,DC=local'
154      state: present
155      offline_domain_join: yes
156      odj_return_blob: yes
157    register: computer_status
158    delegate_to: windc.ansible.local
159
160  - name: Join a workgroup computer to the domain
161    vars:
162      target_blob_file: 'C:\ODJ\blob.txt'
163    ansible.windows.win_shell: |
164      $blob = [Convert]::FromBase64String('{{ computer_status.odj_blob }}')
165      [IO.File]::WriteAllBytes('{{ target_blob_file }}', $blob)
166      & djoin.exe --% /RequestODJ /LoadFile '{{ target_blob_file }}' /LocalOS /WindowsPath "%SystemRoot%"
167
168  - name: Restart to complete domain join
169    ansible.windows.win_restart:
170'''
171
172RETURN = r'''
173odj_blob:
174  description:
175    - The offline domain join BLOB. This is an empty string when in check mode or when offline_domain_join is 'path'.
176    - This field contains the base64 encoded raw bytes of the offline domain join BLOB file.
177  returned: when offline_domain_join is not 'none' and the computer didn't exist
178  type: str
179  sample: <a long base64 string>
180odj_blob_file:
181  description: The path to the offline domain join BLOB file on the target host. If odj_blob_path was specified, this will match that path.
182  returned: when offline_domain_join is 'path' and the computer didn't exist
183  type: str
184  sample: 'C:\Users\admin\AppData\Local\Temp\e4vxonty.rkb'
185djoin:
186  description: Information about the invocation of djoin.exe.
187  returned: when offline_domain_join is True and the computer didn't exist
188  type: dict
189  contains:
190    invocation:
191      description: The full command line used to call djoin.exe
192      type: str
193      returned: always
194      sample: djoin.exe /PROVISION /MACHINE compname /MACHINEOU OU=Hosts,DC=ansible,DC=local /DOMAIN ansible.local /SAVEFILE blobfile.txt
195    rc:
196      description: The return code from djoin.exe
197      type: int
198      returned: when not check mode
199      sample: 87
200    stdout:
201      description: The stdout from djoin.exe
202      type: str
203      returned: when not check mode
204      sample: Computer provisioning completed successfully.
205    stderr:
206      description: The stderr from djoin.exe
207      type: str
208      returned: when not check mode
209      sample: Invalid input parameter combination.
210'''
211