-
Notifications
You must be signed in to change notification settings - Fork 6
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
secret management #104
secret management #104
Changes from all commits
fd01642
5e4cf56
dfc6cd7
c797c89
b5d833d
b001b4e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||
---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,131 @@ | ||||||||
import requests | ||||||||
import logging | ||||||||
import json | ||||||||
from maap.utils import endpoints | ||||||||
from maap.utils import requests_utils | ||||||||
from maap.utils import endpoints | ||||||||
|
||||||||
logger = logging.getLogger(__name__) | ||||||||
|
||||||||
class Secrets: | ||||||||
""" | ||||||||
Functions used for member secrets API interfacing | ||||||||
""" | ||||||||
def __init__(self, member_endpoint, api_header): | ||||||||
self._api_header = api_header | ||||||||
self._members_endpoint = f"{member_endpoint}/{endpoints.MEMBERS_SECRETS}" | ||||||||
|
||||||||
|
||||||||
def get_secrets(self): | ||||||||
""" | ||||||||
Returns a list of secrets for a given user. | ||||||||
|
||||||||
Returns: | ||||||||
list: Returns a list of dicts containing secret names e.g. [{'secret_name': 'secret1'}, {'secret_name': 'secret2'}]. | ||||||||
""" | ||||||||
try: | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Just more informative to log what function is being called than just logging |
||||||||
response = requests.get( | ||||||||
url = self._members_endpoint, | ||||||||
headers=self._api_header | ||||||||
) | ||||||||
logger.debug(f"Response from get_secrets request: {response.text}") | ||||||||
return json.loads(response.text) | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should this be of type list or dict to match the doc string? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's a list of dicts. I've updated the doc string to provide an example. |
||||||||
except Exception as e: | ||||||||
raise(f"Error retrieving secrets: {e}") | ||||||||
|
||||||||
|
||||||||
def get_secret(self, secret_name): | ||||||||
""" | ||||||||
Returns secret value for provided secret name. | ||||||||
|
||||||||
Args: | ||||||||
secret_name (str, required): Secret name. | ||||||||
|
||||||||
Returns: | ||||||||
string: Secret value. | ||||||||
|
||||||||
Raises: | ||||||||
ValueError: If secret name is not provided. | ||||||||
""" | ||||||||
if secret_name is None: | ||||||||
raise ValueError("Secret name parameter cannot be None.") | ||||||||
|
||||||||
try: | ||||||||
response = requests.get( | ||||||||
marjo-luc marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||
url = f"{self._members_endpoint}/{secret_name}", | ||||||||
headers=self._api_header | ||||||||
) | ||||||||
|
||||||||
# Return secret value directly for user ease-of-use | ||||||||
if response.ok: | ||||||||
response = response.json() | ||||||||
return response["secret_value"] | ||||||||
|
||||||||
logger.debug(f"Response from get_secret request: {response.text}") | ||||||||
return json.loads(response.text) | ||||||||
except Exception as e: | ||||||||
raise(f"Error retrieving secret: {e}") | ||||||||
|
||||||||
|
||||||||
def add_secret(self, secret_name=None, secret_value=None): | ||||||||
""" | ||||||||
Adds a secret. Secret name must be provided. Secret value may be null. | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is the use-case of having a secret without a value ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Mostly because an empty string is a valid value and I don't see a good reason placing additional constraints on this. I was also thinking of cases where users might need to have the secret parameter exist but not necessarily care about the value itself. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Saw this later, commented below. |
||||||||
|
||||||||
Args: | ||||||||
secret_name (str, required): Secret name. | ||||||||
secret_value (str, optional): Secret value. | ||||||||
|
||||||||
Returns: | ||||||||
dict: Containing name and value of secret that was just added. | ||||||||
|
||||||||
Raises: | ||||||||
ValueError: If secret name or secret value is not provided. | ||||||||
""" | ||||||||
if secret_name is None or secret_value is None: | ||||||||
raise ValueError("Failed to add secret. Secret name and secret value must not be 'None'.") | ||||||||
|
||||||||
try: | ||||||||
response = requests.post( | ||||||||
url = self._members_endpoint, | ||||||||
headers=self._api_header, | ||||||||
data=json.dumps({"secret_name": secret_name, "secret_value": secret_value}) | ||||||||
) | ||||||||
|
||||||||
logger.debug(f"Response from add_secret: {response.text}") | ||||||||
return json.loads(response.text) | ||||||||
except Exception as e: | ||||||||
raise(f"Error adding secret: {e}") | ||||||||
|
||||||||
|
||||||||
def delete_secret(self, secret_name=None): | ||||||||
""" | ||||||||
Deletes a secret. | ||||||||
|
||||||||
Args: | ||||||||
secret_name (str, required): Secret name. | ||||||||
|
||||||||
Returns: | ||||||||
dict: Containing response code and message indicating whether or not deletion was successful. | ||||||||
|
||||||||
Raises: | ||||||||
ValueError: If secret name is not provided. | ||||||||
""" | ||||||||
if secret_name is None: | ||||||||
raise ValueError("Failed to delete secret. Please provide secret name.") | ||||||||
|
||||||||
try: | ||||||||
response = requests.delete( | ||||||||
url = f"{self._members_endpoint}/{secret_name}", | ||||||||
headers=self._api_header | ||||||||
) | ||||||||
|
||||||||
logger.debug(f"Response from delete_secret: {response.text}") | ||||||||
return json.loads(response.text) | ||||||||
except Exception as e: | ||||||||
raise(f"Error deleting secret: {e}") | ||||||||
|
||||||||
|
||||||||
|
||||||||
|
||||||||
|
||||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,3 +3,5 @@ | |
DPS_JOB_DISMISS = "cancel" | ||
DPS_JOB_LIST = "list" | ||
CMR_ALGORITHM_DATA = "data" | ||
|
||
MEMBERS_SECRETS = "secrets" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you add a section in the functional test to test adding, retrieving and deleting a secret?
https://github.com/MAAP-Project/maap-py/blob/master/test/functional_test.py
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, this is next on my to-do.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Implemented.