2017-10-13 01:40:47 +00:00
Desired State Configuration
===========================
.. contents :: Topics
2018-09-13 17:38:49 +00:00
:local:
2017-10-13 01:40:47 +00:00
What is Desired State Configuration?
`` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ``
Desired State Configuration, or DSC, is a tool built into PowerShell that can
be used to define a Windows host setup through code. The overall purpose of DSC
is the same as Ansible, it is just executed in a different manner. Since
Ansible 2.4, the `` win_dsc `` module has been added and can be used to leverage
existing DSC resources when interacting with a Windows host.
More details on DSC can be viewed at `DSC Overview <https://docs.microsoft.com/en-us/powershell/dsc/overview> `_ .
Host Requirements
`` ` ` ` ` ` ` ` ` ` ` ` ` ` ``
To use the `` win_dsc `` module, a Windows host must have PowerShell v5.0 or
newer installed. All supported hosts, except for Windows Server 2008 (non R2) can be
upgraded to PowerShell v5.
Once the PowerShell requirements have been met, using DSC is as simple as
creating a task with the `` win_dsc `` module.
Why Use DSC?
`` ` ` ` ` ` ` ` ` ``
DSC and Ansible modules have a common goal which is to define and ensure the state of a
resource. Because of
this, resources like the DSC `File resource <https://docs.microsoft.com/en-us/powershell/dsc/fileresource> `_
and Ansible `` win_file `` can be used to achieve the same result. Deciding which to use depends
on the scenario.
Reasons for using an Ansible module over a DSC resource:
* The host does not support PowerShell v5.0, or it cannot easily be upgraded
* The DSC resource does not offer a feature present in an Ansible module. For example
win_regedit can manage the `` REG_NONE `` property type, while the DSC
`` Registry `` resource cannot
* DSC resources have limited check mode support, while some Ansible modules have
better checks
* DSC resources do not support diff mode, while some Ansible modules do
* Custom resources require further installation steps to be run on the host
beforehand, while Ansible modules are in built-in to Ansible
* There are bugs in a DSC resource where an Ansible module works
Reasons for using a DSC resource over an Ansible module:
* The Ansible module does not support a feature present in a DSC resource
* There is no Ansible module available
* There are bugs in an existing Ansible module
In the end, it doesn't matter whether the task is performed with DSC or an
Ansible module; what matters is that the task is performed correctly and the
playbooks are still readable. If you have more experience with DSC over Ansible
and it does the job, just use DSC for that task.
How to Use DSC?
`` ` ` ` ` ` ` ` ` ` ` ` ``
The `` win_dsc `` module takes in a free-form of options so that it changes
according to the resource it is managing. A list of built in resources can be
found at `resources <https://docs.microsoft.com/en-us/powershell/dsc/resources> `_ .
2018-08-22 19:53:30 +00:00
Using the `Registry <https://docs.microsoft.com/en-us/powershell/dsc/registryresource> `_
2018-11-15 21:17:29 +00:00
resource as an example, this is the DSC definition as documented by Microsoft:
.. code-block :: powershell
2017-10-13 01:40:47 +00:00
Registry [string] #ResourceName
{
Key = [string]
ValueName = [string]
[ Ensure = [string] { Enable | Disable } ]
[ Force = [bool] ]
[ Hex = [bool] ]
[ DependsOn = [string[]] ]
[ ValueData = [string[]] ]
[ ValueType = [string] { Binary | Dword | ExpandString | MultiString | Qword | String } ]
}
When defining the task, `` resource_name `` must be set to the DSC resource being
used - in this case the `` resource_name `` should be set to `` Registry `` . The
`` module_version `` can refer to a specific version of the DSC resource
installed; if left blank it will default to the latest version. The other
options are parameters that are used to define the resource, such as `` Key `` and
`` ValueName `` . While the options in the task are not case sensitive,
keeping the case as-is is recommended becuase it makes it easier to distinguish DSC
resource options from Ansible's `` win_dsc `` options.
2018-11-15 21:17:29 +00:00
This is what the Ansible task version of the above DSC Registry resource would look like:
.. code-block :: yaml+jinja
2017-10-13 01:40:47 +00:00
2018-11-15 21:17:29 +00:00
- name: Use win_dsc module with the Registry DSC resource
2017-10-13 01:40:47 +00:00
win_dsc:
resource_name: Registry
Ensure: Present
Key: HKEY_LOCAL_MACHINE\SOFTWARE\ExampleKey
ValueName: TestValue
ValueData: TestData
Property Types
--------------
Each DSC resource property has a type that is associated with it. Ansible
will try to convert the defined options to the correct type during execution.
For simple types like `` [string] `` and `` [bool] `` this is a simple operation,
but complex types like `` [PSCredential] `` or arrays (like `` [string[]] `` ) this
require certain rules.
PSCredential
++++++++++++
A `` [PSCredential] `` object is used to store credentials in a secure way, but
Ansible has no way to serialize this over JSON. To set a DSC PSCredential property,
the definition of that parameter should have two entries that are suffixed with
`` _username `` and `` _password `` for the username and password respectively.
2018-11-15 21:17:29 +00:00
For example:
2017-10-13 01:40:47 +00:00
2018-11-15 21:17:29 +00:00
.. code-block :: yaml+jinja
PsDscRunAsCredential_username: '{{ ansible_user }}'
PsDscRunAsCredential_password: '{{ ansible_password }}'
2017-10-13 01:40:47 +00:00
SourceCredential_username: AdminUser
SourceCredential_password: PasswordForAdminUser
2018-11-15 21:17:29 +00:00
.. Note :: You should set `` no_log: yes `` on the task definition in
2017-10-13 01:40:47 +00:00
Ansible to ensure any credentials used are not stored in any log file or
console output.
2017-11-09 00:02:17 +00:00
CimInstance Type
++++++++++++++++
A `` [CimInstance] `` object is used by DSC to store a dictionary object based on
a custom class defined by that resource. Defining a value that takes in a
`` [CimInstance] `` in YAML is the same as defining a dictionary in YAML.
2018-11-15 21:17:29 +00:00
For example, to define a `` [CimInstance] `` value in Ansible:
.. code-block :: yaml+jinja
2017-11-09 00:02:17 +00:00
# [CimInstance]AuthenticationInfo == MSFT_xWebAuthenticationInformation
2018-06-25 01:38:08 +00:00
AuthenticationInfo:
2017-11-09 00:02:17 +00:00
Anonymous: no
Basic: yes
Digest: no
Windows: yes
In the above example, the CIM instance is a representation of the class
`` MSFT_xWebAuthenticationInformation <https://github.com/PowerShell/xWebAdministration/blob/dev/DSCResources/MSFT_xWebsite/MSFT_xWebsite.schema.mof> ` ` _.
This class accepts four boolean variables, `` Anonymous `` , `` Basic `` ,
`` Digest `` , and `` Windows `` . The keys to use in a `` [CimInstance] `` depend on
the class it represents. Please read through the documentation of the resource
to determine the keys that can be used and the types of each key value. The
class definition is typically located in the `` <resource name>.schema.mof `` .
Arrays
++++++
Simple type arrays like `` [string[]] `` or `` [UInt32[]] `` are defined as a list
or as a comma separated string which are then cast to their type. Using a list
is recommended because the values are not manually parsed by the `` win_dsc ``
module before being passed to the DSC engine. For example, to define a simple
2018-11-15 21:17:29 +00:00
type array in Ansible:
.. code-block :: yaml+jinja
2017-10-13 01:40:47 +00:00
# [string[]]
ValueData: entry1, entry2, entry3
2017-11-09 00:02:17 +00:00
ValueData:
- entry1
- entry2
- entry3
2017-10-13 01:40:47 +00:00
# [UInt32[]]
ReturnCode: 0,3010
2017-11-09 00:02:17 +00:00
ReturnCode:
- 0
- 3010
Complex type arrays like `` [CimInstance[]] `` (array of dicts), can be defined
2018-11-15 21:17:29 +00:00
like this example:
.. code-block :: yaml+jinja
2017-11-09 00:02:17 +00:00
# [CimInstance[]]BindingInfo == MSFT_xWebBindingInformation
BindingInfo:
- Protocol: https
Port: 443
CertificateStoreName: My
CertificateThumbprint: C676A89018C4D5902353545343634F35E6B3A659
HostName: DSCTest
IPAddress: '*'
SSLFlags: 1
- Protocol: http
Port: 80
IPAddress: '*'
The above example, is an array with two values of the class `` MSFT_xWebBindingInformation <https://github.com/PowerShell/xWebAdministration/blob/dev/DSCResources/MSFT_xWebsite/MSFT_xWebsite.schema.mof> ` ` _.
When defining a `` [CimInstance[]] `` , be sure to read the resource documentation
to find out what keys to use in the definition.
2017-10-13 01:40:47 +00:00
Run As Another User
-------------------
By default, DSC runs each resource as the SYSTEM account and not the account
that Ansible use to run the module. This means that resources that are dynamically
loaded based on a user profile, like the `` HKEY_CURRENT_USER `` registry hive,
will be loaded under the `` SYSTEM `` profile. The parameter
`PsDscRunAsCredential` ` is a parameter that can be set for every DSC resource
force the DSC engine to run under a different account. As
`` PsDscRunAsCredential `` has a type of `` PSCredential `` , it is defined with the
`` _username `` and `` _password `` suffix.
Using the Registry resource type as an example, this is how to define a task
2018-11-15 21:17:29 +00:00
to access the `` HKEY_CURRENT_USER `` hive of the Ansible user:
.. code-block :: yaml+jinja
2017-10-13 01:40:47 +00:00
2018-11-15 21:17:29 +00:00
- name: Use win_dsc with PsDscRunAsCredential to run as a different user
2017-10-13 01:40:47 +00:00
win_dsc:
resource_name: Registry
Ensure: Present
Key: HKEY_CURRENT_USER\ExampleKey
ValueName: TestValue
ValueData: TestData
2018-11-15 21:17:29 +00:00
PsDscRunAsCredential_username: '{{ ansible_user }}'
PsDscRunAsCredential_password: '{{ ansible_password }}'
no_log: yes
2017-10-13 01:40:47 +00:00
Custom DSC Resources
`` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ``
DSC resources are not limited to the built-in options from Microsoft. Custom
modules can be installed to manage other resources that are not usually available.
Finding Custom DSC Resources
----------------------------
You can use the
`PSGallery <https://www.powershellgallery.com/> `_ to find custom resources, along with documentation on how to install them on a Windows host.
The `` Find-DscResource `` cmdlet can also be used to find custom resources. For example:
.. code-block :: powershell
2018-11-15 21:17:29 +00:00
# Find all DSC resources in the configured repositories
2017-10-13 01:40:47 +00:00
Find-DscResource
2018-11-15 21:17:29 +00:00
# Find all DSC resources that relate to SQL
2017-10-13 01:40:47 +00:00
Find-DscResource -ModuleName "*sql* "
.. Note :: DSC resources developed by Microsoft that start with `` x `` , means the
resource is experimental and comes with no support.
Installing a Custom Resource
----------------------------
There are three ways that a DSC resource can be installed on a host:
* Manually with the `` Install-Module `` cmdlet
* Using the `` win_psmodule `` Ansible module
* Saving the module manually and copying it another host
This is an example of installing the `` xWebAdministration `` resources using
2018-11-15 21:17:29 +00:00
`` win_psmodule `` :
2017-10-13 01:40:47 +00:00
2018-11-15 21:17:29 +00:00
.. code-block :: yaml+jinja
- name: Install xWebAdministration DSC resource
2017-10-13 01:40:47 +00:00
win_psmodule:
name: xWebAdministration
state: present
Once installed, the win_dsc module will be able to use the resource by referencing it
with the `` resource_name `` option.
The first two methods above only work when the host has access to the internet.
When a host does not have internet access, the module must first be installed
using the methods above on another host with internet access and then copied
across. To save a module to a local filepath, the following PowerShell cmdlet
2018-11-15 21:17:29 +00:00
can be run:
.. comment: Pygments powershell lexer does not support colons (i.e. URLs)
.. code-block :: guess
2017-10-13 01:40:47 +00:00
Save-Module -Name xWebAdministration -Path C:\temp
This will create a folder called `` xWebAdministration `` in `` C:\temp `` which
can be copied to any host. For PowerShell to see this offline resource, it must
be copied to a directory set in the `` PSModulePath `` environment variable.
In most cases the path `` C:\Program Files\WindowsPowerShell\Module `` is set
through this variable, but the `` win_path `` module can be used to add different
paths.
Examples
`` ` ` ` ` ``
Extract a zip file
------------------
2018-11-15 21:17:29 +00:00
.. code-block :: yaml+jinja
2017-10-13 01:40:47 +00:00
2018-11-15 21:17:29 +00:00
- name: Extract a zip file
2017-10-13 01:40:47 +00:00
win_dsc:
resource_name: Archive
2018-11-15 21:17:29 +00:00
Destination: C:\temp\output
2017-10-13 01:40:47 +00:00
Path: C:\temp\zip.zip
Ensure: Present
Create a directory
------------------
2018-11-15 21:17:29 +00:00
.. code-block :: yaml+jinja
2017-10-13 01:40:47 +00:00
2018-11-15 21:17:29 +00:00
- name: Create file with some text
2017-10-13 01:40:47 +00:00
win_dsc:
resource_name: File
DestinationPath: C:\temp\file
Contents: |
Hello
World
Ensure: Present
Type: File
2018-11-15 21:17:29 +00:00
- name: Create directory that is hidden is set with the System attribute
2017-10-13 01:40:47 +00:00
win_dsc:
resource_name: File
DestinationPath: C:\temp\hidden-directory
Attributes: Hidden,System
Ensure: Present
Type: Directory
Interact with Azure
-------------------
2018-11-15 21:17:29 +00:00
.. code-block :: yaml+jinja
2017-10-13 01:40:47 +00:00
2018-11-15 21:17:29 +00:00
- name: Install xAzure DSC resources
2017-10-13 01:40:47 +00:00
win_psmodule:
name: xAzure
state: present
2018-11-15 21:17:29 +00:00
- name: Create virtual machine in Azure
2017-10-13 01:40:47 +00:00
win_dsc:
resource_name: xAzureVM
ImageName: a699494373c04fc0bc8f2bb1389d6106__Windows-Server-2012-R2-201409.01-en.us-127GB.vhd
Name: DSCHOST01
ServiceName: ServiceName
StorageAccountName: StorageAccountName
InstanceSize: Medium
2018-11-15 21:17:29 +00:00
Windows: yes
2017-10-13 01:40:47 +00:00
Ensure: Present
2018-11-15 21:17:29 +00:00
Credential_username: '{{ ansible_user }}'
Credential_password: '{{ ansible_password }}'
2017-10-13 01:40:47 +00:00
Setup IIS Website
-----------------
2018-11-15 21:17:29 +00:00
.. code-block :: yaml+jinja
2017-10-13 01:40:47 +00:00
2018-11-15 21:17:29 +00:00
- name: Install xWebAdministration module
2017-10-13 01:40:47 +00:00
win_psmodule:
name: xWebAdministration
state: present
2018-11-15 21:17:29 +00:00
- name: Install IIS features that are required
2017-10-13 01:40:47 +00:00
win_dsc:
resource_name: WindowsFeature
2018-11-15 21:17:29 +00:00
Name: '{{ item }}'
2017-10-13 01:40:47 +00:00
Ensure: Present
2018-10-16 20:53:22 +00:00
loop:
2017-10-13 01:40:47 +00:00
- Web-Server
- Web-Asp-Net45
2018-11-15 21:17:29 +00:00
- name: Setup web content
2017-10-13 01:40:47 +00:00
win_dsc:
resource_name: File
DestinationPath: C:\inetpub\IISSite\index.html
Type: File
Contents: |
<html>
<head><title>IIS Site</title></head>
<body>This is the body</body>
</html>
Ensure: present
2017-11-09 00:02:17 +00:00
2018-11-15 21:17:29 +00:00
- name: Create new website
2017-10-13 01:40:47 +00:00
win_dsc:
resource_name: xWebsite
Name: NewIISSite
State: Started
PhysicalPath: C:\inetpub\IISSite\index.html
2017-11-09 00:02:17 +00:00
BindingInfo:
- Protocol: https
Port: 8443
CertificateStoreName: My
CertificateThumbprint: C676A89018C4D5902353545343634F35E6B3A659
HostName: DSCTest
IPAddress: '*'
SSLFlags: 1
- Protocol: http
Port: 8080
IPAddress: '*'
AuthenticationInfo:
Anonymous: no
Basic: yes
Digest: no
Windows: yes
2017-10-13 01:40:47 +00:00
.. seealso ::
:doc: `index`
The documentation index
:doc: `playbooks`
An introduction to playbooks
:doc: `playbooks_best_practices`
Best practices advice
2018-09-13 17:38:49 +00:00
:ref: `List of Windows Modules <windows_modules>`
2017-10-13 01:40:47 +00:00
Windows specific module list, all implemented in PowerShell
2018-07-21 13:48:47 +00:00
`User Mailing List <https://groups.google.com/group/ansible-project> `_
2017-10-13 01:40:47 +00:00
Have a question? Stop by the google group!
`irc.freenode.net <http://irc.freenode.net> `_
#ansible IRC chat channel