-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Secrets manager and base provider proposal #2758
Conversation
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.
Looks pretty solid! congrats!
a few nitpicks to fix goal is to go 100% coverage
""" | ||
source of the secret | ||
""" | ||
return self._source |
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 try to get 100% coverage. install codecov.io chrome extension to see that this line is not covered
master/buildbot/secrets/secret.py
Outdated
- source: provider to retrieve secret | ||
- key: secret key identifier | ||
- value: secret value | ||
- props: all other needed properties |
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.
what kind of properties do we need for secrets?
master/buildbot/secrets/secret.py
Outdated
class SecretDetails(object): | ||
""" | ||
A SecretDetails object has secrets attributes: | ||
- source: provider to retrieve 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.
provider where the secret was retrieved
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.
replaced
Codecov Report
@@ Coverage Diff @@
## master #2758 +/- ##
==========================================
+ Coverage 87.31% 87.33% +0.02%
==========================================
Files 305 308 +3
Lines 32564 32622 +58
==========================================
+ Hits 28432 28491 +59
+ Misses 4132 4131 -1
Continue to review full report at Codecov.
|
cb5cf25
to
8ee5636
Compare
9e8d715
to
708b34c
Compare
master/buildbot/secrets/manager.py
Outdated
secret_detail = None | ||
providers = self.master.config.secretsManagers | ||
for provider in providers: | ||
value = provider.get(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.
I think we need this get to be yield. Some providers will need to make network access to do the get
master/buildbot/secrets/manager.py
Outdated
""" | ||
name = 'secrets' | ||
|
||
def get(self, secret, *args, **kwargs): |
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.
this function shall return deferred (inlinecallbacks)
def get(self, *args, **kwargs): | ||
""" | ||
this should be an abstract method | ||
""" |
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 you can mark it abstract https://docs.python.org/2/library/abc.html
master/docs/developer/secrets.rst
Outdated
def __init__(self, provider, key, value, props=None): | ||
|
||
A ``secretDetails`` is a python object initialized with the following parameters: | ||
- provider name to retrieve 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.
name of provider where secret has been retrieved
master/docs/developer/secrets.rst
Outdated
- value returned by the provider API | ||
- properties if needed. | ||
|
||
Each parameter is an object property that should returned the 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.
its not very clear to me what you mean
master/docs/developer/secrets.rst
Outdated
|
||
c['secretsProviders'] = [SecretsProviderOne(params), SecretsProviderTwo(params)] | ||
|
||
If more than one provider is defined in the configuration, the manager returns the first founded 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.
the manager returns the first value found.
master/docs/developer/secrets.rst
Outdated
secretDetails = secretsService.get(secret) | ||
|
||
The get API take the secret key as parameters and read the configuration to obtains the list of configured providers. | ||
The manager get the selected provider and returns a ``SecretDetails``. |
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 manager call the get method of the configured provider and returns a SecretDetails
if the call succeed.
"other2": "value"}) | ||
] | ||
SecretManager.master = self.master | ||
expectedSecretDetail = SecretDetails( |
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.
If not found, I think it should return None, not secretDefails(fakestorage2, 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.
I preferred to return the object because it contains the provider class name information, that will be used to prompt a log error indication from where the information has not been found.
we spoke about that together, I changed it. The get API returns the first found value else returns None
] | ||
SecretManager.master = self.master | ||
expectedSecretDetail = SecretDetails( | ||
OtherFakeSecretStorage({"foo2": "bar", |
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 dont you just write OtherFakeSecretStorage.__name__
?
get is an abstract method in the provider base fixes in the rst
master/buildbot/secrets/manager.py
Outdated
""" | ||
secret_detail = None | ||
providers = self.master.config.secretsManagers | ||
for provider in providers: |
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 should return the first that is not None.
for provider in providers:
value = yield provider.get(secret)
if value is not None:
source_name = provider.__class__.__name__
defer.returnValue(SecretDetails(source_name, secret, value))
# return None is implicit
"foo3", | ||
None) | ||
secret_result = yield secret_service_manager.get("foo3") | ||
self.assertEqual(secret_result, expectedSecretDetail) |
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.
Need to add a test for 2 providers having the secret in their DB (but not the same value):
should return the value of the first provider
# this program; if not, write to the Free Software Foundation, Inc., 51 | ||
# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
# | ||
# Copyright Buildbot Team Members |
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.
We will have several providers, so we should call this module buildbot.secrets.providers (with an s)
master/buildbot/secrets/manager.py
Outdated
for provider in providers: | ||
value = yield provider.get(secret) | ||
source_name = provider.__class__.__name__ | ||
if 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.
if value is not None (a secret might be empty string)
] | ||
SecretManager.master = self.master | ||
secret_result = yield secret_service_manager.get("foo3") | ||
self.assertEqual(secret_result, 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.
I don't see the test with two providers providing the same secret.
Need another test with a secret value being empty string ( empty string is valid secret)
Proposal to implement Buildbot secrets service:
Contributor Checklist: