summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkyleknap <kyleknap@amazon.com>2014-09-10 15:55:18 -0700
committerkyleknap <kyleknap@amazon.com>2014-09-12 10:00:58 -0700
commit6f599baaa2a3b79bbd9798c290b656e0a54497ef (patch)
tree19be2bb4e84352fe930da30762fe22f2c39db1fa
parentd149a870b7315fb663eeffb5d4beba2d841ea3d1 (diff)
downloadboto-6f599baaa2a3b79bbd9798c290b656e0a54497ef.tar.gz
Added support for Amazon Cognito.
Includes support for both Amazon Cognito Sync and Amazon Cognito Identity.
-rw-r--r--README.rst2
-rw-r--r--boto/__init__.py46
-rw-r--r--boto/cognito/__init__.py21
-rw-r--r--boto/cognito/identity/__init__.py42
-rw-r--r--boto/cognito/identity/exceptions.py40
-rw-r--r--boto/cognito/identity/layer1.py303
-rw-r--r--boto/cognito/sync/__init__.py41
-rw-r--r--boto/cognito/sync/exceptions.py50
-rw-r--r--boto/cognito/sync/layer1.py307
-rw-r--r--boto/endpoints.json6
-rw-r--r--docs/source/index.rst2
-rw-r--r--docs/source/ref/cognito-identity.rst26
-rw-r--r--docs/source/ref/cognito-sync.rst26
-rw-r--r--setup.py3
-rw-r--r--tests/integration/cognito/__init__.py41
-rw-r--r--tests/integration/cognito/identity/__init__.py21
-rw-r--r--tests/integration/cognito/identity/test_cognito_identity.py52
-rw-r--r--tests/integration/cognito/sync/__init__.py21
-rw-r--r--tests/integration/cognito/sync/test_cognito_sync.py46
19 files changed, 1095 insertions, 1 deletions
diff --git a/README.rst b/README.rst
index e78a0ad4..92c5c949 100644
--- a/README.rst
+++ b/README.rst
@@ -67,6 +67,8 @@ At the moment, boto supports:
* Amazon Simple Queue Service (SQS) (Python 3)
* Amazon Simple Notification Server (SNS) (Python 3)
* Amazon Simple Email Service (SES) (Python 3)
+ * Amazon Cognito Identity (Python 3)
+ * Amazon Cognito Sync (Python 3)
* Monitoring
diff --git a/boto/__init__.py b/boto/__init__.py
index d76b67cc..1737f45c 100644
--- a/boto/__init__.py
+++ b/boto/__init__.py
@@ -882,6 +882,52 @@ def connect_route53domains(aws_access_key_id=None,
)
+def connect_cognito_identity(aws_access_key_id=None,
+ aws_secret_access_key=None,
+ **kwargs):
+ """
+ Connect to Amazon Cognito Identity
+
+ :type aws_access_key_id: string
+ :param aws_access_key_id: Your AWS Access Key ID
+
+ :type aws_secret_access_key: string
+ :param aws_secret_access_key: Your AWS Secret Access Key
+
+ rtype: :class:`boto.cognito.identity.layer1.CognitoIdentityConnection`
+ :return: A connection to the Amazon Cognito Identity service
+ """
+ from boto.cognito.identity.layer1 import CognitoIdentityConnection
+ return CognitoIdentityConnection(
+ aws_access_key_id=aws_access_key_id,
+ aws_secret_access_key=aws_secret_access_key,
+ **kwargs
+ )
+
+
+def connect_cognito_sync(aws_access_key_id=None,
+ aws_secret_access_key=None,
+ **kwargs):
+ """
+ Connect to Amazon Cognito Sync
+
+ :type aws_access_key_id: string
+ :param aws_access_key_id: Your AWS Access Key ID
+
+ :type aws_secret_access_key: string
+ :param aws_secret_access_key: Your AWS Secret Access Key
+
+ rtype: :class:`boto.cognito.sync.layer1.CognitoSyncConnection`
+ :return: A connection to the Amazon Cognito Sync service
+ """
+ from boto.cognito.sync.layer1 import CognitoSyncConnection
+ return CognitoSyncConnection(
+ aws_access_key_id=aws_access_key_id,
+ aws_secret_access_key=aws_secret_access_key,
+ **kwargs
+ )
+
+
def storage_uri(uri_str, default_scheme='file', debug=0, validate=True,
bucket_storage_uri_class=BucketStorageUri,
suppress_consec_slashes=True, is_latest=False):
diff --git a/boto/cognito/__init__.py b/boto/cognito/__init__.py
new file mode 100644
index 00000000..70cc23fe
--- /dev/null
+++ b/boto/cognito/__init__.py
@@ -0,0 +1,21 @@
+# Copyright (c) 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish, dis-
+# tribute, sublicense, and/or sell copies of the Software, and to permit
+# persons to whom the Software is furnished to do so, subject to the fol-
+# lowing conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
+# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+# IN THE SOFTWARE.
+#
diff --git a/boto/cognito/identity/__init__.py b/boto/cognito/identity/__init__.py
new file mode 100644
index 00000000..e58b480b
--- /dev/null
+++ b/boto/cognito/identity/__init__.py
@@ -0,0 +1,42 @@
+# Copyright (c) 2014 Amazon.com, Inc. or its affiliates.
+# All Rights Reserved
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish, dis-
+# tribute, sublicense, and/or sell copies of the Software, and to permit
+# persons to whom the Software is furnished to do so, subject to the fol-
+# lowing conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
+# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+# IN THE SOFTWARE.
+#
+from boto.regioninfo import RegionInfo, get_regions
+
+
+def regions():
+ """
+ Get all available regions for the Amazon Cognito Identity service.
+
+ :rtype: list
+ :return: A list of :class:`boto.regioninfo.RegionInfo`
+ """
+ from boto.cognito.identity.layer1 import CognitoIdentityConnection
+ return get_regions('cognito-identity',
+ connection_cls=CognitoIdentityConnection)
+
+
+def connect_to_region(region_name, **kw_params):
+ for region in regions():
+ if region.name == region_name:
+ return region.connect(**kw_params)
+ return None
diff --git a/boto/cognito/identity/exceptions.py b/boto/cognito/identity/exceptions.py
new file mode 100644
index 00000000..179089df
--- /dev/null
+++ b/boto/cognito/identity/exceptions.py
@@ -0,0 +1,40 @@
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
+# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+# IN THE SOFTWARE.
+#
+from boto.exception import BotoServerError
+
+
+class LimitExceededException(BotoServerError):
+ pass
+
+
+class ResourceConflictException(BotoServerError):
+ pass
+
+
+class TooManyRequestsException(BotoServerError):
+ pass
+
+
+class InvalidParameterException(BotoServerError):
+ pass
+
+
+class ResourceNotFoundException(BotoServerError):
+ pass
+
+
+class InternalErrorException(BotoServerError):
+ pass
+
+
+class NotAuthorizedException(BotoServerError):
+ pass
diff --git a/boto/cognito/identity/layer1.py b/boto/cognito/identity/layer1.py
new file mode 100644
index 00000000..0a9c8e4e
--- /dev/null
+++ b/boto/cognito/identity/layer1.py
@@ -0,0 +1,303 @@
+# Copyright (c) 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish, dis-
+# tribute, sublicense, and/or sell copies of the Software, and to permit
+# persons to whom the Software is furnished to do so, subject to the fol-
+# lowing conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
+# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+# IN THE SOFTWARE.
+#
+
+import boto
+from boto.compat import json
+from boto.connection import AWSQueryConnection
+from boto.regioninfo import RegionInfo
+from boto.exception import JSONResponseError
+from boto.cognito.identity import exceptions
+
+
+class CognitoIdentityConnection(AWSQueryConnection):
+ """
+ Amazon Cognito
+ Amazon Cognito is a web service that facilitates the delivery of
+ scoped, temporary credentials to mobile devices or other untrusted
+ environments. Amazon Cognito uniquely identifies a device or user
+ and supplies the user with a consistent identity throughout the
+ lifetime of an application.
+
+ Amazon Cognito lets users authenticate with third-party identity
+ providers (Facebook, Google, or Login with Amazon). As a
+ developer, you decide which identity providers to trust. You can
+ also choose to support unauthenticated access from your
+ application. Your users are provided with Cognito tokens that
+ uniquely identify their device and any information provided about
+ third-party logins.
+ """
+ APIVersion = "2014-06-30"
+ DefaultRegionName = "us-east-1"
+ DefaultRegionEndpoint = "cognito-identity.us-east-1.amazonaws.com"
+ ServiceName = "CognitoIdentity"
+ TargetPrefix = "AWSCognitoIdentityService"
+ ResponseError = JSONResponseError
+
+ _faults = {
+ "LimitExceededException": exceptions.LimitExceededException,
+ "ResourceConflictException": exceptions.ResourceConflictException,
+ "TooManyRequestsException": exceptions.TooManyRequestsException,
+ "InvalidParameterException": exceptions.InvalidParameterException,
+ "ResourceNotFoundException": exceptions.ResourceNotFoundException,
+ "InternalErrorException": exceptions.InternalErrorException,
+ "NotAuthorizedException": exceptions.NotAuthorizedException,
+ }
+
+
+ def __init__(self, **kwargs):
+ region = kwargs.pop('region', None)
+ if not region:
+ region = RegionInfo(self, self.DefaultRegionName,
+ self.DefaultRegionEndpoint)
+
+ if 'host' not in kwargs or kwargs['host'] is None:
+ kwargs['host'] = region.endpoint
+
+ super(CognitoIdentityConnection, self).__init__(**kwargs)
+ self.region = region
+
+ def _required_auth_capability(self):
+ return ['hmac-v4']
+
+ def create_identity_pool(self, identity_pool_name,
+ allow_unauthenticated_identities,
+ supported_login_providers=None):
+ """
+ Creates a new identity pool. The identity pool is a store of
+ user identity information that is specific to your AWS
+ account.
+
+ :type identity_pool_name: string
+ :param identity_pool_name: A string that you provide.
+
+ :type allow_unauthenticated_identities: boolean
+ :param allow_unauthenticated_identities: TRUE if the identity pool
+ supports unauthenticated logins.
+
+ :type supported_login_providers: map
+ :param supported_login_providers: Optional key:value pairs mapping
+ provider names to provider app IDs.
+
+ """
+ params = {
+ 'IdentityPoolName': identity_pool_name,
+ 'AllowUnauthenticatedIdentities': allow_unauthenticated_identities,
+ }
+ if supported_login_providers is not None:
+ params['SupportedLoginProviders'] = supported_login_providers
+ return self.make_request(action='CreateIdentityPool',
+ body=json.dumps(params))
+
+ def delete_identity_pool(self, identity_pool_id):
+ """
+ Deletes a user pool. Once a pool is deleted, users will not be
+ able to authenticate with the pool.
+
+ :type identity_pool_id: string
+ :param identity_pool_id: An identity pool ID in the format REGION:GUID.
+
+ """
+ params = {'IdentityPoolId': identity_pool_id, }
+ return self.make_request(action='DeleteIdentityPool',
+ body=json.dumps(params))
+
+ def describe_identity_pool(self, identity_pool_id):
+ """
+ Gets details about a particular identity pool, including the
+ pool name, ID description, creation date, and current number
+ of users.
+
+ :type identity_pool_id: string
+ :param identity_pool_id: An identity pool ID in the format REGION:GUID.
+
+ """
+ params = {'IdentityPoolId': identity_pool_id, }
+ return self.make_request(action='DescribeIdentityPool',
+ body=json.dumps(params))
+
+ def get_id(self, account_id, identity_pool_id, logins=None):
+ """
+ Generates (or retrieves) a Cognito ID. Supplying multiple
+ logins will create an implicit linked account.
+
+ :type account_id: string
+ :param account_id: A standard AWS account ID (9+ digits).
+
+ :type identity_pool_id: string
+ :param identity_pool_id: An identity pool ID in the format REGION:GUID.
+
+ :type logins: map
+ :param logins: A set of optional name/value pairs that map provider
+ names to provider tokens.
+
+ """
+ params = {
+ 'AccountId': account_id,
+ 'IdentityPoolId': identity_pool_id,
+ }
+ if logins is not None:
+ params['Logins'] = logins
+ return self.make_request(action='GetId',
+ body=json.dumps(params))
+
+ def get_open_id_token(self, identity_id, logins=None):
+ """
+ Gets an OpenID token, using a known Cognito ID. This known
+ Cognito ID is returned from GetId. You can optionally add
+ additional logins for the identity. Supplying multiple logins
+ creates an implicit link.
+
+ :type identity_id: string
+ :param identity_id: A unique identifier in the format REGION:GUID.
+
+ :type logins: map
+ :param logins: A set of optional name/value pairs that map provider
+ names to provider tokens.
+
+ """
+ params = {'IdentityId': identity_id, }
+ if logins is not None:
+ params['Logins'] = logins
+ return self.make_request(action='GetOpenIdToken',
+ body=json.dumps(params))
+
+ def list_identities(self, identity_pool_id, max_results, next_token=None):
+ """
+ Lists the identities in a pool.
+
+ :type identity_pool_id: string
+ :param identity_pool_id: An identity pool ID in the format REGION:GUID.
+
+ :type max_results: integer
+ :param max_results: The maximum number of identities to return.
+
+ :type next_token: string
+ :param next_token: A pagination token.
+
+ """
+ params = {
+ 'IdentityPoolId': identity_pool_id,
+ 'MaxResults': max_results,
+ }
+ if next_token is not None:
+ params['NextToken'] = next_token
+ return self.make_request(action='ListIdentities',
+ body=json.dumps(params))
+
+ def list_identity_pools(self, max_results, next_token=None):
+ """
+ Lists all of the Cognito identity pools registered for your
+ account.
+
+ :type max_results: integer
+ :param max_results: The maximum number of identities to return.
+
+ :type next_token: string
+ :param next_token: A pagination token.
+
+ """
+ params = {'MaxResults': max_results, }
+ if next_token is not None:
+ params['NextToken'] = next_token
+ return self.make_request(action='ListIdentityPools',
+ body=json.dumps(params))
+
+ def unlink_identity(self, identity_id, logins, logins_to_remove):
+ """
+ Unlinks a federated identity from an existing account.
+ Unlinked logins will be considered new identities next time
+ they are seen. Removing the last linked login will make this
+ identity inaccessible.
+
+ :type identity_id: string
+ :param identity_id: A unique identifier in the format REGION:GUID.
+
+ :type logins: map
+ :param logins: A set of optional name/value pairs that map provider
+ names to provider tokens.
+
+ :type logins_to_remove: list
+ :param logins_to_remove: Provider names to unlink from this identity.
+
+ """
+ params = {
+ 'IdentityId': identity_id,
+ 'Logins': logins,
+ 'LoginsToRemove': logins_to_remove,
+ }
+ return self.make_request(action='UnlinkIdentity',
+ body=json.dumps(params))
+
+ def update_identity_pool(self, identity_pool_id, identity_pool_name,
+ allow_unauthenticated_identities,
+ supported_login_providers=None):
+ """
+ Updates a user pool.
+
+ :type identity_pool_id: string
+ :param identity_pool_id: An identity pool ID in the format REGION:GUID.
+
+ :type identity_pool_name: string
+ :param identity_pool_name: A string that you provide.
+
+ :type allow_unauthenticated_identities: boolean
+ :param allow_unauthenticated_identities: TRUE if the identity pool
+ supports unauthenticated logins.
+
+ :type supported_login_providers: map
+ :param supported_login_providers: Optional key:value pairs mapping
+ provider names to provider app IDs.
+
+ """
+ params = {
+ 'IdentityPoolId': identity_pool_id,
+ 'IdentityPoolName': identity_pool_name,
+ 'AllowUnauthenticatedIdentities': allow_unauthenticated_identities,
+ }
+ if supported_login_providers is not None:
+ params['SupportedLoginProviders'] = supported_login_providers
+ return self.make_request(action='UpdateIdentityPool',
+ body=json.dumps(params))
+
+ def make_request(self, action, body):
+ headers = {
+ 'X-Amz-Target': '%s.%s' % (self.TargetPrefix, action),
+ 'Host': self.region.endpoint,
+ 'Content-Type': 'application/x-amz-json-1.1',
+ 'Content-Length': str(len(body)),
+ }
+ http_request = self.build_base_http_request(
+ method='POST', path='/', auth_path='/', params={},
+ headers=headers, data=body)
+ response = self._mexe(http_request, sender=None,
+ override_num_retries=10)
+ response_body = response.read().decode('utf-8')
+ boto.log.debug(response_body)
+ if response.status == 200:
+ if response_body:
+ return json.loads(response_body)
+ else:
+ json_body = json.loads(response_body)
+ fault_name = json_body.get('__type', None)
+ exception_class = self._faults.get(fault_name, self.ResponseError)
+ raise exception_class(response.status, response.reason,
+ body=json_body)
diff --git a/boto/cognito/sync/__init__.py b/boto/cognito/sync/__init__.py
new file mode 100644
index 00000000..3d48bd18
--- /dev/null
+++ b/boto/cognito/sync/__init__.py
@@ -0,0 +1,41 @@
+# Copyright (c) 2014 Amazon.com, Inc. or its affiliates.
+# All Rights Reserved
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish, dis-
+# tribute, sublicense, and/or sell copies of the Software, and to permit
+# persons to whom the Software is furnished to do so, subject to the fol-
+# lowing conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
+# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+# IN THE SOFTWARE.
+#
+from boto.regioninfo import RegionInfo, get_regions
+
+
+def regions():
+ """
+ Get all available regions for the Amazon Cognito Sync service.
+
+ :rtype: list
+ :return: A list of :class:`boto.regioninfo.RegionInfo`
+ """
+ from boto.cognito.sync.layer1 import CognitoSyncConnection
+ return get_regions('cognito-sync', connection_cls=CognitoSyncConnection)
+
+
+def connect_to_region(region_name, **kw_params):
+ for region in regions():
+ if region.name == region_name:
+ return region.connect(**kw_params)
+ return None
diff --git a/boto/cognito/sync/exceptions.py b/boto/cognito/sync/exceptions.py
new file mode 100644
index 00000000..d64fb278
--- /dev/null
+++ b/boto/cognito/sync/exceptions.py
@@ -0,0 +1,50 @@
+# Copyright (c) 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish, dis-
+# tribute, sublicense, and/or sell copies of the Software, and to permit
+# persons to whom the Software is furnished to do so, subject to the fol-
+# lowing conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
+# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+# IN THE SOFTWARE.
+#
+from boto.exception import BotoServerError
+
+
+class LimitExceededException(BotoServerError):
+ pass
+
+
+class ResourceConflictException(BotoServerError):
+ pass
+
+
+class TooManyRequestsException(BotoServerError):
+ pass
+
+
+class InvalidParameterException(BotoServerError):
+ pass
+
+
+class ResourceNotFoundException(BotoServerError):
+ pass
+
+
+class InternalErrorException(BotoServerError):
+ pass
+
+
+class NotAuthorizedException(BotoServerError):
+ pass
diff --git a/boto/cognito/sync/layer1.py b/boto/cognito/sync/layer1.py
new file mode 100644
index 00000000..545af5eb
--- /dev/null
+++ b/boto/cognito/sync/layer1.py
@@ -0,0 +1,307 @@
+# Copyright (c) 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish, dis-
+# tribute, sublicense, and/or sell copies of the Software, and to permit
+# persons to whom the Software is furnished to do so, subject to the fol-
+# lowing conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
+# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+# IN THE SOFTWARE.
+#
+from boto.compat import json
+from boto.exception import JSONResponseError
+from boto.connection import AWSAuthConnection
+from boto.regioninfo import RegionInfo
+from boto.cognito.sync import exceptions
+
+
+class CognitoSyncConnection(AWSAuthConnection):
+ """
+ Amazon Cognito Sync
+ Amazon Cognito Sync provides an AWS service and client library
+ that enable cross-device syncing of application-related user data.
+ High-level client libraries are available for both iOS and
+ Android. You can use these libraries to persist data locally so
+ that it's available even if the device is offline. Developer
+ credentials don't need to be stored on the mobile device to access
+ the service. You can use Amazon Cognito to obtain a normalized
+ user ID and credentials. User data is persisted in a dataset that
+ can store up to 1 MB of key-value pairs, and you can have up to 20
+ datasets per user identity.
+ """
+ APIVersion = "2014-06-30"
+ DefaultRegionName = "us-east-1"
+ DefaultRegionEndpoint = "cognito-sync.us-east-1.amazonaws.com"
+ ResponseError = JSONResponseError
+
+ _faults = {
+ "LimitExceededException": exceptions.LimitExceededException,
+ "ResourceConflictException": exceptions.ResourceConflictException,
+ "TooManyRequestsException": exceptions.TooManyRequestsException,
+ "InvalidParameterException": exceptions.InvalidParameterException,
+ "ResourceNotFoundException": exceptions.ResourceNotFoundException,
+ "InternalErrorException": exceptions.InternalErrorException,
+ "NotAuthorizedException": exceptions.NotAuthorizedException,
+ }
+
+
+ def __init__(self, **kwargs):
+ region = kwargs.get('region')
+ if not region:
+ region = RegionInfo(self, self.DefaultRegionName,
+ self.DefaultRegionEndpoint)
+ else:
+ del kwargs['region']
+ kwargs['host'] = region.endpoint
+ super(CognitoSyncConnection, self).__init__(**kwargs)
+ self.region = region
+
+ def _required_auth_capability(self):
+ return ['hmac-v4']
+
+ def delete_dataset(self, identity_pool_id, identity_id, dataset_name):
+ """
+ Deletes the specific dataset. The dataset will be deleted
+ permanently, and the action can't be undone. Datasets that
+ this dataset was merged with will no longer report the merge.
+ Any consequent operation on this dataset will result in a
+ ResourceNotFoundException.
+
+ :type identity_pool_id: string
+ :param identity_pool_id: A name-spaced GUID (for example, us-
+ east-1:23EC4050-6AEA-7089-A2DD-08002EXAMPLE) created by Amazon
+ Cognito. GUID generation is unique within a region.
+
+ :type identity_id: string
+ :param identity_id: A name-spaced GUID (for example, us-
+ east-1:23EC4050-6AEA-7089-A2DD-08002EXAMPLE) created by Amazon
+ Cognito. GUID generation is unique within a region.
+
+ :type dataset_name: string
+ :param dataset_name: A string of up to 128 characters. Allowed
+ characters are a-z, A-Z, 0-9, '_' (underscore), '-' (dash), and '.'
+ (dot).
+
+ """
+ uri = '/identitypools/{0}/identities/{1}/datasets/{2}'.format(
+ identity_pool_id, identity_id, dataset_name)
+ return self.make_request('DELETE', uri, expected_status=200)
+
+ def describe_dataset(self, identity_pool_id, identity_id, dataset_name):
+ """
+ Gets metadata about a dataset by identity and dataset name.
+
+ :type identity_pool_id: string
+ :param identity_pool_id: A name-spaced GUID (for example, us-
+ east-1:23EC4050-6AEA-7089-A2DD-08002EXAMPLE) created by Amazon
+ Cognito. GUID generation is unique within a region.
+
+ :type identity_id: string
+ :param identity_id: A name-spaced GUID (for example, us-
+ east-1:23EC4050-6AEA-7089-A2DD-08002EXAMPLE) created by Amazon
+ Cognito. GUID generation is unique within a region.
+
+ :type dataset_name: string
+ :param dataset_name: A string of up to 128 characters. Allowed
+ characters are a-z, A-Z, 0-9, '_' (underscore), '-' (dash), and '.'
+ (dot).
+
+ """
+ uri = '/identitypools/{0}/identities/{1}/datasets/{2}'.format(
+ identity_pool_id, identity_id, dataset_name)
+ return self.make_request('GET', uri, expected_status=200)
+
+ def describe_identity_pool_usage(self, identity_pool_id):
+ """
+ Gets usage details (for example, data storage) about a
+ particular identity pool.
+
+ :type identity_pool_id: string
+ :param identity_pool_id: A name-spaced GUID (for example, us-
+ east-1:23EC4050-6AEA-7089-A2DD-08002EXAMPLE) created by Amazon
+ Cognito. GUID generation is unique within a region.
+
+ """
+ uri = '/identitypools/{0}'.format(identity_pool_id)
+ return self.make_request('GET', uri, expected_status=200)
+
+ def describe_identity_usage(self, identity_pool_id, identity_id):
+ """
+ Gets usage information for an identity, including number of
+ datasets and data usage.
+
+ :type identity_pool_id: string
+ :param identity_pool_id: A name-spaced GUID (for example, us-
+ east-1:23EC4050-6AEA-7089-A2DD-08002EXAMPLE) created by Amazon
+ Cognito. GUID generation is unique within a region.
+
+ :type identity_id: string
+ :param identity_id: A name-spaced GUID (for example, us-
+ east-1:23EC4050-6AEA-7089-A2DD-08002EXAMPLE) created by Amazon
+ Cognito. GUID generation is unique within a region.
+
+ """
+ uri = '/identitypools/{0}/identities/{1}'.format(
+ identity_pool_id, identity_id)
+ return self.make_request('GET', uri, expected_status=200)
+
+ def list_datasets(self, identity_pool_id, identity_id, next_token=None,
+ max_results=None):
+ """
+ Lists datasets for an identity.
+
+ :type identity_pool_id: string
+ :param identity_pool_id: A name-spaced GUID (for example, us-
+ east-1:23EC4050-6AEA-7089-A2DD-08002EXAMPLE) created by Amazon
+ Cognito. GUID generation is unique within a region.
+
+ :type identity_id: string
+ :param identity_id: A name-spaced GUID (for example, us-
+ east-1:23EC4050-6AEA-7089-A2DD-08002EXAMPLE) created by Amazon
+ Cognito. GUID generation is unique within a region.
+
+ :type next_token: string
+ :param next_token: A pagination token for obtaining the next page of
+ results.
+
+ :type max_results: integer
+ :param max_results: The maximum number of results to be returned.
+
+ """
+ uri = '/identitypools/{0}/identities/{1}/datasets'.format(
+ identity_pool_id, identity_id)
+ params = {}
+ headers = {}
+ return self.make_request('GET', uri, expected_status=200,
+ data=json.dumps(params), headers=headers)
+
+ def list_identity_pool_usage(self, next_token=None, max_results=None):
+ """
+ Gets a list of identity pools registered with Cognito.
+
+ :type next_token: string
+ :param next_token: A pagination token for obtaining the next page of
+ results.
+
+ :type max_results: integer
+ :param max_results: The maximum number of results to be returned.
+
+ """
+ uri = '/identitypools'
+ params = {}
+ headers = {}
+ return self.make_request('GET', uri, expected_status=200,
+ data=json.dumps(params), headers=headers)
+
+ def list_records(self, identity_pool_id, identity_id, dataset_name,
+ last_sync_count=None, next_token=None, max_results=None,
+ sync_session_token=None):
+ """
+ Gets paginated records, optionally changed after a particular
+ sync count for a dataset and identity.
+
+ :type identity_pool_id: string
+ :param identity_pool_id: A name-spaced GUID (for example, us-
+ east-1:23EC4050-6AEA-7089-A2DD-08002EXAMPLE) created by Amazon
+ Cognito. GUID generation is unique within a region.
+
+ :type identity_id: string
+ :param identity_id: A name-spaced GUID (for example, us-
+ east-1:23EC4050-6AEA-7089-A2DD-08002EXAMPLE) created by Amazon
+ Cognito. GUID generation is unique within a region.
+
+ :type dataset_name: string
+ :param dataset_name: A string of up to 128 characters. Allowed
+ characters are a-z, A-Z, 0-9, '_' (underscore), '-' (dash), and '.'
+ (dot).
+
+ :type last_sync_count: long
+ :param last_sync_count: The last server sync count for this record.
+
+ :type next_token: string
+ :param next_token: A pagination token for obtaining the next page of
+ results.
+
+ :type max_results: integer
+ :param max_results: The maximum number of results to be returned.
+
+ :type sync_session_token: string
+ :param sync_session_token: A token containing a session ID, identity
+ ID, and expiration.
+
+ """
+ uri = '/identitypools/{0}/identities/{1}/datasets/{2}/records'.format(
+ identity_pool_id, identity_id, dataset_name)
+ params = {}
+ headers = {}
+ return self.make_request('GET', uri, expected_status=200,
+ data=json.dumps(params), headers=headers)
+
+ def update_records(self, identity_pool_id, identity_id, dataset_name,
+ sync_session_token, record_patches=None,
+ client_context=None):
+ """
+ Posts updates to records and add and delete records for a
+ dataset and user.
+
+ :type identity_pool_id: string
+ :param identity_pool_id: A name-spaced GUID (for example, us-
+ east-1:23EC4050-6AEA-7089-A2DD-08002EXAMPLE) created by Amazon
+ Cognito. GUID generation is unique within a region.
+
+ :type identity_id: string
+ :param identity_id: A name-spaced GUID (for example, us-
+ east-1:23EC4050-6AEA-7089-A2DD-08002EXAMPLE) created by Amazon
+ Cognito. GUID generation is unique within a region.
+
+ :type dataset_name: string
+ :param dataset_name: A string of up to 128 characters. Allowed
+ characters are a-z, A-Z, 0-9, '_' (underscore), '-' (dash), and '.'
+ (dot).
+
+ :type record_patches: list
+ :param record_patches:
+
+ :type sync_session_token: string
+ :param sync_session_token: The SyncSessionToken returned by a previous
+ call to ListRecords for this dataset and identity.
+
+ :type client_context: string
+ :param client_context:
+
+ """
+ uri = '/identitypools/{0}/identities/{1}/datasets/{2}'.format(
+ identity_pool_id, identity_id, dataset_name)
+ params = {'SyncSessionToken': sync_session_token, }
+ headers = {}
+ if record_patches is not None:
+ params['RecordPatches'] = record_patches
+ if client_context is not None:
+ headers['x-amz-Client-Context'] = client_context
+ return self.make_request('POST', uri, expected_status=200,
+ data=json.dumps(params), headers=headers)
+
+ def make_request(self, verb, resource, headers=None, data='',
+ expected_status=None, params=None):
+ if headers is None:
+ headers = {}
+ response = AWSAuthConnection.make_request(
+ self, verb, resource, headers=headers, data=data, params=params)
+ body = json.loads(response.read().decode('utf-8'))
+ if response.status == expected_status:
+ return body
+ else:
+ error_type = response.getheader('x-amzn-ErrorType').split(':')[0]
+ error_class = self._faults.get(error_type, self.ResponseError)
+ raise error_class(response.status, response.reason, body)
diff --git a/boto/endpoints.json b/boto/endpoints.json
index 5c95b5ca..db7c6446 100644
--- a/boto/endpoints.json
+++ b/boto/endpoints.json
@@ -62,6 +62,12 @@
"us-west-1": "monitoring.us-west-1.amazonaws.com",
"us-west-2": "monitoring.us-west-2.amazonaws.com"
},
+ "cognito-identity": {
+ "us-east-1": "cognito-identity.us-east-1.amazonaws.com"
+ },
+ "cognito-sync": {
+ "us-east-1": "cognito-sync.us-east-1.amazonaws.com"
+ },
"datapipeline": {
"us-east-1": "datapipeline.us-east-1.amazonaws.com",
"us-west-2": "datapipeline.us-west-2.amazonaws.com",
diff --git a/docs/source/index.rst b/docs/source/index.rst
index 00f26417..914c5328 100644
--- a/docs/source/index.rst
+++ b/docs/source/index.rst
@@ -73,6 +73,8 @@ Currently Supported Services
* :doc:`Simple Queue Service (SQS) <sqs_tut>` -- (:doc:`API Reference <ref/sqs>`) (Python 3)
* Simple Notification Service (SNS) -- (:doc:`API Reference <ref/sns>`) (Python 3)
* :doc:`Simple Email Service (SES) <ses_tut>` -- (:doc:`API Reference <ref/ses>`) (Python 3)
+ * Amazon Cognito Identity -- (:doc:`API Reference <ref/cognito-identity`) (Python 3)
+ * Amazon Cognito Sync -- (:doc:`API Reference <ref/cognito-sync`) (Python 3)
* **Monitoring**
diff --git a/docs/source/ref/cognito-identity.rst b/docs/source/ref/cognito-identity.rst
new file mode 100644
index 00000000..65ec98ff
--- /dev/null
+++ b/docs/source/ref/cognito-identity.rst
@@ -0,0 +1,26 @@
+.. ref-cognito-identity
+
+================
+Cognito Identity
+================
+
+boto.cognito.identity
+---------------------
+
+.. automodule:: boto.cognito.identity
+ :members:
+ :undoc-members:
+
+boto.cognito.identity.layer1
+----------------------------
+
+.. automodule:: boto.cognito.identity.layer1
+ :members:
+ :undoc-members:
+
+boto.cognito.identity.exceptions
+--------------------------------
+
+.. automodule:: boto.cognito.identity.exceptions
+ :members:
+ :undoc-members:
diff --git a/docs/source/ref/cognito-sync.rst b/docs/source/ref/cognito-sync.rst
new file mode 100644
index 00000000..a8a6dd40
--- /dev/null
+++ b/docs/source/ref/cognito-sync.rst
@@ -0,0 +1,26 @@
+.. ref-cognito-sync
+
+============
+Cognito Sync
+============
+
+boto.cognito.sync
+-----------------
+
+.. automodule:: boto.cognito.sync
+ :members:
+ :undoc-members:
+
+boto.cognito.sync.layer1
+------------------------
+
+.. automodule:: boto.cognito.sync.layer1
+ :members:
+ :undoc-members:
+
+boto.cognito.sync.exceptions
+----------------------------
+
+.. automodule:: boto.cognito.sync.exceptions
+ :members:
+ :undoc-members:
diff --git a/setup.py b/setup.py
index af7db329..b46e683e 100644
--- a/setup.py
+++ b/setup.py
@@ -77,7 +77,8 @@ setup(name = "boto",
"boto.dynamodb2", "boto.support", "boto.cloudtrail",
"boto.directconnect", "boto.kinesis", "boto.rds2",
"boto.cloudsearch2", "boto.logs", "boto.vendored",
- "boto.route53.domains"],
+ "boto.route53.domains", "boto.cognito",
+ "boto.cognito.identity", "boto.cognito.sync"],
package_data = {
"boto.cacerts": ["cacerts.txt"],
"boto": ["endpoints.json"],
diff --git a/tests/integration/cognito/__init__.py b/tests/integration/cognito/__init__.py
new file mode 100644
index 00000000..571bc50d
--- /dev/null
+++ b/tests/integration/cognito/__init__.py
@@ -0,0 +1,41 @@
+# Copyright (c) 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish, dis-
+# tribute, sublicense, and/or sell copies of the Software, and to permit
+# persons to whom the Software is furnished to do so, subject to the fol-
+# lowing conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
+# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+# IN THE SOFTWARE.
+#
+
+import boto
+from tests.compat import unittest
+
+
+class CognitoTest(unittest.TestCase):
+ def setUp(self):
+ self.cognito_identity = boto.connect_cognito_identity()
+ self.cognito_sync = boto.connect_cognito_sync()
+ self.identity_pool_name = 'myIdentityPool'
+ response = self.cognito_identity.create_identity_pool(
+ identity_pool_name=self.identity_pool_name,
+ allow_unauthenticated_identities=False
+ )
+ self.identity_pool_id = response['IdentityPoolId']
+
+ def tearDown(self):
+ self.cognito_identity.delete_identity_pool(
+ identity_pool_id=self.identity_pool_id
+ )
diff --git a/tests/integration/cognito/identity/__init__.py b/tests/integration/cognito/identity/__init__.py
new file mode 100644
index 00000000..70cc23fe
--- /dev/null
+++ b/tests/integration/cognito/identity/__init__.py
@@ -0,0 +1,21 @@
+# Copyright (c) 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish, dis-
+# tribute, sublicense, and/or sell copies of the Software, and to permit
+# persons to whom the Software is furnished to do so, subject to the fol-
+# lowing conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
+# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+# IN THE SOFTWARE.
+#
diff --git a/tests/integration/cognito/identity/test_cognito_identity.py b/tests/integration/cognito/identity/test_cognito_identity.py
new file mode 100644
index 00000000..7d9f6647
--- /dev/null
+++ b/tests/integration/cognito/identity/test_cognito_identity.py
@@ -0,0 +1,52 @@
+# Copyright (c) 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish, dis-
+# tribute, sublicense, and/or sell copies of the Software, and to permit
+# persons to whom the Software is furnished to do so, subject to the fol-
+# lowing conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
+# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+# IN THE SOFTWARE.
+#
+
+from boto.cognito.identity.exceptions import ResourceNotFoundException
+from tests.integration.cognito import CognitoTest
+
+
+class TestCognitoIdentity(CognitoTest):
+ """
+ Test Cognitoy identity pools operations since individual Cognito identities
+ require an AWS account ID.
+ """
+ def test_cognito_identity(self):
+ # Ensure the identity pool is in the list of pools.
+ response = self.cognito_identity.list_identity_pools(max_results=5)
+ expected_identity = {'IdentityPoolId': self.identity_pool_id,
+ 'IdentityPoolName': self.identity_pool_name}
+ self.assertIn(expected_identity, response['IdentityPools'])
+
+ # Ensure the pool's attributes are as expected.
+ response = self.cognito_identity.describe_identity_pool(
+ identity_pool_id=self.identity_pool_id
+ )
+ self.assertEqual(response['IdentityPoolName'], self.identity_pool_name)
+ self.assertEqual(response['IdentityPoolId'], self.identity_pool_id)
+ self.assertFalse(response['AllowUnauthenticatedIdentities'])
+
+ def test_resource_not_found_exception(self):
+ with self.assertRaises(ResourceNotFoundException):
+ # Note the region is us-east-0 which is an invalid region name.
+ self.cognito_identity.describe_identity_pool(
+ identity_pool_id='us-east-0:c09e640-b014-4822-86b9-ec77c40d8d6f'
+ )
diff --git a/tests/integration/cognito/sync/__init__.py b/tests/integration/cognito/sync/__init__.py
new file mode 100644
index 00000000..70cc23fe
--- /dev/null
+++ b/tests/integration/cognito/sync/__init__.py
@@ -0,0 +1,21 @@
+# Copyright (c) 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish, dis-
+# tribute, sublicense, and/or sell copies of the Software, and to permit
+# persons to whom the Software is furnished to do so, subject to the fol-
+# lowing conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
+# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+# IN THE SOFTWARE.
+#
diff --git a/tests/integration/cognito/sync/test_cognito_sync.py b/tests/integration/cognito/sync/test_cognito_sync.py
new file mode 100644
index 00000000..fdfd40ee
--- /dev/null
+++ b/tests/integration/cognito/sync/test_cognito_sync.py
@@ -0,0 +1,46 @@
+# Copyright (c) 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish, dis-
+# tribute, sublicense, and/or sell copies of the Software, and to permit
+# persons to whom the Software is furnished to do so, subject to the fol-
+# lowing conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
+# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+# IN THE SOFTWARE.
+#
+
+from boto.cognito.sync.exceptions import ResourceNotFoundException
+from tests.integration.cognito import CognitoTest
+
+
+class TestCognitoSync(CognitoTest):
+ """
+ Even more so for Cognito Sync, Cognito identites are required. However,
+ AWS account IDs are required to aqcuire a Cognito identity so only
+ Cognito pool identity related operations are tested.
+ """
+ def test_cognito_sync(self):
+ response = self.cognito_sync.describe_identity_pool_usage(
+ identity_pool_id=self.identity_pool_id
+ )
+ identity_pool_usage = response['IdentityPoolUsage']
+ self.assertEqual(identity_pool_usage['SyncSessionsCount'], None)
+ self.assertEqual(identity_pool_usage['DataStorage'], 0)
+
+ def test_resource_not_found_exception(self):
+ with self.assertRaises(ResourceNotFoundException):
+ # Note the region is us-east-0 which is an invalid region name.
+ self.cognito_sync.describe_identity_pool_usage(
+ identity_pool_id='us-east-0:c09e640-b014-4822-86b9-ec77c40d8d6f'
+ )