在 Jenkins 管道中创建和使用新凭证的最佳方式?
Best way to create and use new credential in Jenkins pipeline?
所以我正在构建一个 Jenkins 管道来供应 (Terraform)、配置 (Ansible) 并从我们的容器注册表中部署一组带有“最新”标签的容器。
前两个阶段运行良好。主机已配置并配置为 运行 Docker 个容器。我有 CA 证书、客户端证书和客户端密钥,我需要创建一个 DockerServerCredential,但我仍然不知道如何创建该凭据并在管道中使用它。换句话说,我不想在 Ansible 运行s 之后结束管道,手动将凭证添加到 Jenkins,然后启动另一个管道以使用新凭证部署容器。我想使用 CA、证书和密钥值在我的管道中创建一个 DockerServerCredential,然后将该凭证的名称传递给 docker.withServer()。
所以我知道我可以将它添加到我的 Jenkinsfile 中:
stage('Deploy') {
steps {
script {
def credName = "Docker-Cert-${env.OUT_VM_NAME}"
domain = com.cloudbees.plugins.credentials.domains.Domain.global()
store = Jenkins.instance.getExtensionList('com.cloudbees.plugins.credentials.SystemCredentialsProvider')[0].getStore()
dockerCertCred = new DockerServerCredentials(
CredentialsScope.GLOBAL,
credName,
'',
env.OUT_DCKR_CRED_KEY,
env.OUT_DCKR_CRED_CERT,
env.OUT_DCKR_CRED_CA
)
store.addCredentials(domain, dockerCertCred)
docker.withServer("tcp://${env.OUT_VM_NAME}:2376", credName) {
// things!
}
}
}
}
但我知道 doco 对 avoid using Jenkins.getInstance in a pipeline 说的最佳实践。 And 它会要求我将“staticMethod com.cloudbees.plugins.credentials.domains.Domain global”和“staticMethod jenkins.model.Jenkins getInstance”添加到 Script Approvals,我更喜欢 :/// .
所以我的问题是:你会怎么做?这里的最佳做法是什么?
P.S。我什至不需要保留凭据,所以如果有一个包装器可以创建临时凭据,那将是非常理想的,但我一直找不到。
P.P.S。以前没有创建过插件,希望我能避免这样做。
通过 Ansible 剧本中的 API 调用最终创建了凭据,这是创建密钥和证书的地方。
仍在使用面包屑而不是 API 标记以避免手动创建 API 标记。安装了 Strict Crumb Issuer plugin 以禁用会话 ID 检查并在面包屑上设置 1 小时到期。
- name: Get Jenkins Crumb
uri:
url: "{{ jenkins_host }}/crumbIssuer/api/json"
user: "{{ jenkins_user }}"
password: "{{ jenkins_password }}"
force_basic_auth: yes
return_content: yes
tags:
- always
register: crumb
when: add_credential | bool
- name: Fix newlines
set_fact:
ca_cert_value: "{{ ca_csr_content['content'] | b64decode | replace('\n', '\n') | replace('+', '%2B') }}"
client_cert_value: "{{ client_cert_content['content'] | b64decode | replace('\n', '\n') | replace('+', '%2B') }}"
client_key_value: "{{ client_key_content['content'] | b64decode | replace('\n', '\n') | replace('+', '%2B') }}"
- name: Add Jenkins Credential
uri:
method: POST
url: "{{ jenkins_host }}/credentials/store/system/domain/_/createCredentials"
user: "{{ jenkins_user }}"
password: "{{ jenkins_password }}"
force_basic_auth: yes
body_format: form-urlencoded
follow_redirects: all
headers:
Jenkins-Crumb: "{{ crumb.json | json_query('crumb') }}"
body: |
json={
"": "0",
"credentials": {
"scope": "GLOBAL",
"id": "Docker-Cert-{{ ansible_hostname }}",
"description": "",
"clientKeySecret": "{{ client_key_value }}",
"clientCertificate": "{{ client_cert_value }}",
"serverCaCertificate": "{{ ca_cert_value }}",
"$class": "org.jenkinsci.plugins.docker.commons.credentials.DockerServerCredentials"
}
}
when: add_credential | bool
所以我正在构建一个 Jenkins 管道来供应 (Terraform)、配置 (Ansible) 并从我们的容器注册表中部署一组带有“最新”标签的容器。
前两个阶段运行良好。主机已配置并配置为 运行 Docker 个容器。我有 CA 证书、客户端证书和客户端密钥,我需要创建一个 DockerServerCredential,但我仍然不知道如何创建该凭据并在管道中使用它。换句话说,我不想在 Ansible 运行s 之后结束管道,手动将凭证添加到 Jenkins,然后启动另一个管道以使用新凭证部署容器。我想使用 CA、证书和密钥值在我的管道中创建一个 DockerServerCredential,然后将该凭证的名称传递给 docker.withServer()。
所以我知道我可以将它添加到我的 Jenkinsfile 中:
stage('Deploy') {
steps {
script {
def credName = "Docker-Cert-${env.OUT_VM_NAME}"
domain = com.cloudbees.plugins.credentials.domains.Domain.global()
store = Jenkins.instance.getExtensionList('com.cloudbees.plugins.credentials.SystemCredentialsProvider')[0].getStore()
dockerCertCred = new DockerServerCredentials(
CredentialsScope.GLOBAL,
credName,
'',
env.OUT_DCKR_CRED_KEY,
env.OUT_DCKR_CRED_CERT,
env.OUT_DCKR_CRED_CA
)
store.addCredentials(domain, dockerCertCred)
docker.withServer("tcp://${env.OUT_VM_NAME}:2376", credName) {
// things!
}
}
}
}
但我知道 doco 对 avoid using Jenkins.getInstance in a pipeline 说的最佳实践。 And 它会要求我将“staticMethod com.cloudbees.plugins.credentials.domains.Domain global”和“staticMethod jenkins.model.Jenkins getInstance”添加到 Script Approvals,我更喜欢 :/// .
所以我的问题是:你会怎么做?这里的最佳做法是什么?
P.S。我什至不需要保留凭据,所以如果有一个包装器可以创建临时凭据,那将是非常理想的,但我一直找不到。
P.P.S。以前没有创建过插件,希望我能避免这样做。
通过 Ansible 剧本中的 API 调用最终创建了凭据,这是创建密钥和证书的地方。
仍在使用面包屑而不是 API 标记以避免手动创建 API 标记。安装了 Strict Crumb Issuer plugin 以禁用会话 ID 检查并在面包屑上设置 1 小时到期。
- name: Get Jenkins Crumb
uri:
url: "{{ jenkins_host }}/crumbIssuer/api/json"
user: "{{ jenkins_user }}"
password: "{{ jenkins_password }}"
force_basic_auth: yes
return_content: yes
tags:
- always
register: crumb
when: add_credential | bool
- name: Fix newlines
set_fact:
ca_cert_value: "{{ ca_csr_content['content'] | b64decode | replace('\n', '\n') | replace('+', '%2B') }}"
client_cert_value: "{{ client_cert_content['content'] | b64decode | replace('\n', '\n') | replace('+', '%2B') }}"
client_key_value: "{{ client_key_content['content'] | b64decode | replace('\n', '\n') | replace('+', '%2B') }}"
- name: Add Jenkins Credential
uri:
method: POST
url: "{{ jenkins_host }}/credentials/store/system/domain/_/createCredentials"
user: "{{ jenkins_user }}"
password: "{{ jenkins_password }}"
force_basic_auth: yes
body_format: form-urlencoded
follow_redirects: all
headers:
Jenkins-Crumb: "{{ crumb.json | json_query('crumb') }}"
body: |
json={
"": "0",
"credentials": {
"scope": "GLOBAL",
"id": "Docker-Cert-{{ ansible_hostname }}",
"description": "",
"clientKeySecret": "{{ client_key_value }}",
"clientCertificate": "{{ client_cert_value }}",
"serverCaCertificate": "{{ ca_cert_value }}",
"$class": "org.jenkinsci.plugins.docker.commons.credentials.DockerServerCredentials"
}
}
when: add_credential | bool