Example #1
0
        /// <summary>
        /// Compact SQS access policy
        /// </summary>
        /// <para>
        /// Transforms policies with multiple similar statements:
        /// <code>
        /// {
        ///     "Version": "2012-10-17",
        ///     "Statement": [
        ///     {
        ///         "Effect": "Allow",
        ///         "Principal": {
        ///             "AWS": "*"
        ///         },
        ///         "Action": "sqs:SendMessage",
        ///         "Resource": "arn:aws:sqs:us-east-1:MyQueue",
        ///         "Condition": {
        ///             "ArnLike": {
        ///                 "aws:SourceArn": "arn:aws:sns:us-east-1:FirstTopic"
        ///             }
        ///         }
        ///     },
        ///     {
        ///         "Effect": "Allow",
        ///         "Principal": {
        ///             "AWS": "*"
        ///         },
        ///         "Action": "sqs:SendMessage",
        ///         "Resource": "arn:aws:sqs:us-east-1:MyQueue",
        ///         "Condition": {
        ///             "ArnLike": {
        ///                 "aws:SourceArn": "arn:aws:sns:us-east-1:SecondTopic"
        ///             }
        ///         }
        ///     }]
        /// }
        /// </code>
        ///     into compacted single statement:
        /// <code>
        /// {
        ///     "Version": "2012-10-17",
        ///     "Statement": [
        ///     {
        ///         "Effect": "Allow",
        ///         "Principal": {
        ///             "AWS": "*"
        ///         },
        ///         "Action": "sqs:SendMessage",
        ///         "Resource": "arn:aws:sqs:us-east-1:MyQueue",
        ///         "Condition": {
        ///             "ArnLike": {
        ///                 "aws:SourceArn": [
        ///                 "arn:aws:sns:us-east-1:FirstTopic",
        ///                 "arn:aws:sns:us-east-1:SecondTopic"
        ///                     ]
        ///             }
        ///         }
        ///     }]
        /// }
        /// </code>
        /// </para>
        /// <param name="policy"></param>
        /// <param name="sqsQueueArn"></param>
        public static void CompactSqsPermissions(this Policy policy, string sqsQueueArn)
        {
            var statementsToCompact = policy.Statements
                                      .Where(s => s.Effect == Statement.StatementEffect.Allow)
#pragma warning disable CS0618 // Type or member is obsolete
                                      .Where(s => s.Actions.All(a => string.Equals(a.ActionName, SQSActionIdentifiers.SendMessage.ActionName, StringComparison.OrdinalIgnoreCase)))
#pragma warning restore CS0618 // Type or member is obsolete
                                      .Where(s => s.Resources.All(r => string.Equals(r.Id, sqsQueueArn, StringComparison.OrdinalIgnoreCase)))
                                      .Where(s => s.Principals.All(r => string.Equals(r.Id, "*", StringComparison.OrdinalIgnoreCase)))
                                      .ToList();

            if (statementsToCompact.Count < 2)
            {
                return;
            }

            var topicArns = new HashSet <string>();

            foreach (var statement in statementsToCompact)
            {
                policy.Statements.Remove(statement);
                foreach (var topicArn in statement.Conditions.SelectMany(c => c.Values))
                {
                    topicArns.Add(topicArn);
                }
            }

            policy.AddSqsPermissions(topicArns, sqsQueueArn);
        }
Example #2
0
        /// <summary>
        /// Compact SQS access policy
        /// </summary>
        /// <para>
        /// Transforms policies with multiple similar statements:
        /// <code>
        /// {
        ///     "Version": "2012-10-17",
        ///     "Statement": [
        ///     {
        ///         "Effect": "Allow",
        ///         "Principal": {
        ///             "AWS": "*"
        ///         },
        ///         "Action": "sqs:SendMessage",
        ///         "Resource": "arn:aws:sqs:us-east-1:MyQueue-v1",
        ///         "Condition": {
        ///             "ArnLike": {
        ///                 "aws:SourceArn": "arn:aws:sns:us-east-1:MyQueue-FirstTopic"
        ///             }
        ///         }
        ///     },
        ///     {
        ///         "Effect": "Allow",
        ///         "Principal": {
        ///             "AWS": "*"
        ///         },
        ///         "Action": "sqs:SendMessage",
        ///         "Resource": "arn:aws:sqs:us-east-1:MyQueue-v1",
        ///         "Condition": {
        ///             "ArnLike": {
        ///                 "aws:SourceArn": "arn:aws:sns:us-east-1:MyQueue-SecondTopic"
        ///             }
        ///         }
        ///     },
        ///     {
        ///         "Effect": "Allow",
        ///         "Principal": {
        ///             "AWS": "*"
        ///         },
        ///         "Action": "sqs:SendMessage",
        ///         "Resource": "arn:aws:sqs:us-east-1:MyQueue-v1",
        ///         "Condition": {
        ///             "ArnLike": {
        ///                 "aws:SourceArn": "arn:aws:sns:us-east-1:MyQueue2-FirstTopic"
        ///             }
        ///         }
        ///     },]
        /// }
        /// </code>
        ///     into compacted single statement:
        /// <code>
        /// {
        ///     "Version": "2012-10-17",
        ///     "Statement": [
        ///     {
        ///         "Effect": "Allow",
        ///         "Principal": {
        ///             "AWS": "*"
        ///         },
        ///         "Action": "sqs:SendMessage",
        ///         "Resource": "arn:aws:sqs:us-east-1:MyQueue-v1",
        ///         "Condition": {
        ///             "ArnLike": {
        ///                 "aws:SourceArn": [
        ///                     "arn:aws:sns:us-east-1:MyQueue-*",
        ///                     "arn:aws:sns:us-east-1:MyQueue2-FirstTopic"
        ///                 ]
        ///             }
        ///         }
        ///     }]
        /// }
        /// </code>
        /// </para>
        /// <param name="policy"></param>
        /// <param name="sqsQueueArn"></param>
        public static void CompactSqsPermissions(this Policy policy, string sqsQueueArn)
        {
            var statementsToCompact = policy.Statements
                                      .Where(s => s.Effect == Statement.StatementEffect.Allow)
#pragma warning disable CS0618 // Type or member is obsolete
                                      .Where(s => s.Actions.All(a => string.Equals(a.ActionName, SQSActionIdentifiers.SendMessage.ActionName, StringComparison.OrdinalIgnoreCase)))
#pragma warning restore CS0618 // Type or member is obsolete
                                      .Where(s => s.Resources.All(r => string.Equals(r.Id, sqsQueueArn, StringComparison.OrdinalIgnoreCase)))
                                      .Where(s => s.Principals.All(r => string.Equals(r.Id, "*", StringComparison.OrdinalIgnoreCase)))
                                      .ToList();

            var groupName = GetGroupName(sqsQueueArn);

            if (groupName != null)
            {
                groupName = $":{groupName}-";
            }
            if (statementsToCompact.Count < 2 && groupName == null)
            {
                return;
            }

            var topicArns = new HashSet <string>();

            foreach (var statement in statementsToCompact)
            {
                policy.Statements.Remove(statement);
                foreach (var topicArn in statement.Conditions.SelectMany(c => c.Values))
                {
                    topicArns.Add(
                        groupName != null && topicArn.Contains(groupName, StringComparison.InvariantCultureIgnoreCase)
                            ? $"{GetArnGroupPrefix(topicArn)}-*"
                            : topicArn);
                }
            }

            policy.AddSqsPermissions(topicArns.OrderBy(a => a), sqsQueueArn);
        }