ดังที่ @Connor McCarthy กล่าวขณะที่รอให้ Amazon หาวิธีแก้ปัญหาที่ดีกว่าสำหรับรหัสถาวรที่มากขึ้นในเวลาที่เราต้องการสร้างคีย์บนเซิร์ฟเวอร์ Jenkins
โซลูชันของฉันคือการมีงานเป็นระยะซึ่งจะอัปเดตข้อมูลรับรอง Jenkins สำหรับ ECR ทุก 12 ชั่วโมงโดยอัตโนมัติโดยใช้ Groovy API นี่เป็นคำตอบที่ละเอียดมากแม้ว่าฉันจะทำบางสิ่งที่แตกต่างออกไปและฉันก็ต้องแก้ไขสคริปต์
ขั้นตอน:
- ตรวจสอบให้แน่ใจว่า Jenkins master ของคุณสามารถเข้าถึง AWS API ที่ต้องการ ในการตั้งค่าของฉันอาจารย์เจนกินส์กำลังทำงานบน EC2 ที่มีบทบาท IAM ดังนั้นฉันต้องเพิ่มสิทธิ์
ecr:GetAuthorizationToken
ให้กับบทบาทเซิร์ฟเวอร์ [ อัปเดต ] หากต้องการรับดันใด ๆ ecr:InitiateLayerUpload, ecr:UploadLayerPart, ecr:CompleteLayerUpload, ecr:BatchCheckLayerAvailability, ecr:PutImage
เสร็จสมบูรณ์เรียบร้อยแล้วคุณยังจะต้องให้สิทธิ์เหล่านี้: Amazon AmazonEC2ContainerRegistryPowerUser
มีในตัวนโยบายที่มีความสามารถเหล่านี้เรียกว่า
- ตรวจสอบให้แน่ใจว่าได้ติดตั้ง AWS CLI บนต้นแบบแล้ว ในการตั้งค่าของฉันเมื่อมาสเตอร์ทำงานในคอนเทนเนอร์ debian docker ฉันเพิ่งเพิ่มขั้นตอนการสร้างเชลล์นี้ไปยังงานสร้างคีย์:
dpkg -l python-pip >/dev/null 2>&1 || sudo apt-get install python-pip -y; pip list 2>/dev/null | grep -q awscli || pip install awscli
- ติดตั้งปลั๊กอิน Groovyที่ให้คุณเรียกใช้สคริปต์ Groovy ซึ่งเป็นส่วนหนึ่งของระบบ Jenkins
- ในหน้าจอข้อมูลรับรองให้มองหาคีย์ AWS ECR ของคุณคลิก "ขั้นสูง" และบันทึก "ID" สำหรับตัวอย่างนี้ฉันจะสมมติว่า "12345"
- สร้างงานใหม่ด้วยการเปิดตัวเป็นระยะเวลา 12 ชั่วโมงและเพิ่มขั้นตอนการสร้าง "ระบบ Groovy script" ด้วยสคริปต์ต่อไปนี้:
import jenkins.model.*
import com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl
def changePassword = { username, new_password ->
def creds = com.cloudbees.plugins.credentials.CredentialsProvider.lookupCredentials(
com.cloudbees.plugins.credentials.common.StandardUsernameCredentials.class,
Jenkins.instance)
def c = creds.findResult { it.username == username ? it : null }
if ( c ) {
println "found credential ${c.id} for username ${c.username}"
def credentials_store = Jenkins.instance.getExtensionList(
'com.cloudbees.plugins.credentials.SystemCredentialsProvider'
)[0].getStore()
def result = credentials_store.updateCredentials(
com.cloudbees.plugins.credentials.domains.Domain.global(),
c,
new UsernamePasswordCredentialsImpl(c.scope, "12345", c.description, c.username, new_password))
if (result) {
println "password changed for ${username}"
} else {
println "failed to change password for ${username}"
}
} else {
println "could not find credential for ${username}"
}
}
println "calling AWS for docker login"
def prs = "/usr/local/bin/aws --region us-east-1 ecr get-login".execute()
prs.waitFor()
def logintext = prs.text
if (prs.exitValue()) {
println "Got error from aws cli"
throw new Exception()
} else {
def password = logintext.split(" ")[5]
println "Updating password"
changePassword('AWS', password)
}
โปรดทราบ:
- การใช้สตริงฮาร์ดโค้ด
"AWS"
เป็นชื่อผู้ใช้สำหรับข้อมูลรับรอง ECR - นี่คือการทำงานของ ECR แต่ถ้าคุณมีข้อมูลรับรองหลายชื่อด้วยชื่อผู้ใช้ "AWS" คุณจะต้องอัปเดตสคริปต์เพื่อค้นหาข้อมูลรับรองตาม ฟิลด์คำอธิบายหรือบางอย่าง
- คุณต้องใช้ ID จริงของคีย์ ECR จริงของคุณในสคริปต์เนื่องจาก API สำหรับข้อมูลรับรองจะแทนที่วัตถุข้อมูลรับรองด้วยวัตถุใหม่แทนที่จะเพิ่งอัปเดตและการผูกระหว่างขั้นตอนการสร้างนักเทียบท่าและรหัสนั้นเป็นรหัส หากคุณใช้ค่า
null
สำหรับ ID (เช่นเดียวกับคำตอบที่ฉันเชื่อมโยงมาก่อน) ID ใหม่จะถูกสร้างขึ้นและการตั้งค่าข้อมูลรับรองในขั้นตอนการสร้างนักเทียบท่าจะหายไป
และนั่นคือ - สคริปต์ควรจะสามารถเรียกใช้ทุก ๆ 12 ชั่วโมงและรีเฟรชข้อมูลประจำตัว ECR และเราสามารถใช้ปลั๊กอิน Docker ต่อไปได้