我正在尝试创建一个 python 脚本来与 Azure DevOps 交互,但在身份验证方面遇到问题。我不想使用 PAT。当我尝试使用
DefaultAzureCredential
中的 azure.identity
时,出现以下错误:
“DefaultAzureCredential”对象没有属性“signed_session”
from azure.identity import DefaultAzureCredential
from azure.devops.connection import Connection
credential = DefaultAzureCredential()
connection = Connection(base_url="https://dev.azure.com/org_name", creds=credential)
core_client = connection.clients.get_core_client()
projects = core_client.get_projects()
我找到了另一种方法。这有效,但我注意到建议使用
azure.identity
而不是 azure.common.credentials.get_azure_cli_credentials()
。
from azure.common.credentials import get_azure_cli_credentials
from azure.devops.connection import Connection
credential = get_azure_cli_credentials()[0]
connection = Connection(base_url="https://dev.azure.com/org_name", creds=credential)
core_client = connection.clients.get_core_client()
projects = core_client.get_projects()
我做错了什么
azure.identity
还是有更好的方法?
我有一个名为
sridevOpsdemo
的 Azure DevOps 组织,包含以下项目:
当我运行与你相同的Python代码来列出项目时,我得到了同样的错误:
from azure.identity import DefaultAzureCredential
from azure.devops.connection import Connection
credential = DefaultAzureCredential()
connection = Connection(base_url="https://dev.azure.com/org_name", creds=credential)
core_client = connection.clients.get_core_client()
projects = core_client.get_projects()
回复:
或者,您可以为 DevOps 生成 Azure AD 访问令牌 如果您不想使用 PAT 令牌,请使用 API。
我注册了一个 Azure AD 应用程序并授予了 同意 DevOps 权限:
现在,我通过运行下面的 python 代码使用用户名密码流程生成了访问令牌:
import msal
import requests
organization_url = "https://dev.azure.com/org_name/"
tenant_id = "tenant_id"
client_id = "app_id"
username = "[email protected]"
password = "xxxxxxxx"
scopes = ["499b84ac-1321-427f-aa17-267ca6975798/.default"]
authority = f"https://login.microsoftonline.com/{tenant_id}"
app = msal.PublicClientApplication(client_id=client_id, authority=authority)
result = app.acquire_token_by_username_password(
username=username,
password=password,
scopes=scopes,
)
if "error" in result:
print(f"Authentication error: {result['error']}")
else:
access_token = result.get("access_token")
print(access_token)
回复:
要确认,您可以通过将上述令牌粘贴到jwt.ms中来解码并检查
aud
和scp
声明,如下所示:
您可以通过修改代码中的api_url
,使用上述访问令牌调用任何
DevOps REST API查询,如下所示:
import msal
import requests
organization_url = "https://dev.azure.com/org_name/"
tenant_id = "tenant_id"
client_id = "app_id"
username = "[email protected]"
password = "xxxxxxxx"
scopes = ["499b84ac-1321-427f-aa17-267ca6975798/.default"]
authority = f"https://login.microsoftonline.com/{tenant_id}"
app = msal.PublicClientApplication(client_id=client_id, authority=authority)
result = app.acquire_token_by_username_password(
username=username,
password=password,
scopes=scopes,
)
if "error" in result:
print(f"Authentication error: {result['error']}")
else:
access_token = result.get("access_token")
print(access_token)
headers = {
'Authorization': f'Bearer {access_token}'
}
# List all projects in organization
api_url = f"{organization_url}/_apis/projects"
response = requests.get(api_url, headers=headers)
if response.status_code == 200:
projects = response.json()['value']
print("\nProject Names:")
for project in projects:
print(project['name'])
print()
else:
print(f"Failed to retrieve projects. Status Code: {response.status_code}, Message: {response.text}")
回复:
参考: 无需用户的 DevOps PAT 即可对 Azure DevOps 进行身份验证 - Stack Overflow,作者:wade Zhou - MSFT
我注意到在一些地方(az devops CLI 扩展、Azure SDK for Python、az CLI)使用了
msrest
库。该库被标记为已弃用,但如果 Microsoft 使用它,我认为使用它是有意义的,直到通过 Azure DevOps SDK 可以使用 DefaultAzureCredential。我设法通过将令牌从 msrest.authentication 传递到 BasicTokenAuthentication 来创建一个凭据对象。
from azure.identity import DefaultAzureCredential
from msrest.authentication import BasicTokenAuthentication
from azure.devops.connection import Connection
credential = DefaultAzureCredential()
token = credential.get_token('499b84ac-1321-427f-aa17-267ca6975798/.default')
credentials = BasicTokenAuthentication({'access_token': token.token})
organization_url = 'https://dev.azure.com/myorg'
connection = Connection(base_url=organization_url, creds=credentials)
core_client = connection.clients.get_core_client()
get_projects_response = core_client.get_projects()
if get_projects_response:
for project in get_projects_response:
print(project.name)
输出:
myproject
当 PAT 替换为令牌时,使用 PAT 的文档中的示例也适用