Roles
A role is a mechanism that allows applications to request temporary security credentials on a user or application’s behalf.
This is the multi-page printable view of this section. Click here to print.
A role is a mechanism that allows applications to request temporary security credentials on a user or application’s behalf.
To create a role for a Eucalyptus instance, you must first create a trust policy that you can use for it.
You can create trust policies in two ways:
Create a trust policy file with the contents below and save it in a text file called role-trust-policy.json
:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": { "Service": "ec2.amazonaws.com"},
"Action": "sts:AssumeRole"
}
]
}
Create the role using the euare-rolecreate
command, specifying the trust policy file that was previously created:
# euare-rolecreate --role-name describe-instances -f role-trust-policy.json
# euare-rolelistbypath
arn:aws:iam::408396244283:role/describe-instances
Proceed with applying an access policy to a role.
The other way to create the role is to use the command line options to specify the trust policy:Issue the following string on the command line:
# euare-rolecreate --role-name describe-instances --service http://compute.acme.eucalyptus-systems.com:8773/
# euare-rolelistbypath
arn:aws:iam::408396244283:role/describe-instances
Proceed with applying an access policy to a role.
Create a policy and save it in a text file with a .json
extension. The following example shows a policy that allows listing the contents of an S3 bucket called “mybucket”:
{
"Statement": [
{
"Action": [
"s3:ListBucket"
],
"Effect": "Allow",
"Resource": "arn:aws:s3:::mybucket"
}
]
}
euare-roleuploadpolicy
command, passing in the filename of the policy you created in the previous step: euare-roleuploadpolicy --role-name mytestrole --policy-name s3-list-bucket --policy-document my-test-policy.json
You can use the AWS Java SDK to programmatically perform IAM role-related operations in your Eucalyptus cloud. This example shows how to use the AWS SDK to retrieve the credentials for the IAM role associated with the Eucalyptus instance.The following program lists the contents of the bucket “my-test-bucket” using the credentials stored in the Java system properties:
import com.amazonaws.auth.*;
import com.amazonaws.AmazonClientException;
import com.amazonaws.AmazonServiceException;
import com.amazonaws.auth.AWSCredentialsProvider;
import com.amazonaws.auth.ClasspathPropertiesFileCredentialsProvider;
import com.amazonaws.services.ec2.AmazonEC2;
import com.amazonaws.services.ec2.AmazonEC2Client;
import com.amazonaws.services.s3.*;
import com.amazonaws.services.s3.model.*;
public class MyTestApp {
static AmazonEC2 ec2;
static AmazonS3 s3;
private static void init() throws Exception {
AWSCredentialsProvider credentials = new ClasspathPropertiesFileCredentialsProvider();
s3 = new AmazonS3Client(credentials);
s3.setEndpoint("http://128.0.0.1:8773/services/Walrus");
}
public static void main(String[] args) throws Exception {
init();
try {
String bucketName = "my-test-bucket";
System.out.println("Listing bucket " + bucketName + ":");
ListObjectsRequest listObjectsRequest = new ListObjectsRequest(bucketName, "", "", "", 200);
ObjectListing bucketList;
do {
bucketList = s3.listObjects(listObjectsRequest);
for (S3ObjectSummary objectInfo :
bucketList.getObjectSummaries()) {
System.out.println(" - " + objectInfo.getKey() + " " +
"(size = " + objectInfo.getSize() +
")");
}
listObjectsRequest.setMarker(bucketList.getNextMarker());
} while (bucketList.isTruncated());
} catch (AmazonServiceException eucaServiceException ) {
System.out.println("Exception: " + eucaServiceException.getMessage());
System.out.println("Status Code: " + eucaServiceException.getStatusCode());
System.out.println("Error Code: " + eucaServiceException.getErrorCode());
System.out.println("Request ID: " + eucaServiceException.getRequestId());
} catch (AmazonClientException eucaClientException) {
System.out.println("Error Message: " + eucaClientException.getMessage());
}
System.out.println("===== FINISHED =====");
}
}
This application produces output similar to the following:
Listing bucket my-test-bucket:
- precise-server-cloudimg-amd64-vmlinuz-virtual.manifest.xml (size = 3553)
- precise-server-cloudimg-amd64-vmlinuz-virtual.part.0 (size = 4904032)
- precise-server-cloudimg-amd64.img.manifest.xml (size = 7014)
- precise-server-cloudimg-amd64.img.part.0 (size = 10485760)
- precise-server-cloudimg-amd64.img.part.1 (size = 10485760)
- precise-server-cloudimg-amd64.img.part.10 (size = 10485760)
- precise-server-cloudimg-amd64.img.part.11 (size = 10485760)
- precise-server-cloudimg-amd64.img.part.12 (size = 10485760)
- precise-server-cloudimg-amd64.img.part.13 (size = 10485760)
- precise-server-cloudimg-amd64.img.part.14 (size = 10485760)
- precise-server-cloudimg-amd64.img.part.15 (size = 10485760)
- precise-server-cloudimg-amd64.img.part.16 (size = 10485760)
- precise-server-cloudimg-amd64.img.part.17 (size = 10485760)
- precise-server-cloudimg-amd64.img.part.18 (size = 10485760)
- precise-server-cloudimg-amd64.img.part.19 (size = 10485760)
- precise-server-cloudimg-amd64.img.part.2 (size = 10485760)
- precise-server-cloudimg-amd64.img.part.20 (size = 10485760)
- precise-server-cloudimg-amd64.img.part.21 (size = 10485760)
- precise-server-cloudimg-amd64.img.part.22 (size = 2570400)
- precise-server-cloudimg-amd64.img.part.3 (size = 10485760)
- precise-server-cloudimg-amd64.img.part.4 (size = 10485760)
- precise-server-cloudimg-amd64.img.part.5 (size = 10485760)
- precise-server-cloudimg-amd64.img.part.6 (size = 10485760)
- precise-server-cloudimg-amd64.img.part.7 (size = 10485760)
- precise-server-cloudimg-amd64.img.part.8 (size = 10485760)
- precise-server-cloudimg-amd64.img.part.9 (size = 10485760)
===== FINISHED =====
The problem with this approach is that the credentials are hardcoded into the application - this makes them less secure, and makes the application more difficult to maintain. Using IAM roles is a more secure and easier way to manage credentials for applications that run on Eucalyptus cloud instances.
Create a role with a policy that allows an instance to list the contents of a specific bucket, and then launch an instance with that role (for an example, see Launch an Instance with a Role . An example policy that allows listing of a specific bucket will look similar to the following:
{
"Statement": [
{
"Action": [
"s3:ListBucket"
],
"Effect": "Allow",
"Resource": "arn:aws:s3:::my-test-bucket"
}
]
}
The following line of code retrieves the credentials that are stored in the application’s credentials profile: AWSCredentialsProvider credentials = new ClasspathPropertiesFileCredentialsProvider();
To use the role-based credentials associated with the instance, replace that line of code with the following: AWSCredentialsProvider credentials = new InstanceProfileCredentialsProvider();
The program now looks like this:
import com.amazonaws.auth.*;
import com.amazonaws.AmazonClientException;
import com.amazonaws.AmazonServiceException;
import com.amazonaws.auth.AWSCredentialsProvider;
import com.amazonaws.auth.ClasspathPropertiesFileCredentialsProvider;
import com.amazonaws.services.ec2.AmazonEC2;
import com.amazonaws.services.ec2.AmazonEC2Client;
import com.amazonaws.services.s3.*;
import com.amazonaws.services.s3.model.*;
public class MyTestApp {
static AmazonEC2 ec2;
static AmazonS3 s3;
private static void init() throws Exception {
AWSCredentialsProvider credentials = new InstanceProfileCredentialsProvider();
s3 = new AmazonS3Client(credentials);
s3.setEndpoint("http://128.0.0.1:8773/services/Walrus");
}
public static void main(String[] args) throws Exception {
init();
try {
String bucketName = "my-test-bucket";
System.out.println("Listing bucket " + bucketName + ":");
ListObjectsRequest listObjectsRequest = new ListObjectsRequest(bucketName, "", "", "", 200);
ObjectListing bucketList;
do {
bucketList = s3.listObjects(listObjectsRequest);
for (S3ObjectSummary objectInfo :
bucketList.getObjectSummaries()) {
System.out.println(" - " + objectInfo.getKey() + " " +
"(size = " + objectInfo.getSize() +
")");
}
listObjectsRequest.setMarker(bucketList.getNextMarker());
} while (bucketList.isTruncated());
} catch (AmazonServiceException eucaServiceException ) {
System.out.println("Exception: " + eucaServiceException.getMessage());
System.out.println("Status Code: " + eucaServiceException.getStatusCode());
System.out.println("Error Code: " + eucaServiceException.getErrorCode());
System.out.println("Request ID: " + eucaServiceException.getRequestId());
} catch (AmazonClientException eucaClientException) {
System.out.println("Error Message: " + eucaClientException.getMessage());
}
System.out.println("===== FINISHED =====");
}
}
NOTE: Running this code outside of an instance will result in the following error message:
Listing bucket my-test-bucket:
Error Message: Unable to load credentials from Amazon EC2 metadata service
When the application is running on an instance that was launched with the role you created, the credentials for the role assigned to the instance will be retrieved from the Instance Metadata Service.
A role is assigned a specific set of tasks and permissions. Users may assume a different role than the one they have in order to perform a different set of tasks. For example, the primary administrator is unavailable and the backup administrator is asked to assume the role of the primary administrator during his or her absence. A few points to consider before assuming a role:
The scenario described in this section outlines the procedure for creating a role in order to delegate permissions to an IAM user.Create a role that allows users of an account to manage keypairs. Management of keypairs include the following EC2 actions:
CreateKeyPair
DeleteKeyPair
DescribeKeyPairs
ImportKeyPair Create a role for managing keypairs for the account. In this example, the admin user of ‘devops’ account (001827830003) is creating the role:
{ “Version”: “2012-10-17”, “Statement”: [{ “Effect”: “Allow”, “Principal”: {“AWS”: “arn:aws:iam::001827830003:root”}, “Action”: “sts:AssumeRole” }] }
Add IAM access policy for keypair management to the role:
# cat keypair-mgmt-policy.json
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt1445362739663",
"Action": [
"ec2:CreateKeyPair",
"ec2:DeleteKeyPair",
"ec2:DescribeKeyPairs",
"ec2:ImportKeyPair"
],
"Effect": "Allow",
"Resource": "*"
}
]
}
# euare-roleuploadpolicy --policy-name ec2-keypair-actions --policy-document keypair-mgmt-policy.json devops-ec2-keypair-mgmt-role --region devops-admin@future
Now that the role has been created, follow the AWS IAM best practice of using groups to assign permission to IAM users and attach an IAM access policy to the group to allow any members (example shows ‘user01’ user) to assume the ‘devops-ec2-keypair-mgmt-role’ role:
# euare-groupcreate -g Key-Managers --region devops-admin@future
# euare-groupadduser -u user01 -g Key-Managers --region devops-admin@future
# cat devops-keypair-mgmt-assume-role-policy.json
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Resource": "arn:aws:iam::001827830003:role/devops-ec2-keypair-mgmt-role"
}]
}
# euare-groupuploadpolicy -p keypair-mgmt-role-perm -f devops-keypair-mgmt-assume-role-policy.json Key-Managers --region devops-admin@future
Now that members can assume the ‘devops-ec2-keypair-mgmt-role’ role, run the following command to list all keypairs under the account:
# eval `/usr/bin/euare-assumerole devops-ec2-keypair-mgmt-role --region devops-user01@future`
# euca-describe-keypairs --region @future
KEYPAIR devops-admin 9e:1a:bc:ac:98:b1:97:7c:65:b0:b3:7c:96:f5:d5:7b:a1:3e:36:a6
When done assuming the role, the role must be released using euare-releaserole
:
# eval `/usr/bin/euare-releaserole --region devops-user01@future`
A role can be used to delegate access to resources that are in different accounts that you own.Using roles to access resources across different accounts allows users to assume a role that can access all the resources in in different acccounts, rather than having users log into different accounts to achieve the same result.
The scenario described in this section outlines the procedure for a user in Account B to create a role that provides access to a particular OSGObject Storage Gateway (OSG) bucket owned by Account B, which can be assumed by user in Account A.Using s3cmd , list bucket that will be shared through role:
# ./s3cmd/s3cmd --config=.s3cfg-acctB-user11 ls s3://mongodb-snapshots
2014-12-01 22:34 188563920 s3://mongodb-snapshots/mongodb-backup-monday.img.xz
2014-12-02 13:34 188564068 s3://mongodb-snapshots/mongodb-backup-tuesday.img.xz
Create Role in Account B with Trust Policy for User from Account A:
# cat acctB-role-trust-acctA-policy.json
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": {"AWS": "arn:aws:iam::290122656840:user/user01"},
"Action": "sts:AssumeRole"
}]
}
# euare-rolecreate --role-name cross-bucket-access-mongodb-logs --policy-document acctB-role-trust-acctA-policy.json
Upload IAM Access Policy for Role in Account B:
# cat acctB-mongodb-snapshots-bucket-access-policy.json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "s3:ListBucket",
"Resource": "arn:aws:s3:::mongodb-snapshots"
},
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:DeleteObject"
],
"Resource": "arn:aws:s3:::mongodb-snapshots/*"
}
]
}
# euare-roleuploadpolicy --role-name cross-bucket-access-mongodb-logs --policy-document acctB-mongodb-snapshots-bucket-access-policy.json --policy-name mongodb-logs-bucket-access
Upload IAM access policy to Group (e.g. Testers) associated with user in Account A to allow for Role in Account B to be assumed. For more information, go to Amazon Web Services IAM Best Practices .
# cat acctA-assume-role-acctB-policy.json
{
"Statement": [
{
"Sid": "Stmt1417531456446",
"Action": [
"sts:AssumeRole"
],
"Effect": "Allow",
"Resource": "arn:aws:iam::325271821652:role/cross-bucket-access-mongodb-logs"
}
]
}
# euare-groupuploadpolicy --policy-name mongodb-bucket-access-role --group-name Testers --policy-document acctA-assume-role-acctB-policy.json
The example below demonstrates how to use a python script leveraging the boto library. Another way to assume this role is to run the Euca2ools command, euare-assumerole
, using the AccountA/user01 credentials. For more information regarding assuming a role, see an example from the Assume a Role section. The script below performs the following actions:
Accesses STS to get temporary access key, secret key and token
List contents of bucket “mongodb-snapshots”
======================= #!/bin/env python
import boto from boto.sts import STSConnection from boto.s3.connection import S3Connection from boto.s3.connection import OrdinaryCallingFormat
if name == “main”:
"""
Assuming ‘cross-bucket-access-mongodb-logs’ role by AccountA, User01 user
"""
STSConnection.DefaultRegionEndpoint = “tokens.future.euca-hasp.cs.prc.eucalyptus-systems.com”
sts_connection = STSConnection(aws_access_key_id="
s3 = S3Connection(aws_access_key_id=assumedRoleObject.credentials.access_key,
aws_secret_access_key=assumedRoleObject.credentials.secret_key,
security_token=assumedRoleObject.credentials.session_token,
host="objectstorage.future.euca-hasp.cs.prc.eucalyptus-systems.com",
is_secure=False, port=8773, calling_format=OrdinaryCallingFormat())
bucket_name = "mongodb-snapshots"
bucket = s3.lookup(bucket_name)
if bucket:
print "Bucket Information [%s]:" % bucket_name
print "------------------------------------------------------------"
for key in bucket:
print "\t" + key.name
else:
print "Bucket is not available: " + bucket_name + "\n"
==================
Run the script:
# ./describe-bucket-script.py
Bucket Information [mongodb-snapshots]:
------------------------------------------------------------
mongodb-backup-monday.img.xz
mongodb-backup-tuesday.img.xz