diff --git a/bin/COMPILE.cmd b/bin/COMPILE.cmd index 39a9f23..a8556f5 100644 --- a/bin/COMPILE.cmd +++ b/bin/COMPILE.cmd @@ -14,10 +14,11 @@ SET OLD_PYTHONPATH=%PYTHONPATH% SET PYTHONPATH=c:\GIT\npbackup "%PYTHON64%" -m pip install --upgrade -r npbackup/requirements.txt || exit 1 -"%PYTHON64%" bin\compile.py --audience all +"%PYTHON64%" bin\compile.py --audience all --sign "C:\ODJ\KEYS\NetInventEV.dat" + "%PYTHON32%" -m pip install --upgrade -r npbackup/requirements.txt || exit 1 -"%PYTHON32%" bin\compile.py --audience all +"%PYTHON32%" bin\compile.py --audience all --sign "C:\ODJ\KEYS\NetInventEV.dat" SET PYTHONPATH=%OLD_PYTHONPATH% diff --git a/bin/compile.py b/bin/compile.py index 1a0ce80..ee60ce2 100644 --- a/bin/compile.py +++ b/bin/compile.py @@ -55,6 +55,7 @@ import glob LICENSE_FILE = os.path.join(BASEDIR, os.pardir, "LICENSE") +NUITKA_STANDALONE_SUFFIX = ".dist" del sys.path[0] @@ -183,7 +184,7 @@ def have_nuitka_commercial(): return False -def compile(arch: str, audience: str, build_type: str, onefile: bool, create_tar_only: bool, ev_cert_data: str = None): +def compile(arch: str, audience: str, build_type: str, onefile: bool, create_tar_only: bool, ev_cert_data: str = None, sign_only: bool = False): if build_type not in BUILD_TYPES: print("CANNOT BUILD BOGUS BUILD TYPE") sys.exit(1) @@ -320,7 +321,7 @@ def compile(arch: str, audience: str, build_type: str, onefile: bool, create_tar ) errors = False - if not create_tar_only: + if not create_tar_only and not sign_only: print(CMD) exit_code, output = command_runner(CMD, timeout=0, live_output=True) if exit_code != 0: @@ -334,7 +335,11 @@ def compile(arch: str, audience: str, build_type: str, onefile: bool, create_tar print(f"COMPILED {'WITH SUCCESS' if not errors else 'WITH ERRORS'}") if os.name == "nt" and ev_cert_data: - sign(ev_cert_data=ev_cert_data, dry_run=args.dry_run) + compiled_output_dir = os.path.join( + OUTPUT_DIR, "npbackup-{}{}".format(build_type, NUITKA_STANDALONE_SUFFIX) + ) + npbackup_executable = os.path.join(compiled_output_dir, "npbackup-{}.exe".format(build_type)) + sign(executable=npbackup_executable, arch=arch, ev_cert_data=ev_cert_data, dry_run=args.dry_run) if not onefile: if not create_archive( @@ -354,11 +359,11 @@ def create_archive( """ Create tar releases for each compiled version """ - nuitka_standalone_suffix = ".dist" + compiled_output = os.path.join( - output_dir, "npbackup-{}{}".format(build_type, nuitka_standalone_suffix) + output_dir, "npbackup-{}{}".format(build_type, NUITKA_STANDALONE_SUFFIX) ) - new_compiled_output = compiled_output[: -len(nuitka_standalone_suffix)] + new_compiled_output = compiled_output[: -len(NUITKA_STANDALONE_SUFFIX)] if os.path.isdir(new_compiled_output): shutil.rmtree(new_compiled_output) shutil.move(compiled_output, new_compiled_output) @@ -437,6 +442,23 @@ if __name__ == "__main__": help="Digitally sign windows executables", ) + + parser.add_argument( + "--sign-only", + action="store_true", + default=False, + required=False, + help="Only digitally sign built executables", + ) + + parser.add_argument( + "--dry-run", + action="store_true", + default=False, + required=False, + help="Dry run current action", + ) + parser.add_argument( "--create-tar-only", action="store_true", @@ -469,6 +491,7 @@ if __name__ == "__main__": build_types = BUILD_TYPES create_tar_only = args.create_tar_only + sign_only = args.sign_only for audience in audiences: npbackup_version = get_metadata(os.path.join(BASEDIR, "__version__.py"))[ @@ -493,9 +516,10 @@ if __name__ == "__main__": build_type=build_type, onefile=args.onefile, create_tar_only=create_tar_only, - ev_cert_data=args.ev_cert_data + ev_cert_data=args.ev_cert_data, + sign_only=sign_only ) - if not create_tar_only: + if not create_tar_only and not sign_only: audience_build = "private" if private_build else "public" if result: print( diff --git a/npbackup/configuration.py b/npbackup/configuration.py index 64673a1..166961a 100644 --- a/npbackup/configuration.py +++ b/npbackup/configuration.py @@ -37,7 +37,7 @@ sys.path.insert(0, os.path.normpath(os.path.join(os.path.dirname(__file__), ".." # Try to import a private key, if not available, fallback to the default key try: from PRIVATE._private_secret_keys import AES_KEY - from PRIVATE._private_obfuscation import obfuscation + from PRIVATE._obfuscation import obfuscation AES_KEY = obfuscation(AES_KEY) IS_PRIV_BUILD = True diff --git a/npbackup/windows/sign_windows.py b/npbackup/windows/sign_windows.py index 9892493..7fa2779 100644 --- a/npbackup/windows/sign_windows.py +++ b/npbackup/windows/sign_windows.py @@ -33,14 +33,14 @@ def check_private_ev(): Test if we have private ev data """ try: - from PRIVATE._private_ev_data import AES_EV_KEY - from PRIVATE._private_obfuscation import obfuscation + from PRIVATE._ev_data import AES_EV_KEY + from PRIVATE._obfuscation import obfuscation print("We have private EV certifcate DATA") return obfuscation(AES_EV_KEY) except ImportError as exc: print("ERROR: Cannot load private EV certificate DATA: {}".format(exc)) - sys.exit() + sys.exit(1) def get_ev_data(cert_data_path): @@ -64,7 +64,7 @@ def get_ev_data(cert_data_path): return pkcs12_certificate, pkcs12_password, container_name, cryptographic_provider -def sign(ev_cert_data: str = None, dry_run: bool = False): +def sign(executable: str = None, arch: str = None, ev_cert_data: str = None, dry_run: bool = False): if ev_cert_data: ( pkcs12_certificate, @@ -81,6 +81,16 @@ def sign(ev_cert_data: str = None, dry_run: bool = False): else: signer = SignTool() + if executable: + print(f"Signing {executable}") + result = signer.sign(executable, bitness=arch, dry_run=dry_run) + if not result: + # IMPORTANT: If using an automated crypto USB EV token, we need to stop on error so we don't lock ourselves out of the token with bad password attempts + raise EnvironmentError( + "Could not sign executable ! Is the PKI key connected ?" + ) + return result + for audience in audiences: for arch in arches: for binary in binaries: