Skip to content

szuecs/binary-patch

Repository files navigation

binary-patch

DISCLAIMER: This is only a test!

Why this?

It should be possible to update client binaries without being dependent, that all users have to find and download updates manually.

A mytool --self-update should be enough or an "autoupdate" feature should be possible.

I found https://github.com/inconshreveable/go-update and had an idea.

Idea

A service could run and host all binaries for one organization. Binaries should be created by CI build systems for all platforms and uploaded to a storage system (NFS, ObjectStorage (S3, GCS, ..)).

The clients can send name, architecture and current version to the service and the service can provide an updated version of the binary for the same architecture. All client binaries have to have a small modification to request a new version. This could be done implicitly to support "autoupdate" or explicitly "--self-update" a user request based update procedure.

Examples

Signed Updates

Create /tmp/bindata/ with 1 client application with versions v0.0.1 and v0.0.2 and generate corresponding signature and sha256 checksum files:

% testdata/create_testdata.sh

Build server binary:

% make build.server

Run example:

% build/binary-patch version
binary-patch Version: v0.0.1
================================
    Buildtime: 2017-06-14_09:26:33PM
    GitHash: 0edf55ffe02f054090d81b61b84d0b9b2242b92e
% build/binary-patch signed-patch-update
2017/06/14 23:27:55 use http://localhost:8080/signed-patch-update
% build/binary-patch version
binary-patch Version: v0.0.2
================================
    Buildtime: 2017-06-14_09:26:37PM
    GitHash: 0edf55ffe02f054090d81b61b84d0b9b2242b92e

Upload new version with signature

Current server storage:

% ls -l /tmp/bindata
total 15624
-rwxr-xr-x 1 sszuecs sszuecs 7988426 Jul 10 21:26 binary-patch_v0.0.1_amd64linux
-rw-r--r-- 1 sszuecs sszuecs      65 Jul 10 21:26 binary-patch_v0.0.1_amd64linux.sha256
-rw-r--r-- 1 sszuecs sszuecs      72 Jul 10 21:26 binary-patch_v0.0.1_amd64linux.signature
-rwxr-xr-x 1 sszuecs sszuecs 7988426 Jul 10 21:26 binary-patch_v0.0.2_amd64linux
-rw-r--r-- 1 sszuecs sszuecs      65 Jul 10 21:26 binary-patch_v0.0.2_amd64linux.sha256
-rw-r--r-- 1 sszuecs sszuecs      71 Jul 10 21:26 binary-patch_v0.0.2_amd64linux.signature

Create a new Version of your application

% make build.local VERSION=v0.0.3
% openssl dgst -sha256 -sign testdata/privateKey build/binary-patch > build/binary-patch.signature
% openssl dgst -sha256 build/binary-patch | awk '{print $2}' > build/binary-patch.sha256
% cat build/binary-patch.sha256
c94b10075d0a7b588748fcfddb0de2239605bc78aa147efcff8d590bddc2ea2a
% ls -l build/
total 22288
-rwxr-xr-x 1 sszuecs sszuecs  7988426 Jul 10 21:28 binary-patch
-rwxr-xr-x 1 sszuecs sszuecs 14822023 Jul 10 21:26 binary-patch-server
-rw-r--r-- 1 sszuecs sszuecs       65 Jul 10 21:32 binary-patch.sha256
-rw-r--r-- 1 sszuecs sszuecs       71 Jul 10 21:31 binary-patch.signature

Upload to PUT /upload/:name endpoint:

# create json file, because curl is not able to have huge parameters (base64 of a binary as paramater)
% echo "{\"data\": \"$(cat build/binary-patch | base64)\", \"version\": \"v0.0.3\", \"arch\": \"amd64\", \"os\": \"linux\", \"signature-type\": \"ecdsa\", \"signature\": \"$(cat build/binary-patch.signature | base64)\"}" > my.json
% less my.json
% curl -X PUT -H"content-type: application/json" -d @my.json http://localhost:8080/upload/binary-patch
{"message":"uploaded signed application 'binary-patch' version v0.0.3 for OS linux and architecture amd64"}

Check SHA256 in server target directory is the same as the above calculated on the client:

  % cat /tmp/bindata/binary-patch_v0.0.3_amd64linux.sha256
  c94b10075d0a7b588748fcfddb0de2239605bc78aa147efcff8d590bddc2ea2a

Use your v0.0.1 or v0.0.2 binary to update it (here we create a new v0.0.1):

% make build.local VERSION=v0.0.1
% cp -a build/binary-patch{,.v1}  # make a copy to test unverified an verified updates
% build/binary-patch version
binary-patch Version: v0.0.1
================================
    Buildtime: 2017-07-10_08:21:37PM
    GitHash: 4d2f875f4261b0ea24381089a4965865c4c4079d
% build/binary-patch update
2017/07/10 22:18:47 Update complete
% build/binary-patch version
binary-patch Version: v0.0.3
================================
    Buildtime: 2017-07-10_08:01:21PM
    GitHash: 4d2f875f4261b0ea24381089a4965865c4c4079d
# Worked!
#
# Reset to check signed updates
% cp -a build/binary-patch{.v1,}
% build/binary-patch version
binary-patch Version: v0.0.1
================================
    Buildtime: 2017-07-10_08:21:37PM
    GitHash: 4d2f875f4261b0ea24381089a4965865c4c4079d
% build/binary-patch signed update --public-key testdata/publicKey
% build/binary-patch version
binary-patch Version: v0.0.3
================================
    Buildtime: 2017-07-10_08:01:21PM
    GitHash: 4d2f875f4261b0ea24381089a4965865c4c4079d
# Worked!