GitLab升级到后续的版本之后,由于Session API已经不再支持,通过用户名/密码方式获取Access Token的方式需要换一种方式,这篇文章介绍一下一种通过使用cookie获取的方式。
早期版本,比如Gitlab 8,可以通过如下方式轻松获得Private Token
[root@platform tmp]# curl http://192.168.163.118:32001/api/v3/session --data 'login=root&password=12345678' 2>/dev/null |jq . |grep token
"private_token": "9-9rh18mQz4h3eDMQf5M"
[root@platform tmp]#
详细可参看:https://blog.csdn.net/liumiaocn/article/details/81291556
不可使用原因:随着Access Token功能的全面升级,对于token也能做到多个token以及过期日期的更细粒度的控制,session api也完成了其作用,已经不再支持。
思路:使用cookie,模拟页面操作的方式传入信息,然后从返回的html页面从提取相应的结果内容。
liumiaocn:gitlab liumiao$ cat docker-compose.yml
version: '2'
services:
# Version Control service: Gitlab
gitlab:
image: gitlab/gitlab-ce:12.10.5-ce.0
ports:
- "32001:80"
volumes:
- ./log/:/var/log/gitlab
- ./data/:/var/opt/gitlab
- ./conf/:/etc/gitlab
restart: "no"
liumiaocn:gitlab liumiao$
创建如下目录:
liumiaocn:gitlab liumiao$ ls
docker-compose.yml
liumiaocn:gitlab liumiao$ mkdir -p log data conf
liumiaocn:gitlab liumiao$ ls
conf data docker-compose.yml log
liumiaocn:gitlab liumiao$
启动命令:docker-compose up -d
注:此处设定root用户密码为liumiaocn,后续将使用root/liumiaocn创建和获取Access Token。
使用如下示例命令获取认证token信息,此信息将在步骤2模拟页面登录时使用
liumiaocn:api liumiao$ curl -c cookie.txt -i "http://localhost:32001/users/sign_in" -s >token.txt
liumiaocn:api liumiao$
生成的cookie详细
liumiaocn:api liumiao$ cat cookie.txt
# Netscape HTTP Cookie File
# https://curl.haxx.se/docs/http-cookies.html
# This file was generated by libcurl! Edit at your own risk.
#HttpOnly_localhost FALSE / FALSE 1595212892 _gitlab_session 58ca351d122f3ca23c0eb2a01461a3b2
#HttpOnly_localhost FALSE / FALSE 2226357692 experimentation_subject_id IjcwNWRmZWM2LTcyZWItNGFjNy1iNjJhLTkzMDlkYjg3N2Y1NSI%3D--91dcd3115eb28a5d079a440e429b658b46acae5f
liumiaocn:api liumiao$
token.txt详细内容中包含csrf内容
liumiaocn:api liumiao$ cat token.txt
HTTP/1.1 200 OK
Server: nginx
Date: Mon, 20 Jul 2020 00:41:32 GMT
Content-Type: text/html; charset=utf-8
Transfer-Encoding: chunked
Connection: keep-alive
Vary: Accept-Encoding
Cache-Control: max-age=0, private, must-revalidate
Etag: W/"1756ae89b2b0f51b4c950a1f4ac0add7"
Referrer-Policy: strict-origin-when-cross-origin
Set-Cookie: experimentation_subject_id=IjcwNWRmZWM2LTcyZWItNGFjNy1iNjJhLTkzMDlkYjg3N2Y1NSI%3D--91dcd3115eb28a5d079a440e429b658b46acae5f; path=/; expires=Fri, 20 Jul 2040 00:41:32 -0000; HttpOnly
Set-Cookie: _gitlab_session=58ca351d122f3ca23c0eb2a01461a3b2; path=/; expires=Mon, 20 Jul 2020 02:41:32 -0000; HttpOnly
X-Content-Type-Options: nosniff
X-Download-Options: noopen
X-Frame-Options: DENY
X-Permitted-Cross-Domain-Policies: none
X-Request-Id: MLxE09OKZz5
X-Runtime: 0.049925
X-Ua-Compatible: IE=edge
X-Xss-Protection: 1; mode=block
Strict-Transport-Security: max-age=31536000
Referrer-Policy: strict-origin-when-cross-origin
<html class="devise-layout-html">
<head prefix="og: http://ogp.me/ns#">
<meta charset="utf-8">
...省略
<meta name="csrf-param" content="authenticity_token" />
<meta name="csrf-token" content="1Q8FE1gGh9RnG+YE3FWXKqN/Twh6AQJ4roEVfqzmz5MYBNXOTMqpwtAs0W10V4NxfmFIME+RCUNpQjfhssiSQQ==" />
<meta content="origin-when-cross-origin" name="referrer">
<meta content="width=device-width, initial-scale=1, maximum-scale=1" name="viewport">
...省略
<div class="login-body">
<form class="new_user gl-show-field-errors" id="new_user" aria-live="assertive" action="/users/sign_in" accept-charset="UTF-8" method="post"><input name="utf8" type="hidden" value="✓" /><input type="hidden" name="authenticity_token" value="wN23/hzgdq3+XfeZAq5xKYOZ/6j1pDt0Pz5hSGkzILoN1mcjCCxYu0lqwPCqrGVyXof4kMA0ME/4/UPXdx19aA==" /><div class="form-group">
<label for="user_login" class="label-bold">Username or emaillabel>
...省略
body>
html>
liumiaocn:api liumiao$
从上述返回中提取token的信息“wN23/hzgdq3+XfeZAq5xKYOZ/6j1pDt0Pz5hSGkzILoN1mcjCCxYu0lqwPCqrGVyXof4kMA0ME/4/UPXdx19aA==”
使用用户名、密码以及获取的认证token信息以及cookie文件,通过users/sign_in传入,模拟页面登录方式
liumiaocn:api liumiao$ curl -b cookie.txt -c cookie.txt -i "http://localhost:32001/users/sign_in" \
> --data "user[login]=root&user[password]=liumiaocn" \
> --data-urlencode "authenticity_token=wN23/hzgdq3+XfeZAq5xKYOZ/6j1pDt0Pz5hSGkzILoN1mcjCCxYu0lqwPCqrGVyXof4kMA0ME/4/UPXdx19aA=="
HTTP/1.1 302 Found
Server: nginx
Date: Mon, 20 Jul 2020 01:37:40 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 89
Connection: keep-alive
Cache-Control: max-age=0, private, must-revalidate, no-store
Location: http://localhost:32001/
Pragma: no-cache
Referrer-Policy: strict-origin-when-cross-origin
Set-Cookie: _gitlab_session=2bd98a7c373ebabdd84616e83bfe592e; path=/; HttpOnly
X-Content-Type-Options: nosniff
X-Download-Options: noopen
X-Frame-Options: DENY
X-Permitted-Cross-Domain-Policies: none
X-Request-Id: P6GPvq6Czg7
X-Runtime: 0.729474
X-Ua-Compatible: IE=edge
X-Xss-Protection: 1; mode=block
Strict-Transport-Security: max-age=31536000
Referrer-Policy: strict-origin-when-cross-origin
You are being redirected.liumiaocn:api liumiao$
liumiaocn:api liumiao$
使用cookie文件作为输入,模拟移动至profile/personal_access_tokens页面
liumiaocn:api liumiao$ curl -H 'user-agent: curl' -b cookie.txt -i "http://localhost:32001/profile/personal_access_tokens" -s >token2.txt
liumiaocn:api liumiao$
确认token信息:
liumiaocn:api liumiao$ grep authenticity_token token2.txt
确认cookie信息
liumiaocn:api liumiao$ cat cookie.txt
# Netscape HTTP Cookie File
# https://curl.haxx.se/docs/http-cookies.html
# This file was generated by libcurl! Edit at your own risk.
#HttpOnly_localhost FALSE / FALSE 2226357692 experimentation_subject_id IjcwNWRmZWM2LTcyZWItNGFjNy1iNjJhLTkzMDlkYjg3N2Y1NSI%3D--91dcd3115eb28a5d079a440e429b658b46acae5f
#HttpOnly_localhost FALSE / FALSE 0 _gitlab_session 2bd98a7c373ebabdd84616e83bfe592e
liumiaocn:api liumiao$
创建名为ap-token-test的token,类别为api
liumiaocn:api liumiao$ curl -L -b cookie.txt "http://localhost:32001/profile/personal_access_tokens" \
> --data-urlencode "authenticity_token=vV3nI5JjJeMPO+RlCSS6SmIs1P1xzWRsfy4X1r/sxuqFhpaXCHIIRUuZ6ga2VT1y8gbSpdHd6bU7Mh4p9mP/Ng==" \
> --data 'personal_access_token[name]=ap-token-test&personal_access_token[expires_at]=&personal_access_token[scopes][]=api' >token3.txt
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 349 100 119 100 230 1487 2875 --:--:-- --:--:-- --:--:-- 4362
100 35977 0 35977 0 0 145k 0 --:--:-- --:--:-- --:--:-- 145k
liumiaocn:api liumiao$
注:本来是想写成api-token-test的,写错了,不过不影响结果
token仅仅在首次创建时出现,我们可以很容易地从token3.txt中获取此token信息
liumiaocn:api liumiao$ grep created-personal-access-token token3.txt
liumiaocn:api liumiao$
步骤6:验证token
通过一个api的使用来验证此token是好用的,执行日志示例如下所示:
liumiaocn:api liumiao$ gitlab_url="localhost:32001"
liumiaocn:api liumiao$ access_token="JmHBHzaRxUQoyWdPdES_"
liumiaocn:api liumiao$ curl -H "PRIVATE-TOKEN: ${access_token}" http://${gitlab_url}/api/v4/user/keys
[]liumiaocn:api liumiao$
总结
虽然使用用户名/密码去直接获取access token总会有很多被诟病的地方,但是如果不希望登录gitlab进行操作的话,这也是一种纠结的解决方法。