Showing posts with label RBAC. Show all posts
Showing posts with label RBAC. Show all posts

Friday, July 11, 2014

Removable ZFS pool

Well, I confess the title "Removable ZFS pool" is a bit "forced".
You know, the idea is to visit how to use ZFS on removable media.
At first, this may seen useless, but it can be powerful and effective for:
  • Data safety;
  • Data migration;
  • Data mobility.

The procedure is reasonably well documented by Oracle.
Anyway I think it deserves to be visited yet once more.

I won't get into the underlying detail of physical devices.
For more detail refer to Dynamically Configuring Devices documentation.
I've found deeper detail on another blog post that may also be interesting.
The bottom line of the physical issues will be some device name under /dev.

So for this post I'll be more than happy to exemplify with a 256 MB RAM disk.
In fact I have a somewhat overlapping but specific post on RAM ZFS pools.
As you know, a RAM disk isn't persistent across reboots.
Thus, it will do as a temporary (removable) device.
The underlying device on this post will be:
/dev/ramdisk/d-01
If you plug an USB hard-disk the device name will be different, of course!

Depending on the situation, it's best to temporarily disable the Removable Media Services so that it won't preclude you in manually managing removable devices such as in this particular case.

# svcadm disable -t rmvolmgr

With the root or equivalent role one can find out device names with format:

$ echo | pfexec format
Searching for disks...done
AVAILABLE DISK SELECTIONS:
...

Another very cool method (I've got to know checking other blog) is:
(rmformat is also extensively described in the official documentation)

$ rmformat
Looking for devices...
     1. Logical Node: /dev/rdsk/c3t1d0p0
        Physical Node: /pci@0,0/pci1b0a,df@1f,2/cdrom@1,0
        Connected Device: HL-DT-ST DVDRAM GH22NS40  NL02
        Device Type: CD Reader
    Bus:
    Size:
    Label:
    Access permissions:

...

Once the physical device is known, decide which mountpoint to use.
I assume /mnt is not being used, but it could be any other mountpoint.
Also, it's probably good to have this removable ZFS pool encrypted!
(it could also be compressed, have quotas, reservations and so on...)
The ZFS pool creation command could be as follows:

# zpool create -R /mnt -O encryption=on Backup /dev/ramdisk/d-01
Enter passphrase for 'Backup':
Enter again:

# zpool list Backup
NAME    SIZE  ALLOC  FREE  CAP  DEDUP  HEALTH  ALTROOT
Backup  250M   136K  250M   0%  1.00x  ONLINE  /mnt


# zfs list /mnt
NAME    USED  AVAIL  REFER  MOUNTPOINT
Backup  100K   218M    33K  /mnt


There are a few details to note that are not usually mentioned.
The -R option implies the altroot and cachefile ZFS pool properties.
The value of the cachefile shows that the ZFS pool isn't persistent across reboots.

# zpool get altroot,cachefile Backup
NAME    PROPERTY   VALUE  SOURCE
Backup  altroot    /mnt   local
Backup  cachefile  none   local


For the encryption, note the default behavior of prompting for a passphrase.
There are other options, but this seems particularly handy in this case.
Also note that the default checksum has changed to sha256-mac.
There are other values for the checksum property as well.

# zfs get encryption,checksum Backup
NAME    PROPERTY    VALUE       SOURCE
Backup  encryption  on          local
Backup  checksum    sha256-mac  local


Note:
250 MB out of 256 MB of the RAM disk is available to the ZFS pool.
This represents approximately 97.7% of the RAM disk space.
For this case, an overhead around 2.3% (not bad).

218 MB out 250 MB of the ZFS pool is available to the ZFS file system.
This represents approximately 87.2% of the ZFS pool space.
For this case, an overhead around 12.8% (perhaps not bad).

Consider the total overhead in 218 MB out 256 MB.
As only around 85.2% is available, the total overhead is around 17.5%.

Now consider the 80% usage limit recommendation.
80% of 218 MB is around 174.4 MB which is about 68.1% of 256 MB.
Now we can see that the total overhead is pretty hard: 31.9%.
But ZFS is so good that this doesn't seem so hard after all.
And it's better than some competitors' 40% penalty.
 
Now the removable and encrypted ZFS file system is ready for use.
All the power of ZFS is available; that's remarkable!

When done it's time to remove the ZFS pool (and file system, of course).
This is easily done by simply exporting the ZFS pool.
The ZFS file system is automatically unmounted.
Also, the ZFS pool is forgotten by the system.

# zpool export Backup

# zpool list Backup
cannot open 'Backup': no such pool


# zfs list /mnt
NAME                   USED  AVAIL  REFER  MOUNTPOINT
rpool/ROOT/11.1.20.5  12.2G   191G  6.80G  /


With a real removable storage device, now follow the procedure to disconnect it.
This procedure will vary according to the device, so I won't cover it.
No data is lost as long as the underlying device is "preserved".
That is, all the encrypted data still rest there for later.

In this particular post, the underlying storage device is a RAM disk.
This means that /dev/ramdisk/d-01 will be intact until system shutdown.
Of course, for this post, I'm assuming the device won't be reused or manually destroyed.

Later (any lapse of time, for a real underlying storage device) when it's time to use again the removable ZFS pool it suffices to reconnect the storage device to the system (a procedure I'm not covering) and import the ZFS pool.

After reconnecting the physical storage device but right before importing the ZFS pool, it's possible (and recommended) to query which ZFS pools can be successfully imported for sure. In this query procedure, the system, by default, looks up storage devices under /dev/dsk unless the -d option specifies somewhere else (/dev/ramdisk in this particular post).

# zpool import -d /dev/ramdisk
  pool: Backup
    id: 500609675252772792
 state: ONLINE
action: The pool can be imported ...
config:


    Backup                   ONLINE
      /dev/ramdisk/d-01      ONLINE

 
To actually import the removable ZFS pool an additional and important point is to use the -R option as this is a removable ZFS pool. Not doing so will cache the pool information for persistent remount at each boot, which is presumably not what I want or need.

If the purpose is just to browse and read already existent data, the -o readonly=on will assure no data is accidentally or inadvertently modified.

By the way, as the removable ZFS pool in encrypted, the passphrase will be immediately prompted in order to clear the access to the stored data.

# zpool import -d /dev/ramdisk -R /mnt -o readonly=on Backup
Enter passphrase for 'Backup':

# zpool get readonly Backup
NAME    PROPERTY  VALUE  SOURCE
Backup  readonly  on     -


# touch /mnt/test
touch: cannot create /mnt/test: Read-only file system


# zpool export Backup

If otherwise the intention was really a read/write access possibility:

# zpool import -d /dev/ramdisk -R /mnt Backup
Enter passphrase for 'Backup':

Now it's possible to write (data and metadata) to the ZFS pool:
 
# zfs create -o quota=10m Backup/Project

# zfs list -r Backup
NAME            USED  AVAIL  REFER  MOUNTPOINT
Backup          154K   218M    35K  /mnt
Backup/Project   33K  9.97M    33K  /mnt/Project


When done using the ZFS pool:

# zpool export Backup
 
Removable ZFS pools:
One more cool Solaris stuff !
   

Wednesday, April 30, 2014

Administrative files & pfedit

Here's another great tool from the Solaris 11.1  arsenal: pfedit (1M).
It's the per-file authorized edit of administrative text files.

Great, great tool! And it's even audit enabled!
Imagine the cumbersome work to approach (not match) it with sudo!

For the auditing I think it's worthy to quote the man page:
          ..., in  the  case  of  a  successful  update,  an
attempt  to make unauthorized use, or if an error occurs, an
audit record is generated to capture the subject,  the  file
name,  the  authorization  used, the file change if any, and
the success or failure of the  operation
.  The  audit  event
type and default class is one of:


  AUE_admin_edit:edit administrative file:as
  AUE_admin_file_create:create administrative file:as
  AUE_admin_file_remove:remove administrative file:as

The fundamental idea is rather straightforward.
Add the proper Solaris authorization related to the administrative file.

Example:

Let's authorize user1 to edit /etc/hosts.
The following is just for quick learning, don't do it exactly this way.
In fact, the proper way of doing it is to create a RBAC profile or a role.

# usermod -A +solaris.admin.edit/etc/hosts user1
UX: usermod: user1 is currently logged in, 

some changes may not take effect until next login.

# getent user_attr user1
user1::::auths=solaris.admin.edit/etc/hosts;...


In the above example, user1 happened to be logged in.
But that won't be an issue for this particular case.
Otherwise, it's necessary to get a new session.

user1$ pfedit /etc/hosts
...

#
::1              localhost
127.0.0.1        localhost        loghost

#

...
~

~
"/tmp/hosts.pfedit.AXaGmg" 25L, 587C

Hadn't been for the given Solaris authorization user1 would get:

user1$ pfedit /etc/hosts
pfedit: User user1 is not authorized...


Or at best (typically after a w!):

user1$ vi /etc/hosts
...
"/etc/hosts"
"/etc/hosts" E212: Can't open file for writing
Press ENTER or type command to continue


The pfedit command can also be used to create administrative text files.
Those files can also be deleted (removed) with the -r option.



It isn't a good practice to apply the authorization on a per-user basis.
Let's see a more realistic approach.

In general, it's recommended to:
  • Gather related authorizations in a profile.
  • Assign the profile to a role and the role to authorized logins (users).

For instance:

Assume that user1 and role1 already exist, of course.
Let's invent a level 0 type 1 administration profile.

# profiles -p "Admin L0 T1"
profiles: Admin L0 T1> set auths=solaris.admin.edit/etc/hosts

profiles: Admin L0 T1> set desc="Level 0 Type 1 Administrator"
profiles: Admin L0 T1> exit

# rolemod -P +"Admin L0 T1" role1
# usermod -R +role1 user1

But as in the man page it may be OK (or enough) to not require a role.
Simply assign the profile directly to the login.

# usermod -P +"Admin L0 T1" user1

The trade-offs should be clear:
Directly assigning profiles to logins complicates account management, whereas assigning profiles to roles requires inputing a password every time roles are used (but still better than having a sudo password timeout or a sudo su -).
  

Tuesday, April 8, 2014

NIS & roles

I've already posted about NIS & logins.
This post is a similar one but about NIS & roles.

A role is an account that is used to indirectly access the system.
As a login it posses the concepts of credential and home directory.
Those resources are conveniently centrally managed by NIS services.
Unfortunately NIS can't provide nowadays security requirements.
Nevertheless, it may still be very useful on restricted scenarios.

I reinstate the assumptions listed on NIS & logins.
Nevertheless I make one exception (just for illustration):
the NIS master host nis-1 is an immutable zones of host-1.

On this example, I'll create a role called nis.
The goal is to manage NIS through this role avoiding the cumbersome sudo.

To perform the series of changes on nis-1 reboot it into read-write mode:
(when finished, reboot it once again to reenter the read-only mode)

host-1# zoneadm -z nis-1 reboot -w

Create the role account on the NIS master:

nis-1# roleadd -c "NIS" -K roleauth=user nis

nis-1# getent passwd nis
nis:x:103:10:NIS:/export/home/nis:/usr/bin/pfbash


nis-1# passwd nis
New Password:
Re-enter new Password:
passwd: password successfully changed for nis


Copy the role basic configuration to the appropriate maps' sources:

nis-1# grep nis /etc/passwd >> /var/nis/acct/passwd
nis-1# grep nis /etc/shadow >> /var/nis/acct/shadow

Clean up the local role account from the NIS master:

nis-1# roledel nis

Edit the group and home directory configuration on the passwd map.
It should look like as follows:

nis-1# grep nis /var/nis/acct/passwd
nis:x:103:1001:NIS:/home/nis:/usr/bin/pfbash


nis-1# grep nis /var/nis/group
nis::1001:

Edit the netgroup configuration.
It should look somewhat similar to:
 
nis-1# cat /var/nis/netgroup
...
nisadmin ... (-,nis,business.corp) ...
...

Edit the project configuration on the project map.
It should look like as follows:

nis-1# grep nis /var/nis/project
nisadmin:200:NISAdmin:nis::


nis-1# grep nis /var/nis/user_attr  
nis::::type=role;project=nisadmin;profiles=All;roleauth=user

Edit the automounter configuration on the auto_home map.
It should look like as follows:

nis-1# grep nis /var/nis/auto_home
nis nfs-1.business.corp:/export/home/&


Run make on the updated sources:

nis-1:/var/yp# make
updated passwd
pushed passwd
updated ageing
updated netid
pushed netid
updated project
pushed project
updated netgroup
pushed netgroup
updated auto.home
pushed auto.home
updated user_attr
pushed user_attr


Verify that the maps were correctly updated:

nis-2$ ypmatch -k nis passwd
nis: nis:...:103:1001:NIS:/home/nis:/usr/bin/pfbash

 
nis-2$ ypmatch -k nis auto.home
nis: nfs-1.business.corp:/export/home/&

 
nis-2$ ypmatch -k nisadmin project
nisadmin: nisadmin:102:NISAdmin:nis::

nis-2$ ypmatch -k nis user_attr
nis: nis::::project=nisadmin;type=role;roleauth=user;...

 
nis-2$ ypcat -k netgroup | grep nis
nisadmin (-,nis,business.corp)


Create and export the home directory:

nfs-1# zfs create \
> -o quota=1g \
> -o share.nfs.sec.sys.rw="desktops:servers" \
> rpool/export/home/nis

nfs-1# cp /etc/skel/.profile /export/home/nis
nfs-1# cp /etc/skel/.bashrc /export/home/nis

nfs-1# chown -R nis:root /export/home/nis

nfs-1# ll -a /export/home/nis
total 11
drwxr-xr-x   5 root     root    ... ..
drwxr-xr-x   2 nis     
nis     ... .
-rw-r--r--   1 nis     
nis     ... .profile
-r--r--r--   1 nis     
nis     ... .bashrc

nfs-1# zfs set share.nfs=on rpool/export/home/nis

nfs-1# zfs get -o value share rpool/export/home/nis
VALUE
name=...,path=/export/home/nis,...,rw=servers:desktops


In addition to the update of NIS maps, if there were changes on any NIS netgroup that's referenced on some NFS share, then it's necessary to refresh the NFS service.

In order to be useful, roles must be associated with logins.
To associate the role nis with the login user2 alter the user_attr NIS map.

nis-1# grep nis /var/nis/user_attr  
nis::::project=project1;roles=nis

Then run make on the updated source:

nis-1:/var/yp# make
...

   
NOTE
It's important to note that during this processes there were no disruption of service to clients as all NIS clients should have been associated only to NIS slave servers.