{"id":400512,"date":"2024-06-29T15:18:52","date_gmt":"2024-06-29T15:18:52","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=400512"},"modified":"-0001-11-30T00:00:00","modified_gmt":"2024-06-29T15:18:52","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=400512","title":{"rendered":"<span>\u00abNo Windows no problems\u00bb What?<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/ccb\/2a9\/674\/ccb2a9674eb4ca892a8c68916d1e2744.png\" width=\"500\" height=\"694\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/ccb\/2a9\/674\/ccb2a9674eb4ca892a8c68916d1e2744.png\"\/><figcaption><\/figcaption><\/figure>\n<p>Hi, My name is Alex and I am a DevOps engineer at Altenar. \u201cNo Windows, no problems.\u201d &#8212; that is the answer I got by asking a guru of Ansible &#171;How do you manage Windows?&#187; on one of the local Ansible meetups. Although we have been running a modern stack (k8s, helm, .net core, etc) in production for about two years, that\u2019s not how it has always been. <\/p>\n<p>Our first version of Sportsbook was Windows-based (.NET + MSSQL)<strong> <\/strong>and we managed 100+ servers via Ansible. In this article, I would like to share some insights we learned through years of managing Windows infrastructure via Ansible. \u00a0<\/p>\n<hr\/>\n<h2>Prepare servers for Ansible<\/h2>\n<p>Unlike Linux, Windows requires you to prepare for Ansible to connect to it (more details available <a href=\"https:\/\/docs.ansible.com\/ansible\/latest\/user_guide\/windows_setup.html#winrm-setup\" rel=\"noopener noreferrer nofollow\"><u>here<\/u><\/a> and all the details are out of the scope of this article). However, there is one key point I would like to stress here. The <code>ConfigureRemotingForAnsible.ps1<\/code> script &#8212; that is pretty much what you need to run before you&#8217;ll be able to connect to a VM via Ansible.  <\/p>\n<p>It&#8217;s worth mentioning that we use Terraform for VM provisioning and this is where<a href=\"https:\/\/registry.terraform.io\/providers\/hashicorp\/vsphere\/latest\/docs\/resources\/virtual_machine#run_once_command_list\" rel=\"noopener noreferrer nofollow\"> <u>run_once_command_list<\/u><\/a> becomes very handy. We saved <code>ConfigureRemotingForAnsible.ps1<\/code> on the <code>C:\/<\/code> of the base VM template and used the following option in Terraform:   <\/p>\n<pre><code class=\"haskell\">resource \"vsphere_virtual_machine\" \"vm\" {   # ... other configuration ...    clone {     # ... other configuration ...      customize {       # ... other configuration ...        windows_options {         computer_name         = \"${lower(var.envname)}${var.vmname}${format(\"%03d\", count.index)}\"         organization_name     = \"Altenar\"         join_domain           = \"${var.domain}\"         domain_admin_user     = \"${var.domain_user}\"         domain_admin_password = \"${var.domain_password}\"         admin_password        = \"${var.admin_password}\"         auto_logon            = true          run_once_command_list = [     \"powershell.exe -version 4 -ExecutionPolicy Bypass -File C:\\\\ConfigureRemotingForAnsible.ps1\", ]       }     }   } } <\/code><\/pre>\n<p>Once a new server is provisioned it is ready to be set up by Ansible according to the role we assign to the server.  <\/p>\n<h2>Setting up Ansible<\/h2>\n<p>From the Ansible side, a few initial preparations are also required.<\/p>\n<ol>\n<li>\n<p>Make sure all Windows servers belong to the &#171;Windows&#187; group in your inventory, we use groups but you can list each server individually here or automate the inventory creation process. Inventory management is out of this article scope, but it is well described in<a href=\"https:\/\/docs.ansible.com\/ansible\/latest\/user_guide\/intro_inventory.html\" rel=\"noopener noreferrer nofollow\"> <u>Ansible documentation<\/u><\/a>: <\/p>\n<pre><code>[windows:children] frontend client_api backoffice<\/code><\/pre>\n<\/li>\n<li>\n<p>Create<code> windows.yaml<\/code> file in <em>group_vars <\/em>folder of each environment and\/or in the main <em>group_vars <\/em>folder and add the following content:<\/p>\n<pre><code>ansible_user: \"{{ windows_user|default ('Administrator') }}\" ansible_password: \"{{ windows_password }}\" ansible_port: 5986 ansible_connection: winrm ansible_winrm_transport: credssp<\/code><\/pre>\n<\/li>\n<li>\n<p>Include<a href=\"https:\/\/github.com\/movergan\/fetch-credentials\" rel=\"noopener noreferrer nofollow\"> <u>this<\/u><\/a> role as dependent into the <code>meta\/main.yaml<\/code> file of any of the roles you are planning to execute, for instance:  <\/p>\n<pre><code class=\"json\"># cat roles\/infra\/IIS\/meta\/main.yml --- dependencies:   - { role: infra\/fetch-credentials\/windows } <\/code><\/pre>\n<p>This role checks appropriate environment variables and fails if a Username or Password is not provided. These environment variables are then copied to Ansible variables and used in the settings we defined in p2. <\/p>\n<\/li>\n<li>\n<p>At this time, we have our servers configured and Ansible set up. We are good to go, the only thing left is actually setting up Windows username and password.  <\/p>\n<ol>\n<li>\n<p>You can do it using export WINDOWS_USERNAMEand export WINDOWS_PASSWORD commands:  <\/p>\n<pre><code>export WINDOWS_USERNAME=Administrator export WINDOWS_PASSWORD=******<\/code><\/pre>\n<\/li>\n<li>\n<p>or if you have more than one set of credentials you can use a small <a href=\"https:\/\/github.com\/movergan\/fetch-credentials\/blob\/master\/set_env.sh\" rel=\"noopener noreferrer nofollow\">bash script-helper<\/a>:<\/p>\n<pre><code class=\"bash\"># source set_env.sh Set Value for WINDOWS_DOMAIN_USER: Administrator Set Value for WINDOWS_DOMAIN_PASSWORD: Set Value for WINDOWS_USER: Administrator Set Value for WINDOWS_PASSWORD:<\/code><\/pre>\n<\/li>\n<\/ol>\n<\/li>\n<\/ol>\n<p>Our preparations are done. We are ready to start Ansibling. <\/p>\n<h2>Windows tips and tricks<\/h2>\n<p>Ansible has much fewer modules for Windows than for Linux. There are 104 modules for <strong>windows<\/strong> out of 2832 in total yet it is enough for most of the common cases.  But sometimes we have to be creative. <\/p>\n<p><strong>DSL is your friend<\/strong><\/p>\n<p>The first thing to remember &#8212; DSL is your friend. There are many <a href=\"https:\/\/www.powershellgallery.com\/packages\" rel=\"noopener noreferrer nofollow\">DSL modules<\/a> for <strong>windows<\/strong>, for example using <a href=\"https:\/\/github.com\/dsccommunity\/SqlServerDsc\" rel=\"noopener noreferrer nofollow\">this module<\/a> you can install MSSQL by just one task:<\/p>\n<pre><code class=\"javascript\">- name: Configure SqlSetup   win_dsc:     resource_name: SqlSetup     ForceReboot: False     UpdateEnabled: False     SourcePath: \"{{ disk_image_out.mount_path|default(database_settings.mssql_installation_source) }}\"     InstanceName: \"{{ db_settings.instance_name|upper }}\"     Features: \"{{ sql_setup_components }}\"     InstallSharedDir: \"{{ db_settings.instance_dir_drive }}Program Files\\\\Microsoft SQL Server\"     InstallSharedWOWDir: \"{{ db_settings.instance_dir_drive }}Program Files (x86)\\\\Microsoft SQL Server\"     InstanceDir: \"{{ db_settings.instance_dir_drive }}SQL\"     SQLCollation: 'Latin1_General_CI_AS'     SQLSvcAccount_username: \"{{ ad_settings_domain }}\\\\{{ db_settings.sqlsvcaccount }}$\"     SQLSvcAccount_password: '***'     AgtSvcAccount_username: \"{{ ad_settings_domain }}\\\\{{ db_settings.agtsvcaccount }}$\"     AgtSvcAccount_password: '***'     SQLSysAdminAccounts: \"{{ ad_settings_domain|upper }}\\\\SQL Administrators\"     InstallSQLDataDir:  \"{{db_settings.data_dir_drive}}SQL\\\\{{ db_settings.instance_name|upper }}\\\\MSSQL\\\\Data\"     SQLUserDBDir:       \"{{db_settings.data_dir_drive}}SQL\\\\{{ db_settings.instance_name|upper }}\\\\MSSQL\\\\Data\"     SQLUserDBLogDir:    \"{{db_settings.log_dir_drive }}SQL\\\\{{ db_settings.instance_name|upper }}\\\\MSSQL\\\\Log\"     SQLTempDBDir:       \"{{db_settings.temp_dir_drive}}SQL\\\\{{ db_settings.instance_name|upper }}\\\\MSSQL\\\\Data\\\\Tempdb\"     SQLTempDBLogDir:    \"{{db_settings.temp_dir_drive}}SQL\\\\{{ db_settings.instance_name|upper }}\\\\MSSQL\\\\Log\\\\Tempdb\"     SQLBackupDir:       \"{{db_settings.backup_dir_drive}}SQL\\\\{{ db_settings.instance_name|upper }}\\\\MSSQL\\\\Backup\"     PsDscRunAsCredential_username: \"{{ad_settings_adminuser}}@{{ad_settings_domain}}\"     PsDscRunAsCredential_password: \"{{ad_settings_adminpassword}}\"   tags:   - install_db<\/code><\/pre>\n<p>Use the <a href=\"https:\/\/docs.ansible.com\/ansible\/latest\/collections\/community\/windows\/win_psmodule_module.html\" rel=\"noopener noreferrer nofollow\">win_psmodule<\/a> first to install the required DSC modules on the server first:<\/p>\n<pre><code>- name: install DSC Modules   win_psmodule:     name: \"{{ item }}\"     state: present   with_items:     - \"PSDesiredStateConfiguration\"     - \"SqlServerDsc\"     - \"ServerManager\"     - \"StorageDsc\"     - \"ComputerManagementDsc\"<\/code><\/pre>\n<p>Another big advantage of DSC is that you can run it as a different user, you could&#8217;ve spotted &#171;<em>PsDscRunAsCredential_username<\/em>&#187; and &#171;<em>PsDscRunAsCredential_password<\/em>&#187; directives on the example above. It especially helps when some tasks have to be run from the Domain Administrator account. <\/p>\n<p><strong>DIY modules<\/strong><\/p>\n<p>Didn&#8217;t find an appropriate DSC module? Not a big deal, there are two possible workarounds (apart from the obvious &#8212; using <em>win_shell <\/em>ansible module):<\/p>\n<ol>\n<li>\n<p>Use DSC resource &#171;<a href=\"https:\/\/docs.microsoft.com\/en-us\/powershell\/scripting\/dsc\/reference\/resources\/windows\/scriptresource?view=powershell-7.1\" rel=\"noopener noreferrer nofollow\">Script<\/a>&#171;:<\/p>\n<pre><code>#Part of MSSQL setup playbook. Here we test if created service accounts  #have already been added to the server from AD #if not, we reboot the servers first. - name: Configure and Test the gMSA account   win_dsc:     resource_name: Script     GetScript: \"@{ Result = '{{ item }}'| Use-ServiceAccount -Test }\"     TestScript: \"(iwr https:\/\/raw.githubusercontent.com\/beatcracker\/Powershell-Misc\/master\/Use-ServiceAccount.ps1 -UseBasicParsing).Content | iex; '{{ item }}'| Use-ServiceAccount -Test\"     SetScript: '$global:DSCMachineStatus = 1'     PsDscRunAsCredential_username: \"{{ad_settings_adminuser}}@{{ad_settings_domain}}\"     PsDscRunAsCredential_password: \"{{ad_settings_adminpassword}}\"   with_items:     - \"{{ db_settings.sqlsvcaccount }}\"     - \"{{ db_settings.agtsvcaccount }}\"   register: TestADServiceAccount_result<\/code><\/pre>\n<p>Ansible is an imperative tool, so we have to make sure that any task can be executed multiple times providing us with the same result. Play with &#171;GetScrypt&#187;, &#171;TestScrypt&#187; and &#171;SetScrypt&#187; fields according to your needs. Having it played right should allow you to be able to identify the current state of the resource, change it if required and pass if not. <\/p>\n<\/li>\n<li>\n<p>Create a module yourself. It&#8217;s not that hard, the only difference with making a module for Linux is you need to write code on PowerShell. We encountered a problem where there was no module KDS Root Key creation which is<a href=\"https:\/\/techcommunity.microsoft.com\/t5\/itops-talk-blog\/step-by-step-how-to-work-with-group-managed-service-accounts\/ba-p\/329864\" rel=\"noopener noreferrer nofollow\"> <u>required for MSSQL<\/u><\/a> installation. So we<a href=\"https:\/\/github.com\/movergan\/win_kdsrootkey\" rel=\"noopener noreferrer nofollow\"> <u>created it<\/u><\/a>. Look<a href=\"https:\/\/docs.ansible.com\/ansible\/latest\/dev_guide\/developing_modules_general_windows.html\" rel=\"noopener noreferrer nofollow\"> <u>here<\/u><\/a><u> <\/u>for more details regarding win module development.   <\/p>\n<\/li>\n<\/ol>\n<h2>Conclusion<\/h2>\n<p>I&#8217;ve provided the key aspects related to Ansible usage with Windows. Having Windows servers configured for Ansible we can manage them nearly the same way as we manage Linux servers using Ansible. By using the approaches described in this article we successfully manage Windows servers for jobs like:<\/p>\n<ul>\n<li>\n<p>MSSQL AG cluster installation and update.<\/p>\n<\/li>\n<li>\n<p>IIS configuration.<\/p>\n<\/li>\n<li>\n<p>Windows services failover cluster configuration.<\/p>\n<\/li>\n<li>\n<p>A\/B deployment.<\/p>\n<\/li>\n<\/ul>\n<p>I hope it was useful or at least entertaining.<\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/558766\/\"> https:\/\/habr.com\/ru\/articles\/558766\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<figure class=\"\"><figcaption><\/figcaption><\/figure>\n<p>Hi, My name is Alex and I am a DevOps engineer at Altenar. \u201cNo Windows, no problems.\u201d &#8212; that is the answer I got by asking a guru of Ansible &#171;How do you manage Windows?&#187; on one of the local Ansible meetups. Although we have been running a modern stack (k8s, helm, .net core, etc) in production for about two years, that\u2019s not how it has always been. <\/p>\n<p>Our first version of Sportsbook was Windows-based (.NET + MSSQL)<strong> <\/strong>and we managed 100+ servers via Ansible. In this article, I would like to share some insights we learned through years of managing Windows infrastructure via Ansible. \u00a0<\/p>\n<hr\/>\n<h2>Prepare servers for Ansible<\/h2>\n<p>Unlike Linux, Windows requires you to prepare for Ansible to connect to it (more details available <a href=\"https:\/\/docs.ansible.com\/ansible\/latest\/user_guide\/windows_setup.html#winrm-setup\" rel=\"noopener noreferrer nofollow\"><u>here<\/u><\/a> and all the details are out of the scope of this article). However, there is one key point I would like to stress here. The <code>ConfigureRemotingForAnsible.ps1<\/code> script &#8212; that is pretty much what you need to run before you&#8217;ll be able to connect to a VM via Ansible.  <\/p>\n<p>It&#8217;s worth mentioning that we use Terraform for VM provisioning and this is where<a href=\"https:\/\/registry.terraform.io\/providers\/hashicorp\/vsphere\/latest\/docs\/resources\/virtual_machine#run_once_command_list\" rel=\"noopener noreferrer nofollow\"> <u>run_once_command_list<\/u><\/a> becomes very handy. We saved <code>ConfigureRemotingForAnsible.ps1<\/code> on the <code>C:\/<\/code> of the base VM template and used the following option in Terraform:   <\/p>\n<pre><code class=\"haskell\">resource \"vsphere_virtual_machine\" \"vm\" {   # ... other configuration ...    clone {     # ... other configuration ...      customize {       # ... other configuration ...        windows_options {         computer_name         = \"${lower(var.envname)}${var.vmname}${format(\"%03d\", count.index)}\"         organization_name     = \"Altenar\"         join_domain           = \"${var.domain}\"         domain_admin_user     = \"${var.domain_user}\"         domain_admin_password = \"${var.domain_password}\"         admin_password        = \"${var.admin_password}\"         auto_logon            = true          run_once_command_list = [     \"powershell.exe -version 4 -ExecutionPolicy Bypass -File C:\\\\ConfigureRemotingForAnsible.ps1\", ]       }     }   } } <\/code><\/pre>\n<p>Once a new server is provisioned it is ready to be set up by Ansible according to the role we assign to the server.  <\/p>\n<h2>Setting up Ansible<\/h2>\n<p>From the Ansible side, a few initial preparations are also required.<\/p>\n<ol>\n<li>\n<p>Make sure all Windows servers belong to the &#171;Windows&#187; group in your inventory, we use groups but you can list each server individually here or automate the inventory creation process. Inventory management is out of this article scope, but it is well described in<a href=\"https:\/\/docs.ansible.com\/ansible\/latest\/user_guide\/intro_inventory.html\" rel=\"noopener noreferrer nofollow\"> <u>Ansible documentation<\/u><\/a>: <\/p>\n<pre><code>[windows:children] frontend client_api backoffice<\/code><\/pre>\n<\/li>\n<li>\n<p>Create<code> windows.yaml<\/code> file in <em>group_vars <\/em>folder of each environment and\/or in the main <em>group_vars <\/em>folder and add the following content:<\/p>\n<pre><code>ansible_user: \"{{ windows_user|default ('Administrator') }}\" ansible_password: \"{{ windows_password }}\" ansible_port: 5986 ansible_connection: winrm ansible_winrm_transport: credssp<\/code><\/pre>\n<\/li>\n<li>\n<p>Include<a href=\"https:\/\/github.com\/movergan\/fetch-credentials\" rel=\"noopener noreferrer nofollow\"> <u>this<\/u><\/a> role as dependent into the <code>meta\/main.yaml<\/code> file of any of the roles you are planning to execute, for instance:  <\/p>\n<pre><code class=\"json\"># cat roles\/infra\/IIS\/meta\/main.yml --- dependencies:   - { role: infra\/fetch-credentials\/windows } <\/code><\/pre>\n<p>This role checks appropriate environment variables and fails if a Username or Password is not provided. These environment variables are then copied to Ansible variables and used in the settings we defined in p2. <\/p>\n<\/li>\n<li>\n<p>At this time, we have our servers configured and Ansible set up. We are good to go, the only thing left is actually setting up Windows username and password.  <\/p>\n<ol>\n<li>\n<p>You can do it using export WINDOWS_USERNAMEand export WINDOWS_PASSWORD commands:  <\/p>\n<pre><code>export WINDOWS_USERNAME=Administrator export WINDOWS_PASSWORD=******<\/code><\/pre>\n<\/li>\n<li>\n<p>or if you have more than one set of credentials you can use a small <a href=\"https:\/\/github.com\/movergan\/fetch-credentials\/blob\/master\/set_env.sh\" rel=\"noopener noreferrer nofollow\">bash script-helper<\/a>:<\/p>\n<pre><code class=\"bash\"># source set_env.sh Set Value for WINDOWS_DOMAIN_USER: Administrator Set Value for WINDOWS_DOMAIN_PASSWORD: Set Value for WINDOWS_USER: Administrator Set Value for WINDOWS_PASSWORD:<\/code><\/pre>\n<\/li>\n<\/ol>\n<\/li>\n<\/ol>\n<p>Our preparations are done. We are ready to start Ansibling. <\/p>\n<h2>Windows tips and tricks<\/h2>\n<p>Ansible has much fewer modules for Windows than for Linux. There are 104 modules for <strong>windows<\/strong> out of 2832 in total yet it is enough for most of the common cases.  But sometimes we have to be creative. <\/p>\n<p><strong>DSL is your friend<\/strong><\/p>\n<p>The first thing to remember &#8212; DSL is your friend. There are many <a href=\"https:\/\/www.powershellgallery.com\/packages\" rel=\"noopener noreferrer nofollow\">DSL modules<\/a> for <strong>windows<\/strong>, for example using <a href=\"https:\/\/github.com\/dsccommunity\/SqlServerDsc\" rel=\"noopener noreferrer nofollow\">this module<\/a> you can install MSSQL by just one task:<\/p>\n<pre><code class=\"javascript\">- name: Configure SqlSetup   win_dsc:     resource_name: SqlSetup     ForceReboot: False     UpdateEnabled: False     SourcePath: \"{{ disk_image_out.mount_path|default(database_settings.mssql_installation_source) }}\"     InstanceName: \"{{ db_settings.instance_name|upper }}\"     Features: \"{{ sql_setup_components }}\"     InstallSharedDir: \"{{ db_settings.instance_dir_drive }}Program Files\\\\Microsoft SQL Server\"     InstallSharedWOWDir: \"{{ db_settings.instance_dir_drive }}Program Files (x86)\\\\Microsoft SQL Server\"     InstanceDir: \"{{ db_settings.instance_dir_drive }}SQL\"     SQLCollation: 'Latin1_General_CI_AS'     SQLSvcAccount_username: \"{{ ad_settings_domain }}\\\\{{ db_settings.sqlsvcaccount }}$\"     SQLSvcAccount_password: '***'     AgtSvcAccount_username: \"{{ ad_settings_domain }}\\\\{{ db_settings.agtsvcaccount }}$\"     AgtSvcAccount_password: '***'     SQLSysAdminAccounts: \"{{ ad_settings_domain|upper }}\\\\SQL Administrators\"     InstallSQLDataDir:  \"{{db_settings.data_dir_drive}}SQL\\\\{{ db_settings.instance_name|upper }}\\\\MSSQL\\\\Data\"     SQLUserDBDir:       \"{{db_settings.data_dir_drive}}SQL\\\\{{ db_settings.instance_name|upper }}\\\\MSSQL\\\\Data\"     SQLUserDBLogDir:    \"{{db_settings.log_dir_drive }}SQL\\\\{{ db_settings.instance_name|upper }}\\\\MSSQL\\\\Log\"     SQLTempDBDir:       \"{{db_settings.temp_dir_drive}}SQL\\\\{{ db_settings.instance_name|upper }}\\\\MSSQL\\\\Data\\\\Tempdb\"     SQLTempDBLogDir:    \"{{db_settings.temp_dir_drive}}SQL\\\\{{ db_settings.instance_name|upper }}\\\\MSSQL\\\\Log\\\\Tempdb\"     SQLBackupDir:       \"{{db_settings.backup_dir_drive}}SQL\\\\{{ db_settings.instance_name|upper }}\\\\MSSQL\\\\Backup\"     PsDscRunAsCredential_username: \"{{ad_settings_adminuser}}@{{ad_settings_domain}}\"     PsDscRunAsCredential_password: \"{{ad_settings_adminpassword}}\"   tags:   - install_db<\/code><\/pre>\n<p>Use the <a href=\"https:\/\/docs.ansible.com\/ansible\/latest\/collections\/community\/windows\/win_psmodule_module.html\" rel=\"noopener noreferrer nofollow\">win_psmodule<\/a> first to install the required DSC modules on the server first:<\/p>\n<pre><code>- name: install DSC Modules   win_psmodule:     name: \"{{ item }}\"     state: present   with_items:     - \"PSDesiredStateConfiguration\"     - \"SqlServerDsc\"     - \"ServerManager\"     - \"StorageDsc\"     - \"ComputerManagementDsc\"<\/code><\/pre>\n<p>Another big advantage of DSC is that you can run it as a different user, you could&#8217;ve spotted &#171;<em>PsDscRunAsCredential_username<\/em>&#187; and &#171;<em>PsDscRunAsCredential_password<\/em>&#187; directives on the example above. It especially helps when some tasks have to be run from the Domain Administrator account. <\/p>\n<p><strong>DIY modules<\/strong><\/p>\n<p>Didn&#8217;t find an appropriate DSC module? Not a big deal, there are two possible workarounds (apart from the obvious &#8212; using <em>win_shell <\/em>ansible module):<\/p>\n<ol>\n<li>\n<p>Use DSC resource &#171;<a href=\"https:\/\/docs.microsoft.com\/en-us\/powershell\/scripting\/dsc\/reference\/resources\/windows\/scriptresource?view=powershell-7.1\" rel=\"noopener noreferrer nofollow\">Script<\/a>&#171;:<\/p>\n<pre><code>#Part of MSSQL setup playbook. Here we test if created service accounts  #have already been added to the server from AD #if not, we reboot the servers first. - name: Configure and Test the gMSA account   win_dsc:     resource_name: Script     GetScript: \"@{ Result = '{{ item }}'| Use-ServiceAccount -Test }\"     TestScript: \"(iwr https:\/\/raw.githubusercontent.com\/beatcracker\/Powershell-Misc\/master\/Use-ServiceAccount.ps1 -UseBasicParsing).Content | iex; '{{ item }}'| Use-ServiceAccount -Test\"     SetScript: '$global:DSCMachineStatus = 1'     PsDscRunAsCredential_username: \"{{ad_settings_adminuser}}@{{ad_settings_domain}}\"     PsDscRunAsCredential_password: \"{{ad_settings_adminpassword}}\"   with_items:     - \"{{ db_settings.sqlsvcaccount }}\"     - \"{{ db_settings.agtsvcaccount }}\"   register: TestADServiceAccount_result<\/code><\/pre>\n<p>Ansible is an imperative tool, so we have to make sure that any task can be executed multiple times providing us with the same result. Play with &#171;GetScrypt&#187;, &#171;TestScrypt&#187; and &#171;SetScrypt&#187; fields according to your needs. Having it played right should allow you to be able to identify the current state of the resource, change it if required and pass if not. <\/p>\n<\/li>\n<li>\n<p>Create a module yourself. It&#8217;s not that hard, the only difference with making a module for Linux is you need to write code on PowerShell. We encountered a problem where there was no module KDS Root Key creation which is<a href=\"https:\/\/techcommunity.microsoft.com\/t5\/itops-talk-blog\/step-by-step-how-to-work-with-group-managed-service-accounts\/ba-p\/329864\" rel=\"noopener noreferrer nofollow\"> <u>required for MSSQL<\/u><\/a> installation. So we<a href=\"https:\/\/github.com\/movergan\/win_kdsrootkey\" rel=\"noopener noreferrer nofollow\"> <u>created it<\/u><\/a>. Look<a href=\"https:\/\/docs.ansible.com\/ansible\/latest\/dev_guide\/developing_modules_general_windows.html\" rel=\"noopener noreferrer nofollow\"> <u>here<\/u><\/a><u> <\/u>for more details regarding win module development.   <\/p>\n<\/li>\n<\/ol>\n<h2>Conclusion<\/h2>\n<p>I&#8217;ve provided the key aspects related to Ansible usage with Windows. Having Windows servers configured for Ansible we can manage them nearly the same way as we manage Linux servers using Ansible. By using the approaches described in this article we successfully manage Windows servers for jobs like:<\/p>\n<ul>\n<li>\n<p>MSSQL AG cluster installation and update.<\/p>\n<\/li>\n<li>\n<p>IIS configuration.<\/p>\n<\/li>\n<li>\n<p>Windows services failover cluster configuration.<\/p>\n<\/li>\n<li>\n<p>A\/B deployment.<\/p>\n<\/li>\n<\/ul>\n<p>I hope it was useful or at least entertaining.<\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/558766\/\"> https:\/\/habr.com\/ru\/articles\/558766\/<\/a><br \/><\/br><\/br><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-400512","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/400512","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=400512"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/400512\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=400512"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=400512"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=400512"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}