最近在重构Ambari,在Server修改后在k8s中启动后,通过外部服务调用/api/v1/bootstrap/去拉起agent的时候出现一个问题:

<p>Problem accessing /api/v1/bootstrap/. Reason:
<pre> Server Error</pre></p><h3>Caused by:</h3><pre>java.lang.IllegalArgumentException: Detected a Non-hex character at 1 or 2 position
at org.springframework.security.crypto.codec.Hex.decode(Hex.java:62)
at org.springframework.security.crypto.password.StandardPasswordEncoder.decode(StandardPasswordEncoder.java:105)
at org.springframework.security.crypto.password.StandardPasswordEncoder.matches(StandardPasswordEncoder.java:80)
at org.apache.ambari.server.security.authentication.AmbariLocalAuthenticationProvider.authenticate(AmbariLocalAuthenticationProvider.java:80)
at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:175)
at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:200)
at org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter$AuthenticationManagerDelegator.authenticate(WebSecurityConfigurerAdapter.java:503)
at org.springframework.security.web.authentication.www.BasicAuthenticationFilter.doFilterInternal(BasicAuthenticationFilter.java:180)
at org.apache.ambari.server.security.authentication.AmbariBasicAuthenticationFilter.doFilterInternal(AmbariBasicAuthenticationFilter.java:139)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.apache.ambari.server.security.authentication.AmbariDelegatingAuthenticationFilter.doFilter(AmbariDelegatingAuthenticationFilter.java:123)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at org.apache.ambari.server.security.authorization.AmbariUserAuthorizationFilter.doFilter(AmbariUserAuthorizationFilter.java:95)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:74)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)

第一感觉就是密码加密保存的问题,于是去查询了一下ambari的user_authentication表看到:

mysql> select * from user_authentication;
+------------------------+---------+---------------------+--------------------+---------------+---------------+
| user_authentication_id | user_id | authentication_type | authentication_key | create_time | update_time |
+------------------------+---------+---------------------+--------------------+---------------+---------------+
| 1 | 1 | LOCAL | file | 1649696720000 | 1649696736000 |
+------------------------+---------+---------------------+--------------------+---------------+---------------+

这里的authentication_key有问题,正常来说这个字段存放的应该是hash值,例如这样:

+------------------------+---------+---------------------+----------------------------------------------------------------------------------+---------------+---------------+
| user_authentication_id | user_id | authentication_type | authentication_key | create_time | update_time |
+------------------------+---------+---------------------+----------------------------------------------------------------------------------+---------------+---------------+
| 1 | 1 | LOCAL | 538916f8943ec225d97a9a86a2c6ec0818c1cd400e09e03b660fdaaec4af29ddbb6f2b1033b81b00 | 1644559868000 | 1644559879000 |
+------------------------+---------+---------------------+----------------------------------------------------------------------------------+---------------+---------------+

在org/apache/ambari/server/security/authentication/AmbariLocalAuthenticationProvider.java中的authenticate方法里面进行了密码的处理:

UserAuthenticationEntity authenticationEntity = getAuthenticationEntity(userEntity, UserAuthenticationType.LOCAL);
if (authenticationEntity != null) {
String password = authenticationEntity.getAuthenticationKey();
String presentedPassword = authentication.getCredentials().toString();

if (passwordEncoder.matches(presentedPassword, password)) {
// The user was authenticated, return the authenticated user object

这里的passwordEncoder在ambari中是由StandardPasswordEncoder去执行,因此该matches的实际执行方法为:

public boolean matches(CharSequence rawPassword, String encodedPassword) {
byte[] digested = decode(encodedPassword);
byte[] salt = subArray(digested, 0, saltGenerator.getKeyLength());
return matches(digested, digest(rawPassword, salt));
}

出错的方法就在decode这个方法里:

private byte[] decode(CharSequence encodedPassword) {
return Hex.decode(encodedPassword);
}

encodedPassword是从数据库里面读取出来的hash值,做了hex的解密,但是由于写入数据库的hash有问题,因此这里的内容并不符合hex的标准。


扫码手机观看或分享: