从shell认证到gitlab



我想获得一个临时的GitLab令牌来运行一个简单的脚本。我不想要个人访问令牌,也不是项目访问令牌,因为这对用户来说是太多的点击。我如何登录或登录?GitLab不再支持密码登录,必须使用OAuth。但这意味着我必须接收一个HTTP重定向,运行一个web服务器!

GitLab Oauth对话框在浏览器中验证后可以非常快速。在默认配置中,它甚至不要求确认。然后用户不必离开命令行。小麻烦是留下了一堆身份验证浏览器选项卡/窗口。

只需要处理一个HTTP请求。我们不需要一个web服务器。Netcat可以接受连接,给我们的请求和响应,以及让用户得到一些反馈。与建议相反,这是未加密的。不过,它是在环回设备上。风险应该很低。为了提高安全性,我们需要一个合适的浏览器应用程序来处理自定义协议。WebView可以达到这个效果,但是这样我们就没有简单的shell了。

旋度(或wget)处理必要的API调用。

这是一个用(posix?) shell编写的简单的OAuth客户端:

#!/bin/sh
# fail fast
set -e
# defaults
app_id="$GITLAB_APP_ID"
app_port="8001"
app_addr="127.0.0.1"
api_v4=""
test -z "$GITLAB_HOST" || api_v4="https://${GITLAB_HOST}/api/v4"
test -z "$GITLAB_API_V4" || api_v4="$GITLAB_API_V4"
# display usage info help text
help () {
cat <<-EOHELP
Sign into GitLab on ${api_v4:-GITLAB_API_V4} with application '${app_id:-GITLAB_APP_ID}'

Requires: nc, curl, jq, x-www-browser|open, mktemp, posix(sh, cat, cut, head, rm, grep)
It is meant to work the same in a pipeline as well as on local environment.
It will use the CI_JOB_TOKEN set by GitLab runner or request OAuth from the user.
For OAuth, make the app with [api] access, not confidential, expire tokens: yes,
redirect URI should be set to http://127.0.0.1:8001
Args:
-h|--help       this text
-a|--app_id     set GitLab app id [GITLAB_APP_ID]
-4|--api_v4     set GitLab API v4 address [GITLAB_API_V4]
or set it with a GITLAB_HOST FQDN[:port]
-s|--server     set GitLab API v4 address with a GITLAB_HOST FQDN[:port]
EOHELP
}
# parse command arguments
parse_args () {
while test "$#" -ne 0
do
case "$1" in
-h|--help)          help; exit 0 ;;
-a|--app_id)        app_id="$2"; shift 2 ;; 
-a=*|--app_id=*)    app_id="${1#*=}"; shift 1 ;; 
-4|--api_v4)        api_v4="$2"; shift 2 ;; 
-4=*|--api_v4=*)    api_v4="${1#*=}"; shift 1 ;; 
-s|--server)        api_v4="https://$2/api/v4"; shift 2 ;; 
-s=*|--server=*)    api_v4="https://${1#*=}/api/v4"; shift 1 ;; 
*)                  ( echo "Unexpected arg '$1'"; echo; help ) >&2; exit 1 ;;
esac
done
}
auth_netcat () {
# compatible way to invoke different nc flavors: 1) gnu/bsd/mac 2) busybox
nc -l "$1" "$2" 2>/dev/null || nc -l "$1:$2"
}
auth_browse () {
# compatible way to open a default browser
x-www-browser "$@" || open "$@"
}
authenticate () {

# Use CI_JOB_TOKEN in a pipeline as gitlab_token if available or get oauth access token
if [ -n "$CI_JOB_TOKEN" ]; then
gitlab_user="gitlab-ci-token"
gitlab_token="$CI_JOB_TOKEN"
else
: "${api_v4:?specify a GitLab API v4 URL}"
: "${app_id:?specify a GitLab app ID}"
: "${app_port:?specify the app port}"
: "${app_addr:?specify the app address}"
echo "Getting token" 
auth_file="$(mktemp)"
# Start netcat as a local web server to receive the auth code
auth_netcat "$app_addr" "$app_port" <<-EORSP >"$auth_file" &
HTTP/1.0 200 OK
Content-Length: 13
Authenticated
EORSP
auth_pid=$!
# If netcat started, proceed with requesting auth code
if kill -0 "$auth_pid"; then
auth_state="$auth_pid"
auth_url="${api_v4%/api/v4}/oauth/authorize?response_type=code&scope=api"
auth_url="$auth_url&client_id=$app_id"
auth_url="$auth_url&redirect_uri=http://$app_addr:$app_port"
auth_url="$auth_url&state=$auth_state"
auth_browse "$auth_url" && 
echo "Authentication window opened in your browser:" || 
echo "Authenticate:"
echo "    $auth_url"
fi
# Wait for netcat to receive the code and then request access token and user name
if wait "$auth_pid" 2>/dev/null; then
auth_code="$(head -1 "$auth_file" | grep -Eo 'code=[^&]+' | cut -d= -f2)"
echo "claiming access token"
gitlab_token="$(
curl -sSLf "${api_v4%/api/v4}/oauth/token" 
-F "client_id=$app_id" 
-F "code=$auth_code" 
-F "grant_type=authorization_code" 
-F "redirect_uri=http://$app_addr:$app_port" |
jq -r '.access_token'
)"
echo "getting current user name"
gitlab_user="$(
curl -sSLf "${api_v4}/user/" 
-H "Authorization: Bearer $gitlab_token" |
jq -r '.username'
)"
rm "$auth_file"
else
echo "authentication FAILED"
fi
fi
}
if parse_args "$@" && authenticate >&2
then
echo "GITLAB_USER=${gitlab_user:?}"
echo "GITLAB_TOKEN=${gitlab_token:?}"
fi

然而,这个问题是一个更复杂的要点,使其方便并可供其他人使用。改进欢迎!

如果你复制&粘贴,将空格转换为制表符,这样heredoc就不会中断

相关内容

  • 没有找到相关文章

最新更新