但是我不知道如何在我的构建管道中的脚本步骤中访问服务连接。例如,假设我有一个代表Azure Service Principal凭证的服务连接。我想在脚本步骤中访问这些凭证。
我该如何编写一个利用它们的脚本步骤?
我也一直在思考这个问题。我解决的方法是使用'Azure CLI'任务而不是基本的'Script'(或'Bash')任务。这主要用于运行Az CLI命令,但你也可以运行标准的Bash脚本(或者如果你喜欢PSCore)。
如果你检查运行此任务时存在的环境变量,你将看到一堆关于服务连接的信息,前缀为'ENDPOINT_DATA_'的变量与Josh E所说的相符。它包括Azure订阅ID、名称、服务原则对象ID等。
可选地,你也可以使服务原则详细信息添加到环境中。这将包括SPN密钥、TenantID等作为秘密环境变量。
下面是任务的样子:
- task: AzureCLI@2
displayName: 'Azure CLI'
inputs:
scriptType: bash
scriptLocation: inlineScript
azureSubscription: '<Service Connection Name>'
inlineScript: |
env | sort
- task: AzureCLI@2
displayName: 'Azure CLI, with SPN info'
inputs:
scriptType: bash
scriptLocation: inlineScript
azureSubscription: '<Service Connection Name>'
addSpnToEnvironment: true
inlineScript: |
env | sort
当然,这一切仅适用于Azure云服务连接。您可能会对其他服务连接使用类似的技术,但我还没有进行调查。
name
字符串通过以下正则表达式获取结果环境键的值来检索服务连接:
process.env [name.replace(/\./g, '_').toUpperCase()];
各种服务端点数据的检索被包装在vsts-task-lib/task module中,使得消费任务可以编写如下代码:taskLib.getEndpointAuthorization('SYSTEMVSSCONNECTION', false);
taskLib.getEndpointDataParameter('MYSERVICECONNECTION', 'SOME_PARAMETER_NAME', false);
taskLib.getEndpointUrl('MYSERVICECONNECTION', false) // <-- last param indicates required or not
因此,如果您想要在bash脚本中访问服务连接而不需要进行任何其他自定义,则建议您:system.debug
环境变量。有一些迹象表明,构建任务没有“种子”与它们没有明确请求的连接,因此您可能需要创建一个自定义构建任务,其中之一是其输入的服务连接名称您想要使用的 var dataParam = getVariable('ENDPOINT_DATA_' + id + '_' + key.toUpperCase());
您可能需要反复迭代来确定数据模式/结构。
- task: Kubernetes@1
displayName: 'Kubernetes Login'
# This is needed to run kubectl command from bash.
inputs:
connectionType: 'Kubernetes Service Connection'
kubernetesServiceEndpoint: '<Service Connection Name>'
command: 'login'
- task: Bash@3
displayName: 'Run Component Test'
inputs:
targetType: 'inline'
script: |
#Get the Node Port
nodePort=`kubectl get --namespace $(Build.BuildId) svc <service name> -o=jsonpath='{.spec.ports[0].nodePort}'`
#Run Newman test
newman run postman/Service.postman_collection.json --global-var host=$KUBERNETESNODE --global-var protocol=$SERVICEPROTOCOL --global-var port=$nodePort -r junit
kubectl config set-context
命令设置您的命名空间。 - Joe Kampfparameters:
- name: azureSubscription
type: string
- name: exportAsOutput
type: boolean
default: false
steps:
- task: AzureCLI@2
name: exported_azure_credentials
displayName: 'Export Azure Credentials'
inputs:
azureSubscription: '${{ parameters.azureSubscription }}'
scriptType: pscore
scriptLocation: inlineScript
addSpnToEnvironment: true
${{ if eq(parameters.exportAsOutput, true) }}:
inlineScript: |
Write-Host "##vso[task.setvariable variable=AZURE_TENANT_ID]$env:tenantId"
Write-Host "##vso[task.setvariable variable=AZURE_TENANT_ID;isOutput=true]$env:tenantId"
Write-Host "##vso[task.setvariable variable=AZURE_CLIENT_ID]$env:servicePrincipalId"
Write-Host "##vso[task.setvariable variable=AZURE_CLIENT_ID;isOutput=true]$env:servicePrincipalId"
Write-Host "##vso[task.setvariable variable=AZURE_CLIENT_SECRET]$env:servicePrincipalKey"
Write-Host "##vso[task.setvariable variable=AZURE_CLIENT_SECRET;isOutput=true]$env:servicePrincipalKey"
${{ if eq(parameters.exportAsOutput, false) }}:
inlineScript: |
Write-Host "##vso[task.setvariable variable=AZURE_TENANT_ID]$env:tenantId"
Write-Host "##vso[task.setvariable variable=AZURE_CLIENT_ID]$env:servicePrincipalId"
Write-Host "##vso[task.setvariable variable=AZURE_CLIENT_SECRET]$env:servicePrincipalKey"
DevOps 在处理秘密信息时非常聪明,因此这些信息不会出现在管道日志中。
new DefaultAzureCredential()
进行身份验证可以正常工作了!真是疯狂,'azureSubscription'输入在那里不被认可。 - Aaron Burke正如其他人所述,没有一个很好的内置方式来使用脚本访问Service Connections。因为我不喜欢通过长期存在的环境变量暴露凭据(出于安全和懒惰的原因),所以我编写了一个扩展,允许您使用自定义脚本和Generic Service Connection:https://marketplace.visualstudio.com/items?itemName=cloudpup.authenticated-scripts
此扩展通过将服务连接公开为环境变量实现,这些变量仅在单个脚本任务的生命周期内存在:
服务连接变量 | 环境变量 |
---|---|
url | AS_SC_URL |
username | AS_SC_USERNAME |
password | AS_SC_PASSWORD |
此扩展包含的任务使您可以编写简洁的流水线,例如以下内容:
steps:
- task: AuthenticatedPowerShell@1
inputs:
serviceConnection: 'Testing Authenticated Shell'
targetType: inline
script: 'Write-Host "url: $env:AS_SC_URL | username: $env:AS_SC_USERNAME | password: $env:AS_SC_PASSWORD"'
是的,这是可以实现的,我经常使用这种方法。您首先需要一个任务,该任务将凭据输出到环境变量中,然后您可以从任务输出的环境变量创建自己的变量。我通常使用 AzureCLI:
# Set Variables.
- task: AzureCLI@2
name: setVariables
displayName: Set Output Variables
continueOnError: false
inputs:
azureSubscription: nameOfAzureServiceConnection
scriptType: ps
scriptLocation: inlineScript
addSpnToEnvironment: true # this must be set to true
inlineScript: |
Write-Host "##vso[task.setvariable variable=azureClientId;isOutput=true]$($env:servicePrincipalId)"
Write-Host "##vso[task.setvariable variable=azureClientSecret;isOutput=true]$($env:servicePrincipalKey)"
Write-Host "##vso[task.setvariable variable=azureTenantId;isOutput=true]$($env:tenantId)"
接下来,您可以在下一步中使用您设置的这些新变量,请确保您使用任务名称调用变量,如$(taskName.variableName)。以下示例使用新变量在后续的PowerShell任务中设置环境变量,以供Terraform进行身份验证:
- PowerShell: |
terraform plan -input=false -out=tfplan
displayName: 'Terraform Plan'
env:
ARM_CLIENT_ID: $(setVariables.azureClientId)
ARM_CLIENT_SECRET: $(setVariables.azureClientSecret)
ARM_TENANT_ID: $(setVariables.azureTenantId)
- task: AzurePowerShell@5
inputs:
azureSubscription: 'AzureServiceConnection'
ScriptType: 'InlineScript'
Inline: |
$token = Get-AzAccessToken
echo "##vso[task.setvariable variable=accesstoken;]$($token.Token)"
azurePowerShellVersion: 'LatestVersion'
- script: 'echo This is the token: $(accesstoken)'