Esempio n. 1
0
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))
Esempio n. 2
0
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))
Esempio n. 3
0
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))
Esempio n. 4
0
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))