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 support for using credstash as a secret store #8494

Merged
merged 1 commit into from
Jul 24, 2017

Conversation

justin8
Copy link
Contributor

@justin8 justin8 commented Jul 16, 2017

Description:

Add support for using credstash to store secrets.

It is used by using the same !secret foo syntax as the existing secrets.yaml and keyring methods of storing secrets. The CLI script for managing secrets is very similar to the one for using a keyring. Examples can be seen in the documentation PR below

Pull request in home-assistant.github.io with documentation (if applicable): home-assistant/home-assistant.io#2988

Checklist:

If user exposed functionality or configuration variables are added/changed:

If the code communicates with devices, web services, or third-party tools:

  • Local tests with tox run successfully. Your PR cannot be merged unless tests pass
  • New dependencies have been added to the REQUIREMENTS variable ([example][ex-requir]).
  • New dependencies are only imported inside functions that use them ([example][ex-import]).
  • New dependencies have been added to requirements_all.txt by running script/gen_requirements_all.py.
  • New files were added to .coveragerc.

If the code does not interact with devices:

  • Local tests with tox run successfully. Your PR cannot be merged unless tests pass
  • Tests have been added to verify that the new code works.

@mention-bot
Copy link

@justin8, thanks for your PR! By analyzing the history of the files in this pull request, we identified @fabaff, @balloob and @kellerza to be potential reviewers.

the_secret = getpass.getpass('Please enter the secret for {}: '
.format(args.name))
current_version = int(credstash.getHighestVersion(args.name, table=_SECRET_NAMESPACE))
credstash.putSecret(args.name, the_secret, version=current_version+1, table=_SECRET_NAMESPACE)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

line too long (102 > 79 characters)

if args.action == 'put':
the_secret = getpass.getpass('Please enter the secret for {}: '
.format(args.name))
current_version = int(credstash.getHighestVersion(args.name, table=_SECRET_NAMESPACE))

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

line too long (94 > 79 characters)

def run(args):
"""Handle credstash script."""
parser = argparse.ArgumentParser(
description=("Modify Home-Assistant secrets in the default credstash store. "

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

line too long (85 > 79 characters)

@@ -0,0 +1,60 @@
"""Script to get, put and delete secrets stored in credstash."""
import os

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'os' imported but unused

@MartinHjelmare
Copy link
Member

So this uses the same syntax as for the yaml !secret? Maybe add a short explanation here in the description and a config example? The documentation PR code explains it though.

@justin8
Copy link
Contributor Author

justin8 commented Jul 18, 2017

Correct, it uses the same syntax. I did forget to mention that here, I updated the PR comment to reflect that.

As for the documentation, I kept it similar to the keyring one that already exists as it functions almost identically

@pvizeli pvizeli requested a review from balloob July 20, 2017 13:50

if args.action == 'list':
secrets = [i['name'] for i in credstash.listSecrets(table=table)]
deduped_secrets = list(dict.fromkeys(secrets))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sorted(set(i['name'] for i in credstash.listSecrets(table=table)))

Copy link
Contributor Author

@justin8 justin8 Jul 24, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done (mostly). I kept it as 2 variables to keep the line length under 80 and also to make it a little bit more readable.

@@ -372,6 +386,17 @@ def test_secrets_keyring(self):
_yaml = load_yaml(self._yaml_path, yaml_str)
self.assertEqual({'http': {'api_password': 'yeah'}}, _yaml)

def test_secrets_credstash(self):
"""Test credstash fallback & get_password."""
yaml.credstash = None
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tests should not have any side effects, please use

from unittest.mock import patch
with patch.object(yaml, 'credstash', None):
    …

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, I should've known better. I was just copying the test case directly above to keep in line with existing tests/formatting

@@ -372,6 +386,17 @@ def test_secrets_keyring(self):
_yaml = load_yaml(self._yaml_path, yaml_str)
self.assertEqual({'http': {'api_password': 'yeah'}}, _yaml)

def test_secrets_credstash(self):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't look like your test uses any of the setup in this class. Please move it to be a standalone function in this file.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It uses the self._yaml_path from setup, which itself uses some other parts of the setup.

The path is needed to ensure fall-through when a secret isn't in the local file, that credstash.getSecret is called

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok 👍

@balloob
Copy link
Member

balloob commented Jul 24, 2017

Thanks 🐬

Ok to merge when tests pass.

@balloob balloob merged commit 98568b5 into home-assistant:dev Jul 24, 2017
@justin8 justin8 deleted the credstash branch July 25, 2017 01:34
@balloob balloob mentioned this pull request Jul 29, 2017
@balloob
Copy link
Member

balloob commented Aug 5, 2017

This PR is not mocking out credstash correctly during other tests and now we're doing I/O during unit tests + can no longer run tests offline.

@justin8
Copy link
Contributor Author

justin8 commented Aug 5, 2017

Hmm, how can I mock it out for all the other tests? should I just be adding it to the other test functions for the yaml parser?

@balloob
Copy link
Member

balloob commented Aug 5, 2017

I'm fixing it like this right now: https://github.com/home-assistant/home-assistant/pull/8834/files#diff-0897a49ea1455f0a57774d651fec8d47R16

The credstash test still passes, so I guess that's good?

dethpickle pushed a commit to dethpickle/home-assistant that referenced this pull request Aug 18, 2017
@home-assistant home-assistant locked and limited conversation to collaborators Dec 11, 2017
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants