-
Notifications
You must be signed in to change notification settings - Fork 74
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add AWS Lambda sample scripts to examples
- Loading branch information
1 parent
0e48383
commit b147c8e
Showing
2 changed files
with
191 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
# _ __ | ||
# | |/ /___ ___ _ __ ___ _ _ ® | ||
# | ' </ -_) -_) '_ \/ -_) '_| | ||
# |_|\_\___\___| .__/\___|_| | ||
# |_| | ||
# | ||
# Keeper Commander | ||
# Copyright 2024 Keeper Security Inc. | ||
# Contact: ops@keepersecurity.com | ||
# | ||
# | ||
# Sample AWS Lambda handler script | ||
# In this example, we generate a report that combines the outputs | ||
# of the `security-audit-report` and `user-report` commands, | ||
# and then send those results to a specified email address ("KEEPER_SENDTO") | ||
|
||
|
||
import json | ||
import os | ||
import datetime | ||
from typing import Optional | ||
|
||
from email.mime.application import MIMEApplication | ||
from email.mime.multipart import MIMEMultipart | ||
from email.mime.text import MIMEText | ||
|
||
import boto3 | ||
|
||
from keepercommander import api | ||
from keepercommander.commands.enterprise import UserReportCommand | ||
from keepercommander.commands.security_audit import SecurityAuditReportCommand | ||
from keepercommander.params import KeeperParams | ||
|
||
|
||
# This Lambda's entry point | ||
def lambda_handler(event, context): | ||
params = get_params() | ||
api.login(params) | ||
api.query_enterprise(params, True) | ||
|
||
# Log Commander-related issues (e.g., incorrect credentials) | ||
# using AWS's built-in logging module and abort | ||
if not params.session_token: | ||
print('Not connected') | ||
return 'Error: See Lambda log for details' | ||
if not params.enterprise: | ||
print('Not enterprise administrator') | ||
return 'Error: See Lambda log for details' | ||
|
||
# Generate and send report | ||
report = create_user_report(params) | ||
response = email_result(report) | ||
return response | ||
|
||
|
||
# Create report (format: JSON) combining data from 2 existing Commander reports | ||
def create_user_report(params): # type: (KeeperParams) -> Optional[str] | ||
user_report_cmd = UserReportCommand() | ||
user_report_data = user_report_cmd.execute(params, format='json') | ||
data = json.loads(user_report_data) | ||
users = {x['email']: x for x in data} | ||
security_audit_report = SecurityAuditReportCommand() | ||
security_audit_report_data = security_audit_report.execute(params, format='json') | ||
if security_audit_report_data: | ||
data = json.loads(security_audit_report_data) | ||
for x in data: | ||
if 'email' in x: | ||
email = x['email'] | ||
if email in users: | ||
user = users[email] | ||
for key in x: | ||
if key not in user: | ||
if key not in ('node_path', 'username'): | ||
user[key] = x[key] | ||
else: | ||
users[email] = x | ||
|
||
return json.dumps(list(users.values()), indent=2) | ||
|
||
|
||
# Email report data (as JSON attachment) to recipient specified in this Lambda | ||
# function's environment variables | ||
def email_result(report): | ||
sender = os.environ.get('KEEPER_SENDER') | ||
sendto = os.environ.get('KEEPER_SENDTO') | ||
region = 'us-east-1' | ||
ses_client = boto3.client('ses', region_name=region) | ||
|
||
message = MIMEMultipart('mixed') | ||
message['Subject'] = 'Keeper Commander User Security Report With CSV (attached)' | ||
message['To'] = sendto | ||
message['From'] = sender | ||
now = datetime.datetime.now() | ||
|
||
body = MIMEText(f'User Report Output created and sent at {now}', 'plain') | ||
message.attach(body) | ||
|
||
attachment = MIMEApplication(report) | ||
attachment.add_header( | ||
'Content-Disposition', | ||
'attachment', | ||
filename='user-report.json' | ||
) | ||
message.attach(attachment) | ||
|
||
response = ses_client.send_raw_email( | ||
Source=message['From'], | ||
Destinations=[sendto], | ||
RawMessage={'Data': message.as_string()} | ||
) | ||
|
||
return response | ||
|
||
|
||
# Get required Commander parameters from Lambda's environment variables (in "Configuration") | ||
def get_params(): | ||
user = os.environ.get('KEEPER_USER') | ||
pw = os.environ.get('KEEPER_PASSWORD') | ||
server = os.environ.get('KEEPER_SERVER') | ||
private_key = os.environ.get('KEEPER_PRIVATE_KEY') | ||
token = os.environ.get('KEEPER_DEVICE_TOKEN') | ||
my_params = KeeperParams() | ||
my_params.user = user | ||
my_params.password = pw | ||
my_params.server = server | ||
my_params.device_private_key = private_key | ||
my_params.device_token = token | ||
return my_params | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
#!/usr/bin/env bash | ||
|
||
# To create a `keepercommander` dependency layer for your AWS Lambda function : | ||
# 1. Upload this script to any folder in your CloudShell environment. | ||
# 2. (Optional) Upload your project's `requirements.txt` file to the same folder. | ||
# 3. In that folder, run | ||
# source ./package_layer_content.sh | ||
# 4. There should now be a file named `commander-layer.zip` that can be uploaded | ||
# to your S3 bucket, where it can then be used to create a new Lambda layer | ||
|
||
MAX_LIB_SIZE=262144000 | ||
LAYER_FILENAME='commander-layer.zip' | ||
LAYER_PATH=$(pwd)/$LAYER_FILENAME | ||
LIB_DIR='python' | ||
VENV='commander-venv' | ||
OTHER_DEPS='requirements.txt' | ||
|
||
# Clean up previous artifacts | ||
test -f $LAYER_FILENAME && rm $LAYER_FILENAME | ||
test -d $LIB_DIR && rm -rf $LIB_DIR | ||
test -d $VENV && rm -rf $VENV | ||
|
||
# Create package folder to zip | ||
mkdir $LIB_DIR | ||
|
||
# Create and run virtual environment | ||
python -m venv $VENV | ||
source ./$VENV/bin/activate | ||
|
||
# Install dependencies and package | ||
pip install cryptography --platform manylinux2014_x86_64 --only-binary=:all: -t $LIB_DIR | ||
pip install keepercommander -t $LIB_DIR | ||
|
||
if test -f $OTHER_DEPS; then | ||
pip install -r $OTHER_DEPS -t $LIB_DIR | ||
fi | ||
|
||
deactivate | ||
|
||
# Check uncompressed library size | ||
LIB_SIZE=$(du -sb $LIB_DIR | cut -f 1) | ||
LIB_SIZE_MB=$(du -sm $LIB_DIR | cut -f 1) | ||
|
||
if [ "$LIB_SIZE" -ge $MAX_LIB_SIZE ]; then | ||
echo "*****************************************************************************************************************" | ||
echo 'Operation was aborted' | ||
echo "The resulting layer has too many dependencies and its size ($LIB_SIZE_MB MB) exceeds the maximum allowed (~262 MB)." | ||
echo 'Try breaking up your dependencies into smaller groups and package them as separate layers.' | ||
echo "*****************************************************************************************************************" | ||
else | ||
zip -r $LAYER_FILENAME $LIB_DIR | ||
echo "***************************************************************************" | ||
echo "***************************************************************************" | ||
echo 'Lambda layer file has been created' | ||
printf "To download, copy the following file path: %s\n%s\n$LAYER_PATH%s\n%s\n" | ||
echo 'and click on "Actions" in the upper-right corner of your CloudShell console' | ||
echo "***************************************************************************" | ||
fi | ||
|
||
# Clean-up | ||
rm -rf $LIB_DIR | ||
rm -rf $VENV |