diff --git a/src/main/java/com/eucalyptus/tests/awssdk/TestAutoScalingValidation.java b/src/main/java/com/eucalyptus/tests/awssdk/TestAutoScalingValidation.java index 45f9ca00..c1f167cf 100644 --- a/src/main/java/com/eucalyptus/tests/awssdk/TestAutoScalingValidation.java +++ b/src/main/java/com/eucalyptus/tests/awssdk/TestAutoScalingValidation.java @@ -1,22 +1,3 @@ -/************************************************************************* - * Copyright 2009-2016 Eucalyptus Systems, Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 3 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see http://www.gnu.org/licenses/. - * - * Please contact Eucalyptus Systems, Inc., 6755 Hollister Ave., Goleta - * CA 93117, USA or visit http://www.eucalyptus.com/licenses/ if you need - * additional information or have any questions. - ************************************************************************/ package com.eucalyptus.tests.awssdk; import com.amazonaws.AmazonServiceException; @@ -33,9 +14,10 @@ /** * This application tests parameter validation for auto scaling. *

- * This is verification for the story: + * This is verification for: *

* https://eucalyptus.atlassian.net/browse/EUCA-5016 + * https://eucalyptus.atlassian.net/browse/EUCA-13035 */ public class TestAutoScalingValidation { @@ -66,6 +48,8 @@ public void run() { assertThat(false, "Expected error when creating launch configuration with invalid name"); } catch (AmazonServiceException e) { print("Got expected exception: " + e); + assertThat( e.getErrorCode( ) != null, "Expected error code" ); + assertThat( e.getErrorMessage( ) != null, "Expected error message" ); } // Create launch configuration with missing required parameter @@ -77,6 +61,8 @@ public void run() { assertThat(false, "Expected error when creating launch configuration with missing parameter"); } catch (AmazonServiceException e) { print("Got expected exception: " + e); + assertThat( e.getErrorCode( ) != null, "Expected error code" ); + assertThat( e.getErrorMessage( ) != null, "Expected error message" ); } // Create launch configuration @@ -106,9 +92,11 @@ public void run() { .withMaxSize(1) .withAvailabilityZones(AVAILABILITY_ZONE) ); - assertThat(false, "Expected error when creating launch group with invalid size"); + assertThat(false, "Expected error when creating scaling group with invalid size"); } catch (AmazonServiceException e) { print("Got expected exception: " + e); + assertThat( e.getErrorCode( ) != null, "Expected error code" ); + assertThat( e.getErrorMessage( ) != null, "Expected error message" ); } // Create scaling group with invalid capacity @@ -122,9 +110,11 @@ public void run() { .withDesiredCapacity(2) .withAvailabilityZones(AVAILABILITY_ZONE) ); - assertThat(false, "Expected error when creating launch group with invalid capacity"); + assertThat(false, "Expected error when creating scaling group with invalid capacity"); } catch (AmazonServiceException e) { print("Got expected exception: " + e); + assertThat( e.getErrorCode( ) != null, "Expected error code" ); + assertThat( e.getErrorMessage( ) != null, "Expected error message" ); } // Create scaling group with invalid tag @@ -143,9 +133,23 @@ public void run() { new Tag().withKey("tag1" + nameSuffix).withValue("propagate").withPropagateAtLaunch(Boolean.TRUE) ) ); - assertThat(false, "Expected error when creating launch group with invalid tag"); + assertThat(false, "Expected error when creating scaling group with invalid tag"); } catch (AmazonServiceException e) { print("Got expected exception: " + e); + assertThat( e.getErrorCode( ) != null, "Expected error code" ); + assertThat( e.getErrorMessage( ) != null, "Expected error message" ); + } + + // Create scaling group with missing required parameter + print("Creating auto scaling group with missing required parameters"); + try { + as.createAutoScalingGroup( new CreateAutoScalingGroupRequest( ) + .withAvailabilityZones( AVAILABILITY_ZONE ) ); + assertThat(false, "Expected error when creating scaling group with missing required parameters"); + } catch (AmazonServiceException e) { + print("Got expected exception: " + e); + assertThat( e.getErrorCode( ) != null, "Expected error code" ); + assertThat( e.getErrorMessage( ) != null, "Expected error message" ); } // Create scaling group @@ -166,6 +170,8 @@ public void run() { assertThat(false, "Expected error when creating tag on invalid group"); } catch (AmazonServiceException e) { print("Got expected exception: " + e); + assertThat( e.getErrorCode( ) != null, "Expected error code" ); + assertThat( e.getErrorMessage( ) != null, "Expected error message" ); } // Register cleanup for launch configs @@ -190,6 +196,8 @@ public void run() { assertThat(false, "Expected error when creating invalid scaling policy"); } catch (AmazonServiceException e) { print("Got expected exception: " + e); + assertThat( e.getErrorCode( ) != null, "Expected error code" ); + assertThat( e.getErrorMessage( ) != null, "Expected error message" ); } // Create invalid scaling policy @@ -203,6 +211,102 @@ public void run() { assertThat(false, "Expected error when creating invalid scaling policy"); } catch (AmazonServiceException e) { print("Got expected exception: " + e); + assertThat( e.getErrorCode( ) != null, "Expected error code" ); + assertThat( e.getErrorMessage( ) != null, "Expected error message" ); + } + + // Update group / set desired capacity with missing parameters + try { + as.updateAutoScalingGroup( new UpdateAutoScalingGroupRequest( ) ); + assertThat(false, "Expected error when updating scaling group without required parameters"); + } catch (AmazonServiceException e) { + print("Got expected exception: " + e); + assertThat( e.getErrorCode( ) != null, "Expected error code" ); + assertThat( e.getErrorMessage( ) != null, "Expected error message" ); + } + try { + as.setDesiredCapacity( new SetDesiredCapacityRequest( ) ); + assertThat(false, "Expected error when setting desired capacity for scaling group without required parameters"); + } catch (AmazonServiceException e) { + print("Got expected exception: " + e); + assertThat( e.getErrorCode( ) != null, "Expected error code" ); + assertThat( e.getErrorMessage( ) != null, "Expected error message" ); + } + + // Enable/disable metrics collection with missing parameters + try { + as.enableMetricsCollection( new EnableMetricsCollectionRequest( ) + .withMetrics( "GroupMinSize" ) + .withGranularity( "1Minute" ) + ); + assertThat(false, "Expected error when enabling metrics collection without required parameters"); + } catch (AmazonServiceException e) { + print("Got expected exception: " + e); + assertThat( e.getErrorCode( ) != null, "Expected error code" ); + assertThat( e.getErrorMessage( ) != null, "Expected error message" ); + } + try { + as.disableMetricsCollection( new DisableMetricsCollectionRequest( ) + .withMetrics( "GroupMinSize" ) ); + assertThat(false, "Expected error when disabling metrics collection without required parameters"); + } catch (AmazonServiceException e) { + print("Got expected exception: " + e); + assertThat( e.getErrorCode( ) != null, "Expected error code" ); + assertThat( e.getErrorMessage( ) != null, "Expected error message" ); + } + + // Suspend/resume scaling processes with missing parameters + try { + as.suspendProcesses( new SuspendProcessesRequest( ) ); + assertThat(false, "Expected error when suspending processes without required parameters"); + } catch (AmazonServiceException e) { + print("Got expected exception: " + e); + assertThat( e.getErrorCode( ) != null, "Expected error code" ); + assertThat( e.getErrorMessage( ) != null, "Expected error message" ); + } + try { + as.resumeProcesses( new ResumeProcessesRequest( ) ); + assertThat(false, "Expected error when resuming processes without required parameters"); + } catch (AmazonServiceException e) { + print("Got expected exception: " + e); + assertThat( e.getErrorCode( ) != null, "Expected error code" ); + assertThat( e.getErrorMessage( ) != null, "Expected error message" ); + } + + // Put / execute scaling policies with missing parameters + try { + as.putScalingPolicy( new PutScalingPolicyRequest( ) ); + assertThat(false, "Expected error when putting scaling policy without required parameters"); + } catch (AmazonServiceException e) { + print("Got expected exception: " + e); + assertThat( e.getErrorCode( ) != null, "Expected error code" ); + assertThat( e.getErrorMessage( ) != null, "Expected error message" ); + } + try { + as.executePolicy( new ExecutePolicyRequest( ) ); + assertThat(false, "Expected error when executing scaling policy without required parameters"); + } catch (AmazonServiceException e) { + print("Got expected exception: " + e); + assertThat( e.getErrorCode( ) != null, "Expected error code" ); + assertThat( e.getErrorMessage( ) != null, "Expected error message" ); + } + + // Set instance health/terminate instance with missing parameters + try { + as.setInstanceHealth( new SetInstanceHealthRequest( ) ); + assertThat(false, "Expected error when setting instance health without required parameters"); + } catch (AmazonServiceException e) { + print("Got expected exception: " + e); + assertThat( e.getErrorCode( ) != null, "Expected error code" ); + assertThat( e.getErrorMessage( ) != null, "Expected error message" ); + } + try { + as.terminateInstanceInAutoScalingGroup( new TerminateInstanceInAutoScalingGroupRequest( ) ); + assertThat(false, "Expected error when terminating scaling instance without required parameters"); + } catch (AmazonServiceException e) { + print("Got expected exception: " + e); + assertThat( e.getErrorCode( ) != null, "Expected error code" ); + assertThat( e.getErrorMessage( ) != null, "Expected error message" ); } print("Test complete"); diff --git a/src/main/java/com/eucalyptus/tests/awssdk/TestSTSAssumeRole.java b/src/main/java/com/eucalyptus/tests/awssdk/TestSTSAssumeRole.java index 84308460..18ce1e5e 100644 --- a/src/main/java/com/eucalyptus/tests/awssdk/TestSTSAssumeRole.java +++ b/src/main/java/com/eucalyptus/tests/awssdk/TestSTSAssumeRole.java @@ -80,7 +80,8 @@ public void STSAssumeRoleTest() throws Exception { // create non-admin user in non-euca account then get credentials and connection for user createAccount(account); createUser(account, user); - createIAMPolicy(account, user, NAME_PREFIX + "policy", null); + createIAMPolicy( account, user, NAME_PREFIX + "policy", + "{\"Statement\":[{\"Effect\":\"Allow\",\"Resource\":\"*\",\"Action\":[\"iam:*\"]}]}" ); // get youAre connection for new user AWSCredentialsProvider awsCredentialsProvider = new StaticCredentialsProvider(getUserCreds(account,user)); @@ -239,11 +240,26 @@ public void STSAssumeRoleTest() throws Exception { } ); // Describe images using role - { + try { final DescribeImagesResult imagesResult = getImagesUsingRole(account, user, roleName, roleArn, "222222222222"); assertThat(imagesResult.getImages().size() > 0, "Image not found when using role"); final String imageId = imagesResult.getImages().get(0).getImageId(); print("Found image: " + imageId); + } catch ( AmazonServiceException e ) { + // TODO this catch block can be removed once this test no longer needs to pass against versions < 5.0 + print( "WARNING" ); + print( "WARNING: Unexpected exception assuming role with valid external id, assuming pre-5.0 behaviour: " + e); + print( "WARNING" ); + print( "Authorizing actions on all services for user " + user ); + createIAMPolicy( account, user, NAME_PREFIX + "policy", null ); + print( "Sleeping to allow policy change to propagate" ); + N4j.sleep( 5 ); + { + final DescribeImagesResult imagesResult = getImagesUsingRole(account, user, roleName, roleArn, "222222222222"); + assertThat(imagesResult.getImages().size() > 0, "Image not found when using role"); + final String imageId = imagesResult.getImages().get(0).getImageId(); + print("Found image: " + imageId); + } } // Describe images using role with incorrect external id @@ -258,7 +274,6 @@ public void STSAssumeRoleTest() throws Exception { "Expected 'Not authorized to perform sts:AssumeRole' error message" ); } - // Get caller identity using user credentials { print("Testing get caller identity for user credentials"); diff --git a/src/main/java/com/eucalyptus/tests/awssdk/TestSTSAssumeRolePolicy.groovy b/src/main/java/com/eucalyptus/tests/awssdk/TestSTSAssumeRolePolicy.groovy new file mode 100644 index 00000000..c129e74c --- /dev/null +++ b/src/main/java/com/eucalyptus/tests/awssdk/TestSTSAssumeRolePolicy.groovy @@ -0,0 +1,450 @@ +package com.eucalyptus.tests.awssdk + +import com.amazonaws.AmazonServiceException +import com.amazonaws.auth.* +import com.amazonaws.internal.StaticCredentialsProvider +import com.amazonaws.services.ec2.AmazonEC2 +import com.amazonaws.services.ec2.AmazonEC2Client +import com.amazonaws.services.ec2.model.CreateSecurityGroupRequest +import com.amazonaws.services.ec2.model.DeleteSecurityGroupRequest +import com.amazonaws.services.ec2.model.DescribeSecurityGroupsResult +import com.amazonaws.services.identitymanagement.AmazonIdentityManagement +import com.amazonaws.services.identitymanagement.AmazonIdentityManagementClient +import com.amazonaws.services.identitymanagement.model.* +import com.amazonaws.services.securitytoken.AWSSecurityTokenService +import com.amazonaws.services.securitytoken.AWSSecurityTokenServiceClient +import com.amazonaws.services.securitytoken.model.AssumeRoleRequest +import com.amazonaws.services.securitytoken.model.GetCallerIdentityRequest +import org.testng.annotations.AfterClass +import org.testng.annotations.Test + +import static com.eucalyptus.tests.awssdk.N4j.CLC_IP +import static com.eucalyptus.tests.awssdk.N4j.NAME_PREFIX + +/** + * Test STS AssumeRole policies. + * + * Test assuming role as a user with only a resource policy (i.e. no user/group policy authorizing role use) + * + * This test covers the issues: + * https://eucalyptus.atlassian.net/browse/EUCA-12957 + */ +class TestSTSAssumeRolePolicy { + + private final int sleepSecs = 1 + private final String host + private final String testAcct + private final AWSCredentialsProvider adminCredentials + private final String otherTestAcct + private final AWSCredentialsProvider otherAdminCredentials + + public TestSTSAssumeRolePolicy( ) { + N4j.getCloudInfo( ) + this.host = CLC_IP + this.testAcct= "${NAME_PREFIX}test-acct" + N4j.createAccount(testAcct) + this.adminCredentials = new StaticCredentialsProvider( N4j.getUserCreds(testAcct, 'admin') ) + + this.otherTestAcct= "${NAME_PREFIX}other-test-acct" + N4j.createAccount(otherTestAcct) + this.otherAdminCredentials = new StaticCredentialsProvider( N4j.getUserCreds(otherTestAcct, 'admin') ) + } + + /** + * Called after all the tests in a class + * + * @throws java.lang.Exception + */ + @AfterClass + public void tearDownAfterClass() throws Exception { + N4j.deleteAccount(testAcct) + N4j.deleteAccount(otherTestAcct) + } + + private String cloudUri(String servicePath) { + URI.create("http://${host}:8773/") + .resolve(servicePath) + .toString() + } + + private AWSSecurityTokenService getStsClient(final AWSCredentialsProvider credentials) { + final AWSSecurityTokenService sts = new AWSSecurityTokenServiceClient(credentials) + sts.setEndpoint(cloudUri('/services/Tokens')) + sts + } + + private AmazonIdentityManagement getIamClient(final AWSCredentialsProvider credentials) { + final AmazonIdentityManagement iam = new AmazonIdentityManagementClient(credentials) + iam.setEndpoint(cloudUri('/services/Euare')) + iam + } + + private AmazonEC2 getEC2Client(final AWSCredentialsProvider credentials) { + final AmazonEC2 ec2 = new AmazonEC2Client(credentials) + ec2.setEndpoint(cloudUri("/services/compute")) + ec2 + } + + @Test + public void assumeRolePolicyTest( ) throws Exception { + final String namePrefix = NAME_PREFIX + N4j.print( "Using resource prefix for test: ${namePrefix}" ) + + final List cleanupTasks = [] as List + try { + N4j.print( "Getting account id for other account: ${otherTestAcct}" ) + String otherAccountNumber = getStsClient( otherAdminCredentials ).with { + getCallerIdentity( new GetCallerIdentityRequest( ) ).with { + account + } + } + N4j.print( "Other account id: ${otherAccountNumber}" ) + N4j.assertThat( otherAccountNumber != null, 'Expected other account number' ) + + String userName = "${namePrefix}assume-role-user" + AWSCredentialsProvider userCredentials = null + String userArn = null + String roleArn = null + String untrustingRoleArn = null + getIamClient(adminCredentials).with { + N4j.print( "Creating user for assuming role: ${userName}" ) + userArn = createUser( new CreateUserRequest( userName: userName, path: '/' ) ).with { + user?.arn + } + cleanupTasks.add{ + N4j.print( "Deleting user: ${userName}" ) + deleteUser( new DeleteUserRequest( userName: userName ) ) + } + N4j.print( "Got user arn: ${userArn}" ) + N4j.assertThat( userArn != null, 'Expected user arn' ) + + N4j.print("Creating credentials for user: ${userName}") + userCredentials = createAccessKey( new CreateAccessKeyRequest( userName: userName ) ).with { + new StaticCredentialsProvider( new BasicAWSCredentials( + accessKey.accessKeyId, + accessKey.secretAccessKey + ) ); + } + cleanupTasks.add{ + N4j.print("Deleting credentials for user: ${userName}") + deleteAccessKey( new DeleteAccessKeyRequest( + userName: userName, + accessKeyId: userCredentials.credentials.AWSAccessKeyId + ) ) + } + + final String untrustPolicy = """\ + { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Principal": { + "AWS": "${userArn.replace(userName,'admin')}" + }, + "Action": "sts:AssumeRole" + } + ] + } + """.stripIndent() + + final String trustPolicy = """\ + { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Principal": { + "AWS": [ + "${userArn}", + "${otherAccountNumber}" + ] + }, + "Action": "sts:AssumeRole" + } + ] + } + """.stripIndent() + + final String permissionPolicy = """\ + { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": "ec2:*SecurityGroup*", + "Resource": "*" + } + ] + } + """.stripIndent() + + // ensure iam user available when creating role + N4j.print "Sleeping ${sleepSecs} seconds to ensure iam user available for use" + N4j.sleep sleepSecs + + + + String untrustingRoleName = "${namePrefix}untrusting-role" + N4j.print "Creating role: ${untrustingRoleName}" + untrustingRoleArn = createRole(new CreateRoleRequest( + path: '/', + roleName: untrustingRoleName, + assumeRolePolicyDocument: untrustPolicy + ))?.with { + role?.arn + } + N4j.print "Created role: ${untrustingRoleArn}" + cleanupTasks.add { + N4j.print "Deleting role: ${untrustingRoleArn}" + deleteRole(new DeleteRoleRequest( + roleName: untrustingRoleName + )) + } + + String roleName = "${namePrefix}role" + N4j.print "Creating role: ${roleName}" + roleArn = createRole(new CreateRoleRequest( + path: '/', + roleName: roleName, + assumeRolePolicyDocument: trustPolicy + ))?.with { + role?.arn + } + N4j.print "Created role: ${roleArn}" + cleanupTasks.add { + N4j.print "Deleting role: ${roleArn}" + deleteRole(new DeleteRoleRequest( + roleName: roleName + )) + } + + N4j.print "Creating role permission policy: ${roleName}/role-policy" + putRolePolicy(new PutRolePolicyRequest( + roleName: roleName, + policyName: 'role-policy', + policyDocument: permissionPolicy + )) + N4j.print "Created iam resources for assuming role" + cleanupTasks.add { + N4j.print "Deleting role policy: ${roleName}/role-policy" + deleteRolePolicy(new DeleteRolePolicyRequest( + roleName: roleName, + policyName: 'role-policy', + )) + } + } + + // ensure iam resources available + N4j.print "Sleeping ${sleepSecs} seconds to ensure iam resources are available for use" + N4j.sleep sleepSecs + + String roleCredentialsProviderArn = '' + AWSCredentialsProvider roleCredentialsProviderCredentials = null + final AWSCredentialsProvider roleCredentialsProvider = new AWSCredentialsProvider() { + AWSCredentials awsCredentials = null + @Override + public AWSCredentials getCredentials( ) { + if ( awsCredentials == null ) { + N4j.print "Getting credentials using assume role" + awsCredentials = getStsClient( roleCredentialsProviderCredentials ).with { + assumeRole( new AssumeRoleRequest( + roleArn: roleCredentialsProviderArn, + roleSessionName: 'session-name-here' + ) ).with { + N4j.assertThat(assumedRoleUser != null, "Expected assumedRoleUser") + N4j.assertThat(assumedRoleUser.arn != null, "Expected assumedRoleUser.arn") + N4j.assertThat(assumedRoleUser.assumedRoleId != null, "Expected assumedRoleUser.assumedRoleId") + N4j.assertThat(packedPolicySize == null, "Unexpected packedPolicySize") + N4j.assertThat(credentials != null, "Expected credentials") + N4j.assertThat(credentials.expiration != null, "Expected credentials expiration") + new BasicSessionCredentials( + credentials.accessKeyId, + credentials.secretAccessKey, + credentials.sessionToken + ) + } + } + } + awsCredentials + } + + @Override + public void refresh( ) { + awsCredentials = null + } + } + + N4j.print 'Testing access for untrusted user in same account using role' + roleCredentialsProviderArn = untrustingRoleArn + roleCredentialsProviderCredentials = userCredentials + roleCredentialsProvider.refresh( ) + try { + getEC2Client( roleCredentialsProvider ).with { + N4j.print "Describing security groups using assumed role credentials (should fail)" + describeSecurityGroups( ) + N4j.assertThat( false, 'Expected failure due to user not permitted to assume role' ) + } + } catch ( AmazonServiceException e ) { + N4j.print "Expected exception for assuming role without being trusted: ${e}" + } + + N4j.print 'Testing access for trusted user in same account using role' + roleCredentialsProviderArn = roleArn + roleCredentialsProviderCredentials = userCredentials + roleCredentialsProvider.refresh( ) + getEC2Client( roleCredentialsProvider ).with { + N4j.print "Describing security groups using assumed role credentials" + N4j.print describeSecurityGroups( ).with { DescribeSecurityGroupsResult result -> + N4j.assertThat( securityGroups!=null && securityGroups.size()>0, "Expected visible security groups" ) + result.toString( ) + } + + String groupName = "${namePrefix}group-1" + N4j.print "Creating security group ${groupName} using assumed role credentials" + createSecurityGroup( new CreateSecurityGroupRequest( groupName: groupName, description: 'STS assume role with web identity test group' ) ) + + N4j.print "Deleting security group ${groupName} using assumed role credentials" + deleteSecurityGroup( new DeleteSecurityGroupRequest( groupName: groupName ) ) + } + + N4j.print 'Testing access for untrusted admin user in other account using role\'' + roleCredentialsProviderArn = untrustingRoleArn + roleCredentialsProviderCredentials = otherAdminCredentials + roleCredentialsProvider.refresh( ) + try { + getEC2Client( roleCredentialsProvider ).with { + N4j.print "Describing security groups using assumed role credentials (should fail)" + describeSecurityGroups( ) + N4j.assertThat( false, 'Expected failure due to user not permitted to assume role' ) + } + } catch ( AmazonServiceException e ) { + N4j.print "Expected exception for assuming role without being trusted: ${e}" + } + + N4j.print 'Testing access for trusted admin user in other account using role' + roleCredentialsProviderArn = roleArn + roleCredentialsProviderCredentials = otherAdminCredentials + roleCredentialsProvider.refresh( ) + getEC2Client( roleCredentialsProvider ).with { + N4j.print "Describing security groups using assumed role credentials" + N4j.print describeSecurityGroups().with { DescribeSecurityGroupsResult result -> + N4j.assertThat(securityGroups != null && securityGroups.size() > 0, "Expected visible security groups") + result.toString() + } + } + + AWSCredentialsProvider otherAccountUser1Credentials = null + AWSCredentialsProvider otherAccountUser2Credentials = null + getIamClient( otherAdminCredentials ).with { + String userName1 = "${namePrefix}other-assume-role-user-1" + String userName2 = "${namePrefix}other-assume-role-user-2" + + N4j.print("Creating user for assuming role: ${userName1}") + createUser(new CreateUserRequest(userName: userName1, path: '/')) + cleanupTasks.add { + N4j.print("Deleting user: ${userName1}") + deleteUser(new DeleteUserRequest(userName: userName1)) + } + + N4j.print("Creating credentials for user: ${userName1}") + otherAccountUser1Credentials = createAccessKey(new CreateAccessKeyRequest(userName: userName1)).with { + new StaticCredentialsProvider(new BasicAWSCredentials( + accessKey.accessKeyId, + accessKey.secretAccessKey + )); + } + cleanupTasks.add { + N4j.print("Deleting credentials for user: ${userName1}") + deleteAccessKey(new DeleteAccessKeyRequest( + userName: userName1, + accessKeyId: otherAccountUser1Credentials.credentials.AWSAccessKeyId + )) + } + + N4j.print("Creating user for assuming role: ${userName2}") + createUser(new CreateUserRequest(userName: userName2, path: '/')) + cleanupTasks.add { + N4j.print("Deleting user: ${userName2}") + deleteUser(new DeleteUserRequest(userName: userName2)) + } + + N4j.print "Creating policy allowing role access for: ${userName2}/user-policy" + putUserPolicy(new PutUserPolicyRequest( + userName: userName2, + policyName: 'user-policy', + policyDocument: '''\ + { + "Statement": { + "Effect": "Allow", + "Action": "sts:AssumeRole", + "Resource": "*" + } + } + '''.stripIndent( ) + )) + cleanupTasks.add { + N4j.print "Deleting user policy: ${userName2}/user-policy" + deleteUserPolicy(new DeleteUserPolicyRequest( + userName: userName2, + policyName: 'user-policy', + )) + } + + N4j.print("Creating credentials for user: ${userName2}") + otherAccountUser2Credentials = createAccessKey(new CreateAccessKeyRequest(userName: userName2)).with { + new StaticCredentialsProvider(new BasicAWSCredentials( + accessKey.accessKeyId, + accessKey.secretAccessKey + )); + } + cleanupTasks.add { + N4j.print("Deleting credentials for user: ${userName2}") + deleteAccessKey(new DeleteAccessKeyRequest( + userName: userName2, + accessKeyId: otherAccountUser2Credentials.credentials.AWSAccessKeyId + )) + } + } + + N4j.print 'Testing access for untrusted user in other trusted account using role' + roleCredentialsProviderArn = roleArn + roleCredentialsProviderCredentials = otherAccountUser1Credentials + roleCredentialsProvider.refresh( ) + try { + getEC2Client( roleCredentialsProvider ).with { + N4j.print "Describing security groups using assumed role credentials (should fail)" + describeSecurityGroups( ) + N4j.assertThat( false, 'Expected failure due to user not permitted to assume role' ) + } + } catch ( AmazonServiceException e ) { + N4j.print "Expected exception for assuming role without being trusted: ${e}" + } + + N4j.print 'Testing access for trusted user in other trusted account using role' + roleCredentialsProviderArn = roleArn + roleCredentialsProviderCredentials = otherAccountUser2Credentials + roleCredentialsProvider.refresh( ) + getEC2Client( roleCredentialsProvider ).with { + N4j.print "Describing security groups using assumed role credentials" + N4j.print describeSecurityGroups().with { DescribeSecurityGroupsResult result -> + N4j.assertThat(securityGroups != null && securityGroups.size() > 0, "Expected visible security groups") + result.toString() + } + } + + N4j.print 'Test complete' + } finally { + // Attempt to clean up anything we created + cleanupTasks.reverseEach { Runnable cleanupTask -> + try { + cleanupTask.run() + } catch ( AmazonServiceException e ) { + N4j.print "Error in clean up: ${e}" + } catch ( Exception e ) { + e.printStackTrace() + } + } + } + } +}