Skip to content

Commit

Permalink
Managed CCF governance API (#23627)
Browse files Browse the repository at this point in the history
* Rebase with current mCCF gov TypeSpec

* Update config, initial build

* Managed CCF governance API

* Update with current state from CCF repo

(Renaming CADL to TypeSpec)

* Move files around, and create a minimal `readme.md`

* Prettier

* Update from CCF main, initial errors, and formatting

* Remove prev version

* Update autorest README

* Spell check and small linters

* Drop to supported types for spec validation

* Add JWTs to custom-words

* Move file, use output-file arg

* Correct README name, remove unused package

* Pull in latest changes

* Latest changes and re-generate

* Clearer operation names

* Pull latest changes

* Rename for consistency, and pull latest changes

* Regenerate OpenAPI at correct path

* Initial auto-generated examples

* Correct visibility

* Working towards canonical examples

* Improve examples

* Rename fles

* Ah, build puts these in second location

* Improve proposal examples

* Pull latest: Mark more optionals, correct discriminator use, fix  example-errors

* More tweaks to exmaples

* Latest

* Combine readmes

* Format and custom-words

* Add missing field

* Latest: Verb'd operation IDs

* Latest: Remove readOnlys

* Rename to restore actions

* Rename in source too

* Latest, update examples

* Fix warnings and rebuild with latest version

* Add ManagedCcf to CI pipeline

* Suppress doc-required for Versions, remove local package.json

* Build with 0.45.0 again

* Add specification/confidentialledger to PR trigger

* tsp format

---------

Co-authored-by: Mahati Chamarthy <mahati.chamarthy@gmail.com>
Co-authored-by: Mike Harder <mharder@microsoft.com>
  • Loading branch information
3 people authored Jun 16, 2023
1 parent 16e2be4 commit e6ec127
Show file tree
Hide file tree
Showing 59 changed files with 4,113 additions and 1 deletion.
5 changes: 4 additions & 1 deletion custom-words.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2825,6 +2825,9 @@ Metadatas
Gtid
GTID
gtid
Acks
safeuint
JWTs
Wifi
Nwfs
Hnsw
Expand All @@ -2844,4 +2847,4 @@ manytomany
stransparent
forceencryption
tlsciphers
tlsprotocols
tlsprotocols
6 changes: 6 additions & 0 deletions eng/pipelines/typespec-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ pr:
- eng/pipelines/templates/steps/typespec-ci.yml
- specification/contosowidgetmanager
- specification/cognitiveservices
- specification/confidentialledger
- specification/containerservice
- specification/servicenetworking
- specification/translation
Expand Down Expand Up @@ -69,6 +70,11 @@ jobs:
Folder: specification/cognitiveservices/OpenAI.Inference
DisplayName: OpenAI.Inference

- template: templates/steps/typespec-ci.yml
parameters:
Folder: specification/confidentialledger/Microsoft.ManagedCcf
DisplayName: ManagedCcf

- template: templates/steps/typespec-ci.yml
parameters:
Folder: specification/containerservice/Fleet.Management
Expand Down
48 changes: 48 additions & 0 deletions specification/confidentialledger/Microsoft.ManagedCcf/acks.tsp
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import "@typespec/rest";
import "@typespec/versioning";
import "@azure-tools/typespec-azure-core";

import "./common.tsp";
import "./cose.tsp";

@TypeSpec.Http.route("/gov/members")
namespace Microsoft.ManagedCcf.Acks;

@doc("A compact summary of the service's state up to a certain point in time, updated and signed by members to indicate their participation in and approval of the service.")
@TypeSpec.Rest.resource("state-digests")
model StateDigest {
@doc("Identifier for member this stateDigest applies to.")
@visibility("query")
@key
memberId: memberId;

@doc("Hex-encoding of SHA-256 hash of the root of the service's merkle tree. This should be signed by a new member and submitted as an ACK to mark that member as Active.")
@pattern("^[a-f0-9]{64}$")
digest: string;
}

interface StateDigests {
@doc("Request that this member's stateDigest is updated to a fresher value. Only this member may update their own stateDigest. Returns the refreshed value.")
@TypeSpec.Rest.action("update")
update is Azure.Core.StandardResourceOperations.ResourceAction<
StateDigest,
CoseSigned,
StateDigest,
TxIdWriteHeader
>;

@doc("Submit a signed acknowledgement of a recent digest of the service status, to transition the member to Active.")
@TypeSpec.Rest.action("ack")
acknowledge is Azure.Core.StandardResourceOperations.ResourceAction<
StateDigest,
CoseSigned<StateDigest>,
TypeSpec.Http.NoContentResponse,
TxIdWriteHeader
>;

@doc("Get the stateDigest assigned to the given member, which that member must sign to become active.")
get is Azure.Core.StandardResourceOperations.ResourceRead<
StateDigest,
TxIdReadHeader
>;
}
52 changes: 52 additions & 0 deletions specification/confidentialledger/Microsoft.ManagedCcf/common.tsp
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import "@typespec/http";
import "@azure-tools/typespec-azure-core";

namespace Microsoft.ManagedCcf;

alias transactionIdHeaderField = "x-ms-ccf-transaction-id";

@doc("Uniquely identifies an atomic transaction within a CCF service. Composed of a term number and sequence number. Sequence numbers increase monotonically, apart from during elections where the service may reuse an existing sequence number. Each election will result in a new, higher term number being used for the conflicting and future sequence numbers.")
@pattern("^[0-9]+\\.[0-9]+$")
scalar transactionId extends string;

alias TxIdWriteHdr = {
@doc("Identifier for transaction where this request produced a write on the service. This uniquely identifies the submitted request, and can be used to confirm that the request becomes committed.")
@TypeSpec.Http.header(transactionIdHeaderField)
transactionId: transactionId;
};

alias TxIdWriteHeader = Azure.Core.Traits.ResponseHeadersTrait<TxIdWriteHdr>;

alias TxIdReadHdr = {
@doc("Identifier for transaction this response was read from. The service state may be altered by other write requests. Reads at the same transactionId describe a consistent single point in the service history.")
@TypeSpec.Http.header(transactionIdHeaderField)
transactionId: transactionId;
};

alias TxIdReadHeader = Azure.Core.Traits.ResponseHeadersTrait<TxIdReadHdr>;

alias JavaScriptSource = {
@doc("This contains raw JavaScript source code, not escaped into a JSON object.")
@TypeSpec.Http.header("content-type")
contentType: "text/javascript";
};

@doc("Hex encoding of SHA-256 of a node's public key.")
@pattern("^[a-f0-9]{64}$")
scalar nodeId extends string;

@doc("Hex encoding of SHA-256 of a member certificate's fingerprint.")
@pattern("^[a-f0-9]{64}$")
scalar memberId extends string;

@doc("Hex encoding of SHA-256 of user certificate's fingerprint.")
@pattern("^[a-f0-9]{64}$")
scalar userId extends string;

@doc("Hex encoding of SHA-256 of proposed actions and merkle root of store at proposal creation. Unlike other IDs, this is generated on the service and will not be known in advance.")
@pattern("^[a-f0-9]{64}$")
scalar proposalId extends string;

@doc("A non-negative JSON-safe integer (ie max is 2^53 - 1)")
@minValue(0)
scalar safeuint extends safeint;
14 changes: 14 additions & 0 deletions specification/confidentialledger/Microsoft.ManagedCcf/cose.tsp
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import "@typespec/http";

@doc("HTTP request containing a COSE signature")
model CoseSignature {
@doc("The MIME content type for all auditable member actions is application/cose, containing a CoseSign1 signature.")
@TypeSpec.Http.header("content-type")
contentType: "application/cose";

@doc("A raw CoseSign1 signature. See CCF docs for required headers and body schema: https://microsoft.github.io/CCF/main/use_apps/issue_commands.html#cose-schemas")
@TypeSpec.Http.body
body: bytes;
}

model CoseSigned<T = {}> extends CoseSignature {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"title": "Ballots_Get",
"operationId": "Ballots_Get",
"parameters": {
"api-version": "2023-06-01-preview",
"proposalId": "1c04c5bb4bdc207dbf35bc4b32dbf92cbc23eabb34a6e8b163b2de2c7833e87b",
"memberId": "f8ac7c60c164f7f13c04ba41645b18eabcc55a8f799c83a90d001f4e89907970"
},
"responses": {
"200": {
"body": {
"script": "export function vote (rawProposal, proposerId) { return true }"
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"title": "Ballots_Submit",
"operationId": "Ballots_Submit",
"parameters": {
"api-version": "2023-06-01-preview",
"proposalId": "1c04c5bb4bdc207dbf35bc4b32dbf92cbc23eabb34a6e8b163b2de2c7833e87b",
"memberId": "f8ac7c60c164f7f13c04ba41645b18eabcc55a8f799c83a90d001f4e89907970",
"body": "{binary COSE Sign1}"
},
"responses": {
"200": {
"body": {
"proposalId": "1c04c5bb4bdc207dbf35bc4b32dbf92cbc23eabb34a6e8b163b2de2c7833e87b",
"proposerId": "f8ac7c60c164f7f13c04ba41645b18eabcc55a8f799c83a90d001f4e89907970",
"proposalState": "Open",
"ballotCount": 2,
"finalVotes": {
"f8ac7c60c164f7f13c04ba41645b18eabcc55a8f799c83a90d001f4e89907970": true,
"b9626e3856b3ef3b433e612d59fbb9edd71cfa2efc772bcfbb50aaa9b6e033f7": false
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"title": "EncryptedShares_Get",
"operationId": "EncryptedShares_Get",
"parameters": {
"api-version": "2023-06-01-preview",
"memberId": "f8ac7c60c164f7f13c04ba41645b18eabcc55a8f799c83a90d001f4e89907970"
},
"responses": {
"200": {
"body": {
"encryptedShare": "ZW5jcnlwdGVkU2hhcmUx"
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"title": "Proposals_Create",
"operationId": "Proposals_Create",
"parameters": {
"api-version": "2023-06-01-preview",
"body": "{binary COSE Sign1}"
},
"responses": {
"200": {
"body": {
"proposalId": "1c04c5bb4bdc207dbf35bc4b32dbf92cbc23eabb34a6e8b163b2de2c7833e87b",
"proposerId": "f8ac7c60c164f7f13c04ba41645b18eabcc55a8f799c83a90d001f4e89907970",
"proposalState": "Open",
"ballotCount": 0,
"finalVotes": {}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"title": "Proposals_Get",
"operationId": "Proposals_Get",
"parameters": {
"api-version": "2023-06-01-preview",
"proposalId": "1c04c5bb4bdc207dbf35bc4b32dbf92cbc23eabb34a6e8b163b2de2c7833e87b"
},
"responses": {
"200": {
"body": {
"proposalId": "1c04c5bb4bdc207dbf35bc4b32dbf92cbc23eabb34a6e8b163b2de2c7833e87b",
"proposerId": "f8ac7c60c164f7f13c04ba41645b18eabcc55a8f799c83a90d001f4e89907970",
"proposalState": "Open",
"ballotCount": 2,
"finalVotes": {
"f8ac7c60c164f7f13c04ba41645b18eabcc55a8f799c83a90d001f4e89907970": true,
"b9626e3856b3ef3b433e612d59fbb9edd71cfa2efc772bcfbb50aaa9b6e033f7": false
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"title": "Proposals_GetActions",
"operationId": "Proposals_GetActions",
"parameters": {
"api-version": "2023-06-01-preview",
"proposalId": "1c04c5bb4bdc207dbf35bc4b32dbf92cbc23eabb34a6e8b163b2de2c7833e87b"
},
"responses": {
"200": {
"body": {
"actions": [
{
"name": "set_member",
"args": {
"cert": "-----BEGIN CERTIFICATE-----\nMIIBtzCCATygAwIBAgIUYqXLFcT1aCENVpgp2K+Vv53cauEwCgYIKoZIzj0EAwMw\nEjEQMA4GA1UEAwwHbWVtYmVyMzAeFw0yMzA1MTcxMzUwMzJaFw0yNDA1MTYxMzUw\nMzJaMBIxEDAOBgNVBAMMB21lbWJlcjMwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQI\ngWV8Lcf+eegGXVj1I4N8jWcfTb6MRt0Znl8aFOBBwZ5lgRlTePYLHBb81wOJaX+k\nIYqHRaI3Wblg72gV/dhf4qBYw9ENqJtE2ClenYkRFAX2/1GwjxTOf9XGpBUt5Rij\nUzBRMB0GA1UdDgQWBBT7oAebRrqSDSG89jW0nFF5fHRRTzAfBgNVHSMEGDAWgBT7\noAebRrqSDSG89jW0nFF5fHRRTzAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49BAMD\nA2kAMGYCMQCmCKWLEbCooecDiuMyUf/B2vppNZ75U96B2ypg88Xy5y4xhRV1qoCT\nRT4sUCFl6ioCMQCKm0df2DzlRbhX6+0i6KikBkUf9kFowb5ctikJsym0rTigpPZC\nHaZlaQD2pNBud/0=\n-----END CERTIFICATE-----\n",
"encryption_pub_key": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzIh4oWoiTFCu/8tsfmo9\njTDryaTrL7wo8+HJAGUTL827CiZ8Rm9wgo7iJDOza7UPaPnXpR6kIlZbdItDOx9k\nmJSVWbDMufaqqs+y/i+WrTiDqL02zbT/lI4kx5l7Wyu0VEHT5GmSKQiVyJt/Q4vE\n1b9rKNy3Ol1g5VuW9PKOHFz3tvjWksVWXi16qulN3IjAhSFVRtasbqdNSNdDbirv\nLTe24Y9v7UP8CI3qgjr3x8qLYM/X0ou4ZcJvXWVtxZfQLGVgyZcgHD6OtbYJr9Iy\neh/x+G3pPFg2eQY8xNZgqqtH1StKcI++eD7iSDosKRkN3efCKLeKStg6F/xluarc\nkQIDAQAB\n-----END PUBLIC KEY-----\n"
}
}
]
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"title": "Proposals_List",
"operationId": "Proposals_List",
"parameters": {
"api-version": "2023-06-01-preview"
},
"responses": {
"200": {
"body": {
"value": [
{
"proposalId": "1c04c5bb4bdc207dbf35bc4b32dbf92cbc23eabb34a6e8b163b2de2c7833e87b",
"proposerId": "f8ac7c60c164f7f13c04ba41645b18eabcc55a8f799c83a90d001f4e89907970",
"proposalState": "Open",
"ballotCount": 2,
"finalVotes": {
"f8ac7c60c164f7f13c04ba41645b18eabcc55a8f799c83a90d001f4e89907970": true,
"b9626e3856b3ef3b433e612d59fbb9edd71cfa2efc772bcfbb50aaa9b6e033f7": false
}
}
],
"nextLink": "https://microsoft.com/avwpnzmy"
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"title": "Proposals_Withdraw",
"operationId": "Proposals_Withdraw",
"parameters": {
"api-version": "2023-06-01-preview",
"proposalId": "1c04c5bb4bdc207dbf35bc4b32dbf92cbc23eabb34a6e8b163b2de2c7833e87b",
"body": "{binary COSE Sign1}"
},
"responses": {
"200": {
"body": {
"proposalId": "1c04c5bb4bdc207dbf35bc4b32dbf92cbc23eabb34a6e8b163b2de2c7833e87b",
"proposerId": "f8ac7c60c164f7f13c04ba41645b18eabcc55a8f799c83a90d001f4e89907970",
"proposalState": "Withdrawn",
"ballotCount": 2,
"finalVotes": {
"f8ac7c60c164f7f13c04ba41645b18eabcc55a8f799c83a90d001f4e89907970": true,
"b9626e3856b3ef3b433e612d59fbb9edd71cfa2efc772bcfbb50aaa9b6e033f7": false
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"title": "ServiceState_GetConstitution",
"operationId": "ServiceState_GetConstitution",
"parameters": {
"api-version": "2023-06-01-preview"
},
"responses": {
"200": {
"body": {
"constitution": "export function validate(input) {\n ...\n}\n\nexport function resolve(proposal, proposerId, votes) {\n ...\n}\n\nexport function apply(proposal, proposalId) {\n ...\n}\n"
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"title": "ServiceState_GetJoinPolicies",
"operationId": "ServiceState_GetJoinPolicies",
"parameters": {
"api-version": "2023-06-01-preview"
},
"responses": {
"200": {
"body": {
"sgx": {
"measurements": [
"cs/RoNCp2UCxpN+i1UnVYw=="
]
},
"snp": {
"measurements": [
"XqJZLOA9/xCx9nnsDch4vw=="
],
"hostData": {
"key9497": "NiNrjmA9/aSj4F076mVdrA=="
},
"uvmEndorsements": {
"key9553": "cbneXARxfLGcqw3cc09mYQ=="
}
}
}
}
}
}
Loading

0 comments on commit e6ec127

Please sign in to comment.