Ansible: Creating Windows Service With win_service Module

Issue : Service does not start after service creation. Fails with message - Error 1069: The service did not start due to a logon failure

Introduction

My project had a requirement to create services on a windows server with Ansible. I was given with the service name, the executable location and the service account details (username and password) to create the service. So lets see how I managed to get it working.

Firstly, googling for Windows Service Management with Ansible got me excited when I saw the win_service module.

Creating a Service With win_service Module

Here is an example playbook for creating a service.

- hosts: all
  tasks:
  - name: Set the log on user to a domain account
    win_service:
     name: "{{servcename}}"
     path: C:\temp\test.exe
     state: started
     username: AD1\Myname
     password: 'mypass'

But hold on! Really? Hard coded passwords? No way!! Lets put it in a vault.

Ansible Vault for Storing the Credentials

Ansible vault can be used to store user credentials securely by encrypting it in a file.

Create a file vault.yml file to store the user credentials.

$ vi vault.yml
---
username: AD1\Name
password: mypass

Use the ansible-vault command to encrypt it.

$ansible-vault encrypt vault.yml
Vault password: ******
Confirm password: ******

Provide a password when prompted and create a new credential with this password  in the Ansible Tower and include the vault in the job template credential.

Ansible Tower credential

Now that we have the credentials in our vault, include it into the playbook.

- hosts: all
  tasks:
  - include_vars: "vault/vault.yml"
    no_log: true
  - name: Set the log on user to a domain account
    win_service:
     name: "{{servcename}}"
     path: C:\temp\test.exe
     state: started
     username: '{{username}}'
     password: '{{password}}'

All set now! I ran the playbook and noticed it failed. The service did not start up. Logging into the server and an attempt to start the service manually also failed with the error - "Error 1069: The service did not start due to a logon failure."

Logon failure

As the error showed logon failure, I presumed the problem could be related to password. Lets add a debug statement in the playbook.

- debug: 
   msg: "{{ password }}"
   

The output proved that there is nothing wrong with the password. I even tried to hard code the password in the win_service module which didn't work either.

Well, then the issue might be with the win_service module. Lets create the service with win_service Ansible module and feed the password via powershell.

  - name: Set the log on user to a domain account
    win_service:
     name: "{{servcename}}"
     path: C:\temp\test.exe
     state: started
  - name: Set the service account credentials
    win_shell: Get-CimInstance win32_service -Filter 'Name="{{servcename}}"' | Invoke-CimMethod -MethodName Change -Arguments @{StarName='{{username}}';StartPassword='{{password}}'}
    

Fingers crossed, ran the playbook again. But still the same issue, the service didn't start.

I thought to manually add the password in the service which worked perfectly. Later I deleted the service and ran my playbooks again to re-create the service. To my surprise this time it ran successfully.

This concludes the issue is neither with the passwords nor the win_service module.

Logon as a Service Right

Then it clicked to me, while providing the passwords manually, after clicking on apply, I got the below message that states 'Account has been granted the Log on as a service right' as seen in the below screenshot.

So I came to a realization that it might be an issue with the user not having proper permissions. Providing credentials manually gives the user Logon as a Service right as well, which doesn't happen with the win_service module.

Once I gave the right to the user manually, it works via playbook as well. I digged deeper and found that the user must be given Logon as a Service right to start a service. Voila, we have an Ansible module for setting user rights - win_user_right

Playbook to set Logon as a Service to a user

- name: Add account to Log on as a service
  win_user_right:
    name: SeServiceLogonRight
    users: "{{username}}"
 

Finally it worked!!

The error stated Logon failure which was misleading. If it was shown as 'No logon as service right for user' or anything related to user rights it would have been much easeier for troubleshooting.

Here is the final working playbook.

- hosts: all
  tasks:
  - include_vars: "vault/vault.yml"
    no_log: true
  - name: Add account to Log on as a service
    win_user_right:
     name: SeServiceLogonRight
     users: "{{username}}"
  - name: Set the log on user to a domain account
    win_service:
     name: "{{servcename}}"
     path: C:\temp\test.exe
     state: started
     username: '{{username}}'
     password: '{{password}}'

Conclusion

In this article, we saw how a small, silly, generic error message misguided us. But at the end, a very important lesson learned! If something is not working, be suspicious of everything! :)

Vipin

Vipin

I am a dreamer. I admire the web. I admire anything about the web.