Debugging
Revision 2 as of 2015-06-05 17:34:03
Clear message
From a private email thread from jdstrand:
... Start of ideas for tutorial on developing a snap: What we don't have is a tutorial to tie everything together for the first time developer so they don't have to read through all of the above to do meaningful work. We have something along these lines on Touch: https://developer.ubuntu.com/en/publish/security-policy-groups/ https://developer.ubuntu.com/en/start/platform/guides/app-confinement/ I wrote 'https://developer.ubuntu.com/en/start/platform/guides/app-confinement/' for Touch and 'https://developer.ubuntu.com/en/snappy/guides/security-policy/' (ie, docs/security.md) is roughly equivalent to that, but the Community team has a tech writer that did the other tutorial and AIUI, quite a few others. A tutorial that went step by step through each of python, Go, nodejs and whatever else would be great. If I were writing this myself, I would: 1. write a small cli shell script that tries to write to the install directory, hardcoding paths 2. package the simple cli binary using 'caps: []' 3. install it and show how to run it 4. observe that the script errored out because it couldn't write to the install area due to apparmor (FHS violation), and how to check for security policy issues 5. show how to update the script to use the SNAP_* environment variables (referencing hello-world.env) and fix it to use SNAP_APP_DATA_PATH 6. remove then install the snap 7. run it and show it works now 8. add a simple httpd python service to the existing snap using 'caps: []' 9. install it and show how the systemd service is created in /etc/systemd/system 10. debug why the httpd service didn't start since it is missing the 'network-service' cap 11. update the snap to use 'network-service' cap for the httpd service 12. remove then install the new snap 13. show various systemctl commands to show it is running 14. update the the httpd service to display what the small cli shell script writes out, but with a bug in it (eg, an import error) 15. remove and then install the snap 16. debug the problem with systemctl, lots, etc and fix the bug in the snap 17. remove then install the snap 18. point a browser at the http service 19. run the cli command 20. refresh the browser to show that the cli command updated the page 21. show how to upload to the store As you can see, I've given this some thought. This kinda ties everything together so people can get things done. It provides some best practices (use the SNAP_ variables), teaches a bit about the FHS, a little about debugging, how services and binaries work, a bit on the security sandbox and how to iterate on one's snap. In each step we can link to the appropriate guide for more information. I certainly wouldn't mind writing it, though time being what it is, I haven't yet. We do have a tech writer for this and I'd be happy to review something that he writes. Something similar for Go, nodejs, whatever would also be helpful.
This is just a dump of an email thread that could form the basis of a debugging tutorial. From snappy-devel@:
> When I "start.freedomotic" this is the output: > > (RaspberryPi2)ubuntu@localhost:~$ start.freedomotic > aa-exec: ERROR: profile 'freedomotic_start_5.6.0' does not exist > The file freedomotic.apparmor is present. Infact if I launch "start" in > bin folder with sudo it works. > After a random time the app is killed. > 'start.freedomotic' is not the correct name for the file on either the stable or the rolling snappy releases-- you should be using 'freedomotic.start'. If 'start.freedomotic' is working for you it indicates either you have some old files laying around or your system is out of date. Also, running under sudo from your app's install directory will certainly work-- you are bypassing systemd and the app launcher (it is useful to know that it works on its own though). I downloaded the snap from dropbox: $ click-review /tmp/freedomotic_5.6.0_armhf.snap /tmp/freedomotic_5.6.0_armhf.snap: pass and installed on my beaglebone. $ sudo snappy install --allow-unauthenticated /tmp/freedomotic_5.6.0_armhf.snap Installing /tmp/freedomotic_5.6.0_armhf.snap 2015/05/11 21:29:36 Signature check failed, but installing anyway as requested Name Date Version Developer ubuntu-core 2015-05-08 55 ubuntu docker 2015-05-08 1.6.1.002 freedomotic 2015-05-11 5.6.0 sideload beagleblack 2015-05-08 1.7.1 $ start.freedomotic # <----- your command which correctly doesn't work -bash: start.freedomotic: command not found $ freedomotic.start # <----- what should work based on your comments, # but doesn't -bash: freedomotic.start: command not found In looking at your snappy packaging, you are not specifying any 'binaries', only a service so you won't get a binary you can use from the command line-- only a systemd service. Looking at your package.yaml, there are several issues: $ cat ./package.yaml name: freedomotic architecture: armhf version: 5.6.0 vendor: Freedomotic Team <info@freedomotic.com> icon: meta/freedomotic.svg services: - name: freedomotic description: "freedomotic runtime" start: bin/start integration: freedomotic: apparmor: meta/freedomotic.apparmor First, as mentioned, you don't have a 'binaries' entry[1]. Second, you are using the obsoleted 'integration' hook for specifying security policy[2] (the review tools should've caught this, and I've added a todo to fix this). Looking at freedomotic.apparmor, you aren't doing anything out of the ordinary, so I suggest you change your yaml to simply: name: freedomotic architecture: armhf version: 5.6.0 vendor: Freedomotic Team <info@freedomotic.com> icon: meta/freedomotic.svg services: - name: freedomotic description: "freedomotic runtime" start: bin/start binaries: - name: start exec: bin/start description: "freedomotic runtime cli" With the above you will get a systemd service (that calls 'bin/start') *and* a CLI binary in /apps/bin/freedomotic.start (which also happens to call 'bin/start'-- I'm not sure you actually want to do that in your package, but it illustrates the point I'm trying to make) and you don't have to do anything special for security. After making the above change, make sure your target system is up to date. On my beaglebone black I have: $ system-image-cli -i current build number: 55 device name: generic_armhf channel: ubuntu-core/15.04/edge last update: 2015-05-08 08:10:00 version version: 55 version ubuntu: 20150508 version raw-device: 20150508 If you are on the stable channel, you will have a different build number (I'm not sure about rasp pi2). If I were you, I'd reflash to stable and make sure you have a clean environment. Once you've done that, install the new package with the packaging changes I suggested. If you are iterating and installing the same version over and over again, you will want to do on your target: $ sudo snappy remove freedomotic Removing freedomotic Waiting for freedomotic_freedomotic_5.6.0.service to stop. $ sudo snappy purge freedomotic Purging freedomotic $ sudo snappy install --allow-unauthenticated /tmp/freedomotic_5.6.0_armhf.snap FYI, I built a package with the above changes and now I can use 'freedomotic.start', and it indicates a problem. Eg: $ freedomotic.start /apps/freedomotic.sideload/5.6.0/bin/start: 4: cd: can't cd to /apps/freedomotic/current Launching Freedomotic runtime... /apps/freedomotic.sideload/5.6.0/bin/start: 9: /apps/freedomotic.sideload/5.6.0/bin/start: /apps/freedomotic/current/jre/bin/java: not found This is because the app was sideloaded and your 'start' script doesn't handle that well. You should use the SNAP_* variables in your 'start' script so you aren't hardcoding paths. Eg: $ sudo snappy install hello-world ... $ hello-world.env|grep SNAP_ SNAP_APP_PATH=/apps/hello-world.canonical/1.0.15 SNAP_ORIGIN=canonical SNAP_APP_USER_DATA_PATH=/home/ubuntu//apps/hello-world.canonical/1.0.15 SNAP_FULLNAME=hello-world.canonical SNAP_NAME=hello-world SNAP_APP_TMPDIR=/tmp/snaps/hello-world.canonical/1.0.15/tmp SNAP_OLD_PWD=/tmp SNAP_APP_DATA_PATH=/var/lib//apps/hello-world.canonical/1.0.15 Do be aware of this bug though: https://bugs.launchpad.net/snappy-ubuntu/+bug/1449625 So, looking at 'start', if I change this: appdir=/apps/freedomotic/current cd $appdir export JAVA_HOME="/apps/freedomotic/current/jre" to: appdir=$SNAP_APP_PATH cd $appdir export JAVA_HOME="$appdir/jre" then "freedomatic.start" tries to do something: $ freedomotic.start Launching Freedomotic runtime... log4j:ERROR Could not find value for key log4j.appender.default.file log4j:ERROR Could not instantiate appender named "default.file". INFO [main] - Freedomotic instance ID: c020cc66-8aba-4274-9ccf-2595037d16d6 INFO [main] - Creating new messaging broker INFO [main] - Configuring messaging broker INFO [main] - /apps/freedomotic.sideload/5.6.0/freedomotic The systemd service also tries to do something too: $ sudo systemctl stop freedomotic_freedomotic_5.6.0.service ... $ sudo systemctl start freedomotic_freedomotic_5.6.0.service However, there is a seccomp denial[3][4]: $ sudo sc-logresolve /var/log/syslog May 11 22:00:17 localhost kernel: [264654.298530] audit: type=1326 audit(1431381617.920:34): auid=1000 uid=1000 gid=1000 ses=83 pid=5889 comm="java" exe="/apps/freedomotic.sideload/5.6.0/jre/bin/java" sig=31 arch=40000028 syscall=288(socketpair) compat=0 ip=0xb6e9ab86 code=0x0 'socketpair' is part of the 'network-service' cap (apps by default only get client networking), so you can change your yaml to: name: freedomotic architecture: armhf version: 5.6.0 vendor: Freedomotic Team <info@freedomotic.com> icon: meta/freedomotic.svg services: - name: freedomotic description: "freedomotic runtime" start: bin/start caps: - network-service binaries: - name: start exec: bin/start description: "freedomotic runtime cli" caps: - network-service After making these changes, the app gets farther along, but has another security denial: apparmor="DENIED" operation="mknod" profile="freedomotic.sideload_freedomotic_5.6.0" name="/apps/freedomotic.sideload/5.6.0/freedomotic/plugins/objects/base-things/data/cmd/index.txt" pid=6557 comm="java" requested_mask="c" denied_mask="c" fsuid=0 ouid=0 the app is incorrectly trying to write to the read-only install directory-- security policy enforces the snappy FHS[5]. It should instead be modified to write out to SNAP_APP_DATA_PATH. Attached is a diff of the changes I made. Hope this helps References: [1]https://developer.ubuntu.com/en/snappy/guides/packaging-format-apps/ [2]https://developer.ubuntu.com/en/snappy/guides/package-metadata/ [3]https://developer.ubuntu.com/en/snappy/guides/security-policy/ [4]https://wiki.ubuntu.com/SecurityTeam/Specifications/SnappyConfinement#Debugging [5]https://developer.ubuntu.com/en/snappy/guides/filesystem-layout/ https://developer.ubuntu.com/en/snappy/guides/