Skip to content

Instantly share code, notes, and snippets.

@kmkale
Last active August 23, 2024 19:44
Show Gist options
  • Save kmkale/27bb96c2ecfa5c31d64a6919f3280731 to your computer and use it in GitHub Desktop.
Save kmkale/27bb96c2ecfa5c31d64a6919f3280731 to your computer and use it in GitHub Desktop.

Revisions

  1. kmkale revised this gist Oct 2, 2020. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion mtls-lambda-authoriser.py
    Original file line number Diff line number Diff line change
    @@ -8,7 +8,7 @@
    Let's load our truststore from s3. Doing this outside of handler function so that this will be loaded only on coldstart.
    If the truststore contents change, you need to update the lambda env var 'TRUSTSTORE_FILE_VERSIONID'
    with the new files versionId. And also update the same in 'API Gateway > Custom domain names > Domain details > Truststore version' and wait till Status becomes Available.
    If APi Gateway finds some problem with the truststote, such as could not find complete chain, it will display a warning. The warning details will tell you which cert it has a problem with and the problem. You need to fix the truststore chain till this warning goes away.
    If APi Gateway finds some problem with the truststore, such as could not find complete chain, it will display a warning. The warning details will tell you which cert it has a problem with and the problem. You need to fix the truststore chain till this warning goes away.
    '''

    s3_client = boto3.client('s3')
  2. kmkale revised this gist Oct 1, 2020. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion mtls-lambda-authoriser.py
    Original file line number Diff line number Diff line change
    @@ -5,7 +5,7 @@
    from asn1crypto import pem

    '''
    Lets load our truststore from s3. Doing this outside of handler function so that this will be loaded only on coldstart.
    Let's load our truststore from s3. Doing this outside of handler function so that this will be loaded only on coldstart.
    If the truststore contents change, you need to update the lambda env var 'TRUSTSTORE_FILE_VERSIONID'
    with the new files versionId. And also update the same in 'API Gateway > Custom domain names > Domain details > Truststore version' and wait till Status becomes Available.
    If APi Gateway finds some problem with the truststote, such as could not find complete chain, it will display a warning. The warning details will tell you which cert it has a problem with and the problem. You need to fix the truststore chain till this warning goes away.
  3. kmkale revised this gist Oct 1, 2020. 1 changed file with 0 additions and 2 deletions.
    2 changes: 0 additions & 2 deletions mtls-lambda-authoriser.py
    Original file line number Diff line number Diff line change
    @@ -44,8 +44,6 @@ def lambda_handler(event, context):
    True
    )
    except Exception as inst:
    print(type(inst))
    print(inst.args)
    print(inst)
    print("The certificate could not be validated")
    return {
  4. kmkale revised this gist Oct 1, 2020. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion mtls-lambda-authoriser.py
    Original file line number Diff line number Diff line change
    @@ -8,7 +8,7 @@
    Lets load our truststore from s3. Doing this outside of handler function so that this will be loaded only on coldstart.
    If the truststore contents change, you need to update the lambda env var 'TRUSTSTORE_FILE_VERSIONID'
    with the new files versionId. And also update the same in 'API Gateway > Custom domain names > Domain details > Truststore version' and wait till Status becomes Available.
    If APi Gw finds some problem with the truststote, such as could not find complete chain, it will display a warning. The warning details will tell you which cert it has a problem with and the problem. You need to fix the truststore chain till this warning goes away.
    If APi Gateway finds some problem with the truststote, such as could not find complete chain, it will display a warning. The warning details will tell you which cert it has a problem with and the problem. You need to fix the truststore chain till this warning goes away.
    '''

    s3_client = boto3.client('s3')
  5. kmkale created this gist Sep 29, 2020.
    64 changes: 64 additions & 0 deletions mtls-lambda-authoriser.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,64 @@
    import json
    import os
    from certvalidator import CertificateValidator, ValidationContext, errors
    import boto3
    from asn1crypto import pem

    '''
    Lets load our truststore from s3. Doing this outside of handler function so that this will be loaded only on coldstart.
    If the truststore contents change, you need to update the lambda env var 'TRUSTSTORE_FILE_VERSIONID'
    with the new files versionId. And also update the same in 'API Gateway > Custom domain names > Domain details > Truststore version' and wait till Status becomes Available.
    If APi Gw finds some problem with the truststote, such as could not find complete chain, it will display a warning. The warning details will tell you which cert it has a problem with and the problem. You need to fix the truststore chain till this warning goes away.
    '''

    s3_client = boto3.client('s3')

    bucket = os.environ.get('TRUSTSTORE_BUCKET')
    key = os.environ.get('TRUSTSTORE_FILENAME')
    versionId = os.environ.get('TRUSTSTORE_FILE_VERSIONID')

    download_path = '/tmp/{}'.format(key)
    s3_client.download_file(bucket, key, download_path, ExtraArgs={'VersionId': versionId})

    trust_roots = []
    with open(download_path, 'rb') as f:
    for _, _, der_bytes in pem.unarmor(f.read(), multiple=True):
    trust_roots.append(der_bytes)

    def lambda_handler(event, context):
    print("Received event: " + json.dumps(event, indent=2))
    ''' Get the client cert from lambda event '''
    cert = event["requestContext"]["authentication"]["clientCert"]["clientCertPem"].encode()

    '''
    hard-fail mode, any error in checking revocation is considered a failure. However, if there is no known source of revocation information, it is not considered a failure.
    This allows us to keep using self signed certs too.
    '''
    context = ValidationContext(allow_fetching=True, revocation_mode="hard-fail", trust_roots=trust_roots)

    try:
    validator = CertificateValidator(cert, validation_context=context)
    validator.validate_usage(
    set(['digital_signature', 'key_encipherment']),
    set(['server_auth', 'client_auth']),
    True
    )
    except Exception as inst:
    print(type(inst))
    print(inst.args)
    print(inst)
    print("The certificate could not be validated")
    return {
    "isAuthorized": "false",
    "context": {
    "exception": str(inst.args)
    }
    }
    else:
    print("The certificate is ok")
    return {
    "isAuthorized": "true",
    "context": {
    "exception": None
    }
    }