Initial release

This commit is contained in:
Benjamin Renard 2023-07-07 12:31:07 +02:00
commit 87338a564a
5 changed files with 243 additions and 0 deletions

37
.pre-commit-config.yaml Normal file
View file

@ -0,0 +1,37 @@
# Pre-commit hooks to run tests and ensure code is cleaned.
# See https://pre-commit.com for more information
repos:
- repo: https://github.com/asottile/pyupgrade
rev: v3.3.1
hooks:
- id: pyupgrade
args: ['--keep-percent-format', '--py37-plus']
- repo: https://github.com/psf/black
rev: 22.12.0
hooks:
- id: black
args: ['--target-version', 'py37', '--line-length', '100']
- repo: https://github.com/PyCQA/isort
rev: 5.11.5
hooks:
- id: isort
args: ['--profile', 'black', '--line-length', '100']
- repo: https://github.com/PyCQA/flake8
rev: 6.0.0
hooks:
- id: flake8
args: ['--max-line-length=100']
- repo: local
hooks:
- id: pylint
name: pylint
entry: pylint --extension-pkg-whitelist=cx_Oracle
language: system
types: [python]
require_serial: true
- repo: https://github.com/Lucas-C/pre-commit-hooks-bandit
rev: v1.0.5
hooks:
- id: python-bandit-vulnerability-check
name: bandit
args: [--skip, "B101", --recursive, mylib]

7
.pylintrc Normal file
View file

@ -0,0 +1,7 @@
[MESSAGES CONTROL]
disable=invalid-name,
locally-disabled,
[FORMAT]
# Maximum number of characters on a single line.
max-line-length=100

57
README.md Normal file
View file

@ -0,0 +1,57 @@
# Migrate APT trusted keys
Script to handle migration of obsolete /etc/apt/trusted.gpg to split GPG
keyrings in /etc/apt/trusted.gpg.d.
Note: Useful to fix this type of APT error:
```
Key is stored in legacy trusted.gpg keyring (/etc/apt/trusted.gpg), see the DEPRECATION section in apt-key(8) for details.
```
## Installation
```bash
apt install python3 wget
wget -O /usr/local/sbin/migrate-apt-trusted-keys \
https://gitea.zionetrix.net/bn8/migrate-apt-trusted-keys/raw/branch/main/migrate-apt-trusted-keys
chmod 750 /usr/local/sbin/migrate-apt-trusted-keys
```
## Usage
```
usage: migrate-apt-trusted-keys [-h] [-p KEYRING_PATH] [-o OUTPUT_PATH] [-a]
[-f]
Script to manage the migration from the deprecated /etc/apt/trusted.gpg file
to splited GPG keyring in /etc/apt/trusted.gpg.d.
options:
-h, --help show this help message and exit
-p KEYRING_PATH, --keyring-path KEYRING_PATH
APT keyring file path.
-o OUTPUT_PATH, --output-path OUTPUT_PATH
Output directory path.
-a, --auto Migrate all GPG keys, without user interaction.
-f, --force Force mode: overwrite output file if already exists.
```
## Copyright
Copyright (c) 2023 Benjamin Renard <brenard@zionetrix.net>
## License
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License version 3
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

139
migrate-apt-trusted-keys Executable file
View file

@ -0,0 +1,139 @@
#!/usr/bin/env python3
#
# Script to handle migration of obsolete /etc/apt/trusted.gpg to split GPG
# keyrings in /etc/apt/trusted.gpg.d.
#
# Author : Benjamin Renard <brenard@zionetrix.net>
# Date : Fri, 07 Jul 2023 12:26:54 +0200
# Source : http://gitea.zionetrix.net/bn8/migrate-apt-trusted-keys
# Licence : GPL v3
#
"""
Script to handle migration of obsolete /etc/apt/trusted.gpg to split GPG
keyrings in /etc/apt/trusted.gpg.d.
"""
import argparse
import os
import re
import subprocess
import sys
import traceback
# Variables
raw_output = ""
# Args Parsing
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument(
"-p", "--keyring-path", help="APT keyring file path.", type=str, default="/etc/apt/trusted.gpg"
)
parser.add_argument(
"-o", "--output-path", help="Output directory path.", type=str, default="/etc/apt/trusted.gpg.d"
)
parser.add_argument(
"-a", "--auto", help="Migrate all GPG keys, without user interaction.", action="store_true"
)
parser.add_argument(
"-f",
"--force",
help="Force mode: overwrite output file if already exists.",
action="store_true",
)
args = parser.parse_args()
if not os.path.exists(args.keyring_path):
parser.error(f"APT keyring file {args.keyring_path} not found.")
if not os.path.isdir(args.output_path):
parser.error(f"Output directory {args.output_path} not found (or is not a directory).")
# Execute Command
process = subprocess.run(
args=["gpg", "--keyring", args.keyring_path, "--list-keys"], capture_output=True, check=True
)
if process.returncode > 0:
print("No fingerprints found!")
sys.exit()
raw_output = str(process.stdout.decode("utf-8"))
all_keys = []
current_key = None
key_id_line = re.compile("^ +([0-9A-F]+)$")
uid_line = re.compile("^uid +.*<[^@]+@([^>]+)>$")
for line in raw_output.split("\n")[2:]:
if not line:
continue
if line.startswith("pub") and current_key:
all_keys.append(current_key)
current_key = None
if current_key is None:
current_key = {"lines": [], "id": None, "domain": None}
current_key["lines"].append(line)
m = key_id_line.match(line)
if m:
current_key["id"] = m.group(1)
m = uid_line.match(line)
if m:
current_key["domain"] = m.group(1)
if current_key:
all_keys.append(current_key)
for key in all_keys:
if not args.auto:
print("\n\n")
print("\n".join(key["lines"]))
answer = input("Do you want to migrate this key [Y/n or q to exit]? ")
answer = answer.strip().lower()
if answer == 'q':
sys.exit()
if answer and answer != "y":
continue
print(f"Migrate key {key['id']}...")
name = "-".join(key["domain"].lower().split(".")[:-1]) if key["domain"] else key["id"]
name += ".gpg"
if not args.auto:
answer = input(f"Key name [{name}]? ")
name = answer.strip() if answer else name
output_path = os.path.join(args.output_path, name)
print(f"Export key {key['id']} to {output_path}...")
try:
if os.path.exists(output_path):
if not args.force:
if args.auto:
print(f"Outfile '{output_path}' already exists, pass")
continue
answer = input(f"Outfile '{output_path}' already exists, overwrite [y/N or q to exit]? ")
answer = answer.strip().lower()
if answer == 'q':
sys.exit()
if answer != "y":
continue
print(f"Remove existing output file '{output_path}'")
os.remove(output_path)
# pylint: disable=consider-using-with
export_cmd = subprocess.Popen(
("gpg", "--keyring", args.keyring_path, "--export", key["id"]), stdout=subprocess.PIPE
)
output_cmd = subprocess.check_output(
("gpg", "--dearmour", "-o", output_path), stdin=export_cmd.stdout
)
export_cmd.wait()
print(f"Key {key['id']} exported to {output_path}")
print()
except Exception: # pylint: disable=broad-exception-caught
print(f"Fail to export key {key['id']} to {output_path}")
traceback.print_exc()
# vim: tabstop=4 shiftwidth=4 softtabstop=4 expandtab

3
setup.cfg Normal file
View file

@ -0,0 +1,3 @@
[flake8]
ignore = E501,W503
max-line-length = 100