Using Roles in Eucalyptus to control access

By Neil Soman | February 18, 2014

One of the cool new features in Eucalyptus 4.0 is support for IAM Roles. IAM roles let users define a way for applications to request temporary security credentials on the user's behalf. A role has a set of access control policies associated with it, so that an application only has access to the services and resources that are defined by the policy. Policies are defined as JSON documents.

For instance, the following IAM policy allows access to list a S3 bucket with the name "mybucket":

{
"Statement": [
{
"Action": [
"s3:ListBucket"
],
"Effect": "Allow",
"Resource": "arn:aws:s3:::mybucket"
}
]
}

More information on IAM Roles can be found in Amazon's IAM documentation.

The service that is the equivalent of IAM in Eucalyptus is called Euare (I-am, Eu-are, get it?). The API calls we are interested in for IAM roles are:

  • GetRole
  • CreateRole
  • PutRolePolicy
  • AssumeRole
A really interesting thing about the way we have designed access control is Eucalyptus is that IAM accounts and roles can be used for internal communication between Eucalyptus components, in addition to serving user requests. That is, to the service, there is no difference between an API operation requested by an end user, by an application on an end user's behalf, or by another Eucalyptus component.
An example of this usage is in the Storage Controller (SC) code in 4.0. The SC is responsible for implementing EBS functionality in Eucalyptus. Snapshots are stored in S3, or in case of Eucalyptus, via the Object Storage Gateway into either Walrus, or a distributed backend like RiakCS. However, we don't want to give the Storage Controller access to do whatever it wants with buckets and objects. That would be bad, for instance, if the SC were compromised or misbehaving. 
In addition, we would not like to have the notion of "special" internal operations that only Eucalyptus components are allowed to use. That is not good from a security point of view, as well as more paths to test and debug. So we want to simply use the same functionality that is available to end users.
This is where IAM roles enter the picture.
When Eucalyptus first bootstraps, a role for the S3 access for the SC is created in the "blockstorage" account. For example,
                
CreateRoleType createRoleType = new CreateRoleType();
createRoleType.setDelegateAccount(StorageProperties.BLOCKSTORAGE_ACCOUNT);
createRoleType.setAssumeRolePolicyDocument(StorageProperties.DEFAULT_ASSUME_ROLE_POLICY);
createRoleType.setPath("/blockstorage");
createRoleType.setRoleName(StorageProperties.EBS_ROLE_NAME);
CreateRoleResponseType createRoleResponseType = AsyncRequests.sendSync(euare, createRoleType);
Note the reference to DEFAULT_ASSUME_ROLE_POLICY.

To use roles, the user that is trying to "assume" a role needs to be granted access to the AssumeRole API operation. Our assume role policy looks like:

{
"Statement": [
{
"Action": [
"sts:AssumeRole"
],
"Effect": "Allow",
"Principal": {
"Service": [
"s3.amazonaws.com"
]
}
}

Sts stands for Security Token Service. AsyncRequests.sendSync is the way to dispatch messages among components within Eucalyptus. It knows whether a service is local (i.e. on the same host as the client) or remote, but that is a topic for another day.

We then add an access policy for the role that was created earlier. For example,

{
"Statement": [
"Action": [
"s3:CreateBucket",
"s3:ListBucket",
"s3:DeleteBucket",
]
"Effect": "Allow",
"Resource" : "arn:aws:s3:::snapshots"
}

This policy allows access to the s3:CreateBuckets3:CreateBucket and s3:DeleteBucket  operations against the resource arn:aws:s3:::snapshots,which simply put, means that you can create, list or delete the bucket with the name "snapshots"

We can add other policies to this role to allow specific objects to be accessed. That's it.

To use this role, we use the AssumeRole operation. For example,

AssumeRoleType assumeRoleType = new AssumeRoleType();
assumeRoleType.setDurationSeconds((int) TimeUnit.HOURS.toSeconds(1));
assumeRoleType.setRoleSessionName("S3Session");
assumeRoleType.setRoleArn(roleArn);
AssumeRoleResponseType assumeRoleResponseType = AsyncRequests.sendSync(tokens, assumeRoleType);
CredentialsType credentials = assumeRoleResponseType.getAssumeRoleResult().getCredentials();

This gives us temporary credentials that the SC can now use to interact with the OSG to upload and download snapshots. Notice the call to setDurationSeconds. This means that the credentials will expire in a hour and will have to be renewed.

If you an end user, as opposed to a Eucalyptus component, you can use the Amazon AWS SDK to perform the same operations. You can use the CreateRole, PutRolePolicy and AssumeRole using the SDK, which works exactly the same against Eucalyptus as it does against Amazon IAM.

Enjoy and let us know what you think!

Get Started with Eucalyptus

Use FastStart to easily deploy a private cloud on your own machine from a single command!