Skip to content

Commit

Permalink
Merge branch 'devel' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
grindsa committed May 13, 2021
2 parents 1f3ba76 + 9693b02 commit 45f9d24
Show file tree
Hide file tree
Showing 33 changed files with 2,351 additions and 421 deletions.
3 changes: 3 additions & 0 deletions .github/.codecov.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
ignore:
- "examples/ca_handler/skeleton_ca_handler.py"
- "test" # wildcards accepted
2 changes: 1 addition & 1 deletion .github/wf_data/est_proxy_clientauth.cfg
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[ClientAuth]
[Daemon]
address = 0.0.0.0
port = 17443
key_file = /usr/local/est_proxy/data/certs/est-proxy.key.pem
Expand Down
2 changes: 2 additions & 0 deletions .github/wf_data/est_proxy_srp.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[SRP]
userdb = /usr/local/est_proxy/data/srp/est_proxy.db
4 changes: 4 additions & 0 deletions .github/wf_data/srp/est_proxy.db.bak
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
'--Reserved--type', (0, 8)
'user1', (512, 379)
'user2', (1024, 379)
'user3', (1536, 379)
Binary file added .github/wf_data/srp/est_proxy.db.dat
Binary file not shown.
4 changes: 4 additions & 0 deletions .github/wf_data/srp/est_proxy.db.dir
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
'--Reserved--type', (0, 8)
'user1', (512, 379)
'user2', (1024, 379)
'user3', (1536, 379)
30 changes: 30 additions & 0 deletions .github/workflows/codecov.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: Codecov
on:
push:
branches:
- 'main'
- 'devel'
jobs:
codecov:
name: Codecov Workflow
runs-on: ubuntu-18.04

steps:
- uses: actions/checkout@v1
- name: Set up Python
uses: actions/setup-python@master
with:
python-version: 3.8
- name: Generate coverage report
run: |
python -m pip install --upgrade pip
pip install pytest
pip install pytest-cov
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
pytest --cov=./ --cov-report=xml
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v1
with:
token: ${{ secrets.CODECOV_TOKEN }}
file: ./coverage.xml
flags: unittests
2 changes: 1 addition & 1 deletion .github/workflows/codeql-analysis.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name: "CodeQL"

on:
push:
# push:
pull_request:
branches: [ devel ]
schedule:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/est-globalsign.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ on:
- cron: '0 2 * * 6'

jobs:
est_proto_libest:
est_proto_globalsign:
name: "est_proto_gsign"
runs-on: ubuntu-latest
steps:
Expand Down
22 changes: 22 additions & 0 deletions .github/workflows/est-libest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ jobs:
run: |
sudo cp .github/wf_data/est_proxy_basic.cfg examples/Docker/data/est_proxy.cfg
sudo cp -R .github/wf_data/certs examples/Docker/data/
sudo cp -R .github/wf_data/srp examples/Docker/data/
sudo cp -R .github/wf_data/xca examples/Docker/data/
sudo chmod 777 examples/Docker/data/est_proxy.cfg
sudo cat .github/wf_data/est_proxy_clientauth.cfg >> examples/Docker/data/est_proxy.cfg
Expand All @@ -48,11 +49,32 @@ jobs:
- name: "[ Test ] enroll certificate using estclient"
run: |
docker run -v /tmp/certs:/tmp/certs --env EST_OPENSSL_CACERT=/tmp/certs/cacerts.pem --network est grindsa/estclient estclient.cisco -e -s est-proxy.est -p 17443 -k /tmp/certs/estclient.key.pem -c /tmp/certs/estclient.crt.pem --pem-out -o /tmp/certs -v
sudo openssl x509 -outform der -in /tmp/certs/cert-0-0.pem -out /tmp/certs/cert-0-0.der
sudo ls -la /tmp/certs
- name: "[ Test ] reenroll certificate using estclient"
run: |
docker run -v /tmp/certs:/tmp/certs --env EST_OPENSSL_CACERT=/tmp/certs/cacerts.pem --network est grindsa/estclient estclient.cisco -g -s est-proxy.est -p 17443 -k /tmp/certs/key-x-x.pem -c /tmp/certs/cert-0-0.pem -o /tmp/certs --pem-out -v
sudo openssl x509 -outform der -in /tmp/certs/cert-0-0.pem -out /tmp/certs/cert-0-1.der
- name: "[ PREPARE ] reconfigure est_proxy and enable SRP"
run: |
sudo cat .github/wf_data/est_proxy_srp.cfg >> examples/Docker/data/est_proxy.cfg
cd examples/Docker/
docker-compose restart
docker-compose logs
- name: "[ Test ] enroll certificate using estclient and Clientauth"
run: |
docker run -v /tmp/certs:/tmp/certs --env EST_OPENSSL_CACERT=/tmp/certs/cacerts.pem --network est grindsa/estclient estclient.cisco -e -s est-proxy.est -p 17443 -k /tmp/certs/estclient.key.pem -c /tmp/certs/estclient.crt.pem --pem-out -o /tmp/certs -v
sudo openssl x509 -outform der -in /tmp/certs/cert-0-0.pem -out /tmp/certs/cert-0-2.der
sudo ls -la /tmp/certs
- name: "[ Test ] enroll certificate using estclient and srp"
run: |
docker run -v /tmp/certs:/tmp/certs --env EST_OPENSSL_CACERT=/tmp/certs/cacerts.pem --network est grindsa/estclient estclient.cisco -e -s est-proxy.est -p 17443 --srp --srp-user user1 --srp-password password1 --pem-out -o /tmp/certs -v
sudo openssl x509 -outform der -in /tmp/certs/cert-0-0.pem -out /tmp/certs/cert-0-3.der
sudo ls -la /tmp/certs
- name: "[ * ] collecting test logs"
if: ${{ failure() }}
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -119,3 +119,4 @@ scripts/*
certs/*
data/*
dev_helper.py
.coveralls.yml
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@
# est_proxy

![GitHub release](https://img.shields.io/github/release/grindsa/est_proxy.svg)
![GitHub last commit (branch)](https://img.shields.io/github/last-commit/grindsa/est_proxy/main.svg?label=last%20commit%20into%20master)
![GitHub last commit (branch)](https://img.shields.io/github/last-commit/grindsa/est_proxy/main.svg?label=last%20commit%20into%20main)
![GitHub last commit (branch)](https://img.shields.io/github/last-commit/grindsa/est_proxy/devel.svg?label=last%20commit%20into%20devel)
<!-- [![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/2581/badge)](https://bestpractices.coreinfrastructure.org/projects/2581) -->
<!-- [![codecov](https://codecov.io/gh/grindsa/est_proxy/branch/devel/graph/badge.svg)](https://codecov.io/gh/grindsa/est_proxy/branch/devel) -->
![Codecov main](https://img.shields.io/codecov/c/gh/grindsa/est_proxy/branch/main?label=test%20coverage%20main)
![Codecov devel](https://img.shields.io/codecov/c/gh/grindsa/est_proxy/branch/devel?label=test%20coverage%20devel)

est_proxy is development project to create an est protocol proxy. Main
intention is to provide est enrollment services on CA servers which do not support this
Expand Down
8 changes: 4 additions & 4 deletions docs/est_proxy.cfg.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ grindsa@rlh:~# est_proxy -c est_proxy.cfg
| Section | Option | Description | Values | default|
| :-------| :------| :-----------| :------| :------|
| `DEFAULT` | `debug` | Debug mode| True/False| False|
| `ClientAuth` | `address` | listing IP of est_proxy | True/False | None|
| `ClientAuth` | `port` | listening port of est_proxy | integer | 1443|
| `ClientAuth` | `key_file` | key file in pem format | True/False | None|
| `ClientAuth` | `cert_file` | certifcate file in pem format | Integer |None |
| `Daemon` | `address` | listing IP of est_proxy | True/False | None|
| `Daemon` | `port` | listening port of est_proxy | integer | 1443|
| `Daemon` | `key_file` | key file in pem format | True/False | None|
| `Daemon` | `cert_file` | certifcate file in pem format | Integer |None |
| `CAhandler` | `handler_file` | path and name of ca_handler file to be loaded. If not specified `est_proxy/ca_handler.py` will be loaded | examples/ca_handler/openssl_hander.py | `est_proxy/ca_handler.py`|
| `Logging` | `log_format` | logging formatter | [logging.Formatter](https://docs.python.org/3/library/logging.html#logging.Formatter) | `'%(message)s'`|

Expand Down
20 changes: 12 additions & 8 deletions est_proxy/est_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import importlib
from http.server import BaseHTTPRequestHandler
# pylint: disable=E0401
from est_proxy.helper import config_load, ca_handler_get, logger_setup
from est_proxy.helper import config_load, ca_handler_get, logger_setup # ,b64_encode, cert_san_get, cert_extensions_get, cert_eku_get
from est_proxy.version import __version__

class ESTSrvHandler(BaseHTTPRequestHandler):
Expand Down Expand Up @@ -40,10 +40,10 @@ def __init__(self, *args, **kwargs):
self.connection = args[0]
except BaseException as err_:
self.logger.error('ESTSrvHandler.__init__ store connection settings failed: {0}'.format(err_))
#try:
super().__init__(*args, **kwargs)
#except BaseException as err_:
# self.logger.error('ESTSrvHandler.__init__ superclass init failed: {0}'.format(err_))
try:
super().__init__(*args, **kwargs)
except BaseException as err_:
self.logger.error('ESTSrvHandler.__init__ superclass init failed: {0}'.format(err_))

def _cacerts_get(self):
""" get ca certificates """
Expand All @@ -65,6 +65,12 @@ def _auth_check(self):
self.logger.debug('ESTSrvHandler._auth_check()')
authenticated = False
if self.connection.session.clientCertChain or self.connection.session.srpUsername:
if self.connection.session.clientCertChain:
self.logger.info('Client X.509 SHA1 fingerprint: {0}'.format(self.connection.session.clientCertChain.getFingerprint()))
# cert_bin = b64_encode(self.logger, self.connection.session.clientCertChain.__dict__['x509List'][0].writeBytes())
# serial = cert_eku_get(self.logger, cert_bin)
else:
self.logger.info('Client SRP username: {0}'.format(self.connection.session.srpUsername))
authenticated = True
self.logger.debug('ESTSrvHandler._auth_check() ended with: {0}'.format(authenticated))
return authenticated
Expand Down Expand Up @@ -209,7 +215,7 @@ def _tmpfiles_clean(self, file_name_list):
try:
os.remove(file_name)
except BaseException as err:
print(file_name, err)
self.logger.error('ESTSrvHandler._tmpfiles_clean() failed for {0} with error: {1}'.format(file_name, err))

def _opensslcmd_build(self, file_name_list, pkcs7_file):
""" build ssl cmd """
Expand Down Expand Up @@ -353,8 +359,6 @@ def do_POST(self):
self.logger.debug('ESTSrvHandler.do_POST() end sequence detected.')
break

# self.logger.info("POST request,\nPath: %s\nHeaders:\n%s\n\nBody:\n%s\n", str(self.path), str(self.headers), post_data.decode('utf-8'))
# process requests
(code, content_type, content_length, encoding, content) = self._post_process(post_data)

# write response
Expand Down
100 changes: 83 additions & 17 deletions est_proxy/helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
import textwrap
import OpenSSL
import pytz
from tlslite import SessionCache, HandshakeSettings
from tlslite import SessionCache, HandshakeSettings, VerifierDB
from tlslite.constants import CipherSuite, HashAlgorithm, SignatureAlgorithm, GroupName, SignatureScheme

def b64decode_pad(logger, string):
Expand Down Expand Up @@ -76,6 +76,64 @@ def cert_pem2der(pem_file):
certobj = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, pem_file)
return OpenSSL.crypto.dump_certificate(OpenSSL.crypto.FILETYPE_ASN1, certobj)

def cert_san_get(logger, certificate, recode=True):
""" get subject alternate names from certificate """
logger.debug('cert_san_get()')
if recode:
pem_file = build_pem_file(logger, None, b64_url_recode(logger, certificate), True)
else:
pem_file = certificate

cert = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, pem_file)
san = []
ext_count = cert.get_extension_count()
for i in range(0, ext_count):
ext = cert.get_extension(i)
if 'subjectAltName' in str(ext.get_short_name()):
san_list = ext.__str__().split(',')
for san_name in san_list:
san_name = san_name.rstrip()
san_name = san_name.lstrip()
san.append(san_name)
logger.debug('cert_san_get() ended')
return san

def cert_eku_get(logger, certificate, recode=True):
""" get extended key usage from certificate """
logger.debug('cert_eku_get()')
if recode:
pem_file = build_pem_file(logger, None, b64_url_recode(logger, certificate), True)
else:
pem_file = certificate

cert = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, pem_file)
eku = None
ext_count = cert.get_extension_count()
for i in range(0, ext_count):
ext = cert.get_extension(i)
if 'extendedKeyUsage' in str(ext.get_short_name()):
eku = cert.get_extension(i).get_data()
logger.debug('cert_eku_get() ended')
return eku

def cert_extensions_get(logger, certificate, recode=True):
""" get extenstions from certificate certificate """
logger.debug('cert_extensions_get()')
if recode:
pem_file = build_pem_file(logger, None, b64_url_recode(logger, certificate), True)
else:
pem_file = certificate

cert = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, pem_file)
extension_list = []
ext_count = cert.get_extension_count()
for i in range(0, ext_count):
ext = cert.get_extension(i)
extension_list.append(convert_byte_to_string(base64.b64encode(ext.get_data())))

logger.debug('cert_extensions_get() ended with: {0}'.format(extension_list))
return extension_list

def cert_serial_get(logger, certificate):
""" get serial number form certificate """
logger.debug('cert_serial_get()')
Expand Down Expand Up @@ -199,9 +257,9 @@ def logger_setup(debug, cfg_file=None):
logger = logging.getLogger('est_proxy')
return logger

def hssrv_options_get(logger, task, config_dic):
def hssrv_options_get(logger, config_dic):
""" get parameters for handshake server """
logger.debug('hssrv_options_get({0})'.format(task))
logger.debug('hssrv_options_get()')

hs_settings = HandshakeSettings()

Expand All @@ -215,22 +273,30 @@ def hssrv_options_get(logger, task, config_dic):
# for item in cipher.split(',')]

option_dic = {}
if task == 'ClientAuth':
if 'ClientAuth' in config_dic:
if 'cert_file' in config_dic['ClientAuth'] and 'key_file' in config_dic['ClientAuth']:
# logger.error('Helper.hssrv_options_get(): ClientAuth specified but not configured in config file')
option_dic['certChain'] = config_dic['ClientAuth']['cert_file']
option_dic['privateKey'] = config_dic['ClientAuth']['key_file']
option_dic['sessionCache'] = SessionCache()
option_dic['alpn'] = [bytearray(b'http/1.1')]
option_dic['settings'] = hs_settings
option_dic['reqCert'] = True
option_dic['sni'] = None
else:
logger.error('Helper.hssrv_options_get(): incomplete ClientAuth configuration in config file')
if 'Daemon' in config_dic:
if 'cert_file' in config_dic['Daemon'] and 'key_file' in config_dic['Daemon']:
option_dic['certChain'] = config_dic['Daemon']['cert_file']
option_dic['privateKey'] = config_dic['Daemon']['key_file']
option_dic['sessionCache'] = SessionCache()
option_dic['alpn'] = [bytearray(b'http/1.1')]
option_dic['settings'] = hs_settings
option_dic['reqCert'] = True
option_dic['sni'] = None
else:
logger.error('Helper.hssrv_options_get(): ClientAuth specified but not configured in config file')
logger.error('Helper.hssrv_options_get(): incomplete Daemon configuration in config file')
else:
logger.error('Helper.hssrv_options_get(): Daemon specified but not configured in config file')

if 'SRP' in config_dic:
if 'userdb' in config_dic['SRP']:
try:
srp_db = VerifierDB(config_dic['SRP']['userdb'])
srp_db.open()
option_dic['verifierDB'] = srp_db
except BaseException as err:
logger.error('Helper.hssrv_options_get(): SRP database {0} could not get loaded.'.format(config_dic['SRP']['userdb']))
logger.error('Helper.hssrv_options_get(): Error: {0}'.format(err))
logger.debug('hssrv_options_get() ended')
return option_dic

def uts_now():
Expand Down
Loading

0 comments on commit 45f9d24

Please sign in to comment.