上文https://www.jianshu.com/p/a0d77b0b4809我们通过调用Sonar的API接口实现了对扫描结果获取,并通过一个计算模型完成对整个发布流的质量控制
但我们实际用的过程发现如下问题:
1.上文中接口调用没有传递任何口令但也能成功调用,原因是我们Sonar建的项目是公开的。
2.用户创建及项目创建工作繁琐,没有与内部的项目管理软件打通。
本文我们通过对Api的进一步验证解决这些问题。
1.Sonar Api说明
Sonar的Api一些主要问题,提前列出,避免入坑
1.Sonar的Api各版本差异较大,向下兼容性差
2.Sonar的Api不是很人性化,其Post的接口,参数不是写body中,而是写URL中。
3.当接口返回400/404时通常是你接口参数错了,并不能简单理解为接口地址不存在,而是应该先检查参数值,对api讲大概率是数据不存在。
4.文档是描述接口参数有时候有多个(如projectId/projectKey),很多是二选一的,全部提供了反而报错。
2.Sonar的Api安全
sonar的api调用是可以添加token的,接口是否需要token是根据要操作的接口的权限决定,有些接口强制需要token,具体可参考其api页面介绍。
Token模式
sonar的token是使用Basic Authorization认证,调用接口时在http header中添加如下信息:
header.Add("Authorization", "Basic " + basicToken);
其中值的格式是 Basic空格+token
token的格式是将 登录帐户:密码 进行Base64加密(UTF-8格式)
示例代码.netCore版本
public Dictionary GetAuthHeader()
{
Dictionary header = new Dictionary();
string basicToken = EncodeBase64("admin:123456"); //帐户:密码
header.Add("Authorization", "Basic " + basicToken);
return header;
}
public static string EncodeBase64(string code, string code_type = "UTF-8")
{
string encode = "";
byte[] bytes = Encoding.GetEncoding(code_type).GetBytes(code);
try
{
encode = Convert.ToBase64String(bytes);
}
catch
{
encode = code;
}
return encode;
}
示例代码Java版本
String encodedText = encoder.encodeToString("admin:adssmin".getBytes("UTF-8"));
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.add("Authorization", "Basic " + encodedText);
3.Sonar的常用Api扩展封装参考
创建项目
public string CreateProject(string name, string project)
{
//默认写死了private
string postData = string.Format("name={0}&project={1}&visibility=private", name, project);
string url = sonarRootUrl + "/api/projects/create?" + postData;
Dictionary header = GetAuthHeader();
string result = HttpHelper.HttpPost(url, "", "application/json", header);
return result;
}
删除项目
public string DeleteProject(string project)
{
string postData = string.Format("project={0}", project);
string url = sonarRootUrl + "/api/projects/delete?" + postData;
Dictionary header = GetAuthHeader();
string result = HttpHelper.HttpPost(url, "", "application/json", header);
return result;
}
为用户授权指定项目特定权限
///
/// 为用户授权指定项目权限
///
/// 用户帐户
/// project Key
/// 权限:admin, codeviewer, issueadmin, securityhotspotadmin, scan, user
///
public string AddUserToProject(string userId, string permision, string projectKey)
{
//参数projectId与projectKey二选一,不要全部写上,建议用key,projectId需要库中找
//权限等级admin, codeviewer, issueadmin, securityhotspotadmin, scan, user (对应界面浏览)
//不能批量授予多个权限,如果要授权codeviewer和scan两个权限,则需要分多次调用该接口。
string postData = string.Format("login={0}&permission={1}&projectKey={2}", userId, permision, projectKey);
string url = sonarRootUrl + "/api/permissions/add_user?" + postData;
Dictionary header = GetAuthHeader();
string result = HttpHelper.HttpPost(url, "", "application/json", header);
return result;
}
移除用户在指定项目中权限
public string RemoveUserToProject(string userId, string permision, string projectKey)
{
string postData = string.Format("login={0}&permission={1}&projectKey={2}", userId, permision, projectKey);
string url = sonarRootUrl + "/api/permissions/remove_user?" + postData;
Dictionary header = GetAuthHeader();
string result = HttpHelper.HttpPost(url, "", "application/json", header);
return result;
}
创建用户并生成Token
public string CreateUserWithToken(string userId, string mail, string userName)
{
string output = "";
string postData = string.Format("mail={0}&local=false&login={1}&name={2}", mail, userId, userName);
string url = sonarRootUrl + "/api/users/create?" + postData;
Dictionary header = GetAuthHeader();
string result = HttpHelper.HttpPost(url, "", "application/json", header);
LogHelper.Debug("CreateUserResult:" + result);
output += result;
postData = string.Format("login={0}&name=myToken", userId);
url = sonarRootUrl + "/api/user_tokens/generate?" + postData;
result = HttpHelper.HttpPost(url, postData, "application/json", header);
LogHelper.Debug("CreateUserTokenResult:" + result);
output += result;
result = AddUserToGroup(userId);
output += result;
//这里偷了个懒没有对结果处理,你可以将数据提取整理成对接方真正需要的数据结构。
return output;
}
添加用户到群组
///
/// 添加用户到默认组中
///
///
///
public string AddUserToGroup(string userId, string groupName = "")
{
if (string.IsNullOrEmpty(groupName)) groupName = "defaultGroup";
//如果用id需要去数据库group表看。URL中id与name二选1即可,建议用name。id=3&login={0} name=myDefaultGroup
string postData = string.Format("name={0}&login={1}", groupName, userId);
string url = sonarRootUrl + "/api/user_groups/add_user?" + postData;
Dictionary header = GetAuthHeader();
string result = HttpHelper.HttpPost(url, postData, "application/json", header);
LogHelper.Debug("AddGroupResult:" + result);
return result;
}
移除用户从指定群组
///
/// 将用户从组中移除
///
///
///
///
public string RemoveToGroup(string userId, string groupName = "")
{
if (string.IsNullOrEmpty(groupName)) groupName = "defaultGroup";
string postData = string.Format("name={0}&login={1}", groupName, userId);
string url = sonarRootUrl + "/api/user_groups/remove_user?" + postData;
Dictionary header = GetAuthHeader();
string result = HttpHelper.HttpPost(url, postData, "application/json", header);
return result;
}