/*
* 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.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import java.util.HashSet;
import java.util.Set;
import junit.framework.Assert;
import org.junit.Test;
import com.amazonaws.auth.policy.Principal.Services;
import com.amazonaws.auth.policy.Principal.WebIdentityProviders;
import com.amazonaws.auth.policy.Statement.Effect;
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;
import com.amazonaws.util.json.Jackson;
import com.fasterxml.jackson.databind.JsonNode;
/**
* Unit tests for constructing policy objects and serializing them to JSON.
*/
public class PolicyTest {
@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")));
JsonNode jsonPolicyNode = Jackson.jsonNodeOf(policy.toJson());
JsonNode statementArray = jsonPolicyNode.get("Statement");
assertTrue(statementArray.isArray());
assertTrue(statementArray.size() == 1);
JsonNode statement = statementArray.get(0);
assertTrue(statement.has("Resource"));
assertTrue(statement.has("Principal"));
assertTrue(statement.has("Action"));
assertTrue(statement.has("Effect"));
JsonNode users = statement.get("Principal").get("AWS");
assertEquals(2, users.size());
assertEquals(users.get(0).asText(), "accountId1");
assertEquals(users.get(1).asText(), "accountId2");
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")));
jsonPolicyNode = Jackson.jsonNodeOf(policy.toJson());
statementArray = jsonPolicyNode.get("Statement");
assertTrue(statementArray.size() == 1);
statement = statementArray.get(0);
assertTrue(statement.has("Resource"));
assertTrue(statement.has("Principal"));
assertTrue(statement.has("Action"));
assertTrue(statement.has("Effect"));
JsonNode services = statement.get("Principal").get("Service");
assertTrue(services.isArray());
assertTrue(services.size() == 2);
assertEquals(Services.AmazonEC2.getServiceId(), services.get(0)
.asText());
assertEquals(Services.AmazonElasticTranscoder.getServiceId(), services
.get(1).asText());
policy = new Policy();
policy.withStatements(new Statement(Effect.Allow)
.withResources(new Resource("resource"))
.withPrincipals(Principal.AllUsers)
.withActions(new TestAction("action")));
jsonPolicyNode = Jackson.jsonNodeOf(policy.toJson());
statementArray = jsonPolicyNode.get("Statement");
assertTrue(statementArray.size() == 1);
statement = statementArray.get(0);
assertTrue(statement.has("Resource"));
assertTrue(statement.has("Principal"));
assertTrue(statement.has("Action"));
assertTrue(statement.has("Effect"));
users = statement.get("Principal").get("AWS");
assertEquals(users.asText(), "*");
policy = new Policy();
policy.withStatements(new Statement(Effect.Allow)
.withResources(new Resource("resource"))
.withPrincipals(Principal.AllServices, Principal.AllUsers)
.withActions(new TestAction("action")));
jsonPolicyNode = Jackson.jsonNodeOf(policy.toJson());
statementArray = jsonPolicyNode.get("Statement");
assertTrue(statementArray.size() == 1);
statement = statementArray.get(0);
assertTrue(statement.has("Resource"));
assertTrue(statement.has("Principal"));
assertTrue(statement.has("Action"));
assertTrue(statement.has("Effect"));
users = statement.get("Principal").get("AWS");
services = statement.get("Principal").get("Service");
assertEquals(users.asText(), "*");
assertEquals(services.asText(), "*");
policy = new Policy();
policy.withStatements(new Statement(Effect.Allow)
.withResources(new Resource("resource"))
.withPrincipals(Principal.AllServices, Principal.AllUsers,
Principal.AllWebProviders)
.withActions(new TestAction("action")));
jsonPolicyNode = Jackson.jsonNodeOf(policy.toJson());
statementArray = jsonPolicyNode.get("Statement");
assertTrue(statementArray.size() == 1);
statement = statementArray.get(0);
assertTrue(statement.has("Resource"));
assertTrue(statement.has("Principal"));
assertTrue(statement.has("Action"));
assertTrue(statement.has("Effect"));
users = statement.get("Principal").get("AWS");
services = statement.get("Principal").get("Service");
JsonNode webProviders = statement.get("Principal").get("Federated");
assertEquals(users.asText(), "*");
assertEquals(services.asText(), "*");
assertEquals(webProviders.asText(), "*");
policy = new Policy();
policy.withStatements(new Statement(Effect.Allow)
.withResources(new Resource("resource"))
.withPrincipals(Principal.AllServices, Principal.AllUsers,
Principal.AllWebProviders, Principal.All)
.withActions(new TestAction("action")));
jsonPolicyNode = Jackson.jsonNodeOf(policy.toJson());
statementArray = jsonPolicyNode.get("Statement");
assertTrue(statementArray.size() == 1);
statement = statementArray.get(0);
assertTrue(statement.has("Resource"));
assertTrue(statement.has("Principal"));
assertTrue(statement.has("Action"));
assertTrue(statement.has("Effect"));
users = statement.get("Principal").get("AWS");
services = statement.get("Principal").get("Service");
webProviders = statement.get("Principal").get("Federated");
JsonNode allUsers = statement.get("Principal").get("*");
assertEquals(users.asText(), "*");
assertEquals(services.asText(), "*");
assertEquals(webProviders.asText(), "*");
assertEquals(allUsers.asText(), "*");
policy = new Policy();
policy.withStatements(new Statement(Effect.Allow)
.withResources(new Resource("resource"))
.withPrincipals(new Principal("accountId1"), Principal.AllUsers)
.withActions(new TestAction("action")));
jsonPolicyNode = Jackson.jsonNodeOf(policy.toJson());
statementArray = jsonPolicyNode.get("Statement");
assertTrue(statementArray.size() == 1);
statement = statementArray.get(0);
assertTrue(statement.has("Resource"));
assertTrue(statement.has("Principal"));
assertTrue(statement.has("Action"));
assertTrue(statement.has("Effect"));
users = statement.get("Principal").get("AWS");
assertTrue(users.isArray());
assertEquals(users.get(0).asText(), "accountId1");
assertEquals(users.get(1).asText(), "*");
policy = new Policy();
policy.withStatements(new Statement(Effect.Allow)
.withResources(new Resource("resource"))
.withPrincipals(new Principal(Services.AmazonEC2),
Principal.AllServices, new Principal("accountId1"))
.withActions(new TestAction("action")));
jsonPolicyNode = Jackson.jsonNodeOf(policy.toJson());
statementArray = jsonPolicyNode.get("Statement");
assertTrue(statementArray.size() == 1);
statement = statementArray.get(0);
assertTrue(statement.has("Resource"));
assertTrue(statement.has("Principal"));
assertTrue(statement.has("Action"));
assertTrue(statement.has("Effect"));
users = statement.get("Principal").get("AWS");
services = statement.get("Principal").get("Service");
assertEquals(users.asText(), "accountId1");
assertEquals(services.get(0).asText(),
Services.AmazonEC2.getServiceId());
assertEquals(services.get(1).asText(), "*");
policy = new Policy();
policy.withStatements(new Statement(Effect.Allow)
.withResources(new Resource("resource"))
.withPrincipals(new Principal(Services.AmazonEC2),
Principal.AllServices, new Principal("accountId1"),
new Principal(WebIdentityProviders.Amazon),
Principal.AllWebProviders)
.withActions(new TestAction("action")));
jsonPolicyNode = Jackson.jsonNodeOf(policy.toJson());
statementArray = jsonPolicyNode.get("Statement");
assertTrue(statementArray.size() == 1);
statement = statementArray.get(0);
assertTrue(statement.has("Resource"));
assertTrue(statement.has("Principal"));
assertTrue(statement.has("Action"));
assertTrue(statement.has("Effect"));
users = statement.get("Principal").get("AWS");
services = statement.get("Principal").get("Service");
webProviders = statement.get("Principal").get("Federated");
assertEquals(services.get(0).asText(),
Services.AmazonEC2.getServiceId());
assertEquals(services.get(1).asText(), "*");
assertEquals(users.asText(), "accountId1");
assertEquals(webProviders.get(0).asText(),
WebIdentityProviders.Amazon.getWebIdentityProvider());
assertEquals(webProviders.get(1).asText(), "*");
}
/**
* Policies with multiple conditions that use the same comparison type must
* be merged together in the JSON format, otherwise there will be two keys
* with the same name and one will override the other.
*/
@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")));
JsonNode jsonPolicy = Jackson.jsonNodeOf(policy.toJson());
JsonNode statementArray = jsonPolicy.get("Statement");
assertEquals(statementArray.size(),1);
JsonNode conditions = statementArray.get(0).get("Condition");
assertEquals(conditions.size(),1);
JsonNode stringLikeCondition = conditions.get(StringComparisonType.StringNotLike.toString());
assertTrue(stringLikeCondition.has("key1"));
assertFalse(stringLikeCondition.has("key2"));
assertValidStatementIds(policy);
}
/**
* Tests serializing a more complex policy object with multiple statements.
*/
@Test
public void testMultipleStatements() throws Exception {
Policy policy = new Policy("S3PolicyId1");
policy.withStatements(
new Statement(Effect.Allow)
.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).withPrincipals(Principal.AllUsers)
.withActions(new TestAction("action2"))
.withResources(new Resource("resource"))
.withConditions(new IpAddressCondition("10.1.2.0/24")));
JsonNode jsonPolicy = Jackson.jsonNodeOf(policy.toJson());
assertTrue(jsonPolicy.has("Id"));
JsonNode statementArray = jsonPolicy.get("Statement");
assertEquals(statementArray.size(),2);
assertValidStatementIds(policy);
JsonNode statement;
for (int i = 0; i < statementArray.size(); i++) {
statement = statementArray.get(i);
assertTrue(statement.has("Sid"));
assertTrue(statement.has("Effect"));
assertTrue(statement.has("Principal"));
assertTrue(statement.has("Action"));
assertTrue(statement.has("Resource"));
assertTrue(statement.has("Condition"));
}
}
/**
* Tests that a policy correctly assigns unique statement IDs to any added
* statements without IDs yet.
*/
@Test
public void testStatementIdAssignment() throws Exception {
Policy policy = new Policy("S3PolicyId1");
policy.withStatements(
new Statement(Effect.Allow).withId("0")
.withPrincipals(Principal.AllUsers)
.withActions(new TestAction("action1")),
new Statement(Effect.Allow).withId("1")
.withPrincipals(Principal.AllUsers)
.withActions(new TestAction("action1")), new Statement(
Effect.Deny).withPrincipals(Principal.AllUsers)
.withActions(new TestAction("action2")));
assertValidStatementIds(policy);
}
private class TestAction implements Action {
private final String name;
public TestAction(String name) {
this.name = name;
}
public String getActionName() {
return name;
}
}
/**
* Asserts that each statement in the specified policy has a unique ID
* assigned to it.
*/
private void assertValidStatementIds(Policy policy) {
Set<String> statementIds = new HashSet<String>();
for (Statement statement : policy.getStatements()) {
assertNotNull(statement.getId());
assertFalse(statementIds.contains(statement.getId()));
statementIds.add(statement.getId());
}
}
@Test
public void testPrincipalAccountId() {
String ID_WITH_HYPHEN = "a-b-c-d-e-f-g";
String ID_WITHOUT_HYPHEN = "abcdefg";
Assert.assertEquals(ID_WITHOUT_HYPHEN,
new Principal(ID_WITH_HYPHEN).getId());
Assert.assertEquals(ID_WITHOUT_HYPHEN,
new Principal("AWS", ID_WITH_HYPHEN).getId());
Assert.assertEquals(ID_WITH_HYPHEN,
new Principal("Federated", ID_WITH_HYPHEN).getId());
Assert.assertEquals(ID_WITH_HYPHEN,
new Principal("AWS", ID_WITH_HYPHEN, false).getId());
}
}