Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dev sign all windows executables #8217

Draft
wants to merge 14 commits into
base: dev
Choose a base branch
from
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,4 @@ editor/.lsp/sqlite.db
/com.dynamo.cr/com.dynamo.cr.bob/src/com/dynamo/bob/pipeline/antlr/**/*.tokens

/com.dynamo.cr/com.dynamo.cr.bob/libexec/**/lipo*
ci/gcloud_keyfile.json
90 changes: 90 additions & 0 deletions build_tools/sign.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
#!/usr/bin/env python
# Copyright 2020-2023 The Defold Foundation
# Copyright 2014-2020 King
# Copyright 2009-2014 Ragnar Svensson, Christian Murray
# Licensed under the Defold License version 1.0 (the "License"); you may not use
# this file except in compliance with the License.
#
# You may obtain a copy of the License, together with FAQs at
# https://www.defold.com/license
#
# Unless required by applicable law or agreed to in writing, software distributed
# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
# CONDITIONS OF ANY KIND, either express or implied. See the License for the
# specific language governing permissions and limitations under the License.

import run
import os
import sys

def is_valid_codesigning_identity(codesigning_identity):
return run.command(['security', 'find-identity', '-p', 'codesigning', '-v']).find(codesigning_identity) >= 0


def sign_dmg(file, options):
if options.skip_codesign:
return

if not file:
print("You must provide a file to sign")
sys.exit(1)

if not is_valid_codesigning_identity(options.codesigning_identity):
error("Codesigning certificate not found for signing identity %s" % (options.codesigning_identity))
sys.exit(1)

run.command(['codesign', '-s', options.codesigning_identity, file])


def sign_file(file, platform, options):
if not file:
print("You must provide a file to sign")
sys.exit(1)

if options.skip_codesign:
print("Code signing not enabled. Ignoring file " + file)
return

print("Signing file " + file)
if 'win32' in platform:
run.command([
'gcloud',
'auth',
'activate-service-account',
'--key-file', options.gcloud_keyfile], silent = True)

storepass = run.command([
'gcloud',
'auth',
'print-access-token'], silent = True)

jsign = os.path.join(os.environ['DYNAMO_HOME'], 'ext','share','java','jsign-4.2.jar')
keystore = "projects/%s/locations/%s/keyRings/%s" % (options.gcloud_projectid, options.gcloud_location, options.gcloud_keyringname)
result = run.command([
'java', '-jar', jsign,
'--storetype', 'GOOGLECLOUD',
'--storepass', storepass,
'--keystore', keystore,
'--alias', options.gcloud_keyname,
'--certfile', options.gcloud_certfile,
'--tsmode', 'RFC3161',
'--tsaurl', 'http://timestamp.globalsign.com/tsa/r6advanced1',
file], silent = True)

# make sure to remove the password before displaying the output
result = result.replace(storepass, "***")
print(result)

elif 'macos' in platform:
if not is_valid_codesigning_identity(options.codesigning_identity):
print("Codesigning certificate not found for signing identity %s" % (options.codesigning_identity))
sys.exit(1)

run.command([
'codesign',
'--deep',
'--force',
'--options', 'runtime',
'--entitlements', './scripts/entitlements.plist',
'-s', options.codesigning_identity,
file])
50 changes: 29 additions & 21 deletions ci/ci.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,34 @@ def b64decode_to_file(str, destfile):
with open(destfile, "wb") as f:
f.write(base64.decodebytes(str.encode()))

def create_gcloud_code_signing_options(gcloud_keyfile = None, gcloud_certfile = None):
opts = []

if not gcloud_keyfile or not gcloud_certfile:
return opts

# windows EV Code Signing with key in Google Cloud KMS
opts.append("--gcloud-location=europe-west3")
opts.append("--gcloud-keyname=ev-windows-key")
opts.append("--gcloud-keyringname=ev-key-ring")
opts.append("--gcloud-projectid=defold-editor")

gcloud_keyfile = os.path.abspath(gcloud_keyfile)
if not os.path.exists(gcloud_keyfile):
print("Google Cloud key file not found:", gcloud_keyfile)
sys.exit(1)
print("Using Google Cloud key file", gcloud_keyfile)
opts.append('--gcloud-keyfile=%s' % gcloud_keyfile)

gcloud_certfile = os.path.abspath(gcloud_certfile)
if not os.path.exists(gcloud_certfile):
print("Google Cloud certificate not found:", gcloud_certfile)
sys.exit(1)
print("Using Google Cloud certificate ", gcloud_certfile)
opts.append('--gcloud-certfile=%s' % gcloud_certfile)

return opts

def setup_keychain(args):
print("Setting up keychain")
keychain_pass = "foobar"
Expand Down Expand Up @@ -294,27 +322,7 @@ def sign_editor2(platform, gcloud_keyfile = None, gcloud_certfile = None):
opts = []

opts.append('--platform=%s' % platform)

# windows EV Code Signing with key in Google Cloud KMS
if gcloud_keyfile and gcloud_certfile:
opts.append("--gcloud-location=europe-west3")
opts.append("--gcloud-keyname=ev-windows-key")
opts.append("--gcloud-keyringname=ev-key-ring")
opts.append("--gcloud-projectid=defold-editor")

gcloud_keyfile = os.path.abspath(gcloud_keyfile)
if not os.path.exists(gcloud_keyfile):
print("Google Cloud key file not found:", gcloud_keyfile)
sys.exit(1)
print("Using Google Cloud key file", gcloud_keyfile)
opts.append('--gcloud-keyfile=%s' % gcloud_keyfile)

gcloud_certfile = os.path.abspath(gcloud_certfile)
if not os.path.exists(gcloud_certfile):
print("Google Cloud certificate not found:", gcloud_certfile)
sys.exit(1)
print("Using Google Cloud certificate ", gcloud_certfile)
opts.append('--gcloud-certfile=%s' % gcloud_certfile)
opts.extend(create_gcloud_code_signing_options(gcloud_keyfile, gcloud_certfile))

cmd = ' '.join(args + opts)
call(cmd)
Expand Down
69 changes: 7 additions & 62 deletions editor/scripts/bundle.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ def get_tag_suffix(self):
# defold/build_tools
import run
import http_cache
from sign import sign_file, sign_dmg


DEFAULT_ARCHIVE_DOMAIN=os.environ.get("DM_ARCHIVE_DOMAIN", "d.defold.com")
Expand Down Expand Up @@ -187,56 +188,6 @@ def rmtree(path):
if os.path.exists(path):
shutil.rmtree(path, onerror=remove_readonly_retry)

def mac_certificate(codesigning_identity):
if run.command(['security', 'find-identity', '-p', 'codesigning', '-v']).find(codesigning_identity) >= 0:
return codesigning_identity
else:
return None

def sign_file(platform, options, file):
if options.skip_codesign:
return
if 'win32' in platform:
run.command([
'gcloud',
'auth',
'activate-service-account',
'--key-file', options.gcloud_keyfile], silent = True)

storepass = run.command([
'gcloud',
'auth',
'print-access-token'], silent = True)

jsign = os.path.join(os.environ['DYNAMO_HOME'], 'ext','share','java','jsign-4.2.jar')
keystore = "projects/%s/locations/%s/keyRings/%s" % (options.gcloud_projectid, options.gcloud_location, options.gcloud_keyringname)
run.command([
'java', '-jar', jsign,
'--storetype', 'GOOGLECLOUD',
'--storepass', storepass,
'--keystore', keystore,
'--alias', options.gcloud_keyname,
'--certfile', options.gcloud_certfile,
'--tsmode', 'RFC3161',
'--tsaurl', 'http://timestamp.globalsign.com/tsa/r6advanced1',
file], silent = True)

if 'macos' in platform:
codesigning_identity = options.codesigning_identity
certificate = mac_certificate(codesigning_identity)
if certificate == None:
print("Codesigning certificate not found for signing identity %s" % (codesigning_identity))
sys.exit(1)

run.command([
'codesign',
'--deep',
'--force',
'--options', 'runtime',
'--entitlements', './scripts/entitlements.plist',
'-s', certificate,
file])

def launcher_path(options, platform, exe_suffix):
if options.launcher:
return options.launcher
Expand Down Expand Up @@ -520,13 +471,13 @@ def sign(options):
jdk_dir = "jdk-%s" % (java_version)
jdk_path = os.path.join(sign_dir, "Defold.app", "Contents", "Resources", "packages", jdk_dir)
for exe in find_files(os.path.join(jdk_path, "bin"), "*"):
sign_file('macos', options, exe)
sign_file(exe, 'macos', options)
for lib in find_files(os.path.join(jdk_path, "lib"), "*.dylib"):
sign_file('macos', options, lib)
sign_file('macos', options, os.path.join(jdk_path, "lib", "jspawnhelper"))
sign_file('macos', options, os.path.join(sign_dir, "Defold.app"))
sign_file(lib, 'macos', options)
sign_file(os.path.join(jdk_path, "lib", "jspawnhelper"), 'macos', options)
sign_file(os.path.join(sign_dir, "Defold.app"), 'macos', options)
elif 'win32' in platform:
sign_file('win32', options, os.path.join(sign_dir, "Defold", "Defold.exe"))
sign_file(os.path.join(sign_dir, "Defold", "Defold.exe"), 'win32', options)

# create editor bundle with signed files
os.remove(bundle_file)
Expand Down Expand Up @@ -574,13 +525,7 @@ def create_dmg(options, platform):
run.command(['hdiutil', 'create', '-fs', 'JHFS+', '-volname', 'Defold', '-srcfolder', dmg_dir, dmg_file])

# sign the dmg
if not options.skip_codesign:
certificate = mac_certificate(options.codesigning_identity)
if certificate == None:
error("Codesigning certificate not found for signing identity %s" % (options.codesigning_identity))
sys.exit(1)

run.command(['codesign', '-s', certificate, dmg_file])
sign_dmg(dmg_file, options)


def create_installer(options):
Expand Down
Binary file modified packages/luajit-2.1.0-6c4826f-win32.tar.gz
Binary file not shown.
Binary file modified packages/luajit-2.1.0-6c4826f-x86_64-win32.tar.gz
Binary file not shown.
11 changes: 7 additions & 4 deletions scripts/ev_code_signing.sh
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
#!/usr/bin/env bash

gcloud_keyfile="defold-editor-db2d7e2b52d7.json"
file=${1}

gcloud_projectid="defold-editor"
gcloud_location="europe-west3"
gcloud_keyringname="ev-key-ring"
gcloud_keyname="ev-windows-key"
gcloud_certfile="codesign-chain.pem"
gcloud_certfile="ci/gcloud_certfile.cer"
gcloud_keyfile="ci/gcloud_keyfile.json"

keystore="projects/${gcloud_projectid}/locations/${gcloud_location}/keyRings/${gcloud_keyringname}"
jsign="tmp/dynamo_home/ext/share/java/jsign-4.2.jar"

jsign="${DYNAMO_HOME}/ext/share/java/jsign-4.2.jar"

gcloud auth activate-service-account --key-file="${gcloud_keyfile}"

java -jar "${jsign}" --storetype GOOGLECLOUD --storepass "$(gcloud auth print-access-token)" --keystore "${keystore}" --alias "${gcloud_keyname}" --certfile "${gcloud_certfile}" --tsmode 'RFC3161' --tsaurl 'http://timestamp.globalsign.com/tsa/r6advanced1' Defold.exe
java -jar "${jsign}" --storetype GOOGLECLOUD --storepass "$(gcloud auth print-access-token)" --keystore "${keystore}" --alias "${gcloud_keyname}" --certfile "${gcloud_certfile}" --tsmode 'RFC3161' --tsaurl 'http://timestamp.globalsign.com/tsa/r6advanced1' ${file}