diff --git a/core/core_constants.cpp b/core/core_constants.cpp
index d88dda66090..ceab71ff2e6 100644
--- a/core/core_constants.cpp
+++ b/core/core_constants.cpp
@@ -704,6 +704,7 @@ void register_global_constants() {
BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_EDITOR_INSTANTIATE_OBJECT);
BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_EDITOR_BASIC_SETTING);
BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_READ_ONLY);
+ BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_SECRET);
BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_DEFAULT);
BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_NO_EDITOR);
diff --git a/core/object/object.h b/core/object/object.h
index ed2c6254174..2e709d6ffe5 100644
--- a/core/object/object.h
+++ b/core/object/object.h
@@ -118,6 +118,7 @@ enum PropertyUsageFlags {
PROPERTY_USAGE_EDITOR_INSTANTIATE_OBJECT = 1 << 26, // For Object properties, instantiate them when creating in editor.
PROPERTY_USAGE_EDITOR_BASIC_SETTING = 1 << 27, //for project or editor settings, show when basic settings are selected.
PROPERTY_USAGE_READ_ONLY = 1 << 28, // Mark a property as read-only in the inspector.
+ PROPERTY_USAGE_SECRET = 1 << 29, // Export preset credentials that should be stored separately from the rest of the export config.
PROPERTY_USAGE_DEFAULT = PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_EDITOR,
PROPERTY_USAGE_NO_EDITOR = PROPERTY_USAGE_STORAGE,
diff --git a/doc/classes/@GlobalScope.xml b/doc/classes/@GlobalScope.xml
index a0b623936a6..b98d9adcecc 100644
--- a/doc/classes/@GlobalScope.xml
+++ b/doc/classes/@GlobalScope.xml
@@ -2842,6 +2842,9 @@
The property is read-only in the [EditorInspector].
+
+ An export preset property with this flag contains confidential information and is stored separately from the rest of the export preset configuration.
+
Default usage (storage, editor and network).
diff --git a/editor/export/editor_export.cpp b/editor/export/editor_export.cpp
index 3f192342a18..c6faefc45fe 100644
--- a/editor/export/editor_export.cpp
+++ b/editor/export/editor_export.cpp
@@ -37,7 +37,9 @@ EditorExport *EditorExport::singleton = nullptr;
void EditorExport::_save() {
Ref config;
+ Ref credentials;
config.instantiate();
+ credentials.instantiate();
for (int i = 0; i < export_presets.size(); i++) {
Ref preset = export_presets[i];
String section = "preset." + itos(i);
@@ -83,16 +85,21 @@ void EditorExport::_save() {
config->set_value(section, "encryption_exclude_filters", preset->get_enc_ex_filter());
config->set_value(section, "encrypt_pck", preset->get_enc_pck());
config->set_value(section, "encrypt_directory", preset->get_enc_directory());
- config->set_value(section, "script_encryption_key", preset->get_script_encryption_key());
+ credentials->set_value(section, "script_encryption_key", preset->get_script_encryption_key());
String option_section = "preset." + itos(i) + ".options";
for (const PropertyInfo &E : preset->get_properties()) {
- config->set_value(option_section, E.name, preset->get(E.name));
+ if (E.usage & PROPERTY_USAGE_SECRET) {
+ credentials->set_value(option_section, E.name, preset->get(E.name));
+ } else {
+ config->set_value(option_section, E.name, preset->get(E.name));
+ }
}
}
config->save("res://export_presets.cfg");
+ credentials->save("res://.godot/export_credentials.cfg");
}
void EditorExport::save_presets() {
@@ -202,6 +209,13 @@ void EditorExport::load_config() {
return;
}
+ Ref credentials;
+ credentials.instantiate();
+ err = credentials->load("res://.godot/export_credentials.cfg");
+ if (!(err == OK || err == ERR_FILE_NOT_FOUND)) {
+ return;
+ }
+
block_save = true;
int index = 0;
@@ -284,22 +298,30 @@ void EditorExport::load_config() {
if (config->has_section_key(section, "encryption_exclude_filters")) {
preset->set_enc_ex_filter(config->get_value(section, "encryption_exclude_filters"));
}
- if (config->has_section_key(section, "script_encryption_key")) {
- preset->set_script_encryption_key(config->get_value(section, "script_encryption_key"));
+ if (credentials->has_section_key(section, "script_encryption_key")) {
+ preset->set_script_encryption_key(credentials->get_value(section, "script_encryption_key"));
}
String option_section = "preset." + itos(index) + ".options";
List options;
-
config->get_section_keys(option_section, &options);
for (const String &E : options) {
Variant value = config->get_value(option_section, E);
-
preset->set(E, value);
}
+ if (credentials->has_section(option_section)) {
+ options.clear();
+ credentials->get_section_keys(option_section, &options);
+
+ for (const String &E : options) {
+ Variant value = credentials->get_value(option_section, E);
+ preset->set(E, value);
+ }
+ }
+
add_export_preset(preset);
index++;
}
diff --git a/editor/export/editor_export_platform.cpp b/editor/export/editor_export_platform.cpp
index 670f5af713b..65ffa45b383 100644
--- a/editor/export/editor_export_platform.cpp
+++ b/editor/export/editor_export_platform.cpp
@@ -818,6 +818,14 @@ String EditorExportPlatform::_export_customize(const String &p_path, LocalVector
return save_path.is_empty() ? p_path : save_path;
}
+String EditorExportPlatform::_get_script_encryption_key(const Ref &p_preset) const {
+ const String from_env = OS::get_singleton()->get_environment(ENV_SCRIPT_ENCRYPTION_KEY);
+ if (!from_env.is_empty()) {
+ return from_env.to_lower();
+ }
+ return p_preset->get_script_encryption_key().to_lower();
+}
+
Vector EditorExportPlatform::get_forced_export_files() {
Vector files;
@@ -946,7 +954,7 @@ Error EditorExportPlatform::export_project_files(const Ref &
}
// Get encryption key.
- String script_key = p_preset->get_script_encryption_key().to_lower();
+ String script_key = _get_script_encryption_key(p_preset);
key.resize(32);
if (script_key.length() == 64) {
for (int i = 0; i < 32; i++) {
@@ -1577,7 +1585,7 @@ Error EditorExportPlatform::save_pack(const Ref &p_preset, b
Ref fhead = f;
if (enc_pck && enc_directory) {
- String script_key = p_preset->get_script_encryption_key().to_lower();
+ String script_key = _get_script_encryption_key(p_preset);
Vector key;
key.resize(32);
if (script_key.length() == 64) {
diff --git a/editor/export/editor_export_platform.h b/editor/export/editor_export_platform.h
index df5a66f099a..3b9663ebdf3 100644
--- a/editor/export/editor_export_platform.h
+++ b/editor/export/editor_export_platform.h
@@ -43,6 +43,8 @@ struct EditorProgress;
class EditorExportPlugin;
+const String ENV_SCRIPT_ENCRYPTION_KEY = "GODOT_SCRIPT_ENCRYPTION_KEY";
+
class EditorExportPlatform : public RefCounted {
GDCLASS(EditorExportPlatform, RefCounted);
@@ -116,6 +118,7 @@ private:
bool _is_editable_ancestor(Node *p_root, Node *p_node);
String _export_customize(const String &p_path, LocalVector[> &customize_resources_plugins, LocalVector][> &customize_scenes_plugins, HashMap &export_cache, const String &export_base_path, bool p_force_save);
+ String _get_script_encryption_key(const Ref &p_preset) const;
protected:
struct ExportNotifier {
diff --git a/editor/export/editor_export_preset.cpp b/editor/export/editor_export_preset.cpp
index ac934796052..2aca19a2ad5 100644
--- a/editor/export/editor_export_preset.cpp
+++ b/editor/export/editor_export_preset.cpp
@@ -302,4 +302,15 @@ String EditorExportPreset::get_script_encryption_key() const {
return script_key;
}
+Variant EditorExportPreset::get_or_env(const StringName &p_name, const String &p_env_var, bool *r_valid) const {
+ const String from_env = OS::get_singleton()->get_environment(p_env_var);
+ if (!from_env.is_empty()) {
+ if (r_valid) {
+ *r_valid = true;
+ }
+ return from_env;
+ }
+ return get(p_name, r_valid);
+}
+
EditorExportPreset::EditorExportPreset() {}
diff --git a/editor/export/editor_export_preset.h b/editor/export/editor_export_preset.h
index 003e3c05a35..194858b4e87 100644
--- a/editor/export/editor_export_preset.h
+++ b/editor/export/editor_export_preset.h
@@ -152,6 +152,8 @@ public:
void set_script_encryption_key(const String &p_key);
String get_script_encryption_key() const;
+ Variant get_or_env(const StringName &p_name, const String &p_env_var, bool *r_valid = nullptr) const;
+
const List &get_properties() const { return properties; }
EditorExportPreset();
diff --git a/platform/android/doc_classes/EditorExportPlatformAndroid.xml b/platform/android/doc_classes/EditorExportPlatformAndroid.xml
index 1a077742879..11129ca1496 100644
--- a/platform/android/doc_classes/EditorExportPlatformAndroid.xml
+++ b/platform/android/doc_classes/EditorExportPlatformAndroid.xml
@@ -58,21 +58,27 @@
Path of the debug keystore file.
+ Can be overridden with the environment variable [code]GODOT_ANDROID_KEYSTORE_DEBUG_PATH[/code].
Password for the debug keystore file.
+ Can be overridden with the environment variable [code]GODOT_ANDROID_KEYSTORE_DEBUG_PASSWORD[/code].
User name for the debug keystore file.
+ Can be overridden with the environment variable [code]GODOT_ANDROID_KEYSTORE_DEBUG_USER[/code].
Path of the release keystore file.
+ Can be overridden with the environment variable [code]GODOT_ANDROID_KEYSTORE_RELEASE_PATH[/code].
Password for the release keystore file.
+ Can be overridden with the environment variable [code]GODOT_ANDROID_KEYSTORE_RELEASE_PASSWORD[/code].
User name for the release keystore file.
+ Can be overridden with the environment variable [code]GODOT_ANDROID_KEYSTORE_RELEASE_USER[/code].
Background layer of the application adaptive icon file.
diff --git a/platform/android/export/export_plugin.cpp b/platform/android/export/export_plugin.cpp
index 87f4cf2de2d..d8dd453faff 100644
--- a/platform/android/export/export_plugin.cpp
+++ b/platform/android/export/export_plugin.cpp
@@ -1825,12 +1825,12 @@ void EditorExportPlatformAndroid::get_export_options(List *r_optio
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, vformat("%s/%s", PNAME("architectures"), abi)), is_default));
}
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "keystore/debug", PROPERTY_HINT_GLOBAL_FILE, "*.keystore,*.jks"), ""));
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "keystore/debug_user"), ""));
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "keystore/debug_password"), ""));
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "keystore/release", PROPERTY_HINT_GLOBAL_FILE, "*.keystore,*.jks"), ""));
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "keystore/release_user"), ""));
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "keystore/release_password"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "keystore/debug", PROPERTY_HINT_GLOBAL_FILE, "*.keystore,*.jks", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SECRET), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "keystore/debug_user", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SECRET), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "keystore/debug_password", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SECRET), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "keystore/release", PROPERTY_HINT_GLOBAL_FILE, "*.keystore,*.jks", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SECRET), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "keystore/release_user", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SECRET), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "keystore/release_password", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SECRET), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "version/code", PROPERTY_HINT_RANGE, "1,4096,1,or_greater"), 1));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "version/name"), "1.0"));
@@ -2277,9 +2277,9 @@ bool EditorExportPlatformAndroid::has_valid_export_configuration(const Refget("keystore/debug");
- String dk_user = p_preset->get("keystore/debug_user");
- String dk_password = p_preset->get("keystore/debug_password");
+ String dk = p_preset->get_or_env("keystore/debug", ENV_ANDROID_KEYSTORE_DEBUG_PATH);
+ String dk_user = p_preset->get_or_env("keystore/debug_user", ENV_ANDROID_KEYSTORE_DEBUG_USER);
+ String dk_password = p_preset->get_or_env("keystore/debug_password", ENV_ANDROID_KEYSTORE_DEBUG_PASS);
if ((dk.is_empty() || dk_user.is_empty() || dk_password.is_empty()) && (!dk.is_empty() || !dk_user.is_empty() || !dk_password.is_empty())) {
valid = false;
@@ -2294,9 +2294,9 @@ bool EditorExportPlatformAndroid::has_valid_export_configuration(const Refget("keystore/release");
- String rk_user = p_preset->get("keystore/release_user");
- String rk_password = p_preset->get("keystore/release_password");
+ String rk = p_preset->get_or_env("keystore/release", ENV_ANDROID_KEYSTORE_RELEASE_PATH);
+ String rk_user = p_preset->get_or_env("keystore/release_user", ENV_ANDROID_KEYSTORE_RELEASE_USER);
+ String rk_password = p_preset->get_or_env("keystore/release_password", ENV_ANDROID_KEYSTORE_RELEASE_PASS);
if ((rk.is_empty() || rk_user.is_empty() || rk_password.is_empty()) && (!rk.is_empty() || !rk_user.is_empty() || !rk_password.is_empty())) {
valid = false;
@@ -2507,9 +2507,9 @@ void EditorExportPlatformAndroid::get_command_line_flags(const Ref &p_preset, bool p_debug, const String &export_path, EditorProgress &ep) {
int export_format = int(p_preset->get("gradle_build/export_format"));
String export_label = export_format == EXPORT_FORMAT_AAB ? "AAB" : "APK";
- String release_keystore = p_preset->get("keystore/release");
- String release_username = p_preset->get("keystore/release_user");
- String release_password = p_preset->get("keystore/release_password");
+ String release_keystore = p_preset->get_or_env("keystore/release", ENV_ANDROID_KEYSTORE_RELEASE_PATH);
+ String release_username = p_preset->get_or_env("keystore/release_user", ENV_ANDROID_KEYSTORE_RELEASE_USER);
+ String release_password = p_preset->get_or_env("keystore/release_password", ENV_ANDROID_KEYSTORE_RELEASE_PASS);
String target_sdk_version = p_preset->get("gradle_build/target_sdk");
if (!target_sdk_version.is_valid_int()) {
target_sdk_version = itos(DEFAULT_TARGET_SDK_VERSION);
@@ -2529,9 +2529,9 @@ Error EditorExportPlatformAndroid::sign_apk(const Ref &p_pre
String password;
String user;
if (p_debug) {
- keystore = p_preset->get("keystore/debug");
- password = p_preset->get("keystore/debug_password");
- user = p_preset->get("keystore/debug_user");
+ keystore = p_preset->get_or_env("keystore/debug", ENV_ANDROID_KEYSTORE_DEBUG_PATH);
+ password = p_preset->get_or_env("keystore/debug_password", ENV_ANDROID_KEYSTORE_DEBUG_PASS);
+ user = p_preset->get_or_env("keystore/debug_user", ENV_ANDROID_KEYSTORE_DEBUG_USER);
if (keystore.is_empty()) {
keystore = EDITOR_GET("export/android/debug_keystore");
@@ -2886,9 +2886,9 @@ Error EditorExportPlatformAndroid::export_project_helper(const Refget("keystore/debug");
- String debug_password = p_preset->get("keystore/debug_password");
- String debug_user = p_preset->get("keystore/debug_user");
+ String debug_keystore = p_preset->get_or_env("keystore/debug", ENV_ANDROID_KEYSTORE_DEBUG_PATH);
+ String debug_password = p_preset->get_or_env("keystore/debug_password", ENV_ANDROID_KEYSTORE_DEBUG_PASS);
+ String debug_user = p_preset->get_or_env("keystore/debug_user", ENV_ANDROID_KEYSTORE_DEBUG_USER);
if (debug_keystore.is_empty()) {
debug_keystore = EDITOR_GET("export/android/debug_keystore");
@@ -2908,9 +2908,9 @@ Error EditorExportPlatformAndroid::export_project_helper(const Refget("keystore/release");
- String release_username = p_preset->get("keystore/release_user");
- String release_password = p_preset->get("keystore/release_password");
+ String release_keystore = p_preset->get_or_env("keystore/release", ENV_ANDROID_KEYSTORE_RELEASE_PATH);
+ String release_username = p_preset->get_or_env("keystore/release_user", ENV_ANDROID_KEYSTORE_RELEASE_USER);
+ String release_password = p_preset->get_or_env("keystore/release_password", ENV_ANDROID_KEYSTORE_RELEASE_PASS);
if (release_keystore.is_relative_path()) {
release_keystore = OS::get_singleton()->get_resource_dir().path_join(release_keystore).simplify_path();
}
diff --git a/platform/android/export/export_plugin.h b/platform/android/export/export_plugin.h
index f9dad5ce5e0..390b8c6465c 100644
--- a/platform/android/export/export_plugin.h
+++ b/platform/android/export/export_plugin.h
@@ -49,6 +49,15 @@ const String SPLASH_CONFIG_XML_CONTENT = R"SPLASH(
)SPLASH";
+// Optional environment variables for defining confidential information. If any
+// of these is set, they will override the values set in the credentials file.
+const String ENV_ANDROID_KEYSTORE_DEBUG_PATH = "GODOT_ANDROID_KEYSTORE_DEBUG_PATH";
+const String ENV_ANDROID_KEYSTORE_DEBUG_USER = "GODOT_ANDROID_KEYSTORE_DEBUG_USER";
+const String ENV_ANDROID_KEYSTORE_DEBUG_PASS = "GODOT_ANDROID_KEYSTORE_DEBUG_PASSWORD";
+const String ENV_ANDROID_KEYSTORE_RELEASE_PATH = "GODOT_ANDROID_KEYSTORE_RELEASE_PATH";
+const String ENV_ANDROID_KEYSTORE_RELEASE_USER = "GODOT_ANDROID_KEYSTORE_RELEASE_USER";
+const String ENV_ANDROID_KEYSTORE_RELEASE_PASS = "GODOT_ANDROID_KEYSTORE_RELEASE_PASSWORD";
+
struct LauncherIcon {
const char *export_path;
int dimensions = 0;
diff --git a/platform/ios/doc_classes/EditorExportPlatformIOS.xml b/platform/ios/doc_classes/EditorExportPlatformIOS.xml
index ef2b0a256de..70b999eb0f6 100644
--- a/platform/ios/doc_classes/EditorExportPlatformIOS.xml
+++ b/platform/ios/doc_classes/EditorExportPlatformIOS.xml
@@ -35,9 +35,11 @@
UUID of the provisioning profile. If left empty, Xcode will download or create a provisioning profile automatically. See [url=https://developer.apple.com/help/account/manage-profiles/edit-download-or-delete-profiles]Edit, download, or delete provisioning profiles[/url].
+ Can be overridden with the environment variable [code]GODOT_IOS_PROVISIONING_PROFILE_UUID_DEBUG[/code].
UUID of the provisioning profile. If left empty, Xcode will download or create a provisioning profile automatically. See [url=https://developer.apple.com/help/account/manage-profiles/edit-download-or-delete-profiles]Edit, download, or delete provisioning profiles[/url].
+ Can be overridden with the environment variable [code]GODOT_IOS_PROVISIONING_PROFILE_UUID_RELEASE[/code].
Application version visible to the user, can only contain numeric characters ([code]0-9[/code]) and periods ([code].[/code]).
diff --git a/platform/ios/export/export_plugin.cpp b/platform/ios/export/export_plugin.cpp
index 9c0e4e39e8e..06741a12e4d 100644
--- a/platform/ios/export/export_plugin.cpp
+++ b/platform/ios/export/export_plugin.cpp
@@ -160,10 +160,10 @@ void EditorExportPlatformIOS::get_export_options(List *r_options)
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/app_store_team_id"), "", false, true));
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/provisioning_profile_uuid_debug"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/provisioning_profile_uuid_debug", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SECRET), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/code_sign_identity_debug", PROPERTY_HINT_PLACEHOLDER_TEXT, "iPhone Developer"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "application/export_method_debug", PROPERTY_HINT_ENUM, "App Store,Development,Ad-Hoc,Enterprise"), 1));
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/provisioning_profile_uuid_release"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/provisioning_profile_uuid_release", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SECRET), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/code_sign_identity_release", PROPERTY_HINT_PLACEHOLDER_TEXT, "iPhone Distribution"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "application/export_method_release", PROPERTY_HINT_ENUM, "App Store,Development,Ad-Hoc,Enterprise"), 0));
@@ -253,8 +253,8 @@ void EditorExportPlatformIOS::_fix_config_file(const Ref &p_
};
String dbg_sign_id = p_preset->get("application/code_sign_identity_debug").operator String().is_empty() ? "iPhone Developer" : p_preset->get("application/code_sign_identity_debug");
String rel_sign_id = p_preset->get("application/code_sign_identity_release").operator String().is_empty() ? "iPhone Distribution" : p_preset->get("application/code_sign_identity_release");
- bool dbg_manual = !p_preset->get("application/provisioning_profile_uuid_debug").operator String().is_empty() || (dbg_sign_id != "iPhone Developer");
- bool rel_manual = !p_preset->get("application/provisioning_profile_uuid_release").operator String().is_empty() || (rel_sign_id != "iPhone Distribution");
+ bool dbg_manual = !p_preset->get_or_env("application/provisioning_profile_uuid_debug", ENV_IOS_PROFILE_UUID_DEBUG).operator String().is_empty() || (dbg_sign_id != "iPhone Developer");
+ bool rel_manual = !p_preset->get_or_env("application/provisioning_profile_uuid_release", ENV_IOS_PROFILE_UUID_RELEASE).operator String().is_empty() || (rel_sign_id != "iPhone Distribution");
String str;
String strnew;
str.parse_utf8((const char *)pfile.ptr(), pfile.size());
@@ -288,9 +288,9 @@ void EditorExportPlatformIOS::_fix_config_file(const Ref &p_
int export_method = p_preset->get(p_debug ? "application/export_method_debug" : "application/export_method_release");
strnew += lines[i].replace("$export_method", export_method_string[export_method]) + "\n";
} else if (lines[i].find("$provisioning_profile_uuid_release") != -1) {
- strnew += lines[i].replace("$provisioning_profile_uuid_release", p_preset->get("application/provisioning_profile_uuid_release")) + "\n";
+ strnew += lines[i].replace("$provisioning_profile_uuid_release", p_preset->get_or_env("application/provisioning_profile_uuid_release", ENV_IOS_PROFILE_UUID_RELEASE)) + "\n";
} else if (lines[i].find("$provisioning_profile_uuid_debug") != -1) {
- strnew += lines[i].replace("$provisioning_profile_uuid_debug", p_preset->get("application/provisioning_profile_uuid_debug")) + "\n";
+ strnew += lines[i].replace("$provisioning_profile_uuid_debug", p_preset->get_or_env("application/provisioning_profile_uuid_debug", ENV_IOS_PROFILE_UUID_DEBUG)) + "\n";
} else if (lines[i].find("$code_sign_style_debug") != -1) {
if (dbg_manual) {
strnew += lines[i].replace("$code_sign_style_debug", "Manual") + "\n";
@@ -304,7 +304,7 @@ void EditorExportPlatformIOS::_fix_config_file(const Ref &p_
strnew += lines[i].replace("$code_sign_style_release", "Automatic") + "\n";
}
} else if (lines[i].find("$provisioning_profile_uuid") != -1) {
- String uuid = p_debug ? p_preset->get("application/provisioning_profile_uuid_debug") : p_preset->get("application/provisioning_profile_uuid_release");
+ String uuid = p_debug ? p_preset->get_or_env("application/provisioning_profile_uuid_debug", ENV_IOS_PROFILE_UUID_DEBUG) : p_preset->get_or_env("application/provisioning_profile_uuid_release", ENV_IOS_PROFILE_UUID_RELEASE);
strnew += lines[i].replace("$provisioning_profile_uuid", uuid) + "\n";
} else if (lines[i].find("$code_sign_identity_debug") != -1) {
strnew += lines[i].replace("$code_sign_identity_debug", dbg_sign_id) + "\n";
diff --git a/platform/ios/export/export_plugin.h b/platform/ios/export/export_plugin.h
index 0fde3b7c0b7..9afefef121b 100644
--- a/platform/ios/export/export_plugin.h
+++ b/platform/ios/export/export_plugin.h
@@ -49,6 +49,11 @@
#include
+// Optional environment variables for defining confidential information. If any
+// of these is set, they will override the values set in the credentials file.
+const String ENV_IOS_PROFILE_UUID_DEBUG = "GODOT_IOS_PROVISIONING_PROFILE_UUID_DEBUG";
+const String ENV_IOS_PROFILE_UUID_RELEASE = "GODOT_IOS_PROVISIONING_PROFILE_UUID_RELEASE";
+
class EditorExportPlatformIOS : public EditorExportPlatform {
GDCLASS(EditorExportPlatformIOS, EditorExportPlatform);
diff --git a/platform/macos/doc_classes/EditorExportPlatformMacOS.xml b/platform/macos/doc_classes/EditorExportPlatformMacOS.xml
index f57af3bbd74..64e1efde269 100644
--- a/platform/macos/doc_classes/EditorExportPlatformMacOS.xml
+++ b/platform/macos/doc_classes/EditorExportPlatformMacOS.xml
@@ -50,9 +50,11 @@
PKCS #12 certificate file used to sign [code].app[/code] bundle.
+ Can be overridden with the environment variable [code]GODOT_MACOS_CODESIGN_CERTIFICATE_FILE[/code].
Password for the certificate file used to sign [code].app[/code] bundle.
+ Can be overridden with the environment variable [code]GODOT_MACOS_CODESIGN_CERTIFICATE_PASSWORD[/code].
Tool to use for code signing.
@@ -138,6 +140,7 @@
Provisioning profile file downloaded from Apple developer account dashboard. See [url=https://developer.apple.com/help/account/manage-profiles/edit-download-or-delete-profiles]Edit, download, or delete provisioning profiles[/url].
+ Can be overridden with the environment variable [code]GODOT_MACOS_CODESIGN_PROVISIONING_PROFILE[/code].
Path to the custom export template. If left empty, default template is used.
@@ -156,18 +159,23 @@
Apple App Store Connect API issuer key file.
+ Can be overridden with the environment variable [code]GODOT_MACOS_NOTARIZATION_API_KEY[/code].
Apple App Store Connect API issuer key ID.
+ Can be overridden with the environment variable [code]GODOT_MACOS_NOTARIZATION_API_KEY_ID[/code].
Apple App Store Connect API issuer UUID.
+ Can be overridden with the environment variable [code]GODOT_MACOS_NOTARIZATION_API_UUID[/code].
Apple ID account name (email address).
+ Can be overridden with the environment variable [code]GODOT_MACOS_NOTARIZATION_APPLE_ID_NAME[/code].
Apple ID app-specific password.
+ Can be overridden with the environment variable [code]GODOT_MACOS_NOTARIZATION_APPLE_ID_PASSWORD[/code].
Tool to use for notarization.
diff --git a/platform/macos/export/export_plugin.cpp b/platform/macos/export/export_plugin.cpp
index cd9d17dd4fc..be677f4da2a 100644
--- a/platform/macos/export/export_plugin.cpp
+++ b/platform/macos/export/export_plugin.cpp
@@ -73,7 +73,7 @@ String EditorExportPlatformMacOS::get_export_option_warning(const EditorExportPr
ad_hoc = true;
} break;
case 2: { // "rcodesign"
- ad_hoc = p_preset->get("codesign/certificate_file").operator String().is_empty() || p_preset->get("codesign/certificate_password").operator String().is_empty();
+ ad_hoc = p_preset->get_or_env("codesign/certificate_file", ENV_MAC_CODESIGN_CERT_FILE).operator String().is_empty() || p_preset->get_or_env("codesign/certificate_password", ENV_MAC_CODESIGN_CERT_FILE).operator String().is_empty();
} break;
#ifdef MACOS_ENABLED
case 3: { // "codesign"
@@ -114,7 +114,7 @@ String EditorExportPlatformMacOS::get_export_option_warning(const EditorExportPr
}
if (p_name == "codesign/provisioning_profile" && dist_type == 2) {
- String pprof = p_preset->get("codesign/provisioning_profile");
+ String pprof = p_preset->get_or_env("codesign/provisioning_profile", ENV_MAC_CODESIGN_PROFILE);
if (pprof.is_empty()) {
return TTR("Provisioning profile is required for App Store distribution.");
}
@@ -154,8 +154,8 @@ String EditorExportPlatformMacOS::get_export_option_warning(const EditorExportPr
if (notary_tool == 2 || notary_tool == 3) {
if (p_name == "notarization/apple_id_name" || p_name == "notarization/api_uuid") {
- String apple_id = p_preset->get("notarization/apple_id_name");
- String api_uuid = p_preset->get("notarization/api_uuid");
+ String apple_id = p_preset->get_or_env("notarization/apple_id_name", ENV_MAC_NOTARIZATION_APPLE_ID);
+ String api_uuid = p_preset->get_or_env("notarization/api_uuid", ENV_MAC_NOTARIZATION_UUID);
if (apple_id.is_empty() && api_uuid.is_empty()) {
return TTR("Neither Apple ID name nor App Store Connect issuer ID name not specified.");
}
@@ -164,28 +164,28 @@ String EditorExportPlatformMacOS::get_export_option_warning(const EditorExportPr
}
}
if (p_name == "notarization/apple_id_password") {
- String apple_id = p_preset->get("notarization/apple_id_name");
- String apple_pass = p_preset->get("notarization/apple_id_password");
+ String apple_id = p_preset->get_or_env("notarization/apple_id_name", ENV_MAC_NOTARIZATION_APPLE_ID);
+ String apple_pass = p_preset->get_or_env("notarization/apple_id_password", ENV_MAC_NOTARIZATION_APPLE_PASS);
if (!apple_id.is_empty() && apple_pass.is_empty()) {
return TTR("Apple ID password not specified.");
}
}
if (p_name == "notarization/api_key_id") {
- String api_uuid = p_preset->get("notarization/api_uuid");
- String api_key = p_preset->get("notarization/api_key_id");
+ String api_uuid = p_preset->get_or_env("notarization/api_uuid", ENV_MAC_NOTARIZATION_UUID);
+ String api_key = p_preset->get_or_env("notarization/api_key_id", ENV_MAC_NOTARIZATION_KEY_ID);
if (!api_uuid.is_empty() && api_key.is_empty()) {
return TTR("App Store Connect API key ID not specified.");
}
}
} else if (notary_tool == 1) {
if (p_name == "notarization/api_uuid") {
- String api_uuid = p_preset->get("notarization/api_uuid");
+ String api_uuid = p_preset->get_or_env("notarization/api_uuid", ENV_MAC_NOTARIZATION_UUID);
if (api_uuid.is_empty()) {
return TTR("App Store Connect issuer ID name not specified.");
}
}
if (p_name == "notarization/api_key_id") {
- String api_key = p_preset->get("notarization/api_key_id");
+ String api_key = p_preset->get_or_env("notarization/api_key_id", ENV_MAC_NOTARIZATION_KEY_ID);
if (api_key.is_empty()) {
return TTR("App Store Connect API key ID not specified.");
}
@@ -398,10 +398,10 @@ void EditorExportPlatformMacOS::get_export_options(List *r_options
// "codesign" only options:
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "codesign/identity", PROPERTY_HINT_PLACEHOLDER_TEXT, "Type: Name (ID)"), ""));
// "rcodesign" only options:
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "codesign/certificate_file", PROPERTY_HINT_GLOBAL_FILE, "*.pfx,*.p12"), ""));
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "codesign/certificate_password", PROPERTY_HINT_PASSWORD), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "codesign/certificate_file", PROPERTY_HINT_GLOBAL_FILE, "*.pfx,*.p12", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SECRET), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "codesign/certificate_password", PROPERTY_HINT_PASSWORD, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SECRET), ""));
// "codesign" and "rcodesign" only options:
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "codesign/provisioning_profile", PROPERTY_HINT_GLOBAL_FILE, "*.provisionprofile"), "", false, true));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "codesign/provisioning_profile", PROPERTY_HINT_GLOBAL_FILE, "*.provisionprofile", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SECRET), "", false, true));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "codesign/entitlements/custom_file", PROPERTY_HINT_GLOBAL_FILE, "*.plist"), "", true));
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/entitlements/allow_jit_code_execution"), false));
@@ -434,12 +434,12 @@ void EditorExportPlatformMacOS::get_export_options(List *r_options
r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "notarization/notarization", PROPERTY_HINT_ENUM, "Disabled,rcodesign"), 0, true));
#endif
// "altool" and "notarytool" only options:
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "notarization/apple_id_name", PROPERTY_HINT_PLACEHOLDER_TEXT, "Apple ID email"), "", false, true));
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "notarization/apple_id_password", PROPERTY_HINT_PASSWORD, "Enable two-factor authentication and provide app-specific password"), "", false, true));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "notarization/apple_id_name", PROPERTY_HINT_PLACEHOLDER_TEXT, "Apple ID email", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SECRET), "", false, true));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "notarization/apple_id_password", PROPERTY_HINT_PASSWORD, "Enable two-factor authentication and provide app-specific password", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SECRET), "", false, true));
// "altool", "notarytool" and "rcodesign" only options:
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "notarization/api_uuid", PROPERTY_HINT_PLACEHOLDER_TEXT, "App Store Connect issuer ID UUID"), "", false, true));
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "notarization/api_key", PROPERTY_HINT_GLOBAL_FILE, "*.p8"), "", false, true));
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "notarization/api_key_id", PROPERTY_HINT_PLACEHOLDER_TEXT, "App Store Connect API key ID"), "", false, true));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "notarization/api_uuid", PROPERTY_HINT_PLACEHOLDER_TEXT, "App Store Connect issuer ID UUID", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SECRET), "", false, true));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "notarization/api_key", PROPERTY_HINT_GLOBAL_FILE, "*.p8", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SECRET), "", false, true));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "notarization/api_key_id", PROPERTY_HINT_PLACEHOLDER_TEXT, "App Store Connect API key ID", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SECRET), "", false, true));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/microphone_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use the microphone"), "", false, true));
r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/microphone_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary()));
@@ -776,24 +776,24 @@ Error EditorExportPlatformMacOS::_notarize(const Ref &p_pres
args.push_back("notary-submit");
- if (p_preset->get("notarization/api_uuid") == "") {
+ if (p_preset->get_or_env("notarization/api_uuid", ENV_MAC_NOTARIZATION_UUID) == "") {
add_message(EXPORT_MESSAGE_ERROR, TTR("Notarization"), TTR("App Store Connect issuer ID name not specified."));
return Error::FAILED;
}
- if (p_preset->get("notarization/api_key") == "") {
+ if (p_preset->get_or_env("notarization/api_key", ENV_MAC_NOTARIZATION_KEY) == "") {
add_message(EXPORT_MESSAGE_ERROR, TTR("Notarization"), TTR("App Store Connect API key ID not specified."));
return Error::FAILED;
}
args.push_back("--api-issuer");
- args.push_back(p_preset->get("notarization/api_uuid"));
+ args.push_back(p_preset->get_or_env("notarization/api_uuid", ENV_MAC_NOTARIZATION_UUID));
args.push_back("--api-key");
- args.push_back(p_preset->get("notarization/api_key_id"));
+ args.push_back(p_preset->get_or_env("notarization/api_key_id", ENV_MAC_NOTARIZATION_KEY_ID));
- if (!p_preset->get("notarization/api_key").operator String().is_empty()) {
+ if (!p_preset->get_or_env("notarization/api_key", ENV_MAC_NOTARIZATION_KEY).operator String().is_empty()) {
args.push_back("--api-key-path");
- args.push_back(p_preset->get("notarization/api_key"));
+ args.push_back(p_preset->get_or_env("notarization/api_key", ENV_MAC_NOTARIZATION_KEY));
}
args.push_back(p_path);
@@ -840,40 +840,40 @@ Error EditorExportPlatformMacOS::_notarize(const Ref &p_pres
args.push_back(p_path);
- if (p_preset->get("notarization/apple_id_name") == "" && p_preset->get("notarization/api_uuid") == "") {
+ if (p_preset->get_or_env("notarization/apple_id_name", ENV_MAC_NOTARIZATION_APPLE_ID) == "" && p_preset->get_or_env("notarization/api_uuid", ENV_MAC_NOTARIZATION_UUID) == "") {
add_message(EXPORT_MESSAGE_ERROR, TTR("Notarization"), TTR("Neither Apple ID name nor App Store Connect issuer ID name not specified."));
return Error::FAILED;
}
- if (p_preset->get("notarization/apple_id_name") != "" && p_preset->get("notarization/api_uuid") != "") {
+ if (p_preset->get_or_env("notarization/apple_id_name", ENV_MAC_NOTARIZATION_APPLE_ID) != "" && p_preset->get_or_env("notarization/api_uuid", ENV_MAC_NOTARIZATION_UUID) != "") {
add_message(EXPORT_MESSAGE_ERROR, TTR("Notarization"), TTR("Both Apple ID name and App Store Connect issuer ID name are specified, only one should be set at the same time."));
return Error::FAILED;
}
- if (p_preset->get("notarization/apple_id_name") != "") {
- if (p_preset->get("notarization/apple_id_password") == "") {
+ if (p_preset->get_or_env("notarization/apple_id_name", ENV_MAC_NOTARIZATION_APPLE_ID) != "") {
+ if (p_preset->get_or_env("notarization/apple_id_password", ENV_MAC_NOTARIZATION_APPLE_PASS) == "") {
add_message(EXPORT_MESSAGE_ERROR, TTR("Notarization"), TTR("Apple ID password not specified."));
return Error::FAILED;
}
args.push_back("--apple-id");
- args.push_back(p_preset->get("notarization/apple_id_name"));
+ args.push_back(p_preset->get_or_env("notarization/apple_id_name", ENV_MAC_NOTARIZATION_APPLE_ID));
args.push_back("--password");
- args.push_back(p_preset->get("notarization/apple_id_password"));
+ args.push_back(p_preset->get_or_env("notarization/apple_id_password", ENV_MAC_NOTARIZATION_APPLE_PASS));
} else {
- if (p_preset->get("notarization/api_key_id") == "") {
+ if (p_preset->get_or_env("notarization/api_key_id", ENV_MAC_NOTARIZATION_KEY_ID) == "") {
add_message(EXPORT_MESSAGE_ERROR, TTR("Notarization"), TTR("App Store Connect API key ID not specified."));
return Error::FAILED;
}
args.push_back("--issuer");
- args.push_back(p_preset->get("notarization/api_uuid"));
+ args.push_back(p_preset->get_or_env("notarization/api_uuid", ENV_MAC_NOTARIZATION_UUID));
- if (!p_preset->get("notarization/api_key").operator String().is_empty()) {
+ if (!p_preset->get_or_env("notarization/api_key", ENV_MAC_NOTARIZATION_KEY).operator String().is_empty()) {
args.push_back("--key");
- args.push_back(p_preset->get("notarization/api_key"));
+ args.push_back(p_preset->get_or_env("notarization/api_key", ENV_MAC_NOTARIZATION_KEY));
}
args.push_back("--key-id");
- args.push_back(p_preset->get("notarization/api_key_id"));
+ args.push_back(p_preset->get_or_env("notarization/api_key_id", ENV_MAC_NOTARIZATION_KEY_ID));
}
args.push_back("--no-progress");
@@ -925,35 +925,35 @@ Error EditorExportPlatformMacOS::_notarize(const Ref &p_pres
args.push_back("--primary-bundle-id");
args.push_back(p_preset->get("application/bundle_identifier"));
- if (p_preset->get("notarization/apple_id_name") == "" && p_preset->get("notarization/api_uuid") == "") {
+ if (p_preset->get_or_env("notarization/apple_id_name", ENV_MAC_NOTARIZATION_APPLE_ID) == "" && p_preset->get_or_env("notarization/api_uuid", ENV_MAC_NOTARIZATION_UUID) == "") {
add_message(EXPORT_MESSAGE_ERROR, TTR("Notarization"), TTR("Neither Apple ID name nor App Store Connect issuer ID name not specified."));
return Error::FAILED;
}
- if (p_preset->get("notarization/apple_id_name") != "" && p_preset->get("notarization/api_uuid") != "") {
+ if (p_preset->get_or_env("notarization/apple_id_name", ENV_MAC_NOTARIZATION_APPLE_ID) != "" && p_preset->get_or_env("notarization/api_uuid", ENV_MAC_NOTARIZATION_UUID) != "") {
add_message(EXPORT_MESSAGE_ERROR, TTR("Notarization"), TTR("Both Apple ID name and App Store Connect issuer ID name are specified, only one should be set at the same time."));
return Error::FAILED;
}
- if (p_preset->get("notarization/apple_id_name") != "") {
- if (p_preset->get("notarization/apple_id_password") == "") {
+ if (p_preset->get_or_env("notarization/apple_id_name", ENV_MAC_NOTARIZATION_APPLE_ID) != "") {
+ if (p_preset->get_or_env("notarization/apple_id_password", ENV_MAC_NOTARIZATION_APPLE_PASS) == "") {
add_message(EXPORT_MESSAGE_ERROR, TTR("Notarization"), TTR("Apple ID password not specified."));
return Error::FAILED;
}
args.push_back("--username");
- args.push_back(p_preset->get("notarization/apple_id_name"));
+ args.push_back(p_preset->get_or_env("notarization/apple_id_name", ENV_MAC_NOTARIZATION_APPLE_ID));
args.push_back("--password");
- args.push_back(p_preset->get("notarization/apple_id_password"));
+ args.push_back(p_preset->get_or_env("notarization/apple_id_password", ENV_MAC_NOTARIZATION_APPLE_PASS));
} else {
- if (p_preset->get("notarization/api_key") == "") {
+ if (p_preset->get_or_env("notarization/api_key", ENV_MAC_NOTARIZATION_KEY) == "") {
add_message(EXPORT_MESSAGE_ERROR, TTR("Notarization"), TTR("App Store Connect API key ID not specified."));
return Error::FAILED;
}
args.push_back("--apiIssuer");
- args.push_back(p_preset->get("notarization/api_uuid"));
+ args.push_back(p_preset->get_or_env("notarization/api_uuid", ENV_MAC_NOTARIZATION_UUID));
args.push_back("--apiKey");
- args.push_back(p_preset->get("notarization/api_key_id"));
+ args.push_back(p_preset->get_or_env("notarization/api_key_id", ENV_MAC_NOTARIZATION_KEY_ID));
}
args.push_back("--type");
@@ -1032,8 +1032,8 @@ Error EditorExportPlatformMacOS::_code_sign(const Ref &p_pre
args.push_back(p_ent_path);
}
- String certificate_file = p_preset->get("codesign/certificate_file");
- String certificate_pass = p_preset->get("codesign/certificate_password");
+ String certificate_file = p_preset->get_or_env("codesign/certificate_file", ENV_MAC_CODESIGN_CERT_FILE);
+ String certificate_pass = p_preset->get_or_env("codesign/certificate_password", ENV_MAC_CODESIGN_CERT_PASS);
if (!certificate_file.is_empty() && !certificate_pass.is_empty()) {
args.push_back("--p12-file");
args.push_back(certificate_file);
@@ -1763,7 +1763,7 @@ Error EditorExportPlatformMacOS::export_project(const Ref &p
ad_hoc = true;
} break;
case 2: { // "rcodesign"
- ad_hoc = p_preset->get("codesign/certificate_file").operator String().is_empty() || p_preset->get("codesign/certificate_password").operator String().is_empty();
+ ad_hoc = p_preset->get_or_env("codesign/certificate_file", ENV_MAC_CODESIGN_CERT_FILE).operator String().is_empty() || p_preset->get_or_env("codesign/certificate_password", ENV_MAC_CODESIGN_CERT_PASS).operator String().is_empty();
} break;
#ifdef MACOS_ENABLED
case 3: { // "codesign"
@@ -1857,7 +1857,7 @@ Error EditorExportPlatformMacOS::export_project(const Ref &p
int dist_type = p_preset->get("export/distribution_type");
if (dist_type == 2) {
- String pprof = p_preset->get("codesign/provisioning_profile");
+ String pprof = p_preset->get_or_env("codesign/provisioning_profile", ENV_MAC_CODESIGN_PROFILE);
String teamid = p_preset->get("codesign/apple_team_id");
String bid = p_preset->get("application/bundle_identifier");
if (!pprof.is_empty() && !teamid.is_empty()) {
@@ -1990,7 +1990,7 @@ Error EditorExportPlatformMacOS::export_project(const Ref &p
if (err == OK && sign_enabled) {
int dist_type = p_preset->get("export/distribution_type");
if (dist_type == 2) {
- String pprof = p_preset->get("codesign/provisioning_profile").operator String();
+ String pprof = p_preset->get_or_env("codesign/provisioning_profile", ENV_MAC_CODESIGN_PROFILE).operator String();
if (!pprof.is_empty()) {
Ref da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
err = da->copy(pprof, tmp_app_path_name + "/Contents/embedded.provisionprofile");
@@ -2147,7 +2147,7 @@ bool EditorExportPlatformMacOS::has_valid_project_configuration(const Refget("codesign/certificate_file").operator String().is_empty() || p_preset->get("codesign/certificate_password").operator String().is_empty();
+ ad_hoc = p_preset->get_or_env("codesign/certificate_file", ENV_MAC_CODESIGN_CERT_FILE).operator String().is_empty() || p_preset->get_or_env("codesign/certificate_password", ENV_MAC_CODESIGN_CERT_PASS).operator String().is_empty();
} break;
#ifdef MACOS_ENABLED
case 3: { // "codesign"
diff --git a/platform/macos/export/export_plugin.h b/platform/macos/export/export_plugin.h
index a8caf535c49..0477a8c0cc0 100644
--- a/platform/macos/export/export_plugin.h
+++ b/platform/macos/export/export_plugin.h
@@ -43,6 +43,17 @@
#include
+// Optional environment variables for defining confidential information. If any
+// of these is set, they will override the values set in the credentials file.
+const String ENV_MAC_CODESIGN_CERT_FILE = "GODOT_MACOS_CODESIGN_CERTIFICATE_FILE";
+const String ENV_MAC_CODESIGN_CERT_PASS = "GODOT_MACOS_CODESIGN_CERTIFICATE_PASSWORD";
+const String ENV_MAC_CODESIGN_PROFILE = "GODOT_MACOS_CODESIGN_PROVISIONING_PROFILE";
+const String ENV_MAC_NOTARIZATION_UUID = "GODOT_MACOS_NOTARIZATION_API_UUID";
+const String ENV_MAC_NOTARIZATION_KEY = "GODOT_MACOS_NOTARIZATION_API_KEY";
+const String ENV_MAC_NOTARIZATION_KEY_ID = "GODOT_MACOS_NOTARIZATION_API_KEY_ID";
+const String ENV_MAC_NOTARIZATION_APPLE_ID = "GODOT_MACOS_NOTARIZATION_APPLE_ID_NAME";
+const String ENV_MAC_NOTARIZATION_APPLE_PASS = "GODOT_MACOS_NOTARIZATION_APPLE_ID_PASSWORD";
+
class EditorExportPlatformMacOS : public EditorExportPlatform {
GDCLASS(EditorExportPlatformMacOS, EditorExportPlatform);
diff --git a/platform/uwp/export/export_plugin.cpp b/platform/uwp/export/export_plugin.cpp
index 163236e5064..aac61184b11 100644
--- a/platform/uwp/export/export_plugin.cpp
+++ b/platform/uwp/export/export_plugin.cpp
@@ -80,8 +80,8 @@ void EditorExportPlatformUWP::get_export_options(List *r_options)
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "identity/product_guid", PROPERTY_HINT_PLACEHOLDER_TEXT, "00000000-0000-0000-0000-000000000000"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "identity/publisher_guid", PROPERTY_HINT_PLACEHOLDER_TEXT, "00000000-0000-0000-0000-000000000000"), ""));
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "signing/certificate", PROPERTY_HINT_GLOBAL_FILE, "*.pfx"), ""));
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "signing/password"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "signing/certificate", PROPERTY_HINT_GLOBAL_FILE, "*.pfx", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SECRET), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "signing/password", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SECRET), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "signing/algorithm", PROPERTY_HINT_ENUM, "MD5,SHA1,SHA256"), 2));
r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "version/major"), 1));
@@ -465,8 +465,8 @@ Error EditorExportPlatformUWP::export_project(const Ref &p_p
int cert_alg = EDITOR_GET("export/uwp/debug_algorithm");
if (!p_debug) {
- cert_path = p_preset->get("signing/certificate");
- cert_pass = p_preset->get("signing/password");
+ cert_path = p_preset->get_or_env("signing/certificate", ENV_UWP_SIGNING_CERT);
+ cert_pass = p_preset->get_or_env("signing/password", ENV_UWP_SIGNING_PASS);
cert_alg = p_preset->get("signing/algorithm");
}
diff --git a/platform/uwp/export/export_plugin.h b/platform/uwp/export/export_plugin.h
index 37a32b1f7f7..b42a2ae6d99 100644
--- a/platform/uwp/export/export_plugin.h
+++ b/platform/uwp/export/export_plugin.h
@@ -85,6 +85,11 @@ static const char *uwp_device_capabilities[] = {
nullptr
};
+// Optional environment variables for defining confidential information. If any
+// of these is set, they will override the values set in the credentials file.
+const String ENV_UWP_SIGNING_CERT = "GODOT_UWP_SIGNING_CERTIFICATE";
+const String ENV_UWP_SIGNING_PASS = "GODOT_UWP_SIGNING_PASSWORD";
+
class EditorExportPlatformUWP : public EditorExportPlatform {
GDCLASS(EditorExportPlatformUWP, EditorExportPlatform);
diff --git a/platform/windows/doc_classes/EditorExportPlatformWindows.xml b/platform/windows/doc_classes/EditorExportPlatformWindows.xml
index fee8a118bc5..ec2b105f580 100644
--- a/platform/windows/doc_classes/EditorExportPlatformWindows.xml
+++ b/platform/windows/doc_classes/EditorExportPlatformWindows.xml
@@ -64,12 +64,15 @@
PKCS #12 certificate file used to sign executable or certificate SHA-1 hash (if [member codesign/identity_type] is set to "Use certificate store"). See [url=https://learn.microsoft.com/en-us/dotnet/framework/tools/signtool-exe]Sign Tool[/url].
+ Can be overridden with the environment variable [code]GODOT_WINDOWS_CODESIGN_IDENTITY[/code].
Type of identity to use. See [url=https://learn.microsoft.com/en-us/dotnet/framework/tools/signtool-exe]Sign Tool[/url].
+ Can be overridden with the environment variable [code]GODOT_WINDOWS_CODESIGN_IDENTITY_TYPE[/code].
Password for the certificate file used to sign executable. See [url=https://learn.microsoft.com/en-us/dotnet/framework/tools/signtool-exe]Sign Tool[/url].
+ Can be overridden with the environment variable [code]GODOT_WINDOWS_CODESIGN_PASSWORD[/code].
If [code]true[/code], time-stamp is added to the signature. See [url=https://learn.microsoft.com/en-us/dotnet/framework/tools/signtool-exe]Sign Tool[/url].
diff --git a/platform/windows/export/export_plugin.cpp b/platform/windows/export/export_plugin.cpp
index 1863a3083b7..ca390236fb7 100644
--- a/platform/windows/export/export_plugin.cpp
+++ b/platform/windows/export/export_plugin.cpp
@@ -328,9 +328,9 @@ void EditorExportPlatformWindows::get_export_options(List *r_optio
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "binary_format/architecture", PROPERTY_HINT_ENUM, "x86_64,x86_32,arm64"), "x86_64"));
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/enable"), false, true));
- r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "codesign/identity_type", PROPERTY_HINT_ENUM, "Select automatically,Use PKCS12 file (specify *.PFX/*.P12 file),Use certificate store (specify SHA-1 hash)"), 0));
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "codesign/identity", PROPERTY_HINT_GLOBAL_FILE, "*.pfx,*.p12"), ""));
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "codesign/password", PROPERTY_HINT_PASSWORD), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "codesign/identity_type", PROPERTY_HINT_ENUM, "Select automatically,Use PKCS12 file (specify *.PFX/*.P12 file),Use certificate store (specify SHA-1 hash)", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SECRET), 0));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "codesign/identity", PROPERTY_HINT_GLOBAL_FILE, "*.pfx,*.p12", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SECRET), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "codesign/password", PROPERTY_HINT_PASSWORD, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SECRET), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/timestamp"), true));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "codesign/timestamp_server_url"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "codesign/digest_algorithm", PROPERTY_HINT_ENUM, "SHA1,SHA256"), 1));
@@ -518,21 +518,21 @@ Error EditorExportPlatformWindows::_code_sign(const Ref &p_p
//identity
#ifdef WINDOWS_ENABLED
- int id_type = p_preset->get("codesign/identity_type");
+ int id_type = p_preset->get_or_env("codesign/identity_type", ENV_WIN_CODESIGN_ID_TYPE);
if (id_type == 0) { //auto select
args.push_back("/a");
} else if (id_type == 1) { //pkcs12
- if (p_preset->get("codesign/identity") != "") {
+ if (p_preset->get_or_env("codesign/identity", ENV_WIN_CODESIGN_ID) != "") {
args.push_back("/f");
- args.push_back(p_preset->get("codesign/identity"));
+ args.push_back(p_preset->get_or_env("codesign/identity", ENV_WIN_CODESIGN_ID));
} else {
add_message(EXPORT_MESSAGE_WARNING, TTR("Code Signing"), TTR("No identity found."));
return FAILED;
}
} else if (id_type == 2) { //Windows certificate store
- if (p_preset->get("codesign/identity") != "") {
+ if (p_preset->get_or_env("codesign/identity", ENV_WIN_CODESIGN_ID) != "") {
args.push_back("/sha1");
- args.push_back(p_preset->get("codesign/identity"));
+ args.push_back(p_preset->get_or_env("codesign/identity", ENV_WIN_CODESIGN_ID));
} else {
add_message(EXPORT_MESSAGE_WARNING, TTR("Code Signing"), TTR("No identity found."));
return FAILED;
@@ -543,9 +543,9 @@ Error EditorExportPlatformWindows::_code_sign(const Ref &p_p
}
#else
int id_type = 1;
- if (p_preset->get("codesign/identity") != "") {
+ if (p_preset->get_or_env("codesign/identity", ENV_WIN_CODESIGN_ID) != "") {
args.push_back("-pkcs12");
- args.push_back(p_preset->get("codesign/identity"));
+ args.push_back(p_preset->get_or_env("codesign/identity", ENV_WIN_CODESIGN_ID));
} else {
add_message(EXPORT_MESSAGE_WARNING, TTR("Code Signing"), TTR("No identity found."));
return FAILED;
@@ -553,13 +553,13 @@ Error EditorExportPlatformWindows::_code_sign(const Ref &p_p
#endif
//password
- if ((id_type == 1) && (p_preset->get("codesign/password") != "")) {
+ if ((id_type == 1) && (p_preset->get_or_env("codesign/password", ENV_WIN_CODESIGN_PASS) != "")) {
#ifdef WINDOWS_ENABLED
args.push_back("/p");
#else
args.push_back("-pass");
#endif
- args.push_back(p_preset->get("codesign/password"));
+ args.push_back(p_preset->get_or_env("codesign/password", ENV_WIN_CODESIGN_PASS));
}
//timestamp
diff --git a/platform/windows/export/export_plugin.h b/platform/windows/export/export_plugin.h
index c466971202b..184b2f96f8c 100644
--- a/platform/windows/export/export_plugin.h
+++ b/platform/windows/export/export_plugin.h
@@ -36,6 +36,12 @@
#include "editor/editor_settings.h"
#include "editor/export/editor_export_platform_pc.h"
+// Optional environment variables for defining confidential information. If any
+// of these is set, they will override the values set in the credentials file.
+const String ENV_WIN_CODESIGN_ID_TYPE = "GODOT_WINDOWS_CODESIGN_IDENTITY_TYPE";
+const String ENV_WIN_CODESIGN_ID = "GODOT_WINDOWS_CODESIGN_IDENTITY";
+const String ENV_WIN_CODESIGN_PASS = "GODOT_WINDOWS_CODESIGN_PASSWORD";
+
class EditorExportPlatformWindows : public EditorExportPlatformPC {
GDCLASS(EditorExportPlatformWindows, EditorExportPlatformPC);
]