Using Secure Shell to Create a Team File Drop
Steven J Zeil
A file drop is an area where members of a team can easily deposit files elated to their work.
Of course, there are numerous file sharing services available, such a Google Drive or DropBox, but these limit the uses that can be made of the shared files. For example, you can store HTML pages in a file sharing service, but you cannot serve those as a website from such a service.
In fact, the case that I want to talk about in this document is specifically creating a shared website to which only the team members can contribute but that can be served for public viewing to all.
1 Special-Purpose SSH Keys
We will be exploiting the power of SSH keys, so make sure you know how to create an authorize them.
1.1 Creating Special-Purpose Key Pairs
Suppose that you wanted to allow someone else to try out a program that you had written and that is sitting somewhere in your account area. Let’s also suppose that you don’t want to make this program available to the entire world. For example, perhaps you are working on a programming assignment in one of my courses and you want me to take a look at your running program.
-
You could, of course, tell me your login name and password, but that would be a bad idea unless you really, really trust me. (And why should you?)
-
Based on what we have just seen, you could create an ssh key pair, add the public key to your
authorized_keys
file, give me the private key and its passphrase. Then, after I had tried your program out, you could simply remove that keu from~/.ssh/authorized_keys
to lock me back out.But that’s still way too trusting of you. During the time I had access to your program, I would have access to everything in your account. I would, even using the ssh keys, be logged in as you.
But we can actually adapt that second approach by limiting the key pair to running only a specific command or program when anyone uses it to log in.
-
Edit the public key that you created in the earlier steps.
The key is typically written as a single long line ending in yourLoginName
@
_machineName_, reflecting where you created the key. To the front of that line, addcommand="/usr/bin/env",no-port-forwarding
and a blank space, right in front of the “ssh-rsa
”.(If you aren’t familiar with te
env
command in Linux, run it to see what it does.) -
Add that edited public key to your authorized keys list on the server as you did earlier.
-
You should still have a key agent running on your client. If not, restart it and add your private key.
Now try logging in via that key by giving the following commands on the client:
ssh yourCSLogin@atria.cs.odu.edu ssh yourCSLogin@atria.cs.odu.edu pwd
Notice that, whether you give a specific command for
ssh
to execute on the remote server or omit it, trying for a normal login session, what actually happens is that you are logged in to your account, theenv
command is run, and then you are logged out.
So, to return to our earlier example, if you were working on a programming assignment in one of my courses and you want me to take a look at your running program, you could create a special-purpose key pair to run that program (and do nothing else), and then give me the private key and passphrase, knowing that I would be limited to using your account for that single purpose.
1.2 Playing with Fire: Password-Free Key Pairs
Now we are going to do something a bit dangerous.
-
Shut down the key agent on your client machine with the command
ssh-agent -k
-
Create a new key pair, giving them a different name from the ones you set up earlier.
This time, however, when prompted for a pass phrase, just hit Enter to create a key pair without a pass phrase.
-
Now, adding that key to your authorized key list would be risky, because anyone who got a copy of the private key would be able to log into your account using no passphrase at all.
So, to keep this safe, immediately edit that public key. This time add
command="pwd",no-port-forwarding
to the beginning of the public key.
-
Add that edited public key to your authorized key list on the server.
-
On the client, give the command
ssh -l
yourCSLoginName-i
path/To/Your/New/Private/Keyatria.cs.odu.edu
You should see that the command is executed without your being prompted for a password or pass phrase.
When you have succeeded in completing these steps, you can remove the keys you have added to your ~/.ssh/authorized_keys
file on the server.
2 Background – Serving Web Pages
Anyone with a CS account can publish web pages on the CS web server. the mechanism for doing this is very straightforward:
Any file stored on the Linux file system at
~
_loginName_/public_html/
_whatever_will appear on the web server at the URL
http://www.cs.odu.edu/~
_loginName_/
_whatever_
To see this in action (if you have not previously taken advantage of this service), create the directory ~/public_html
if you do not already have one.
Inside there, create a file named firstPage.html
containing
<html>
<head>
<title>First page</title>
</head>
<body>
<p>
This is page 1. There is
no page 2.
</p>
</body>
</html>
Then direct a web browser to http://www.cs.odu.edu/~
_yourLoginName_/firstPage.html
and you should see your page.
If not, look at your permissions. The web server does not run under your account. But it needs to be able to access your public_html
directory. That means that you need to carefully open up the correct path to your web content without leaving your entire account wide open.
-
Your login directory must provide execute permission to the world. (“Execute” permission on a directory means that someone who knows the name of a file within the directory can get to that file. However, Execute permission on a directory does not allow someone else to list the contents of your directory to see what’s in there.)
chmod 711 ~
-
Similarly, the web server will need to get to files within your
public_html
directory (and any sub directories within it):chmod 611 ~/public_html
-
The actual web content within your
public_html
directory (and any sub-directories of it) must be readable by the web server:find ~/public_html/* -type d -exec chmod 755 {} \; find ~/public_html/* -type f -exec chmod 644 {} \;
3 Copying (synchronizing) files
Web sites generally consist of multiple files, including HTML, graphics and style sheets. These are often arranged into a hierarchy of directories.
If you and a group of team mates want to copy files from each of your own work areas into a shared directory within your public_html
directory, how are you going to do it.
-
The basic
cp
command will copy files, including entire directory structures (with the-r
option). But your teammates would only be able to do this if their work area is on the same machine and if you made the directories writeable by everyone in the world, which is not a good idea unless you want your website trashed by every wannabe hacker and script-kiddie on the network. -
ftp
,sftp
, andscp
would allow for more controlled access.-
Because
sftp
andscp
are really variations onssh
, we might expect that we could usessh
keys to give our team members access to the web site directories.That is indeed our goal in this task, but…
-
sftp
andscp
work only one file at a time, making it hard to keep multiple nested directories in sync.It could be done by using packing the whole website into a
.zip
or other archive format, trasnferring the archive file in one step withsftp
orscp
, and then issuing anssh
command to unpack the archive on the remote server.But that’s kind of messy, and many updates to a website will only affect one or two files at a time. Transferring the whole thing on every update could be excessively slow.
-
If we’re going to use
ssh
keys to give our teammates access to the directory, we’d like to limit that access to just that directory and not allow them to run arbitrary commands under your login. That would seem to be a job for thecommand=
feature ofssh
public keys. But it’s not clear what copmmand to use to limit people to just copying file and, expecially, to copying file to/from a specific directory.
-
3.1 rsync
A better tool for this sort of copying is the program rsynch
, a powerful utility for copying and synchronizing complicated directory structures.
rsynch
can be used for local copies on a machine or to copy things across the network. It’s smart enough to recognize when a destination machine already has an up-to-date copy of a file, and will skip over any files that don’t really need to be transferred. In fact, when looking at large files in which only a few bytes may been changed, rsync
is capable of saving transfer time by splitting the file into changed and unchanged pieces, transferring only the parts that have changed, and then reassembling the whole file afterwards.
A basic rsync
command looks like
rsync
options source_file_directory destination_file_directory
For example, the options -auvz
(or -a -u -v -z
) cause rsync to try to maintain a “mirror” of the source directory, transferring only newer files and preserving modification dates. If we give the source and destination directories as ordinary file paths, e.g.
rsync -auvz ~/myWorkArea/ ~/public_html/website/
then all files (including directories and files within those directories, recursively) in ~/myWorkArea/
that are newer than their counterparts in ~/public_html/website/
would be copied into the website. (BTW, those slashes on the ends of the paths are important.)
Now, we could do more or less the same with an ordinary copy command:
cp -ar ~/myWorkArea/* ~/public_html/website/
But we can make things more interesting by adding a -e ssh
instruction, telling rsynch
to use ssh
for across-the-network transfers, and then adding loginName@
_machineName_:
to the source or destination directory (or to both) to indicate rewources that exist on another machine or in someone else’s account. For example, from my home Linux box, I might update a web site on the CS Dept server like this:
rsync -auvz -e "ssh" ~/myWorkArea/ zeil@atria.cs.odu.edu/home/zeil/public_html/website/
Normally, if I do this, I will be prompted for a password to log into atria
. If I have set up ssh keys for access to atria
and if I am running a key agent, though, I will be able to do the transfer without entering a password.
If I want to use a specific ssh
key set, I can modify the ssh
command that rsync
will use:
rsync -auvz -e "ssh -i $HOME/.ssh/myPrivateKey" ~/myWorkArea/ zeil@atria.cs.odu.edu:/home/zeil/public_html/website/
Could I set this up to use a passphrase-free key? Well, I would only want to do that if I could limit the key to accepting rsync
connections and only to portions of my website.
3.2 rrsync
And, in fact, rsync
provides a special script/command just for that purpose.
-
Copy the file
/usr/share/doc/rsync/scripts/rrsync.gz
into a convenient directory to which only you have access. (I have a directory~/bin
for these sorts of personal commands and scripts.)cd
to that directory and unpack the file, then make it executable.gunzip rrsync.gz chmod +x rrsync
-
You can look at the file with any editor. the opening comments explain a bit about how to use it. But, in essence, you can list this command in an
ssh
key, together with a directory name, and anyone logging in with that key will be limited to makingrsync
transfers to that directory or to subdirectories within it.For example, if I placed my copy of
rrsync
in/home/zeil/bin
. then I might add, to my ssh keycommand="/home/zeil/bin/rrsync /home/zeil/public_html/webSite/",no-port-forwarding,no-agent-forwarding
-
You can then give an rsync command to copy files from your local client to your remote website directory. The one difference from normal
rsync
commands is that you give the remote directory as a relative path within the starting directory you placed in therrsync
entry:rsync -auvz -e "ssh -i $HOME/.ssh/myPrivateKey" ~/myWorkArea/ zeil@atria.cs.odu.edu:./
i.e., starting from
/home/zeil/public_html/webSite/
in therrsync
entry, go to./
(/home/zeil/public_html/webSite/./
being the same as/home/zeil/public_html/webSite/
).
#
4 Setting Up a Tream Website
-
Set up a website directory for the team. For the same of this example, I’m going to set up a site that would be accessed as
http://www.cs.odu.edu/~zeil/projectReports/
.The web pages at URLs
http://www.cs.odu.edu/~zeil/
… are located in directory/home/zeil/public_html/
…. Of course, you would need to replace my login namezeil
by your own to set up your own website.So, in the directory
/home/zeil/public_html
, I would create a directoryprojectReports/
. I would set the permissions to711
, so that I have full access (7) and the webserver can navigate to specified directories (1).- Even though I’m setting this up for my team, they don’t need write access to the directory because we’re going to set things up so that when depositing files, they are logged in as me.
-
In that directory, add a web page titled “
index.html
” that displays simply the phrase “Project Reports”.(An
index.html
file displays by default if someone browses to the directory without naming a specific file. By providing anindex.html
file, you not only set up a convenient starting point for a website, you also prevent people from using their web browser to simply list all of the files in your directory.) -
Set up a passphrase-free pair of ssh keys. Add the
command=rrsync
… limitation to the front of the public key:
command="/home/zeil/bin/rrsync
/home/zeil/public_html/projectReports/",no-port-forwarding,no-agent-forwarding
…rest of public key…
Add that restricted public key to your `authorized_keys` file.
- You can now distribute the private half of that key to your teammates, knowing that the only use they can make of it is to add and update files in the website.