/*
* Copyright 2010-2013 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.
*/
using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;
using Amazon.Auth.AccessControlPolicy.Internal;
namespace Amazon.Auth.AccessControlPolicy
{
///
/// An AWS access control policy is a object that acts as a container for one or
/// more statements, which specify fine grained rules for allowing or denying
/// various types of actions from being performed on your AWS resources.
///
/// By default, all requests to use your resource coming from anyone but you are
/// denied. Access control polices can override that by allowing different types
/// of access to your resources, or by explicitly denying different types of
/// access.
///
///
/// Each statement in an AWS access control policy takes the form:
/// "A has permission to do B to C where D applies".
///
/// -
/// A is the prinicpal
/// The AWS account that is making a request to
/// access or modify one of your AWS resources.
///
///
/// -
/// B is the action
/// the way in which your AWS resource is being accessed or modified, such
/// as sending a message to an Amazon SQS queue, or storing an object in an Amazon S3 bucket.
///
///
/// -
/// C is the resource
/// your AWS entity that the principal wants to access, such
/// as an Amazon SQS queue, or an object stored in Amazon S3.
///
///
/// -
/// D is the set of conditions
/// optional constraints that specify when to allow or deny
/// access for the principal to access your resource. Many expressive conditions are available,
/// some specific to each service. For example you can use date conditions to allow access to
/// your resources only after or before a specific time.
///
///
///
///
///
/// Note that an AWS access control policy should not be confused with the
/// similarly named "POST form policy" concept used in Amazon S3.
///
///
public class Policy
{
///
/// The default policy version
///
private const string DEFAULT_POLICY_VERSION = "2012-10-17";
private string id;
private string version = DEFAULT_POLICY_VERSION;
private IList statements = new List();
///
/// Constructs an empty AWS access control policy ready to be populated with
/// statements.
///
public Policy()
{
}
///
/// Constructs a new AWS access control policy with the specified policy ID.
/// The policy ID is a user specified string that serves to help developers
/// keep track of multiple polices. Policy IDs are often used as a human
/// readable name for a policy.
///
/// The policy ID for the new policy object. Policy IDs serve to
/// help developers keep track of multiple policies, and are often
/// used to give the policy a meaningful, human readable name.
public Policy(string id)
{
this.id = id;
}
///
/// Constructs a new AWS access control policy with the specified policy ID
/// and collection of statements. The policy ID is a user specified string
/// that serves to help developers keep track of multiple polices. Policy IDs
/// are often used as a human readable name for a policy.
///
/// The policy ID for the new policy object. Policy IDs serve to
/// help developers keep track of multiple policies, and are often
/// used to give the policy a meaningful, human readable name.
/// The statements to include in the new policy.
public Policy(string id, IList statements)
{
this.id = id;
this.statements = statements;
}
///
/// Gets and Sets the policy ID for this policy. Policy IDs serve to help
/// developers keep track of multiple policies, and are often used as human
/// readable name for a policy.
///
public string Id
{
get
{
return id;
}
set
{
this.id = value;
}
}
///
/// Sets the policy ID for this policy and returns the updated policy so that
/// multiple calls can be chained together.
///
/// Policy IDs serve to help developers keep track of multiple policies, and
/// are often used as human readable name for a policy.
///
///
/// The polich ID for this policy
/// this instance
public Policy WithId(string id)
{
Id = id;
return this;
}
///
/// Gets and sets the version of this AWS policy.
///
public string Version
{
get
{
return version;
}
set
{
this.version = value;
}
}
///
/// Gets and Sets the collection of statements contained by this policy. Individual
/// statements in a policy are what specify the rules that enable or disable
/// access to your AWS resources.
///
public IList Statements
{
get
{
return statements;
}
set
{
this.statements = value;
}
}
///
/// Checks to see if the permissions set in the statement are already set by another
/// statement in the policy.
///
/// The statement to verify
/// True if the statement's permissions are already allowed by the statement
public bool CheckIfStatementExists(Statement statement)
{
if (this.Statements == null)
return false;
foreach (var existingStatement in this.Statements)
{
if (existingStatement.Effect != statement.Effect)
continue;
if(!StatementContainsResources(existingStatement, statement.Resources))
continue;
if (!StatementContainsActions(existingStatement, statement.Actions))
continue;
if (!StatementContainsConditions(existingStatement, statement.Conditions))
continue;
if (!StatementContainsPrincipals(existingStatement, statement.Principals))
continue;
return true;
}
return false;
}
private static bool StatementContainsResources(Statement statement, IList resources)
{
foreach(var resource in resources)
{
if(statement.Resources.FirstOrDefault(x => string.Equals(x.Id, resource.Id)) == null)
return false;
}
return true;
}
private static bool StatementContainsActions(Statement statement, IList actions)
{
foreach (var action in actions)
{
if (statement.Actions.FirstOrDefault(x => string.Equals(x.ActionName, action.ActionName)) == null)
return false;
}
return true;
}
private static bool StatementContainsConditions(Statement statement, IList conditions)
{
foreach (var condition in conditions)
{
if (statement.Conditions.FirstOrDefault(x =>
string.Equals(x.Type, condition.Type) &&
string.Equals(x.ConditionKey, condition.ConditionKey) &&
x.Values.Intersect(condition.Values).Count() == condition.Values.Count()) == null)
return false;
}
return true;
}
private static bool StatementContainsPrincipals(Statement statement, IList principals)
{
foreach (var principal in principals)
{
if (statement.Principals.FirstOrDefault(x =>
string.Equals(x.Id, principal.Id) &&
string.Equals(x.Provider, principal.Provider)) == null)
return false;
}
return true;
}
///
/// Sets the collection of statements contained by this policy and returns
/// this policy object so that additional method calls can be chained
/// together.
///
/// Individual statements in a policy are what specify the rules that enable
/// or disable access to your AWS resources.
///
///
/// The collection of statements included in this policy.
/// this instance
public Policy WithStatements(params Statement[] statements)
{
if (this.Statements == null)
{
this.Statements = new List();
}
foreach (Statement element in statements)
{
this.Statements.Add(element);
}
return this;
}
///
/// Returns a JSON string representation of this AWS access control policy,
/// suitable to be sent to an AWS service as part of a request to set an
/// access control policy.
///
/// A JSON string representation of this AWS access control policy.
public string ToJson()
{
return ToJson(true);
}
///
/// Returns a JSON string representation of this AWS access control policy,
/// suitable to be sent to an AWS service as part of a request to set an
/// access control policy.
///
/// Toggle pretty print for the generated JSON document
/// A JSON string representation of this AWS access control policy.
public string ToJson(bool prettyPrint)
{
return JsonPolicyWriter.WritePolicyToString(prettyPrint, this);
}
///
/// Parses a JSON document of a policy and creates a Policy object.
///
/// JSON document of a policy.
///
public static Policy FromJson(string json)
{
return JsonPolicyReader.ReadJsonStringToPolicy(json);
}
}
}