Skip to content

AWS IAM: Creating Custom Policies


AWS IAM
For more information on AWS IAM, visit aws.amazon.com


AWS Policy Description


AWS Identity and Access Management or IAM is the centralized service within AWS that handles Authentication for various AWS services. When creating a user or a role in IAM, permissions are granted with policies that are either attached to a user, a group, or a role. AWS pre-defines a lot of access policies, but sometimes the pre-canned policies are not adequate for a desired use case, in which case a custom policy can be built that can be attached to a user, group, or role, that can fit the desired use case exactly.


Policy Creation Pre-Requisites


The only pre-requisite for creating a custom access policy is to have an active AWS account that you have access to and can log in to follow along with this tutorial.


Creating a Policy from the Console


Policies are created as part of IAM, In order to create a custom policy, we will need to first navigate to the IAM console within our AWS account.


1.    Log into your AWS account:
Open a browser window and visit the AWS Console Page


2.    Locate and navigate to the IAM Service:
From the top left side of the navigational menu bar, click on the Services menu, and then choose IAM by either navigating to the Security, Identity, and Compliance section of the listed services, or by typing the first few letters of the service name in the search box, and then choosing it from the filtered list.


IAM


3.    Creating a Policy:
From the IAM console dashboard, click on Policies in the right side navigational menu to see a list of all available managed policies. From the Policies view, click on the Create policy button to start the process of creating a new custom policy.


IAM Dashboard

IAM Create Policy


4.    Choose Policy Service:
Next, we need to select the service that will granted access to by the policy, actions that specified resources will be allowed to take against the service, resources that the policy will allow to execute specified actions against the specified service, and optionally any conditions or circumstances under which the policy will grant those permissions. In this example we are going to construct a custom policy that will allow a defined (Resource), the ability to List Functions, and List Tags (Action), against the Lambda Service (Service). There are two ways to construct a policy. The first way is to use the Policy Visual Editor, which is the default way we can easily define a policy. The second way is to click on the JSON tab, and to paste a pre-constructed policy in JSON format into the editor. For the purpose of this tutorial, we will simply use the Visual Editor to construct our policy.


In the Service section, use the filter box to search for and select Lambda


IAM Policy Service


Next, in the Actions section, choose the actions that we will allow a later defined resource to perform against the Lambda service. In this example we want to allow our defined resource(s), the List Function and List Tag action permissions on the Lambda service. So in the Actions section of the Create policy wizard (1), click Select actions, and then expand the List section of the Access level actions (2), and select ListFunctions from the available options. Next, Expand the Read section, and select the ListTags action (3).


IAM Policy Actions


Note

For this example we are not expanding and or selecting anything from either the Write, or Permissions management sections because we want to keep this example policy simple. In a real world example, we may have a set of various List/Read/Write/Manage actions that we want to allow resources to access on the service. In that use case, you can of course specify any or all of the List/Read/Write/Manage permissions that fit your use case to be included in the same policy.


Next, click into the Resources section, from here, we can choose the specific resources that we want to allow our selected actions to be performed by. We can get granular in this section and select individual resources by selecting Specific, under the resource type, and then clicking on the Add ARN link, or we can be less granular and select All resources. The specific resource type will be determined by the Role, once created, more than the policy, meaning that if in the resource selection section, we select All resources, then the 'all resources' will apply to the role service that we select when we construct the role. For example once we complete this policy, if we create a role, and select EC2 as the role service, then applying this policy with All resources selected, would indicate that the resource is any EC2 instance, inherited from the role service, as opposed to a single EC2 instance which we could define by selecting Specific and clicking the Add ARN link in the policy resource section, and selecting a very specific resource via its ARN. Again, to keep things simple, lets select All Resources.


IAM All Policy Resources


Example of selecting a specific ARN resource:


IAM Specific Policy Resource


Last, if we want to specify any conditions, then we can click on the Request conditions section and define things such as requiring MFA, or Source IP addresses, etc. For this example we will not set any conditions, and instead just press the Review policy button.


IAM Policy Conditions


5.    Name and the Review the Policy:
Next, in the Review policy page, Type a name and description for your new policy, review the permissions that the policy will grant, and then click the Create policy button.


IAM Review Policy


6.    Verify the new Policy:
Now that the policy has been created, we just want to verify that the policy is now available in the main policies dashboard. When the policy is created by clicking on the Create policy button, your returned back to the main dashboard view. From the IAM Policies dashboard, type the name of the new policy that was just created inoto the search filter, and verify that it appears in the filtered policy list.


IAM Verify Policy


Creating a Policy from the CLI


Now that we have walked through creating the policy in the AWS console, lets walk through a quick example on how to create this same policy using the AWS CLI.


1.    Create the policy:
First we need to create the policy, to instantiate the new custom policy, use the following syntax:


Syntax:

aws iam create-policy --path {PATH} \
--policy-name {PolicyName} \
--description {"PolicyDescription String"} \
--policy-document {"Policy InLine Trust Policy JSON or File Location"}


Example Request:

aws iam create-policy --path / \
--policy-name Test_Lambda_List_Tags_CLI \
--description "Policy to allow access to List Functions and List Tags applied to Functions." \
--policy-document "{\"Version\": \"2012-10-17\",\"Statement\": [{\"Sid\": \"VisualEditor0\",\"Effect\": \"Allow\",\"Action\": [\"lambda:ListFunctions\",\"lambda:ListTags\"],\"Resource\": \"*\"}]}"

Example Response:

{
    "Policy": {
        "PolicyName": "Test_Lambda_List_Tags_CLI",
        "PolicyId": "ABCDEFGHIJ1234567KLM7",
        "Arn": "arn:aws:iam::123456789012:policy/Test_Lambda_List_Tags_CLI",
        "Path": "/",
        "DefaultVersionId": "v1",
        "AttachmentCount": 0,
        "IsAttachable": true,
        "CreateDate": "2018-08-04T18:16:51.844Z",
        "UpdateDate": "2018-08-04T18:16:51.844Z"
    }
}


2.    Verify New Policy:
Now that we have instantiated the policy, we need to verify that the policy was added successfully. We can do this with the list-policies cli command, mixed with a little JQ magic.


Syntax:

aws iam list-policies --scope Local | jq '.Policies[] | select(.PolicyName == "{FUNCTION_NAME}")'


Example Request:

aws iam list-policies --scope Local | jq '.Policies[] | select(.PolicyName == "Test_Lambda_List_Tags_CLI")'

Example Response:

{
  "PolicyName": "Test_Lambda_List_Tags_CLI",
  "PolicyId": "ABCDEFGHIJ1234567KLM7",
  "Arn": "arn:aws:iam::123456789012:policy/Test_Lambda_List_Tags_CLI",
  "Path": "/",
  "DefaultVersionId": "v1",
  "AttachmentCount": 0,
  "IsAttachable": true,
  "CreateDate": "2018-08-04T18:16:51Z",
  "UpdateDate": "2018-08-04T18:16:51Z"
}


Creating a Policy with CloudFormation


Create Managed Policy CloudFormation Template

The following cloudformation template example will create a policy identical the policy created in the above example. Upon completion, the policy can be verified/modified by going to IAM and clicking on Policies from the left menu. The policy is available to be applied to any role, user, or group.

AWSTemplateFormatVersion: "2010-09-09"
Description: "This cloudformation template will create a managed policy allowing access to Lambda for List Fn, and List Tag requests"

#####################
# Define Parameters
#####################
Parameters:
  PolicyName:
    Type: String
    Description: The name that will be applied to the custom policy.

  PolicyDescription:
    Type: String
    Description: Type a description for this policy. This can NOT be changed after initial assignment.

#####################
# Define Resources
#####################
Resources: 
  # ---------------------
  # Define Policy Resource
  # ---------------------
  ManagedPolicy:
    Type: "AWS::IAM::ManagedPolicy"
    Properties: 
      ManagedPolicyName: !Ref PolicyName
      Description: !Ref PolicyDescription
      Path: "/"
      PolicyDocument:
        Version: "2012-10-17"
        Statement: 
          - 
            Effect: "Allow"
            Action: 
              - "lambda:ListFunctions"
              - "lambda:ListTags"
            Resource: "*"

#####################
# Define Outputs:
#####################
Outputs:
  PolicyName:
    Description: The name of the newly created managed policy
    Value: !Ref PolicyName


Role with Attached Managed Custom Policy CloudFormation Template

The following cloudformation template example will create a role that contains a custom managed policy identical the policy created in the above example. Upon completion, both the policy and the role can be verified/modified by going to IAM and clicking on Policies/Roles respectively from the left menu. The policy is available to be applied to any role, user, or group.

AWSTemplateFormatVersion: "2010-09-09"
Description: "This cloudformation template will create a managed policy allowing access to Lambda for List Fn, and List Tag requests, and will assign it to a newly created role"

#####################
# Define Parameters
#####################
Parameters:
  RoleName:
    Type: String
    Description: The name that will be applied to the Role.

  SessionDuration:
    Type: String
    Description: The maximum session duration (in seconds) for the specified role. Minimum value of 3600. Maximum value of 43200
    Default: 3600

  PolicyName:
    Type: String
    Description: The name that will be applied to the custom policy.

  PolicyDescription:
    Type: String
    Description: Type a description for this policy. This can NOT be changed after initial assignment.

#####################
# Define Resources
#####################
Resources: 
  # ---------------------
  # Define Role Resource
  # ---------------------
  Role: 
    Type: "AWS::IAM::Role"
    Properties: 
      RoleName: !Ref RoleName
      AssumeRolePolicyDocument: 
        Version: "2012-10-17"
        Statement: 
          - 
            Effect: "Allow"
            Principal: 
              Service: 
                - "ec2.amazonaws.com"
            Action: 
              - "sts:AssumeRole"
      Path: "/"
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/AmazonS3FullAccess
      MaxSessionDuration: !Ref SessionDuration

  # ---------------------
  # Define Policy Resource
  # ---------------------
  ManagedPolicy:
    Type: "AWS::IAM::ManagedPolicy"
    DependsOn: "Role"
    Properties: 
      ManagedPolicyName: !Ref PolicyName
      Description: !Ref PolicyDescription
      Path: "/"
      PolicyDocument:
        Version: "2012-10-17"
        Statement: 
          - 
            Effect: "Allow"
            Action: 
              - "lambda:ListFunctions"
              - "lambda:ListTags"
            Resource: "*"
      Roles: 
        - !Ref Role

  # -------------------------------
  # Define Instance Profile Resource
  # -------------------------------
  InstanceProfile: 
    Type: "AWS::IAM::InstanceProfile"
    Properties: 
      Path: "/"
      Roles: 
        - !Ref Role

#####################
# Define Outputs:
#####################
Outputs:
  PolicyName:
    Description: The name of the newly created managed policy
    Value: !Ref PolicyName
  RoleName:
    Description: The name of the newly created role
    Value: !Ref RoleName
  RoleARN:
    Description: The ARN of the newly created role
    Value: !GetAtt Role.Arn
  InstanceProfileArn:
    Description: The ARN of the newly created Instance Profile.
    Value: !GetAtt InstanceProfile.Arn


Role with InLine Policy CloudFormation Template

The following cloudformation template example will create a role that contains a custom in-line policy identical the policy created in the above example. Upon completion, the role can be verified/modified by going to IAM and clicking on Roles from the left menu. The policy is only available within the created role, in-line, meaning that it can NOT be applied to any other roles, users, or groups. It is available as part of the new role ONLY.

AWSTemplateFormatVersion: "2010-09-09"
Description: "This cloudformation template will create a role with a custom in-line policy allowing access to Lambda for List Fn, and List Tag requests"

#####################
# Define Parameters
#####################
Parameters:
  RoleName:
    Type: String
    Description: The name that will be applied to the Role.

  SessionDuration:
    Type: String
    Description: The maximum session duration (in seconds) for the specified role. Minimum value of 3600. Maximum value of 43200
    Default: 3600

  PolicyName:
    Type: String
    Description: The name that will be applied to the custom policy.

#####################
# Define Resources
#####################
Resources: 
  # ---------------------
  # Define Role Resource
  # ---------------------
  Role: 
    Type: "AWS::IAM::Role"
    Properties: 
      RoleName: !Ref RoleName
      AssumeRolePolicyDocument: 
        Version: "2012-10-17"
        Statement: 
          - 
            Effect: "Allow"
            Principal: 
              Service: 
                - "ec2.amazonaws.com"
            Action: 
              - "sts:AssumeRole"
      Path: "/"
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/AmazonS3FullAccess
      MaxSessionDuration: !Ref SessionDuration

  # ---------------------
  # Define Policy Resource
  # ---------------------
  Policy:
    DependsOn: "Role"
    Type: "AWS::IAM::Policy"
    Properties: 
      PolicyName: !Ref PolicyName
      PolicyDocument:
        Version: "2012-10-17"
        Statement: 
          - 
            Effect: "Allow"
            Action: 
              - "lambda:ListFunctions"
              - "lambda:ListTags"
            Resource: "*"
      Roles:
        -
          !Ref Role

  # -------------------------------
  # Define Instance Profile Resource
  # -------------------------------
  InstanceProfile: 
    Type: "AWS::IAM::InstanceProfile"
    Properties: 
      Path: "/"
      Roles: 
        - !Ref Role

#####################
# Define Outputs:
#####################
Outputs:
  RoleName:
    Description: The name of the newly created role
    Value: !Ref RoleName
  RoleARN:
    Description: The ARN of the newly created role
    Value: !GetAtt Role.Arn
  InstanceProfileArn:
    Description: The ARN of the newly created Instance Profile.
    Value: !GetAtt InstanceProfile.Arn


IAM Policies Additional Resources


No Additional Resources.


Role Site/Information References


AWS CloudFormation: Roles Documentation
AWS CloudFormation: Policy Documentation
AWS CloudFormation: Managed Policy Documentation


Comments