Пример #1
0
def put_file_with_creds(bucket, key, content, access_key, secret_key):
    """ 
    Get a file from S3 using Specific Credentials

    :param bucket: name of bucket
    :param key: key id in bucket
    :param content: file body content
    :param access_key: user's access_key
    :param secret_key: user's secret_key
    :raise: AWSError: couldn't fetch file contents from S3
    """
    if key is None or len(key) <= 0:
        raise ValidationError("Key name cannot be empty.")

    if bucket is None or len(bucket) <= 0:
        raise ValidationError("Bucket name cannot be empty.")

    s3 = boto3.client("s3",
        aws_access_key_id=access_key,
        aws_secret_access_key=secret_key)

    try:
        s3.put_object(
            Bucket=bucket,
            Key=key,
            Body=content)

    except ClientError as error:
        raise AWSError("Problem putting {} from {} bucket ({})"
                       .format(key, bucket, str(error)))
    return
Пример #2
0
def send_feedback(table_name, user_name, subject, message):
    """ Log feedback to website_feedback table

    Args:
        table_name: name of dynamodb table to pull feedback from
        user_name: unique id of user, username/email/uuid
        subject: string subject of user feedback
        message: string containing user feedback
    Returns:
        None
    Raises:
        AWSError: Could not write to database
    """
    dynamodb = boto3.client('dynamodb')
    try:
        dynamodb.put_item(TableName=table_name,
                          Item={
                              'feedback_time': {
                                  'N': str(systime.time())
                              },
                              'user_name': {
                                  'S': user_name
                              },
                              'subject': {
                                  'S': subject
                              },
                              'message': {
                                  'S': message
                              },
                          })
    except ClientError as error:
        raise AWSError('DynamoDB Error: {}'.format(str(error)))
Пример #3
0
def get_file_with_creds(bucket, key, access_key, secret_key):
    """
    Get a file from S3 using Specific Credentials

    :param bucket: name of bucket
    :param key: key id in bucket
    :param access_key: user's access_key
    :param secret_key: user's secret_key
    :return: Stream object with contents
    :raise: AWSError: couldn't fetch file contents from S3
    """
    if key is None or len(key) <= 0:
        raise ValidationError("Key name cannot be empty.")

    if bucket is None or len(bucket) <= 0:
        raise ValidationError("Bucket name cannot be empty.")

    s3 = boto3.client("s3",
        aws_access_key_id=access_key,
        aws_secret_access_key=secret_key)
    try:
        response = s3.get_object(Bucket=bucket, Key=key)
    except ClientError as error:
        raise AWSError("Error loading file from S3: {}".format(str(error)))
    return response
Пример #4
0
def get_temp_link(bucket, key, key_id, secret_key, expiry=300):
    """
    Get expiring S3 url with temp token
    NB: bucket must be in us-east-1 to use path addressing!

    :param bucket: name of bucket
    :param key: key id in bucket
    :param key_id: Amazon AWS API key id
    :param secret_key: Amazon AWS Secret API key
    :param expiry: number of seconds token is valid for (default=600)
    :return: Temporary S3 link to file using temp credentials
    :raise: AWSError: error getting presigned link from S3
    """
    session = Session(
        aws_access_key_id=key_id,
        aws_secret_access_key=secret_key
    )
    s3_client = session.client("s3", config=Config(s3={'addressing_style': 'path'}))
    try:
        link = s3_client.generate_presigned_url(
            ExpiresIn=expiry,
            ClientMethod="get_object",
            Params={
                "Bucket": bucket,
                "Key": key,
            }
        )
    except ClientError as error:
        raise AWSError("Error generating temp link: {}".format(str(error)))
    return link
Пример #5
0
def put_object_metadata(bucket, key, meta_key, meta_value):
    """
    Get file metadata from S3

    :param bucket: name of bucket
    :param key: key id in bucket
    :param meta_key: key for updated metadata
    :param meta_value: value for updated metadata
    :return: S3 metadata object
    :raise: AWSError: couldn't load metadata from S3
    """
    # Get downloads file metadata from S3 bucket
    s3_client = boto3.client("s3")

    try:
        metadata = s3_client.head_object(Bucket=bucket,
                                         Key=key)["Metadata"]
        metadata[meta_key] = meta_value
        s3_client.copy_object(
            Bucket=bucket,
            Key=key,
            CopySource={
                'Bucket': bucket,
                'Key': key,
            },
            Metadata=metadata,
            MetadataDirective='REPLACE'
        )
    except ClientError as error:
        raise AWSError("Error loading metadata from S3: {}".format(str(error)))
Пример #6
0
def get_binary_contents(bucket, key, config=None):
    """ 
    Get file contents from S3

    :param bucket: name of bucket
    :param key: key id in bucket
    :return: Stream object with contents
    :raise: AWSError: couldn't fetch file contents from S3
    """
    s3_resource = boto3.resource("s3") if config is None else boto3.resource("s3", config=config)
    try:
        response = s3_resource.Object(bucket, key).get()
    except ClientError as error:
        raise AWSError("Error loading file from S3: {}".format(str(error)))
    return response
Пример #7
0
def get_json_contents(bucket, key):
    """
    Get json file from S3

    :param bucket: name of bucket
    :param key: key id in bucket
    :return: JSON from S3 bucket
    :raise: AWSError: couldn't fetch file contents from S3
    """
    s3_resource = boto3.resource("s3")
    try:
        response = s3_resource.Object(bucket, key).get()
    except ClientError as error:
        raise AWSError("Error loading file from S3: {}".format(str(error)))
    return json.load(response["Body"])
Пример #8
0
def get_object_metadata(bucket, key):
    """
    Get file metadata from S3

    :param bucket: name of bucket
    :param key: key id in bucket
    :return: S3 metadata object
    :raise: AWSError: couldn't load metadata from S3
    """
    # Get downloads file metadata from S3 bucket
    s3_resource = boto3.resource("s3")
    obj = s3_resource.Object(bucket, key)
    try:
        obj.load()
    except ClientError as error:
        raise AWSError("Error loading metadata from S3: {}".format(str(error)))
    return obj
Пример #9
0
def get_feedback_digest(table_name, days=1):
    """ Get website feedback and return records timezones are shifted to account for EST

    Args:
        table_name: name of dynamodb table to pull feedback from
        days: optional number of days (starting from yesterday) to return feedback for (default 1)
    Returns:
        set of feedback objects or false if empty
    Raises:
        AWSError: dynamodb scan failed
    """
    utc_timezone = UTC()
    eastern_timezone = USTimeZone(-5, "Eastern", "EST", "EDT")

    epoch = datetime(1970, 1, 1, tzinfo=utc_timezone)
    zero_time = time(0, 0, 0, 0, eastern_timezone)
    today = datetime.now(eastern_timezone)
    yesterday = today - timedelta(days)
    today = (datetime.combine(today, zero_time) - epoch).total_seconds()
    yesterday = (datetime.combine(yesterday, zero_time) -
                 epoch).total_seconds()

    dynamodb = boto3.client('dynamodb')
    try:
        feedback = dynamodb.scan(
            TableName=table_name,
            FilterExpression='feedback_time BETWEEN :yesterday AND :today',
            ExpressionAttributeValues={
                ':yesterday': {
                    'N': str(yesterday)
                },
                ':today': {
                    'N': str(today)
                },
            })
    except ClientError as error:
        raise AWSError('DynamoDB Error: {}'.format(str(error)))

    if feedback['Count'] > 0:
        return feedback['Items']
    else:
        return False
Пример #10
0
def put_doc_file(bucket, key, filename, url, caption=None, thumb=None):
    """
    Appends to a file in S3

    :param bucket: file bucket name
    :param key: key prefix
    :param filename: filename to be written
    :param url: location of filename
    :param caption: caption file contents
    :param thumb: thumbnail file contents
    :raise: AWSError: Error adding file to S3 bucket
    """
    if key is None or len(key) <= 0:
        raise ValidationError("Key name cannot be empty.")

    s3_resource = boto3.resource("s3")

    timestr = datetime.now().strftime("%Y%m%d-%H:%M:%S.%f-")
    docobj = s3_resource.Object(bucket, key + "/" + timestr + filename)

    if caption is not None:
        capobj = s3_resource.Object(bucket, key + "/" + timestr + filename + ".cap")
    else:
        pass

    if thumb is not None:
        thumbobj = s3_resource.Object(bucket, key + "/" + timestr + filename)

    try:
        file_content = requests.get(url).content
        docobj.put(Body=file_content)
        if caption is not None:
            capobj.put(Body=caption)
        if thumb is not None:
            thumbobj.put(Body=str(thumb))

    except ClientError as error:
        raise AWSError("Problem getting {} from {} bucket ({})"
                       .format(key, bucket, str(error)))
    return
Пример #11
0
def save_request(chat_id,
                 msg_id,
                 user_name,
                 event,
                 table_name="MajlisMonitorBot"):
    """
    Save a telegram request to dynamodb

    :param chat_id: telegram chat id from api
    :param msg_id: telegram msg id from api
    :param user_name: name of telegram user
    :param event: event that triggered lambda call
    :param table_name: optional table name (default="MajlisMonitorBot")
    :return: response object from put_item call
    :raise: AWSError: db call failed
    """
    timestr = datetime.now().strftime("%Y%m%d-%H:%M:%S.%f.msg")
    message = str(chat_id) + str(msg_id) + "-" + str(user_name)
    record = {
        "datetime": {
            "S": timestr
        },
        "message_id": {
            "S": message
        },
        "request": {
            "S": str(event)
        },
    }
    dynamodb = boto3.client("dynamodb")
    try:
        response = dynamodb.put_item(TableName=table_name, Item=record)
    except ClientError as error:
        raise AWSError("Problem writing to DB {} ({})".format(
            table_name, str(error)))
    return response
Пример #12
0
def put_text_file(bucket, key, text):
    """ 
    Appends to a file in S3

    :param bucket: file bucket name
    :param key: file key name
    :param text: text to be written
    :raise: AWSError: Error adding file to S3 bucket
    """
    if key is None or len(key) <= 0:
        raise ValidationError("Key name cannot be empty.")

    s3_resource = boto3.resource("s3")

    timestr = datetime.now().strftime("%Y%m%d-%H:%M:%S.%f.msg")
    key = key + "/" + timestr
    s3_new_file = s3_resource.Object(bucket, key)

    try:
        s3_new_file.put(Body=text)
    except ClientError as error:
        raise AWSError("Problem getting object {} from {} ({})"
                       .format(key, bucket, str(error)))
    return
Пример #13
0
def send_email(email_from,
               email_to,
               subject,
               text_body,
               html_body,
               file_name,
               file_data,
               src_email=None):
    """ Send email with text, html and attachment sections

    Args:
        email_from: address to send from
        email_to: address to send to
        subject: email subject line
        text_body: text/plain body of email
        html_body: text/html body of email, preferred display
        file_name: name of attachment file
        file_data: raw binary file data
    Returns:
        SES response object from AWS API
    Raises:
        FeedbackError: no body text provided or SES response is empty
    """
    # Compose email with link or binary
    sesclient = boto3.client('ses', region_name='us-east-1')
    msg = MIMEMultipart()
    msg['Subject'] = str(subject)
    msg['From'] = email_from
    msg['To'] = email_to
    if html_body and text_body:
        email_content = MIMEMultipart('alternative')
        email_content.attach(MIMEText(text_body, 'plain', 'UTF-8'))
        email_content.attach(MIMEText(html_body, 'html', 'UTF-8'))
        msg.attach(email_content)
    elif text_body:
        msg.attach(MIMEText(text_body, 'plain', 'UTF-8'))
    else:
        raise ValidationError('No body text found')

    # attachment must be last part or clients won't show it
    if file_data:
        part = MIMEApplication(file_data)
        part.add_header('Content-Disposition',
                        'attachment',
                        filename=file_name)
        msg.attach(part)

    try:
        if src_email == None:
            response = sesclient.send_raw_email(
                RawMessage={'Data': msg.as_string()})
        else:
            response = sesclient.send_raw_email(
                Source=src_email, RawMessage={'Data': msg.as_string()})
    except ClientError as error:
        raise AWSError('SendMail UnknownError: {}'.format(str(error)))

    if response is None:
        raise FeedbackError('Unknown Error: Return Value is None')

    return response