| Index: third_party/gsutil/boto/boto/sts/connection.py | 
| diff --git a/third_party/gsutil/boto/boto/sts/connection.py b/third_party/gsutil/boto/boto/sts/connection.py | 
| new file mode 100644 | 
| index 0000000000000000000000000000000000000000..49e04c294c9af5da5be53596092f81cf4ed584fd | 
| --- /dev/null | 
| +++ b/third_party/gsutil/boto/boto/sts/connection.py | 
| @@ -0,0 +1,207 @@ | 
| +# Copyright (c) 2011 Mitch Garnaat http://garnaat.org/ | 
| +# Copyright (c) 2011, Eucalyptus Systems, Inc. | 
| +# | 
| +# 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.connection import AWSQueryConnection | 
| +from boto.regioninfo import RegionInfo | 
| +from credentials import Credentials, FederationToken, AssumedRole | 
| +import boto | 
| +import boto.utils | 
| +import datetime | 
| +import threading | 
| + | 
| +_session_token_cache = {} | 
| + | 
| + | 
| +class STSConnection(AWSQueryConnection): | 
| + | 
| +    DefaultRegionName = 'us-east-1' | 
| +    DefaultRegionEndpoint = 'sts.amazonaws.com' | 
| +    APIVersion = '2011-06-15' | 
| + | 
| +    def __init__(self, aws_access_key_id=None, aws_secret_access_key=None, | 
| +                 is_secure=True, port=None, proxy=None, proxy_port=None, | 
| +                 proxy_user=None, proxy_pass=None, debug=0, | 
| +                 https_connection_factory=None, region=None, path='/', | 
| +                 converter=None, validate_certs=True): | 
| +        if not region: | 
| +            region = RegionInfo(self, self.DefaultRegionName, | 
| +                                self.DefaultRegionEndpoint, | 
| +                                connection_cls=STSConnection) | 
| +        self.region = region | 
| +        self._mutex = threading.Semaphore() | 
| +        AWSQueryConnection.__init__(self, aws_access_key_id, | 
| +                                    aws_secret_access_key, | 
| +                                    is_secure, port, proxy, proxy_port, | 
| +                                    proxy_user, proxy_pass, | 
| +                                    self.region.endpoint, debug, | 
| +                                    https_connection_factory, path, | 
| +                                    validate_certs=validate_certs) | 
| + | 
| +    def _required_auth_capability(self): | 
| +        return ['sign-v2'] | 
| + | 
| +    def _check_token_cache(self, token_key, duration=None, window_seconds=60): | 
| +        token = _session_token_cache.get(token_key, None) | 
| +        if token: | 
| +            now = datetime.datetime.utcnow() | 
| +            expires = boto.utils.parse_ts(token.expiration) | 
| +            delta = expires - now | 
| +            if delta < datetime.timedelta(seconds=window_seconds): | 
| +                msg = 'Cached session token %s is expired' % token_key | 
| +                boto.log.debug(msg) | 
| +                token = None | 
| +        return token | 
| + | 
| +    def _get_session_token(self, duration=None, | 
| +                           mfa_serial_number=None, mfa_token=None): | 
| +        params = {} | 
| +        if duration: | 
| +            params['DurationSeconds'] = duration | 
| +        if mfa_serial_number: | 
| +            params['SerialNumber'] = mfa_serial_number | 
| +        if mfa_token: | 
| +            params['TokenCode'] = mfa_token | 
| +        return self.get_object('GetSessionToken', params, | 
| +                                Credentials, verb='POST') | 
| + | 
| +    def get_session_token(self, duration=None, force_new=False, | 
| +                          mfa_serial_number=None, mfa_token=None): | 
| +        """ | 
| +        Return a valid session token.  Because retrieving new tokens | 
| +        from the Secure Token Service is a fairly heavyweight operation | 
| +        this module caches previously retrieved tokens and returns | 
| +        them when appropriate.  Each token is cached with a key | 
| +        consisting of the region name of the STS endpoint | 
| +        concatenated with the requesting user's access id.  If there | 
| +        is a token in the cache meeting with this key, the session | 
| +        expiration is checked to make sure it is still valid and if | 
| +        so, the cached token is returned.  Otherwise, a new session | 
| +        token is requested from STS and it is placed into the cache | 
| +        and returned. | 
| + | 
| +        :type duration: int | 
| +        :param duration: The number of seconds the credentials should | 
| +            remain valid. | 
| + | 
| +        :type force_new: bool | 
| +        :param force_new: If this parameter is True, a new session token | 
| +            will be retrieved from the Secure Token Service regardless | 
| +            of whether there is a valid cached token or not. | 
| + | 
| +        :type mfa_serial_number: str | 
| +        :param mfa_serial_number: The serial number of an MFA device. | 
| +            If this is provided and if the mfa_passcode provided is | 
| +            valid, the temporary session token will be authorized with | 
| +            to perform operations requiring the MFA device authentication. | 
| + | 
| +        :type mfa_token: str | 
| +        :param mfa_token: The 6 digit token associated with the | 
| +            MFA device. | 
| +        """ | 
| +        token_key = '%s:%s' % (self.region.name, self.provider.access_key) | 
| +        token = self._check_token_cache(token_key, duration) | 
| +        if force_new or not token: | 
| +            boto.log.debug('fetching a new token for %s' % token_key) | 
| +            try: | 
| +                self._mutex.acquire() | 
| +                token = self._get_session_token(duration, | 
| +                                                mfa_serial_number, | 
| +                                                mfa_token) | 
| +                _session_token_cache[token_key] = token | 
| +            finally: | 
| +                self._mutex.release() | 
| +        return token | 
| + | 
| +    def get_federation_token(self, name, duration=None, policy=None): | 
| +        """ | 
| +        :type name: str | 
| +        :param name: The name of the Federated user associated with | 
| +                     the credentials. | 
| + | 
| +        :type duration: int | 
| +        :param duration: The number of seconds the credentials should | 
| +                         remain valid. | 
| + | 
| +        :type policy: str | 
| +        :param policy: A JSON policy to associate with these credentials. | 
| + | 
| +        """ | 
| +        params = {'Name': name} | 
| +        if duration: | 
| +            params['DurationSeconds'] = duration | 
| +        if policy: | 
| +            params['Policy'] = policy | 
| +        return self.get_object('GetFederationToken', params, | 
| +                                FederationToken, verb='POST') | 
| + | 
| +    def assume_role(self, role_arn, role_session_name, policy=None, | 
| +                    duration_seconds=None, external_id=None): | 
| +        """ | 
| +        Returns a set of temporary credentials that the caller can use to | 
| +        access resources that are allowed by the temporary credentials.  The | 
| +        credentials are valid for the duration that the caller specified, which | 
| +        can be from 15 minutes (900 seconds) to 1 hour (3600 seconds) | 
| + | 
| +        :type role_arn: str | 
| +        :param role_arn: The Amazon Resource Name (ARN) of the role that the | 
| +            caller is assuming. | 
| + | 
| +        :type role_session_name: str | 
| +        :param role_session_name: The session name of the temporary security | 
| +            credentials. The session name is part of the AssumedRoleUser. | 
| + | 
| +        :type policy: str | 
| +        :param policy: A supplemental policy that can be associated with the | 
| +            temporary security credentials. The caller can limit the | 
| +            permissions that are available on the role's temporary security | 
| +            credentials to maintain the least amount of privileges.  When a | 
| +            service call is made with the temporary security credentials, both | 
| +            policies (the role policy and supplemental policy) are checked. | 
| + | 
| + | 
| +        :type duration_seconds: int | 
| +        :param duration_seconds: he duration, in seconds, of the role session. | 
| +            The value can range from 900 seconds (15 minutes) to 3600 seconds | 
| +            (1 hour).  By default, the value is set to 3600 seconds. | 
| + | 
| +        :type external_id: str | 
| +        :param external_id: A unique identifier that is used by | 
| +            third-party services to ensure that they are assuming a role that | 
| +            corresponds to the correct users. For third-party services that | 
| +            have access to resources across multiple AWS accounts, the unique | 
| +            client ID helps third-party services simplify access control | 
| +            verification. | 
| + | 
| +        :return: An instance of :class:`boto.sts.credentials.AssumedRole` | 
| + | 
| +        """ | 
| +        params = { | 
| +            'RoleArn': role_arn, | 
| +            'RoleSessionName': role_session_name | 
| +        } | 
| +        if policy is not None: | 
| +            params['Policy'] = policy | 
| +        if duration_seconds is not None: | 
| +            params['DurationSeconds'] = duration_seconds | 
| +        if external_id is not None: | 
| +            params['ExternalId'] = external_id | 
| +        return self.get_object('AssumeRole', params, AssumedRole, verb='POST') | 
|  |