0
votes

I am working on a boto script that will create an IAM Policy and store it's attributes in a Dynamodb table. I have a python function which calls from another file for attributes like region, instance_type, ebs_volume_size, meta_template_name, start_time, end_time. While writing the code for Cloudtrail I am getting an error for putItem saying

"An error occurred (ValidationException) when calling the CreateTable operation: Invalid KeySchema: Some index key attribute have no definition".

This is my code I am not sure what is wrong.

import jmespath
import boto3
import sys
import json
import time
import meta_templates
from jinja2 import Template
iam = boto3.client('iam')
sts = boto3.client('sts')
ec2 = boto3.resource('ec2')
cloudtrail = boto3.client('cloudtrail')
s3  = boto3.client('s3')
sqs = boto3.client('sqs')
lambd = boto3.client('lambda')
dynamodb = boto3.resource('dynamodb')

###########################
##### Global variables ####
###########################
region="us-east-2"
instance_type="t2.micro"
ebs_volume_size="20"
meta_template_name="ec2_policy_meta_template"
###############################

start_time_1 = input("What's the start time")
end_time1 = input("What's the end time")
def create_aws_iam_policy_template(**kwargs):
  template_data = {}
  template_data["region"] = kwargs.get('region')
  template_data["start_time"] = kwargs.get('end_time')
  template_data["end_time"] = kwargs.get('start_time')
  template_data["instance_types"] = kwargs.get('instance_type')
  template_data["ebs_volume_size"] = kwargs.get('ebs_volume_size')
  template_data["meta_template_name"] = kwargs.get('meta_template_name')

  meta_template_dict = getattr(meta_templates, template_data["meta_template_name"])
  meta_template_json = json.dumps(meta_template_dict)
  template_json = Template(meta_template_json).render(template_data)
  return template_json  


template_json = create_aws_iam_policy_template(
  region=region,
  instance_type=instance_type,
  ebs_volume_size=ebs_volume_size,
  meta_template_name=meta_template_name,
  start_time = start_time_1,
  end_time = end_time1
)


print(template_json)


#Create S3 Bucket for CloudTrail

# Create a bucket policy
bucket_name = 'goodbucket3'
bucket_policy = {
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {"Service": "cloudtrail.amazonaws.com"},
            "Action": "s3:GetBucketAcl",
            "Resource": f"arn:aws:s3:::{bucket_name}"
        },
        {
            "Effect": "Allow",
            "Principal": {"Service": "cloudtrail.amazonaws.com"},
            "Action": "s3:PutObject",
            "Resource": f"arn:aws:s3:::{bucket_name}/AWSLogs/562922379100/*",
            "Condition": {"StringEquals": {"s3:x-amz-acl": "bucket-owner-full-control"}}
        }
    ]
}

# Convert the policy from JSON dict to string
bucket_policy = json.dumps(bucket_policy)

# Set the new policy
s3.put_bucket_policy(Bucket='goodbucket3', Policy=bucket_policy)
result = s3.get_bucket_policy(Bucket='goodbucket3')

logs = cloudtrail.create_trail(
    Name='GoodTrail',
    S3BucketName='goodbucket3',
)
response = cloudtrail.start_logging(
    Name= f"arn:aws:cloudtrail:us-east-1:562922379100:trail/GoodTrail"
)


table =dynamodb.create_table(
    TableName='GoodTable',
            KeySchema=[
            {
                'AttributeName': 'Content',
                'KeyType': 'HASH'  # Partition key
            },
            {
                'AttributeName': 'Details',
                'KeyType': 'HASH'  # Sort key
            }
        ],
    AttributeDefinitions=[
    {
      "AttributeName": "Content",
      "AttributeType": "S"
    }
    ],
  ProvisionedThroughput={
    "ReadCapacityUnits": 1,
    "WriteCapacityUnits": 1
  }
)
time.sleep(20)
table = dynamodb.Table('GoodTable')
response = table.put_item(
    Item= {
        'Content': 'Volume Size', 
        'Details': f'{ebs_volume_size}',
    }
)
response = table.put_item(
    Item= {
        'Content': 'Instance Type', 
        'Details': f'{instance_type}',
    }
)
response = table.put_item(
    Item= {
        'Content': 'Region', 
        'Details': f'{region}',
    }
)
1

1 Answers

1
votes

from the documentation PutItem

When you add an item, the primary key attributes are the only required attributes. Attribute values cannot be null.

You declared your Schema with S3BucketName as the Partition key.

    ],
      KeySchema=[
    {
      "AttributeName": "S3BucketName",
      "KeyType": "HASH"
    }
  ],

So when you add an item you have to provide that too.

For example:

        KeySchema=[
            {
                'AttributeName': 'year',
                'KeyType': 'HASH'  # Partition key
            },
            {
                'AttributeName': 'title',
                'KeyType': 'RANGE'  # Sort key
            }
        ]
    response = table.put_item(
       Item={
            'year': year,
            'title': title,
            'info': {
                'plot': plot,
                'rating': rating
            }
        }
    )

Getting Started Developing with Python and DynamoDB