GitHub Release Asset ๋ค์ด๋ก๋ 403 ์ด์
- name: Get Assets from GHR
uri:
url: "https://api.github.com/repos/{owner}/{repo}/releases/tags/{tag}"
headers:
authorization: "Bearer {{ github_token }}"
return_content: true
register: response
- name: Download Asset from GHR
get_url:
url: "https://api.github.com/repos/{owner}/{repo}/releases/assets/{asset_id}"
# ์ ๋ผ์ธ์ ์ฌ์ค url: "{{ response.json.assets[0].url }}"
headers:
authorization: "Bearer {{ github_token }}"
accept: "application/octet-stream"
dest: "/tmp/{{ asset_filename }}"
mode: "0644"
EC2 Linux Base Image ๋ฒ ์ดํน์ ์ํด ์์ ๊ฐ์ด ๊ณตํต ๋ฐ์ด๋๋ฆฌ๋ฅผ ์ค์นํ๋ ๊ณผ์ ์ Ansible Playbook ์ผ๋ก ์งํํ๊ณ ์์๋ค.
amazon-ebs.ths: fatal: [default]: FAILED! => {"changed": false, "dest": "/tmp/{asset_filename}", "elapsed": 0, "msg": "Request failed", "response": "HTTP Error 403: Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.", "status_code": 403, "url": "https://api.github.com/repos/{owner}/{repo}/releases/assets/{asset_id}"}
์ด๋๋ ๊ฐ์์ค๋ฝ๊ฒ ์์ ๊ฐ์ 403 ์๋ฌ๊ฐ ๋ฐ์ํ์ฌ ํด๋น ์๋ฌ๋ฅผ ํธ๋ฌ๋ธ์ํ ํ๋ ๊ณผ์ ์ ๊ธฐ๋กํ๋ คํ๋ค.
GitHub ์์ Release Asset ์ ๋ค์ด๋ก๋ํ๋ ค๋ฉด ์ฐ์ Get a release by tag name API ๋ฅผ ํตํด Asset ์ ๋ค์ด๋ก๋ํ ์ ์๋ API ๊ฒฝ๋ก๋ฅผ JSON response ์์ assets property ์ ๋ช ์๋ url ์ ํตํด ๋ฐ์์์ผํ๋ค.
API ๊ฒฝ๋ก๋ Get a release asset ํ์์ผ๋ก ์ฃผ์ด์ง๋๋ฐ, ๋ฐ์ด๋๋ฆฌ๋ฅผ ์ง์ ์ ์ผ๋ก ๋ค์ด๋ก๋๋ฐ๊ธฐ ์ํด์ Accept: application/octet-stream
ํค๋๋ฅผ ์ถ๊ฐํด์ฃผ์ด์ผํ๋ค. ์ด๋ GitHub ๋ 200 ์ ๋ฐํํ๋ฉฐ ์ง์ stream ์ ์๋ํ ์๋ ์๊ณ , 302 ์ ๋ฐํํด stream ๋ฐ์ ์ ์๋ storage ๊ฒฝ๋ก๋ก redirect ํด์ค ์๋ ์๋ค.
302 Redirect Response ์ Location ํค๋์ ํฌํจ๋ ๊ฒฝ๋ก๋ ๋ณดํต pre-signed URL ๋ก GitHub ๊ฐ ์ ๊ณตํ๋ ๋ค์ํ storage backend ๋ก ๋ถํฐ ๋ฐ์ด๋๋ฆฌ๋ฅผ ๋ค์ด๋ฐ์ ์ ์๋ค. (Related GitHub Discussion)
- name: Get Assets from GHR
uri:
url: "https://api.github.com/repos/{owner}/{repo}/releases/tags/{tag}"
headers:
authorization: "Bearer {{ github_token }}"
return_content: true
register: response
- name: Get Asset metadata response
uri:
url: "https://api.github.com/repos/{owner}/{repo}/releases/assets/{asset_id}"
# ์ ๋ผ์ธ์ ์ฌ์ค url: "{{ response.json.assets[0].url }}"
headers:
authorization: "Bearer {{ github_token }}"
accept: "application/octet-stream"
status_code: [200, 302]
return_content: true
follow_redirects: no
register: asset_response
- name: Save binary stream to file (200 OK)
copy:
content: "{{ asset_response.content }}"
dest: "/tmp/{{ asset_filename }}"
mode: '0644'
when: asset_response.status == 200
- name: Download binary from pre-signed URL (302 Redirect)
get_url:
url: "{{ asset_response.location }}"
dest: "/tmp/{{ asset_filename }}"
mode: '0644'
when: asset_response.status == 302
์ฒ์์ Ansible ์ get_url
๋ชจ๋์ด 302 Redirect ๋ฅผ ์ฒ๋ฆฌํ์ง ๋ชปํ๋ ์ค ์์๋ค. pre-signed URL ์ ๊ธฐ๋ณธ์ ์ผ๋ก ์ถ๊ฐ์ ์ธ ์ธ์ฆ์ด ํ์ํ์ง ์๊ธฐ ๋๋ฌธ์ Authorization Header ์ ์ถฉ๋๋ก ์ธํ ์ด์๋ก ์๊ฐํ๋ค. ๋๋ฌธ์ ์์ ๊ฐ์ด uri
๋ชจ๋์ ํ์ฉํ์ฌ HTTP Response Status Code ์ ๋ฐ๋ผ ๋ค๋ฅด๊ฒ ์ฒ๋ฆฌํ๋๋ก Ansible Playbook ์ ์์ ํ๊ณ , 302 Redirect ๋ฅผ ๋ฐ๋ก ์ฒ๋ฆฌํ์ฌ 403 ์๋ฌ ์์ด ๋ฐ์ด๋๋ฆฌ๋ฅผ ์ฑ๊ณต์ ์ผ๋ก ๋ค์ด๋ฐ์ ์ ์์๋ค.
curl -L \
-H "Authorization: Bearer {{ github_token }}" \
https://api.github.com/repos/{owner}/{repo}/releases/tags/{tag}
curl -v -L \
-H "Authorization: Bearer {{ github_token }}" \
-H "Accept: application/octet-stream" \
-o {{ asset_filename }} \
https://api.github.com/repos/{owner}/{repo}/releases/assets/{asset_id}
ํต์ ๊ณผ์ ์ ๋ ์์ธํ ๋ค์ฌ๋ค๋ณด๊ธฐ ์ํด ์์ ๊ฐ์ด curl command ๋ฅผ ํตํด API ๋ฅผ ํธ์ถํ ๊ฒฐ๊ณผ, curl command ๋ 302 Redirect ๋ฅผ ๋ฌธ์ ์์ด ์ฒ๋ฆฌํ๊ณ ๋ฐ์ด๋๋ฆฌ ์ญ์ ์ฑ๊ณต์ ์ผ๋ก ๋ค์ด๋ก๋ ๋ฐ์ ์ ์์๋ค.
๋๋ฌธ์ ๋๋์ฑ Ansible ์ get_url
๋ชจ๋์ ์์ฌํ๊ฒ ๋์๊ณ , ์ง์ ์์ค์ฝ๋๋ฅผ ์ฐพ์๋ณด๊ธฐ๋กํ๋ค. get_url
๋ชจ๋์ ๋ด๋ถ์ ์ผ๋ก urls
๋ชจ๋์์ ์ ๊ณตํ๋ fetch_url ์ ์ฌ์ฉํ๊ณ ์์๊ณ , ์ด๋ฏธ ๋ด๋ถ์ Redirect ๋ฅผ handle ํ๋ HTTPRedirectHandler ๊ฐ ํฌํจ๋์ด์์๋ค.
์ด๋ฅผ ํตํด Ansible ์ get_url
๋ชจ๋์ ๋ฌธ์ ๋ ์๋๋ผ๋ ๊ฒ์ ์๊ฒ๋์๊ณ , 403 ์๋ฌ๋ฅผ reproduce ํ๊ธฐ ์ํด Ansible Playbook ์ ์ฌ์คํํด๋ณธ ๊ฒฐ๊ณผ ์ด๋ฒ์ ๋ฌธ์ ์์ด ๋ฐ์ด๋๋ฆฌ๊ฐ ๋ค์ด๋ก๋ ๋์๋ค.
๊ฐํ์ ์ผ๋ก 403 ์๋ฌ๊ฐ ๋ฐ์ํ๋ ๊ฒ์ด ์์ํด์ ์คํจํ๋ ์คํ๊ณผ ์ฑ๊ณตํ๋ ์คํ์ Response ๋ฅผ ๋ถ์ํ ๊ฒฐ๊ณผ, ์คํจํ 302 Redirect ์ Location Header ๋ ๋ฐ์ด๋๋ฆฌ๋ฅผ objects.githubusercontent.com
์์ ๋ฐ์์ค๊ณ ์์๊ณ , ์ฑ๊ณตํ ๊ฒ์ release-assets.githubusercontent.com
์์ ๋ฐ์ด๋๋ฆฌ๋ฅผ ๋ฐ์์ค๊ณ ์์๋ค.
์๋ฌด๋๋ GitHub ๊ฐ ๋ค์ํ storage backend ๋ก ๋ถํฐ ๋ฐ์ด๋๋ฆฌ๋ฅผ streaming ํ๊ธฐ ๋๋ฌธ์ objects.githubusercontent.com
์๋ฒ์์ ๋ญ๊ฐ ์ด์๊ฐ ์์๊ฑฐ๋ ์ธ์ฆ ์ ์ฑ
์ด ๋ฌ๋๋ ๋ชจ์์ด๋ค.
๊ฒฐ๋ก ์ ์ผ๋ก 302 Redirect ๋์ ๋๋ฉ์ธ์ ๋ฐ๋ผ ๊ฐํ์ ์ผ๋ก 403 ์ด์๊ฐ ๋ฐ์ํ ์ ์์ผ๋, uri
๋ชจ๋์ ํตํด ์ง์ 302 Location Header ๋ฅผ ํ์ธํ๊ณ ์ดํ์ get_url
๋ชจ๋์ ํตํด ๋ฐ์ด๋๋ฆฌ๋ฅผ ๋ค์ด๋ก๋๋ฐ๋ ๋ฐฉ์์ผ๋ก 2๋จ๊ณ์ ๊ฑฐ์ณ ์ฒ๋ฆฌํ๋ ๊ฒ์ด ๊ฐ์ฅ ์์ ํด๋ณด์ธ๋ค.