mirror of
https://github.com/PurpleI2P/pyseeder
synced 2025-01-30 16:44:16 +00:00
Merge pull request #4 from l-n-s/devel
Added --no-encryption option and github transport
This commit is contained in:
commit
e54a17fbbe
18
pyseeder.py
18
pyseeder.py
@ -2,13 +2,20 @@
|
|||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import argparse
|
import argparse
|
||||||
|
import logging
|
||||||
|
|
||||||
import pyseeder.transport
|
import pyseeder.transport
|
||||||
import pyseeder.actions
|
import pyseeder.actions
|
||||||
from pyseeder.utils import PyseederException
|
from pyseeder.utils import PyseederException
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
parser = argparse.ArgumentParser()
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument('--loglevel', default=logging.INFO, help="Log level",
|
||||||
|
choices=[logging.CRITICAL, logging.ERROR, logging.WARNING,
|
||||||
|
logging.INFO, logging.DEBUG])
|
||||||
|
|
||||||
subparsers = parser.add_subparsers(title="actions",
|
subparsers = parser.add_subparsers(title="actions",
|
||||||
help="Command to execute")
|
help="Command to execute")
|
||||||
|
|
||||||
@ -25,6 +32,8 @@ def main():
|
|||||||
help="RSA private key (default: data/priv_key.pem)")
|
help="RSA private key (default: data/priv_key.pem)")
|
||||||
kg_parser.add_argument("--cert", default=None,
|
kg_parser.add_argument("--cert", default=None,
|
||||||
help="Certificate (example: data/user_at_mail.i2p.crt)")
|
help="Certificate (example: data/user_at_mail.i2p.crt)")
|
||||||
|
kg_parser.add_argument("--no-encryption", action="store_true",
|
||||||
|
help="Disable private key encryption")
|
||||||
kg_parser.set_defaults(func=pyseeder.actions.keygen)
|
kg_parser.set_defaults(func=pyseeder.actions.keygen)
|
||||||
|
|
||||||
|
|
||||||
@ -44,6 +53,8 @@ echo $YOUR_PASSWORD | %(prog)s --netdb /path/to/netDb \\
|
|||||||
help="Output file (default: output/i2pseeds.su3)")
|
help="Output file (default: output/i2pseeds.su3)")
|
||||||
rs_parser.add_argument("--netdb", required=True,
|
rs_parser.add_argument("--netdb", required=True,
|
||||||
help="Path to netDb folder (example: ~/.i2pd/netDb)")
|
help="Path to netDb folder (example: ~/.i2pd/netDb)")
|
||||||
|
rs_parser.add_argument("--no-encryption", action="store_true",
|
||||||
|
help="Disable private key encryption")
|
||||||
rs_parser.set_defaults(func=pyseeder.actions.reseed)
|
rs_parser.set_defaults(func=pyseeder.actions.reseed)
|
||||||
|
|
||||||
|
|
||||||
@ -97,12 +108,17 @@ echo $YOUR_PASSWORD | %(prog)s --netdb /path/to/netDb \\
|
|||||||
help=".su3 file (default: output/i2pseeds.su3)")
|
help=".su3 file (default: output/i2pseeds.su3)")
|
||||||
serve_parser.set_defaults(func=pyseeder.actions.serve)
|
serve_parser.set_defaults(func=pyseeder.actions.serve)
|
||||||
|
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
logging.basicConfig(level=args.loglevel,
|
||||||
|
format='%(levelname)-8s %(message)s')
|
||||||
|
|
||||||
if hasattr(args, "func"):
|
if hasattr(args, "func"):
|
||||||
try:
|
try:
|
||||||
args.func(args)
|
args.func(args)
|
||||||
except PyseederException as pe:
|
except PyseederException as pe:
|
||||||
print("Pyseeder error: {}".format(pe))
|
log.critical("Pyseeder error: {}".format(pe))
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
else:
|
else:
|
||||||
parser.print_help()
|
parser.print_help()
|
||||||
|
@ -11,9 +11,14 @@ def keygen(args):
|
|||||||
for f in [args.cert, args.private_key]: check_writable(f)
|
for f in [args.cert, args.private_key]: check_writable(f)
|
||||||
|
|
||||||
from pyseeder.crypto import keygen
|
from pyseeder.crypto import keygen
|
||||||
from getpass import getpass
|
|
||||||
priv_key_password = getpass("Set private key password: ").encode("utf-8")
|
if args.no_encryption:
|
||||||
keygen(args.cert, args.private_key, priv_key_password, args.signer_id)
|
priv_key_password = None
|
||||||
|
else:
|
||||||
|
from getpass import getpass
|
||||||
|
priv_key_password = getpass("Set private key password: ").encode("utf-8")
|
||||||
|
|
||||||
|
keygen(args.cert, args.private_key, args.signer_id, priv_key_password)
|
||||||
|
|
||||||
def reseed(args):
|
def reseed(args):
|
||||||
"""Sub-command to generate reseed file"""
|
"""Sub-command to generate reseed file"""
|
||||||
@ -21,7 +26,12 @@ def reseed(args):
|
|||||||
for f in [args.netdb, args.private_key]: check_readable(f)
|
for f in [args.netdb, args.private_key]: check_readable(f)
|
||||||
|
|
||||||
from pyseeder.su3file import SU3File
|
from pyseeder.su3file import SU3File
|
||||||
priv_key_password = input().encode("utf-8")
|
|
||||||
|
if args.no_encryption:
|
||||||
|
priv_key_password = None
|
||||||
|
else:
|
||||||
|
priv_key_password = input().encode("utf-8")
|
||||||
|
|
||||||
su3file = SU3File(args.signer_id)
|
su3file = SU3File(args.signer_id)
|
||||||
su3file.reseed(args.netdb)
|
su3file.reseed(args.netdb)
|
||||||
su3file.write(args.outfile, args.private_key, priv_key_password)
|
su3file.write(args.outfile, args.private_key, priv_key_password)
|
||||||
|
@ -13,19 +13,23 @@ from cryptography.x509.oid import NameOID
|
|||||||
from cryptography.hazmat.primitives import hashes
|
from cryptography.hazmat.primitives import hashes
|
||||||
from cryptography.hazmat.primitives.asymmetric import padding
|
from cryptography.hazmat.primitives.asymmetric import padding
|
||||||
|
|
||||||
def keygen(pub_key, priv_key, priv_key_password, user_id):
|
def keygen(pub_key, priv_key, user_id, priv_key_password=None):
|
||||||
"""Generate new private key and certificate RSA_SHA512_4096"""
|
"""Generate new private key and certificate RSA_SHA512_4096"""
|
||||||
# Generate our key
|
# Generate our key
|
||||||
key = rsa.generate_private_key(public_exponent=65537, key_size=4096,
|
key = rsa.generate_private_key(public_exponent=65537, key_size=4096,
|
||||||
backend=default_backend())
|
backend=default_backend())
|
||||||
|
|
||||||
|
if priv_key_password:
|
||||||
|
ea = serialization.BestAvailableEncryption(priv_key_password)
|
||||||
|
else:
|
||||||
|
ea = serialization.NoEncryption()
|
||||||
|
|
||||||
# Write our key to disk for safe keeping
|
# Write our key to disk for safe keeping
|
||||||
with open(priv_key, "wb") as f:
|
with open(priv_key, "wb") as f:
|
||||||
f.write(key.private_bytes(
|
f.write(key.private_bytes(
|
||||||
encoding=serialization.Encoding.PEM,
|
encoding=serialization.Encoding.PEM,
|
||||||
format=serialization.PrivateFormat.TraditionalOpenSSL,
|
format=serialization.PrivateFormat.TraditionalOpenSSL,
|
||||||
encryption_algorithm=serialization.BestAvailableEncryption(
|
encryption_algorithm=ea,
|
||||||
priv_key_password),
|
|
||||||
))
|
))
|
||||||
|
|
||||||
# Various details about who we are. For a self-signed certificate the
|
# Various details about who we are. For a self-signed certificate the
|
||||||
@ -57,7 +61,7 @@ def keygen(pub_key, priv_key, priv_key_password, user_id):
|
|||||||
f.write(cert.public_bytes(serialization.Encoding.PEM))
|
f.write(cert.public_bytes(serialization.Encoding.PEM))
|
||||||
|
|
||||||
|
|
||||||
def append_signature(target_file, priv_key, priv_key_password):
|
def append_signature(target_file, priv_key, priv_key_password=None):
|
||||||
"""Append signature to the end of file"""
|
"""Append signature to the end of file"""
|
||||||
with open(target_file, "rb") as f:
|
with open(target_file, "rb") as f:
|
||||||
contents = f.read()
|
contents = f.read()
|
||||||
|
@ -25,7 +25,7 @@ class SU3File:
|
|||||||
self.VERSION = str(int(time.time())).encode("utf-8")
|
self.VERSION = str(int(time.time())).encode("utf-8")
|
||||||
#self.keytype = "RSA_SHA512_4096"
|
#self.keytype = "RSA_SHA512_4096"
|
||||||
|
|
||||||
def write(self, filename, priv_key, priv_key_password):
|
def write(self, filename, priv_key, priv_key_password=None):
|
||||||
"""Write file to disc"""
|
"""Write file to disc"""
|
||||||
nullbyte = bytes([0])
|
nullbyte = bytes([0])
|
||||||
with open(filename, "wb") as f:
|
with open(filename, "wb") as f:
|
||||||
|
@ -3,9 +3,11 @@ import urllib.request
|
|||||||
from urllib.error import URLError
|
from urllib.error import URLError
|
||||||
import os
|
import os
|
||||||
import importlib
|
import importlib
|
||||||
|
import logging
|
||||||
|
|
||||||
from pyseeder.utils import PyseederException
|
from pyseeder.utils import PyseederException, TransportException
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
RESEED_URLS = [
|
RESEED_URLS = [
|
||||||
"https://reseed.i2p-projekt.de/",
|
"https://reseed.i2p-projekt.de/",
|
||||||
@ -55,4 +57,6 @@ def upload(filename, config):
|
|||||||
except ImportError:
|
except ImportError:
|
||||||
raise PyseederException(
|
raise PyseederException(
|
||||||
"{} transport can't be loaded".format(t))
|
"{} transport can't be loaded".format(t))
|
||||||
|
except TransportException as e:
|
||||||
|
log.error("Transport error: {}".format(e))
|
||||||
|
|
||||||
|
49
pyseeder/transports/github.py
Normal file
49
pyseeder/transports/github.py
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# (re)uploads reseed file to github repository releases as an asset
|
||||||
|
import requests
|
||||||
|
|
||||||
|
from urllib.parse import urljoin
|
||||||
|
from mimetypes import guess_type
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
|
||||||
|
from pyseeder.utils import TransportException
|
||||||
|
|
||||||
|
TRANSPORT_NAME = "github"
|
||||||
|
|
||||||
|
def run(filename, config):
|
||||||
|
API_URL = "https://api.github.com/"
|
||||||
|
asset_name = os.path.split(filename)[-1]
|
||||||
|
content_type = guess_type(asset_name)[0] or "application/zip"
|
||||||
|
creds = (config["username"], config["token"])
|
||||||
|
release_info_url = urljoin(API_URL, "/repos/{}/releases/tags/{}".format(
|
||||||
|
config["repo"], config["release_tag"]))
|
||||||
|
|
||||||
|
# get release info
|
||||||
|
try:
|
||||||
|
resp = requests.get(release_info_url, auth=creds)
|
||||||
|
except:
|
||||||
|
raise TransportException("Failed to connect to GitHub API")
|
||||||
|
|
||||||
|
if resp.status_code is not 200:
|
||||||
|
raise TransportException("Check your GitHub API auth settings")
|
||||||
|
|
||||||
|
# delete old asset
|
||||||
|
for x in resp.json()["assets"]:
|
||||||
|
if x["name"] == asset_name:
|
||||||
|
r = requests.delete(x["url"], auth=creds)
|
||||||
|
if r.status_code is not 204:
|
||||||
|
raise TransportException("Failed to delete asset from GitHub")
|
||||||
|
|
||||||
|
# upload new asset
|
||||||
|
upload_url = resp.json()["upload_url"].split("{")[0] # wat
|
||||||
|
headers = {'Content-Type': content_type}
|
||||||
|
params = {'name': asset_name}
|
||||||
|
|
||||||
|
data = open(filename, 'rb').read()
|
||||||
|
r = requests.post(upload_url, headers=headers, params=params, auth=creds,
|
||||||
|
data=data)
|
||||||
|
|
||||||
|
if r.status_code is not 201:
|
||||||
|
raise TransportException("Failed to upload asset to GitHub API")
|
||||||
|
|
@ -1 +1,2 @@
|
|||||||
cryptography>=1.4
|
cryptography>=1.4
|
||||||
|
requests
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[transports]
|
[transports]
|
||||||
; enabled transports separated by space
|
; enabled transports separated by space
|
||||||
enabled=git
|
enabled=github
|
||||||
|
|
||||||
[git]
|
[git]
|
||||||
; Folder with git repository to use
|
; Folder with git repository to use
|
||||||
@ -8,3 +8,15 @@ folder=/home/user/reseed-data-repo
|
|||||||
|
|
||||||
[dropbox]
|
[dropbox]
|
||||||
; todo
|
; todo
|
||||||
|
|
||||||
|
[github]
|
||||||
|
; GitHub username
|
||||||
|
username=username
|
||||||
|
; GitHub API token
|
||||||
|
; Generate token for this script here --> https://github.com/settings/tokens
|
||||||
|
; Check scope: public_repo (shall be enough)
|
||||||
|
token=token
|
||||||
|
; Repository
|
||||||
|
repo=username/repo-name
|
||||||
|
; Repository tag to which asset is being uploaded
|
||||||
|
release_tag=v1.0
|
||||||
|
Loading…
x
Reference in New Issue
Block a user