This is a sample Ansible exam that I’ve created to prepare for EX407. I have not taken the EX407 exam yet.
No answers to the sample exam questions will be provided.
Requirements
There are 18 questions in total.
You will need five RHEL 7 (or CentOS 7) virtual machines to be able to successfully complete all questions.
One VM will be configured as an Ansible control node. Other four VMs will be used to apply playbooks to solve the sample exam questions. The following FQDNs will be used throughout the sample exam.
- ansible-control.hl.local – Ansible control node
- ansible2.hl.local – managed host
- ansible3.hl.local – managed host
- ansible4.hl.local – managed host
- ansible5.hl.local – managed host
There are a couple of requiremens that should be met before proceeding further:
- ansible-control.hl.local server has passwordless SSH access to all managed servers (using the root user).
- ansible5.hl.local server has a 1GB secondary
/dev/sdb
disk attached. - There are no regular users created on any of the servers.
Tips and Suggestions
I tried to cover as many exam objectives as possible, however, note that there will be no questions related to dynamic inventory.
Some questions may depend on the outcome of others. Please read all questions before proceeding.
Note that the purpose of the sample exam is to test your skills. Please don’t post your playbooks in the comments section.
Sample Exam Questions
Note: you have root access to all five servers.
Task 1: Ansible Installation and Configuration
Install ansible package on the control node (including any dependencies) and configure the following:
- Create a regular user automation with the password of devops. Use this user for all sample exam tasks.
- All playbooks and other Ansible configuration that you create for this sample exam should be stored in
/home/automation/plays
.
Create a configuration file /home/automation/plays/ansible.cfg
to meet the following requirements:
- The roles path should include
/home/automation/plays/roles
, as well as any other path that may be required for the course of the sample exam. - The inventory file path is
/home/automation/plays/inventory
. - Privilege escallation is disabled by default.
- Ansible should be able to manage 10 hosts at a single time.
- Ansible should connect to all managed nodes using the automation user.
Create an inventory file /home/automation/plays/inventory
with the following:
- ansible2.hl.local is a member of the proxy host group.
- ansible3.hl.local is a member of the webservers host group.
- ansible4.hl.local is a member of the webservers host group.
- ansible5.hl.local is a member of the database host group.
Task 2: Ad-Hoc Commands
Generate an SSH keypair on the control node. You can perform this step manually.
Write a script /home/automation/plays/adhoc
that uses Ansible ad-hoc commands to achieve the following:
- User automation is created on all inventory hosts.
- SSH key (that you generated) is copied to all inventory hosts for the automation user and stored in
/home/automation/.ssh/authorized_keys
. - The automation user is allowed to elevate privileges on all inventory hosts without having to provide a password.
After running the adhoc script, you should be able to SSH into all inventory hosts using the automation user without password, as well as a run all privileged commands.
Task 3: File Content
Create a playbook /home/automation/plays/motd.yml
that runs on all inventory hosts and does the following:
- The playbook should replace any existing content of
/etc/motd
with text. Text depends on the host group. - On hosts in the proxy host group the line should be “Welcome to HAProxy server”.
- On hosts in the webserver host group the line should be “Welcome to Apache server”.
- On hosts in the database host group the line should be “Welcome to MySQL server”.
Task 4: Configure SSH Server
Create a playbook /home/automation/plays/sshd.yml
that runs on all inventory hosts and configures SSHD daemon as follows:
- banner is set to
/etc/motd
- X11Forwarding is disabled
- MaxAuthTries is set to 3
Task 5: Ansible Vault
Create Ansible vault file /home/automation/plays/secret.yml
. Encryption/decryption password is devops.
Add the following variables to the vault:
- user_password with value of devops
- database_password with value of devops
Store Ansible vault password in the file /home/automation/plays/vault_key
.
Task 6: Users and Groups
You have been provided with the list of users below.
Use /home/automation/plays/vars/user_list.yml
file to save this content.
--- users: - username: alice uid: 1201 - username: vincent uid: 1202 - username: sandy uid: 2201 - username: patrick uid: 2202
Create a playbook /home/automation/plays/users.yml
that uses the vault file /home/automation/plays/secret.yml
to achieve the following:
- Users whose user ID starts with 1 should be created on servers in the webservers host group. User password should be used from the user_password variable.
- Users whose user ID starts with 2 should be created on servers in the database host group. User password should be used from the user_password variable.
- All users should be members of a supplementary group wheel.
- Shell should be set to
/bin/bash
for all users. - Account passwords should use the SHA512 hash format.
- Each user should have an SSH key uploaded (use the SSH key that you created previously, see task #2).
After running the playbook, users should be able to SSH into their respective servers without passwords.
Task 7: Scheduled Tasks
Create a playbook /home/automation/plays/regular_tasks.yml
that runs on servers in the proxy host group and does the following:
- A root crontab record is created that runs every hour.
- The cron job appends the file
/var/log/time.log
with the output from the date command.
Task 8: Software Repositories
Create a playbook /home/automation/plays/repository.yml
that runs on servers in the database host group and does the following:
- A YUM repository file is created.
- The name of the repository is mysql56-community.
- The description of the repository is “MySQL 5.6 YUM Repo”.
- Repository baseurl is http://repo.mysql.com/yum/mysql-5.6-community/el/7/x86_64/.
- Repository GPG key is at http://repo.mysql.com/RPM-GPG-KEY-mysql.
- Repository GPG check is enabled.
- Repository is enabled.
Task 9: Create and Work with Roles
Create a role called sample-mysql and store it in /home/automation/plays/roles
. The role should satisfy the following requirements:
- A primary partition number 1 of size 800MB on device
/dev/sdb
is created. - An LVM volume group called
vg_database
is created that uses the primary partition created above. - An LVM logical volume called
lv_mysql
is created of size 512MB in the volume groupvg_database
. - An XFS filesystem on the logical volume
lv_mysql
is created. - Logical volume
lv_mysql
is permanently mounted on/mnt/mysql_backups
. - mysql-community-server package is installed.
- Firewall is configured to allow all incoming traffic on MySQL port TCP 3306.
- MySQL root user password should be set from the variable database_password (see task #5).
- MySQL server should be started and enabled on boot.
- MySQL server configuration file is generated from the
my.cnf.j2
Jinja2 template with the following content:
[mysqld] bind_address = {{ ansible_default_ipv4.address }} skip_name_resolve datadir=/var/lib/mysql socket=/var/lib/mysql/mysql.sock symbolic-links=0 sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES [mysqld_safe] log-error=/var/log/mysqld.log pid-file=/var/run/mysqld/mysqld.pid
Create a playbook /home/automation/plays/mysql.yml
that uses the role and runs on hosts in the database host group.
Task 10: Create and Work with Roles (Some More)
Create a role called sample-apache and store it in /home/automation/plays/roles
. The role should satisfy the following requirements:
- The httpd, mod_ssl and php packages are installed. Apache service is running and enabled on boot.
- Firewall is configured to allow all incoming traffic on HTTP port TCP 80 and HTTPS port TCP 443.
- Apache service should be restarted every time the file
/var/www/html/index.html
is modified. - A Jinja2 template file
index.html.j2
is used to create the file/var/www/html/index.html
with the following content:
The address of the server is: IPV4ADDRESS
IPV4ADDRESS is the IP address of the managed node.
Create a playbook /home/automation/plays/apache.yml
that uses the role and runs on hosts in the webservers host group.
Task 11: Download Roles From an Ansible Galaxy and Use Them
Use Ansible Galaxy to download and install geerlingguy.haproxy role in /home/automation/plays/roles
.
Create a playbook /home/automation/plays/haproxy.yml
that runs on servers in the proxy host group and does the following:
- Use geerlingguy.haproxy role to load balance request between hosts in the webservers host group.
- Use roundrobin load balancing method.
- HAProxy backend servers should be configured for HTTP only (port 80).
- Firewall is configured to allow all incoming traffic on port TCP 80.
If your playbook works, then doing “curl http://ansible2.hl.local/” should return output from the web server (see task #10). Running the command again should return output from the other web server.
Task 12: Security
Create a playbook /home/automation/plays/selinux.yml
that runs on hosts in the webservers host group and does the following:
- Uses the selinux RHEL system role.
- Enables httpd_can_network_connect SELinux boolean.
- The change must survive system reboot.
Task 13: Use Conditionals to Control Play Execution
Create a playbook /home/automation/plays/sysctl.yml
that runs on all inventory hosts and does the following:
- If a server has more than 2048MB of RAM, then parameter vm.swappiness is set to 10.
- If a server has less than 2048MB of RAM, then the following error message is displayed:
Server memory less than 2048MB
Task 14: Use Archiving
Create a playbook /home/automation/plays/archive.yml
that runs on hosts in the database host group and does the following:
- A file
/mnt/mysql_backups/database_list.txt
is created that contains the following line: dev,test,qa,prod. - A gzip archive of the file
/mnt/mysql_backups/database_list.txt
is created and stored in/mnt/mysql_backups/archive.gz
.
Task 15: Work with Ansible Facts
Create a playbook /home/automation/plays/facts.yml
that runs on hosts in the database host group and does the following:
- A custom Ansible fact server_role=mysql is created that can be retrieved from ansible_local.custom.sample_exam when using Ansible setup module.
Task 16: Software Packages
Create a playbook /home/automation/plays/packages.yml
that runs on all inventory hosts and does the following:
- Installs tcpdump and mailx packages on hosts in the proxy host groups.
- Installs lsof and mailx and packages on hosts in the database host groups.
Task 17: Services
Create a playbook /home/automation/plays/target.yml
that runs on hosts in the webserver host group and does the following:
- Sets the default boot target to multi-user.
Task 18. Create and Use Templates to Create Customised Configuration Files
Create a playbook /home/automation/plays/server_list.yml
that does the following:
- Playbook uses a Jinja2 template
server_list.j2
to create a file/etc/server_list.txt
on hosts in the database host group. - The file
/etc/server_list.txt
is owned by the automation user. - File permissions are set to 0600.
- SELinux file label should be set to net_conf_t.
- The content of the file is a list of FQDNs of all inventory hosts.
After running the playbook, the content of the file /etc/server_list.txt
should be the following:
ansible2.hl.local ansible3.hl.local ansible4.hl.local ansible5.hl.local
Note: if the FQDN of any inventory host changes, re-running the playbook should update the file with the new values.
Hi @lisenet,
Thanks for sharing this lab. I’ve used your RHCE lab for my studies and to be honest, in my humble option, your lab was harder than the proper exam itself. So I will use your lab again but this time for my EX407 studies and hopefully when I take the exam I will feel the same, and with a new cert on my belt.
Thanks once again! :)
You’re welcome. Good luck with your Ansible exam!
Hello, Congratulations and thanks for this lab.
First, I have a question about Task 5.
How I can use condition with first caracter of userid?
Thanks very much
Fred
Hi, thanks very much! The goal of the sample exam is to test your Ansible skills. If you don’t know how to solve a task, then you need to work with Ansible documentation to find a solution. Good luck!
I had a hard time with this one but here is what I used.
– name: create user for uid for webservers
user:
name: “{{item.username}}”
password: “{{pass_works | password_hash(‘sha512’)}}”
groups: wheel
shell: /bin/bash
ssh_key_file: .ssh/id_rsa
generate_ssh_key: yes
ssh_key_bits: 2048
uid: “{{item.uid}}”
when: ‘”webservers” in group_names and “12” in item.uid|string’
loop: “{{users}}”
– name: create user for uid for database
user:
name: “{{item.username}}”
password: “{{pass_works | password_hash(‘sha512’)}}”
groups: wheel
shell: /bin/bash
ssh_key_file: .ssh/id_rsa
generate_ssh_key: yes
ssh_key_bits: 2048
uid: “{{item.uid}}”
when: ‘”database” in group_names and “22” in item.uid|string’
loop: “{{users}}”
Without posting a solution, I believe a helpful hint to solve this problem is regex.
you can also solve this by using multiple tasks using different hostgroup. so no conditions is needed and no regex is needed.
– name: create users WEBSERVERS
user:
name: “{{ item.username }}”
uid: “{{ item.uid }}”
groups: wheel
shell: /bin/bash
password: “{{ user_password|password_hash(‘sha512’, (256*256)|random(seed=inventory_hostname)|string) }}”
when: “‘webservers’ in group_names and (item.uid|string)[0] == ‘1’”
with_items:
– “{{ users }}”
Thank you Tomas,
If you have other examples, don’t hesitate to post here.
Nice Sample Exam Tomas well done!
Solved all.
If someone need a tip for solve some question I can give a hand too! :)
Hi Tomas.
Thanks for useful examples.
Any tips regarding Task 18?
Hi Adam, my advise would be to check Ansible documentation. You will find the answer on docs.ansible.com.
Tomas
Solved it with creating role, delegate_to and post_tasks :-)
I hope that this is one of the proper solutions.
Well done!
Hello Adam,
Create role is not necessar for the Task18, just create template with magic variables.
Thanks
Hi
Do you have sample questions for high availability clustering exam
Nope. Clustering is much less popular compared to RHCE or Ansible.
Hello Tomas,
I have a question ?
What are differences between two conditions:
when: “‘proxy’ in group_names”
and
when: ” {{ inventory_hostname in groups[‘proxy’] }}
thanks you very much
The first one looks for a group membership in the array of all the groups the host is in.
The second one checks if the hostname as configured in Ansible’s inventory host file belongs to a specific group in the inventory.
Thanks you very much tomas
Have a nice day
Hello Tomas,
How much focus I need to give for HA Load Balancing configurations for ansible exam.. i.e. Can I expect the configuration of HA using ansible or NOT ??
It’s usefull to know, so I’d suggest you to learn how to do it. Anything that falls under the exam objectives can be expected during the exam.
hi Tomas ! is it 2.3 or 2.7 version ?
Neither, it’s generic. Pick any Ansible version that you want to test your skills on.
Hey,
Just to clarify, task 12 that utilises RHEL System Roles would be only on the newer v2.7 exam.
RHEL System Roles was available from RHEL 7.4 only and the Ansible v2.3 (407k exam) was based on RHEL 7.3 afaik
Also, in the official RH learning guide for this course in Ansible v2.3 2017, System Roles are not covered at all but they are covered in the latest v2.7 2019 learning guide.
In other words, if you are doing the 407kv27 exam, definitely learn it, if you are doing the older exam, I guess you are OK to skim it, BUT learn it anyway as it seems Red Hat is going to be pushing more and more official system roles to be released so you will encounter them in the real world.
PS. Instead of using system roles, for v2.3 play around with modules like wait_for and async/polling as there is an overlap there in terms of end results.
Love your work by the way Tomas.
Yea, you’re right. Ansible v2.3 exam was based on RHEL 7.3, therefore you can skip the system roles question if you want to.
Hi Tomas,
For Task 12, we can use block?
Thank you
Sure. The way you solve it is not important as long as you get the desired result.
for “Enables httpd_can_network_connect SELinux boolean”, we must use variables or use module?
You can use anything that solves the problem for you.
—
– name: First Plays
hosts: webservers
tasks:
– name: block
block:
– include_role:
name: rhel-system-roles.selinux
rescue:
– name: debug
fail:
when: not selinux_reboot_required
– name: reboot
reboot:
– include_role:
name: rhel-system-roles.selinux
AND
group_vars/webservers.yml:
selinux_booleans:
– name: httpd_can_network_connect
sate: on
persistent: ‘yes’
What’s the reason for using reboot in the playbook?
Sorry,
AND
group_vars/webservers/webservers.yml:
selinux_booleans:
– name: httpd_can_network_connect
sate: on
persistent: ‘yes’
“Sometimes, the SELinux role must ensure managed hosts are rebooted in order to completely apply its changes. However, it does not ever reboot hosts itselfs. This is so that you can control how the reboot is handled. But it means that it is a little more complicated than usual to properly use this role in a play.
The way this works is that the role will set a Boolean variable, selinux_reboot_required to true and fail if a reboot is needed’ RedHat
Hi, Tomas
great work, for question 17, I can only think of running the command modile with systemctl set-default multi-user
but that’s not what you intended to test right? service module seem unable to set the target right?
Try to avoid the command module in playbooks, because it’s easy to write non-idempotent playbooks this way.
What happens when you set the default target with a systemctl command? Have a think about it.
Hi, Tomas
Many thanks for the prompt replies, really appreciate it.
I am aware that the command modules should be avoided. I tried to use the systemd module, surprisingly it didn’t throw any error, but also it didn’t change the default target, have you verify that your target has changed?
“`
tasks:
– name: change target with systemd
systemd:
name: multi-user.target
state: started
enabled: True
“`
No worries, you’re welcome.
Hi, Tomas,
Managed to think about a more idempotent solution, but still wouldn’t be super excited about it, as this is not really a solution for service.
“`
file:
path: /etc/systemd/system/default.target
src: /lib/systemd/system/multi-user.target
state: link
“`
Now you’re getting somewhere!
Hi Tomas,
“What happens when you set the default target with a systemctl command? Have a think about it”:
systemctl create a symlink?
maybe it’s preferable to use file module
Thanks you very much
No worries, you’re welcome.
Hi Tomas,
I have question for Task 10:
“Apache service should be restarted every time the file /var/www/html/index.html is modified.”
We must use “handlers” after template module?
Thanks you very much
You can use handlers to restart a service.
thank you tomas, but when i must notify my handlers?
With my template?
thank you
Use Ansile documentation :)
– name: template
template:
src: “templates/index.html.j2”
dest: “/var/www/html/index.html”
notify: restart httpd
Well done!
thanks you
I have other question:
My service will restart only when my template is copied.
But if my file index.html is modify by others, my handler don’t works.
That’s expected, because the handler only runs when it’s triggered. If you have a process that modifies the file but does not trigger the handler, then the handler will not run.
Thanks you very much Tomas!
Curious about questions to relate to updating config files.
Not about the answer, more about best practices. The simplest solution for updating configs seems to be using replace with regex and lineinfile modules. Is the best practice to use such modules against config files or to use templates that get copied over?
If you want to update a single line, then using a regex with lineinfile makes sense. If you have multiple lines that need changing, then using a template might be a better option.
Hi Tomas,
For “Task 2: Ad-Hoc Commands”, with whitch user we must run script?
root ?
Thanks you
Create a regular user automation. Use this user for all sample exam tasks.
Thanks Tomas for the sample test. I have a question regarding the exam if you can help me out here.
Will we get access to docs.ansible.com or some form of it during the RedHat exam or only ansible-doc is available?
Documentation will be provided.
Hello Tomas,
In task 6 , “Each user should have an SSH key uploaded (use the SSH key that you create previously)”,
I don’t understant; we must use key file of automation user?
Thanks a lot
good, i understood, when you say “previously”, we must use ssh keys that we have created during creation of users ( alice…etc)
thanks
Yes, as the question says, use the key that you created previously.
My last question for tonight :-)
How i can push my key between servers?
I can use rsync?
You can use
ssh-copy-id
command.Task 2 , is achieved using adhoc command or playbook or running a script on the destination server ?
This statement is confusing ”
Create an SSH keypair. Write a script /home/automation/plays/adhoc that uses Ansible ad-hoc commands to achieve the following:”
If we have to use adhoc commands then we dont need to create a file.
I know during the exam we will not be getting any explanation to the question.. it up to the students to analyze and sort out the problem. ( KIOSK Exams )
You have to write a script that uses ad-hoc commands. I’m sorry, but I don’t see anything confusing about this question.
Task 6. Are we supposed to be parsing the first character of uid ? For the life of me I can’t parse it unless I force uid to be a string in the user_list.yml by surrounding the uid’s with double quotes. I could use , etc on the number but that is not what we are looking for either I suppose. Maybe i’m reading into your question too much ?
Thank you for putting this together it is really making be dig into it and prep for the exam.
Thanks,
Phil
No worries, good luck with your prep!
Thank you for this post again, Tomas. I got my certification yesterday on ver. 2.7 and this exercise was extremely helpful. I am glad I found your site :)
You’re welcome!
2. SSH key (that you generated) is copied to all inventory hosts for the automation user and stored in /home/automation/.ssh/authorized_keys.
Hi Tomas.
in this question I must create ssh-key with script adhoc or I can create ssh-keygen before this script?
Can you show ad-hoc comand for this question please.
You should create the keypair manually before writing the script.
I tried for few hours, i could not find the substring or taking out first charecter from a string in the documentation, either i am dumb or its too much for a non genius to get certified. Giving up :(
For task 6, I do that:
—
– hosts: all
become: yes
vars_files:
– secret.yml
– user_list.yml
tasks:
– name: Creating users
user:
name: “{{ item.username }}”
uid: “{{ item.uid }}”
password: “{{ user_password | password_hash(‘sha512’) }}”
shell: /bin/bash
groups: wheel
with_items: “{{ users }}”
when: (( inventory_hostname in groups[‘webservers’] ) and ( “{{ item.uid }}” >= “1000” and “{{ item.uid }}” = “2000” and “{{ item.uid }}” = “1000” and “{{ item.uid }}” = “2000” and “{{ item.uid }}” < "3000" ))
For task 6, I do that:
—
– hosts: all
become: yes
vars_files:
– secret.yml
– user_list.yml
tasks:
– name: Creating users
user:
name: “{{ item.username }}”
uid: “{{ item.uid }}”
password: “{{ user_password | password_hash(‘sha512’) }}”
shell: /bin/bash
groups: wheel
with_items: “{{ users }}”
when: (( inventory_hostname in groups[‘webservers’] ) and ( “{{ item.uid }}” >= “1000” and “{{ item.uid }}” = “2000” and “{{ item.uid }}” < "3000" ))
this when statement also works for me:
when: inventory_hostname in groups[‘webservers’] and item.uid|string|first == “1”
@lisenet for question 18 . I Got some solution but I’m unable o get the full inventory, I’m able to take the inventory of webserver group only if I mention ‘all’, it throws an error.
this is my templates– and can you tell me how to achieve all server inventory details.
127.0.0.1 localhost
::1 locahost
{% for host in groups[‘webserver’] %}
{{ hostvars[host].ansible_default_ipv4.address }} {{ hostvars[host].ansible_facts.hostname }} {{ hostvars[host].ansible_facts.fqdn }}
{% endfor %}
$ cat server_list.j2
{% for host in groups[‘all’] %}
{{hostvars[host][‘ansible_facts’][‘fqdn’]}}
{% endfor %}
$ cat server_list.yml
—
– hosts: all
become: yes
tasks:
– name: copy template
template:
src: server_list.j2
dest: /etc/server_list.txt
mode: ‘0600’
setype: net_conf_t
when: inventory_hostname in groups[‘database’]
the question says only apply to the database group not all. That’s what i am thinking too. If i set to all, i can easily get the results. Scratching my head for a solution.
You can use the when statement that applies to a group as per Eduardo’s example above.
Thank you for those awesome questions! lisenet.
for task 6. I am confused with the following two statements because my understanding is they are not same.
*Each user should have an SSH key uploaded (use the SSH key that you create previously –if the ssh key is the same one specified in the Task 2, then the user, automation, can ssh into users’s respective servers as their account without passwords.)
*After running the playbook, users should be able to SSH into their respective servers without passwords. — does it means users can ssh into their respective servers from the control node? then it needs these users exist and have their ssh key generated on the control node.
You should use the SSH keys that you created previously for task #2.
Thanks for your reply. Tomas :-)
In task 2, it only asks to generate the ssh key for the user, automation. It does not mention to generate the ssh keys for other users on the control node.
for the task 6, I use two plays in the playbook. the first play to create users and their ssh public key on control node, update known_hosts key for them. the second play to upload their ssh public key to their respective server. so the users can ssh their servers without password from the control node.
It does not have to. You can reuse the same SSH keys as many times and on as many users as you want.
The goal of this sample example is to allow people to test theirs Ansible skills. Whether you write one play or two plays is irrelevant, as long as you solve the task. How you solve it is really up to you, because there is no one right answer.
Thank you for the nice information, Tomas
It is good to know. I never thought different accounts can use the same SSH keys(paired private/public SSH keys) for the SSH passwordless login before. it makes sense. I did a quick test and it works. Thanks again :-)
You’re welcome! It’s just a keypair, similar to TLS certificates, you can deploy them on multiple servers.
First of all, i wanted to thank you for doing an awesome job, i’m planning to take the ansible exam in 5 weeks, i have noticed on the second task, when i try to modify the /usr/sbin/visudo file, it looks like its taking the changes but when you look inside the file, there’s nothing in there. So i ended up creating a file in the file in the /etc/sudoers.d
Thank!
You shouldn’t be editing the binary. What you want is
/etc/sudoers
.Thanks Tomas, awesome job.
I use to change escalation privileges using /sbin/visudo (CentOS7). Can I keep using it or is there any module to change the escalation privileges?
Not sure what you have in mind, because the
visudo
command is used to edit the sudoers file.Thanks for the work you do for linux,
Please point me to a reliable study guide for ex407 exam.
I also have a situation where our remote servers do not permit remote root login via ssh, we use su to elevate from a normal user. My question is how do I su to root when deploying playbook as the ssh key if the support user not root without compromising security.
thanks
I used DO407, if you have RHLS, that’s all you need.
If you want to use su, then take a look at
become_method: su
.I’ve been using DO407 to study, that also includes a bit of Tower and Vagrant, however, I don’t see these mentioned as an objective on the EX407 exam. Would it be safe to assume they are not covered on the day?
Hi, Ansible Tower and Vagrant are not part of the latest EX407 objectives.
Hello,
Last week I passed with 300 score, so happy :)
Well done!
Congrats! How relevant did you find these practice questions?
You passed exam with these questions? Was it same?
These aren’t exam questions, it’s a sample exam that I had created before I took EX407.
Hi, thank you for the tips, i have some questions:
1- will this questions help me to pass EX294(RHEL8) exam. cause i heard both exams are basically the same.
2- in Task10, you said “Apache service should be restarted every time the file /var/www/html/index.html is modified.”
does this mean whenever i change index.html via the palybook or any change will trigger httpd to be restarted.
3- how to note this questions to be near the actual exam questions.
4- The services that appears in the tasks, are limited (for example only httpd and mysql), or we can face other complicated services such as (iscsi…ldap….)
Thank you in advance.
The sample questions should help you to get an idea of what the exam might look like. If you can solve them all in less than 3 hours, then you are in a position to book the exam.
With regards to the #10, the service should be restarted every time the playbook modifies the index file.
In theory you can expect any service that is covered by official Red Hat training to appear on the exam.
Excellent sample test, it definitely played apart in me successfully passing the EX407 exam.
I don’t see how it’ meant to create ad-hoc script for generating SSH-KEYS on the nodes when you haven’t provisioned the controller’s key?
As the tasks says, you need to generate an SSH keypair on the control node and then copy the files to all inventory hosts for the automation user.
please send ad-hoc answer
Unfortunatelly no answers to the sample exam questions will be provided.
Hi,
Just wanted to say thank you for putting together this excellent practice exam. Unfortunately for me I discovered it too late (literally a day before my EX294 exam). I did not make it but plan a retake after practicing with this exam and being able to complete it within 3 hours. I literally ran out of time…
No worries, I’m sure that you’ll smash it the next time!
Hi Everyone,
In my practice lab I am working on below mention scenario,
1. Create a logical volume (“mylvol1”) of size 1024M on volume group (“myvg1”)
With Given conditions:
a. If volume group doesn’t exist, message “Volume Group does not exist” should be displayed.
b. If there is not enough free space in volume group (“myvg1”), message “Not enough Free Space” should be displayed. And logical volume (“mylvol1”) should be created with 700M size instead of 1024M.
I am unable to create logic for condition “b”, please guide me.
Thanks.
The logic for part b should be something like this:
Check the disk space of the volume group, if it’s less that the required volume size, then display the message, if it’s greater that the required volume size, then create the volume.
Tomas, I am not exaggerating or making up stories here. but the grading in RHCE is really weird. The script that they are running to check your config and output is unimaginable. :) But I am an RHCE now.
My serious question to you.
What do you think Ansible exam? you got 300/300. Are they just focus on the result? they dont care about your playbook etc?
Is this just a result based?
I think that it’s an interesting yet challenging exam that requires you to know Ansible really well. As with all Red Hat exams, you need to solve problems, and the outcome is what matters the most from my experience.
There are different ways you can write a playbook that achieves a specific goal (e.g. creates a new partition). The content of such playbook will depend on your experience and familiarity with the tool. As long as your playbook creates a partition, you should receive points for the task.
It helps if you approach Red Hat exams from a customer’s point of view (pretty much what happens in reality). If a customer asks you to deploy a new website, they expect the end result to be a running website, they don’t care that much whether you use Apache, Nginx or Lighttpd to deliver the solution.
Hi Tomas
I wrote my ex294 and passed thanks to you. Honestly when I first found this page , I found many of the questions challenging, but after some practice it was a breeze . Thanks again
Good job, congratulations!
Hi Tomas,
For task 5, does it matter if we modify the user_list.yml file? Like so:
—
users:
– username: alice
uid: 1201
– username: vincent
uid: 1202
– username: sandy
uid: 2201
– username: patrick
uid: 2202
question no.2 “/home/automation/plays/adhoc” a directory?
do files containing ad hoc commands need to be in a directory?
If you’re explicitly asked to put ad-hoc commands in a directory then yes, otherwise no.
Tip for people stuck on task 9 like I was:
You need to disable the default mysql module with the below command:
sudo yum module disable mysql
See:
https://dev.mysql.com/doc/mysql-repo-excerpt/8.0/en/linux-installation-yum-repo.html
Hi,
For task 11 “Use geerlingguy.haproxy role to load balance request between hosts in the webservers host group”, the value of backend should be set automatically based on the inventory ?
The var haproxy_backend_servers can be dynamically created ?
I would to share my solution for task 6 , thats so hard but I do it :D ! I hope to schedule the exam in january in 2020.
– hosts: all
become: true
vars_files:
– user_list.yml
– secret.yml
tasks:
– user:
name: “{{ item.username }}”
uid: “{{ item.uid }}”
password: “{{ user_password | password_hash(‘sha512’) }}”
shell: /bin/bash
groups: wheel
with_items: “{{ users }}”
when:
– “‘webservers’ in group_names and item.uid|string|first == ‘1’ ”
– user:
name: “{{ item.username }}”
uid: “{{ item.uid }}”
password: “{{ user_password | password_hash(‘sha512’) }}”
shell: /bin/bash
groups: wheel
with_items: “{{ users }}”
when:
– “‘database’ in group_names and item.uid|string|first == ‘2’ “
Hi,
Nice one on the item.uid|string|first == ‘1’ !
I see you’re using ‘with_items: “{{ users }}”’. I’ve seen this in a lot of other playbooks as well and I was wondering what the preferred way is?
The official RedHat course materials for EX294-8.0 state that since Ansible 2.5, the recommended way to write loops is to use the loop keyword. However, you do need to know the with_items keyword because you can encounter it in older playbooks…
I’m guessing you should still get a pass if you use the older style, seeing as that it still works.
Hi Serge thanks for your tip!
I’ve revisited the ansible documentation for loop scenarions and yes they recommend use loop than with_items.
I will force me to write with loop .
Thanks!
So for task 6 is there any reason why my playbook would not be idempotent? Not sure how to ask this without giving the answer away. I’m simply user the user module to loop through the users list provided with appropriate conditionals targeting the UID and the server’s group membership. It works as expected but I always get a changed result when I run it.
Are you regenerating the password hash every time?
I guess? I’m using “password: “{{ user_password | password_hash(‘sha512’) }}” which I guess generates a different hash every time hence the change? Just not sure how else I would do it.
Check the module documentation, I’m sure that you’ll find the answer in there!
Yup. Correct as usual :)
Thanks!
Hi There
Sorry for stupid question but Task 1 add user is a manual task am i correcnt?
It is a manual task.
Hi,
I passed the ex407 and now i want to take the EX294. Is there a difference? Do I need to study extra for the EX294? or can I directly book my exam?
I didn’t take EX294 so don’t take my word for it, but looking at the exam objectives as well as Red Hat training material they are almost identical. If you studied and passed EX407, you should be able to pass EX294 because the objectives are 95% the same.
Task 16 asks us to run the playbook against all hosts but then says to only define a variable for groups proxy and database. This means the playbook would fail against the webservers group as the variable wouldn’t be defined. I’m assuming that the solution here is to implement a conditional on the task to only run when the packages variable is defined? Seems like the obvious fix but wanted to confirm that there’s nothing else I’m missing.
Thanks!
Task 16 asks you to run the playbook against all hosts and install packages based on host groups. Whether you decide to use variables or not is completelly up to you.
Makes sense. Thanks
BTW I just passed the ex294 with a 276 in large part due to this site. So thanks for the quality material as usual!
Well done, you’re welcome!
Hi Tomas,
Just did my EX294 re-take and passed it with a 279 score. So just wanted to say a big THANK YOU for putting this sample exam together, it has been a great help! In fact more so, in my opinion, than the lab materials offered with the official RH294 course on RHLS….
If anyone is interested, I will post a terraform plan, an ansible playbook and a few ancillary scripts to easily build, configure and start, stop a lab, on github that you could use to practice this sample exam.
Requirements are:
– KVM installed (works on CentOS 8 and Fedora 30)
– RHEL8 qcow2 image (you can download this if you have a free Red Hat developer account, it’s only 713MB).
– about 6GB of memory available on your system (I’ve given all VMs 1024MB of memory but you can easily change this)
– Approx 14GB of free space on root
No worries, you’re welcome!
Thanks sir!
I am passed in ex407 using your content how base for my studies
Well done, congratulations!
Fabiano, first of all congratulations for the fact, that you’ve managed to pass the EX407 exam. I would like to ask you, if the questions given by Tomas ( Tomas, your sample exam, appears to cover almost 100% of the topics, great job!!! ) were more difficult than the “real” ones and if there was a mandatory bash script creation on the exam?
Thank you in advance
Hi
I prepare for EX294 and i have following question:
I configure partition on disk with condition, when size is too big for disk, fail, display message.
I do something like that:
tasks:
– name: block for disk
block:
– name: check size
parted:
device: /dev/vdb
number: 1
state: present
part_end: 1GiB
register: disk_data
ignore_errors: yes
– name: fail size
fail:
msg: “{{ disk_data.failed }} ERROR”
when: disk_rozmiar.failed == 1
It’s work, but I wonder about when condition.
In my registered variable key failed it’s only I think for check that size is ok or not.
This is output from registered variable:
“msg”: {
“changed”: true,
“disk”: {
“dev”: “/dev/vdb”,
“logical_block”: 512,
“model”: “Virtio Block Device”,
“physical_block”: 512,
“size”: 2097152.0,
“table”: “msdos”,
“unit”: “kib”
},
“failed”: false,
“partitions”: [],
“script”: “rm 1”
}
It’s this condition is properly set, or maybe i’m doing something wrong.
Regards
What do you want to achieve here?
Hi
i want achieve, that when a partition size is a bigger than free disk space, then I have error msg in play, and from rescue block tasks are run
Regards
Tom
OK, what you want to do is to gather disk size info and register it so that you can use it later. Then implement a logical operation where an error message is displayed if the partition size is bigger that the disk size.
There are several ways you can get disk size info, you can use stat, you can use parted, or you can use Ansible facts.
Take a look at one of my Ansible playbooks on GitHub.
Hello Tomas,
Quick Question. For the task 12.
“Uses the selinux RHEL system role”
Should I install system role using galaxy and use them?
You can if that solves the problem.
Hi Tom,
Task 2: Can you please clarify how can automation user on control node use ansible adhoc commands to setup itself (automation) on managed hosts when the user itself doesn’t exist there?
Thank you
You have root access to all servers.
Thank you Tom!
Task 1: requires privilege escalation disabled by default. With this in place, is the expectation for automation user to be able to run privileged commands on managed hosts without manually using -b | –become ? If this is true then I don’t understand how could that be, please help me understand.
It means that you need to disable by default. It doesn’t say that you can’t use privilege escallation.