利用ArchUnit在工程中禁用某些风险包

5/30/2024 工作工作经验

利用ArchUnit在工程中禁用某些风险包

# 一、需求背景

在日常开发中,依赖管理是一个常见的问题,我们享受着各种开源组件带来便利的同时,不同包中同名类也为工程带来了安全隐患。尤其是当我们的工程依赖一些可能存在安全隐患的库时,这个问题变得更加重要。比如我们引入了一个SDK,它把fastjson的代码直接放到了自己的SDK中,在这种情况下,exclusions就无能为力了,为了确保研发同学在工程中不会误引用fastjson,我们采用了ArchUnit开发自定义规则进行检查。

ArchUnit是一个强大的工具,可以根据一组自定义规则来验证代码库,我们可以通过编写单元测试来确保代码符合定义的架构规则。为了更早的发现问题,以及在一些单元测试不完善的老工程中也能够校验拦截,我这次介绍的是基于ArchUnit的Maven插件,在工程编译构建时完成自定义架构规则的校验。

# 二、实现过程

# 2.1 自定义ArchUnit规则插件

ArchUnit具体的API不详细赘述,官方文档写的很详细:ArchUnit文档 (opens new window)

之所以要开发规则插件,也是为了规则可以在不同工程中复用,如果是小团队,或者只有一两个工程,可以省略这步,直接把校验规则类,放到自己的工程中。

如下没有任何类应该依赖 fastjson 包的实现

public class ImportClassRule {
    // 没有任何类应该依赖 fastjson 包
    public static final ArchRule NO_CLASSES_SHOULD_IMPORT_JD_FASTJSON = ArchRuleDefinition.noClasses()
            .should().dependOnClassesThat().resideInAPackage("com.fastjson..");

}
1
2
3
4
5
6

# 2.2 集成ArchUnit Maven插件

接下来我们需要在,待检查工程的pom.xml文件中添加ArchUnitMaven插件的依赖。

ArchUnit Maven插件地址: https://github.com/societe-generale/arch-unit-maven-plugin

<build>
    <plugins>
        <plugin>
            <groupId>com.societegenerale.commons</groupId>
            <artifactId>arch-unit-maven-plugin</artifactId>
            <version>2.9.3</version>
            <configuration>
                <!-- noFailOnError设为false表示如果架构规则校验失败,Maven构建将会失败 -->
                <noFailOnError>false</noFailOnError>
                <rules>
                    <!-- 自定义规则项 -->
                    <configurableRules>
                        <configurableRule>
                            <!-- 自定义规则类的全限定名 -->
                            <rule>com.xxxxx.ImportClassRule</rule>
                            <!-- 规则的范围 -->
                            <applyOn>
                                <!-- 包名,指定规则应用于哪个包下的类 -->
                                <packageName>com.xxxxx</packageName>
                                <!-- scope为main表示只检查主代码,不检查测试代码 -->
                                <scope>main</scope>
                            </applyOn>
                            <checks>
                                <!-- 需要检查的自定义规则名称 -->
                                <check>NO_CLASSES_SHOULD_IMPORT_JD_FASTJSON</check>
                            </checks>
                        </configurableRule>
                    </configurableRules>
                </rules>
            </configuration>
            <executions>
                <execution>
                    <!-- 指定在哪个阶段执行插件的目标(goal) -->
                    <phase>compile</phase>
                    <goals>
                        <goal>arch-test</goal>
                    </goals>
                </execution>
            </executions>
         
        </plugin>
    </plugins>
</build>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

# 2.3 执行Maven构建验证自定义规则

完成以上配置后,我们可以通过Maven命令来执行编译,如果编译失败,表示工程中有代码违反了我们的架构规则。

写了个测试类,进行编译,异常信息如下:

ArchUnit Maven plugin reported architecture failures listed below :Rule Violated - com.xxxxx.ImportClassRule

Architecture Violation [Priority: MEDIUM] - Rule 'no classes should depend on classes that reside in a package 'com.jd.fastjson..'' was violated (1 times)

# 三、总结

通过在Maven构建过程中集成ArchUnit,我们可以快速校验代码是否符合预定义的架构规则,更早的发现问题并修复。这对于工程不会使用有安全隐患的第三方类非常有帮助。使用这种方式,我们可以在不移除必要依赖的情况下,规避掉潜在的安全风险。