I continued to work on integrating with cloud storage services this week. As of now, it is important that I get something working as soon as possible, therefore my focus was to just get the SSHFS protocol to work as expected.
Last week, I worked on the CREATE part of the REST API endpoint that mounts the remote filesystem. For some reason I got confused and change the CREATE method to save an uploaded file to the cloud server after mounting it and then unmount it shortly after. I changed the READ, UPDATE and DELETE methods from what I had initially planned earlier too, such that they mount the filesystem, perform the desired operation on a file based on the HTTP request, then proceed to unmounting in one go. It turns out that is the wrong way, so I will need to make amends. To reiterate, the CREATE method should just mount the remote filesystem, the READ method reads the contents of specific file from the mounted filesystem and put it in the body of the HTTP response, the UPDATE method saves the given file to the mounted filesystem, overwrite if it already exists and then finally the DELETE method unmounts the filesystem.
Apart from that, it is not important for me to implement a caching mechanism at this point of time (there is a cache done by a previous intern, but I would have to change it since it only works closely with Dropbox), so the REST API endpoint for the cache as of now should do those methods mentioned earlier. Sometimes you just got to keep things simple like that. I gotta learn how to prioritize my tasks properly as well. At least I now know, using SSHFS alone, that it can perform the basic necessary operations, so the change would not be so troublesome.
Authenticating with SSHFS
Another important aspect of integrating with cloud storage services is authentication. In the case of SSHFS, we could use the password given by the user to authenticate our application when we attempt to connect to a cloud storage service, but we all know that passwords are not very secure. Furthermore, the user’s password is in plain text when it is encoded in a URI, which we used to save all the necessary information, like the protocol to use (SSHFS, WebDAV, etc), user credentials, hostname of the cloud server and a path, so there is a high chance of it being compromised. A more secure method would be to use public key authentication. If you ever used a Git service, you know that you first have to generate a pair of SSH keys, both public and private, then add the public key to your Git account so that you could authenticate yourself using your private key when pushing your code to a Git repository for example. When that is done, you will never have to type a single password ever again, as long you keep the public key in your Git account and have the private key in your machine. Normally, the server would keep a list of the public keys in ~/.ssh/authorized_keys . The client would need to show that it has that public key and the private key associated with it when connecting to the server through ssh. Similarly, our application could provide a public key to the user, so that they could add it to their account of whatever cloud storage service they use. Then, every time the application wants to mount the remote filesystem, the ssh protocol attempts to find a private key stored in ~/.ssh to be used to authenticate ourselves to the cloud server. If you have multiple key pairs, then you can specify a private key like this:
sshfs [email protected]:[dir] mountpoint -o IdentityFile=/absolute/path/to/your/private/key
Usually when connecting to the remote server for the first time, ssh would give a prompt on terminal screen saying that the authenticity of the host could not be established, presents a fingerprint of the server’s public key to the user, then asks if you would still wanna continue connecting, which should be responded with a yes or no. Once that is done, ssh woud add the server’s host key to a file, ~/.ssh/known_hosts, so that it would not give that prompt again. To do this in our application, we would just use a named pipe to output the ‘yes’ as input to the ssh command. However, the problem was that the prompt would still come out even after piping in a ‘yes’. There must be a way circumvent this. Knowing most of us, we would probably do a search on Google to solve our problem, but alas I couldn’t find what I was looking for. It turns out that the answer came from the ssh manual page. There is an option to disable the checking of the server’s authenticity on the first connection, which is as such:
sshfs [email protected]:[dir] mountpoint -o StrictHostKeyChecking=false
Now our application does not even need to pipe anything into the sshfs driver. I should probably learn to look more at the manual pages first before searching everywhere on Google whenever something like this happen again.