Rescuing Apps in a Cloud Foundry Environment
This will be a note-taking blog. If you have any suggestions or information on how to do this, I would appreciate it if you could write it in the comments section.
We were developing a Cloud Foundry application and deployed the app, but lost the source code of the app due to a laptop failure.
I’d like to think about rescuing the app from this situation (so aside from the obvious thing to commit/push to git frequently).
Cloud Foundry allows you to login to the application container instance via SSH. In other words, you can use SSH to access the directory where the application is installed, which means you can access the deployed files.
To access the files via SSH, you need to have SSH permission at the space level and the application level. Even if your application allows SSH connections, you will not be able to connect to it unless the space it belongs to allows SSH connections.
You will need to install the Cloud Foundry Command Line Interface (CLI) since you will need to use cf commands to do this. And login via CLI beforehand.
|$ cf api <endpoint>
$ cf login
SSH permission at the space level
SSH permission at the space level needs to be done by a user who has Space Manager permissions. If you don’t have the privilege, you will need to ask someone who does have the privilege to do it for you. In some cases, you may only be allowed to do this temporarily because it concerns the entire space.
|$ cf allow-space-ssh <SPACE NAME>|
To revoke the permission, execute the same command as disallow-space-ssh.
To check the current status, following.
|$$ cf space-ssh-allowed <SPACE NAME>
ssh support is enabled in space ‘<SPACE NAME>’
SSH permissions at the application level
SSH permission at the application level must be performed by a user who has the Space Developer authority. Also, the actual login can only be performed by a user with the Space Developer authority.
|$ cf enable-ssh <APP NAME>|
<APP NAME> is the application name, which is the name of the application displayed in the application list in the BTP Cockpit.
To revoke the permission, execute the same command as disable-ssh.
You can check the current status as follows
|$ cf ssh-enabled <APP NAME>
ssh support is enabled for ‘<APP NAME>’
It is important to note that you need to restart the application for the changes to take effect. As far as I can tell, even if the status check shows that ssh support is enabled after changing to enable, the change does not seem to take effect until the application is restarted and I cannot actually use ssh.
Try to log in using SSH
After enabling SSH, try logging in.
For the Node.js app, it looked like this
|% cf ssh nodejstestapp
app deps logs profile.d staging_info.yml tmp
vcap@56dad81d-b04c-4283-6421-6ee8:~$ cd app
package.json server.js node_modules package-lock.json static
In the case of the Java app, it looked like this
|% cf ssh javatestapp
app deps logs profile.d staging_info.yml tmp
vcap@7ef6de71-8eb6-4b87-60b7-0261:~$ cd app
index.html META-INF WEB-INF
vcap@7ef6de71-8eb6-4b87-60b7-0261:~/app$ cd WEB-INF/
beans.xml classes lib web.xml
This application is a Java web application that was deployed by creating a War file, which is unzipped and stored under the app directory. In other words, if you can copy the contents of the app directory, you can recreate the War file.
How to use SCP ?
Now that I know where the files are, I want to download them locally. It would be convenient if the cf command had the SCP client function, but it doesn’t, so we need to take some tricky steps.
The first step is to check the endpoint to connect to. This can be displayed with the following command.
|% cf curl /v2/info|grep app_ssh_endpoint
You can get the name of the server and port to connect to from this. In the above example, the server name is ssh.cf.eu10.hana.ondemand.com and the port is 2222.
Then, we will get the GUID of the application, which will correspond to the user information when connecting.
|% cf app <APP_NAME> –guid
Finally, you will get a password. This password is a one-time password and has an expiration date, so you may want to assemble the SCP command below first before running it.
|% cf ssh-code
Now that we have all the information needed to execute the scp command, we can assemble the scp command, but we need to change the user name to
where the last /0 is the instance number starting with 0. The /0 at the end is the instance number starting from 0. If your application is running on multiple instances and you want to connect to the second instance, you need to return to /1 instead of /0. From what we got above, it will be cf:16fa1e5e-de94-45f0-b7b1-21dca34baeec/0
Please refer to man or help for the explanation of the scp command.
If you want to copy the entire app directory to local, from the above sample example, the scp command would be as follows
|% scp -r -P 2222 -o User=cf:16fa1e5e-de94-45f0-b7b1-21dca34baeec/0 ssh.cf.eu10.hana.ondemand.com:/app ./
cf:firstname.lastname@example.org’s password: (input one-time password from “cf ssh-code”)
server.js 100% 21KB 34.5KB/s 00:00
mime 100% 149 0.6KB/s 00:00
mime.cmd 100% 271 1.0KB/s 00:00
mime.ps1 100% 478 1.8KB/s 00:00
…………(Files will be copied locally.)………….
This will allow you to copy the file locally.
I haven’t tried it, but I think GUI-based SCP clients can also be connected with the above information (depending on the client).
Can we completely rescue the source code?
This may vary depending on the language used in the application. As seen in the above example, if it is an interpreter language such as node.js, python, or HTML5 app, the deployed app will be the code, and the code will have been uploaded as a Cloud Foundry application. These can be rescued.
*But in reality, for HTML5 apps, etc., you may deploy a transpiled version. What to make of this transpiled code is another matter. The code is not the original code written by the programmer, and there is a big possibility that the code is very hard to read, but the logic is readable, so it is not the worst case scenario.
On the other hand, if you are using a compiler type language such as Java, the deployed file is a compiled file. This can sometimes be reverted to human-readable code by using a decompiler, but it will often be different from the original complete code, just like the transpiled code mentioned earlier. As a result, applications that use compiler-type languages are considered to be difficult in terms of code rescue. However, if the elements that make the application work (DB connection information, etc.) are not statically embedded in the code, it should be possible to use the rescued files to redeploy to a different server.
To prevent this from happening
In the end, it all comes down to “back up properly,” but please don’t give up when you find yourself in this situation.
Also, as an application, since it can be accessed via SSH, you can output a file using the Cloud Foundry app and then access it via SSH to check it. This is difficult to do in production because it has the drawback of being volatile, but it can be quite useful during development.
I pray that the world will return to normal.