Jamie
Jamie

Reputation: 155

AWS MalformedPolicyDocument when calling the CreateRole operation: This policy contains invalid Json

I'm trying to attach create an IAM role using Python Boto3 SDK however I keep receiving the following error:

An error occurred (MalformedPolicyDocument) when calling the CreateRole operation: This policy contains invalid JSON

This is my method to create_role:

iam = boto3.client('iam')

    try:
        with open('IAMPolicy.json') as json_file:
            template = json.load(json_file)
            template = str(template)

        role = iam.create_role(
            RoleName = iam_role_name,
            AssumeRolePolicyDocument = template,
            Description = iam_role_description
        )
        print(role)
        print('IAM role' + iam_role_name + ' successfully created.')
    except ClientError as e:
        print(e)
        sys.exit('Exiting the system because IAM role creation failed.')

And here is my example role I am trying to create.

{
   "Version": "2012-10-17",
   "Statement": [
      {
         "Effect": "Allow",
         "Action": [
            "s3:PutObject",
            "s3:PutBucketNotification",
            "s3:PutBucketPolicy",
            "s3:CreateBucket",
            "s3:GetBucketPolicy"
         ],
         "Resource": [
            "arn:aws:s3:::*/*",
            "arn:aws:s3:::mybucket1729788"
         ]
      }
   ]
}

The policy is valid according to IAM Management policy validator in the console so I'm not sure where I'm going wrong. Anyone able to help?

Upvotes: 1

Views: 2495

Answers (2)

smac2020
smac2020

Reputation: 10704

Your JSON does not look valid. I used this JSON and it worked fine:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::81454804xxxx:user/PowerUserxxxx"
      },
      "Action": "sts:AssumeRole",
      "Condition": {}
    }
  ]
}

More information here: How to use trust policies with IAM roles.

I just tested this trusted policy via Java code and it worked perfectly.

import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import software.amazon.awssdk.services.iam.model.*;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.iam.IamClient;

import java.io.FileReader;

public class CreateRole {

    public static void main(String[] args) {

        final String USAGE = "\n" +
                "Usage:\n" +
                "    CreateRole <rolename> <fileLocation> \n\n" +
                "Where:\n" +
                "    rolename - the name of the role to create. \n\n" +
                "    fileLocation - the location of the JSON document that represents the trust policy. \n\n" ;

        if (args.length != 2) {
            System.out.println(USAGE);
            System.exit(1);
        }

        String rolename = args[0];
        String fileLocation = args[1];
        Region region = Region.AWS_GLOBAL;
        IamClient iam = IamClient.builder()
                .region(region)
                .build();

        String result = createIAMRole(iam, rolename, fileLocation) ;
        iam.close();
    }

    public static String createIAMRole(IamClient iam, String rolename, String fileLocation ) {

        try {

            JSONObject jsonObject = (JSONObject) readJson(fileLocation);

            CreateRoleRequest request = CreateRoleRequest.builder()
                    .roleName(rolename)
                    .assumeRolePolicyDocument(jsonObject.toJSONString())
                    .description("Created using the AWS SDK for Java")
                    .build();

            CreateRoleResponse response = iam.createRole(request);
            System.out.println("The ARN of the role is "+response.role().arn());

        } catch (IamException e) {
            System.err.println(e.awsErrorDetails().errorMessage());
            System.exit(1);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }

    public static Object readJson(String filename) throws Exception {
        FileReader reader = new FileReader(filename);
        JSONParser jsonParser = new JSONParser();
        return jsonParser.parse(reader);
    }
}

Upvotes: 1

samtoddler
samtoddler

Reputation: 9615

The trouble is you are providing an IAM Policy when you are supposed to provide a Trust Policy for the IAM role while creating the role, create_role something like below:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::111122223333:root"
      },
      "Action": "sts:AssumeRole",
      "Condition": {}
    }
  ]
}

Trust policy

A JSON policy document in which you define the principals that you trust to assume the role. A role trust policy is a required resource-based policy that is attached to a role in IAM. The principals that you can specify in the trust policy include users, roles, accounts, and services

Below is an example


assume_role_policy_document = json.dumps({
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::111122223333:root"
      },
      "Action": "sts:AssumeRole",
      "Condition": {}
    }
  ]
})


create_role_response = iam.create_role(
    RoleName = "myrolenamee,
    AssumeRolePolicyDocument = assume_role_policy_document
)

After creating the role you attach your custom policy, using attach_role_policy

response = iam.attach_role_policy(
    RoleName='myrolename',
    PolicyArn='arn:aws:iam::123456789012:policy/mycustompolicy'
)

Roles terms and concepts

How to use trust policies with IAM roles

Creating a role to delegate permissions to an AWS service

Upvotes: 0

Related Questions