AWS Session Policy

AWS Session Policy

AWS Session policy is a limiting AWS policy, which limits the maximum permission for a particular AWS session (assumed role session or user federated session). It is very similar to Permissions Boundary and Service Control Policy (SCP) in the way that instead of granting or revoking permissions, it is used to limit the total permissions. But the way it differs from them is that instead of applying these maximum permissions to an identity like user or role (in the case of Permissions Boundary) or to an account or OU (in the case of SCP), Session policy applies the maximum permissions to an assumed session. 

At the time of the writing of this article, an assumed session in this context which has support for AWS session policies can come from one of the following ways : 

  • Assumed Role from an IAM user or another role
  • Assumed Role through an Enterprise SAML Identity provider
  • Assumed Role through a web-based identity provider like Amazon, Google, Facebook, etc. 
  • Federated User from an IAM user or AWS Root user

To put it simply, whenever you are assuming a role or federating a user (creating temporary credentials for a user), you are creating a temporary session from those identities and you will be given an opportunity to supply Session policies to restrict permissions in those specific time-bound sessions. The policy follows the same JSON structure as other policy types with standard elements, please refer to an example below:

The following session policy sets the maximum permission for the session its applied to be only able to list a single Amazon S3 bucket named example_bucket:

{
  "Version": "2012-10-17",
  "Statement": {
    "Effect": "Allow",
    "Action": "s3:ListBucket",
    "Resource": "arn:aws:s3:::example_bucket"
  }
}

A real use case for Session policies

Before you read this, keep in mind that Session policies are advanced AWS policies so this scenario might be a little complicated for some, but it presents a very real use case of how Session policies are used by Organizations today. 

We are taking the example of a mature software company that uses Federated identities to login to AWS, meaning the users are not created in AWS, but are leveraged from the company’s Identity portal. Employees first login using their corporate credentials to the SSO portal. Once the employee’s login is verified, they select the AWS account and the IAM role which they want to access. And if they have been granted permissions to access that AWS account, SSO portal uses its native AWS identity to assume the requested role on user’s behalf, and sends 2 things back to the user – url for login to the AWS console and the credentials to access AWS CLI (aws access key, secret access key and session token). Here is a diagram showing this in action:

DESIGN FOR AWS SINGLE SIGN ON (SSO) USING CORPORATE IDENTITY

So coming to the Security scenario. In light of the recent security breach at this company due to unauthorized access of cloud resources from a leak of AWS security credentials via an exposed Git repo, the Security Leadership have given the following policy mandate – “Any user accessing corporate infrastructure or resources including Cloud systems via the command-line can only be allowed to make such an access from a Corporate Bastion system.” This is specifically to prevent the risk of unauthorized access via exposed command-line secrets like AWS access key, secret and session token. This makes total sense from a security perspective, as even though your adversaries may have your stolen AWS session credentials, they still can’t access anything if the access is restricted for any source IP address not in the Corporate Bastion IP address ranges. And there is no logical reason to put this restriction on the console access as the urls don’t run the same risk of loss of credentials via Git repos, and it would impact developer productivity if they are only allowed to access AWS console from Bastion. In order to implement the source IP restriction, we could create a policy like below:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "This_should_exactly_match_the_perms_that_the_assumed_role_needs",
            "Effect": "Allow",
            "Action": "s3:ListBucket",
            "Resource": "arn:aws:s3:::example_bucket"
        },
        {
            "Sid": "Denies_any_access_from_non_bastion_IP_range",
            "Effect": "Deny",
            "Action": "*",
            "Resource": "*",
            "Condition": {
                "NotIpAddress": {
                    "aws:SourceIp": "210.75.12.75/16"
                }
            }
        }
    ]
}

But as we saw in the design of federated AWS SSO using Corporate Identity, the SSO portal was assuming the same AWS role for getting CLI credentials as well as the console url. So we cannot apply the above IAM policy on the AWS role since then it would be applicable to both the CLI access as well as console access. And that’s the problem that Session policies aim to solve as they are used for putting access restrictions on individual sessions created from the same role. So you can solve the security mandate for this design by doing the two things below: 

  • Assume the same role twice once for creating the console url, and other for creating the CLI credentials
  • When you are assuming the role for CLI credentials, pass in a session policy like the one detailed above

Similar to Permission Boundary and SCP, AWS Session policy is also a limiting policy as it sets the maximum permission that a user session can have.

Video Demo

In this demo, we would first assume an AWS Role from an IAM user without an attached session policy. And then, we would attach the session policy to show the differences in residual permissions in the two cases.

Follow us on: