/* * Copyright 2010-2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"). * You may not use this file except in compliance with the License. * A copy of the License is located at * * http://aws.amazon.com/apache2.0 * * or in the "license" file accompanying this file. This file is distributed * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either * express or implied. See the License for the specific language governing * permissions and limitations under the License. */ package com.amazonaws.auth.policy; import static org.hamcrest.Matchers.contains; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThat; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import org.junit.Test; import com.amazonaws.auth.policy.Principal.Services; import com.amazonaws.auth.policy.Statement.Effect; import com.amazonaws.auth.policy.conditions.ConditionFactory; import com.amazonaws.auth.policy.conditions.IpAddressCondition; import com.amazonaws.auth.policy.conditions.IpAddressCondition.IpAddressComparisonType; import com.amazonaws.auth.policy.conditions.StringCondition; import com.amazonaws.auth.policy.conditions.StringCondition.StringComparisonType; /** * Unit tests for generating AWS policy object from JSON string. */ public class PolicyReaderTest { final String POLICY_VERSION = "2012-10-17"; @Test public void testPrincipals() { Policy policy = new Policy(); policy.withStatements(new Statement(Effect.Allow) .withResources(new Resource("resource")) .withPrincipals(new Principal("accountId1"), new Principal("accountId2")) .withActions(new TestAction("action"))); policy = Policy.fromJson(policy.toJson()); assertEquals(1, policy.getStatements().size()); List<Statement> statements = new LinkedList<Statement>(policy.getStatements()); assertEquals(Effect.Allow, statements.get(0).getEffect()); assertEquals("action", statements.get(0).getActions().get(0).getActionName()); assertEquals("resource", statements.get(0).getResources().get(0).getId()); assertEquals(2, statements.get(0).getPrincipals().size()); assertEquals("AWS", statements.get(0).getPrincipals().get(0).getProvider()); assertEquals("accountId1", statements.get(0).getPrincipals().get(0).getId()); assertEquals("AWS", statements.get(0).getPrincipals().get(1).getProvider()); assertEquals("accountId2", statements.get(0).getPrincipals().get(1).getId()); policy = new Policy(); policy.withStatements(new Statement(Effect.Allow).withResources(new Resource("resource")).withPrincipals(new Principal(Services.AmazonEC2), new Principal(Services.AmazonElasticTranscoder)) .withActions(new TestAction("action"))); policy = Policy.fromJson(policy.toJson()); assertEquals(1, policy.getStatements().size()); statements = new LinkedList<Statement>(policy.getStatements()); assertEquals(Effect.Allow, statements.get(0).getEffect()); assertEquals(1, statements.get(0).getActions().size()); assertEquals("action", statements.get(0).getActions().get(0).getActionName()); assertEquals(2, statements.get(0).getPrincipals().size()); assertEquals("Service", statements.get(0).getPrincipals().get(0).getProvider()); assertEquals(Services.AmazonEC2.getServiceId(), statements.get(0).getPrincipals().get(0).getId()); assertEquals("Service", statements.get(0).getPrincipals().get(1).getProvider()); assertEquals(Services.AmazonElasticTranscoder.getServiceId(), statements.get(0).getPrincipals().get(1).getId()); policy = new Policy(); policy.withStatements(new Statement(Effect.Allow).withResources(new Resource("resource")).withPrincipals(Principal.All) .withActions(new TestAction("action"))); policy = Policy.fromJson(policy.toJson()); assertEquals(1, policy.getStatements().size()); statements = new LinkedList<Statement>(policy.getStatements()); assertEquals(Effect.Allow, statements.get(0).getEffect()); assertEquals(1, statements.get(0).getActions().size()); assertEquals("action", statements.get(0).getActions().get(0).getActionName()); assertEquals(1, statements.get(0).getPrincipals().size()); assertEquals(Principal.All, statements.get(0).getPrincipals().get(0)); policy = new Policy(); policy.withStatements(new Statement(Effect.Allow).withResources(new Resource("resource")).withPrincipals(Principal.AllUsers, Principal.AllServices, Principal.AllWebProviders) .withActions(new TestAction("action"))); policy = Policy.fromJson(policy.toJson()); assertEquals(1, policy.getStatements().size()); statements = new LinkedList<Statement>(policy.getStatements()); assertEquals(Effect.Allow, statements.get(0).getEffect()); assertEquals(1, statements.get(0).getActions().size()); assertEquals("action", statements.get(0).getActions().get(0).getActionName()); assertEquals(3, statements.get(0).getPrincipals().size()); assertThat(statements.get(0).getPrincipals(), contains(Principal.AllUsers, Principal.AllServices, Principal.AllWebProviders)); } @Test public void testMultipleConditionKeysForConditionType() throws Exception { Policy policy = new Policy(); policy.withStatements(new Statement(Effect.Allow) .withResources(new Resource("arn:aws:sqs:us-east-1:987654321000:MyQueue")) .withPrincipals(Principal.AllUsers) .withActions(new TestAction("foo")) .withConditions( new StringCondition(StringComparisonType.StringNotLike, "key1", "foo"), new StringCondition(StringComparisonType.StringNotLike, "key1", "bar"))); policy = Policy.fromJson(policy.toJson()); assertEquals(1, policy.getStatements().size()); List<Statement> statements = new LinkedList<Statement>(policy.getStatements()); assertEquals(Effect.Allow, statements.get(0).getEffect()); assertEquals(1, statements.get(0).getActions().size()); assertEquals("foo", statements.get(0).getActions().get(0).getActionName()); assertEquals(1, statements.get(0).getConditions().size()); assertEquals("StringNotLike", statements.get(0).getConditions().get(0).getType()); assertEquals("key1", statements.get(0).getConditions().get(0).getConditionKey()); assertEquals(2, statements.get(0).getConditions().get(0).getValues().size()); assertEquals("foo", statements.get(0).getConditions().get(0).getValues().get(0)); assertEquals("bar", statements.get(0).getConditions().get(0).getValues().get(1)); } /** * Test policy parsing when the "Effect" is not mentioned in a Statement. * The Effect must be default to "Deny" when it is not mentioned. */ @Test public void testPolicyParsingWithNoEffect() { String jsonString = "{" + "\"Statement\": [{" + "\"Action\": [" + "\"elasticmapreduce:*\"," + "\"iam:PassRole\"" + "]," + "\"Resource\": [\"*\"]" + "}]" + "}"; Policy policy = Policy.fromJson(jsonString); assertEquals(1, policy.getStatements().size()); List<Statement> statements = new LinkedList<Statement>(policy.getStatements()); assertEquals(Effect.Deny, statements.get(0).getEffect()); assertEquals(1, statements.size()); } @Test public void testMultipleStatements() throws Exception { Policy policy = new Policy("S3PolicyId1"); policy.withStatements( new Statement(Effect.Allow) .withId("0") .withPrincipals(Principal.AllUsers) .withActions(new TestAction("action1")) .withResources(new Resource("resource")) .withConditions( new IpAddressCondition("192.168.143.0/24"), new IpAddressCondition(IpAddressComparisonType.NotIpAddress, "192.168.143.188/32")), new Statement(Effect.Deny) .withId("1") .withPrincipals(Principal.AllUsers) .withActions(new TestAction("action2")) .withResources(new Resource("resource")) .withConditions(new IpAddressCondition("10.1.2.0/24"))); policy = Policy.fromJson(policy.toJson()); assertEquals(2, policy.getStatements().size()); assertEquals("S3PolicyId1", policy.getId()); List<Statement> statements = new LinkedList<Statement>(policy.getStatements()); assertEquals(Effect.Allow, statements.get(0).getEffect()); assertEquals("0", statements.get(0).getId()); assertEquals(1, statements.get(0).getPrincipals().size()); assertEquals("*", statements.get(0).getPrincipals().get(0).getId()); assertEquals("AWS", statements.get(0).getPrincipals().get(0).getProvider()); assertEquals(1, statements.get(0).getResources().size()); assertEquals("resource", statements.get(0).getResources().get(0).getId()); assertEquals(1, statements.get(0).getActions().size()); assertEquals("action1", statements.get(0).getActions().get(0).getActionName()); assertEquals(2, statements.get(0).getConditions().size()); assertEquals("IpAddress", statements.get(0).getConditions().get(0).getType()); assertEquals(ConditionFactory.SOURCE_IP_CONDITION_KEY, statements.get(0).getConditions().get(0).getConditionKey()); assertEquals(1, statements.get(0).getConditions().get(0).getValues().size()); assertEquals("192.168.143.0/24", statements.get(0).getConditions().get(0).getValues().get(0)); assertEquals("NotIpAddress", statements.get(0).getConditions().get(1).getType()); assertEquals(1, statements.get(0).getConditions().get(1).getValues().size()); assertEquals("192.168.143.188/32", statements.get(0).getConditions().get(1).getValues().get(0)); assertEquals(ConditionFactory.SOURCE_IP_CONDITION_KEY, statements.get(1).getConditions().get(0).getConditionKey()); assertEquals(Effect.Deny, statements.get(1).getEffect()); assertEquals("1", statements.get(1).getId()); assertEquals(1, statements.get(1).getPrincipals().size()); assertEquals("*", statements.get(1).getPrincipals().get(0).getId()); assertEquals("AWS", statements.get(1).getPrincipals().get(0).getProvider()); assertEquals(1, statements.get(1).getResources().size()); assertEquals("resource", statements.get(1).getResources().get(0).getId()); assertEquals(1, statements.get(1).getActions().size()); assertEquals("action2", statements.get(1).getActions().get(0).getActionName()); assertEquals(1, statements.get(1).getConditions().size()); assertEquals("IpAddress", statements.get(1).getConditions().get(0).getType()); assertEquals(ConditionFactory.SOURCE_IP_CONDITION_KEY, statements.get(0).getConditions().get(0).getConditionKey()); assertEquals(1, statements.get(0).getConditions().get(0).getValues().size()); assertEquals("10.1.2.0/24", statements.get(1).getConditions().get(0).getValues().get(0)); } @Test public void testNoJsonArray() { String jsonString = "{" + "\"Version\": \"2012-10-17\"," + "\"Statement\": [" + "{" + "\"Effect\": \"Allow\"," + "\"Principal\": {" + "\"AWS\": \"*\"" + "}," + "\"Action\": \"sts:AssumeRole\"," + "\"Condition\": {" + "\"IpAddress\": {" + " \"aws:SourceIp\": \"10.10.10.10/32\"" + "}" + "}" + "}" + "]" + "}" ; Policy policy = Policy.fromJson(jsonString); assertEquals(POLICY_VERSION, policy.getVersion()); List<Statement> statements = new LinkedList<Statement>(policy.getStatements()); assertEquals(1, statements.size()); assertEquals(1, statements.get(0).getActions().size()); assertEquals(Effect.Allow, statements.get(0).getEffect()); assertEquals("sts:AssumeRole", statements.get(0).getActions().get(0).getActionName()); assertEquals(1, statements.get(0).getConditions().size()); assertEquals("IpAddress", statements.get(0).getConditions().get(0).getType()); assertEquals("aws:SourceIp", statements.get(0).getConditions().get(0).getConditionKey()); assertEquals(1, statements.get(0).getConditions().get(0).getValues().size()); assertEquals("10.10.10.10/32", statements.get(0).getConditions().get(0).getValues().get(0)); assertEquals(1, statements.get(0).getPrincipals().size()); assertEquals("*", statements.get(0).getPrincipals().get(0).getId()); assertEquals("AWS", statements.get(0).getPrincipals().get(0).getProvider()); } /** * Tests that SAML-based federated user is supported as principal. */ @Test public void testFederatedUserBySAMLProvider() { String jsonString = "{" + "\"Version\":\"2012-10-17\"," + "\"Statement\":[" + "{" + "\"Sid\":\"\"," + "\"Effect\":\"Allow\"," + "\"Principal\":{" + "\"Federated\":\"arn:aws:iam::862954416975:saml-provider/myprovider\"" + "}," + "\"Action\":\"sts:AssumeRoleWithSAML\"," + "\"Condition\":{" + "\"StringEquals\":{" + "\"SAML:aud\":\"https://signin.aws.amazon.com/saml\"" + "}" + "}" + "}" + "]" + "}"; Policy policy = Policy.fromJson(jsonString); assertEquals(POLICY_VERSION, policy.getVersion()); List<Statement> statements = new LinkedList<Statement>(policy.getStatements()); assertEquals(1, statements.size()); assertEquals(1, statements.get(0).getActions().size()); assertEquals(Effect.Allow, statements.get(0).getEffect()); assertEquals("sts:AssumeRoleWithSAML", statements.get(0).getActions().get(0).getActionName()); assertEquals(1, statements.get(0).getConditions().size()); assertEquals("StringEquals", statements.get(0).getConditions().get(0).getType()); assertEquals("SAML:aud", statements.get(0).getConditions().get(0).getConditionKey()); assertEquals(1, statements.get(0).getConditions().get(0).getValues().size()); assertEquals("https://signin.aws.amazon.com/saml", statements.get(0).getConditions().get(0).getValues().get(0)); assertEquals(1, statements.get(0).getPrincipals().size()); assertEquals("arn:aws:iam::862954416975:saml-provider/myprovider", statements.get(0).getPrincipals().get(0).getId()); assertEquals("Federated", statements.get(0).getPrincipals().get(0).getProvider()); } @Test public void testCloudHSMServicePrincipal() { String jsonString = "{" + "\"Version\":\"2008-10-17\"," + "\"Statement\":[" + "{\"Sid\":\"\"," + "\"Effect\":\"Allow\"," + "\"Principal\":{\"Service\":\"cloudhsm.amazonaws.com\"}," + "\"Action\":\"sts:AssumeRole\"}" + "]" + "}"; Policy policy = Policy.fromJson(jsonString); assertEquals(POLICY_VERSION, policy.getVersion()); List<Statement> statements = new LinkedList<Statement>(policy.getStatements()); assertEquals(1, statements.size()); assertEquals(1, statements.get(0).getActions().size()); assertEquals(Effect.Allow, statements.get(0).getEffect()); assertEquals("sts:AssumeRole", statements.get(0).getActions().get(0).getActionName()); assertEquals(0, statements.get(0).getConditions().size()); assertEquals(1, statements.get(0).getPrincipals().size()); assertEquals(Services.AWSCloudHSM.getServiceId(), statements.get(0).getPrincipals().get(0).getId()); assertEquals("Service", statements.get(0).getPrincipals().get(0).getProvider()); } private class TestAction implements Action { private final String name; public TestAction(String name) { this.name = name; } public String getActionName() { return name; } } /** * This test case was written as result of the following TT * * @see TT:0030871921 * * When a service is mentioned in the principal, we always try to * figure out the service from * <code>com.amazonaws.auth.policy.Principal.Services</code> enum. For * new services introduced, if the enum is not updated, then the parsing * fails. */ @Test public void testPrincipalWithServiceNotInServicesEnum() { String jsonString = "{" + "\"Version\":\"2008-10-17\"," + "\"Statement\":[" + "{" + "\"Sid\":\"\"," + "\"Effect\":\"Allow\"," + "\"Principal\":{" + "\"Service\":\"workspaces.amazonaws.com\" " + "}," + "\"Action\":\"sts:AssumeRole\"" + "}" + "]" + "}"; Policy policy = Policy.fromJson(jsonString); assertEquals(POLICY_VERSION, policy.getVersion()); List<Statement> statements = new LinkedList<Statement>( policy.getStatements()); assertEquals(1, statements.size()); assertEquals(1, statements.get(0).getActions().size()); assertEquals(Effect.Allow, statements.get(0).getEffect()); assertEquals("sts:AssumeRole", statements.get(0).getActions().get(0) .getActionName()); assertEquals(0, statements.get(0).getConditions().size()); assertEquals(1, statements.get(0).getPrincipals().size()); assertEquals("workspaces.amazonaws.com", statements.get(0) .getPrincipals().get(0).getId()); assertEquals("Service", statements.get(0).getPrincipals().get(0) .getProvider()); } @Test public void testAccountNamePrincipalWithDashesAreStrippedByDefault() { String jsonString = "{" + "\"Version\": \"2012-10-17\"," + "\"Statement\": [" + "{" + "\"Effect\": \"Allow\"," + "\"Principal\": {" + "\"AWS\": \"test-string\"" + "}" + "}" + "]" + "}" ; Policy policy = Policy.fromJson(jsonString); List<Statement> statements = new ArrayList<Statement>(policy.getStatements()); assertEquals("teststring", statements.get(0).getPrincipals().get(0).getId()); } @Test public void testAccountNamePrincipalWithDashesAreNotStrippedWhenDisabled() { String jsonString = "{" + "\"Version\": \"2012-10-17\"," + "\"Statement\": [" + "{" + "\"Effect\": \"Allow\"," + "\"Principal\": {" + "\"AWS\": \"test-string\"" + "}" + "}" + "]" + "}" ; Policy policy = Policy.fromJson(jsonString, new PolicyReaderOptions().withStripAwsPrincipalIdHyphensEnabled(false)); List<Statement> statements = new ArrayList<Statement>(policy.getStatements()); assertEquals("test-string", statements.get(0).getPrincipals().get(0).getId()); } }