如何使用 Java Agent 在运行时修改 Java 类(以魔改 Jenkins 为例)

本文讲述了如何使用 Java Agent 在 Jenkins 运行时修改类字节码,以绕过 Jenkins 插件升级的签名验证,实现从镜像站点加速下载。通过定位 Jenkins 代码,创建 Maven 工程并编写 Agent,最终成功部署并解决 Jenkins 插件更新速度慢的问题。
摘要由CSDN通过智能技术生成

遇到问题

起因

深夜更新 Jenkins 插件的时候,遇到了一个问题:插件下载速度太慢了,并且有大概率失败。

因此我研究了一下 Jenkins 的插件升级机制,研究是否可以使用镜像站点加速。

初步研究

Jenkins 的 升级信息(包含本体和插件)来自于 http://mirrors.jenkins-ci.org/updates/update-center.json 这个 URL。

这个 JSON 文件描述了所有可用插件的 版本信息下载地址 ,并且 Jenkins 在 插件中心高级 选项卡里提供了修改这个地址的功能。

我找到了 jenkins-zh 社区提供的 升级信息 镜像地址 https://updates.jenkins-zh.cn/update-center.json,他们所提供的 JSON 文件内部,将所有 下载地址 替换为等价的 清华 TUNA 镜像站 的地址。

遭遇困境

但是当我把镜像地址填入 Jenkins,点击 更新 时,界面突然弹出来巨长一串超出屏幕的报错,提示 签名验证失败

为什么

Jenkins 在这个 JSON 文件内做了签名认证。

也就是说,Jenkins 允许你从另外的 URL 获取到 update-center.json 这个文件,但是 JSON 文件内部描述的 下载地址 等信息是 无法修改 的,否则会破坏签名认证。

这也就意味着,插件下载的过程仍然无法使用镜像站点加速。

怎么办

两个方法:

  1. 重新签名 update-center.json 并替换 Jenkins 内的 CA 文件,让修改后的 update-center.json 变得合法
  2. 修改代码重新编译 Jenkins,关掉这个签名认证 (既然允许自定义 升级信息 地址,又何必非要做 签名认证 呢?)

方法 1 的问题

如果有一天我不使用这个镜像站了,我还得想办法恢复 CA 文件。

并且每次 update-center.json 有变动,我都得重新签名。尽管可以制作或者寻找现有的自动化工具,但是终究需要额外部署一套工具。

方法 2 的问题

每次 Jenkins 版本更新都需要重新编译 Jenkins,着实麻烦。

更好的办法

我想到了一个更好的办法,使用 Java Agent 机制,在运行时覆盖掉 Jenkins 签名验证方法,让它跳过实际的签名验证,永远返回正确。

这样即便是 Jenkins 版本更新,只要 升级信息 签名验证代码流程不变,这个方法就可以一直有效。

实施流程

什么是 Java Agent

Java Agent 通过在 Java 命令上添加参数 -javaagent:XXXXXX.jar 来启动,它允许你在主类之外,额外加载一个 Jar 包,并提供机制,允许你在类加载时,修改类的字节码。

通过 Java Agent 机制,可以在不修改源代码的情况下,在运行时修改 Java 程序。

定位 Jenkins 代码

简要查阅了 Jenkins 的源代码,定位到了 Jenkins 中,负责校验升级信息签名的方法来自 hudson.model.UpdateSite 类的 verifySignature 方法

    /**
     * Verifies the signature in the update center data file.
     */
    private FormValidation verifySignature(JSONObject o) throws IOException {
   
        return getJsonSignatureValidator().verifySignature(o);
    }

参见 https://github.com/jenkinsci/jenkins/blob/6d6c2793e41539c214241cc49df6515ec0395ff4/core/src/main/java/hudson/model/UpdateSite.java#L267

我们的目标是,将这个方法的代码体,修改成如下内容

return FormValidation.ok();

这样,修改后的方法,永远会返回校验正常。

编写 Java Agent

知道了要修改什么,就可以开始编写 Java Agent 了。

我们选用 javassist 这个库,这是一个 IBM 推出的库,可以便捷地修改 Java 类字节码。

创建 Maven 工程

首先我们创建一个 Maven 工程,和常见的工程类似,但是 Pom 文件的设置有些许区别:

<!-- 略去了不重要的内容 -->
    <dependencies>
        <!-- 引入 javassist 包 -->
        <dependency>
            <groupId>org.javassist</groupId>
            
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码农炎可

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值