Client SDK Version 1.8.0
Ionic Security client SDK for Python users
AgentKeyServices Implementors Overview

Introduction to AgentKeyServicesBase

ionicsdk.services.AgentKeyServicesBase is an interface that users of the SDK can use to write their own custom key services that our ciphers can use.


Using AgentKeyServicesBase

You can define your own key services class by implementing the interface defined in Services.py.

An example below illustrates creating a key services class and creating a ionicsdk.chunkcipher.ChunkCipherAuto cipher using that service.

Example Custom Key Services:

class PassThruAgent(ionicsdk.AgentKeyServicesBase):
def __init__(self, agentkeyservice):
# This custom implementation is just a wrapper around an existing Ionic Agent Service
self.services = agentkeyservice
# Our wrapper attempts to reduce the number of server calls by creating local caches
self.cachedNewKeys = []
self.cacheExistingKeys = {}
self.cacheNum = 16
# Our wrapper also simplifies the interface by having a local copy of the attributes and metadata
self.attributes = { "classifications": ["c1", "c2"], "color": ["green"] }
self.metadata = { "test-meta-key": "test-meta-value" }
self.mutableAttributes = {u"test-mutable-1": [u"test-mutable-value-1", u"test-mutable-value-2"], u"test-mutable-2":[u"test-mutable-value-1",]}
# This lets us check that the cache is working
self.serverCalls = 0;
def hasactiveprofile(self):
# We can just pass through to the Ionic Service in some cases
return self.services.hasactiveprofile()
def getactiveprofile(self):
return self.services.getactiveprofile
def createkey(self, attributesdict = None, metadatadict = None, mutableAttributesdict = None):
# If our cache is empty, request a number of keys
if len(self.cachedNewKeys) == 0:
# Record our server call
self.serverCalls += 1
# In this example, we're ignoring the attributes passed in and use the local ones. By using a standard set of
# attributes, we can actually do this cache. We could combine with the method parameters or let them over-ride,
# but then we would need to make sure cache keys actually used the correct attributes.
self.cachedNewKeys = self.services.createkeys(self.cacheNum, self.attributes, self.metadata, self.mutableAttributes)
# Grab a key from the new key cache.
key = self.cachedNewKeys.pop()
# Add this key to the in use key cache, so GetKey calls won't have to go to the server.
self.cacheExistingKeys[key.id] = key
return key
def createkeys(self, keycount, attributesdict = None, metadatadict = None, mutableAttributesdict = None):
# If we still have enough keys in cache use those, otherwise, just pass thru.
if len(self.cachedNewKeys) >= keycount:
keys = []
for i in range(keycount):
keys.append(self.cachedNewKeys.pop())
else:
# Record our server call.
self.serverCalls += 1
keys = self.services.createkeys(keycount, self.attributes, self.metadata, self.mutableAttributes)
# Add these keys to the in use key cache, so GetKey calls won't have to go to the server.
for key in keys:
self.cacheExistingKeys[key.id] = key
return keys
def getkey(self, keyidstring, metadatadict = None):
# Check if the key is in cache, if so return immediately.
key = self.cacheExistingKeys.get(keyidstring)
if key:
return key
# If the key is not in cache, it might have been created in a previous run of this code and therefore not in cache.
# In that case, we can just pass through.
self.serverCalls += 1
key = self.services.getkey(keyidstring, self.metadata)
# Add this key to the in use key cache.
self.cacheExistingKeys[key.id] = key
return key
def getkeys(self, keyidstringlist, metadatadict = None):
# Run through the list of requested keys and find the ones in cache and the ones we need to try to retrieve from the server.
keys = []
unfoundIds = []
for keyid in keyidstringlist:
key = self.cacheExistingKeys.get(keyid)
if key:
keys.append(key)
else:
unfoundIds.append(keyid)
if len(unfoundIds):
self.serverCalls += 1
serverKeys = self.services.getkeys(unfoundIds, self.metadata)
keys.extend(serverKeys)
# Add these keys to the in use key cache.
for key in serverKeys:
self.cacheExistingKeys[key.id] = key
return keys


Using our example key services class:

# Create a normal Ionic Agent Service
plaintextPersistor = ionicsdk.DeviceProfilePersistorPlaintextFile("plaintext.sep")
agent = ionicsdk.Agent(profilepersistor=plaintextPersistor)
# Create our wrapper
wrappedAgent = PassThruAgent(agent)
# initialize a cipher using our custom service
cipher = ionicsdk.ChunkCipherAuto(wrappedAgent)