底层直接开辟了docker环境,结合opensumi得到一个持久化的在线编译环境(服务器ip地址+端口号,每个学生用不同的端口号),为了保证每个人的网址都只能自己用,需要在这个网址访问之前加上验证**【需要验证是否正确,还需要验证这个链接和用户是否匹配】**
历程(记录一下探索及学习历程,大家可以直接略过)
这个项目是我近所里工作的时候,师兄就已经想到了用nginx实现反向代理。
一开始服务器的域名是ide.agileserve.org.cn:30888,每个学生访问的时候直接在网址后面加入路由,路由名称为自己的名字,但在配置完nginx之后,访问时总是访问不到资源,它总是以根目录去访问,可能和一开始不了解nginx导致location中的proxy_pass写错了。
于是后来新建了域名*.ide.agileserve.org.cn:30888,可以取代*为自己的名字,在nginx.conf中配置了server_name(访问的地址)和proxy_pass(被保护的地址),解析成功,因此需要开始想办法加入认证了【也是后来才想这么清楚的】。
但当时想到的解决办法:
1、不采用代理,建立一个网站,并建立相应的(第三方账号-在线编译环境地址-标识码)数据库,可以连接第三方账号登录,进入后可以看到一个按钮,点击后可跳转到在线编译环境中,在跳转时进行数据库及cookie相关验证
- 需要了解如何进行第三方账号授权
需要创建应用,填写如下:
得到application相关信息:
且在网页授权登录代码中需要填写以下相关信息
function gethref() {
var client_id = "${Application ID}"
var redirect_uri = "${Callback URL}"
var response_type = "code"
var state = "linda"
var scope = "api"
window.location.href = "https://gitlab.agileserve.org.cn:8001/oauth/authorize?client_id=" + client_id + "&redirect_uri=" + redirect_uri + "&response_type=" + response_type + "&state=" + state + "&&scope=" + scope + ""
}
但用户cookie被暴露在网志中,所有人仍然可以直接利用网址进入别人的编译环境,被pass掉。
此外,“OpenID强调验证(authentication)[验证是不是],而OAuth强调授权(authorization)[是不是以及有哪些权利]。 ”
2、
点击网站的按钮时进行身份验证或者填写表单,根据表单信息再进行跳转
##重大发现
我并没有跳出来,应该是对链接进行类似加密处理一样才行,对链接进行证书验证。该证书就是gitlab下发的。
因此现在只有三种方法①在nginx中加入验证阶段,即验证成功才可以跳转② 直接用ip地址加端口号,访问时加入gitlab验证③在gitlab上加入一个按钮,可以跳转链接【不可以,还是可以直接访问链接】
3、在nginx中加入auth_basic(文件名),auth_basic_user_file(密码存放的文件),即在登陆这个网站时会跳出一个对话框,填写用户名和密码,与文件匹配即正确进入,否则不可以,具体步骤如下:
①下载密码生成工具
ubuntu下执行sudo apt-get install apache2-utils
centos下执行sudo yum -y install httpd-tools
② 创建文件并录入用户名和密码
执行
cd /etc/nginx
mkdir db
cd db
#生成密码
htpasswd -c ./passwd.db ×××(用户名)
输入两次密码
因此在/etc/nginx/db文件夹下有文件passwd.db
③在nginx.conf中加入
...
location / {
auth_basic "secret";
auth_basic_user_file /etc/nginx/db/passwd.db;
proxy_pass http://10.30.19.35:6900/;
...
}
...
验证的方式过于low,而且需要给所有人匹配用户名和密码,因此使用第三方授权代理,搜到了oauth2-proxy和vouch-proxy,源码地址分别是https://github.com/oauth2-proxy/oauth2-proxy和https://github.com/vouch/vouch-proxy,以下进入正题。
vouch-proxy的使用
看官网文件Readme可以选择源码编译或docker运行
- 源码编译
Vouch Proxy (VP)强迫用户在登陆一个网站时必须登陆并授权,具体步骤: -
- 前提工作:
nginx安装apt install nginx
vouch-proxy代码下载git clone https://github.com/vouch/vouch-proxy.git
根据“需要了解如何进行第三方账号授权”内容块获取gitlab授权的ApplicationID、Secret和CallbackURL,参考本文第1点或者click this link
- 前提工作:
-
- 执行
cd vouch-proxy
cp ./config/config.yml_example_gitlab_ce ./config/config.yml
-
- 修改config.yml
# Vouch Proxy configuration
# bare minimum to get Vouch Proxy running with GitLab CE Authentication
vouch:
# domains:
# valid domains that the jwt cookies can be set into
# the callback_urls will be to these domains
domains:
- ide.agileserve.org.cn
# - OR -
# instead of setting specific domains you may prefer to allow all users...
# set allowAllUsers: true to use Vouch Proxy to just accept anyone who can authenticate at the configured provider
# allowAllUsers: true
cookie:
# allow the jwt/cookie to be set into http://yourdomain.com (defaults to true, requiring https://yourdomain.com)
secure: false
# vouch.cookie.domain must be set when enabling allowAllUsers
# domain: yourdomain.com
oauth:
# Create a new global or group application and paste the id and the secret
provider: oidc
client_id: "${client_id}"
client_secret: "${secret}"
scopes:
- openid
- email
- profile
auth_url: https://gitlab.agileserve.org.cn:8001/oauth/authorize#gitlab地址加/oauth/authorize
token_url: https://gitlab.agileserve.org.cn:8001/oauth/token
user_info_url: https://gitlab.agileserve.org.cn:8001/oauth/userinfo
callback_url: ${redirect_url}#vouch-proxy运行地址加/auth
-
- nginx.conf中配置如下两种:
①访问时由auth_request拦截到另一个入口,由vouch-proxy进行验证,成功则放行
- nginx.conf中配置如下两种:
server {
listen 30888;#访问的地址监听的端口号
#listen 443 ssl http2;
server_name *.ide.agileserve.org.cn;#访问的地址
root /var/www/html/;
#ssl_certificate /etc/letsencrypt/live/protectedapp.yourdomain.com/fullchain.pem;
#ssl_certificate_key /etc/letsencrypt/live/protectedapp.yourdomain.com/privkey.pem;
auth_request /validate;# 所有请求的初始入口
location = /validate {
proxy_pass http://127.0.0.1:9090/validate;# 该请求传递给vouch-proxy
proxy_set_header Host $http_host;# be sure to pass the original host header
# Vouch Proxy only acts on the request headers
proxy_pass_request_body off;
proxy_set_header Content-Length "";
# optionally add X-Vouch-User as returned by Vouch Proxy along with the request
auth_request_set $auth_resp_x_vouch_user $upstream_http_x_vouch_user;
# optionally add X-Vouch-IdP-Claims-* custom claims you are tracking
# auth_request_set $auth_resp_x_vouch_idp_claims_groups $upstream_http_x_vouch_idp_claims_groups;
# auth_request_set $auth_resp_x_vouch_idp_claims_given_name $upstream_http_x_vouch_idp_claims_given_name;
# optinally add X-Vouch-IdP-AccessToken or X-Vouch-IdP-IdToken
# auth_request_set $auth_resp_x_vouch_idp_accesstoken $upstream_http_x_vouch_idp_accesstoken;
# auth_request_set $auth_resp_x_vouch_idp_idtoken $upstream_http_x_vouch_idp_idtoken;
# these return values are used by the @error401 call
auth_request_set $auth_resp_jwt $upstream_http_x_vouch_jwt;
auth_request_set $auth_resp_err $upstream_http_x_vouch_err;
auth_request_set $auth_resp_failcount $upstream_http_x_vouch_failcount;
# Vouch Proxy can run behind the same Nginx reverse proxy
# may need to comply to "upstream" server naming
# proxy_pass http://vouch.yourdomain.com/validate;
# proxy_set_header Host $http_host;
}
# if validate returns `401 not authorized` then forward the request to the error401block
error_page 401 = @error401;
location @error401 {
# redirect to Vouch Proxy for login
return 302 https://127.0.0.1:9090/login?url=$scheme://$http_host$request_uri&vouch-failcount=$auth_resp_failcount&X-Vouch-Token=$auth_resp_jwt&error=$auth_resp_err;
# you usually *want* to redirect to Vouch running behind the same Nginx config proteced by https
# but to get started you can just forward the end user to the port that vouch is running on
# return 302 http://vouch.yourdomain.com:9090/login?url=$scheme://$http_host$request_uri&vouch-failcount=$auth_resp_failcount&X-Vouch-Token=$auth_resp_jwt&error=$auth_resp_err;
}
location / {
# forward authorized requests to your service protectedapp.yourdomain.com
proxy_pass "http://10.30.19.35:6900";#被保护的地址
# you may need to set these variables in this block as per https://github.com/vouch/vouch-proxy/issues/26#issuecomment-425215810
# auth_request_set $auth_resp_x_vouch_user $upstream_http_x_vouch_user
# auth_request_set $auth_resp_x_vouch_idp_claims_groups $upstream_http_x_vouch_idp_claims_groups;
# auth_request_set $auth_resp_x_vouch_idp_claims_given_name $upstream_http_x_vouch_idp_claims_given_name;
# set user header (usually an email)
proxy_set_header X-Vouch-User $auth_resp_x_vouch_user;
# optionally pass any custom claims you are tracking
# proxy_set_header X-Vouch-IdP-Claims-Groups $auth_resp_x_vouch_idp_claims_groups;
# proxy_set_header X-Vouch-IdP-Claims-Given_Name $auth_resp_x_vouch_idp_claims_given_name;
# optionally pass the accesstoken or idtoken
# proxy_set_header X-Vouch-IdP-AccessToken $auth_resp_x_vouch_idp_accesstoken;
# proxy_set_header X-Vouch-IdP-IdToken $auth_resp_x_vouch_idp_idtoken;
}
}
②访问后均在一个路由上,并进行请求分发
server {
listen 443 ssl http2;
server_name protectedapp.yourdomain.com;
ssl_certificate /etc/letsencrypt/live/protectedapp.yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/protectedapp.yourdomain.com/privkey.pem;
# This location serves all Vouch Proxy endpoints as /vp_in_a_path/$uri
# including /vp_in_a_path/validate, /vp_in_a_path/login, /vp_in_a_path/logout, /vp_in_a_path/auth, /vp_in_a_path/auth/$STATE, etc
location /vp_in_a_path {
proxy_pass http://127.0.0.1:9090; # must not! have a slash at the end
proxy_set_header Host $http_host;
proxy_pass_request_body off;
proxy_set_header Content-Length "";
# these return values are used by the @error401 call
auth_request_set $auth_resp_jwt $upstream_http_x_vouch_jwt;
auth_request_set $auth_resp_err $upstream_http_x_vouch_err;
auth_request_set $auth_resp_failcount $upstream_http_x_vouch_failcount;
}
# if /vp_in_a_path/validate returns `401 not authorized` then forward the request to the error401block
error_page 401 = @error401;
location @error401 {
# redirect to Vouch Proxy for login
return 302 https://protectedapp.yourdomain.com/vp_in_a_path/login?url=$scheme://$http_host$request_uri&vouch-failcount=$auth_resp_failcount&X-Vouch-Token=$auth_resp_jwt&error=$auth_resp_err;
}
location / {
auth_request /vp_in_a_path/validate;
proxy_pass http://127.0.0.1:8080;
# see the Nginx config above for additional headers which can be set from Vouch Proxy
}
}
运行nginx -t
和nginx -s reload
让nginx的配置生效
-
- 在vouch-proxy文件夹下依次执行
./do.sh goget
./do.sh build
./vouch-proxy
如果端口占用,则用命令lsof -i:9090
查询,若占用了,则换端口(即更改default.yml中的port)
- docker运行
docker pull quay.io/vouch/vouch-proxy
通源码方式一样,拷贝并修改config.yml
将包含config.yml文件的文件夹config工作目录及进行映射
docker run -d \
-p 9090:9090 \
--name vouch-proxy \
-v ${PWD}/config:/config \
quay.io/vouch/vouch-proxy
额外的工作
由于我们需要给每一个学生不同的操作环境并将他们的代码持久化在我们的卷上,因此我们需要更改vouch-proxy源码,利用授权之后学生的username(唯一的)作为key去数据库中查询到真正的内网地址,并存放在cookie中传递,nginx中直接获取,即可实现跳转。
过程中参考过,留个纪念
NGINX集成第三方系统时进行鉴权
linux环境下nginx反向代理gitlab社区版
基于k8s Ingress Nginx+OAuth2+Gitlab无代码侵入实现自定义服务的外部验证
修改了gitlab的配置
Nginx实现代理和用户验证