How do you provide domain credentials to ansible's mount module? - ansible

I've figured out how to use the shell module to create a mount on the network using the following command:
- name: mount image folder share
shell: "mount -t cifs -o domain=MY_DOMAIN,username=USER,password=PASSWORD //network_path/folder /local_path/folder
sudo_user: root
args:
executable: /bin/bash
But it seems like it's better practice to use Ansible's mount module to do the same thing.
Specifically, I'm confused about going about providing the options for domain=MY_DOMAIN,username=USER,password=PASSWORD. I see there is a flag for opts, but I'm not quite sure how this would look.

Expanding on #adam-kalnas answer:
Creating an fstab entry and then calling mount will allow you to mount the file-system in more appropriate permission level (i.e. not 0777). By doing state: present ansible will only create the entry in /etc/fstab and then can be mounted by the user. From ansible mount module documentation:
absent and present only deal with fstab but will not affect current
mounting.
Additionally, you'd want to avoid leaving credentials in the /etc/fstab file (as its readable by all, human or service). To avoid that, create a credential file that is appropriately secured.
All together looks something like this:
- name: Create credential file (used for fstab entry)
copy:
content: |
username=USER
password=PASSWORD
dest: /home/myusername/.credential
mode: 0600
become: true
become_user: myusername
- name: Create fstab entry for product image folder share
mount:
state: present
fstype: cifs
opts: "credentials=/home/myusername/.credential,file_mode=0755,dir_mode=0755,user"
src="//network_path/folder"
path="/local_path/folder"
become: true
- name: Mount product image folder share
shell: |
mount "/local_path/folder"
become: true
become_user: myusername

Here's the command I ended up going with:
- name: mount product image folder share
mount: state="present"
fstype="cifs"
opts="domain= MY_DOMAIN,username=USER,password=PASSWORD,file_mode=0777,dir_mode=0777" src="//network_path/folder" name="/local_path/folder"
sudo_user: root
sudo: yes
A few notes about it:
I don't think the file_mode=0777,dir_mode=0777 should have to be required, but in my situation is was needed in order for me to have write access to the folder. I could read the folder without specifying the permissions, but I couldn't write to it.
This snippet is required right not because of this ansible bug I tested this on 1.9.0 and 1.9.1, and it was an issue in both versions.
sudo_user: root
sudo: yes

I have not personally used the mount module, but from the documentation it looks like you'd want to do something like:
- name: mount image folder share
mount: fstype="cifs"
opts="domain=MY_DOMAIN,username=USER,password=PASSWORD"
src="//network_path/folder"
name="/local_path/folder"
I'd give that a try, and run it using -vvvv to see all the ansible output. If it doesn't work then the debug output should give you a pretty decent idea of how to proceed.

Related

Best way to create directory if not exists, but do not modify if exists

I would like to create a new directory with a specified mode/owner but only if it does not yet exist.
I can do it by first checking stat:
- name: Determine if exists
stat:
path: "{{ my_path }}"
register: path
- name: Create path
file:
path: "{{ my_path }}"
owner: someuser
group: somegroup
mode: 0775
state: directory
when: not path.stat.exists
Is it possible to do this without the extra step?
If not, is there a better way to accomplish this?
Ansible can be used to manage the directory in question, always ensuring that it will have the defined ownership and permissions irrespective of whether it exists or not.
If you want to avoid any chances of modifying an existing directory for some reason, the way you accomplished it using Ansible modules (requiring two tasks) is correct.
However, if you do need to accomplish this in 1 step - you can use the command module to run the install command to create directory.
Example:
- name: Create path
command:
cmd: "install -o someuser -g somegroup -m 0775 -d {{ my_path }}"
creates: "{{ my_path }}"
Here we are using the creates property to prevent the command from running when the path already exists.

How do I create an Ansible "pre-handler" that runs before the task but only if the task needs to run?

How do I create an Ansible "pre-handler" that runs before the task, but only if the task needs to run? In other words, Ansible will first check if the task needs to be run. If it does, it runs the pre-handler and then runs the task. If the task does not need to be run, the pre-handler is never run.
My use case is a root filesystem mounted as read-only. I have an Ansible task to create .bashrc. I would like Ansible to remount the filesystem as read-write if and only if .bashrc needs to be updated. Remounting the filesystem before and after each Ansible run is not practical because making it read-only again requires a reboot.
A handler is notified by a task if that task changed something. So a "pre-handler" is not possible as the task needs to run to see if it changes something or not.
However, you can notify a handler from a task running in check mode. If you want to do things in order, you'll need to force the run of handlers with the meta module.
Would something like the below example solve your problem ?
- name: Check if .bashrc has the correct content
copy: &bashrc_copy_params
src: bashrc_root
dest: /root/.bashrc
owner: root
group: root
mode: 0644
check_mode: true
notify: remount root fs rw
- meta: flush_handlers
- name: Really copy .bashrc
copy: *bashrc_copy_params
Note that you can achieve the exact same result without a handler in this specific case. Below, an other example with a block that will run only when the check reports a change. It is even better than the previous example as the real copy task will be totally skipped if not needed.
- name: Check if .bashrc has the correct content
copy: &bashrc_copy_params
src: bashrc_root
dest: /root/.bashrc
owner: root
group: root
mode: 0644
check_mode: true
register: bashrc_state
- when: bashrc_state.changed | bool
block:
- name: remount root fs rw
debug:
msg: for example only, replace with your own task
- name: Really copy .bashrc
copy: *bashrc_copy_params
Note: The &bashrc_copy_params and *bashrc_copy_params notations in my above examples are yaml anchors. See learn yaml in Y minutes for an explanation if needed. They are allowed in Ansible but must be declared and used in the same file.

Ansible - Fetching a file from a Windows remote share

I'm trying to get a file from a windows DFS share to the localhost (linux) to parse it later.
The path to the file is something like : \\windows_host\folder\file
And I'm trying to use the fetch module with something similar to this:
- name: Test
hosts: all
connection: local
gather_facts: no
tasks:
- name: Fetching a file from a Windows DFS Share
fetch:
src: \\windows_host\folder\file
dest: local_folder/file
flat: yes
But when I run it, it does not get the file and if I use the verbose option it says:
"msg": "the remote file does not exist, not transferring, ignored"
Though the file exists at the specific location.. so I think the problem is with the path encoding (I might be wrong) and I have tried a few different formats but so far no luck.
Does anyone know how to do that or what I'm doing wrong?
Alternative ways to get the file are also appreciated considering anyway that
I'm not allowed to mount the share or to have any service (ftp/http/etc..) returning the file
Thanks in advance
ValerioG
I actually managed to make it work using the command module and smbclient command in linux.
In case someone needs something similar, the playbook below works for me.
---
- name: Test
hosts: all
connection: local
gather_facts: no
vars_files:
- vault_with_AD_credentials.yaml
tasks:
- name: Getting the Exchange Data file from Windows Share
run_once: yes
command: smbclient '\\windows_host\share' -c 'lcd local_folder; cd remote_folder; get filename' -U {{ ad_username }}%{{ ad_password }}

Ansible: /etc not writable

I am trying to copy a file in to /etc. But I am getting "msg: Destination /etc not writable" when i run the playbook. Here is my Playbook task part. Really Appreciate your help.
tasks:
- name: copy rsyslog
sudo: yes
copy:
src: /home/nandakumar.nachimuth/playbooks/rhn_check/rtest.conf
dest: /etc/rtest.conf
owner: root
group: root
mode: 0755
ignore_errors: yes
Error
msg: Destination /etc not writable
Note:I have provided the ssh and sudo pass while running the Playbook.
Instead of using sudo with your tasks, try adding become: yes with your playbook
example
- hosts: all
become: yes
Also, make sure that you are really entering the sudo password instead of the user password.
You need to reconfigure sshd to allow your user to switch to use sudo without password. To do that you will have to fire up sudo visudo and then change the line with your user to look like this:
your_username ALL=(ALL) NOPASSWD: ALL
And that will do the trick.
The user should have root permissions.
I think this should help. My issue was though user1 has root permissions i was getting unable to write error, Just by placing "become: yes", I get rid of this error.
- hosts: analytics
user: user1
become: yes
become_user: root
gather_facts: yes
roles:
- name: xxxxx
You need to specify sudo after user with hosts
example:
-hosts: abc
user: xyz
sudo: yes
This will work for you.

Ansible copy module requires writable parent directory?

Need to set /proc/sys/net/ipv4/conf/all/forwarding to 1
That's can be easily done via command
- name: Enable IPv4 traffic forwarding
command: echo 1 > /proc/sys/net/ipv4/conf/all/forwarding
But that's bad practice - it will be always "changed" task.
So I tried the following:
- name: Enable IPv4 traffic forwarding
copy: content=1 dest="/proc/sys/net/ipv4/conf/all/forwarding" force=yes
Which failed with msg: "Destination /proc/sys/net/ipv4/conf/all not writable"
According to sources seems like copy always requires parent directory will be writable. But 1) I don't understand why 2) Any other "idiomatic" way to set destination file to required value?
While I still do not understand why copy needs to check parent directory permissions, thanks to #larsks:
sysctl module changes both sysctl.conf and /proc values
and this solves my task
- name: Enable IPv4 traffic forwarding
copy: content=1 dest="/proc/sys/net/ipv4/conf/all/forwarding" unsafe_writes=true
will disable Ansible's atomic write functionality, and instead write 1 to the file directly.
Atomic writes are good and useful because they mean you will never get a corrupted file that has the output of multiple processes interleaved, but /proc is a special magic thing. The classic Unix dance of writing to a temporary file until you're done, and then renaming it to the final filename you want breaks because /proc doesn't let you create random temporary files.
I found a workaround for this problem:
- name: Create temp copy of mongod.conf
copy:
src : /etc/mongod.conf
dest: /tmp/mongod.conf
remote_src: yes
diff: no
check_mode: no
changed_when: false
- name: Copy config file mongod.conf
copy:
src : "/source/of/your/mongod.conf"
dest: "/tmp/mongod.conf"
register: result
- name: Copy temp mongod.conf to /etc/mongod.conf
shell: "cp --force /tmp/mongod.conf /etc/mongod.conf"
when: result.changed == true

Resources