def dmg_signpackage(pkgfile, dstfile, keychain, mac_id, subject_ou, fake=False, passphrase=None): """ Sign a mac build, putting results into `dstfile`. pkgfile must be a tar, which gets unpacked, signed, and repacked. """ # Keep track of our output in a list here, and we can output everything # when we're done This is to avoid interleaving the output from # multiple processes. # TODO: Is it even possible to do 'fake' signing? logs = [] logs.append("Repacking %s to %s" % (pkgfile, dstfile)) tmpdir = tempfile.mkdtemp() pkgdir = os.path.dirname(pkgfile) try: # Unpack it logs.append("Unpacking %s to %s" % (pkgfile, tmpdir)) unpacktar(pkgfile, tmpdir) for macdir in os.listdir(tmpdir): macdir = os.path.join(tmpdir, macdir) log.debug('Checking if we should sign %s', macdir) if shouldSign(macdir, 'mac'): log.debug('Signing %s', macdir) # Grab the code resources file. Need to find the filename code_resources = macdir + \ "/Contents/_CodeSignature/CodeResources" lockfile = os.path.join(os.path.dirname(keychain), '.lock') dmg_signfile(macdir, keychain, mac_id, code_resources, get_identifier(macdir), subject_ou, lockfile, passphrase=passphrase) # Repack it logs.append("Packing %s" % dstfile) tar_dir(dstfile, tmpdir) except: log.exception("Error signing %s", pkgfile) return False finally: # Clean up after ourselves, and output our logs shutil.rmtree(tmpdir) log.info("\n ".join(logs))
def main(): allowed_formats = ("signcode", "osslsigncode", "gpg", "mar", "dmg", "dmgv2", "jar", "b2gmar") from optparse import OptionParser import random parser = OptionParser(__doc__) parser.set_defaults( hosts=[], cert=None, log_level=logging.INFO, output_dir=None, output_file=None, formats=[], includes=[], excludes=[], nsscmd=None, tokenfile=None, noncefile=None, cachedir=None, ) parser.add_option("-H", "--host", dest="hosts", action="append", help="format[:format]:hostname[:port]") parser.add_option("-c", "--server-cert", dest="cert") parser.add_option("-t", "--token-file", dest="tokenfile", help="file where token is stored") parser.add_option("-n", "--nonce-file", dest="noncefile", help="file where nonce is stored") parser.add_option( "-d", "--output-dir", dest="output_dir", help= "output directory; if not set then files are replaced with signed copies" ) parser.add_option( "-o", "--output-file", dest="output_file", help= "output file; if not set then files are replaced with signed copies. This can only be used when signing a single file" ) parser.add_option("-f", "--formats", dest="formats", action="append", help="signing formats (one or more of %s)" % ", ".join(allowed_formats)) parser.add_option("-q", "--quiet", dest="log_level", action="store_const", const=logging.WARN) parser.add_option("-v", "--verbose", dest="log_level", action="store_const", const=logging.DEBUG) parser.add_option("-i", "--include", dest="includes", action="append", help="add to include patterns") parser.add_option("-x", "--exclude", dest="excludes", action="append", help="add to exclude patterns") parser.add_option("--nsscmd", dest="nsscmd", help="command to re-sign nss libraries, if required") parser.add_option("--cachedir", dest="cachedir", help="local cache directory") # TODO: Concurrency? # TODO: Different certs per server? options, args = parser.parse_args() logging.basicConfig(level=options.log_level, format="%(asctime)s - %(message)s") if not options.hosts: parser.error("at least one host is required") if not options.cert: parser.error("certificate is required") if not os.path.exists(options.cert): parser.error("certificate not found") if not options.tokenfile: parser.error("token file is required") if not options.noncefile: parser.error("nonce file is required") # Covert nsscmd to win32 path if required if sys.platform == 'win32' and options.nsscmd: nsscmd = options.nsscmd.strip() if nsscmd.startswith("/"): drive = nsscmd[1] options.nsscmd = "%s:%s" % (drive, nsscmd[2:]) # Handle format formats = [] for fmt in options.formats: if "," in fmt: for fmt in fmt.split(","): if fmt not in allowed_formats: parser.error("invalid format: %s" % fmt) formats.append(fmt) elif fmt not in allowed_formats: parser.error("invalid format: %s" % fmt) else: formats.append(fmt) if options.output_file and (len(args) > 1 or os.path.isdir(args[0])): parser.error( "-o / --output-file can only be used when signing a single file") if options.output_dir: if os.path.exists(options.output_dir): if not os.path.isdir(options.output_dir): parser.error("output_dir (%s) must be a directory", options.output_dir) else: os.makedirs(options.output_dir) if not options.includes: # Do everything! options.includes.append("*") if not formats: parser.error("no formats specified") format_urls = defaultdict(list) for h in options.hosts: # The last two parts of a host is the actual hostname:port. Any parts # before that are formats - there could be 0..n formats so this is # tricky to split. parts = h.split(":") h = parts[-2:] fmts = parts[:-2] # If no formats are specified, the host is assumed to support all of them. if not fmts: fmts = formats for f in fmts: format_urls[f].append("https://%s" % ":".join(h)) missing_fmt_hosts = set(formats) - set(format_urls.keys()) if missing_fmt_hosts: parser.error("no hosts capable of signing formats: %s" % " ".join(missing_fmt_hosts)) log.debug("in %s", os.getcwd()) buildValidatingOpener(options.cert) token = open(options.tokenfile, 'rb').read() for fmt in formats: urls = format_urls[fmt] random.shuffle(urls) # The only difference between dmg and dmgv2 are the servers they use. # The server side code only understands "dmg" as a format, so we need # to translate this now that we've chosen our URLs if fmt == "dmgv2": fmt = "dmg" log.debug("doing %s signing", fmt) log.debug("possible hosts are %s" % urls) files = [] # We want to package the ".app" file in a tar for mac signing. if fmt == "dmg": for fd in args: packtar(fd + '.tar.gz', [fd], os.getcwd()) files.append(fd + '.tar.gz') # For other platforms we sign all of the files individually. else: files = findfiles(args, options.includes, options.excludes) for f in files: log.debug("%s", f) log.debug("checking %s for signature...", f) if fmt in ('signcode', 'osslsigncode') and is_authenticode_signed(f): log.info( "Skipping %s because it looks like it's already signed", f) continue if options.output_dir: dest = os.path.join(options.output_dir, os.path.basename(f)) else: dest = None if not remote_signfile(options, urls, f, fmt, token, dest): log.error("Failed to sign %s with %s", f, fmt) sys.exit(1) if fmt == "dmg": for fd in args: log.debug("unpacking %s", fd) unpacktar(fd + '.tar.gz', os.getcwd()) os.unlink(fd + '.tar.gz')
def dmg_signpackage(pkgfile, dstfile, keychain, mac_id, subject_ou, fake=False, passphrase=None): """ Sign a mac build, putting results into `dstfile`. pkgfile must be a tar, which gets unpacked, signed, and repacked. """ # Keep track of our output in a list here, and we can output everything # when we're done This is to avoid interleaving the output from # multiple processes. from flufl.lock import Lock, TimeOutError, NotLockedError from datetime import timedelta import pexpect # TODO: Is it even possible to do 'fake' signing? logs = [] logs.append("Repacking %s to %s" % (pkgfile, dstfile)) # pexpect requires a string as input unlock_command = 'security unlock-keychain ' + keychain lock_command = ['security', 'lock-keychain', keychain] lockfile = os.path.join(os.path.dirname(keychain), '.lock') tmpdir = tempfile.mkdtemp() try: # Unpack it logs.append("Unpacking %s to %s" % (pkgfile, tmpdir)) unpacktar(pkgfile, tmpdir) for macdir in os.listdir(tmpdir): macdir = os.path.join(tmpdir, macdir) log.debug('Checking if we should sign %s', macdir) if shouldSign(macdir, 'mac'): log.debug('Need to sign %s', macdir) try: sign_lock = None # Acquire a lock for the signing command, to ensure we don't have a # race condition where one process locks the keychain immediately after another # unlocks it. log.debug("Try to acquire %s", lockfile) sign_lock = Lock(lockfile) # Put a 30 second timeout on waiting for the lock. sign_lock.lock(timedelta(0, 30)) # Unlock the keychain so that we do not get a user-interaction prompt to use # the keychain for signing. This operation requires a password. child = pexpect.spawn(unlock_command) child.expect('password to unlock .*') child.sendline(passphrase) # read output until child exits child.read() child.close() if child.exitstatus != 0: raise ValueError("keychain unlock failed") # Sign the thing! dmg_signfile(macdir, keychain, mac_id, subject_ou, fake) except TimeOutError: # timed out acquiring lock, give an error log.exception( "Timeout acquiring lock %s for codesign, is something broken? ", lockfile) raise except: # catch any other locking error log.exception( "Error acquiring %s for codesign, is something broken?", lockfile) raise finally: # Lock the keychain again, no matter what happens # This command does not require a password check_call(lock_command) # Release the lock, if it was acquired if sign_lock: try: sign_lock.unlock() log.debug("Release %s", lockfile) except NotLockedError: log.debug("%s was already unlocked", lockfile) # Repack it logs.append("Packing %s" % dstfile) tar_dir(dstfile, tmpdir) except: log.exception("Error signing %s", pkgfile) raise finally: # Clean up after ourselves, and output our logs shutil.rmtree(tmpdir) log.info("\n ".join(logs))
def main(): allowed_formats = ("sha2signcode", "signcode", "osslsigncode", "gpg", "mar", "dmg", "dmgv2", "jar", "emevoucher") from optparse import OptionParser import random parser = OptionParser(__doc__) parser.set_defaults( hosts=[], cert=None, log_level=logging.INFO, output_dir=None, output_file=None, formats=[], includes=[], excludes=[], nsscmd=None, tokenfile=None, noncefile=None, cachedir=None, ) parser.add_option( "-H", "--host", dest="hosts", action="append", help="format[:format]:hostname[:port]") parser.add_option("-c", "--server-cert", dest="cert") parser.add_option("-t", "--token-file", dest="tokenfile", help="file where token is stored") parser.add_option("-n", "--nonce-file", dest="noncefile", help="file where nonce is stored") parser.add_option("-d", "--output-dir", dest="output_dir", help="output directory; if not set then files are replaced with signed copies") parser.add_option("-o", "--output-file", dest="output_file", help="output file; if not set then files are replaced with signed copies. This can only be used when signing a single file") parser.add_option("-f", "--formats", dest="formats", action="append", help="signing formats (one or more of %s)" % ", ".join(allowed_formats)) parser.add_option("-q", "--quiet", dest="log_level", action="store_const", const=logging.WARN) parser.add_option( "-v", "--verbose", dest="log_level", action="store_const", const=logging.DEBUG) parser.add_option("-i", "--include", dest="includes", action="append", help="add to include patterns") parser.add_option("-x", "--exclude", dest="excludes", action="append", help="add to exclude patterns") parser.add_option("--nsscmd", dest="nsscmd", help="command to re-sign nss libraries, if required") parser.add_option("--cachedir", dest="cachedir", help="local cache directory") # TODO: Concurrency? # TODO: Different certs per server? options, args = parser.parse_args() logging.basicConfig( level=options.log_level, format="%(asctime)s - %(message)s") if not options.hosts: parser.error("at least one host is required") if not options.cert: parser.error("certificate is required") if not os.path.exists(options.cert): parser.error("certificate not found") if not options.tokenfile: parser.error("token file is required") if not options.noncefile: parser.error("nonce file is required") # Covert nsscmd to win32 path if required if sys.platform == 'win32' and options.nsscmd: nsscmd = options.nsscmd.strip() if nsscmd.startswith("/"): drive = nsscmd[1] options.nsscmd = "%s:%s" % (drive, nsscmd[2:]) # Handle format formats = [] for fmt in options.formats: if "," in fmt: for fmt in fmt.split(","): if fmt not in allowed_formats: parser.error("invalid format: %s" % fmt) formats.append(fmt) elif fmt not in allowed_formats: parser.error("invalid format: %s" % fmt) else: formats.append(fmt) # bug 1164456 # GPG signing must happen last because it will be invalid if done prior to # any format that modifies the file in-place. if "gpg" in formats: formats.remove("gpg") formats.append("gpg") if options.output_file and (len(args) > 1 or os.path.isdir(args[0])): parser.error( "-o / --output-file can only be used when signing a single file") if options.output_dir: if os.path.exists(options.output_dir): if not os.path.isdir(options.output_dir): parser.error( "output_dir (%s) must be a directory", options.output_dir) else: os.makedirs(options.output_dir) if not options.includes: # Do everything! options.includes.append("*") if not formats: parser.error("no formats specified") format_urls = defaultdict(list) for h in options.hosts: # The last two parts of a host is the actual hostname:port. Any parts # before that are formats - there could be 0..n formats so this is # tricky to split. parts = h.split(":") h = parts[-2:] fmts = parts[:-2] # If no formats are specified, the host is assumed to support all of them. if not fmts: fmts = formats for f in fmts: format_urls[f].append("https://%s" % ":".join(h)) missing_fmt_hosts = set(formats) - set(format_urls.keys()) if missing_fmt_hosts: parser.error("no hosts capable of signing formats: %s" % " ".join(missing_fmt_hosts)) log.debug("in %s", os.getcwd()) buildValidatingOpener(options.cert) token = open(options.tokenfile, 'rb').read() for fmt in formats: urls = format_urls[fmt] random.shuffle(urls) # The only difference between dmg and dmgv2 are the servers they use. # The server side code only understands "dmg" as a format, so we need # to translate this now that we've chosen our URLs if fmt == "dmgv2": fmt = "dmg" log.debug("doing %s signing", fmt) log.debug("possible hosts are %s" % urls) files = [] # We want to package the ".app" file in a tar for mac signing. if fmt == "dmg": for fd in args: packtar(fd + '.tar.gz', [fd], os.getcwd()) files.append(fd + '.tar.gz') # For other platforms we sign all of the files individually. else: files = findfiles(args, options.includes, options.excludes) for f in files: log.debug("%s", f) log.debug("checking %s for signature...", f) if fmt in ('sha2signcode', 'signcode', 'osslsigncode') and is_authenticode_signed(f): log.info("Skipping %s because it looks like it's already signed", f) continue if options.output_dir: dest = os.path.join(options.output_dir, os.path.basename(f)) else: dest = None if not remote_signfile(options, urls, f, fmt, token, dest): log.error("Failed to sign %s with %s", f, fmt) sys.exit(1) if fmt == "dmg": for fd in args: log.debug("unpacking %s", fd) unpacktar(fd + '.tar.gz', os.getcwd()) os.unlink(fd + '.tar.gz')
def dmg_signpackage(pkgfile, dstfile, keychain, mac_id, subject_ou, fake=False, passphrase=None): """ Sign a mac build, putting results into `dstfile`. pkgfile must be a tar, which gets unpacked, signed, and repacked. """ # Keep track of our output in a list here, and we can output everything # when we're done This is to avoid interleaving the output from # multiple processes. from flufl.lock import Lock, TimeOutError, NotLockedError from datetime import timedelta import pexpect # TODO: Is it even possible to do 'fake' signing? logs = [] logs.append("Repacking %s to %s" % (pkgfile, dstfile)) # pexpect requires a string as input unlock_command = 'security unlock-keychain ' + keychain lock_command = ['security', 'lock-keychain', keychain] lockfile = os.path.join(os.path.dirname(keychain), '.lock') tmpdir = tempfile.mkdtemp() try: # Unpack it logs.append("Unpacking %s to %s" % (pkgfile, tmpdir)) unpacktar(pkgfile, tmpdir) for macdir in os.listdir(tmpdir): macdir = os.path.join(tmpdir, macdir) log.debug('Checking if we should sign %s', macdir) if shouldSign(macdir, 'mac'): log.debug('Need to sign %s', macdir) try: sign_lock = None # Acquire a lock for the signing command, to ensure we don't have a # race condition where one process locks the keychain immediately after another # unlocks it. log.debug("Try to acquire %s", lockfile) sign_lock = Lock(lockfile) # Put a 30 second timeout on waiting for the lock. sign_lock.lock(timedelta(0, 30)) # Unlock the keychain so that we do not get a user-interaction prompt to use # the keychain for signing. This operation requires a password. child = pexpect.spawn(unlock_command) child.expect('password to unlock .*') child.sendline(passphrase) # read output until child exits child.read() child.close() if child.exitstatus != 0: raise ValueError("keychain unlock failed") # Sign the thing! dmg_signfile(macdir, keychain, mac_id, subject_ou, fake) except TimeOutError: # timed out acquiring lock, give an error log.exception("Timeout acquiring lock %s for codesign, is something broken? ", lockfile) raise except: # catch any other locking error log.exception("Error acquiring %s for codesign, is something broken?", lockfile) raise finally: # Lock the keychain again, no matter what happens # This command does not require a password check_call(lock_command) # Release the lock, if it was acquired if sign_lock: try: sign_lock.unlock() log.debug("Release %s", lockfile) except NotLockedError: log.debug("%s was already unlocked", lockfile) # Repack it logs.append("Packing %s" % dstfile) tar_dir(dstfile, tmpdir) except: log.exception("Error signing %s", pkgfile) raise finally: # Clean up after ourselves, and output our logs shutil.rmtree(tmpdir) log.info("\n ".join(logs))
def main(): from optparse import OptionParser import random parser = OptionParser(__doc__) parser.set_defaults( hosts=[], cert=None, log_level=logging.INFO, output_dir=None, output_file=None, formats=[], includes=[], excludes=[], nsscmd=None, tokenfile=None, noncefile=None, cachedir=None, ) parser.add_option("-H", "--host", dest="hosts", action="append", help="hostname[:port]") parser.add_option("-c", "--server-cert", dest="cert") parser.add_option("-t", "--token-file", dest="tokenfile", help="file where token is stored") parser.add_option("-n", "--nonce-file", dest="noncefile", help="file where nonce is stored") parser.add_option( "-d", "--output-dir", dest="output_dir", help= "output directory; if not set then files are replaced with signed copies" ) parser.add_option( "-o", "--output-file", dest="output_file", help= "output file; if not set then files are replaced with signed copies. This can only be used when signing a single file" ) parser.add_option( "-f", "--formats", dest="formats", action="append", help= "signing formats (one or more of \"signcode\", \"gpg\", or \"osx\")") parser.add_option("-q", "--quiet", dest="log_level", action="store_const", const=logging.WARN) parser.add_option("-v", "--verbose", dest="log_level", action="store_const", const=logging.DEBUG) parser.add_option("-i", "--include", dest="includes", action="append", help="add to include patterns") parser.add_option("-x", "--exclude", dest="excludes", action="append", help="add to exclude patterns") parser.add_option("--nsscmd", dest="nsscmd", help="command to re-sign nss libraries, if required") parser.add_option("--cachedir", dest="cachedir", help="local cache directory") # TODO: Concurrency? # TODO: Different certs per server? options, args = parser.parse_args() logging.basicConfig(level=options.log_level, format="%(asctime)s - %(message)s") if not options.hosts: parser.error("at least one host is required") if not options.cert: parser.error("certificate is required") if not os.path.exists(options.cert): parser.error("certificate not found") if not options.tokenfile: parser.error("token file is required") if not options.noncefile: parser.error("nonce file is required") # Covert nsscmd to win32 path if required if sys.platform == 'win32' and options.nsscmd: nsscmd = options.nsscmd.strip() if nsscmd.startswith("/"): drive = nsscmd[1] options.nsscmd = "%s:%s" % (drive, nsscmd[2:]) # Handle format formats = [] allowed_formats = ("signcode", "gpg", "mar", "dmg", "jar", "b2gmar") for fmt in options.formats: if "," in fmt: for fmt in fmt.split(","): if fmt not in allowed_formats: parser.error("invalid format: %s" % fmt) formats.append(fmt) elif fmt not in allowed_formats: parser.error("invalid format: %s" % fmt) else: formats.append(fmt) if options.output_file and (len(args) > 1 or os.path.isdir(args[0])): parser.error( "-o / --output-file can only be used when signing a single file") if options.output_dir: if os.path.exists(options.output_dir): if not os.path.isdir(options.output_dir): parser.error("output_dir (%s) must be a directory", options.output_dir) else: os.makedirs(options.output_dir) if not options.includes: # Do everything! options.includes.append("*") if not formats: parser.error("no formats specified") buildValidatingOpener(options.cert) urls = ["https://%s" % host for host in options.hosts] random.shuffle(urls) log.debug("in %s", os.getcwd()) token = open(options.tokenfile, 'rb').read() for fmt in formats: log.debug("doing %s signing", fmt) files = [] # We want to package the ".app" file in a tar for mac signing. if fmt == "dmg": for fd in args: packtar(fd + '.tar.gz', [fd], os.getcwd()) files.append(fd + '.tar.gz') # For other platforms we sign all of the files individually. else: files = findfiles(args, options.includes, options.excludes) for f in files: log.debug("%s", f) log.debug("checking %s for signature...", f) if fmt == 'signcode' and is_authenticode_signed(f): log.info( "Skipping %s because it looks like it's already signed", f) continue if options.output_dir: dest = os.path.join(options.output_dir, os.path.basename(f)) else: dest = None if not remote_signfile(options, urls, f, fmt, token, dest): log.error("Failed to sign %s with %s", f, fmt) sys.exit(1) if fmt == "dmg": for fd in args: log.debug("unpacking %s", fd) unpacktar(fd + '.tar.gz', os.getcwd()) os.unlink(fd + '.tar.gz')
def main(): from optparse import OptionParser import random parser = OptionParser(__doc__) parser.set_defaults( hosts=[], cert=None, log_level=logging.INFO, output_dir=None, output_file=None, formats=[], includes=[], excludes=[], nsscmd=None, tokenfile=None, noncefile=None, cachedir=None, ) parser.add_option( "-H", "--host", dest="hosts", action="append", help="hostname[:port]") parser.add_option("-c", "--server-cert", dest="cert") parser.add_option("-t", "--token-file", dest="tokenfile", help="file where token is stored") parser.add_option("-n", "--nonce-file", dest="noncefile", help="file where nonce is stored") parser.add_option("-d", "--output-dir", dest="output_dir", help="output directory; if not set then files are replaced with signed copies") parser.add_option("-o", "--output-file", dest="output_file", help="output file; if not set then files are replaced with signed copies. This can only be used when signing a single file") parser.add_option("-f", "--formats", dest="formats", action="append", help="signing formats (one or more of \"signcode\", \"gpg\", or \"osx\")") parser.add_option("-q", "--quiet", dest="log_level", action="store_const", const=logging.WARN) parser.add_option( "-v", "--verbose", dest="log_level", action="store_const", const=logging.DEBUG) parser.add_option("-i", "--include", dest="includes", action="append", help="add to include patterns") parser.add_option("-x", "--exclude", dest="excludes", action="append", help="add to exclude patterns") parser.add_option("--nsscmd", dest="nsscmd", help="command to re-sign nss libraries, if required") parser.add_option("--cachedir", dest="cachedir", help="local cache directory") # TODO: Concurrency? # TODO: Different certs per server? options, args = parser.parse_args() logging.basicConfig( level=options.log_level, format="%(asctime)s - %(message)s") if not options.hosts: parser.error("at least one host is required") if not options.cert: parser.error("certificate is required") if not os.path.exists(options.cert): parser.error("certificate not found") if not options.tokenfile: parser.error("token file is required") if not options.noncefile: parser.error("nonce file is required") # Covert nsscmd to win32 path if required if sys.platform == 'win32' and options.nsscmd: nsscmd = options.nsscmd.strip() if nsscmd.startswith("/"): drive = nsscmd[1] options.nsscmd = "%s:%s" % (drive, nsscmd[2:]) # Handle format formats = [] allowed_formats = ("signcode", "gpg", "mar", "dmg", "jar", "b2gmar") for fmt in options.formats: if "," in fmt: for fmt in fmt.split(","): if fmt not in allowed_formats: parser.error("invalid format: %s" % fmt) formats.append(fmt) elif fmt not in allowed_formats: parser.error("invalid format: %s" % fmt) else: formats.append(fmt) if options.output_file and (len(args) > 1 or os.path.isdir(args[0])): parser.error( "-o / --output-file can only be used when signing a single file") if options.output_dir: if os.path.exists(options.output_dir): if not os.path.isdir(options.output_dir): parser.error( "output_dir (%s) must be a directory", options.output_dir) else: os.makedirs(options.output_dir) if not options.includes: # Do everything! options.includes.append("*") if not formats: parser.error("no formats specified") buildValidatingOpener(options.cert) urls = ["https://%s" % host for host in options.hosts] random.shuffle(urls) log.debug("in %s", os.getcwd()) token = open(options.tokenfile, 'rb').read() for fmt in formats: log.debug("doing %s signing", fmt) files = [] # We want to package the ".app" file in a tar for mac signing. if fmt == "dmg": for fd in args: packtar(fd + '.tar.gz', [fd], os.getcwd()) files.append(fd + '.tar.gz') # For other platforms we sign all of the files individually. else: files = findfiles(args, options.includes, options.excludes) for f in files: log.debug("%s", f) log.debug("checking %s for signature...", f) if fmt == 'signcode' and is_authenticode_signed(f): log.info("Skipping %s because it looks like it's already signed", f) continue if options.output_dir: dest = os.path.join(options.output_dir, os.path.basename(f)) else: dest = None if not remote_signfile(options, urls, f, fmt, token, dest): log.error("Failed to sign %s with %s", f, fmt) sys.exit(1) if fmt == "dmg": for fd in args: log.debug("unpacking %s", fd) unpacktar(fd + '.tar.gz', os.getcwd()) os.unlink(fd + '.tar.gz')