A AWS Lambda function that acts as a secure proxy for the Google Custom Search API. It uses AWS KMS to encrypt and protect API credentials, and exposes a simple REST endpoint via API Gateway.
This Lambda function:
- Accepts search queries via HTTP GET requests
- Decrypts KMS-encrypted Google API credentials at runtime
- Proxies requests to the Google Custom Search API
- Returns results to the caller with CORS headers enabled
Client → API Gateway → Lambda Function → Google Custom Search API
↑
AWS KMS
(credential decryption)
- AWS CLI configured with appropriate permissions
- Terraform installed
- A Google Custom Search Engine with:
- An API Key
- A Search Engine ID (cx)
- Python 3.x (for Lambda runtime)
cd lambda
zip lambda_function.zip lambda_function.pycd ../terraform
terraform init
terraform plan
terraform applyKMS_KEY_ID=$(terraform output -raw kms_key_id)./encrypt_credentials.shThis script will use the KMS key to encrypt your GOOGLE_API_KEY and SEARCH_ENGINE_ID.
Add the encrypted values to terraform.tfvars:
encrypted_google_api_key = "<base64-encrypted-value>"
encrypted_search_engine_id = "<base64-encrypted-value>"terraform applyterraform output api_endpointUse this endpoint in your application configuration (see application.yml).
GET https://<api-id>.execute-api.<region>.amazonaws.com/search
| Parameter | Required | Description |
|---|---|---|
q |
✅ Yes | The search query string |
num |
❌ No | Number of results to return (default: 10, max: 10) |
start |
❌ No | Starting index for pagination (default: 1) |
curl "https://<api-id>.execute-api.us-east-1.amazonaws.com/search?q=aws+lambda&num=5"{
"kind": "customsearch#search",
"items": [
{
"title": "AWS Lambda – Serverless Compute",
"link": "https://aws.amazon.com/lambda/",
"snippet": "AWS Lambda lets you run code without provisioning or managing servers..."
}
]
}| Status Code | Reason |
|---|---|
400 |
Missing required q parameter |
500 |
Internal Lambda or decryption error |
4xx/5xx |
Errors returned from Google API |
These are set automatically by Terraform after encryption:
| Variable | Description |
|---|---|
ENCRYPTED_GOOGLE_API_KEY |
KMS-encrypted, base64-encoded Google API key |
ENCRYPTED_SEARCH_ENGINE_ID |
KMS-encrypted, base64-encoded Search Engine ID |
In your Spring Boot or other application, configure the proxy endpoint via application.yml:
google:
search:
proxy:
endpoint: ${GOOGLE_SEARCH_PROXY_ENDPOINT:https://your-api-id.execute-api.us-east-1.amazonaws.com/search}The endpoint can be overridden at runtime using the GOOGLE_SEARCH_PROXY_ENDPOINT environment variable.
- KMS Encryption: API credentials are never stored in plaintext. They are encrypted using AWS KMS and decrypted only at Lambda invocation time.
- IAM Roles: The Lambda execution role should have the minimum required KMS
Decryptpermission scoped to the specific key. - CORS: Currently set to
*(allow all origins). RestrictAccess-Control-Allow-Originin production to your specific domain. - No credential logging: Decrypted credentials are used in-memory only and never logged.