Skip to content

Commit

Permalink
Merge pull request #227 from cmurp25/mainline
Browse files Browse the repository at this point in the history
Inline lambda + api key storing for static frontend
  • Loading branch information
D42H5 authored Dec 11, 2024
2 parents da870d3 + 9f9a321 commit c3e4c9f
Showing 1 changed file with 107 additions and 10 deletions.
117 changes: 107 additions & 10 deletions cdk/api_gateway/shared_api_gateway.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@

import boto3
import json
from pathlib import Path
import os

from constructs import Construct
from dns import MakerspaceDns
Expand Down Expand Up @@ -162,6 +164,33 @@ def __init__(self, scope: Construct, stage: str,
# Add the api key to the usage plan
self.plan.add_api_key(self.api_key)

# WARNING:
# The following is a band-aid patch that should be fixed in the future.
# With the implementation of api key and the need for the STATIC frontend
# to be able to use the backend api, the need to statically store the
# backend api key is a thing. This, unfortunately, means that any method
# that requires the api key will visibly show this in network traffic.
# As such, while the frontend remains static, the api key should be used
# behind the Amplify login page to reduce the chance of security risk of
# leaking the key. This also means that the SharedAPIGateway stack MUST
# be created before the Visit stack to ensure the api key is written to
# the right location before the s3 bucket is deployed.

# Config filename
config_filename: str = ".env"

# Data to store
data: str = f"BACKEND_KEY={backend_api_key}"

# Path to the file to write the data to
# Assumes directory structure is cdk/visit/console/{stage_name} and the CWD
# is 'cdk'
config_path: Path = Path(f"{os.getcwd()}/visit/console/{stage_name}/{config_filename}")

# Write data to the file
with open(config_path, "w") as outfile:
outfile.write(data)


def create_rest_api(self):

Expand Down Expand Up @@ -215,16 +244,6 @@ def create_usage_plan(self, plan_name: str = "UsagePlan"):
]
)

def api_key_checker_lambda(self):
self.lambda_api_key_checker = aws_lambda.Function(
self,
'ApiKeyChecker',
function_name=PhysicalName.GENERATE_IF_NEEDED,
code=aws_lambda.Code.from_asset('api_gateway/lambda_code/api_key_checker'),
handler='api_key_checker.handler',
timeout=Duration.seconds(29),
runtime=aws_lambda.Runtime.PYTHON_3_12)


"""
Users:
Expand Down Expand Up @@ -394,3 +413,81 @@ def route_tiger_training(self, tiger_training: aws_lambda.Function):

# methods
self.tiger_training.add_method('ANY', tiger_training, api_key_required=True)


def api_key_checker_lambda(self):
#self.lambda_api_key_checker = aws_lambda.Function(
# self,
# 'ApiKeyChecker',
# function_name=PhysicalName.GENERATE_IF_NEEDED,
# code=aws_lambda.Code.from_asset('api_gateway/lambda_code/api_key_checker'),
# handler='api_key_checker.handler',
# timeout=Duration.seconds(15),
# runtime=aws_lambda.Runtime.PYTHON_3_12)

# Create a Lambda function to query for an API Key
self.lambda_api_key_checker = aws_lambda.Function(
self, "ApiKeyCheckerFunction",
runtime=aws_lambda.Runtime.PYTHON_3_12,
handler="index.handler",
timeout=Duration.seconds(15),
code=aws_lambda.Code.from_inline("""
import boto3
import logging
import json
import time
logger = logging.getLogger()
logger.setLevel(logging.INFO)
def delete_key(client, api_key_name: str) -> bool:
deleted_key: bool = False
response = client.get_api_keys(includeValues=False)
# Check for matching key name
for key in response['items']:
if key['name'] == api_key_name:
# Delete the key
try:
client.delete_api_key(apiKey=key['id'])
logger.info(f"Deleted key '{key['id']}'")
deleted_key = True
except Exception as e:
raise Exception(f"Error deleting API Key: {e}")
return deleted_key
def handler(event, context):
logger.info("Event:")
logger.info(json.dumps(event, indent=2))
try:
client = boto3.client('apigateway')
if 'ApiKeyName' not in event:
raise Exception("Missing 'ApiKeyName' from event input fields.")
api_key_name = event['ApiKeyName']
# Try and delete the key
delete_key(client, api_key_name)
# Wait 5 seconds for changes to propagate
time.sleep(5)
# Ensure key was deleted (delete_key should return False for no key deleted)
key_deleted: bool = delete_key(client, api_key_name)
if key_deleted:
raise Exception(f"Api key still existed after deleting first time.")
return {}
except Exception as e:
raise Exception(f"Error occurred: {e}")
"""),
)

0 comments on commit c3e4c9f

Please sign in to comment.