Source code for labelbot.auth

"""Functions for handling authentication procedures.

.. module:: auth
    :synopsis: Functions for handling authentication procedures.
.. moduleauthor:: Lars Hummelgren <larshum@kth.se> & Joakim Croona <jcroona@kth.se>
"""

import datetime
import http.client
import json
import jwcrypto
import python_jwt
import requests
import boto3
import botocore
import hmac
import hashlib

USER_AGENT = "label-bot"


[docs]def generate_jwt_token(private_pem: bytes, app_id: int) -> str: """Generates a JWT token valid for 10 minutes using the private key. Args: private_pem: the private key that is used to generate a JWT app_id the Application id Returns: The JWT that was generated using the private key and the app id """ private_key = jwcrypto.jwk.JWK.from_pem(private_pem) payload = {"iss": app_id} duration = datetime.timedelta(minutes=10) return python_jwt.generate_jwt(payload, private_key, "RS256", duration)
[docs]def generate_installation_access_token(jwt_token: str, installation_id) -> str: """Generates an installation access token using a JWT token and an installation id. An installation access token is valid for 1 hour. Args: jwt_token: a valid JWT token installation_id: the installation id of the app. Returns: An installation access token from the GitHub API """ headers = { "Authorization": f"Bearer {jwt_token}", "Accept": "application/vnd.github.machine-man-preview+json", "User-Agent": USER_AGENT, } url = f"https://api.github.com/app/installations/{installation_id}/access_tokens" r = requests.post(url, headers=headers) return r.json()["token"]
[docs]def get_pem(bucket_name: str, bucket_key: str) -> bytes: """Reads a private PEM file from an S3 bucket. Args: bucket_name: Name of the S3 bucket. bucket_key: Bucket key for the PEM file. Returns: Contents of the PEM file. """ s3 = boto3.resource("s3") s3.Bucket(bucket_name).download_file(bucket_key, "/tmp/key.pem") with open("/tmp/key.pem", "rb") as f: return f.read()
[docs]def authenticate_request(shared_secret: str, body: str, signature: str) -> bool: """Checks if the MAC (message authentication code) sent in the request is really from GitHub. Args: shared_secret: A secret shared between GitHub and the bot. body: Body of the HTTP request. signature: The header containing the MAC. Returns: True iff the signature is a MAC computed with the body of the request and the shared secret. """ if signature is None: return False sha_body = hmac.new( shared_secret.encode("utf8"), body.encode("utf8"), hashlib.sha1 ).hexdigest() _, sha_github = signature.split("=") return hmac.compare_digest(sha_body, sha_github)