<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>二次开发 on FICN&#39;s blog</title>
    <link>https://blog.fnicen.top/categories/%E4%BA%8C%E6%AC%A1%E5%BC%80%E5%8F%91/</link>
    <description>Recent content in 二次开发 on FICN&#39;s blog</description>
    <generator>Hugo -- 0.139.3</generator>
    <language>en</language>
    <lastBuildDate>Thu, 09 Apr 2026 14:26:51 +0800</lastBuildDate>
    <atom:link href="https://blog.fnicen.top/categories/%E4%BA%8C%E6%AC%A1%E5%BC%80%E5%8F%91/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>为Kite开发集群内基于exec参数启动kubelogin的OIDC认证功能</title>
      <link>https://blog.fnicen.top/posts/%E4%B8%BAkite%E5%BC%80%E5%8F%91%E9%9B%86%E7%BE%A4%E5%86%85%E5%9F%BA%E4%BA%8Eexec%E5%8F%82%E6%95%B0%E5%90%AF%E5%8A%A8kubelogin%E7%9A%84oidc%E8%AE%A4%E8%AF%81%E5%8A%9F%E8%83%BD/</link>
      <pubDate>Thu, 09 Apr 2026 14:26:51 +0800</pubDate>
      <guid>https://blog.fnicen.top/posts/%E4%B8%BAkite%E5%BC%80%E5%8F%91%E9%9B%86%E7%BE%A4%E5%86%85%E5%9F%BA%E4%BA%8Eexec%E5%8F%82%E6%95%B0%E5%90%AF%E5%8A%A8kubelogin%E7%9A%84oidc%E8%AE%A4%E8%AF%81%E5%8A%9F%E8%83%BD/</guid>
      <description>&lt;h2 id=&#34;现状&#34;&gt;现状&lt;/h2&gt;
&lt;p&gt;我在集群中使用Keycloak + kubelgoin + Webhook的认证模式，具体流程如下：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;在API-Server中将认证模式设置为Webhook模式，由Webhook手动校验OIDC&lt;/li&gt;
&lt;li&gt;执行&lt;code&gt;kubectl&lt;/code&gt;时，&lt;code&gt;exec&lt;/code&gt;命令启动&lt;code&gt;kubelogin&lt;/code&gt;，以&lt;code&gt;device-code&lt;/code&gt;形式唤起Keycloak进行认证&lt;/li&gt;
&lt;li&gt;认证完成后Keycloak给出&lt;code&gt;token&lt;/code&gt;，由kubectl将&lt;code&gt;id_token&lt;/code&gt;添加到GET请求的&lt;code&gt;Authorization&lt;/code&gt;字段发送至API-Server&lt;/li&gt;
&lt;li&gt;API-Server向Webhook POST一个&lt;code&gt;TokenReview&lt;/code&gt;，Webhook解析&lt;code&gt;token&lt;/code&gt;、验证后根据规则组装成&lt;code&gt;UserInfo&lt;/code&gt;发往后续准入环节等&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;现在项目中引入了&lt;a href=&#34;https://kite.zzde.me/zh/&#34;&gt;Kite&lt;/a&gt;作为集群管理面板&lt;/p&gt;
&lt;p&gt;Kite的底层是通过&lt;code&gt;K8s-Client&lt;/code&gt;向API-Server发送HTTP请求执行相应操作，本质上与&lt;code&gt;kubectl&lt;/code&gt;相似，且都需要读取预先配置的&lt;code&gt;kubeconfig&lt;/code&gt;文件获取配置上下文，如集群地址、当前集群用户、用户证书等&lt;/p&gt;
&lt;div class=&#34;admonition warning&#34;&gt;
  &lt;div class=&#34;admonition-title&#34;&gt;不足&lt;/div&gt;
  &lt;div class=&#34;admonition-content&#34;&gt;&lt;p&gt;Kite本身不负责集群身份认证，而是将安全性转移至进入Kite面板的认证。因此Kite虽然原生支持OIDC，但只能支持进入Kite管理界面时的OIDC认证，而非集群内身份认证&lt;/p&gt;
&lt;p&gt;也正因这个原因，Kite无法处理&lt;code&gt;kubeconfig&lt;/code&gt;中配置了&lt;code&gt;exec&lt;/code&gt;参数动态获取认证凭证的用户，在界面中将该用户上下文显示为不可用状态&lt;/p&gt;
&lt;p&gt;为了解决这个问题，Kite创建了一个专用的Service Account，并使用其&lt;code&gt;token&lt;/code&gt;通过集群认证（将&lt;code&gt;token&lt;/code&gt;放入&lt;code&gt;kubeconfig&lt;/code&gt;然后被Kite正常读取使用）&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id=&#34;需求&#34;&gt;需求&lt;/h2&gt;
&lt;p&gt;我需要二次开发Kite，使Kite支持进行集群内OIDC device-code模式认证&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;用户只需要指定Issuer、client_secret等必要信息，即可提供Keycloak认证界面供用户进行认证&lt;/li&gt;
&lt;li&gt;认证通过后，需要能够接收Keycloak响应的各种&lt;code&gt;token&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;记录该&lt;code&gt;token&lt;/code&gt;，禁用原&lt;code&gt;kubeconfig&lt;/code&gt;配置&lt;/li&gt;
&lt;li&gt;之后调用&lt;code&gt;K8s-Client&lt;/code&gt;发送API请求时都在&lt;code&gt;Authorization&lt;/code&gt;字段附加&lt;code&gt;token&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;如果&lt;code&gt;token&lt;/code&gt;过期，则在前端提示用户需要重新进行OIDC认证&lt;/li&gt;
&lt;li&gt;如果请求被准入环节拦截，需要提示用户根据准入规定重新认证 / 增量认证 / 拒绝请求&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;准备&#34;&gt;准备&lt;/h2&gt;
&lt;p&gt;使用Postman测试不带&lt;code&gt;Authorization&lt;/code&gt;的API请求响应，返回403：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;kind&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Status&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;apiVersion&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;v1&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;metadata&amp;#34;&lt;/span&gt;: {},
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;status&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Failure&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;message&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;nodes is forbidden: User \&amp;#34;system:anonymous\&amp;#34; cannot list resource \&amp;#34;nodes\&amp;#34; in API group \&amp;#34;\&amp;#34; at the cluster scope&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;reason&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Forbidden&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;details&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;kind&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;nodes&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;code&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;403&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;p&gt;使用Postman附带Keycloak客户端ID、客户端Secret向$base_url发送认证请求：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;device_code&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;vfpIiDEl8-M7euodTglJTkbUnKr99l7GGDNQK7If0EM&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;user_code&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;PSWY-TSRS&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;verification_uri&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;https://192.168.5.96:31443/realms/k8s-auth/device&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;verification_uri_complete&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;https://192.168.5.96:31443/realms/k8s-auth/device?user_code=PSWY-TSRS&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;expires_in&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;600&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;interval&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;5&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;p&gt;认证完成后尝试拉取Token：&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
