在docker模式下apollo portal接入自建keycloak实现单点登录
apollo portal docker部署
拉取docker镜像
docker pull apolloconfig/apollo-portal
创建挂载目录
新建文件夹用于存放配置文件和日志
mkdir -p apollo-portal/config
mkdir -p apollo-portal/logs
修改配置文件
在config目录下新建三个配置文件
- apollo-env.properties,将下面的地址换成你自己的各环境apollo config服务地址
dev.meta=http://fill-in-dev-meta-server:8080
fat.meta=http://fill-in-fat-meta-server:8080
uat.meta=http://fill-in-uat-meta-server:8080
pro.meta=http://fill-in-pro-meta-server:8080
注:后期如果需要增减环境,除了需要修改这个配置文件之外,还需要在管理页面,系统参数,PortalDB配置管理里将apollo.portal.envs的值改为你需要的环境列表,改完后重启portal服务才能生效
- application-github.properties
# DataSource
spring.datasource.url = jdbc:mysql://192.168.50.80:3306/ApolloPortalDB?characterEncoding=utf8
spring.datasource.username = dbUsername
spring.datasource.password = dbPassword
- application-oidc.yml
server:
# 解析反向代理请求头
forward-headers-strategy: framework
spring:
security:
oauth2:
client:
provider:
# provider-name 是 oidc 提供者的名称, 任意字符均可,我这里是keycloak, registration 的配置需要用到这个名称
keycloak:
# 必须是 https, oidc 的 issuer-uri
# 例如 你的 issuer-uri 是 https://host:port/auth/realms/apollo/.well-known/openid-configuration, 那么此处只需要配置 https://host:port/auth/realms/apollo 即可, spring boot 处理的时候会加上 /.well-known/openid-configuration 的后缀
issuer-uri: https://keycloak.domain.com/realms/starcloud
registration:
# registration-name 是 oidc 客户端的名称, 任意字符均可, oidc 登录必须配置一个 authorization_code 类型的 registration
keycloak:
# oidc 登录必须配置一个 authorization_code 类型的 registration
authorization-grant-type: authorization_code
client-authentication-method: basic
# client-id 是在 oidc 提供者处配置的客户端ID, 用于登录 provider
client-id: apollo-portal
# provider 的名称, 需要和上面配置的 provider 名称保持一致
provider: keycloak
# openid 为 oidc 登录的必须 scope, 此处可以添加其它自定义的 scope
scope:
- openid
# client-secret 是在 oidc 提供者处配置的客户端密码, 用于登录 provider
# 从安全角度考虑更推荐使用环境变量来配置, 环境变量的命名规则为: 将配置项的 key 当中的 点(.)、横杠(-)替换为下划线(_), 然后将所有字母改为大写, spring boot 会自动处理符合此规则的环境变量
# 例如 spring.security.oauth2.client.registration.<fill-in-the-registration-name-here>.client-secret -> SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_<FILL_IN_THE_REGISTRATION_NAME_HERE>_CLIENT_SECRET (<FILL_IN_THE_REGISTRATION_NAME_HERE> 可以替换为自定义的 oidc 客户端的名称)
client-secret: d43c91c0-xxxx-xxxx-xxxx-xxxxxxxxxxxx
启动docker容器
记得在环境变量里指定java opts,指定spring.profiles.active为github,oidc上面的配置才能生效
docker run\
-d\
--name='apollo_portal'\
--net='br0'\
--ip='192.168.50.68'\
-e 'JAVA_OPTS'='-Dspring.profiles.active=github,oidc'\
-v '/mnt/user/appdata/apollo-portal/config/':'/apollo-portal/config':'rw'\
-v '/mnt/user/appdata/apollo-portal/logs/':'/logs':'rw' 'apolloconfig/apollo-portal'
命令执行执行后发现容器启动失败,看日志输出有下面的异常
...
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:141)
at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:126)
at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:280)
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:451)
... 80 common frames omitted
很明显是证书问题,因为我的keycloak服务( 这是搭建过程 )使用的是自签名证书,显然是不被信任的。 java程序想要信任自签名证书的一个方法是在jdk的信任keystore里将自己的证书加入进去,apollo portal镜像使用的是openjdk镜像,这个受信任的keystore是/usr/local/openjdk-8/lib/security/cacerts文件,所以这里需要对官方镜像做一些改动。
获取keycloak tls证书
我的keycloak服务使用的是keytool生成的keystore文件作为tls加密凭证的( 详情 ),所以需要通过keystore文件生成证书,并写入到镜像的jdk keystore里
#下面这个文件夹是keycloak keystore所在文件夹
cd /mnt/user/appdata/keycloak/conf
#根据keystore生成证书文件
keytool -exportcert -keystore keystore.jks -alias keycloak -file keycloak.cer
将证书写入镜像jdk keystore
编写dockerfile制作镜像
FROM apolloconfig/apollo-portal
WORKDIR /apollo-portal
#将keycloak的证书拷贝到镜像里
COPY keycloak.cer .
#利用keytool 将自签名证书放到jdk keystore里
RUN keytool -import -trustcacerts -keystore /usr/local/openjdk-8/lib/security/cacerts -alias keycloak -file keycloak.cer -storepass changeit -noprompt
编译成镜像并启动容器
docker build -t apollo/portal .
docker run\
-d\
--name='apollo_portal'\
--net='br0'\
--ip='192.168.50.68'\
-e 'JAVA_OPTS'='-Dspring.profiles.active=github,oidc'\
-v '/mnt/user/appdata/apollo-portal/config/':'/apollo-portal/config':'rw'\
-v '/mnt/user/appdata/apollo-portal/logs/':'/logs':'rw' 'apollo/portal'
这次成功启动。访问portal也成功跳转到keycloak单点登录页面,用keycloak里面已经创建好的用户成功登录了portal。但现在有个问题就是通过keycloak登录的用户 是普通用户,无法对portal进行系统管理。解决方法有两种:
- 在docker启动命令里暂时移除oidc配置,启动后使用之前的管理用户(默认是apollo)登录系统,然后指定通过SSO登录的用户为新的管理员。
- 直接修改portal数据库:
UPDATE
`ApolloPortalDB`.`ServerConfig`
SET
`Value` = '8a0aca75-7e0e-4ec3-b360-23b21f009b67'
WHERE
`Key` = 'superAdmin';
本人使用的是第二种方法,但改完数据库后重新登录没有立即生效,重启了一下portal服务才生效