|
42Crunch 安全审计是 42Crunch API 安全平台的 3 项服务之一:它使用 OpenAPI (Swagger) 文件,并沿着两个轴(安全性和数据)对其进行分析。
- 在安全级别,审核服务会查看所使用的传输(是否使用 TLS?)、身份验证方法(基本、API 密钥、OAuth),对于 OAuth,则查看使用的授权类型和范围。每个问题都有一个负分:分数的值取决于数据和操作灵敏度。例如,如果数据被标记为高度敏感且操作为 DELETE,则分数受到的影响比数据不敏感且操作为 GET 时更严重。
- 在数据级别,审核服务分析如何指定标头、路径参数、查询参数和正文负载。特别是,它检测字符串是否具有模式和边界,数字是否具有边界,并且通常,架构是否可用于所有响应类型。目标是确保彻底定义所有入站和出站流量,以防止不需要的流量通过我们的 API 防火墙。
生成高质量的开放API文件
我们的客户使用两种方法:
- API设计首先,其中使用专门的编辑器(如SwaggerHub或红绿灯)来创建OpenAPI文件。
- 代码优先,其中 OpenAPI 是通过代码注释生成的。弹簧启动是一个广泛使用的框架,它通过弹簧狐狸框架为OAS生成提供了一流的支持。该框架能够利用 Swagger 注释。
在本文档中,我们将重点介绍影响 42Crunch 审核分数的核心注释,从而允许我们生成强大的白名单来保护您的 API。
美洲国家组织安全定义
超过 30% 的审核分数基于安全定义及其应用方式。安全定义定义了 API 的安全方式:基本身份验证、API 密钥和 OAuth2 是规范目前支持的三种身份验证类型。
我们将解释如何添加 API 密钥定义,然后添加 OAuth2 定义,这是最常用的定义。
使用接口密钥
我们的目标是将以下安全定义添加到我们的OAS文档中:在本例中,我们有一个API密钥,该密钥在称为x-access-token的标头中传递。
"securityDefinitions": { "access-token":
{ "type": "apiKey", "in": "header", "name":
"x-access-token", "description":
"Most operations need to user token retrieved calling /api/login" } }我们首先需要将安全方案添加到 API 案卷定义中,如下所示:
@Bean public Docket apiDocket()
{ return new Docket(DocumentationType.SWAGGER_2) .select()
.apis(RequestHandlerSelectors.basePackage("com.xliic"))
.paths(PathSelectors.any()) .build() .apiInfo(getApiInfo())
.produces(DEFAULT_PRODUCES_AND_CONSUMES)
.consumes(DEFAULT_PRODUCES_AND_CONSUMES) .useDefaultResponseMessages(false)
.securitySchemes(securitySchemes())) .enableUrlTemplating(false)
.host("apis.xliic.com")
.protocols(Stream.of("https").collect(toSet())); }
安全方案操作编译可在 API 中使用的安全定义的列表。让我们从添加一个简单的 API 密钥定义开始。我们首先声明 API 密钥方案:
private ApiKey apikeyScheme()
{ return new ApiKey("access-token", "x-access-token", "header");
}然后,我们将此方案添加到方案列表中。 Docket 配置上的安全方案需要一个安全方案列表,您可以按如下方式构建这些方案:
private ArrayList securitySchemes ()
{ ArrayList secList = Lists.newArrayList();
<strong>secList.add(apikeyScheme());
</strong> return secList; } 生成的开放 API 定义如下所示:
&#34;securityDefinitions&#34;: { &#34;access-token&#34;:
{ &#34;type&#34;: &#34;apiKey&#34;, &#34;name&#34;:
&#34;x-access-token&#34;, &#34;in&#34;: &#34;header&#34; } },使用 OAuth 作为身份验证方案
如果我们的 API 使用的是通过 OAuth 生成的访问令牌,则可以使用 OAuth 方案对象来描述它。
private OAuth oauthScheme()
{ GrantType grantType = new AuthorizationCodeGrant(
new TokenRequestEndpoint(Constants.OAUTH_SERVER + &#34;/authorize&#34;,
&#34;CLIENT_ID&#34;, &#34;CLIENT_SECRET&#34;),
new TokenEndpoint(Constants.OAUTH_SERVER + &#34;/token&#34;, &#34;oauthtoken&#34;));
OAuth oauth = new OAuth (&#34;oauth&#34;, Arrays.asList(scopes()),
Arrays.asList(grantType));
return oauth; } 在此函数中,我们声明 OAuth 授权类型(此处为授权码授予),包括授权和令牌终结点。如果作用域相关联,则在数组中定义它们。
private AuthorizationScope[] scopes()
{ AuthorizationScope[]
scopes = { new AuthorizationScope(&#34;read&#34;, &#34;for read operations&#34;),
new AuthorizationScope(&#34;write&#34;, &#34;for write operations&#34;),
new AuthorizationScope(&#34;delete&#34;, &#34;for delete operations&#34;) };
return scopes; }请注意,必需的CLIENT_ID、CLIENT_SECRET和 OAuth 令牌信息将用作 Swagger UI 呈现的一部分(它们不在 OpenAPI 文件本身中使用)。
开放API定义中的相应定义如下:
&#34;securityDefinitions&#34;:
{ &#34;oauth&#34;:
{ &#34;type&#34;: &#34;oauth2&#34;, &#34;authorizationUrl&#34;:
&#34;https://oauth.acme.com/authorize&#34;, &#34;tokenUrl&#34;:
&#34;https://oauth.acme.com/token&#34;, &#34;flow&#34;:
&#34;accessCode&#34;, &#34;scopes&#34;:
{ &#34;read&#34;: &#34;for read operations&#34;, &#34;write&#34;:
&#34;for write operations&#34;, &#34;delete&#34;:
&#34;for delete operations&#34; } } }
如果要同时使用 APIKey 和 OAuth 安全定义,只需将它们都添加到声明中,如下所示:
private ArrayList securitySchemes ()
{ // Add the two security definitions to a single
list ArrayList secList = Lists.newArrayList();
secList.add(apikeyScheme());
secList.add(oauthScheme());
return secList; }应用安全性
一旦您为服务 (API) 定义了安全方案,我们现在可以定义如何对它应用它们。在第 1 部分 的示例中,我们定义了两种方案:API Key 和 OAuth,根据 OAS 规范,我们可以根据需要注入模式,我们可以让 API 具有全局安全模式,或者我们可以按资源使用安全粒度来定义它。
在 API 级别应用安全性
为了定义全局身份验证方案,您需要在控制器级别添加相应的授权注释,如以下示例所示:
@RestController
@RequestMapping(&#34;/v2&#34;)
@Api(value = &#34;Set of endpoints for Creating, Retrieving,
Updating and Deleting of Persons.&#34;, authorizations = {
@Authorization(value = &#34;access-token&#34;) })
public class PersonController {此代码段将此 API 的全局安全方案设置为访问令牌。
在操作级别应用安全性
您可能需要在资源级别定义一个安全方案,换句话说,您可以说:
- API MyAPI
- /客户
- 获取 :使用 API 密钥
- 帖子: 使用 OAuth2
为此,您需要在 API 操作级别添加授权注释,如下所示:
@RequestMapping(method = RequestMethod.GET,
path = &#34;/person/{id}&#34;,
produces = MediaType.APPLICATION_JSON_VALUE)
@ApiOperation(nickname = &#34;getPersonByID&#34;, value = &#34;Retrieve Person by id&#34;,
notes = &#34;Returns a specific person by their identifier. 404 if does not exist.&#34;,
response = Person.class,
authorizations = { @Authorization(value = &#34;access-token&#34;) })同样,您可以将 OAuth2 指定为另一个操作(例如删除操作)所需的安全方案。
@RequestMapping(method = RequestMethod.DELETE, path = &#34;/person/{id}&#34;)
@ApiOperation(value = &#34;Delete Person by id&#34;,
notes = &#34;Deletes a person from the system. 404 if the person&#39;s identifier is not found.&#34;,
authorizations = { @Authorization(value=&#34;oauth&#34;,scopes =
{@AuthorizationScope(scope=&#34;delete&#34;,
description = &#34;Delete person&#34;)})})42紧缩扩展支持
可以通过弹簧狐将自定义OAS扩展添加到您的定义中。这可用于注入特定于 42Crunch 的扩展,如下图所示:
@RequestMapping(method = RequestMethod.POST, path = &#34;/login&#34;,
produces = MediaType.APPLICATION_JSON_VALUE)
@ApiOperation(value = &#34;Create a person&#34;, notes = &#34;API login &#34;,
extensions = { @Extension(properties = {
@ExtensionProperty(name = &#34;x-42c-no-authentication&#34;, value = &#34;true&#34;)
})
})
public Person login( @RequestParam @Min(10) @Max(50)
@Pattern(regexp = Constants.EMAIL_REGEX) String email,
@RequestParam @Min(10) @Max(50) @Pattern(regexp = Constants.PASSWORD_REGEX)
String password)这是生成的 OAS 代码段:
&#34;paths&#34;:{ &#34;/login&#34;:{
&#34;post&#34;:{ ... &#34;deprecated&#34;:false,
&#34;x-42c-no-authentication&#34;:&#34;true&#34; }此 OAS 扩展允许您从 42Crunch 安全审核中禁用对 API 中不需要身份验证的操作(例如用于身份验证的登录或注册操作)的身份验证检查。
结论
本文中介绍的方法将允许您生成丰富、强化的 OpenAPI 定义,并修复 42Crunch 安全审计报告的问题。添加注释还带来了代码和 API 合约之间完全同步的好处,然后可以使用其他 42Crunch 平台服务来测试和保护 API。
引用:
https://medium.com/future-vision/the-great-authenticators-of-rest-738e81109331参考:42Crunch |
|