Implement Containers for Secrets

Registered by Huseyin Gedikli

Containers will allow us to store asymmetric keys inside Barbican.

Containers basically has a name and references for secrets. If Container type is RSA, users will provide us 3 secret references such as public key, private key, private key passphrase references. Users will continue to store their keys using the secrets API.

Secrets will also have "container_id" field in case users want to associate their secrets with "generic" containers.

So there will be 2 types of containers. Generic and RSA. If the container is generic, then user can associate their secrets with the generic container by updating the container_id field in the secret.

If container type is RSA, then user have to provide 3 secret ids for RSA container.

Sample Request for creating a generic type Container

Endpoint: barbicanapi/v1/{tenant_id}/containers
Request Type: POST
Request Body:

{
 "name":"generic container",
 "type":"generic"
}

Response:
{"container_ref": "barbicanapi/v1/{tenant_id}/containers/05a47308-d045-43d6-bfe3-1dbcd0c3a97b"}

Sample Request for creating an RSA Container
Endpoint: barbicanapi/v1/{tenant_id}/containers
Request Type: POST
Request Body:

{
 "name":"rsa container",
 "type":"rsa",
 "public_key_ref":"05a47308-d045-43d6-bfe3-1dbcd0c3a97b",
 "private_key_ref":"05a47308-d045-43d6-bfe3-1dbcd0c3a97b",
 "private_key_passpharase_ref":"05a47308-d045-43d6-bfe3-1dbcd0c3a97b"
}

All fields (public/private/passphrase) are optional. User can create an empty RSA container and update these fields with a PUT request later.

 * Containers belong to Tenants.
 * Deleting a container will delete all referenced secrets
 * Generic Containers are for users who wants to associate their secrets with containers. A sample scenario would be user creating a container named 'nova_secrets' and associating all nova related keys with it.

User workflow for storing RSA keys in Barbican:
Create a secret with the private key payload.
Create a secret with the public key payload.
Create a secret with the private key passphrase payload.
Create "rsa" type container or update existing RSA container with secret ids.

User workflow for generating RSA keys in Barbican
Make a POST to order api
Order api creates 3 secrets and a RSA type container. RSA type references 3 secrets (public/private/passphrase)
Order api returns the container id

Blueprint information

Status:
Complete
Approver:
None
Priority:
Undefined
Drafter:
Huseyin Gedikli
Direction:
Needs approval
Assignee:
Huseyin Gedikli
Definition:
New
Series goal:
Accepted for icehouse
Implementation:
Implemented
Milestone target:
None
Started by
Douglas Mendizábal
Completed by
Douglas Mendizábal

Related branches

Sprints

Whiteboard

Gerrit topic: https://review.openstack.org/#q,topic:bp/crud-endpoints-secret-container,n,z

Addressed by: https://review.openstack.org/70189
    Adds container endpoints to Barbican API

API Specs : https://etherpad.openstack.org/p/keypairs

Question[hgedikli]:
Users can create a generic container named "staging_environment_keys" and assign his secrets to it. What should we do if user wants to assign RSA containers to generic type containers?
[john-wood] I think if we want Containers to hold other Containers or Secrets, then either the Container type needs to extend Secret, or else we need to allow Containers to have separate Secret and Container associations.

Question[Rob Clark]:
How will this handle situations where RSA containers only require two parts, the public and private keys but no password. Is the absence of password enough or is an empty string required?
Answer[hgedikli] All RSA fields are optional, so a user can create an empty container, or container with only public key, private key, etc.

Comment (atiwari)
1. Seems we are talking about two separate concepts, In case of "Generic" type you are using a container as a "Tag/Key Ring/Group" where we can group multiple secrets and in case of RSA it is nothing but a Key Pair and used to group only 3 items.
   [hgedikli] I agree these are 2 different concepts and I think we should create RSA Key Containers initially. We can create grouping endpoints later.

Question:
How this container helps to group multiple RSA *key pairs*? In my opinion container is a generic term and should not limit the contents in it, in case of RSA this violated.
 [hgedikli] It doesn't, that's why I had the question about generic containers referencing RSA containers. But I like the idea of having separate endpoints for groups. That way groups can reference secrets and RSA containers.

Suggestion:
These are two separate concepts and has to be addressed separately, so that it can be utilized better.
 [hgedikli] Agreed
There is no question on the value addition from this feature, but In my opinion we need two separate resources

1. KeyPairs: To associate keys like RSA which has multiple secrets.
  [hgedikli] We want to keep the RSA container entity. Associating secrets with each other gets really complicated for user, so user will create a separate entity for storing RSA key pairs.
2. KeyRings: This will provide grouping (container) of keys no matter what type (RSA/ASE ...) and can be hooked up with tenant.
  [hgedikli] I agree with this approach. My suggestion would be let's create the RSA containers, and come back to grouping secrets after we have that in place. We'll have to make sure groups/keyrings can store secrets and containers.

At the same time we should start API specs so that other community members can understand concepts and share their ideas.
  [hgedikli] I'll start working on the API specs.
  [hgedikli] API Specs : https://etherpad.openstack.org/p/keypairs

Question [hgedikli] :
Would it make more sense to call Containers KeyPairs? If so, we can use containers for grouping (container can store secrets and key pairs)

Question [john-wood]:
Gist of List vs Map based example payloads: https://gist.github.com/CoderLisa/8833443

Is there a way we can make the handling of custom Container types more generic in the code base?
A concern with the current approach is that custom handler logic is needed to deal with custom container elements. For example, logic needs to be added to deal with each container model variation added, such as to handle attributes like 'private_key_id' on RSA container types. An alternative approach is to keep a single Container type, but then add an association table to Secrets that are available in a Container. This association could hold a name attribute (such as 'private_key_id'), such that when a Container model is retrieved it could have a 'secrets' dict attribute that maps the names to the Secret IDs. The Container would have a type that indicates if it is RSA or not (for example), and validation logic would gut check the values passed up relative to that type (such as enforcing the json has a 'private_key' element represented). Other than validation logic though, Container CRUD relative to REST calls could be handled the same regardless of Container type.

Thoughts?

Comment [atiwari]
I like the "List Based" approach and that exactly what I was proposing. This way we can justify the genericness of Container resource and type will govern what kind of secret the container has. Options are "DSA", "RSA", "Cert", ....

Comment [hgedikli]
I'm onboard with the list approach however I'm concerned about how to handle situations like if we want to add extra attributes (not a secret-container relationship) to containers based on their type? List approach will work in RSA case since right now all we need is 3 references to secrets. If we need to add extra fields to containers with business logic, we will eventually need each type of containers to live on their own table. If we all agree not needing extra attributes in the future, I would definitelly want to move forward with the list approach. Thoughts?

(?)

Work Items

Dependency tree

* Blueprints in grey have been implemented.

This blueprint contains Public information 
Everyone can see this information.