Skip to content

Commit

Permalink
Merge branch 'release/23.4.2'
Browse files Browse the repository at this point in the history
  • Loading branch information
davedittrich committed Apr 20, 2023
2 parents 013c503 + 1d67c64 commit 260677f
Show file tree
Hide file tree
Showing 16 changed files with 89 additions and 65 deletions.
10 changes: 5 additions & 5 deletions .github/workflows/test-build-publish.yml
Expand Up @@ -16,7 +16,7 @@ jobs:
env:
HEAD_COMMIT: ${{ toJson(github.event.head_commit) }}
- name: Check out src from GitHub
uses: actions/checkout@v2
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Set up Python
Expand Down Expand Up @@ -117,8 +117,8 @@ jobs:
repository_url: https://test.pypi.org/legacy/
user: __token__
password: ${{ secrets.PSEC_TEST_PYPI_PASSWORD }}
packages_dir: ${{ steps.get_vars.outputs.ARTIFACT }}
verify_metadata: false
packages-dir: ${{ steps.get_vars.outputs.ARTIFACT }}
verify-metadata: false
- name: Publish tagged artifacts to PyPI
if: >-
github.event_name == 'push' &&
Expand All @@ -128,7 +128,7 @@ jobs:
with:
user: __token__
password: ${{ secrets.PSEC_PYPI_PASSWORD }}
packages_dir: ${{ steps.get_vars.outputs.ARTIFACT }}
verify_metadata: false
packages-dir: ${{ steps.get_vars.outputs.ARTIFACT }}
verify-metadata: false
# ![2-test-build-publish]

15 changes: 15 additions & 0 deletions HISTORY.rst
Expand Up @@ -24,6 +24,21 @@ History
.. Fixed for any bug fixes.
.. Security in case of vulnerabilities.
23.4.2 (2023-04-20)
~~~~~~~~~~~~~~~~~~~

Added
^^^^^

- Added bats test for `secrets find` command.

Changed
^^^^^^^

- Switched to using f-strings for formatting.
- Fixed broken bats tests.
- Update GitHub Actions workflows.

23.4.1 (2023-04-19)
~~~~~~~~~~~~~~~~~~~

Expand Down
4 changes: 2 additions & 2 deletions README.rst
Expand Up @@ -17,7 +17,7 @@ Python command line app for managing groups of secrets (passwords, API keys, etc
other project variables. Reduces security risks from things like weak default passwords,
secrets stored in files in the source code repository directory.

Version: 23.4.1
Version: 23.4.2

* Free software: `Apache 2.0 License <https://www.apache.org/licenses/LICENSE-2.0>`_
* Documentation: https://python_secrets.readthedocs.org.
Expand Down Expand Up @@ -1218,7 +1218,7 @@ Decrypted, it looks like this:
myapp_app_password=brunt.outclass.alike.turbine
--
Sent using psec version 23.4.1
Sent using psec version 23.4.2
https://pypi.org/project/python-secrets/
https://github.com/davedittrich/python_secrets
Expand Down
2 changes: 1 addition & 1 deletion VERSION
@@ -1 +1 @@
23.4.1
23.4.2
2 changes: 1 addition & 1 deletion psec/__init__.py
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-

__version__ = None
__release__ = '23.4.1'
__release__ = '23.4.2'

# Get development version from repository tags.
try:
Expand Down
7 changes: 4 additions & 3 deletions psec/__main__.py
Expand Up @@ -72,10 +72,11 @@ def __init__(self):
self.logger = self.LOG
self.secret_factory = SecretFactory()

def build_option_parser(self, description, version):
def build_option_parser(self, description, version, argparse_kwargs=None):
parser = super().build_option_parser(
description,
version
version,
argparse_kwargs,
)
# OCD hack: Make ``help`` output report main program name,
# even if run as ``python -m psec.main`` or such.
Expand Down Expand Up @@ -296,7 +297,7 @@ def clean_up(self, cmd, result, err):
):
self.timer.stop()
elapsed = self.timer.elapsed()
self.stderr.write('[+] elapsed time {}\n'.format(elapsed))
self.stderr.write(f'[+] elapsed time {elapsed}\n')
bell()


Expand Down
38 changes: 19 additions & 19 deletions psec/cli/ssh.py
Expand Up @@ -7,6 +7,7 @@
import os
import pexpect
import re
import shlex
import socket
import sys
import tempfile
Expand Down Expand Up @@ -174,18 +175,18 @@ def _write_fingerprints_pubkeys_to_files(hostdict=None,
dir = os.path.join(known_hosts_root, 'fingerprints', host)
os.makedirs(dir, exist_ok=True)
ktype = _get_type(fingerprint)
fp_file = os.path.join(dir, '{}.fingerprint'.format(ktype))
fp_file = os.path.join(dir, f'{ktype}.fingerprint')
with open(fp_file, 'w') as f:
f.write('{}\n'.format(fingerprint))
f.write(f'{fingerprint}\n')
logger.debug("[+] wrote fingerprint to '%s'", fp_file)

for hostkey in v['hostkey']:
dir = os.path.join(known_hosts_root, 'known_hosts', host)
os.makedirs(dir, exist_ok=True)
ktype = _get_type(hostkey)
hk_file = os.path.join(dir, '{}.known_hosts'.format(ktype))
hk_file = os.path.join(dir, f'{ktype}.known_hosts')
with open(hk_file, 'w') as f:
f.write('{}\n'.format(hostkey))
f.write(f'{hostkey}\n')
logger.debug("[+] wrote hostkey to '%s'", hk_file)
pass

Expand All @@ -197,7 +198,7 @@ def _ansible_verbose(verbose_level=1):
"""
flag = ''
if verbose_level > 1:
flag = '-{}'.format("v" * (verbose_level - 1))
flag = f'-{"v" * (verbose_level - 1)}'
return flag


Expand All @@ -216,7 +217,7 @@ def _ansible_set_hostkeys(hostkeys, # nosec
cmd = ['ansible-playbook',
ask_become_pass,
_ansible_verbose(verbose_level),
'-e', "'{}'".format(hostkeys),
'-e', f"'{hostkeys}'",
playbook.name
]
ansible = pexpect.spawnu(
Expand Down Expand Up @@ -244,7 +245,7 @@ def _ansible_remove_hostkeys(hostkeys, # nosec
cmd = ['ansible-playbook',
ask_become_pass,
_ansible_verbose(verbose_level),
'-e', "'{}'".format(ssh_hosts),
'-e', f"'{ssh_hosts}'",
'-e', 'remove_keys=true',
playbook.name,
]
Expand All @@ -261,7 +262,7 @@ def _ansible_remove_hostkeys(hostkeys, # nosec
def _ansible_debug(hostkeys):
"""Debug Ansible"""
cmd = ['ansible',
'-e', "'{}'".format(hostkeys),
'-e', f"'{hostkeys}'",
'-m', 'debug',
'-a', 'var=vars',
'all'
Expand Down Expand Up @@ -434,7 +435,7 @@ def __init__(self,
for host, info in self.host_info.items():
for item in ['public_dns', 'public_ip']:
for key in info['full_hostkey']:
pubkey = "{} {}".format(info[item], key)
pubkey = f"{info[item]} {key}"
if host not in self.hostdict:
self.hostdict[host] = dict()
try:
Expand Down Expand Up @@ -610,8 +611,7 @@ def extract_keys(self, console_output=[], short_name=None):
_host = line.split(' Host: ')[1]
if _host != "":
public_ip = _host
public_dns = '{}.{}'.format(short_name,
self.domain)
public_dns = f'{short_name}.{self.domain}'
if short_name not in self.hostdict:
self.hostdict[short_name] = dict()
self.hostdict[short_name]['public_ip'] = public_ip # noqa
Expand Down Expand Up @@ -654,11 +654,11 @@ def extract_keys(self, console_output=[], short_name=None):
# TODO(dittrich): Should use regex instead.
fields = line.split(' ')
# 'digitalocean_droplet.red (remote-exec): ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIA69uuX+ItFoAAe+xE9c+XggGw7Z2Z7t3YVRJxSHMupv root@debian.example.com' # noqa
hostid = "{},{}".format(public_dns, public_ip)
hostid = f"{public_dns},{public_ip}"
if fields[1] == '(remote-exec):':
pubkey = "{} {} {}".format(hostid, fields[2], fields[3])
pubkey = f"{hostid} {fields[2]} {fields[3]}"
else:
pubkey = "{} {} {}".format(hostid, fields[0], fields[1])
pubkey = f"{hostid} {fields[0]} {fields[1]}"
try:
self.hostdict[short_name]['hostkey'].extend([pubkey])
except KeyError:
Expand Down Expand Up @@ -686,9 +686,9 @@ def get_hostkey_list_as_json(self):
raise RuntimeError('[-] no host IP or name found or specified')
for key in self.hostkey:
if self.public_ip is not None:
keylist.append("{} {}".format(self.public_ip, key))
keylist.append(f"{self.public_ip} {key}")
if self.public_dns is not None:
keylist.append("{} {}".format(self.public_dns, key))
keylist.append(f"{self.public_dns} {key}")
return json.dumps({'ssh_host_public_keys': keylist})

def get_hostkey_list(self):
Expand Down Expand Up @@ -778,7 +778,7 @@ def take_action(self, parsed_args):
# se.get_secret('aws_privatekey_path')
home = os.path.expanduser('~')
ssh_config = os.path.join(home, '.ssh', 'config')
snippet_prefix = 'psec.{}'.format(se._environment)
snippet_prefix = f'psec.{se._environment}'
if parsed_args.clean:
files = glob.glob(os.path.join(ssh_config + '.d',
snippet_prefix + ".*"))
Expand All @@ -791,7 +791,7 @@ def take_action(self, parsed_args):
if private_key_file is None:
raise RuntimeError('[-] no SSH private key specified')
for host, info in host_info.items():
snippet = 'psec.{}.{}'.format(se._environment, host)
snippet = f'psec.{se._environment}.{host}'
if parsed_args.show_config:
# TODO(dittrich): finish this...
print()
Expand All @@ -806,7 +806,7 @@ def take_action(self, parsed_args):
)

output, exitstatus = pexpect.runu(
'update-dotdee {}'.format(ssh_config),
f"update-dotdee {shlex.quote(ssh_config)}",
withexitstatus=1)
if exitstatus == 0:
if self.app_args.verbose_level >= 1:
Expand Down
7 changes: 4 additions & 3 deletions psec/cli/utils/tfbackend.py
Expand Up @@ -47,13 +47,14 @@ def take_action(self, parsed_args):
tmpdir = e.get_tmpdir_path()
backend_file = os.path.join(os.getcwd(), 'tfbackend.tf')
tfstate_file = os.path.join(tmpdir, 'terraform.tfstate')
backend_text = textwrap.dedent("""\
terraform {{
backend_text = textwrap.dedent(
f"""terraform {{
backend "local" {{
path = "{tfstate_file}"
}}
}}
""".format(tfstate_file=tfstate_file))
"""
)

if parsed_args.path:
self.logger.debug('[+] showing terraform state file path')
Expand Down
6 changes: 3 additions & 3 deletions psec/cli/utils/tfoutput.py
Expand Up @@ -112,14 +112,14 @@ def take_action(self, parsed_args):
self.logger.info(
' '.join(['/usr/local/bin/terraform',
'output',
'-state={}'.format(tfstate),
f'-state={tfstate}',
'-json'])
)
p = subprocess.Popen(
[
'/usr/local/bin/terraform',
'output',
'-state={}'.format(shlex.quote(tfstate)),
f'-state={shlex.quote(tfstate)}',
'-json'
],
env=dict(os.environ),
Expand All @@ -131,7 +131,7 @@ def take_action(self, parsed_args):
dout = json.loads(jout.decode('UTF-8'))
for prefix in dout.keys():
for k, v in dout[prefix]['value'].items():
data.append(["{}_{}".format(prefix, k), v])
data.append([f"{prefix}_{k}", v])
return columns, data


Expand Down
8 changes: 4 additions & 4 deletions psec/google_oauth2.py
Expand Up @@ -145,7 +145,7 @@ def command_to_url(self, command):
"""
Produce an URL for a given command.
"""
return '{}/{}'.format(self.GOOGLE_ACCOUNTS_BASE_URL, command)
return f'{self.GOOGLE_ACCOUNTS_BASE_URL}/{command}'

def url_escape(self, text):
"""
Expand All @@ -165,9 +165,9 @@ def url_format_params(self, params):
"""
param_fragments = []
for param in sorted(params.items(), key=lambda x: x[0]):
param_fragments.append('{}={}'.format(
param[0], self.url_escape(param[1])
))
param_fragments.append(
f'{param[0]}={self.url_escape(param[1])}'
)
return '&'.join(param_fragments)

def generate_permission_url(
Expand Down
6 changes: 3 additions & 3 deletions psec/secrets_environment/__init__.py
Expand Up @@ -267,9 +267,9 @@ def get_environment_path(self, env=None, subdir=None, host=None):
_path = self.get_secrets_basedir() / str(env)
if not (subdir is None and host is None):
valid_subdir = r'a-zA-Z0-9_/'
invalid_subdir = re.compile('[^{}]'.format(valid_subdir))
invalid_subdir = re.compile(f'[^{valid_subdir}]')
valid_host = r'a-zA-Z0-9_\./' # noqa
invalid_host = re.compile('[^{}]'.format(valid_host))
invalid_host = re.compile(f'[^{valid_host}]')
if subdir is None and host is not None:
raise RuntimeError(
'[-] Must specify subdir when specifying host')
Expand Down Expand Up @@ -462,7 +462,7 @@ def _set_secret(self, secret, value):
_env_var = self.get_secret_export(secret)
if _env_var is None:
if self.env_var_prefix is not None:
_env_var = '{}{}'.format(self.env_var_prefix, secret)
_env_var = f'{self.env_var_prefix}{secret}'
else:
_env_var = secret
if self.preserve_existing and bool(os.getenv(_env_var)):
Expand Down

0 comments on commit 260677f

Please sign in to comment.