Skip to content

Commit

Permalink
[ATL-1925] feat(agent): define key-management interface (2) (#66)
Browse files Browse the repository at this point in the history
* feat(agent): add keystore subproject

* feat(agent): add intefaces & models for custodian layer

* docs(agent): add readme about key-mangement

* feat(agent): fix as reviewed

* feat(agent): implement InMemoryDIDKeyStorage

* feat(agent): add tests for InMemoryDIDKeyStorage

* feat(agent): add createCustodialDID endpoint

* feat(agent): refine createCustodialDID endpoint

* feat(agent): refine createCustodialDID endpoint
  • Loading branch information
patlo-iog authored Oct 18, 2022
1 parent c4440df commit bcb0991
Show file tree
Hide file tree
Showing 8 changed files with 336 additions and 35 deletions.
62 changes: 58 additions & 4 deletions prism-agent/api/http/castor/schemas.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,6 @@ components:
DIDOperationResponse:
type: object
required:
- did
- type
- deactivated
- scheduledOperation
properties:
scheduledOperation:
Expand Down Expand Up @@ -188,6 +185,64 @@ components:
example: "eyJhbGciOiJFUzI1NksifQ.eyJ1cGRhdGVLZXkiOnsia3R5IjoiRUMiLCJjcnYiOiJzZWNwMjU2azEiLCJ4Ijoid2Z3UUNKM09ScVZkbkhYa1Q4UC1MZ19HdHhCRWhYM3R5OU5VbnduSHJtdyIsInkiOiJ1aWU4cUxfVnVBblJEZHVwaFp1eExPNnFUOWtQcDNLUkdFSVJsVHBXcmZVIn0sImRlbHRhSGFzaCI6IkVpQ3BqTjQ3ZjBNcTZ4RE5VS240aFNlZ01FcW9EU19ycFEyOVd5MVY3M1ZEYncifQ.RwZK1DG5zcr4EsrRImzStb0VX5j2ZqApXZnuoAkA3IoRdErUscNG8RuxNZ0FjlJtjMJ0a-kn-_MdtR0wwvWVgg"
description: "Base64 of signature of data in the request"

CreateCustodialDidRequest:
type: object
required:
- documentTemplate
properties:
documentTemplate:
type: object
required:
- storage
- publicKeys
- services
properties:
storage:
type: string
example: "mainnet"
publicKeys:
type: array
items:
type: object
required:
- id
- purposes
properties:
id:
type: string
description: Identifier of a verification material in the DID Document
example: key-01
purposes:
type: array
items:
type: string
enum:
[
"authentication",
"assertionMethod",
"keyAgreement",
"capabilityInvocation",
"capabilityDelegation",
]
example: [ "authentication", "assertionMethod" ]
services:
type: array
items:
$ref: "#/components/schemas/Service"

CreateCustodialDIDResponse:
type: object
required:
- did
- longFormDid
properties:
did:
$ref: "#/components/schemas/DID"
longFormDid:
type: string
description: A long-form DID for the created DID
example: did:prism:1:abc123:abc123

Delta:
type: object
required:
Expand Down Expand Up @@ -311,7 +366,6 @@ components:
publicKeys:
$ref: "#/components/schemas/PublicKey"


# ----------------------------------
# ASYNC OPERATIONS
# ----------------------------------
Expand Down
72 changes: 62 additions & 10 deletions prism-agent/api/http/prism-agent-openapi-spec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ tags:
description: DID Operations REST API
- name: DID Authentication
description: DID Authentication REST API
- name: DID Registrar
description: DID Registrar REST API
# Pollux
- name: Schema Registry
description: Schema Registry REST API
Expand All @@ -36,8 +38,8 @@ paths:
post:
tags: [ "DID" ]
operationId: createDid
summary: Create DID with the associated DID Document with the option to publish to blockchain.
description: Create DID with the associated DID Document with the option to publish to blockchain.
summary: Publish DID create operation to blockchain.
description: Publish DID create operation to blockchain.
requestBody:
required: true
content:
Expand Down Expand Up @@ -67,8 +69,8 @@ paths:
get:
tags: [ "DID" ]
operationId: getDid
summary: Get DID.
description: Get DID.
summary: Resolve DID.
description: Resolve DID.
parameters:
- $ref: "./castor/parameters.yaml#/components/parameters/didRefInPath"
responses:
Expand All @@ -89,8 +91,8 @@ paths:
post:
tags: [ "DID" ]
operationId: updateDid
summary: Update DID.
description: Update DID.
summary: Publish DID update operation to blockchain.
description: Publish DID update operation to blockchain.
parameters:
- $ref: "./castor/parameters.yaml#/components/parameters/didRefInPath"
requestBody:
Expand Down Expand Up @@ -128,8 +130,8 @@ paths:
post:
tags: [ "DID" ]
operationId: deactivateDID
summary: Deactivates either published or unpublished DID.
description: Deactivates either published or unpublished DID.
summary: Publish DID deactivate operation to blockchain.
description: Publish DID deactivate operation to blockchain.
parameters:
- $ref: "./castor/parameters.yaml#/components/parameters/didRefInPath"
requestBody:
Expand Down Expand Up @@ -167,8 +169,8 @@ paths:
post:
tags: [ "DID" ]
operationId: recoverDid
summary: Recover DID.
description: Recover DID.
summary: Publish DID recover operation to blockchain.
description: Publish DID recover operation to blockchain.
parameters:
- $ref: "./castor/parameters.yaml#/components/parameters/didRefInPath"
requestBody:
Expand Down Expand Up @@ -251,6 +253,7 @@ paths:
tags: [ "DID Authentication" ]
operationId: createDidAuthenticationChallenge
summary: Create a new authentication challenge
deprecated: true
description: |
Create a new authentication challenge that will be later verified
by Castor for a relying-party.
Expand Down Expand Up @@ -279,6 +282,7 @@ paths:
tags: [ "DID Authentication" ]
operationId: createDidAuthenticationChallengeSubmission
summary: Create a verification from challenge
deprecated: true
description: |
Submit a challenge submission that will be verified by Castor for a relying-party.
requestBody:
Expand All @@ -301,6 +305,54 @@ paths:
schema:
$ref: "./castor/schemas.yaml#/components/schemas/ErrorResponse"

/did-registrar/dids:
post:
tags: [ "DID Registrar" ]
operationId: createCustodialDid
summary: Create DID with the DID Document template where keys are managed by PrismAgent.
description: Create DID with the DID Document template where keys are managed by PrismAgent.
requestBody:
required: true
content:
application/json:
schema:
$ref: "./castor/schemas.yaml#/components/schemas/CreateCustodialDidRequest"
responses:
"200":
description: Created unpublished DID.
content:
application/json:
schema:
$ref: "./castor/schemas.yaml#/components/schemas/CreateCustodialDIDResponse"
"422":
description: The DID creation failed.
content:
application/json:
schema:
$ref: "./castor/schemas.yaml#/components/schemas/ErrorResponse"

/did-registrar/dids/{didRef}/publications:
post:
tags: [ "DID Registrar" ]
operationId: publishCustodialDid
summary: Publish DID stored in PrismAgent wallet to blockchain
description: Publish DID stored in PrismAgent wallet to blockchain
parameters:
- $ref: "./castor/parameters.yaml#/components/parameters/didRefInPath"
responses:
"202":
description: Publishing DID to Blockchain.
content:
application/json:
schema:
$ref: "./castor/schemas.yaml#/components/schemas/DIDOperationResponse"
"422":
description: The DID publication failed.
content:
application/json:
schema:
$ref: "./castor/schemas.yaml#/components/schemas/ErrorResponse"

# ----------------------------------
# Pollux
# ----------------------------------
Expand Down
1 change: 1 addition & 0 deletions prism-agent/service/build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ val apiBaseDirectory = settingKey[File]("The base directory for PrismAgent API s
ThisBuild / apiBaseDirectory := baseDirectory.value / "../api"

val commonSettings = Seq(
testFrameworks := Seq(new TestFramework("zio.test.sbt.ZTestFramework")),
githubTokenSource := TokenSource.Environment("ATALA_GITHUB_TOKEN"),
resolvers += Resolver.githubPackages("input-output-hk", "atala-prism-sdk"),
// Needed for Kotlin coroutines that support new memory management mode
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,23 +18,3 @@ private[custodian] trait DIDKeyStorage {
def removeKey(did: DID, keyId: String): Task[Option[ECKeyPair]]

}

// TODO: implement
private[custodian] class InMemoryDIDKeyStorage(store: Ref[Map[DID, Map[String, ECKeyPair]]]) extends DIDKeyStorage {
override def listKeys(did: DID): Task[Map[String, ECKeyPair]] = ???

override def getKey(did: DID, keyId: String): Task[Option[ECKeyPair]] = ???

override def upsertKey(did: DID, keyId: String, keyPair: ECKeyPair): Task[Unit] = ???

override def removeKey(did: DID, keyId: String): Task[Option[ECKeyPair]] = ???

}

private[custodian] object InMemoryDIDKeyStorage {
val layer: ULayer[DIDKeyStorage] = {
ZLayer.fromZIO(
Ref.make(Map.empty[DID, Map[String, ECKeyPair]]).map(store => InMemoryDIDKeyStorage(store))
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package io.iohk.atala.agent.custodian.keystore

import io.iohk.atala.agent.custodian.model.ECKeyPair
import io.iohk.atala.castor.core.model.did.DID
import zio.{Ref, Task, ULayer, ZLayer}

private[custodian] class InMemoryDIDKeyStorage(store: Ref[Map[DID, Map[String, ECKeyPair]]]) extends DIDKeyStorage {
override def listKeys(did: DID): Task[Map[String, ECKeyPair]] = store.get.map(_.getOrElse(did, Map.empty))

override def getKey(did: DID, keyId: String): Task[Option[ECKeyPair]] = listKeys(did).map(_.get(keyId))

override def upsertKey(did: DID, keyId: String, keyPair: ECKeyPair): Task[Unit] = store
.update { currentStore =>
val currentStoredKeys = currentStore.getOrElse(did, Map.empty)
val updatedStoredKeys = currentStoredKeys.updated(keyId, keyPair)
currentStore.updated(did, updatedStoredKeys)
}

override def removeKey(did: DID, keyId: String): Task[Option[ECKeyPair]] = store
.getAndUpdate { currentStore =>
val currentStoredKeys = currentStore.getOrElse(did, Map.empty)
val updatedStoredKeys = currentStoredKeys.removed(keyId)
currentStore.updated(did, updatedStoredKeys)
}
.map(_.getOrElse(did, Map.empty).get(keyId))

}

private[custodian] object InMemoryDIDKeyStorage {
val layer: ULayer[DIDKeyStorage] = {
ZLayer.fromZIO(
Ref.make(Map.empty[DID, Map[String, ECKeyPair]]).map(store => InMemoryDIDKeyStorage(store))
)
}
}
Loading

0 comments on commit bcb0991

Please sign in to comment.