diff --git a/integration/keeper_secrets_manager_cli/README.md b/integration/keeper_secrets_manager_cli/README.md index ebe34716..440786c1 100644 --- a/integration/keeper_secrets_manager_cli/README.md +++ b/integration/keeper_secrets_manager_cli/README.md @@ -6,6 +6,10 @@ For more information see our official documentation page https://docs.keeper.io/ # Change History +## 1.0.17 +* KSM-392 - Ability to update fields where the label is a blank string (`""`) +* Pinned KSM Core version to 16.5.1 + ## 1.0.16 * KSM-362 - Synchronize secrets to GCP diff --git a/integration/keeper_secrets_manager_cli/keeper_secrets_manager_cli/secret.py b/integration/keeper_secrets_manager_cli/keeper_secrets_manager_cli/secret.py index a6f09d9e..40dad3cb 100644 --- a/integration/keeper_secrets_manager_cli/keeper_secrets_manager_cli/secret.py +++ b/integration/keeper_secrets_manager_cli/keeper_secrets_manager_cli/secret.py @@ -560,10 +560,16 @@ def update(self, uid, fields=None, custom_fields=None, fields_json=None, custom_ if len(record) == 0: raise KsmCliException("Cannot find a record for UID {}.".format(uid)) + def _get_label(x): + label = x.get("label") + if label is None or label == "": + label = x.get("type") + return label + # Get a list of all labels/type allowed. labels = { - "field": [x.get("label", x.get("type")) for x in record[0].dict.get("fields", [])], - "custom_field": [x.get("label", x.get("type")) for x in record[0].dict.get("custom", [])] + "field": [_get_label(x) for x in record[0].dict.get("fields", [])], + "custom_field": [_get_label(x) for x in record[0].dict.get("custom", [])] } data = [ diff --git a/integration/keeper_secrets_manager_cli/requirements.txt b/integration/keeper_secrets_manager_cli/requirements.txt index 8e9d038e..15658067 100644 --- a/integration/keeper_secrets_manager_cli/requirements.txt +++ b/integration/keeper_secrets_manager_cli/requirements.txt @@ -1,4 +1,4 @@ -keeper-secrets-manager-core>=16.5.1 +keeper-secrets-manager-core==16.5.1 keeper-secrets-manager-helper prompt-toolkit~=2.0 jsonpath-rw-ext diff --git a/integration/keeper_secrets_manager_cli/setup.py b/integration/keeper_secrets_manager_cli/setup.py index fece0206..eeae67f2 100644 --- a/integration/keeper_secrets_manager_cli/setup.py +++ b/integration/keeper_secrets_manager_cli/setup.py @@ -8,7 +8,7 @@ long_description = f.read() install_requires = [ - 'keeper-secrets-manager-core>=16.5.1', + 'keeper-secrets-manager-core==16.5.1', 'keeper-secrets-manager-helper', 'prompt-toolkit~=2.0', 'click', @@ -25,7 +25,7 @@ # Version set in the keeper_secrets_manager_cli.version file. setup( name="keeper-secrets-manager-cli", - version="1.0.16", + version="1.0.17", description="Command line tool for Keeper Secrets Manager", long_description=long_description, long_description_content_type="text/markdown", diff --git a/integration/keeper_secrets_manager_cli/tests/secret_test.py b/integration/keeper_secrets_manager_cli/tests/secret_test.py index cae103dc..0bcf0e15 100644 --- a/integration/keeper_secrets_manager_cli/tests/secret_test.py +++ b/integration/keeper_secrets_manager_cli/tests/secret_test.py @@ -612,6 +612,57 @@ def test_update(self): 'did not get correct error message for save') self.assertEqual(1, result.exit_code, "the exit code was not 1") + def test_update_blank_labels(self): + """Test updating an existing record + """ + + mock_config = MockConfig.make_config() + secrets_manager = SecretsManager(config=InMemoryKeyValueStorage(mock_config)) + + res = mock.Response() + one = res.add_record(title="My Record 1") + one.field("login", label="", value="My Login 1") + one.field("password", label="", value="My Password 1") + + queue = mock.ResponseQueue(client=secrets_manager) + queue.add_response(res) + + # The good one + queue.add_response(res) + queue.add_response(mock.Response(content="", status_code=200)) + + # The bad field + queue.add_response(res) + + # Bad server response + queue.add_response(res) + queue.add_response(mock.Response(content="I hate you and your little dog.", status_code=500)) + + # JSON + queue.add_response(res) + queue.add_response(mock.Response(content="", status_code=200)) + + # JSON Bad + queue.add_response(res) + + with patch('keeper_secrets_manager_cli.KeeperCli.get_client') \ + as mock_client: + mock_client.return_value = secrets_manager + + Profile.init(token='MY_TOKEN') + + # Because of click/testing.py:278 ResourceWarning: unclosed file <_io.FileIO ... + warnings.simplefilter("ignore", ResourceWarning) + + # The good one! + runner = CliRunner() + result = runner.invoke(cli, [ + 'secret', 'update', '-u', one.uid, + '--field', '"login=New Login"', + ], catch_exceptions=False) + print(result.output) + self.assertEqual(0, result.exit_code, "the exit code was not 0") + def test_kv_split(self): """Test splitting the key/value pairs """