-
Notifications
You must be signed in to change notification settings - Fork 14
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
Supporting Client Secret rotation programatically + documentation update #15
base: main
Are you sure you want to change the base?
Conversation
@@ -367,3 +370,141 @@ def setSandbox(self,sandbox:str=None)->dict: | |||
self.header["x-sandbox-name"] = sandbox | |||
self.__configObject__["sandbox"] = sandbox | |||
return self.getConfigObject() | |||
|
|||
def setOauthV2setup(self,credentialId:str=None,orgDevId:str=None)->bool: |
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.
can we use python style conventions in functions, namely with underscores for functions
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.
I would have agreed but the whole package is using the camelCase notation.
I would think that we should be consistent over the different modules and keep camelCase usage.
It does not hurt in the end.
Also changing the method names is a massive breaking change.
if self.connectionType != "oauthV2": | ||
raise Exception("You are trying to set credential ID or orgDevId for auth that is not OauthV2. We do not support these auth type.") | ||
if credentialId is None: | ||
raise ValueError("credentialId is None") |
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.
With these exceptions what are the expectations on how the user recovers, what do they need 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.
The rotating client capability are not supported for JWT or Oauth V1.
There is no recovery, except moving to OauthV2 credential type.
How do you recommend to provide that feedback ?
aepp/configs.py
Outdated
raise ValueError("orgDevId is None") | ||
self.credentialId = credentialId | ||
self.orgDevId = orgDevId | ||
return True |
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.
why are we returning boolean from a mutator function, typically a mutator would return void and an accessor function would return a datatype
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.
True, for some reason, I thought it would be interesting to get when the function has correctly executed but definitely not normal setup, I will change it in the next commit.
orgDevId : OPTIONAL : the org Id but NOT the IMS string. It is defined on your project page. | ||
Example : https://developer.adobe.com/console/projects/<orgId>/<projectId>/credentials/<credentialId>/details/oauthservertoserver | ||
""" | ||
if self.connectionType != "oauthV2": |
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.
should we move these checks into Utils instead
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.
I am not sure what part you are referring about.
the configs part ? We can, we just need to change the reference everywhere.
If it is in configs.py
vs utils.py
it does not matter.
Let me know.
I would believe that it would be a different PR to be honest.
'x-api-key' : self.client_id | ||
} | ||
endpoint = f"https://api.adobe.io/console/organizations/{orgDevId}/credentials/{credentialId}/secrets" | ||
res = self.connector.getData(endpoint,headers=myheader) |
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.
do we need to do any validations on res?
@@ -12,7 +12,7 @@ | |||
import os |
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.
please add unit tests to this PR based on our new convention with all features
cf.write(json.dumps(json_data, indent=4)) | ||
return True | ||
|
||
def deleteSecrete(self,secretUID:str=None,credentialId:str=None,orgDevId:str=None,)->None: |
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.
lets rename to delete_secret
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.
As explained above, the package current naming convention is using lower camelCase, so I think we should keep it consistent.
Otherwise, we would need to rename all existing methods which is a massive breaking change.
aepp/configs.py
Outdated
} | ||
with open(destination, "w") as cf: | ||
cf.write(json.dumps(json_data, indent=4)) | ||
return True |
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.
again lets not return bool from these functions, typically set and update either return void or a data structure that contains a status
orgDevId : OPTIONAL : the org Id but NOT the IMS string. It is defined on your project page. | ||
Example : https://developer.adobe.com/console/projects/<orgId>/<projectId>/credentials/<credentialId>/details/oauthservertoserver | ||
""" | ||
if self.connectionType != "oauthV2": |
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.
see my comments above on these if statements
@@ -0,0 +1,258 @@ | |||
# Connect Object class | |||
|
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.
can we move this to the Readme or code, not sure we need an individual markdown file, was there a reason to create separate documentation around this
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.
As you can see the ConnectObject Instance is actually a module by itself providing way to connect to the AEP API without the need of other modules, it can also serve as a way to rotate your client secret programmatically.
As a specific class and method available, it has to follow the current structure and get its own markdown file.
The readMe would be pretty long with that.
'Authorization' : 'Bearer '+self.token, | ||
'x-api-key' : self.client_id | ||
} | ||
endpoint = f"https://api.adobe.io/console/organizations/{orgDevId}/credentials/{credentialId}/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.
will this endpoint be the same for stage and prod?
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.
Good question. I am only able to follow what is actually providing on the official documentation. https://developer.adobe.com/developer-console/docs/guides/authentication/ServerToServerAuthentication/implementation/
I do not think that you are using OauthV2, but Oauth V1.
I would suggest that we go live so provide clients with this functionality and if you ever need it and it is required to have a different url, we can use a variable to modify the endpoint automatically.
We can even use the environment
parameter from the configuration file or configure method to define the correct endpoint if it turns out to be different from the stage and prod.
I have added unit tests and modified the return statement for the void functions as asked. |
from unittest.mock import patch, MagicMock, Mock, ANY | ||
|
||
@patch("aepp.configs.importConfigFile") | ||
def test_importConfigFile_Oauth(mock_data): |
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.
nit change 0auth to oauth
|
||
@patch("aepp.configs.importConfigFile") | ||
def test_importConfigFile_Oauth(mock_data): | ||
mock_data.return_value = { |
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.
I'm not sure we need this test, from what I see its just saying that mock_data is a dict, is there a case ever where it wouldnt be a dict?
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.
You can just define mock_data as a fixture that can be leveraged in the methods below
Client Rotating Option + ConnectInstance Documentation
Providing the option to rotate client secrets for Oauth V2 connection as described in the documentation : https://developer.adobe.com/developer-console/docs/guides/authentication/ServerToServerAuthentication/implementation/
At the same time, documenting the ConnectInstance class.
Motivation and Context
When clients wants to change their secret, they may want to do it programmatically and not via UI.
We now support that option via the ConnectInstance object.
How Has This Been Tested?
Tested on client implementation.
Types of changes
Checklist: