def __call__(self): try: table_name = self.action_params.get(parser.Props.TABLE_NAME, None) # parse expected item conditions expected_item_conditions = ( parser.Parser.parse_expected_attribute_conditions( self.action_params.get(parser.Props.EXPECTED, {}) ) ) # parse item item_attributes = parser.Parser.parse_item_attributes( self.action_params[parser.Props.ITEM] ) # parse return_values param return_values_json = self.action_params.get( parser.Props.RETURN_VALUES, parser.Values.RETURN_VALUES_NONE ) return_values = models.InsertReturnValuesType(return_values_json) # parse return_item_collection_metrics return_item_collection_metrics = self.action_params.get( parser.Props.RETURN_ITEM_COLLECTION_METRICS, parser.Values.RETURN_ITEM_COLLECTION_METRICS_NONE ) return_consumed_capacity = self.action_params.get( parser.Props.RETURN_CONSUMED_CAPACITY, parser.Values.RETURN_CONSUMED_CAPACITY_NONE ) except Exception: raise AWSValidationException() try: # put item result, old_item = storage.put_item( self.context, table_name, item_attributes, return_values, if_not_exist=False, expected_condition_map=expected_item_conditions ) if not result: raise AWSErrorResponseException() # format response response = {} if old_item: response[parser.Props.ATTRIBUTES] = ( parser.Parser.format_item_attributes(item_attributes) ) if (return_item_collection_metrics != parser.Values.RETURN_ITEM_COLLECTION_METRICS_NONE): response[parser.Props.ITEM_COLLECTION_METRICS] = { parser.Props.ITEM_COLLECTION_KEY: { parser.Parser.format_item_attributes( models.AttributeValue("S", "key") ) }, parser.Props.SIZE_ESTIMATED_RANGE_GB: [0] } if (return_consumed_capacity != parser.Values.RETURN_CONSUMED_CAPACITY_NONE): response[parser.Props.CONSUMED_CAPACITY] = ( parser.Parser.format_consumed_capacity( return_consumed_capacity, None ) ) return response except AWSErrorResponseException as e: raise e except Exception: raise AWSErrorResponseException()
def __call__(self): try: table_name = self.action_params.get(parser.Props.TABLE_NAME, None) # get attributes_to_get attributes_to_get = self.action_params.get( parser.Props.ATTRIBUTES_TO_GET, None) select_type = (models.SelectType.all() if attributes_to_get is None else models.AttributeToGet.specified(attributes_to_get)) # parse key_attributes key_attributes = parser.Parser.parse_item_attributes( self.action_params[parser.Props.KEY]) # TODO(dukhlov): # it would be nice to validate given table_name, key_attributes and # attributes_to_get to schema expectation consistent_read = self.action_params.get( parser.Props.CONSISTENT_READ, False) return_consumed_capacity = self.action_params.get( parser.Props.RETURN_CONSUMED_CAPACITY, parser.Values.RETURN_CONSUMED_CAPACITY_NONE) # format conditions to get item indexed_condition_map = { name: [models.IndexedCondition.eq(value)] for name, value in key_attributes.iteritems() } except Exception: raise AWSValidationException() try: # get item result = storage.select_item(self.context, table_name, indexed_condition_map, select_type=select_type, limit=2, consistent=consistent_read) # format response if result.count == 0: return {} assert result.count == 1 response = { parser.Props.ITEM: parser.Parser.format_item_attributes(result.items[0]) } if (return_consumed_capacity != parser.Values.RETURN_CONSUMED_CAPACITY_NONE): response[parser.Props.CONSUMED_CAPACITY] = ( parser.Parser.format_consumed_capacity( return_consumed_capacity, None)) return response except AWSErrorResponseException as e: raise e except Exception: raise AWSErrorResponseException()
def __call__(self): try: table_name = self.action_params.get(parser.Props.TABLE_NAME, None) # parse expected item conditions expected_item_conditions = ( parser.Parser.parse_expected_attribute_conditions( self.action_params.get(parser.Props.EXPECTED, {}))) # parse item key_attributes = parser.Parser.parse_item_attributes( self.action_params[parser.Props.KEY]) # parse return_values param return_values = self.action_params.get( parser.Props.RETURN_VALUES, parser.Values.RETURN_VALUES_NONE) # parse return_item_collection_metrics return_item_collection_metrics = self.action_params.get( parser.Props.RETURN_ITEM_COLLECTION_METRICS, parser.Values.RETURN_ITEM_COLLECTION_METRICS_NONE) return_consumed_capacity = self.action_params.get( parser.Props.RETURN_CONSUMED_CAPACITY, parser.Values.RETURN_CONSUMED_CAPACITY_NONE) except Exception: raise AWSValidationException() try: # put item result = storage.delete_item( self.context, table_name, key_attributes, expected_condition_map=expected_item_conditions) except AWSErrorResponseException as e: raise e except Exception: raise AWSErrorResponseException() if not result: raise AWSErrorResponseException() # format response response = {} try: if return_values != parser.Values.RETURN_VALUES_NONE: # TODO(dukhlov): # It is needed to return all deleted item attributes # response[parser.Props.ATTRIBUTES] = ( parser.Parser.format_item_attributes(key_attributes)) if (return_item_collection_metrics != parser.Values.RETURN_ITEM_COLLECTION_METRICS_NONE): response[parser.Props.ITEM_COLLECTION_METRICS] = { parser.Props.ITEM_COLLECTION_KEY: { parser.Parser.format_item_attributes( models.AttributeValue(models.ATTRIBUTE_TYPE_STRING, "key")) }, parser.Props.SIZE_ESTIMATED_RANGE_GB: [0] } if (return_consumed_capacity != parser.Values.RETURN_CONSUMED_CAPACITY_NONE): response[parser.Props.CONSUMED_CAPACITY] = ( parser.Parser.format_consumed_capacity( return_consumed_capacity, None)) return response except Exception: raise exception.AWSErrorResponseException()
def __call__(self): try: table_name = self.action_params.get(parser.Props.TABLE_NAME, None) # parse table attributes attribute_definitions = parser.Parser.parse_attribute_definitions( self.action_params.get(parser.Props.ATTRIBUTE_DEFINITIONS, {}) ) # parse table key schema key_attrs = parser.Parser.parse_key_schema( self.action_params.get(parser.Props.KEY_SCHEMA, []) ) # parse table indexed field list indexed_def_map = parser.Parser.parse_local_secondary_indexes( self.action_params.get( parser.Props.LOCAL_SECONDARY_INDEXES, []) ) # prepare table_schema structure table_schema = models.TableSchema( attribute_definitions, key_attrs, indexed_def_map ) except Exception: raise AWSValidationException() try: # creating table table_meta = storage.create_table( self.context, table_name, table_schema ) result = { parser.Props.TABLE_DESCRIPTION: { parser.Props.ATTRIBUTE_DEFINITIONS: ( parser.Parser.format_attribute_definitions( table_meta.schema.attribute_type_map ) ), parser.Props.CREATION_DATE_TIME: 0, parser.Props.ITEM_COUNT: 0, parser.Props.KEY_SCHEMA: ( parser.Parser.format_key_schema( table_meta.schema.key_attributes ) ), parser.Props.PROVISIONED_THROUGHPUT: ( parser.Values.PROVISIONED_THROUGHPUT_DUMMY ), parser.Props.TABLE_NAME: table_name, parser.Props.TABLE_STATUS: ( parser.Parser.format_table_status(table_meta.status) ), parser.Props.TABLE_SIZE_BYTES: 0 } } if table_meta.schema.index_def_map: table_def = result[parser.Props.TABLE_DESCRIPTION] table_def[parser.Props.LOCAL_SECONDARY_INDEXES] = ( parser.Parser.format_local_secondary_indexes( table_meta.schema.key_attributes[0], table_meta.schema.index_def_map ) ) return result except TableAlreadyExistsException: raise AWSDuplicateTableError(table_name) except AWSErrorResponseException as e: raise e except Exception: raise AWSErrorResponseException()
def _authorize(self, req, auth_uri): # Read request signature and access id. # If we find X-Auth-User in the headers we ignore a key error # here so that we can use both authentication methods. # Returning here just means the user didn't supply AWS # authentication and we'll let the app try native keystone next. LOG.info(_("Checking AWS credentials..")) signature = self._get_signature(req) if not signature: if 'X-Auth-User' in req.headers: return self.application elif 'X-Auth-Token' in req.headers: return self.application else: LOG.info(_("No AWS Signature found.")) raise AWSIncompleteSignatureError() access = self._get_access(req) if not access: if 'X-Auth-User' in req.headers: return self.application else: LOG.info(_("No AWSAccessKeyId/Authorization Credential")) raise AWSIncompleteSignatureError() LOG.info(_("AWS credentials found, checking against keystone.")) if not auth_uri: LOG.error( _("Ec2Token authorization failed, no auth_uri " "specified in config file")) raise AWSErrorResponseException(_('Service misconfigured')) # Make a copy of args for authentication and signature verification. auth_params = dict(req.params) # 'Signature' param Not part of authentication args auth_params.pop('Signature', None) # Authenticate the request. # AWS v4 authentication requires a hash of the body body_hash = hashlib.sha256(req.body).hexdigest() creds = { 'ec2Credentials': { 'access': access, 'signature': signature, 'host': req.host, 'verb': req.method, 'path': req.path, 'params': auth_params, 'headers': req.headers, 'body_hash': body_hash } } creds_json = json.dumps(creds) headers = {'Content-Type': 'application/json'} keystone_ec2_uri = self._conf_get_keystone_ec2_uri(auth_uri) LOG.info(_('Authenticating with %s'), keystone_ec2_uri) response = requests.post(keystone_ec2_uri, data=creds_json, headers=headers) result = response.json() try: if self._is_v2_token(result): token_id = result['access']['token']['id'] tenant = result['access']['token']['tenant']['name'] tenant_id = result['access']['token']['tenant']['id'] metadata = result['access'].get('metadata', {}) roles = metadata.get('roles', []) elif self._is_v3_token(result): token_id = response.headers['X-Subject-Token'] tenant = result['token']['project']['name'] tenant_id = result['token']['project']['id'] metadata = result['token']['roles'] roles = [r['name'] for r in metadata] else: raise AWSInvalidClientTokenIdError() LOG.info(_("AWS authentication successful.")) except (AttributeError, KeyError): LOG.info(_("AWS authentication failure.")) # Try to extract the reason for failure so we can return the # appropriate AWS error via raising an exception try: reason = result['error']['message'] except KeyError: reason = None if reason == "EC2 access key not found.": raise AWSInvalidClientTokenIdError() elif reason == "EC2 signature not supplied.": raise AWSSignatureError() else: raise AWSAccessDeniedError() # Authenticated! ec2_creds = { 'ec2Credentials': { 'access': access, 'signature': signature } } req.headers['X-Auth-EC2-Creds'] = json.dumps(ec2_creds) req.headers['X-Auth-Token'] = token_id req.headers['X-Tenant-Name'] = tenant req.headers['X-Tenant-Id'] = tenant_id req.headers['X-Auth-URL'] = auth_uri req.headers['X-Roles'] = ','.join(roles) return self.application
def __call__(self): try: table_name = self.action_params.get(parser.Props.TABLE_NAME, None) # parse select_type attributes_to_get = self.action_params.get( parser.Props.ATTRIBUTES_TO_GET, None ) if attributes_to_get is not None: attributes_to_get = frozenset(attributes_to_get) select = self.action_params.get( parser.Props.SELECT, None ) index_name = self.action_params.get(parser.Props.INDEX_NAME, None) select_type = parser.Parser.parse_select_type(select, attributes_to_get, index_name) # parse exclusive_start_key_attributes exclusive_start_key_attributes = self.action_params.get( parser.Props.EXCLUSIVE_START_KEY, None ) if exclusive_start_key_attributes is not None: exclusive_start_key_attributes = ( parser.Parser.parse_item_attributes( exclusive_start_key_attributes ) ) # parse indexed_condition_map indexed_condition_map = parser.Parser.parse_attribute_conditions( self.action_params.get(parser.Props.KEY_CONDITIONS, None) ) # TODO(dukhlov): # it would be nice to validate given table_name, key_attributes and # attributes_to_get to schema expectation consistent_read = self.action_params.get( parser.Props.CONSISTENT_READ, False ) limit = self.action_params.get(parser.Props.LIMIT, None) return_consumed_capacity = self.action_params.get( parser.Props.RETURN_CONSUMED_CAPACITY, parser.Values.RETURN_CONSUMED_CAPACITY_NONE ) order_asc = self.action_params.get( parser.Props.SCAN_INDEX_FORWARD, None ) order_type = ( None if order_asc is None else models.ORDER_TYPE_ASC if order_asc else models.ORDER_TYPE_DESC ) except Exception: raise AWSValidationException() try: # select item result = storage.query( self.context, table_name, indexed_condition_map, select_type=select_type, index_name=index_name, limit=limit, consistent=consistent_read, order_type=order_type, exclusive_start_key=exclusive_start_key_attributes ) # format response if select_type.type == models.SelectType.SELECT_TYPE_COUNT: response = { parser.Props.COUNT: result.count } else: response = { parser.Props.COUNT: result.count, parser.Props.ITEMS: [ parser.Parser.format_item_attributes(row) for row in result.items ] } if (return_consumed_capacity != parser.Values.RETURN_CONSUMED_CAPACITY_NONE): response[parser.Props.CONSUMED_CAPACITY] = ( parser.Parser.format_consumed_capacity( return_consumed_capacity, None ) ) if limit == result.count: response[parser.Props.LAST_EVALUATED_KEY] = ( parser.Parser.format_item_attributes( result.last_evaluated_key) ) return response except AWSErrorResponseException as e: raise e except Exception: raise AWSErrorResponseException()