2016-03-28 22:06:04 -07:00
|
|
|
#!/usr/bin/python3
|
|
|
|
|
|
|
|
|
|
import argparse
|
|
|
|
|
import json
|
|
|
|
|
import hashlib
|
2016-03-29 11:27:10 -07:00
|
|
|
from OpenSSL import crypto
|
2016-03-28 22:06:04 -07:00
|
|
|
import socket
|
|
|
|
|
import struct
|
|
|
|
|
import urllib.request
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
parser = argparse.ArgumentParser(description='iconograph fetcher')
|
|
|
|
|
parser.add_argument(
|
2016-03-29 10:24:22 -07:00
|
|
|
'--base-url',
|
|
|
|
|
dest='base_url',
|
|
|
|
|
action='store',
|
|
|
|
|
required=True)
|
2016-03-29 11:27:10 -07:00
|
|
|
parser.add_argument(
|
|
|
|
|
'--ca-cert',
|
|
|
|
|
dest='ca_cert',
|
|
|
|
|
action='store',
|
|
|
|
|
required=True)
|
2016-03-28 22:06:04 -07:00
|
|
|
parser.add_argument(
|
2016-03-29 10:24:22 -07:00
|
|
|
'--image-type',
|
|
|
|
|
dest='image_type',
|
|
|
|
|
action='store',
|
|
|
|
|
required=True)
|
2016-03-28 22:06:04 -07:00
|
|
|
FLAGS = parser.parse_args()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Fetcher(object):
|
|
|
|
|
|
|
|
|
|
_MAX_BP = 10000
|
|
|
|
|
|
2016-03-29 11:27:10 -07:00
|
|
|
def __init__(self, base_url, image_type, ca_cert):
|
2016-03-28 22:06:04 -07:00
|
|
|
self._base_url = base_url
|
|
|
|
|
self._image_type = image_type
|
2016-03-29 11:27:10 -07:00
|
|
|
with open(ca_cert, 'r') as fh:
|
|
|
|
|
self._ca_cert = crypto.load_certificate(crypto.FILETYPE_PEM, fh.read())
|
|
|
|
|
|
|
|
|
|
def _Unwrap(self, wrapped):
|
|
|
|
|
cert = crypto.load_certificate(crypto.FILETYPE_PEM, wrapped['cert'])
|
|
|
|
|
crypto.verify(
|
|
|
|
|
cert,
|
|
|
|
|
wrapped['sig'].encode('ascii'),
|
|
|
|
|
wrapped['inner'].encode('ascii'),
|
|
|
|
|
'sha256')
|
2016-03-28 22:06:04 -07:00
|
|
|
|
|
|
|
|
def _GetManifest(self):
|
|
|
|
|
url = '%s/%s.manifest.json' % (self._base_url, self._image_type)
|
2016-03-29 11:27:10 -07:00
|
|
|
resp = urllib.request.urlopen(url).read().decode('utf8')
|
|
|
|
|
return self._Unwrap(json.loads(resp))
|
2016-03-28 22:06:04 -07:00
|
|
|
|
|
|
|
|
def _ChooseImage(self, manifest):
|
|
|
|
|
hostname = socket.gethostname()
|
|
|
|
|
hash_base = hashlib.sha256(hostname.encode('ascii'))
|
|
|
|
|
for image in manifest:
|
|
|
|
|
hashobj = hash_base.copy()
|
|
|
|
|
hashobj.update(struct.pack('!L', image['timestamp']))
|
|
|
|
|
my_bp = struct.unpack('!I', hashobj.digest()[-4:])[0] % self._MAX_BP
|
|
|
|
|
if my_bp < image['rollout_‱']:
|
|
|
|
|
return image
|
|
|
|
|
|
|
|
|
|
def Fetch(self):
|
|
|
|
|
manifest = self._GetManifest()
|
2016-03-29 11:27:10 -07:00
|
|
|
#image = self._ChooseImage(manifest)
|
|
|
|
|
#print(image)
|
2016-03-28 22:06:04 -07:00
|
|
|
|
|
|
|
|
|
2016-03-29 11:27:10 -07:00
|
|
|
fetcher = Fetcher(FLAGS.base_url, FLAGS.image_type, FLAGS.ca_cert)
|
2016-03-28 22:06:04 -07:00
|
|
|
fetcher.Fetch()
|