一個(gè)功能直接調(diào)用了 k8s 的 API, 在集群從 1.5 升級到 1.6 后突然報(bào) 403, 錯誤信息是
system:anonymous 用戶對相應(yīng)的資源沒有權(quán)限
關(guān)于匿名請求
什么是 system:anonymous
用戶? 這是 k8s 給沒有被其它驗(yàn)證方法所拒絕的匿名請求分配的一個(gè)用戶, 并且它屬于 system:unauthenticated
這個(gè)組汞窗。
例如, apiserver 配置了 token 驗(yàn)證, 并且允許匿名請求池凄。一個(gè)帶了 bearer token 然而不能通過驗(yàn)證的請求會收到 401 Unauthorized
突琳。一個(gè)沒有帶 token 的請求則被視為匿名請求致稀。
繼續(xù) debug
出問題的 API 是通過 basic auth 的方式調(diào)用的, 并且以 username:password
的形式寫在 url 里。 集群升級前, 能夠通過驗(yàn)證, 但升級后卻無法通過驗(yàn)證, 并且成為了一個(gè)匿名請求。
查閱相關(guān)的文檔, 發(fā)現(xiàn)匿名請求在 1.5.1-1.5.x 是默認(rèn)關(guān)閉的, 而在 1.6+ 則默認(rèn)開啟苔咪。因?yàn)?1) 無法通過驗(yàn)證, 2) 匿名請求被允許, 所以才收到了 403。但為什么升級了集群, 驗(yàn)證就無法通過了呢柳骄。
分析新舊集群請求的差異, 發(fā)現(xiàn)舊集群上, 驗(yàn)證也不是一次通過的团赏。是第一次請求收到了 401, 然后第二次請求才通過。并且第二次請求帶有 basic auth 的 header, 而前者則沒有耐薯。這下問題很明確了, username:password
寫在 url 里是無法被 api-server 所解析的, 在舊集群上, 匿名請求不被允許, 所以收到 401, 瀏覽器(猜測)看到 401, 于是把驗(yàn)證信息放到 header 里再發(fā)了一個(gè)請求, 這一次驗(yàn)證通過了~~ 在新集群上, 由于第一次請求返回了 403, 所以瀏覽器也不會再去嘗試一次了舔清。
歸根結(jié)底,這還是之前使用 username:password
寫在 url 里這種驗(yàn)證方式埋下的坑可柿。這種方式已經(jīng)被廢棄, server 不解析也是合情合理的~