/// <summary> /// Check to see if the policy for the queue has already given permission to the topic. /// </summary> /// <param name="policy"></param> /// <param name="topicArn"></param> /// <param name="sqsQueueArn"></param> /// <returns></returns> private static bool HasSQSPermission(Policy policy, string topicArn, string sqsQueueArn) { foreach (Statement statement in policy.Statements) { // See if the statement contains the topic as a resource bool containsResource = false; foreach (var resource in statement.Resources) { if (resource.Id.Equals(sqsQueueArn)) { containsResource = true; break; } } // If queue found as the resource see if the condition is for this topic if (containsResource) { foreach (var condition in statement.Conditions) { if ((string.Equals(condition.Type, ConditionFactory.StringComparisonType.StringLike.ToString(), StringComparison.OrdinalIgnoreCase) || string.Equals(condition.Type, ConditionFactory.StringComparisonType.StringEquals.ToString(), StringComparison.OrdinalIgnoreCase) || string.Equals(condition.Type, ConditionFactory.ArnComparisonType.ArnEquals.ToString(), StringComparison.OrdinalIgnoreCase) || string.Equals(condition.Type, ConditionFactory.ArnComparisonType.ArnLike.ToString(), StringComparison.OrdinalIgnoreCase)) && string.Equals(condition.ConditionKey, ConditionFactory.SOURCE_ARN_CONDITION_KEY, StringComparison.OrdinalIgnoreCase) && condition.Values.Contains<string>(topicArn)) return true; } } } return false; }
/// <summary> /// Add statement to the policy that gives the sns topic access to send a message to the queue. /// </summary> /// <param name="policy"></param> /// <param name="topicArn"></param> /// <param name="sqsQueueArn"></param> private static void AddSQSPermission(Policy policy, string topicArn, string sqsQueueArn) { Statement statement = new Statement(Statement.StatementEffect.Allow); statement.Actions.Add(SQSActionIdentifiers.SendMessage); statement.Resources.Add(new Resource(sqsQueueArn)); statement.Conditions.Add(ConditionFactory.NewSourceArnCondition(topicArn)); statement.Principals.Add(new Principal("*")); policy.Statements.Add(statement); }
public static void CreateLambdaFunction(string functionName, string iamRoleName, out string iamRoleArn, out string functionArn) { var iamCreateResponse = iamClient.CreateRole(new CreateRoleRequest { RoleName = iamRoleName, AssumeRolePolicyDocument = LAMBDA_ASSUME_ROLE_POLICY }); iamRoleArn = iamCreateResponse.Role.Arn; var statement = new Statement(Statement.StatementEffect.Allow); statement.Actions.Add(S3ActionIdentifiers.PutObject); statement.Actions.Add(S3ActionIdentifiers.GetObject); statement.Resources.Add(new Resource("*")); var policy = new Amazon.Auth.AccessControlPolicy.Policy(); policy.Statements.Add(statement); iamClient.PutRolePolicy(new PutRolePolicyRequest { RoleName = iamRoleName, PolicyName = "admin", PolicyDocument = policy.ToJson() }); // Wait for the role and policy to propagate Thread.Sleep(5000); MemoryStream stream = CreateScriptStream(); var uploadRequest = new CreateFunctionRequest { FunctionName = functionName, Code = new FunctionCode { ZipFile = stream }, Handler = "helloworld.handler", //Mode = Mode.Event, Runtime = Runtime.Nodejs, Role = iamCreateResponse.Role.Arn }; var uploadResponse = Client.CreateFunction(uploadRequest); createdFunctionNames.Add(functionName); Assert.IsTrue(uploadResponse.CodeSize > 0); Assert.IsNotNull(uploadResponse.FunctionArn); functionArn = uploadResponse.FunctionArn; }
public void Save(string sourceArn, IAmazonSimpleNotificationService client) { ActionIdentifier[] actions = { SNSActionIdentifiers.Subscribe}; var snsPolicy = new Policy() .WithStatements(GetDefaultStatement(sourceArn)) .WithStatements(new Statement(Statement.StatementEffect.Allow) .WithPrincipals(_accountIds.Select(a => new Principal(a)).ToArray()) .WithResources(new Resource(sourceArn)) .WithActionIdentifiers(actions)); var attributeValue = snsPolicy.ToJson(); var setQueueAttributesRequest = new SetTopicAttributesRequest(sourceArn, "Policy", attributeValue); client.SetTopicAttributes(setQueueAttributesRequest); }
public static void Save(string sourceArn, string queueArn, string queueUrl, IAmazonSQS client) { var topicArnWildcard = CreateTopicArnWildcard(sourceArn); ActionIdentifier[] actions = { SQSActionIdentifiers.SendMessage }; Policy sqsPolicy = new Policy() .WithStatements(new Statement(Statement.StatementEffect.Allow) .WithPrincipals(Principal.AllUsers) .WithResources(new Resource(queueArn)) .WithConditions(ConditionFactory.NewSourceArnCondition(topicArnWildcard)) .WithActionIdentifiers(actions)); SetQueueAttributesRequest setQueueAttributesRequest = new SetQueueAttributesRequest(); setQueueAttributesRequest.QueueUrl = queueUrl; setQueueAttributesRequest.Attributes["Policy"] = sqsPolicy.ToJson(); client.SetQueueAttributes(setQueueAttributesRequest); }
/// <summary> /// Helper method for AuthorizeS3ToSendMessage() /// </summary> /// <param name="response"></param> /// <param name="bucket"></param> /// <param name="policy"></param> /// <param name="statement"></param> private static void GetNewPolicyAndStatement(GetQueueAttributesResponse response, string bucket, out Policy policy, out Statement statement) { if (!string.IsNullOrEmpty(response.Policy)) { policy = Policy.FromJson(response.Policy); } else { policy = new Policy(); } var sourceArn = string.Format(CultureInfo.InvariantCulture, "arn:aws:s3:*:*:{0}", bucket); statement = new Statement(Statement.StatementEffect.Allow); statement.Actions.Add(SQSActionIdentifiers.SendMessage); statement.Resources.Add(new Resource(response.QueueARN)); statement.Conditions.Add(ConditionFactory.NewSourceArnCondition(sourceArn)); statement.Principals.Add(new Principal("*")); }
/// <summary> /// This is a utility method which updates the policy of a queue to allow the /// S3 bucket to publish events to it. /// </summary> /// <param name="queueUrl">The queue that will have its policy updated.</param> /// <param name="bucket">The bucket that will be given access to send messages from.</param> /// <returns>The ARN for the SQS queue. This can be used when setting up the S3 bucket notification.</returns> public string AuthorizeS3ToSendMessage(string queueUrl, string bucket) { var getAttributeResponse = this.GetQueueAttributes(new GetQueueAttributesRequest { QueueUrl = queueUrl, AttributeNames = new List<string> { "All"} }); Policy policy; if (!string.IsNullOrEmpty(getAttributeResponse.Policy)) { policy = Policy.FromJson(getAttributeResponse.Policy); } else { policy = new Policy(); } var sourceArn = string.Format(CultureInfo.InvariantCulture, "arn:aws:s3:*:*:{0}", bucket); Statement statement = new Statement(Statement.StatementEffect.Allow); statement.Actions.Add(SQSActionIdentifiers.SendMessage); statement.Resources.Add(new Resource(getAttributeResponse.QueueARN)); statement.Conditions.Add(ConditionFactory.NewSourceArnCondition(sourceArn)); statement.Principals.Add(new Principal("*")); if (!policy.CheckIfStatementExists(statement)) { policy.Statements.Add(statement); var policyString = policy.ToJson(); this.SetQueueAttributes(new SetQueueAttributesRequest { QueueUrl = queueUrl, Attributes = new Dictionary<string, string> { {"Policy", policyString} } }); } return getAttributeResponse.QueueARN; }
public void TestIfStatementAlreadyExists() { var policy = new Policy(); Statement statement = new Statement(Statement.StatementEffect.Allow); statement.Actions.Add(SQSActionIdentifiers.SendMessage); statement.Resources.Add(new Resource("the:queue:arn")); statement.Conditions.Add(ConditionFactory.NewSourceArnCondition("source:arn")); statement.Principals.Add(new Principal("*")); policy.Statements.Add(statement); Statement newStatement = new Statement(Statement.StatementEffect.Allow); newStatement.Actions.Add(SQSActionIdentifiers.SendMessage); newStatement.Resources.Add(new Resource("the:queue:arn")); newStatement.Conditions.Add(ConditionFactory.NewSourceArnCondition("source:arn")); newStatement.Principals.Add(new Principal("*")); Assert.IsTrue(policy.CheckIfStatementExists(newStatement)); newStatement.Effect = Statement.StatementEffect.Deny; Assert.IsFalse(policy.CheckIfStatementExists(newStatement)); newStatement.Effect = Statement.StatementEffect.Allow; Assert.IsTrue(policy.CheckIfStatementExists(newStatement)); newStatement.Actions.Add(SQSActionIdentifiers.AddPermission); Assert.IsFalse(policy.CheckIfStatementExists(newStatement)); newStatement.Actions.Remove(SQSActionIdentifiers.AddPermission); Assert.IsTrue(policy.CheckIfStatementExists(newStatement)); newStatement.Principals.Add(new Principal("data")); Assert.IsFalse(policy.CheckIfStatementExists(newStatement)); newStatement.Principals.RemoveAt(1); Assert.IsTrue(policy.CheckIfStatementExists(newStatement)); newStatement.Conditions[0].ConditionKey = "new:arn"; Assert.IsFalse(policy.CheckIfStatementExists(newStatement)); }
public void TestAnonymousPrincipal() { var policy = new Policy { Statements = { new Statement(Statement.StatementEffect.Deny) { Principals = { Principal.Anonymous } } } }; var json = policy.ToJson(); Console.WriteLine(json); Assert.IsTrue(json.Contains("\"Principal\" : \"*\"")); var roundTripPolicy = Policy.FromJson(json); Assert.AreEqual(Principal.Anonymous, roundTripPolicy.Statements[0].Principals[0]); }
public ISubscribeReponseMessage Subscribe(string queueUrl) { var sqsConfig = new AmazonSQSConfig {ServiceURL = SqsServiceUrl}; var snsConfig = new AmazonSimpleNotificationServiceConfig {ServiceURL = SnsServiceUrl}; using (var sqsClient = _awsConfig.CreateAwsClient<AmazonSQSClient>(sqsConfig)) { var attributesRequest = new GetQueueAttributesRequest(queueUrl, new List<string> {"QueueArn"}); var attributesResponse = sqsClient.GetQueueAttributes(attributesRequest); using (var snsClient = _awsConfig.CreateAwsClient<AmazonSimpleNotificationServiceClient>(snsConfig)) { var subribeResonse = snsClient.Subscribe(new SubscribeRequest(TopicArn, "sqs", attributesResponse.QueueARN)); } var actions = new ActionIdentifier[2]; actions[0] = SQSActionIdentifiers.SendMessage; actions[1] = SQSActionIdentifiers.ReceiveMessage; var sqsPolicy = new Policy().WithStatements( new Statement(Statement.StatementEffect.Allow).WithPrincipals(Principal.AllUsers) .WithResources( new Resource(attributesResponse.QueueARN)) .WithConditions( ConditionFactory.NewSourceArnCondition( TopicArn)) .WithActionIdentifiers(actions)); var setQueueAttributesRequest = new SetQueueAttributesRequest(); var attributes = new Dictionary<string, string> {{"Policy", sqsPolicy.ToJson()}}; var attRequest = new SetQueueAttributesRequest(attributesRequest.QueueUrl, attributes); sqsClient.SetQueueAttributes(attRequest); return new SubcriptionMessage("Ok"); } }
public void create_sqs_queue() { GetUserNameAndPassword(); var sqsClient = Amazon.AWSClientFactory.CreateAmazonSQSClient(_key, _secret); var snsTopic = Amazon.AWSClientFactory.CreateAmazonSNSClient(_key, _secret); var topicArn = "arn:aws:sns:us-east-1:451419498740:Elliott-has-an-awesome-blog"; //Create a new SQS queue var createQueueRequest = new CreateQueueRequest().WithQueueName("elliotts-blog"); var createQueueResponse = sqsClient.CreateQueue(createQueueRequest); // keep the queueUrl handy var queueUrl = createQueueResponse.CreateQueueResult.QueueUrl; // get the Access Resource Name so we can allow the SNS to put messages on it var getQueueArnRequest = new GetQueueAttributesRequest() .WithQueueUrl(queueUrl) .WithAttributeName("QueueArn"); var getQueueArnResponse = sqsClient.GetQueueAttributes(getQueueArnRequest); var queueArn = getQueueArnResponse.GetQueueAttributesResult.Attribute[0].Value; //create a Policy for the SQS queue that allows SNS to publish to it var allowSnsStatement = new Statement(Statement.StatementEffect.Allow) .WithPrincipals(Principal.AllUsers) .WithResources(new Resource(queueArn)) .WithConditions(ConditionFactory.NewSourceArnCondition(topicArn)) .WithActionIdentifiers(SQSActionIdentifiers.SendMessage); var policy = new Policy("allow sns").WithStatements(new[] {allowSnsStatement}); var attribute = new Attribute().WithName("Policy").WithValue(policy.ToJson()); var setQueueAttributesRequest = new SetQueueAttributesRequest().WithQueueUrl(queueUrl).WithAttribute(attribute); sqsClient.SetQueueAttributes(setQueueAttributesRequest); // ok, now lets create the subscription for sqs with the queueArn we created var subscribeRequest = new SubscribeRequest() .WithEndpoint(queueArn) .WithTopicArn(topicArn) .WithProtocol("sqs"); snsTopic.Subscribe(subscribeRequest); }
public virtual void GrantNotificationPermission(AmazonSQSClient sqsClient, string queueArn, string queueUrl, string topicArn) { // Create a policy to allow the queue to receive notifications from the SNS topic var policy = new Policy("SubscriptionPermission") { Statements = { new Statement(Statement.StatementEffect.Allow) { Actions = {SQSActionIdentifiers.SendMessage}, Principals = {new Principal("*")}, Conditions = {ConditionFactory.NewSourceArnCondition(topicArn)}, Resources = {new Resource(queueArn)} } } }; var attributes = new Dictionary<string, string>(); attributes.Add("Policy", policy.ToJson()); // Create the request to set the queue attributes for policy var setQueueAttributesRequest = new SetQueueAttributesRequest { QueueUrl = queueUrl, Attributes = attributes }; // Set the queue policy sqsClient.SetQueueAttributes(setQueueAttributesRequest); }
public void LambdaFunctionTest() { const string HELLO_SCRIPT = @"console.log('Loading http') exports.handler = function (request, response) { response.write(""Hello, world!""); response.end(); console.log(""Request completed""); }"; MemoryStream stream = new MemoryStream(); using (ZipArchive archive = new ZipArchive(stream, ZipArchiveMode.Create, true)) { var entry = archive.CreateEntry("helloworld.js"); using (var entryStream = entry.Open()) using (var writer = new StreamWriter(entryStream)) { writer.Write(HELLO_SCRIPT); } } stream.Position = 0; var functionName = "HelloWorld"; bool uploaded = false; var iamRoleName = "Lambda-" + DateTime.Now.Ticks; bool iamRoleCreated = false; try { var iamCreateResponse = iamClient.CreateRole(new CreateRoleRequest { RoleName = iamRoleName, AssumeRolePolicyDocument = LAMBDA_ASSUME_ROLE_POLICY }); var statement = new Statement(Statement.StatementEffect.Allow); statement.Actions.Add(S3ActionIdentifiers.PutObject); statement.Actions.Add(S3ActionIdentifiers.GetObject); statement.Resources.Add(new Resource("*")); var policy = new Policy(); policy.Statements.Add(statement); iamClient.PutRolePolicy(new PutRolePolicyRequest { RoleName = iamRoleName, PolicyName = "admin", PolicyDocument = policy.ToJson() }); // Wait for the role and policy to propagate Thread.Sleep(5000); var uploadRequest = new UploadFunctionRequest { FunctionName = functionName, FunctionZip = stream, Handler = "helloworld.handler", Mode = Mode.Event, Runtime = Runtime.Nodejs, Role = iamCreateResponse.Role.Arn }; var uploadResponse = lambdaClient.UploadFunction(uploadRequest); uploaded = true; Assert.IsTrue(uploadResponse.CodeSize > 0); Assert.IsNotNull(uploadResponse.ConfigurationId); // List all the functions and make sure the newly uploaded function is in the collection var listResponse = lambdaClient.ListFunctions(); var function = listResponse.Functions.FirstOrDefault(x => x.FunctionName == functionName); Assert.IsNotNull(function); Assert.AreEqual("helloworld.handler", function.Handler); Assert.AreEqual(iamCreateResponse.Role.Arn, function.Role); // Get the function with a presigned URL to the uploaded code var getFunctionResponse = lambdaClient.GetFunction(functionName); Assert.AreEqual("helloworld.handler", getFunctionResponse.Configuration.Handler); Assert.IsNotNull(getFunctionResponse.Code.Location); // Get the function's configuration only var getFunctionConfiguration = lambdaClient.GetFunctionConfiguration(functionName); Assert.AreEqual("helloworld.handler", getFunctionConfiguration.Handler); // Call the function var invokeResponse = lambdaClient.InvokeAsync(functionName); Assert.AreEqual(invokeResponse.Status, 202); // Status Code Accepted } finally { if(uploaded) lambdaClient.DeleteFunction(functionName); if (iamRoleCreated) iamClient.DeleteRole(new DeleteRoleRequest { RoleName = iamRoleName }); } }
public string SetSqsPolicyForSnsPublish(Uri queueUrl, string queueArn, string mytopicArn) { queueUrl.Requires("queueUrl").IsNotNull(); queueArn.Requires("queueArn").IsNotNullOrWhiteSpace(); mytopicArn.Requires("mytopicArn").IsNotNullOrWhiteSpace(); var sqsPolicy = new Policy().WithStatements( new Statement(Statement.StatementEffect.Allow) .WithResources(new Resource(queueArn)) .WithPrincipals(Principal.AllUsers) .WithActionIdentifiers(SQSActionIdentifiers.SendMessage) .WithConditions(ConditionFactory.NewCondition(ConditionFactory.ArnComparisonType.ArnEquals, ConditionSourceArn, mytopicArn))); var attributes = new Dictionary<string, string> { {QueueAttributeName.Policy, sqsPolicy.ToJson()} }; var setQueueAttributesRequest = new SetQueueAttributesRequest(queueUrl.AbsoluteUri, attributes); using (var sqs = amazonSqsFactory()) { var response = sqs.SetQueueAttributes(setQueueAttributesRequest); return response.ResponseMetadata.RequestId; } }
/// <summary> /// Subscribes an existing Amazon SQS queue to existing Amazon SNS topics asynchronously. /// <para> /// The policy applied to the SQS queue is similar to this: /// <code> /// { /// "Version" : "2008-10-17", /// "Statement" : [{ /// "Sid" : "topic-subscription-arn:aws:sns:us-west-2:599109622955:myTopic", /// "Effect" : "Allow", /// "Principal" : "*", /// "Action" : ["sqs:SendMessage"], /// "Resource":["arn:aws:sqs:us-west-2:599109622955:myQueue"], /// "Condition" : { /// "ArnLike":{ /// "aws:SourceArn":["arn:aws:sns:us-west-2:599109622955:myTopic"] /// } /// } /// }] /// } /// </code> /// </para> /// <para> /// There might be a small time period immediately after /// subscribing the SQS queue to the SNS topic and updating the SQS queue's /// policy, where messages are not able to be delivered to the queue. After a /// moment, the new queue policy will propagate and the queue will be able to /// receive messages. This delay only occurs immediately after initially /// subscribing the queue. /// </para> /// </summary> /// <param name="topicArns">The topics to subscribe to</param> /// <param name="sqsClient">The SQS client used to get attributes and set the policy on the SQS queue.</param> /// <param name="sqsQueueUrl">The queue to add a subscription to.</param> /// <returns>The mapping of topic ARNs to subscription ARNs as returned by Amazon SNS when the queue is /// successfully subscribed to each topic.</returns> public async Task<IDictionary<string, string>> SubscribeQueueToTopicsAsync(IList<string> topicArns, ICoreAmazonSQS sqsClient, string sqsQueueUrl) { // Get the queue's existing policy and ARN var queueAttributes = await sqsClient.GetAttributesAsync(sqsQueueUrl).ConfigureAwait(false); string sqsQueueArn = queueAttributes["QueueArn"]; Policy policy; string policyStr = null; if(queueAttributes.ContainsKey("Policy")) policyStr = queueAttributes["Policy"]; if (string.IsNullOrEmpty(policyStr)) policy = new Policy(); else policy = Policy.FromJson(policyStr); var subscriptionArns = new Dictionary<string,string>(); foreach (var topicArn in topicArns) { if (!HasSQSPermission(policy, topicArn, sqsQueueArn)) AddSQSPermission(policy, topicArn, sqsQueueArn); SubscribeResponse response = await this.SubscribeAsync(new SubscribeRequest { TopicArn = topicArn, Protocol = "sqs", Endpoint = sqsQueueArn, }).ConfigureAwait(false); subscriptionArns.Add(topicArn, response.SubscriptionArn); } var setAttributes = new Dictionary<string, string> { { "Policy", policy.ToJson() } }; await sqsClient.SetAttributesAsync(sqsQueueUrl, setAttributes).ConfigureAwait(false); return subscriptionArns; }
public void LambdaFunctionTest() { const string HELLO_SCRIPT = @"console.log('Loading http') exports.handler = function (request, response) { response.write(""Hello, world!""); response.end(); console.log(""Request completed""); }"; MemoryStream stream = new MemoryStream(); using (ZipArchive archive = new ZipArchive(stream, ZipArchiveMode.Create, true)) { var entry = archive.CreateEntry("helloworld.js"); using (var entryStream = entry.Open()) using (var writer = new StreamWriter(entryStream)) { writer.Write(HELLO_SCRIPT); } } stream.Position = 0; var functionName = "HelloWorld"; bool uploaded = false; var iamRoleName = "Lambda-" + DateTime.Now.Ticks; bool iamRoleCreated = false; try { var iamCreateResponse = iamClient.CreateRole(new CreateRoleRequest { RoleName = iamRoleName, AssumeRolePolicyDocument = LAMBDA_ASSUME_ROLE_POLICY }); var statement = new Statement(Statement.StatementEffect.Allow); statement.Actions.Add(S3ActionIdentifiers.PutObject); statement.Actions.Add(S3ActionIdentifiers.GetObject); statement.Resources.Add(new Resource("*")); var policy = new Amazon.Auth.AccessControlPolicy.Policy(); policy.Statements.Add(statement); iamClient.PutRolePolicy(new PutRolePolicyRequest { RoleName = iamRoleName, PolicyName = "admin", PolicyDocument = policy.ToJson() }); // Wait for the role and policy to propagate Thread.Sleep(5000); var uploadRequest = new UploadFunctionRequest { FunctionName = functionName, FunctionZip = stream, Handler = "helloworld.handler", Mode = Mode.Event, Runtime = Runtime.Nodejs, Role = iamCreateResponse.Role.Arn }; var uploadResponse = lambdaClient.UploadFunction(uploadRequest); uploaded = true; Assert.IsTrue(uploadResponse.CodeSize > 0); Assert.IsNotNull(uploadResponse.ConfigurationId); // List all the functions and make sure the newly uploaded function is in the collection var listResponse = lambdaClient.ListFunctions(); var function = listResponse.Functions.FirstOrDefault(x => x.FunctionName == functionName); Assert.IsNotNull(function); Assert.AreEqual("helloworld.handler", function.Handler); Assert.AreEqual(iamCreateResponse.Role.Arn, function.Role); // Get the function with a presigned URL to the uploaded code var getFunctionResponse = lambdaClient.GetFunction(functionName); Assert.AreEqual("helloworld.handler", getFunctionResponse.Configuration.Handler); Assert.IsNotNull(getFunctionResponse.Code.Location); // Get the function's configuration only var getFunctionConfiguration = lambdaClient.GetFunctionConfiguration(functionName); Assert.AreEqual("helloworld.handler", getFunctionConfiguration.Handler); // Call the function var invokeResponse = lambdaClient.InvokeAsync(functionName); Assert.AreEqual(invokeResponse.Status, 202); // Status Code Accepted } finally { if (uploaded) { lambdaClient.DeleteFunction(functionName); } if (iamRoleCreated) { iamClient.DeleteRole(new DeleteRoleRequest { RoleName = iamRoleName }); } } }
/// <summary> /// Subscribes an existing Amazon SQS queue to an existing Amazon SNS topic. /// <para> /// The policy applied to the SQS queue is similar to this: /// <code> /// { /// "Version" : "2008-10-17", /// "Statement" : [{ /// "Sid" : "topic-subscription-arn:aws:sns:us-west-2:599109622955:myTopic", /// "Effect" : "Allow", /// "Principal" : { /// "AWS":["*"] /// }, /// "Action" : ["sqs:SendMessage"], /// "Resource":["arn:aws:sqs:us-west-2:599109622955:myQueue"], /// "Condition" : { /// "ArnLike":{ /// "aws:SourceArn":["arn:aws:sns:us-west-2:599109622955:myTopic"] /// } /// } /// }] /// } /// </code> /// </para> /// <para> /// There might be a small time period immediately after /// subscribing the SQS queue to the SNS topic and updating the SQS queue's /// policy, where messages are not able to be delivered to the queue. After a /// moment, the new queue policy will propagate and the queue will be able to /// receive messages. This delay only occurs immediately after initially /// subscribing the queue. /// </para> /// </summary> /// <param name="topicArn">The topic to subscribe to</param> /// <param name="sqsClient">The SQS client used to get attributes and set the policy on the SQS queue.</param> /// <param name="sqsQueueUrl">The queue to add a subscription to.</param> /// <returns>The subscription ARN as returned by Amazon SNS when the queue is /// successfully subscribed to the topic.</returns> public string SubscribeQueue(string topicArn, IAmazonSQS sqsClient, string sqsQueueUrl) { // Get the queue's existing policy and ARN var getAttributeResponse = sqsClient.GetQueueAttributes(new GetQueueAttributesRequest() { AttributeNames = new List<string>() { "All" }, QueueUrl = sqsQueueUrl }); string sqsQueueArn = getAttributeResponse.QueueARN; Policy policy; string policyStr = getAttributeResponse.Policy; if (string.IsNullOrEmpty(policyStr)) policy = new Policy(); else policy = Policy.FromJson(policyStr); if (!HasSQSPermission(policy, topicArn, sqsQueueArn)) { AddSQSPermission(policy, topicArn, sqsQueueArn); sqsClient.SetQueueAttributes(new SetQueueAttributesRequest() { QueueUrl = sqsQueueUrl, Attributes = new Dictionary<string, string>() { { "Policy", policy.ToJson() } } }); } var subscribeResponse = this.Subscribe(new SubscribeRequest() { TopicArn = topicArn, Protocol = "sqs", Endpoint = sqsQueueArn }); return subscribeResponse.SubscriptionArn; }
public string SetSqsPolicyForSnsPublish(Uri queueUrl, string queueArn, string mytopicArn) { Validate.That(queueUrl).IsNotNull(); Validate.That(queueArn).IsNotNullOrEmpty(); Validate.That(mytopicArn).IsNotNullOrEmpty(); var sqsPolicy = new Policy().WithStatements( new Statement(Statement.StatementEffect.Allow) .WithResources(new Resource(queueArn)) .WithPrincipals(Principal.AllUsers) .WithActionIdentifiers(SQSActionIdentifiers.SendMessage) .WithConditions(ConditionFactory.NewCondition(ConditionFactory.ArnComparisonType.ArnEquals, conditionSourceArn, mytopicArn))); var setQueueAttributesRequest = new SetQueueAttributesRequest().WithQueueUrl(queueUrl.AbsoluteUri).WithPolicy(sqsPolicy.ToJson()); using (var sqs = amazonSqsFactory()) { var response = sqs.SetQueueAttributes(setQueueAttributesRequest); return response.ResponseMetadata.RequestId; } }
/// <summary> /// This is a utility method which updates the policy of a topic to allow the /// S3 bucket to publish events to it. /// </summary> /// <param name="topicArn">The topic that will have its policy updated.</param> /// <param name="bucket">The bucket that will be given access to publish from.</param> public void AuthorizeS3ToPublish(string topicArn, string bucket) { var attributes = this.GetTopicAttributes(new GetTopicAttributesRequest { TopicArn = topicArn }).Attributes; Policy policy; if(attributes.ContainsKey("Policy") && !string.IsNullOrEmpty(attributes["Policy"])) { policy = Policy.FromJson(attributes["Policy"]); } else { policy = new Policy(); } var sourceArn = string.Format(CultureInfo.InvariantCulture, "arn:aws:s3:*:*:{0}", bucket); Statement newStatement = new Statement(Statement.StatementEffect.Allow); newStatement.Actions.Add(SNSActionIdentifiers.Publish); newStatement.Resources.Add(new Resource(topicArn)); newStatement.Conditions.Add(ConditionFactory.NewSourceArnCondition(sourceArn)); newStatement.Principals.Add(new Principal("*")); if (!policy.CheckIfStatementExists(newStatement)) { policy.Statements.Add(newStatement); var policyString = policy.ToJson(); this.SetTopicAttributes(new SetTopicAttributesRequest { TopicArn = topicArn, AttributeName = "Policy", AttributeValue = policyString }); } }
/// <summary> /// Helper method for AuthorizeS3ToPublishAsync() /// </summary> /// <param name="attributes"></param> /// <param name="topicArn"></param> /// <param name="bucket"></param> /// <param name="policy"></param> /// <param name="statement"></param> private static void GetNewPolicyAndStatementForTopicAttributes(Dictionary<string, string> attributes, string topicArn, string bucket, out Policy policy, out Statement statement) { if(attributes.ContainsKey("Policy") && !string.IsNullOrEmpty(attributes["Policy"])) { policy = Policy.FromJson(attributes["Policy"]); } else { policy = new Policy(); } var sourceArn = string.Format(CultureInfo.InvariantCulture, "arn:aws:s3:*:*:{0}", bucket); statement = new Statement(Statement.StatementEffect.Allow); statement.Actions.Add(SNSActionIdentifiers.Publish); statement.Resources.Add(new Resource(topicArn)); statement.Conditions.Add(ConditionFactory.NewSourceArnCondition(sourceArn)); statement.Principals.Add(new Principal("*")); }