hello云胜

技术与生活

0%

kubesphere 对接 企业OAuth2登录

亲身实践kubesphere 对接 企业OAuth2登录。踩了不少坑。网上也没有太多资料。

如果你也在开发这块功能,我相信这篇文章应该会提供一些帮助。

开发provider

我们需要开发一个自定义的认证provider,作用是去调用我们自己的OAuth服务。

因为每个公司自己的OAuth服务的接口定义和返回值可能存在些许的差异,所以必须编写这个适配的provider。

这一块的代码开发难度不大。因为官方已经给出了GitHub 的 GitHubIdentityProvider 和阿里云IDaaS的 AliyunIDaasProvider。

只要照葫芦画瓢即可。

具体步骤

  1. 创建目录

    pkg/apiserver/authentication/identityprovider/ 目录下创建一个插件的包。

  2. 主要就是实现几个接口。

​ 我是直接把GitHubIdentityProvider 的代码复制了过来,改成自己公司的名字。

​ ![image-20230804142445964](D:\github\docs\云原生\kubesphere\kubesphere 对接 企业OAuth2登录.assets\image-20230804142445964.png)

主要修改的地方就是这里的结构定义,需要根据你自己公司的auth服务来改。

![image-20230804142545972](D:\github\docs\云原生\kubesphere\kubesphere 对接 企业OAuth2登录.assets\image-20230804142545972.png)

这里根据实际情况来改。要说的是在username上我吃了个大亏。后面你会看到。

至于其他代码就不写了,基本不需要改动。

  1. 注册自己的provider

    在pkg/apiserver/authentication/options.go里import刚才编写的类

    1
    _ "kubesphere.io/kubesphere/pkg/apiserver/authentication/identityprovider/xxx"

提供OAuth服务的接口

我们需要3个OAuth相关的url地址

1
2
3
4
5
const (
authURL = "OAuth进行登录的页面"
tokenURL = "根据登录的页面返回的code,来获取access_token的接口"
userInfoURL = "根据access_token获取用户信息的接口"
)

另外,还需要进行OAuth认证的clientID和clientSecret。这个找你们公司服务OAuth服务的工程师要,肯定有的。

我在开发调试过程中发现公司提供的tokenURL和userInfoURL同kubesphere对接有点问题。

kubesphere发起tokenURL是用的post请求。参数名为code

然后userInfoURL是把access_token放在header里,名字为authorization

(一部血泪史)

所以又自己开发了这两个接口。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@PostMapping("/getToken")
public TokenResponse getToken(@RequestParam String code) {
log.info("============getToken============");
TokenResponse token = authSdkService.getToken(code);
return token;
}

@GetMapping("/getUserInfo")
public AccountResponse getUserInfo(HttpServletRequest request) {
String authorization = request.getHeader("authorization");
// authorization带着bear xxxxx +++++
String[] s = authorization.split(" ");
String token = s[1];
RestResponse<AccountResponse> accountResponseRestResponse = authSdkService.accountInfo(token);
AccountResponse data = accountResponseRestResponse.getData();
return data;
}

(用java写的。因为我们公司auth团队只提供java版本的sdk

这个代码和apiserver无关。)

打镜像并部署

开发完apiserver,就需要打自己的apiserver镜像,并部署到自己的k8s中。

步骤比较简单,但如果你是第一次打kubesphere的镜像,可能会遇到一些问题。

我这边记录下我遇到的问题

  1. 依赖的问题

    kubesphere使用vendor管理依赖。

需要执行

1
2
3
go mod tidy
go mod download
go mod vendor

这会将依赖拷贝到vendor目录下,否则编译go会找不到

  1. 无执行权限的问题

    1
    chmod +x hack/*.sh
  2. build镜像时需要传参

    以确定下载的helm的安装包

    TARGETARCH : amd64

    TARGETOS : linux

好了,然后在代码的根目录执行

1
2
3
docker build -f build/ks-apiserver/Dockerfile -t harbor-test.xxx.net/kubesphere/ks-apiserver:1.0.0 --build-arg TARGETOS=linux --build-arg TARGETARCH=amd64 .

docker push harbor-test.xxx.net/kubesphere/ks-apiserver:1.0.0

部署到集群中。修改ks-apiserver

1
kubectl -n kubesphere-system edit deploy ks-apiserver

如果不出意外,到现在我们完成了apiserver的部署。

配置kubesphere

修改ks-install

1
kubectl -n kubesphere-system edit cc ks-installer

对authentication进行修改

举例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
spec:
authentication:
jwtSecret: ''
authenticateRateLimiterMaxTries: 10
authenticateRateLimiterDuration: 10m0s
oauthOptions:
accessTokenMaxAge: 1h
accessTokenInactivityTimeout: 30m
identityProviders:
- name: zzzz
type: xxxIDaaSProvider
mappingMethod: auto
provider:
clientID: 'f7d8ba1339b07988xxxxxx6'
clientSecret: '0ae8e4f66358cd8xxxxx97726968'
redirectURL: http://xxxx/oauth/redirect/zzzz
endpoint:
tokenURL: http://xxxx/auth/getToken
authURL: https://iam.xxxx.net/
userInfoURL: http://xxxx/auth/getUserInfo

这里必须要说的是redirectURL。这里我一开始是不知道填什么的,也没有文档告知。

后来看github和ali的那个测试代码

![image-20230804145554881](D:\github\docs\云原生\kubesphere\kubesphere 对接 企业OAuth2登录.assets\image-20230804145554881.png)

发现他们的跳转地址写的都是ks-console的地址加上/oauth/redirect/后面接上自己provider的名字。

这才猜测应该这么写。着实坑人。

还有type就是写你的provider的类类型。

后来看了ks-console的代码,才确认是这么写没错。

给你们看看

![image-20230804145831136](D:\github\docs\云原生\kubesphere\kubesphere 对接 企业OAuth2登录.assets\image-20230804145831136.png)

/oauth/redirect之后会调到ks-apiserver的/oauth/callback接口

![image-20230804145921044](D:\github\docs\云原生\kubesphere\kubesphere 对接 企业OAuth2登录.assets\image-20230804145921044.png)

调到ks-apiserver的/oauth/callback接口又在哪里呢?

pkg/kapis/oauth/register.go 这里是注册router的地方

![image-20230804150102310](D:\github\docs\云原生\kubesphere\kubesphere 对接 企业OAuth2登录.assets\image-20230804150102310.png)

而这个oauthCallback,经过调用最终会到我们在第一步编写的provider里

![image-20230804150218639](D:\github\docs\云原生\kubesphere\kubesphere 对接 企业OAuth2登录.assets\image-20230804150218639.png)

![image-20230804150248944](D:\github\docs\云原生\kubesphere\kubesphere 对接 企业OAuth2登录.assets\image-20230804150248944.png)

所以,经过这一遭,你应该明白整个跳转流程了吧。

好,我来总结一下

  1. 经过这一番改造。打开kubesphere,会显示通过xxx登录的按钮

![image-20230804150434512](D:\github\docs\云原生\kubesphere\kubesphere 对接 企业OAuth2登录.assets\image-20230804150434512.png)

  1. 点击之后,就会跳到对应的认证页面

    根据的是authURL

    以github为例

    ![github-login-page](D:\github\docs\云原生\kubesphere\kubesphere 对接 企业OAuth2登录.assets\github-login-page.png)

  2. 在这里登录之后

​ 根据auth2的交互流程。会返回一个授权码code。

  1. 登录成功就会进行跳转

    跳转的地址就是redirectURL

  2. 认证

    kubesphere(以后简称ks)这个跳转接口会进行回调

    在回调里触发我们编写的provider

​ 根据tokenURL + code获取了access_token

​ 再使用userInfoURL和access_token获取userInfo

ok,到此为止。成功完成auth登录。

参考资料: OAuth 2.0身份提供者 (kubesphere.io)