Add CLI usage for pki.py and update Makefile (#254)

* Add CLI usage for pki.py

* Bump to 2.1.0

* Replace direct openssl invocation with pki utility

* Bolder

* Ordering and version in README

* Refine help
This commit is contained in:
Abhinav Singh 2020-01-06 19:51:18 -08:00 committed by GitHub
parent 067664e6ed
commit ac29e34137
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 138 additions and 22 deletions

1
.gitignore vendored
View File

@ -18,6 +18,7 @@ proxy.py.iml
*.csr
*.crt
*.key
*.pem
venv*
cover

View File

@ -30,18 +30,31 @@ autopep8:
https-certificates:
# Generate server key
openssl genrsa -out $(HTTPS_KEY_FILE_PATH) 2048
python -m proxy.common.pki gen_private_key \
--private-key-path $(HTTPS_KEY_FILE_PATH)
python -m proxy.common.pki remove_passphrase \
--private-key-path $(HTTPS_KEY_FILE_PATH)
# Generate server certificate
openssl req -new -x509 -days 3650 -key $(HTTPS_KEY_FILE_PATH) -out $(HTTPS_CERT_FILE_PATH)
python -m proxy.common.pki gen_public_key \
--private-key-path $(HTTPS_KEY_FILE_PATH) \
--public-key-path $(HTTPS_CERT_FILE_PATH)
ca-certificates:
# Generate CA key
openssl genrsa -out $(CA_KEY_FILE_PATH) 2048
python -m proxy.common.pki gen_private_key \
--private-key-path $(CA_KEY_FILE_PATH)
python -m proxy.common.pki remove_passphrase \
--private-key-path $(CA_KEY_FILE_PATH)
# Generate CA certificate
openssl req -new -x509 -days 3650 -key $(CA_KEY_FILE_PATH) -out $(CA_CERT_FILE_PATH)
python -m proxy.common.pki gen_public_key \
--private-key-path $(CA_KEY_FILE_PATH) \
--public-key-path $(CA_CERT_FILE_PATH)
# Generate key that will be used to generate domain certificates on the fly
# Generated certificates are then signed with CA certificate / key generated above
openssl genrsa -out $(CA_SIGNING_KEY_FILE_PATH) 2048
python -m proxy.common.pki gen_private_key \
--private-key-path $(CA_SIGNING_KEY_FILE_PATH)
python -m proxy.common.pki remove_passphrase \
--private-key-path $(CA_SIGNING_KEY_FILE_PATH)
lib-clean:
find . -name '*.pyc' -exec rm -f {} +

View File

@ -88,9 +88,9 @@ Table of Contents
* [Http](#http-client)
* [build_http_request](#build_http_request)
* [build_http_response](#build_http_response)
* [Websocket](#websocket)
* [WebsocketFrame](#websocketframe)
* [WebsocketClient](#websocketclient)
* [Public Key Infrastructure](#pki)
* [API Usage](#api-usage)
* [CLI Usage](#cli-usage)
* [Frequently Asked Questions](#frequently-asked-questions)
* [SyntaxError: invalid syntax](#syntaxerror-invalid-syntax)
* [Unable to load plugins](#unable-to-load-plugins)
@ -1161,7 +1161,7 @@ Utilities
## TCP Sockets
#### new_socket_connection
### new_socket_connection
Attempts to create an IPv4 connection, then IPv6 and
finally a dual stack connection to provided address.
@ -1172,7 +1172,7 @@ finally a dual stack connection to provided address.
>>> conn.close()
```
#### socket_connection
### socket_connection
`socket_connection` is a convenient decorator + context manager
around `new_socket_connection` which ensures `conn.close` is implicit.
@ -1194,9 +1194,9 @@ As a decorator:
## Http Client
#### build_http_request
### build_http_request
##### Generate HTTP GET request
#### Generate HTTP GET request
```python
>>> build_http_request(b'GET', b'/')
@ -1204,7 +1204,7 @@ b'GET / HTTP/1.1\r\n\r\n'
>>>
```
##### Generate HTTP GET request with headers
#### Generate HTTP GET request with headers
```python
>>> build_http_request(b'GET', b'/',
@ -1213,7 +1213,7 @@ b'GET / HTTP/1.1\r\nConnection: close\r\n\r\n'
>>>
```
##### Generate HTTP POST request with headers and body
#### Generate HTTP POST request with headers and body
```python
>>> import json
@ -1223,19 +1223,53 @@ b'GET / HTTP/1.1\r\nConnection: close\r\n\r\n'
b'POST /form HTTP/1.1\r\nContent-type: application/json\r\n\r\n{"email": "hello@world.com"}'
```
#### build_http_response
### build_http_response
TODO
## Websocket
## PKI
#### WebsocketFrame
### API Usage
TODO
#### gen_private_key
#### gen_public_key
#### remove_passphrase
#### gen_csr
#### sign_csr
#### WebsocketClient
See [pki.py](https://github.com/abhinavsingh/proxy.py/blob/develop/proxy/common/pki.py) are
method definitions.
TODO
### CLI Usage
Use `proxy.common.pki` module for:
1) Generation of public and private keys
2) Generating CSR requests
3) Signing CSR requests using custom CA.
```bash
python -m proxy.common.pki -h
usage: pki.py [-h] [--password PASSWORD] [--private-key-path PRIVATE_KEY_PATH]
[--public-key-path PUBLIC_KEY_PATH] [--subject SUBJECT]
action
proxy.py v2.1.0 : PKI Utility
positional arguments:
action Valid actions: remove_passphrase, gen_private_key,
gen_public_key, gen_csr, sign_csr
optional arguments:
-h, --help show this help message and exit
--password PASSWORD Password to use for encryption. Default: proxy.py
--private-key-path PRIVATE_KEY_PATH
Private key path
--public-key-path PUBLIC_KEY_PATH
Public key path
--subject SUBJECT Subject to use for public key generation. Default:
/CN=example.com
```
## Internal Documentation
@ -1377,7 +1411,7 @@ usage: proxy [-h] [--backlog BACKLOG] [--basic-auth BASIC_AUTH]
[--static-server-dir STATIC_SERVER_DIR] [--threadless]
[--timeout TIMEOUT] [--version]
proxy.py v2.0.0
proxy.py v2.1.0
optional arguments:
-h, --help show this help message and exit

View File

@ -8,6 +8,8 @@
:copyright: (c) 2013-present by Abhinav Singh and contributors.
:license: BSD, see LICENSE for more details.
"""
import sys
import argparse
import contextlib
import os
import uuid
@ -18,6 +20,7 @@ from typing import List, Generator, Optional, Tuple
from .utils import bytes_
from .constants import COMMA
from .version import __version__
logger = logging.getLogger(__name__)
@ -212,3 +215,68 @@ def run_openssl_command(command: List[str], timeout: int) -> bool:
)
cmd.communicate(timeout=timeout)
return cmd.returncode == 0
if __name__ == '__main__':
available_actions = (
'remove_passphrase', 'gen_private_key', 'gen_public_key',
'gen_csr', 'sign_csr'
)
parser = argparse.ArgumentParser(
description='proxy.py v%s : PKI Utility' % __version__,
)
parser.add_argument(
'action',
type=str,
default=None,
help='Valid actions: ' + ', '.join(available_actions)
)
parser.add_argument(
'--password',
type=str,
default='proxy.py',
help='Password to use for encryption. Default: proxy.py',
)
parser.add_argument(
'--private-key-path',
type=str,
default=None,
help='Private key path',
)
parser.add_argument(
'--public-key-path',
type=str,
default=None,
help='Public key path',
)
parser.add_argument(
'--subject',
type=str,
default='/CN=example.com',
help='Subject to use for public key generation. Default: /CN=example.com',
)
args = parser.parse_args(sys.argv[1:])
# Validation
if args.action not in available_actions:
print('Invalid --action. Valid values ' + ', '.join(available_actions))
sys.exit(1)
if args.action in ('gen_private_key', 'gen_public_key'):
if args.private_key_path is None:
print('--private-key-path is required for ' + args.action)
sys.exit(1)
if args.action == 'gen_public_key':
if args.public_key_path is None:
print('--public-key-file is required for private key generation')
sys.exit(1)
# Execute
if args.action == 'gen_private_key':
gen_private_key(args.private_key_path, args.password)
elif args.action == 'gen_public_key':
gen_public_key(args.public_key_path, args.private_key_path,
args.password, args.subject)
elif args.action == 'remove_passphrase':
remove_passphrase(args.private_key_path, args.password,
args.private_key_path)

View File

@ -8,5 +8,5 @@
:copyright: (c) 2013-present by Abhinav Singh and contributors.
:license: BSD, see LICENSE for more details.
"""
VERSION = (2, 0, 0)
VERSION = (2, 1, 0)
__version__ = '.'.join(map(str, VERSION[0:3]))