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 adata
field with the actual response data. - In case of
error
, the response contains amessage
field with an error message. - In case of
fail
, the response may contain amessage
field with a human readable message, as well as adata
field with additional information.fail
is 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
-
manifestSignatureRootECDSA
stringBase64 encoded ECDSA signature of the manifest signed by the Coordinator's root key.
-
manifestFingerprint
stringHex encoded SHA-256 hash of the manifest.
-
manifest
stringBase64 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
-
manifestSignatureRootECDSA
stringBase64 encoded ECDSA signature of the manifest signed by the Coordinator's root key.
-
manifestSignature
stringHex encoded SHA-256 hash of the manifest.
-
manifest
stringBase64 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
-
manifest
stringBase64 encoded manifest.
Example request body:
{
"manifest": "eyJQYWNrYWdlcyI6e30sIk1hcmJsZXMiOnt9fQo="
}
Returns
-
recoveryKeys
objectAn 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 fromRecoveryKeys
in 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
-
recoveryKeys
objectAn 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 fromRecoveryKeys
in 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
-
nonce
string (optional)Base64 URL encoded nonce to be included in the quote.
Returns
-
cert
stringPEM-encoded certificate chain containing the Coordinator's Root CA and Intermediate CA. Can be used for trust establishment between a client and the Coordinator.
-
quote
stringBase64-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
-
cert
stringPEM-encoded certificate chain containing the Coordinator's Root CA and Intermediate CA. Can be used for trust establishment between a client and the Coordinator.
-
quote
stringBase64-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
-
recoverySecret
stringBase64 encoded recovery secret.
Example request body:
{
"recoverySecret": "AAECAwQFBgcICQoLDA0ODw=="
}
Returns
-
remaining
intRemaining secret shares to be uploaded for recovery to complete.
-
message
stringA 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
-
statusMessage
stringA 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
-
s
string (required) one or moreSecret name to retrieve.
Returns
-
secrets
objectKey-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
-
s
string (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
-
type
stringThe type of the secret. One of
cert-ecdsa
,cert-ed25519
,cert-rsa
,symmetric-key
,plain
. -
size
integerSize 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
-
shared
boolSpecifies whether this secret is shared across all marbles, or if it's unique to each marble.
-
userDefined
boolSpecifies whether a secret should be generated by the MarbleRun (false), or if it will be uploaded by a user at a later point (true).
-
cert
stringBase64 encoded X.509 certificate.
-
validFor
intValidity of the certificate in days.
-
private
stringBase64 encoded private key matching the certificate or symmetric key.
-
public
stringBase64 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
-
secrets
objectKey-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
-
key
stringBase64 encoded symmetric-key or arbitrary base64 encoded data for secrets of type
plain
. -
cert
stringBase64 encoded X.509 certificate.
-
public
stringBase64 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
-
sgxQuote
stringBase64 encoded SGX quote.
Example request body:
{
"sgxQuote": "U0dYIHF1b3RlCg=="
}
Returns
-
signature
stringBase64 encoded ECDSA signature of the SHA-256 hash of the base64-encoded SGX quote and the TCB status:
-
tcbStatus
stringThe 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
-
status
intA status code that matches the internal code of the Coordinator's current state.
-
message
stringA 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
-
statusCode
intA status code that matches the internal code of the Coordinator's current state.
-
statusMessage
stringA 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
-
updateLog
array 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:
-
manifest
stringBase64 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:
-
packages
objectKey-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
-
SecurityVersion
intThe 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
-
manifest
stringBase64 encoded manifest.
Example request body:
{
"manifest": "eyJQYWNrYWdlcyI6e30sIk1hcmJsZXMiOnt9fQo="
}
Returns
-
message
stringA human readable message indicating the success or progress of the update process.
-
missingUsers
array 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
-
message
stringA 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
-
manifest
stringBase64 encoded manifest.
-
missingUsers
array of stringsAn array of user IDs that haven't yet acknowledged the update.
-
message
stringA 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
-
manifest
stringBase64 encoded manifest.
-
missingUsers
array of stringsAn array of user IDs that haven't yet acknowledged the update.
-
message
stringA 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
-
message
stringA 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."
}