コード例 #1
0
ファイル: server.py プロジェクト: wyllys66/PyKMIP
 def __init__(self):
     super(self.__class__, self).__init__()
     self.logger = logging.getLogger(__name__)
     self.key_factory = KeyFactory()
     self.secret_factory = SecretFactory()
     self.attribute_factory = AttributeFactory()
     self.repo = MemRepo()
コード例 #2
0
ファイル: server.py プロジェクト: wyllys66/PyKMIP
class KMIPImpl(KMIP):

    def __init__(self):
        super(self.__class__, self).__init__()
        self.logger = logging.getLogger(__name__)
        self.key_factory = KeyFactory()
        self.secret_factory = SecretFactory()
        self.attribute_factory = AttributeFactory()
        self.repo = MemRepo()

    def create(self, object_type, template_attribute, credential=None):
        self.logger.debug('create() called')
        self.logger.debug('object type = %s' % object_type)
        bit_length = 256
        attributes = template_attribute.attributes
        ret_attributes = []
        if object_type.enum != OT.SYMMETRIC_KEY:
            self.logger.debug('invalid object type')
            return self._get_invalid_field_result('invalid object type')
        try:
            alg_attr =\
                self._validate_req_field(attributes,
                                         AT.CRYPTOGRAPHIC_ALGORITHM.value,
                                         (CA.AES.value,),
                                         'unsupported algorithm')
            len_attr = self._validate_req_field(attributes,
                                                AT.CRYPTOGRAPHIC_LENGTH.value,
                                                (128, 256, 512),
                                                'unsupported key length',
                                                False)
            self._validate_req_field(attributes,
                                     AT.CRYPTOGRAPHIC_USAGE_MASK.value,
                                     (),
                                     '')
        except InvalidFieldException as e:
            self.logger.debug('InvalidFieldException raised')
            return e.result

        crypto_alg = CryptographicAlgorithm(CA(alg_attr.attribute_value.value))

        if len_attr is None:
            self.logger.debug('cryptographic length not supplied')
            attribute_type = AT.CRYPTOGRAPHIC_LENGTH
            length_attribute = self.attribute_factory.\
                create_attribute(attribute_type, bit_length)
            attributes.append(length_attribute)
            ret_attributes.append(length_attribute)
        else:
            bit_length = len_attr.attribute_value.value

        key = self._gen_symmetric_key(bit_length, crypto_alg)
        s_uuid, uuid_attribute = self._save(key, attributes)
        ret_attributes.append(uuid_attribute)
        template_attribute = TemplateAttribute(attributes=ret_attributes)
        return CreateResult(ResultStatus(RS.SUCCESS),
                            object_type=object_type,
                            uuid=UniqueIdentifier(s_uuid),
                            template_attribute=template_attribute)

    def register(self, object_type, template_attribute, secret,
                 credential=None):
        self.logger.debug('register() called')
        self.logger.debug('object type = %s' % object_type)
        attributes = template_attribute.attributes
        ret_attributes = []
        if object_type is None:
            self.logger.debug('invalid object type')
            return self._get_missing_field_result('object type')
        if object_type.enum != OT.SYMMETRIC_KEY:
            self.logger.debug('invalid object type')
            return self._get_invalid_field_result('invalid object type')
        if secret is None or not isinstance(secret, SymmetricKey):
            msg = 'object type does not match that of secret'
            self.logger.debug(msg)
            return self._get_invalid_field_result(msg)

        self.logger.debug('Collecting all attributes')
        if attributes is None:
            attributes = []
        attributes.extend(self._get_key_block_attributes(secret.key_block))

        self.logger.debug('Verifying all attributes are valid and set')
        try:
            self._validate_req_field(attributes,
                                     AT.CRYPTOGRAPHIC_ALGORITHM.value,
                                     (CA.AES.value,),
                                     'unsupported algorithm')
            self._validate_req_field(attributes,
                                     AT.CRYPTOGRAPHIC_LENGTH.value,
                                     (128, 256, 512),
                                     'unsupported key length')
            self._validate_req_field(attributes,
                                     AT.CRYPTOGRAPHIC_USAGE_MASK.value,
                                     (),
                                     '')
        except InvalidFieldException as e:
            self.logger.debug('InvalidFieldException raised')
            return RegisterResult(e.result.result_status,
                                  e.result.result_reason,
                                  e.result.result_message)

        s_uuid, uuid_attribute = self._save(secret, attributes)
        ret_attributes.append(uuid_attribute)
        template_attribute = TemplateAttribute(attributes=ret_attributes)
        return RegisterResult(ResultStatus(RS.SUCCESS),
                              uuid=UniqueIdentifier(s_uuid),
                              template_attribute=template_attribute)

    def get(self,
            uuid=None,
            key_format_type=None,
            key_compression_type=None,
            key_wrapping_specification=None,
            credential=None):
        self.logger.debug('get() called')
        ret_value = RS.OPERATION_FAILED
        if uuid is None or not hasattr(uuid, 'value'):
            self.logger.debug('no uuid provided')
            reason = ResultReason(ResultReasonEnum.ITEM_NOT_FOUND)
            message = ResultMessage('')
            return GetResult(ResultStatus(ret_value), reason, message)
        if key_format_type is None:
            self.logger.debug('key format type is None, setting to raw')
            key_format_type = KeyFormatType(KeyFormatTypeEnum.RAW)
        if key_format_type.enum != KeyFormatTypeEnum.RAW:
            self.logger.debug('key format type is not raw')
            reason = ResultReason(ResultReasonEnum.
                                  KEY_FORMAT_TYPE_NOT_SUPPORTED)
            message = ResultMessage('')
            return GetResult(ResultStatus(ret_value), reason, message)
        if key_compression_type is not None:
            self.logger.debug('key compression type is not None')
            reason = ResultReason(ResultReasonEnum.
                                  KEY_COMPRESSION_TYPE_NOT_SUPPORTED)
            message = ResultMessage('')
            return GetResult(ResultStatus(ret_value), reason, message)
        if key_wrapping_specification is not None:
            self.logger.debug('key wrapping specification is not None')
            reason = ResultReason(ResultReasonEnum.FEATURE_NOT_SUPPORTED)
            message = ResultMessage('key wrapping is not currently supported')
            return GetResult(ResultStatus(ret_value), reason, message)

        self.logger.debug('retrieving object from repo')
        managed_object, _ = self.repo.get(uuid.value)

        if managed_object is None:
            self.logger.debug('object not found in repo')
            reason = ResultReason(ResultReasonEnum.ITEM_NOT_FOUND)
            message = ResultMessage('')
            return GetResult(ResultStatus(ret_value), reason, message)

        # currently only symmetric keys are supported, fix this in future
        object_type = ObjectType(OT.SYMMETRIC_KEY)
        ret_value = RS.SUCCESS
        return GetResult(ResultStatus(ret_value),
                         object_type=object_type,
                         uuid=uuid,
                         secret=managed_object)

    def destroy(self, uuid):
        self.logger.debug('destroy() called')
        ret_value = RS.OPERATION_FAILED
        if uuid is None or not hasattr(uuid, 'value'):
            self.logger.debug('no uuid provided')
            reason = ResultReason(ResultReasonEnum.ITEM_NOT_FOUND)
            message = ResultMessage('')
            return DestroyResult(ResultStatus(ret_value), reason, message)

        msg = 'deleting object from repo: {0}'.format(uuid)
        self.logger.debug(msg)
        if not self.repo.delete(uuid.value):
            self.logger.debug('repo did not find and delete managed object')
            reason = ResultReason(ResultReasonEnum.ITEM_NOT_FOUND)
            message = ResultMessage('')
            return DestroyResult(ResultStatus(ret_value), reason, message)

        ret_value = RS.SUCCESS
        return DestroyResult(ResultStatus(ret_value), uuid=uuid)

    def locate(self, maximum_items=None, storage_status_mask=None,
               object_group_member=None, attributes=None,
               credential=None):
        self.logger.debug('locate() called')
        msg = 'locating object(s) from repo'
        self.logger.debug(msg)
        try:
            uuids = self.repo.locate(maximum_items, storage_status_mask,
                                     object_group_member, attributes)
            return LocateResult(ResultStatus(RS.SUCCESS), uuids=uuids)
        except NotImplementedError:
            msg = ResultMessage('Locate Operation Not Supported')
            reason = ResultReason(ResultReasonEnum.OPERATION_NOT_SUPPORTED)
            return LocateResult(ResultStatus(RS.OPERATION_FAILED),
                                result_reason=reason,
                                result_message=msg)

    def _validate_req_field(self, attrs, name, expected, msg, required=True):
        self.logger.debug('Validating attribute %s' % name)
        seen = False
        found_attr = None
        for attr in attrs:
            if self._validate_field(attr, name, expected, msg):
                if seen:
                    # TODO check what spec says to do on this
                    msg = 'duplicate attribute: %s' % name
                    self.logger.debug(msg)
                    result = self._get_duplicate_attribute_result(name)
                    raise InvalidFieldException(result)
                seen = True
                found_attr = attr
        if required and not seen:
            result = self._get_missing_field_result(name)
            raise InvalidFieldException(result)
        return found_attr

    def _validate_field(self, attr, name, expected, msg):
        if attr.attribute_name.value == name:
            self.logger.debug('validating attribute %s' % name)
            if not expected or attr.attribute_value.value in expected:
                self.logger.debug('attribute validated')
                return True
            else:
                self.logger.debug('attribute not validated')
                result = self._get_invalid_field_result(msg)
                raise InvalidFieldException(result)
        else:
            return False

    def _get_invalid_field_result(self, msg):
        status = ResultStatus(RS.OPERATION_FAILED)
        reason = ResultReason(ResultReasonEnum.INVALID_FIELD)
        message = ResultMessage(msg)
        return OperationResult(status, reason, message)

    def _get_missing_field_result(self, name):
        msg = '%s not supplied' % name
        self.logger.debug(msg)
        status = ResultStatus(RS.OPERATION_FAILED)
        reason = ResultReason(ResultReasonEnum.ITEM_NOT_FOUND)
        message = ResultMessage(msg)
        return OperationResult(status, reason, message)

    def _get_duplicate_attribute_result(self, name):
        msg = '%s supplied multiple times' % name
        self.logger.debug(msg)
        status = ResultStatus(RS.OPERATION_FAILED)
        reason = ResultReason(ResultReasonEnum.INDEX_OUT_OF_BOUNDS)
        message = ResultMessage(msg)
        return OperationResult(status, reason, message)

    def _gen_symmetric_key(self, bit_length, crypto_alg):
        key_format_type = KeyBlock.KeyFormatType(KeyFormatTypeEnum.RAW)
        key_material = RawKey(bytearray(os.urandom(int(bit_length/8))))
        key_value = KeyValueStruct(key_format_type, key_material)
        crypto_length = CryptographicLength(bit_length)
        key_block = KeyBlock(key_format_type, None, key_value, crypto_alg,
                             crypto_length, None)
        return SymmetricKey(key_block)

    def _save(self, key, attributes):
        s_uuid = self.repo.save(key, attributes)
        self.logger.debug('creating object with uuid = %s' % s_uuid)
        attribute_type = AT.UNIQUE_IDENTIFIER
        attribute = self.attribute_factory.create_attribute(attribute_type,
                                                            s_uuid)
        attributes.append(attribute)
        # Calling update to also store the UUID
        self.repo.update(s_uuid, key, attributes)
        return s_uuid, attribute

    def _get_key_block_attributes(self, key_block):
        self.logger.debug('getting all key attributes from key block')
        attributes = []
        if key_block.cryptographic_algorithm is not None:
            self.logger.debug('crypto_alg set on key block')
            self.logger.debug('adding crypto algorithm attribute')
            at = AT.CRYPTOGRAPHIC_ALGORITHM
            alg = key_block.cryptographic_algorithm.enum
            attributes.append(self.attribute_factory.create_attribute(at, alg))
        if key_block.cryptographic_length is not None:
            self.logger.debug('crypto_length set on key block')
            self.logger.debug('adding crypto length attribute')
            at = AT.CRYPTOGRAPHIC_LENGTH
            len = key_block.cryptographic_length.value
            attributes.append(self.attribute_factory.create_attribute(at, len))
        self.logger.debug('getting key value attributes')
        if key_block.key_wrapping_data is not None:
            self.logger.debug('no wrapping data so key value is struct')
            kv = key_block.key_value
            if isinstance(kv, KeyValue):
                kv = key_block.key_value
            if isinstance(kv, KeyValueStruct):
                if kv.attributes is not None:
                    self.logger.debug('adding the key value struct attributes')
                    attributes.extend(kv.attributes)
        return attributes