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

First stab at a re-write. #1

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
Open

First stab at a re-write. #1

wants to merge 9 commits into from

Conversation

drahamim
Copy link
Owner

No description provided.

@lrosenman
Copy link

Looks good, but I'm not a python language lawyer.

csrgen.py Outdated Show resolved Hide resolved
csrgen.py Outdated Show resolved Hide resolved
return str(args.domain + '_csr_config')


def main(args):

Choose a reason for hiding this comment

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

Seems to me like there's too much implementation logic in the main() function. I'd try to move a lot of this to functions and keep only business logic in main(). Maybe you could create one function for each args.command.

Choose a reason for hiding this comment

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

Choose a reason for hiding this comment

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

+1 to keeping main() down to a small set of function calls.

Choose a reason for hiding this comment

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

Also consider trapping the case where command is not in the expected set of commands. Don't really see where that is documented and/or output to the user.

Comment on lines +53 to +58
try:
os.stat(file).st_size > 1
except:
return False
else:
return file
Copy link

@danielhoherd danielhoherd May 19, 2022

Choose a reason for hiding this comment

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

Suggested change
try:
os.stat(file).st_size > 1
except:
return False
else:
return file
try:
return os.stat(file).st_size > 1 or file
except FileNotFoundError:
return False

Choose a reason for hiding this comment

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

Actually that may not be right. A docstring would be helpful to define the desired behavior. I think I misinterpreted it.

Copy link
Owner Author

Choose a reason for hiding this comment

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

This is suppoed to check that the file exists and is not empty.

try:
subprocess.call(['openssl', 'rsa', '-in',
args.key, '-check'])
except:

Choose a reason for hiding this comment

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

I think this should be, but I'm not 100% sure.

Suggested change
except:
except subprocess.CalledProcessError:

"""


def check_file(file):

Choose a reason for hiding this comment

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

The name check_file is ambiguous... what are you checking? Consider a name file_exists so your code reads more naturally, ex. if file_exists():

Choose a reason for hiding this comment

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

Aaaand I just realized this is already a library function: os.path.exists() for any path, pathlib.Path.is_file() for files in particular.

Choose a reason for hiding this comment

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

Also the file parameter is a bit ambiguous. Are you looking for a file_name with a string representation, a path-like object, an actual file object?

Can document in code by checking your parameter first thing in the code: if not isinstance(file, str): raise TypeError.

In general, good practice to check your parameters before using them, to make debugging easier.

except:
return False
else:
return file

Choose a reason for hiding this comment

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

I see two different types being returned by this function: bool False and str file.

Choose one and stick with it. Looks like you want bool here.

Copy link
Owner Author

Choose a reason for hiding this comment

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

If it returns true how does that affect argparse value?

return file


def check_domain(input):

Choose a reason for hiding this comment

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

Same comments as earlier:

  • what are you checking for? consider is_domain
  • what type is input?

Copy link
Owner Author

Choose a reason for hiding this comment

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

Two things. Check if it is a domain or if it is a file with domains. Maybe I should create 2 flags rather then combining them in one?

CN = domain.strip().lower()
domain = fp.readline()
count += 1
elif 1 <= count <= 100:

Choose a reason for hiding this comment

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

Suggest creating a named constant at the top of the file instead of burying 100 here, to make maintenance easier. ex. MAX_DOMAINS = 100

env = Environment(loader=file_loader)


description = """

Choose a reason for hiding this comment

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

PEP8 says constants should be named in all caps.

https://peps.python.org/pep-0008/#constants

Choose a reason for hiding this comment

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

NIT: mixed use of single-quote and double-quotes throughout this file.

def gen_csr_config(args, config_file):
tm = env.get_template(config_file)
print(config_file)
SANS = list()

Choose a reason for hiding this comment

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

All-caps variable names are generally used for constants. Suggest sans here.

https://peps.python.org/pep-0008/#constants

print(config_file)
SANS = list()
print("Generating CSR configuration..")
if type(args.domain) is tuple:

Choose a reason for hiding this comment

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

instanceof() is permissive of subclasses whereas type() is requires exact match. Consider using instanceof() in most cases.

if type(args.domain) is tuple:
domain_file, is_file = args.domain
with open(domain_file) as fp:
domain = fp.readline()

Choose a reason for hiding this comment

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

Suggest using for domain in fp: instead of this combo of readline() and a while-loop. Code ends up much simpler & easier to maintain.

if args.key:
if check_file(args.key):
try:
subprocess.call(['openssl', 'rsa', '-in',

Choose a reason for hiding this comment

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

Here and elsewhere: suggest checking & printing stderr and/or return code from any subprocess call / run. This allows you to debug why something fails much more easily.

def main(args):
if args.command == 'csr':
# Look for csrgen config files
config_file_search = fnmatch.filter(os.listdir(), "*_gen_config")

Choose a reason for hiding this comment

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

I see _gen_config in quite a few places. Consider replacing it with a named constant for maintainability.

if args.command == 'config':
tm = Template(config_template)
config_file_name = args.org + "_gen_config"
print("Creating config template file: {filename}".format(

Choose a reason for hiding this comment

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

NIT use an f-string instead of "".format()

ex. print(f"creating {config_file_name}")

config_file_name = args.org + "_gen_config"
print("Creating config template file: {filename}".format(
filename=config_file_name))
config_file = open(config_file_name, "w")

Choose a reason for hiding this comment

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

Prefer with open() as f: to calling open and close separately.

domain = args.domain
CN = domain.strip().lower()

generated_csr_config = open(args.domain + '_csr_config', 'w')

Choose a reason for hiding this comment

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

Prefer with open() as f: to calling open and close separately.

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

Successfully merging this pull request may close these issues.

4 participants