feat: plugin-huawei

This commit is contained in:
xiaojunnuo
2023-05-09 09:19:17 +08:00
parent d602df4c70
commit 003ea9310b
36 changed files with 1640 additions and 61 deletions
@@ -0,0 +1,25 @@
import { IsAccess, AccessInput } from "@certd/pipeline";
@IsAccess({
name: "huawei",
title: "华为云授权",
desc: "",
})
export class HuaweiAccess {
@AccessInput({
title: "accessKeyId",
component: {
placeholder: "accessKeyId",
},
required: true,
})
accessKeyId = "";
@AccessInput({
title: "accessKeySecret",
component: {
placeholder: "accessKeySecret",
},
required: true,
})
accessKeySecret = "";
}
@@ -0,0 +1 @@
export * from "./huawei-access";
@@ -0,0 +1,114 @@
import _ from "lodash";
import { CreateRecordOptions, IDnsProvider, IsDnsProvider, RemoveRecordOptions } from "@certd/plugin-cert";
import { Autowire, ILogger } from "@certd/pipeline";
import { HuaweiAccess } from "../access";
import { HuaweiYunClient } from "../lib/client";
@IsDnsProvider({
name: "huawei",
title: "华为云",
desc: "华为云DNS解析提供商",
accessType: "huawei",
})
export class HuaweiDnsProvider implements IDnsProvider {
client: any;
@Autowire()
access!: HuaweiAccess;
@Autowire()
logger!: ILogger;
endpoint = "https://domains-external.myhuaweicloud.com";
async onInit() {
const access: any = this.access;
this.client = new HuaweiYunClient(access);
}
async getDomainList() {
const url = `${this.endpoint}/v2/domains`;
const ret = await this.client.request({
url,
method: "GET",
});
return ret.domains;
}
async matchDomain(dnsRecord: string) {
const list = await this.getDomainList();
let domain = null;
for (const item of list) {
if (_.endsWith(dnsRecord, item.DomainName)) {
domain = item.DomainName;
break;
}
}
if (!domain) {
throw new Error("can not find Domain ," + dnsRecord);
}
return domain;
}
async getRecords(domain: string, rr: string, value: string) {
const params: any = {
RegionId: "cn-hangzhou",
DomainName: domain,
RRKeyWord: rr,
ValueKeyWord: undefined,
};
if (value) {
params.ValueKeyWord = value;
}
const requestOption = {
method: "POST",
};
const ret = await this.client.request("DescribeDomainRecords", params, requestOption);
return ret.DomainRecords.Record;
}
async createRecord(options: CreateRecordOptions): Promise<any> {
const { fullRecord, value, type } = options;
this.logger.info("添加域名解析:", fullRecord, value);
const domain = await this.matchDomain(fullRecord);
const rr = fullRecord.replace("." + domain, "");
const params = {
RegionId: "cn-hangzhou",
DomainName: domain,
RR: rr,
Type: type,
Value: value,
// Line: 'oversea' // 海外
};
const requestOption = {
method: "POST",
};
try {
const ret = await this.client.request("AddDomainRecord", params, requestOption);
this.logger.info("添加域名解析成功:", value, value, ret.RecordId);
return ret.RecordId;
} catch (e: any) {
if (e.code === "DomainRecordDuplicate") {
return;
}
this.logger.info("添加域名解析出错", e);
throw e;
}
}
async removeRecord(options: RemoveRecordOptions): Promise<any> {
const { fullRecord, value, record } = options;
const params = {
RegionId: "cn-hangzhou",
RecordId: record,
};
const requestOption = {
method: "POST",
};
const ret = await this.client.request("DeleteDomainRecord", params, requestOption);
this.logger.info("删除域名解析成功:", fullRecord, value, ret.RecordId);
return ret.RecordId;
}
}
@@ -0,0 +1 @@
import "./huawei-dns-provider";
@@ -0,0 +1,2 @@
export * from "./access";
export * from "./dns-provider";
@@ -0,0 +1,24 @@
# License
[The MIT License (MIT)](http://opensource.org/licenses/MIT)
Copyright (c) 2009-2013 Jeff Mott
Copyright (c) 2013-2016 Evan Vosberg
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
@@ -0,0 +1,20 @@
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,35 @@
var signer = require("./signer");
var https = require("https");
var sig = new signer.Signer();
//Set the AK/SK to sign and authenticate the request.
sig.Key = "QTWAOYTTINDUT2QVKYUC";
sig.Secret = "MFyfvK41ba2giqM7**********KGpownRZlmVmHc";
//The following example shows how to set the request URL and parameters to query a VPC list.
//Specify a request method, such as GET, PUT, POST, DELETE, HEAD, and PATCH.
//Set request host.
//Set request URI.
//Set parameters for the request URL.
var r = new signer.HttpRequest("GET", "endpoint.example.com/v1/77b6a44cba5143ab91d13ab9a8ff44fd/vpcs?limie=1");
//Add header parameters, for example, x-domain-id for invoking a global service and x-project-id for invoking a project-level service.
r.headers = { "Content-Type": "application/json" };
//Add a body if you have specified the PUT or POST method. Special characters, such as the double quotation mark ("), contained in the body must be escaped.
r.body = "";
var opt = sig.Sign(r);
console.log(opt.headers["X-Sdk-Date"]);
console.log(opt.headers["Authorization"]);
var req = https.request(opt, function (res) {
console.log(res.statusCode);
console.log("headers:", JSON.stringify(res.headers));
res.on("data", function (chunk) {
console.log(chunk.toString());
});
});
req.on("error", function (err) {
console.log(err.message);
});
req.write(r.body);
req.end();
@@ -0,0 +1,501 @@
// HWS API Gateway Signature
(function (root, factory) {
"use strict";
/*global define*/
if (typeof define === "function" && define.amd) {
// AMD
define(["CryptoJS"], function (CryptoJS) {
var crypto_wrapper = {
hmacsha256: function (keyByte, message) {
return CryptoJS.HmacSHA256(message, keyByte).toString(CryptoJS.enc.Hex);
},
HexEncodeSHA256Hash: function (body) {
return CryptoJS.SHA256(body);
},
};
return factory(crypto_wrapper);
});
} else if (typeof wx === "object") {
// wechat
var CryptoJS = require("./js/hmac-sha256.js");
var crypto_wrapper = {
hmacsha256: function (keyByte, message) {
return CryptoJS.HmacSHA256(message, keyByte).toString(CryptoJS.enc.Hex);
},
HexEncodeSHA256Hash: function (body) {
return CryptoJS.SHA256(body);
},
};
module.exports = factory(crypto_wrapper);
} else if (typeof module === "object" && module.exports) {
// Node
var crypto = require("crypto");
var crypto_wrapper = {
hmacsha256: function (keyByte, message) {
return crypto.createHmac("SHA256", keyByte).update(message).digest().toString("hex");
},
HexEncodeSHA256Hash: function (body) {
return crypto.createHash("SHA256").update(body).digest().toString("hex");
},
};
module.exports = factory(crypto_wrapper);
} else {
// Browser
var CryptoJS = root.CryptoJS;
var crypto_wrapper = {
hmacsha256: function (keyByte, message) {
return CryptoJS.HmacSHA256(message, keyByte).toString(CryptoJS.enc.Hex);
},
HexEncodeSHA256Hash: function (body) {
return CryptoJS.SHA256(body);
},
};
root.signer = factory(crypto_wrapper);
}
})(this, function (crypto_wrapper) {
"use strict";
var Algorithm = "SDK-HMAC-SHA256";
var HeaderXDate = "X-Sdk-Date";
var HeaderAuthorization = "Authorization";
var HeaderContentSha256 = "x-sdk-content-sha256";
const hexTable = new Array(256);
for (var i = 0; i < 256; ++i) hexTable[i] = "%" + ((i < 16 ? "0" : "") + i.toString(16)).toUpperCase();
const noEscape = [
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0, // 0 - 15
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0, // 16 - 31
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1,
1,
0, // 32 - 47
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
0,
0,
0,
0,
0,
0, // 48 - 63
0,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1, // 64 - 79
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
0,
0,
0,
0,
1, // 80 - 95
0,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1, // 96 - 111
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
0,
0,
0,
1,
0, // 112 - 127
];
// function urlEncode is based on https://github.com/nodejs/node/blob/master/lib/querystring.js
// Copyright Joyent, Inc. and other Node contributors.
function urlEncode(str) {
if (typeof str !== "string") {
if (typeof str === "object") str = String(str);
else str += "";
}
var out = "";
var lastPos = 0;
for (var i = 0; i < str.length; ++i) {
var c = str.charCodeAt(i);
// ASCII
if (c < 0x80) {
if (noEscape[c] === 1) continue;
if (lastPos < i) out += str.slice(lastPos, i);
lastPos = i + 1;
out += hexTable[c];
continue;
}
if (lastPos < i) out += str.slice(lastPos, i);
// Multi-byte characters ...
if (c < 0x800) {
lastPos = i + 1;
out += hexTable[0xc0 | (c >> 6)] + hexTable[0x80 | (c & 0x3f)];
continue;
}
if (c < 0xd800 || c >= 0xe000) {
lastPos = i + 1;
out += hexTable[0xe0 | (c >> 12)] + hexTable[0x80 | ((c >> 6) & 0x3f)] + hexTable[0x80 | (c & 0x3f)];
continue;
}
// Surrogate pair
++i;
if (i >= str.length) throw new errors.URIError("ERR_INVALID_URI");
var c2 = str.charCodeAt(i) & 0x3ff;
lastPos = i + 1;
c = 0x10000 + (((c & 0x3ff) << 10) | c2);
out += hexTable[0xf0 | (c >> 18)] + hexTable[0x80 | ((c >> 12) & 0x3f)] + hexTable[0x80 | ((c >> 6) & 0x3f)] + hexTable[0x80 | (c & 0x3f)];
}
if (lastPos === 0) return str;
if (lastPos < str.length) return out + str.slice(lastPos);
return out;
}
function HttpRequest(method, url, headers, body) {
if (method === undefined) {
this.method = "";
} else {
this.method = method;
}
if (url === undefined) {
this.host = "";
this.uri = "";
this.query = {};
} else {
this.query = {};
var host, path;
var i = url.indexOf("://");
if (i !== -1) {
url = url.substr(i + 3);
}
var i = url.indexOf("?");
if (i !== -1) {
var query_str = url.substr(i + 1);
url = url.substr(0, i);
var spl = query_str.split("&");
for (var i in spl) {
var kv = spl[i];
var index = kv.indexOf("=");
var key, value;
if (index >= 0) {
key = kv.substr(0, index);
value = kv.substr(index + 1);
} else {
key = kv;
value = "";
}
if (key !== "") {
key = decodeURI(key);
value = decodeURI(value);
if (this.query[key] === undefined) {
this.query[key] = [value];
} else {
this.query[key].push(value);
}
}
}
}
var i = url.indexOf("/");
if (i === -1) {
host = url;
path = "/";
} else {
host = url.substr(0, i);
path = url.substr(i);
}
this.host = host;
this.uri = decodeURI(path);
}
if (headers === undefined) {
this.headers = {};
} else {
this.headers = headers;
}
if (body === undefined) {
this.body = "";
} else {
this.body = body;
}
}
function findHeader(r, header) {
for (var k in r.headers) {
if (k.toLowerCase() === header.toLowerCase()) {
return r.headers[k];
}
}
return null;
}
// Build a CanonicalRequest from a regular request string
//
// CanonicalRequest =
// HTTPRequestMethod + '\n' +
// CanonicalURI + '\n' +
// CanonicalQueryString + '\n' +
// CanonicalHeaders + '\n' +
// SignedHeaders + '\n' +
// HexEncode(Hash(RequestPayload))
function CanonicalRequest(r, signedHeaders) {
var hexencode = findHeader(r, HeaderContentSha256);
if (hexencode === null) {
var data = RequestPayload(r);
hexencode = crypto_wrapper.HexEncodeSHA256Hash(data);
}
return (
r.method +
"\n" +
CanonicalURI(r) +
"\n" +
CanonicalQueryString(r) +
"\n" +
CanonicalHeaders(r, signedHeaders) +
"\n" +
signedHeaders.join(";") +
"\n" +
hexencode
);
}
function CanonicalURI(r) {
var pattens = r.uri.split("/");
var uri = [];
for (var k in pattens) {
var v = pattens[k];
uri.push(urlEncode(v));
}
var urlpath = uri.join("/");
if (urlpath[urlpath.length - 1] !== "/") {
urlpath = urlpath + "/";
}
//r.uri = urlpath
return urlpath;
}
function CanonicalQueryString(r) {
var keys = [];
for (var key in r.query) {
keys.push(key);
}
keys.sort();
var a = [];
for (var i in keys) {
var key = urlEncode(keys[i]);
var value = r.query[keys[i]];
if (Array.isArray(value)) {
value.sort();
for (var iv in value) {
a.push(key + "=" + urlEncode(value[iv]));
}
} else {
a.push(key + "=" + urlEncode(value));
}
}
return a.join("&");
}
function CanonicalHeaders(r, signedHeaders) {
var headers = {};
for (var key in r.headers) {
headers[key.toLowerCase()] = r.headers[key];
}
var a = [];
for (var i in signedHeaders) {
var value = headers[signedHeaders[i]];
a.push(signedHeaders[i] + ":" + value.trim());
}
return a.join("\n") + "\n";
}
function SignedHeaders(r) {
var a = [];
for (var key in r.headers) {
a.push(key.toLowerCase());
}
a.sort();
return a;
}
function RequestPayload(r) {
return r.body;
}
// Create a "String to Sign".
function StringToSign(canonicalRequest, t) {
var bytes = crypto_wrapper.HexEncodeSHA256Hash(canonicalRequest);
return Algorithm + "\n" + t + "\n" + bytes;
}
// Create the HWS Signature.
function SignStringToSign(stringToSign, signingKey) {
return crypto_wrapper.hmacsha256(signingKey, stringToSign);
}
// Get the finalized value for the "Authorization" header. The signature
// parameter is the output from SignStringToSign
function AuthHeaderValue(signature, Key, signedHeaders) {
return Algorithm + " Access=" + Key + ", SignedHeaders=" + signedHeaders.join(";") + ", Signature=" + signature;
}
function twoChar(s) {
if (s >= 10) {
return "" + s;
} else {
return "0" + s;
}
}
function getTime() {
var date = new Date();
return (
"" +
date.getUTCFullYear() +
twoChar(date.getUTCMonth() + 1) +
twoChar(date.getUTCDate()) +
"T" +
twoChar(date.getUTCHours()) +
twoChar(date.getUTCMinutes()) +
twoChar(date.getUTCSeconds()) +
"Z"
);
}
function Signer() {
this.Key = "";
this.Secret = "";
}
Signer.prototype.Sign = function (r) {
var headerTime = findHeader(r, HeaderXDate);
if (headerTime === null) {
headerTime = getTime();
r.headers[HeaderXDate] = headerTime;
}
if (r.method !== "PUT" && r.method !== "PATCH" && r.method !== "POST") {
r.body = "";
}
var queryString = CanonicalQueryString(r);
if (queryString !== "") {
queryString = "?" + queryString;
}
var options = {
hostname: r.host,
path: encodeURI(r.uri) + queryString,
method: r.method,
headers: r.headers,
};
if (findHeader(r, "host") === null) {
r.headers.host = r.host;
}
var signedHeaders = SignedHeaders(r);
var canonicalRequest = CanonicalRequest(r, signedHeaders);
var stringToSign = StringToSign(canonicalRequest, headerTime);
var signature = SignStringToSign(stringToSign, this.Secret);
options.headers[HeaderAuthorization] = AuthHeaderValue(signature, this.Key, signedHeaders);
return options;
};
return {
HttpRequest: HttpRequest,
Signer: Signer,
urlEncode: urlEncode,
findHeader: findHeader,
SignedHeaders: SignedHeaders,
CanonicalRequest: CanonicalRequest,
StringToSign: StringToSign,
};
});
@@ -0,0 +1,10 @@
var assert = require("assert");
var signer = require('./signer')
var s = ""
for (i = 0; i < 0x80; i++) {
s = s + signer.urlEncode(String.fromCharCode(i))
}
console.log(s)
assert.equal(s, "%00%01%02%03%04%05%06%07%08%09%0A%0B%0C%0D%0E%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F%20%21%22%23%24%25%26%27%28%29%2A%2B%2C-.%2F0123456789%3A%3B%3C%3D%3E%3F%40ABCDEFGHIJKLMNOPQRSTUVWXYZ%5B%5C%5D%5E_%60abcdefghijklmnopqrstuvwxyz%7B%7C%7D~%7F")
@@ -0,0 +1,42 @@
// @ts-ignore
import signer from "./signer";
import https from "https";
import { HuaweiAccess } from "../access";
import { axios } from "@certd/acme-client";
export type ApiRequestOptions = {
method: string;
url: string;
headers: any;
body: any;
};
export class HuaweiYunClient {
access: HuaweiAccess;
constructor(access: HuaweiAccess) {
this.access = access;
}
async request(options: ApiRequestOptions) {
const sig = new signer.Signer();
//Set the AK/SK to sign and authenticate the request.
sig.Key = this.access.accessKeyId;
sig.Secret = this.access.accessKeySecret;
//The following example shows how to set the request URL and parameters to query a VPC list.
//Specify a request method, such as GET, PUT, POST, DELETE, HEAD, and PATCH.
//Set request host.
//Set request URI.
//Set parameters for the request URL.
const r = new signer.HttpRequest(options.method, options.url, options.headers, options.body);
//Add header parameters, for example, x-domain-id for invoking a global service and x-project-id for invoking a project-level service.
r.headers = { "Content-Type": "application/json" };
//Add a body if you have specified the PUT or POST method. Special characters, such as the double quotation mark ("), contained in the body must be escaped.
r.body = "";
const opt = sig.Sign(r);
console.log("opt", opt);
console.log(opt.headers["X-Sdk-Date"]);
console.log(opt.headers["Authorization"]);
const res = await axios.request(opt);
return res;
}
}
@@ -0,0 +1,501 @@
// HWS API Gateway Signature
(function (root, factory) {
"use strict";
/*global define*/
if (typeof define === "function" && define.amd) {
// AMD
define(["CryptoJS"], function (CryptoJS) {
var crypto_wrapper = {
hmacsha256: function (keyByte, message) {
return CryptoJS.HmacSHA256(message, keyByte).toString(CryptoJS.enc.Hex);
},
HexEncodeSHA256Hash: function (body) {
return CryptoJS.SHA256(body);
},
};
return factory(crypto_wrapper);
});
} else if (typeof wx === "object") {
// wechat
var CryptoJS = require("./js/hmac-sha256.js");
var crypto_wrapper = {
hmacsha256: function (keyByte, message) {
return CryptoJS.HmacSHA256(message, keyByte).toString(CryptoJS.enc.Hex);
},
HexEncodeSHA256Hash: function (body) {
return CryptoJS.SHA256(body);
},
};
module.exports = factory(crypto_wrapper);
} else if (typeof module === "object" && module.exports) {
// Node
var crypto = require("crypto");
var crypto_wrapper = {
hmacsha256: function (keyByte, message) {
return crypto.createHmac("SHA256", keyByte).update(message).digest().toString("hex");
},
HexEncodeSHA256Hash: function (body) {
return crypto.createHash("SHA256").update(body).digest().toString("hex");
},
};
module.exports = factory(crypto_wrapper);
} else {
// Browser
var CryptoJS = root.CryptoJS;
var crypto_wrapper = {
hmacsha256: function (keyByte, message) {
return CryptoJS.HmacSHA256(message, keyByte).toString(CryptoJS.enc.Hex);
},
HexEncodeSHA256Hash: function (body) {
return CryptoJS.SHA256(body);
},
};
root.signer = factory(crypto_wrapper);
}
})(this, function (crypto_wrapper) {
"use strict";
var Algorithm = "SDK-HMAC-SHA256";
var HeaderXDate = "X-Sdk-Date";
var HeaderAuthorization = "Authorization";
var HeaderContentSha256 = "x-sdk-content-sha256";
const hexTable = new Array(256);
for (var i = 0; i < 256; ++i) hexTable[i] = "%" + ((i < 16 ? "0" : "") + i.toString(16)).toUpperCase();
const noEscape = [
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0, // 0 - 15
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0, // 16 - 31
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1,
1,
0, // 32 - 47
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
0,
0,
0,
0,
0,
0, // 48 - 63
0,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1, // 64 - 79
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
0,
0,
0,
0,
1, // 80 - 95
0,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1, // 96 - 111
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
0,
0,
0,
1,
0, // 112 - 127
];
// function urlEncode is based on https://github.com/nodejs/node/blob/master/lib/querystring.js
// Copyright Joyent, Inc. and other Node contributors.
function urlEncode(str) {
if (typeof str !== "string") {
if (typeof str === "object") str = String(str);
else str += "";
}
var out = "";
var lastPos = 0;
for (var i = 0; i < str.length; ++i) {
var c = str.charCodeAt(i);
// ASCII
if (c < 0x80) {
if (noEscape[c] === 1) continue;
if (lastPos < i) out += str.slice(lastPos, i);
lastPos = i + 1;
out += hexTable[c];
continue;
}
if (lastPos < i) out += str.slice(lastPos, i);
// Multi-byte characters ...
if (c < 0x800) {
lastPos = i + 1;
out += hexTable[0xc0 | (c >> 6)] + hexTable[0x80 | (c & 0x3f)];
continue;
}
if (c < 0xd800 || c >= 0xe000) {
lastPos = i + 1;
out += hexTable[0xe0 | (c >> 12)] + hexTable[0x80 | ((c >> 6) & 0x3f)] + hexTable[0x80 | (c & 0x3f)];
continue;
}
// Surrogate pair
++i;
if (i >= str.length) throw new errors.URIError("ERR_INVALID_URI");
var c2 = str.charCodeAt(i) & 0x3ff;
lastPos = i + 1;
c = 0x10000 + (((c & 0x3ff) << 10) | c2);
out += hexTable[0xf0 | (c >> 18)] + hexTable[0x80 | ((c >> 12) & 0x3f)] + hexTable[0x80 | ((c >> 6) & 0x3f)] + hexTable[0x80 | (c & 0x3f)];
}
if (lastPos === 0) return str;
if (lastPos < str.length) return out + str.slice(lastPos);
return out;
}
function HttpRequest(method, url, headers, body) {
if (method === undefined) {
this.method = "";
} else {
this.method = method;
}
if (url === undefined) {
this.host = "";
this.uri = "";
this.query = {};
} else {
this.query = {};
var host, path;
var i = url.indexOf("://");
if (i !== -1) {
url = url.substr(i + 3);
}
var i = url.indexOf("?");
if (i !== -1) {
var query_str = url.substr(i + 1);
url = url.substr(0, i);
var spl = query_str.split("&");
for (var i in spl) {
var kv = spl[i];
var index = kv.indexOf("=");
var key, value;
if (index >= 0) {
key = kv.substr(0, index);
value = kv.substr(index + 1);
} else {
key = kv;
value = "";
}
if (key !== "") {
key = decodeURI(key);
value = decodeURI(value);
if (this.query[key] === undefined) {
this.query[key] = [value];
} else {
this.query[key].push(value);
}
}
}
}
var i = url.indexOf("/");
if (i === -1) {
host = url;
path = "/";
} else {
host = url.substr(0, i);
path = url.substr(i);
}
this.host = host;
this.uri = decodeURI(path);
}
if (headers === undefined) {
this.headers = {};
} else {
this.headers = headers;
}
if (body === undefined) {
this.body = "";
} else {
this.body = body;
}
}
function findHeader(r, header) {
for (var k in r.headers) {
if (k.toLowerCase() === header.toLowerCase()) {
return r.headers[k];
}
}
return null;
}
// Build a CanonicalRequest from a regular request string
//
// CanonicalRequest =
// HTTPRequestMethod + '\n' +
// CanonicalURI + '\n' +
// CanonicalQueryString + '\n' +
// CanonicalHeaders + '\n' +
// SignedHeaders + '\n' +
// HexEncode(Hash(RequestPayload))
function CanonicalRequest(r, signedHeaders) {
var hexencode = findHeader(r, HeaderContentSha256);
if (hexencode === null) {
var data = RequestPayload(r);
hexencode = crypto_wrapper.HexEncodeSHA256Hash(data);
}
return (
r.method +
"\n" +
CanonicalURI(r) +
"\n" +
CanonicalQueryString(r) +
"\n" +
CanonicalHeaders(r, signedHeaders) +
"\n" +
signedHeaders.join(";") +
"\n" +
hexencode
);
}
function CanonicalURI(r) {
var pattens = r.uri.split("/");
var uri = [];
for (var k in pattens) {
var v = pattens[k];
uri.push(urlEncode(v));
}
var urlpath = uri.join("/");
if (urlpath[urlpath.length - 1] !== "/") {
urlpath = urlpath + "/";
}
//r.uri = urlpath
return urlpath;
}
function CanonicalQueryString(r) {
var keys = [];
for (var key in r.query) {
keys.push(key);
}
keys.sort();
var a = [];
for (var i in keys) {
var key = urlEncode(keys[i]);
var value = r.query[keys[i]];
if (Array.isArray(value)) {
value.sort();
for (var iv in value) {
a.push(key + "=" + urlEncode(value[iv]));
}
} else {
a.push(key + "=" + urlEncode(value));
}
}
return a.join("&");
}
function CanonicalHeaders(r, signedHeaders) {
var headers = {};
for (var key in r.headers) {
headers[key.toLowerCase()] = r.headers[key];
}
var a = [];
for (var i in signedHeaders) {
var value = headers[signedHeaders[i]];
a.push(signedHeaders[i] + ":" + value.trim());
}
return a.join("\n") + "\n";
}
function SignedHeaders(r) {
var a = [];
for (var key in r.headers) {
a.push(key.toLowerCase());
}
a.sort();
return a;
}
function RequestPayload(r) {
return r.body;
}
// Create a "String to Sign".
function StringToSign(canonicalRequest, t) {
var bytes = crypto_wrapper.HexEncodeSHA256Hash(canonicalRequest);
return Algorithm + "\n" + t + "\n" + bytes;
}
// Create the HWS Signature.
function SignStringToSign(stringToSign, signingKey) {
return crypto_wrapper.hmacsha256(signingKey, stringToSign);
}
// Get the finalized value for the "Authorization" header. The signature
// parameter is the output from SignStringToSign
function AuthHeaderValue(signature, Key, signedHeaders) {
return Algorithm + " Access=" + Key + ", SignedHeaders=" + signedHeaders.join(";") + ", Signature=" + signature;
}
function twoChar(s) {
if (s >= 10) {
return "" + s;
} else {
return "0" + s;
}
}
function getTime() {
var date = new Date();
return (
"" +
date.getUTCFullYear() +
twoChar(date.getUTCMonth() + 1) +
twoChar(date.getUTCDate()) +
"T" +
twoChar(date.getUTCHours()) +
twoChar(date.getUTCMinutes()) +
twoChar(date.getUTCSeconds()) +
"Z"
);
}
function Signer() {
this.Key = "";
this.Secret = "";
}
Signer.prototype.Sign = function (r) {
var headerTime = findHeader(r, HeaderXDate);
if (headerTime === null) {
headerTime = getTime();
r.headers[HeaderXDate] = headerTime;
}
if (r.method !== "PUT" && r.method !== "PATCH" && r.method !== "POST") {
r.body = "";
}
var queryString = CanonicalQueryString(r);
if (queryString !== "") {
queryString = "?" + queryString;
}
var options = {
hostname: r.host,
path: encodeURI(r.uri) + queryString,
method: r.method,
headers: r.headers,
};
if (findHeader(r, "host") === null) {
r.headers.host = r.host;
}
var signedHeaders = SignedHeaders(r);
var canonicalRequest = CanonicalRequest(r, signedHeaders);
var stringToSign = StringToSign(canonicalRequest, headerTime);
var signature = SignStringToSign(stringToSign, this.Secret);
options.headers[HeaderAuthorization] = AuthHeaderValue(signature, this.Key, signedHeaders);
return options;
};
return {
HttpRequest: HttpRequest,
Signer: Signer,
urlEncode: urlEncode,
findHeader: findHeader,
SignedHeaders: SignedHeaders,
CanonicalRequest: CanonicalRequest,
StringToSign: StringToSign,
};
});
@@ -0,0 +1,15 @@
import dayjs from "dayjs";
export const ZoneOptions = [{ value: "cn-hangzhou" }];
export function appendTimeSuffix(name: string) {
if (name == null) {
name = "certd";
}
return name + "-" + dayjs().format("YYYYMMDD-HHmmss");
}
export function checkRet(ret: any) {
if (ret.code != null) {
throw new Error("执行失败:" + ret.Message);
}
}