import os import sys import base64 from OpenSSL import crypto sys.path.insert(1, os.path.dirname(os.path.dirname(sys.path[0]))) from mozharness.base.script import BaseScript from mozharness.base.python import VirtualenvMixin, virtualenv_config_options from mozharness.mozilla.signed_certificate_timestamp import SignedCertificateTimestamp class CTSubmitter(BaseScript, VirtualenvMixin): config_options = virtualenv_config_options config_options = [ [["--chain"], { "dest": "chain", "help": "URL from which to download the cert chain to be " "submitted to CT (in PEM format)" }], [["--log"], { "dest": "log", "help": "URL for the log to which the chain should be submitted" }], [["--sct"], { "dest": "sct", "help": "File where the SCT from the log should be written" }], ] def __init__(self): BaseScript.__init__(self, config_options=self.config_options, config={ "virtualenv_modules": [ "pem", "redo", "requests", ], "virtualenv_path": "venv", }, require_config_file=False, all_actions=["add-chain"], default_actions=["add-chain"], ) self.chain_url = self.config["chain"] self.log_url = self.config["log"] self.sct_filename = self.config["sct"] def add_chain(self): from redo import retry import requests import pem def get_chain(): r = requests.get(self.chain_url) r.raise_for_status() return r.text chain = retry(get_chain) req = {"chain": []} chain = pem.parse(chain) for i in range(len(chain)): cert = crypto.load_certificate(crypto.FILETYPE_PEM, str(chain[i])) der = crypto.dump_certificate(crypto.FILETYPE_ASN1, cert) req["chain"].append(base64.b64encode(der)) def post_chain(): r = requests.post(self.log_url + '/ct/v1/add-chain', json=req) r.raise_for_status() return r.json() resp = retry(post_chain) sct = SignedCertificateTimestamp(resp) self.write_to_file(self.sct_filename, sct.to_rfc6962()) if __name__ == "__main__": myScript = CTSubmitter() myScript.run_and_exit()