<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet href="https://blog.kali-team.cn/feed_style.xsl" type="text/xsl"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <tabi:metadata xmlns:tabi="https://github.com/welpo/tabi">
        <tabi:base_url>https://blog.kali-team.cn</tabi:base_url>
        <tabi:separator>
            •
        </tabi:separator>
        <tabi:about_feeds>
            这是Web Feed，又称为Atom Feed，把现在的网址复制到新闻阅读器即可订阅本站文章。造访「About Feeds」来了解更多资讯。
        </tabi:about_feeds>
        <tabi:visit_the_site>
            造访网站
        </tabi:visit_the_site>
        <tabi:recent_posts>
            近期文章
        </tabi:recent_posts>
        <tabi:last_updated_on>
            更新于 $DATE
        </tabi:last_updated_on>
        <tabi:default_theme></tabi:default_theme>
        <tabi:post_listing_date>date</tabi:post_listing_date>
        <tabi:current_section>sonarqube</tabi:current_section>
    </tabi:metadata><link rel="extra-stylesheet" href="https://blog.kali-team.cn/skins/arch.css?h=8b651815fde702215b07" /><title>Kali-Team - sonarqube</title>
        <subtitle>三米前有蕉皮的博客</subtitle>
    <link href="https://blog.kali-team.cn/tags/sonarqube/atom.xml" rel="self" type="application/atom+xml"/>
    <link href="https://blog.kali-team.cn/tags/sonarqube/" rel="alternate" type="text/html"/>
    <generator uri="https://www.getzola.org/">Zola</generator><updated>2026-10-18T00:00:00+00:00</updated><id>https://blog.kali-team.cn/tags/sonarqube/atom.xml</id><entry xml:lang="en">
        <title>安全开发-SonarQube</title>
        <published>2026-10-18T00:00:00+00:00</published>
        <updated>2026-10-18T00:00:00+00:00</updated>
        <author>
            <name>三米前有蕉皮</name>
        </author>
        <link rel="alternate" href="https://blog.kali-team.cn/blog/2026/09/安全开发-SonarQube/" type="text/html"/>
        <id>https://blog.kali-team.cn/blog/2026/09/安全开发-SonarQube/</id>
        
            <content type="html">&lt;h2 id=&quot;qian-yan&quot;&gt;&lt;a class=&quot;header-anchor no-hover-padding&quot; href=&quot;#qian-yan&quot; aria-label=&quot;Anchor link for: qian-yan&quot;&gt;&lt;span class=&quot;link-icon&quot; aria-hidden=&quot;true&quot;&gt;&lt;/span&gt;&lt;/a&gt;
前言&lt;/h2&gt;
&lt;p&gt;Rancher 集群、Gitea 代码与流水线、Nexus 制品源就位之后，还差一环：&lt;strong&gt;你自己写的代码&lt;/strong&gt;有没有 bug、有没有安全漏洞、有没有难维护的“坏味道“——这是 &lt;strong&gt;SonarQube&lt;/strong&gt; 的活。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;SonarQube&lt;/strong&gt; 是 SonarSource 公司的开源代码质量平台：Web 面板（下称 Server）展示每个项目代码的健康状况，并自带&lt;strong&gt;质量门禁&lt;/strong&gt;机制。本文做三件事：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;搭建&lt;/strong&gt;：Rancher + 官方 Helm chart 部署，重点两件事——内网&lt;strong&gt;自签 CA 证书&lt;/strong&gt;的信任（&lt;code&gt;caCerts&lt;/code&gt;）、&lt;strong&gt;Gitea OIDC 单点登录&lt;/strong&gt;接入；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;使用&lt;/strong&gt;：手动创建项目、创建 token、看懂面板数据；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CI/CD 联动&lt;/strong&gt;：把 &lt;code&gt;sonarqube.yaml&lt;/code&gt; 流水线逐段拆掉，让每次推送 / PR 自动做一遍 &lt;strong&gt;SAST（静态应用安全测试）&lt;/strong&gt;——不运行代码、只“读“代码就能发现问题。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;1-bei-jing-gai-nian-sonarqube-sao-shen-me&quot;&gt;&lt;a class=&quot;header-anchor no-hover-padding&quot; href=&quot;#1-bei-jing-gai-nian-sonarqube-sao-shen-me&quot; aria-label=&quot;Anchor link for: 1-bei-jing-gai-nian-sonarqube-sao-shen-me&quot;&gt;&lt;span class=&quot;link-icon&quot; aria-hidden=&quot;true&quot;&gt;&lt;/span&gt;&lt;/a&gt;
1 背景概念：SonarQube 扫什么&lt;/h2&gt;
&lt;h3 id=&quot;1-1-sast-bu-yun-xing-dai-ma-zhi-du-dai-ma-jiu-fa-xian-wen-ti&quot;&gt;&lt;a class=&quot;header-anchor no-hover-padding&quot; href=&quot;#1-1-sast-bu-yun-xing-dai-ma-zhi-du-dai-ma-jiu-fa-xian-wen-ti&quot; aria-label=&quot;Anchor link for: 1-1-sast-bu-yun-xing-dai-ma-zhi-du-dai-ma-jiu-fa-xian-wen-ti&quot;&gt;&lt;span class=&quot;link-icon&quot; aria-hidden=&quot;true&quot;&gt;&lt;/span&gt;&lt;/a&gt;
1.1 SAST：不运行代码，只“读“代码就发现问题&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;静态分析&lt;/strong&gt;：程序不运行，工具把源代码解析成语法结构，再按一套规则库找出潜在问题，业内把“静态应用安全测试“缩写成 &lt;strong&gt;SAST&lt;/strong&gt;。一次 SonarQube 扫描输出三类问题，优先级从高到低：&lt;/p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;类型&lt;/th&gt;&lt;th&gt;英文&lt;/th&gt;&lt;th&gt;是什么&lt;/th&gt;&lt;th&gt;例子&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;漏洞&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Vulnerability&lt;/td&gt;&lt;td&gt;安全洞，攻击者可能利用&lt;/td&gt;&lt;td&gt;SQL 注入：把用户输入直接拼进 SQL 语句&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;缺陷&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Bug&lt;/td&gt;&lt;td&gt;逻辑错误，运行时会出错或行为不对&lt;/td&gt;&lt;td&gt;空指针：一个可能为空的对象没检查就直接用&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;坏味道&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Code Smell&lt;/td&gt;&lt;td&gt;不致错但让代码难读难维护&lt;/td&gt;&lt;td&gt;一个 300 行的函数、魔法数字满天飞&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;漏洞第一优先（攻击者正盯着），缺陷其次（程序会坏），坏味道是“健康管理“（慢慢清，别堆积）。有些问题只有运行时才暴露——那要靠测试或动态扫描。&lt;/p&gt;
&lt;h3 id=&quot;1-2-zhi-liang-men-jin-sao-miao-de-pan-ding-biao-zhun&quot;&gt;&lt;a class=&quot;header-anchor no-hover-padding&quot; href=&quot;#1-2-zhi-liang-men-jin-sao-miao-de-pan-ding-biao-zhun&quot; aria-label=&quot;Anchor link for: 1-2-zhi-liang-men-jin-sao-miao-de-pan-ding-biao-zhun&quot;&gt;&lt;span class=&quot;link-icon&quot; aria-hidden=&quot;true&quot;&gt;&lt;/span&gt;&lt;/a&gt;
1.2 质量门禁：扫描的判定标准&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;质量门禁（Quality Gate）&lt;/strong&gt; 是一组阈值（例如“新增漏洞 = 0、覆盖率 ≥ X%“），每次扫描后自动判定 &lt;strong&gt;Passed / Failed&lt;/strong&gt;。流水线里门禁还能“卡“住流程：扫描不通过就不许合并 / 发布（本环境目前只到“扫描出报告”，尚未接成卡点，详见“常见问题与坑“）。&lt;/p&gt;
&lt;h3 id=&quot;1-3-server-yu-scanner-de-fen-gong-shui-cun-jie-guo-shui-gan-huo&quot;&gt;&lt;a class=&quot;header-anchor no-hover-padding&quot; href=&quot;#1-3-server-yu-scanner-de-fen-gong-shui-cun-jie-guo-shui-gan-huo&quot; aria-label=&quot;Anchor link for: 1-3-server-yu-scanner-de-fen-gong-shui-cun-jie-guo-shui-gan-huo&quot;&gt;&lt;span class=&quot;link-icon&quot; aria-hidden=&quot;true&quot;&gt;&lt;/span&gt;&lt;/a&gt;
1.3 Server 与 Scanner 的分工：谁存结果、谁干活&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Server（服务端）&lt;/strong&gt;：Web 服务（本环境 &lt;code&gt;sonarqube.kali-team.internal&lt;/code&gt;），存分析结果，提供面板、门禁判定和权限管理。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SonarScanner CLI（扫描器）&lt;/strong&gt;：跑在 CI 侧的命令行工具，&lt;strong&gt;用 Java 写&lt;/strong&gt;（需要 &lt;strong&gt;JRE&lt;/strong&gt; 运行），按配置读代码、做分析、把结果传给 Server。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;两半靠一个唯一标识对上号——仓库根目录的 &lt;code&gt;sonar-project.properties&lt;/code&gt; 文件：&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;ini&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;sonar.projectKey&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; =&lt;/span&gt;&lt;span&gt; example        &lt;/span&gt;&lt;span class=&quot;z-4 z-i&quot;&gt;# 项目唯一标识：必须与 SonarQube Server 上创建的项目 Key 完全一致&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;sonar.projectName&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; =&lt;/span&gt;&lt;span&gt; 项目例子       &lt;/span&gt;&lt;span class=&quot;z-4 z-i&quot;&gt;# 显示名称：面板上看到的名字&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;sonar.sources&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; =&lt;/span&gt;&lt;span&gt; .                 &lt;/span&gt;&lt;span class=&quot;z-4 z-i&quot;&gt;# 扫描范围：扫哪些目录（这里是整个仓库）&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;JRE 这里要记一下&lt;/strong&gt;：流水线跑在内网任务容器里、到不了公网下载 JRE，所以任务镜像&lt;strong&gt;预装了 JRE&lt;/strong&gt;；Scanner 本体很小（约 9MB），从 Nexus 的 &lt;code&gt;sonar-scanner-cli&lt;/code&gt; 仓库下载。&lt;/p&gt;
&lt;h3 id=&quot;1-4-sast-de-ding-wei-dui-zhao-sca-yu-dast&quot;&gt;&lt;a class=&quot;header-anchor no-hover-padding&quot; href=&quot;#1-4-sast-de-ding-wei-dui-zhao-sca-yu-dast&quot; aria-label=&quot;Anchor link for: 1-4-sast-de-ding-wei-dui-zhao-sca-yu-dast&quot;&gt;&lt;span class=&quot;link-icon&quot; aria-hidden=&quot;true&quot;&gt;&lt;/span&gt;&lt;/a&gt;
1.4 SAST 的定位：对照 SCA 与 DAST&lt;/h3&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;/th&gt;&lt;th&gt;SAST（SonarQube）&lt;/th&gt;&lt;th&gt;SCA（Dependency-Track）&lt;/th&gt;&lt;th&gt;DAST（动态，本环境未部署）&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;看什么&lt;/td&gt;&lt;td&gt;&lt;strong&gt;你自己写的代码&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;你引用的第三方依赖&lt;/strong&gt;的已知漏洞&lt;/td&gt;&lt;td&gt;运行中的系统（黑盒发请求探测）&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;输入&lt;/td&gt;&lt;td&gt;源代码&lt;/td&gt;&lt;td&gt;SBOM（软件物料清单）&lt;/td&gt;&lt;td&gt;HTTP 请求 / 响应&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;发现什么&lt;/td&gt;&lt;td&gt;注入风险、逻辑缺陷、坏味道&lt;/td&gt;&lt;td&gt;依赖组件的 CVE / KEV&lt;/td&gt;&lt;td&gt;运行服务的真实攻击面&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;典型动作&lt;/td&gt;&lt;td&gt;修代码&lt;/td&gt;&lt;td&gt;升级依赖版本&lt;/td&gt;&lt;td&gt;修配置 / 堵接口&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;SonarQube 看代码，Dependency-Track 看依赖&lt;/strong&gt;。在流水线里两者是各自独立的 workflow：&lt;code&gt;sonarqube.yaml&lt;/code&gt; 扫自己的代码，&lt;code&gt;dependency-track.yaml&lt;/code&gt; 传 SBOM 查依赖——互不干扰，合起来构成“代码 + 依赖“两道安检。&lt;/p&gt;
&lt;h2 id=&quot;2-da-jian&quot;&gt;&lt;a class=&quot;header-anchor no-hover-padding&quot; href=&quot;#2-da-jian&quot; aria-label=&quot;Anchor link for: 2-da-jian&quot;&gt;&lt;span class=&quot;link-icon&quot; aria-hidden=&quot;true&quot;&gt;&lt;/span&gt;&lt;/a&gt;
2 搭建&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;版本：SonarQube Community 26.7.0.124771 / chart 2026.4.1，经 Rancher + 官方 Helm chart 部署。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;2-1-zong-ti-si-lu-yao-na-xie-zu-jian&quot;&gt;&lt;a class=&quot;header-anchor no-hover-padding&quot; href=&quot;#2-1-zong-ti-si-lu-yao-na-xie-zu-jian&quot; aria-label=&quot;Anchor link for: 2-1-zong-ti-si-lu-yao-na-xie-zu-jian&quot;&gt;&lt;span class=&quot;link-icon&quot; aria-hidden=&quot;true&quot;&gt;&lt;/span&gt;&lt;/a&gt;
2.1 总体思路：要哪些组件&lt;/h3&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;组件&lt;/th&gt;&lt;th&gt;本环境的来源&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;SonarQube 本体&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;官方 chart &lt;code&gt;sonarqube&lt;/code&gt;（chart 2026.4.1，对应 &lt;strong&gt;Community 版 26.7.0.124771&lt;/strong&gt; 构建），在 Rancher 界面里安装&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;数据库&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;复用&lt;/strong&gt; Nexus 安装时带出来的共享 PostgreSQL（middleware 命名空间），只为它建一个专属库 &lt;code&gt;sonarqube&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;CA 证书&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;kali-team-root-ca.crt&lt;/code&gt;——内网根证书，搭集群时就已获取&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Ingress&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;域名 &lt;code&gt;sonarqube.kali-team.internal&lt;/code&gt;，TLS 由集群网关统一终结&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;chart 来自 SonarSource 官方 chart 仓库（https://sonarsource.github.io/helm-chart-sonarqube）。&lt;strong&gt;Community（社区版）免费，Enterprise 等是付费版&lt;/strong&gt;——本环境用社区版。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://blog.kali-team.cn/blog/2026/09/%E5%AE%89%E5%85%A8%E5%BC%80%E5%8F%91-SonarQube/sonarqube-rancher-chart.png&quot; alt=&quot;Rancher 里的 sonarqube chart&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;图 1：Rancher 界面里的 sonarqube chart（2026.4.1），Community 版 26.7.0.124771——本环境从这里安装&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;这次部署有两处“内网特色“（官方文档示例里不会强调的）：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;证书全是自签的&lt;/strong&gt;：SonarQube 的 OIDC 登录要连 Gitea 的 https 端点，不信任内网 CA 就会握手失败——chart 专门提供了 &lt;code&gt;caCerts&lt;/code&gt; 配置来覆盖默认 CA 库；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;数据库不随 chart 带&lt;/strong&gt;：复用 middleware 命名空间的共享 PostgreSQL，用 &lt;code&gt;jdbcOverwrite&lt;/code&gt; 指过去。&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;2-2-zai-gong-xiang-postgresql-shang-jian-sonarqube-ku&quot;&gt;&lt;a class=&quot;header-anchor no-hover-padding&quot; href=&quot;#2-2-zai-gong-xiang-postgresql-shang-jian-sonarqube-ku&quot; aria-label=&quot;Anchor link for: 2-2-zai-gong-xiang-postgresql-shang-jian-sonarqube-ku&quot;&gt;&lt;span class=&quot;link-icon&quot; aria-hidden=&quot;true&quot;&gt;&lt;/span&gt;&lt;/a&gt;
2.2 在共享 PostgreSQL 上建 sonarqube 库&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;kubectl&lt;/code&gt; 本身没有 psql 客户端，所以临时起一个 &lt;strong&gt;pod&lt;/strong&gt;（&lt;code&gt;--rm&lt;/code&gt; 表示退出后自动删除）当“跳板“，在里面执行建库 SQL：&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4 z-i&quot;&gt;# 从现成的 secret 读取共享 PostgreSQL 的超级用户密码&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4 z-i&quot;&gt;#    secret 是 k8s 里的凭据对象，密码以 base64 编码存放，管道里 base64 -d 解码&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-9&quot;&gt;export&lt;/span&gt;&lt;span&gt; POSTGRES_PASSWORD&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;z-4&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;z-3 z-i&quot;&gt;kubectl&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; get secret --namespace middleware postgresql&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-7&quot;&gt;  -o jsonpath=&amp;quot;{.data.postgres-password}&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; |&lt;/span&gt;&lt;span class=&quot;z-3 z-i&quot;&gt; base64&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; -d&lt;/span&gt;&lt;span class=&quot;z-4&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4 z-i&quot;&gt;# 起一个临时 postgresql-client pod 执行&amp;quot;建库&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4 z-i&quot;&gt;#    --rm              退出后自动删 pod&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4 z-i&quot;&gt;#    --restart=&amp;#39;Never&amp;#39; 不重启&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4 z-i&quot;&gt;#    --tty -i          分配终端、接标准输入&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4 z-i&quot;&gt;#    --command -- ...  覆盖容器默认启动命令，直接跑 psql&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3 z-i&quot;&gt;kubectl&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; run postgresql-client --rm --tty -i --restart=&amp;#39;Never&amp;#39;&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-7&quot;&gt;  --namespace middleware&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-7&quot;&gt;  --image registry-1.docker.io/bitnami/postgresql:latest&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-7&quot;&gt;  --env=&amp;quot;PGPASSWORD=&lt;/span&gt;&lt;span&gt;$POSTGRES_PASSWORD&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-7&quot;&gt;  --command -- psql --host postgresql -U postgres -d postgres -p&lt;/span&gt;&lt;span class=&quot;z-14&quot;&gt; 5432&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-7&quot;&gt;  -c &amp;quot;CREATE DATABASE sonarqube;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;密码从集群现成的 secret 读、不手敲（不进 shell 历史，文内占位）；&lt;code&gt;postgresql&lt;/code&gt; 是共享库在集群内的服务名，&lt;code&gt;5432&lt;/code&gt; 是 PostgreSQL 默认端口。实际输出：&lt;code&gt;CREATE DATABASE&lt;/code&gt; 一行成功，临时 pod 自动删除。&lt;/p&gt;
&lt;h3 id=&quot;2-3-ba-nei-wang-ca-zheng-shu-fang-jin-secret&quot;&gt;&lt;a class=&quot;header-anchor no-hover-padding&quot; href=&quot;#2-3-ba-nei-wang-ca-zheng-shu-fang-jin-secret&quot; aria-label=&quot;Anchor link for: 2-3-ba-nei-wang-ca-zheng-shu-fang-jin-secret&quot;&gt;&lt;span class=&quot;link-icon&quot; aria-hidden=&quot;true&quot;&gt;&lt;/span&gt;&lt;/a&gt;
2.3 把内网 CA 证书放进 Secret&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;为什么需要&lt;/strong&gt;：内网的证书都是&lt;strong&gt;自签&lt;/strong&gt;的——公网体系里证书由人人信任的公共 CA 签发，内网里大家信任的是自建 CA。SonarQube（Java 程序）配置 OIDC 登录时要&lt;strong&gt;主动连 Gitea 的 https 端点&lt;/strong&gt;，它会用自己的 &lt;strong&gt;CA 信任库&lt;/strong&gt;校验对方证书——内网 CA 不在库里，握手直接被拒（证书错误）。&lt;/p&gt;
&lt;p&gt;官方 Helm chart 文档有专门一节讲这个场景（“Use custom cacerts”，就是针对&lt;strong&gt;离线环境 / 内部工具 / 自签证书&lt;/strong&gt;说的）：思路是把要信任的证书先放进一个 k8s &lt;strong&gt;Secret&lt;/strong&gt;，再用 chart 的 &lt;code&gt;caCerts&lt;/code&gt; 配置指向它，&lt;strong&gt;覆盖默认 CA 库&lt;/strong&gt;：&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4 z-i&quot;&gt;# chart 文档的示例写法（本环境 Secret 名用 kali-team-root-ca）&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; v1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; Secret&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;  name&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; my-cacerts&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;stringData&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;  cert-1.crt&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt; |&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-7&quot;&gt;    xxxxxxxxxxxxxxxxxxxxxxx   # 证书的 PEM 内容&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;本环境实际执行（证书文件是搭集群时已获取的根证书，放在集群节点上）：&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3 z-i&quot;&gt;kubectl&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; create secret generic kali-team-root-ca&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-7&quot;&gt;  -n sonarqube&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-7&quot;&gt;  --from-file=kali-team-root-ca.crt=kali-team-root-ca.crt&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4 z-i&quot;&gt;# 输出：secret/kali-team-root-ca created&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;怎么验证&lt;/strong&gt;：Secret 建好只是第一步，真正的验证在 SonarQube 起来之后——OIDC 登录走通，就说明服务端成功连上了 Gitea 的 https 端点且证书校验通过。&lt;/p&gt;
&lt;h3 id=&quot;2-4-helm-values-gai-dong&quot;&gt;&lt;a class=&quot;header-anchor no-hover-padding&quot; href=&quot;#2-4-helm-values-gai-dong&quot; aria-label=&quot;Anchor link for: 2-4-helm-values-gai-dong&quot;&gt;&lt;span class=&quot;link-icon&quot; aria-hidden=&quot;true&quot;&gt;&lt;/span&gt;&lt;/a&gt;
2.4 Helm values 改动&lt;/h3&gt;
&lt;p&gt;部署时改动的 values（chart 的部署参数；diff 形式，&lt;code&gt;+&lt;/code&gt; 为相对 chart 默认值新增 / 改动的行）：&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;diff&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4&quot;&gt;@@&lt;/span&gt;&lt;span&gt; caCerts&lt;/span&gt;&lt;span class=&quot;z-4&quot;&gt; @@&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; caCerts:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;z-11&quot;&gt;  enabled: false&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt;  enabled: true&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt;  secret: kali-team-root-ca&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4&quot;&gt;@@&lt;/span&gt;&lt;span&gt; community&lt;/span&gt;&lt;span class=&quot;z-4&quot;&gt; @@&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; community:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   buildNumber: 26.7.0.124771&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;z-11&quot;&gt;  enabled: false&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt;  enabled: true&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4&quot;&gt;@@&lt;/span&gt;&lt;span&gt; deploymentStrategy&lt;/span&gt;&lt;span class=&quot;z-4&quot;&gt; @@&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; deploymentStrategy:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;z-11&quot;&gt;  type: Recreate&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt;  type: RollingUpdate&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt;  maxSurge: 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt;  maxUnavailable: 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4&quot;&gt;@@&lt;/span&gt;&lt;span&gt; ingress&lt;/span&gt;&lt;span class=&quot;z-4&quot;&gt; @@&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; ingress:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;z-11&quot;&gt;  enabled: false&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt;  enabled: true&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   hosts:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;z-11&quot;&gt;    - name: sonarqube.your-org.com&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt;    - name: sonarqube.kali-team.internal&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4&quot;&gt;@@&lt;/span&gt;&lt;span&gt; jdbcOverwrite&lt;/span&gt;&lt;span class=&quot;z-4&quot;&gt; @@&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; jdbcOverwrite:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;z-11&quot;&gt;  enabled: false&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;z-11&quot;&gt;  jdbcPassword: sonarPass&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;z-11&quot;&gt;  jdbcUrl: jdbc:postgresql://myPostgres/myDatabase&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;z-11&quot;&gt;  jdbcUsername: sonarUser&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt;  enabled: true&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt;  jdbcPassword: &amp;lt;POSTGRES_PASSWORD&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt;  jdbcUrl: jdbc:postgresql://postgresql.middleware.svc.cluster.local:5432/sonarqube&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt;  jdbcUsername: postgres&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4&quot;&gt;@@&lt;/span&gt;&lt;span&gt; persistence&lt;/span&gt;&lt;span class=&quot;z-4&quot;&gt; @@&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; persistence:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;z-11&quot;&gt;  enabled: false&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt;  enabled: true&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;z-11&quot;&gt;  size: 5Gi&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt;  size: 10Gi&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4&quot;&gt;@@&lt;/span&gt;&lt;span&gt; resources.limits&lt;/span&gt;&lt;span class=&quot;z-4&quot;&gt; @@&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; resources:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   limits:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     cpu: 800m&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;z-11&quot;&gt;    memory: 6144M&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt;    memory: 4196M&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   requests:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     cpu: 400m&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4&quot;&gt;@@&lt;/span&gt;&lt;span&gt; 末尾新增&lt;/span&gt;&lt;span class=&quot;z-4&quot;&gt; @@&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt;monitoringPasscode: community&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;配置&lt;/th&gt;&lt;th&gt;原因&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;caCerts&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;enabled: true&lt;/code&gt; + &lt;code&gt;secret&lt;/code&gt; 指向前面建好的 &lt;code&gt;kali-team-root-ca&lt;/code&gt;——让 SonarQube 信任内网 CA；验证方式：OIDC 登录可用&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;community&lt;/code&gt;&lt;/td&gt;&lt;td&gt;chart 同时支持 Community（免费）与 Enterprise（付费），&lt;code&gt;enabled: true&lt;/code&gt; 选社区版；&lt;code&gt;buildNumber&lt;/code&gt; 钉住具体构建号 &lt;code&gt;26.7.0.124771&lt;/code&gt;（与图 1 chart 页一致，版本钉死避免意外漂移）&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;deploymentStrategy&lt;/code&gt;&lt;/td&gt;&lt;td&gt;chart 默认 &lt;code&gt;Recreate&lt;/code&gt;（先删旧 pod 再起新 pod——中间有短暂“服务不可用“窗口）；改成 &lt;code&gt;RollingUpdate&lt;/code&gt;（滚动更新：先起新的、就绪后再删旧的），&lt;code&gt;maxSurge: 1&lt;/code&gt;（更新期间最多多出一个新 pod）、&lt;code&gt;maxUnavailable: 0&lt;/code&gt;（新的没就绪前旧的不下线，服务不断）&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;ingress&lt;/code&gt;&lt;/td&gt;&lt;td&gt;启用并填域名 &lt;code&gt;sonarqube.kali-team.internal&lt;/code&gt;；流量经集群统一网关终结 TLS，证书由内网 CA 签发——这也是“浏览器直接打开域名就是绿锁“的原因&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;jdbcOverwrite&lt;/code&gt;&lt;/td&gt;&lt;td&gt;SonarQube 的分析数据必须落 PostgreSQL，chart 默认的 &lt;code&gt;jdbcUrl&lt;/code&gt; 是占位符 &lt;code&gt;myPostgres/myDatabase&lt;/code&gt;——必须覆盖：&lt;code&gt;enabled: true&lt;/code&gt;，URL 指向共享库的集群内地址 &lt;code&gt;postgresql.middleware.svc.cluster.local:5432&lt;/code&gt;，库名 &lt;code&gt;sonarqube&lt;/code&gt;（2.2 建的）、用户名 &lt;code&gt;postgres&lt;/code&gt;（本环境直接用共享库超级用户）、密码用 2.2 读到的值（占位）。&lt;strong&gt;整篇搭建里“数据放哪“只由这一段决定&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;persistence&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;enabled: true&lt;/code&gt; + &lt;code&gt;10Gi&lt;/code&gt;——申请一块 PVC（Persistent Volume Claim，跨重启不丢的“磁盘“）存 SonarQube 自身的文件类数据，pod 重建不丢；&lt;code&gt;storageClass&lt;/code&gt; 不指定，用集群默认&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;resources.limits.memory&lt;/code&gt;&lt;/td&gt;&lt;td&gt;思路是“&lt;strong&gt;内存给多点，java 开发的，避免执行任务的时候 OOM&lt;/strong&gt;“（OOM = Out Of Memory，内存不够被系统杀掉）。SonarQube 是 Java 服务，分析任务吃内存，上限给低了 pod 会被 OOM 杀掉反复重启。chart 默认 6144M，本环境最终值 4196M（约 4.1Gi）——这台小规格节点的实际内存是上限&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;monitoringPasscode&lt;/code&gt;&lt;/td&gt;&lt;td&gt;chart 必填参数，&lt;strong&gt;需要指定添加&lt;/strong&gt;，本环境对应社区版填 &lt;code&gt;community&lt;/code&gt;；不填 chart 校验不过&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;其余 values 保持 chart 默认（安全上下文、探针、日志级别等），此处不逐项展开。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;2-5-an-zhuang-yu-yan-zheng&quot;&gt;&lt;a class=&quot;header-anchor no-hover-padding&quot; href=&quot;#2-5-an-zhuang-yu-yan-zheng&quot; aria-label=&quot;Anchor link for: 2-5-an-zhuang-yu-yan-zheng&quot;&gt;&lt;span class=&quot;link-icon&quot; aria-hidden=&quot;true&quot;&gt;&lt;/span&gt;&lt;/a&gt;
2.5 安装与验证&lt;/h3&gt;
&lt;p&gt;在图 1 的页面点部署（Deploy），等 pod 就绪。验证两层：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;pod 层&lt;/strong&gt;：Rancher 工作负载页里 sonarqube 的 pod 状态 &lt;code&gt;Running&lt;/code&gt;，重启次数稳定；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;服务层&lt;/strong&gt;：浏览器打开 &lt;code&gt;https://sonarqube.kali-team.internal&lt;/code&gt; 出现登录页（浏览器信任内网 CA、证书有效——这一步同时验证了 ingress 与域名证书）。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;到这里搭建完成，进入网页做“首次登录与初始配置“。&lt;/p&gt;
&lt;h2 id=&quot;3-shou-ci-deng-lu-yu-chu-shi-pei-zhi&quot;&gt;&lt;a class=&quot;header-anchor no-hover-padding&quot; href=&quot;#3-shou-ci-deng-lu-yu-chu-shi-pei-zhi&quot; aria-label=&quot;Anchor link for: 3-shou-ci-deng-lu-yu-chu-shi-pei-zhi&quot;&gt;&lt;span class=&quot;link-icon&quot; aria-hidden=&quot;true&quot;&gt;&lt;/span&gt;&lt;/a&gt;
3 首次登录与初始配置&lt;/h2&gt;
&lt;h3 id=&quot;3-1-yong-mo-ren-admin-zhang-hao-deng-lu&quot;&gt;&lt;a class=&quot;header-anchor no-hover-padding&quot; href=&quot;#3-1-yong-mo-ren-admin-zhang-hao-deng-lu&quot; aria-label=&quot;Anchor link for: 3-1-yong-mo-ren-admin-zhang-hao-deng-lu&quot;&gt;&lt;span class=&quot;link-icon&quot; aria-hidden=&quot;true&quot;&gt;&lt;/span&gt;&lt;/a&gt;
3.1 用默认 admin 账号登录&lt;/h3&gt;
&lt;p&gt;全新 SonarQube 内置一个管理员账号：用户名 &lt;code&gt;admin&lt;/code&gt;，&lt;strong&gt;默认密码 &lt;code&gt;admin&lt;/code&gt;&lt;/strong&gt;。登录后第一眼看到的是“创建项目“引导页（图 2——此时界面还是英文）。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;默认密码务必在首次登录后修改&lt;/strong&gt;，新值按团队凭据规范存放（文章只占位，不落明文）。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img src=&quot;https://blog.kali-team.cn/blog/2026/09/%E5%AE%89%E5%85%A8%E5%BC%80%E5%8F%91-SonarQube/sonarqube-first-login.png&quot; alt=&quot;首次登录后的创建项目引导页&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;图 2：初始 admin/admin 登录后看到的创建项目引导页（此时界面还是英文）&lt;/em&gt;&lt;/p&gt;
&lt;h3 id=&quot;3-2-an-zhuang-zhong-wen-yu-yan-bao-yu-oidc-cha-jian&quot;&gt;&lt;a class=&quot;header-anchor no-hover-padding&quot; href=&quot;#3-2-an-zhuang-zhong-wen-yu-yan-bao-yu-oidc-cha-jian&quot; aria-label=&quot;Anchor link for: 3-2-an-zhuang-zhong-wen-yu-yan-bao-yu-oidc-cha-jian&quot;&gt;&lt;span class=&quot;link-icon&quot; aria-hidden=&quot;true&quot;&gt;&lt;/span&gt;&lt;/a&gt;
3.2 安装中文语言包与 OIDC 插件&lt;/h3&gt;
&lt;p&gt;SonarQube 的扩展机制是 &lt;strong&gt;Marketplace（插件市场）&lt;/strong&gt;：进 &lt;strong&gt;Administration → Marketplace&lt;/strong&gt; 搜索、安装，状态 &lt;code&gt;Install Pending&lt;/code&gt;（等待重启生效），&lt;strong&gt;重启后自动加载&lt;/strong&gt;。要装两个：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;中文语言包&lt;/strong&gt;：界面变中文（后面的截图都是中文界面）；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;OpenID Connect 插件&lt;/strong&gt;：&lt;strong&gt;OIDC&lt;/strong&gt; 是建立在 OAuth2 之上的标准身份登录协议，实现“一次登录、处处通行“——SonarQube 的 OIDC 登录模块不是天生就有的，先装插件（第 4 章）。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&quot;https://blog.kali-team.cn/blog/2026/09/%E5%AE%89%E5%85%A8%E5%BC%80%E5%8F%91-SonarQube/sonarqube-plugin-chinese.png&quot; alt=&quot;Marketplace 安装中文语言包&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;图 3：Marketplace 里的中文语言包，状态 Install Pending（等待重启生效）&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://blog.kali-team.cn/blog/2026/09/%E5%AE%89%E5%85%A8%E5%BC%80%E5%8F%91-SonarQube/sonarqube-plugin-oidc.png&quot; alt=&quot;Marketplace 安装 OpenID Connect 插件&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;图 4：Marketplace 里的 OpenID Connect（OIDC）插件，同样 Install Pending&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;重启后引导页变成中文界面：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://blog.kali-team.cn/blog/2026/09/%E5%AE%89%E5%85%A8%E5%BC%80%E5%8F%91-SonarQube/sonarqube-onboarding-chinese.png&quot; alt=&quot;中文界面生效后的引导页&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;图 5：服务重启后语言包生效，引导页已是中文&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&quot;4-pei-zhi-oidc-deng-lu-yong-gitea-zhang-hao-jin-sonarqube&quot;&gt;&lt;a class=&quot;header-anchor no-hover-padding&quot; href=&quot;#4-pei-zhi-oidc-deng-lu-yong-gitea-zhang-hao-jin-sonarqube&quot; aria-label=&quot;Anchor link for: 4-pei-zhi-oidc-deng-lu-yong-gitea-zhang-hao-jin-sonarqube&quot;&gt;&lt;span class=&quot;link-icon&quot; aria-hidden=&quot;true&quot;&gt;&lt;/span&gt;&lt;/a&gt;
4 配置 OIDC 登录：用 Gitea 账号进 SonarQube&lt;/h2&gt;
&lt;h3 id=&quot;4-1-wei-shen-me-neng-fu-yong-gitea-dan-dian-deng-lu&quot;&gt;&lt;a class=&quot;header-anchor no-hover-padding&quot; href=&quot;#4-1-wei-shen-me-neng-fu-yong-gitea-dan-dian-deng-lu&quot; aria-label=&quot;Anchor link for: 4-1-wei-shen-me-neng-fu-yong-gitea-dan-dian-deng-lu&quot;&gt;&lt;span class=&quot;link-icon&quot; aria-hidden=&quot;true&quot;&gt;&lt;/span&gt;&lt;/a&gt;
4.1 为什么能复用 Gitea 单点登录&lt;/h3&gt;
&lt;p&gt;Gitea 内置了 &lt;strong&gt;OIDC 提供方（IdP）&lt;/strong&gt;：各平台在 Gitea 组织里建一个 &lt;strong&gt;OAuth2 应用&lt;/strong&gt;（客户端），拿到一对 Client ID/Secret 填进自己，之后开发者用 Gitea 账号登录一次、进所有平台都不用再输密码。SonarQube 的接入方式与其它平台相同：Gitea 侧建应用、SonarQube 侧填设置。&lt;/p&gt;
&lt;h3 id=&quot;4-2-xian-kan-shuo-ming-shu-oidc-fa-xian-duan-dian&quot;&gt;&lt;a class=&quot;header-anchor no-hover-padding&quot; href=&quot;#4-2-xian-kan-shuo-ming-shu-oidc-fa-xian-duan-dian&quot; aria-label=&quot;Anchor link for: 4-2-xian-kan-shuo-ming-shu-oidc-fa-xian-duan-dian&quot;&gt;&lt;span class=&quot;link-icon&quot; aria-hidden=&quot;true&quot;&gt;&lt;/span&gt;&lt;/a&gt;
4.2 先看“说明书“：OIDC 发现端点&lt;/h3&gt;
&lt;p&gt;Gitea 在 &lt;code&gt;https://hub.kali-team.internal/.well-known/openid-configuration&lt;/code&gt; 暴露一份 JSON“说明书“（&lt;strong&gt;发现端点&lt;/strong&gt;）：issuer、各端点地址、支持的 scope 全列在里面——&lt;strong&gt;打开这个链接就知道怎么填了&lt;/strong&gt;：SonarQube 的 OIDC 表单字段基本都能从这份 JSON 里找到对应值。&lt;/p&gt;
&lt;h3 id=&quot;4-3-gitea-ce-chuang-jian-oauth2-ying-yong&quot;&gt;&lt;a class=&quot;header-anchor no-hover-padding&quot; href=&quot;#4-3-gitea-ce-chuang-jian-oauth2-ying-yong&quot; aria-label=&quot;Anchor link for: 4-3-gitea-ce-chuang-jian-oauth2-ying-yong&quot;&gt;&lt;span class=&quot;link-icon&quot; aria-hidden=&quot;true&quot;&gt;&lt;/span&gt;&lt;/a&gt;
4.3 Gitea 侧：创建 OAuth2 应用&lt;/h3&gt;
&lt;p&gt;在 &lt;code&gt;dev-sec-ops&lt;/code&gt; 组织 → &lt;strong&gt;设置 → 应用 → 创建 OAuth2 应用程序&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;应用名称&lt;/strong&gt;：&lt;code&gt;SonarQube&lt;/code&gt;；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;重定向 URL&lt;/strong&gt;：&lt;code&gt;https://sonarqube.kali-team.internal/oauth2/callback/oidc&lt;/code&gt;——SonarQube 侧的固定“回调地址“，OIDC 插件的默认回调，照抄即可；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;客户端类型&lt;/strong&gt;：机密客户端（confidential——能安全保管客户端密钥的客户端，Web 服务属此类）。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;创建后 Gitea 颁发 &lt;strong&gt;Client ID&lt;/strong&gt;（半公开的标识）与 &lt;strong&gt;Client Secret&lt;/strong&gt;（等价于密码），占位 &lt;code&gt;&amp;lt;client-id&amp;gt;&lt;/code&gt; / &lt;code&gt;&amp;lt;client-secret&amp;gt;&lt;/code&gt;，只写进 SonarQube 的 OIDC 设置。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://blog.kali-team.cn/blog/2026/09/%E5%AE%89%E5%85%A8%E5%BC%80%E5%8F%91-SonarQube/gitea-oauth-app-sonarqube.png&quot; alt=&quot;Gitea 组织里的 SonarQube OAuth2 应用&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;图 6：Gitea dev-sec-ops 组织的 OAuth2 应用里创建的 SonarQube 应用：重定向 URL 指向 SonarQube 的 OIDC 回调（Client ID / Secret 已打码）&lt;/em&gt;&lt;/p&gt;
&lt;h3 id=&quot;4-4-sonarqube-ce-tian-oidc-she-zhi&quot;&gt;&lt;a class=&quot;header-anchor no-hover-padding&quot; href=&quot;#4-4-sonarqube-ce-tian-oidc-she-zhi&quot; aria-label=&quot;Anchor link for: 4-4-sonarqube-ce-tian-oidc-she-zhi&quot;&gt;&lt;span class=&quot;link-icon&quot; aria-hidden=&quot;true&quot;&gt;&lt;/span&gt;&lt;/a&gt;
4.4 SonarQube 侧：填 OIDC 设置&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Administration → General Settings → 权限&lt;/strong&gt;（OIDC 插件提供的表单），关键项：&lt;/p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;字段&lt;/th&gt;&lt;th&gt;值&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Issuer（签发方）&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;https://hub.kali-team.internal&lt;/code&gt;——声明“我的 IdP 是 Gitea“，SonarQube 会拿这个地址去自动读取 4.2 的发现端点&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Client ID / Client Secret&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;&amp;lt;client-id&amp;gt;&lt;/code&gt; / &lt;code&gt;&amp;lt;client-secret&amp;gt;&lt;/code&gt;（4.3 创建的应用的身份凭据）&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Scopes&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;openid email profile groups&lt;/code&gt;——&lt;code&gt;openid&lt;/code&gt; 是基础身份（必需）、&lt;code&gt;email&lt;/code&gt; / &lt;code&gt;profile&lt;/code&gt; 是邮箱与资料、&lt;strong&gt;&lt;code&gt;groups&lt;/code&gt; 关键&lt;/strong&gt;：把用户的组信息带进令牌，平台按组授权限&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;签名算法&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;RS256&lt;/code&gt;——Gitea 给令牌签名用的算法（发现端点里能查到），SonarQube 用它验“令牌没被篡改“&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;&lt;img src=&quot;https://blog.kali-team.cn/blog/2026/09/%E5%AE%89%E5%85%A8%E5%BC%80%E5%8F%91-SonarQube/sonarqube-oidc-settings.png&quot; alt=&quot;SonarQube 的 OIDC 设置&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;图 7：SonarQube Administration → General Settings → 权限里的 OIDC 配置：Issuer 指向 hub.kali-team.internal，scopes 为 openid email profile groups（Client ID / Secret 已打码）&lt;/em&gt;&lt;/p&gt;
&lt;h3 id=&quot;4-5-liang-ge-tong-yong-she-zhi&quot;&gt;&lt;a class=&quot;header-anchor no-hover-padding&quot; href=&quot;#4-5-liang-ge-tong-yong-she-zhi&quot; aria-label=&quot;Anchor link for: 4-5-liang-ge-tong-yong-she-zhi&quot;&gt;&lt;span class=&quot;link-icon&quot; aria-hidden=&quot;true&quot;&gt;&lt;/span&gt;&lt;/a&gt;
4.5 两个通用设置&lt;/h3&gt;
&lt;p&gt;同一个 &lt;strong&gt;General Settings&lt;/strong&gt; 页还有两处要看（图 8）：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Server base URL&lt;/strong&gt;：填 &lt;code&gt;https://sonarqube.kali-team.internal&lt;/code&gt;。&lt;strong&gt;配置 Server base URL，不然 OIDC 跳转的时候会默认跳到 localhost&lt;/strong&gt;——OIDC 流程里 SonarQube 需要知道“我对外叫什么地址“，不配就默认 &lt;code&gt;localhost&lt;/code&gt;，用户从 Gitea 授权回来后会被送回自己电脑，登录闭环直接断掉。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;JRE auto-provisioning&lt;/strong&gt;：关闭。这个开关打开时，SonarQube 会按需要从&lt;strong&gt;公网&lt;/strong&gt;下载 JRE 供 scanner 使用——内网到不了公网，索性关掉；任务镜像已预装 JRE，scanner 不需要向服务端要。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&quot;https://blog.kali-team.cn/blog/2026/09/%E5%AE%89%E5%85%A8%E5%BC%80%E5%8F%91-SonarQube/sonarqube-general-settings.png&quot; alt=&quot;通用设置：JRE auto-provisioning 关闭与 Server base URL&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;图 8：General Settings：JRE auto-provisioning 关闭（内网无法从公网下载 JRE）、Server base URL 填内网域名（否则 OIDC 跳转默认回 localhost）&lt;/em&gt;&lt;/p&gt;
&lt;h3 id=&quot;4-6-yan-zheng-yong-gitea-connect-deng-lu&quot;&gt;&lt;a class=&quot;header-anchor no-hover-padding&quot; href=&quot;#4-6-yan-zheng-yong-gitea-connect-deng-lu&quot; aria-label=&quot;Anchor link for: 4-6-yan-zheng-yong-gitea-connect-deng-lu&quot;&gt;&lt;span class=&quot;link-icon&quot; aria-hidden=&quot;true&quot;&gt;&lt;/span&gt;&lt;/a&gt;
4.6 验证：用“Gitea Connect“登录&lt;/h3&gt;
&lt;p&gt;登出 admin，回到登录页——表单已经不一样了：没有账号 + 密码，只有“&lt;strong&gt;通过 Gitea Connect 登录&lt;/strong&gt;“和”&lt;strong&gt;更多选项&lt;/strong&gt;“（图 9）。点“通过 Gitea Connect 登录”，浏览器跳到 Gitea，授权后自动回 SonarQube，此时已以 Gitea 身份登录——顶部菜单能看到当前身份（图 10），全程没输任何密码。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://blog.kali-team.cn/blog/2026/09/%E5%AE%89%E5%85%A8%E5%BC%80%E5%8F%91-SonarQube/sonarqube-login-oidc.png&quot; alt=&quot;登录页的 Gitea Connect 入口&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;图 9：OIDC 生效后，登录页没有密码框，只有“通过 Gitea Connect 登录“与“更多选项“&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://blog.kali-team.cn/blog/2026/09/%E5%AE%89%E5%85%A8%E5%BC%80%E5%8F%91-SonarQube/sonarqube-oidc-logged-in.png&quot; alt=&quot;以 Gitea 身份登录成功&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;图 10：从 Gitea 授权回来后已以 Gitea 身份登录（顶部菜单显示当前身份），进入引导页&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;验证清单&lt;/strong&gt;：登录页出现 Gitea 入口 ✓ → 跳转授权后无需密码回到 SonarQube ✓ → 顶部菜单显示 Gitea 身份 ✓。三条都过，说明 OIDC 链路（含 2.3 的 caCerts 证书信任）走通。&lt;/p&gt;
&lt;h2 id=&quot;5-shi-yong-chuang-jian-xiang-mu-yu-ling-pai&quot;&gt;&lt;a class=&quot;header-anchor no-hover-padding&quot; href=&quot;#5-shi-yong-chuang-jian-xiang-mu-yu-ling-pai&quot; aria-label=&quot;Anchor link for: 5-shi-yong-chuang-jian-xiang-mu-yu-ling-pai&quot;&gt;&lt;span class=&quot;link-icon&quot; aria-hidden=&quot;true&quot;&gt;&lt;/span&gt;&lt;/a&gt;
5 使用：创建项目与令牌&lt;/h2&gt;
&lt;h3 id=&quot;5-1-chuang-jian-xiang-mu-shou-dong&quot;&gt;&lt;a class=&quot;header-anchor no-hover-padding&quot; href=&quot;#5-1-chuang-jian-xiang-mu-shou-dong&quot; aria-label=&quot;Anchor link for: 5-1-chuang-jian-xiang-mu-shou-dong&quot;&gt;&lt;span class=&quot;link-icon&quot; aria-hidden=&quot;true&quot;&gt;&lt;/span&gt;&lt;/a&gt;
5.1 创建项目（手动）&lt;/h3&gt;
&lt;p&gt;引导页里有几种建项目方式，最常见的是接代码平台集成后由平台自动建；本环境没接，&lt;strong&gt;手动创建&lt;/strong&gt;：填名称、Key，绑定分支（图 11），“选择质量门禁“直接用&lt;strong&gt;默认策略&lt;/strong&gt;（内置阈值，1.2）。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://blog.kali-team.cn/blog/2026/09/%E5%AE%89%E5%85%A8%E5%BC%80%E5%8F%91-SonarQube/sonarqube-create-project.png&quot; alt=&quot;创建项目对话框&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;图 11：手动创建项目对话框：名称「项目例子」、Key &lt;code&gt;example&lt;/code&gt;、绑定 main 分支&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Key 必须与仓库对上&lt;/strong&gt;（最重要的规则，否则扫描结果挂不上号）：&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3 z-i&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; cat sonar-project.properties&lt;/span&gt;&lt;span class=&quot;z-4 z-i&quot;&gt;   # example 仓库根目录的文件&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3 z-i&quot;&gt;sonar.projectKey&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; = example&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3 z-i&quot;&gt;sonar.projectName&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; = 项目例子&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3 z-i&quot;&gt;sonar.sources&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; = .&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;文件里的 &lt;code&gt;sonar.projectKey&lt;/code&gt; 必须与创建的项目 Key &lt;strong&gt;完全一致&lt;/strong&gt;（这里都是 &lt;code&gt;example&lt;/code&gt;）。&lt;/p&gt;
&lt;h3 id=&quot;5-2-chuang-jian-ling-pai-sao-miao-qi-de-ping-ju&quot;&gt;&lt;a class=&quot;header-anchor no-hover-padding&quot; href=&quot;#5-2-chuang-jian-ling-pai-sao-miao-qi-de-ping-ju&quot; aria-label=&quot;Anchor link for: 5-2-chuang-jian-ling-pai-sao-miao-qi-de-ping-ju&quot;&gt;&lt;span class=&quot;link-icon&quot; aria-hidden=&quot;true&quot;&gt;&lt;/span&gt;&lt;/a&gt;
5.2 创建令牌（扫描器的凭据）&lt;/h3&gt;
&lt;p&gt;向导下一步推荐“使用 GitHub CI 分析项目“（图 12）：核心是两个环境变量 &lt;code&gt;SONAR_TOKEN&lt;/code&gt;（令牌）与 &lt;code&gt;SONAR_HOST_URL&lt;/code&gt;（SonarQube 地址）。Gitea Actions 与 GitHub Actions &lt;strong&gt;语法兼容&lt;/strong&gt;，官方的 &lt;code&gt;sonarqube-scan-action&lt;/code&gt; 可以直接用（内网自托管版见下文）。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://blog.kali-team.cn/blog/2026/09/%E5%AE%89%E5%85%A8%E5%BC%80%E5%8F%91-SonarQube/sonarqube-ci-guidance.png&quot; alt=&quot;向导推荐使用 GitHub CI 分析项目&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;图 12：向导的“使用 GitHub CI 分析项目“步骤说明：流水线里传入 SONAR_TOKEN 与 SONAR_HOST_URL&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;点进去创建令牌（图 13），&lt;strong&gt;记下生成的密钥&lt;/strong&gt;（文内占位 &lt;code&gt;&amp;lt;SONARQUBE_ANALYSIS_TOKEN&amp;gt;&lt;/code&gt;；截图本身不含令牌值）。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://blog.kali-team.cn/blog/2026/09/%E5%AE%89%E5%85%A8%E5%BC%80%E5%8F%91-SonarQube/sonarqube-token-dialog.png&quot; alt=&quot;创建项目令牌对话框&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;图 13：创建项目令牌对话框（令牌尚未生成，图中不含令牌值）&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;令牌怎么存（红线）&lt;/strong&gt;：这是一个用户级 API token，长期有效，等价于“账号的钥匙“。本环境只放进 example 仓库的 Gitea &lt;strong&gt;Secrets&lt;/strong&gt;（仓库级加密环境变量，日志里打印自动打码）：&lt;/p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Secret&lt;/th&gt;&lt;th&gt;值&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;SONAR_TOKEN&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;&amp;lt;SONARQUBE_ANALYSIS_TOKEN&amp;gt;&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;SONAR_HOST_URL&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;https://sonarqube.kali-team.internal&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;不进代码、不进文章、不进聊天&lt;/strong&gt;——谁拿到令牌，谁就能以你的名义向 SonarQube 提交分析结果。&lt;/p&gt;
&lt;h3 id=&quot;5-3-yong-sonarscanner-cli-shou-dong-sao-miao-mei-you-liu-shui-xian-shi&quot;&gt;&lt;a class=&quot;header-anchor no-hover-padding&quot; href=&quot;#5-3-yong-sonarscanner-cli-shou-dong-sao-miao-mei-you-liu-shui-xian-shi&quot; aria-label=&quot;Anchor link for: 5-3-yong-sonarscanner-cli-shou-dong-sao-miao-mei-you-liu-shui-xian-shi&quot;&gt;&lt;span class=&quot;link-icon&quot; aria-hidden=&quot;true&quot;&gt;&lt;/span&gt;&lt;/a&gt;
5.3 用 SonarScanner CLI 手动扫描（没有流水线时）&lt;/h3&gt;
&lt;p&gt;暂时没有流水线的场景（新项目没接 CI、开发机一次性验证、流水线坏了本地复现），用 &lt;strong&gt;SonarScanner CLI&lt;/strong&gt; 直接扫——就是流水线里那个 scanner，区别只是“由你在命令行驱动“。三步：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;第 1 步：获取 scanner&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;官方下载站内网到不了，从 Nexus raw 仓库 &lt;code&gt;sonar-scanner-cli&lt;/code&gt; 取——raw 仓库没有目录列表，&lt;strong&gt;必须显式写全文件名&lt;/strong&gt;：&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4 z-i&quot;&gt;# 做什么：从内网 Nexus 仓库下载 scanner&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4 z-i&quot;&gt;# 怎么做：wget 显式文件名（raw 仓库不能&amp;quot;列目录挑文件&amp;quot;）&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4 z-i&quot;&gt;# 为什么：官方站内网不可达；Nexus 里这份是官方站取回缓存的同一文件&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3 z-i&quot;&gt;wget&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; https://nexus.kali-team.internal/repository/sonar-scanner-cli/sonar-scanner-8.1.0.6389-linux.tgz&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4 z-i&quot;&gt;# 解压到 /opt，并把 bin 目录加进 PATH，之后 sonar-scanner 命令直接可用&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3 z-i&quot;&gt;tar&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; -xzf sonar-scanner-8.1.0.6389-linux.tgz -d /opt/&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-9&quot;&gt;export&lt;/span&gt;&lt;span&gt; PATH&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;$PATH&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt;:/opt/sonar-scanner-8.1.0.6389-linux/bin&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;两个前提：scanner 是 Java 程序，开发机要先装一个 JRE（JDK 发行版里就带；流水线任务镜像已预装，1.3）；Java 不读系统信任库（详见“常见问题与坑“），开发机若没装内网 CA，系统信任库与 Java 的 &lt;code&gt;cacerts&lt;/code&gt; 两处都要导入，思路同 6.2 的“双通道“。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;第 2 步：写 &lt;code&gt;sonar-project.properties&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;scanner 靠这个文件对上目标；example 用的是最小形式（上面三行），完整字段按需取用：&lt;/p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;字段&lt;/th&gt;&lt;th&gt;必填&lt;/th&gt;&lt;th&gt;作用&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;sonar.projectKey&lt;/code&gt;&lt;/td&gt;&lt;td&gt;是&lt;/td&gt;&lt;td&gt;项目唯一标识：&lt;strong&gt;必须与 SonarQube 上创建的项目 Key 一致&lt;/strong&gt;，对不上结果就挂不到项目下&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;sonar.projectName&lt;/code&gt;&lt;/td&gt;&lt;td&gt;建议&lt;/td&gt;&lt;td&gt;面板显示名&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;sonar.projectVersion&lt;/code&gt;&lt;/td&gt;&lt;td&gt;建议&lt;/td&gt;&lt;td&gt;项目版本，随分析记录展示&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;sonar.sources&lt;/code&gt;&lt;/td&gt;&lt;td&gt;是&lt;/td&gt;&lt;td&gt;扫描哪些目录，多个用逗号分隔；&lt;code&gt;.&lt;/code&gt; = 整个仓库（example 的写法）&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;sonar.exclusions&lt;/code&gt;&lt;/td&gt;&lt;td&gt;可选&lt;/td&gt;&lt;td&gt;排除模式，如 &lt;code&gt;**/vendor/**,**/node_modules/**&lt;/code&gt;——生成代码 / 第三方代码不该占扫描指标&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;sonar.sourceEncoding&lt;/code&gt;&lt;/td&gt;&lt;td&gt;可选&lt;/td&gt;&lt;td&gt;源码编码，本环境统一 &lt;code&gt;UTF-8&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;sonar.language&lt;/code&gt;&lt;/td&gt;&lt;td&gt;可选&lt;/td&gt;&lt;td&gt;手动指定语言；&lt;strong&gt;可省略&lt;/strong&gt;——scanner 会自动识别（example 的 Go 没写这条，照样识别）&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;第 3 步：执行扫描&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4 z-i&quot;&gt;# 做什么：扫描当前目录的代码，结果提交给 SonarQube&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4 z-i&quot;&gt;# 怎么做：命令行 -D 传两个参数——服务器地址 + 令牌（-D 是 scanner 传配置&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4 z-i&quot;&gt;#         的方式，命令行参数优先于 properties 文件）&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4 z-i&quot;&gt;# 为什么：令牌是 scanner 连接 SonarQube 的凭据；&amp;lt;SONARQUBE_ANALYSIS_TOKEN&amp;gt; 为本文占位符&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3 z-i&quot;&gt;sonar-scanner&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-7&quot;&gt;  -Dsonar.host.url=https://sonarqube.kali-team.internal&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-7&quot;&gt;  -Dsonar.token=&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt;SONARQUBE_ANALYSIS_TOKEN&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;跑成功后，5.1 创建的项目页面上会出现一条新的分析记录——和流水线扫的是同一个页面、同一份数据：质量门禁判定、三维度评级、问题列表都在这里看。&lt;/p&gt;
&lt;h3 id=&quot;5-4-pei-zhi-zhi-liang-men-jin-dian-na-li-pei-shen-me&quot;&gt;&lt;a class=&quot;header-anchor no-hover-padding&quot; href=&quot;#5-4-pei-zhi-zhi-liang-men-jin-dian-na-li-pei-shen-me&quot; aria-label=&quot;Anchor link for: 5-4-pei-zhi-zhi-liang-men-jin-dian-na-li-pei-shen-me&quot;&gt;&lt;span class=&quot;link-icon&quot; aria-hidden=&quot;true&quot;&gt;&lt;/span&gt;&lt;/a&gt;
5.4 配置质量门禁：点哪里、配什么&lt;/h3&gt;
&lt;p&gt;这一节只讲操作，分项目级和系统级两层。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;项目级：给本项目选一个门禁&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;项目列表 → 点进项目 → &lt;strong&gt;Project Settings&lt;/strong&gt; → &lt;strong&gt;Quality Gate&lt;/strong&gt; → 从下拉里选一个。内置的 &lt;strong&gt;Sonar way&lt;/strong&gt; 是出厂推荐阈值，也可以选自定义门禁；改动只影响当前项目。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;系统级：在 Quality Gates 页自定义条件&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;管理员入口 → &lt;strong&gt;Quality Gates&lt;/strong&gt; → 新建 / 编辑门禁，逐条设置条件。本环境参考口径：&lt;/p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;条件&lt;/th&gt;&lt;th&gt;阈值&lt;/th&gt;&lt;th&gt;含义&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;新代码覆盖率&lt;/td&gt;&lt;td&gt;≥ 80%&lt;/td&gt;&lt;td&gt;新增代码里被单元测试覆盖的比例&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;新代码重复率&lt;/td&gt;&lt;td&gt;≤ 3%&lt;/td&gt;&lt;td&gt;新增代码里互相复制的比例&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;维护性等级&lt;/td&gt;&lt;td&gt;A&lt;/td&gt;&lt;td&gt;评级 A–E，A 最好&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;安全等级&lt;/td&gt;&lt;td&gt;A&lt;/td&gt;&lt;td&gt;同上&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;为什么都是“&lt;strong&gt;新代码&lt;/strong&gt;“：门禁条件可按“全部代码“或“新代码”（“新代码期“内的变动，按版本基线 / 时间窗口划定）定义——对老项目设全量门禁，存量问题会把它永远钉在 Failed，先管增量才可落地。&lt;/p&gt;
&lt;p&gt;提醒：门禁配置后&lt;strong&gt;每次扫描都判定&lt;/strong&gt;（含 5.3 的手动扫描）；本环境现状是判定只展示在页面上，Failed 不会让流水线失败（详见“常见问题与坑“）。&lt;/p&gt;
&lt;h2 id=&quot;6-ci-cd-lian-dong-sonarqube-yaml-zhu-duan-jiang&quot;&gt;&lt;a class=&quot;header-anchor no-hover-padding&quot; href=&quot;#6-ci-cd-lian-dong-sonarqube-yaml-zhu-duan-jiang&quot; aria-label=&quot;Anchor link for: 6-ci-cd-lian-dong-sonarqube-yaml-zhu-duan-jiang&quot;&gt;&lt;span class=&quot;link-icon&quot; aria-hidden=&quot;true&quot;&gt;&lt;/span&gt;&lt;/a&gt;
6 CI/CD 联动：sonarqube.yaml 逐段讲&lt;/h2&gt;
&lt;h3 id=&quot;6-1-sast-zai-liu-shui-xian-li-de-wei-zhi&quot;&gt;&lt;a class=&quot;header-anchor no-hover-padding&quot; href=&quot;#6-1-sast-zai-liu-shui-xian-li-de-wei-zhi&quot; aria-label=&quot;Anchor link for: 6-1-sast-zai-liu-shui-xian-li-de-wei-zhi&quot;&gt;&lt;span class=&quot;link-icon&quot; aria-hidden=&quot;true&quot;&gt;&lt;/span&gt;&lt;/a&gt;
6.1 SAST 在流水线里的位置&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;.gitea/workflows/sonarqube.yaml&lt;/code&gt; 的触发条件：打版本 tag（&lt;code&gt;v*&lt;/code&gt; push）、PR 事件、&lt;code&gt;repository_dispatch&lt;/code&gt;（webhook）、&lt;code&gt;workflow_dispatch&lt;/code&gt;（手动）——&lt;strong&gt;每次代码变动都自动做一遍静态扫描&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;在流水线里：&lt;code&gt;docker.yaml&lt;/code&gt; 管构建镜像、&lt;code&gt;dependency-track.yaml&lt;/code&gt; 管依赖扫描（SCA）、&lt;code&gt;sonarqube.yaml&lt;/code&gt; 管自己的代码扫描（SAST）——三条并行、各管一段。&lt;/p&gt;
&lt;h3 id=&quot;6-2-si-ge-bu-zou-zhu-duan-kan&quot;&gt;&lt;a class=&quot;header-anchor no-hover-padding&quot; href=&quot;#6-2-si-ge-bu-zou-zhu-duan-kan&quot; aria-label=&quot;Anchor link for: 6-2-si-ge-bu-zou-zhu-duan-kan&quot;&gt;&lt;span class=&quot;link-icon&quot; aria-hidden=&quot;true&quot;&gt;&lt;/span&gt;&lt;/a&gt;
6.2 四个步骤逐段看&lt;/h3&gt;
&lt;p&gt;全文（example 仓库真实文件，注释保留原样）：&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-14&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4 z-i&quot;&gt;  # Trigger analysis when pushing to your main branches, and when creating a pull request.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;  push&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;    tags&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4&quot;&gt;      -&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; &amp;quot;v*&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;  pull_request&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;      types&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-4&quot;&gt; [&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt;opened&lt;/span&gt;&lt;span class=&quot;z-4&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; synchronize&lt;/span&gt;&lt;span class=&quot;z-4&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; reopened&lt;/span&gt;&lt;span class=&quot;z-4&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;  repository_dispatch&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-4 z-i&quot;&gt;  # 通过 Webhook 触发&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;  workflow_dispatch&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-4 z-i&quot;&gt;   # 支持手动立即触发&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; Main Workflow&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;jobs&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;  sonarqube&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;    runs-on&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; ubuntu-host&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;    env&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;      RUNNER_TOOL_CACHE&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; /toolcache&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;    steps&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4&quot;&gt;      -&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; name&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; Init&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;        run&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt; |&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-7&quot;&gt;          echo -n | openssl s_client -showcerts -connect hub.kali-team.internal:443 2&amp;gt;/dev/null | sed -ne &amp;#39;/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p&amp;#39; &amp;gt;&amp;gt; hub.kali-team.internal.crt&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-7&quot;&gt;          sudo cp hub.kali-team.internal.crt /usr/local/share/ca-certificates/&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-7&quot;&gt;          sudo update-ca-certificates&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4&quot;&gt;      -&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; name&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; Checkout code&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;        uses&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; https://hub.kali-team.internal/actions/checkout@v4&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;        env&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;          GIT_SSL_NO_VERIFY&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-14&quot;&gt; true&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;        with&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;          submodules&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-14&quot;&gt; true&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;          fetch-depth&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-14&quot;&gt; 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;          token&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; ${{ secrets.TOKEN }}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4&quot;&gt;      -&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; name&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; Verify Certificate&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;        run&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt; |&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-7&quot;&gt;          sudo cp kali-team-ca.crt /usr/local/share/ca-certificates/&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-7&quot;&gt;          sudo mkdir -p /etc/docker/certs.d/mirror.kali-team.internal&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-7&quot;&gt;          sudo cp kali-team-ca.crt /etc/docker/certs.d/mirror.kali-team.internal/ca.crt&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-7&quot;&gt;          sudo update-ca-certificates&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4&quot;&gt;      -&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; name&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; SonarQube Scan 静态代码扫描&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;        uses&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; https://hub.kali-team.internal/actions/sonarqube-scan-action@v9&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;        env&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;          SONAR_TOKEN&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; ${{ secrets.SONAR_TOKEN }}&lt;/span&gt;&lt;span class=&quot;z-4 z-i&quot;&gt; # 创建项目的时候创建的长期有效的Token&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;          SONAR_HOST_URL&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; ${{ secrets.SONAR_HOST_URL }}&lt;/span&gt;&lt;span class=&quot;z-4 z-i&quot;&gt; # SonarQube服务器地址&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;          NODE_EXTRA_CA_CERTS&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; /usr/local/share/ca-certificates/kali-team-ca.crt&lt;/span&gt;&lt;span class=&quot;z-4 z-i&quot;&gt; # 信任dev-sec-ops证书&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4 z-i&quot;&gt;          # SONAR_ROOT_CERT: ${{ secrets.SONAR_ROOT_CERT }}  #sonar是java写的，他不读取系统证书，所以还要加到环境变量，PEM格式的证书&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;        with&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;            scannerBinariesUrl&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; https://nexus.kali-team.internal/repository/sonar-scanner-cli/&lt;/span&gt;&lt;span class=&quot;z-4 z-i&quot;&gt; # 下载SonarScanner CLI的URL，使用私有Nexus仓库&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;            scannerFile&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; sonar-scanner-8.1.0.6389-linux.tgz&lt;/span&gt;&lt;span class=&quot;z-4 z-i&quot;&gt; # 显式文件名（Nexus raw 仓库无目录列表接口，实测 GET / 返回 404）&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;            projectBaseDir&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-14&quot;&gt; .&lt;/span&gt;&lt;span class=&quot;z-4 z-i&quot;&gt; # 项目根目录，默认为当前工作目录&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;            skipSignatureVerification&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-14&quot;&gt; true&lt;/span&gt;&lt;span class=&quot;z-4 z-i&quot;&gt;  # 不知道为什么内网有时候访问hkps://keyserver.ubuntu.com提示证书错误&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;前三步与另外两条流水线相同：&lt;strong&gt;Init&lt;/strong&gt; 抓内网 Gitea 证书进系统信任库；&lt;strong&gt;Checkout&lt;/strong&gt; 克隆代码；&lt;strong&gt;Verify Certificate&lt;/strong&gt; 把内网 CA 同时放进系统信任库与 Docker 证书目录（&lt;code&gt;/etc/docker/certs.d/&lt;/code&gt;），让 git、docker 都认内网 https。重点讲最后一步：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Scanner 从哪来？Nexus 仓库。&lt;/strong&gt; 官方站在公网，scanner 压缩包（约 9MB）从 &lt;strong&gt;Nexus raw 仓库&lt;/strong&gt; &lt;code&gt;sonar-scanner-cli&lt;/code&gt; 取，&lt;code&gt;scannerBinariesUrl&lt;/code&gt; 指向它。raw 仓库&lt;strong&gt;没有目录列表接口&lt;/strong&gt;（&lt;code&gt;GET /&lt;/code&gt; 直接 404），必须在 &lt;code&gt;scannerFile&lt;/code&gt; 里&lt;strong&gt;显式写死文件名&lt;/strong&gt;。大头的 &lt;strong&gt;JRE&lt;/strong&gt; 完全不下载：任务镜像已预装。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Java 不读系统证书。&lt;/strong&gt; scanner 是 Java 程序，用自己的证书库（keystore，&lt;code&gt;$JAVA_HOME/lib/security/cacerts&lt;/code&gt;），&lt;strong&gt;不读&lt;/strong&gt; Linux 系统信任库——前面导再多次，Java 也看不见。解法分两路：node 部分靠 &lt;code&gt;NODE_EXTRA_CA_CERTS&lt;/code&gt;（node.js 的“额外信任证书“环境变量）；Java 部分由 action 内部用 &lt;code&gt;keytool&lt;/code&gt;（JDK 自带的证书管理工具）把 &lt;code&gt;kali-team-ca.crt&lt;/code&gt; 导入 &lt;code&gt;cacerts&lt;/code&gt;。两路都通，https 握手才成功。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;项目怎么对上号？&lt;/strong&gt; &lt;code&gt;projectBaseDir: .&lt;/code&gt; 告诉 scanner 从当前目录开始扫，它在该目录读 &lt;code&gt;sonar-project.properties&lt;/code&gt;：文件里 &lt;code&gt;sonar.projectKey=example&lt;/code&gt; 必须与 Server 侧项目一致，结果就挂到那个项目下。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;skipSignatureVerification: true&lt;/code&gt;。&lt;/strong&gt; 官方 action 默认还会对下载包做 &lt;strong&gt;GPG 签名校验&lt;/strong&gt;（防篡改的签名机制）。内网 Nexus 的包是自己传的，没有签名可验；验签还要连公网密钥服务器（文件注释里的实测现象：内网访问 &lt;code&gt;hkps://keyserver.ubuntu.com&lt;/code&gt; 有时报证书错误）——所以关掉。完整性改由“内网 Nexus + 内部管控流程“保证。&lt;/p&gt;
&lt;h3 id=&quot;6-3-shi-ce-run-8&quot;&gt;&lt;a class=&quot;header-anchor no-hover-padding&quot; href=&quot;#6-3-shi-ce-run-8&quot; aria-label=&quot;Anchor link for: 6-3-shi-ce-run-8&quot;&gt;&lt;span class=&quot;link-icon&quot; aria-hidden=&quot;true&quot;&gt;&lt;/span&gt;&lt;/a&gt;
6.3 实测：run #8&lt;/h3&gt;
&lt;p&gt;在 Gitea Actions 页面手动触发 &lt;code&gt;sonarqube.yaml&lt;/code&gt;：&lt;code&gt;sonarqube&lt;/code&gt; job 耗时 &lt;strong&gt;21s&lt;/strong&gt;，状态 success。随后 SonarQube 上 &lt;code&gt;example&lt;/code&gt; 项目（显示名「项目例子」）出现扫描记录：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://blog.kali-team.cn/blog/2026/09/%E5%AE%89%E5%85%A8%E5%BC%80%E5%8F%91-SonarQube/sonarqube-projects-list.png&quot; alt=&quot;SonarQube 项目列表&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;图 14：SonarQube 项目列表：&lt;code&gt;项目例子&lt;/code&gt;（61 行代码，Go）最新分析 Quality Gate Passed，Security / Reliability / Maintainability 三维度 A/0、A/0、A/1，Coverage 0.0%——与下表同一份数据&lt;/em&gt;&lt;/p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;指标&lt;/th&gt;&lt;th&gt;实测值&lt;/th&gt;&lt;th&gt;怎么读&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Quality Gate&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Passed&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;扫描通过门禁标准&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;代码行数&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;61&lt;/td&gt;&lt;td&gt;example 项目很小&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Security / Reliability / Maintainability&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;0 / 0 / 1（open issues）&lt;/td&gt;&lt;td&gt;安全漏洞 / 稳定性缺陷 / 可维护性坏味道三维度未关闭问题数，评级 A；那个“1“是坏味道&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Coverage&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;0.0%&lt;/td&gt;&lt;td&gt;单元测试覆盖的代码比例——示例项目没写单测，0% 符合预期&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;最后分析时间&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;2026-10-15 14:12 UTC&lt;/td&gt;&lt;td&gt;即本次 run 完成时间&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;目前流水线停在“&lt;strong&gt;扫描并出报告&lt;/strong&gt;“：门禁用的是内置默认策略，判定只展示在 SonarQube 页面上，尚未接成“卡住流水线“的硬卡点（详见“常见问题与坑”）。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;7-chang-jian-wen-ti-yu-keng&quot;&gt;&lt;a class=&quot;header-anchor no-hover-padding&quot; href=&quot;#7-chang-jian-wen-ti-yu-keng&quot; aria-label=&quot;Anchor link for: 7-chang-jian-wen-ti-yu-keng&quot;&gt;&lt;span class=&quot;link-icon&quot; aria-hidden=&quot;true&quot;&gt;&lt;/span&gt;&lt;/a&gt;
7 常见问题与坑&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;OIDC 连 Gitea 报证书错误（内网自签 CA）。&lt;/strong&gt; 现象：配置 / 调试 OIDC 时 SonarQube 连 &lt;code&gt;hub.kali-team.internal&lt;/code&gt; 证书校验失败。根因：SonarQube 是 Java 程序、用自带 CA 信任库，内网 CA 不在默认库里。解法：chart 的 &lt;code&gt;caCerts&lt;/code&gt;——根证书先建 Secret，&lt;code&gt;caCerts.enabled: true&lt;/code&gt; + &lt;code&gt;secret&lt;/code&gt; 指向它覆盖默认库（2.3、2.4 的 &lt;code&gt;caCerts&lt;/code&gt; 项）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;OIDC 授权后跳转到 localhost。&lt;/strong&gt; 根因：Server base URL 没配，SonarQube 以为自己在 &lt;code&gt;localhost&lt;/code&gt;，回调地址算错。解法：General Settings 里填真实内网域名。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Scanner 连不上 SonarQube 的 https（Java 不读系统证书）。&lt;/strong&gt; 根因：scanner 是 Java 程序，用自己的 &lt;code&gt;cacerts&lt;/code&gt;；解法是双通道——action 内 &lt;code&gt;keytool&lt;/code&gt; 导入内网 CA 到 &lt;code&gt;cacerts&lt;/code&gt;，node 侧走 &lt;code&gt;NODE_EXTRA_CA_CERTS&lt;/code&gt;（6.2 的证书步骤）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Scanner 下载 404（Nexus raw 无目录列表）。&lt;/strong&gt; 不写 &lt;code&gt;scannerFile&lt;/code&gt; 时 action 无法列目录找文件（6.2 的第一步）。教训：raw 仓库取文件，永远显式写文件名。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;apt-get remove wget&lt;/code&gt; 误删扫描器的下载工具。&lt;/strong&gt; 流水线 Init 里曾有一句删 wget 的“瘦身“，而 scan-action 靠 &lt;code&gt;wget&lt;/code&gt; 从 Nexus 拉 scanner——删完下载直接失败。&lt;code&gt;7dce1ad&lt;/code&gt; 删掉该行后一次跑通。教训：给任务容器做工具面改动前，先确认每个 action 实际用到哪些命令。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;初始 admin 默认密码（admin/admin）。&lt;/strong&gt; 全新 SonarQube 用 &lt;code&gt;admin/admin&lt;/code&gt; 可登；首次登录后必须修改，新值按团队凭据规范存放；本文与截图一律占位 / 打码。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;质量门禁尚未卡流水线。&lt;/strong&gt; 现状是“扫描并出报告“：门禁用内置默认策略，即使判定 Failed，流水线也不会因此失败。要“扫不过不许合并 / 发布“，需让流水线在门禁不通过时失败（官方 scan-action 支持等待门禁判定并据此置失败，可作为后续接入项）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;chart 要求指定 &lt;code&gt;monitoringPasscode&lt;/code&gt;。&lt;/strong&gt; 不填 chart 校验不过（2.4 的第 8 项）；&lt;strong&gt;需要指定添加&lt;/strong&gt;，本环境用 &lt;code&gt;community&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;内存上限给低了 Java 服务 OOM。&lt;/strong&gt; 思路是“&lt;strong&gt;内存给多点，java 开发的，避免执行任务的时候 OOM&lt;/strong&gt;“（2.4 的第 7 项）；若 pod 反复被杀（重启次数不停涨），第一反应查 &lt;code&gt;resources.limits.memory&lt;/code&gt;。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;8-xiao-jie&quot;&gt;&lt;a class=&quot;header-anchor no-hover-padding&quot; href=&quot;#8-xiao-jie&quot; aria-label=&quot;Anchor link for: 8-xiao-jie&quot;&gt;&lt;span class=&quot;link-icon&quot; aria-hidden=&quot;true&quot;&gt;&lt;/span&gt;&lt;/a&gt;
8 小结&lt;/h2&gt;
&lt;p&gt;这一篇给内网 DevSecOps 体系补上&lt;strong&gt;代码质量 / 安全&lt;/strong&gt;一环：SonarQube 装进 k3s（官方 chart + 共享 PostgreSQL + 自签 CA 覆盖），接入 Gitea OIDC 统一登录，&lt;code&gt;sonarqube.yaml&lt;/code&gt; 让每次推送 / PR 自动跑一遍 SAST 扫描——21 秒出结果，质量门禁判定在页面上可见。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;概念&lt;/strong&gt;：SAST 不运行代码就能找漏洞 / 缺陷 / 坏味道；质量门禁是扫描的判定标准；Server 存结果、Scanner 干活，&lt;code&gt;sonar-project.properties&lt;/code&gt; 的 projectKey 是两者对上的唯一标识；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;搭建&lt;/strong&gt;：共享 PostgreSQL 上临时 pod 建库、自签 CA 进 Secret 用 &lt;code&gt;caCerts&lt;/code&gt; 覆盖、values 五个重点（community 版、jdbcOverwrite、ingress、persistence、内存）；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;初始配置 + OIDC&lt;/strong&gt;：改 admin 默认密码、Marketplace 装中文与 OIDC 插件、按发现端点填 Issuer / Client / scopes、配 Server base URL（否则跳转回 localhost）；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;使用&lt;/strong&gt;：手动建项目（Key 与仓库 properties 对齐）、令牌只进 Gitea Secrets；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CI/CD&lt;/strong&gt;：scanner 走 Nexus raw 仓库（文件名显式写死）、Java 证书双通道（keytool + NODE_EXTRA_CA_CERTS）、实测 run #8：21s、Quality Gate Passed、61 行、0/0/1；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;坑&lt;/strong&gt;：自签 CA、localhost 跳转、Java 证书、raw 无目录列表、wget 被误删、默认密码、门禁未卡点、monitoringPasscode、OOM。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;下一步可选：把质量门禁接成流水线硬卡点（扫不过不许合并，官方 action 支持等待门禁判定）、配更严的门禁策略（New Code 周期、覆盖率阈值）、接入更多项目（key 规则通用——&lt;code&gt;sonar-project.properties&lt;/code&gt; 的 key 与服务端项目一致即可）。至此内网五平台齐位：Gitea（代码）→ Harbor（镜像）→ Nexus（制品）→ SonarQube（代码质量）→ Dependency-Track（依赖安全），流水线覆盖“代码 → 镜像 → 依赖 → 质量“全链。&lt;/p&gt;
&lt;h2 id=&quot;can-kao&quot;&gt;&lt;a class=&quot;header-anchor no-hover-padding&quot; href=&quot;#can-kao&quot; aria-label=&quot;Anchor link for: can-kao&quot;&gt;&lt;span class=&quot;link-icon&quot; aria-hidden=&quot;true&quot;&gt;&lt;/span&gt;&lt;/a&gt;
参考&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class=&quot;external&quot; rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https://docs.sonarsource.com/sonarqube-server/&quot;&gt;SonarQube 官方文档&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&quot;external&quot; rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https://sonarsource.github.io/helm-chart-sonarqube&quot;&gt;SonarQube Helm chart（本部署 chart 来源，含 “Use custom cacerts” 说明）&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&quot;external&quot; rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https://docs.sonarsource.com/sonarqube-server/9.8/analyzing-source-code/scanners/sonarscanner&quot;&gt;SonarScanner CLI 文档&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&quot;external&quot; rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https://docs.sonarsource.com/sonarqube-server/user-guide/managing-tokens&quot;&gt;SonarQube Token 管理&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&quot;external&quot; rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https://about.gitea.com/resources/tutorials/gitea-integrate-sonarqube&quot;&gt;Gitea + SonarQube 集成教程&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&quot;external&quot; rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https://github.com/SonarSource/sonarqube-scan-action&quot;&gt;SonarQube scan action（本流水线自托管版为 composite 重写）&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
        <summary type="html">SonarQube（代码质量 / SAST 静态扫描平台）</summary>
        </entry>
</feed>
