From 521b3ea840b229e9470ab6c5b7331ab504560386 Mon Sep 17 00:00:00 2001 From: Swetha Lohith <126152564+swethalohith2@users.noreply.github.com> Date: Sat, 19 Oct 2024 06:34:46 +0530 Subject: [PATCH] INSTA 16270 update api credentials (#107) * Remove api and add new one for patch credential * add update cred with multiple associations * update readme * add patch credential value * update readme --- docs/synctl-patch-credential.md | 8 +++ docs/synctl-update-credential.md | 20 +++++- synctl/cli.py | 111 +++++++++++++++++++------------ 3 files changed, 92 insertions(+), 47 deletions(-) diff --git a/docs/synctl-patch-credential.md b/docs/synctl-patch-credential.md index e0eb69c..91000b1 100644 --- a/docs/synctl-patch-credential.md +++ b/docs/synctl-patch-credential.md @@ -13,19 +13,27 @@ synctl patch cred [options] -h, --help show this help message and exit --verify-tls verify tls certificate + --value set credential value --apps, --applications [ ...] set multiple applications --websites [ ...] set websites --mobile-apps [ ...] set mobile appliactions ``` ## Examples +### Patch a synthetic credential value +``` +synctl patch cred swecred --value +``` + ### Patch a Synthetic credential with multiple applications. ``` synctl patch cred --applications/--apps "$APPLICATION1" "$APPLICATION2" "$APPLICATION3" ..." ``` + ### Patch a Synthetic credential with multiple websites. ``` synctl patch cred --websites "$WEBSITE1" "$WEBSITE2" ... ``` + ### Patch a Synthetic credential with multiple mobile applications. ``` synctl patch cred --mobile-applications/--mobile-apps "$APPLICATION1" "$APPLICATION2" "$APPLICATION3" ..." diff --git a/docs/synctl-update-credential.md b/docs/synctl-update-credential.md index a74a0e0..ab49d3e 100644 --- a/docs/synctl-update-credential.md +++ b/docs/synctl-update-credential.md @@ -4,11 +4,25 @@ Update Synthetic credential ## Syntax ``` -synctl update cred --value +synctl update cred [options] ``` ## Options ### Common options ``` - -h, --help show this help message and exit - --verify-tls verify tls certificate + -h, --help show this help message and exit + --verify-tls verify tls certificate + + --value set credential value + --apps, --applications [ ...] set multiple applications + --websites [ ...] set multiple websites + --mobile-apps, --mobile-applications [ ...] set multiple mobile appliactions +``` +## Examples +### Common Example for credentials +``` +synctl update cred swecred --value \ + --apps "$APPID-1" "$APPID-2" ...\ + --websites "$MOBILE-APPID-1" "$MOBILE-APPID-2" ...\ + --mobile-apps "$WEBSITE-1" "$WEBSITE-2" ... +``` \ No newline at end of file diff --git a/synctl/cli.py b/synctl/cli.py index 222ccab..d070c76 100755 --- a/synctl/cli.py +++ b/synctl/cli.py @@ -208,16 +208,23 @@ def validate_args(args): # Estimate the cost of Instana-hosted Pop synctl get pop-cost""" -PATCH_USAGE = """synctl patch test id [options] +PATCH_USAGE = """synctl patch {test,cred} id [options] examples: # set active to false synctl patch test --active false # update frequency to 5, run test every 5min -synctl patch test --frequency 5""" +synctl patch test --frequency 5 -UPDATE_USAGE = """synctl update {test,alert} [options] +# update a credential value +synctl patch cred --value + +# update a credential with multiple applications +synctl patch cred --apps "$APPLICATION1" "$APPLICATION2" ... +""" + +UPDATE_USAGE = """synctl update {test,alert, cred} [options] examples: # update synthetic test/smart alert using file @@ -244,6 +251,12 @@ def validate_args(args): --test "$SYNTHETIC_TEST1" "$SYNTHETIC_TEST2" "$SYNTHETIC_TEST3" ... \\ --violation-count 2 \\ --severity warning + +# update credential with multiple options +synctl update cred \\ + --apps "$APP-ID1" "$APP-ID2" \\ + --websites "$WEBSITE-ID1" "$WEBSITE-ID2" \\ + --mobile-apps "$MOBILEAPP-ID1" "$MOBILEAPP-ID2" # enable/disable a smart alert synctl update alert --enable @@ -1410,7 +1423,10 @@ def __init__(self): Base.__init__(self) self.credential_config = { "credentialName": "", - "credentialValue": "" + "credentialValue": "", + "applications": [], + "mobileApps": [], + "websites": [] } def set_credential_name(self, key): @@ -1425,15 +1441,13 @@ def set_credential_applications(self, applications: list): def set_credential_websites(self, websites: list): self.credential_config["websites"] = websites - def set_credential_mobile_apps(self, mobile_apps): + def set_credential_mobile_apps(self, mobile_apps: list): self.credential_config["mobileApps"] = mobile_apps def get_json(self): """return payload as json""" if len(self.credential_config["credentialName"]) == 0: self.exit_synctl(ERROR_CODE, "Error: no credential name, set --key ") - elif len(self.credential_config["credentialValue"]) == 0: - self.exit_synctl(ERROR_CODE, "Error: no credential value, set --value ") result = json.dumps(self.credential_config) return result @@ -1605,53 +1619,42 @@ def delete_credentials(self, cred_list): def update_a_credential(self, cred): self.check_host_and_token(self.auth["host"], self.auth["token"]) + host = self.auth["host"] + token = self.auth["token"] if cred is None: - print("credential should not be empty") + self.exit_synctl(ERROR_CODE, "credential should not be empty") return - credential = self.retrieve_credentials() - - host = self.auth["host"] - token = self.auth["token"] + cred_payload = self.payload + put_url = f"{host}/api/synthetics/settings/credentials/{cred}" - # delete cred - delete_url = f"{host}/api/synthetics/settings/credentials/{cred}" headers = { - "Content-Type": "application/json", + 'Content-Type': 'application/json', "Authorization": f"apiToken {token}" } - if cred in credential: - delete_res = requests.delete(delete_url, + try: + update_result = requests.put(put_url, headers=headers, + data=cred_payload, timeout=60, verify=self.insecure) - if _status_is_204(delete_res.status_code): - pass + if _status_is_200(update_result.status_code): + print(f"cred {cred} updated") + elif _status_is_400(update_result.status_code): + print(f'Error: {update_result}', update_result.content) + elif _status_is_429(update_result.status_code): + print(update_result.content) + self.exit_synctl(ERROR_CODE, TOO_MANY_REQUEST_ERROR) else: - self.exit_synctl(ERROR_CODE, f"Fail to delete {cred}") - else: - self.exit_synctl(ERROR_CODE, f"no credential {cred}") - - # create cred - create_url = f"{host}/api/synthetics/settings/credentials/" + print( + f'update cred {cred} failed, status code: {update_result.status_code, }') + except requests.ConnectTimeout as timeout_error: + self.exit_synctl(f"Connection to {host} timed out, error is {timeout_error}") + except requests.ConnectionError as connect_error: + self.exit_synctl(f"Connection to {host} failed, error is {connect_error}") - credential = self.retrieve_credentials() - cred_payload = self.payload - if cred not in credential: - create_cred_res = requests.post(create_url, - headers=headers, - data=cred_payload, - timeout=60, - verify=self.insecure) - if _status_is_201(create_cred_res.status_code): - print(f"Credential \"{cred}\" updated") - else: - print('Update credential failed, status code:', - create_cred_res.status_code) - else: - print("Credential already exists") def patch_applications(self, cred, applications): payload = {"applications": []} @@ -1680,6 +1683,15 @@ def patch_mobile_apps(self, cred, mobile_apps): payload["mobileApps"] = mobile_apps self.__patch_a_credential(cred, json.dumps(payload)) + def patch_credential_value(self, cred, cred_value): + payload = {"credentialValue": ""} + if cred_value is None: + print("No value for credential") + return + else: + payload["credentialValue"] = cred_value + self.__patch_a_credential(cred, json.dumps(payload)) + def __patch_a_credential(self, cred, data): self.check_host_and_token(self.auth["host"], self.auth["token"]) host = self.auth["host"] @@ -1689,7 +1701,7 @@ def __patch_a_credential(self, cred, data): print("credential should not be empty") return - patch_url = f"{host}/api/synthetics/settings/credentials/associations/{cred}" + patch_url = f"{host}/api/synthetics/settings/credentials/{cred}" if data is None: self.exit_synctl(ERROR_CODE, "Patch Error:data cannot be empty") @@ -4955,6 +4967,8 @@ def patch_command_options(self): '--remaining-days-check', type=int, metavar="", help='check remaining days for expiration of SSL certificate') # Patch cred + patch_exclusive_group.add_argument( + '--value', type=str, metavar="", help='set credential value') patch_exclusive_group.add_argument( '--applications', '--apps', nargs="+", metavar="", help="set applications") patch_exclusive_group.add_argument( @@ -5001,7 +5015,7 @@ def update_command_options(self): update_group.add_argument( '--custom-properties', type=str, metavar="", help="set custom property of a test") update_group.add_argument( - '--apps', '--applications', '--app-id', '--application-id', type=str, metavar="", help="application id") + '--apps', '--applications', '--app-id', '--application-id',nargs='+', type=str, metavar="", help="application id") update_group.add_argument( '--websites', type=str, nargs='+', metavar="", help="website id, support multiple websites") update_group.add_argument( @@ -5672,6 +5686,8 @@ def main(): cred_instance.patch_websites(get_args.id, get_args.websites) if get_args.mobile_apps is not None: cred_instance.patch_mobile_apps(get_args.id, get_args.mobile_apps) + if get_args.value is not None: + cred_instance.patch_credential_value(get_args.id, get_args.value) elif COMMAND_UPDATE == get_args.sub_command: if get_args.syn_type == SYN_TEST: invalid_options = ["name", "severity", "alert_channel", "test", "violation_count"] @@ -5792,9 +5808,16 @@ def main(): update_alert.update_a_smart_alert(get_args.id, updated_alert_config) if get_args.syn_type == SYN_CRED: cred_payload = CredentialConfiguration() - if get_args.value is not None: + if get_args.id is not None: cred_payload.set_credential_name(get_args.id) - cred_payload.set_credential_value(get_args.value) + if get_args.value is not None: + cred_payload.set_credential_value(get_args.value) + if get_args.apps is not None: + cred_payload.set_credential_applications(get_args.apps) + if get_args.websites is not None: + cred_payload.set_credential_websites(get_args.websites) + if get_args.mobile_apps is not None: + cred_payload.set_credential_mobile_apps(get_args.mobile_apps) cred_instance.set_cred_payload(payload=cred_payload.get_json()) cred_instance.update_a_credential(get_args.id)