前言
由于Windows 11更新了Smart App Control( 智能应用控制(SAC)是Windows 11的一项新的安全功能,可以阻止不受信任或有潜在危险的应用程序 。)它会阻止没有签名的恶意文件。但是,考虑到需要在Win11的新机器上部署Auto agent,因此需要对dll文件进行自动签名。数字签名需要购买,它被集成在Bamboo Plan上,我需要对Bamboo的Plan进行自动触发。
1. 数字签名
数字签名(又称公钥数字签名)是只有信息的发送者才能产生的别人无法伪造的一段数字串,这段数字串同时也是对信息的发送者发送信息真实性的一个有效证明。数字签名通常定义两种互补的运算,一个用于签名,另一个用于验证。数字签名用到了非对称密钥加密技术与数字摘要技术。
1.1Windows SDK SignTool.exe 微软文件签名工具
签名工具是一个命令行工具,用于对文件进行数字签名,验证文件和时间戳文件中的签名。
安装 Visual Studio
和 Windows SDK
时会自动安装此工具。要运行工具,我们建议您使用 Visual Studio 命令提示符或 Windows SDK 命令提示符(也称 CMD Shell)。您可以使用这些实用程序轻松运行工具,而不需要导航到安装文件夹。有关更多信息,请参见Visual Studio
和 Windows SDK
命令提示。
如果您的计算机上已安装了 Visual Studio
:在任务栏上依次单击 Start->All Programs->Visual Studio->Visual Studio Tools->Visual Studio Command Prompt。
-或 -
如果您的计算机上已安装了 Windows SDK
:在任务栏上依次单击 Start->All Programs->Windows SDK 文件夹和Command Prompt(或CMD Shell)。
你需要对安装的SignTool.exe
设置环境变量,一般安装在C:\Program Files (x86)\Windows Kits\10\App Certification Kit
在命令提示处,键入下列命令:
signtool [command] [options] [file_name | ...]
2. Bamboo
Atlassian Bamboo 是一款持续集成构建服务器软件(Build Server)(非开源软件)。 可见Bamboo也是Atlassian公司的产品,跟前面的JIRA及后面提到的FishEye和Confluence都是一家人。
它可以根据你配置的项目所在的路径使用浏览器打开,让你的代码提交后,它会自动检测并自动进行编译,比如我提交了代码,我的mercurial的名称是赵丹丹,那么代码提交后Bamboo会自动所搜到我刚提交的版本集,然后编译(也可以手动运行编译),并且会显示"Changed By Wenhao"。
如果编译成功则会提示成功,如果编译失败则会打印对应的错误日志。
2.1 触发Plan
思路:首先,我需要触发Plan,然后循环等待结果,我可以使用while循环,通过buildResultKey
来确认Plan是否成功。
1)触发代码:
public void RunPlan(string _buildNo)
{
//这里与官网不同
string testJobsRunURL = RestAPI.bambooBaseURL + $"/queue/{_buildNo}?stage&executeAllStages";
HttpWebResponse webResponse = RestAPI.BambooAPIResponse(testJobsRunURL,"POST");
if (webResponse.StatusCode == HttpStatusCode.OK)
{
Console.WriteLine("200 OK when request to " + testJobsRunURL);
using (Stream resStream = webResponse.GetResponseStream())
{
//把数据流存入StreamReadr,选用编码格式
using (StreamReader reader = new StreamReader(resStream, Encoding.UTF8))
{
responseContent = reader.ReadToEnd().ToString();
Console.WriteLine(responseContent);
XmlDocument doc = new XmlDocument();
doc.LoadXml(responseContent);
XmlElement nList = (XmlElement)doc.SelectSingleNode("/restQueuedBuild");
//Wait(nList.GetAttribute("buildResultKey"));
new_buildResultKey = nList.GetAttribute("buildResultKey");
}
}
}
}
这里是生成的字符串需要转为XML
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<restQueuedBuild planKey="PHEN-MAN" buildNumber="1344" buildResultKey="PHEN-MAN-1344">
<triggerReason>Manual build</triggerReason>
<link href="https://bamboo.tc.lenovo.com/rest/api/latest/result/PHEN-MAN-1344" rel="self"/>
</restQueuedBuild>
2.2 获取结果:
public void generateSummarySheet(string _buildNo, string _expandParams)
{
string testJobsResultURL = RestAPI.bambooBaseURL + $"/result/{_buildNo}.json" + $"?expand={_expandParams}"; //e.g. https://bamboo.tc.lenovo.com/rest/api/latest/result/PHEN-UWP-latest.json?expand=stages.stage.results.result
HttpWebResponse webResponse = RestAPI.BambooAPIResponse(testJobsResultURL,"GET");
if (webResponse.StatusCode == HttpStatusCode.OK)
{
Console.WriteLine("200 OK when request to " + testJobsResultURL);
using (Stream resStream = webResponse.GetResponseStream())
{
//把数据流存入StreamReadr,选用编码格式
using (StreamReader reader = new StreamReader(resStream, Encoding.UTF8))
{
//通过ReadToEnd()把整个HTTP响应作为一个字符串取回,
//也可以通过 StreamReader.ReadLine()方法逐行取回HTTP响应的内容。
responseContent = reader.ReadToEnd().ToString();
bambooPlanAPILink = (string)JObject.Parse(responseContent).SelectToken("$.link.href"); //e.g. "https://bamboo.tc.lenovo.com/rest/api/latest/result/PHEN-UWP-452"
buildResultKey = (string)JObject.Parse(responseContent).SelectToken("$.buildResultKey"); //e.g. "PHEN-UWP-452"
buildCompletedDate = (string)JObject.Parse(responseContent).SelectToken("$.buildCompletedDate");
finished = (string)JObject.Parse(responseContent).SelectToken("$.finished");
successful = (string)JObject.Parse(responseContent).SelectToken("$.successful");
buildReason = (string)JObject.Parse(responseContent).SelectToken("$.buildReason");
//Console.WriteLine(bambooPlanAPILink);
//Console.WriteLine(buildResultKey);
//Console.WriteLine(buildCompletedDate);
//Console.WriteLine(finished);
//Console.WriteLine(successful);
//Console.WriteLine(buildReason);
}
}
}
else
{
Console.WriteLine($"Status code={webResponse.StatusCode}! Now you can't access {testJobsResultURL} yet!");
}
}
2.3循环调用:
public void getResult()
{
//"Summary" Sheet
string buildKey = ConfigReader.Instance.GetConfig().SelectToken("$.planBuildKey").ToString(); //e.g. "PHEN-UWP-492" or "PHEN-UWP-latest"
//string testResultsFile = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, $"{buildKey}_{DateTime.Now.ToString("_yyyyMMdd_hhmmss")}.xlsx"); //e.g. D:\vantage-uwp-automation\BambooAPI\bin\Debug\netcoreapp3.1\PHEN-UWP-latest__20210818_021811.xlsx
//Console.WriteLine($"Generating [Summary] sheet from the result of {buildKey} ...");
//RunPlan(buildKey);
int n = 0;
while (true) {
DateTime dt1 = DateTime.Now;
while ((DateTime.Now - dt1).TotalMilliseconds < 10000)
{
continue;
};
n++;
generateSummarySheet(buildKey, RestAPI.expandParamsForTestPlanSummary);
if ((new_buildResultKey==buildResultKey)&&(successful=="True")) {
break;
}
if (n >= 12) {
Console.WriteLine("Signature Failed!" + "bambooPlanAPILink: " + bambooPlanAPILink +
" buildCompletedDate: " + buildCompletedDate + " Success: " + successful + " buildReason: " + buildReason);
break;
}
}
Console.WriteLine($"Success____________________________End of signature____________________________");
//"AllTests" Sheet
}
Remove-item alias:curl
cURL -k --user username:password -X POST -d "stage&executeAllStages" https://bamboo.tc.lenovo.com/rest/api/latest/queue/PHEN-MAN
cURL -k --user username:password -X GET https://bamboo.tc.lenovo.com/rest/api/latest/result/PHEN-MAN-latest.json?expand=stages.stage.results.result
参考
C#操作XML方法:新增、修改和删除节点与属性
Bamboo API官方文档
Github上的C#调用实现
BAMBOO REST API: HOW TO TRIGGER A PLAN AND WAITING FOR A RESULT