人訪問(wèn)令牌(PAT)創(chuàng)建與安全使用全指南)
1. 為什么你需要一個(gè)個(gè)人訪問(wèn)令牌如果你在命令行里用git push往 GitHub 推送代碼時(shí)突然彈出一個(gè)窗口讓你輸入用戶名和密碼而你明明記得密碼是對(duì)的卻死活登錄不上去那你大概率是遇到了 GitHub 在 2021 年 8 月 13 日之后實(shí)施的一項(xiàng)重大安全策略變更。簡(jiǎn)單來(lái)說(shuō)GitHub 不再支持使用賬戶密碼Password通過(guò) HTTPS 協(xié)議進(jìn)行 Git 操作認(rèn)證了。取而代之的就是今天我們要詳細(xì)拆解的主角——個(gè)人訪問(wèn)令牌。這個(gè)令牌英文叫 Personal Access Token你可以把它理解為你賬戶的一個(gè)“專用鑰匙”或者“臨時(shí)工牌”。和你的主密碼不同這把鑰匙的權(quán)限是你可以精細(xì)控制的。你可以只給它讀取倉(cāng)庫(kù)代碼的權(quán)限也可以給它寫(xiě)入、刪除倉(cāng)庫(kù)的權(quán)限甚至可以給它管理組織、訪問(wèn)包倉(cāng)庫(kù)等高級(jí)權(quán)限。最關(guān)鍵的是這把鑰匙是“一次性”的當(dāng)然可以設(shè)置有效期萬(wàn)一泄露了你可以隨時(shí)單獨(dú)吊銷這把鑰匙而無(wú)需修改你的主賬戶密碼其他用令牌訪問(wèn)的服務(wù)也不會(huì)受影響。所以無(wú)論你是需要在 CI/CD 流水線如 GitHub Actions, Jenkins中自動(dòng)拉取推送代碼還是用腳本調(diào)用 GitHub API 管理你的項(xiàng)目抑或是僅僅想在本地命令行里順暢地使用 Git創(chuàng)建并配置一個(gè)個(gè)人訪問(wèn)令牌都是你現(xiàn)在必須掌握的技能。這不僅是繞過(guò)密碼認(rèn)證限制的解決方案更是一種更安全、更現(xiàn)代的憑證管理實(shí)踐。2. 令牌創(chuàng)建前的核心決策權(quán)限與有效期直接跳到創(chuàng)建步驟很簡(jiǎn)單但如果不理解背后的選項(xiàng)你可能會(huì)創(chuàng)建出一個(gè)權(quán)限過(guò)大或過(guò)小的令牌埋下安全風(fēng)險(xiǎn)或?qū)е潞罄m(xù)操作失敗。因此在點(diǎn)擊“Generate token”按鈕之前我們必須先搞清楚兩個(gè)核心概念作用域和有效期。2.1 作用域給你的令牌劃定工作邊界作用域決定了這個(gè)令牌能干什么。GitHub 提供了非常細(xì)粒度的權(quán)限控制主要分為以下幾大類repo倉(cāng)庫(kù)這是最常用、最核心的權(quán)限。它下面又細(xì)分為repo完全控制私有和公共倉(cāng)庫(kù)的代碼、議題、拉取請(qǐng)求等。權(quán)限極大請(qǐng)謹(jǐn)慎授予。public_repo僅能訪問(wèn)公共倉(cāng)庫(kù)。repo:status僅能訪問(wèn)倉(cāng)庫(kù)的提交狀態(tài)常用于CI系統(tǒng)報(bào)告構(gòu)建狀態(tài)。repo_deployment訪問(wèn)部署狀態(tài)。repo:invite接受倉(cāng)庫(kù)邀請(qǐng)。security_events讀寫(xiě)安全事件用于代碼掃描。workflow工作流如果你使用 GitHub Actions需要這個(gè)權(quán)限來(lái)啟用、禁用工作流文件。write:packages / read:packages包管理用于向 GitHub Packages 推送或拉取容器鏡像、npm包等。delete_repo刪除倉(cāng)庫(kù)顧名思義允許刪除倉(cāng)庫(kù)。高危權(quán)限非必要不勾選。admin:org管理組織管理組織成員、團(tuán)隊(duì)等。通常用于自動(dòng)化管理腳本。user用戶訪問(wèn)用戶個(gè)人資料信息如郵箱。admin:public_key管理公鑰管理賬戶的 SSH 密鑰。admin:gpg_key管理GPG密鑰管理賬戶的 GPG 密鑰。實(shí)操心得最小權(quán)限原則我的經(jīng)驗(yàn)是永遠(yuǎn)遵循“最小權(quán)限原則”。如果你只是需要在本地命令行推送代碼到自己的私有倉(cāng)庫(kù)那么只勾選repo就足夠了。如果你為 CI/CD 流水線創(chuàng)建令牌并且這個(gè)流水線只需要拉取代碼和推送構(gòu)建狀態(tài)那么repo拉取代碼 repo:status推送狀態(tài)可能是更安全的選擇。絕對(duì)不要因?yàn)槭∈戮鸵还赡X地勾選所有權(quán)限這相當(dāng)于給了小偷一把萬(wàn)能鑰匙。2.2 有效期為令牌設(shè)置一個(gè)“保質(zhì)期”GitHub 允許你為令牌設(shè)置一個(gè)有效期這是一個(gè)非常重要的安全特性。選項(xiàng)通常包括7天30天90天自定義天數(shù)最長(zhǎng)不超過(guò)1年永不過(guò)期不推薦為什么強(qiáng)烈不建議選擇“永不過(guò)期”令牌一旦泄露就擁有了長(zhǎng)期有效的訪問(wèn)權(quán)限。設(shè)置有效期相當(dāng)于增加了一層時(shí)間防火墻。即使令牌不慎泄露攻擊者也只能在有效期內(nèi)作惡。到期后令牌自動(dòng)失效你需要?jiǎng)?chuàng)建新的這本身也是一次安全審計(jì)的機(jī)會(huì)。對(duì)于生產(chǎn)環(huán)境的自動(dòng)化流程我通常設(shè)置為90天并建立一個(gè)日歷提醒在到期前一周進(jìn)行輪換。對(duì)于臨時(shí)性的腳本或測(cè)試7天或30天就足夠了。3. 手把手創(chuàng)建你的第一個(gè)令牌理解了核心概念后我們進(jìn)入實(shí)操環(huán)節(jié)。請(qǐng)跟隨以下步驟在 GitHub 上創(chuàng)建你的第一個(gè)個(gè)人訪問(wèn)令牌。3.1 進(jìn)入令牌創(chuàng)建頁(yè)面登錄你的 GitHub 賬戶。點(diǎn)擊頁(yè)面右上角的你的頭像在下拉菜單中選擇“Settings”設(shè)置。在左側(cè)邊欄的最底部找到并點(diǎn)擊“Developer settings”開(kāi)發(fā)者設(shè)置。在左側(cè)邊欄中點(diǎn)擊“Personal access tokens”個(gè)人訪問(wèn)令牌。點(diǎn)擊“Tokens (classic)”或直接點(diǎn)擊“Generate new token”按鈕下的“Generate new token (classic)”。目前 GitHub 推薦新的細(xì)粒度令牌但經(jīng)典令牌更通用我們先從經(jīng)典的開(kāi)始。3.2 填寫(xiě)令牌信息與配置權(quán)限現(xiàn)在你會(huì)看到一個(gè)表單頁(yè)面。Note備注這里非常重要不要隨便填個(gè)“test”。請(qǐng)用一個(gè)清晰的名字描述這個(gè)令牌的用途例如“My-MacBook-Pro-Git-CLI”、“Company-CI-Jenkins-Production”、“Script-Auto-Create-Repo”。未來(lái)當(dāng)你擁有多個(gè)令牌時(shí)清晰的備注能幫你快速識(shí)別和管理。Expiration有效期根據(jù)我們之前的討論選擇一個(gè)合適的有效期。例如用于個(gè)人電腦的可以選擇“90天”。Select scopes選擇作用域滾動(dòng)權(quán)限列表根據(jù)你的需求勾選。對(duì)于最常見(jiàn)的“本地Git推送拉取”場(chǎng)景勾選“repo”這一個(gè)就夠了。它會(huì)自動(dòng)選中所有倉(cāng)庫(kù)相關(guān)的子權(quán)限。可選Repository access倉(cāng)庫(kù)訪問(wèn)如果你只想讓令牌訪問(wèn)特定倉(cāng)庫(kù)可以在這里選擇。默認(rèn)是“All repositories”。3.3 生成并安全保存令牌滾動(dòng)到頁(yè)面底部點(diǎn)擊綠色的“Generate token”按鈕。關(guān)鍵時(shí)刻頁(yè)面刷新后你會(huì)看到一個(gè)以ghp_開(kāi)頭的長(zhǎng)字符串新格式令牌以github_pat_開(kāi)頭。這個(gè)令牌只會(huì)在此刻顯示一次如果你刷新或離開(kāi)這個(gè)頁(yè)面就再也看不到它了。你必須立即將其復(fù)制并保存到安全的地方。我推薦的做法是密碼管理器存入 1Password、Bitwarden、LastPass 等密碼管理工具這是最安全的方式。本地加密文件如果你不使用密碼管理器可以將其保存在本地一個(gè)加密的文本文件或使用gpg加密。絕對(duì)禁止不要將其寫(xiě)入普通的文本文件不要提交到 Git 倉(cāng)庫(kù)不要通過(guò)明文郵件或聊天工具發(fā)送。復(fù)制保存后這個(gè)令牌就可以使用了。你可以在 “Personal access tokens” 列表頁(yè)面看到它但只能看到部分打碼的字符并可以隨時(shí)在這里將其吊銷。4. 在 Git 命令行中使用令牌創(chuàng)建好令牌后我們需要用它來(lái)替代密碼。Git 通過(guò) HTTPS 協(xié)議克隆或推送時(shí)用戶名是你的 GitHub 用戶名密碼就是這個(gè)令牌。4.1 首次克隆倉(cāng)庫(kù)當(dāng)你克隆一個(gè)私有倉(cāng)庫(kù)時(shí)在 URL 中直接嵌入令牌是最直接的方法僅用于一次性操作或腳本。git clone https://ghp_你的令牌內(nèi)容github.com/你的用戶名/倉(cāng)庫(kù)名.git例如git clone https://ghp_abc123def456github.com/zhangsan/my-private-repo.git4.2 為現(xiàn)有倉(cāng)庫(kù)配置遠(yuǎn)程認(rèn)證對(duì)于已經(jīng)克隆到本地的倉(cāng)庫(kù)或者你不想在URL中暴露令牌更推薦使用 Git 的憑證存儲(chǔ)助手。方法一使用緩存臨時(shí)git config --global credential.helper cache # 可以設(shè)置緩存時(shí)間默認(rèn)900秒15分鐘例如設(shè)置為1小時(shí) git config --global credential.helper cache --timeout3600設(shè)置后當(dāng)你下一次執(zhí)行g(shù)it pull或git push時(shí)會(huì)提示你輸入用戶名和密碼此處密碼填令牌。輸入一次后在緩存時(shí)間內(nèi)就不再需要輸入了。適合臨時(shí)使用。方法二使用系統(tǒng)存儲(chǔ)長(zhǎng)期這是更常用的方式令牌會(huì)安全地存儲(chǔ)在系統(tǒng)的密鑰鏈中。macOS:git config --global credential.helper osxkeychainLinux:git config --global credential.helper libsecret # 或 gnome-keyring, cache, storeWindows:git config --global credential.helper wincred配置好后執(zhí)行一次需要認(rèn)證的操作如git push在彈出的窗口或命令行中用戶名填你的 GitHub 用戶名密碼填剛才生成的個(gè)人訪問(wèn)令牌。之后系統(tǒng)就會(huì)記住這個(gè)憑證。方法三在遠(yuǎn)程 URL 中永久配置不推薦但需了解你也可以直接修改遠(yuǎn)程倉(cāng)庫(kù)的 URL將令牌寫(xiě)進(jìn)去。但這樣做令牌會(huì)以明文形式出現(xiàn)在.git/config文件中。git remote set-url origin https://ghp_你的令牌內(nèi)容github.com/你的用戶名/倉(cāng)庫(kù)名.git踩坑實(shí)錄認(rèn)證失敗的常見(jiàn)原因用戶名錯(cuò)誤密碼/令牌欄填對(duì)了但用戶名欄填的是郵箱地址或其他內(nèi)容。請(qǐng)確保用戶名是你的 GitHub 登錄用戶名通常不含郵箱域名。令牌權(quán)限不足如果你只勾選了public_repo卻試圖推送私有倉(cāng)庫(kù)就會(huì)失敗。檢查令牌的作用域。令牌已過(guò)期創(chuàng)建時(shí)設(shè)置了有效期到期后令牌自動(dòng)失效。去 GitHub 設(shè)置頁(yè)面檢查令牌狀態(tài)并創(chuàng)建新的。憑證助手沖突如果你之前用其他方式存儲(chǔ)了錯(cuò)誤的密碼系統(tǒng)可能會(huì)一直嘗試舊的錯(cuò)誤憑證??梢試L試清除緩存# 對(duì)于 cache git credential-cache exit # 或直接刪除全局配置重新設(shè)置 git config --global --unset credential.helper然后在執(zhí)行操作時(shí)重新輸入。5. 在自動(dòng)化腳本與 CI/CD 中安全使用令牌在自動(dòng)化環(huán)境中我們無(wú)法進(jìn)行交互式輸入因此需要將令牌以環(huán)境變量或配置文件的形式提供給腳本或 CI/CD 平臺(tái)。核心原則是絕對(duì)不要將令牌硬編碼在腳本或代碼倉(cāng)庫(kù)中。5.1 環(huán)境變量法推薦在運(yùn)行腳本的機(jī)器上將令牌設(shè)置為環(huán)境變量。# Linux/macOS export GITHUB_TOKENghp_你的令牌內(nèi)容 # 然后你的腳本或命令可以通過(guò) $GITHUB_TOKEN 引用它 # 例如使用 curl 調(diào)用 API curl -H Authorization: token $GITHUB_TOKEN https://api.github.com/user# Windows (PowerShell) $env:GITHUB_TOKENghp_你的令牌內(nèi)容 # 在同一個(gè) PowerShell 會(huì)話中生效5.2 在 CI/CD 平臺(tái)中配置以 GitHub Actions 為例GitHub Actions 提供了最安全的方式來(lái)使用令牌。使用內(nèi)置的GITHUB_TOKEN在每個(gè) GitHub Actions 工作流運(yùn)行時(shí)都會(huì)自動(dòng)生成一個(gè)臨時(shí)的GITHUB_TOKEN密鑰并擁有當(dāng)前倉(cāng)庫(kù)的默認(rèn)權(quán)限。你無(wú)需自己創(chuàng)建可以直接在 YAML 文件中使用${{ secrets.GITHUB_TOKEN }}。這是最安全、最推薦的方式因?yàn)樗詣?dòng)擁有最小權(quán)限且生命周期短暫。jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkoutv3 with: token: ${{ secrets.GITHUB_TOKEN }}使用自定義倉(cāng)庫(kù)密鑰如果你需要跨倉(cāng)庫(kù)訪問(wèn)或者需要GITHUB_TOKEN不具備的權(quán)限如訪問(wèn)其他倉(cāng)庫(kù)、管理組織則需要將自己創(chuàng)建的個(gè)人訪問(wèn)令牌添加到倉(cāng)庫(kù)的密鑰中。進(jìn)入你的 GitHub 倉(cāng)庫(kù)。點(diǎn)擊“Settings”-“Secrets and variables”-“Actions”。點(diǎn)擊“New repository secret”。Name 填寫(xiě)為MY_PAT或其他你喜歡的名字。Value 粘貼你的個(gè)人訪問(wèn)令牌。在工作流文件中通過(guò)${{ secrets.MY_PAT }}來(lái)引用它。env: MY_TOKEN: ${{ secrets.MY_PAT }} steps: - run: | echo Using token for API call curl -H Authorization: token $MY_TOKEN https://api.github.com/user/repos注意事項(xiàng)CI/CD 中的令牌安全永遠(yuǎn)不要echo或print令牌即使在 CI/CD 的日志中也要避免直接輸出令牌內(nèi)容。大多數(shù)平臺(tái)會(huì)自動(dòng)屏蔽以secret.方式引用的變量輸出但自己仍需小心。使用最小權(quán)限令牌為 CI/CD 創(chuàng)建的令牌權(quán)限應(yīng)精確到所需的最小范圍。如果只是拉取代碼可能連repo的寫(xiě)權(quán)限都不需要可以考慮更細(xì)的權(quán)限或使用actions/checkout等官方 Action。定期輪換為 CI/CD 設(shè)置的令牌也應(yīng)設(shè)置有效期并建立流程定期更新倉(cāng)庫(kù)密鑰中的值。6. 令牌的進(jìn)階管理與安全實(shí)踐創(chuàng)建和使用令牌只是第一步良好的管理習(xí)慣才能確保長(zhǎng)期的安全。6.1 令牌的日常管理回到 GitHub 的“Settings” - “Developer settings” - “Personal access tokens”頁(yè)面這里是你管理所有令牌的控制臺(tái)。查看與識(shí)別你可以看到所有活躍的令牌列表包括備注名、權(quán)限范圍、上次使用時(shí)間和過(guò)期時(shí)間。清晰的備注名至關(guān)重要。吊銷令牌如果某個(gè)令牌泄露或不再需要立即點(diǎn)擊對(duì)應(yīng)的“Revoke”按鈕。這是令牌相比密碼的最大優(yōu)勢(shì)——定點(diǎn)清除不影響其他服務(wù)。權(quán)限復(fù)審定期例如每季度回顧令牌列表檢查每個(gè)令牌是否還有存在的必要其權(quán)限是否仍然合適。6.2 啟用雙因素認(rèn)證提升賬戶安全個(gè)人訪問(wèn)令牌是認(rèn)證的一種方式而保護(hù)生成令牌的源頭——你的 GitHub 賬戶——同樣重要。強(qiáng)烈建議為你的 GitHub 賬戶啟用雙因素認(rèn)證。啟用 2FA 后即使你的密碼泄露攻擊者沒(méi)有你的第二因素如手機(jī)驗(yàn)證碼、安全密鑰也無(wú)法登錄從而無(wú)法創(chuàng)建新的令牌或管理現(xiàn)有令牌。這為你的賬戶增加了一道堅(jiān)固的防線。你可以在“Settings” - “Password and authentication”中設(shè)置 2FA。6.3 令牌泄露的應(yīng)急處理如果你懷疑或確認(rèn)某個(gè)令牌已經(jīng)泄露例如發(fā)現(xiàn)未知的倉(cāng)庫(kù)操作、API調(diào)用請(qǐng)立即執(zhí)行以下步驟立即吊銷泄露的令牌在令牌管理頁(yè)面找到它并點(diǎn)擊“Revoke”。這會(huì)立即使該令牌失效所有使用該令牌的客戶端和服務(wù)將立即失去訪問(wèn)權(quán)限。審查日志在“Settings” - “Security” - “Security log”中查看賬戶的完整活動(dòng)日志。篩選相關(guān)時(shí)間段的操作確認(rèn)是否有未授權(quán)的活動(dòng)。輪換相關(guān)憑證如果該令牌用于 CI/CD 或其他重要服務(wù)在吊銷舊令牌后需要立即創(chuàng)建新令牌并更新所有使用該令牌的服務(wù)配置。評(píng)估影響根據(jù)令牌的權(quán)限范圍檢查是否有倉(cāng)庫(kù)被惡意修改、是否有敏感信息被竊取、是否有未知的部署或包發(fā)布。必要時(shí)回滾代碼或數(shù)據(jù)。7. 經(jīng)典令牌與細(xì)粒度令牌的選擇在創(chuàng)建令牌時(shí)你可能注意到了 GitHub 在推廣新的“細(xì)粒度個(gè)人訪問(wèn)令牌”。這里簡(jiǎn)單對(duì)比一下幫助你做選擇特性經(jīng)典個(gè)人訪問(wèn)令牌細(xì)粒度個(gè)人訪問(wèn)令牌權(quán)限模型粗粒度基于預(yù)定義的作用域如repo,admin:org。一個(gè)作用域內(nèi)權(quán)限全有或全無(wú)。極細(xì)粒度可以精確到單個(gè)倉(cāng)庫(kù)的讀/寫(xiě)權(quán)限甚至倉(cāng)庫(kù)內(nèi)特定區(qū)域如議題、拉取請(qǐng)求。資源訪問(wèn)通常可以訪問(wèn)用戶有權(quán)訪問(wèn)的所有資源如所有倉(cāng)庫(kù)。創(chuàng)建時(shí)必須指定可以訪問(wèn)的特定倉(cāng)庫(kù)或所有倉(cāng)庫(kù)權(quán)限在資源上也是細(xì)分的。有效期最長(zhǎng)1年或永不過(guò)期。最長(zhǎng)1年不能設(shè)置為永不過(guò)期。適用場(chǎng)景通用場(chǎng)景需要訪問(wèn)多個(gè)倉(cāng)庫(kù)或?qū)挿簷?quán)限的自動(dòng)化腳本、命令行工具。對(duì)安全性要求極高的場(chǎng)景需要將權(quán)限限制在特定倉(cāng)庫(kù)和特定操作例如只為某個(gè)第三方應(yīng)用授權(quán)訪問(wèn)單個(gè)倉(cāng)庫(kù)的議題。當(dāng)前狀態(tài)仍可使用但 GitHub 可能會(huì)在未來(lái)停止支持。GitHub 推薦使用代表更現(xiàn)代的、更安全的權(quán)限管理方向。個(gè)人建議對(duì)于個(gè)人在命令行中使用或者需要寬泛權(quán)限的自動(dòng)化腳本例如管理自己所有倉(cāng)庫(kù)的腳本經(jīng)典令牌目前更簡(jiǎn)單直接。對(duì)于授予第三方應(yīng)用集成或者CI/CD 中需要訪問(wèn)特定倉(cāng)庫(kù)的場(chǎng)景強(qiáng)烈建議使用細(xì)粒度令牌。它能實(shí)現(xiàn)最小權(quán)限原則的極致大幅降低安全風(fēng)險(xiǎn)。長(zhǎng)遠(yuǎn)來(lái)看逐漸遷移到細(xì)粒度令牌是更佳實(shí)踐。創(chuàng)建細(xì)粒度令牌的流程類似只是在權(quán)限選擇界面變成了可逐項(xiàng)展開(kāi)的、按倉(cāng)庫(kù)和權(quán)限類型勾選的樹(shù)狀結(jié)構(gòu)更加直觀。創(chuàng)建和管理個(gè)人訪問(wèn)令牌從最初的“繞過(guò)密碼認(rèn)證的權(quán)宜之計(jì)”已經(jīng)演變?yōu)楝F(xiàn)代開(kāi)發(fā)工作流中不可或缺的安全憑證管理環(huán)節(jié)。理解其原理謹(jǐn)慎分配權(quán)限妥善保管并定期審計(jì)這些習(xí)慣能讓你的自動(dòng)化流程既高效又穩(wěn)固。下次當(dāng)你的git push遇到認(rèn)證問(wèn)題時(shí)你應(yīng)該能從容地打開(kāi) GitHub 設(shè)置頁(yè)面生成一把合適的“鑰匙”并知道如何安全地使用它了。