Moving VM’s between hosts

About a year ago I purchased a 1U IBM X3550 server to run VMware vSphere 5 on. While it was cool to have a server that had dual quad procs and 8 gig of ram in it, the noise it put off was too much for my family room. (Just think of half a dozen 1 inch fans running at 15,000RPM almost constantly.) Recently I have been spending more time in the family room and the noise has gotten to a level that it is almost impossible to do anything in the room with out hearing it. (Like watch tv, a movie, play a game, etc.) So I started looking at my favorite used hardware site, geeks.com, for a new “server”. Well it finally arrived today, an HP XW8600 workstation. It is another dual quad proc, however it has 16GB of ram, and 12 SATA ports and a larger case, and the best of all, almost absolutely quiet.

So with it installed, I needed to start moving the VM’s from the IBM Server to the HP Server. In an enterprise environment, this usually isn’t a problem as you usually have a shared storage (SAN) that each of the hosts connect to. Well in my little home lab I don’t have shared storage. I did try to use COMSTAR in Solaris 10 to export a “Disk” as an iSCSI target. While this would work, it was going to take forever to transfer 1TB of VM’s from one server to a VM running on my Mac and back to the new server.

So a googling I went, and what I found was a way easier way to copy the VM’s over. ovftool, which runs on Windows, Linux and Mac. What it does is allow you to export and import OVF files to a VMware host. The side benefit of that is that you can export from one and import to another all on one line.

So I downloaded the Mac version and started coping. The basic syntax is like this:


./ovftool -ds=TargetDataStoreName vi://root@sourcevSphereHost/SourceVM vi://root@destvSphereHost

So if one of my VM’s is called mtdew, and I had it thin provisioned on the source host and wanted it the same on the destination host, and my datastore is called “vmwareraid” I would run this:

./ovftool -ds=vmwareraid -dm=thin vi://root@ibmx3550/mtdew vi://root@hpxw8600

where ibmx3550 is the source server and hpxw8600 is the destination server. If you don’t specify the “-dm=thin” then when it is copied over, it will become a “thick” disk, aka us the entire space allocated when created. (I.E. a 50GB disk that only has 10GB in use would still use 50GB if the -dm=thin is not used.)

There are some gotchas that you will have to look out for:

  1. Network configs, I had one VM that had multiple internal network’s defined. Those were not defined on the new server, so there is a “mapping” that you have to do. I decided I didn’t need them on the new server so I just deleted them before I copied it over.
  2. VM’s must be in a powered off state. I tried them in a “paused” state and it did not want to run right.
  3. It takes time, depending on the speed of the network, disk, etc, it will take a lot of time to do this, and the VM’s have to be down while it happens. So definitely not a way to move “production” vm’s unless you have a maintenance window.
  4. It will show % complete as it goes, which is cool, but the way it does it is weird. It will show the % at like 11 or 12 and then I turn my head and all of the sudden it says it is completed.
  5. I did have some issues with a vm that I am not sure what happened to it, but when I try to copy it, I get an error: “Error: vim.fault.FileNotFound”… It may be due to me renaming something on the vm at some point in the past.

Hope this helps some other “home lab user”…

 

 

Ultra Restricted Shell in Solaris

How to setup a readonly environment on Solaris:

If you want to give a specific user readonly access to your solaris machine via ssh, and want to log everything they do, it is sort of easy to setup. Here is a quick step-by-step guide to setting it up.

1. First you will need to chose what restricted shell you want to use. In this case I used bash as I wanted the .bash_history file to contain the exact time every command was run on the system. Since Solaris does not come with the rbash command, the only thing you need to do is make a copy of /usr/bin/bash to /usr/bin/rbash.

2. Make the user’s shell be /usr/bin/rbash, this will make them use the restricted bash shell.

3. Make their home directory owned by root.

4. Make their .profile owned by root

5. Create a .bash_history file and make it owned by that user. This should be the only file in their directory that is owned by the user.

6. Pick a location for your “restricted” binaries to reside. If this user will be logging in to multiple machines and you have a shared file system (say /home) I would suggest making the directory in /home; say /home/rbin.. This way you only have to put /home/rbin in their PATH.

7. Make symbolic links in your restricted binary directory to the binaries you want to run. I.e. ls, ps, more, prstat,passwd and hostname :

lrwxrwxrwx 1 root root 17 Feb 19 20:47 hostname -> /usr/bin/hostname*
lrwxrwxrwx 1 root root 11 Feb 19 19:56 ls -> /usr/bin/ls*
lrwxrwxrwx 1 root root 13 Feb 19 19:57 more -> /usr/bin/more*
lrwxrwxrwx 1 root root 15 Feb 19 19:56 prstat -> /usr/bin/prstat*
lrwxrwxrwx 1 root root 11 Feb 19 19:56 ps -> /usr/bin/ps*
lrwxrwxrwx 1 root root 11 Feb 19 19:56 passwd -> /usr/bin/passwd*

By making these sym links instead of the actual binaries, you do not have to worry if you have multiple platforms that you are going between (i.e. Sparc, x86) and doing custom logic to use the right binary.

8. Create the users .profile with the following in it:

readonly PATH=/home/rbin
readonly TMOUT=900
readonly EXTENDED_HISTORY=ON
readonly HOSTNAME="`hostname`"
readonly export HISTTIMEFORMAT="%F %T "
readonly export PS1='${HOSTNAME}:${PWD}> '

This will make it so they can not change any of the Environment variables. It sets their path to /home/rbin. Sets a inactivity time out to be 15 minutes. Sets the extended history to be on (this logs the time each command was executed in their .bash_history file). And finally sets their prompt and makes it readonly as well.

9. The last thing you need to do is change the permissions on the scp and sftp-server binaries so that the user can not execute them. Otherwise, they would be able to download files and go any where on the server they want. (Restricted shell will prevent them from cd’ing out of their home directory) To do this, I created a group and put my user in it as their primary group. Say the group was called rdonly. Now I do the following:


setfacl -m group:rdonly:--- /usr/lib/ssh/sftp-server
setfacl -m group:rdonly:--- /usr/bin/scp

So the files should show up like this now:

bash-3.00# ls -la /usr/lib/ssh/sftp-server /usr/bin/scp
-r-xr-xr-x+ 1 root bin 40484 Jan 22 2005 /usr/bin/scp
-r-xr-xr-x+ 1 root bin 35376 Jan 22 2005 /usr/lib/ssh/sftp-server

And the getfacl will look like this:


bash-3.00# getfacl /usr/bin/scp

# file: /usr/bin/scp
# owner: root
# group: bin
user::r-x
group::r-x #effective:r-x
group:rdonly:--- #effective:---
mask:r-x
other:r-x

This makes it so when the user tries to sftp or scp in to the machine, it will immediately disconnect them as they don’t have permissions to run those 2 executables.

That is about it. Don’t forget to set their password, make sure it has a policy set on it to be changed often and require a combination of letters, numbers and special characters and that it is at least 8 characters in length.

So now when the user logs in they will see something similar to this:

[laptop:~] unixwiz% ssh unixwiz@fozzy
Password:
Last login: Thu Feb 19 22:10:15 2009 from laptop
fozzy:/home/unixwiz> cd /
-rbash: cd: restricted
fozzy:/home/unixwiz> vi /tmp/test
-rbash: vi: command not found
fozzy:/home/unixwiz> PATH=$PATH:/usr/bin
-rbash: PATH: readonly variable
fozzy:/home/unixwiz> timed out waiting for input: auto-logout

As you can see, it will give you errors if you try to do something that you are not allowed to do. The last line shows the time out message where it closes the connection due to inactivity.

Now if the administrator goes and looks at the users .bash_history file they would see this:

#1235099570
cd /
#1235099577
vi /tmp/test
#1235099587
PATH=$PATH:/usr/bin

The #number is the exact time that the user ran the command below it. The item is the seconds since the epoch…

Why everyone should use bart (AKA do the Bart Man)

If you are using Solaris 10, and you have not used bart yet, you should stop everything and take a look at it.

For those who don’t know what bart is, it is the Basic Auditing and Reporting Tool that is in Solaris 10.

In a quick synopsis bart will create a report that shows all files/directories on a solaris machine. This report contains the permissions, owners, sizes, modify times and md5 hashes of all files on the system, along with acl’s if you are using ZFS.

So why is bart so important? First, it can be used as a security tool. When you install a new Solaris 10 system, the first thing you should do after you get it installed and patched and before it is placed on the network is run a bart on the system and save the report to a cd. This will be the “baseline” image of the system. Then every week/month you should run a bart against the machine again and then use the compare option to see what files have changed, added or deleted from the system. Where this comes in really handy is if your think that your machine has been hacked or compromised. You can use the comparison to determine which files may have been modified by the hacker.

But there is a non-security use for bart as well that is VERY useful. This use is one that I had not thought of until I needed it the other day. So what is this use? Reseting the permissions on files that were accidentally changed by an in-experienced UNIX person thinking that a “chmod -R 777 *” is the best way to fix their problems.

The first thing that came to my mind when I saw this happen was oh no, the machine had not even been backed up yet, and a day’s worth of work would have been lost. Even if the machine had been backed up, do you realize how long it would take to restore a file system with 40,000+ files, just because the permissions were screwed up. ( Note, the permissions on the various files were very different and even included some setuid, and setgiud files which were wiped out as well.)

So how did bart save the day? Luckly I had taken a bart of the machine before the work had begun on the file system. So after the chmod command was issued, I then took a bart of the file system again. I now could run a bart compare against the control and test manifest and see exactly what all had changed.

Once I had this output, I could then create a script to change the permissions of the files/directories back to the original values. All told after I finished tweaking my script it took about 20 minutes to reset the permissions on all the files and directories.

So here is a quick start to getting your first bart manifest of your system:

1. Create a bart_rules file. If you do not create a rules file, your output will only have Files and not directories listed in it. My simple bart_rules file looks like this:

/
CHECK ALL
/home
IGNORE ALL

I ignore the /home file system as in my case it was nfs mounted. In reality you would want to include all local file systems.

2. Create the bart, I keep the rules file in /root/bart_rules so I would run the command:

bart create -R / -r /root/bart_rules > /tmp/bart.output

This will create a bart manifest and output it to /tmp/bart.output. Looking at the first couple of lines of it looks like this:

unixwiz@sungeek:/home/unixwiz> head -20 /tmp/bart.out
! Version 1.0
! Saturday, May 17, 2008 (21:24:27)
# Format:
#fname D size mode acl dirmtime uid gid
#fname P size mode acl mtime uid gid
#fname S size mode acl mtime uid gid
#fname F size mode acl mtime uid gid contents
#fname L size mode acl lnmtime uid gid dest
#fname B size mode acl mtime uid gid devnode
#fname C size mode acl mtime uid gid devnode
/ D 1024 40755 user::rwx,group::r-x,mask:r-x,other:r-x 481d0e43 0 0
/.ICEauthority F 310 100600 user::rw-,group::---,mask:---,other:--- 44c581c2 0 0 3eb63faf448e8a2b2c1a7b2019a8bde3
/.Xauthority F 99 100600 user::rw-,group::---,mask:---,other:--- 44c560e0 0 0 5ffe2e5f4b6f73e662001f62f7cae4d3
/.bash_history F 649 100600 user::rw-,group::---,mask:---,other:--- 481d1109 0 0 9132e0e798d5d05644cafc90c2aa876a
/.dt D 512 40755 user::rwx,group::r-x,mask:r-x,other:r-x 44c560e0 0 0
/.dt/appmanager D 512 40755 user::rwx,group::r-x,mask:r-x,other:r-x 44c5534d 0 0
/.dt/help D 512 40755 user::rwx,group::r-x,mask:r-x,other:r-x 44c5534d 0 0
/.dt/icons D 512 40755 user::rwx,group::r-x,mask:r-x,other:r-x 44c5534d 0 0
/.dt/sessionlogs D 512 40755 user::rwx,group::r-x,mask:r-x,other:r-x 44c5534c 0 0
/.dt/sessionlogs/sungeek_DISPLAY=:0 F 132 100644 user::rw-,group::r--,mask:r--,other:r-- 44c560e0 0 0 6d4e62fc972046a7a85fdb36a0ce21fd

The first part of the file, the part that begins with #fname is a legend as to how each type of line is formed.
So looking at the first actual line of the contents :
/ D 1024 40755 user::rwx,group::r-x,mask:r-x,other:r-x 481d0e43 0 0
We see that the fnmae is /, it is a directory, with a size of 1024. Its mode is 755, the last modified time is the “481d0e43” and it is owned by uid 0 and gid 0.

Looking at a file in particular we see this:

/httpd/htdocs/index.html F 10 100644 user::rw-,group::r--,mask:r--,other:r-- 463d4f4b 0 0 b7a9369d4cc9f82ed707bce91ced8af8

In the above, we see that the file is 10 bytes, has a permissions of 644 and is owned by root/root.

Now suppose that I for some reason by accident was in the /httpd/htdocs directory and did a chmod -R 777 *. Since I had my control manifest, I would then run another bart and then use the compare option. What I would get is something like this:

#bart compare /tmp/bart.output /tmp/bart.output2
/httpd/htdocs/index.html:
mode control:100644 test:100777
acl control:user::rw-,group::r--,mask:r--,other:r-- test:user::rwx,group::rwx,mask:rwx,other:rwx

Here we can see that the permissions has changed from 644 to 777. But the output is not really easy to parse with a script. So we need to use the “-p” option on the bart compare:

#bart compare -p /tmp/bart.output /tmp/bart.output2
/httpd/htdocs/index.html mode 100644 100777 acl user::rw-,group::r--,mask:r--,other:r-- user::rwx,group::rwx,mask:rwx,other:rwx

In the above, since the only thing that was changed was the mode, that is the only thing that is listed.

here are some other examples:

/var/samba/locks/browse.dat mtime 482f8544 482f8800
/var/samba/locks/unexpected.tdb contents 7c3404e9622749702e3df56caf26fe72 72983947ada3260a236394a51aef0d31

The first line shows that the file browse.dat modify time changed, but nothing else. The second line shows that the unexpected.tdb had it’s contents change. This can been see by the 2 different hashes.

Here is another example of the index.html file above, after it had been edited:

bash-3.00# bart compare /tmp/bart.out /tmp/bart.out3
/httpd/htdocs/index.html:
size control:10 test:26
mode control:100644 test:100777
acl control:user::rw-,group::r--,mask:r--,other:r-- test:user::rwx,group::rwx,mask:rwx,other:rwx
mtime control:463d4f4b test:482f8b89
contents control:b7a9369d4cc9f82ed707bce91ced8af8 test:1567caf683e3859cb5da7335c35438f7

Once again this is in the “human” readable format, the “machine” readable looks like :

bash-3.00# bart compare -p /tmp/bart.out /tmp/bart.out3
/httpd/htdocs/index.html size 10 26 mode 100644 100777 acl user::rw-,group::r--,mask:r--,other:r-- user::rwx,group::rwx,mask:rwx,other:rwx mtime 463d4f4b 482f8b89 contents b7a9369d4cc9f82ed707bce91ced8af8 1567caf683e3859cb5da7335c35438f7

(the above is actually all on one line.)

Once you have the output of the bart after the “oops” you will need to run the bart compare with options to ignore some items. Since I am only interested in the mode, the size, mtime and contents can be ignored. I used the following:

bash-3.00# bart compare -i size,mtime,contents,uid,gid -p /tmp/bart.out /tmp/bart.out2

This only shows files that have had their mode changed:

bash-3.00# bart compare -i size,mtime,contents,uid,gid -p /tmp/bart.out /tmp/bart.out2
/httpd/htdocs/index.html mode 100644 100777 acl user::rw-,group::r--,mask:r--,other:r-- user::rwx,group::rwx,mask:rwx,other:rwx

You should redirect this output to a file, so that it can then be used to generate a script.
With the output in a file I then did this:

cat /tmp/bart.compare | awk '{print "chmod "$3" "$1}' > /tmp/CHANGEPERMS

So basicly I cat the file and print the chmod command allong with the 3rd field (100644) and then the first field (/httpd/htdocs/index.html) and redirect this to a new file. Once I spot check this file, you can then run it and it will “reset” the permissions back.

Now everything I have shown above is based on the machine having a UFS file system. If you run bart against a file system that is ZFS, you will get a manifest that looks something like this:


/home/unixwiz/bin/php F 10587732 100755 owner@::deny,owner@:read_data/write_data/append_data/write_xattr/execute/write_attributes/write_acl/write_owner:allow,group@:write_data/append_data:deny,group@:read_data/execute:allow,everyone@:write_data/append_data/write_xattr/write_attributes/write_acl/write_owner:deny,everyone@:read_data/read_xattr/execute/read_attributes/read_acl/synchronize:allow 4743a7fa 100 14 9b8cfb15ed069bd6e43d7c2ae11a3e23

It shows the ZFS extended acl’s.

So if you haven’t started using bart, you should start as soon as possible.