PyKMIP library version 0.0.1
This implementation supports version 1.1 of the KMIP spec. The library supports the following operations for SymmetricKey objects: create register get destroy
This commit is contained in:
parent
a0d8c9195e
commit
1cb6deaf0b
6
.gitignore
vendored
6
.gitignore
vendored
@ -1,3 +1,9 @@
|
||||
.project
|
||||
.pydevproject
|
||||
*.pyc
|
||||
|
||||
.coverage
|
||||
.tox/
|
||||
ChangeLog
|
||||
PyKMIP.egg-info/
|
||||
dist/
|
||||
|
2
AUTHORS
Normal file
2
AUTHORS
Normal file
@ -0,0 +1,2 @@
|
||||
Nathan Reller <Nathan.Reller@jhuapl.edu>
|
||||
Peter Hamilton <peter.hamilton@jhuapl.edu>
|
202
LICENSE
202
LICENSE
@ -1 +1,201 @@
|
||||
/* FIXME Insert a license here */
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright 2013, Rackspace (http://www.rackspace.com)
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
70
bin/run_server.py
Normal file
70
bin/run_server.py
Normal file
@ -0,0 +1,70 @@
|
||||
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import logging
|
||||
import optparse
|
||||
import sys
|
||||
|
||||
from thrift.server import TServer
|
||||
from thrift.transport import TSocket
|
||||
from thrift.transport import TTransport
|
||||
|
||||
from kmip.core.server import KMIPImpl
|
||||
|
||||
from kmip.services.kmip_protocol import KMIPProtocolFactory
|
||||
from kmip.services.kmip_server import Processor
|
||||
|
||||
|
||||
def run_server(host='127.0.0.1', port=5696):
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
handler = KMIPImpl()
|
||||
processor = Processor(handler)
|
||||
transport = TSocket.TServerSocket(host, port)
|
||||
tfactory = TTransport.TBufferedTransportFactory()
|
||||
pfactory = KMIPProtocolFactory()
|
||||
server = TServer.TSimpleServer(processor, transport, tfactory, pfactory)
|
||||
|
||||
logger.info('Starting the KMIP server')
|
||||
|
||||
try:
|
||||
server.serve()
|
||||
except KeyboardInterrupt:
|
||||
logger.info('KeyboardInterrupt received while serving')
|
||||
except Exception, e:
|
||||
logger.info('Exception received while serving: {0}'.format(e))
|
||||
finally:
|
||||
transport.close()
|
||||
|
||||
logger.info('Shutting down KMIP server')
|
||||
|
||||
|
||||
def build_cli_parser():
|
||||
parser = optparse.OptionParser(usage="%prog [options]",
|
||||
description="Run KMIP Server")
|
||||
parser.add_option("-n", "--hostname", action="store", default='127.0.0.1',
|
||||
dest="hostname",
|
||||
help="Hostname/IP address of platform running the KMIP "
|
||||
"server (e.g., localhost, 127.0.0.1)")
|
||||
parser.add_option("-p", "--port", action="store", default=5696,
|
||||
dest="port", help="Port number for KMIP services")
|
||||
return parser
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = build_cli_parser()
|
||||
|
||||
opts, args = parser.parse_args(sys.argv[1:])
|
||||
|
||||
run_server(opts.hostname, opts.port)
|
6
bin/run_server.sh
Executable file
6
bin/run_server.sh
Executable file
@ -0,0 +1,6 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -eu
|
||||
|
||||
python run_server.py
|
||||
|
6
bin/run_tests.sh
Executable file
6
bin/run_tests.sh
Executable file
@ -0,0 +1,6 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -eu
|
||||
|
||||
tox
|
||||
|
1
docs/README
Normal file
1
docs/README
Normal file
@ -0,0 +1 @@
|
||||
PyKMIP documentation goes here.
|
@ -0,0 +1,57 @@
|
||||
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import logging.config
|
||||
import os
|
||||
import sys
|
||||
|
||||
path = os.path.join(os.path.dirname(__file__), 'logconfig.ini')
|
||||
|
||||
if os.path.exists(path):
|
||||
logging.config.fileConfig(path)
|
||||
else:
|
||||
minor_version = sys.version_info[1]
|
||||
|
||||
if minor_version == 7:
|
||||
config = {
|
||||
'version': 1,
|
||||
'disable_existing_loggers': False,
|
||||
'formatters': {
|
||||
'simpleFormatter': {
|
||||
'format':
|
||||
'%(asctime)s - %(name)s - %(levelname)s - %(message)s'
|
||||
}
|
||||
},
|
||||
'handlers': {
|
||||
'consoleHandler': {
|
||||
'level': 'DEBUG',
|
||||
'class': 'logging.StreamHandler',
|
||||
'formatter': 'simpleFormatter',
|
||||
'stream': sys.stdout
|
||||
}
|
||||
},
|
||||
'loggers': {
|
||||
'root': {
|
||||
'level': 'DEBUG',
|
||||
'handlers': ['consoleHandler']
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
logging.config.dictConfig(config)
|
||||
else:
|
||||
logging.basicConfig()
|
||||
|
||||
__all__ = ['test', 'transport']
|
17
kmip/core/__init__.py
Normal file
17
kmip/core/__init__.py
Normal file
@ -0,0 +1,17 @@
|
||||
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
__all__ = ['attributes', 'enums', 'errors', 'messages', 'objects',
|
||||
'primitives', 'protocol', 'utils']
|
350
kmip/core/attributes.py
Normal file
350
kmip/core/attributes.py
Normal file
@ -0,0 +1,350 @@
|
||||
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import enums
|
||||
|
||||
from kmip.core.enums import Tags
|
||||
|
||||
from kmip.core.errors import ErrorStrings
|
||||
|
||||
from kmip.core.primitives import Struct
|
||||
from kmip.core.primitives import Integer
|
||||
from kmip.core.primitives import Enumeration
|
||||
from kmip.core.primitives import TextString
|
||||
|
||||
from utils import BytearrayStream
|
||||
|
||||
|
||||
# 3.1
|
||||
class UniqueIdentifier(TextString):
|
||||
|
||||
def __init__(self, value=None):
|
||||
super(self.__class__, self).__init__(value,
|
||||
Tags.UNIQUE_IDENTIFIER)
|
||||
|
||||
|
||||
# 3.2
|
||||
class Name(Struct):
|
||||
|
||||
class NameValue(TextString):
|
||||
|
||||
def __init__(self, value=None):
|
||||
super(self.__class__, self).__init__(value, Tags.NAME_VALUE)
|
||||
|
||||
class NameType(Enumeration):
|
||||
|
||||
ENUM_TYPE = enums.NameType
|
||||
|
||||
def __init__(self, value=None):
|
||||
super(self.__class__, self).__init__(value, Tags.NAME_TYPE)
|
||||
|
||||
def __init__(self, name_value=None, name_type=None):
|
||||
super(self.__class__, self).__init__(tag=Tags.NAME)
|
||||
self.name_value = name_value
|
||||
self.name_type = name_type
|
||||
|
||||
def read(self, istream):
|
||||
super(self.__class__, self).read(istream)
|
||||
tstream = BytearrayStream(istream.read(self.length))
|
||||
|
||||
# Read the value and type of the name
|
||||
self.name_value = Name.NameValue()
|
||||
self.name_type = Name.NameType()
|
||||
self.name_value.read(tstream)
|
||||
self.name_type.read(tstream)
|
||||
|
||||
self.is_oversized(tstream)
|
||||
|
||||
def write(self, ostream):
|
||||
tstream = BytearrayStream()
|
||||
|
||||
# Write the value and type of the name
|
||||
self.name_value.write(tstream)
|
||||
self.name_type.write(tstream)
|
||||
|
||||
# Write the length and value of the template attribute
|
||||
self.length = tstream.length()
|
||||
super(self.__class__, self).write(ostream)
|
||||
ostream.write(tstream.buffer)
|
||||
|
||||
def validate(self):
|
||||
self.__validate()
|
||||
|
||||
def __validate(self):
|
||||
# TODO (peter-hamilton) Finish implementation.
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def create(cls, name_value, name_type):
|
||||
value = cls.NameValue(name_value)
|
||||
n_type = cls.NameType(name_type)
|
||||
return Name(name_value=value,
|
||||
name_type=n_type)
|
||||
|
||||
|
||||
# 3.3
|
||||
class ObjectType(Enumeration):
|
||||
|
||||
ENUM_TYPE = enums.ObjectType
|
||||
|
||||
def __init__(self, value=None):
|
||||
super(self.__class__, self).__init__(value, Tags.OBJECT_TYPE)
|
||||
|
||||
|
||||
# 3.4
|
||||
class CryptographicAlgorithm(Enumeration):
|
||||
|
||||
ENUM_TYPE = enums.CryptographicAlgorithm
|
||||
|
||||
def __init__(self, value=None):
|
||||
super(self.__class__, self).__init__(value,
|
||||
Tags.CRYPTOGRAPHIC_ALGORITHM)
|
||||
|
||||
|
||||
# 3.5
|
||||
class CryptographicLength(Integer):
|
||||
|
||||
def __init__(self, value=None):
|
||||
super(self.__class__, self).__init__(value,
|
||||
Tags.CRYPTOGRAPHIC_LENGTH)
|
||||
|
||||
|
||||
# 3.6
|
||||
class CryptographicParameters(Struct):
|
||||
|
||||
class BlockCipherMode(Enumeration):
|
||||
ENUM_TYPE = enums.BlockCipherMode
|
||||
|
||||
def __init__(self, value=None):
|
||||
super(self.__class__, self).__init__(value,
|
||||
Tags.BLOCK_CIPHER_MODE)
|
||||
|
||||
class PaddingMethod(Enumeration):
|
||||
ENUM_TYPE = enums.PaddingMethod
|
||||
|
||||
def __init__(self, value=None):
|
||||
super(self.__class__, self).__init__(value,
|
||||
Tags.PADDING_METHOD)
|
||||
|
||||
class HashingAlgorithm(Enumeration):
|
||||
ENUM_TYPE = enums.HashingAlgorithm
|
||||
|
||||
def __init__(self, value=None):
|
||||
super(self.__class__, self).__init__(value,
|
||||
Tags.HASHING_ALGORITHM)
|
||||
|
||||
class KeyRoleType(Enumeration):
|
||||
ENUM_TYPE = enums.KeyRoleType
|
||||
|
||||
def __init__(self, value=None):
|
||||
super(self.__class__, self).__init__(value,
|
||||
Tags.KEY_ROLE_TYPE)
|
||||
|
||||
def __init__(self,
|
||||
block_cipher_mode=None,
|
||||
padding_method=None,
|
||||
hashing_algorithm=None,
|
||||
key_role_type=None):
|
||||
super(self.__class__, self).__init__(tag=Tags.CRYPTOGRAPHIC_PARAMETERS)
|
||||
self.block_cipher_mode = block_cipher_mode
|
||||
self.padding_method = padding_method
|
||||
self.hashing_algorithm = hashing_algorithm
|
||||
self.key_role_type = key_role_type
|
||||
|
||||
def read(self, istream):
|
||||
super(self.__class__, self).read(istream)
|
||||
tstream = BytearrayStream(istream.read(self.length))
|
||||
|
||||
if self.is_tag_next(Tags.BLOCK_CIPHER_MODE, tstream):
|
||||
self.block_cipher_mode = CryptographicParameters.BlockCipherMode()
|
||||
self.block_cipher_mode.read(tstream)
|
||||
|
||||
if self.is_tag_next(Tags.PADDING_METHOD, tstream):
|
||||
self.padding_method = CryptographicParameters.PaddingMethod()
|
||||
self.padding_method.read(tstream)
|
||||
|
||||
if self.is_tag_next(Tags.HASHING_ALGORITHM, tstream):
|
||||
self.hashing_algorithm = CryptographicParameters.HashingAlgorithm()
|
||||
self.hashing_algorithm.read(tstream)
|
||||
|
||||
if self.is_tag_next(Tags.KEY_ROLE_TYPE, tstream):
|
||||
self.key_role_type = CryptographicParameters.KeyRoleType()
|
||||
self.key_role_type.read(tstream)
|
||||
|
||||
self.is_oversized(tstream)
|
||||
self.validate()
|
||||
|
||||
def write(self, ostream):
|
||||
tstream = BytearrayStream()
|
||||
|
||||
# Write the contents of the request payload
|
||||
if self.block_cipher_mode is not None:
|
||||
self.block_cipher_mode.write(tstream)
|
||||
if self.padding_method is not None:
|
||||
self.padding_method.write(tstream)
|
||||
if self.hashing_algorithm is not None:
|
||||
self.hashing_algorithm.write(tstream)
|
||||
if self.key_role_type is not None:
|
||||
self.key_role_type.write(tstream)
|
||||
|
||||
# Write the length and value of the request payload
|
||||
self.length = tstream.length()
|
||||
super(self.__class__, self).write(ostream)
|
||||
ostream.write(tstream.buffer)
|
||||
|
||||
def validate(self):
|
||||
self.__validate()
|
||||
|
||||
def __validate(self):
|
||||
# TODO (peter-hamilton) Finish implementation.
|
||||
pass
|
||||
|
||||
|
||||
# 3.8
|
||||
class CertificateType(Enumeration):
|
||||
ENUM_TYPE = enums.CertificateType
|
||||
|
||||
def __init__(self, value=None):
|
||||
super(self.__class__, self).__init__(value,
|
||||
Tags.CERTIFICATE_TYPE)
|
||||
|
||||
|
||||
# 3.19
|
||||
class CryptographicUsageMask(Integer):
|
||||
|
||||
ENUM_TYPE = enums.CryptographicUsageMask
|
||||
|
||||
def __init__(self, value=None):
|
||||
super(self.__class__, self).__init__(value,
|
||||
Tags.CRYPTOGRAPHIC_USAGE_MASK)
|
||||
|
||||
|
||||
# 3.33
|
||||
class ObjectGroup(TextString):
|
||||
|
||||
def __init__(self, value=None):
|
||||
super(self.__class__,
|
||||
self).__init__(value, Tags.OBJECT_GROUP)
|
||||
|
||||
|
||||
# 3.36
|
||||
class ApplicationSpecificInformation(Struct):
|
||||
|
||||
class ApplicationNamespace(TextString):
|
||||
|
||||
def __init__(self, value=None):
|
||||
super(self.__class__,
|
||||
self).__init__(value, Tags.APPLICATION_NAMESPACE)
|
||||
|
||||
class ApplicationData(TextString):
|
||||
|
||||
def __init__(self, value=None):
|
||||
super(self.__class__,
|
||||
self).__init__(value, Tags.APPLICATION_DATA)
|
||||
|
||||
def __init__(self, application_namespace=None,
|
||||
application_data=None):
|
||||
super(self.__class__,
|
||||
self).__init__(Tags.APPLICATION_SPECIFIC_INFORMATION)
|
||||
|
||||
self.application_namespace = application_namespace
|
||||
self.application_data = application_data
|
||||
|
||||
self.validate()
|
||||
|
||||
def read(self, istream):
|
||||
super(self.__class__, self).read(istream)
|
||||
tstream = BytearrayStream(istream.read(self.length))
|
||||
|
||||
self.application_namespace = self.ApplicationNamespace()
|
||||
self.application_data = self.ApplicationData()
|
||||
|
||||
self.application_namespace.read(tstream)
|
||||
self.application_data.read(tstream)
|
||||
|
||||
self.is_oversized(tstream)
|
||||
self.validate()
|
||||
|
||||
def write(self, ostream):
|
||||
tstream = BytearrayStream()
|
||||
|
||||
self.application_namespace.write(tstream)
|
||||
self.application_data.write(tstream)
|
||||
|
||||
# Write the length and value of the request payload
|
||||
self.length = tstream.length()
|
||||
super(self.__class__, self).write(ostream)
|
||||
ostream.write(tstream.buffer)
|
||||
|
||||
def validate(self):
|
||||
self.__validate()
|
||||
|
||||
def __validate(self):
|
||||
name = self.__class__.__name__
|
||||
msg = ErrorStrings.BAD_EXP_RECV
|
||||
|
||||
if self.application_namespace is not None:
|
||||
if self.application_data is None:
|
||||
member = 'application_data'
|
||||
raise ValueError(msg.format('{}.{}'.format(name, member),
|
||||
'value', 'not None', 'None'))
|
||||
else:
|
||||
member = 'application_namespace'
|
||||
exp_type = self.ApplicationNamespace
|
||||
if not isinstance(self.application_namespace, exp_type):
|
||||
rcv_type = type(self.application_namespace)
|
||||
raise TypeError(msg.format('{}.{}'.format(name, member),
|
||||
'type', exp_type, rcv_type))
|
||||
|
||||
if self.application_data is not None:
|
||||
if self.application_namespace is None:
|
||||
member = 'application_namespace'
|
||||
raise ValueError(msg.format('{}.{}'.format(name, member),
|
||||
'value', 'not None', 'None'))
|
||||
else:
|
||||
member = 'application_data'
|
||||
exp_type = self.ApplicationData
|
||||
if not isinstance(self.application_data, exp_type):
|
||||
rcv_type = type(self.application_data)
|
||||
raise TypeError(msg.format('{}.{}'.format(name, member),
|
||||
'type', exp_type, rcv_type))
|
||||
|
||||
@classmethod
|
||||
def create(cls, application_namespace, application_data):
|
||||
namespace = ApplicationSpecificInformation.\
|
||||
ApplicationNamespace(application_namespace)
|
||||
data = ApplicationSpecificInformation.\
|
||||
ApplicationData(application_data)
|
||||
return ApplicationSpecificInformation(application_namespace=namespace,
|
||||
application_data=data)
|
||||
|
||||
|
||||
# 3.37
|
||||
class ContactInformation(TextString):
|
||||
|
||||
def __init__(self, value=None):
|
||||
super(self.__class__,
|
||||
self).__init__(value, Tags.CONTACT_INFORMATION)
|
||||
|
||||
|
||||
# 3.39
|
||||
# TODO (peter-hamilton) A CustomAttribute TextString is not sufficient to
|
||||
# TODO (peter-hamilton) cover all potential custom attributes. This is a
|
||||
# TODO (peter-hamilton) temporary stopgap.
|
||||
class CustomAttribute(TextString):
|
||||
|
||||
def __init__(self, value=None):
|
||||
super(self.__class__,
|
||||
self).__init__(value, Tags.ATTRIBUTE_VALUE)
|
561
kmip/core/enums.py
Normal file
561
kmip/core/enums.py
Normal file
@ -0,0 +1,561 @@
|
||||
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
# In case of new content, remove the following line to enable flake8 tests
|
||||
# flake8: noqa
|
||||
|
||||
from enum import Enum
|
||||
|
||||
|
||||
class AttributeType(Enum):
|
||||
UNIQUE_IDENTIFIER = 'Unique Identifier'
|
||||
NAME = 'Name'
|
||||
OBJECT_TYPE = 'Object Type'
|
||||
CRYPTOGRAPHIC_ALGORITHM = 'Cryptographic Algorithm'
|
||||
CRYPTOGRAPHIC_LENGTH = 'Cryptographic Length'
|
||||
CRYPTOGRAPHIC_PARAMETERS = 'Cryptographic Parameters'
|
||||
CRYPTOGRAPHIC_DOMAIN_PARAMETERS = 'Cryptographic Domain Parameters'
|
||||
CERTIFICATE_TYPE = 'Certificate Type'
|
||||
CERTIFICATE_LENGTH = 'Certificate Length'
|
||||
X_509_CERTIFICATE_IDENTIFIER = 'X.509 Certificate Identifier'
|
||||
X_509_CERTIFICATE_SUBJECT = 'X.509 Certificate Subject'
|
||||
X_509_CERTIFICATE_ISSUER = 'X.509 Certificate Issuer'
|
||||
CERTIFICATE_IDENTIFIER = 'Certificate Identifier'
|
||||
CERTIFICATE_SUBJECT = 'Certificate Subject'
|
||||
CERTIFICATE_ISSUER = 'Certificate Issuer'
|
||||
DIGITAL_SIGNATURE_ALGORITHM = 'Digital Signature Algorithm'
|
||||
DIGEST = 'Digest'
|
||||
OPERATION_POLICY_NAME = 'Operation Policy Name'
|
||||
CRYPTOGRAPHIC_USAGE_MASK = 'Cryptographic Usage Mask'
|
||||
LEASE_TIME = 'Lease Time'
|
||||
USAGE_LIMITS = 'Usage Limits'
|
||||
STATE = 'State'
|
||||
INITIAL_DATE = 'Initial Date'
|
||||
ACTIVATION_DATE = 'Activation Date'
|
||||
PROCESS_START_DATE = 'Process Start Date'
|
||||
PROTECT_STOP_DATE = 'Protect Stop Date'
|
||||
DEACTIVATION_DATE = 'Deactivation Date'
|
||||
DESTROY_DATE = 'Destroy Date'
|
||||
COMPROMISE_OCCURRENCE_DATE = 'Compromise Occurrence Date'
|
||||
COMPROMISE_DATE = 'Compromise Date'
|
||||
REVOCATION_REASON = 'Revocation Reason'
|
||||
ARCHIVE_DATE = 'Archive Date'
|
||||
OBJECT_GROUP = 'Object Group'
|
||||
FRESH = 'Fresh'
|
||||
LINK = 'Link'
|
||||
APPLICATION_SPECIFIC_INFORMATION = 'Application Specific Information'
|
||||
CONTACT_INFORMATION = 'Contact Information'
|
||||
LAST_CHANGE_DATE = 'Last Change Date'
|
||||
CUSTOM_ATTRIBUTE = 'Custom Attribute'
|
||||
|
||||
|
||||
# 9.1.1.2
|
||||
class Types(Enum):
|
||||
DEFAULT = 0x00
|
||||
STRUCTURE = 0x01
|
||||
INTEGER = 0x02
|
||||
LONG_INTEGER = 0x03
|
||||
BIG_INTEGER = 0x04
|
||||
ENUMERATION = 0x05
|
||||
BOOLEAN = 0x06
|
||||
TEXT_STRING = 0x07
|
||||
BYTE_STRING = 0x08
|
||||
DATE_TIME = 0x09
|
||||
INTERVAL = 0x0A
|
||||
|
||||
|
||||
# 9.1.3.1
|
||||
class Tags(Enum):
|
||||
DEFAULT = 0x420000
|
||||
ACTIVATION_DATE = 0x420001
|
||||
APPLICATION_DATA = 0x420002
|
||||
APPLICATION_NAMESPACE = 0x420003
|
||||
APPLICATION_SPECIFIC_INFORMATION = 0x420004
|
||||
ARCHIVE_DATE = 0x420005
|
||||
ASYNCHRONOUS_CORRELATION_VALUE = 0x420006
|
||||
ASYNCHRONOUS_INDICATOR = 0x420007
|
||||
ATTRIBUTE = 0x420008
|
||||
ATTRIBUTE_INDEX = 0x420009
|
||||
ATTRIBUTE_NAME = 0x42000A
|
||||
ATTRIBUTE_VALUE = 0x42000B
|
||||
AUTHENTICATION = 0x42000C
|
||||
BATCH_COUNT = 0x42000D
|
||||
BATCH_ERROR_CONTINUATION_OPTION = 0x42000E
|
||||
BATCH_ITEM = 0x42000F
|
||||
BATCH_ORDER_OPTION = 0x420010
|
||||
BLOCK_CIPHER_MODE = 0x420011
|
||||
CANCELLATION_RESULT = 0x420012
|
||||
CERTIFICATE = 0x420013
|
||||
CERTIFICATE_IDENTIFIER = 0x420014 # DEPRECATED
|
||||
CERTIFICATE_ISSUER = 0x420015 # DEPRECATED
|
||||
CERTIFICATE_ISSUER_ALTERNATIVE_NAME = 0x420016 # DEPRECATED
|
||||
CERTIFICATE_ISSUER_DISTINGUISHED_NAME = 0x420017 # DEPRECATED
|
||||
CERTIFICATE_REQUEST = 0x420018
|
||||
CERTIFICATE_REQUEST_TYPE = 0x420019
|
||||
CERTIFICATE_SUBJECT = 0x42001A # DEPRECATED
|
||||
CERTIFICATE_SUBJECT_ALTERNATIVE_NAME = 0x42001B # DEPRECATED
|
||||
CERTIFICATE_SUBJECT_DISTINGUISHED_NAME = 0x42001C # DEPRECATED
|
||||
CERTIFICATE_TYPE = 0x42001D
|
||||
CERTIFICATE_VALUE = 0x42001E
|
||||
COMMON_TEMPLATE_ATTRIBUTE = 0x42001F
|
||||
COMPROMISE_DATE = 0x420020
|
||||
COMPROMISE_OCCURRENCE_DATE = 0x420021
|
||||
CONTACT_INFORMATION = 0x420022
|
||||
CREDENTIAL = 0x420023
|
||||
CREDENTIAL_TYPE = 0x420024
|
||||
CREDENTIAL_VALUE = 0x420025
|
||||
CRITICALITY_INDICATOR = 0x420026
|
||||
CRT_COEFFICIENT = 0x420027
|
||||
CRYPTOGRAPHIC_ALGORITHM = 0x420028
|
||||
CRYPTOGRAPHIC_DOMAIN_PARAMETERS = 0x420029
|
||||
CRYPTOGRAPHIC_LENGTH = 0x42002A
|
||||
CRYPTOGRAPHIC_PARAMETERS = 0x42002B
|
||||
CRYPTOGRAPHIC_USAGE_MASK = 0x42002C
|
||||
CUSTOM_ATTRIBUTE = 0x42002D
|
||||
D = 0x42002E
|
||||
DEACTIVATION_DATE = 0x42002F
|
||||
DERIVATION_DATA = 0x420030
|
||||
DERIVATION_METHOD = 0x420031
|
||||
DERIVATION_PARAMETERS = 0x420032
|
||||
DESTROY_DATE = 0x420033
|
||||
DIGEST = 0x420034
|
||||
DIGEST_VALUE = 0x420035
|
||||
ENCRYPTION_KEY_INFORMATION = 0x420036
|
||||
G = 0x420037
|
||||
HASHING_ALGORITHM = 0x420038
|
||||
INITIAL_DATE = 0x420039
|
||||
INITIALIZATION_VECTOR = 0x42003A
|
||||
ISSUER = 0x42003B # DEPRECATED
|
||||
ITERATION_COUNT = 0x42003C
|
||||
IV_COUNTER_NONCE = 0x42003D
|
||||
J = 0x42003E
|
||||
KEY = 0x42003F
|
||||
KEY_BLOCK = 0x420040
|
||||
KEY_COMPRESSION_TYPE = 0x420041
|
||||
KEY_FORMAT_TYPE = 0x420042
|
||||
KEY_MATERIAL = 0x420043
|
||||
KEY_PART_IDENTIFIER = 0x420044
|
||||
KEY_VALUE = 0x420045
|
||||
KEY_WRAPPING_DATA = 0x420046
|
||||
KEY_WRAPPING_SPECIFICATION = 0x420047
|
||||
LAST_CHANGE_DATE = 0x420048
|
||||
LEASE_TIME = 0x420049
|
||||
LINK = 0x42004A
|
||||
LINK_TYPE = 0x42004B
|
||||
LINKED_OBJECT_IDENTIFIER = 0x42004C
|
||||
MAC_SIGNATURE = 0x42004D
|
||||
MAC_SIGNATURE_KEY_INFORMATION = 0x42004E
|
||||
MAXIMUM_ITEMS = 0x42004F
|
||||
MAXIMUM_RESPONSE_SIZE = 0x420050
|
||||
MESSAGE_EXTENSION = 0x420051
|
||||
MODULUS = 0x420052
|
||||
NAME = 0x420053
|
||||
NAME_TYPE = 0x420054
|
||||
NAME_VALUE = 0x420055
|
||||
OBJECT_GROUP = 0x420056
|
||||
OBJECT_TYPE = 0x420057
|
||||
OFFSET = 0x420058
|
||||
OPAQUE_DATA_TYPE = 0x420059
|
||||
OPAQUE_DATA_VALUE = 0x42005A
|
||||
OPAQUE_OBJECT = 0x42005B
|
||||
OPERATION = 0x42005C
|
||||
OPERATION_POLICY_NAME = 0x42005D
|
||||
P = 0x42005E
|
||||
PADDING_METHOD = 0x42005F
|
||||
PRIME_EXPONENT_P = 0x420060
|
||||
PRIME_EXPONENT_Q = 0x420061
|
||||
PRIME_FIELD_SIZE = 0x420062
|
||||
PRIVATE_EXPONENT = 0x420063
|
||||
PRIVATE_KEY = 0x420064
|
||||
PRIVATE_KEY_TEMPLATE_ATTRIBUTE = 0x420065
|
||||
PRIVATE_KEY_UNIQUE_IDENTIFIER = 0x420066
|
||||
PROCESS_START_DATE = 0x420067
|
||||
PROTECT_STOP_DATE = 0x420068
|
||||
PROTOCOL_VERSION = 0x420069
|
||||
PROTOCOL_VERSION_MAJOR = 0x42006A
|
||||
PROTOCOL_VERSION_MINOR = 0x42006B
|
||||
PUBLIC_EXPONENT = 0x42006C
|
||||
PUBLIC_KEY = 0x42006D
|
||||
PUBLIC_KEY_TEMPLATE_ATTRIBUTE = 0x42006E
|
||||
PUBLIC_KEY_UNIQUE_IDENTIFIER = 0x42006F
|
||||
PUT_FUNCTION = 0x420070
|
||||
Q = 0x420071
|
||||
Q_STRING = 0x420072
|
||||
QLENGTH = 0x420073
|
||||
QUERY_FUNCTION = 0x420074
|
||||
RECOMMENDED_CURVE = 0x420075
|
||||
REPLACED_UNIQUE_IDENTIFIER = 0x420076
|
||||
REQUEST_BATCH_ITEM = 0x42000F
|
||||
REQUEST_HEADER = 0x420077
|
||||
REQUEST_MESSAGE = 0x420078
|
||||
REQUEST_PAYLOAD = 0x420079
|
||||
RESPONSE_BATCH_ITEM = 0x42000F
|
||||
RESPONSE_HEADER = 0x42007A
|
||||
RESPONSE_MESSAGE = 0x42007B
|
||||
RESPONSE_PAYLOAD = 0x42007C
|
||||
RESULT_MESSAGE = 0x42007D
|
||||
RESULT_REASON = 0x42007E
|
||||
RESULT_STATUS = 0x42007F
|
||||
REVOCATION_MESSAGE = 0x420080
|
||||
REVOCATION_REASON = 0x420081
|
||||
REVOCATION_REASON_CODE = 0x420082
|
||||
KEY_ROLE_TYPE = 0x420083
|
||||
SALT = 0x420084
|
||||
SECRET_DATA = 0x420085
|
||||
SECRET_DATA_TYPE = 0x420086
|
||||
SERIAL_NUMBER = 0x420087 # DEPRECATED
|
||||
SERVER_INFORMATION = 0x420088
|
||||
SPLIT_KEY = 0x420089
|
||||
SPLIT_KEY_METHOD = 0x42008A
|
||||
SPLIT_KEY_PARTS = 0x42008B
|
||||
SPLIT_KEY_THRESHOLD = 0x42008C
|
||||
STATE = 0x42008D
|
||||
STORAGE_STATUS_MASK = 0x42008E
|
||||
SYMMETRIC_KEY = 0x42008F
|
||||
TEMPLATE = 0x420090
|
||||
TEMPLATE_ATTRIBUTE = 0x420091
|
||||
TIME_STAMP = 0x420092
|
||||
UNIQUE_BATCH_ITEM_ID = 0x420093
|
||||
UNIQUE_IDENTIFIER = 0x420094
|
||||
USAGE_LIMITS = 0x420095
|
||||
USAGE_LIMITS_COUNT = 0x420096
|
||||
USAGE_LIMITS_TOTAL = 0x420097
|
||||
USAGE_LIMITS_UNIT = 0x420098
|
||||
USERNAME = 0x420099
|
||||
VALIDITY_DATE = 0x42009A
|
||||
VALIDITY_INDICATOR = 0x42009B
|
||||
VENDOR_EXTENSION = 0x42009C
|
||||
VENDOR_IDENTIFICATION = 0x42009D
|
||||
WRAPPING_METHOD = 0x42009E
|
||||
X = 0x42009F
|
||||
Y = 0x4200A0
|
||||
PASSWORD = 0x4200A1
|
||||
DEVICE_IDENTIFIER = 0x4200A2
|
||||
ENCODING_OPTION = 0x4200A3
|
||||
EXTENSION_INFORMATION = 0x4200A4
|
||||
EXTENSION_NAME = 0x4200A5
|
||||
EXTENSION_TAG = 0x4200A6
|
||||
EXTENSION_TYPE = 0x4200A7
|
||||
FRESH = 0x4200A8
|
||||
MACHINE_IDENTIFIER = 0x4200A9
|
||||
MEDIA_IDENTIFIER = 0x4200AA
|
||||
NETWORK_IDENTIFIER = 0x4200AB
|
||||
OBJECT_GROUP_MEMBER = 0x4200AC
|
||||
CERTIFICATE_LENGTH = 0x4200AD
|
||||
DIGITAL_SIGNATURE_ALGORITHM = 0x4200AE
|
||||
CERTIFICATE_SERIAL_NUMBER = 0x4200AF
|
||||
DEVICE_SERIAL_NUMBER = 0x4200B0
|
||||
ISSUER_ALTERNATIVE_NAME = 0x4200B1
|
||||
ISSUER_DISTINGUISHED_NAME = 0x4200B2
|
||||
SUBJECT_ALTERNATIVE_NAME = 0x4200B3
|
||||
SUBJECT_DISTINGUISHED_NAME = 0x4200B4
|
||||
X_509_CERTIFICATE_IDENTIFER = 0x4200B5
|
||||
X_509_CERTIFICATE_ISSUER = 0x4200B6
|
||||
X_509_CERTIFICATE_SUBJECT = 0x4200B7
|
||||
|
||||
|
||||
# 9.1.3.2.1
|
||||
class CredentialType(Enum):
|
||||
USERNAME_AND_PASSWORD = 0x00000001
|
||||
DEVICE = 0x00000002
|
||||
|
||||
|
||||
# 9.1.3.2.2
|
||||
class KeyCompressionType(Enum):
|
||||
EC_PUBLIC_KEY_TYPE_UNCOMPRESSED = 0x00000001
|
||||
EC_PUBLIC_KEY_TYPE_X9_62_COMPRESSED_PRIME = 0x00000002
|
||||
EC_PUBLIC_KEY_TYPE_X9_62_COMPRESSED_CHAR2 = 0x00000003
|
||||
EC_PUBLIC_KEY_TYPE_X9_62_HYBRID = 0x00000004
|
||||
|
||||
|
||||
# 9.1.3.2.3
|
||||
class KeyFormatType(Enum):
|
||||
RAW = 0x00000001
|
||||
OPAQUE = 0x00000002
|
||||
PKCS_1 = 0x00000003
|
||||
PKCS_8 = 0x00000004
|
||||
X_509 = 0x00000005
|
||||
EC_PRIVATE_KEY = 0x00000006
|
||||
TRANSPARENT_SYMMETRIC_KEY = 0x00000007
|
||||
TRANSPARENT_DSA_PRIVATE_KEY = 0x00000008
|
||||
TRANSPARENT_DSA_PUBLIC_KEY = 0x00000009
|
||||
TRANSPARENT_RSA_PRIVATE_KEY = 0x0000000A
|
||||
TRANSPARENT_RSA_PUBLIC_KEY = 0x0000000B
|
||||
TRANSPARENT_DH_PRIVATE_KEY = 0x0000000C
|
||||
TRANSPARENT_DH_PUBLIC_KEY = 0x0000000D
|
||||
TRANSPARENT_ECDSA_PRIVATE_KEY = 0x0000000E
|
||||
TRANSPARENT_ECDSA_PUBLIC_KEY = 0x0000000F
|
||||
TRANSPARENT_ECDH_PRIVATE_KEY = 0x00000010
|
||||
TRANSPARENT_ECDH_PUBLIC_KEY = 0x00000011
|
||||
TRANSPARENT_ECMQV_PRIVATE_KEY = 0x00000012
|
||||
TRANSPARENT_ECMQV_PUBLIC_KEY = 0x00000013
|
||||
|
||||
|
||||
# 9.1.3.2.4
|
||||
class WrappingMethod(Enum):
|
||||
ENCRYPT = 0x00000001
|
||||
MAC_SIGN = 0x00000002
|
||||
ENCRYPT_THEN_MAC_SIGN = 0x00000003
|
||||
MAC_SIGN_THEN_ENCRYPT = 0x00000004
|
||||
TR_31 = 0x00000005
|
||||
|
||||
|
||||
# 9.1.3.2.6
|
||||
class CertificateType(Enum):
|
||||
X_509 = 0x00000001
|
||||
PGP = 0x00000002
|
||||
|
||||
|
||||
# 9.1.3.2.8
|
||||
class SplitKeyMethod(Enum):
|
||||
XOR = 0x00000001
|
||||
POLYNOMIAL_SHARING_GF = 0x00000002
|
||||
POLYNOMIAL_SHARING_PRIME_FIELD = 0x00000003
|
||||
|
||||
|
||||
# 9.1.3.2.9
|
||||
class SecretDataType(Enum):
|
||||
PASSWORD = 0x00000001
|
||||
SEED = 0x00000002
|
||||
|
||||
|
||||
# 9.1.3.2.10
|
||||
class OpaqueDataType(Enum):
|
||||
pass
|
||||
|
||||
|
||||
# 9.1.3.2.11
|
||||
class NameType(Enum):
|
||||
UNINTERPRETED_TEXT_STRING = 0x00000001
|
||||
URI = 0x00000002
|
||||
|
||||
|
||||
# 9.1.3.2.12
|
||||
class ObjectType(Enum):
|
||||
CERTIFICATE = 0x00000001
|
||||
SYMMETRIC_KEY = 0x00000002
|
||||
PUBLIC_KEY = 0x00000003
|
||||
PRIVATE_KEY = 0x00000004
|
||||
SPLIT_KEY = 0x00000005
|
||||
TEMPLATE = 0x00000006
|
||||
SECRET_DATA = 0x00000007
|
||||
OPAQUE_DATA = 0x00000008
|
||||
|
||||
|
||||
# 9.1.3.2.13
|
||||
class CryptographicAlgorithm(Enum):
|
||||
DES = 0x00000001
|
||||
TRIPLE_DES = 0x00000002 # '3DES' is invalid syntax
|
||||
AES = 0x00000003
|
||||
RSA = 0x00000004
|
||||
DSA = 0x00000005
|
||||
ECDSA = 0x00000006
|
||||
HMAC_SHA1 = 0x00000007
|
||||
HMAC_SHA224 = 0x00000008
|
||||
HMAC_SHA256 = 0x00000009
|
||||
HMAC_SHA384 = 0x0000000A
|
||||
HMAC_SHA512 = 0x0000000B
|
||||
HMAC_MD5 = 0x0000000C
|
||||
DH = 0x0000000D
|
||||
ECDH = 0x0000000E
|
||||
ECMQV = 0x0000000F
|
||||
BLOWFISH = 0x00000010
|
||||
CAMELLIA = 0x00000011
|
||||
CAST5 = 0x00000012
|
||||
IDEA = 0x00000013
|
||||
MARS = 0x00000014
|
||||
RC2 = 0x00000015
|
||||
RC4 = 0x00000016
|
||||
RC5 = 0x00000017
|
||||
SKIPJACK = 0x00000018
|
||||
TWOFISH = 0x00000019
|
||||
|
||||
|
||||
# 9.1.3.2.14
|
||||
class BlockCipherMode(Enum):
|
||||
CBC = 0x00000001
|
||||
ECB = 0x00000002
|
||||
PCBC = 0x00000003
|
||||
CFB = 0x00000004
|
||||
OFB = 0x00000005
|
||||
CTR = 0x00000006
|
||||
CMAC = 0x00000007
|
||||
CCM = 0x00000008
|
||||
GCM = 0x00000009
|
||||
CBC_MAC = 0x0000000A
|
||||
XTS = 0x0000000B
|
||||
AES_KEY_WRAP_PADDING = 0x0000000C
|
||||
NIST_KEY_WRAP = 0x0000000D
|
||||
X9_102_AESKW = 0x0000000E
|
||||
X9_102_TDKW = 0x0000000F
|
||||
X9_102_AKW1 = 0x00000010
|
||||
X9_102_AKW2 = 0x00000011
|
||||
|
||||
|
||||
# 9.1.3.2.15
|
||||
class PaddingMethod(Enum):
|
||||
NONE = 0x00000001
|
||||
OAEP = 0x00000002
|
||||
PKCS5 = 0x00000003
|
||||
SSL3 = 0x00000004
|
||||
ZEROS = 0x00000005
|
||||
ANSI_X9_23 = 0x00000006
|
||||
ISO_10126 = 0x00000007
|
||||
PKCS1_V_1_5 = 0x00000008
|
||||
X9_31 = 0x00000009
|
||||
PSS = 0x0000000A
|
||||
|
||||
|
||||
# 9.1.3.2.16
|
||||
class HashingAlgorithm(Enum):
|
||||
MD2 = 0x00000001
|
||||
MD4 = 0x00000002
|
||||
MD5 = 0x00000003
|
||||
SHA_1 = 0x00000004
|
||||
SHA_224 = 0x00000005
|
||||
SHA_256 = 0x00000006
|
||||
SHA_384 = 0x00000007
|
||||
SHA_512 = 0x00000008
|
||||
RIPEMD_160 = 0x00000009
|
||||
TIGER = 0x0000000A
|
||||
WHIRLPOOL = 0x0000000B
|
||||
|
||||
|
||||
# 9.1.3.2.17
|
||||
class KeyRoleType(Enum):
|
||||
BDK = 0x00000001
|
||||
CVK = 0x00000002
|
||||
DEK = 0x00000003
|
||||
MKAC = 0x00000004
|
||||
MKSMC = 0x00000005
|
||||
MKSMI = 0x00000006
|
||||
MKDAC = 0x00000007
|
||||
MKDN = 0x00000008
|
||||
MKCP = 0x00000009
|
||||
MKOTH = 0x0000000A
|
||||
KEK = 0x0000000B
|
||||
MAC_16609 = 0x0000000C
|
||||
MAC_97971 = 0x0000000D
|
||||
MAC_97972 = 0x0000000E
|
||||
MAC_97973 = 0x0000000F
|
||||
MAC_97974 = 0x00000010
|
||||
MAC_97975 = 0x00000011
|
||||
ZPK = 0x00000012
|
||||
PVKIBM = 0x00000013
|
||||
PVKPVV = 0x00000014
|
||||
PVKOTH = 0x00000015
|
||||
|
||||
|
||||
# 9.1.3.2.27
|
||||
class Operation(Enum):
|
||||
CREATE = 0x00000001
|
||||
CREATE_KEY_PAIR = 0x00000002
|
||||
REGISTER = 0x00000003
|
||||
REKEY = 0x00000004
|
||||
DERIVE_KEY = 0x00000005
|
||||
CERTIFY = 0x00000006
|
||||
RECERTIFY = 0x00000007
|
||||
LOCATE = 0x00000008
|
||||
CHECK = 0x00000009
|
||||
GET = 0x0000000A
|
||||
GET_ATTRIBUTES = 0x0000000B
|
||||
GET_ATTRIBUTE_LIST = 0x0000000C
|
||||
ADD_ATTRIBUTE = 0x0000000D
|
||||
MODIFY_ATTRIBUTE = 0x0000000E
|
||||
DELETE_ATTRIBUTE = 0x0000000F
|
||||
OBTAIN_LEASE = 0x00000010
|
||||
GET_USAGE_ALLOCATION = 0x00000011
|
||||
ACTIVATE = 0x00000012
|
||||
REVOKE = 0x00000013
|
||||
DESTROY = 0x00000014
|
||||
ARCHIVE = 0x00000015
|
||||
RECOVER = 0x00000016
|
||||
VALIDATE = 0x00000017
|
||||
QUERY = 0x00000018
|
||||
CANCEL = 0x00000019
|
||||
POLL = 0x0000001A
|
||||
NOTIFY = 0x0000001B
|
||||
PUT = 0x0000001C
|
||||
REKEY_KEY_PAIR = 0x0000001D
|
||||
DISCOVER_VERSIONS = 0x0000001E
|
||||
|
||||
|
||||
# 9.1.3.2.28
|
||||
class ResultStatus(Enum):
|
||||
SUCCESS = 0x00000000
|
||||
OPERATION_FAILED = 0x00000001
|
||||
OPERATION_PENDING = 0x00000002
|
||||
OPERATION_UNDONE = 0x00000003
|
||||
|
||||
|
||||
# 9.1.3.2.29
|
||||
class ResultReason(Enum):
|
||||
ITEM_NOT_FOUND = 0x00000001
|
||||
RESPONSE_TOO_LARGE = 0x00000002
|
||||
AUTHENTICATION_NOT_SUCCESSFUL = 0x00000003
|
||||
INVALID_MESSAGE = 0x00000004
|
||||
OPERATION_NOT_SUPPORTED = 0x00000005
|
||||
MISSING_DATA = 0x00000006
|
||||
INVALID_FIELD = 0x00000007
|
||||
FEATURE_NOT_SUPPORTED = 0x00000008
|
||||
OPERATION_CANCELED_BY_REQUESTER = 0x00000009
|
||||
CRYPTOGRAPHIC_FAILURE = 0x0000000A
|
||||
ILLEGAL_OPERATION = 0x0000000B
|
||||
PERMISSION_DENIED = 0x0000000C
|
||||
OBJECT_ARCHIVED = 0x0000000D
|
||||
INDEX_OUT_OF_BOUNDS = 0x0000000E
|
||||
APPLICATION_NAMESPACE_NOT_SUPPORTED = 0x0000000F
|
||||
KEY_FORMAT_TYPE_NOT_SUPPORTED = 0x00000010
|
||||
KEY_COMPRESSION_TYPE_NOT_SUPPORTED = 0x00000011
|
||||
ENCODING_OPTION_ERROR = 0x00000012
|
||||
GENERAL_FAILURE = 0x00000100
|
||||
|
||||
|
||||
# 9.1.3.2.30
|
||||
class BatchErrorContinuationOption(Enum):
|
||||
CONTINUE = 0x00000001
|
||||
STOP = 0x00000002
|
||||
UNDO = 0x00000003
|
||||
|
||||
|
||||
# 9.1.3.2.32
|
||||
class EncodingOption(Enum):
|
||||
NO_ENCODING = 0x00000001
|
||||
TTLV_ENCODING = 0x00000002
|
||||
|
||||
|
||||
# 9.1.3.3
|
||||
# 9.1.3.3.1
|
||||
class CryptographicUsageMask(Enum):
|
||||
SIGN = 0x00000001
|
||||
VERIFY = 0x00000002
|
||||
ENCRYPT = 0x00000004
|
||||
DECRYPT = 0x00000008
|
||||
WRAP_KEY = 0x00000010
|
||||
UNWRAP_KEY = 0x00000020
|
||||
EXPORT = 0x00000040
|
||||
MAC_GENERATE = 0x00000080
|
||||
MAC_VERIFY = 0x00000100
|
||||
DERIVE_KEY = 0x00000200
|
||||
CONTENT_COMMITMENT = 0x00000400
|
||||
KEY_AGREEMENT = 0x00000800
|
||||
CERTIFICATE_SIGN = 0x00001000
|
||||
CRL_SIGN = 0x00002000
|
||||
GENERATE_CRYPTOGRAM = 0x00004000
|
||||
VALIDATE_CRYPTOGRAM = 0x00008000
|
||||
TRANSLATE_ENCRYPT = 0x00010000
|
||||
TRANSLATE_DECRYPT = 0x00020000
|
||||
TRANSLATE_WRAP = 0x00040000
|
||||
TRANSLATE_UNWRAP = 0x00080000
|
130
kmip/core/errors.py
Normal file
130
kmip/core/errors.py
Normal file
@ -0,0 +1,130 @@
|
||||
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
|
||||
class ErrorStrings:
|
||||
BAD_EXP_RECV = "Bad {0} {1}: expected {2}, received {3}"
|
||||
BAD_ENCODING = "Bad {0} {1}: encoding mismatch"
|
||||
|
||||
|
||||
class BaseError(Exception):
|
||||
"""Base class for exceptions defined in this module."""
|
||||
|
||||
def __init__(self, args):
|
||||
[setattr(self, k, v) for k, v in args.iteritems() if k is not 'self']
|
||||
|
||||
|
||||
class KMIPServerError(BaseError):
|
||||
"""Base Exception for KMIP server errors."""
|
||||
def __init__(self, args):
|
||||
super(KMIPServerError, self).__init__(args)
|
||||
|
||||
|
||||
class KMIPServerZombieError(KMIPServerError):
|
||||
"""KMIP server error for hung and persistent live KMIP servers."""
|
||||
def __init__(self, pid):
|
||||
message = 'KMIP server alive after termination: PID {0}'.format(pid)
|
||||
super(KMIPServerZombieError, self).__init__({'message': message})
|
||||
|
||||
def __str__(self):
|
||||
return self.message
|
||||
|
||||
|
||||
class KMIPServerSuicideError(KMIPServerError):
|
||||
"""KMIP server error for prematurely dead KMIP servers."""
|
||||
def __init__(self, pid):
|
||||
message = 'KMIP server dead prematurely: PID {0}'.format(pid)
|
||||
super(KMIPServerSuicideError, self).__init__({'message': message})
|
||||
|
||||
def __str__(self):
|
||||
return self.message
|
||||
|
||||
|
||||
class InitError(BaseError):
|
||||
"""Exception thrown for bad initializations."""
|
||||
def __init__(self, cls, exp, recv):
|
||||
super(InitError, self).__init__(locals())
|
||||
|
||||
def __str__(self):
|
||||
msg = "Tried to initialize {0} instance with bad type: "
|
||||
msg += "expected {1}, received {2}"
|
||||
return msg.format(self.cls, self.exp, self.recv)
|
||||
|
||||
|
||||
class WriteValueError(BaseError):
|
||||
def __init__(self, cls, attr, value):
|
||||
super(WriteValueError, self).__init__(locals())
|
||||
|
||||
def __str__(self):
|
||||
msg = "Tried to write {0}.{1} with invalid value: {2}"
|
||||
return msg.format(self.cls, self.attr, self.value)
|
||||
|
||||
|
||||
class WriteTypeError(BaseError):
|
||||
def __init__(self, cls, attr, value):
|
||||
super(WriteTypeError, self).__init__(locals())
|
||||
|
||||
def __str__(self):
|
||||
msg = "Tried to write {0}.{1} with invalid type: {2}"
|
||||
return msg.format(self.cls, self.attr, self.value)
|
||||
|
||||
|
||||
class WriteOverflowError(BaseError):
|
||||
def __init__(self, cls, attr, exp, recv):
|
||||
super(WriteOverflowError, self).__init__(locals())
|
||||
|
||||
def __str__(self):
|
||||
msg = "Tried to write {0}.{1} with too many bytes: "
|
||||
msg += "expected {2}, received {3}"
|
||||
return msg.format(self.cls, self.attr, self.exp, self.recv)
|
||||
|
||||
|
||||
class ReadValueError(BaseError):
|
||||
def __init__(self, cls, attr, exp, recv):
|
||||
super(ReadValueError, self).__init__(locals())
|
||||
|
||||
def __str__(self):
|
||||
msg = "Tried to read {0}.{1}: expected {2}, received {3}"
|
||||
return msg.format(self.cls, self.attr, self.exp, self.recv)
|
||||
|
||||
|
||||
class InvalidLengthError(ValueError):
|
||||
def __init__(self, cls, exp, recv):
|
||||
msg = "Invalid length read for {0}: expected {1}, received {2}"
|
||||
super(InvalidLengthError, self).__init__(msg.format(cls, exp, recv))
|
||||
|
||||
|
||||
class StreamNotEmptyError(BaseError):
|
||||
def __init__(self, cls, extra):
|
||||
super(StreamNotEmptyError, self).__init__(locals())
|
||||
|
||||
def __str__(self):
|
||||
msg = "Invalid length used to read {0}, bytes remaining: {1}"
|
||||
return msg.format(self.cls, self.extra)
|
||||
|
||||
|
||||
class StateTypeError(TypeError):
|
||||
def __init__(self, cls, exp, recv):
|
||||
msg = "Tried to initialize {0} instance with bad type: "
|
||||
msg += "expected {1}, received {2}"
|
||||
super(StateTypeError, self).__init__(msg.format(cls, exp, recv))
|
||||
|
||||
|
||||
class StateOverflowError(ValueError):
|
||||
def __init__(self, cls, attr, exp, recv):
|
||||
msg = "Tried to write {0}.{1} with too many bytes: "
|
||||
msg += "expected {2}, received {3}"
|
||||
super(StateOverflowError, self).__init__(msg.format(cls, attr, exp,
|
||||
recv))
|
14
kmip/core/factories/__init__.py
Normal file
14
kmip/core/factories/__init__.py
Normal file
@ -0,0 +1,14 @@
|
||||
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
290
kmip/core/factories/attribute_values.py
Normal file
290
kmip/core/factories/attribute_values.py
Normal file
@ -0,0 +1,290 @@
|
||||
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from kmip.core.enums import AttributeType
|
||||
|
||||
from kmip.core.attributes import ApplicationSpecificInformation
|
||||
from kmip.core.attributes import ContactInformation
|
||||
from kmip.core.attributes import CryptographicAlgorithm
|
||||
from kmip.core.attributes import CryptographicLength
|
||||
from kmip.core.attributes import CryptographicUsageMask
|
||||
from kmip.core.attributes import CustomAttribute
|
||||
from kmip.core.attributes import Name
|
||||
from kmip.core.attributes import ObjectGroup
|
||||
from kmip.core.attributes import UniqueIdentifier
|
||||
|
||||
from kmip.core import utils
|
||||
|
||||
|
||||
class AttributeValueFactory(object):
|
||||
|
||||
def create_attribute_value(self, name, value):
|
||||
# Switch on the name of the attribute
|
||||
if name is AttributeType.UNIQUE_IDENTIFIER:
|
||||
value = self._create_unique_identifier(value)
|
||||
elif name is AttributeType.NAME:
|
||||
value = self._create_name(value)
|
||||
elif name is AttributeType.OBJECT_TYPE:
|
||||
value = self._create_object_type(value)
|
||||
elif name is AttributeType.CRYPTOGRAPHIC_ALGORITHM:
|
||||
value = self._create_cryptographic_algorithm(value)
|
||||
elif name is AttributeType.CRYPTOGRAPHIC_LENGTH:
|
||||
value = self._create_cryptographic_length(value)
|
||||
elif name is AttributeType.CRYPTOGRAPHIC_PARAMETERS:
|
||||
value = self._create_cryptographic_parameters(value)
|
||||
elif name is AttributeType.CRYPTOGRAPHIC_DOMAIN_PARAMETERS:
|
||||
value = self._create_cryptographic_domain_parameters(value)
|
||||
elif name is AttributeType.CERTIFICATE_TYPE:
|
||||
value = self._create_certificate_type(value)
|
||||
elif name is AttributeType.CERTIFICATE_LENGTH:
|
||||
value = self._create_certificate_length(value)
|
||||
elif name is AttributeType.X_509_CERTIFICATE_IDENTIFIER:
|
||||
value = self._create_x_509_certificate_identifier(value)
|
||||
elif name is AttributeType.X_509_CERTIFICATE_SUBJECT:
|
||||
value = self._create_x_509_certificate_subject(value)
|
||||
elif name is AttributeType.X_509_CERTIFICATE_ISSUER:
|
||||
value = self._create_x_509_certificate_issuer(value)
|
||||
elif name is AttributeType.CERTIFICATE_IDENTIFIER:
|
||||
value = self._create_certificate_identifier(value)
|
||||
elif name is AttributeType.CERTIFICATE_SUBJECT:
|
||||
value = self._create_certificate_subject(value)
|
||||
elif name is AttributeType.CERTIFICATE_ISSUER:
|
||||
value = self._create_certificate_issuer(value)
|
||||
elif name is AttributeType.DIGITAL_SIGNATURE_ALGORITHM:
|
||||
value = self._create_digital_signature_algorithm(value)
|
||||
elif name is AttributeType.DIGEST:
|
||||
value = self._create_digest(value)
|
||||
elif name is AttributeType.OPERATION_POLICY_NAME:
|
||||
value = self._create_operation_policy_name(value)
|
||||
elif name is AttributeType.CRYPTOGRAPHIC_USAGE_MASK:
|
||||
value = self._create_cryptographic_usage_mask(value)
|
||||
elif name is AttributeType.LEASE_TIME:
|
||||
value = self._create_lease_time(value)
|
||||
elif name is AttributeType.USAGE_LIMITS:
|
||||
value = self._create_usage_limits(value)
|
||||
elif name is AttributeType.STATE:
|
||||
value = self._create_state(value)
|
||||
elif name is AttributeType.INITIAL_DATE:
|
||||
value = self._create_initial_date(value)
|
||||
elif name is AttributeType.ACTIVATION_DATE:
|
||||
value = self._create_activation_date(value)
|
||||
elif name is AttributeType.PROCESS_START_DATE:
|
||||
value = self._create_process_start_date(value)
|
||||
elif name is AttributeType.PROTECT_STOP_DATE:
|
||||
value = self._create_protect_stop_date(value)
|
||||
elif name is AttributeType.DEACTIVATION_DATE:
|
||||
value = self._create_deactivation_date(value)
|
||||
elif name is AttributeType.DESTROY_DATE:
|
||||
value = self._create_destroy_date(value)
|
||||
elif name is AttributeType.COMPROMISE_OCCURRENCE_DATE:
|
||||
value = self._create_compromise_occurrence_date(value)
|
||||
elif name is AttributeType.COMPROMISE_DATE:
|
||||
value = self._create_compromise_date(value)
|
||||
elif name is AttributeType.REVOCATION_REASON:
|
||||
value = self._create_revocation_reason(value)
|
||||
elif name is AttributeType.ARCHIVE_DATE:
|
||||
value = self._create_archive_date(value)
|
||||
elif name is AttributeType.OBJECT_GROUP:
|
||||
value = self._create_object_group(value)
|
||||
elif name is AttributeType.FRESH:
|
||||
value = self._create_fresh(value)
|
||||
elif name is AttributeType.LINK:
|
||||
value = self._create_link(value)
|
||||
elif name is AttributeType.APPLICATION_SPECIFIC_INFORMATION:
|
||||
value = self._create_application_specific_information(value)
|
||||
elif name is AttributeType.CONTACT_INFORMATION:
|
||||
value = self._create_contact_information(value)
|
||||
elif name is AttributeType.LAST_CHANGE_DATE:
|
||||
value = self._create_last_change_date(value)
|
||||
elif name is AttributeType.CUSTOM_ATTRIBUTE:
|
||||
value = self._create_custom_attribute(value)
|
||||
else:
|
||||
if not isinstance(name, str):
|
||||
raise ValueError('Unrecognized attribute type: '
|
||||
'{}'.format(name))
|
||||
elif name.startswith('x-'):
|
||||
# Custom attribute indicated
|
||||
value = self._create_custom_attribute(value)
|
||||
|
||||
return value
|
||||
|
||||
def _create_unique_identifier(self, uuid):
|
||||
return UniqueIdentifier(uuid)
|
||||
|
||||
def _create_name(self, name):
|
||||
if name is not None:
|
||||
name_value = name.get('name_value')
|
||||
name_type = name.get('name_type')
|
||||
|
||||
return Name.create(name_value, name_type)
|
||||
else:
|
||||
return Name()
|
||||
|
||||
def _create_object_type(self, obj):
|
||||
raise NotImplementedError()
|
||||
|
||||
def _create_cryptographic_algorithm(self, alg):
|
||||
return CryptographicAlgorithm(alg)
|
||||
|
||||
def _create_cryptographic_length(self, length):
|
||||
if length is not None and not isinstance(length, int):
|
||||
msg = utils.build_er_error(CryptographicLength,
|
||||
'constructor argument type', int,
|
||||
type(length))
|
||||
raise TypeError(msg)
|
||||
|
||||
return CryptographicLength(length)
|
||||
|
||||
def _create_cryptographic_parameters(self, params):
|
||||
raise NotImplementedError()
|
||||
|
||||
def _create_cryptographic_domain_parameters(self, params):
|
||||
raise NotImplementedError()
|
||||
|
||||
def _create_certificate_type(self, cert):
|
||||
raise NotImplementedError()
|
||||
|
||||
def _create_certificate_length(self, length):
|
||||
raise NotImplementedError()
|
||||
|
||||
def _create_x_509_certificate_identifier(self, ident):
|
||||
raise NotImplementedError()
|
||||
|
||||
def _create_x_509_certificate_subject(self, subject):
|
||||
raise NotImplementedError()
|
||||
|
||||
def _create_x_509_certificate_issuer(self, issuer):
|
||||
raise NotImplementedError()
|
||||
|
||||
def _create_certificate_identifier(self, ident):
|
||||
raise NotImplementedError()
|
||||
|
||||
def _create_certificate_subject(self, subject):
|
||||
raise NotImplementedError()
|
||||
|
||||
def _create_certificate_issuer(self, issuer):
|
||||
raise NotImplementedError()
|
||||
|
||||
def _create_digital_signature_algorithm(self, alg):
|
||||
raise NotImplementedError()
|
||||
|
||||
def _create_digest(self, digest):
|
||||
raise NotImplementedError()
|
||||
|
||||
def _create_operation_policy_name(self, name):
|
||||
raise NotImplementedError()
|
||||
|
||||
def _create_cryptographic_usage_mask(self, flags):
|
||||
mask = None
|
||||
if flags is not None:
|
||||
mask = 0
|
||||
for flag in flags:
|
||||
mask |= flag.value
|
||||
|
||||
return CryptographicUsageMask(mask)
|
||||
|
||||
def _create_lease_time(self, lease):
|
||||
raise NotImplementedError()
|
||||
|
||||
def _create_usage_limits(self, limits):
|
||||
raise NotImplementedError()
|
||||
|
||||
def _create_state(self, state):
|
||||
raise NotImplementedError()
|
||||
|
||||
def _create_initial_date(self, date):
|
||||
raise NotImplementedError()
|
||||
|
||||
def _create_activation_date(self, date):
|
||||
raise NotImplementedError()
|
||||
|
||||
def _create_process_start_date(self, date):
|
||||
raise NotImplementedError()
|
||||
|
||||
def _create_protect_stop_date(self, date):
|
||||
raise NotImplementedError()
|
||||
|
||||
def _create_deactivation_date(self, date):
|
||||
raise NotImplementedError()
|
||||
|
||||
def _create_destroy_date(self, date):
|
||||
raise NotImplementedError()
|
||||
|
||||
def _create_compromise_occurrence_date(self, date):
|
||||
raise NotImplementedError()
|
||||
|
||||
def _create_compromise_date(self, date):
|
||||
raise NotImplementedError()
|
||||
|
||||
def _create_revocation_reason(self, reason):
|
||||
raise NotImplementedError()
|
||||
|
||||
def _create_archive_date(self, date):
|
||||
raise NotImplementedError()
|
||||
|
||||
def _create_object_group(self, group):
|
||||
if group is not None and not isinstance(group, str):
|
||||
msg = utils.build_er_error(ObjectGroup,
|
||||
'constructor argument type', str,
|
||||
type(group))
|
||||
raise TypeError(msg)
|
||||
|
||||
return ObjectGroup(group)
|
||||
|
||||
def _create_fresh(self, fresh):
|
||||
raise NotImplementedError()
|
||||
|
||||
def _create_link(self, link):
|
||||
raise NotImplementedError()
|
||||
|
||||
def _create_application_specific_information(self, info):
|
||||
if info is None:
|
||||
return ApplicationSpecificInformation()
|
||||
else:
|
||||
application_namespace = info.get('application_namespace')
|
||||
application_data = info.get('application_data')
|
||||
|
||||
if not isinstance(application_namespace, str):
|
||||
msg = utils.build_er_error(ApplicationSpecificInformation,
|
||||
'constructor argument type',
|
||||
str, type(application_namespace))
|
||||
raise TypeError(msg)
|
||||
|
||||
if not isinstance(application_data, str):
|
||||
msg = utils.build_er_error(ApplicationSpecificInformation,
|
||||
'constructor argument type',
|
||||
str, type(application_data))
|
||||
raise TypeError(msg)
|
||||
|
||||
return ApplicationSpecificInformation.create(application_namespace,
|
||||
application_data)
|
||||
|
||||
def _create_contact_information(self, info):
|
||||
if info is None:
|
||||
return ContactInformation()
|
||||
else:
|
||||
if not isinstance(info, str):
|
||||
msg = utils.build_er_error(ContactInformation,
|
||||
'constructor argument type', str,
|
||||
type(info))
|
||||
raise TypeError(msg)
|
||||
|
||||
return ContactInformation(info)
|
||||
|
||||
def _create_last_change_date(self, date):
|
||||
raise NotImplementedError()
|
||||
|
||||
def _create_custom_attribute(self, data):
|
||||
return CustomAttribute(data)
|
56
kmip/core/factories/attributes.py
Normal file
56
kmip/core/factories/attributes.py
Normal file
@ -0,0 +1,56 @@
|
||||
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from enum import Enum
|
||||
|
||||
from kmip.core.factories.attribute_values import AttributeValueFactory
|
||||
|
||||
from kmip.core.objects import Attribute
|
||||
|
||||
from kmip.core import utils
|
||||
|
||||
|
||||
class AttributeFactory(object):
|
||||
|
||||
def __init__(self):
|
||||
self.value_factory = AttributeValueFactory()
|
||||
|
||||
def _create_attribute(self, name, value, index):
|
||||
attribute_name = Attribute.AttributeName(name)
|
||||
|
||||
if index is None:
|
||||
return Attribute(attribute_name=attribute_name,
|
||||
attribute_value=value)
|
||||
else:
|
||||
attribute_index = Attribute.AttributeIndex(index)
|
||||
return Attribute(attribute_name=attribute_name,
|
||||
attribute_index=attribute_index,
|
||||
attribute_value=value)
|
||||
|
||||
def create_attribute(self, name, value, index=None):
|
||||
value = self.value_factory.create_attribute_value(name, value)
|
||||
|
||||
if isinstance(name, Enum):
|
||||
name = name.value
|
||||
elif isinstance(name, str):
|
||||
# Name is already a string, pass
|
||||
pass
|
||||
else:
|
||||
msg = utils.build_er_error(Attribute, 'name',
|
||||
'{} or {}'.format('Enum', 'str'),
|
||||
type(name))
|
||||
raise TypeError(msg)
|
||||
|
||||
return self._create_attribute(name, value, index)
|
72
kmip/core/factories/credentials.py
Normal file
72
kmip/core/factories/credentials.py
Normal file
@ -0,0 +1,72 @@
|
||||
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from kmip.core.enums import CredentialType
|
||||
|
||||
from kmip.core.objects import Credential
|
||||
|
||||
|
||||
class CredentialFactory(object):
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def _create_credential(self, credential_type, credential_value):
|
||||
credential_type = Credential.CredentialType(credential_type)
|
||||
return Credential(credential_type=credential_type,
|
||||
credential_value=credential_value)
|
||||
|
||||
def create_credential(self, cred_type, value):
|
||||
# Switch on the type of the credential
|
||||
if cred_type is CredentialType.USERNAME_AND_PASSWORD:
|
||||
value = self._create_username_password_credential(value)
|
||||
elif cred_type is CredentialType.DEVICE:
|
||||
value = self._create_device_credential(value)
|
||||
else:
|
||||
msg = 'Unrecognized credential type: {}'
|
||||
raise ValueError(msg.format(cred_type))
|
||||
|
||||
return self._create_credential(cred_type, value)
|
||||
|
||||
def _create_username_password_credential(self, value):
|
||||
username = value.get('Username')
|
||||
password = value.get('Password')
|
||||
|
||||
username = Credential.UsernamePasswordCredential.Username(username)
|
||||
password = Credential.UsernamePasswordCredential.Password(password)
|
||||
|
||||
return Credential.UsernamePasswordCredential(username=username,
|
||||
password=password)
|
||||
|
||||
def _create_device_credential(self, value):
|
||||
dsn = value.get('Device Serial Number')
|
||||
password = value.get('Password')
|
||||
dev_id = value.get('Device Identifier')
|
||||
net_id = value.get('Network Identifier')
|
||||
mach_id = value.get('Machine Identifier')
|
||||
med_id = value.get('Media Identifier')
|
||||
|
||||
dsn = Credential.DeviceCredential.DeviceSerialNumber(dsn)
|
||||
password = Credential.DeviceCredential.Password(password)
|
||||
dev_id = Credential.DeviceCredential.DeviceIdentifier(dev_id)
|
||||
net_id = Credential.DeviceCredential.NetworkIdentifier(net_id)
|
||||
mach_id = Credential.DeviceCredential.MachineIdentifier(mach_id)
|
||||
med_id = Credential.DeviceCredential.MediaIdentifier(med_id)
|
||||
|
||||
return Credential.DeviceCredential(device_serial_number=dsn,
|
||||
password=password,
|
||||
device_identifier=dev_id,
|
||||
network_identifier=net_id,
|
||||
machine_identifier=mach_id,
|
||||
media_identifier=med_id)
|
126
kmip/core/factories/keys.py
Normal file
126
kmip/core/factories/keys.py
Normal file
@ -0,0 +1,126 @@
|
||||
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from kmip.core.enums import KeyFormatType
|
||||
|
||||
from kmip.core.keys import RawKey
|
||||
|
||||
|
||||
class KeyFactory(object):
|
||||
|
||||
def create_key(self, key_format, value=None):
|
||||
if value is None:
|
||||
value = {}
|
||||
|
||||
# Switch on the format type of the key
|
||||
if key_format is KeyFormatType.RAW:
|
||||
return self._create_raw_key(value)
|
||||
elif key_format is KeyFormatType.OPAQUE:
|
||||
return self._create_opaque_key(value)
|
||||
elif key_format is KeyFormatType.PKCS_1:
|
||||
return self._create_pkcs_1_key(value)
|
||||
elif key_format is KeyFormatType.PKCS_8:
|
||||
return self._create_pkcs_8_key(value)
|
||||
elif key_format is KeyFormatType.X_509:
|
||||
return self._create_x_509_key(value)
|
||||
elif key_format is KeyFormatType.EC_PRIVATE_KEY:
|
||||
return self._create_ec_private_key(value)
|
||||
elif key_format is KeyFormatType.TRANSPARENT_SYMMETRIC_KEY:
|
||||
return self._create_transparent_symmetric_key(value)
|
||||
elif key_format is KeyFormatType.TRANSPARENT_DSA_PRIVATE_KEY:
|
||||
return self._create_transparent_dsa_private_key(value)
|
||||
elif key_format is KeyFormatType.TRANSPARENT_DSA_PUBLIC_KEY:
|
||||
return self._create_transparent_dsa_public_key(value)
|
||||
elif key_format is KeyFormatType.TRANSPARENT_RSA_PRIVATE_KEY:
|
||||
return self._create_transparent_rsa_private_key(value)
|
||||
elif key_format is KeyFormatType.TRANSPARENT_RSA_PUBLIC_KEY:
|
||||
return self._create_transparent_rsa_public_key(value)
|
||||
elif key_format is KeyFormatType.TRANSPARENT_DH_PRIVATE_KEY:
|
||||
return self._create_transparent_dh_private_key(value)
|
||||
elif key_format is KeyFormatType.TRANSPARENT_DH_PUBLIC_KEY:
|
||||
return self._create_transparent_dh_public_key(value)
|
||||
elif key_format is KeyFormatType.TRANSPARENT_ECDSA_PRIVATE_KEY:
|
||||
return self._create_transparent_ecdsa_private_key(value)
|
||||
elif key_format is KeyFormatType.TRANSPARENT_ECDSA_PUBLIC_KEY:
|
||||
return self._create_transparent_ecdsa_public_key(value)
|
||||
elif key_format is KeyFormatType.TRANSPARENT_ECDH_PRIVATE_KEY:
|
||||
return self._create_transparent_ecdh_private_key(value)
|
||||
elif key_format is KeyFormatType.TRANSPARENT_ECDH_PUBLIC_KEY:
|
||||
return self._create_transparent_ecdh_public_key(value)
|
||||
elif key_format is KeyFormatType.TRANSPARENT_ECMQV_PRIVATE_KEY:
|
||||
return self._create_transparent_ecmqv_private_key(value)
|
||||
elif key_format is KeyFormatType.TRANSPARENT_ECMQV_PUBLIC_KEY:
|
||||
return self._create_transparent_ecmqv_public_key(value)
|
||||
else:
|
||||
msg = 'Unrecognized key format type: {}'
|
||||
raise ValueError(msg.format(key_format))
|
||||
|
||||
def _create_raw_key(self, value):
|
||||
data = value.get('bytes')
|
||||
return RawKey(data)
|
||||
|
||||
def _create_opaque_key(self, value):
|
||||
raise NotImplementedError()
|
||||
|
||||
def _create_pkcs_1_key(self, value):
|
||||
raise NotImplementedError()
|
||||
|
||||
def _create_pkcs_8_key(self, value):
|
||||
raise NotImplementedError()
|
||||
|
||||
def _create_x_509_key(self, value):
|
||||
raise NotImplementedError()
|
||||
|
||||
def _create_ec_private_key(self, value):
|
||||
raise NotImplementedError()
|
||||
|
||||
def _create_transparent_symmetric_key(self, value):
|
||||
raise NotImplementedError()
|
||||
|
||||
def _create_transparent_dsa_private_key(self, value):
|
||||
raise NotImplementedError()
|
||||
|
||||
def _create_transparent_dsa_public_key(self, value):
|
||||
raise NotImplementedError()
|
||||
|
||||
def _create_transparent_rsa_private_key(self, value):
|
||||
raise NotImplementedError()
|
||||
|
||||
def _create_transparent_rsa_public_key(self, value):
|
||||
raise NotImplementedError()
|
||||
|
||||
def _create_transparent_dh_private_key(self, value):
|
||||
raise NotImplementedError()
|
||||
|
||||
def _create_transparent_dh_public_key(self, value):
|
||||
raise NotImplementedError()
|
||||
|
||||
def _create_transparent_ecdsa_private_key(self, value):
|
||||
raise NotImplementedError()
|
||||
|
||||
def _create_transparent_ecdsa_public_key(self, value):
|
||||
raise NotImplementedError()
|
||||
|
||||
def _create_transparent_ecdh_private_key(self, value):
|
||||
raise NotImplementedError()
|
||||
|
||||
def _create_transparent_ecdh_public_key(self, value):
|
||||
raise NotImplementedError()
|
||||
|
||||
def _create_transparent_ecmqv_private_key(self, value):
|
||||
raise NotImplementedError()
|
||||
|
||||
def _create_transparent_ecmqv_public_key(self, value):
|
||||
raise NotImplementedError()
|
140
kmip/core/factories/secrets.py
Normal file
140
kmip/core/factories/secrets.py
Normal file
@ -0,0 +1,140 @@
|
||||
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from kmip.core.factories.keys import KeyFactory
|
||||
|
||||
from kmip.core.attributes import CryptographicAlgorithm
|
||||
from kmip.core.attributes import CryptographicLength
|
||||
|
||||
from kmip.core.enums import ObjectType
|
||||
|
||||
from kmip.core.errors import ErrorStrings
|
||||
|
||||
from kmip.core.objects import Attribute
|
||||
from kmip.core.objects import KeyBlock
|
||||
from kmip.core.objects import KeyWrappingData
|
||||
from kmip.core.objects import KeyValueStruct
|
||||
from kmip.core.objects import KeyValue
|
||||
|
||||
from kmip.core.secrets import SymmetricKey
|
||||
from kmip.core.secrets import Template
|
||||
|
||||
from kmip.core import utils
|
||||
|
||||
|
||||
class SecretFactory(object):
|
||||
|
||||
def __init__(self):
|
||||
self.key_factory = KeyFactory()
|
||||
|
||||
self.base_error = ErrorStrings.BAD_EXP_RECV
|
||||
self.template_input = self.base_error.format('Template', '{0}', '{1}',
|
||||
'{2}')
|
||||
|
||||
def create_secret(self, secret_type, value=None):
|
||||
if secret_type is ObjectType.CERTIFICATE:
|
||||
return self._create_certificate(value)
|
||||
elif secret_type is ObjectType.SYMMETRIC_KEY:
|
||||
return self._create_symmetric_key(value)
|
||||
elif secret_type is ObjectType.PUBLIC_KEY:
|
||||
return self._create_public_key(value)
|
||||
elif secret_type is ObjectType.PRIVATE_KEY:
|
||||
return self._create_private_key(value)
|
||||
elif secret_type is ObjectType.SPLIT_KEY:
|
||||
return self._create_split_key(value)
|
||||
elif secret_type is ObjectType.TEMPLATE:
|
||||
return self._create_template(value)
|
||||
elif secret_type is ObjectType.SECRET_DATA:
|
||||
return self._create_secret_data(value)
|
||||
elif secret_type is ObjectType.OPAQUE_DATA:
|
||||
return self._create_opaque_data(value)
|
||||
|
||||
def _create_certificate(self, value):
|
||||
raise NotImplementedError()
|
||||
|
||||
def _create_symmetric_key(self, value):
|
||||
if value is None:
|
||||
return SymmetricKey()
|
||||
else:
|
||||
key_type = value.get('key_format_type')
|
||||
key_compression_type = value.get('key_compression_type')
|
||||
key_value = value.get('key_value')
|
||||
cryptographic_algorithm = value.get('cryptographic_algorithm')
|
||||
cryptographic_length = value.get('cryptographic_length')
|
||||
key_wrapping_data = value.get('key_wrapping_data')
|
||||
|
||||
key_format_type = KeyBlock.KeyFormatType(key_type)
|
||||
|
||||
key_comp_type = None
|
||||
if key_compression_type is not None:
|
||||
key_comp_type = KeyBlock.KeyCompressionType(
|
||||
key_compression_type)
|
||||
|
||||
key_material = self.key_factory.create_key(key_type,
|
||||
key_value)
|
||||
key_val_struc = KeyValueStruct(key_format_type=key_format_type,
|
||||
key_material=key_material)
|
||||
key_value = KeyValue(key_value=key_val_struc,
|
||||
key_format_type=key_format_type)
|
||||
crypto_algorithm = CryptographicAlgorithm(cryptographic_algorithm)
|
||||
crypto_length = CryptographicLength(cryptographic_length)
|
||||
|
||||
key_wrap_data = None
|
||||
if key_wrapping_data is not None:
|
||||
# TODO (peter-hamilton) This currently isn't used in the tests
|
||||
# TODO (peter-hamilton) but needs to be updated to properly
|
||||
# TODO (peter-hamilton) create a KeyWrappingData object.
|
||||
key_wrap_data = KeyWrappingData(key_wrapping_data)
|
||||
|
||||
key_block = KeyBlock(key_format_type,
|
||||
key_comp_type,
|
||||
key_value,
|
||||
crypto_algorithm,
|
||||
crypto_length,
|
||||
key_wrap_data)
|
||||
return SymmetricKey(key_block)
|
||||
|
||||
def _create_public_key(self, value):
|
||||
raise NotImplementedError()
|
||||
|
||||
def _create_private_key(self, value):
|
||||
raise NotImplementedError()
|
||||
|
||||
def _create_split_key(self, value):
|
||||
raise NotImplementedError()
|
||||
|
||||
def _create_template(self, value):
|
||||
if value is None:
|
||||
return Template()
|
||||
else:
|
||||
if not isinstance(value, list):
|
||||
msg = utils.build_er_error(Template,
|
||||
'constructor argument type', list,
|
||||
type(value))
|
||||
raise TypeError(msg)
|
||||
else:
|
||||
for val in value:
|
||||
if not isinstance(val, Attribute):
|
||||
msg = utils.build_er_error(Template,
|
||||
'constructor argument type',
|
||||
Attribute, type(val))
|
||||
raise TypeError(msg)
|
||||
return Template(value)
|
||||
|
||||
def _create_secret_data(self, value):
|
||||
raise NotImplementedError()
|
||||
|
||||
def _create_opaque_data(self, value):
|
||||
raise NotImplementedError()
|
102
kmip/core/keys.py
Normal file
102
kmip/core/keys.py
Normal file
@ -0,0 +1,102 @@
|
||||
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
# This module defines classes representing all of the different key types
|
||||
# used by KMIP, including the more detailed structures of the Transparent
|
||||
# Keys defined in Section 2.1.7.
|
||||
|
||||
from kmip.core.enums import Tags
|
||||
|
||||
from kmip.core.primitives import Struct
|
||||
from kmip.core.primitives import ByteString
|
||||
|
||||
from kmip.core.utils import BytearrayStream
|
||||
|
||||
|
||||
class RawKey(ByteString):
|
||||
|
||||
def __init__(self, value=None):
|
||||
super(self.__class__, self).__init__(value, Tags.KEY_MATERIAL)
|
||||
|
||||
|
||||
class OpaqueKey(ByteString):
|
||||
|
||||
def __init__(self, value=None):
|
||||
super(self.__class__, self).__init__(value, Tags.KEY_MATERIAL)
|
||||
|
||||
|
||||
class PKCS1Key(ByteString):
|
||||
|
||||
def __init__(self, value=None):
|
||||
super(self.__class__, self).__init__(value, Tags.KEY_MATERIAL)
|
||||
|
||||
|
||||
class PKCS8Key(ByteString):
|
||||
|
||||
def __init__(self, value=None):
|
||||
super(self.__class__, self).__init__(value, Tags.KEY_MATERIAL)
|
||||
|
||||
|
||||
class X509Key(ByteString):
|
||||
|
||||
def __init__(self, value=None):
|
||||
super(self.__class__, self).__init__(value, Tags.KEY_MATERIAL)
|
||||
|
||||
|
||||
class ECPrivateKey(ByteString):
|
||||
|
||||
def __init__(self, value=None):
|
||||
super(self.__class__, self).__init__(value, Tags.KEY_MATERIAL)
|
||||
|
||||
|
||||
# 2.1.7.1
|
||||
class TransparentSymmetricKey(Struct):
|
||||
|
||||
class Key(ByteString):
|
||||
|
||||
def __init__(self, value=None):
|
||||
super(self.__class__, self).__init__(value, Tags.KEY)
|
||||
|
||||
def __init__(self, key=None):
|
||||
super(self.__class__, self).__init__(Tags.KEY_MATERIAL)
|
||||
self.key = key
|
||||
self.validate()
|
||||
|
||||
def read(self, istream):
|
||||
super(self.__class__, self).read(istream)
|
||||
tstream = BytearrayStream(istream.read(self.length))
|
||||
|
||||
self.key = TransparentSymmetricKey.Key()
|
||||
self.key.read(tstream)
|
||||
|
||||
self.is_oversized(tstream)
|
||||
self.validate()
|
||||
|
||||
def write(self, ostream):
|
||||
tstream = BytearrayStream()
|
||||
|
||||
self.key.write(tstream)
|
||||
|
||||
# Write the length and value of the key wrapping data
|
||||
self.length = tstream.length()
|
||||
super(self.__class__, self).write(ostream)
|
||||
ostream.write(tstream.buffer)
|
||||
|
||||
def validate(self):
|
||||
self.__validate()
|
||||
|
||||
def __validate(self):
|
||||
# TODO (peter-hamilton) Finish implementation.
|
||||
pass
|
2
kmip/core/messages/.gitignore
vendored
Normal file
2
kmip/core/messages/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
/test_in.txt
|
||||
/test_out.txt
|
16
kmip/core/messages/__init__.py
Normal file
16
kmip/core/messages/__init__.py
Normal file
@ -0,0 +1,16 @@
|
||||
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
__all__ = ['contents', 'messages', 'operations']
|
224
kmip/core/messages/contents.py
Normal file
224
kmip/core/messages/contents.py
Normal file
@ -0,0 +1,224 @@
|
||||
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from kmip.core import enums
|
||||
from kmip.core import objects
|
||||
from kmip.core import utils
|
||||
|
||||
from kmip.core.primitives import Struct
|
||||
from kmip.core.primitives import Integer
|
||||
from kmip.core.primitives import Enumeration
|
||||
from kmip.core.primitives import Boolean
|
||||
from kmip.core.primitives import TextString
|
||||
from kmip.core.primitives import ByteString
|
||||
from kmip.core.primitives import DateTime
|
||||
|
||||
|
||||
# 6.1
|
||||
class ProtocolVersion(Struct):
|
||||
|
||||
class ProtocolVersionMajor(Integer):
|
||||
def __init__(self, value=None):
|
||||
super(self.__class__, self).\
|
||||
__init__(value, enums.Tags.PROTOCOL_VERSION_MAJOR)
|
||||
|
||||
class ProtocolVersionMinor(Integer):
|
||||
def __init__(self, value=None):
|
||||
super(self.__class__, self).\
|
||||
__init__(value, enums.Tags.PROTOCOL_VERSION_MINOR)
|
||||
|
||||
def __init__(self,
|
||||
protocol_version_major=None,
|
||||
protocol_version_minor=None):
|
||||
super(self.__class__, self).__init__(tag=enums.Tags.PROTOCOL_VERSION)
|
||||
self.protocol_version_major = protocol_version_major
|
||||
self.protocol_version_minor = protocol_version_minor
|
||||
|
||||
def read(self, istream):
|
||||
super(self.__class__, self).read(istream)
|
||||
tstream = utils.BytearrayStream(istream.read(self.length))
|
||||
|
||||
# Read the major and minor portions of the version number
|
||||
self.protocol_version_major = ProtocolVersion.ProtocolVersionMajor()
|
||||
self.protocol_version_minor = ProtocolVersion.ProtocolVersionMinor()
|
||||
self.protocol_version_major.read(tstream)
|
||||
self.protocol_version_minor.read(tstream)
|
||||
|
||||
self.is_oversized(tstream)
|
||||
|
||||
def write(self, ostream):
|
||||
tstream = utils.BytearrayStream()
|
||||
|
||||
# Write the major and minor portions of the protocol version
|
||||
self.protocol_version_major.write(tstream)
|
||||
self.protocol_version_minor.write(tstream)
|
||||
|
||||
# Write the length and value of the protocol version
|
||||
self.length = tstream.length()
|
||||
super(self.__class__, self).write(ostream)
|
||||
ostream.write(tstream.buffer)
|
||||
|
||||
def validate(self):
|
||||
# TODO (peter-hamilton) Finish implementation.
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def create(cls, major, minor):
|
||||
major_version = cls.ProtocolVersionMajor(major)
|
||||
minor_version = cls.ProtocolVersionMinor(minor)
|
||||
return ProtocolVersion(major_version, minor_version)
|
||||
|
||||
|
||||
# 6.2
|
||||
class Operation(Enumeration):
|
||||
ENUM_TYPE = enums.Operation
|
||||
|
||||
def __init__(self, value=None):
|
||||
super(self.__class__, self).__init__(value, enums.Tags.OPERATION)
|
||||
|
||||
|
||||
# 6.3
|
||||
class MaximumResponseSize(Integer):
|
||||
def __init__(self, value=None):
|
||||
super(self.__class__, self).\
|
||||
__init__(value, enums.Tags.MAXIMUM_RESPONSE_SIZE)
|
||||
|
||||
|
||||
# 6.4
|
||||
class UniqueBatchItemID(ByteString):
|
||||
def __init__(self, value=None):
|
||||
super(self.__class__, self)\
|
||||
.__init__(value, enums.Tags.UNIQUE_BATCH_ITEM_ID)
|
||||
|
||||
|
||||
# 6.5
|
||||
class TimeStamp(DateTime):
|
||||
def __init__(self, value=None):
|
||||
super(self.__class__, self).__init__(value, enums.Tags.TIME_STAMP)
|
||||
|
||||
|
||||
# 6.6
|
||||
class Authentication(Struct):
|
||||
|
||||
def __init__(self, credential=None):
|
||||
super(self.__class__, self).__init__(tag=enums.Tags.AUTHENTICATION)
|
||||
self.credential = credential
|
||||
|
||||
def read(self, istream):
|
||||
super(self.__class__, self).read(istream)
|
||||
tstream = utils.BytearrayStream(istream.read(self.length))
|
||||
|
||||
# Read the credential
|
||||
self.credential = objects.Credential()
|
||||
self.credential.read(tstream)
|
||||
|
||||
self.is_oversized(tstream)
|
||||
|
||||
def write(self, ostream):
|
||||
tstream = utils.BytearrayStream()
|
||||
|
||||
# Write the credential
|
||||
self.credential.write(tstream)
|
||||
|
||||
# Write the length and value of the protocol version
|
||||
self.length = tstream.length()
|
||||
super(self.__class__, self).write(ostream)
|
||||
ostream.write(tstream.buffer)
|
||||
|
||||
def validate(self):
|
||||
# TODO (peter-hamilton) Finish implementation.
|
||||
pass
|
||||
|
||||
|
||||
# 6.7
|
||||
class AsynchronousIndicator(Boolean):
|
||||
def __init__(self, value=None):
|
||||
super(self.__class__, self).\
|
||||
__init__(value, enums.Tags.ASYNCHRONOUS_INDICATOR)
|
||||
|
||||
|
||||
# 6.8
|
||||
class AsynchronousCorrelationValue(ByteString):
|
||||
def __init__(self, value=None):
|
||||
super(self.__class__, self).\
|
||||
__init__(value, enums.Tags.ASYNCHRONOUS_CORRELATION_VALUE)
|
||||
|
||||
|
||||
# 6.9
|
||||
class ResultStatus(Enumeration):
|
||||
ENUM_TYPE = enums.ResultStatus
|
||||
|
||||
def __init__(self, value=None):
|
||||
super(self.__class__, self).__init__(value, enums.Tags.RESULT_STATUS)
|
||||
|
||||
|
||||
# 6.10
|
||||
class ResultReason(Enumeration):
|
||||
ENUM_TYPE = enums.ResultReason
|
||||
|
||||
def __init__(self, value=None):
|
||||
super(self.__class__, self).__init__(value, enums.Tags.RESULT_REASON)
|
||||
|
||||
|
||||
# 6.11
|
||||
class ResultMessage(TextString):
|
||||
def __init__(self, value=None):
|
||||
super(self.__class__, self).__init__(value, enums.Tags.RESULT_MESSAGE)
|
||||
|
||||
|
||||
# 6.12
|
||||
class BatchOrderOption(Boolean):
|
||||
def __init__(self, value=None):
|
||||
super(self.__class__, self).\
|
||||
__init__(value, enums.Tags.BATCH_ORDER_OPTION)
|
||||
|
||||
|
||||
# 6.13
|
||||
class BatchErrorContinuationOption(Enumeration):
|
||||
ENUM_TYPE = enums.BatchErrorContinuationOption
|
||||
|
||||
def __init__(self, value=None):
|
||||
super(self.__class__, self).\
|
||||
__init__(value, enums.Tags.BATCH_ERROR_CONTINUATION_OPTION)
|
||||
|
||||
|
||||
# 6.14
|
||||
class BatchCount(Integer):
|
||||
def __init__(self, value=None):
|
||||
super(self.__class__, self).__init__(value, enums.Tags.BATCH_COUNT)
|
||||
|
||||
|
||||
# 6.16
|
||||
class MessageExtension(Struct):
|
||||
def __init__(self):
|
||||
super(self.__class__, self).__init__(tag=enums.Tags.MESSAGE_EXTENSION)
|
||||
|
||||
|
||||
# 9.1.3.2.2
|
||||
class KeyCompressionType(Enumeration):
|
||||
ENUM_TYPE = enums.KeyCompressionType
|
||||
|
||||
def __init__(self, value=None):
|
||||
super(self.__class__, self).\
|
||||
__init__(value, enums.Tags.KEY_COMPRESSION_TYPE)
|
||||
|
||||
|
||||
# 9.1.3.2.3
|
||||
class KeyFormatType(Enumeration):
|
||||
ENUM_TYPE = enums.KeyFormatType
|
||||
|
||||
def __init__(self, value=None):
|
||||
super(self.__class__, self).\
|
||||
__init__(value, enums.Tags.KEY_FORMAT_TYPE)
|
397
kmip/core/messages/messages.py
Normal file
397
kmip/core/messages/messages.py
Normal file
@ -0,0 +1,397 @@
|
||||
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from kmip.core.enums import Tags
|
||||
|
||||
from kmip.core.messages import contents
|
||||
from kmip.core.messages.contents import AsynchronousCorrelationValue
|
||||
from kmip.core.messages.contents import BatchErrorContinuationOption
|
||||
|
||||
from kmip.core.messages import operations
|
||||
|
||||
from kmip.core.primitives import Struct
|
||||
|
||||
from kmip.core.utils import BytearrayStream
|
||||
|
||||
|
||||
class RequestHeader(Struct):
|
||||
|
||||
def __init__(self,
|
||||
protocol_version=None,
|
||||
maximum_response_size=None,
|
||||
asynchronous_indicator=None,
|
||||
authentication=None,
|
||||
batch_error_cont_option=None,
|
||||
batch_order_option=None,
|
||||
time_stamp=None,
|
||||
batch_count=None):
|
||||
super(self.__class__, self).__init__(tag=Tags.REQUEST_HEADER)
|
||||
self.protocol_version = protocol_version
|
||||
self.maximum_response_size = maximum_response_size
|
||||
self.asynchronous_indicator = asynchronous_indicator
|
||||
self.authentication = authentication
|
||||
self.batch_error_cont_option = batch_error_cont_option
|
||||
self.batch_order_option = batch_order_option
|
||||
self.time_stamp = time_stamp
|
||||
self.batch_count = batch_count
|
||||
|
||||
def read(self, istream):
|
||||
super(self.__class__, self).read(istream)
|
||||
tstream = BytearrayStream(istream.read(self.length))
|
||||
|
||||
self.protocol_version = contents.ProtocolVersion()
|
||||
self.protocol_version.read(tstream)
|
||||
|
||||
# Read the maximum response size if it is present
|
||||
if self.is_tag_next(Tags.MAXIMUM_RESPONSE_SIZE, tstream):
|
||||
self.maximum_response_size = contents.MaximumResponseSize()
|
||||
self.maximum_response_size.read(tstream)
|
||||
|
||||
# Read the asynchronous indicator if it is present
|
||||
if self.is_tag_next(Tags.ASYNCHRONOUS_INDICATOR, tstream):
|
||||
self.asynchronous_indicator = contents.AsynchronousIndicator()
|
||||
self.asynchronous_indicator.read(tstream)
|
||||
|
||||
# Read the authentication if it is present
|
||||
if self.is_tag_next(Tags.AUTHENTICATION, tstream):
|
||||
self.authentication = contents.Authentication()
|
||||
self.authentication.read(tstream)
|
||||
|
||||
# Read the batch error continuation option if it is present
|
||||
if self.is_tag_next(Tags.BATCH_ERROR_CONTINUATION_OPTION, tstream):
|
||||
self.batch_error_cont_option = BatchErrorContinuationOption()
|
||||
self.batch_error_cont_option.read(tstream)
|
||||
|
||||
# Read the batch order option if it is present
|
||||
if self.is_tag_next(Tags.BATCH_ORDER_OPTION, tstream):
|
||||
self.batch_order_option = contents.BatchOrderOption()
|
||||
self.batch_order_option.read(tstream)
|
||||
|
||||
# Read the time stamp if it is present
|
||||
if self.is_tag_next(Tags.TIME_STAMP, tstream):
|
||||
self.time_stamp = contents.TimeStamp()
|
||||
self.time_stamp.read(tstream)
|
||||
|
||||
self.batch_count = contents.BatchCount()
|
||||
self.batch_count.read(tstream)
|
||||
|
||||
self.is_oversized(tstream)
|
||||
|
||||
def write(self, ostream):
|
||||
tstream = BytearrayStream()
|
||||
|
||||
# Write the contents of a request header to the stream
|
||||
self.protocol_version.write(tstream)
|
||||
if self.maximum_response_size is not None:
|
||||
self.maximum_response_size.write(tstream)
|
||||
if self.asynchronous_indicator is not None:
|
||||
self.asynchronous_indicator.write(tstream)
|
||||
if self.authentication is not None:
|
||||
self.authentication.write(tstream)
|
||||
if self.batch_error_cont_option is not None:
|
||||
self.batch_error_cont_option.write(tstream)
|
||||
if self.batch_order_option is not None:
|
||||
self.batch_order_option.write(tstream)
|
||||
if self.time_stamp is not None:
|
||||
self.time_stamp.write(tstream)
|
||||
self.batch_count.write(tstream)
|
||||
|
||||
# Write the length and value of the request header
|
||||
self.length = tstream.length()
|
||||
super(self.__class__, self).write(ostream)
|
||||
ostream.write(tstream.buffer)
|
||||
|
||||
|
||||
class ResponseHeader(Struct):
|
||||
|
||||
def __init__(self,
|
||||
protocol_version=None,
|
||||
time_stamp=None,
|
||||
batch_count=None):
|
||||
super(self.__class__, self).__init__(tag=Tags.RESPONSE_HEADER)
|
||||
self.protocol_version = protocol_version
|
||||
self.time_stamp = time_stamp
|
||||
self.batch_count = batch_count
|
||||
self.validate()
|
||||
|
||||
def read(self, istream):
|
||||
super(self.__class__, self).read(istream)
|
||||
tstream = BytearrayStream(istream.read(self.length))
|
||||
|
||||
self.protocol_version = contents.ProtocolVersion()
|
||||
self.protocol_version.read(tstream)
|
||||
|
||||
self.time_stamp = contents.TimeStamp()
|
||||
self.time_stamp.read(tstream)
|
||||
|
||||
self.batch_count = contents.BatchCount()
|
||||
self.batch_count.read(tstream)
|
||||
|
||||
self.is_oversized(tstream)
|
||||
self.validate()
|
||||
|
||||
def write(self, ostream):
|
||||
tstream = BytearrayStream()
|
||||
|
||||
# Write the contents of a response header to the stream
|
||||
self.protocol_version.write(tstream)
|
||||
self.time_stamp.write(tstream)
|
||||
self.batch_count.write(tstream)
|
||||
|
||||
# Write the length and value of the request header
|
||||
self.length = tstream.length()
|
||||
super(self.__class__, self).write(ostream)
|
||||
ostream.write(tstream.buffer)
|
||||
|
||||
def validate(self):
|
||||
if self.protocol_version is not None:
|
||||
# TODO (peter-hamilton) conduct type check
|
||||
self.protocol_version.validate()
|
||||
if self.time_stamp is not None:
|
||||
# TODO (peter-hamilton) conduct type check
|
||||
self.time_stamp.validate()
|
||||
if self.batch_count is not None:
|
||||
# TODO (peter-hamilton) conduct type check
|
||||
self.batch_count.validate()
|
||||
|
||||
|
||||
class RequestBatchItem(Struct):
|
||||
|
||||
def __init__(self,
|
||||
operation=None,
|
||||
unique_batch_item_id=None,
|
||||
request_payload=None,
|
||||
message_extension=None):
|
||||
super(self.__class__, self).__init__(tag=Tags.REQUEST_BATCH_ITEM)
|
||||
self.operation = operation
|
||||
self.unique_batch_item_id = unique_batch_item_id
|
||||
self.request_payload = request_payload
|
||||
self.message_extension = message_extension
|
||||
|
||||
def read(self, istream):
|
||||
super(self.__class__, self).read(istream)
|
||||
tstream = BytearrayStream(istream.read(self.length))
|
||||
|
||||
# Read the batch item operation
|
||||
self.operation = contents.Operation()
|
||||
self.operation.read(tstream)
|
||||
|
||||
# Read the unique batch item ID if it is present
|
||||
if self.is_tag_next(Tags.UNIQUE_BATCH_ITEM_ID, tstream):
|
||||
self.unique_batch_item_id = contents.UniqueBatchItemID()
|
||||
self.unique_batch_item_id.read(tstream)
|
||||
|
||||
# Lookup the response payload class that belongs to the operation
|
||||
cls = operations.REQUEST_MAP.get(self.operation.enum)
|
||||
self.request_payload = cls()
|
||||
self.request_payload.read(tstream)
|
||||
|
||||
# Read the message extension if it is present
|
||||
if self.is_tag_next(Tags.MESSAGE_EXTENSION, tstream):
|
||||
self.message_extension = contents.MessageExtension()
|
||||
self.message_extension.read(tstream)
|
||||
|
||||
self.is_oversized(tstream)
|
||||
|
||||
def write(self, ostream):
|
||||
tstream = BytearrayStream()
|
||||
|
||||
# Write the contents of the batch item to the stream
|
||||
self.operation.write(tstream)
|
||||
|
||||
if self.unique_batch_item_id is not None:
|
||||
self.unique_batch_item_id.write(tstream)
|
||||
|
||||
self.request_payload.write(tstream)
|
||||
|
||||
if self.message_extension is not None:
|
||||
self.message_extension.write(tstream)
|
||||
|
||||
# Write the length and value of the batch item
|
||||
self.length = tstream.length()
|
||||
super(self.__class__, self).write(ostream)
|
||||
ostream.write(tstream.buffer)
|
||||
|
||||
|
||||
class ResponseBatchItem(Struct):
|
||||
|
||||
def __init__(self,
|
||||
operation=None,
|
||||
unique_batch_item_id=None,
|
||||
result_status=None,
|
||||
result_reason=None,
|
||||
result_message=None,
|
||||
async_correlation_value=None,
|
||||
response_payload=None,
|
||||
message_extension=None):
|
||||
super(self.__class__, self).__init__(tag=Tags.RESPONSE_BATCH_ITEM)
|
||||
self.operation = operation
|
||||
self.unique_batch_item_id = unique_batch_item_id
|
||||
self.result_status = result_status
|
||||
self.result_reason = result_reason
|
||||
self.result_message = result_message
|
||||
self.async_correlation_value = async_correlation_value
|
||||
self.response_payload = response_payload
|
||||
self.message_extension = message_extension
|
||||
self.validate()
|
||||
|
||||
def read(self, istream):
|
||||
super(self.__class__, self).read(istream)
|
||||
tstream = BytearrayStream(istream.read(self.length))
|
||||
|
||||
# Read the batch item operation if it is present
|
||||
if self.is_tag_next(Tags.OPERATION, tstream):
|
||||
self.operation = contents.Operation()
|
||||
self.operation.read(tstream)
|
||||
|
||||
# Read the unique batch item ID if it is present
|
||||
if self.is_tag_next(Tags.UNIQUE_BATCH_ITEM_ID, tstream):
|
||||
self.unique_batch_item_id = contents.UniqueBatchItemID()
|
||||
self.unique_batch_item_id.read(tstream)
|
||||
|
||||
# Read the batch item result status
|
||||
self.result_status = contents.ResultStatus()
|
||||
self.result_status.read(tstream)
|
||||
|
||||
# Read the batch item result reason if it is present
|
||||
if self.is_tag_next(Tags.RESULT_REASON, tstream):
|
||||
self.result_reason = contents.ResultReason()
|
||||
self.result_reason.read(tstream)
|
||||
|
||||
# Read the batch item result message if it is present
|
||||
if self.is_tag_next(Tags.RESULT_MESSAGE, tstream):
|
||||
self.result_message = contents.ResultMessage()
|
||||
self.result_message.read(tstream)
|
||||
|
||||
# Read the batch item asynchronous correlation value if it is present
|
||||
if self.is_tag_next(Tags.ASYNCHRONOUS_CORRELATION_VALUE, tstream):
|
||||
self.async_correlation_value = AsynchronousCorrelationValue()
|
||||
self.async_correlation_value.read(tstream)
|
||||
|
||||
# Lookup the response payload class that belongs to the operation
|
||||
cls = operations.RESPONSE_MAP.get(self.operation.enum)
|
||||
expected = cls()
|
||||
if self.is_tag_next(expected.tag, tstream):
|
||||
self.response_payload = cls()
|
||||
self.response_payload.read(tstream)
|
||||
|
||||
# Read the message extension if it is present
|
||||
if self.is_tag_next(Tags.MESSAGE_EXTENSION, tstream):
|
||||
self.message_extension = contents.MessageExtension()
|
||||
self.message_extension.read(tstream)
|
||||
|
||||
self.is_oversized(tstream)
|
||||
self.validate()
|
||||
|
||||
def write(self, ostream):
|
||||
tstream = BytearrayStream()
|
||||
|
||||
# Write the contents of the batch item to the stream
|
||||
if self.operation is not None:
|
||||
self.operation.write(tstream)
|
||||
if self.unique_batch_item_id is not None:
|
||||
self.unique_batch_item_id.write(tstream)
|
||||
|
||||
self.result_status.write(tstream)
|
||||
|
||||
if self.result_reason is not None:
|
||||
self.result_reason.write(tstream)
|
||||
if self.result_message is not None:
|
||||
self.result_message.write(tstream)
|
||||
if self.async_correlation_value is not None:
|
||||
self.async_correlation_value.write(tstream)
|
||||
if self.response_payload is not None:
|
||||
self.response_payload.write(tstream)
|
||||
if self.message_extension is not None:
|
||||
self.message_extension.write(tstream)
|
||||
|
||||
# Write the length and value of the batch item
|
||||
self.length = tstream.length()
|
||||
super(self.__class__, self).write(ostream)
|
||||
ostream.write(tstream.buffer)
|
||||
|
||||
def validate(self):
|
||||
pass
|
||||
|
||||
|
||||
class RequestMessage(Struct):
|
||||
|
||||
def __init__(self, request_header=None, batch_items=None,):
|
||||
super(self.__class__, self).__init__(tag=Tags.REQUEST_MESSAGE)
|
||||
self.request_header = request_header
|
||||
self.batch_items = batch_items
|
||||
|
||||
def read(self, istream):
|
||||
super(self.__class__, self).read(istream)
|
||||
|
||||
self.request_header = RequestHeader()
|
||||
self.request_header.read(istream)
|
||||
|
||||
self.batch_items = []
|
||||
for _ in xrange(self.request_header.batch_count.value):
|
||||
batch_item = RequestBatchItem()
|
||||
batch_item.read(istream)
|
||||
self.batch_items.append(batch_item)
|
||||
|
||||
def write(self, ostream):
|
||||
tstream = BytearrayStream()
|
||||
|
||||
# Write the request header and all batch items
|
||||
self.request_header.write(tstream)
|
||||
for batch_item in self.batch_items:
|
||||
batch_item.write(tstream)
|
||||
|
||||
# Write the TTLV encoding of the request message
|
||||
self.length = tstream.length()
|
||||
super(self.__class__, self).write(ostream)
|
||||
ostream.write(tstream.buffer)
|
||||
|
||||
|
||||
class ResponseMessage(Struct):
|
||||
|
||||
def __init__(self, response_header=None, batch_items=None,):
|
||||
super(self.__class__, self).__init__(tag=Tags.RESPONSE_MESSAGE)
|
||||
self.response_header = response_header
|
||||
self.batch_items = batch_items
|
||||
self.validate()
|
||||
|
||||
def read(self, istream):
|
||||
super(self.__class__, self).read(istream)
|
||||
|
||||
self.response_header = ResponseHeader()
|
||||
self.response_header.read(istream)
|
||||
|
||||
self.batch_items = []
|
||||
for _ in xrange(self.response_header.batch_count.value):
|
||||
batch_item = ResponseBatchItem()
|
||||
batch_item.read(istream)
|
||||
self.batch_items.append(batch_item)
|
||||
self.validate()
|
||||
|
||||
def write(self, ostream):
|
||||
tstream = BytearrayStream()
|
||||
|
||||
# Write the request header and all batch items
|
||||
self.response_header.write(tstream)
|
||||
for batch_item in self.batch_items:
|
||||
batch_item.write(tstream)
|
||||
|
||||
# Write the TTLV encoding of the request message
|
||||
self.length = tstream.length()
|
||||
super(self.__class__, self).write(ostream)
|
||||
ostream.write(tstream.buffer)
|
||||
|
||||
def validate(self):
|
||||
pass
|
439
kmip/core/messages/operations.py
Normal file
439
kmip/core/messages/operations.py
Normal file
@ -0,0 +1,439 @@
|
||||
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from kmip.core.factories.secrets import SecretFactory
|
||||
|
||||
from kmip.core import attributes
|
||||
from kmip.core import enums
|
||||
from kmip.core.enums import Tags
|
||||
|
||||
from kmip.core.objects import KeyWrappingSpecification
|
||||
from kmip.core.objects import TemplateAttribute
|
||||
|
||||
from kmip.core.primitives import Struct
|
||||
from kmip.core.primitives import Enumeration
|
||||
|
||||
from kmip.core.utils import BytearrayStream
|
||||
|
||||
|
||||
# 4.1
|
||||
class CreateRequestPayload(Struct):
|
||||
|
||||
def __init__(self,
|
||||
object_type=None,
|
||||
template_attribute=None):
|
||||
super(self.__class__, self).__init__(tag=enums.Tags.REQUEST_PAYLOAD)
|
||||
self.object_type = object_type
|
||||
self.template_attribute = template_attribute
|
||||
self.validate()
|
||||
|
||||
def read(self, istream):
|
||||
super(self.__class__, self).read(istream)
|
||||
tstream = BytearrayStream(istream.read(self.length))
|
||||
|
||||
self.object_type = attributes.ObjectType()
|
||||
self.template_attribute = TemplateAttribute()
|
||||
|
||||
self.object_type.read(tstream)
|
||||
self.template_attribute.read(tstream)
|
||||
|
||||
self.is_oversized(tstream)
|
||||
self.validate()
|
||||
|
||||
def write(self, ostream):
|
||||
tstream = BytearrayStream()
|
||||
|
||||
# Write the object type and template attribute of the request payload
|
||||
self.object_type.write(tstream)
|
||||
self.template_attribute.write(tstream)
|
||||
|
||||
# Write the length and value of the request payload
|
||||
self.length = tstream.length()
|
||||
super(self.__class__, self).write(ostream)
|
||||
ostream.write(tstream.buffer)
|
||||
|
||||
def validate(self):
|
||||
# TODO (peter-hamilton) Finish implementation.
|
||||
pass
|
||||
|
||||
|
||||
class CreateResponsePayload(Struct):
|
||||
|
||||
def __init__(self,
|
||||
object_type=None,
|
||||
unique_identifier=None,
|
||||
template_attribute=None):
|
||||
super(self.__class__, self).__init__(tag=enums.Tags.RESPONSE_PAYLOAD)
|
||||
self.object_type = object_type
|
||||
self.unique_identifier = unique_identifier
|
||||
self.template_attribute = template_attribute
|
||||
self.validate()
|
||||
|
||||
def read(self, istream):
|
||||
super(self.__class__, self).read(istream)
|
||||
tstream = BytearrayStream(istream.read(self.length))
|
||||
|
||||
self.object_type = attributes.ObjectType()
|
||||
self.unique_identifier = attributes.UniqueIdentifier()
|
||||
|
||||
self.object_type.read(tstream)
|
||||
self.unique_identifier.read(tstream)
|
||||
|
||||
if self.is_tag_next(Tags.TEMPLATE_ATTRIBUTE, tstream):
|
||||
self.template_attribute = TemplateAttribute()
|
||||
self.template_attribute.read(tstream)
|
||||
|
||||
self.is_oversized(tstream)
|
||||
self.validate()
|
||||
|
||||
def write(self, ostream):
|
||||
tstream = BytearrayStream()
|
||||
|
||||
# Write the contents of the request payload
|
||||
self.object_type.write(tstream)
|
||||
self.unique_identifier.write(tstream)
|
||||
|
||||
if self.template_attribute is not None:
|
||||
self.template_attribute.write(tstream)
|
||||
|
||||
# Write the length and value of the request payload
|
||||
self.length = tstream.length()
|
||||
super(self.__class__, self).write(ostream)
|
||||
ostream.write(tstream.buffer)
|
||||
|
||||
def validate(self):
|
||||
# TODO (peter-hamilton) Finish implementation.
|
||||
pass
|
||||
|
||||
|
||||
# 4.3
|
||||
class RegisterRequestPayload(Struct):
|
||||
|
||||
def __init__(self,
|
||||
object_type=None,
|
||||
template_attribute=None,
|
||||
secret=None):
|
||||
super(self.__class__, self).__init__(Tags.REQUEST_PAYLOAD)
|
||||
|
||||
self.secret_factory = SecretFactory()
|
||||
self.object_type = object_type
|
||||
self.template_attribute = template_attribute
|
||||
self.secret = secret
|
||||
|
||||
self.validate()
|
||||
|
||||
def read(self, istream):
|
||||
super(self.__class__, self).read(istream)
|
||||
tstream = BytearrayStream(istream.read(self.length))
|
||||
|
||||
self.object_type = attributes.ObjectType()
|
||||
self.template_attribute = TemplateAttribute()
|
||||
|
||||
self.object_type.read(tstream)
|
||||
self.template_attribute.read(tstream)
|
||||
|
||||
secret_type = self.object_type.enum
|
||||
secret = self.secret_factory.create_secret(secret_type)
|
||||
|
||||
if self.is_tag_next(secret.tag, tstream):
|
||||
self.secret = secret
|
||||
self.secret.read(tstream)
|
||||
|
||||
self.is_oversized(tstream)
|
||||
self.validate()
|
||||
|
||||
def write(self, ostream):
|
||||
tstream = BytearrayStream()
|
||||
|
||||
# Write the contents of the request payload
|
||||
self.object_type.write(tstream)
|
||||
self.template_attribute.write(tstream)
|
||||
|
||||
if self.secret is not None:
|
||||
self.secret.write(tstream)
|
||||
|
||||
# Write the length and value of the request payload
|
||||
self.length = tstream.length()
|
||||
super(self.__class__, self).write(ostream)
|
||||
ostream.write(tstream.buffer)
|
||||
|
||||
def validate(self):
|
||||
self.__validate()
|
||||
|
||||
def __validate(self):
|
||||
# TODO (peter-hamilton) Finish implementation.
|
||||
pass
|
||||
|
||||
|
||||
class RegisterResponsePayload(Struct):
|
||||
|
||||
def __init__(self,
|
||||
unique_identifier=None,
|
||||
template_attribute=None):
|
||||
super(self.__class__, self).__init__(Tags.RESPONSE_PAYLOAD)
|
||||
|
||||
self.unique_identifier = unique_identifier
|
||||
self.template_attribute = template_attribute
|
||||
|
||||
self.validate()
|
||||
|
||||
def read(self, istream):
|
||||
super(self.__class__, self).read(istream)
|
||||
tstream = BytearrayStream(istream.read(self.length))
|
||||
|
||||
self.unique_identifier = attributes.UniqueIdentifier()
|
||||
self.unique_identifier.read(tstream)
|
||||
|
||||
if self.is_tag_next(Tags.TEMPLATE_ATTRIBUTE, tstream):
|
||||
self.template_attribute = TemplateAttribute()
|
||||
self.template_attribute.read(tstream)
|
||||
|
||||
self.is_oversized(tstream)
|
||||
self.validate()
|
||||
|
||||
def write(self, ostream):
|
||||
tstream = BytearrayStream()
|
||||
|
||||
# Write the contents of the request payload
|
||||
self.unique_identifier.write(tstream)
|
||||
|
||||
if self.template_attribute is not None:
|
||||
self.template_attribute.write(tstream)
|
||||
|
||||
# Write the length and value of the request payload
|
||||
self.length = tstream.length()
|
||||
super(self.__class__, self).write(ostream)
|
||||
ostream.write(tstream.buffer)
|
||||
|
||||
def validate(self):
|
||||
self.__validate()
|
||||
|
||||
def __validate(self):
|
||||
# TODO (peter-hamilton) Finish implementation.
|
||||
pass
|
||||
|
||||
|
||||
# 4.11
|
||||
class GetRequestPayload(Struct):
|
||||
|
||||
# 9.1.3.2.2
|
||||
class KeyCompressionType(Enumeration):
|
||||
ENUM_TYPE = enums.KeyCompressionType
|
||||
|
||||
def __init__(self, value=None):
|
||||
super(self.__class__, self).__init__(value,
|
||||
Tags.KEY_COMPRESSION_TYPE)
|
||||
|
||||
# 9.1.3.2.3
|
||||
class KeyFormatType(Enumeration):
|
||||
ENUM_TYPE = enums.KeyFormatType
|
||||
|
||||
def __init__(self, value=None):
|
||||
super(self.__class__, self).__init__(value, Tags.KEY_FORMAT_TYPE)
|
||||
|
||||
def __init__(self,
|
||||
unique_identifier=None,
|
||||
key_format_type=None,
|
||||
key_compression_type=None,
|
||||
key_wrapping_specification=None):
|
||||
super(self.__class__, self).__init__(tag=enums.Tags.REQUEST_PAYLOAD)
|
||||
self.unique_identifier = unique_identifier
|
||||
self.key_format_type = key_format_type
|
||||
self.key_compression_type = key_compression_type
|
||||
self.key_wrapping_specification = key_wrapping_specification
|
||||
self.validate()
|
||||
|
||||
def read(self, istream):
|
||||
super(self.__class__, self).read(istream)
|
||||
tstream = BytearrayStream(istream.read(self.length))
|
||||
|
||||
if self.is_tag_next(Tags.UNIQUE_IDENTIFIER, tstream):
|
||||
self.unique_identifier = attributes.UniqueIdentifier()
|
||||
self.unique_identifier.read(tstream)
|
||||
|
||||
if self.is_tag_next(Tags.KEY_FORMAT_TYPE, tstream):
|
||||
self.key_format_type = GetRequestPayload.KeyFormatType()
|
||||
self.key_format_type.read(tstream)
|
||||
|
||||
if self.is_tag_next(Tags.KEY_COMPRESSION_TYPE, tstream):
|
||||
self.key_compression_type = GetRequestPayload.KeyCompressionType()
|
||||
self.key_compression_type.read(tstream)
|
||||
|
||||
if self.is_tag_next(Tags.KEY_WRAPPING_SPECIFICATION, tstream):
|
||||
self.key_wrapping_specification = KeyWrappingSpecification()
|
||||
self.key_wrapping_specification.read(tstream)
|
||||
|
||||
self.is_oversized(tstream)
|
||||
self.validate()
|
||||
|
||||
def write(self, ostream):
|
||||
tstream = BytearrayStream()
|
||||
|
||||
# Write the contents of the request payload
|
||||
if self.unique_identifier is not None:
|
||||
self.unique_identifier.write(tstream)
|
||||
if self.key_format_type is not None:
|
||||
self.key_format_type.write(tstream)
|
||||
if self.key_compression_type is not None:
|
||||
self.key_compression_type.write(tstream)
|
||||
if self.key_wrapping_specification is not None:
|
||||
self.key_wrapping_specification.write(tstream)
|
||||
|
||||
# Write the length and value of the request payload
|
||||
self.length = tstream.length()
|
||||
super(self.__class__, self).write(ostream)
|
||||
ostream.write(tstream.buffer)
|
||||
|
||||
def validate(self):
|
||||
self.__validate()
|
||||
|
||||
def __validate(self):
|
||||
# TODO (peter-hamilton) Finish implementation
|
||||
pass
|
||||
|
||||
|
||||
class GetResponsePayload(Struct):
|
||||
|
||||
def __init__(self,
|
||||
object_type=None,
|
||||
unique_identifier=None,
|
||||
secret=None):
|
||||
super(self.__class__, self).__init__(tag=Tags.RESPONSE_PAYLOAD)
|
||||
self.object_type = object_type
|
||||
self.unique_identifier = unique_identifier
|
||||
self.secret = secret
|
||||
self.secret_factory = SecretFactory()
|
||||
self.validate()
|
||||
|
||||
def read(self, istream):
|
||||
super(self.__class__, self).read(istream)
|
||||
tstream = BytearrayStream(istream.read(self.length))
|
||||
|
||||
self.object_type = attributes.ObjectType()
|
||||
self.unique_identifier = attributes.UniqueIdentifier()
|
||||
|
||||
self.object_type.read(tstream)
|
||||
self.unique_identifier.read(tstream)
|
||||
|
||||
secret_type = self.object_type.enum
|
||||
self.secret = self.secret_factory.create_secret(secret_type)
|
||||
self.secret.read(tstream)
|
||||
|
||||
self.is_oversized(tstream)
|
||||
self.validate()
|
||||
|
||||
def write(self, ostream):
|
||||
tstream = BytearrayStream()
|
||||
|
||||
self.object_type.write(tstream)
|
||||
self.unique_identifier.write(tstream)
|
||||
self.secret.write(tstream)
|
||||
|
||||
# Write the length and value of the request payload
|
||||
self.length = tstream.length()
|
||||
super(self.__class__, self).write(ostream)
|
||||
ostream.write(tstream.buffer)
|
||||
|
||||
def validate(self):
|
||||
self.__validate()
|
||||
|
||||
def __validate(self):
|
||||
# TODO (peter-hamilton) Finish implementation.
|
||||
pass
|
||||
|
||||
|
||||
# 4.21
|
||||
class DestroyRequestPayload(Struct):
|
||||
|
||||
def __init__(self,
|
||||
unique_identifier=None):
|
||||
super(self.__class__, self).__init__(enums.Tags.REQUEST_PAYLOAD)
|
||||
self.unique_identifier = unique_identifier
|
||||
self.validate()
|
||||
|
||||
def read(self, istream):
|
||||
super(self.__class__, self).read(istream)
|
||||
tstream = BytearrayStream(istream.read(self.length))
|
||||
|
||||
if self.is_tag_next(Tags.UNIQUE_IDENTIFIER, tstream):
|
||||
self.unique_identifier = attributes.UniqueIdentifier()
|
||||
self.unique_identifier.read(tstream)
|
||||
|
||||
self.is_oversized(tstream)
|
||||
self.validate()
|
||||
|
||||
def write(self, ostream):
|
||||
tstream = BytearrayStream()
|
||||
|
||||
if self.unique_identifier is not None:
|
||||
self.unique_identifier.write(tstream)
|
||||
|
||||
# Write the length and value of the request payload
|
||||
self.length = tstream.length()
|
||||
super(self.__class__, self).write(ostream)
|
||||
ostream.write(tstream.buffer)
|
||||
|
||||
def validate(self):
|
||||
self.__validate()
|
||||
|
||||
def __validate(self):
|
||||
# TODO (peter-hamilton) Finish implementation.
|
||||
pass
|
||||
|
||||
|
||||
class DestroyResponsePayload(Struct):
|
||||
|
||||
def __init__(self,
|
||||
unique_identifier=None):
|
||||
super(self.__class__, self).__init__(enums.Tags.RESPONSE_PAYLOAD)
|
||||
self.unique_identifier = unique_identifier
|
||||
self.validate()
|
||||
|
||||
def read(self, istream):
|
||||
super(self.__class__, self).read(istream)
|
||||
tstream = BytearrayStream(istream.read(self.length))
|
||||
|
||||
self.unique_identifier = attributes.UniqueIdentifier()
|
||||
self.unique_identifier.read(tstream)
|
||||
|
||||
self.is_oversized(tstream)
|
||||
self.validate()
|
||||
|
||||
def write(self, ostream):
|
||||
tstream = BytearrayStream()
|
||||
|
||||
self.unique_identifier.write(tstream)
|
||||
|
||||
# Write the length and value of the request payload
|
||||
self.length = tstream.length()
|
||||
super(self.__class__, self).write(ostream)
|
||||
ostream.write(tstream.buffer)
|
||||
|
||||
def validate(self):
|
||||
self.__validate()
|
||||
|
||||
def __validate(self):
|
||||
# TODO (peter-hamilton) Finish implementation.
|
||||
pass
|
||||
|
||||
|
||||
REQUEST_MAP = {enums.Operation.CREATE: CreateRequestPayload,
|
||||
enums.Operation.GET: GetRequestPayload,
|
||||
enums.Operation.DESTROY: DestroyRequestPayload,
|
||||
enums.Operation.REGISTER: RegisterRequestPayload}
|
||||
RESPONSE_MAP = {enums.Operation.CREATE: CreateResponsePayload,
|
||||
enums.Operation.GET: GetResponsePayload,
|
||||
enums.Operation.DESTROY: DestroyResponsePayload,
|
||||
enums.Operation.REGISTER: RegisterResponsePayload}
|
845
kmip/core/objects.py
Normal file
845
kmip/core/objects.py
Normal file
@ -0,0 +1,845 @@
|
||||
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import attributes
|
||||
from kmip.core.attributes import CryptographicParameters
|
||||
|
||||
from kmip.core.factories.attribute_values import AttributeValueFactory
|
||||
from kmip.core.factories.keys import KeyFactory
|
||||
|
||||
from kmip.core import enums
|
||||
from kmip.core.enums import AttributeType
|
||||
from kmip.core.enums import Tags
|
||||
from kmip.core.enums import Types
|
||||
from kmip.core.enums import CredentialType
|
||||
|
||||
from kmip.core.errors import ErrorStrings
|
||||
|
||||
from kmip.core.primitives import Struct
|
||||
from kmip.core.primitives import TextString
|
||||
from kmip.core.primitives import ByteString
|
||||
from kmip.core.primitives import Integer
|
||||
from kmip.core.primitives import Enumeration
|
||||
|
||||
from utils import BytearrayStream
|
||||
|
||||
|
||||
# 2.1
|
||||
# 2.1.1
|
||||
class Attribute(Struct):
|
||||
|
||||
class AttributeName(TextString):
|
||||
|
||||
def __init__(self, value=None):
|
||||
super(self.__class__, self).__init__(value, Tags.ATTRIBUTE_NAME)
|
||||
|
||||
class AttributeIndex(Integer):
|
||||
|
||||
def __init__(self, value=None):
|
||||
super(self.__class__, self).__init__(value, Tags.ATTRIBUTE_INDEX)
|
||||
|
||||
def __init__(self,
|
||||
attribute_name=None,
|
||||
attribute_index=None,
|
||||
attribute_value=None):
|
||||
super(self.__class__, self).__init__(tag=Tags.ATTRIBUTE)
|
||||
|
||||
self.value_factory = AttributeValueFactory()
|
||||
|
||||
self.attribute_name = attribute_name
|
||||
self.attribute_index = attribute_index
|
||||
self.attribute_value = attribute_value
|
||||
|
||||
if attribute_value is not None:
|
||||
attribute_value.tag = Tags.ATTRIBUTE_VALUE
|
||||
|
||||
def read(self, istream):
|
||||
super(self.__class__, self).read(istream)
|
||||
tstream = BytearrayStream(istream.read(self.length))
|
||||
|
||||
# Read the name of the attribute
|
||||
self.attribute_name = Attribute.AttributeName()
|
||||
self.attribute_name.read(tstream)
|
||||
|
||||
# Read the attribute index if it is next
|
||||
if self.is_tag_next(Tags.ATTRIBUTE_INDEX, tstream):
|
||||
self.attribute_index = Attribute.AttributeIndex()
|
||||
self.attribute_index.read(tstream)
|
||||
|
||||
# Lookup the attribute class that belongs to the attribute name
|
||||
name = self.attribute_name.value
|
||||
enum_name = name.replace('.', '_').replace(' ', '_').upper()
|
||||
enum_type = None
|
||||
|
||||
try:
|
||||
enum_type = AttributeType[enum_name]
|
||||
except KeyError:
|
||||
# Likely custom attribute, pass raw name string as attribute type
|
||||
enum_type = name
|
||||
|
||||
value = self.value_factory.create_attribute_value(enum_type, None)
|
||||
self.attribute_value = value
|
||||
self.attribute_value.tag = Tags.ATTRIBUTE_VALUE
|
||||
self.attribute_value.read(tstream)
|
||||
|
||||
self.is_oversized(tstream)
|
||||
|
||||
def write(self, ostream):
|
||||
tstream = BytearrayStream()
|
||||
|
||||
self.attribute_name.write(tstream)
|
||||
if self.attribute_index is not None:
|
||||
self.attribute_index.write(tstream)
|
||||
self.attribute_value.write(tstream)
|
||||
|
||||
# Write the length and value of the attribute
|
||||
self.length = tstream.length()
|
||||
super(self.__class__, self).write(ostream)
|
||||
ostream.write(tstream.buffer)
|
||||
|
||||
|
||||
# 2.1.2
|
||||
class Credential(Struct):
|
||||
|
||||
class CredentialType(Enumeration):
|
||||
|
||||
ENUM_TYPE = CredentialType
|
||||
|
||||
def __init__(self, value=None):
|
||||
super(self.__class__, self).__init__(value, Tags.CREDENTIAL_TYPE)
|
||||
|
||||
class UsernamePasswordCredential(Struct):
|
||||
|
||||
class Username(TextString):
|
||||
def __init__(self, value=None):
|
||||
super(self.__class__, self).__init__(value, Tags.USERNAME)
|
||||
|
||||
class Password(TextString):
|
||||
def __init__(self, value=None):
|
||||
super(self.__class__, self).__init__(value, Tags.PASSWORD)
|
||||
|
||||
def __init__(self, username=None, password=None):
|
||||
super(self.__class__, self).__init__(tag=Tags.CREDENTIAL_VALUE)
|
||||
self.username = username
|
||||
self.password = password
|
||||
self.validate()
|
||||
|
||||
def read(self, istream):
|
||||
super(self.__class__, self).read(istream)
|
||||
tstream = BytearrayStream(istream.read(self.length))
|
||||
|
||||
# Read the username of the credential
|
||||
self.username = self.Username()
|
||||
self.username.read(tstream)
|
||||
|
||||
# Read the password if it is next
|
||||
if self.is_tag_next(Tags.PASSWORD, tstream):
|
||||
self.password = self.Password()
|
||||
self.password.read(tstream)
|
||||
|
||||
self.is_oversized(tstream)
|
||||
self.validate()
|
||||
|
||||
def write(self, ostream):
|
||||
tstream = BytearrayStream()
|
||||
|
||||
self.username.write(tstream)
|
||||
if self.password is not None:
|
||||
self.password.write(tstream)
|
||||
|
||||
# Write the length and value of the credential
|
||||
self.length = tstream.length()
|
||||
super(self.__class__, self).write(ostream)
|
||||
ostream.write(tstream.buffer)
|
||||
|
||||
def validate(self):
|
||||
pass
|
||||
|
||||
class DeviceCredential(Struct):
|
||||
|
||||
class DeviceSerialNumber(TextString):
|
||||
|
||||
def __init__(self, value=None):
|
||||
super(Credential.DeviceCredential.DeviceSerialNumber, self).\
|
||||
__init__(value, Tags.DEVICE_SERIAL_NUMBER)
|
||||
|
||||
class Password(TextString):
|
||||
|
||||
def __init__(self, value=None):
|
||||
super(Credential.DeviceCredential.Password, self).\
|
||||
__init__(value, Tags.PASSWORD)
|
||||
|
||||
class DeviceIdentifier(TextString):
|
||||
|
||||
def __init__(self, value=None):
|
||||
super(Credential.DeviceCredential.DeviceIdentifier, self).\
|
||||
__init__(value, Tags.DEVICE_IDENTIFIER)
|
||||
|
||||
class NetworkIdentifier(TextString):
|
||||
|
||||
def __init__(self, value=None):
|
||||
super(Credential.DeviceCredential.NetworkIdetifier, self).\
|
||||
__init__(value, Tags.NETWORK_IDENTIFIER)
|
||||
|
||||
class MachineIdentifier(TextString):
|
||||
|
||||
def __init__(self, value=None):
|
||||
super(Credential.DeviceCredential.MachineIdentifier, self).\
|
||||
__init__(value, Tags.MACHINE_IDENTIFIER)
|
||||
|
||||
class MediaIdentifier(TextString):
|
||||
|
||||
def __init__(self, value=None):
|
||||
super(Credential.DeviceCredential.MediaIdentifier, self).\
|
||||
__init__(value, Tags.MEDIA_IDENTIFIER)
|
||||
|
||||
def __init__(self,
|
||||
device_serial_number=None,
|
||||
password=None,
|
||||
device_identifier=None,
|
||||
network_identifier=None,
|
||||
machine_identifier=None,
|
||||
media_identifier=None):
|
||||
super(self.__class__, self).__init__(tag=Tags.CREDENTIAL_VALUE)
|
||||
super.device_serial_number = device_serial_number
|
||||
super.password = password
|
||||
super.device_identifier = device_identifier
|
||||
super.network_identifier = network_identifier
|
||||
super.machine_identifier = machine_identifier
|
||||
super.media_identifier = media_identifier
|
||||
|
||||
def read(self, istream):
|
||||
super(self.__class__, self).read(istream)
|
||||
tstream = BytearrayStream(istream.read(self.length))
|
||||
|
||||
# Read the password if it is next
|
||||
if self.is_tag_next(Tags.DEVICE_SERIAL_NUMBER, tstream):
|
||||
self.device_serial_number = self.DeviceSerialNumber()
|
||||
self.device_serial_number.read(tstream)
|
||||
|
||||
# Read the password if it is next
|
||||
if self.is_tag_next(Tags.PASSWORD, tstream):
|
||||
self.password = self.Password()
|
||||
self.password.read(tstream)
|
||||
|
||||
# Read the password if it is next
|
||||
if self.is_tag_next(Tags.DEVICE_IDENTIFIER, tstream):
|
||||
self.device_identifier = self.DeviceIdentifier()
|
||||
self.device_identifier.read(tstream)
|
||||
|
||||
# Read the password if it is next
|
||||
if self.is_tag_next(Tags.NETWORK_IDENTIFIER, tstream):
|
||||
self.network_identifier = self.NetworkIdentifier()
|
||||
self.network_identifier.read(tstream)
|
||||
|
||||
# Read the password if it is next
|
||||
if self.is_tag_next(Tags.MACHINE_IDENTIFIER, tstream):
|
||||
self.machine_identifier = self.MachineIdentifier()
|
||||
self.machine_identifier.read(tstream)
|
||||
|
||||
# Read the password if it is next
|
||||
if self.is_tag_next(Tags.MEDIA_IDENTIFIER, tstream):
|
||||
self.media_identifier = self.MediaIdentifier()
|
||||
self.media_identifier.read(tstream)
|
||||
|
||||
self.is_oversized(tstream)
|
||||
self.validate()
|
||||
|
||||
def write(self, ostream):
|
||||
tstream = BytearrayStream()
|
||||
|
||||
if self.device_serial_number is not None:
|
||||
self.device_serial_number.write(tstream)
|
||||
if self.password is not None:
|
||||
self.password.write(tstream)
|
||||
if self.device_identifier is not None:
|
||||
self.device_identifier.write(tstream)
|
||||
if self.network_identifier is not None:
|
||||
self.network_identifier.write(tstream)
|
||||
if self.machine_identifier is not None:
|
||||
self.machine_identifier.write(tstream)
|
||||
if self.media_identifier is not None:
|
||||
self.media_identifier.write(tstream)
|
||||
|
||||
# Write the length and value of the credential
|
||||
self.length = tstream.length()
|
||||
super(self.__class__, self).write(ostream)
|
||||
ostream.write(tstream.buffer)
|
||||
|
||||
def validate(self):
|
||||
pass
|
||||
|
||||
def __init__(self, credential_type=None, credential_value=None):
|
||||
super(self.__class__, self).__init__(tag=Tags.CREDENTIAL)
|
||||
self.credential_type = credential_type
|
||||
self.credential_value = credential_value
|
||||
|
||||
def read(self, istream):
|
||||
super(self.__class__, self).read(istream)
|
||||
tstream = BytearrayStream(istream.read(self.length))
|
||||
|
||||
# Read the type of the credential
|
||||
self.credential_type = self.CredentialType()
|
||||
self.credential_type.read(tstream)
|
||||
|
||||
# Use the type to determine what credential value to read
|
||||
if self.credential_type.enum is CredentialType.USERNAME_AND_PASSWORD:
|
||||
self.credential_value = self.UsernamePasswordCredential()
|
||||
elif self.credential_type.enum is CredentialType.DEVICE:
|
||||
self.credential_value = self.DeviceCredential()
|
||||
else:
|
||||
# TODO (peter-hamilton) Use more descriptive error here
|
||||
raise NotImplementedError()
|
||||
self.credential_value.read(tstream)
|
||||
|
||||
self.is_oversized(tstream)
|
||||
self.validate()
|
||||
|
||||
def write(self, ostream):
|
||||
tstream = BytearrayStream()
|
||||
|
||||
self.credential_type.write(tstream)
|
||||
self.credential_value.write(tstream)
|
||||
|
||||
# Write the length and value of the credential
|
||||
self.length = tstream.length()
|
||||
super(self.__class__, self).write(ostream)
|
||||
ostream.write(tstream.buffer)
|
||||
|
||||
def validate(self):
|
||||
pass
|
||||
|
||||
|
||||
# 2.1.3
|
||||
class KeyBlock(Struct):
|
||||
|
||||
class KeyFormatType(Enumeration):
|
||||
ENUM_TYPE = enums.KeyFormatType
|
||||
|
||||
def __init__(self, value=None):
|
||||
super(self.__class__, self).__init__(value, Tags.KEY_FORMAT_TYPE)
|
||||
|
||||
class KeyCompressionType(Enumeration):
|
||||
ENUM_TYPE = enums.KeyCompressionType
|
||||
|
||||
def __init__(self, value=None):
|
||||
super(self.__class__, self).__init__(value,
|
||||
Tags.KEY_COMPRESSION_TYPE)
|
||||
|
||||
def __init__(self,
|
||||
key_format_type=None,
|
||||
key_compression_type=None,
|
||||
key_value=None,
|
||||
cryptographic_algorithm=None,
|
||||
cryptographic_length=None,
|
||||
key_wrapping_data=None):
|
||||
super(self.__class__, self).__init__(Tags.KEY_BLOCK)
|
||||
self.key_format_type = key_format_type
|
||||
self.key_compression_type = key_compression_type
|
||||
self.key_value = key_value
|
||||
self.cryptographic_algorithm = cryptographic_algorithm
|
||||
self.cryptographic_length = cryptographic_length
|
||||
self.key_wrapping_data = key_wrapping_data
|
||||
self.validate()
|
||||
|
||||
def read(self, istream):
|
||||
super(self.__class__, self).read(istream)
|
||||
tstream = BytearrayStream(istream.read(self.length))
|
||||
|
||||
self.key_format_type = KeyBlock.KeyFormatType()
|
||||
self.key_format_type.read(tstream)
|
||||
key_format_type = self.key_format_type.enum
|
||||
|
||||
if self.is_tag_next(Tags.KEY_COMPRESSION_TYPE, tstream):
|
||||
self.key_compression_type = KeyBlock.KeyCompressionType()
|
||||
self.key_compression_type.read(tstream)
|
||||
|
||||
self.key_value = KeyValue(key_format_type=key_format_type)
|
||||
self.key_value.read(tstream)
|
||||
|
||||
if self.is_tag_next(Tags.CRYPTOGRAPHIC_ALGORITHM, tstream):
|
||||
self.cryptographic_algorithm = attributes.CryptographicAlgorithm()
|
||||
self.cryptographic_algorithm.read(tstream)
|
||||
|
||||
if self.is_tag_next(Tags.CRYPTOGRAPHIC_LENGTH, tstream):
|
||||
self.cryptographic_length = attributes.CryptographicLength()
|
||||
self.cryptographic_length.read(tstream)
|
||||
|
||||
if self.is_tag_next(Tags.KEY_WRAPPING_DATA, tstream):
|
||||
self.key_wrapping_data = KeyWrappingData()
|
||||
self.key_wrapping_data.read(tstream)
|
||||
|
||||
self.is_oversized(tstream)
|
||||
self.validate()
|
||||
|
||||
def write(self, ostream):
|
||||
tstream = BytearrayStream()
|
||||
|
||||
self.key_format_type.write(tstream)
|
||||
|
||||
if self.key_compression_type is not None:
|
||||
self.key_compression_type.write(tstream)
|
||||
|
||||
self.key_value.write(tstream)
|
||||
|
||||
if self.cryptographic_algorithm is not None:
|
||||
self.cryptographic_algorithm.write(tstream)
|
||||
if self.cryptographic_length is not None:
|
||||
self.cryptographic_length.write(tstream)
|
||||
if self.key_wrapping_data is not None:
|
||||
self.key_wrapping_data.write(tstream)
|
||||
|
||||
# Write the length and value of the credential
|
||||
self.length = tstream.length()
|
||||
super(self.__class__, self).write(ostream)
|
||||
ostream.write(tstream.buffer)
|
||||
|
||||
def validate(self):
|
||||
self.__validate()
|
||||
|
||||
def __validate(self):
|
||||
if self.key_format_type is not None:
|
||||
if type(self.key_format_type) is not KeyBlock.KeyFormatType:
|
||||
member = 'KeyBlock.key_format_type'
|
||||
exp_type = KeyBlock.KeyFormatType
|
||||
rcv_type = type(self.key_format_type)
|
||||
msg = ErrorStrings.BAD_EXP_RECV.format(member, 'type',
|
||||
exp_type, rcv_type)
|
||||
raise TypeError(msg)
|
||||
|
||||
|
||||
# 2.1.4
|
||||
class KeyValueString(ByteString):
|
||||
|
||||
def __init__(self, value=None):
|
||||
super(self.__class__, self).__init__(value, Tags.KEY_VALUE)
|
||||
|
||||
|
||||
class KeyValueStruct(Struct):
|
||||
|
||||
def __init__(self,
|
||||
key_format_type=None,
|
||||
key_material=None,
|
||||
attributes=None):
|
||||
super(self.__class__, self).__init__(Tags.KEY_VALUE)
|
||||
self.key_format_type = key_format_type
|
||||
self.key_material = key_material
|
||||
self.attributes = attributes
|
||||
self.key_factory = KeyFactory()
|
||||
self.validate()
|
||||
|
||||
def read(self, istream):
|
||||
super(self.__class__, self).read(istream)
|
||||
tstream = BytearrayStream(istream.read(self.length))
|
||||
|
||||
self.key_material = self.key_factory.create_key(self.key_format_type)
|
||||
self.key_material.read(tstream)
|
||||
|
||||
self.attributes = list()
|
||||
|
||||
# Read the attributes, 0 or more
|
||||
while self.is_tag_next(Tags.ATTRIBUTE, tstream):
|
||||
attribute = Attribute()
|
||||
attribute.read(tstream)
|
||||
self.attributes.append(attribute)
|
||||
|
||||
self.is_oversized(tstream)
|
||||
self.validate()
|
||||
|
||||
def write(self, ostream):
|
||||
tstream = BytearrayStream()
|
||||
|
||||
self.key_material.write(tstream)
|
||||
|
||||
if self.attributes is not None:
|
||||
for attribute in self.attributes:
|
||||
attribute.write(tstream)
|
||||
|
||||
# Write the length and value of the credential
|
||||
self.length = tstream.length()
|
||||
super(self.__class__, self).write(ostream)
|
||||
ostream.write(tstream.buffer)
|
||||
|
||||
def validate(self):
|
||||
self.__validate()
|
||||
|
||||
def __validate(self):
|
||||
# TODO (peter-hamilton) Finish implementation.
|
||||
pass
|
||||
|
||||
|
||||
class KeyValue(Struct):
|
||||
'''
|
||||
KeyValue can be either a ByteString or a Struct. Therefore, this class
|
||||
acts as a wrapper for two different KeyValue objects, KeyValueString,
|
||||
which represents the ByteString format, and KeyValueStruct, which
|
||||
represents the Struct format, both of which are defined above. This
|
||||
KeyValue object does not read or write itself; instead, it reads and
|
||||
writes its internal key_value attribute, which is either a KeyValueString
|
||||
or a KeyValueStruct.
|
||||
|
||||
When reading, the class determines what the format of its internal
|
||||
structure should be by looking at the type of the object it will read
|
||||
using KeyValue.is_type_next(). This is one of the only places in the
|
||||
code where this approach is used.
|
||||
'''
|
||||
|
||||
def __init__(self,
|
||||
key_value=None,
|
||||
key_format_type=None):
|
||||
super(self.__class__, self).__init__(Tags.KEY_VALUE)
|
||||
self.key_value = key_value
|
||||
self.key_format_type = key_format_type
|
||||
if self.key_value is not None:
|
||||
self.type = key_value.type
|
||||
self.validate()
|
||||
|
||||
def read(self, istream):
|
||||
if self.is_type_next(Types.BYTE_STRING, istream):
|
||||
self.key_value = KeyValueString()
|
||||
self.key_value.read(istream)
|
||||
elif self.is_type_next(Types.STRUCTURE, istream):
|
||||
kft = self.key_format_type
|
||||
self.key_value = KeyValueStruct(key_format_type=kft)
|
||||
self.key_value.read(istream)
|
||||
|
||||
def write(self, ostream):
|
||||
tstream = BytearrayStream()
|
||||
self.key_value.write(tstream)
|
||||
ostream.write(tstream.buffer)
|
||||
|
||||
def validate(self):
|
||||
self.__validate()
|
||||
|
||||
def __validate(self):
|
||||
# TODO (peter-hamilton) Finish implementation.
|
||||
pass
|
||||
|
||||
|
||||
# 2.1.5
|
||||
class WrappingMethod(Enumeration):
|
||||
ENUM_TYPE = enums.WrappingMethod
|
||||
|
||||
def __init__(self, value=None):
|
||||
super(WrappingMethod, self).__init__(value, Tags.WRAPPING_METHOD)
|
||||
|
||||
|
||||
class EncodingOption(Enumeration):
|
||||
ENUM_TYPE = enums.EncodingOption
|
||||
|
||||
def __init__(self, value=None):
|
||||
super(WrappingMethod, self).__init__(value, Tags.ENCODING_OPTION)
|
||||
|
||||
|
||||
class KeyInformation(Struct):
|
||||
|
||||
def __init__(self,
|
||||
unique_identifier=None,
|
||||
cryptographic_parameters=None,
|
||||
tag=Tags.ENCRYPTION_KEY_INFORMATION):
|
||||
super(self.__class__, self).\
|
||||
__init__(tag=Tags.ENCRYPTION_KEY_INFORMATION)
|
||||
self.unique_identifier = unique_identifier
|
||||
self.cryptographic_parameters = cryptographic_parameters
|
||||
self.validate()
|
||||
|
||||
def read(self, istream):
|
||||
super(self.__class__, self).read(istream)
|
||||
tstream = BytearrayStream(istream.read(self.length))
|
||||
|
||||
self.unique_identifier = attributes.UniqueIdentifier()
|
||||
self.unique_identifier.read(tstream)
|
||||
|
||||
if self.is_tag_next(Tags.CRYPTOGRAPHIC_PARAMETERS, tstream):
|
||||
self.cryptographic_parameters = CryptographicParameters()
|
||||
self.cryptographic_parameters.read(tstream)
|
||||
|
||||
self.is_oversized(tstream)
|
||||
self.validate()
|
||||
|
||||
def write(self, ostream):
|
||||
tstream = BytearrayStream()
|
||||
|
||||
self.unique_identifier.write(tstream)
|
||||
|
||||
if self.cryptographic_parameters is not None:
|
||||
self.cryptographic_parameters.write(tstream)
|
||||
|
||||
# Write the length and value of the template attribute
|
||||
self.length = tstream.length()
|
||||
super(self.__class__, self).write(ostream)
|
||||
ostream.write(tstream.buffer)
|
||||
|
||||
def validate(self):
|
||||
self.__validate()
|
||||
|
||||
def __validate(self):
|
||||
# TODO (peter-hamilton) Finish implementation.
|
||||
pass
|
||||
|
||||
|
||||
class EncryptionKeyInformation(KeyInformation):
|
||||
|
||||
def __init__(self,
|
||||
unique_identifier=None,
|
||||
cryptographic_parameters=None,
|
||||
tag=Tags.ENCRYPTION_KEY_INFORMATION):
|
||||
super(self.__class__, self).\
|
||||
__init__(unique_identifier, cryptographic_parameters, tag)
|
||||
|
||||
def validate(self):
|
||||
self.__validate()
|
||||
|
||||
def __validate(self):
|
||||
# TODO (peter-hamilton) Finish implementation.
|
||||
pass
|
||||
|
||||
|
||||
class MACSignatureKeyInformation(KeyInformation):
|
||||
|
||||
def __init__(self,
|
||||
unique_identifier=None,
|
||||
cryptographic_parameters=None,
|
||||
tag=Tags.MAC_SIGNATURE_KEY_INFORMATION):
|
||||
super(self.__class__, self).\
|
||||
__init__(unique_identifier, cryptographic_parameters, tag)
|
||||
|
||||
def validate(self):
|
||||
self.__validate()
|
||||
|
||||
def __validate(self):
|
||||
# TODO (peter-hamilton) Finish implementation.
|
||||
pass
|
||||
|
||||
|
||||
class KeyWrappingData(Struct):
|
||||
|
||||
class MACSignature(ByteString):
|
||||
|
||||
def __init__(self, value=None):
|
||||
super(self.__class__, self).__init__(value, Tags.MAC_SIGNATURE)
|
||||
|
||||
class IVCounterNonce(ByteString):
|
||||
|
||||
def __init__(self, value=None):
|
||||
super(self.__class__, self).__init__(value, Tags.IV_COUNTER_NONCE)
|
||||
|
||||
def __init__(self,
|
||||
wrapping_method=None,
|
||||
encryption_key_information=None,
|
||||
mac_signature_key_information=None,
|
||||
mac_signature=None,
|
||||
iv_counter_nonce=None,
|
||||
encoding_option=None):
|
||||
super(self.__class__, self).__init__(Tags.KEY_WRAPPING_DATA)
|
||||
self.wrapping_method = wrapping_method
|
||||
self.encryption_key_information = encryption_key_information
|
||||
self.mac_signature_key_information = mac_signature_key_information
|
||||
self.mac_signature = mac_signature
|
||||
self.iv_counter_nonce = iv_counter_nonce
|
||||
self.encoding_option = encoding_option
|
||||
self.validate()
|
||||
|
||||
def read(self, istream):
|
||||
super(self.__class__, self).read(istream)
|
||||
tstream = BytearrayStream(istream.read(self.length))
|
||||
|
||||
self.wrapping_method = WrappingMethod()
|
||||
self.wrapping_method.read(tstream)
|
||||
|
||||
if self.is_tag_next(Tags.ENCRYPTION_KEY_INFORMATION, tstream):
|
||||
self.encryption_key_information = EncryptionKeyInformation()
|
||||
self.encryption_key_information.read(tstream)
|
||||
|
||||
if self.is_tag_next(Tags.MAC_SIGNATURE_KEY_INFORMATION, tstream):
|
||||
self.mac_signature_key_information = MACSignatureKeyInformation()
|
||||
self.mac_signature_key_information.read(tstream)
|
||||
|
||||
if self.is_tag_next(Tags.MAC_SIGNATURE, tstream):
|
||||
self.mac_signature = KeyWrappingData.MACSignature()
|
||||
self.mac_signature.read(tstream)
|
||||
|
||||
if self.is_tag_next(Tags.IV_COUNTER_NONCE, tstream):
|
||||
self.iv_counter_nonce = KeyWrappingData.IVCounterNonce()
|
||||
self.iv_counter_nonce.read(tstream)
|
||||
|
||||
if self.is_tag_next(Tags.ENCODING_OPTION, tstream):
|
||||
self.encoding_option = EncodingOption()
|
||||
self.encoding_option.read(tstream)
|
||||
|
||||
self.is_oversized(tstream)
|
||||
self.validate()
|
||||
|
||||
def write(self, ostream):
|
||||
tstream = BytearrayStream()
|
||||
|
||||
# Write the contents of the key wrapping data
|
||||
self.wrapping_method.write(tstream)
|
||||
|
||||
if self.encryption_key_information is not None:
|
||||
self.encryption_key_information.write(tstream)
|
||||
if self.mac_signature_key_information is not None:
|
||||
self.mac_signature_key_information.write(tstream)
|
||||
if self.mac_signature is not None:
|
||||
self.mac_signature.write(tstream)
|
||||
if self.iv_counter_nonce is not None:
|
||||
self.iv_counter_nonce.write(tstream)
|
||||
if self.encoding_option is not None:
|
||||
self.encoding_option.write(tstream)
|
||||
|
||||
# Write the length and value of the key wrapping data
|
||||
self.length = tstream.length()
|
||||
super(self.__class__, self).write(ostream)
|
||||
ostream.write(tstream.buffer)
|
||||
|
||||
def validate(self):
|
||||
self.__validate()
|
||||
|
||||
def __validate(self):
|
||||
# TODO (peter-hamilton) Finish implementation
|
||||
pass
|
||||
|
||||
|
||||
# 2.1.6
|
||||
class KeyWrappingSpecification(Struct):
|
||||
|
||||
class AttributeName(TextString):
|
||||
|
||||
def __init__(self, value=None):
|
||||
super(self.__class__, self).__init__(value, Tags.ATTRIBUTE_NAME)
|
||||
|
||||
def __init__(self,
|
||||
wrapping_method=None,
|
||||
encryption_key_information=None,
|
||||
mac_signature_key_information=None,
|
||||
attribute_name=None,
|
||||
encoding_option=None):
|
||||
super(self.__class__, self).\
|
||||
__init__(tag=Tags.KEY_WRAPPING_SPECIFICATION)
|
||||
self.wrapping_method = wrapping_method
|
||||
self.encryption_key_information = encryption_key_information
|
||||
self.mac_signature_key_information = mac_signature_key_information
|
||||
self.attribute_name = attribute_name
|
||||
self.encoding_option = encoding_option
|
||||
|
||||
def read(self, istream):
|
||||
super(self.__class__, self).read(istream)
|
||||
tstream = BytearrayStream(istream.read(self.length))
|
||||
|
||||
self.wrapping_method = WrappingMethod()
|
||||
self.wrapping_method.read(tstream)
|
||||
|
||||
if self.is_tag_next(Tags.ENCRYPTION_KEY_INFORMATION, tstream):
|
||||
self.encryption_key_information = EncryptionKeyInformation()
|
||||
self.encryption_key_information.read(tstream)
|
||||
|
||||
if self.is_tag_next(Tags.MAC_SIGNATURE_KEY_INFORMATION, tstream):
|
||||
self.mac_signature_key_information = MACSignatureKeyInformation()
|
||||
self.mac_signature_key_information.read(tstream)
|
||||
|
||||
if self.is_tag_next(Tags.ATTRIBUTE_NAME, tstream):
|
||||
self.attribute_name = KeyWrappingSpecification.AttributeName()
|
||||
self.attribute_name.read(tstream)
|
||||
|
||||
if self.is_tag_next(Tags.ENCODING_OPTION, tstream):
|
||||
self.encoding_option = EncodingOption()
|
||||
self.encoding_option.read(tstream)
|
||||
|
||||
self.is_oversized(tstream)
|
||||
self.validate()
|
||||
|
||||
def write(self, ostream):
|
||||
tstream = BytearrayStream()
|
||||
|
||||
# Write the contents of the key wrapping data
|
||||
self.wrapping_method.write(tstream)
|
||||
|
||||
if self.encryption_key_information is not None:
|
||||
self.encryption_key_information.write(tstream)
|
||||
if self.mac_signature_key_information is not None:
|
||||
self.mac_signature_key_information.write(tstream)
|
||||
if self.attribute_name is not None:
|
||||
self.attribute_name.write(tstream)
|
||||
if self.encoding_option is not None:
|
||||
self.encoding_option.write(tstream)
|
||||
|
||||
# Write the length and value of the key wrapping data
|
||||
self.length = tstream.length()
|
||||
super(self.__class__, self).write(ostream)
|
||||
ostream.write(tstream.buffer)
|
||||
|
||||
def validate(self):
|
||||
self.__validate()
|
||||
|
||||
def __validate(self):
|
||||
# TODO (peter-hamilton) Finish implementation.
|
||||
pass
|
||||
|
||||
|
||||
# 2.1.8
|
||||
class TemplateAttribute(Struct):
|
||||
|
||||
def __init__(self,
|
||||
names=None,
|
||||
attributes=None):
|
||||
super(self.__class__, self).__init__(tag=Tags.TEMPLATE_ATTRIBUTE)
|
||||
self.names = names
|
||||
self.attributes = attributes
|
||||
self.validate()
|
||||
|
||||
def read(self, istream):
|
||||
super(self.__class__, self).read(istream)
|
||||
tstream = BytearrayStream(istream.read(self.length))
|
||||
|
||||
self.names = list()
|
||||
self.attributes = list()
|
||||
|
||||
# Read the names of the template attribute, 0 or more
|
||||
while self.is_tag_next(Tags.NAME, tstream):
|
||||
name = attributes.Name()
|
||||
name.read(tstream)
|
||||
self.names.append(name)
|
||||
|
||||
# Read the attributes of the template attribute, 0 or more
|
||||
while self.is_tag_next(Tags.ATTRIBUTE, tstream):
|
||||
attribute = Attribute()
|
||||
attribute.read(tstream)
|
||||
self.attributes.append(attribute)
|
||||
|
||||
self.is_oversized(tstream)
|
||||
self.validate()
|
||||
|
||||
def write(self, ostream):
|
||||
tstream = BytearrayStream()
|
||||
|
||||
# Write the names and attributes of the template attribute
|
||||
if self.names is not None:
|
||||
for name in self.names:
|
||||
name.write(tstream)
|
||||
if self.attributes is not None:
|
||||
for attribute in self.attributes:
|
||||
attribute.write(tstream)
|
||||
|
||||
# Write the length and value of the template attribute
|
||||
self.length = tstream.length()
|
||||
super(self.__class__, self).write(ostream)
|
||||
ostream.write(tstream.buffer)
|
||||
|
||||
def validate(self):
|
||||
self.__validate()
|
||||
|
||||
def __validate(self):
|
||||
# TODO (peter-hamilton) Finish implementation.
|
||||
pass
|
618
kmip/core/primitives.py
Normal file
618
kmip/core/primitives.py
Normal file
@ -0,0 +1,618 @@
|
||||
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from struct import pack, unpack
|
||||
from enum import Enum
|
||||
|
||||
from kmip.core.enums import Types
|
||||
from kmip.core.enums import Tags
|
||||
|
||||
from kmip.core.errors import ErrorStrings
|
||||
|
||||
import errors
|
||||
import utils
|
||||
|
||||
|
||||
class Base(object):
|
||||
TAG_SIZE = 3
|
||||
TYPE_SIZE = 1
|
||||
LENGTH_SIZE = 4
|
||||
|
||||
def __init__(self, tag=Tags.DEFAULT, type=Types.DEFAULT):
|
||||
self.tag = tag
|
||||
self.type = type
|
||||
self.length = None
|
||||
|
||||
# TODO (peter-hamilton) Convert this into a classmethod, class name can be
|
||||
# obtained from cls parameter that replaces self
|
||||
def is_oversized(self, stream):
|
||||
extra = len(stream.peek())
|
||||
if extra > 0:
|
||||
raise errors.StreamNotEmptyError(Base.__name__, extra)
|
||||
|
||||
def read_tag(self, istream):
|
||||
# Read in the bytes for the tag
|
||||
tts = istream.read(self.TAG_SIZE)
|
||||
tag = unpack('!I', '\x00' + tts[0:self.TAG_SIZE])[0]
|
||||
|
||||
enum_tag = Tags(tag)
|
||||
|
||||
# Verify that the tag matches for the current object
|
||||
if enum_tag is not self.tag:
|
||||
raise errors.ReadValueError(Base.__name__, 'tag',
|
||||
hex(self.tag.value), hex(tag))
|
||||
|
||||
def read_type(self, istream):
|
||||
# Read in the bytes for the type
|
||||
tts = istream.read(self.TYPE_SIZE)
|
||||
num_bytes = len(tts)
|
||||
if num_bytes != self.TYPE_SIZE:
|
||||
min_bytes = 'a minimum of {0} bytes'.format(self.TYPE_SIZE)
|
||||
raise errors.ReadValueError(Base.__name__, 'type', min_bytes,
|
||||
'{0} bytes'.format(num_bytes))
|
||||
typ = unpack('!B', tts)[0]
|
||||
|
||||
enum_typ = Types(typ)
|
||||
|
||||
if enum_typ is not self.type:
|
||||
raise errors.ReadValueError(Base.__name__, 'type',
|
||||
self.type.value, typ)
|
||||
|
||||
def read_length(self, istream):
|
||||
# Read in the bytes for the length
|
||||
lst = istream.read(self.LENGTH_SIZE)
|
||||
num_bytes = len(lst)
|
||||
if num_bytes != self.LENGTH_SIZE:
|
||||
min_bytes = 'a minimum of {0} bytes'.format(self.LENGTH_SIZE)
|
||||
raise errors.ReadValueError(Base.__name__, 'length', min_bytes,
|
||||
'{0} bytes'.format(num_bytes))
|
||||
length = unpack('!I', lst)[0]
|
||||
|
||||
# Verify that the length matches the expected length, if one exists
|
||||
if self.length is not None:
|
||||
if length is not self.length:
|
||||
raise errors.ReadValueError(Base.__name__, 'length',
|
||||
self.length, length)
|
||||
else:
|
||||
self.length = length
|
||||
|
||||
def read_value(self, istream):
|
||||
raise NotImplementedError()
|
||||
|
||||
def read(self, istream):
|
||||
self.read_tag(istream)
|
||||
self.read_type(istream)
|
||||
self.read_length(istream)
|
||||
|
||||
def write_tag(self, ostream):
|
||||
# Write the tag to the output stream
|
||||
ostream.write(pack('!I', self.tag.value)[1:])
|
||||
|
||||
def write_type(self, ostream):
|
||||
if type(self.type) is not Types:
|
||||
msg = ErrorStrings.BAD_EXP_RECV
|
||||
raise TypeError(msg.format(Base.__name__, 'type',
|
||||
Types, type(self.type)))
|
||||
ostream.write(pack('!B', self.type.value))
|
||||
|
||||
def write_length(self, ostream):
|
||||
if type(self.length) is not int:
|
||||
msg = ErrorStrings.BAD_EXP_RECV
|
||||
raise TypeError(msg.format(Base.__name__, 'length',
|
||||
int, type(self.length)))
|
||||
num_bytes = utils.count_bytes(self.length)
|
||||
if num_bytes > self.LENGTH_SIZE:
|
||||
raise errors.WriteOverflowError(Base.__name__, 'length',
|
||||
self.LENGTH_SIZE, num_bytes)
|
||||
ostream.write(pack('!I', self.length))
|
||||
|
||||
def write_value(self, ostream):
|
||||
raise NotImplementedError()
|
||||
|
||||
def write(self, ostream):
|
||||
self.write_tag(ostream)
|
||||
self.write_type(ostream)
|
||||
self.write_length(ostream)
|
||||
|
||||
def validate(self):
|
||||
raise NotImplementedError()
|
||||
|
||||
@staticmethod
|
||||
def is_tag_next(tag, stream):
|
||||
next_tag = stream.peek(Base.TAG_SIZE)
|
||||
if len(next_tag) != Base.TAG_SIZE:
|
||||
return False
|
||||
next_tag = unpack('!I', '\x00' + next_tag)[0]
|
||||
if next_tag == tag.value:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def is_type_next(kmip_type, stream):
|
||||
tag_type_size = Base.TAG_SIZE + Base.TYPE_SIZE
|
||||
tt = stream.peek(tag_type_size)
|
||||
|
||||
if len(tt) != tag_type_size:
|
||||
return False
|
||||
|
||||
typ = unpack('!B', tt[Base.TAG_SIZE:])[0]
|
||||
|
||||
if typ == kmip_type.value:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
class Struct(Base):
|
||||
|
||||
def __init__(self, tag=Tags.DEFAULT):
|
||||
super(Struct, self).__init__(tag, type=Types.STRUCTURE)
|
||||
|
||||
def __repr__(self):
|
||||
return '<Struct>'
|
||||
|
||||
|
||||
class Integer(Base):
|
||||
LENGTH = 4
|
||||
|
||||
def __init__(self, value=None, tag=Tags.DEFAULT):
|
||||
super(Integer, self).__init__(tag, type=Types.INTEGER)
|
||||
|
||||
self.value = value
|
||||
self.length = self.LENGTH
|
||||
self.padding_length = self.LENGTH
|
||||
|
||||
self.validate()
|
||||
|
||||
def read_value(self, istream):
|
||||
if self.length is not self.LENGTH:
|
||||
raise errors.ReadValueError(Integer.__name__, 'length',
|
||||
self.LENGTH, self.length)
|
||||
|
||||
self.value = unpack('!i', str(istream.read(self.length)))[0]
|
||||
pad = unpack('!i', str(istream.read(self.padding_length)))[0]
|
||||
|
||||
if pad is not 0:
|
||||
raise errors.ReadValueError(Integer.__name__, 'pad', 0,
|
||||
pad)
|
||||
self.validate()
|
||||
|
||||
def read(self, istream):
|
||||
super(Integer, self).read(istream)
|
||||
self.read_value(istream)
|
||||
|
||||
def write_value(self, ostream):
|
||||
ostream.write(pack('!i', self.value))
|
||||
ostream.write(pack('!i', 0))
|
||||
|
||||
def write(self, ostream):
|
||||
super(Integer, self).write(ostream)
|
||||
self.write_value(ostream)
|
||||
|
||||
def validate(self):
|
||||
self.__validate()
|
||||
|
||||
def __validate(self):
|
||||
if self.value is not None:
|
||||
data_type = type(self.value)
|
||||
if data_type is not int:
|
||||
raise errors.StateTypeError(Integer.__name__, int,
|
||||
data_type)
|
||||
num_bytes = utils.count_bytes(self.value)
|
||||
if num_bytes > self.length:
|
||||
raise errors.StateOverflowError(Integer.__name__,
|
||||
'value', self.length,
|
||||
num_bytes)
|
||||
|
||||
def __repr__(self):
|
||||
return '<Integer, %d>' % (self.value)
|
||||
|
||||
|
||||
class LongInteger(Base):
|
||||
LENGTH = 8
|
||||
|
||||
def __init__(self, value=None, tag=Tags.DEFAULT):
|
||||
super(LongInteger, self).__init__(tag, type=Types.LONG_INTEGER)
|
||||
self.value = value
|
||||
self.length = self.LENGTH
|
||||
|
||||
self.validate()
|
||||
|
||||
def read_value(self, istream):
|
||||
if self.length is not self.LENGTH:
|
||||
raise errors.ReadValueError(LongInteger.__name__, 'length',
|
||||
self.LENGTH, self.length)
|
||||
|
||||
self.value = unpack('!q', str(istream.read(self.length)))[0]
|
||||
self.validate()
|
||||
|
||||
def read(self, istream):
|
||||
super(LongInteger, self).read(istream)
|
||||
self.read_value(istream)
|
||||
|
||||
def write_value(self, ostream):
|
||||
ostream.write(pack('!q', self.value))
|
||||
|
||||
def write(self, ostream):
|
||||
super(LongInteger, self).write(ostream)
|
||||
self.write_value(ostream)
|
||||
|
||||
def validate(self):
|
||||
self.__validate()
|
||||
|
||||
def __validate(self):
|
||||
if self.value is not None:
|
||||
data_type = type(self.value)
|
||||
if data_type not in (int, long):
|
||||
raise errors.StateTypeError(LongInteger.__name__,
|
||||
'{0} or {1}'.format(int, long),
|
||||
data_type)
|
||||
num_bytes = utils.count_bytes(self.value)
|
||||
if num_bytes > self.length:
|
||||
raise errors.StateOverflowError(LongInteger.__name__,
|
||||
'value', self.length,
|
||||
num_bytes)
|
||||
|
||||
def __repr__(self):
|
||||
return '<Long Integer, %d>' % (self.value)
|
||||
|
||||
|
||||
class BigInteger(Base):
|
||||
BLOCK_SIZE = 8
|
||||
SHIFT_SIZE = 64
|
||||
|
||||
def __init__(self, value=None, tag=Tags.DEFAULT):
|
||||
super(BigInteger, self).__init__(tag, type=Types.BIG_INTEGER)
|
||||
self.value = value
|
||||
|
||||
if self.value is not None:
|
||||
self.real_length = utils.count_bytes(self.value)
|
||||
self.padding_length = self.BLOCK_SIZE - (self.length %
|
||||
self.BLOCK_SIZE)
|
||||
if self.padding_length == self.BLOCK_SIZE:
|
||||
self.padding_length = 0
|
||||
else:
|
||||
self.length = None
|
||||
self.padding_length = None
|
||||
|
||||
self.validate()
|
||||
|
||||
def read_value(self, istream):
|
||||
if (self.length < self.BLOCK_SIZE) or (self.length % self.BLOCK_SIZE):
|
||||
raise errors.InvalidLengthError(BigInteger.__name__,
|
||||
('multiple'
|
||||
'of {0}'.format(self.BLOCK_SIZE)),
|
||||
self.length)
|
||||
self.value = 0
|
||||
num_blocks = self.length / self.BLOCK_SIZE
|
||||
|
||||
# Read first block as signed data
|
||||
self.value = unpack('!q', str(istream.read(self.BLOCK_SIZE)))[0]
|
||||
|
||||
# Shift current value and add on next unsigned block
|
||||
for _ in xrange(num_blocks - 1):
|
||||
self.value = self.value << self.SHIFT_SIZE
|
||||
stream_data = istream.read(self.BLOCK_SIZE)
|
||||
self.value += unpack('!Q', stream_data)[0]
|
||||
|
||||
self.validate()
|
||||
|
||||
def read(self, istream):
|
||||
super(BigInteger, self).read(istream)
|
||||
self.read_value(istream)
|
||||
|
||||
def write_value(self, ostream):
|
||||
# 1. Determine the sign of the value (+/-); save it.
|
||||
# 2. Extend hex of value with 0s until encoding is right size (8x).
|
||||
# 3. Write out each block of the encoding as signed, 2s complement:
|
||||
# pack('!q', sign * block)
|
||||
|
||||
# Determine sign for padding
|
||||
pad_byte = 0x00
|
||||
pad_nybl = 0x0
|
||||
|
||||
if self.value < 0:
|
||||
pad_byte = 0xff
|
||||
pad_nybl = 0xf
|
||||
|
||||
# Compose padding bytes
|
||||
pad = ''
|
||||
for _ in xrange(self.padding_length):
|
||||
pad += hex(pad_byte)[2:]
|
||||
|
||||
str_rep = hex(self.value).rstrip("Ll")[2:]
|
||||
if len(str_rep) % 2:
|
||||
pad += hex(pad_nybl)[2]
|
||||
|
||||
# Compose value for block-based write
|
||||
str_rep = pad + str_rep
|
||||
num_blocks = len(str_rep) / self.BLOCK_SIZE
|
||||
|
||||
# Write first block as signed data
|
||||
block = int(str_rep[0:self.BLOCK_SIZE], 16)
|
||||
ostream.write(pack('!q', block))
|
||||
|
||||
# Write remaining blocks as unsigned data
|
||||
for i in xrange(1, num_blocks):
|
||||
block = str_rep[(self.BLOCK_SIZE * i):(self.BLOCK_SIZE * (i + 1))]
|
||||
block = int(block, 16)
|
||||
ostream.write(pack('!Q', block))
|
||||
|
||||
def write(self, ostream):
|
||||
super(BigInteger, self).write(ostream)
|
||||
self.write_value(ostream)
|
||||
|
||||
def validate(self):
|
||||
self.__validate()
|
||||
|
||||
def __validate(self):
|
||||
if self.value is not None:
|
||||
data_type = type(self.value)
|
||||
if data_type not in (int, long):
|
||||
raise errors.StateTypeError(BigInteger.__name__,
|
||||
'{0} or {1}'.format(int, long),
|
||||
data_type)
|
||||
num_bytes = utils.count_bytes(self.length)
|
||||
if num_bytes > self.LENGTH_SIZE:
|
||||
raise errors.StateOverflowError(BigInteger.__name__,
|
||||
'length', self.LENGTH_SIZE,
|
||||
num_bytes)
|
||||
|
||||
|
||||
class Enumeration(Integer):
|
||||
ENUM_TYPE = None
|
||||
|
||||
def __init__(self, value=None, tag=Tags.DEFAULT):
|
||||
self.enum = value
|
||||
self.validate()
|
||||
|
||||
if self.enum is None:
|
||||
super(Enumeration, self).__init__(None, tag)
|
||||
else:
|
||||
super(Enumeration, self).__init__(self.enum.value, tag)
|
||||
self.type = Types.ENUMERATION
|
||||
|
||||
def read(self, istream):
|
||||
super(Enumeration, self).read(istream)
|
||||
self.enum = self.ENUM_TYPE(self.value)
|
||||
self.validate()
|
||||
|
||||
def write(self, ostream):
|
||||
super(Enumeration, self).write(ostream)
|
||||
|
||||
def validate(self):
|
||||
self.__validate()
|
||||
|
||||
def __validate(self):
|
||||
if self.enum is not None:
|
||||
if type(self.enum) is not self.ENUM_TYPE:
|
||||
msg = ErrorStrings.BAD_EXP_RECV
|
||||
raise TypeError(msg.format(Enumeration.__name__, 'value',
|
||||
Enum, type(self.enum)))
|
||||
|
||||
def __repr__(self):
|
||||
return '<Enumeration, %s, %d>' % (self.enum.name, self.enum.value)
|
||||
|
||||
|
||||
class Boolean(Base):
|
||||
|
||||
def __init__(self, value=None, tag=Tags.DEFAULT):
|
||||
super(Boolean, self).__init__(tag, type=Types.BOOLEAN)
|
||||
self.value = value
|
||||
self.length = 8
|
||||
|
||||
def read_value(self, istream):
|
||||
value = unpack('!Q', str(istream[0:self.length]))[0]
|
||||
|
||||
if value == 1:
|
||||
self.value = True
|
||||
elif value == 0:
|
||||
self.value = False
|
||||
else:
|
||||
raise errors.ReadValueError(Boolean.__name__, 'value',
|
||||
value)
|
||||
|
||||
for _ in xrange(self.length):
|
||||
istream.pop(0)
|
||||
|
||||
def read(self, istream):
|
||||
super(Boolean, self).read(istream)
|
||||
self.read_value(istream)
|
||||
|
||||
def write_value(self, ostream):
|
||||
if self.value is None:
|
||||
raise errors.WriteValueError(Boolean.__name__, 'value',
|
||||
self.value)
|
||||
|
||||
data_buffer = bytearray()
|
||||
|
||||
if isinstance(self.value, type(True)):
|
||||
if self.value:
|
||||
data_buffer.extend(pack('!Q', 1))
|
||||
else:
|
||||
data_buffer.extend(pack('!Q', 0))
|
||||
else:
|
||||
raise errors.WriteTypeError(Boolean.__name__, 'value',
|
||||
type(self.value))
|
||||
|
||||
ostream.extend(data_buffer)
|
||||
|
||||
def write(self, ostream):
|
||||
super(Boolean, self).write(ostream)
|
||||
self.write_value(ostream)
|
||||
|
||||
def validate(self):
|
||||
self.__validate()
|
||||
|
||||
def __validate(self):
|
||||
pass
|
||||
|
||||
def __repr__(self):
|
||||
return '<Boolean, %s>' % (self.value)
|
||||
|
||||
|
||||
class TextString(Base):
|
||||
PADDING_SIZE = 8
|
||||
BYTE_FORMAT = '!c'
|
||||
|
||||
def __init__(self, value=None, tag=Tags.DEFAULT):
|
||||
super(TextString, self).__init__(tag, type=Types.TEXT_STRING)
|
||||
self.value = value
|
||||
|
||||
self.validate()
|
||||
|
||||
if self.value is not None:
|
||||
self.length = len(self.value)
|
||||
self.padding_length = self.PADDING_SIZE - (self.length %
|
||||
self.PADDING_SIZE)
|
||||
if self.padding_length == self.PADDING_SIZE:
|
||||
self.padding_length = 0
|
||||
else:
|
||||
self.length = None
|
||||
self.padding_length = None
|
||||
|
||||
def read_value(self, istream):
|
||||
# Read string text
|
||||
self.value = ''
|
||||
for _ in xrange(self.length):
|
||||
self.value += unpack(self.BYTE_FORMAT, str(istream.read(1)))[0]
|
||||
|
||||
# Read padding and check content
|
||||
self.padding_length = self.PADDING_SIZE - (self.length %
|
||||
self.PADDING_SIZE)
|
||||
if self.padding_length < self.PADDING_SIZE:
|
||||
for _ in xrange(self.padding_length):
|
||||
pad = unpack('!B', str(istream.read(1)))[0]
|
||||
if pad is not 0:
|
||||
raise errors.ReadValueError(TextString.__name__, 'pad', 0,
|
||||
pad)
|
||||
|
||||
def read(self, istream):
|
||||
super(TextString, self).read(istream)
|
||||
self.read_value(istream)
|
||||
self.validate()
|
||||
|
||||
def write_value(self, ostream):
|
||||
# Write string to stream
|
||||
for char in self.value:
|
||||
ostream.write(pack(self.BYTE_FORMAT, char))
|
||||
|
||||
# Write padding to stream
|
||||
for _ in xrange(self.padding_length):
|
||||
ostream.write(pack('!B', 0))
|
||||
|
||||
def write(self, ostream):
|
||||
super(TextString, self).write(ostream)
|
||||
self.write_value(ostream)
|
||||
|
||||
def validate(self):
|
||||
self.__validate()
|
||||
|
||||
def __validate(self):
|
||||
if self.value is not None:
|
||||
data_type = type(self.value)
|
||||
if data_type is not str:
|
||||
msg = ErrorStrings.BAD_EXP_RECV
|
||||
raise TypeError(msg.format('TextString', 'value', str,
|
||||
data_type))
|
||||
|
||||
def __repr__(self):
|
||||
return '<TextString, %s>' % (self.value)
|
||||
|
||||
|
||||
class ByteString(Base):
|
||||
PADDING_SIZE = 8
|
||||
BYTE_FORMAT = '!B'
|
||||
|
||||
def __init__(self, value=None, tag=Tags.DEFAULT):
|
||||
super(ByteString, self).__init__(tag, type=Types.BYTE_STRING)
|
||||
self.value = value
|
||||
|
||||
self.validate()
|
||||
|
||||
if self.value is not None:
|
||||
self.length = len(self.value)
|
||||
self.padding_length = self.PADDING_SIZE - (self.length %
|
||||
self.PADDING_SIZE)
|
||||
if self.padding_length == self.PADDING_SIZE:
|
||||
self.padding_length = 0
|
||||
else:
|
||||
self.length = None
|
||||
self.padding_length = None
|
||||
|
||||
def read_value(self, istream):
|
||||
# Read bytes into bytearray
|
||||
self.value = bytearray()
|
||||
for _ in xrange(self.length):
|
||||
self.value.append(istream.read(1))
|
||||
|
||||
# Read padding and check content
|
||||
self.padding_length = self.PADDING_SIZE - (self.length %
|
||||
self.PADDING_SIZE)
|
||||
if self.padding_length == self.PADDING_SIZE:
|
||||
self.padding_length = 0
|
||||
|
||||
if self.padding_length < self.PADDING_SIZE:
|
||||
for _ in xrange(self.padding_length):
|
||||
pad = unpack('!B', str(istream.read(1)))[0]
|
||||
if pad is not 0:
|
||||
raise errors.ReadValueError(TextString.__name__, 'pad', 0,
|
||||
pad)
|
||||
|
||||
def read(self, istream):
|
||||
super(ByteString, self).read(istream)
|
||||
self.read_value(istream)
|
||||
|
||||
def write_value(self, ostream):
|
||||
# Write bytes to stream
|
||||
for byte in self.value:
|
||||
ostream.write(pack(self.BYTE_FORMAT, byte))
|
||||
|
||||
# Write padding to stream
|
||||
for _ in xrange(self.padding_length):
|
||||
ostream.write(pack('!B', 0))
|
||||
|
||||
def write(self, ostream):
|
||||
super(ByteString, self).write(ostream)
|
||||
self.write_value(ostream)
|
||||
|
||||
def validate(self):
|
||||
self.__validate()
|
||||
|
||||
def __validate(self):
|
||||
if self.value is not None:
|
||||
data_type = type(self.value)
|
||||
if data_type is not bytearray:
|
||||
msg = ErrorStrings.BAD_EXP_RECV
|
||||
raise TypeError(msg.format('ByteString', 'value', bytearray,
|
||||
data_type))
|
||||
|
||||
def __repr__(self):
|
||||
return '<Integer, %s>' % (self.value)
|
||||
|
||||
|
||||
class DateTime(LongInteger):
|
||||
|
||||
def __init__(self, value=None, tag=Tags.DEFAULT):
|
||||
super(DateTime, self).__init__(value, tag)
|
||||
self.type = Types.DATE_TIME
|
||||
|
||||
|
||||
class Interval(Integer):
|
||||
|
||||
def __init__(self, value=None, tag=Tags.DEFAULT):
|
||||
super(Interval, self).__init__(value, tag)
|
||||
self.type = Types.INTERVAL
|
14
kmip/core/repo/__init__.py
Normal file
14
kmip/core/repo/__init__.py
Normal file
@ -0,0 +1,14 @@
|
||||
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
47
kmip/core/repo/mem_repo.py
Normal file
47
kmip/core/repo/mem_repo.py
Normal file
@ -0,0 +1,47 @@
|
||||
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from kmip.core.repo.repo import ManagedObjectRepo
|
||||
|
||||
|
||||
class MemRepo(ManagedObjectRepo):
|
||||
|
||||
def __init__(self):
|
||||
self.repo = {}
|
||||
self.uuid = 1
|
||||
|
||||
def save(self, managed_object, attributes):
|
||||
# TODO (nate) verify the parameters
|
||||
uuid = "{0}".format(self.uuid)
|
||||
self.repo[uuid] = (managed_object, attributes)
|
||||
self.uuid += 1
|
||||
return uuid
|
||||
|
||||
def get(self, uuid):
|
||||
if uuid is None or uuid not in self.repo:
|
||||
return (None, None)
|
||||
return self.repo[uuid]
|
||||
|
||||
def update(self, uuid, managed_object, attributes):
|
||||
if uuid is None:
|
||||
return False
|
||||
self.repo[uuid] = (managed_object, attributes)
|
||||
return True
|
||||
|
||||
def delete(self, uuid):
|
||||
if uuid is None or uuid not in self.repo:
|
||||
return False
|
||||
del self.repo[uuid]
|
||||
return True
|
73
kmip/core/repo/repo.py
Normal file
73
kmip/core/repo/repo.py
Normal file
@ -0,0 +1,73 @@
|
||||
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
|
||||
class ManagedObjectRepo(object):
|
||||
"""Stores and manages KMIP managed objects.
|
||||
|
||||
The KMIP specification details the managed objects that are stored by a
|
||||
KMIP server. This repository abstraction is an interface for KMIP servers
|
||||
to store managed objects.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def save(self, managed_object, attributes):
|
||||
"""Save a managed object
|
||||
|
||||
This saves a managed object into the repository and returns a UUID
|
||||
string that can be used to reference the object in the repository.
|
||||
:param managed_object: managed object to save from secrets.py
|
||||
:param attributes: attributes to store with the managed object
|
||||
:returns: a UUID string that can be used to retrieve the object later
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def get(self, uuid):
|
||||
"""Retrieve a managed object
|
||||
|
||||
Retrieve a managed object from the repository. The UUID is used to
|
||||
identify the managed object to return. The UUID is returned from the
|
||||
save call.
|
||||
|
||||
A tuple is returned that contains the managed object and all of its
|
||||
attributes.
|
||||
:param uuid: UUID of the managed object
|
||||
:returns: (managed_object, attributes) if object exists, otherwise
|
||||
(None, None)
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def update(self, uuid, managed_object, attributes):
|
||||
"""Updates a managed object
|
||||
|
||||
Updates the values for a managed_object.
|
||||
:param uuid: UUID of the managed object
|
||||
:param managed_object: managed object
|
||||
:param attributes: attributes to store with the managed object
|
||||
:returns: True if object existed and successfully updated, otherwise
|
||||
False
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def delete(self, uuid):
|
||||
"""Delete a managed object from the repository
|
||||
|
||||
Delete a managed object from the repository.
|
||||
:param uuid: UUID of the managed object
|
||||
:returns: True if successfully deleted, False if not found
|
||||
"""
|
||||
raise NotImplementedError
|
408
kmip/core/secrets.py
Normal file
408
kmip/core/secrets.py
Normal file
@ -0,0 +1,408 @@
|
||||
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from kmip.core.attributes import CertificateType
|
||||
|
||||
from kmip.core import enums
|
||||
from kmip.core.enums import Tags
|
||||
|
||||
from kmip.core.objects import Attribute
|
||||
from kmip.core.objects import KeyBlock
|
||||
|
||||
from kmip.core.primitives import Struct
|
||||
from kmip.core.primitives import Integer
|
||||
from kmip.core.primitives import Enumeration
|
||||
from kmip.core.primitives import BigInteger
|
||||
from kmip.core.primitives import ByteString
|
||||
|
||||
from kmip.core.utils import BytearrayStream
|
||||
|
||||
|
||||
# 2.2
|
||||
# 2.2.1
|
||||
class Certificate(Struct):
|
||||
|
||||
class CertificateValue(ByteString):
|
||||
|
||||
def __init__(self, value=None):
|
||||
super(self.__class__, self).__init__(value,
|
||||
Tags.CERTIFICATE_VALUE)
|
||||
|
||||
def __init__(self,
|
||||
certificate_type=None,
|
||||
certificate_value=None):
|
||||
super(self.__class__, self).__init__(Tags.CERTIFICATE)
|
||||
self.certificate_type = certificate_type
|
||||
self.certificate_value = certificate_value
|
||||
self.validate()
|
||||
|
||||
def read(self, istream):
|
||||
super(self.__class__, self).read(istream)
|
||||
tstream = BytearrayStream(istream.read(self.length))
|
||||
|
||||
self.certificate_type = CertificateType()
|
||||
self.certificate_value = Certificate.CertificateValue()
|
||||
|
||||
self.certificate_type.read(tstream)
|
||||
self.certificate_value.read(tstream)
|
||||
|
||||
self.is_oversized(tstream)
|
||||
self.validate()
|
||||
|
||||
def write(self, ostream):
|
||||
tstream = BytearrayStream()
|
||||
|
||||
# Write the details of the certificate
|
||||
self.certificate_type.write(tstream)
|
||||
self.certificate_value.write(tstream)
|
||||
|
||||
# Write the length and value of the template attribute
|
||||
self.length = tstream.length()
|
||||
super(self.__class__, self).write(ostream)
|
||||
ostream.write(tstream.buffer)
|
||||
|
||||
def validate(self):
|
||||
self.__validate()
|
||||
|
||||
def __validate(self):
|
||||
# TODO (peter-hamilton) Finish implementation.
|
||||
pass
|
||||
|
||||
|
||||
# 2.2.2
|
||||
class KeyBlockKey(Struct):
|
||||
|
||||
def __init__(self, key_block=None, tag=Tags.DEFAULT):
|
||||
super(KeyBlockKey, self).__init__(tag)
|
||||
self.key_block = key_block
|
||||
self.validate()
|
||||
|
||||
def read(self, istream):
|
||||
super(KeyBlockKey, self).read(istream)
|
||||
tstream = BytearrayStream(istream.read(self.length))
|
||||
|
||||
self.key_block = KeyBlock()
|
||||
self.key_block.read(tstream)
|
||||
|
||||
self.is_oversized(tstream)
|
||||
self.validate()
|
||||
|
||||
def write(self, ostream):
|
||||
tstream = BytearrayStream()
|
||||
|
||||
self.key_block.write(tstream)
|
||||
|
||||
# Write the length and value of the template attribute
|
||||
self.length = tstream.length()
|
||||
super(KeyBlockKey, self).write(ostream)
|
||||
ostream.write(tstream.buffer)
|
||||
|
||||
def validate(self):
|
||||
self.__validate()
|
||||
|
||||
def __validate(self):
|
||||
# TODO (peter-hamilton) Finish implementation.
|
||||
pass
|
||||
|
||||
|
||||
class SymmetricKey(KeyBlockKey):
|
||||
|
||||
def __init__(self, key_block=None):
|
||||
super(self.__class__, self).__init__(key_block, Tags.SYMMETRIC_KEY)
|
||||
self.validate()
|
||||
|
||||
def validate(self):
|
||||
self.__validate()
|
||||
|
||||
def __validate(self):
|
||||
# TODO (peter-hamilton) Finish implementation.
|
||||
pass
|
||||
|
||||
|
||||
# 2.2.3
|
||||
class PublicKey(KeyBlockKey):
|
||||
|
||||
def __init__(self, key_block=None):
|
||||
super(self.__class__, self).__init__(key_block, Tags.PUBLIC_KEY)
|
||||
self.validate()
|
||||
|
||||
def validate(self):
|
||||
self.__validate()
|
||||
|
||||
def __validate(self):
|
||||
# TODO (peter-hamilton) Finish implementation.
|
||||
pass
|
||||
|
||||
|
||||
# 2.2.4
|
||||
class PrivateKey(KeyBlockKey):
|
||||
|
||||
def __init__(self, key_block=None):
|
||||
super(self.__class__, self).__init__(key_block, Tags.PRIVATE_KEY)
|
||||
self.validate()
|
||||
|
||||
def validate(self):
|
||||
self.__validate()
|
||||
|
||||
def __validate(self):
|
||||
# TODO (peter-hamilton) Finish implementation.
|
||||
pass
|
||||
|
||||
|
||||
# 2.2.5
|
||||
class SplitKey(Struct):
|
||||
|
||||
class SplitKeyParts(Integer):
|
||||
|
||||
def __init__(self, value=None):
|
||||
super(self.__class__, self).__init__(value,
|
||||
Tags.SPLIT_KEY_PARTS)
|
||||
|
||||
class KeyPartIdentifier(Integer):
|
||||
|
||||
def __init__(self, value=None):
|
||||
super(self.__class__, self).__init__(value,
|
||||
Tags.KEY_PART_IDENTIFIER)
|
||||
|
||||
class SplitKeyThreshold(Integer):
|
||||
|
||||
def __init__(self, value=None):
|
||||
super(self.__class__, self).__init__(value,
|
||||
Tags.SPLIT_KEY_THRESHOLD)
|
||||
|
||||
class SplitKeyMethod(Enumeration):
|
||||
ENUM_TYPE = enums.SplitKeyMethod
|
||||
|
||||
def __init__(self, value=None):
|
||||
super(self.__class__, self).__init__(value,
|
||||
Tags.SPLIT_KEY_METHOD)
|
||||
|
||||
class PrimeFieldSize(BigInteger):
|
||||
|
||||
def __init__(self, value=None):
|
||||
super(self.__class__, self).__init__(value,
|
||||
Tags.PRIME_FIELD_SIZE)
|
||||
|
||||
def __init__(self,
|
||||
split_key_parts=None,
|
||||
key_part_identifier=None,
|
||||
split_key_threshold=None,
|
||||
split_key_method=None,
|
||||
prime_field_size=None,
|
||||
key_block=None):
|
||||
super(self.__class__, self).__init__(Tags.SPLIT_KEY)
|
||||
self.split_key_parts = split_key_parts
|
||||
self.key_part_identifier = key_part_identifier
|
||||
self.split_key_threshold = split_key_threshold
|
||||
self.split_key_method = split_key_method
|
||||
self.prime_field_size = prime_field_size
|
||||
self.key_block = key_block
|
||||
self.validate()
|
||||
|
||||
def read(self, istream):
|
||||
super(self.__class__, self).read(istream)
|
||||
tstream = BytearrayStream(istream.read(self.length))
|
||||
|
||||
self.split_key_parts = SplitKey.SplitKeyParts()
|
||||
self.split_key_parts.read(tstream)
|
||||
|
||||
self.key_part_identifier = SplitKey.KeyPartIdentifier()
|
||||
self.key_part_identifier.read(tstream)
|
||||
|
||||
self.split_key_threshold = SplitKey.SplitKeyThreshold()
|
||||
self.split_key_threshold.read(tstream)
|
||||
|
||||
if self.is_tag_next(Tags.PRIME_FIELD_SIZE, tstream):
|
||||
self.prime_field_size = SplitKey.PrimeFieldSize()
|
||||
self.prime_field_size.read(tstream)
|
||||
|
||||
self.key_block = KeyBlock()
|
||||
self.key_block.read(tstream)
|
||||
|
||||
self.is_oversized(tstream)
|
||||
self.validate()
|
||||
|
||||
def write(self, ostream):
|
||||
tstream = BytearrayStream()
|
||||
|
||||
self.split_key_parts.write(tstream)
|
||||
self.key_part_identifier.write(tstream)
|
||||
self.split_key_threshold.write(tstream)
|
||||
self.split_key_method.write(tstream)
|
||||
|
||||
if self.prime_field_size is not None:
|
||||
self.prime_field_size.write(tstream)
|
||||
|
||||
self.key_block.write(tstream)
|
||||
|
||||
# Write the length and value of the template attribute
|
||||
self.length = tstream.length()
|
||||
super(self.__class__, self).write(ostream)
|
||||
ostream.write(tstream.buffer)
|
||||
|
||||
def validate(self):
|
||||
self.__validate()
|
||||
|
||||
def __validate(self):
|
||||
# TODO (peter-hamilton) Finish implementation.
|
||||
pass
|
||||
|
||||
|
||||
# 2.2.6
|
||||
class Template(Struct):
|
||||
|
||||
def __init__(self, attributes=None):
|
||||
super(self.__class__, self).__init__(Tags.TEMPLATE)
|
||||
self.attributes = attributes
|
||||
self.validate()
|
||||
|
||||
def read(self, istream):
|
||||
super(self.__class__, self).read(istream)
|
||||
tstream = BytearrayStream(istream.read(self.length))
|
||||
|
||||
self.attributes = list()
|
||||
|
||||
attribute = Attribute()
|
||||
attribute.read(tstream)
|
||||
self.attributes.append(attribute)
|
||||
|
||||
while self.is_tag_next(Tags.ATTRIBUTE, tstream):
|
||||
attribute = Attribute()
|
||||
attribute.read(tstream)
|
||||
self.attributes.append(attribute)
|
||||
|
||||
self.is_oversized(tstream)
|
||||
self.validate()
|
||||
|
||||
def write(self, ostream):
|
||||
tstream = BytearrayStream()
|
||||
|
||||
for attribute in self.attributes:
|
||||
attribute.write(tstream)
|
||||
|
||||
# Write the length and value of the template attribute
|
||||
self.length = tstream.length()
|
||||
super(self.__class__, self).write(ostream)
|
||||
ostream.write(tstream.buffer)
|
||||
|
||||
def validate(self):
|
||||
self.__validate()
|
||||
|
||||
def __validate(self):
|
||||
# TODO (peter-hamilton) Finish implementation.
|
||||
pass
|
||||
|
||||
|
||||
# 2.2.7
|
||||
class SecretData(Struct):
|
||||
|
||||
class SecretDataType(Enumeration):
|
||||
ENUM_TYPE = enums.SecretDataType
|
||||
|
||||
def __init__(self, value=None):
|
||||
super(self.__class__, self).__init__(value, Tags.SECRET_DATA_TYPE)
|
||||
|
||||
def __init__(self,
|
||||
secret_data_type=None,
|
||||
key_block=None):
|
||||
super(self.__class__, self).__init__(Tags.SECRET_DATA)
|
||||
self.secret_data_type = secret_data_type
|
||||
self.key_block = key_block
|
||||
self.validate()
|
||||
|
||||
def read(self, istream):
|
||||
super(self.__class__, self).read(istream)
|
||||
tstream = BytearrayStream(istream.read(self.length))
|
||||
|
||||
self.secret_data_type = SecretData.SecretDataType()
|
||||
self.key_block = KeyBlock()
|
||||
|
||||
self.secret_data_type.read(tstream)
|
||||
self.key_block.read(tstream)
|
||||
|
||||
self.is_oversized(tstream)
|
||||
self.validate()
|
||||
|
||||
def write(self, ostream):
|
||||
tstream = BytearrayStream()
|
||||
|
||||
self.secret_data_type.write(tstream)
|
||||
self.key_block.write(tstream)
|
||||
|
||||
# Write the length and value of the template attribute
|
||||
self.length = tstream.length()
|
||||
super(self.__class__, self).write(ostream)
|
||||
ostream.write(tstream.buffer)
|
||||
|
||||
def validate(self):
|
||||
self.__validate()
|
||||
|
||||
def __validate(self):
|
||||
# TODO (peter-hamilton) Finish implementation.
|
||||
pass
|
||||
|
||||
|
||||
# 2.2.8
|
||||
class OpaqueObject(Struct):
|
||||
|
||||
class OpaqueDataType(Enumeration):
|
||||
ENUM_TYPE = enums.OpaqueDataType
|
||||
|
||||
def __init__(self, value=None):
|
||||
super(self.__class__, self).__init__(value, Tags.OPAQUE_DATA_TYPE)
|
||||
|
||||
class OpaqueDataValue(ByteString):
|
||||
|
||||
def __init__(self, value=None):
|
||||
super(self.__class__, self).__init__(value, Tags.OPAQUE_DATA_VALUE)
|
||||
|
||||
def __init__(self,
|
||||
opaque_data_type=None,
|
||||
opaque_data_value=None):
|
||||
super(self.__class__, self).__init__(Tags.OPAQUE_OBJECT)
|
||||
self.opaque_data_type = opaque_data_type
|
||||
self.opaque_data_value = opaque_data_value
|
||||
self.validate()
|
||||
|
||||
def read(self, istream):
|
||||
super(self.__class__, self).read(istream)
|
||||
tstream = BytearrayStream(istream.read(self.length))
|
||||
|
||||
self.opaque_data_type = OpaqueObject.OpaqueDataType()
|
||||
self.opaque_data_value = OpaqueObject.OpaqueDataValue()
|
||||
|
||||
self.opaque_data_type.read(tstream)
|
||||
self.opaque_data_value.read(tstream)
|
||||
|
||||
self.is_oversized(tstream)
|
||||
self.validate()
|
||||
|
||||
def write(self, ostream):
|
||||
tstream = BytearrayStream()
|
||||
|
||||
self.opaque_data_type.write(tstream)
|
||||
self.opaque_data_value.write(tstream)
|
||||
|
||||
# Write the length and value of the template attribute
|
||||
self.length = tstream.length()
|
||||
super(self.__class__, self).write(ostream)
|
||||
ostream.write(tstream.buffer)
|
||||
|
||||
def validate(self):
|
||||
self.__validate()
|
||||
|
||||
def __validate(self):
|
||||
# TODO (peter-hamilton) Finish implementation.
|
||||
pass
|
357
kmip/core/server.py
Normal file
357
kmip/core/server.py
Normal file
@ -0,0 +1,357 @@
|
||||
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import logging
|
||||
import os
|
||||
|
||||
from kmip.core.attributes import CryptographicLength
|
||||
from kmip.core.attributes import CryptographicAlgorithm
|
||||
from kmip.core.attributes import ObjectType
|
||||
from kmip.core.attributes import UniqueIdentifier
|
||||
from kmip.core.enums import AttributeType as AT
|
||||
from kmip.core.enums import CryptographicAlgorithm as CA
|
||||
from kmip.core.enums import KeyFormatType as KeyFormatTypeEnum
|
||||
from kmip.core.enums import ObjectType as OT
|
||||
from kmip.core.enums import ResultReason as ResultReasonEnum
|
||||
from kmip.core.enums import ResultStatus as RS
|
||||
from kmip.core.factories.attributes import AttributeFactory
|
||||
from kmip.core.factories.keys import KeyFactory
|
||||
from kmip.core.factories.secrets import SecretFactory
|
||||
from kmip.core.keys import RawKey
|
||||
|
||||
from kmip.core.messages.contents import KeyFormatType
|
||||
from kmip.core.messages.contents import ResultStatus
|
||||
from kmip.core.messages.contents import ResultReason
|
||||
from kmip.core.messages.contents import ResultMessage
|
||||
|
||||
from kmip.core.objects import KeyBlock
|
||||
from kmip.core.objects import KeyValue
|
||||
from kmip.core.objects import KeyValueStruct
|
||||
from kmip.core.objects import TemplateAttribute
|
||||
from kmip.core.repo.mem_repo import MemRepo
|
||||
from kmip.core.secrets import SymmetricKey
|
||||
from kmip.services.results import CreateResult
|
||||
from kmip.services.results import DestroyResult
|
||||
from kmip.services.results import GetResult
|
||||
from kmip.services.results import OperationResult
|
||||
from kmip.services.results import RegisterResult
|
||||
|
||||
|
||||
class KMIP(object):
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def create(self, object_type, template_attribute, credential=None):
|
||||
raise NotImplementedError
|
||||
|
||||
def register(self, object_type, template_attribute, secret,
|
||||
credential=None):
|
||||
raise NotImplementedError
|
||||
|
||||
def get(self, uuid=None, key_format_type=None, key_compression_type=None,
|
||||
key_wrapping_specification=None, credential=None):
|
||||
raise NotImplementedError
|
||||
|
||||
def destroy(self, uuid, credential=None):
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
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 _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(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
|
||||
|
||||
|
||||
class InvalidFieldException(Exception):
|
||||
|
||||
def __init__(self, result):
|
||||
super(self.__class__, self).__init__()
|
||||
self.result = result
|
97
kmip/core/utils.py
Normal file
97
kmip/core/utils.py
Normal file
@ -0,0 +1,97 @@
|
||||
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from binascii import hexlify
|
||||
|
||||
from kmip.core.errors import ErrorStrings
|
||||
|
||||
|
||||
def bit_length(num):
|
||||
s = bin(num)
|
||||
s = s.lstrip('0b')
|
||||
return len(s)
|
||||
|
||||
|
||||
def count_bytes(num):
|
||||
bits = bit_length(num)
|
||||
num_bytes = bits / 8
|
||||
if bits == 0 or bits % 8:
|
||||
num_bytes += 1
|
||||
return num_bytes
|
||||
|
||||
|
||||
def print_bytearray(array):
|
||||
sbuffer = hexlify_bytearray(array)
|
||||
print 'buffer: {0}'.format(sbuffer)
|
||||
|
||||
|
||||
def hexlify_bytearray(array):
|
||||
sbuffer = bytes(array[0:])
|
||||
return hexlify(sbuffer)
|
||||
|
||||
|
||||
def is_stream_empty(stream):
|
||||
if len(stream.peek(1)) > 0:
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
|
||||
def build_er_error(class_object, descriptor, expected, received,
|
||||
attribute=None):
|
||||
msg = ErrorStrings.BAD_EXP_RECV
|
||||
|
||||
class_string = ''
|
||||
if attribute is None:
|
||||
class_string = '{0}'.format(class_object.__name__)
|
||||
else:
|
||||
class_string = '{0}.{1}'.format(class_object.__name__, attribute)
|
||||
|
||||
return msg.format(class_string, descriptor, expected, received)
|
||||
|
||||
|
||||
class BytearrayStream(object):
|
||||
def __init__(self, data=None):
|
||||
if data is None:
|
||||
self.buffer = bytearray()
|
||||
else:
|
||||
self.buffer = bytearray(data)
|
||||
|
||||
def read(self, n=None):
|
||||
if n is None:
|
||||
return str(self.buffer[0:])
|
||||
|
||||
length = len(self.buffer)
|
||||
if n > length:
|
||||
n = length
|
||||
|
||||
data = self.buffer[0:n]
|
||||
for _ in xrange(n):
|
||||
self.buffer.pop(0)
|
||||
return str(data)
|
||||
|
||||
def peek(self, n=None):
|
||||
length = len(self.buffer)
|
||||
if n is None or n > length:
|
||||
n = length
|
||||
return str(self.buffer[0:n])
|
||||
|
||||
def write(self, b):
|
||||
prev_bytes = len(self.buffer)
|
||||
self.buffer.extend(b)
|
||||
return len(self.buffer) - prev_bytes
|
||||
|
||||
def length(self):
|
||||
return len(self.buffer)
|
14
kmip/demos/__init__.py
Normal file
14
kmip/demos/__init__.py
Normal file
@ -0,0 +1,14 @@
|
||||
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
69
kmip/demos/create.py
Normal file
69
kmip/demos/create.py
Normal file
@ -0,0 +1,69 @@
|
||||
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from kmip.core.enums import AttributeType
|
||||
from kmip.core.enums import CredentialType
|
||||
from kmip.core.enums import ObjectType
|
||||
from kmip.core.enums import CryptographicAlgorithm
|
||||
from kmip.core.enums import CryptographicUsageMask
|
||||
|
||||
from kmip.core.factories.attributes import AttributeFactory
|
||||
from kmip.core.factories.credentials import CredentialFactory
|
||||
|
||||
from kmip.core.objects import TemplateAttribute
|
||||
|
||||
from kmip.services.kmip_client import KMIPProxy
|
||||
|
||||
import logging
|
||||
import os
|
||||
|
||||
if __name__ == '__main__':
|
||||
f_log = os.path.join(os.path.dirname(__file__), '..', 'logconfig.ini')
|
||||
logging.config.fileConfig(f_log)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
attribute_factory = AttributeFactory()
|
||||
credential_factory = CredentialFactory()
|
||||
|
||||
credential_type = CredentialType.USERNAME_AND_PASSWORD
|
||||
credential_value = {'Username': 'Peter', 'Password': 'abc123'}
|
||||
credential = credential_factory.create_credential(credential_type,
|
||||
credential_value)
|
||||
|
||||
client = KMIPProxy()
|
||||
client.open()
|
||||
|
||||
object_type = ObjectType.SYMMETRIC_KEY
|
||||
attribute_type = AttributeType.CRYPTOGRAPHIC_ALGORITHM
|
||||
algorithm = attribute_factory.create_attribute(attribute_type,
|
||||
CryptographicAlgorithm.AES)
|
||||
mask_flags = [CryptographicUsageMask.ENCRYPT,
|
||||
CryptographicUsageMask.DECRYPT]
|
||||
attribute_type = AttributeType.CRYPTOGRAPHIC_USAGE_MASK
|
||||
usage_mask = attribute_factory.create_attribute(attribute_type,
|
||||
mask_flags)
|
||||
attributes = [algorithm, usage_mask]
|
||||
template_attribute = TemplateAttribute(attributes=attributes)
|
||||
|
||||
result = client.create(object_type, template_attribute,
|
||||
credential)
|
||||
client.close()
|
||||
|
||||
logger.debug('create() result status: {}'.format(
|
||||
result.result_status.enum))
|
||||
logger.debug('created object type: {}'.format(result.object_type.enum))
|
||||
logger.debug('created UUID: {}'.format(result.uuid.value))
|
||||
logger.debug('created template attribute: {}'.
|
||||
format(result.template_attribute))
|
70
kmip/demos/destroy.py
Normal file
70
kmip/demos/destroy.py
Normal file
@ -0,0 +1,70 @@
|
||||
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from kmip.core.enums import AttributeType
|
||||
from kmip.core.enums import CredentialType
|
||||
from kmip.core.enums import ObjectType
|
||||
from kmip.core.enums import CryptographicAlgorithm
|
||||
from kmip.core.enums import CryptographicUsageMask
|
||||
|
||||
from kmip.core.factories.attributes import AttributeFactory
|
||||
from kmip.core.factories.credentials import CredentialFactory
|
||||
|
||||
from kmip.core.objects import TemplateAttribute
|
||||
|
||||
from kmip.services.kmip_client import KMIPProxy
|
||||
|
||||
import logging
|
||||
import os
|
||||
|
||||
if __name__ == '__main__':
|
||||
f_log = os.path.join(os.path.dirname(__file__), '..', 'logconfig.ini')
|
||||
logging.config.fileConfig(f_log)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
attribute_factory = AttributeFactory()
|
||||
credential_factory = CredentialFactory()
|
||||
|
||||
credential_type = CredentialType.USERNAME_AND_PASSWORD
|
||||
credential_value = {'Username': 'Peter', 'Password': 'abc123'}
|
||||
credential = credential_factory.create_credential(credential_type,
|
||||
credential_value)
|
||||
client = KMIPProxy()
|
||||
client.open()
|
||||
|
||||
# Create a SYMMETRIC_KEY object
|
||||
object_type = ObjectType.SYMMETRIC_KEY
|
||||
attribute_type = AttributeType.CRYPTOGRAPHIC_ALGORITHM
|
||||
algorithm = attribute_factory.create_attribute(attribute_type,
|
||||
CryptographicAlgorithm.AES)
|
||||
mask_flags = [CryptographicUsageMask.ENCRYPT,
|
||||
CryptographicUsageMask.DECRYPT]
|
||||
attribute_type = AttributeType.CRYPTOGRAPHIC_USAGE_MASK
|
||||
usage_mask = attribute_factory.create_attribute(attribute_type,
|
||||
mask_flags)
|
||||
attributes = [algorithm, usage_mask]
|
||||
template_attribute = TemplateAttribute(attributes=attributes)
|
||||
|
||||
result = client.create(object_type, template_attribute,
|
||||
credential)
|
||||
uuid = result.uuid.value
|
||||
|
||||
# Destroy the SYMMETRIC_KEY object
|
||||
result = client.destroy(uuid, credential)
|
||||
client.close()
|
||||
|
||||
logger.debug('destroy() result status: {}'.format(
|
||||
result.result_status.enum))
|
||||
logger.debug('destroyed UUID: {}'.format(result.uuid.value))
|
69
kmip/demos/get.py
Normal file
69
kmip/demos/get.py
Normal file
@ -0,0 +1,69 @@
|
||||
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from kmip.core.enums import AttributeType
|
||||
from kmip.core.enums import CredentialType
|
||||
from kmip.core.enums import ObjectType
|
||||
from kmip.core.enums import CryptographicAlgorithm
|
||||
from kmip.core.enums import CryptographicUsageMask
|
||||
|
||||
from kmip.core.factories.attributes import AttributeFactory
|
||||
from kmip.core.factories.credentials import CredentialFactory
|
||||
|
||||
from kmip.core.objects import TemplateAttribute
|
||||
|
||||
from kmip.services.kmip_client import KMIPProxy
|
||||
|
||||
import logging
|
||||
import os
|
||||
|
||||
if __name__ == '__main__':
|
||||
f_log = os.path.join(os.path.dirname(__file__), '..', 'logconfig.ini')
|
||||
logging.config.fileConfig(f_log)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
attribute_factory = AttributeFactory()
|
||||
credential_factory = CredentialFactory()
|
||||
|
||||
credential_type = CredentialType.USERNAME_AND_PASSWORD
|
||||
credential_value = {'Username': 'Peter', 'Password': 'abc123'}
|
||||
credential = credential_factory.create_credential(credential_type,
|
||||
credential_value)
|
||||
client = KMIPProxy()
|
||||
client.open()
|
||||
|
||||
object_type = ObjectType.SYMMETRIC_KEY
|
||||
attribute_type = AttributeType.CRYPTOGRAPHIC_ALGORITHM
|
||||
algorithm = attribute_factory.create_attribute(attribute_type,
|
||||
CryptographicAlgorithm.AES)
|
||||
mask_flags = [CryptographicUsageMask.ENCRYPT,
|
||||
CryptographicUsageMask.DECRYPT]
|
||||
attribute_type = AttributeType.CRYPTOGRAPHIC_USAGE_MASK
|
||||
usage_mask = attribute_factory.create_attribute(attribute_type,
|
||||
mask_flags)
|
||||
attributes = [algorithm, usage_mask]
|
||||
template_attribute = TemplateAttribute(attributes=attributes)
|
||||
|
||||
result = client.create(object_type, template_attribute,
|
||||
credential)
|
||||
uuid = result.uuid.value
|
||||
|
||||
result = client.get(uuid, credential)
|
||||
client.close()
|
||||
|
||||
logger.debug('get() result status: {}'.format(result.result_status.enum))
|
||||
logger.debug('retrieved object type: {}'.format(result.object_type.enum))
|
||||
logger.debug('retrieved UUID: {}'.format(result.uuid.value))
|
||||
logger.debug('retrieved secret: {}'.format(result.secret))
|
84
kmip/demos/register.py
Normal file
84
kmip/demos/register.py
Normal file
@ -0,0 +1,84 @@
|
||||
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from kmip.core.enums import AttributeType
|
||||
from kmip.core.enums import CredentialType
|
||||
from kmip.core.enums import CryptographicAlgorithm
|
||||
from kmip.core.enums import CryptographicUsageMask
|
||||
from kmip.core.enums import KeyFormatType
|
||||
from kmip.core.enums import ObjectType
|
||||
|
||||
from kmip.core.factories.attributes import AttributeFactory
|
||||
from kmip.core.factories.credentials import CredentialFactory
|
||||
from kmip.core.factories.secrets import SecretFactory
|
||||
|
||||
from kmip.core.objects import TemplateAttribute
|
||||
|
||||
from kmip.services.kmip_client import KMIPProxy
|
||||
|
||||
import logging
|
||||
import os
|
||||
|
||||
if __name__ == '__main__':
|
||||
f_log = os.path.join(os.path.dirname(__file__), '..', 'logconfig.ini')
|
||||
logging.config.fileConfig(f_log)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
attribute_factory = AttributeFactory()
|
||||
credential_factory = CredentialFactory()
|
||||
secret_factory = SecretFactory()
|
||||
|
||||
credential_type = CredentialType.USERNAME_AND_PASSWORD
|
||||
credential_value = {'Username': 'Peter', 'Password': 'abc123'}
|
||||
credential = credential_factory.create_credential(credential_type,
|
||||
credential_value)
|
||||
client = KMIPProxy()
|
||||
client.open()
|
||||
|
||||
object_type = ObjectType.SYMMETRIC_KEY
|
||||
algorithm_value = CryptographicAlgorithm.AES
|
||||
|
||||
mask_flags = [CryptographicUsageMask.ENCRYPT,
|
||||
CryptographicUsageMask.DECRYPT]
|
||||
attribute_type = AttributeType.CRYPTOGRAPHIC_USAGE_MASK
|
||||
usage_mask = attribute_factory.create_attribute(attribute_type,
|
||||
mask_flags)
|
||||
attributes = [usage_mask]
|
||||
template_attribute = TemplateAttribute(attributes=attributes)
|
||||
|
||||
secret_features = {}
|
||||
|
||||
key_format_type = KeyFormatType.RAW
|
||||
secret_features.update([('key_format_type', key_format_type)])
|
||||
|
||||
# TODO (peter-hamilton) Replace with calls to crypto libraries
|
||||
key_data = {'bytes': bytearray('\x00\x00\x00\x00\x00\x00\x00\x00'
|
||||
'\x00\x00\x00\x00\x00\x00\x00\x00')}
|
||||
|
||||
secret_features.update([('key_value', key_data)])
|
||||
secret_features.update([('cryptographic_algorithm', algorithm_value)])
|
||||
secret_features.update([('cryptographic_length', 128)])
|
||||
|
||||
secret = secret_factory.create_secret(object_type, secret_features)
|
||||
|
||||
result = client.register(object_type, template_attribute, secret,
|
||||
credential)
|
||||
client.close()
|
||||
|
||||
logger.debug('register() result status: {}'.format(
|
||||
result.result_status.enum))
|
||||
logger.debug('registered UUID: {}'.format(result.uuid.value))
|
||||
logger.debug('registered template attribute: {}'.
|
||||
format(result.template_attribute))
|
@ -1,29 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# TODO insert license here
|
||||
|
||||
from transport.kmip import KMIP
|
||||
from transport.kmip.ttypes import *
|
||||
|
||||
from thrift import Thrift
|
||||
from thrift.transport import TSocket
|
||||
from thrift.transport import TTransport
|
||||
from thrift.protocol import TBinaryProtocol
|
||||
|
||||
try:
|
||||
|
||||
transport = TSocket.TSocket('localhost', 9090)
|
||||
transport = TTransport.TBufferedTransport(transport)
|
||||
protocol = TBinaryProtocol.TBinaryProtocol(transport)
|
||||
client = KMIP.Client(protocol)
|
||||
transport.open()
|
||||
|
||||
print 'ping-client()'
|
||||
client.create()
|
||||
print 'register_mo-client()'
|
||||
client.register_mo()
|
||||
|
||||
transport.close()
|
||||
|
||||
except Thrift.TException, tx:
|
||||
print '%s' % (tx.message)
|
@ -1,32 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# TODO insert license here
|
||||
|
||||
from transport.kmip import KMIP
|
||||
from transport.kmip.ttypes import *
|
||||
|
||||
from thrift.transport import TSocket
|
||||
from thrift.transport import TTransport
|
||||
from thrift.protocol import TBinaryProtocol
|
||||
from thrift.server import TServer
|
||||
|
||||
class KMIPHandler:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def create(self):
|
||||
print 'create()'
|
||||
|
||||
def register_mo(self):
|
||||
print 'register_mo()'
|
||||
|
||||
handler = KMIPHandler()
|
||||
processor = KMIP.Processor(handler)
|
||||
transport = TSocket.TServerSocket(port=9090)
|
||||
tfactory = TTransport.TBufferedTransportFactory()
|
||||
pfactory = TBinaryProtocol.TBinaryProtocolFactory()
|
||||
server = TServer.TSimpleServer(processor, transport, tfactory, pfactory)
|
||||
|
||||
print 'Starting the KMIP server...'
|
||||
server.serve()
|
||||
print 'done.'
|
21
kmip/logconfig.ini
Normal file
21
kmip/logconfig.ini
Normal file
@ -0,0 +1,21 @@
|
||||
[loggers]
|
||||
keys=root
|
||||
|
||||
[handlers]
|
||||
keys=consoleHandler
|
||||
|
||||
[formatters]
|
||||
keys=simpleFormatter
|
||||
|
||||
[logger_root]
|
||||
level=DEBUG
|
||||
handlers=consoleHandler
|
||||
|
||||
[handler_consoleHandler]
|
||||
class=StreamHandler
|
||||
level=DEBUG
|
||||
formatter=simpleFormatter
|
||||
args=(sys.stdout,)
|
||||
|
||||
[formatter_simpleFormatter]
|
||||
format=%(asctime)s - %(name)s - %(levelname)s - %(message)s
|
14
kmip/services/__init__.py
Normal file
14
kmip/services/__init__.py
Normal file
@ -0,0 +1,14 @@
|
||||
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
276
kmip/services/kmip_client.py
Normal file
276
kmip/services/kmip_client.py
Normal file
@ -0,0 +1,276 @@
|
||||
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from kmip.services.results import CreateResult
|
||||
from kmip.services.results import GetResult
|
||||
from kmip.services.results import DestroyResult
|
||||
from kmip.services.results import RegisterResult
|
||||
|
||||
from kmip.core import attributes as attr
|
||||
|
||||
from kmip.core.enums import Operation as OperationEnum
|
||||
|
||||
from kmip.core import objects
|
||||
from kmip.core.server import KMIP
|
||||
|
||||
from kmip.core.messages.contents import Authentication
|
||||
from kmip.core.messages.contents import BatchCount
|
||||
from kmip.core.messages.contents import ProtocolVersion
|
||||
from kmip.core.messages.contents import Operation
|
||||
|
||||
from kmip.core.messages import messages
|
||||
from kmip.core.messages import operations
|
||||
|
||||
from kmip.services.kmip_protocol import KMIPProtocol
|
||||
|
||||
from kmip.core.utils import BytearrayStream
|
||||
|
||||
from thrift.transport import TSocket
|
||||
from thrift.transport import TTransport
|
||||
|
||||
import logging
|
||||
import logging.config
|
||||
|
||||
|
||||
class KMIPProxy(KMIP):
|
||||
|
||||
# TODO (peter-hamilton) Move these defaults into config
|
||||
def __init__(self, hostname='127.0.0.1', port=5696):
|
||||
super(self.__class__, self).__init__()
|
||||
self.logger = logging.getLogger(__name__)
|
||||
self.socket = TSocket.TSocket(hostname, port)
|
||||
self.transport = TTransport.TBufferedTransport(self.socket)
|
||||
self.protocol = KMIPProtocol(self.transport)
|
||||
|
||||
def open(self):
|
||||
self.transport.open()
|
||||
|
||||
def close(self):
|
||||
self.transport.close()
|
||||
|
||||
def create(self, object_type, template_attribute, credential=None):
|
||||
object_type = attr.ObjectType(object_type)
|
||||
return self._create(object_type=object_type,
|
||||
template_attribute=template_attribute,
|
||||
credential=credential)
|
||||
|
||||
def get(self, uuid=None, key_format_type=None, key_compression_type=None,
|
||||
key_wrapping_specification=None, credential=None):
|
||||
return self._get(unique_identifier=uuid, credential=credential)
|
||||
|
||||
def destroy(self, uuid, credential=None):
|
||||
return self._destroy(unique_identifier=uuid,
|
||||
credential=credential)
|
||||
|
||||
def register(self, object_type, template_attribute, secret,
|
||||
credential=None):
|
||||
object_type = attr.ObjectType(object_type)
|
||||
return self._register(object_type=object_type,
|
||||
template_attribute=template_attribute,
|
||||
secret=secret,
|
||||
credential=credential)
|
||||
|
||||
def _create(self,
|
||||
object_type=None,
|
||||
template_attribute=None,
|
||||
credential=None):
|
||||
operation = Operation(OperationEnum.CREATE)
|
||||
|
||||
if object_type is None:
|
||||
raise ValueError('object_type cannot be None')
|
||||
|
||||
req_pl = operations.CreateRequestPayload(
|
||||
object_type=object_type,
|
||||
template_attribute=template_attribute)
|
||||
batch_item = messages.RequestBatchItem(operation=operation,
|
||||
request_payload=req_pl)
|
||||
|
||||
message = self._build_request_message(credential, [batch_item])
|
||||
self._send_message(message)
|
||||
message = messages.ResponseMessage()
|
||||
data = self._receive_message()
|
||||
message.read(data)
|
||||
batch_items = message.batch_items
|
||||
batch_item = batch_items[0]
|
||||
payload = batch_item.response_payload
|
||||
|
||||
if payload is None:
|
||||
payload_unique_identifier = None
|
||||
payload_template_attribute = None
|
||||
payload_object_type = None
|
||||
else:
|
||||
payload_unique_identifier = payload.unique_identifier
|
||||
payload_template_attribute = payload.template_attribute
|
||||
payload_object_type = payload.object_type
|
||||
|
||||
result = CreateResult(batch_item.result_status,
|
||||
batch_item.result_reason,
|
||||
batch_item.result_message,
|
||||
payload_object_type,
|
||||
payload_unique_identifier,
|
||||
payload_template_attribute)
|
||||
return result
|
||||
|
||||
def _get(self,
|
||||
unique_identifier=None,
|
||||
key_format_type=None,
|
||||
key_compression_type=None,
|
||||
key_wrapping_specification=None,
|
||||
credential=None):
|
||||
operation = Operation(OperationEnum.GET)
|
||||
|
||||
uuid = None
|
||||
kft = None
|
||||
kct = None
|
||||
kws = None
|
||||
|
||||
if unique_identifier is not None:
|
||||
uuid = attr.UniqueIdentifier(unique_identifier)
|
||||
if key_format_type is not None:
|
||||
kft = operations.GetRequestPayload.KeyFormatType(key_format_type)
|
||||
if key_compression_type is not None:
|
||||
kct = key_compression_type
|
||||
kct = operations.GetRequestPayload.KeyCompressionType(kct)
|
||||
if key_wrapping_specification is not None:
|
||||
kws = objects.KeyWrappingSpecification(key_wrapping_specification)
|
||||
|
||||
req_pl = operations.GetRequestPayload(unique_identifier=uuid,
|
||||
key_format_type=kft,
|
||||
key_compression_type=kct,
|
||||
key_wrapping_specification=kws)
|
||||
|
||||
batch_item = messages.RequestBatchItem(operation=operation,
|
||||
request_payload=req_pl)
|
||||
message = self._build_request_message(credential, [batch_item])
|
||||
self._send_message(message)
|
||||
message = messages.ResponseMessage()
|
||||
data = self._receive_message()
|
||||
message.read(data)
|
||||
batch_items = message.batch_items
|
||||
batch_item = batch_items[0]
|
||||
payload = batch_item.response_payload
|
||||
|
||||
if payload is None:
|
||||
payload_unique_identifier = None
|
||||
payload_object_type = None
|
||||
payload_secret = None
|
||||
else:
|
||||
payload_unique_identifier = payload.unique_identifier
|
||||
payload_object_type = payload.object_type
|
||||
payload_secret = payload.secret
|
||||
|
||||
result = GetResult(batch_item.result_status,
|
||||
batch_item.result_reason,
|
||||
batch_item.result_message,
|
||||
payload_object_type,
|
||||
payload_unique_identifier,
|
||||
payload_secret)
|
||||
return result
|
||||
|
||||
def _destroy(self,
|
||||
unique_identifier=None,
|
||||
credential=None):
|
||||
operation = Operation(OperationEnum.DESTROY)
|
||||
|
||||
uuid = None
|
||||
if unique_identifier is not None:
|
||||
uuid = attr.UniqueIdentifier(unique_identifier)
|
||||
|
||||
payload = operations.DestroyRequestPayload(unique_identifier=uuid)
|
||||
|
||||
batch_item = messages.RequestBatchItem(operation=operation,
|
||||
request_payload=payload)
|
||||
message = self._build_request_message(credential, [batch_item])
|
||||
self._send_message(message)
|
||||
message = messages.ResponseMessage()
|
||||
data = self._receive_message()
|
||||
message.read(data)
|
||||
batch_items = message.batch_items
|
||||
batch_item = batch_items[0]
|
||||
payload = batch_item.response_payload
|
||||
|
||||
if payload is None:
|
||||
payload_unique_identifier = None
|
||||
else:
|
||||
payload_unique_identifier = payload.unique_identifier
|
||||
|
||||
result = DestroyResult(batch_item.result_status,
|
||||
batch_item.result_reason,
|
||||
batch_item.result_message,
|
||||
payload_unique_identifier)
|
||||
return result
|
||||
|
||||
def _register(self,
|
||||
object_type=None,
|
||||
template_attribute=None,
|
||||
secret=None,
|
||||
credential=None):
|
||||
operation = Operation(OperationEnum.REGISTER)
|
||||
|
||||
if object_type is None:
|
||||
raise ValueError('object_type cannot be None')
|
||||
|
||||
req_pl = operations.RegisterRequestPayload(
|
||||
object_type=object_type,
|
||||
template_attribute=template_attribute,
|
||||
secret=secret)
|
||||
batch_item = messages.RequestBatchItem(operation=operation,
|
||||
request_payload=req_pl)
|
||||
|
||||
message = self._build_request_message(credential, [batch_item])
|
||||
self._send_message(message)
|
||||
message = messages.ResponseMessage()
|
||||
data = self._receive_message()
|
||||
message.read(data)
|
||||
batch_items = message.batch_items
|
||||
batch_item = batch_items[0]
|
||||
payload = batch_item.response_payload
|
||||
|
||||
if payload is None:
|
||||
payload_unique_identifier = None
|
||||
payload_template_attribute = None
|
||||
else:
|
||||
payload_unique_identifier = payload.unique_identifier
|
||||
payload_template_attribute = payload.template_attribute
|
||||
|
||||
result = RegisterResult(batch_item.result_status,
|
||||
batch_item.result_reason,
|
||||
batch_item.result_message,
|
||||
payload_unique_identifier,
|
||||
payload_template_attribute)
|
||||
return result
|
||||
|
||||
def _build_request_message(self, credential, batch_items):
|
||||
protocol_version = ProtocolVersion.create(1, 1)
|
||||
|
||||
authentication = None
|
||||
if credential is not None:
|
||||
authentication = Authentication(credential)
|
||||
|
||||
batch_count = BatchCount(len(batch_items))
|
||||
req_header = messages.RequestHeader(protocol_version=protocol_version,
|
||||
authentication=authentication,
|
||||
batch_count=batch_count)
|
||||
|
||||
return messages.RequestMessage(request_header=req_header,
|
||||
batch_items=batch_items)
|
||||
|
||||
def _send_message(self, message):
|
||||
stream = BytearrayStream()
|
||||
message.write(stream)
|
||||
self.protocol.write(stream.buffer)
|
||||
|
||||
def _receive_message(self):
|
||||
return self.protocol.read()
|
50
kmip/services/kmip_protocol.py
Normal file
50
kmip/services/kmip_protocol.py
Normal file
@ -0,0 +1,50 @@
|
||||
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from struct import unpack
|
||||
|
||||
from thrift.protocol.TProtocol import TProtocolBase
|
||||
|
||||
import binascii
|
||||
import logging
|
||||
|
||||
from kmip.core.utils import BytearrayStream
|
||||
|
||||
|
||||
class KMIPProtocol(TProtocolBase):
|
||||
HEADER_SIZE = 8
|
||||
|
||||
def __init__(self, trans, buffer_size=1024):
|
||||
TProtocolBase.__init__(self, trans)
|
||||
self.logger = logging.getLogger(__name__)
|
||||
|
||||
def write(self, data):
|
||||
if len(data) > 0:
|
||||
sbuffer = bytes(data)
|
||||
self.logger.debug('buffer: {0}'.format(binascii.hexlify(sbuffer)))
|
||||
self.trans.write(sbuffer)
|
||||
self.trans.flush()
|
||||
|
||||
def read(self):
|
||||
header = self.trans.readAll(self.HEADER_SIZE)
|
||||
msg_size = unpack('!I', header[4:])[0]
|
||||
payload = self.trans.readAll(msg_size)
|
||||
return BytearrayStream(header + payload)
|
||||
|
||||
|
||||
class KMIPProtocolFactory(object):
|
||||
|
||||
def getProtocol(self, trans):
|
||||
return KMIPProtocol(trans)
|
253
kmip/services/kmip_server.py
Executable file
253
kmip/services/kmip_server.py
Executable file
@ -0,0 +1,253 @@
|
||||
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import time
|
||||
|
||||
from thrift.Thrift import TProcessor
|
||||
|
||||
from kmip.core.messages.messages import RequestMessage
|
||||
from kmip.core.messages.messages import ResponseMessage
|
||||
from kmip.core.messages.messages import ResponseBatchItem
|
||||
from kmip.core.messages.messages import ResponseHeader
|
||||
|
||||
from kmip.core.messages.contents import AsynchronousIndicator
|
||||
from kmip.core.messages.contents import BatchErrorContinuationOption
|
||||
from kmip.core.messages.contents import BatchCount
|
||||
from kmip.core.messages.contents import TimeStamp
|
||||
|
||||
from kmip.core.primitives import Base
|
||||
|
||||
from kmip.core.messages.operations import CreateResponsePayload
|
||||
from kmip.core.messages.operations import GetResponsePayload
|
||||
from kmip.core.messages.operations import DestroyResponsePayload
|
||||
from kmip.core.messages.operations import RegisterResponsePayload
|
||||
|
||||
from kmip.core.enums import Operation
|
||||
from kmip.core.enums import ResultStatus as RS
|
||||
from kmip.core.enums import Tags
|
||||
from kmip.core.enums import BatchErrorContinuationOption as BECO
|
||||
|
||||
from kmip.core.utils import BytearrayStream
|
||||
|
||||
|
||||
class Processor(TProcessor):
|
||||
def __init__(self, handler):
|
||||
self._handler = handler
|
||||
|
||||
def process(self, istream, ostream):
|
||||
stream = istream.read()
|
||||
|
||||
if Base.is_tag_next(Tags.REQUEST_MESSAGE, stream):
|
||||
message = RequestMessage()
|
||||
message.read(stream)
|
||||
result = self._process_request(message)
|
||||
tstream = BytearrayStream()
|
||||
result.write(tstream)
|
||||
ostream.write(tstream.buffer)
|
||||
elif Base.is_tag_next(Tags.RESPONSE_MESSAGE, stream):
|
||||
message = ResponseMessage()
|
||||
message.read(stream)
|
||||
self._process_response(message)
|
||||
else:
|
||||
raise ValueError('Processing error: stream contains unknown'
|
||||
'message type')
|
||||
|
||||
def _process_request(self, message):
|
||||
header = message.request_header
|
||||
|
||||
protocol_version = header.protocol_version
|
||||
# maximum_response_size = header.maximum_response_size
|
||||
asynchronous_indicator = header.asynchronous_indicator
|
||||
# authentication = header.authentication
|
||||
batch_error_cont_option = header.batch_error_cont_option
|
||||
# batch_order_option = header.batch_order_option
|
||||
# time_stamp = header.time_stamp
|
||||
request_batch_count = header.batch_count.value
|
||||
|
||||
# TODO (peter-hamilton) Log receipt of message with time stamp
|
||||
|
||||
if asynchronous_indicator is None:
|
||||
asynchronous_indicator = AsynchronousIndicator(False)
|
||||
|
||||
if batch_error_cont_option is None:
|
||||
batch_error_cont_option = BatchErrorContinuationOption(BECO.STOP)
|
||||
|
||||
request_batch_items = message.batch_items
|
||||
response_batch_items = []
|
||||
|
||||
for i in xrange(request_batch_count):
|
||||
request_batch_item = request_batch_items[i]
|
||||
failure_occurred = False
|
||||
|
||||
operation = request_batch_item.operation
|
||||
ubi_id = request_batch_item.unique_batch_item_id
|
||||
payload = request_batch_item.request_payload
|
||||
message_extension = request_batch_item.message_extension
|
||||
|
||||
result = self._process_operation(operation, payload)
|
||||
|
||||
result_status = result[0]
|
||||
result_reason = result[1]
|
||||
result_message = result[2]
|
||||
asyn_cv = None
|
||||
response_payload = None
|
||||
message_extension = None
|
||||
|
||||
if result_status.enum is RS.SUCCESS:
|
||||
response_payload = result[3]
|
||||
elif result_status.enum is RS.OPERATION_FAILED:
|
||||
failure_occurred = True
|
||||
result_reason = result[1]
|
||||
elif result_status.enum is RS.OPERATION_PENDING:
|
||||
# TODO (peter-hamilton) Need to add a way to track async
|
||||
# TODO (peter-hamilton) operations.
|
||||
asyn_cv = '\x00'
|
||||
elif result_status.enum is RS.OPERATION_UNDONE:
|
||||
result_reason = result[1]
|
||||
else:
|
||||
msg = 'Unrecognized operation result status: {}'
|
||||
raise RuntimeError(msg.format(result_status))
|
||||
|
||||
resp_bi = ResponseBatchItem(operation=operation,
|
||||
unique_batch_item_id=ubi_id,
|
||||
result_status=result_status,
|
||||
result_reason=result_reason,
|
||||
result_message=result_message,
|
||||
async_correlation_value=asyn_cv,
|
||||
response_payload=response_payload,
|
||||
message_extension=message_extension)
|
||||
response_batch_items.append(resp_bi)
|
||||
|
||||
if failure_occurred:
|
||||
if batch_error_cont_option.enum is BECO.STOP:
|
||||
break
|
||||
elif batch_error_cont_option.enum is BECO.UNDO:
|
||||
# TODO (peter-hamilton) Tell client to undo operations.
|
||||
# TODO (peter-hamilton) Unclear what response should be.
|
||||
break
|
||||
elif batch_error_cont_option.enum is BECO.CONTINUE:
|
||||
continue
|
||||
else:
|
||||
msg = 'Unrecognized batch error continuation option: {}'
|
||||
raise RuntimeError(msg.format(batch_error_cont_option))
|
||||
|
||||
response_batch_count = BatchCount(len(response_batch_items))
|
||||
response_time_stamp = TimeStamp(int(time.time()))
|
||||
response_header = ResponseHeader(protocol_version=protocol_version,
|
||||
time_stamp=response_time_stamp,
|
||||
batch_count=response_batch_count)
|
||||
|
||||
response_message = ResponseMessage(response_header=response_header,
|
||||
batch_items=response_batch_items)
|
||||
return response_message
|
||||
|
||||
def _process_response(self, message):
|
||||
raise NotImplementedError()
|
||||
|
||||
def _process_operation(self, operation, payload):
|
||||
op = operation.enum
|
||||
|
||||
if op is Operation.CREATE:
|
||||
return self._process_create_request(payload)
|
||||
elif op is Operation.GET:
|
||||
return self._process_get_request(payload)
|
||||
elif op is Operation.DESTROY:
|
||||
return self._process_destroy_request(payload)
|
||||
elif op is Operation.REGISTER:
|
||||
return self._process_register_request(payload)
|
||||
else:
|
||||
raise NotImplementedError()
|
||||
|
||||
def _process_create_request(self, payload):
|
||||
object_type = payload.object_type
|
||||
template_attribute = payload.template_attribute
|
||||
result = self._handler.create(object_type, template_attribute)
|
||||
|
||||
result_status = result.result_status
|
||||
result_reason = result.result_reason
|
||||
result_message = result.result_message
|
||||
created_type = result.object_type
|
||||
uuid = result.uuid
|
||||
template_attribute = result.template_attribute
|
||||
|
||||
resp_pl = CreateResponsePayload(object_type=created_type,
|
||||
unique_identifier=uuid,
|
||||
template_attribute=template_attribute)
|
||||
|
||||
return (result_status, result_reason, result_message, resp_pl)
|
||||
|
||||
def _process_get_request(self, payload):
|
||||
uuid = None
|
||||
kft = None
|
||||
kct = None
|
||||
|
||||
unique_identifier = payload.unique_identifier
|
||||
key_format_type = payload.key_format_type
|
||||
key_compression_type = payload.key_compression_type
|
||||
key_wrapping_specification = payload.key_wrapping_specification
|
||||
|
||||
if unique_identifier is not None:
|
||||
uuid = unique_identifier
|
||||
if key_format_type is not None:
|
||||
kft = key_format_type
|
||||
if key_compression_type is not None:
|
||||
kct = key_compression_type
|
||||
|
||||
result = self._handler.get(uuid, kft, kct,
|
||||
key_wrapping_specification)
|
||||
|
||||
result_status = result.result_status
|
||||
result_reason = result.result_reason
|
||||
result_message = result.result_message
|
||||
retrieved_type = result.object_type
|
||||
uuid = result.uuid
|
||||
secret = result.secret
|
||||
|
||||
resp_pl = GetResponsePayload(object_type=retrieved_type,
|
||||
unique_identifier=uuid,
|
||||
secret=secret)
|
||||
|
||||
return (result_status, result_reason, result_message, resp_pl)
|
||||
|
||||
def _process_destroy_request(self, payload):
|
||||
uuid = payload.unique_identifier
|
||||
result = self._handler.destroy(uuid)
|
||||
|
||||
result_status = result.result_status
|
||||
result_reason = result.result_reason
|
||||
result_message = result.result_message
|
||||
uuid = result.uuid
|
||||
|
||||
payload = DestroyResponsePayload(unique_identifier=uuid)
|
||||
|
||||
return (result_status, result_reason, result_message, payload)
|
||||
|
||||
def _process_register_request(self, payload):
|
||||
object_type = payload.object_type
|
||||
template_attribute = payload.template_attribute
|
||||
secret = payload.secret
|
||||
result = self._handler.register(object_type, template_attribute,
|
||||
secret)
|
||||
|
||||
result_status = result.result_status
|
||||
result_reason = result.result_reason
|
||||
result_message = result.result_message
|
||||
uuid = result.uuid
|
||||
template_attr = result.template_attribute
|
||||
|
||||
resp_pl = RegisterResponsePayload(unique_identifier=uuid,
|
||||
template_attribute=template_attr)
|
||||
|
||||
return (result_status, result_reason, result_message, resp_pl)
|
127
kmip/services/results.py
Normal file
127
kmip/services/results.py
Normal file
@ -0,0 +1,127 @@
|
||||
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
|
||||
class OperationResult(object):
|
||||
|
||||
def __init__(self,
|
||||
result_status,
|
||||
result_reason=None,
|
||||
result_message=None):
|
||||
self.result_status = result_status
|
||||
|
||||
if result_reason is not None:
|
||||
self.result_reason = result_reason
|
||||
else:
|
||||
self.result_reason = None
|
||||
|
||||
if result_message is not None:
|
||||
self.result_message = result_message
|
||||
else:
|
||||
self.result_message = None
|
||||
|
||||
|
||||
class CreateResult(OperationResult):
|
||||
|
||||
def __init__(self,
|
||||
result_status,
|
||||
result_reason=None,
|
||||
result_message=None,
|
||||
object_type=None,
|
||||
uuid=None,
|
||||
template_attribute=None):
|
||||
super(self.__class__, self).__init__(result_status,
|
||||
result_reason,
|
||||
result_message)
|
||||
if object_type is not None:
|
||||
self.object_type = object_type
|
||||
else:
|
||||
self.object_type = None
|
||||
|
||||
if uuid is not None:
|
||||
self.uuid = uuid
|
||||
else:
|
||||
self.uuid = None
|
||||
|
||||
if template_attribute is not None:
|
||||
self.template_attribute = template_attribute
|
||||
else:
|
||||
self.template_attribute = None
|
||||
|
||||
|
||||
class RegisterResult(OperationResult):
|
||||
|
||||
def __init__(self,
|
||||
result_status,
|
||||
result_reason=None,
|
||||
result_message=None,
|
||||
uuid=None,
|
||||
template_attribute=None):
|
||||
super(self.__class__, self).__init__(result_status,
|
||||
result_reason,
|
||||
result_message)
|
||||
if uuid is not None:
|
||||
self.uuid = uuid
|
||||
else:
|
||||
self.uuid = None
|
||||
|
||||
if template_attribute is not None:
|
||||
self.template_attribute = template_attribute
|
||||
else:
|
||||
self.template_attribute = None
|
||||
|
||||
|
||||
class GetResult(OperationResult):
|
||||
|
||||
def __init__(self,
|
||||
result_status,
|
||||
result_reason=None,
|
||||
result_message=None,
|
||||
object_type=None,
|
||||
uuid=None,
|
||||
secret=None):
|
||||
super(self.__class__, self).__init__(result_status,
|
||||
result_reason,
|
||||
result_message)
|
||||
if object_type is not None:
|
||||
self.object_type = object_type
|
||||
else:
|
||||
self.object_type = None
|
||||
|
||||
if uuid is not None:
|
||||
self.uuid = uuid
|
||||
else:
|
||||
self.uuid = None
|
||||
|
||||
if secret is not None:
|
||||
self.secret = secret
|
||||
else:
|
||||
self.secret = None
|
||||
|
||||
|
||||
class DestroyResult(OperationResult):
|
||||
|
||||
def __init__(self,
|
||||
result_status,
|
||||
result_reason=None,
|
||||
result_message=None,
|
||||
uuid=None):
|
||||
super(self.__class__, self).__init__(result_status,
|
||||
result_reason,
|
||||
result_message)
|
||||
if uuid is not None:
|
||||
self.uuid = uuid
|
||||
else:
|
||||
self.uuid = None
|
14
kmip/tests/__init__.py
Normal file
14
kmip/tests/__init__.py
Normal file
@ -0,0 +1,14 @@
|
||||
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
14
kmip/tests/core/__init__.py
Normal file
14
kmip/tests/core/__init__.py
Normal file
@ -0,0 +1,14 @@
|
||||
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
14
kmip/tests/core/messages/__init__.py
Normal file
14
kmip/tests/core/messages/__init__.py
Normal file
@ -0,0 +1,14 @@
|
||||
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
14
kmip/tests/core/messages/test_contents.py
Normal file
14
kmip/tests/core/messages/test_contents.py
Normal file
@ -0,0 +1,14 @@
|
||||
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
1537
kmip/tests/core/messages/test_messages.py
Normal file
1537
kmip/tests/core/messages/test_messages.py
Normal file
File diff suppressed because it is too large
Load Diff
14
kmip/tests/core/messages/test_operations.py
Normal file
14
kmip/tests/core/messages/test_operations.py
Normal file
@ -0,0 +1,14 @@
|
||||
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
62
kmip/tests/core/test_attributes.py
Normal file
62
kmip/tests/core/test_attributes.py
Normal file
@ -0,0 +1,62 @@
|
||||
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from testtools import TestCase
|
||||
|
||||
from kmip.core.utils import BytearrayStream
|
||||
|
||||
|
||||
class TestNameValue(TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestNameValue, self).setUp()
|
||||
self.stream = BytearrayStream()
|
||||
|
||||
def tearDown(self):
|
||||
super(TestNameValue, self).tearDown()
|
||||
|
||||
def test_write_no_padding(self):
|
||||
pass
|
||||
|
||||
def test_write_with_padding(self):
|
||||
pass
|
||||
|
||||
def test_read_no_padding(self):
|
||||
pass
|
||||
|
||||
def test_read_with_padding(self):
|
||||
pass
|
||||
|
||||
|
||||
class TestName(TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestName, self).setUp()
|
||||
self.stream = BytearrayStream()
|
||||
|
||||
def tearDown(self):
|
||||
super(TestName, self).tearDown()
|
||||
|
||||
def test_minimum_write(self):
|
||||
pass
|
||||
|
||||
def test_maximum_write(self):
|
||||
pass
|
||||
|
||||
def test_minimum_read(self):
|
||||
pass
|
||||
|
||||
def test_maximum_read(self):
|
||||
pass
|
1392
kmip/tests/core/test_primitives.py
Normal file
1392
kmip/tests/core/test_primitives.py
Normal file
File diff suppressed because it is too large
Load Diff
508
kmip/tests/core/test_server.py
Normal file
508
kmip/tests/core/test_server.py
Normal file
@ -0,0 +1,508 @@
|
||||
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from testtools import TestCase
|
||||
|
||||
from kmip.core.attributes import CryptographicAlgorithm
|
||||
from kmip.core.attributes import CryptographicLength
|
||||
from kmip.core.attributes import CryptographicUsageMask
|
||||
from kmip.core.attributes import UniqueIdentifier
|
||||
from kmip.core.attributes import ObjectType
|
||||
from kmip.core.enums import AttributeType
|
||||
from kmip.core.enums import CryptographicAlgorithm as CryptoAlgorithmEnum
|
||||
from kmip.core.enums import CryptographicUsageMask as CryptoUsageMaskEnum
|
||||
from kmip.core.enums import KeyCompressionType as KeyCompressionTypeEnum
|
||||
from kmip.core.enums import KeyFormatType as KeyFormatTypeEnum
|
||||
from kmip.core.enums import ObjectType as ObjectTypeEnum
|
||||
from kmip.core.enums import ResultReason
|
||||
from kmip.core.enums import ResultStatus
|
||||
from kmip.core.factories.attributes import AttributeFactory
|
||||
from kmip.core.keys import RawKey
|
||||
from kmip.core.messages.contents import KeyCompressionType
|
||||
from kmip.core.messages.contents import KeyFormatType
|
||||
from kmip.core.objects import KeyBlock
|
||||
from kmip.core.objects import KeyValueStruct
|
||||
from kmip.core.objects import TemplateAttribute
|
||||
from kmip.core.secrets import SymmetricKey
|
||||
from kmip.core.server import KMIPImpl
|
||||
|
||||
|
||||
class TestKMIPServer(TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestKMIPServer, self).setUp()
|
||||
self.kmip = KMIPImpl()
|
||||
self.algorithm_name = CryptoAlgorithmEnum.AES
|
||||
self.key_length = 256
|
||||
self.key = bytearray(range(0, 32))
|
||||
self.usage_mask = CryptoUsageMaskEnum.ENCRYPT.value |\
|
||||
CryptoUsageMaskEnum.DECRYPT.value
|
||||
|
||||
def tearDown(self):
|
||||
super(TestKMIPServer, self).tearDown()
|
||||
|
||||
def test_create(self):
|
||||
obj_type = ObjectType(ObjectTypeEnum.SYMMETRIC_KEY)
|
||||
attributes = self._get_attrs()
|
||||
template_attribute = TemplateAttribute(attributes=attributes)
|
||||
res = self.kmip.create(obj_type, template_attribute)
|
||||
self.assertNotEqual(None, res, 'result is None')
|
||||
self.assertEqual(ResultStatus.SUCCESS, res.result_status.enum,
|
||||
'result status did not return success')
|
||||
|
||||
def test_create_no_length(self):
|
||||
obj_type = ObjectType(ObjectTypeEnum.SYMMETRIC_KEY)
|
||||
attributes = self._get_attrs()[0:2]
|
||||
template_attribute = TemplateAttribute(attributes=attributes)
|
||||
res = self.kmip.create(obj_type, template_attribute)
|
||||
self.assertNotEqual(None, res, 'result is None')
|
||||
attrs = res.template_attribute.attributes
|
||||
self.assertEqual(ResultStatus.SUCCESS, res.result_status.enum,
|
||||
'result status did not return success')
|
||||
self.assertTrue(self._check_attr_exists(attributes[2], attrs),
|
||||
'length attribute not returned')
|
||||
|
||||
def test_create_no_alg(self):
|
||||
obj_type = ObjectType(ObjectTypeEnum.SYMMETRIC_KEY)
|
||||
attributes = [self._get_attrs()[1]]
|
||||
template_attribute = TemplateAttribute(attributes=attributes)
|
||||
res = self.kmip.create(obj_type, template_attribute)
|
||||
self.assertNotEqual(None, res, 'result is None')
|
||||
self.assertEqual(ResultStatus.OPERATION_FAILED, res.result_status.enum,
|
||||
'result status did not return failed')
|
||||
|
||||
def test_create_no_usage_mask(self):
|
||||
obj_type = ObjectType(ObjectTypeEnum.SYMMETRIC_KEY)
|
||||
attributes = [self._get_attrs()[0]]
|
||||
template_attribute = TemplateAttribute(attributes=attributes)
|
||||
res = self.kmip.create(obj_type, template_attribute)
|
||||
self.assertNotEqual(None, res, 'result is None')
|
||||
self.assertEqual(ResultStatus.OPERATION_FAILED, res.result_status.enum,
|
||||
'result status did not return failed')
|
||||
|
||||
def test_register(self):
|
||||
obj_type = ObjectType(ObjectTypeEnum.SYMMETRIC_KEY)
|
||||
key = self._get_symmetric_key()
|
||||
attributes = []
|
||||
template_attribute = TemplateAttribute(attributes=attributes)
|
||||
res = self.kmip.register(obj_type, template_attribute, key)
|
||||
self.assertNotEqual(None, res, 'result is None')
|
||||
self.assertEqual(ResultStatus.SUCCESS, res.result_status.enum,
|
||||
'result status did not return success')
|
||||
|
||||
def test_register_attrs_in_key_value(self):
|
||||
obj_type = ObjectType(ObjectTypeEnum.SYMMETRIC_KEY)
|
||||
key = self._get_symmetric_key()
|
||||
key.key_block.cryptographic_algorithm = None
|
||||
key.key_block.cryptographic_length = None
|
||||
key.key_block.key_value.attributes = self._get_attrs()
|
||||
attributes = []
|
||||
template_attribute = TemplateAttribute(attributes=attributes)
|
||||
res = self.kmip.register(obj_type, template_attribute, key)
|
||||
self.assertNotEqual(None, res, 'result is None')
|
||||
self.assertEqual(ResultStatus.SUCCESS, res.result_status.enum,
|
||||
'result status did not return success')
|
||||
|
||||
def test_register_attrs_in_template(self):
|
||||
obj_type = ObjectType(ObjectTypeEnum.SYMMETRIC_KEY)
|
||||
key = self._get_symmetric_key()
|
||||
key.key_block.cryptographic_algorithm = None
|
||||
key.key_block.cryptographic_length = None
|
||||
key.key_block.key_value.attributes = []
|
||||
attributes = self._get_attrs()
|
||||
template_attribute = TemplateAttribute(attributes=attributes)
|
||||
res = self.kmip.register(obj_type, template_attribute, key)
|
||||
self.assertNotEqual(None, res, 'result is None')
|
||||
self.assertEqual(ResultStatus.SUCCESS, res.result_status.enum,
|
||||
'result status did not return success')
|
||||
|
||||
def test_register_no_alg(self):
|
||||
obj_type = ObjectType(ObjectTypeEnum.SYMMETRIC_KEY)
|
||||
key = self._get_symmetric_key()
|
||||
key.key_block.cryptographic_algorithm = None
|
||||
attributes = []
|
||||
template_attribute = TemplateAttribute(attributes=attributes)
|
||||
res = self.kmip.register(obj_type, template_attribute, key)
|
||||
self.assertEqual(ResultStatus.OPERATION_FAILED,
|
||||
res.result_status.enum,
|
||||
'result status did not return failed')
|
||||
self.assertEqual(ResultReason.ITEM_NOT_FOUND,
|
||||
res.result_reason.enum,
|
||||
'result reason did not match')
|
||||
|
||||
def test_register_alg_in_key_value_and_key_block(self):
|
||||
obj_type = ObjectType(ObjectTypeEnum.SYMMETRIC_KEY)
|
||||
key = self._get_symmetric_key()
|
||||
key.key_block.key_value.attributes = [self._get_alg_attr()]
|
||||
attributes = []
|
||||
template_attribute = TemplateAttribute(attributes=attributes)
|
||||
res = self.kmip.register(obj_type, template_attribute, key)
|
||||
self.assertEqual(ResultStatus.OPERATION_FAILED,
|
||||
res.result_status.enum,
|
||||
'result status did not return failed')
|
||||
self.assertEqual(ResultReason.INDEX_OUT_OF_BOUNDS,
|
||||
res.result_reason.enum,
|
||||
'result reason did not match')
|
||||
|
||||
def test_register_alg_in_template_and_key_block(self):
|
||||
obj_type = ObjectType(ObjectTypeEnum.SYMMETRIC_KEY)
|
||||
key = self._get_symmetric_key()
|
||||
attributes = [self._get_alg_attr()]
|
||||
template_attribute = TemplateAttribute(attributes=attributes)
|
||||
res = self.kmip.register(obj_type, template_attribute, key)
|
||||
self.assertEqual(ResultStatus.OPERATION_FAILED,
|
||||
res.result_status.enum,
|
||||
'result status did not return failed')
|
||||
self.assertEqual(ResultReason.INDEX_OUT_OF_BOUNDS,
|
||||
res.result_reason.enum,
|
||||
'result reason did not match')
|
||||
|
||||
def test_register_alg_in_template_and_key_value(self):
|
||||
obj_type = ObjectType(ObjectTypeEnum.SYMMETRIC_KEY)
|
||||
key = self._get_symmetric_key()
|
||||
key.key_block.cryptographic_algorithm = None
|
||||
key.key_block.key_value.attributes = [self._get_alg_attr()]
|
||||
attributes = [self._get_alg_attr()]
|
||||
template_attribute = TemplateAttribute(attributes=attributes)
|
||||
res = self.kmip.register(obj_type, template_attribute, key)
|
||||
self.assertEqual(ResultStatus.OPERATION_FAILED,
|
||||
res.result_status.enum,
|
||||
'result status did not return failed')
|
||||
self.assertEqual(ResultReason.INDEX_OUT_OF_BOUNDS,
|
||||
res.result_reason.enum,
|
||||
'result reason did not match')
|
||||
|
||||
def test_register_invalid_alg(self):
|
||||
unsupported_algs = (CryptoAlgorithmEnum.RSA,
|
||||
CryptoAlgorithmEnum.DSA,
|
||||
CryptoAlgorithmEnum.ECDSA,
|
||||
CryptoAlgorithmEnum.HMAC_SHA1,
|
||||
CryptoAlgorithmEnum.HMAC_SHA224,
|
||||
CryptoAlgorithmEnum.HMAC_SHA256,
|
||||
CryptoAlgorithmEnum.HMAC_SHA384,
|
||||
CryptoAlgorithmEnum.HMAC_SHA512,
|
||||
CryptoAlgorithmEnum.HMAC_MD5,
|
||||
CryptoAlgorithmEnum.DH,
|
||||
CryptoAlgorithmEnum.ECDH,
|
||||
CryptoAlgorithmEnum.ECMQV,
|
||||
CryptoAlgorithmEnum.BLOWFISH,
|
||||
CryptoAlgorithmEnum.CAMELLIA,
|
||||
CryptoAlgorithmEnum.CAST5,
|
||||
CryptoAlgorithmEnum.IDEA,
|
||||
CryptoAlgorithmEnum.MARS,
|
||||
CryptoAlgorithmEnum.RC2,
|
||||
CryptoAlgorithmEnum.RC4,
|
||||
CryptoAlgorithmEnum.RC5,
|
||||
CryptoAlgorithmEnum.SKIPJACK,
|
||||
CryptoAlgorithmEnum.TWOFISH)
|
||||
for alg in unsupported_algs:
|
||||
obj_type = ObjectType(ObjectTypeEnum.SYMMETRIC_KEY)
|
||||
key = self._get_symmetric_key()
|
||||
key.key_block.cryptographic_algorithm = CryptographicAlgorithm(alg)
|
||||
attributes = []
|
||||
template_attribute = TemplateAttribute(attributes=attributes)
|
||||
res = self.kmip.register(obj_type, template_attribute, key)
|
||||
self.assertEqual(ResultStatus.OPERATION_FAILED,
|
||||
res.result_status.enum,
|
||||
'result status did not return failed')
|
||||
self.assertEqual(ResultReason.INVALID_FIELD,
|
||||
res.result_reason.enum,
|
||||
'result reason did not match')
|
||||
|
||||
def test_register_no_length(self):
|
||||
obj_type = ObjectType(ObjectTypeEnum.SYMMETRIC_KEY)
|
||||
key = self._get_symmetric_key()
|
||||
key.key_block.cryptographic_length = None
|
||||
attributes = []
|
||||
template_attribute = TemplateAttribute(attributes=attributes)
|
||||
res = self.kmip.register(obj_type, template_attribute, key)
|
||||
self.assertEqual(ResultStatus.OPERATION_FAILED,
|
||||
res.result_status.enum,
|
||||
'result status did not return failed')
|
||||
self.assertEqual(ResultReason.ITEM_NOT_FOUND,
|
||||
res.result_reason.enum,
|
||||
'result reason did not match')
|
||||
|
||||
def test_register_length_in_key_value_and_key_block(self):
|
||||
obj_type = ObjectType(ObjectTypeEnum.SYMMETRIC_KEY)
|
||||
key = self._get_symmetric_key()
|
||||
key.key_block.key_value.attributes = [self._get_length_attr()]
|
||||
attributes = []
|
||||
template_attribute = TemplateAttribute(attributes=attributes)
|
||||
res = self.kmip.register(obj_type, template_attribute, key)
|
||||
self.assertEqual(ResultStatus.OPERATION_FAILED,
|
||||
res.result_status.enum,
|
||||
'result status did not return failed')
|
||||
self.assertEqual(ResultReason.INDEX_OUT_OF_BOUNDS,
|
||||
res.result_reason.enum,
|
||||
'result reason did not match')
|
||||
|
||||
def test_register_length_in_template_and_key_block(self):
|
||||
obj_type = ObjectType(ObjectTypeEnum.SYMMETRIC_KEY)
|
||||
key = self._get_symmetric_key()
|
||||
attributes = [self._get_length_attr()]
|
||||
template_attribute = TemplateAttribute(attributes=attributes)
|
||||
res = self.kmip.register(obj_type, template_attribute, key)
|
||||
self.assertEqual(ResultStatus.OPERATION_FAILED,
|
||||
res.result_status.enum,
|
||||
'result status did not return failed')
|
||||
self.assertEqual(ResultReason.INDEX_OUT_OF_BOUNDS,
|
||||
res.result_reason.enum,
|
||||
'result reason did not match')
|
||||
|
||||
def test_register_length_in_template_and_key_value(self):
|
||||
obj_type = ObjectType(ObjectTypeEnum.SYMMETRIC_KEY)
|
||||
key = self._get_symmetric_key()
|
||||
key.key_block.cryptographic_length = None
|
||||
key.key_block.key_value.attributes = [self._get_length_attr()]
|
||||
attributes = [self._get_length_attr()]
|
||||
template_attribute = TemplateAttribute(attributes=attributes)
|
||||
res = self.kmip.register(obj_type, template_attribute, key)
|
||||
self.assertEqual(ResultStatus.OPERATION_FAILED,
|
||||
res.result_status.enum,
|
||||
'result status did not return failed')
|
||||
self.assertEqual(ResultReason.INDEX_OUT_OF_BOUNDS,
|
||||
res.result_reason.enum,
|
||||
'result reason did not match')
|
||||
|
||||
def test_register_invalid_length(self):
|
||||
unsupported_lens = (-1, 0, 2048, 5, 18)
|
||||
for len in unsupported_lens:
|
||||
obj_type = ObjectType(ObjectTypeEnum.SYMMETRIC_KEY)
|
||||
key = self._get_symmetric_key()
|
||||
key.key_block.cryptographic_length = CryptographicLength(len)
|
||||
attributes = []
|
||||
template_attribute = TemplateAttribute(attributes=attributes)
|
||||
res = self.kmip.register(obj_type, template_attribute, key)
|
||||
self.assertEqual(ResultStatus.OPERATION_FAILED,
|
||||
res.result_status.enum,
|
||||
'result status did not return failed')
|
||||
self.assertEqual(ResultReason.INVALID_FIELD,
|
||||
res.result_reason.enum,
|
||||
'result reason did not match')
|
||||
|
||||
def test_register_no_usage_mask(self):
|
||||
obj_type = ObjectType(ObjectTypeEnum.SYMMETRIC_KEY)
|
||||
key = self._get_symmetric_key()
|
||||
key.key_block.key_value.attributes = []
|
||||
attributes = []
|
||||
template_attribute = TemplateAttribute(attributes=attributes)
|
||||
res = self.kmip.register(obj_type, template_attribute, key)
|
||||
self.assertEqual(ResultStatus.OPERATION_FAILED,
|
||||
res.result_status.enum,
|
||||
'result status did not return failed')
|
||||
self.assertEqual(ResultReason.ITEM_NOT_FOUND,
|
||||
res.result_reason.enum,
|
||||
'result reason did not match')
|
||||
|
||||
def test_register_no_object_type(self):
|
||||
obj_type = None
|
||||
key = self._get_symmetric_key()
|
||||
attributes = []
|
||||
template_attribute = TemplateAttribute(attributes=attributes)
|
||||
res = self.kmip.register(obj_type, template_attribute, key)
|
||||
self.assertNotEqual(None, res, 'result is None')
|
||||
self.assertEqual(ResultStatus.OPERATION_FAILED,
|
||||
res.result_status.enum,
|
||||
'result status did not return failed')
|
||||
self.assertEqual(ResultReason.ITEM_NOT_FOUND,
|
||||
res.result_reason.enum,
|
||||
'result reason did not match')
|
||||
|
||||
def test_register_unsupported_object_type(self):
|
||||
unsupported_types = (ObjectTypeEnum.CERTIFICATE,
|
||||
ObjectTypeEnum.PUBLIC_KEY,
|
||||
ObjectTypeEnum.PRIVATE_KEY,
|
||||
ObjectTypeEnum.SPLIT_KEY,
|
||||
ObjectTypeEnum.TEMPLATE,
|
||||
ObjectTypeEnum.SECRET_DATA,
|
||||
ObjectTypeEnum.OPAQUE_DATA)
|
||||
for unsupported_type in unsupported_types:
|
||||
obj_type = ObjectType(unsupported_type)
|
||||
key = self._get_symmetric_key()
|
||||
attributes = []
|
||||
template_attribute = TemplateAttribute(attributes=attributes)
|
||||
res = self.kmip.register(obj_type, template_attribute, key)
|
||||
self.assertNotEqual(None, res, 'result is None')
|
||||
self.assertEqual(ResultStatus.OPERATION_FAILED,
|
||||
res.result_status.enum,
|
||||
'result status did not return failed')
|
||||
self.assertEqual(ResultReason.INVALID_FIELD,
|
||||
res.result_reason.enum,
|
||||
'result reason did not match')
|
||||
|
||||
def test_register_object_type_mismatch(self):
|
||||
unsupported_types = (ObjectTypeEnum.CERTIFICATE,
|
||||
ObjectTypeEnum.PUBLIC_KEY,
|
||||
ObjectTypeEnum.PRIVATE_KEY,
|
||||
ObjectTypeEnum.SPLIT_KEY,
|
||||
ObjectTypeEnum.TEMPLATE,
|
||||
ObjectTypeEnum.SECRET_DATA,
|
||||
ObjectTypeEnum.OPAQUE_DATA)
|
||||
for unsupported_type in unsupported_types:
|
||||
obj_type = ObjectType(unsupported_type)
|
||||
key = self._get_symmetric_key()
|
||||
attributes = []
|
||||
template_attribute = TemplateAttribute(attributes=attributes)
|
||||
res = self.kmip.register(obj_type, template_attribute, key)
|
||||
self.assertNotEqual(None, res, 'result is None')
|
||||
self.assertEqual(ResultStatus.OPERATION_FAILED,
|
||||
res.result_status.enum,
|
||||
'result status did not return failed')
|
||||
self.assertEqual(ResultReason.INVALID_FIELD,
|
||||
res.result_reason.enum,
|
||||
'result reason did not match')
|
||||
|
||||
def test_get(self):
|
||||
uuid = self._create()
|
||||
key_format_type = KeyFormatType(KeyFormatTypeEnum.RAW)
|
||||
res = self.kmip.get(uuid, key_format_type)
|
||||
self.assertEqual(ResultStatus.SUCCESS, res.result_status.enum,
|
||||
'result status did not return success')
|
||||
|
||||
def test_get_no_key_format_type(self):
|
||||
uuid = self._create()
|
||||
res = self.kmip.get(uuid, None)
|
||||
self.assertEqual(ResultStatus.SUCCESS, res.result_status.enum,
|
||||
'result status did not return success')
|
||||
|
||||
def test_get_unknown(self):
|
||||
uuids = ('some random string', UniqueIdentifier('no key here'))
|
||||
for uuid in uuids:
|
||||
key_format_type = KeyFormatType(KeyFormatTypeEnum.RAW)
|
||||
res = self.kmip.get(uuid, key_format_type)
|
||||
self.assertEqual(ResultStatus.OPERATION_FAILED,
|
||||
res.result_status.enum,
|
||||
'result status did not return failed')
|
||||
self.assertEqual(ResultReason.ITEM_NOT_FOUND,
|
||||
res.result_reason.enum,
|
||||
'result reason did not match')
|
||||
|
||||
def test_get_no_uuid(self):
|
||||
self._create()
|
||||
key_format_type = KeyFormatType(KeyFormatTypeEnum.RAW)
|
||||
res = self.kmip.get(None, key_format_type)
|
||||
self.assertEqual(ResultStatus.OPERATION_FAILED, res.result_status.enum,
|
||||
'result status did not return failed')
|
||||
|
||||
def test_get_with_key_compression(self):
|
||||
uuid = self._create()
|
||||
key_format_type = KeyFormatType(KeyFormatTypeEnum.RAW)
|
||||
key_compression = KeyCompressionType(KeyCompressionTypeEnum.
|
||||
EC_PUBLIC_KEY_TYPE_UNCOMPRESSED)
|
||||
res = self.kmip.get(uuid, key_format_type, key_compression)
|
||||
self.assertEqual(ResultStatus.OPERATION_FAILED, res.result_status.enum,
|
||||
'result status did not return failed')
|
||||
self.assertEqual(ResultReason.KEY_COMPRESSION_TYPE_NOT_SUPPORTED,
|
||||
res.result_reason.enum,
|
||||
'result reason did not match')
|
||||
|
||||
def test_destroy(self):
|
||||
uuid = self._create()
|
||||
key_format_type = KeyFormatType(KeyFormatTypeEnum.RAW)
|
||||
res = self.kmip.get(uuid, key_format_type)
|
||||
self.assertEqual(ResultStatus.SUCCESS, res.result_status.enum,
|
||||
'result status did not return success')
|
||||
res = self.kmip.destroy(uuid)
|
||||
self.assertEqual(ResultStatus.SUCCESS, res.result_status.enum,
|
||||
'result status did not return success')
|
||||
res = self.kmip.destroy(uuid)
|
||||
self.assertEqual(ResultStatus.OPERATION_FAILED,
|
||||
res.result_status.enum,
|
||||
'result status did not return failed')
|
||||
self.assertEqual(ResultReason.ITEM_NOT_FOUND,
|
||||
res.result_reason.enum,
|
||||
'result reason did not match')
|
||||
|
||||
def test_destroy_no_uuid(self):
|
||||
res = self.kmip.destroy(None)
|
||||
self.assertEqual(ResultStatus.OPERATION_FAILED,
|
||||
res.result_status.enum,
|
||||
'result status did not return failed')
|
||||
self.assertEqual(ResultReason.ITEM_NOT_FOUND,
|
||||
res.result_reason.enum,
|
||||
'result reason did not match')
|
||||
|
||||
def test_destroy_unknown(self):
|
||||
uuids = ('some random string', UniqueIdentifier('no key here'))
|
||||
for uuid in uuids:
|
||||
key_format_type = KeyFormatType(KeyFormatTypeEnum.RAW)
|
||||
res = self.kmip.get(uuid, key_format_type)
|
||||
self.assertEqual(ResultStatus.OPERATION_FAILED,
|
||||
res.result_status.enum,
|
||||
'result status did not return failed')
|
||||
res = self.kmip.destroy(uuid)
|
||||
self.assertEqual(ResultStatus.OPERATION_FAILED,
|
||||
res.result_status.enum,
|
||||
'result status did not return failed')
|
||||
self.assertEqual(ResultReason.ITEM_NOT_FOUND,
|
||||
res.result_reason.enum,
|
||||
'result reason did not match')
|
||||
|
||||
def _create(self):
|
||||
obj_type = ObjectType(ObjectTypeEnum.SYMMETRIC_KEY)
|
||||
attributes = self._get_attrs()
|
||||
template_attribute = TemplateAttribute(attributes=attributes)
|
||||
res = self.kmip.create(obj_type, template_attribute)
|
||||
self.assertNotEqual(None, res, 'result is None')
|
||||
self.assertEqual(ResultStatus.SUCCESS, res.result_status.enum,
|
||||
'result status did not return success')
|
||||
return res.uuid
|
||||
|
||||
def _get_symmetric_key(self):
|
||||
# only need usage attribute
|
||||
attrs = [self._get_attrs()[1]]
|
||||
key_format_type = KeyBlock.KeyFormatType(KeyFormatTypeEnum.RAW)
|
||||
key_material = RawKey(self.key)
|
||||
key_value = KeyValueStruct(key_format_type, key_material, attrs)
|
||||
crypto_alg = CryptographicAlgorithm(self.algorithm_name)
|
||||
crypto_length = CryptographicLength(self.key_length)
|
||||
usage = CryptographicUsageMask(self.usage_mask)
|
||||
key_block = KeyBlock(key_format_type, None, key_value, crypto_alg,
|
||||
crypto_length, usage)
|
||||
return SymmetricKey(key_block)
|
||||
|
||||
def _get_attrs(self):
|
||||
attr_factory = AttributeFactory()
|
||||
algorithm = self._get_alg_attr(self.algorithm_name)
|
||||
length = self._get_length_attr(self.key_length)
|
||||
attribute_type = AttributeType.CRYPTOGRAPHIC_USAGE_MASK
|
||||
mask_flags = [CryptoUsageMaskEnum.ENCRYPT,
|
||||
CryptoUsageMaskEnum.DECRYPT]
|
||||
usage_mask = attr_factory.create_attribute(attribute_type,
|
||||
mask_flags)
|
||||
return [algorithm, usage_mask, length]
|
||||
|
||||
def _get_alg_attr(self, alg=None):
|
||||
if alg is None:
|
||||
alg = self.algorithm_name
|
||||
attr_factory = AttributeFactory()
|
||||
attribute_type = AttributeType.CRYPTOGRAPHIC_ALGORITHM
|
||||
return attr_factory.create_attribute(attribute_type, alg)
|
||||
|
||||
def _get_length_attr(self, length=None):
|
||||
if length is None:
|
||||
length = self.key_length
|
||||
attr_factory = AttributeFactory()
|
||||
attribute_type = AttributeType.CRYPTOGRAPHIC_LENGTH
|
||||
return attr_factory.create_attribute(attribute_type, length)
|
||||
|
||||
def _check_attr_exists(self, attr_expected, attributes):
|
||||
for attribute in attributes:
|
||||
if attribute.attribute_name.value ==\
|
||||
attr_expected.attribute_name.value:
|
||||
return attribute.attribute_value.value ==\
|
||||
attr_expected.attribute_value.value
|
||||
return False
|
134
kmip/tests/core/test_utils.py
Normal file
134
kmip/tests/core/test_utils.py
Normal file
@ -0,0 +1,134 @@
|
||||
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from testtools import TestCase
|
||||
|
||||
from kmip.core.errors import ErrorStrings
|
||||
|
||||
from kmip.core import utils
|
||||
|
||||
|
||||
class TestUtils(TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestUtils, self).setUp()
|
||||
|
||||
def tearDown(self):
|
||||
super(TestUtils, self).tearDown()
|
||||
|
||||
def test_count_bytes(self):
|
||||
num = 65535
|
||||
bytes_exp = 2
|
||||
bytes_obs = utils.count_bytes(num)
|
||||
self.assertEqual(bytes_exp, bytes_obs,
|
||||
'Value {0} requires {1} bytes to encode, '
|
||||
'received {2} byte(s)'.format(num, bytes_exp,
|
||||
bytes_obs))
|
||||
|
||||
def test_count_bytes_overflow(self):
|
||||
num = 65536
|
||||
bytes_exp = 3
|
||||
bytes_obs = utils.count_bytes(num)
|
||||
self.assertEqual(bytes_exp, bytes_obs,
|
||||
'Value {0} requires {1} bytes to encode, '
|
||||
'received {2} bytes'.format(num, bytes_exp,
|
||||
bytes_obs))
|
||||
|
||||
def test_count_bytes_zero(self):
|
||||
num = 0
|
||||
bytes_exp = 1
|
||||
bytes_obs = utils.count_bytes(num)
|
||||
self.assertEqual(bytes_exp, bytes_obs,
|
||||
'Value {0} requires {1} bytes to encode, '
|
||||
'received {2} byte(s)'.format(num, bytes_exp,
|
||||
bytes_obs))
|
||||
|
||||
|
||||
class TestBytearrayStream(TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestBytearrayStream, self).setUp()
|
||||
self.stream = utils.BytearrayStream()
|
||||
|
||||
self.bad_type = ErrorStrings.BAD_EXP_RECV.format('BytearrayStream.{0}',
|
||||
'type', '{1}', '{2}')
|
||||
self.bad_len = ErrorStrings.BAD_EXP_RECV.format('BytearrayStream.{0}',
|
||||
'length', '{1}', '{2}')
|
||||
self.bad_val = ErrorStrings.BAD_EXP_RECV.format('BytearrayStream.{0}',
|
||||
'value', '{1}', '{2}')
|
||||
|
||||
def tearDown(self):
|
||||
super(TestBytearrayStream, self).tearDown()
|
||||
|
||||
def test_init(self):
|
||||
value = '\x00'
|
||||
b = utils.BytearrayStream(value)
|
||||
|
||||
buf_type = type(b.buffer)
|
||||
msg = self.bad_type.format('buffer', bytearray, buf_type)
|
||||
self.assertIsInstance(b.buffer, bytearray,
|
||||
msg.format(bytearray, type(b.buffer)))
|
||||
|
||||
length = len(b.buffer)
|
||||
msg = self.bad_len.format('buffer', 1, length)
|
||||
self.assertEqual(1, length, msg)
|
||||
|
||||
content = str(b.buffer)
|
||||
msg = self.bad_val.format('buffer', value, content)
|
||||
self.assertEqual(value, content, msg)
|
||||
|
||||
def test_init_unset(self):
|
||||
b = utils.BytearrayStream()
|
||||
|
||||
buf_type = type(b.buffer)
|
||||
msg = self.bad_type.format('buffer', bytearray, buf_type)
|
||||
self.assertIsInstance(b.buffer, bytearray,
|
||||
msg.format(bytearray, type(b.buffer)))
|
||||
|
||||
length = len(b.buffer)
|
||||
msg = self.bad_len.format('buffer', 0, length)
|
||||
self.assertEqual(0, length, msg)
|
||||
|
||||
def test_read(self):
|
||||
# TODO (peter-hamilton) Finish implementation.
|
||||
self.skip('')
|
||||
|
||||
def test_write(self):
|
||||
# TODO (peter-hamilton) Finish implementation.
|
||||
self.skip('')
|
||||
|
||||
def test_peek(self):
|
||||
# TODO (peter-hamilton) Finish implementation.
|
||||
value = ('\x00\x01\x02\x03')
|
||||
expected = value
|
||||
b = expected
|
||||
expected = b
|
||||
b = utils.BytearrayStream(value)
|
||||
|
||||
def test_peek_overflow(self):
|
||||
# TODO (peter-hamilton) Finish implementation.
|
||||
self.skip('')
|
||||
|
||||
def test_peek_empty(self):
|
||||
# TODO (peter-hamilton) Finish implementation.
|
||||
self.skip('')
|
||||
|
||||
def test_peek_none(self):
|
||||
# TODO (peter-hamilton) Finish implementation.
|
||||
self.skip('')
|
||||
|
||||
def test_length(self):
|
||||
# TODO (peter-hamilton) Finish implementation.
|
||||
self.skip('')
|
14
kmip/tests/services/__init__.py
Normal file
14
kmip/tests/services/__init__.py
Normal file
@ -0,0 +1,14 @@
|
||||
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
385
kmip/tests/services/test_kmip_client.py
Normal file
385
kmip/tests/services/test_kmip_client.py
Normal file
@ -0,0 +1,385 @@
|
||||
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from testtools import TestCase
|
||||
|
||||
from subprocess import Popen
|
||||
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
|
||||
from kmip.core.enums import AttributeType
|
||||
from kmip.core.enums import CredentialType
|
||||
from kmip.core.enums import CryptographicAlgorithm
|
||||
from kmip.core.enums import CryptographicUsageMask
|
||||
from kmip.core.enums import ObjectType
|
||||
from kmip.core.enums import KeyFormatType
|
||||
from kmip.core.enums import ResultStatus
|
||||
from kmip.core.enums import ResultReason
|
||||
|
||||
from kmip.core.errors import KMIPServerSuicideError
|
||||
from kmip.core.errors import KMIPServerZombieError
|
||||
|
||||
from kmip.core.factories.attributes import AttributeFactory
|
||||
from kmip.core.factories.credentials import CredentialFactory
|
||||
from kmip.core.factories.secrets import SecretFactory
|
||||
|
||||
from kmip.core.objects import Attribute
|
||||
from kmip.core.objects import TemplateAttribute
|
||||
|
||||
from kmip.core.secrets import SymmetricKey
|
||||
|
||||
from kmip.services.kmip_client import KMIPProxy
|
||||
|
||||
import kmip.core.utils as utils
|
||||
|
||||
|
||||
class TestKMIPClient(TestCase):
|
||||
STARTUP_TIME = 1.0
|
||||
SHUTDOWN_TIME = 0.1
|
||||
KMIP_PORT = 9090
|
||||
|
||||
def setUp(self):
|
||||
super(TestKMIPClient, self).setUp()
|
||||
|
||||
self.attr_factory = AttributeFactory()
|
||||
self.cred_factory = CredentialFactory()
|
||||
self.secret_factory = SecretFactory()
|
||||
|
||||
# Set up the KMIP server process
|
||||
path = os.path.join(os.path.dirname(__file__), os.path.pardir,
|
||||
os.path.pardir, os.path.pardir, 'bin',
|
||||
'run_server.py')
|
||||
self.server = Popen(['python', '{0}'.format(path), '-p',
|
||||
'{0}'.format(self.KMIP_PORT)], stderr=sys.stdout)
|
||||
|
||||
time.sleep(self.STARTUP_TIME)
|
||||
|
||||
if self.server.poll() is not None:
|
||||
raise KMIPServerSuicideError(self.server.pid)
|
||||
|
||||
# Set up and open the client proxy; shutdown the server if open fails
|
||||
try:
|
||||
self.client = KMIPProxy(port=self.KMIP_PORT)
|
||||
self.client.open()
|
||||
except Exception, e:
|
||||
self._shutdown_server()
|
||||
raise e
|
||||
|
||||
def tearDown(self):
|
||||
super(TestKMIPClient, self).tearDown()
|
||||
|
||||
# Close the client proxy and shutdown the server
|
||||
self.client.close()
|
||||
self._shutdown_server()
|
||||
|
||||
def test_create(self):
|
||||
result = self._create_symmetric_key()
|
||||
|
||||
self._check_result_status(result.result_status.enum, ResultStatus,
|
||||
ResultStatus.SUCCESS)
|
||||
self._check_object_type(result.object_type.enum, ObjectType,
|
||||
ObjectType.SYMMETRIC_KEY)
|
||||
self._check_uuid(result.uuid.value, str)
|
||||
|
||||
# Check the template attribute type
|
||||
self._check_template_attribute(result.template_attribute,
|
||||
TemplateAttribute, 2,
|
||||
[[str, 'Cryptographic Length', int,
|
||||
256],
|
||||
[str, 'Unique Identifier', str,
|
||||
None]])
|
||||
|
||||
def test_get(self):
|
||||
credential_type = CredentialType.USERNAME_AND_PASSWORD
|
||||
credential_value = {'Username': 'Peter', 'Password': 'abc123'}
|
||||
credential = self.cred_factory.create_credential(credential_type,
|
||||
credential_value)
|
||||
result = self._create_symmetric_key()
|
||||
uuid = result.uuid.value
|
||||
|
||||
result = self.client.get(uuid, credential)
|
||||
|
||||
self._check_result_status(result.result_status.enum, ResultStatus,
|
||||
ResultStatus.SUCCESS)
|
||||
self._check_object_type(result.object_type.enum, ObjectType,
|
||||
ObjectType.SYMMETRIC_KEY)
|
||||
self._check_uuid(result.uuid.value, str)
|
||||
|
||||
# Check the secret type
|
||||
secret = result.secret
|
||||
|
||||
expected = SymmetricKey
|
||||
message = utils.build_er_error(result.__class__, 'type', expected,
|
||||
secret, 'secret')
|
||||
self.assertIsInstance(secret, expected, message)
|
||||
|
||||
def test_destroy(self):
|
||||
credential_type = CredentialType.USERNAME_AND_PASSWORD
|
||||
credential_value = {'Username': 'Peter', 'Password': 'abc123'}
|
||||
credential = self.cred_factory.create_credential(credential_type,
|
||||
credential_value)
|
||||
result = self._create_symmetric_key()
|
||||
uuid = result.uuid.value
|
||||
|
||||
# Verify the secret was created
|
||||
result = self.client.get(uuid, credential)
|
||||
|
||||
self._check_result_status(result.result_status.enum, ResultStatus,
|
||||
ResultStatus.SUCCESS)
|
||||
self._check_object_type(result.object_type.enum, ObjectType,
|
||||
ObjectType.SYMMETRIC_KEY)
|
||||
self._check_uuid(result.uuid.value, str)
|
||||
|
||||
secret = result.secret
|
||||
|
||||
expected = SymmetricKey
|
||||
message = utils.build_er_error(result.__class__, 'type', expected,
|
||||
secret, 'secret')
|
||||
self.assertIsInstance(secret, expected, message)
|
||||
|
||||
# Destroy the SYMMETRIC_KEY object
|
||||
result = self.client.destroy(uuid, credential)
|
||||
self._check_result_status(result.result_status.enum, ResultStatus,
|
||||
ResultStatus.SUCCESS)
|
||||
self._check_uuid(result.uuid.value, str)
|
||||
|
||||
# Verify the secret was destroyed
|
||||
result = self.client.get(uuid, credential)
|
||||
|
||||
self._check_result_status(result.result_status.enum, ResultStatus,
|
||||
ResultStatus.OPERATION_FAILED)
|
||||
|
||||
expected = ResultReason
|
||||
observed = type(result.result_reason.enum)
|
||||
message = utils.build_er_error(result.result_reason.__class__, 'type',
|
||||
expected, observed)
|
||||
self.assertEqual(expected, observed, message)
|
||||
|
||||
expected = ResultReason.ITEM_NOT_FOUND
|
||||
observed = result.result_reason.enum
|
||||
message = utils.build_er_error(result.result_reason.__class__,
|
||||
'value', expected, observed)
|
||||
self.assertEqual(expected, observed, message)
|
||||
|
||||
def test_register(self):
|
||||
credential_type = CredentialType.USERNAME_AND_PASSWORD
|
||||
credential_value = {'Username': 'Peter', 'Password': 'abc123'}
|
||||
credential = self.cred_factory.create_credential(credential_type,
|
||||
credential_value)
|
||||
|
||||
object_type = ObjectType.SYMMETRIC_KEY
|
||||
algorithm_value = CryptographicAlgorithm.AES
|
||||
mask_flags = [CryptographicUsageMask.ENCRYPT,
|
||||
CryptographicUsageMask.DECRYPT]
|
||||
attribute_type = AttributeType.CRYPTOGRAPHIC_USAGE_MASK
|
||||
usage_mask = self.attr_factory.create_attribute(attribute_type,
|
||||
mask_flags)
|
||||
attributes = [usage_mask]
|
||||
template_attribute = TemplateAttribute(attributes=attributes)
|
||||
|
||||
secret_features = {}
|
||||
|
||||
key_format_type = KeyFormatType.RAW
|
||||
secret_features.update([('key_format_type', key_format_type)])
|
||||
|
||||
key_data = {'bytes': bytearray('\x00\x00\x00\x00\x00\x00\x00\x00'
|
||||
'\x00\x00\x00\x00\x00\x00\x00\x00')}
|
||||
|
||||
secret_features.update([('key_value', key_data)])
|
||||
secret_features.update([('cryptographic_algorithm', algorithm_value)])
|
||||
secret_features.update([('cryptographic_length', 128)])
|
||||
|
||||
secret = self.secret_factory.create_secret(object_type,
|
||||
secret_features)
|
||||
|
||||
result = self.client.register(object_type, template_attribute, secret,
|
||||
credential)
|
||||
|
||||
self._check_result_status(result.result_status.enum, ResultStatus,
|
||||
ResultStatus.SUCCESS)
|
||||
self._check_uuid(result.uuid.value, str)
|
||||
|
||||
# Check the template attribute type
|
||||
self._check_template_attribute(result.template_attribute,
|
||||
TemplateAttribute, 1,
|
||||
[[str, 'Unique Identifier', str,
|
||||
None]])
|
||||
# Check that the returned key bytes match what was provided
|
||||
uuid = result.uuid.value
|
||||
result = self.client.get(uuid, credential)
|
||||
|
||||
self._check_result_status(result.result_status.enum, ResultStatus,
|
||||
ResultStatus.SUCCESS)
|
||||
self._check_object_type(result.object_type.enum, ObjectType,
|
||||
ObjectType.SYMMETRIC_KEY)
|
||||
self._check_uuid(result.uuid.value, str)
|
||||
|
||||
# Check the secret type
|
||||
secret = result.secret
|
||||
|
||||
expected = SymmetricKey
|
||||
message = utils.build_er_error(result.__class__, 'type', expected,
|
||||
secret, 'secret')
|
||||
self.assertIsInstance(secret, expected, message)
|
||||
|
||||
key_block = result.secret.key_block
|
||||
key_value = key_block.key_value
|
||||
key_material = key_value.key_value.key_material
|
||||
|
||||
expected = key_data.get('bytes')
|
||||
observed = key_material.value
|
||||
message = utils.build_er_error(key_material.__class__, 'value',
|
||||
expected, observed, 'value')
|
||||
self.assertEqual(expected, observed, message)
|
||||
|
||||
def _shutdown_server(self):
|
||||
if self.server.poll() is not None:
|
||||
return
|
||||
else:
|
||||
# Terminate the server process. If it resists, kill it.
|
||||
pid = self.server.pid
|
||||
self.server.terminate()
|
||||
time.sleep(self.SHUTDOWN_TIME)
|
||||
|
||||
if self.server.poll() is None:
|
||||
raise KMIPServerZombieError(pid)
|
||||
|
||||
def _create_symmetric_key(self):
|
||||
credential_type = CredentialType.USERNAME_AND_PASSWORD
|
||||
credential_value = {'Username': 'Peter', 'Password': 'abc123'}
|
||||
credential = self.cred_factory.create_credential(credential_type,
|
||||
credential_value)
|
||||
|
||||
object_type = ObjectType.SYMMETRIC_KEY
|
||||
attribute_type = AttributeType.CRYPTOGRAPHIC_ALGORITHM
|
||||
algorithm = self.attr_factory.create_attribute(
|
||||
attribute_type,
|
||||
CryptographicAlgorithm.AES)
|
||||
|
||||
mask_flags = [CryptographicUsageMask.ENCRYPT,
|
||||
CryptographicUsageMask.DECRYPT]
|
||||
attribute_type = AttributeType.CRYPTOGRAPHIC_USAGE_MASK
|
||||
usage_mask = self.attr_factory.create_attribute(attribute_type,
|
||||
mask_flags)
|
||||
attributes = [algorithm, usage_mask]
|
||||
template_attribute = TemplateAttribute(attributes=attributes)
|
||||
|
||||
return self.client.create(object_type, template_attribute,
|
||||
credential)
|
||||
|
||||
def _check_result_status(self, result_status, result_status_type,
|
||||
result_status_value):
|
||||
# Error check the result status type and value
|
||||
expected = result_status_type
|
||||
message = utils.build_er_error(result_status_type, 'type', expected,
|
||||
result_status)
|
||||
self.assertIsInstance(result_status, expected, message)
|
||||
|
||||
expected = result_status_value
|
||||
message = utils.build_er_error(result_status_type, 'value', expected,
|
||||
result_status)
|
||||
self.assertEqual(expected, result_status, message)
|
||||
|
||||
def _check_uuid(self, uuid, uuid_type):
|
||||
# Error check the UUID type and value
|
||||
not_expected = None
|
||||
message = utils.build_er_error(uuid_type, 'type',
|
||||
'not {0}'.format(not_expected), uuid)
|
||||
self.assertNotEqual(not_expected, uuid, message)
|
||||
|
||||
expected = uuid_type
|
||||
message = utils.build_er_error(uuid_type, 'type', expected, uuid)
|
||||
self.assertEqual(expected, type(uuid), message)
|
||||
|
||||
def _check_object_type(self, object_type, object_type_type,
|
||||
object_type_value):
|
||||
# Error check the object type type and value
|
||||
expected = object_type_type
|
||||
message = utils.build_er_error(object_type_type, 'type', expected,
|
||||
object_type)
|
||||
self.assertIsInstance(object_type, expected, message)
|
||||
|
||||
expected = object_type_value
|
||||
message = utils.build_er_error(object_type_type, 'value', expected,
|
||||
object_type)
|
||||
self.assertEqual(expected, object_type, message)
|
||||
|
||||
def _check_template_attribute(self, template_attribute,
|
||||
template_attribute_type, num_attributes,
|
||||
attribute_features):
|
||||
# Error check the template attribute type
|
||||
expected = template_attribute_type
|
||||
message = utils.build_er_error(template_attribute.__class__, 'type',
|
||||
expected, template_attribute)
|
||||
self.assertIsInstance(template_attribute, expected, message)
|
||||
|
||||
attributes = template_attribute.attributes
|
||||
|
||||
expected = num_attributes
|
||||
observed = len(attributes)
|
||||
message = utils.build_er_error(TemplateAttribute.__class__, 'number',
|
||||
expected, observed, 'attributes')
|
||||
|
||||
for i in xrange(num_attributes):
|
||||
features = attribute_features[i]
|
||||
self._check_attribute(attributes[i], features[0], features[1],
|
||||
features[2], features[3])
|
||||
|
||||
def _check_attribute(self, attribute, attribute_name_type,
|
||||
attribute_name_value, attribute_value_type,
|
||||
attribute_value_value):
|
||||
# Error check the attribute name and value type and value
|
||||
attribute_name = attribute.attribute_name
|
||||
attribute_value = attribute.attribute_value
|
||||
|
||||
self._check_attribute_name(attribute_name, attribute_name_type,
|
||||
attribute_name_value)
|
||||
|
||||
if attribute_name_value == 'Unique Identifier':
|
||||
self._check_uuid(attribute_value.value, attribute_value_type)
|
||||
else:
|
||||
self._check_attribute_value(attribute_value, attribute_value_type,
|
||||
attribute_value_value)
|
||||
|
||||
def _check_attribute_name(self, attribute_name, attribute_name_type,
|
||||
attribute_name_value):
|
||||
# Error check the attribute name type and value
|
||||
expected = attribute_name_type
|
||||
observed = type(attribute_name.value)
|
||||
message = utils.build_er_error(attribute_name_type, 'type', expected,
|
||||
observed)
|
||||
self.assertEqual(expected, observed, message)
|
||||
|
||||
expected = attribute_name_value
|
||||
observed = attribute_name.value
|
||||
message = utils.build_er_error(attribute_name_type, 'value', expected,
|
||||
observed)
|
||||
self.assertEqual(expected, observed, message)
|
||||
|
||||
def _check_attribute_value(self, attribute_value, attribute_value_type,
|
||||
attribute_value_value):
|
||||
expected = attribute_value_type
|
||||
observed = type(attribute_value.value)
|
||||
message = utils.build_er_error(Attribute, 'type', expected, observed,
|
||||
'attribute_value')
|
||||
self.assertEqual(expected, observed, message)
|
||||
|
||||
expected = attribute_value_value
|
||||
observed = attribute_value.value
|
||||
message = utils.build_er_error(Attribute, 'value', expected, observed,
|
||||
'attribute_value')
|
||||
self.assertEqual(expected, observed, message)
|
@ -1,95 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Autogenerated by Thrift Compiler (0.9.1)
|
||||
#
|
||||
# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
|
||||
#
|
||||
# options string: py
|
||||
#
|
||||
|
||||
import sys
|
||||
import pprint
|
||||
from urlparse import urlparse
|
||||
from thrift.transport import TTransport
|
||||
from thrift.transport import TSocket
|
||||
from thrift.transport import THttpClient
|
||||
from thrift.protocol import TBinaryProtocol
|
||||
|
||||
from kmip import KMIP
|
||||
from kmip.ttypes import *
|
||||
|
||||
if len(sys.argv) <= 1 or sys.argv[1] == '--help':
|
||||
print ''
|
||||
print 'Usage: ' + sys.argv[0] + ' [-h host[:port]] [-u url] [-f[ramed]] function [arg1 [arg2...]]'
|
||||
print ''
|
||||
print 'Functions:'
|
||||
print ' void create()'
|
||||
print ' void register_mo()'
|
||||
print ''
|
||||
sys.exit(0)
|
||||
|
||||
pp = pprint.PrettyPrinter(indent = 2)
|
||||
host = 'localhost'
|
||||
port = 9090
|
||||
uri = ''
|
||||
framed = False
|
||||
http = False
|
||||
argi = 1
|
||||
|
||||
if sys.argv[argi] == '-h':
|
||||
parts = sys.argv[argi+1].split(':')
|
||||
host = parts[0]
|
||||
if len(parts) > 1:
|
||||
port = int(parts[1])
|
||||
argi += 2
|
||||
|
||||
if sys.argv[argi] == '-u':
|
||||
url = urlparse(sys.argv[argi+1])
|
||||
parts = url[1].split(':')
|
||||
host = parts[0]
|
||||
if len(parts) > 1:
|
||||
port = int(parts[1])
|
||||
else:
|
||||
port = 80
|
||||
uri = url[2]
|
||||
if url[4]:
|
||||
uri += '?%s' % url[4]
|
||||
http = True
|
||||
argi += 2
|
||||
|
||||
if sys.argv[argi] == '-f' or sys.argv[argi] == '-framed':
|
||||
framed = True
|
||||
argi += 1
|
||||
|
||||
cmd = sys.argv[argi]
|
||||
args = sys.argv[argi+1:]
|
||||
|
||||
if http:
|
||||
transport = THttpClient.THttpClient(host, port, uri)
|
||||
else:
|
||||
socket = TSocket.TSocket(host, port)
|
||||
if framed:
|
||||
transport = TTransport.TFramedTransport(socket)
|
||||
else:
|
||||
transport = TTransport.TBufferedTransport(socket)
|
||||
protocol = TBinaryProtocol.TBinaryProtocol(transport)
|
||||
client = KMIP.Client(protocol)
|
||||
transport.open()
|
||||
|
||||
if cmd == 'create':
|
||||
if len(args) != 0:
|
||||
print 'create requires 0 args'
|
||||
sys.exit(1)
|
||||
pp.pprint(client.create())
|
||||
|
||||
elif cmd == 'register_mo':
|
||||
if len(args) != 0:
|
||||
print 'register_mo requires 0 args'
|
||||
sys.exit(1)
|
||||
pp.pprint(client.register_mo())
|
||||
|
||||
else:
|
||||
print 'Unrecognized method %s' % cmd
|
||||
sys.exit(1)
|
||||
|
||||
transport.close()
|
@ -1,295 +0,0 @@
|
||||
#
|
||||
# Autogenerated by Thrift Compiler (0.9.1)
|
||||
#
|
||||
# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
|
||||
#
|
||||
# options string: py
|
||||
#
|
||||
|
||||
from thrift.Thrift import TType, TMessageType, TException, TApplicationException
|
||||
from ttypes import *
|
||||
from thrift.Thrift import TProcessor
|
||||
from thrift.transport import TTransport
|
||||
from thrift.protocol import TBinaryProtocol, TProtocol
|
||||
try:
|
||||
from thrift.protocol import fastbinary
|
||||
except:
|
||||
fastbinary = None
|
||||
|
||||
|
||||
class Iface:
|
||||
def create(self):
|
||||
pass
|
||||
|
||||
def register_mo(self):
|
||||
pass
|
||||
|
||||
|
||||
class Client(Iface):
|
||||
def __init__(self, iprot, oprot=None):
|
||||
self._iprot = self._oprot = iprot
|
||||
if oprot is not None:
|
||||
self._oprot = oprot
|
||||
self._seqid = 0
|
||||
|
||||
def create(self):
|
||||
self.send_create()
|
||||
self.recv_create()
|
||||
|
||||
def send_create(self):
|
||||
self._oprot.writeMessageBegin('create', TMessageType.CALL, self._seqid)
|
||||
args = create_args()
|
||||
args.write(self._oprot)
|
||||
self._oprot.writeMessageEnd()
|
||||
self._oprot.trans.flush()
|
||||
|
||||
def recv_create(self):
|
||||
(fname, mtype, rseqid) = self._iprot.readMessageBegin()
|
||||
if mtype == TMessageType.EXCEPTION:
|
||||
x = TApplicationException()
|
||||
x.read(self._iprot)
|
||||
self._iprot.readMessageEnd()
|
||||
raise x
|
||||
result = create_result()
|
||||
result.read(self._iprot)
|
||||
self._iprot.readMessageEnd()
|
||||
return
|
||||
|
||||
def register_mo(self):
|
||||
self.send_register_mo()
|
||||
self.recv_register_mo()
|
||||
|
||||
def send_register_mo(self):
|
||||
self._oprot.writeMessageBegin('register_mo', TMessageType.CALL, self._seqid)
|
||||
args = register_mo_args()
|
||||
args.write(self._oprot)
|
||||
self._oprot.writeMessageEnd()
|
||||
self._oprot.trans.flush()
|
||||
|
||||
def recv_register_mo(self):
|
||||
(fname, mtype, rseqid) = self._iprot.readMessageBegin()
|
||||
if mtype == TMessageType.EXCEPTION:
|
||||
x = TApplicationException()
|
||||
x.read(self._iprot)
|
||||
self._iprot.readMessageEnd()
|
||||
raise x
|
||||
result = register_mo_result()
|
||||
result.read(self._iprot)
|
||||
self._iprot.readMessageEnd()
|
||||
return
|
||||
|
||||
|
||||
class Processor(Iface, TProcessor):
|
||||
def __init__(self, handler):
|
||||
self._handler = handler
|
||||
self._processMap = {}
|
||||
self._processMap["create"] = Processor.process_create
|
||||
self._processMap["register_mo"] = Processor.process_register_mo
|
||||
|
||||
def process(self, iprot, oprot):
|
||||
(name, type, seqid) = iprot.readMessageBegin()
|
||||
if name not in self._processMap:
|
||||
iprot.skip(TType.STRUCT)
|
||||
iprot.readMessageEnd()
|
||||
x = TApplicationException(TApplicationException.UNKNOWN_METHOD, 'Unknown function %s' % (name))
|
||||
oprot.writeMessageBegin(name, TMessageType.EXCEPTION, seqid)
|
||||
x.write(oprot)
|
||||
oprot.writeMessageEnd()
|
||||
oprot.trans.flush()
|
||||
return
|
||||
else:
|
||||
self._processMap[name](self, seqid, iprot, oprot)
|
||||
return True
|
||||
|
||||
def process_create(self, seqid, iprot, oprot):
|
||||
args = create_args()
|
||||
args.read(iprot)
|
||||
iprot.readMessageEnd()
|
||||
result = create_result()
|
||||
self._handler.create()
|
||||
oprot.writeMessageBegin("create", TMessageType.REPLY, seqid)
|
||||
result.write(oprot)
|
||||
oprot.writeMessageEnd()
|
||||
oprot.trans.flush()
|
||||
|
||||
def process_register_mo(self, seqid, iprot, oprot):
|
||||
args = register_mo_args()
|
||||
args.read(iprot)
|
||||
iprot.readMessageEnd()
|
||||
result = register_mo_result()
|
||||
self._handler.register_mo()
|
||||
oprot.writeMessageBegin("register_mo", TMessageType.REPLY, seqid)
|
||||
result.write(oprot)
|
||||
oprot.writeMessageEnd()
|
||||
oprot.trans.flush()
|
||||
|
||||
|
||||
# HELPER FUNCTIONS AND STRUCTURES
|
||||
|
||||
class create_args:
|
||||
|
||||
thrift_spec = (
|
||||
)
|
||||
|
||||
def read(self, iprot):
|
||||
if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None:
|
||||
fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec))
|
||||
return
|
||||
iprot.readStructBegin()
|
||||
while True:
|
||||
(fname, ftype, fid) = iprot.readFieldBegin()
|
||||
if ftype == TType.STOP:
|
||||
break
|
||||
else:
|
||||
iprot.skip(ftype)
|
||||
iprot.readFieldEnd()
|
||||
iprot.readStructEnd()
|
||||
|
||||
def write(self, oprot):
|
||||
if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None:
|
||||
oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec)))
|
||||
return
|
||||
oprot.writeStructBegin('create_args')
|
||||
oprot.writeFieldStop()
|
||||
oprot.writeStructEnd()
|
||||
|
||||
def validate(self):
|
||||
return
|
||||
|
||||
|
||||
def __repr__(self):
|
||||
L = ['%s=%r' % (key, value)
|
||||
for key, value in self.__dict__.iteritems()]
|
||||
return '%s(%s)' % (self.__class__.__name__, ', '.join(L))
|
||||
|
||||
def __eq__(self, other):
|
||||
return isinstance(other, self.__class__) and self.__dict__ == other.__dict__
|
||||
|
||||
def __ne__(self, other):
|
||||
return not (self == other)
|
||||
|
||||
class create_result:
|
||||
|
||||
thrift_spec = (
|
||||
)
|
||||
|
||||
def read(self, iprot):
|
||||
if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None:
|
||||
fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec))
|
||||
return
|
||||
iprot.readStructBegin()
|
||||
while True:
|
||||
(fname, ftype, fid) = iprot.readFieldBegin()
|
||||
if ftype == TType.STOP:
|
||||
break
|
||||
else:
|
||||
iprot.skip(ftype)
|
||||
iprot.readFieldEnd()
|
||||
iprot.readStructEnd()
|
||||
|
||||
def write(self, oprot):
|
||||
if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None:
|
||||
oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec)))
|
||||
return
|
||||
oprot.writeStructBegin('create_result')
|
||||
oprot.writeFieldStop()
|
||||
oprot.writeStructEnd()
|
||||
|
||||
def validate(self):
|
||||
return
|
||||
|
||||
|
||||
def __repr__(self):
|
||||
L = ['%s=%r' % (key, value)
|
||||
for key, value in self.__dict__.iteritems()]
|
||||
return '%s(%s)' % (self.__class__.__name__, ', '.join(L))
|
||||
|
||||
def __eq__(self, other):
|
||||
return isinstance(other, self.__class__) and self.__dict__ == other.__dict__
|
||||
|
||||
def __ne__(self, other):
|
||||
return not (self == other)
|
||||
|
||||
class register_mo_args:
|
||||
|
||||
thrift_spec = (
|
||||
)
|
||||
|
||||
def read(self, iprot):
|
||||
if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None:
|
||||
fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec))
|
||||
return
|
||||
iprot.readStructBegin()
|
||||
while True:
|
||||
(fname, ftype, fid) = iprot.readFieldBegin()
|
||||
if ftype == TType.STOP:
|
||||
break
|
||||
else:
|
||||
iprot.skip(ftype)
|
||||
iprot.readFieldEnd()
|
||||
iprot.readStructEnd()
|
||||
|
||||
def write(self, oprot):
|
||||
if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None:
|
||||
oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec)))
|
||||
return
|
||||
oprot.writeStructBegin('register_mo_args')
|
||||
oprot.writeFieldStop()
|
||||
oprot.writeStructEnd()
|
||||
|
||||
def validate(self):
|
||||
return
|
||||
|
||||
|
||||
def __repr__(self):
|
||||
L = ['%s=%r' % (key, value)
|
||||
for key, value in self.__dict__.iteritems()]
|
||||
return '%s(%s)' % (self.__class__.__name__, ', '.join(L))
|
||||
|
||||
def __eq__(self, other):
|
||||
return isinstance(other, self.__class__) and self.__dict__ == other.__dict__
|
||||
|
||||
def __ne__(self, other):
|
||||
return not (self == other)
|
||||
|
||||
class register_mo_result:
|
||||
|
||||
thrift_spec = (
|
||||
)
|
||||
|
||||
def read(self, iprot):
|
||||
if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None:
|
||||
fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec))
|
||||
return
|
||||
iprot.readStructBegin()
|
||||
while True:
|
||||
(fname, ftype, fid) = iprot.readFieldBegin()
|
||||
if ftype == TType.STOP:
|
||||
break
|
||||
else:
|
||||
iprot.skip(ftype)
|
||||
iprot.readFieldEnd()
|
||||
iprot.readStructEnd()
|
||||
|
||||
def write(self, oprot):
|
||||
if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None:
|
||||
oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec)))
|
||||
return
|
||||
oprot.writeStructBegin('register_mo_result')
|
||||
oprot.writeFieldStop()
|
||||
oprot.writeStructEnd()
|
||||
|
||||
def validate(self):
|
||||
return
|
||||
|
||||
|
||||
def __repr__(self):
|
||||
L = ['%s=%r' % (key, value)
|
||||
for key, value in self.__dict__.iteritems()]
|
||||
return '%s(%s)' % (self.__class__.__name__, ', '.join(L))
|
||||
|
||||
def __eq__(self, other):
|
||||
return isinstance(other, self.__class__) and self.__dict__ == other.__dict__
|
||||
|
||||
def __ne__(self, other):
|
||||
return not (self == other)
|
@ -1 +0,0 @@
|
||||
__all__ = ['ttypes', 'constants', 'KMIP']
|
@ -1,11 +0,0 @@
|
||||
#
|
||||
# Autogenerated by Thrift Compiler (0.9.1)
|
||||
#
|
||||
# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
|
||||
#
|
||||
# options string: py
|
||||
#
|
||||
|
||||
from thrift.Thrift import TType, TMessageType, TException, TApplicationException
|
||||
from ttypes import *
|
||||
|
@ -1,18 +0,0 @@
|
||||
#
|
||||
# Autogenerated by Thrift Compiler (0.9.1)
|
||||
#
|
||||
# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
|
||||
#
|
||||
# options string: py
|
||||
#
|
||||
|
||||
from thrift.Thrift import TType, TMessageType, TException, TApplicationException
|
||||
|
||||
from thrift.transport import TTransport
|
||||
from thrift.protocol import TBinaryProtocol, TProtocol
|
||||
try:
|
||||
from thrift.protocol import fastbinary
|
||||
except:
|
||||
fastbinary = None
|
||||
|
||||
|
@ -1 +1,4 @@
|
||||
# TODO: Add any library dependencies here
|
||||
enum34
|
||||
sqlalchemy
|
||||
thrift
|
||||
|
||||
|
42
setup.py
Normal file
42
setup.py
Normal file
@ -0,0 +1,42 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
# implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import setuptools
|
||||
|
||||
setuptools.setup(
|
||||
name='PyKMIP',
|
||||
version='0.0.1',
|
||||
description='KMIP v1.1 library',
|
||||
keywords='KMIP',
|
||||
author='Peter Hamilton',
|
||||
author_email='peter.hamilton@jhuapl.edu',
|
||||
url='http://www.jhuapl.edu',
|
||||
license='Apache License, Version 2.0',
|
||||
packages=setuptools.find_packages(exclude=["kmip.tests", "kmip.tests.*"]),
|
||||
classifiers=[
|
||||
"Intended Audience :: Developers",
|
||||
"License :: OSI Approved :: Apache Software License",
|
||||
"Natural Language :: English",
|
||||
"Operating System :: MacOS :: MacOS X",
|
||||
"Operating System :: POSIX",
|
||||
"Operating System :: POSIX :: BSD",
|
||||
"Operating System :: POSIX :: Linux",
|
||||
"Operating System :: Microsoft :: Windows",
|
||||
"Programming Language :: Python",
|
||||
"Programming Language :: Python :: 2",
|
||||
"Programming Language :: Python :: 2.6",
|
||||
"Programming Language :: Python :: 2.7",
|
||||
],
|
||||
)
|
@ -1 +1,11 @@
|
||||
# TODO: add any test requirements here
|
||||
coverage
|
||||
pytest
|
||||
flake8
|
||||
testtools
|
||||
fixtures
|
||||
testresources
|
||||
mock
|
||||
testscenarios
|
||||
testrepository
|
||||
sphinx
|
||||
|
@ -1,43 +0,0 @@
|
||||
/**
|
||||
* This is the thrift definition file. It defines all of the methods and objects
|
||||
* for the KMIP server. This file is used by thrift to generate the plumbing for
|
||||
* a KMIP client and server.
|
||||
*
|
||||
* This file generated the files under kmip/thrift.
|
||||
*
|
||||
* If this file is updated then run the following command to update the
|
||||
* kmip/thrift directory.
|
||||
*
|
||||
* thrift -o kmip -r --gen py thrift/tutorial.thrift
|
||||
*/
|
||||
|
||||
/**
|
||||
* The first thing to know about are types. The available types in Thrift are:
|
||||
*
|
||||
* bool Boolean, one byte
|
||||
* byte Signed byte
|
||||
* i16 Signed 16-bit integer
|
||||
* i32 Signed 32-bit integer
|
||||
* i64 Signed 64-bit integer
|
||||
* double 64-bit floating point value
|
||||
* string String
|
||||
* binary Blob (byte array)
|
||||
* map<t1,t2> Map from one type to another
|
||||
* list<t1> Ordered list of one type
|
||||
* set<t1> Set of unique elements of one type
|
||||
*
|
||||
*/
|
||||
|
||||
namespace cpp thrift
|
||||
namespace d thrift
|
||||
namespace java thrift
|
||||
namespace php thrift
|
||||
namespace perl thrift
|
||||
|
||||
service KMIP {
|
||||
|
||||
void create(),
|
||||
/* Did not use register because it is a reserved word */
|
||||
void register_mo()
|
||||
|
||||
}
|
16
tox.ini
Normal file
16
tox.ini
Normal file
@ -0,0 +1,16 @@
|
||||
[tox]
|
||||
envlist = pep8,py27,py26
|
||||
|
||||
[testenv]
|
||||
deps = -r{toxinidir}/requirements.txt
|
||||
-r{toxinidir}/test-requirements.txt
|
||||
|
||||
commands =
|
||||
coverage run --source=kmip/ -m pytest --strict {posargs}
|
||||
coverage report
|
||||
|
||||
[testenv:pep8]
|
||||
commands = flake8 {posargs}
|
||||
|
||||
[flake8]
|
||||
exclude = .git,.tox,dist,rpmbuild,*.egg-info
|
Loading…
Reference in New Issue
Block a user