Páginas

Friday, 11 October 2019

Working with Jinja2 templates - II



Another way of using Jinja2 templates

{{ ansible_mounts | json_query("[?fstype == 'jfs2'].mount") | to_nice_yaml }}

We break it down:
 ansible_mounts : variable
json_query: filter to query a complex structure. ("[?fstype == 'jfs2'].mount") We select the file system type and show the mount fact
to_nice_yaml : give it some format, set it in yaml format

This is the information that we get when we run a playbook with that jinja template

- /
- /usr
- /var
- /tmp
- /home
- /admin
- /opt
- /var/adm/ras/livedump
- /usr/SE
- /usr/tws
- /home/metron
- /usr/SE/tools
- /usr/tws/TWS/stdlist


This is the whole information we get if we run the setup module and gather the information about ansible_mounts

ansible havut440 -m setup -a "filter=ansible_mounts"
havut440 | SUCCESS => {
    "ansible_facts": {
        "ansible_mounts": [
            {
                "block_available": 149827,
                "block_size": 4096,
                "block_total": 163840,
                "block_used": 14013,
                "device": "/dev/hd4",
                "fstype": "jfs2",
                "inode_available": 136867,
                "inode_total": 140635,
                "inode_used": 3768,
                "mount": "/",
                "options": "rw,log=/dev/hd8",
                "size_available": 613691392,
                "size_total": 671088640,
                "time": "Sep 06 11:03"
            },
            {
                "block_available": 241881,
                "block_size": 4096,
                "block_total": 1081344,
                "block_used": 839463,
                "device": "/dev/hd2",
                "fstype": "jfs2",
                "inode_available": 266615,
                "inode_total": 307293,
                "inode_used": 40678,
                "mount": "/usr",
                "options": "rw,log=/dev/hd8",
                "size_available": 990744576,
                "size_total": 4429185024,
                "time": "Sep 06 11:03"
            },
            {
                "block_available": 186123,
                "block_size": 4096,
                "block_total": 262144,
                "block_used": 76021,
                "device": "/dev/hd9var",
                "fstype": "jfs2",
                "inode_available": 167015,
                "inode_total": 175362,
                "inode_used": 8347,
                "mount": "/var",
                "options": "rw,log=/dev/hd8",
                "size_available": 762359808,
                "size_total": 1073741824,
                "time": "Sep 06 11:03"
            },
            {
                "block_available": 310047,
                "block_size": 4096,
                "block_total": 393216,
                "block_used": 83169,
                "device": "/dev/hd3",
                "fstype": "jfs2",
                "inode_available": 284868,
                "inode_total": 285485,
                "inode_used": 617,
                "mount": "/tmp",
                "options": "rw,nosuid,log=/dev/hd8",
                "size_available": 1269952512,
                "size_total": 1610612736,
                "time": "Sep 06 11:03"
            },
            {
                "block_available": 159061,
                "block_size": 4096,
                "block_total": 163840,
                "block_used": 4779,
                "device": "/dev/hd1",
                "fstype": "jfs2",
                "inode_available": 141501,
                "inode_total": 141771,
                "inode_used": 270,
                "mount": "/home",
                "options": "rw,nosuid,log=/dev/hd8",
                "size_available": 651513856,
                "size_total": 671088640,
                "time": "Sep 06 11:04"
            },
            {
                "block_available": 32673,
                "block_size": 4096,
                "block_total": 32768,
                "block_used": 95,
                "device": "/dev/hd11admin",
                "fstype": "jfs2",
                "inode_available": 29127,
                "inode_total": 29138,
                "inode_used": 11,
                "mount": "/admin",
                "options": "rw,log=/dev/hd8",
                "size_available": 133828608,
                "size_total": 134217728,
                "time": "Sep 06 11:04"
            },
            {
                "block_available": 0,
                "block_size": 1024,
                "block_total": -1,
                "block_used": -1,
                "device": "/proc",
                "fstype": "procfs",
                "inode_available": 0,
                "inode_total": 0,
                "inode_used": 0,
                "mount": "/proc",
                "options": "rw",
                "size_available": 0,
                "size_total": -1024,
                "time": "Sep 06 11:04"
            },
            {
                "block_available": 162074,
                "block_size": 4096,
                "block_total": 425984,
                "block_used": 263910,
                "device": "/dev/hd10opt",
                "fstype": "jfs2",
                "inode_available": 145670,
                "inode_total": 152065,
                "inode_used": 6395,
                "mount": "/opt",
                "options": "rw,log=/dev/hd8",
                "size_available": 663855104,
                "size_total": 1744830464,
                "time": "Sep 06 11:04"
            },
            {
                "block_available": 65444,
                "block_size": 4096,
                "block_total": 65536,
                "block_used": 92,
                "device": "/dev/livedump",
                "fstype": "jfs2",
                "inode_available": 58200,
                "inode_total": 58204,
                "inode_used": 4,
                "mount": "/var/adm/ras/livedump",
                "options": "rw,log=/dev/hd8",
                "size_available": 268058624,
                "size_total": 268435456,
                "time": "Sep 06 11:04"
            },
            {
                "block_available": 189364,
                "block_size": 4096,
                "block_total": 196608,
                "block_used": 7244,
                "device": "/dev/SElv",
                "fstype": "jfs2",
                "inode_available": 168419,
                "inode_total": 171683,
                "inode_used": 3264,
                "mount": "/usr/SE",
                "options": "rw,log=/dev/hd8",
                "size_available": 775634944,
                "size_total": 805306368,
                "time": "Sep 06 11:04"
            },
            {
                "block_available": 190030,
                "block_size": 4096,
                "block_total": 393216,
                "block_used": 203186,
                "device": "/dev/twslv",
                "fstype": "jfs2",
                "inode_available": 171564,
                "inode_total": 174867,
                "inode_used": 3303,
                "mount": "/usr/tws",
                "options": "rw,log=/dev/hd8",
                "size_available": 778362880,
                "size_total": 1610612736,
                "time": "Sep 06 11:04"
            },
            {
                "block_available": 91932,
                "block_size": 4096,
                "block_total": 98304,
                "block_used": 6372,
                "device": "/dev/metlv",
                "fstype": "jfs2",
                "inode_available": 82484,
                "inode_total": 87189,
                "inode_used": 4705,
                "mount": "/home/metron",
                "options": "rw,log=/dev/hd8",
                "size_available": 376553472,
                "size_total": 402653184,
                "time": "Sep 06 11:04"
            },
            {
                "block_available": 196466,
                "block_size": 4096,
                "block_total": 196608,
                "block_used": 142,
                "device": "/dev/SEtoolslv",
                "fstype": "jfs2",
                "inode_available": 174652,
                "inode_total": 174668,
                "inode_used": 16,
                "mount": "/usr/SE/tools",
                "options": "rw,log=/dev/hd8",
                "size_available": 804724736,
                "size_total": 805306368,
                "time": "Sep 06 11:04"
            },
            {
                "block_available": 226126,
                "block_size": 4096,
                "block_total": 262144,
                "block_used": 36018,
                "device": "/dev/twsstdlv",
                "fstype": "jfs2",
                "inode_available": 203925,
                "inode_total": 204264,
                "inode_used": 339,
                "mount": "/usr/tws/TWS/stdlist",
                "options": "rw,log=/dev/hd8",
                "size_available": 926212096,
                "size_total": 1073741824,
                "time": "Sep 06 11:04"
            }
        ],
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false
}

Working with Jinja2 Templates


You can use Jinja2 Language to create templates based on the information of each host where the playbook runs.

Let's say, we are interested in getting  the list of the filesystems on a host.
We could use the following syntax in the Jinja template:

{{ ansible_mounts | selectattr("fstype", "equalto", "jfs2" ) | map(attribute='mount') | join ('\n') }}

We break it down:
 ansible_mounts : variable
selectattr : lets you select the object * ("fstype", "equalto", "jfs2" ) and you can set a condition, in this case only filesystems that are jfs (not nfs,...)
map: applies a filter to select some of the objects, in this case the value "mount"
join: give it some format , in our case set a new line between the values

This is the information that we get when we run a playbook with that jinja template

/
/usr
/var
/tmp
/home
/admin
/opt
/var/adm/ras/livedump
/usr/SE
/usr/tws
/home/metron
/usr/SE/tools
/usr/tws/TWS/stdlist


This is the whole information we get if we run the setup module and gather the information about ansible_mounts

ansible havut440 -m setup -a "filter=ansible_mounts"
havut440 | SUCCESS => {
    "ansible_facts": {
        "ansible_mounts": [
            {
                "block_available": 149827,
                "block_size": 4096,
                "block_total": 163840,
                "block_used": 14013,
                "device": "/dev/hd4",
                "fstype": "jfs2",
                "inode_available": 136867,
                "inode_total": 140635,
                "inode_used": 3768,
                "mount": "/",
                "options": "rw,log=/dev/hd8",
                "size_available": 613691392,
                "size_total": 671088640,
                "time": "Sep 06 11:03"
            },
            {
                "block_available": 241881,
                "block_size": 4096,
                "block_total": 1081344,
                "block_used": 839463,
                "device": "/dev/hd2",
                "fstype": "jfs2",
                "inode_available": 266615,
                "inode_total": 307293,
                "inode_used": 40678,
                "mount": "/usr",
                "options": "rw,log=/dev/hd8",
                "size_available": 990744576,
                "size_total": 4429185024,
                "time": "Sep 06 11:03"
            },
            {
                "block_available": 186123,
                "block_size": 4096,
                "block_total": 262144,
                "block_used": 76021,
                "device": "/dev/hd9var",
                "fstype": "jfs2",
                "inode_available": 167015,
                "inode_total": 175362,
                "inode_used": 8347,
                "mount": "/var",
                "options": "rw,log=/dev/hd8",
                "size_available": 762359808,
                "size_total": 1073741824,
                "time": "Sep 06 11:03"
            },
            {
                "block_available": 310047,
                "block_size": 4096,
                "block_total": 393216,
                "block_used": 83169,
                "device": "/dev/hd3",
                "fstype": "jfs2",
                "inode_available": 284868,
                "inode_total": 285485,
                "inode_used": 617,
                "mount": "/tmp",
                "options": "rw,nosuid,log=/dev/hd8",
                "size_available": 1269952512,
                "size_total": 1610612736,
                "time": "Sep 06 11:03"
            },
            {
                "block_available": 159061,
                "block_size": 4096,
                "block_total": 163840,
                "block_used": 4779,
                "device": "/dev/hd1",
                "fstype": "jfs2",
                "inode_available": 141501,
                "inode_total": 141771,
                "inode_used": 270,
                "mount": "/home",
                "options": "rw,nosuid,log=/dev/hd8",
                "size_available": 651513856,
                "size_total": 671088640,
                "time": "Sep 06 11:04"
            },
            {
                "block_available": 32673,
                "block_size": 4096,
                "block_total": 32768,
                "block_used": 95,
                "device": "/dev/hd11admin",
                "fstype": "jfs2",
                "inode_available": 29127,
                "inode_total": 29138,
                "inode_used": 11,
                "mount": "/admin",
                "options": "rw,log=/dev/hd8",
                "size_available": 133828608,
                "size_total": 134217728,
                "time": "Sep 06 11:04"
            },
            {
                "block_available": 0,
                "block_size": 1024,
                "block_total": -1,
                "block_used": -1,
                "device": "/proc",
                "fstype": "procfs",
                "inode_available": 0,
                "inode_total": 0,
                "inode_used": 0,
                "mount": "/proc",
                "options": "rw",
                "size_available": 0,
                "size_total": -1024,
                "time": "Sep 06 11:04"
            },
            {
                "block_available": 162074,
                "block_size": 4096,
                "block_total": 425984,
                "block_used": 263910,
                "device": "/dev/hd10opt",
                "fstype": "jfs2",
                "inode_available": 145670,
                "inode_total": 152065,
                "inode_used": 6395,
                "mount": "/opt",
                "options": "rw,log=/dev/hd8",
                "size_available": 663855104,
                "size_total": 1744830464,
                "time": "Sep 06 11:04"
            },
            {
                "block_available": 65444,
                "block_size": 4096,
                "block_total": 65536,
                "block_used": 92,
                "device": "/dev/livedump",
                "fstype": "jfs2",
                "inode_available": 58200,
                "inode_total": 58204,
                "inode_used": 4,
                "mount": "/var/adm/ras/livedump",
                "options": "rw,log=/dev/hd8",
                "size_available": 268058624,
                "size_total": 268435456,
                "time": "Sep 06 11:04"
            },
            {
                "block_available": 189364,
                "block_size": 4096,
                "block_total": 196608,
                "block_used": 7244,
                "device": "/dev/SElv",
                "fstype": "jfs2",
                "inode_available": 168419,
                "inode_total": 171683,
                "inode_used": 3264,
                "mount": "/usr/SE",
                "options": "rw,log=/dev/hd8",
                "size_available": 775634944,
                "size_total": 805306368,
                "time": "Sep 06 11:04"
            },
            {
                "block_available": 190030,
                "block_size": 4096,
                "block_total": 393216,
                "block_used": 203186,
                "device": "/dev/twslv",
                "fstype": "jfs2",
                "inode_available": 171564,
                "inode_total": 174867,
                "inode_used": 3303,
                "mount": "/usr/tws",
                "options": "rw,log=/dev/hd8",
                "size_available": 778362880,
                "size_total": 1610612736,
                "time": "Sep 06 11:04"
            },
            {
                "block_available": 91932,
                "block_size": 4096,
                "block_total": 98304,
                "block_used": 6372,
                "device": "/dev/metlv",
                "fstype": "jfs2",
                "inode_available": 82484,
                "inode_total": 87189,
                "inode_used": 4705,
                "mount": "/home/metron",
                "options": "rw,log=/dev/hd8",
                "size_available": 376553472,
                "size_total": 402653184,
                "time": "Sep 06 11:04"
            },
            {
                "block_available": 196466,
                "block_size": 4096,
                "block_total": 196608,
                "block_used": 142,
                "device": "/dev/SEtoolslv",
                "fstype": "jfs2",
                "inode_available": 174652,
                "inode_total": 174668,
                "inode_used": 16,
                "mount": "/usr/SE/tools",
                "options": "rw,log=/dev/hd8",
                "size_available": 804724736,
                "size_total": 805306368,
                "time": "Sep 06 11:04"
            },
            {
                "block_available": 226126,
                "block_size": 4096,
                "block_total": 262144,
                "block_used": 36018,
                "device": "/dev/twsstdlv",
                "fstype": "jfs2",
                "inode_available": 203925,
                "inode_total": 204264,
                "inode_used": 339,
                "mount": "/usr/tws/TWS/stdlist",
                "options": "rw,log=/dev/hd8",
                "size_available": 926212096,
                "size_total": 1073741824,
                "time": "Sep 06 11:04"
            }
        ],
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false
}


Resources:

Jinja templates


* To use the option equal, you must be running Jinja Template version 2.9 or later

Monday, 23 September 2019

Populate a file with the values registered from a variable

Sometimes you need to run a command and redirect the output to a file. You can use the shell module but if you want to follow best practices and avoid the shell module, you can use Jinja templates


 Using a Jinja template

  •     Identify the name of the variable on the remote host that you want to use
              ansible zubi -m setup | grep mounts

              "ansible_mounts": [


  • Create the Jinja template and give it some format

           cat /etc/ansible/templates/df.jinja2
           {{ ansible_mounts | json_query('[].mount') | to_nice_yaml }}


  • Create the playbook that will populate the file. Using the template module
---
- hosts: zubi
  become: yes
  become_user: root
  become_method: sudo
  tasks:

   - name: build filesystem list
     template:
          src: /etc/ansible/templates/df.jinja2
          dest: /var/lsoffs


Result:
[ec2-user@zubi ~]$ cat /var/lsoffs
- /
- /var
- /opt
- /tmp


  

Tuesday, 17 September 2019

Iptables

Iptables is the software firewall that is included with most Linux distributions by default.
Using Iptables you can define rules which will allow only selective traffic on your server

The order of the rules is important. The rules are processed by order.
If a packet doesn't match a rule, the next rule is examined until a rule is matched.

When you add/delete a new rule, that rule gets active inmmediately.

# Display iptables rules
iptables -L

Chain INPUT (policy ACCEPT)
target     prot opt source               destination
DROP       tcp  --  servername.net  anywhere             tcp dpt:ssh

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

Chain LOGGING (0 references)
target     prot opt source               destination


You can display the number of line for each rule
iptables -L --line-numbers

iptables -L --line-numbers
Chain INPUT (policy ACCEPT)
num  target     prot opt source               destination
1    DROP       tcp  --  servername.net  anywhere             tcp dpt:ssh


You can use iptables -S to list active rules by specification

iptables -S
-P INPUT ACCEPT
-P FORWARD ACCEPT
-P OUTPUT ACCEPT
-N LOGGING
-A INPUT -s 10.4.x.x/32 -p tcp -m tcp --dport 22 -j DROP


You can use verbose option which is useful when trying to get an idea of which rules are matching against packets
iptables -L -n -v

# Make rules persistent to a reboot
service iptables save
When you run that, your rules are added into the file /etc/sysconfig/iptables


# Insert rules
You can use the option - A which appends the rule to the end of the chain
iptables -A INPUT -p tcp -s 10.26.0.0/15 --dport 19001 -j ACCEPT


or you can use -I which adds the rule as the given rule number. If you skip the number, it will be added
at the top of the chain
iptables -I INPUT 2 -p tcp -s 10.4.64.39 --dport 1526 -j ACCEPT


# Delete rules

iptables -F to delete all the rules
iptables -F INPUT to delete all of the rules in the INPUT chain
iptables -D INPUT 3 to delete rules by specification

# LOG
Open your /etc/syslog.conf file and append the following line:
kern.warning /var/log/iptables.log

iptables -A INPUT -p tcp -s vhali100 --dport 22 -j LOGGING
iptables -A LOGGING -m limit --limit 2/min -j LOG --log-prefix "IPTables-Dropped: " --log-level 4
iptables -A LOGGING -j DROP

m limit: This uses the limit matching module. Using this you can limit the logging using –limit option.
–limit 2/min: This indicates the maximum average matching rate for logging. In this example, for the similar packets it will limit logging to 2 per minute. You can also specify 2/second, 2/minute, 2/hour, 2/day. This is helpful when you don’t want to clutter your log messages with repeated messages of the same dropped packets.
-j LOG: This indicates that the target for this packet is LOG. i.e write to the log file.
–log-prefix “IPTables-Dropped: ” You can specify any log prefix, which will be appended to the log messages that will be written to the /var/log/messages file
–log-level 4 This is the standard syslog levels. 4 is warning. You can use number from the range 0 through 7. 0 is emergency and 7 is debug.

Thursday, 1 August 2019

Making shell/command module idempotent

Sometimes you have to use shell or command modules for your playbooks, the flip side is that everytime you run the playbook the task is executed.
This is how I got this around so if there is no need for a change the command/shell won't run.

You have to add a previous task that will query the state of what you want to check and store the results in a variable

- name: Check rsh permissions
  shell: ls -ld /usr/bin/rsh | awk '{print $1}' | grep -E 'r|w|x'
  register: rsh
  ignore_errors: yes
  changed_when: false

Then you add the task that will implement the change and use the when statement. 
Adding the rsh.rc == 0 means that this task will only run when the previous command is successful, that is when /usr/bin/rsh has some permissions assigned

- name: Disable rsh
  command: chmod ugo= /usr/bin/rsh
  args:
    warn: no
  when: "rsh.rc == 0"

You can use this same structure to make idempotent the shell/command module




Thursday, 4 July 2019

Limit the displayed output of a task

When you are using loops in complex data structures, the output of a task can be huge and unbearable.There is no need to display that info since there is no added value.

To get rid of that output, you can use the label directive with loop_control

This is an example of how I use this in a task, in my case I use this task to search for all the .profile files under / and set root as owner:

   - name: Search .profile files
     find:
      paths: '/'
      patterns: '*.profile'
      recurse: yes
      hidden: yes
     register: profileout

   - name: Set root as .profile files owner
     file:
      path: "{{ item.path }}"
      owner: root
     loop: "{{ profileout.files }}"
     loop_control:
       label: "{{ item.path }}"


without the lines in bold this is the output:

[ec2-user@arconada playbooks]$ ansible-playbook profile.yml

PLAY [zubi] ********************************************************************************************************

TASK [Gathering Facts] *********************************************************************************************
ok: [zubi]

TASK [Search .profile files] ***************************************************************************************
ok: [zubi]

TASK [Set root as .profile files owner] ****************************************************************************
ok: [zubi] => (item={u'rusr': True, u'uid': 0, u'rgrp': True, u'xoth': False, u'islnk': False, u'woth': False, u'nlink': 1, u'issock': False, u'mtime': 1513629874.0, u'gr_name': u'root', u'path': u'/etc/lvm/profile/cache-mq.profile', u'xusr': False, u'atime': 1513629874.0, u'inode': 854459, u'isgid': False, u'size': 531, u'isdir': False, u'ctime': 1551319647.8698492, u'roth': True, u'isblk': False, u'xgrp': False, u'isuid': False, u'dev': 51713, u'wgrp': False, u'isreg': True, u'isfifo': False, u'mode': u'0444', u'pw_name': u'root', u'gid': 0, u'ischr': False, u'wusr': False})
ok: [zubi] => (item={u'rusr': True, u'uid': 0, u'rgrp': True, u'xoth': False, u'islnk': False, u'woth': False, u'nlink': 1, u'issock': False, u'mtime': 1513629874.0, u'gr_name': u'root', u'path': u'/etc/lvm/profile/cache-smq.profile', u'xusr': False, u'atime': 1513629874.0, u'inode': 854460, u'isgid': False, u'size': 339, u'isdir': False, u'ctime': 1551319647.8698492, u'roth': True, u'isblk': False, u'xgrp': False, u'isuid': False, u'dev': 51713, u'wgrp': False, u'isreg': True, u'isfifo': False, u'mode': u'0444', u'pw_name': u'root', u'gid': 0, u'ischr': False, u'wusr': False})
ok: [zubi] => (item={u'rusr': True, u'uid': 0, u'rgrp': True, u'xoth': False, u'islnk': False, u'woth': False, u'nlink': 1, u'issock': False, u'mtime': 1533091209.0, u'gr_name': u'root', u'path': u'/etc/lvm/profile/command_profile_template.profile', u'xusr': False, u'atime': 1533091209.0, u'inode': 854461, u'isgid': False, u'size': 3020, u'isdir': False, u'ctime': 1551319647.8698492, u'roth': True, u'isblk': False, u'xgrp': False, u'isuid': False, u'dev': 51713, u'wgrp': False, u'isreg': True, u'isfifo': False, u'mode': u'0444', u'pw_name': u'root', u'gid': 0, u'ischr': False, u'wusr': False})
ok: [zubi] => (item={u'rusr': True, u'uid': 0, u'rgrp': True, u'xoth': False, u'islnk': False, u'woth': False, u'nlink': 1, u'issock': False, u'mtime': 1513629874.0, u'gr_name': u'root', u'path': u'/etc/lvm/profile/lvmdbusd.profile', u'xusr': False, u'atime': 1513629874.0, u'inode': 854462, u'isgid': False, u'size': 2309, u'isdir': False, u'ctime': 1551319647.8698492, u'roth': True, u'isblk': False, u'xgrp': False, u'isuid': False, u'dev': 51713, u'wgrp': False, u'isreg': True, u'isfifo': False, u'mode': u'0444', u'pw_name': u'root', u'gid': 0, u'ischr': False, u'wusr': False})
ok: [zubi] => (item={u'rusr': True, u'uid': 0, u'rgrp': True, u'xoth': False, u'islnk': False, u'woth': False, u'nlink': 1, u'issock': False, u'mtime': 1533091209.0, u'gr_name': u'root', u'path': u'/etc/lvm/profile/metadata_profile_template.profile', u'xusr': False, u'atime': 1533091209.0, u'inode': 854463, u'isgid': False, u'size': 828, u'isdir': False, u'ctime': 1551319647.8698492, u'roth': True, u'isblk': False, u'xgrp': False, u'isuid': False, u'dev': 51713, u'wgrp': False, u'isreg': True, u'isfifo': False, u'mode': u'0444', u'pw_name': u'root', u'gid': 0, u'ischr': False, u'wusr': False})
ok: [zubi] => (item={u'rusr': True, u'uid': 0, u'rgrp': True, u'xoth': False, u'islnk': False, u'woth': False, u'nlink': 1, u'issock': False, u'mtime': 1513629874.0, u'gr_name': u'root', u'path': u'/etc/lvm/profile/thin-generic.profile', u'xusr': False, u'atime': 1513629874.0, u'inode': 854496, u'isgid': False, u'size': 76, u'isdir': False, u'ctime': 1551319647.8698492, u'roth': True, u'isblk': False, u'xgrp': False, u'isuid': False, u'dev': 51713, u'wgrp': False, u'isreg': True, u'isfifo': False, u'mode': u'0444', u'pw_name': u'root', u'gid': 0, u'ischr': False, u'wusr': False})
ok: [zubi] => (item={u'rusr': True, u'uid': 0, u'rgrp': True, u'xoth': False, u'islnk': False, u'woth': False, u'nlink': 1, u'issock': False, u'mtime': 1513629874.0, u'gr_name': u'root', u'path': u'/etc/lvm/profile/thin-performance.profile', u'xusr': False, u'atime': 1513629874.0, u'inode': 854497, u'isgid': False, u'size': 80, u'isdir': False, u'ctime': 1551319647.8698492, u'roth': True, u'isblk': False, u'xgrp': False, u'isuid': False, u'dev': 51713, u'wgrp': False, u'isreg': True, u'isfifo': False, u'mode': u'0444', u'pw_name': u'root', u'gid': 0, u'ischr': False, u'wusr': False})

PLAY RECAP *********************************************************************************************************
zubi                       : ok=3    changed=0    unreachable=0    failed=0


With the lines in bold

[ec2-user@arconada playbooks]$ ansible-playbook profile.yml

PLAY [zubi] ********************************************************************************************************

TASK [Gathering Facts] *********************************************************************************************
ok: [zubi]

TASK [Search .profile files] ***************************************************************************************
ok: [zubi]

TASK [Set root as .profile files owner] ****************************************************************************
ok: [zubi] => (item=/etc/lvm/profile/cache-mq.profile)
ok: [zubi] => (item=/etc/lvm/profile/cache-smq.profile)
ok: [zubi] => (item=/etc/lvm/profile/command_profile_template.profile)
ok: [zubi] => (item=/etc/lvm/profile/lvmdbusd.profile)
ok: [zubi] => (item=/etc/lvm/profile/metadata_profile_template.profile)
ok: [zubi] => (item=/etc/lvm/profile/thin-generic.profile)
ok: [zubi] => (item=/etc/lvm/profile/thin-performance.profile)

PLAY RECAP *********************************************************************************************************
zubi                       : ok=3    changed=0    unreachable=0    failed=0

Thursday, 9 May 2019

Access EC2 Instance from ssh client


If you need to grant somebody access to an EC2 instance from a ssh client and you don't want to share the .pem key that was generated when you created the instance

You can do the following:

  • Tell them to download Putty generator, Generate a new private and public key
  • Tell them to send you the public key
  • Edit the file /home/ec2-user/.ssh/authorized_keys on the EC2 instance and add the public key
  • Tell them to configure putty and add the private key to use for that connection
When you configure the session in Putty, remember that you have to log in as ec2-user.

Note: Take into account that if your EC2 instance is shutdown, the DNS name gets generated again, so if you had a session saved with that name, you will have to change it to the new one


References:



Tuesday, 30 April 2019

Using lookup plugin


I wanted to create a playbook to create a mksysb image and use the date command to append it into the file.
The option that I had is to use one of the lookup plugins to access data from the host where I am running the playbook.
In this case, I used pipe to read the output from a command and used a variable to store the value and use it in my tasks. If I need to run my playbook several times, my mksysb will not be overwritten.



---
- name: Create backup
  hosts: qualys
  vars:
    date: "{{ lookup('pipe', 'date +%Y%m%d') }}"
  tasks:

   - name: Mount NFS filesystem
     aix_filesystem:
       filesystem: /mnt
       nfs_server: unxshr
       device: /Store/ansible/mksysb
       state: mounted

   - name: Run mksysb on "{{ ansible_hostname }}"
     mksysb:
       name: "{{ ansible_hostname }}.{{ date }}.mksysb"
       storage_path: /mnt
       exclude_files: yes
       exclude_wpar_files: yes

   - name: Compress mksysb file
     archive:
       path: "/mnt/{{ ansible_hostname }}.{{ date }}.mksysb"
       remove: yes

   - name: Umount NFS filesystem
     aix_filesystem:
       filesystem: /mnt
       nfs_server: unxshr
       device: /Store/ansible/mksysb
       state: unmounted


References:

Lookup Plugins

Friday, 12 April 2019

Modify your SNMP configuration with regexp

I used the following play to modify the SNMP configuration but you can use it to modify any other files.

I used the replace module instead of lineinfile since you can find several matches for any of these lines that you want to replace.
The tricky thing about this task is the use of Regular expressions in Python.
The module works in the following way, what it is matched with the regexp expression will be replaced by the replace line.
What was challenging for me was to learn the backreferences. This is used to match a regular expression and use it later in your replace line.
I will use the last line to explain how it works.
You have to add the regular expression you want to match inside the parentheses. You can name it using ?P , otherwise it will be named as expression number 1.
In my example is ?P<comm>

In my case I wanted to replace
community tivoli 192.132.10.0 255.255.255.0      writeOnly
with
community tivoli 192.132.10.0 255.255.255.0      readOnly

I used the following regexp line in my play

community
\s for whitespace
\w* for word characters plus the * to match 0 or more repetitions to match tivoli
\s for whitespace
\b(?:\d{1,3}\.){3}\d{1,3}\b\ to match 192.132.10.0
s\ for whitespace
b(?:\d{1,3}\.){3}\d{1,3}\b) to match 255.255.255.0
(?P<rw>readWrite) to match readWrite

In the line, I used the group I had created g<comm> (if I hadn't name it I would have used g<1> ) and the pattern I wanted to add which was readOnly.
My new line will be g<comm> which is community tivoli 192.132.10.0 255.255.255.0 plus readOnly

   - name: SNMP Configuration
     replace:
      path: /etc/snmpd.conf
      regexp: "{{ item.regexp }}"
      replace: "{{ item.line }}"
     loop:
       - { regexp: '^community(.+)public', line: '#community      public' }
       - { regexp: '^community(.+)private', line: '#community      private' }
       - { regexp: '^community(.+)system', line: '#community      system' }
       - { regexp: '(?P<comm>^community\s\w*\s\b(?:\d{1,3}\.){3}\d{1,3}\b\s\b(?:\d{1,3}\.){3}\d{1,3}\b)\s(?P<rw>readWrite)', line: '\g<comm>      readOnly' }


References:

Saturday, 23 March 2019

Playbook to replace ssh keys using a loop

Task:

I had to replace dsa keys (which by the way are not secure and disabled by default from openssh 7.0 onwards)  with rsa keys for one user with several keys in the authorized_keys file

Objective:
To create a playbook that ran task1,task2,..taskn for each user.

Solution:
Use include_tasks feature and loop the users


This is the main playbook where I define the loop and the tasks to be executed

sshd.yml
---
- name: Reorganize SSH keys
  hosts: servers
  tasks:

   - include_tasks: "sshd_tasks.yml"
     loop:
       - userkey1
       - userkey2


The playbook checks if userkey1 exists in authorized_keys for username1 and if that's the case, a rsa key is added by task2, which is stored on /repo/sshd/userkey1/.ssh/id_rsa.pub
The third task is to remove the old dsa key

If userkey1 doesn't exist, the second task is skipped and the third task will do nothing.
I do the same for userkey2.

If I had more userkeys to check, I would add them to the loop


sshd_tasks.yml
---
  - name: Check if dsa key exists for {{ item }}
    command: grep ssh-dss.*{{ item }} /etc/ssh_keys/username1/authorized_keys
    register: sshkey
    changed_when: "sshkey.rc == 0"
    failed_when: "sshkey.rc == 2"

  - name: Add rsa key for {{ item }} into authorized keys
    authorized_key:
     user: username1
     state: present
     exclusive: no
     key: "{{ lookup('file', '/repo/sshd/{{ item }}/.ssh/id_rsa.pub') }}"
     path: /etc/ssh_keys/username1/authorized_keys
    when: "sshkey.rc == 0"

  - name: Remove dsa keys for {{ item }}
    lineinfile:
     dest: /etc/ssh_keys/username1/authorized_keys
     regexp: '^ssh-dss.*{{ item }}'
     state: absent



Example:

PLAY [Reorganize SSH keys] *********************************************************************************************************

TASK [Gathering Facts] *************************************************************************************************************
ok: [zubi]

TASK [include_tasks] ***************************************************************************************************************
included: /etc/ansible/playbooks/sshd_tasks.yml for zubi=> (item=userkey1)
included: /etc/ansible/playbooks/sshd_tasks.yml for zubi=> (item=userkey2)

TASK [Check if dsa key exists for userkey1] ****************************************************************************************
changed: [zubi]

TASK [Add rsa key for userkey1into authorized keys] *******************************************************************************
changed: [zubi]

TASK [Remove dsa keys for userkey1] ************************************************************************************************
changed: [zubi]

TASK [Check if dsa key exists for userkey2] ****************************************************************************************
changed: [zubi]

TASK [Add rsa key for userkey2 into authorized keys] *******************************************************************************
changed: [zubi]

TASK [Remove dsa keys for userkey2] ************************************************************************************************
changed: [zubi]

PLAY RECAP *************************************************************************************************************************
zubi                   : ok=9    changed=6    unreachable=0    failed=0


Saturday, 16 March 2019

Changing standard output on ansible

If you need to show the output of a command from a playbook  and you want to get it in a more human readable format, you can do it modifying your config file.
Add the following option to your configuration file /etc/ansible/ansible.cfg

stdout_callback = debug


If we try with a simple playbook

- name: show df output
   command: df -h
   register: df

 - debug:
     msg: "{{ df.stdout }}"


Before

ASK [debug] ****************************************************************************************************************************
ok: [zubi] => {
    "msg": "Filesystem      Size  Used Avail Use% Mounted on\ndevtmpfs        476M     0  476M   0% /dev\ntmpfs           493M     0  493M   0% /dev/shm\ntmpfs           493M  448K  493M   1% /run\ntmpfs           493M     0  493M   0% /sys/fs/cgroup\n/dev/xvda1      8.0G  1.2G  6.9G  15% /\ntmpfs            99M     0   99M   0% /run/user/1000"

}



After

TASK [debug] ****************************************************************************************************************************
ok: [zubi] => {}

MSG:

Filesystem      Size  Used Avail Use% Mounted on
devtmpfs        476M     0  476M   0% /dev
tmpfs           493M     0  493M   0% /dev/shm
tmpfs           493M  448K  493M   1% /run
tmpfs           493M     0  493M   0% /sys/fs/cgroup
/dev/xvda1      8.0G  1.2G  6.9G  15% /
tmpfs            99M     0   99M   0% /run/user/1000

Sunday, 10 March 2019

Changing system hostname on AWS

When you log into an instance for the firs time, you'll see that it is automatically  created with a horrendous hostname based on your ip and so on.

I consider it handy to set a new name for your computer. You can follow this easy steps if you don't have a public DNS domain name.

Check your OS with this command

cat /etc/system-release
Amazon Linux release 2 (Karoo)

Step 1

For Amazon Linux 2: Use the hostnamectl command
sudo hostnamectl set-hostname "servername.localdomain"

For Amazon Linux AMI: Open /etc/sysconfig/network and set
HOSTNAME=servername.localdomain


Step 2
Open the /etc/hosts file and change the entry beginning with 127.0.0.1 to look like this
127.0.0.1 servername.localdomain servername localhost4 localhost4.localdomain4

Step 3
Reboot the instance


If you do not want to modify the hostname for your instance, but you would like to have a more useful system name when you log into your instance follow the next steps

Step 1
Create a file in /etc/profile.d that sets the environment variable called NICKNAME

sudo sh -c 'echo "export NICKNAME=servername" > /etc/profile.d/prompt.sh'

Step 2
Open /etc/bashrc (RedHat/Amazon) or /etc/bash.bashrc (Debian/Ubuntu)
and edit the file with sudo 
sudo vi /etc/bashrc

and look for the line that starts with [ "$PS1")

[ "$PS1" = "\\s-\\v\\\$ " ] && PS1="[\u@\h \W]\\$ "

replace it with

[ "$PS1" = "\\s-\\v\\\$ " ] && PS1="[\u@$NICKNAME \W]\\$ "

Step 3
Log out and then log back in