/* * 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); } } }