Sunday, 30 October 2016

Exploring file encryption in Linux


This article explores file encryption in Linux using tools that readily available from the OS ISO itself.
There are numerous other command line & GUI tools that can be used to encrypt files linux.

We can use file encryption tools to indirectly encrypt directory content as well. We just need to create a tar archive of the directory & we are goof to go.

Method 1: Using gpg


GnuPG stands for GNU Privacy Guard and is GNU’s tool for secure communication and data storage. It can be used to encrypt data and to create digital signatures. It includes an advanced key management facility.

Encrypting a file in linux:

To encrypt a single file, use command gpg as follows:

[root@centops ~]# gpg -c myfile.txt
can't connect to `/root/.gnupg/S.gpg-agent': No such file or directory
gpg-agent[39037]: directory `/root/.gnupg/private-keys-v1.d' created

-c : Encrypt with symmetric cipher using a passphrase. The default symmetric cipher used is CAST5, but may be chosen with the –cipher-algo option.

Decrypt a file:

To decrypt file use the gpg command as follows:

[root@centops ~]# gpg myfile.txt.gpg
gpg: 3DES encrypted data
can't connect to `/root/.gnupg/S.gpg-agent': No such file or directory
gpg: encrypted with 1 passphrase
gpg: WARNING: message was not integrity protected
[root@centops ~]# cat myfile.txt
this is a test to check for file encryption!!:
[root@centops ~]#


Method 2: using zip


We can use -e option to encrypt the file resulting from a zip operation. Given below is an example.

[root@centops ~]# zip -e  myfile.txt.zip myfile.txt
Enter password:
Verify password:
  adding: myfile.txt (stored 0%)
[root@centops ~]# ls -l myfile.txt.zip
-rw-r--r--. 1 root root 245 Oct 30 07:51 myfile.txt.zip
[root@centops ~]#
[root@centops ~]# unzip myfile.txt.zip
Archive:  myfile.txt.zip
[myfile.txt.zip] myfile.txt password:
 extracting: myfile.txt
[root@centops ~]# cat myfile.txt
this is a test to check for file encryption!!:
[root@centops ~]#


Method 3: Using openssl


HowTo : Encrypt a File

$ openssl enc -aes-256-cbc -salt -in file.txt -out file.txt.enc


openssl OpenSSL command line tool.
enc                 Encoding with Ciphers.
-aes-256-cbc The encryption cipher to be used.
-salt Adds strength to the encryption.
-in Specifies the input file.
-out Specifies the output file.

-salt option should ALWAYS be used if the key is being derived from a password.

The reason for this is that without the salt the same password always generates the same encryption key.

When the salt is being used the first eight bytes of the encrypted data are reserved for the salt: it is generated at random when encrypting a file and read from the encrypted file when it is decrypted.

HowTo : Decrypt a File

$ openssl enc -aes-256-cbc -d -in file.txt.enc -out file.txt


-d Decrypts data.
-in Specifies the data to decrypt.
-out Specifies the file to put the decrypted data in.

Base64 Encode and Decode:

Base64 encoding is a standard method for converting 8-bit binary information into a limited subset of ASCII characters.

It is needed for safe transport through e-mail systems, and other systems that are not 8-bit safe.

By default the encrypted file is in a binary format.
If you are going to send it by email, you have to save encrypted file in Base64-encode.

To encrypt file in Base64-encode, you should add -a option :

$ openssl enc -aes-256-cbc -salt -a -in file.txt -out file.txt.enc


-a Tells OpenSSL that the encrypted data is in Base64-ensode.

Option -a should also be added during decryption :

$ openssl enc -aes-256-cbc -d -a -in file.txt.enc -out file.txt

Non interactive Encrypt / Decrypt
Since the password is visible, this form should only be used where security is not important.

By default a user is prompted to enter the password.

If you are creating a BASH script, you may want to set the password in non interactive way, using -k option.
Public key cryptography was invented just for such cases.

Encrypt a file using a supplied password :

$ openssl enc -aes-256-cbc -salt -in file.txt -out file.txt.enc -k PASSWORD

Decrypt a file using a supplied password :

$ openssl enc -aes-256-cbc -d -in file.txt.enc -out file.txt -k PASSWORD

Thursday, 27 October 2016

Removing a zpool from a Solaris 11 zone

In this article I'll demonstrate how to remove a zpool assigned to a local zone. The zone needs to be in shutdown state for this to work.

I've shutdown the zone & entered zonecfg interface:

root@global:/etc/zones# zonecfg -z localzone

To view the assigned zpools type:

zonecfg:localzone> info zpool
zpool:
        name: dpool01
        storage: dev:/dev/dsk/c0t60002AC0000000000000453B0000935Dd0
zpool:
        name: dpool02
        storage: dev:/dev/dsk/c0t60002AC0000000000000453E0000935Dd0
zpool:
        name: expdmp
        storage: dev:/dev/dsk/c0t5000CCA0705EDCCCd0
zpool:
        name: expdmp1
        storage: dev:/dev/dsk/c0t60002AC000000000000045440000935Dd0

I need to remove expdmp. So I typed remove zpool name=expdmp but it gave me an error:

zonecfg:localzone> remove zpool name=expdmp
Zone localzone already installed; remove zpool not allowed in 'installed' state.
Use 'zoneadm mark' to mark the zone 'unavailable' or detach the zone
before removing a 'zpool' resource.
zonecfg:localzone> exit

So, I had to detach the zone.

root@global:/etc/zones# zoneadm -z localzone detach
Exported zone zpool: localzone_rpool
Exported zone zpool: localzone_dpool01
Exported zone zpool: localzone_dpool02
Exported zone zpool: localzone_expdmp
Exported zone zpool: localzone_expdmp1

Then remove the zpool:

root@global:/etc/zones# zonecfg -z localzone
zonecfg:localzone> remove zpool name=expdmp
zonecfg:localzone> verify
zonecfg:localzone> commit
zonecfg:localzone> exit

Once done, attach the zone & boot it.

root@global:/etc/zones# zoneadm -z localzone attach
Imported zone zpool: localzone_rpool
Imported zone zpool: localzone_dpool01
Imported zone zpool: localzone_dpool02
Imported zone zpool: localzone_expdmp1
Progress being logged to /var/log/zones/zoneadm.20161018T124012Z.localzone.attach
    Installing: Using existing zone boot environment
      Zone BE root dataset: localzone_rpool/rpool/ROOT/solaris-0
                     Cache: Using /var/pkg/publisher.
  Updating non-global zone: Linking to image /.
Processing linked: 1/1 done
  Updating non-global zone: Auditing packages.
No updates necessary for this image.

  Updating non-global zone: Zone updated.
                    Result: Attach Succeeded.
Log saved in non-global zone as /zones/localzone/root/var/log/zones/zoneadm.20161018T124012Z.localzone.attach
You have new mail in /var/mail/root

root@global:/etc/zones# zoneadm -z localzone boot

Wednesday, 26 October 2016

Migrating a zone from Solaris 11.3 to 11.1

The title of the article is misleading since it's not exactly a migration. I did have to rebuild the entire zone from scratch. This post is a description of a specific scenario & the procedure followed to complete the task at hand.

So, to start with I shut down the zone on my Solaris 11.3 global zone & detached it. The SAN admin exported all the LUNs from the 11.3 global zone to the Solaris 11.1 global zone. I could see the migrated disks on the destination system.
In our current environment we configure local zones such that they their root zpools on a dedicated SAN disk.
On the Solaris 11.1 host, the export pools were visible in zpool import output:

root@solaris11dot1:/tmp# zpool import | grep localzone
  pool: localzone_dpool01
        localzone_dpool01                        UNAVAIL  newer version
  pool: localzone_rpool
        localzone_rpool                            UNAVAIL  newer version


I did the zone configuration & when I tried to attach the zone on the Solaris 11.1 global zone, it began to import the two zpools belonging to the local zone & after a few seconds threw the following error:

root@solaris11dot1:/tmp# zoneadm -z localzone attach
cannot import 'localzone_rpool': pool is formatted using a newer ZFS version: unsupported version
zoneadm: zone 'localzone': failed to verify and/or setup all required zone zpool resources
zoneadm: zone 'localzone': attach not done
Manually correct the problem(s) reported above and attach the zone with:

        zoneadm -z localzone attach
or uninstall the zone with:
        zoneadm -z localzone uninstall

I tried to import the zpool manually but this also failed.

root@solaris11dot1:/tmp# zpool import localzone_rpool
cannot import 'localzone_rpool': pool is formatted using a newer ZFS version: unsupported version


So, the zfs version was upgraded in Solaris 11.3 & there is no backward compatibility.

To fix this problem, one method could be to ask the SAN admin to export the disks back to the Solaris 11.3 server, import the pools, destroy them & ask the SAN admin to export the disks again to the Solaris 11.1 server. But that would be a lengthy process.

So, here's the quick fix:

We can't delete an unavailable exported pool. So I did a forceful creation of the zpools with the required nomenclature on the disks used by the exported pools & then exported them.

 zpool create -f localzone_rpool c0t60002AC00000000000004A480000935Dd0
 zpool create -f localzone_dpool01 c0t60002AC00000000000004A490000935Dd0

 zpool export localzone_rpool
 zpool export localzone_dpool01

After this the zone attach worked & the zone was able to boot smoothly.

My VI cheat sheet


The VI editor is an indispensable tool for any UNIX system administrator. In this post I'd like to share some of the common vi commands & options that I use or try to use on a routine basis.


Leaving vi:

shift +zz -> write & quit.
wq -> write & save
q! -> quit without saving.
:w filename -> save ac copy of the currently open file with a new name.


vi modes:

command mode -> aAiIoOc -> inset mode
command mode  <- ESC <- insert mode
command mode -> : ! / ? -> promtpt/ex mode
command mode <- press enter <- promtpt/ex mode


Copying command sequences:

Copy an example command sequence: jhhkkkkll
The commands get copied to OSs' clipboard
Open a file in vi & while in command mode right click to paste the copied command sequence.
The result is that vi executes the command sequence.

Open multiple files for editing in a single vi command:

:n -> go to next file
:N -> go to previous file
:rew -> rewind to first file.
:r -> read a file into current file.



Basic cursor movement:

h -> move cursor left
l -> move cursor right
j -> down 1 line from current character
k -> up 1 line from current character

Moving around b/w text:

w -> forward a word
b -> backward a word
e -> forward to end of current word
) -> forward a sentence
( -> backward a sentence
} -> forward a paragraph
{ -> backward a paragraph

Note:
vi assumes end of sentences by . & paragraph changes by blank lines.
You can prefix a number before the movement commands


Moving by lines:

^ -> move cursor to beginning of current line
0 -> move cursor to beginning of current line
$ -> move cursor to end of current line
1G -> move to first line
G -> move to end of file
nG -> move to nth line of file
% -> matching paren/braces
ctrl+g -> display file status & line number


Scrolling:

ctrl+d -> scroll down half a screen
ctrl+u -> scroll up half a screen
ctrl+f -> scroll forward by a screen
ctrl+b -> scroll backward by a screen


Inserting text:

i -> insert before cursor
I -> insert at beginning of line
a -> append after cursor
A -> append at the end of line
o -> open a new line below current line
O -> open a new line above current line

File Management:

:w -> write without quitting
:q -> quit without writing.
:q! -> quit without saving changes.


Deleting text:

x -> delete current character
dd -> delete current line
dw -> delete current word
d^ -> delete to beginning of line
d$ -> delete to end of line

Note:
You can prefix a number before the deletion commands


Changing text:

r -> r followed by character replaces current character with the character typed with r
R -> override mode i.e the characters you type replace the characters already present on the cursor prompt.
~ -> changes case of current characters on the cursor


Undo, redo & repeat:

u -> undoes last change
ctrl+r -> redoes last change (undoes undo)
U -> undoes all changes on current line
. -> repeats last change


Delete, yank & put:

dd -> delete (cut) the line
yy -> copy the line
dx -> delete an amount
yx -> copy an amount
y$ -> copy from cursor position to end of the line
y^ -> copy from cursor position to beginning of the line
p -> put after cursor
P -> put before cursor

Note:
delete & yank go into vi's buffers & the buffer holds only the most recent yank/delete
As with delete, y can use a number or movement command


Searching text:

/ -> search for a pattern

Using regex in search patterns:

. -> a search for a.c yields abc or aec i.e. the . (dot) replaces exactly one character.
\ -> the backslash is used to remove special meaning of special characters like ., $ & ^
^string -> search for lines beginning with the searched string.
$string -> search for lines ending with the searched string.
[] -> matches a character set. The expression in the brackets stands for a single character in the set.


Search & replace:

:%s/old/new/g -> replaces every occurance of old with new in the entire file.
:%s/the[ym]/(&)/g -> enclose the search results in parenthesis throughout the file.
:%s/\(he\) \(is\)/\2 \1/ -> replace all occurances of 'he is' with 'is he'.

Indenting:

>> -> incdents current line (inserts a tab)
<< -> outdents current line (removes a tab)

Note:
Both >> & << can use a number prefix to indent/outdent multiple lines.


Filtering through shell commands:

!! ->  filters current line through shell command
n!! -> filters n lines
!% -> filters to matching pattern
!{ -> filters previous paragraph
!} -> filters next paragraph

Although this is a cheat sheet but I feel the need to elaborate on filtering. Vi allows the usage to any shell command that accepts some type of text as input, manipulate the text & provide output.
This way we can use the text manipulation capabilities of awk, sed & tr from within vi.

Using lines & line ranges in colon commands:

: line [,line] command -> performs commands on lines specified.
n -> line number
. -> current line
$ -> last line of file
/regex/ -> regular expression
% -. all lines.


Here are a couple of examples:

:%>> -> indent all lines.
:.,$ ! tr a-z A-Z -> change all lines between current line & last line of the file to upper case.
: /the/, /end/ d -> delete everything between the strings 'the' & 'end'

One liner for a more readable nslookup output

nslookup is a common command run to verify host name resolution. If we need to check information for a couple of systems, it' s easy.
If we need to validate the details for hundreds of servers then we can run the for loop over the host names and provide the information but it won't be very readable as it'll contains the name of DNS nameserver in every iteration of the loop.
So I created a quick one liner to produce a neat (relatively neat) output.

So, I put the host names in a file named pt2dns like below:

#cat pt2dns
test27367-bkp
test27368-bkp
test27369-bkp
test27370-bkp
test27371-bkp
test27372-bkp
test27373-bkp
test27374-bkp
test27375-bkp
-------------
-------------

Then I ran the below one liner:

for i in $(<pt2dns) ; do echo "server name " `nslookup  $i | awk  '/example/ {print $2}'` "has an IP address" `nslookup  $i | awk  '/172/ {print $2}'` ; done


I did an awk pattern search for the domain name the first time & the subnet name in the second awk pattern search.

This produces the following output:

server name  test27367-bkp.example.com.in has an IP address 172.27.27.202
server name  test27368-bkp.example.com.in has an IP address 172.27.27.203
server name  test27371-bkp.example.com.in has an IP address 172.27.27.204
server name  test27372-bkp.example.com.in has an IP address 172.27.27.205
server name  test27373-bkp.example.com.in has an IP address 172.27.27.206
server name  test27374-bkp.example.com.in has an IP address 172.27.27.207

This is definitely easier to read & copy out in a file/excel work sheet compared to the normal nslookup output.

Tuesday, 25 October 2016

Quick 2 liner to measure used global zone resources

I have a situation where I have a lot of local zones with capped resources running on my global zones.

root@myglobalzone:~# zoneadm list | grep -v global
localzone60051
localzone60043
localzone60063
localzone30025
localzone60049
localzone30061
localzone60039
localzone60105
localzone60101
localzone60161
localzone50059
localzone30081
localzone30035
localzone30083

I need to find the total capped physical memory & the dedicated CPUs used by the local zones so that I can ascertain if the global zone can accommodate more local zones.

I could measure the used capacities by checking the zonecfg for each zone one by one, noting it down & summing the total. That would be a boring and time consuming process.

Here is a quick 2 line trick to get the required information within seconds:

root@myglobalzone:~#  for i in $(zoneadm list | grep -v global); do zonecfg -z $i info dedicated-cpu | grep ncpus | awk '{print $2}'| tr "\n" "+" ; done
16+16+4+48+16+4+16+8+8+8+12+128+32+64+root@myglobalzone:~#

root@myglobalzone:~# echo "16+16+4+48+16+4+16+8+8+8+12+128+32+64+" | sed "s/.$/ /"  | bc
380
root@myglobalzone:~#
root@myglobalzone:~# for i in $(zoneadm list | grep -v global); do zonecfg -z $i info capped-memory | grep physical | awk '{print $2}'| tr "\n" "+" |tr -d "G"; done
16+16+8+64+16+12+16+16+16+16+36+192+32+64+root@myglobalzone:~#

root@myglobalzone:~# echo "16+16+8+64+16+12+16+16+16+16+36+192+32+64+"  | sed "s/.$/ /"  | bc
520

Hope this time saver helps!

Monday, 17 October 2016

Script for identifying multiple disks on a Linux server

This is a short script for identifying 3 PAR disks allocated to a physical server running Linux with multipathing enabled.

Put the disk WWN details provided by the SAN admin in a file called detail.txt.

Now run the following for loop to extract the mpath devices corresponding to the disk WWNs.

#!/bin/bash

for i in `cat detail.txt | awk '{print $3}' |  egrep -v 'showvlun|VV_WWN' | uniq -u`

do

echo "corresponding to 

 `cat detail.txt | awk '{print $3}' |  egrep -v 'showvlun|VV_WWN' | uniq -u | grep -i $i` disk is 
  `multipath -ll | grep -i -A1 $i |awk '{print $1}'` "
  
done

The output of the script is as follows:

corresponding to

 60002AC00000000000004BD20000935D disk is
  mpathv
size=500G
corresponding to

 60002AC00000000000004BD30000935D disk is
  mpatht
size=500G
corresponding to

 60002AC00000000000004BD40000935D disk is
  mpaths
size=500G
corresponding to

 60002AC00000000000004BD50000935D disk is
  mpathu
size=500G
corresponding to

 60002AC00000000000004BD60000935D disk is
  mpathw
size=500G

Primer on Expect scripting


This article is an elementary quick start towards learning expect scripting. Expect is a scripting language used to provide input to an interactive program non-interactively. The most well-known use of expect for UNIX administrators in feeding passwords on the command line non-interactively which can help speed up scripts by miles.

Expect is not installed in the OS by default but is available on the base repo in the OS ISO.

The following  expect commands are used when automating an interactive process over the shell:

  • send – to send the strings to the process
  • expect – wait for the specific string from the process
  • spawn – to start the command
  • timeout - time after which an expect script will exit.
  • set - declare variables for use in the code.


The path for the expect interpreter is /usr/bin/expect.

I'd just like to explore some avenues where us administrators make use of expect to make our life easier.

Common anatomy of an expect script:

#!/usr/bin/expect

##variable declaration (optional)##

##spawn <command> (starting the interactive session)##
##expect "password:" (expect a password prompt)##
##send "password\r" (pass the password string to the prompt non-interactively)##
##expect eof (end of script)##


Example 1: Change a user's password non-interactively.

Here's the code:

#!/usr/bin/expect

set timeout 10

set user [lindex $argv 0]

set password [lindex $argv 1]

spawn passwd $user

expect "password:"
send "$password\r"
expect "password:"
send "$password\r"

expect eof


The test looks like this:

# ./e3.sh testuser 123

spawn passwd testuser
Changing password for user testuser.
New password:
BAD PASSWORD: it is WAY too short
BAD PASSWORD: is too simple
Retype new password:
passwd: all authentication tokens updated successfully.


Example 2: Login using expect & start an interactive session

#!/usr/bin/expect

set timeout 1

set login "test"
set addr "centdb"
set pw "123"

spawn ssh -t $login@$addr
expect "$login@$addr\'s password:"
send "$pw\r"

interact


Example 3: Run shell commands within an expect script

#!/usr/bin/expect

set timeout 1

set login "test"
set addr "centdb"
set pw "123"

spawn ssh -t $login@$addr
expect "$login@$addr\'s password:"
send "$pw\r"
expect "$"  # put here string from your server prompt
send "mkdir expect_testing\r"
expect "$" 
send "ls -l expect_testing\r"
expect "$" 

expect eof


Example 4: Using expect inside a bash shell script

#!/bin/bash

expect <<'EOF'

spawn passwd sa

expect "password:"
send "123\r"
expect "password:"
send "123\r"
expect eof

EOF

Example 5: Using expect within a bash shell script to initiate an ssh session

#!/bin/bash

##beginning expect block for entering password non-interactively##
/usr/bin/expect << EOL

set timeout 1
expect <<'EOF'

spawn ssh 192.168.87.129

expect "password:"
send "123\r"
expect "# "
send "uname -a;exit\r"
expect eof
EOF
##end of script##


Example 6: Running an expect one-liner using -c option (interactive session followed)

sa@buntu:~$ expect -c "spawn ssh sa@buntu; expect \"password:\";send \"123\r\";interact"


Example 7: Expect one-liner using -c option in a non-interactive session.

 expect -c "spawn ssh 192.168.87.129; expect \"password:\";send \"123\r\";expect \"# \"; send \"uname -a;exit\r\";expect eof"


The above examples are common uses of the expect script. 

I hope this helps someone somewhere save a lot of time spent entering passwords.

Script to identity & label disks in Solaris

While working with Oracle databases running on Solaris servers, often we come across activities involving storage allocation of multiple disks for usage by the database. Those familiar with Oracle ASM would be aware that for disks to be used by Oracle ASM they must be labeled such that all the disk space is assigned to slice 6 starting from cylinder 1.

This is a small script I wrote to match WWNs to disk names if the storage is being allocated from HP 3PAR storage arrays.

The SAN administrator will usually provide a text file consisting of the WWN details looking something like the small snippet below:

Active VLUNs
Lun VVName               -------------VV_WWN------------- HostName      -Host_WWN/iSCSI_Name-  Port Type Status ID
 30disk_root_desc 60002AC00000000000004A570000935D server_loc 21000024FF88018A      0:2:2 host active  1
 30disk_root_desc 60002AC00000000000004A570000935D server_loc 21000024FF880186      1:2:1 host active  1
 30disk_root_desc 60002AC00000000000004A570000935D server_loc 21000024FF880186      1:2:1 host active  1
 30disk_root_desc 60002AC00000000000004A570000935D server_loc 21000024FF88018A      1:2:2 host active  1
 30disk_root_desc 60002AC00000000000004A570000935D server_loc 21000024FF880186      2:2:1 host active  1
 30disk_root_desc 60002AC00000000000004A570000935D server_loc 21000024FF88018A      2:2:2 host active  1
 30disk_root_desc 60002AC00000000000004A570000935D server_loc 21000024FF880186      3:2:1 host active  1
 30disk_root_desc 60002AC00000000000004A570000935D server_loc 21000024FF88018A      3:2:2 host active  1
------------------------------------------------------------------------------------------------------------------
  8 total


Copy the contents of the text file into a file on the server & name it detail.txt.

Here is the script:

#!/bin/bash

for i in `cat detail.txt | awk '{print $3}' |  egrep -v 'showvlun|VV_WWN' | uniq -u` 
do

echo "Corresponding to  

`cat detail.txt | awk '{print $2,$3}' |  egrep -v 'Templates|VVName|total|VLUNs|cli%' | uniq -u | cut -d "_" -f2,3,4 | grep $i | sed '/^$/d' ` 

disk is `echo | format | grep -i $i | awk '{print $1,$6}' | egrep -v '3PARdata|scsi|alt'` "

done


The output of this script will be as follows:


Corresponding to

root_desc 60002AC00000000000000BEE0000935C

disk is c0t60002AC00000000000000BEE0000935Cd0: 149.99GB
Corresponding to

bin_desc 60002AC00000000000000BEF0000935C
 
disk is c0t60002AC00000000000000BEF0000935Cd0: 50.00GB


The output prints the VV name, WWN, the matching disk name & the size of the disk. 


To label all the disks in one go, put the names of the disks in a file named disks.txt & run the following for loop:

for i in `cat disks.txt`
do
printf  "p\n0\n\n\n0\n0\n1\n\n\n0\\n0\n6\n\n\n1\n$\nlabel\nyes\nquit\nquit" | format -d $i
done

The above for loop will label all the disks assigning all space to slice 6 starting at cylinder 1.

Monday, 3 October 2016

Troubleshooting the error: "Unexpected failure. Password file/table unchanged." on Solaris 11

I recently did some modifications & a bit of hardening to the zone I whose snapshot I use as a sort of template for other zones. while creating users I found that I wasn't allowed to set their passwords or change passwords of existing users.
I kept getting "Unexpected failure. Password file/table unchanged." when modifying passwords.

root@ztemplate:/etc/default# passwd test
New Password:
Unexpected failure. Password file/table unchanged.

Now, My first instinct from what I've read pointed me to PAM but unfortunately the file /etc/pam.conf was unused i.e. everything was commented.

After a bit of trial & error I found the issue.

It was a misconfiguration in /etc/default/passwd file in the password complexity tunables section:

MINDIFF=3
MINALPHA=2
MINUPPER=2
MINLOWER=2
MAXREPEATS=0
MINSPECIAL=1
MINDIGIT=1
WHITESPACE=YES
MINNONALPHA=1

Actually, MINNONALPHA parameter cannot be used in conjunction with MINSPECIAL & MINDIGIT.

When I commented out MINNONALPHA the parameter I was able to update passwords again flawlessly keeping in line with the password complexity tunables.

Here's a quick description of the above mentioned tunables:

MAXREPEATS
Maximum number of allowable consecutive repeating characters. If MAXREPEATS is not set or is zero (0), the default is no checks

MINALPHA
Minimum number of alpha character required. If MINALPHA is not set, the default is 2.

MINDIFF
Minimum differences required between an old and a new password. If MINDIFF is not set, the default is 3.

MINDIGIT
Minimum number of digits required. If MINDIGIT is not set or is set to zero (0), the default is no checks. You cannot be specify MINDIGIT if MINNONALPHA is also specified.

MINLOWER
Minimum number of lower case letters required. If not set or zero (0), the default is no checks.

MINNONALPHA
Minimum number of non-alpha (including numeric and special) required. If MINNONALPHA is not set, the default is 1. You cannot specify MINNONALPHA if MINDIGIT or MINSPECIAL is also specified.

MINSPECIAL
Minimum number of special (non-alpha and non-digit) characters required. If MINSPECIAL is not set or is zero (0), the default is no checks. You cannot specify MINSPECIAL if you also specify MINNONALPHA.

MINUPPER
Minimum number of upper case letters required. If MINUPPER is not set or is zero (0), the default is no checks.

WHITESPACE
Determine if white space characters are allowed in passwords. Valid values are YES and NO. If WHITESPACE is not set or is set to YES, white space characters are allowed.


I hope this helps someone dealing with this error in the future.

Saturday, 1 October 2016

Managing remote Linux systems with OpenLMI



OpenLMI stands for Open Linux Management Infrastructure. It aims at improving productivity of system administrators by providing a standardized remote API to management functions. OpenLMI was introduced as part of RHEL 7 beta & can be used to manage systems running RHEL, Centos & fedora. Support for other linux variants might be added in the future.

It has the following key features:

  • Configure, manage and monitor storage (local & remote)
  • Configure and manage networks.
  • Install and manage software.
  • Add and manage users.
  • Manage system services.
  • Manage power state.
  • Query system and hardware configuration.
  • System Logging.
  • Active firewall management.
  • Join IPA and MS Active Directory domains.


OpenLMI consists of two components:

  1. LMI metacommand (A command line utility to perform discovery and operations on remote managed systems. For example, it can start a printing service on remote system)
  2. LMIShell (A high-level python-based WBEM client, that can be used for scripting or as an interactive shell to manage remote systems)

When configured OpenLMI works in a server-client model. We configure the server component in the management host & use it to administrator client hosts.

Since this is a lab setup I've shutdown firewalld & set SELinux to permissive.

Installation & configuration:


For the purpose of this demonstration I spun up two CentOS hosts, one to be the server & other to be the client.

Configuring the server/management node:

Install the openlmi-tools & openlmi-scripts packages.

#yum install openlmi-tools openlmi-scripts* -y

you need to have EPEL repository enabled before attempting to install these packages.

Configuring the client node:

On the client to be managed by the server node install the openlmi package.

#yum install openlmi -y

This is a metapackage that installs the OpenLMI infrastructure and a base set of OpenLMI Providers.

Now start the component in charge of receiving instructions (the object broker pegasus)

#systemctl start tog-pegasus.service

To have the service automatically started when the system boots, use the command:

# systemctl enable tog-pegasus.service

We need to give a password to the pegasus user:

#passwd pegasus 


Server client connectivity:

In order to allow the management node to connect to the client node we need to get the certificate for the client node:

# scp 192.168.44.137:/etc/Pegasus/ca.crt /etc/pki/ca-trust/source/anchors/devbox-cert.pem

Add the certificate to the management nodes' trust store:

#[root@instructor ~]# update-ca-trust extract
p11-kit: the CKA_X_CRITICAL attribute is not valid for the object
p11-kit: couldn't load file into objects: /usr/share/pki/ca-trust-source/ca-bundle.supplement.p11-kit
p11-kit: the CKA_X_CRITICAL attribute is not valid for the object
p11-kit: couldn't load file into objects: /usr/share/pki/ca-trust-source/ca-bundle.supplement.p11-kit
p11-kit: the CKA_X_CRITICAL attribute is not valid for the object
p11-kit: couldn't load file into objects: /usr/share/pki/ca-trust-source/ca-bundle.supplement.p11-kit
p11-kit: the CKA_X_CRITICAL attribute is not valid for the object
p11-kit: couldn't load file into objects: /usr/share/pki/ca-trust-source/ca-bundle.supplement.p11-kit
p11-kit: the CKA_X_CRITICAL attribute is not valid for the object
p11-kit: couldn't load file into objects: /usr/share/pki/ca-trust-source/ca-bundle.supplement.p11-kit

You can ignore the errors.


Testing:

To test the configuration, type the following command to connect to the client node (devbox in this example)) from the management node (instructor in this example):

[root@instructor ~]# lmi -h devbox

Once connected we are brought into the LMIShell & from here we can gather information about the client node & also perform a plethora of administrative functions on the client.

When we run the first command from the LMIShell we'll need to authenticate with the pegasus user but that's a one time thing.

So, if we need to check the status of sshd service type the following command:

lmi> service show sshd.service
username: pegasus
password:
Name=sshd
Caption=OpenSSH server daemon
Enabled=Yes
Status=Running

If we want to stop & start a service we do by typing service stop <service name> followed by service start <service name>

lmi> service show crond.service
Name=crond
Caption=Command Scheduler
Enabled=Yes
Status=Running
lmi> service stop crond.service
lmi> service show crond.service
Name=crond
Caption=Command Scheduler
Enabled=Yes
Status=Stopped - OK
lmi> service start crond.service
lmi> service show crond.service
Name=crond
Caption=Command Scheduler
Enabled=Yes
Status=Running
lmi>

To list out local storage devices present on a client node type:

lmi> storage list
Name                  Size        Format
/dev/sda              21474836480 MS-DOS partition table
/dev/sdb              5368709120  physical volume (LVM)
/dev/sr0              5368709120  Unknown
/dev/mapper/repo-epel 5364514816  xfs
/dev/sda1             314572800   xfs
/dev/sda2             2147483648  swap
/dev/sda3             19011731456 xfs

To get a list of available commands type ? 

lmi> ?

Static commands
===============
EOF  exit  help

Application commands (type help <topic>):
=========================================
file   hwinfo    locale  power   selinux  sssd     sw      user
group  journald  net     realmd  service  storage  system

Built-in commands (type :help):
===============================
:..  :cd  :pwd  :help


Conclusion:

I've read about OpenLMI being compared to Puppet in some places. I'm not sure how apt is this comparison. More information about OpenLMI can be found on its official website. Some documentation on OpenLMI can be found here.

Using capture groups in grep in Linux

Introduction Let me start by saying that this article isn't about capture groups in grep per se. What we are going to do here with gr...