Coordinator client API
The Coordinator exposes an HTTP-REST interface, referred to as the Client API.
Responses of the API follow the JSend specification.
This means all endpoints return a JSON object with a status field that's either success, fail, or error:
- In case of
success, the response contains adatafield with the actual response data. - In case of
error, the response contains amessagefield with an error message. - In case of
fail, the response may contain amessagefield with a human readable message, as well as adatafield with additional information.failis only used in API version 2, and is returned on invalid requests by the client.
The MarbleRun CLI and the MarbleRun Go SDK use the Client API to interact with the Coordinator. It may also be used directly by applications for programmatic access.
Retrieve the Coordinator's manifest
- v2
- v1
GET /api/v2/manifest
Get the currently set manifest.
The endpoint returns a manifest signature as base64 encoded bytes (signed by the root ECDSA key) and a SHA-256 of the currently set manifest. Further, the manifest itself is returned as base64 encoded bytes. All returned values don't change when a package update has been applied.
Users can retrieve and inspect the manifest through this endpoint before interacting with the application.
Example for retrieving the deployed manifest with curl:
curl --cacert marblerun.crt "https://$MARBLERUN/api/v2/manifest" | jq '.data.ManifestSignature' --raw-output | base64 -d
Returns
-
manifestSignatureRootECDSAstringBase64 encoded ECDSA signature of the manifest signed by the Coordinator's root key.
-
manifestFingerprintstringHex encoded SHA-256 hash of the manifest.
-
manifeststringBase64 encoded manifest.
Example response:
{
"status": "success",
"data": {
"manifestSignatureRootECDSA": "bWFuaWZlc3RTaWduYXR1cmVSb290RUNEU0E=",
"manifestFingerprint": "c2fd772483c510d49a339ae207588642f46eb8f22537f77d6ac348691a41ba32",
"manifest": "eyJQYWNrYWdlcyI6e30sIk1hcmJsZXMiOnt9fQo="
}
}
GET /manifest
Get the currently set manifest.
The endpoint returns a manifest signature as base64 encoded bytes (signed by the root ECDSA key) and a SHA-256 of the currently set manifest. Further, the manifest itself is returned as base64 encoded bytes. All returned values don't change when a package update has been applied.
Users can retrieve and inspect the manifest through this endpoint before interacting with the application.
Example for requesting the deployed manifest hash with curl:
curl --cacert marblerun.crt "https://$MARBLERUN/manifest" | jq '.data.ManifestSignature' --raw-output
Example for verifying the deployed manifest via the intermediate key signature:
# get manifest signature (signed by coordinator root key)
curl --cacert marblerun.crt "https://$MARBLERUN/manifest" | jq '.data.ManifestSignatureRootECDSA' --raw-output | base64 -d > manifest.sig
# extract root public key from coordinator certificate root
marblerun certificate root $MARBLERUN
openssl x509 -in marblerunRootCA.crt -pubkey -noout > root.pubkey
# verify signature
openssl dgst -sha256 -verify root.pubkey -signature manifest.sig manifest.json
# verification fails? try to remove newlines from manifest
awk 'NF {sub(/\r/, ""); printf "%s",$0;}' original.manifest.json > formated.manifest.json
Returns
-
manifestSignatureRootECDSAstringBase64 encoded ECDSA signature of the manifest signed by the Coordinator's root key.
-
manifestSignaturestringHex encoded SHA-256 hash of the manifest.
-
manifeststringBase64 encoded manifest.
Example response:
{
"status": "success",
"data": {
"manifestSignatureRootECDSA": "bWFuaWZlc3RTaWduYXR1cmVSb290RUNEU0E=",
"manifestSignature": "c2fd772483c510d49a339ae207588642f46eb8f22537f77d6ac348691a41ba32",
"manifest": "eyJQYWNrYWdlcyI6e30sIk1hcmJsZXMiOnt9fQo="
}
}
Set the Coordinator's manifest
- v2
- v1
POST /api/v2/manifest
Before deploying applications to a MarbleRun deployment, a manifest needs to be set. On success, a key-value mapping for encrypted secrets to be used for recovering the Coordinator in case of disaster recovery is returned. The key matches each supplied key from RecoveryKeys in the Manifest.
Example for setting the manifest with curl:
curl --cacert marblerun.crt --data-binary @manifest-request.json "https://$MARBLERUN/manifest"
Request body
-
manifeststringBase64 encoded manifest.
Example request body:
{
"manifest": "eyJQYWNrYWdlcyI6e30sIk1hcmJsZXMiOnt9fQo="
}
Returns
-
recoveryKeysobjectAn optional field that will be present if the manifest contains
RecoveryKeys. Key-value mapping of strings to strings, where the key matches each supplied key fromRecoveryKeysin the manifest, and the value is the base64 encoded encrypted recovery secret.
Example response:
{
"status": "success",
"data": {
"recoveryKeys": {
"recoveryKey1": "ZW5jcnlwdGVkUmVjb3ZlcnlTZWNyZXQxCg==",
"recoveryKey2": "ZW5jcnlwdGVkUmVjb3ZlcnlTZWNyZXQyCg=="
}
}
}
POST /manifest
Before deploying applications to a MarbleRun deployment, a manifest needs to be set. On success, a key-value mapping for encrypted secrets to be used for recovering the Coordinator in case of disaster recovery is returned. The key matches each supplied key from RecoveryKeys in the Manifest.
Example for setting the manifest with curl:
curl --cacert marblerun.crt --data-binary @manifest.json "https://$MARBLERUN/manifest"
Request body
Raw JSON encoded manifest. See Defining a Manifest for more information.
Example request body:
{
"Packages": {
"package1": {},
"package2": {}
},
"Marbles": {
"marble1": {},
"marble2": {}
},
"Secrets": {},
"Users": {},
"Roles": {},
"TLS": {},
"RecoveryKeys": {
"recoveryKey1": "-----BEGIN PUBLIC KEY-----\nMIIBpTANBgk...",
"recoveryKey2": "-----BEGIN PUBLIC KEY-----\nMIIBpTANBgk..."
}
}
Returns
-
recoveryKeysobjectAn optional field that will be present if the manifest contains
RecoveryKeys. Key-value mapping of strings to strings, where the key matches each supplied key fromRecoveryKeysin the manifest, and the value is the base64 encoded encrypted recovery secret.
Example response:
{
"status": "success",
"data": {
"recoveryKeys": {
"recoveryKey1": "ZW5jcnlwdGVkUmVjb3ZlcnlTZWNyZXQxCg==",
"recoveryKey2": "ZW5jcnlwdGVkUmVjb3ZlcnlTZWNyZXQyCg=="
}
}
}
Retrieve the Coordinator's SGX quote and certificates
- v2
- v1
GET /api/v2/quote[?nonce=<base64_url_encoding(nonce)>]
Retrieves and SGX-DCAP quote from the Coordinator. Learn more about DCAP in the official Intel DCAP orientation.
This endpoint can be used to verify the integrity of the Coordinator and the cluster at any time.
Query parameters
-
noncestring (optional)Base64 URL encoded nonce to be included in the quote.
Returns
-
certstringPEM-encoded certificate chain containing the Coordinator's Root CA and Intermediate CA. Can be used for trust establishment between a client and the Coordinator.
-
quotestringBase64-encoded SGX quote where the report data is a SHA-256 hash of the Coordinator's root certificate complete ASN.1 DER content and the nonce, if provided:
report_data = SHA256(coordinator_root_cert + nonce)
Example response:
{
"status": "success",
"data": {
"cert": "-----BEGIN CERTIFICATE-----\nMIIBpTANBgk...",
"quote": "U0dYIHF1b3RlCg=="
}
}
GET /quote
Retrieves and SGX-DCAP quote from the Coordinator. Learn more about DCAP in the official Intel DCAP orientation.
This endpoint can be used to verify the integrity of the Coordinator and the cluster at any time.
Returns
-
certstringPEM-encoded certificate chain containing the Coordinator's Root CA and Intermediate CA. Can be used for trust establishment between a client and the Coordinator.
-
quotestringBase64-encoded SGX quote where the report data is a SHA-256 hash of the Coordinator's root certificate complete ASN.1 DER content:
report_data = SHA256(coordinator_root_cert)
Example response:
{
"status": "success",
"data": {
"cert": "-----BEGIN CERTIFICATE-----\nMIIBpTANBgk...",
"quote": "U0dYIHF1b3RlCg=="
}
}
Recover the Coordinator
- v2
- v1
POST /api/v2/recover
Recover the Coordinator using decrypted recovery secrets.
This API endpoint is only available when the coordinator is in recovery mode. Before you can use the endpoint, you need to decrypt the recovery secret which you may have received when setting the manifest initially. See Recovering the Coordinator on how to retrieve the recovery key needed to use this API endpoint correctly.
Example for recovering the Coordinator with curl:
curl -k -X POST --data-binary @recovery_key.json "https://$MARBLERUN/recover"
Request body
-
recoverySecretstringBase64 encoded recovery secret.
Example request body:
{
"recoverySecret": "AAECAwQFBgcICQoLDA0ODw=="
}
Returns
-
remainingintRemaining secret shares to be uploaded for recovery to complete.
-
messagestringA human readable message indicating the success or progress of the recovery process.
Example response:
{
"status": "success",
"data": {
"remaining": 2,
"message": "Secret was processed successfully. Upload the next secret. Remaining secrets: 2"
}
}
POST /recover
Recover the Coordinator using decrypted recovery secrets.
This API endpoint is only available when the coordinator is in recovery mode. Before you can use the endpoint, you need to decrypt the recovery secret which you may have received when setting the manifest initially. See Recovering the Coordinator on how to retrieve the recovery key needed to use this API endpoint correctly.
Example for recovering the Coordinator with curl:
curl -k -X POST --data-binary @recovery_key_decrypted "https://$MARBLERUN/recover"
Request body
Raw binary encoded recovery secret.
Returns
-
statusMessagestringA human readable message indicating the success or progress of the recovery process.
Example response:
{
"status": "success",
"data": {
"statusMessage": "Secret was processed successfully. Upload the next secret. Remaining secrets: 2"
}
}
Retrieve MarbleRun managed secrets
- v2
- v1
GET /api/v2/secrets?s=<secretName1>[&s=<secretName2>...]
Each requests allows specifying one or more secrets in the form of a query string, where each parameter s specifies one secret.
A query string for the secrets symmetricKeyShared and certShared may look like the following:
s=symmetricKeyShared&s=certShared
This API endpoint only works when Users were defined in the manifest.
The user connects via mutual TLS using the user client certificate in the TLS Handshake.
For more information, look up Managing secrets.
Example for retrieving the secrets symmetricKeyShared and certShared:
curl --cacert marblerun.crt --cert user_certificate.crt --key user_private.key "https://$MARBLERUN/secrets?s=symmetricKeyShared&s=certShared"
Query parameters
-
sstring (required) one or moreSecret name to retrieve.
Returns
-
secretsobjectKey-value mapping of strings to secret objects, where the key matches each supplied secret name in the query string.
Example response:
{
"status": "success",
"data": {
"secrets": {
"symmetricKeyShared": {
"type": "symmetric-key",
"size": 128,
"shared": true,
"userDefined": false,
"private": "QUFBQUFBQUFBQUFBQUFBQQ==",
"public": "QUFBQUFBQUFBQUFBQUFBQQ==",
},
"certShared": {
"type": "cert-ecdsa",
"size": 256,
"shared": true,
"userDefined": false,
"cert": "LS0tLS1CRU...",
},
},
},
}
GET /secrets?s=<secretName1>[&s=<secretName2>...]
Each requests allows specifying one or more secrets in the form of a query string, where each parameter s specifies one secret.
A query string for the secrets symmetricKeyShared and certShared may look like the following:
s=symmetricKeyShared&s=certShared
This API endpoint only works when Users were defined in the manifest.
The user connects via mutual TLS using the user client certificate in the TLS Handshake.
For more information, look up Managing secrets.
Example for retrieving the secrets symmetricKeyShared and certShared:
curl --cacert marblerun.crt --cert user_certificate.crt --key user_private.key "https://$MARBLERUN/secrets?s=symmetricKeyShared&s=certShared"
Query parameters
-
sstring (required) one or moreSecret name to retrieve.
Returns
Key-value mapping of strings to secret objects, where the key matches each supplied secret name in the query string.
Example response:
{
"status": "success",
"data": {
"symmetricKeyShared": {
"type": "symmetric-key",
"size": 128,
"shared": true,
"userDefined": false,
"private": "QUFBQUFBQUFBQUFBQUFBQQ==",
"public": "QUFBQUFBQUFBQUFBQUFBQQ==",
},
"certShared": {
"type": "cert-ecdsa",
"size": 256,
"shared": true,
"userDefined": false,
"cert": "LS0tLS1CRU...",
},
},
}
Secret object
-
typestringThe type of the secret. One of
cert-ecdsa,cert-ed25519,cert-rsa,symmetric-key,plain. -
sizeintegerSize of the key in bits.
- For Type
symmetric-key, this is a multiple of 8. - For Type
cert-ecdsa, this maps to a curve supported by Go's crypto library, currently: 224, 256, 384, or 521. - For
cert-ed25519, this is omitted.
- For Type
-
sharedboolSpecifies whether this secret is shared across all marbles, or if it's unique to each marble.
-
userDefinedboolSpecifies whether a secret should be generated by the MarbleRun (false), or if it will be uploaded by a user at a later point (true).
-
certstringBase64 encoded X.509 certificate.
-
validForintValidity of the certificate in days.
-
privatestringBase64 encoded private key matching the certificate or symmetric key.
-
publicstringBase64 encoded public key matching the certificate or symmetric key.
Set secrets
- v2
- v1
POST /api/v2/secrets
This API endpoint only works when Users were defined in the manifest.
The user connects via mutual TLS using the user client certificate in the TLS Handshake.
For more information, look up Managing secrets.
Example for setting secrets from the file secrets.json:
curl --cacert marblerun.crt --cert user_certificate.crt --key user_private.key --data-binary @secrets.json "https://$MARBLERUN/secrets"
Request body
-
secretsobjectKey-value mapping of strings to user secret objects, where the key is the name of the secret.
Example request body:
{
"secrets": {
"symmetricKeyShared": {
"key": "QUFBQUFBQUFBQUFBQUFBQQ==",
},
"certShared": {
"cert": "LS0tLS1CRU...",
"public": "LS0tLS1CRU...",
},
}
}
POST /secrets
Setting secrets requires uploading them in JSON format.
This API endpoint only works when Users were defined in the manifest.
The user connects via mutual TLS using the user client certificate in the TLS Handshake.
For more information, look up Managing secrets.
Example for setting secrets from the file secrets.json:
curl --cacert marblerun.crt --cert user_certificate.crt --key user_private.key --data-binary @secrets.json "https://$MARBLERUN/secrets"
Request body
Key-value mapping of strings to user secret objects, where the key is the name of the secret.
Example request body:
{
"symmetricKeyShared": {
"key": "QUFBQUFBQUFBQUFBQUFBQQ==",
},
"certShared": {
"cert": "LS0tLS1CRU...",
"public": "LS0tLS1CRU...",
},
}
User secret object
-
keystringBase64 encoded symmetric-key or arbitrary base64 encoded data for secrets of type
plain. -
certstringBase64 encoded X.509 certificate.
-
publicstringBase64 encoded public key matching the certificate.
Only key, or cert and public may be set for a given secret.
Verify and sign an SGX quote
This endpoint is disabled by default. You can enable it in the manifest.
- v2
- v1
POST /api/v2/sign-quote
Send an SGX quote to the Coordinator for verification. If the quote is valid, the Coordinator will sign the quote using its root ECDSA key, and return the signature with the TCB status of the quote.
The Coordinator doesn't verify if the quote matches any packages in the configured manifest.
The signature is created over the SHA-256 hash of the base64-encoded SGX quote and the TCB status:
signature = ECDSA_sign(root_priv_key, SHA256(base64(SGX_quote) + string(TCB_status)))
If the quote is invalid, the Coordinator will return a JSend fail response, which may look like the following:
{
"status": "fail",
"data": {
"sgxQuote": "quote verification failed: OE_QUOTE_VERIFICATION_ERROR"
},
"message": "quote verification failed",
}
Request body
-
sgxQuotestringBase64 encoded SGX quote.
Example request body:
{
"sgxQuote": "U0dYIHF1b3RlCg=="
}
Returns
-
signaturestringBase64 encoded ECDSA signature of the SHA-256 hash of the base64-encoded SGX quote and the TCB status:
-
tcbStatusstringThe TCB status of the SGX quote.
Example response:
{
"status": "success",
"data": {
"verificationSignature": "RUNEU0Ffc2lnbihyb290X3ByaXZfa2V5LCBTSEEyNTYoYmFzZTY0KFNHWF9xdW90ZSkgKyBzdHJpbmcoVENCX3N0YXR1cykpKQo=",
"tcbStatus": "UpToDate"
}
}
This API endpoint isn't available in API version 1.
Get the current status of the Coordinator
- v2
- v1
GET /api/v2/status
Get the current status of the Coordinator.
The status indicates the current state of the coordinator, and can be one of the following:
- Coordinator is in recovery mode. Either upload a key to unseal the saved state, or set a new manifest. Waiting for user input on /recover.
- Coordinator is ready to accept a manifest on /manifest.
- Coordinator is running correctly and ready to accept marbles through the Marble API.
Returns
-
statusintA status code that matches the internal code of the Coordinator's current state.
-
messagestringA human readable message indicating the current state of the Coordinator.
GET /status
Get the current status of the Coordinator.
The status indicates the current state of the coordinator, and can be one of the following:
- Coordinator is in recovery mode. Either upload a key to unseal the saved state, or set a new manifest. Waiting for user input on /recover.
- Coordinator is ready to accept a manifest on /manifest.
- Coordinator is running correctly and ready to accept marbles through the Marble API.
Returns
-
statusCodeintA status code that matches the internal code of the Coordinator's current state.
-
statusMessagestringA human readable message indicating the current state of the Coordinator.
Get a log of all performed updates
- v2
- v1
GET /api/v2/update
Returns a structured log of all updates performed via the /update or /secrets endpoint, including timestamp, author, and affected resources.
Returns
-
updateLogarray of stringsA log of all performed updates. Each entry in the array is one JSON structured log entry.
Example response:
{
"status": "success",
"data": {
"updateLog": [
"{\"time\":\"2024-01-01T00:00:00.0\",\"update\":\"Initial manifest set\"}"
]
}
}
GET /update
Returns a structured log of all updates performed via the /update or /secrets endpoint, including timestamp, author, and affected resources.
Returns
A string comprising the log of all performed updates. The log is structured as a JSON array of objects, where each object is a log entry.
Example response:
{
"status": "success",
"data": "{\"time\":\"2024-01-01T00:00:00.0\",\"update\":\"Initial manifest set\"}\n"}"
}
Update the manifest
- v2
- v1
POST /api/v2/update
This API endpoint only works if Users are defined in the Manifest.
It requires uploading a manifest containing only the packages to be updated, or, if enabled, a completely new manifest.
The Coordinator will verify the manifest and return an error if the manifest is invalid.
For more information, have a look at updating a Manifest.
Request body
For package updates:
-
manifeststringBase64 encoded manifest, containing only the packages to be updated, or, if enabled, a completely new manifest.
Example request body:
{
"manifest": "eyJQYWNrYWdlcyI6e30sIk1hcmJsZXMiOnt9fQo="
}
POST /update
This API endpoint only works if Users are defined in the Manifest.
It requires uploading a manifest containing only the packages to be updated, or, if enabled, a completely new manifest.
The Coordinator will verify the manifest and return an error if the manifest is invalid.
For more information, have a look at updating a Manifest.
Example for updating the manifest with curl:
curl --cacert marblerun.crt --cert user_certificate.crt --key user_private.key --data-binary @update_manifest.json "https://$MARBLERUN/update"
Request body
For package updates:
-
packagesobjectKey-value mapping of strings to package objects, where the key is the name of the package to be updated.
Example request body for package updates:
{
"packages": {
"package1": {
"SecurityVersion": 4,
},
"package2": {
"SecurityVersion": 3,
}
}
}
For full manifest updates the request body should contain the full manifest. See Defining a Manifest for more information.
Packages object
-
SecurityVersionintThe new security version of the package.
Acknowledge a pending manifest update
This feature is an option with MarbleRun Enterprise.
- v2
- v1
POST /api/v2/update-manifest
If multiple users are allowed to perform full manifest updates, acknowledgement is required from all users before the manifest is applied.
Each user must upload the same manifest to acknowledge the update.
See multi-party updates for more information.
Request body
-
manifeststringBase64 encoded manifest.
Example request body:
{
"manifest": "eyJQYWNrYWdlcyI6e30sIk1hcmJsZXMiOnt9fQo="
}
Returns
-
messagestringA human readable message indicating the success or progress of the update process.
-
missingUsersarray of stringsAn array of user IDs that haven't yet acknowledged the update.
Example response:
{
"status": "success",
"data": {
"message": "2 users still needs to acknowledge the update manifest.",
"missingUsers": ["user1", "user2"]
}
}
POST /update-manifest
If multiple users are allowed to perform full manifest updates, acknowledgement is required from all users before the manifest is applied.
Each user must upload the same manifest to acknowledge the update.
See multi-party updates for more information.
Request body
Raw JSON encoded manifest.
Example request body:
{
"Packages": {
"package1": {},
"package2": {}
},
"Marbles": {
"marble1": {},
"marble2": {}
},
"Secrets": {},
"Users": {},
"Roles": {},
"TLS": {},
"RecoveryKeys": {
"recoveryKey1": "-----BEGIN PUBLIC KEY-----\nMIIBpTANBgk...",
"recoveryKey2": "-----BEGIN PUBLIC KEY-----\nMIIBpTANBgk..."
}
}
Returns
-
messagestringA human readable message indicating the success or progress of the update process.
Example response:
{
"status": "success",
"data": {
"message": "2 users still needs to acknowledge the update manifest.",
}
}
View a pending manifest update
This feature is an option with MarbleRun Enterprise.
- v2
- v1
GET /api/v2/update-manifest
Once a multi-party update has been initiated, users can view the pending manifest update.
Returns
-
manifeststringBase64 encoded manifest.
-
missingUsersarray of stringsAn array of user IDs that haven't yet acknowledged the update.
-
messagestringA human readable message indicating the progress of the update process.
Example response:
{
"status": "success",
"data": {
"manifest": "eyJQYWNrYWdlcyI6e30sIk1hcmJsZXMiOnt9fQo=",
"missingUsers": ["user1", "user2"],
"message": "2 users still needs to acknowledge the update manifest."
}
}
GET /update-manifest
Once a multi-party update has been initiated, users can view the pending manifest update.
Returns
-
manifeststringBase64 encoded manifest.
-
missingUsersarray of stringsAn array of user IDs that haven't yet acknowledged the update.
-
messagestringA human readable message indicating the progress of the update process.
Example response:
{
"status": "success",
"data": {
"manifest": "eyJQYWNrYWdlcyI6e30sIk1hcmJsZXMiOnt9fQo=",
"missingUsers": ["user1", "user2"],
"message": "2 users still needs to acknowledge the update manifest."
}
}
Cancel a pending manifest update
This feature is an option with MarbleRun Enterprise.
- v2
- v1
POST /api/v2/update-cancel
If a multi-party update has been initiated, users can cancel the pending manifest update.
Returns
-
messagestringA human readable message about the status of the update.
Example response:
{
"status": "success",
"data": {
"message": "Update successfully cancelled."
}
}
POST /update-cancel
If a multi-party update has been initiated, users can cancel the pending manifest update.
Returns
A human readable message about the status of the update.
Example response:
{
"status": "success",
"data": "Update successfully cancelled."
}
