Skip to content

Commit

Permalink
Add SQS AddPermission operation (#1773)
Browse files Browse the repository at this point in the history
* Add SQS AddPermission operation

* Add missing SQS AddPermission test

* Fix PHPCSFixer issue

* Add to changelog

* Fixup changelog

* Fix order

* Fixup composer
  • Loading branch information
stevenbrookes authored Oct 3, 2024
1 parent 1a3902d commit 571d043
Show file tree
Hide file tree
Showing 7 changed files with 349 additions and 1 deletion.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## NOT RELEASED

### Added

- Add AddPermission endpoint

### Changed

- Enable compiler optimization for the `sprintf` function.
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
},
"extra": {
"branch-alias": {
"dev-master": "2.1-dev"
"dev-master": "2.2-dev"
}
}
}
218 changes: 218 additions & 0 deletions src/Input/AddPermissionRequest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
<?php

namespace AsyncAws\Sqs\Input;

use AsyncAws\Core\Exception\InvalidArgument;
use AsyncAws\Core\Input;
use AsyncAws\Core\Request;
use AsyncAws\Core\Stream\StreamFactory;

final class AddPermissionRequest extends Input
{
/**
* The URL of the Amazon SQS queue to which permissions are added.
*
* Queue URLs and names are case-sensitive.
*
* @required
*
* @var string|null
*/
private $queueUrl;

/**
* The unique identification of the permission you're setting (for example, `AliceSendMessage`). Maximum 80 characters.
* Allowed characters include alphanumeric characters, hyphens (`-`), and underscores (`_`).
*
* @required
*
* @var string|null
*/
private $label;

/**
* The Amazon Web Services account numbers of the principals [^1] who are to receive permission. For information about
* locating the Amazon Web Services account identification, see Your Amazon Web Services Identifiers [^2] in the *Amazon
* SQS Developer Guide*.
*
* [^1]: https://docs.aws.amazon.com/general/latest/gr/glos-chap.html#P
* [^2]: https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-making-api-requests.html#sqs-api-request-authentication
*
* @required
*
* @var string[]|null
*/
private $awsAccountIds;

/**
* The action the client wants to allow for the specified principal. Valid values: the name of any action or `*`.
*
* For more information about these actions, see Overview of Managing Access Permissions to Your Amazon Simple Queue
* Service Resource [^1] in the *Amazon SQS Developer Guide*.
*
* Specifying `SendMessage`, `DeleteMessage`, or `ChangeMessageVisibility` for `ActionName.n` also grants permissions
* for the corresponding batch versions of those actions: `SendMessageBatch`, `DeleteMessageBatch`, and
* `ChangeMessageVisibilityBatch`.
*
* [^1]: https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-overview-of-managing-access.html
*
* @required
*
* @var string[]|null
*/
private $actions;

/**
* @param array{
* QueueUrl?: string,
* Label?: string,
* AWSAccountIds?: string[],
* Actions?: string[],
* '@region'?: string|null,
* } $input
*/
public function __construct(array $input = [])
{
$this->queueUrl = $input['QueueUrl'] ?? null;
$this->label = $input['Label'] ?? null;
$this->awsAccountIds = $input['AWSAccountIds'] ?? null;
$this->actions = $input['Actions'] ?? null;
parent::__construct($input);
}

/**
* @param array{
* QueueUrl?: string,
* Label?: string,
* AWSAccountIds?: string[],
* Actions?: string[],
* '@region'?: string|null,
* }|AddPermissionRequest $input
*/
public static function create($input): self
{
return $input instanceof self ? $input : new self($input);
}

/**
* @return string[]
*/
public function getActions(): array
{
return $this->actions ?? [];
}

/**
* @return string[]
*/
public function getAwsAccountIds(): array
{
return $this->awsAccountIds ?? [];
}

public function getLabel(): ?string
{
return $this->label;
}

public function getQueueUrl(): ?string
{
return $this->queueUrl;
}

/**
* @internal
*/
public function request(): Request
{
// Prepare headers
$headers = [
'Content-Type' => 'application/x-amz-json-1.0',
'X-Amz-Target' => 'AmazonSQS.AddPermission',
'Accept' => 'application/json',
];

// Prepare query
$query = [];

// Prepare URI
$uriString = '/';

// Prepare Body
$bodyPayload = $this->requestBody();
$body = empty($bodyPayload) ? '{}' : json_encode($bodyPayload, 4194304);

// Return the Request
return new Request('POST', $uriString, $query, $headers, StreamFactory::create($body));
}

/**
* @param string[] $value
*/
public function setActions(array $value): self
{
$this->actions = $value;

return $this;
}

/**
* @param string[] $value
*/
public function setAwsAccountIds(array $value): self
{
$this->awsAccountIds = $value;

return $this;
}

public function setLabel(?string $value): self
{
$this->label = $value;

return $this;
}

public function setQueueUrl(?string $value): self
{
$this->queueUrl = $value;

return $this;
}

private function requestBody(): array
{
$payload = [];
if (null === $v = $this->queueUrl) {
throw new InvalidArgument(\sprintf('Missing parameter "QueueUrl" for "%s". The value cannot be null.', __CLASS__));
}
$payload['QueueUrl'] = $v;
if (null === $v = $this->label) {
throw new InvalidArgument(\sprintf('Missing parameter "Label" for "%s". The value cannot be null.', __CLASS__));
}
$payload['Label'] = $v;
if (null === $v = $this->awsAccountIds) {
throw new InvalidArgument(\sprintf('Missing parameter "AWSAccountIds" for "%s". The value cannot be null.', __CLASS__));
}

$index = -1;
$payload['AWSAccountIds'] = [];
foreach ($v as $listValue) {
++$index;
$payload['AWSAccountIds'][$index] = $listValue;
}

if (null === $v = $this->actions) {
throw new InvalidArgument(\sprintf('Missing parameter "Actions" for "%s". The value cannot be null.', __CLASS__));
}

$index = -1;
$payload['Actions'] = [];
foreach ($v as $listValue) {
++$index;
$payload['Actions'][$index] = $listValue;
}

return $payload;
}
}
58 changes: 58 additions & 0 deletions src/SqsClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
use AsyncAws\Sqs\Exception\RequestThrottledException;
use AsyncAws\Sqs\Exception\TooManyEntriesInBatchRequestException;
use AsyncAws\Sqs\Exception\UnsupportedOperationException;
use AsyncAws\Sqs\Input\AddPermissionRequest;
use AsyncAws\Sqs\Input\ChangeMessageVisibilityBatchRequest;
use AsyncAws\Sqs\Input\ChangeMessageVisibilityRequest;
use AsyncAws\Sqs\Input\CreateQueueRequest;
Expand Down Expand Up @@ -69,6 +70,63 @@

class SqsClient extends AbstractApi
{
/**
* Adds a permission to a queue for a specific principal [^1]. This allows sharing access to the queue.
*
* When you create a queue, you have full control access rights for the queue. Only you, the owner of the queue, can
* grant or deny permissions to the queue. For more information about these permissions, see Allow Developers to Write
* Messages to a Shared Queue [^2] in the *Amazon SQS Developer Guide*.
*
* > - `AddPermission` generates a policy for you. You can use `SetQueueAttributes` to upload your policy. For more
* > information, see Using Custom Policies with the Amazon SQS Access Policy Language [^3] in the *Amazon SQS
* > Developer Guide*.
* > - An Amazon SQS policy can have a maximum of seven actions per statement.
* > - To remove the ability to change queue permissions, you must deny permission to the `AddPermission`,
* > `RemovePermission`, and `SetQueueAttributes` actions in your IAM policy.
* > - Amazon SQS `AddPermission` does not support adding a non-account principal.
* >
*
* > Cross-account permissions don't apply to this action. For more information, see Grant cross-account permissions to
* > a role and a username [^4] in the *Amazon SQS Developer Guide*.
*
* [^1]: https://docs.aws.amazon.com/general/latest/gr/glos-chap.html#P
* [^2]: https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-writing-an-sqs-policy.html#write-messages-to-shared-queue
* [^3]: https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-creating-custom-policies.html
* [^4]: https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-customer-managed-policy-examples.html#grant-cross-account-permissions-to-role-and-user-name
*
* @see https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_AddPermission.html
* @see https://docs.aws.amazon.com/aws-sdk-php/v3/api/api-sqs-2012-11-05.html#addpermission
*
* @param array{
* QueueUrl: string,
* Label: string,
* AWSAccountIds: string[],
* Actions: string[],
* '@region'?: string|null,
* }|AddPermissionRequest $input
*
* @throws OverLimitException
* @throws RequestThrottledException
* @throws QueueDoesNotExistException
* @throws InvalidAddressException
* @throws InvalidSecurityException
* @throws UnsupportedOperationException
*/
public function addPermission($input): Result
{
$input = AddPermissionRequest::create($input);
$response = $this->getResponse($input->request(), new RequestContext(['operation' => 'AddPermission', 'region' => $input->getRegion(), 'exceptionMapping' => [
'OverLimit' => OverLimitException::class,
'RequestThrottled' => RequestThrottledException::class,
'QueueDoesNotExist' => QueueDoesNotExistException::class,
'InvalidAddress' => InvalidAddressException::class,
'InvalidSecurity' => InvalidSecurityException::class,
'UnsupportedOperation' => UnsupportedOperationException::class,
]]));

return new Result($response);
}

/**
* Changes the visibility timeout of a specified message in a queue to a new value. The default visibility timeout for a
* message is 30 seconds. The minimum is 0 seconds. The maximum is 12 hours. For more information, see Visibility
Expand Down
16 changes: 16 additions & 0 deletions tests/Integration/SqsClientTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use AsyncAws\Core\Credentials\NullProvider;
use AsyncAws\Core\Test\TestCase;
use AsyncAws\Sqs\Enum\QueueAttributeName;
use AsyncAws\Sqs\Input\AddPermissionRequest;
use AsyncAws\Sqs\Input\ChangeMessageVisibilityBatchRequest;
use AsyncAws\Sqs\Input\ChangeMessageVisibilityRequest;
use AsyncAws\Sqs\Input\CreateQueueRequest;
Expand All @@ -25,6 +26,21 @@

class SqsClientTest extends TestCase
{
public function testAddPermission(): void
{
$client = $this->getClient();

$input = new AddPermissionRequest([
'QueueUrl' => 'change me',
'Label' => 'change me',
'AWSAccountIds' => ['change me'],
'Actions' => ['change me'],
]);
$result = $client->addPermission($input);

$result->resolve();
}

public function testChangeMessageVisibility()
{
$sqs = $this->getClient();
Expand Down
35 changes: 35 additions & 0 deletions tests/Unit/Input/AddPermissionRequestTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

namespace AsyncAws\Sqs\Tests\Unit\Input;

use AsyncAws\Core\Test\TestCase;
use AsyncAws\Sqs\Input\AddPermissionRequest;

class AddPermissionRequestTest extends TestCase
{
public function testRequest(): void
{
$input = new AddPermissionRequest([
'QueueUrl' => 'https://sqs.us-east-1.amazonaws.com/177715257436/MyQueue/',
'Label' => 'MyLabel',
'AWSAccountIds' => ['177715257436', '111111111111'],
'Actions' => ['SendMessage', 'ReceiveMessage'],
]);

// see https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_AddPermission.html
$expected = '
POST / HTTP/1.0
Content-Type: application/x-amz-json-1.0
x-amz-target: AmazonSQS.AddPermission
Accept: application/json
{
"QueueUrl": "https://sqs.us-east-1.amazonaws.com/177715257436/MyQueue/",
"Label": "MyLabel",
"Actions": ["SendMessage", "ReceiveMessage"],
"AWSAccountIds": ["177715257436", "111111111111"]
}';

self::assertRequestEqualsHttpRequest($expected, $input->request());
}
}
Loading

0 comments on commit 571d043

Please sign in to comment.