Ansible Obtain thumbprint hash from local machine - ansible

Im trying to obtain the thumbprint from a localmachine's cert store so I can then use the variable of the hash to pass the thumbprint into an ssl_bindings task. So far I have this, but it returns a lot of data. Should I filter the data out or is there an easier way to get the thumbprint from an existing store? I've seen this done with powershell so I may just go that route if I cant figure this out.
- name: Obtain information about LocalMachines Cert Store
community.windows.win_certificate_info:
store_location: LocalMachine
register: cert

I ended up doing this. If anyone knows how to use the native ansible module to get the hash, that would be cool.
- name: Run powershell one-liner to get the thumbprint hash
ansible.windows.win_powershell:
script: |
(Get-ChildItem cert:\LocalMachine\My | where-object { $_.Subject -like "*$hostname*" } | Select-Object -Last 1).Thumbprint
register: hash
- name: Add an HTTPS binding to the website using the hash
win_iis_webbinding:
name: "{{ iis_site }}"
protocol: https
port: 443
certificate_hash: "{{ hash.output[0] }}"
state: present

Related

Pre VM Deployment checks in ansible

I have been trying for the past days to make a playbook to check for some things before ansible starts creating a new windows VM, I'm a junior engineer and just starting on the path of Ansible
I figured out the ping part but what I really want to know is if there's some way to check if the computer name is already registered in Active Directory and if it is the workflow should stop.
I am not sure if win_domain_computer can also just check.
Thanks
I think a powershell request is a way to do that.
In my playbook, we don't check name in Active Directory, but we check dns record
with a task, something similar with get-adcomputer should be ok.
Task dns example :
- block:
- name: Check dns record
win_shell: Get-DnsServerResourceRecord -ComputerName DNSSERVER -Name "{{ SERVERNAME }}" -ZoneName DNSZONE -RRType "A" -ErrorAction Ignore | select -ExpandProperty RecordData | select -ExpandProperty IPv4Address | select -Property IPAddressToString -ExpandProperty IPAddressToString
register: reg_dnscheck
changed_when: reg_dnscheck.rc == 1
failed_when: reg_dnscheck.rc > 1

ansible- checking for application installation in a task

can anyone assist with interrupting this code?
i need to pull out the variable output and test this
-can i pull out the var to a debug/msg?
also- im not sure if the with items is pulling the name of a host
that passed the check for the installation of application1
- name: check if application1 is installed if yes continue
win_shell: |
$application1 = ("","Wow6432Node: |ForEach-Object {Get-ChildItem HKLM:/SOFTWARE\$_\Microsoft\hostname }}"Windows\CurrentVersion\Uninstall\}
select#(n=Name;e={$.getvalue("displayname")}} Where {$. -like "*application1*"}).name.length -gt 0
with_items:"{{ hostname }}"
changed_when: false
ignore_errors: true
register: output
win_shell: echo output.stdout```

Need to fix the formatting issue in ansible - File from remote server

I am writing ansible code to update a DB table and output of the DB update is copied to a text file.
Fetching the contents of the file from remote server and displaying in ansible output. Having issue in formatting the table contents
Please find below the code.
win_shell: 'invoke-sqlcmd –ServerInstance {{ DBServer }} -Database {{ DBname }} -Query "{{ query2 }}" -ErrorAction Stop -QueryTimeout 65535 | Out-File -FilePath {{ log_path }}'
- name:
win_shell: cat "{{ log_path }}"
register: log_output
- name: Current DB vaules - Before deployment
debug:
msg: "{{log_output.stdout}}"
The Ansible output is displayed as
"msg": "\r\nCALCULATION THREAD_COUNT\r\n---------------------- -----------------------\r\n 4 96\r\n\r\n\r\n"
Need output exactly as it is in log file
CALCULATION THREAD_COUNT
---------------------- -----------------------
4 96
Query used
SELECT CALCULATION,THREAD_COUNT FROM CALCULATOR_DESC
Please suggest to produce a proper formatting when I run ansible code
You cannot control that, formatting is done by various callback plugins and using debug module is not as in doing a print() from your code. It is more like doing logging.info(msg).

Escaping slash in a win_regedit path on Ansible

I have the following inside a playbook of Ansible 2.3.0.0:
- name: Disable SSL2, SSL3, RC4. Activate TLS
win_regedit:
path: 'HKLM:\System\CurrentControlSet\Control\SecurityProviders\SCHANNEL\{{ item.path }}'
name: "{{ item.name }}"
data: "{{ item.data }}"
type: dword
with_items:
# more items working correctly
- { path: "Ciphers\\RC4 128/128", name: 'Enabled', data: 0 }
- { path: "Ciphers\\RC4 40/128", name: 'Enabled', data: 0 }
- { path: "Ciphers\\RC4 56/128", name: 'Enabled', data: 0 }
I've tried every single combination of quotes and slashes I could think of to escape the /, and still either throws syntax error or considers the last 128 as another folder of the registry path rather than part of the key itself.
Is there any way Ansible can take that 128/128 literally and not as part of a path?
Sorry, but you are out of luck with win_regedit and forward slash.
win_regedit use PowerShell and Get-ItemProperty with friends under the hood.
And PowerShell treat forward slash character as level separator, whether you escape it or not.
You can google for some ways to overcome this in PowerShell (example1, example2).
But with win_regedit Ansible module you can't use that tricks.
So either you write your own PowerShell script with tricks from above articles and use script module, or prepare registry template and use win_regmerge module (it uses reg.exe under the hood) to import required settings.
Thanks to #KonstantinSuvorov I've done a workaround that, although ugly, works. Perform this step to create the registry key directly with PowerShell before the win_regedit:
- win_shell: $path=new-item -path 'HKLM:\System\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Ciphers';$key = (get-item HKLM:\).OpenSubKey("System\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Ciphers", $true);$key.CreateSubKey('RC4 128/128');$key.CreateSubKey('RC4 40/128');$key.CreateSubKey('RC4 56/128');$key.Close()

How to upload encrypted file using ansible vault?

Does anyone have an example of decrypting and uploading a file using ansible-vault.
I am thinking about keeping my ssl certificates encrypted in source control.
It seems something like the following should work.
---
- name: upload ssl crt
copy: src=../../vault/encrypted.crt dest=/usr/local/etc/ssl/domain.crt
The copy module now does this seamlessly as of Ansible 2.1.x. Just encrypt your file with Ansible Vault and then issue the copy task on the file.
(For reference, here's the feature that added this: https://github.com/ansible/ansible/pull/15417)
UPDATE: Deprecated as of 2016, Ansible 2.1
On any Ansible version prior of 2.1:
That's not going to work. What you will get is your encrypted.crt (with Ansible Vault) uploaded literally as domain.crt
What you need to do is make your playbook part of a "Vault" and add a variable that contains your certificate content. Something like this:
---
- name: My cool playbook
hosts: all
vars:
mycert: |
aasfasdfasfas
sdafasdfasdfasdfsa
asfasfasfddasfasdfa
tasks:
# Apparently this causes new lines on newer ansible versions
# - name: Put uncrypted cert in a file
# shell: echo '{{ mycert }}' > mydecrypted.pem
# You can try this as per
# https://github.com/ansible/ansible/issues/9172
- copy:
content: "{{ mycert }}"
dest: /mydecrypted.pem
- name: Upload Cert
copy: src=/home/ubuntu/mydecrypted.pem dest=/home/ubuntu/mydecrypteddest.pem
- name: Delete decrypted cert
file: path=/home/ubuntu/mydecrypted.pem state=absent
You can choose to put your mycert variable in a separate variable file using Ansible Vault too.
The copy module has been updated in Ansible 2.1. From the changelog:
"copy module can now transparently use a vaulted file as source, if
vault passwords were provided it will decrypt and copy on the fly."
Noting it here, since some people will inevitably not look past the
accepted answer. – JK Laiho
There is a feature request to support this natively in the copy module. But until that is implemented, here is the workaround (similar to #dave1010's answer, but repeating common parts for completeness):
Create a secrets.yml file encrypted with ansible vault which contains your secrets, for example:
---
private_ssl_key: |
-----BEGIN PRIVATE KEY-----
abcabcabcabcabcabcabcabcabc
-----END PRIVATE KEY-----
private_crt: |
-----BEGIN CERTIFICATE-----
abcabcabcabcabcabcabcabcabc
-----END CERTIFICATE-----
In your playbook, include it:
vars_files:
- secrets.yml
Then you can use the variables in tasks:
- name: Copy private kay
copy: content="{{ private_ssl_key }}" dest=/some/path/ssl.key
However, this doesn't work if the file that you are trying to copy is a binary file. In that case, you need to first encode the content with base64:
cat your_secret_file | /usr/bin/base64
Then put the base64 encoded value in your secrets.yml file, e.g.:
crt_b64: |
ndQbmFQSmxrK2IwOFZnZHNJa0sKICAxdDhFRUdmVzhMM...
Then you can create the remote file in two steps:
- name: Copy certificate (base64 encoded)
copy: content="{{ crt_b64 }}" dest=/some/path/cert.b64
- name: Decode certificate
shell: "base64 -d /some/path/cert.b64 > /some/path/cert.txt"
args:
creates: /some/path/cert.txt
Note that you could delete the temporary cert.b64 file on the remote host. But then re-running the playbook will re-create it instead of skipping this task. So, I prefer to leave it there.
UPDATE:
This feature has been implemented in Ansible 2.1.
copy module can now transparently use a vaulted file as source, if
vault passwords were provided it will decrypt and copy on the fly.
Ansible 2.5 added the parameter decrypt to the copy module.
For example, if you encrypted your file using something like:
$ ansible-vault encrypt vault/encrypted.crt
Now you can use copy + decrypt:
---
- name: upload ssl crt
copy:
src: path/to/encrypted-with-vault.crt
dest: /usr/local/etc/ssl/domain.crt
decrypt: yes
mode: 0600
I used a template and a vars_file to do it:
In your top-level playbook:
vars_files:
- secretvars.yml
In a task:
- name: Private ssl key
template: src=etc-ssl-private-site.key dest=/etc/ssl/private/site.key
In the template (etc-ssl-private-site.key) all you need is the variable:
{{ private_ssl_key }}
In the encrypted secretvars.yml (encrypt this with ansible-vault):
---
private_ssl_key: |
-----BEGIN PRIVATE KEY-----
abcabcabcabcabcabcabcabcabc
-----END PRIVATE KEY-----
Update: As of April 2016 my Github PR has been merged and is available in Ansible 2.1 and later. The below was an interim solution until the PR was merged.
Wanting to do the same thing I created an action plugin to implement the feature. This is available via github. The plugin is exactly the copy action plugin as shipped with ansible, but with support for vault decryption.
You can use it like this:
- name: Copy Some Secret File
copyv: src="secret.txt" dest="/tmp/"
if secret.txt is encrypted (and the vault password is supplied) then it will be decrypted and copied.
I think, you have a simpler way to do this.
If you use certificate+key in one file in some format (like pkcs12 or just concatenated), you can use generic openssl (or gpg, or something else) encryption. It will look like this:
openssl enc -e -aes-256-ctr -in original.pem -out encrypted.aes -k <pass-vault>
After that you can just copy encrypted.aes to remote host and decrypt it in-place:
- name: copy encrypted cert and key
copy: src=encrypted.aes dest=/root/ansible-files/ mode=0600
- name: decrypt cert and key
command: openssl enc -aes-256-ctr -d -in /root/ansible-files/encrypted.aes -out <dest> -k {{ pass-vault }}
If you have separate key file in pem or der format, you can use
openssl rsa -in original.pem -out encrypted.pem -aes256 -passout pass:<pass-vault>
Until the 'copy' module has been extended to automatically decrypt vault files, here's a simple workaround:
When stdout is not a tty, ansible-vault view <file> prints cleartext to stdout without invoking a pager.
In combination with a 'pipe' lookup, this behavior can be used with a vault password file to feed into the copy module's 'content' option:
- name: "install host key"
copy: content="{{ lookup('pipe', 'ansible-vault view ' + src_key_file) }}"
dest={{ dest_key_file }}
You can also use local_action to temporairly decrypt your file as part of the playbook:
- name: "temporairly decrypt the twpol.enc"
sudo: False
local_action: shell ansible-vault view --vault-password-file {{ lookup('env', 'ANSIBLE_VAULT_PASS_FILE') }} ./roles/copykey/files/key.enc > ./roles/copykey/files/key.txt
- name: "copy the key to the target machine."
copy: src=key.txt dest=/tmp
- name: "remove decrypted key.txt file"
sudo: False
local_action: rm ./roles/copykey/files/key.txt
+1 for the copy: content= {{ private_ssl_key }}" method suggested by #utapyngo above.
If you are doing your key distribution as a role, rather than just in a playbook (and why not, since key distribution is something you might need again later), keep in mind the following:
You only get one file for your vars, so all the keys (say you have different bundles based on host machines or whatever) have to go together in <role>/vars/main.yml
Variables in this <role>/vars/main.yml are referenceable without any paths (that's nice!)
Remember that whenever you want the content of the variable, you need quotes AND curlies, i.e., "{{ your_variable_name }}"
If you want to copy more than one file per task, you need a with_items: loop
If you want to keep your sensitive data that you've gone through so much trouble to encrypt in the first place off the screen, a neat trick is to next your key variables inside a dictionary; that way, in your with_items loop you are feeding it the dictionary key rather than the contents of the variable itself.

Resources