Vincent Batts @vbatts
$> finger $(whoami)
Login: vbatts Name: Vincent Batts
Directory: /home/vbatts Shell: /bin/bash
Such mail.
Plan:
OHMAN
$> id -Gn
devel opencontainers docker appc redhat golang slackware
tar archives
Slackware packages (tar(1) archives)
Red Hat *.rpm (custom key/value binary and cpio(1))
Java *.jar and *.war (zip(1) archive)
Container Images (tar(1) archives)
Opaque Object storage
changed object = new object
cryptographic assurance
inflate/deflate (RFC1951)
same objects, but variation in compression
Gzip (RFC1952)
`gzip` vs Golang `compress/gzip` vs Zlib
ideally compress for transfer and storage, but not for identity
#!/bin/sh
dd if=/dev/urandom of=rando.img bs=1M count=2
cat rando.img | gzip -n > rando.img.gz
cat rando.img | gzip -n -9 > rando.img.9.gz
cat rando.img | xz > rando.img.xz
cat rando.img | xz -9 > rando.img.9.xz
sha1sum rando.img* > SHA1
cat rando.img | gzip -n > rando.img.gz
cat rando.img | gzip -n -9 > rando.img.9.gz
cat rando.img | xz > rando.img.xz
cat rando.img | xz -9 > rando.img.9.xz
sha1sum -c ./SHA1
#!/usr/bin/env ruby
require 'zlib'
include Zlib
input = File.open(ARGV.first)
GzipWriter.open(ARGV.first + '.gz', DEFAULT_COMPRESSION, HUFFMAN_ONLY) do |gz|
gz.write(IO.binread(input))
end
input.flush()
input.close()
package main
import (
"compress/gzip"
"io"
"os"
)
func main() {
input, err := os.Open(os.Args[1])
if err != nil {
println(err.Error())
os.Exit(1)
}
output, err := os.Create(os.Args[1] + ".gz")
if err != nil {
println(err.Error())
os.Exit(1)
}
gz := gzip.NewWriter(output)
if _, err := io.Copy(gz, input); err != nil {
println(err.Error())
os.Exit(1)
}
}
Regardless of transport, ensure resulting filesystem
(*.tar archive, rsync, bittorrent, IPFS, etc)
`rpm -qV <package>` functionality
Future hopes could be IMA/EVM
Passive validation of directory hierarchies
BSD mtree(8)
dm-verity in select use-cases
libarchive-formats(5) (so `bsdtar`)
[root@host /]# gomtree -c -K sha256 -p /usr/ | head -30
# user: root
# machine: host
# tree: /usr
# date: Wed Sep 26 16:07:53 2018
# keywords: size,type,uid,gid,mode,link,nlink,time,sha256digest
# .
/set type=file nlink=1 mode=0664 uid=0 gid=0
. size=100 type=dir mode=0755 time=1524747817.000000000
tmp size=10 type=link mode=0777 link=../var/tmp time=1517996467.000000000
# bin
bin size=5268 type=dir mode=0555 time=1537977678.074646319
\133 size=48 mode=0555 time=1521637266.000000000 sha256digest=afd97bbd643bfe1473794af167cd5c6f44fe449681033e3584b40b836f624b4b
alias size=29 mode=0755 time=1521122304.000000000 sha256digest=c9e358c5012c2cf9171ec4f7692ac3a1cbc280617b610d77d813653a1d0dfeb8
applydeltarpm size=72752 mode=0755 time=1517985721.000000000 sha256digest=359f076a0a259bdab3d8139546319efe076fe49733c44aae1a823872e51451eb
arch size=51 mode=0555 time=1521637267.000000000 sha256digest=209bae4071910ef54b4a3bd302059bf7e00870d8bacffcd7c5489425f37ed16f
gomtree
[root@host /]# casync mtree /usr/
. type=dir mode=0755 uid=0 gid=0 time=1524747817.000000000
bin type=dir mode=0555 uid=0 gid=0 time=1537977212.955190222
bin/[ type=file mode=0555 size=48 uid=0 gid=0 time=1521637266.000000000 sha512256digest=f02fe283c47d25e8273a4ce6297eef3e9f2300f597207fa6b82fc12694bd9771
bin/alias type=file mode=0755 size=29 uid=0 gid=0 time=1521122304.000000000 sha512256digest=c526d0d764732aa40fa866033bc49882f1e575ff89f969261eb354945db57d75
bin/applydeltarpm type=file mode=0755 size=72752 uid=0 gid=0 time=1517985721.000000000 sha512256digest=794cd98d3aac69cd3a2ab0e6820e0070555fdbc79de906a79addb98b919baa47
bin/arch type=file mode=0555 size=51 uid=0 gid=0 time=1521637267.000000000 sha512256digest=5516a6b4ee54e9f5fa7d8842781bcb6b3799e2dfa581ce1941c1c9f06a22d648
bin/awk type=link mode=0777 link=gawk uid=0 gid=0 time=1519649348.000000000
bin/b2sum type=file mode=0555 size=52 uid=0 gid=0 time=1521637266.000000000 sha512256digest=423c318bb3cad9826bf3b932baccb66baf2c7f0d55cb0d7d10f41d7e4ebb8fe6
bin/base32 type=file mode=0555 size=53 uid=0 gid=0 time=1521637266.000000000 sha512256digest=45b43efd608aca559aa0dea075a46a554f7e7fcc3534ea2c7f8edc344a342ead
bin/base64 type=file mode=0555 size=53 uid=0 gid=0 time=1521637266.000000000 sha512256digest=d63d00e263f95f09a27ddd4fc6a00b76835e5371af0a2c9a32e3929305810536
[...]
casync mtree
> skopeo copy docker://docker.io/busybox:latest oci:busybox:latest
> umoci unpack --image ./busybox:latest busybox-bundle
> cat busybox-bundle/sha256_9b9b48e2d92691f344ad1701e7df04f89dd2041f2f05cccfec39af8ac3a62d25.mtree
# user: root
# machine: host
# tree: busybox-bundle/rootfs
# date: Wed Sep 26 16:21:46 2018
# keywords: size,type,uid,gid,mode,link,nlink,tar_time,sha256digest,xattr
# .
/set type=file nlink=1 mode=0664 uid=0 gid=0
. size=52 type=dir mode=0755 tar_time=0.000000000
# bin
bin size=4638 type=dir mode=0755 tar_time=1533068407.000000000
\133 size=1083720 mode=0755 nlink=393 tar_time=1533068407.000000000 sha256digest=ee8001feee768df41ff9a2b704b4a027d7ed76f78f09648a5b7ad9f1d7d45640
\133\133 size=1083720 mode=0755 nlink=393 tar_time=1533068407.000000000 sha256digest=ee8001feee768df41ff9a2b704b4a027d7ed76f78f09648a5b7ad9f1d7d45640
acpid size=1083720 mode=0755 nlink=393 tar_time=1533068407.000000000 sha256digest=ee8001feee768df41ff9a2b704b4a027d7ed76f78f09648a5b7ad9f1d7d45640
add-shell size=1083720 mode=0755 nlink=393 tar_time=1533068407.000000000 sha256digest=ee8001feee768df41ff9a2b704b4a027d7ed76f78f09648a5b7ad9f1d7d45640
addgroup size=1083720 mode=0755 nlink=393 tar_time=1533068407.000000000 sha256digest=ee8001feee768df41ff9a2b704b4a027d7ed76f78f09648a5b7ad9f1d7d45640
adduser size=1083720 mode=0755 nlink=393 tar_time=1533068407.000000000 sha256digest=ee8001feee768df41ff9a2b704b4a027d7ed76f78f09648a5b7ad9f1d7d45640
adjtimex size=1083720 mode=0755 nlink=393 tar_time=1533068407.000000000 sha256digest=ee8001feee768df41ff9a2b704b4a027d7ed76f78f09648a5b7ad9f1d7d45640
[...]
umoci unpack
tar cf /tmp/demo.tar .
gomtree -c -T /tmp/demo.tar -K sha256digest | tee /tmp/demo.mtree
gomtree -f /tmp/demo.mtree -T /tmp/demo.tar
echo $?
read
gomtree -f /tmp/demo.mtree -p ./
echo $?
touch $0 # SCANDALOUS
gomtree -f /tmp/demo.mtree -p ./
Tar Archive Support
go get -u github.com/vbatts/go-mtree/cmd/gomtree
gomtree -c -p ./ -K sha256digest | tee /tmp/demo.mtree
gomtree -f /tmp/demo.mtree -p ./
echo $?
read
touch $0 # SCANDALOUS
gomtree -f /tmp/demo.mtree -p ./
Directory Path
mtree -c -p ./ -K sha256digest | tee /tmp/demo.mtree
mtree -f /tmp/demo.mtree -p ./
echo $?
read
touch $0 # SCANDALOUS
mtree -f /tmp/demo.mtree -p ./
BSD mtree || mtree-port
#!/usr/bin/env python
import libarchive
with libarchive.file_writer('../demo.mtree', 'mtree') as a:
a.add_files('./')
with packages: libarchive and python-libarchive-c
NOTICE: libarchive uses older mtree format
[root@host /]# bsdtar --format mtree -cf foo.mtree /usr
bsdtar: Removing leading '/' from member names
[root@fa97e1919c44 /]# more foo.mtree
#mtree
./usr gname=root uname=root time=1524747817.0 mode=755 gid=0 uid=0 type=dir
./usr/tmp gname=root uname=root time=1517996467.0 mode=777 gid=0 uid=0 type=link link=../var/tmp
./usr/bin gname=root uname=root time=1537976676.897120032 mode=555 gid=0 uid=0 type=dir
./usr/bin/[ gname=root uname=root time=1521637266.0 mode=555 gid=0 uid=0 type=file size=48
./usr/bin/alias gname=root uname=root time=1521122304.0 mode=755 gid=0 uid=0 type=file size=29
[...]
bsdtar (libarchive)
NOTICE: libarchive uses older mtree format
get familiarized with mtree format
make your implementation compatible
consider your provenance and sharing fs metadata use-cases