From fbbbe75429373c9a4325f1769165e7f278b7f10d Mon Sep 17 00:00:00 2001 From: Patrick VanderKnyff Date: Thu, 9 Apr 2026 12:39:40 -0700 Subject: [PATCH 1/5] Add check for uppercase default --- .../connector_packager/xsd_validator.py | 18 ++++++++++++++++++ .../invalid/oauth-config.xml | 18 ++++++++++++++++++ .../valid/oauth-config.xml | 18 ++++++++++++++++++ connector-packager/tests/test_xsd_validator.py | 15 +++++++++++++++ 4 files changed, 69 insertions(+) create mode 100644 connector-packager/tests/test_resources/oauth_default_config_id/invalid/oauth-config.xml create mode 100644 connector-packager/tests/test_resources/oauth_default_config_id/valid/oauth-config.xml diff --git a/connector-packager/connector_packager/xsd_validator.py b/connector-packager/connector_packager/xsd_validator.py index 2ca41d82..47b19202 100644 --- a/connector-packager/connector_packager/xsd_validator.py +++ b/connector-packager/connector_packager/xsd_validator.py @@ -175,6 +175,9 @@ def validate_file_specific_rules(file_to_test: ConnectorFile, path_to_file: Path return validate_file_specific_rules_tdr(file_to_test, path_to_file, xml_violations_buffer, properties) elif file_to_test.file_type == 'connection-dialog': return validate_file_specific_rules_tcd(file_to_test, path_to_file, xml_violations_buffer, properties) + elif file_to_test.file_type == 'oauth-config': + return validate_file_specific_rules_oauth_config(file_to_test, path_to_file, xml_violations_buffer, properties) + return True @@ -348,6 +351,21 @@ def validate_file_specific_rules_tcd(file_to_test: ConnectorFile, path_to_file: return True +def validate_file_specific_rules_oauth_config(file_to_test: ConnectorFile, path_to_file: Path, xml_violations_buffer: List[str], properties: ConnectorProperties) -> bool: + xml_tree = parse(str(path_to_file)) + root = xml_tree.getroot() + + # oauthConfigId is case sensitive, and if it's default it must be lowercase + oauthConfigId = root.find('.//oauthConfigId') + if oauthConfigId is not None and 'default' == oauthConfigId.text.lower(): + if 'default' != oauthConfigId.text: + xml_violations_buffer.append("'default' OAuth Config must be lowercase as oauthConfigId is case sensitive" + + str(path_to_file) + ".") + return False + + + return True + # Check if connector file content contains warnings needs to notify connector developer def warn_file_specific_rules(file_to_test: ConnectorFile, path_to_file: Path): diff --git a/connector-packager/tests/test_resources/oauth_default_config_id/invalid/oauth-config.xml b/connector-packager/tests/test_resources/oauth_default_config_id/invalid/oauth-config.xml new file mode 100644 index 00000000..260d5935 --- /dev/null +++ b/connector-packager/tests/test_resources/oauth_default_config_id/invalid/oauth-config.xml @@ -0,0 +1,18 @@ + + + test_oauth + + DEFAULT + ****** + ****** + http://localhost:55555/Callback + + /oauth2/v2.0/authorize + /oauth2/v2.0/token + + openid + email + profile + offline_access + + diff --git a/connector-packager/tests/test_resources/oauth_default_config_id/valid/oauth-config.xml b/connector-packager/tests/test_resources/oauth_default_config_id/valid/oauth-config.xml new file mode 100644 index 00000000..1b749bcc --- /dev/null +++ b/connector-packager/tests/test_resources/oauth_default_config_id/valid/oauth-config.xml @@ -0,0 +1,18 @@ + + + test_oauth + + default + ****** + ****** + http://localhost:55555/Callback + + /oauth2/v2.0/authorize + /oauth2/v2.0/token + + openid + email + profile + offline_access + + diff --git a/connector-packager/tests/test_xsd_validator.py b/connector-packager/tests/test_xsd_validator.py index 6fb5ad97..7c8ea15f 100644 --- a/connector-packager/tests/test_xsd_validator.py +++ b/connector-packager/tests/test_xsd_validator.py @@ -483,3 +483,18 @@ def test_validate_config_label(self): self.assertFalse(validate_single_file(file_to_test, test_file, xml_violations_buffer, dummy_properties), "The configLabel field must be located after authUri and tokenUri.") + + def test_validate_oauth_default_config_id(self): + test_file = TEST_FOLDER / "oauth_default_config_id/valid/oauth-config.xml" + file_to_test = ConnectorFile("oauth-config.xml", "oauth-config") + xml_violations_buffer = [] + + self.assertTrue(validate_single_file(file_to_test, test_file, xml_violations_buffer, dummy_properties), + "Lowercase default should be accepted") + + test_file = TEST_FOLDER / "oauth_default_config_id/invalid/oauth-config.xml" + file_to_test = ConnectorFile("oauth-config.xml", "oauth-config") + xml_violations_buffer = [] + + self.assertFalse(validate_single_file(file_to_test, test_file, xml_violations_buffer, dummy_properties), + "Uppercase default should be rejected") From 712a0bd375cdac79e5a1a0bba48c7513906577c8 Mon Sep 17 00:00:00 2001 From: Patrick VanderKnyff Date: Thu, 9 Apr 2026 12:41:47 -0700 Subject: [PATCH 2/5] Bump packager version --- connector-packager/CHANGELOG.md | 3 +++ connector-packager/connector_packager/version.py | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/connector-packager/CHANGELOG.md b/connector-packager/CHANGELOG.md index ca448602..50b1cbbb 100644 --- a/connector-packager/CHANGELOG.md +++ b/connector-packager/CHANGELOG.md @@ -4,6 +4,9 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [2.1.2] - 4/9/2026 +- Add checks non-lowercase default OAuth config id + ## [2.1.1] - 8/29/2025 - Add checks for secure field violations diff --git a/connector-packager/connector_packager/version.py b/connector-packager/connector_packager/version.py index 985e0403..2d7b19ad 100644 --- a/connector-packager/connector_packager/version.py +++ b/connector-packager/connector_packager/version.py @@ -1,2 +1,2 @@ -__version__ = '2.1.0' +__version__ = '2.1.2' __default_min_version_tableau__ = '2019.4' From 8b23e560e8e3159b8dee9b34d334cfbdb1b97894 Mon Sep 17 00:00:00 2001 From: Patrick VanderKnyff Date: Thu, 9 Apr 2026 14:39:00 -0700 Subject: [PATCH 3/5] Add checks for no default and duplciate IDs --- .../connector_properties.py | 1 + .../connector_packager/xsd_validator.py | 36 ++++- .../connectionBuilder.js | 5 + .../connectionFields.xml | 36 +++++ .../connectionMetadata.xml | 8 ++ .../connectionProperties.js | 7 + .../connectionResolver.xml | 23 +++ .../oauth_default_and_missing_ids/dialect.xml | 7 + .../manifest.xml | 38 +++++ .../oauth-config.xml | 18 +++ .../oauth-config2.xml | 17 +++ .../connectionBuilder.js | 5 + .../connectionFields.xml | 36 +++++ .../connectionMetadata.xml | 8 ++ .../connectionProperties.js | 7 + .../connectionResolver.xml | 23 +++ .../oauth_duplicate_config_ids/dialect.xml | 7 + .../oauth_duplicate_config_ids/manifest.xml | 39 +++++ .../oauth-config.xml | 18 +++ .../oauth-config2.xml | 18 +++ .../oauth-config3.xml | 18 +++ .../oauth_no_default/connectionBuilder.js | 5 + .../oauth_no_default/connectionFields.xml | 36 +++++ .../oauth_no_default/connectionMetadata.xml | 8 ++ .../oauth_no_default/connectionProperties.js | 7 + .../oauth_no_default/connectionResolver.xml | 23 +++ .../oauth_no_default/dialect.xml | 7 + .../oauth_no_default/manifest.xml | 38 +++++ .../oauth_no_default/oauth-config.xml | 18 +++ .../oauth_no_default/oauth-config2.xml | 18 +++ .../tests/test_xsd_validator.py | 134 ++++++++++++------ 31 files changed, 623 insertions(+), 46 deletions(-) create mode 100644 connector-packager/tests/test_resources/oauth_default_and_missing_ids/connectionBuilder.js create mode 100644 connector-packager/tests/test_resources/oauth_default_and_missing_ids/connectionFields.xml create mode 100644 connector-packager/tests/test_resources/oauth_default_and_missing_ids/connectionMetadata.xml create mode 100644 connector-packager/tests/test_resources/oauth_default_and_missing_ids/connectionProperties.js create mode 100644 connector-packager/tests/test_resources/oauth_default_and_missing_ids/connectionResolver.xml create mode 100644 connector-packager/tests/test_resources/oauth_default_and_missing_ids/dialect.xml create mode 100644 connector-packager/tests/test_resources/oauth_default_and_missing_ids/manifest.xml create mode 100644 connector-packager/tests/test_resources/oauth_default_and_missing_ids/oauth-config.xml create mode 100644 connector-packager/tests/test_resources/oauth_default_and_missing_ids/oauth-config2.xml create mode 100644 connector-packager/tests/test_resources/oauth_duplicate_config_ids/connectionBuilder.js create mode 100644 connector-packager/tests/test_resources/oauth_duplicate_config_ids/connectionFields.xml create mode 100644 connector-packager/tests/test_resources/oauth_duplicate_config_ids/connectionMetadata.xml create mode 100644 connector-packager/tests/test_resources/oauth_duplicate_config_ids/connectionProperties.js create mode 100644 connector-packager/tests/test_resources/oauth_duplicate_config_ids/connectionResolver.xml create mode 100644 connector-packager/tests/test_resources/oauth_duplicate_config_ids/dialect.xml create mode 100644 connector-packager/tests/test_resources/oauth_duplicate_config_ids/manifest.xml create mode 100644 connector-packager/tests/test_resources/oauth_duplicate_config_ids/oauth-config.xml create mode 100644 connector-packager/tests/test_resources/oauth_duplicate_config_ids/oauth-config2.xml create mode 100644 connector-packager/tests/test_resources/oauth_duplicate_config_ids/oauth-config3.xml create mode 100644 connector-packager/tests/test_resources/oauth_no_default/connectionBuilder.js create mode 100644 connector-packager/tests/test_resources/oauth_no_default/connectionFields.xml create mode 100644 connector-packager/tests/test_resources/oauth_no_default/connectionMetadata.xml create mode 100644 connector-packager/tests/test_resources/oauth_no_default/connectionProperties.js create mode 100644 connector-packager/tests/test_resources/oauth_no_default/connectionResolver.xml create mode 100644 connector-packager/tests/test_resources/oauth_no_default/dialect.xml create mode 100644 connector-packager/tests/test_resources/oauth_no_default/manifest.xml create mode 100644 connector-packager/tests/test_resources/oauth_no_default/oauth-config.xml create mode 100644 connector-packager/tests/test_resources/oauth_no_default/oauth-config2.xml diff --git a/connector-packager/connector_packager/connector_properties.py b/connector-packager/connector_packager/connector_properties.py index 64d099ac..876695ff 100644 --- a/connector-packager/connector_packager/connector_properties.py +++ b/connector-packager/connector_packager/connector_properties.py @@ -7,3 +7,4 @@ def __init__(self): self.backwards_compatibility_mode = False self.is_jdbc = False self.connection_metadata_database = True + self.oauth_config_ids = [] diff --git a/connector-packager/connector_packager/xsd_validator.py b/connector-packager/connector_packager/xsd_validator.py index 47b19202..7e0929cb 100644 --- a/connector-packager/connector_packager/xsd_validator.py +++ b/connector-packager/connector_packager/xsd_validator.py @@ -74,6 +74,12 @@ def validate_all_xml(files_list: List[ConnectorFile], folder_path: Path, propert warn_file_specific_rules(file_to_test, path_to_file) + # If we have oauth-configs, we need to confirm we have at least one default config + if len(properties.oauth_config_ids) > 1: + if "default" not in properties.oauth_config_ids: + xml_violations_found += 1 + xml_violations_buffer.append("Connector has embedded OAuth configs, but does not define a default config.") + if xml_violations_found <= 0: logger.debug("No XML violations found") else: @@ -355,13 +361,35 @@ def validate_file_specific_rules_oauth_config(file_to_test: ConnectorFile, path_ xml_tree = parse(str(path_to_file)) root = xml_tree.getroot() - # oauthConfigId is case sensitive, and if it's default it must be lowercase + oauthConfigId = root.find('.//oauthConfigId') - if oauthConfigId is not None and 'default' == oauthConfigId.text.lower(): + + # No config id is equivilant to default + if oauthConfigId is None: + if "default" in properties.oauth_config_ids: + xml_violations_buffer.append("Multiple defualt OAuth configs (Note: no oauthConfigId is equivilant to default). " + + str(path_to_file)) + return False + else: + properties.oauth_config_ids.append("default") + return True + + # oauthConfigId is case sensitive, and if it's default it must be lowercase + if oauthConfigId.text.lower() == 'default': if 'default' != oauthConfigId.text: - xml_violations_buffer.append("'default' OAuth Config must be lowercase as oauthConfigId is case sensitive" + - str(path_to_file) + ".") + xml_violations_buffer.append("'default' OAuth Config must be lowercase as oauthConfigId is case sensitive. " + + str(path_to_file)) return False + + # Check that new oauth config is unique + if oauthConfigId.text in properties.oauth_config_ids: + xml_violations_buffer.append("OAuth config ID of '" + oauthConfigId.text + "' already defined. " + + str(path_to_file)) + return False + else: + properties.oauth_config_ids.append(oauthConfigId.text) + + return True diff --git a/connector-packager/tests/test_resources/oauth_default_and_missing_ids/connectionBuilder.js b/connector-packager/tests/test_resources/oauth_default_and_missing_ids/connectionBuilder.js new file mode 100644 index 00000000..a5d1430f --- /dev/null +++ b/connector-packager/tests/test_resources/oauth_default_and_missing_ids/connectionBuilder.js @@ -0,0 +1,5 @@ +(function dsbuilder(attr) { + var urlBuilder = "jdbc:postgresql://" + attr[connectionHelper.attributeServer] + ":" + attr[connectionHelper.attributePort] + "/" + attr[connectionHelper.attributeDatabase] + "?"; + + return [urlBuilder]; +}) diff --git a/connector-packager/tests/test_resources/oauth_default_and_missing_ids/connectionFields.xml b/connector-packager/tests/test_resources/oauth_default_and_missing_ids/connectionFields.xml new file mode 100644 index 00000000..505fded0 --- /dev/null +++ b/connector-packager/tests/test_resources/oauth_default_and_missing_ids/connectionFields.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/connector-packager/tests/test_resources/oauth_default_and_missing_ids/connectionMetadata.xml b/connector-packager/tests/test_resources/oauth_default_and_missing_ids/connectionMetadata.xml new file mode 100644 index 00000000..8c358c71 --- /dev/null +++ b/connector-packager/tests/test_resources/oauth_default_and_missing_ids/connectionMetadata.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/connector-packager/tests/test_resources/oauth_default_and_missing_ids/connectionProperties.js b/connector-packager/tests/test_resources/oauth_default_and_missing_ids/connectionProperties.js new file mode 100644 index 00000000..f8113f87 --- /dev/null +++ b/connector-packager/tests/test_resources/oauth_default_and_missing_ids/connectionProperties.js @@ -0,0 +1,7 @@ +(function propertiesbuilder(attr) { + var props = {}; + props["user"] = attr[connectionHelper.attributeUsername]; + props["password"] = attr[connectionHelper.attributePassword]; + + return props; +}) diff --git a/connector-packager/tests/test_resources/oauth_default_and_missing_ids/connectionResolver.xml b/connector-packager/tests/test_resources/oauth_default_and_missing_ids/connectionResolver.xml new file mode 100644 index 00000000..986d6237 --- /dev/null +++ b/connector-packager/tests/test_resources/oauth_default_and_missing_ids/connectionResolver.xml @@ -0,0 +1,23 @@ + + + + + +