The Secret Containers resource is now available in Barbican, so it should also be added to the client.
We need to be able to consume and create Container resources in the Python library using Python objects to represent the containers.
Add new Classes to the client to represent the different types of Containers available in Barbican in a new containers module:
barbicanclient.containers.Container barbicanclient.containers.CertificateContainer barbicanclient.containers.RSAContainer
The classes should be usable thusly:
from barbicanclient.containers import Container, RSAContainer # New Generic Container my_container = Container() my_container.add("Secret Name in Container", Secret(...)) my_container.save() # New RSA Container my_rsa_container = RSAContainer() my_rsa_container.public_key = Secret(...) my_rsa_container.private_key = Secret(...) my_rsa_container.private_key_passphrase = Secret(...) #optional my_rsa_container.save() # RSAContainer should be subclassed from Container my_rsa_container.add("public_key", Secret(...)) # should work my_rsa_container.add("unsupported_secret_name", Secret(...)) # should raise exception # New Certificate Container my_cert_container = CertificateContainer() my_cert_container.certificate = Secret(...) my_cert_container.private_key = Secret(...) my_cert_container.private_key_passphrase = Secret(...) my_cert_container.intermediates = Secret(...) my_cert_container.save() # CertificateContainer should be subclassed from Container my_cert_container.add('certificate', Secret(...)) # should work my_cert_container.add('unsupported_secret_name', Secret(...)) # should raise exception
Objects should be lazy, so requests should not be sent until the save() method is called. The save() method should also recursively store secrets if they have not yet been stored to the Barbican instance.
Once the save() method is called for the first time the Container becomes immutable, subsequent calls to add() or save() should raise exceptions. Basically, any action that would modify the container, except for delete(), should raise an exception.
Retrieving existing containers should be done via a ContainerManager accessible from the client object:
from barbicanclient import client barbican = client.Client(...) my_container = barbican.containers.get('https://ref_to_container/UUID')
The get() method should return an instance of the appropriate Container class. Listing existing methods should be done via the ContainerManager as well:
my_containers = barbican.containers.list(limit=10, offset=0) isinstance(my_containers, list) # should return True
Container deletion should be done on either the Container object or using the ContainerManger:
my_container = barbican.containers.get('https://ref_to_container/UUID') my_container.delete() # or barbican.containers.delete('https://ref_to_container/UUID')
The proposed functionality above pushes most of the actions to the Container objects, while keeping the ContainerManager functionality somewhat light. As an alternative, the ContanerManager could perform all of the functionality, while making the Container objects simple.
I think container creation in a single method could get ugly really fast, so I would prefer to avoid it.
Logging should be done in a manner consistent with the rest of the library.
None as this is new functionality.
Blueprint Draft: dougmendizabal Implementation: TBD
Testing should be consistent with existing testing in the library.
All new Container functionality needs to be documented.
Containers in the Client etherpad: https://etherpad.openstack.org/p/python-barbicanclient-containers