环境准备
- Java 8
- 引用官方提供的java项目骨架
- nexus oss 3.29.2-02 (api版本类似) https://sonatype-download.global.ssl.fastly.net/repository/downloads-prod-group/3/nexus-3.29.2-02-unix.tar.gz
git clone https://github.com/sonatype-nexus-community/nexus-format-archetype
cd nexus-format-archetype
mvn clean install
根据骨架的pom文件,编写新项目的创建命令,这里的pom文件信息如下
根据这个文件信息生成创建命令
# 退出nexus-format-archetype目录
# 新建项目
mkdir nexus-audit-plugin
cd nexus-audit-plugin
mvn archetype:generate -DarchetypeGroupId=org.sonatype.nexus.archetype -DarchetypeArtifact
Id=format-plugin -DarchetypeVersion=1.0.61-SNAPSHOT -DgroupId=com.sec.nexus -DartifactId=nexus-audit-plugin -DpluginFormat=audit -DpluginClass=Audit -Dversion=1.0-SNAPSHOT
如果提示没有找到 org.sonatype.nexus.archetype
,可能是mvn install没有安装成功, 手动移到目录中。
开发说明
这里默认创建的模板是基于 AuditRecipeSupport
类实现的。该类是一个抽象类,提供了审计功能的支持。它通常用于实现需要审计功能的Nexus插件或扩展。通过继承这个类,我们可以方便地记录和管理审计日志,跟踪系统中的重要操作和事件。
import org.sonatype.nexus.repository.audit.AuditRecipeSupport;
import org.sonatype.nexus.repository.Repository;
public class CustomAuditRecipe extends AuditRecipeSupport {
public CustomAuditRecipe(Repository repository) {
super(repository);
}
@Override
protected void doSomething() {
// 自定义的审计逻辑
auditLog.info("Package uploaded to repository: {}", getRepository().getName());
}
}
我们这里使用 ContributedHandler
是一个接口,主要用于扩展Nexus Repository的功能。通过实现这个接口,我们可以创建自定义的处理器,并将其插入到Nexus的请求处理链中。具体来说,ContributedHandler
可以用于以下场景:
- 自定义请求处理:可以拦截和处理Nexus中的HTTP请求,添加自定义的逻辑。例如,可以在请求到达特定仓库之前进行验证或修改请求。
- 扩展现有功能:可以在现有的Nexus功能基础上添加新的功能,而不需要修改Nexus的核心代码。
示例代码如下
import org.sonatype.nexus.repository.view.Request;
import org.sonatype.nexus.repository.view.Response;
import org.sonatype.nexus.repository.view.handlers.ContributedHandler;
public class LoggingHandler implements ContributedHandler {
private static final Logger LOG = LoggerFactory.getLogger(LoggingHandler.class);
@Override
public Response handle(Request request, Context context) throws Exception {
LOG.info("Received request for path: {}", request.getPath());
// 继续处理请求
return context.proceed(request);
}
}
根据文档 ContributedHandler
继承自 Handler
接口,而 Handler
接口中有一个核心方法
@Nonnull
Response handle(@Nonnull Context context) throws Exception;
- 这是
Handler
接口中的唯一方法,也是ContributedHandler
需要实现的方法。 - 该方法用于处理传入的请求,并返回一个
Response
对象。 Context
对象包含了请求的上下文信息,包括请求和响应对象。
实现
实现对maven拉取包的记录
import javax.annotation.Nonnull;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonatype.nexus.repository.Repository;
import org.sonatype.nexus.repository.types.ProxyType;
import org.sonatype.nexus.repository.view.Context;
import org.sonatype.nexus.repository.view.Payload;
import org.sonatype.nexus.repository.view.Response;
import org.sonatype.nexus.repository.maven.MavenPath;
import static java.lang.String.format;
@Named
@Singleton
public class ScannerHandler implements ContributedHandler {
private static final Logger LOG = LoggerFactory.getLogger(ScannerHandler.class);
private final ConfigurationHelper configurationHelper;
private final MavenScanner mavenScanner;
private final NpmScanner npmScanner;
private final PypiScanner pypiScanner;
// private SnykClient snykClient;
private SnykSecurityCapabilityConfiguration configuration;
@Inject
public ScannerHandler() {
}
@Nonnull
@Override
public Response handle(@Nonnull Context context) throws Exception {
Response response = context.proceed();
Repository repository = context.getRepository();
if (!ProxyType.NAME.equals(repository.getType().getValue())) {
LOG.warn("Only proxy repositories are supported: {} - {}", repository.getName(), repository.getType());
return response;
}
Payload payload = response.getPayload();
String repositoryFormat = repository.getFormat().getValue();
switch (repositoryFormat) {
case "maven2": {
Object mavenPathAttribute = context.getAttributes().get(MavenPath.class.getName());
if (!(mavenPathAttribute instanceof MavenPath)) {
LOG.warn("Could not extract maven path from {}", context.getRequest().getPath());
return null;
}
String clientIp = "";
MavenPath mavenPath = (MavenPath) mavenPathAttribute;
MavenPath parsedMavenPath = mavenPathParser.parsePath(mavenPath.getPath());
MavenPath.Coordinates coordinates = parsedMavenPath.getCoordinates();
LOG.info(">>>coordinates: {},{},{},{},{}", coordinates.getGroupId(),clientIp, coordinates.getArtifactId(), coordinates.getVersion());
break;
}
default:
LOG.error("format {} is not supported", repositoryFormat);
return response;
}
return response;
}
在处理不同类型的仓库格式时,除了 maven2
和 npm
,还有许多其他常见的仓库格式,如 nuget
、pypi
、docker
、rubygems
等
@Inject
是依赖注入框架(如Guice)中的一个注解,用于标记构造函数、方法或字段,以便框架在运行时自动注入依赖项。通过使用 @Inject
注解,您可以让依赖注入框架自动创建和注入所需的依赖对象,而无需手动实例化它们。
在该示例代码中,@Inject
注解标记了 ScannerHandler
类的构造函数,这意味着依赖注入框架会自动为 ScannerHandler
提供所需的依赖项。
等同代码如下
// 手动创建依赖项
// 手动注入依赖项
ScannerHandler scannerHandler = new ScannerHandler();
结合使用 @Named
和 @Singleton
,可以创建一个命名的单例类,在依赖注入时既能保证单例模式,又能通过名称进行区分。希望这些信息对您有所帮助。
运行打包
mvn clean package
集成jar包
临时集成测试
3.29版本
移动到 nexus-3.29.2-02/deploy
目录下
最新版本
./nexus run
bundle:list
bundle:install file:////tmp/nexus-security-plugin.jar
# 激活
bundle:start <org.sonatype.nexus.plugins:nexus-repository-foo ID>
测试结果如下:
永久安装
复制nexus-repository-foo-1.0.0.jar) 到 <nexus_dir>/deploy
目录下, 该文件夹由 Nexus Repository 监控,如果 Nexus Repository 正在运行,则插件应在复制到此处后 60 秒内加载。