Simple Python scp wrapper

Inspired by the following article I decided to write a simply python scp wrapper which is based on the ideas taken from the perl script also mentioned on the same page.

The whole point of this wrapper is dead simple: to allow certain users scp into their specific directories with out granting full ssh access.

The configuration file is straightforward:
/opt/etc/scponly.conf

scponly=/tmp:/home/scptest

Below is the wrapper in all its amature (must admit I’m not a developer at all) glory ;-)

/opt/bin/scp-wrapper.py:

#!/usr/bin/python
 
import sys
import os
import pwd
from subprocess import call, Popen, PIPE
import re
 
def fail(msg):
    """(str) -> str Prints error message to STDOUT
    >>> fail('Error')
    Error
    >>> fail('Wrong argument')
    Wrong argument
    """
    
    print msg
    sys.exit(1)
 
def access_verify(user, dirto):
    """(str) -> Boolean Returns TRUE iff user is allowed to scp
    """
  
    if user in users:
        for d in users[user]:
            print user, dirto[-1:],  d.rstrip()[-1:], dirto[:-1] == d.rstrip(), dirto == d[:-1].rstrip()
            if dirto == d.rstrip():
                return True
            elif (dirto[-1:] == "/" or d.rstrip()[-1:] == "/") and (dirto[:-1] == d.rstrip() or dirto == d.rstrip()[:-1]):
                return True
            else:
                return False
    return False
 
if __name__ == '__main__':
 
    users = {}
    conf = "/usr/local/etc/scponly.conf"
 
    # Reading configuration file
 
    fp = open(conf, "r")
    for line in fp.readlines():
        record = line.split("=")
        users[record[0]] = record[1].split(":")
    fp.close()
  
    command = sys.argv[2]
    scp_args = command.split()
 
    if scp_args[0] != "scp":
        msg = "Only scp is allowed"
        fail(msg)
 
    if scp_args[1] != "-t" and not "-f" and not "-v":
        msg = "Restricted; only server mode is allowed"
        fail(msg)
 
    destdir = scp_args[-1]
   if not os.path.isfile(destdir) or os.path.isfile(destdir):
        destdirv = os.path.dirname(destdir)
    else:
        destdirv = destdir
    uname = pwd.getpwuid(os.getuid())[0]
    if not access_verify(uname, destdirv):
        msg = "User " + uname + " is not authorized to scp to this host."
        fail(msg)
    else:
        scp_args.pop(0)
        if len(scp_args) == 2:
            call(["/usr/bin/scp", scp_args[0], destdir])
        elif len(scp_args) == 3:
            call(["/usr/bin/scp", scp_args[0], scp_args[1], destdir])

Just create a new user and set its shell (-s option in useradd) to /opt/bin/scp-wrapper.py. Hope it helps.
Enjoy and have fun!

OpenLDAP do_syncrep retrying attempts

Do you observe the error messages on your Linux OpenLDAP replica or master server similar to the ones listed below:

May 16 12:05:21 ldapserver1 slapd[5420]: do_syncrep2: rid=005 (-1) Can’t contact LDAP server
May 16 12:05:21 ldapserver1 slapd[5420]: do_syncrepl: rid=005 rc -1 retrying (4 retries left)
May 16 12:05:21 ldapserver1 slapd[5420]: do_syncrep2: rid=002 (-1) Can’t contact LDAP server
May 16 12:05:21 ldapserver1 slapd[5420]: do_syncrepl: rid=002 rc -1 retrying (4 retries left)
May 16 14:05:27 ldapserver1 slapd[5420]: do_syncrep2: rid=005 (-1) Can’t contact LDAP server
May 16 14:05:27 ldapserver1 slapd[5420]: do_syncrepl: rid=005 rc -1 retrying (4 retries left)
May 16 14:05:27 ldapserver1 slapd[5420]: do_syncrep2: rid=002 (-1) Can’t contact LDAP server
May 16 14:05:27 ldapserver1 slapd[5420]: do_syncrepl: rid=002 rc -1 retrying (4 retries left)
May 16 16:05:32 ldapserver1 slapd[5420]: do_syncrep2: rid=005 (-1) Can’t contact LDAP server
May 16 16:05:32 ldapserver1 slapd[5420]: do_syncrepl: rid=005 rc -1 retrying (4 retries left)
May 16 16:05:32 ldapserver1 slapd[5420]: do_syncrep2: rid=002 (-1) Can’t contact LDAP server
May 16 16:05:32 ldapserver1 slapd[5420]: do_syncrepl: rid=002 rc -1 retrying (4 retries left)

If yes and these messages seem to pop up every two hours then you might consider updating the following sysctl parameters:

net.ipv4.tcp_keepalive_time
net.ipv4.tcp_keepalive_intvl
net.ipv4.tcp_keepalive_probes 

Where:

  • net.ipv4.tcp_keepalive_time – How often TCP sends out keepalive messages when keepalive is enabled. Default: 2hours.
  • net.ipv4.tcp_keepalive_intvl – How frequently the probes are send out. Multiplied by
    tcp_keepalive_probes it is time to kill not responding connection, after probes started. Default value: 75sec i.e. connection will be aborted after ~11 minutes of retries.
  • net.ipv4.tcp_keepalive_probes – How many keepalive probes TCP sends out, until it decides that the connection is broken. Default value: 9.

Hopefully that would make your OpenLDAP replication more reliable.

How to create new thin devices using symcli and add them to a masking view and a storage group

Below are the steps that I used recently to create and present a few thin devices. More precisely:

  • Boot disk – 50GB
  • Two TDEVs 150GB each. One for data and the other for logs.
  1. Create a nested initiator group:
  2. symaccess -sid VMAX-SID create -name IG_SERVERNAME_HBA0 -type initiator -consistent_lun
    symaccess -sid VMAX-SID -name IG_SERVERNAME_HBA0 -type initiator -wwn 50060b0000c30e38 add
    
    symaccess -sid VMAX-SID create -name IG_SERVERNAME_HBA1 -type initiator -consistent_lun
    symaccess -sid VMAX-SID -name IG_SERVERNAME_HBA1 -type initiator -wwn 50060b0000c30e3a add
    
    symaccess -sid VMAX-SID create -name IG_SERVERNAME -type initiator -consistent_lun
    symaccess -sid VMAX-SID -name IG_SERVERNAME -type initiator -ig IG_SERVERNAME_HBA0 add
    symaccess -sid VMAX-SID -name IG_SERVERNAME -type initiator -ig IG_SERVERNAME_HBA1 add
    
  3. Show initiator group’s details:
  4. symaccess -sid VMAX-SID show IG_SERVERNAME -type initiator -detail
    
  5. Create storage group:
  6. symaccess -sid VMAX-SID create -name SG_SERVERNAME -type storage
    
  7. Create thin devices and bind them to a pool:
  8. symconfigure -sid VMAX-SID -cmd "create dev count=1, size=50GB, emulation=fba, config=TDEV, binding to pool=Pool1;" prepare
    symconfigure -sid VMAX-SID -cmd "create dev count=1, size=50GB, emulation=fba, config=TDEV, binding to pool=Pool1;" commit
    
    symconfigure -sid VMAX-SID -cmd "create dev count=2, size=150GB, emulation=fba, config=TDEV, binding to pool=Pool1;" prepare
    symconfigure -sid VMAX-SID -cmd "create dev count=2, size=150GB, emulation=fba, config=TDEV, binding to pool=Pool1;" commit
    

    Don’t forget to record the device IDs. In my case they were the following: 016B (50GB),016C (150GB) and 005F (150GB) respectively.

  9. Add new devices to our storage group:
  10. Adding disks to the storage group and further masking require additional explanation. As all we know, boot device must be lun 0. But you can’t assign a specific LUN ID to every new device in one go during the masking step since there is only a single option, i.e. -lun, which tells the starting LUN ID. BUT, and that’s important, this option, -lun, would assign the starting LUN ID to a device with the smallest ID. And in my case that would be TDEV 005F and that wasn’t what my task was all about. To overcome that hurdle, I firstly added devices 016B (boot disk) and 016C (data disk) and masked them to a storage group with -lun 0 options. By doing that, I could guarantee that my boot device would be assigned LUN 0 (obviously 016B (hex) is smaller than 016C (hex)). After that all I had to do is to add the third data device to the storage group and it would be automatically assigned the next available LUN ID.

    symaccess -sid VMAX-SID -name SG_SERVERNAME -type storage add devs 016B,016C
    
  11. Create a new masking view and assign LUN IDs to the devices:
  12. symaccess -sid VMAX-SID create view -name MV_SERVERNAME -sg SG_SERVERNAME -pg PG_NAME -ig IG_SERVERNAME -lun 0
    
  13. Add third device to the storage group:
  14. symaccess -sid VMAX-SID -name SG_SERVERNAME -type storage add devs 005F
    
  15. Associate the storage group with a FAST VP policy:
  16. symfast -sid VMAX-SID -fp_name FAST_VP_NAME  associate -sg SG_SERVERNAME
    
  17. View the details of newly created masking view:
  18. symaccess -sid VMAX-SID show view MV_SERVERNAME
    

Job done!