Browse Source

gverify

tags/0.1
devrandom 10 years ago
parent
commit
deb988a3cd
2 changed files with 105 additions and 3 deletions
  1. 13
    3
      README.md
  2. 92
    0
      bin/gverify

+ 13
- 3
README.md View File

@@ -23,14 +23,24 @@ Copy any additional build inputs into a directory named _inputs_.

Then execute the build using a YAML description file (can be run as non-root):

bin/gbuild <package>-desc.yml
bin/gbuild <package>.yml

or if you need to specify a commit for one of the git remotes:

bin/gbuild --commit <dir>=<hash> <package>-desc.yml
bin/gbuild --commit <dir>=<hash> <package>.yml

The resulting report will appear in result/\<package\>-res.yml

To sign the result, perform:

bin/gsign --signer <signer> --release <release-name> <package>.yml

Where <signer> is your signing PGP key ID and <release-name> is the name for the current release. This will put the result and signature in the sigs/<package>/<release-name>. The sigs/<package> directory can be managed through git to coordinate multiple signers.

After you've merged everybody's signatures, verify them:

bin/gverify --release <release-name> <package>.yml

## Poking around

* Log files are captured to the _var_ directory
@@ -38,7 +48,7 @@ The resulting report will appear in result/\<package\>-res.yml
* To start the target VM run `start-target 32 lucid-i386` or `start-target 64 lucid-amd64`
* To ssh into the target run `on-target` or `on-target -u root`
* On the target, the _build_ directory contains the code as it is compiled and _install_ contains intermediate libraries
* By convention, the script in \<package\>-desc.yml starts with any environment setup you would need to manually compile things on the target
* By convention, the script in \<package\>.yml starts with any environment setup you would need to manually compile things on the target

TODO:
- disable sudo in target, just in case of a hypervisor exploit

+ 92
- 0
bin/gverify View File

@@ -0,0 +1,92 @@
#!/usr/bin/ruby

require 'optparse'
require 'yaml'
require 'fileutils'
require 'pathname'

@options = {}

def system!(cmd)
system(cmd) or raise "failed to run #{cmd}"
end

def sanitize(str, where)
raise "unsanitary string in #{where}" if (str =~ /[^\w.-]/)
str
end

def sanitize_path(str, where)
raise "unsanitary string in #{where}" if (str =~ /[^@\w\/.-]/)
str
end

def info(str)
puts str unless @options[:quiet]
end

################################

OptionParser.new do |opts|
opts.banner = "Usage: build [options] <build-description>.yml"

opts.on("-q", "--quiet", "be quiet") do |v|
@options[:quiet] = v
end
opts.on("-r REL", "--release REL", "release name") do |v|
@options[:release] = v
end

opts.on("-d DEST", "--destination DEST", "directory to place signature in") do |v|
@options[:destination] = v
end
end.parse!

base_dir = Pathname.new(__FILE__).expand_path.dirname.parent

build_desc_file = ARGV.shift or raise "must supply YAML build description file"

build_desc = YAML.load_file(build_desc_file)

in_sums = []

result_dir = 'result'

package_name = build_desc["name"] or raise "must supply name"
package_name = sanitize(package_name, "package name")

destination = @options[:destination] || File.join(base_dir, "sigs", package_name)
release = @options[:release] || "current"
release = sanitize(release, "release")

release_path = File.join(destination, release)

File.exists?(release_path) or raise "#{release_path} does not exist"

result_file = "#{package_name}-res.yml"

#system!("gpg --detach-sign -u #{signer} -o #{release_path}/signature.pgp #{result_path}")

current_manifest = nil

did_fail = false

Dir.foreach(release_path) do |signer_dir|
next if signer_dir == "." or signer_dir == ".."
signer_path = sanitize_path(File.join(release_path, signer_dir), "signer path")
next if !File.directory?(signer_path)
result_path = sanitize_path(File.join(signer_path, result_file), "result path")
result = YAML.load_file(result_path)
if !system("gpg --quiet --batch --verify #{File.join(signer_path, 'signature.pgp')} #{result_path}")
puts "#{signer_dir}: BAD SIGNATURE"
did_fail = true
elsif current_manifest and result['out_manifest'] != current_manifest
puts "#{signer_dir}: MISMATCH"
did_fail = true
else
puts "#{signer_dir}: OK"
end
current_manifest = result['out_manifest']
end

exit 1 if did_fail

Loading…
Cancel
Save