def file_modified(self, fn): # is the file in the whitelist settings = _get_settings('cdn_sync') if settings['cdn_sync_enable'] != 'enabled': return fns = settings['cdn_sync_files'] if not fns: raise PluginError('No file whitelist set') basename = os.path.basename(fn) if basename not in fns.split(','): print('%s not in %s' % (basename, fns)) return # bucket not set if not settings['cdn_sync_bucket']: raise PluginError('No bucket set') # upload try: key = os.path.join(settings['cdn_sync_folder'], os.path.basename(fn)) session = boto3.Session( aws_access_key_id=settings['cdn_sync_username'], aws_secret_access_key=settings['cdn_sync_password'], region_name=settings['cdn_sync_region']) s3 = session.resource('s3') bucket = s3.Bucket(settings['cdn_sync_bucket']) bucket.Acl().put(ACL='public-read') print("uploading %s as %s" % (fn, key)) blob = open(fn, 'rb').read() obj = bucket.put_object(Key=key, Body=blob) obj.Acl().put(ACL='public-read') except BaseException as e: raise PluginError(e)
def archive_finalize(self, arc, metadata): # get settings settings = _get_settings('info_readme') if settings['info_readme_enable'] != 'enabled': return None if not settings['info_readme_filename']: raise PluginError('No filename set') if not settings['info_readme_template']: raise PluginError('No template set') # does the readme file already exist? if _archive_get_files_from_glob(arc, settings['info_readme_filename']): print("archive already has %s" % settings['info_readme_filename']) return # read in the file and do substititons try: template = open(settings['info_readme_template'], 'rb').read() except IOError as e: raise PluginError(e) for key in metadata: template = template.replace(key, metadata[key]) # add it to the archive _archive_add(arc, settings['info_readme_filename'], template.encode('utf-8'))
def _sigul_detached_sign_data(contents, config, key): # check is valid if not config: raise PluginError('No config file set') if not key: raise PluginError('No signing key set') # write firmware to temp file src = tempfile.NamedTemporaryFile(mode='wb', prefix='sigul_', suffix=".bin", dir=None, delete=True) src.write(contents) src.flush() # get asc file from temp file dst = tempfile.NamedTemporaryFile(mode='wb', prefix='sigul_', suffix=".asc", dir=None, delete=True) # sign argv = ['sigul', '--batch', '--config-file', config, 'sign-data', '--output', dst.name, key, src.name] ps = subprocess.Popen(argv, stdout=subprocess.PIPE, stderr=subprocess.PIPE) if ps.wait() != 0: raise PluginError('Failed to sign: %s' % ps.stderr.read()) # read back the temp file return open(dst.name, 'rb').read()
def verify(self, data): """ Verify that the data was signed by something we trust """ gpg = gnupg.GPG(gnupghome=self._homedir, gpgbinary='gpg2') ver = gpg.verify(data) if not ver.valid: raise PluginError( 'Firmware was signed with an unknown private key') return True
def oauth_authorize(self, callback): # check enabled if settings['auth_azure_enable'] != 'enabled': raise PluginError('plugin not enabled') # generate the guid to only accept initiated logins guid = uuid.uuid4() session['auth_azure_state'] = guid return remote_app.authorize(callback=callback, state=guid)
def _sign_blob(self, contents): # get settings settings = _get_settings('sign_pkcs7') if settings['sign_pkcs7_enable'] != 'enabled': return None if not settings['sign_pkcs7_privkey']: raise PluginError('No private key set') if not settings['sign_pkcs7_certificate']: raise PluginError('No certificate set') # write firmware to temp file src = tempfile.NamedTemporaryFile(mode='wb', prefix='pkcs7_', suffix=".bin", dir=None, delete=True) src.write(contents) src.flush() # get p7b file from temp file dst = tempfile.NamedTemporaryFile(mode='wb', prefix='pkcs7_', suffix=".p7b", dir=None, delete=True) # sign argv = [ 'certtool', '--p7-detached-sign', '--p7-time', '--load-privkey', settings['sign_pkcs7_privkey'], '--load-certificate', settings['sign_pkcs7_certificate'], '--infile', src.name, '--outfile', dst.name ] ps = subprocess.Popen(argv, stdout=subprocess.PIPE, stderr=subprocess.PIPE) if ps.wait() != 0: raise PluginError('Failed to sign: %s' % ps.stderr.read()) # read back the temp file return open(dst.name, 'rb').read()
def __init__(self, key_uid=None, homedir='/tmp'): """ Set defaults """ # check exists if not os.path.exists(homedir): try: os.mkdir(homedir) except OSError as e: raise PluginError(e) # find correct key ID for the UID self._keyid = None gpg = gnupg.GPG(gnupghome=homedir, gpgbinary='gpg2') for privkey in gpg.list_keys(True): for uid in privkey['uids']: if uid.find(key_uid) != -1: self._keyid = privkey['keyid'] if not self._keyid: raise PluginError('No imported private key for %s' % key_uid) self._homedir = homedir
def oauth_get_data(self): # check enabled if settings['auth_azure_enable'] != 'enabled': raise PluginError('plugin not enabled') # get response success try: oauth_response = remote_app.authorized_response() except OAuthException as e: raise PluginError(str(e)) if oauth_response is None: raise PluginError('Access Denied' + str(request)) # check response for correct GUID if str(session['auth_azure_state']) != str(request.args['state']): raise PluginError('State has been messed with, end authentication') # save the access token -- treat as a password session['auth_azure_token'] = (oauth_response['access_token'], '') # fixme user.access_token not in db? # get the profile ID resp = remote_app.get('me') if not resp: raise PluginError('No suitable profile response') if not resp.data: raise PluginError('No suitable profile data') return resp.data
def file_modified(self, fn): # is the file in the whitelist settings = _get_settings('cdn_purge') if settings['cdn_purge_enable'] != 'enabled': return fns = settings['cdn_purge_files'] if not fns: raise PluginError('No file whitelist set') basename = os.path.basename(fn) if not _basename_matches_globs(basename, fns.split(',')): print('%s not in %s' % (basename, fns)) return # URI not set if not settings['cdn_purge_uri']: raise PluginError('No URI set') if not settings['cdn_purge_method']: raise PluginError('No request method set') # purge url = settings['cdn_purge_uri'] + basename headers = {} if settings['cdn_purge_accesskey']: headers['AccessKey'] = settings['cdn_purge_accesskey'] r = requests.request(settings['cdn_purge_method'], url, headers=headers) if r.text: try: response = json.loads(r.text) if response['status'] != 'ok': raise PluginError('Failed to purge metadata on CDN: ' + r.text) except ValueError as e: # BunnyCDN doesn't sent a JSON blob raise PluginError('Failed to purge metadata on CDN: %s: %s' % (r.text, str(e)))
def _metadata_modified(self, fn): # plugin not enabled settings = _get_settings('sign_gpg') if settings['sign_gpg_enable'] != 'enabled': return # generate if not settings['sign_gpg_keyring_dir']: raise PluginError('No keyring directory set') if not settings['sign_gpg_metadata_uid']: raise PluginError('No metadata signing UID set') affidavit = Affidavit(settings['sign_gpg_metadata_uid'], settings['sign_gpg_keyring_dir']) if not affidavit: return blob = open(fn, 'rb').read() blob_asc = affidavit.create(blob) fn_asc = fn + '.asc' with open(fn_asc, 'w') as f: f.write(blob_asc) # inform the plugin loader ploader.file_modified(fn_asc)
def archive_sign(self, arc, firmware_cff): # plugin not enabled settings = _get_settings('sign_gpg') if settings['sign_gpg_enable'] != 'enabled': return # already signed detached_fn = _get_basename_safe(firmware_cff.get_name() + '.asc') if _archive_get_files_from_glob(arc, detached_fn): return # create the detached signature if not settings['sign_gpg_keyring_dir']: raise PluginError('No keyring directory set') if not settings['sign_gpg_firmware_uid']: raise PluginError('No firmware signing UID set') affidavit = Affidavit(settings['sign_gpg_firmware_uid'], settings['sign_gpg_keyring_dir']) contents = firmware_cff.get_bytes().get_data() contents_asc = affidavit.create(contents) # add it to the archive _archive_add(arc, detached_fn, contents_asc.encode('utf-8'))
def file_modified(self, fn): # is the file in the whitelist settings = _get_settings('cdn_purge') if settings['cdn_purge_enable'] != 'enabled': return fns = settings['cdn_purge_files'] if not fns: raise PluginError('No file whitelist set') basename = os.path.basename(fn) if not _basename_matches_globs(basename, fns.split(',')): print('%s not in %s' % (basename, fns)) return # URI not set if not settings['cdn_purge_uri']: raise PluginError('No URI set') # purge url = settings['cdn_purge_uri'] + basename headers = {'AccessKey': settings['cdn_purge_accesskey']} r = requests.get(url, headers=headers) if r.text: raise PluginError('Failed to purge metadata on CDN: ' + r.text)