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

Add resource_exists method #32

Merged
merged 1 commit into from
Aug 2, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
[conjur-api-python#30](https://github.com/cyberark/conjur-api-python/pull/30)
- Add support for Show Resource endpoint
[conjur-api-python#31](https://github.com/cyberark/conjur-api-python/pull/31)
- Add `resource_exists` method
[conjur-api-python#32](https://github.com/cyberark/conjur-api-python/pull/32)
- Add support for LDAP authentication
[conjur-api-python#22](https://github.com/cyberark/conjur-api-python/pull/22)

Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,10 @@ For example: `client.list({'kind': 'user', 'inspect': True})`

Gets a resource based on its kind and ID. Resource is json data that contains metadata about the resource.

#### `resource_exists(kind, resource_id)`

Check the existence of a resource based on its kind and ID. Returns a boolean.

#### `get_role(kind, role_id)`

Gets a role based on its kind and ID. Role is json data that contains metadata about the role.
Expand Down
6 changes: 6 additions & 0 deletions conjur_api/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,12 @@ async def get_resource(self, kind: str, resource_id: str) -> json:
"""
return await self._api.get_resource(kind, resource_id)

async def resource_exists(self, kind: str, resource_id: str) -> bool:
"""
Check for the existance of a resource based on its kind and ID
"""
return await self._api.resource_exists(kind, resource_id)

async def get_role(self, kind: str, role_id: str) -> json:
"""
Gets a role based on its kind and ID
Expand Down
29 changes: 28 additions & 1 deletion conjur_api/http/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
from conjur_api.interface.authentication_strategy_interface import AuthenticationStrategyInterface
from conjur_api.wrappers.http_response import HttpResponse
from conjur_api.wrappers.http_wrapper import HttpVerb, invoke_endpoint
from conjur_api.errors.errors import InvalidResourceException, MissingRequiredParameterException
from conjur_api.errors.errors import HttpStatusError, InvalidResourceException, MissingRequiredParameterException
# pylint: disable=too-many-instance-attributes
from conjur_api.models import Resource, ConjurConnectionInfo, ListPermittedRolesData, \
ListMembersOfData, CreateHostData, CreateTokenData, SslVerificationMetadata, SslVerificationMode
Expand Down Expand Up @@ -179,6 +179,33 @@ async def get_resource(self, kind: str, resource_id: str) -> dict:
# ?tocpath=Developer%7CREST%C2%A0APIs%7C_____19
return resource

async def resource_exists(self, kind: str, resource_id: str) -> bool:
"""
This method is used to check whether a specific resource exists.
"""
params = {
'account': self._account,
'kind': kind,
'identifier': resource_id
}
params.update(self._default_params)

try:
await invoke_endpoint(HttpVerb.HEAD, ConjurEndpoint.RESOURCE,
params,
api_token=await self.api_token,
ssl_verification_metadata=self.ssl_verification_data)
except HttpStatusError as err:
if err.status == 404:
return False

if err.status == 403:
return True

raise

return True

async def get_role(self, kind: str, resource_id: str) -> dict:
"""
This method is used to fetch a specific role.
Expand Down
1 change: 1 addition & 0 deletions conjur_api/wrappers/http_wrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ class HttpVerb(Enum):
PUT = 3
DELETE = 4
PATCH = 5
HEAD = 6


# pylint: disable=too-many-locals,consider-using-f-string,too-many-arguments
Expand Down
11 changes: 11 additions & 0 deletions tests/https/test_unit_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,17 @@ async def test_client_get_resource_invokes_api(self, mock_api_token, mock_invoke
self.assertTrue(exists_in_args('dummy', args))
mock_invoke_endpoint.assert_called_once()

@patch.object(Api, '_api_token', new_callable=PropertyMock)
async def test_client_resource_exists_invokes_api(self, mock_api_token, mock_invoke_endpoint):
mock_api_token.return_value = 'test_token'
await self.client.resource_exists('role', 'dummy')

args, kwargs = mock_invoke_endpoint.call_args
self.assertEqual('test_token', kwargs.get('api_token'))
self.assertTrue(exists_in_args('role', args))
self.assertTrue(exists_in_args('dummy', args))
mock_invoke_endpoint.assert_called_once()

@patch.object(Api, '_api_token', new_callable=PropertyMock)
async def test_client_get_many_invokes_api(self, mock_api_token, mock_invoke_endpoint):
mock_api_token.return_value = 'test_token'
Expand Down
1 change: 1 addition & 0 deletions tests/https/test_unit_http.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ def test_http_verb_has_all_the_verbs_expected(self):
self.assertTrue(HttpVerb.POST)
self.assertTrue(HttpVerb.DELETE)
self.assertTrue(HttpVerb.PATCH)
self.assertTrue(HttpVerb.HEAD)


def create_ssl_verification_metadata(mode=SslVerificationMode.TRUST_STORE, cert_path=None):
Expand Down