Introduction
Cloudbase Open API enables developers to invoke CloudBase services as administrators via HTTP.
For languages for which CloudBase does not provide an SDK (such as Java, Go, C++, etc.), developers can access Cloudbase in this way.
Understanding the Request Structure
- Service Address
https://tcb-api.tencentcloudapi.com
- Request Method
Supported HTTP request methods: GET, POST, PUT, PATCH, DELETE
- Request Header Construction
Header Field | Type | Required | Description |
---|---|---|---|
X-CloudBase-Authorization | String | Required | Structure: "<Credential Version> <CloudBase Signature>" , CloudBase Open API standard credential |
X-CloudBase-SessionToken | String | Required | Session Token for Tencent Cloud CAM temporary key |
X-CloudBase-TimeStamp | Number | No | Unix timestamp in seconds |
content-type | String | No | Specify application/json for POST requests |
Usage Example
Query database documents
curl -X GET https://tcb-api.tencentcloudapi.com/api/v2/envs/{envId}/databases/{collectionName}/documents/{docId} \
-H "X-CloudBase-Authorization: <authorization>" \
-H "X-CloudBase-TimeStamp: 1551113065" \
-H "X-CloudBase-SessionToken: <sessiontoken>" \
How to Obtain Credentials
1. Obtain Credentials from Cloud Hosting Request Headers
In Cloud Hosting services, credential information can be obtained from the request headers, with the credential field x-cloudbase-authorization
and the temporary key field x-cloudbase-sessiontoken
.
Take the Node.js service in Cloud Hosting as an example:
const express = require("express");
const got = require("got");
const app = express();
app.get("/", async (req, res) => {
// Obtain credential information from request headers
const authorization = req.headers["x-cloudbase-authorization"];
const sessiontoken = req.headers["x-cloudbase-sessiontoken"];
const timestamp = req.headers["x-cloudbase-timestamp"];
// Use credentials to make a request to CloudBase Open API
// Take querying documents as an example, first construct the url
const envId = "foo";
const collectionName = "bar";
const docId = "123";
const url = `https://tcb-api.tencentcloudapi.com/api/v2/envs/${envId}/databases/${collectionName}/documents/${docId}`;
// Send the request with credentials added to the headers
const response = await got(url, {
headers: {
"X-CloudBase-Authorization": authorization,
"X-CloudBase-TimeStamp": timestamp,
"X-CloudBase-SessionToken": sessiontoken,
},
});
res.send(response.body);
});
app.listen(3000);
2. Node.js service computes credentials using the signature toolkit
Node.js developers can directly use the Node.js signature toolkit without implementing the signature calculation process themselves:
import { sign } from "@cloudbase/signature-nodejs";
const tmpSecretId = "Tencent Cloud temporary key SecretId";
const tmpSecretKey = "Tencent Cloud temporary key SecretKey";
const token = "Tencent Cloud temporary key Token";
const headers = {
host: "api.tcloudbase.com",
"content-type": "application/json; charset=utf-8",
};
const timestamp = Math.floor(new Date().getTime() / 1000);
const version = "1.0";
const { authorization } = sign({
secretId: tmpSecretId,
secretKey: tmpSecretKey,
method: "POST",
url: "https://api.tcloudbase.com/",
headers,
timestamp,
params: {},
});
// Open API request header
const reqHeaders = {};
reqHeaders["X-CloudBase-Authorization"] = version + " " + authorization;
reqHeaders["X-CloudBase-SessionToken"] = token;
reqHeaders["X-CloudBase-TimeStamp"] = timestamp;
- When using a permanent key, you can ignore the sessionToken field. To obtain a Tencent Cloud permanent key, visit the Access Key page in the Tencent Cloud console.
- In the cloud function environment, it can be obtained by reading the environment variable process.env.TENCENTCLOUD_SESSIONTOKEN. When using temporary keys, be sure to set this header field. :::
3. Compute credentials by yourself using a temporary key
For certain scenarios, developers can retrieve Tencent Cloud temporary keys by themselves and compute credentials. The standard process can be referred to in the Tencent Cloud CAM signature process.
The CloudBase standard credential computation process is largely the same as the Tencent Cloud CAM signature process, but simplified in parameters. Please read the following steps in conjunction with the Tencent Cloud CAM signature process. :::
(1) CanonicalRequest
Among them, the parameters of CanonicalRequest
are simplified, and api.tcloudbase.com
is a hypothetical domain, as follows:
Field | Value |
---|---|
HTTPRequestMethod | "POST" |
CanonicalURI | "//api.tcloudbase.com/" |
CanonicalQueryString | empty |
CanonicalHeaders | "content-type:application/json charset=utf-8\nhost:api.tcloudbase.com\n" |
SignedHeaders | "content-type;host" |
HashedRequestPayload | empty |
Therefore, CanonicalRequest
is fixed as follows:
POST
//api.tcloudbase.com/
content-type:application/json; charset=utf-8
host:api.tcloudbase.com
content-type;host
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
(2) StringToSign
Then compute StringToSign
, assuming the timestamp is 1600227242
, as follows:
TC3-HMAC-SHA256
1600227242
2020-09-16/tcb/tc3_request
0b986c5cd287577210de28ce0ff9167ada0dbb88736b07ce307b45615a49307e
(3) Signature
Assume the SecretKey is wH72j2a5ZzhwgnXViwVNqdWhWn4AG4iasv26D4JdjBA=
, and the Date is 2020-09-16
, then the Signature is:
0ce229810e251baa0ee2bb786c5f9eb6cb7758f55df28cbc161883c48a997e04
(4) Concatenate Authorization
TC3-HMAC-SHA256 Credential=AKIDDo-bNhLNl3kEY5HRzEG-CNUotmyFSadvpKimESWTfND98qyfrpYLCtQJ92_z9yN8/2020-09-16/tcb/tc3_request, SignedHeaders=content-type;host, Signature=0ce229810e251baa0ee2bb786c5f9eb6cb7758f55df28cbc161883c48a997e04
(5) Add the CloudBase signature version
Prepend 1.0
to get:
1.0 TC3-HMAC-SHA256 Credential=AKIDDo-bNhLNl3kEY5HRzEG-CNUotmyFSadvpKimESWTfND98qyfrpYLCtQJ92_z9yN8/2020-09-16/tcb/tc3_request, SignedHeaders=content-type;host, Signature=0ce229810e251baa0ee2bb786c5f9eb6cb7758f55df28cbc161883c48a997e04
Example Calculation for JS Credentials
const crypto = require("crypto");
const axios = require("axios");
// Key parameters
const SECRET_ID = "AKIDz8krbsJ5yKBZQpn74WFkmLPx3*******";
const SECRET_KEY = "Gu5t9xGARNpq86cd98joQYCN3*******";
const token = ""; //For permanent keys, the token is not required
const service = "tcb"; //Fixed value
const timestamp = Math.floor(new Date().getTime() / 1000); // Timestamp
const version = "1.0"; // Fixed value
const date = getDate(timestamp); // Time processing to obtain UTC date
// ************* Step 1: Concatenate the canonical request string (no action required here as all are fixed values) *************
const signedHeaders = "content-type;host";
const canonicalRequest = `POST\n//api.tcloudbase.com/\n\ncontent-type:application/json; charset=utf-8\nhost:api.tcloudbase.com\n\ncontent-type;host\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855`;
// ************* Step 2: Concatenate the string to be signed (essentially identical to the sample code) *************
const algorithm = "TC3-HMAC-SHA256";
const hashedCanonicalRequest = getHash(canonicalRequest);
const credentialScope = date + "/" + service + "/" + "tc3_request";
const stringToSign =
algorithm +
"\n" +
timestamp +
"\n" +
credentialScope +
"\n" +
hashedCanonicalRequest;
console.log(stringToSign);
// ************* Step 3: Calculate the signature (essentially identical to the sample code) *************
const kDate = sha256(date, "TC3" + SECRET_KEY);
const kService = sha256(service, kDate);
const kSigning = sha256("tc3_request", kService);
const signature = sha256(stringToSign, kSigning, "hex");
console.log(signature);
// ************* Step 4: Concatenate Authorization (essentially identical to the sample code) *************
const authorization =
algorithm +
" " +
"Credential=" +
SECRET_ID +
"/" +
credentialScope +
", " +
"SignedHeaders=" +
signedHeaders +
", " +
"Signature=" +
signature;
console.log(authorization);
// ************* Step 5: Concatenate request headers (supplementary) *************
const reqHeaders = {};
reqHeaders["X-CloudBase-Authorization"] = version + " " + authorization;
reqHeaders["X-CloudBase-SessionToken"] = token;
reqHeaders["X-CloudBase-TimeStamp"] = timestamp;
// ************* Step 6: Test access (request database) *************
axios({
method: "get",
url: "https://tcb-api.tencentcloudapi.com/api/v2/envs/${envid}/databases/${dbname}/documents/${docid}",
headers: reqHeaders,
}).then((res) => res.data);
// The following code is present in the sample code
function sha256(message, secret = "", encoding) {
const hmac = crypto.createHmac("sha256", secret);
return hmac.update(message).digest(encoding);
}
function getHash(message, encoding = "hex") {
const hash = crypto.createHash("sha256");
return hash.update(message).digest(encoding);
}
function getDate(timestamp) {
const date = new Date(timestamp * 1000);
const year = date.getUTCFullYear();
const month = ("0" + (date.getUTCMonth() + 1)).slice(-2);
const day = ("0" + date.getUTCDate()).slice(-2);
return `${year}-${month}-${day}`;
}
Python Credentials Sample Calculation Reference
# -*- coding: utf-8 -*-
import hashlib, hmac, json, os, sys, time
from datetime import datetime
# Key parameters
secret_id = "AKIDz8krbsJ5yKBZQpn74WFkmLPx3*******"
secret_key = "Gu5t9xGARNpq86cd98joQYCN3*******"
service = "tcb"
version = "1.0"
algorithm = "TC3-HMAC-SHA256"
timestamp = int(time.time())
date = datetime.utcfromtimestamp(timestamp).strftime("%Y-%m-%d")
# ************* Step 1: Concatenate specification request strings *************
signed_headers = "content-type;host"
canonical_request = "POST\n//api.tcloudbase.com/\n\ncontent-type:application/json; charset=utf-8\nhost:api.tcloudbase.com\n\ncontent-type;host\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
# ************* Step 2: Concatenate strings to be signed *************
credential_scope = date + "/" + service + "/" + "tc3_request"
hashed_canonical_request = hashlib.sha256(canonical_request.encode("utf-8")).hexdigest()
string_to_sign = (algorithm + "\n" +
str(timestamp) + "\n" +
credential_scope + "\n" +
hashed_canonical_request)
print(string_to_sign)
# ************* Step 3 Calculate the signature *************
# Calculate signature digest function
def sign(key, msg):
return hmac.new(key, msg.encode("utf-8"), hashlib.sha256).digest()
secret_date = sign(("TC3" + secret_key).encode("utf-8"), date)
secret_service = sign(secret_date, service)
secret_signing = sign(secret_service, "tc3_request")
signature = hmac.new(secret_signing, string_to_sign.encode("utf-8"), hashlib.sha256).hexdigest()
print(signature)
#************Step 4: Concatenate Authorization *************
authorization = (algorithm + " " +
"Credential=" + secret_id + "/" + credential_scope + ", " +
"SignedHeaders=" + signed_headers + ", " +
"Signature=" + signature)
print(authorization)
Java Credential Instance Calculation Reference
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
import java.util.TreeMap;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;
public class TencentCloudAPITC3Demo {
private final static Charset UTF8 = StandardCharsets.UTF_8;
private final static String SECRET_ID = "AKIDz8krbsJ5yKBZQpn74WFkmLPx3*******";
private final static String SECRET_KEY = "Gu5t9xGARNpq86cd98joQYCN3*******";
public static byte[] hmac256(byte[] key, String msg) throws Exception {
Mac mac = Mac.getInstance("HmacSHA256");
SecretKeySpec secretKeySpec = new SecretKeySpec(key, mac.getAlgorithm());
mac.init(secretKeySpec);
return mac.doFinal(msg.getBytes(UTF8));
}
public static String sha256Hex(String s) throws Exception {
MessageDigest md = MessageDigest.getInstance("SHA-256");
byte[] d = md.digest(s.getBytes(UTF8));
return DatatypeConverter.printHexBinary(d).toLowerCase();
}
public static void main(String[] args) throws Exception {
String service = "tcb";//Fixed value
String version = "1.0";
String algorithm = "TC3-HMAC-SHA256";
String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
// Note the time zone, otherwise errors may occur
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
String date = sdf.format(new Date(Long.valueOf(timestamp + "000")));
// ************* Step 1: Concatenate the canonical request string (no action required here as all are fixed values) *************
String signedHeaders = "content-type;host";
String canonicalRequest = `POST\n//api.tcloudbase.com/\n\ncontent-type:application/json; charset=utf-8\nhost:api.tcloudbase.com\n\ncontent-type;host\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855`
// ************* Step 2: Concatenate the string to be signed (essentially identical to the sample code) *************
String credentialScope = date + "/" + service + "/" + "tc3_request";
String hashedCanonicalRequest = sha256Hex(canonicalRequest);
String stringToSign = algorithm + "\n" + timestamp + "\n" + credentialScope + "\n" + hashedCanonicalRequest;
System.out.println(stringToSign);
// ************* Step 3: Calculate the signature (essentially identical to the sample code) *************
byte[] secretDate = hmac256(("TC3" + SECRET_KEY).getBytes(UTF8), date);
byte[] secretService = hmac256(secretDate, service);
byte[] secretSigning = hmac256(secretService, "tc3_request");
String signature = DatatypeConverter.printHexBinary(hmac256(secretSigning, stringToSign)).toLowerCase();
System.out.println(signature);
// ************* Step 4: Concatenate Authorization (essentially identical to the sample code) *************
String authorization = algorithm + " " + "Credential=" + SECRET_ID + "/" + credentialScope + ", "
+ "SignedHeaders=" + signedHeaders + ", " + "Signature=" + signature;
System.out.println(authorization);
// ************* Step 5: Concatenate request headers (supplementary) *************
TreeMap<String, String> headers = new TreeMap<String, String>();
headers.put("X-CloudBase-Authorization", version + " " + authorization);
headers.put("X-CloudBase-SessionToken", token);
headers.put("X-CloudBase-TimeStamp", timestamp);
// Use these headers to make network requests and access the relevant interfaces
//...Related network request code
}
}