Skip to content
This repository has been archived by the owner on Jun 29, 2022. It is now read-only.

Secure auth credential and profile files with ansible vault encryption #59

Merged
merged 3 commits into from
Jul 14, 2017

Conversation

chambridge
Copy link

This is a first step where all i/o to data/credentials and data/profiles are encrypted/decrypted using the ansible vault api.

Some notable changes:

  • Added ability to pass in vault password via a file (this is for scripting purposes & easing testing)
  • Data in credentials and profiles file are no longer using CSV Writer. Now data is stored as an encrypted JSON string that allows us to load the file back into an Python list of dictionaries instead of harder to read file parsing.

@coveralls
Copy link

coveralls commented Jul 13, 2017

Coverage Status

Coverage increased (+10.8%) to 62.143% when pulling 14c6493 on issues/47-part1 into f95cbb8 on master.

Copy link

@noahl noahl left a comment

Choose a reason for hiding this comment

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

I have some comments, but overall I am looking forward to this change. It will be a big improvement to Rho, and will remove some hesitations that customers could have about using Rho.

@@ -15,28 +15,50 @@
"""

from __future__ import print_function
import csv
import json
Copy link

Choose a reason for hiding this comment

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

👍 👍

"""
auth_found = False
for cred in cred_list:
if cred.get('name') == auth_name:
Copy link

Choose a reason for hiding this comment

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

Do we ever have credentials with no "name" field? I really don't know, just asking.

Copy link
Author

Choose a reason for hiding this comment

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

No. A name is a required field for an auth credential.
https://github.com/quipucords/rho/blob/master/rho/authaddcommand.py#L78

Copy link

Choose a reason for hiding this comment

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

Thanks!

cred_list.append(new_cred)

data = json.dumps(cred_list, separators=(',', ': '))
with open(credentials_path, 'wb') as cred_file:
Copy link

Choose a reason for hiding this comment

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

This makes me nervous, because if something goes wrong, I think we lose the old credentials file as well as the new one. How about writing to a new temporary file and then renaming the temp file to credentials_path?

Copy link
Author

Choose a reason for hiding this comment

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

moved writing data into vault file. It now takes an object then coverts to json, the writes to temporary file, the moves to final file location.


os.remove('data/cred-temp')
if self.options.name:
Copy link

Choose a reason for hiding this comment

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

I think that in general there is a lot of duplicated code in these files, specifically in the self.parse.add_option calls and in the "get Vault password, read credentials file, and then rewrite credentials file" patterns. I would like to move that to helper functions/classes. We could either put them in a new file, or combine all of the auth-related commands into a single file and put the helpers there.

Copy link
Author

Choose a reason for hiding this comment

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

I've collapsed the vault init flow to a helper method in the vault.py file. Open to changes in the init for commands around the self.parse.add_option, perhaps we can pursue this as part of #38.

Copy link

Choose a reason for hiding this comment

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

Sounds good to me.

rho/vault.py Outdated

def load_as_json(self, secure_file):
"""read vault secured file and return json decoded object"""
return json.loads(self.load(open(secure_file).read()))
Copy link

Choose a reason for hiding this comment

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

Maybe json.loads(self.load_secure_file(secure_file))?

Copy link
Author

Choose a reason for hiding this comment

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

yep. That was my intent, but must have gotten side tracked. Will fix.

@@ -58,7 +71,7 @@ def test_scan_facts_default(self):
"--reset", "--reportfile",
"data/test_report.csv", "--facts",
"default", "ansible_forks",
"100"])
"100", "--vault", "./vault_pass"])
Copy link

Choose a reason for hiding this comment

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

Let's use /tmp for these files. I can imagine that writing to ./vault_pass in some directory we don't control could cause problems for someone later on.

Also, please pull the default file paths for testing out into module-level constants or group the shared code. I know the rest of the code isn't written that way, but I think that it all should be, and at least we can avoid making it worse.

Copy link
Author

Choose a reason for hiding this comment

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

I've moved all the files for testing to /tmp. Hopefully this is what you were going for, if not lets capture further updates here: #33

@coveralls
Copy link

coveralls commented Jul 14, 2017

Coverage Status

Coverage increased (+11.2%) to 62.5% when pulling bef60ac on issues/47-part1 into f95cbb8 on master.

1 similar comment
@coveralls
Copy link

Coverage Status

Coverage increased (+11.2%) to 62.5% when pulling bef60ac on issues/47-part1 into f95cbb8 on master.

Copy link

@noahl noahl left a comment

Choose a reason for hiding this comment

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

Looks good! This is a big improvement in Rho. 👍

"""
auth_found = False
for cred in cred_list:
if cred.get('name') == auth_name:
Copy link

Choose a reason for hiding this comment

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

Thanks!


os.remove('data/cred-temp')
if self.options.name:
Copy link

Choose a reason for hiding this comment

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

Sounds good to me.

@@ -66,7 +67,14 @@ def _create_ping_inventory(profile_ranges, profile_port, profile_auth_list,

string_header = copy(string_to_write)

for auth_item in profile_auth_list:
for cred_item in profile_auth_list:
auth_item = []
Copy link

Choose a reason for hiding this comment

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

Minor suggestion:

auth_item = [
    cred_item.get('id'),
    cred_item.get('name'),
    ... ]

@coveralls
Copy link

Coverage Status

Coverage increased (+11.5%) to 62.839% when pulling e24704d on issues/47-part1 into f95cbb8 on master.

2 similar comments
@coveralls
Copy link

Coverage Status

Coverage increased (+11.5%) to 62.839% when pulling e24704d on issues/47-part1 into f95cbb8 on master.

@coveralls
Copy link

Coverage Status

Coverage increased (+11.5%) to 62.839% when pulling e24704d on issues/47-part1 into f95cbb8 on master.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants