Skip to content

Commit 767cb76

Browse files
andrewkrugjoelferrier
authored andcommitted
Bug/17 scan keys unavailable (#19)
* move repository uri default location to central decouple config * add exception for key metadata missing * remove future deprecated scan keys call and replace with metadata from s3 * add decoupled and pin version of gnupg to best likely supported version * pin version of gnupg in setup.py * add decouple settings file * update docs to include instructions to add key json
1 parent 0ab1a5a commit 767cb76

File tree

7 files changed

+70
-18
lines changed

7 files changed

+70
-18
lines changed

docs/architecture.rst

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,21 @@ Metadata files have been introduced to remove s3 hosting as a requirement for re
2828
The new repository structure introduces several new requirements.
2929

3030
1. **Optional** The public portion of the GPG used for signing modules and metadata should present at the root of the repository with the filename ``REPO_SIGNING_KEY.asc``. If the signing key is not present the ``--gpg-no-verify`` flag must be used with Margarita Shotgun.
31-
2. **Required** A folder must exist in at the path ``/repodata`` which contains the following files.
31+
2. **Optional** A JSON file with key metadata including the key fingerprint. REPO_SIGNING_KEY.json.
32+
Example:
33+
```
34+
{
35+
"uids": ["Lime Signing Key (Threat Response Official Lime Signing Key) <security@threatresponse.cloud>"],
36+
"fingerprint": "80DA92CB09161F241C8F9BC918BA980367172B17"
37+
}
38+
```
39+
3. **Required** A folder must exist in at the path ``/repodata`` which contains the following files.
3240

3341
1. **Required** ``repomd.xml`` contains repository metadata including one or more manifests of kernel modules.
3442
2. **Optional** ``repomd.xml.sig`` detached signature for ``repomd.xml``. If not present in the repository the ``--gpg-no-verify`` flag must be used with Margarita Shotgun.
3543
3. **Optional** Manifest files. Techinally manifests can be stored at any relative path but it is recommended that they be stored in the ``repodata`` directory.
3644

37-
3. **Optional** A ``modules`` directory is recommended which will contain the following files. Note the following files can have any location relative to the repository root, the ``modules`` directory is simply best practice.
45+
4. **Optional** A ``modules`` directory is recommended which will contain the following files. Note the following files can have any location relative to the repository root, the ``modules`` directory is simply best practice.
3846

3947
1. **Required** Compiled lime kernel modules. Module filenames are arbitrary as the files are explicitly listed in a manifest
4048
2. **Optional** Detached kernel module signatures. If signatures are not present the ``--gpg-no-verify`` flag must be used with Margarita Shotgun. The signature filename is arbitary as it is explicitly listed in a manifest.
@@ -44,6 +52,7 @@ Below is an example directory listing of the repository structure.
4452
.. code-block:: text
4553
4654
├── REPO_SIGNING_KEY.asc
55+
├── REPO_SIGNING_KEY.json
4756
├── modules
4857
│ ├── lime-2.6.32-131.0.15.el6.centos.plus.x86_64.ko
4958
│ ├── lime-2.6.32-131.0.15.el6.centos.plus.x86_64.ko.sig

margaritashotgun/cli.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from yaml import YAMLError
77
from margaritashotgun import __version__
88
from margaritashotgun.exceptions import *
9-
9+
from margaritashotgun.settings import *
1010
logger = logging.getLogger(__name__)
1111

1212
default_allowed_keys = ["aws", "hosts", "workers", "logging", "repository"]
@@ -28,7 +28,7 @@
2828
"prefix": None},
2929
"repository": {
3030
"enabled": False,
31-
"url": "https://threatresponse-lime-modules.s3.amazonaws.com/",
31+
"url": REPOSITORY_BUCKET_URI,
3232
"gpg_verify": True,
3333
"manifest": "primary"
3434
}}

margaritashotgun/exceptions.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,18 @@ def __init__(self, url):
8888
)
8989
MargaritaShotgunError.__init__(self, msg)
9090

91+
class RepositoryMissingKeyMetadataError(MargaritaShotgunError):
92+
"""
93+
Raised when signing public key is missing from repository
94+
"""
95+
def __init__(self, url):
96+
msg = (
97+
"Repository missing a key metadata file with signature "
98+
"at {0}, contact the repository maintainer or disable "
99+
"gpg verification with --gpg-no-verify".format(url)
100+
)
101+
MargaritaShotgunError.__init__(self, msg)
102+
91103
class RepositoryMissingSignatureError(MargaritaShotgunError):
92104
"""
93105
Raised when a detached signature is missing in remote repository"

margaritashotgun/repository.py

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,18 @@
11
import gnupg
22
import gzip
33
import hashlib
4+
import json
45
import logging
56
import os
67
import requests
78
import time
89
import xmltodict
10+
911
from datetime import datetime
1012
from io import BytesIO
1113
from margaritashotgun.exceptions import *
1214
from prompt_toolkit import prompt
15+
from margaritashotgun.settings import *
1316

1417
logger = logging.getLogger(__name__)
1518

@@ -31,7 +34,8 @@ def __init__(self, url, gpg_verify):
3134
self.gpg_verify = gpg_verify
3235
self.metadata_dir = 'repodata'
3336
self.metadata_file = 'repomd.xml'
34-
self.repo_signing_key = 'REPO_SIGNING_KEY.asc'
37+
self.repo_signing_key = PUBLIC_SIGNING_KEY_FILE
38+
self.key_metadata = PUBLIC_SIGNING_KEY_METADATA
3539

3640
self.gpg = None
3741
self.key_path = None
@@ -52,23 +56,43 @@ def init_gpg(self):
5256

5357
def get_signing_key(self):
5458
"""
55-
Download a local copy of repo signing key and generate key metadata
59+
Download a local copy of repo signing key for installation
60+
"""
61+
62+
"""
63+
Download a local copy of repo signing key key metadata.
64+
Fixes #17 Scan Keys no available in all GPG versions.
5665
"""
57-
tmp_path = "/tmp/{0}".format(self.repo_signing_key)
66+
tmp_key_path = "/tmp/{0}".format(self.repo_signing_key)
67+
tmp_metadata_path = "/tmp/{0}".format(self.key_metadata)
68+
5869
repo_key_path = "{0}/{1}".format(self.url, self.repo_signing_key)
59-
req = requests.get(repo_key_path)
60-
if req.status_code is 200:
70+
repo_metadata_path = "{0}/{1}".format(self.url, self.key_metadata)
71+
72+
73+
req_key = requests.get(repo_key_path)
74+
req_metadata = requests.get(repo_metadata_path)
75+
76+
# Fetch the key to disk
77+
if req_key.status_code is 200:
6178
logger.debug(("found repository signing key at "
62-
"{0}".format(repo_key_path)))
63-
self.raw_key = req.content
64-
with open(tmp_path, 'wb') as f:
79+
"{0}".format(repo_key_path)))
80+
self.raw_key = req_key.content
81+
with open(tmp_key_path, 'wb') as f:
6582
f.write(self.raw_key)
66-
key_info = self.gpg.scan_keys(tmp_path)
67-
# we only scan one key, return a single key_info
68-
key_info = key_info[0]
6983
else:
7084
raise RepositoryMissingSigningKeyError(repo_key_path)
71-
return (tmp_path, key_info)
85+
86+
# Fetch the fingerprint from the metadata
87+
if req_metadata.status_code is 200:
88+
logger.debug(("found key metadata at "
89+
"{0}".format(repo_metadata_path)))
90+
print(req_metadata.content)
91+
key_info = json.loads(req_metadata.content.decode('utf-8'))
92+
else:
93+
RepositoryMissingKeyMetadataError
94+
95+
return (tmp_key_path, key_info)
7296

7397
def check_signing_key(self):
7498
"""

margaritashotgun/settings.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
from decouple import config
2+
3+
REPOSITORY_BUCKET_URI = 'https://threatresponse-lime-modules.s3.amazonaws.com/'
4+
PUBLIC_SIGNING_KEY_FILE = 'REPO_SIGNING_KEY.asc'
5+
PUBLIC_SIGNING_KEY_METADATA = 'REPO_SIGNING_KEY.json'

requirements.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,6 @@ enum34
1010
requests
1111
xmltodict
1212
logutils
13-
python-gnupg
13+
python-gnupg==0.3.9
1414
prompt_toolkit
15+
python-decouple

setup.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ def run(self):
2020
download_url="https://github.com/ThreatResponse/margaritashotgun/archive/v0.4.0.tar.gz",
2121
use_2to3=True,
2222
install_requires=['boto3>=1.3.0',
23+
'python-decouple',
2324
'paramiko>=1.16.0',
2425
'pyyaml>=3.11',
2526
's3fs>=0.0.2',
@@ -28,7 +29,7 @@ def run(self):
2829
'requests',
2930
'xmltodict',
3031
'logutils==0.3.3',
31-
'python-gnupg',
32+
'python-gnupg==0.3.9',
3233
'prompt_toolkit'],
3334
tests_require=['pytest',
3435
'pytest-cov',

0 commit comments

Comments
 (0)