一、 前置步骤
如何获取 AK/SK
- Access Key:简写为AK,对http请求进行签名,签名机制是为了访问更加安全, access key为用户独有,并作为身份标识;
- Secret Key:简写为SK,用户私有的,请勿给他人。
调用智能边缘云 OpenAPI 需要 AK/SK 认证鉴权,下面为 AK/SK 获取方法:
AK/SK 从 天翼云 IAM 申请,获取地址:https://vip.ctcdn.cn/
登录页面中选择【天翼云账号】登录,如下图所示:
登录后,在左侧【个人中心】下,选择【AccessKey管理】,点击【新增】,工作区选择【系统内置工作区】。
创建 AK 后,点击查看,验证后就可以获取到 SK。
充值与集群自助权限申请
调用 OpenAPI 开通资源前,需要确保账户下有集群自助权限,确认地址:https://ecx.ctyun.cn/vm/vm/list ;
- 账号充值:按需开通资源时,要求可用现金余额最少100元;
- 如果在租户控制台创建资源时没有集群可选项(下图 ①),请找售后或运营申请集群自助权限;
- 如果在租户控制台看到集群下没有配额(下图 ②),请找售后或运营申请资源配额。
调用地址
API 的调用地址:https://ecx-global.ctapi.ctyun.cn
二、签名示例
认证头部header部分
名称 | 描述 | 是否必选 | 示例 |
---|---|---|---|
Content-Type | 消息体的类型 | 是 | application/json |
ctyun-eop-request-id | 流水号 | 是 | 0ffb9b07-d5a8-4e19-b3ce-12dfb9705a1d |
Eop-Authorization | 签名认证信息 | 是 | 4a4bdc57e06542199b5f98d4cd107be2 Headers=ctyun-eop-request-id;eop-date Signature=b2WEo4nh9ewn6SWOP0ii5g8L0z9CT5gprpDWntlCX9I= |
Eop-date | 时间,15分钟有效期(实际传时间为北京东八区UTC+8时间。TZ仅为格式,非UTC时间。) | 是 | 20221107T093029Z |
Python
Python SDK 下载地址:https://eop.ctyun.cn/ebp/static/sdk/py/ctapi_sdk_python.py
调用方法:将下面代码复制到下载的 sdk 代码最下面后执行
# 认证信息
ak = "your ak"
sk = "your sk"
endpoint = "https://ecx-global.ctapi.ctyun.cn"
# 请求路径
path1 = "/v3/cluster/describeRegionClusters"
path2 = "/v3/cluster/describeInstanceSpec"
path3 = "/v3/vpc/createVPC"
# 请求参数
params1 = {}
params2 = {"nodeCode": "hn-changde-1"}
params3 = {"nodeCode": "hn-changde-1"}
# 发起请求
response1 = get(f"{endpoint}{path1}", params1)
response2 = get(f"{endpoint}{path2}", params2)
response3 = post(f"{endpoint}{path2}", "", params3)
# 打印响应
print("Response for describeRegionClusters:")
print(json.loads(response1))
print("\nResponse for describeInstanceSpec:")
print(json.loads(response2))
Golang
Go SDK 下载地址:https://eop.ctyun.cn/ebp/static/sdk/go/ctapi_sdk_go.zip
调用方法:下面代码包括了 sdk 代码和调用示例
package main
import (
"bytes"
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"sort"
"strings"
"time"
"github.com/google/uuid"
)
const (
METHOD_GET = "GET"
METHOD_POST = "POST"
METHOD_HEAD = "HEAD"
METHOD_PATCH = "PATCH"
METHOD_PUT = "PUT"
METHOD_DELETE = "DELETE"
)
var (
ak = "ak"
sk = "sk"
endpoint = "https://ecx-global.ctapi.ctyun.cn"
)
func hmacSHA256(secret, data string) []byte {
h := hmac.New(sha256.New, []byte(secret))
h.Write([]byte(data))
return h.Sum(nil)
}
func base64OfHmac(data []byte) string {
return base64.StdEncoding.EncodeToString(data)
}
func getRequestUUID() string {
return uuid.New().String()
}
func getSortedStr(data map[string]interface{}) string {
keys := make([]string, 0, len(data))
for k := range data {
keys = append(keys, k)
}
sort.Strings(keys)
var strList []string
for _, k := range keys {
strList = append(strList, fmt.Sprintf("%s=%v", k, data[k]))
}
return strings.Join(strList, "&")
}
func buildSign(ak, sk string, queryParams, bodyParams map[string]interface{}, eopDate, requestUUID, method string, file bool, contentType string) string {
var bodyStr string
if !file {
if bodyParams != nil {
bodyBytes, _ := json.Marshal(bodyParams)
bodyStr = string(bodyBytes)
}
}
var bodyDigest string
if method == METHOD_POST || method == METHOD_PUT {
if file {
bodyDigest = fmt.Sprintf("%x", sha256.Sum256([]byte(bodyStr)))
} else {
bodyBytes, _ := json.Marshal(bodyParams)
bodyDigest = fmt.Sprintf("%x", sha256.Sum256(bodyBytes))
}
} else {
bodyDigest = fmt.Sprintf("%x", sha256.Sum256([]byte(bodyStr)))
}
headerStr := fmt.Sprintf("ctyun-eop-request-id:%s\neop-date:%s\n", requestUUID, eopDate)
queryStr := getSortedStr(queryParams)
signatureStr := fmt.Sprintf("%s\n%s\n%s", headerStr, queryStr, bodyDigest)
printLog(fmt.Sprintf("signature_str is: %s", signatureStr))
kTime := hmacSHA256(sk, eopDate)
kAk := hmacSHA256(string(kTime), ak)
kDate := hmacSHA256(string(kAk), strings.Split(eopDate, "T")[0])
signatureBase64 := base64OfHmac(hmacSHA256(string(kDate), signatureStr))
signHeader := fmt.Sprintf("%s Headers=ctyun-eop-request-id;eop-date Signature=%s", ak, signatureBase64)
return signHeader
}
func getSignHeaders(ak, sk string, queryParams, body map[string]interface{}, method, contentType string, file bool, uuid string) map[string]string {
now := time.Now()
eopDate := now.Format("20060102T150405Z")
headers := map[string]string{
"Content-type": contentType,
"ctyun-eop-request-id": uuid,
"Eop-Authorization": buildSign(ak, sk, queryParams, body, eopDate, uuid, method, file, contentType),
"Eop-date": eopDate,
}
return headers
}
func execute(ak, sk, urlStr, method string, queryParams, bodyParams map[string]interface{}, headerParams map[string]string, contentType string, file bool) (string, error) {
queryStr := getSortedStr(queryParams)
requestUUID := getRequestUUID()
headers := getSignHeaders(ak, sk, queryParams, bodyParams, method, contentType, file, requestUUID)
for k, v := range headerParams {
headers[k] = v
}
if len(queryStr) > 0 {
urlStr = fmt.Sprintf("%s?%s", urlStr, queryStr)
}
var reqBody []byte
if bodyParams != nil {
reqBody, _ = json.Marshal(bodyParams)
}
fmt.Println("Request URL:", urlStr)
fmt.Println("Request Method:", method)
fmt.Println("Request Headers:", headers)
fmt.Println("Request Body:", string(reqBody))
req, err := http.NewRequest(method, urlStr, bytes.NewBuffer(reqBody))
if err != nil {
return "", err
}
for k, v := range headers {
req.Header.Set(k, v)
}
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return "", err
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println("Response Status:", resp.Status)
fmt.Println("Response Headers:", resp.Header)
fmt.Println("Response Body:", string(body))
return string(body), nil
}
/* ********************************* 调用示例 *********************************************** */
func printLog(logInfo string) {
now := time.Now()
logInfo = fmt.Sprintf("[%s]: %s", now.Format("2006-01-02 15:04:05"), logInfo)
fmt.Println(logInfo)
}
func main() {
path1 := "/v3/cluster/describeRegionClusters"
path2 := "/v3/cluster/describeInstanceSpec"
params1 := map[string]interface{}{}
params2 := map[string]interface{}{"nodeCode": "hn-changde-1"}
response1, err := execute(ak, sk, endpoint+path1, METHOD_GET, params1, nil, nil, "application/json;charset=UTF-8", false)
if err != nil {
fmt.Println("Error:", err)
return
}
fmt.Println("Response for describeRegionClusters:")
fmt.Println(response1)
response2, err := execute(ak, sk, endpoint+path2, METHOD_GET, params2, nil, nil, "application/json;charset=UTF-8", false)
if err != nil {
fmt.Println("Error:", err)
return
}
fmt.Println("\nResponse for describeInstanceSpec:")
fmt.Println(response2)
}
三、OpenAPI 接口文档
接口文档地址: https://eop.ctyun.cn/ebp/ctapiDocument/search?sid=69&data=55
接口在线调试,如下图所示,填写 AK/SK 后测试接口:
SDK 下载地址: