AzureDevOps - 關於 SSH Key
前言
這幾天,遇到一個很有趣的問題,原本不想記錄的 XDDD,但覺得實在太有趣了,所以紀錄一下,不然大概過 21 天後,大概就忘記了 ( 誤 ),而且 Google 要查到我這種特殊的情況,可能也查不到 ( 但有類似的~ ),所以想說,那就把關於 SSH Public Key 的豆知識,簡單紀錄一下。
問題 SSH Public Key 重複
這個的問題起源在如下圖,我使用了 SkyS 帳號,登入 S Organization,想加入 SSH Public Key,但他出現了底下的錯誤。
An error occurred while adding the Macbook key: It may be a duplicate of another key. Please check the current list and try again.
簡單的說,就是這個 Key 已經重複了,所以不能新增,請確認列表。但...等等啊,底下是空的啊啊啊啊!!!!!
好,基本上,這就是問題的起源。
來看看 Azure DevOps Public Key 的機制
首先,根據小弟查到的資料,在 Azure DevOps Service 的 Public Key 機制,不同帳號的 Public Key 是不可重複的,所以,其實網路上,有些人遇到上述的狀況。一個原因就是,很不幸的,剛好你的 Key 和別人的 Key 重複到 ( 買樂透都沒那麼準 ),另外一種狀況就是,自己可能用了別的帳號,並且將 SSH Public Key 填入,但忘記了 ( 這小弟自己倒是滿容易遇到的 XDD )。
所以,遇到這一個問題,最簡單的解法,重新產生一個 SSH Public Key,或是用盡荒蕪之力,想出以前是否有用這個 Key 註冊過。
好玩的問題
知道了這個限制後,小弟用了荒蕪之力,想到我有另外一個帳號 SkyM,因為已經在其他的 Organization 上 ( M Organization ) ,用了這個 Key,所以自然在 SkyA 的 S Organization ,不能註冊 SSH Public Key。
好,那我就用 SkyM 帳號,去登入 S Organization,並註冊 SSH Public Key,總可以了吧!!!
結果..... 使用 SkyM 帳號去 S Organization 還是不行啊!!!!!!!!! ( 翻 )
真正的答案
後來發現,不行的原因,是因為,在 S Organization 的 SkyM 帳號,和 M Organization 的 SkyM 帳號,雖然 EMail 完全一樣,但實際上完全不一樣 Orz...
乍看下,都一樣,但其實 S Organization 有加入 Study4.TW 的 AAD
所以~~
- S Organization - SkyM 代表的是 Study4.TW 的 SkyM 帳號
- M Organization - SkyM 代表的是 另外一個 AAD 的 SkyM 帳號
所以雖然 EMail 一樣,但本質是不一樣的,也因此在 S Organization 使用 SkyM 帳號來註冊 SSH Public Key,依舊是錯誤,因為會被 Azure DevOps Service 認為是不同的帳號。
另外,在延伸一下,小弟還有一個 P Organization,裡面也有 SkyM 帳號,而這時 M Organization - SkyM 和 P Organization - SkyM 都是可以正常重複註冊 SSH Public Key 的,但其實 M Organization 也是有加入 AAD,而 P Organization 沒有加入 AAD,為什麼可以 ??
原因是因為 P Organization 因為沒有加入 AAD,所以等同於 M Organization 的 SkyM,因為都是同一個 ( 都是 AAD 原生的 ),而 S Organization 的 Study4.TW AAD 為了要讓 SkyM 加入,但又不是同一個 AAD,所以 SkyM 其實不是原生的 AAD 加入進去,而是以 Study4.TW 來賓的身份加入,也因此形成了不一樣的結果。
所以~
- S Organization - SkyM 代表的是 Study4.TW 的 SkyM 帳號 ( 為 Study4.TW 的來賓帳號 )
- M Organization - SkyM 代表的是 另外一個 AAD 的 SkyM 帳號 ( 原生的 AAD 帳號 )
- P Organization - SkyM 此組織沒加入 AAD,所以直接使用原生的 AAD SkyM 帳號 ( 原生的 AAD 帳號 )
但是,以上的情境,目前測試下來,有一個例外...
那就是原生的 Microsoft Account ... ( Hotmail , livemail 等....),目前測試的情況下,若遇到 MSA 帳號,這個 MSA 帳號無論加到哪個 AAD 裡面,還是都可以加入 SSH Public Key,這是滿特別的現象...
Note : 不要想說刪掉 SSH Public Key 就可以重複使用喔 XDDD,就算已經刪掉,還是不能和那個被刪掉的重複~~
Note : 我有用 REST API 去取得 originId,的確,在 SkyM 的帳號下, M , P Organization 的 ID 是一樣的,而 S Organization 則不同,但 MSA 情境下,originId 雖然全部不同,但還是可以新增,或許有什麼沒猜想到的邏輯吧。
解法
當然,還是有解法。那就是產生不同的 SSH Public Key,來對應不同的 Organization。
我們可以在 SSH Public Key 的目錄底下 ( 通常為 .ssh 目錄底下 ) 加入 config 檔案,內容如下:
這邊利用了別名的方式來處理,分別為
- devopsfabrikam 對應到 ~/.ssh/privatekeyforfabrikam
- devopscontoso 對應到 ~/.ssh/privatekeyforcontoso
但因為對於 Azure DevOps Service 下,位置都是一樣 ( ssh.dev.azure.com ),所以 HostName 不變。 但其實因為 SSH Public Key 切開了,所以就可以分別用到不同的 Organization 底下。
不過這個做法有一個壞處,就是 Git Remote 的位置,要改成上述的別名。
- git@devopsfabrikam:v3/Fabrikam/Project1/fabrepo
- git@devopscontoso:v3/Contoso/Project2/conrepo
不過,至少也是官方文件的標準解法。
# The settings in each Host section are applied to any Git SSH remote URL with a
# matching hostname.
# Generally:
# * SSH uses the first matching line for each parameter name, e.g. if there's
# multiple values for a parameter across multiple matching Host sections
# * "IdentitiesOnly yes" prevents keys cached in ssh-agent from being tried before
# the IdentityFile values we explicitly set.
# * On Windows, ~/.ssh/your_private_key maps to %USERPROFILE%\.ssh\your_private_key,
# e.g. C:\Users\<username>\.ssh\your_private_key.
# Most common scenario: to use the same key across all hosted Azure DevOps
# organizations, add a Host entry like this:
Host ssh.dev.azure.com
IdentityFile ~/.ssh/id_rsa
IdentitiesOnly yes
# This model will also work if you still use the older SSH URLs with a
# hostname of vs-ssh.visualstudio.com:
Host vs-ssh.visualstudio.com
IdentityFile ~/.ssh/id_rsa
IdentitiesOnly yes
# Less common scenario: if you need different keys for different organizations,
# you'll need to use host aliases to create separate Host sections.
# This is because all hosted Azure DevOps URLs have the same hostname
# (ssh.dev.azure.com), so SSH has no way to distinguish them by default.
#
# Imagine that we have the following two SSH URLs:
# * git@ssh.dev.azure.com:v3/Fabrikam/Project1/fab_repo
# * For this, we want to use `fabrikamkey`, so we'll create `devops_fabrikam` as
# a Host alias and tell SSH to use `fabrikamkey`.
# * git@ssh.dev.azure.com:v3/Contoso/Project2/con_repo
# * For this, we want to use `contosokey`, so we'll create `devops_contoso` as
# a Host alias and tell SSH to use `contosokey`.
#
# To set explicit keys for the two host aliases and to tell SSH to use the correct
# actual hostname, add the next two Host sections:
Host devops_fabrikam
HostName ssh.dev.azure.com
IdentityFile ~/.ssh/private_key_for_fabrikam
# IdentitiesOnly yes
Host devops_contoso
HostName ssh.dev.azure.com
IdentityFile ~/.ssh/private_key_for_contoso
IdentitiesOnly yes
#
# Then, instead of using the real URLs, tell Git you want to use these URLs:
# * git@devops_fabrikam:v3/Fabrikam/Project1/fab_repo
# * git@devops_contoso:v3/Contoso/Project2/con_repo
#
# At the end of the file, you can put global defaults for other SSH hosts you
# may connect to. Note that "*" also matches any hosts that match the sections
# above, and remember that SSH uses the first matching line for each parameter name.
Host *
後記
滿有意思的一個問題,其實開始找問題的時候,一直圍繞在,為什麼不能使用,當下也認定了,可能是因為就算帳號不同,Key 可能也不能相同的錯誤認真,後來看了 config 裡面的 to use the same key across all hosted Azure DevOps organizations, add a Host entry like this:
才重新思考,是不是有哪個細節錯了,所以有了這篇文章的產生。但畢竟這是實驗出來的結果,小弟是沒找到任何的文件敘述,也沒辦法看 Source Code,所以這邊就給大家一個參考方向... ( 或許文章還是錯的呢 QQ ),但至少目前從這個方向,是解決了小弟的問題,或許有一日,遇到 Azure DevOps 的工程師,到時候再問問看,有沒有正確解答 XDDD
總之,結案!! 謝謝大家~~
參考資料
- https://danielwertheim.se/help-i-need-multiple-accounts-and-ssh-keys-to-the-same-git-provider/
- https://medium.com/@benjamintodts/using-different-ssh-keys-in-a-multitenant-git-remote-4a9b04db2e43
- https://docs.microsoft.com/en-us/azure/devops/repos/git/use-ssh-keys-to-authenticate?view=azure-devops#migrate