Browse Source

[Improve] Add LDAP user not exsitst action config (#10451)

3.1.0-release
旺阳 2 years ago committed by GitHub
parent
commit
6515c66208
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 7
      docs/docs/en/architecture/configuration.md
  2. 8
      docs/docs/zh/architecture/configuration.md
  3. 39
      dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/security/LdapUserNotExistActionType.java
  4. 2
      dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/security/impl/ldap/LdapAuthenticator.java
  5. 25
      dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/security/impl/ldap/LdapService.java
  6. 13
      dolphinscheduler-api/src/main/resources/application.yaml
  7. 14
      dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/security/SecurityConfigLDAPTest.java
  8. 26
      dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/security/impl/ldap/LdapAuthenticatorTest.java
  9. 7
      dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/security/impl/ldap/LdapServiceTest.java
  10. 13
      dolphinscheduler-standalone-server/src/main/resources/application.yaml

7
docs/docs/en/architecture/configuration.md

@ -221,11 +221,12 @@ spring.messages.basename|i18n/messages| i18n config
security.authentication.type|PASSWORD| authentication type security.authentication.type|PASSWORD| authentication type
security.authentication.ldap.user.admin|read-only-admin|admin user account when you log-in with LDAP security.authentication.ldap.user.admin|read-only-admin|admin user account when you log-in with LDAP
security.authentication.ldap.urls|ldap://ldap.forumsys.com:389/|LDAP urls security.authentication.ldap.urls|ldap://ldap.forumsys.com:389/|LDAP urls
security.authentication.ldap.base.dn|dc=example,dc=com|LDAP base dn security.authentication.ldap.base-dn|dc=example,dc=com|LDAP base dn
security.authentication.ldap.username|cn=read-only-admin,dc=example,dc=com|LDAP username security.authentication.ldap.username|cn=read-only-admin,dc=example,dc=com|LDAP username
security.authentication.ldap.password|password|LDAP password security.authentication.ldap.password|password|LDAP password
security.authentication.ldap.user.identity.attribute|uid|LDAP user identity attribute security.authentication.ldap.user.identity-attribute|uid|LDAP user identity attribute
security.authentication.ldap.user.email.attribute|mail|LDAP user email attribute security.authentication.ldap.user.email-attribute|mail|LDAP user email attribute
security.authentication.ldap.user.not-exist-action|CREATE|action when LDAP user is not exist. Default CREATE: automatically create user when user not exist, DENY: deny log-in when user not exist
### master.properties [master-service log config] ### master.properties [master-service log config]

8
docs/docs/zh/architecture/configuration.md

@ -212,12 +212,12 @@ spring.messages.basename|i18n/messages|i18n配置
security.authentication.type|PASSWORD|权限校验类型 security.authentication.type|PASSWORD|权限校验类型
security.authentication.ldap.user.admin|read-only-admin|LDAP登陆时,系统管理员账号 security.authentication.ldap.user.admin|read-only-admin|LDAP登陆时,系统管理员账号
security.authentication.ldap.urls|ldap://ldap.forumsys.com:389/|LDAP urls security.authentication.ldap.urls|ldap://ldap.forumsys.com:389/|LDAP urls
security.authentication.ldap.base.dn|dc=example,dc=com|LDAP base dn security.authentication.ldap.base-dn|dc=example,dc=com|LDAP base dn
security.authentication.ldap.username|cn=read-only-admin,dc=example,dc=com|LDAP账号 security.authentication.ldap.username|cn=read-only-admin,dc=example,dc=com|LDAP账号
security.authentication.ldap.password|password|LDAP密码 security.authentication.ldap.password|password|LDAP密码
security.authentication.ldap.user.identity.attribute|uid|LDAP用户身份标识字段名 security.authentication.ldap.user.identity-attribute|uid|LDAP用户身份标识字段名
security.authentication.ldap.user.email.attribute|mail|LDAP邮箱字段名 security.authentication.ldap.user.email-attribute|mail|LDAP邮箱字段名
security.authentication.ldap.user.not-exist-action|CREATE|当LDAP用户不存在时执行的操作。CREATE:当用户不存在时自动新建用户, DENY:当用户不存在时拒绝登陆
## 6.master.properties [Master服务配置] ## 6.master.properties [Master服务配置]
|参数 |默认值| 描述| |参数 |默认值| 描述|

39
dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/security/LdapUserNotExistActionType.java

@ -0,0 +1,39 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dolphinscheduler.api.security;
import com.baomidou.mybatisplus.annotation.EnumValue;
/**
* ldap user not exist action type
*/
public enum LdapUserNotExistActionType {
CREATE(0, "automatically create user when user not exist"),
DENY(1, "deny log-in when user not exist"),
;
LdapUserNotExistActionType(int code, String desc) {
this.code = code;
this.desc = desc;
}
@EnumValue
private final int code;
private final String desc;
}

2
dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/security/impl/ldap/LdapAuthenticator.java

@ -36,7 +36,7 @@ public class LdapAuthenticator extends AbstractAuthenticator {
if (ldapEmail != null) { if (ldapEmail != null) {
//check if user exist //check if user exist
user = usersService.getUserByUserName(userId); user = usersService.getUserByUserName(userId);
if (user == null) { if (user == null && ldapService.createIfUserNotExists()) {
user = usersService.createUser(ldapService.getUserType(userId), userId, ldapEmail); user = usersService.createUser(ldapService.getUserType(userId), userId, ldapEmail);
} }
} }

25
dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/security/impl/ldap/LdapService.java

@ -17,8 +17,11 @@
package org.apache.dolphinscheduler.api.security.impl.ldap; package org.apache.dolphinscheduler.api.security.impl.ldap;
import org.apache.dolphinscheduler.api.security.LdapUserNotExistActionType;
import org.apache.dolphinscheduler.common.enums.UserType; import org.apache.dolphinscheduler.common.enums.UserType;
import org.apache.commons.lang3.StringUtils;
import java.util.Properties; import java.util.Properties;
import javax.naming.Context; import javax.naming.Context;
@ -48,7 +51,7 @@ public class LdapService {
@Value("${security.authentication.ldap.urls:null}") @Value("${security.authentication.ldap.urls:null}")
private String ldapUrls; private String ldapUrls;
@Value("${security.authentication.ldap.base.dn:null}") @Value("${security.authentication.ldap.base-dn:null}")
private String ldapBaseDn; private String ldapBaseDn;
@Value("${security.authentication.ldap.username:null}") @Value("${security.authentication.ldap.username:null}")
@ -57,12 +60,15 @@ public class LdapService {
@Value("${security.authentication.ldap.password:null}") @Value("${security.authentication.ldap.password:null}")
private String ldapPrincipalPassword; private String ldapPrincipalPassword;
@Value("${security.authentication.ldap.user.identity.attribute:null}") @Value("${security.authentication.ldap.user.identity-attribute:null}")
private String ldapUserIdentifyingAttribute; private String ldapUserIdentifyingAttribute;
@Value("${security.authentication.ldap.user.email.attribute:null}") @Value("${security.authentication.ldap.user.email-attribute:null}")
private String ldapEmailAttribute; private String ldapEmailAttribute;
@Value("${security.authentication.ldap.user.not-exist-action:CREATE}")
private String ldapUserNotExistAction;
/*** /***
* get user type by configured admin userId * get user type by configured admin userId
* @param userId login userId * @param userId login userId
@ -130,4 +136,17 @@ public class LdapService {
env.put(Context.PROVIDER_URL, ldapUrls); env.put(Context.PROVIDER_URL, ldapUrls);
return env; return env;
} }
public LdapUserNotExistActionType getLdapUserNotExistAction(){
if (StringUtils.isBlank(ldapUserNotExistAction)) {
logger.info("security.authentication.ldap.user.not.exist.action configuration is empty, the default value 'CREATE'");
return LdapUserNotExistActionType.CREATE;
}
return LdapUserNotExistActionType.valueOf(ldapUserNotExistAction);
}
public boolean createIfUserNotExists(){
return getLdapUserNotExistAction() == LdapUserNotExistActionType.CREATE;
}
} }

13
dolphinscheduler-api/src/main/resources/application.yaml

@ -134,15 +134,18 @@ security:
type: PASSWORD type: PASSWORD
# IF you set type `LDAP`, below config will be effective # IF you set type `LDAP`, below config will be effective
ldap: ldap:
# admin userId
user.admin: read-only-admin
# ldap server config # ldap server config
urls: ldap://ldap.forumsys.com:389/ urls: ldap://ldap.forumsys.com:389/
base.dn: dc=example,dc=com base-dn: dc=example,dc=com
username: cn=read-only-admin,dc=example,dc=com username: cn=read-only-admin,dc=example,dc=com
password: password password: password
user.identity.attribute: uid user:
user.email.attribute: mail # admin userId when you use LDAP login
admin: read-only-admin
identity-attribute: uid
email-attribute: mail
# action when ldap user is not exist (supported types: CREATE,DENY)
not-exist-action: CREATE
# Override by profile # Override by profile

14
dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/security/SecurityConfigLDAPTest.java

@ -18,6 +18,7 @@
package org.apache.dolphinscheduler.api.security; package org.apache.dolphinscheduler.api.security;
import org.apache.dolphinscheduler.api.controller.AbstractControllerTest; import org.apache.dolphinscheduler.api.controller.AbstractControllerTest;
import org.apache.dolphinscheduler.api.security.impl.ldap.LdapService;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
@ -32,9 +33,22 @@ public class SecurityConfigLDAPTest extends AbstractControllerTest {
@Autowired @Autowired
private SecurityConfig securityConfig; private SecurityConfig securityConfig;
@Autowired
private LdapService ldapService;
@Test @Test
public void testAuthenticator() { public void testAuthenticator() {
Authenticator authenticator = securityConfig.authenticator(); Authenticator authenticator = securityConfig.authenticator();
Assert.assertNotNull(authenticator); Assert.assertNotNull(authenticator);
} }
@Test
public void testLdapUserNotExistAction() {
LdapUserNotExistActionType authenticator = ldapService.getLdapUserNotExistAction();
Assert.assertEquals(LdapUserNotExistActionType.CREATE, authenticator);
boolean isCreateAction = ldapService.createIfUserNotExists();
Assert.assertEquals(Boolean.TRUE, isCreateAction);
}
} }

26
dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/security/impl/ldap/LdapAuthenticatorTest.java

@ -21,6 +21,7 @@ import static org.mockito.Mockito.when;
import org.apache.dolphinscheduler.api.controller.AbstractControllerTest; import org.apache.dolphinscheduler.api.controller.AbstractControllerTest;
import org.apache.dolphinscheduler.api.enums.Status; import org.apache.dolphinscheduler.api.enums.Status;
import org.apache.dolphinscheduler.api.security.LdapUserNotExistActionType;
import org.apache.dolphinscheduler.api.service.SessionService; import org.apache.dolphinscheduler.api.service.SessionService;
import org.apache.dolphinscheduler.api.service.UsersService; import org.apache.dolphinscheduler.api.service.UsersService;
import org.apache.dolphinscheduler.api.utils.Result; import org.apache.dolphinscheduler.api.utils.Result;
@ -30,6 +31,7 @@ import org.apache.dolphinscheduler.dao.entity.Session;
import org.apache.dolphinscheduler.dao.entity.User; import org.apache.dolphinscheduler.dao.entity.User;
import java.util.Date; import java.util.Date;
import java.util.Map;
import java.util.UUID; import java.util.UUID;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
@ -51,11 +53,12 @@ import org.springframework.test.context.TestPropertySource;
"security.authentication.type=LDAP", "security.authentication.type=LDAP",
"security.authentication.ldap.user.admin=read-only-admin", "security.authentication.ldap.user.admin=read-only-admin",
"security.authentication.ldap.urls=ldap://ldap.forumsys.com:389/", "security.authentication.ldap.urls=ldap://ldap.forumsys.com:389/",
"security.authentication.ldap.base.dn=dc=example,dc=com", "security.authentication.ldap.base-dn=dc=example,dc=com",
"security.authentication.ldap.username=cn=read-only-admin,dc=example,dc=com", "security.authentication.ldap.username=cn=read-only-admin,dc=example,dc=com",
"security.authentication.ldap.password=password", "security.authentication.ldap.password=password",
"security.authentication.ldap.user.identity.attribute=uid", "security.authentication.ldap.user.identity-attribute=uid",
"security.authentication.ldap.user.email.attribute=mail", "security.authentication.ldap.user.email-attribute=mail",
"security.authentication.ldap.user.not-exist-action=CREATE",
}) })
public class LdapAuthenticatorTest extends AbstractControllerTest { public class LdapAuthenticatorTest extends AbstractControllerTest {
private static Logger logger = LoggerFactory.getLogger(LdapAuthenticatorTest.class); private static Logger logger = LoggerFactory.getLogger(LdapAuthenticatorTest.class);
@ -98,23 +101,32 @@ public class LdapAuthenticatorTest extends AbstractControllerTest {
mockSession.setIp(ip); mockSession.setIp(ip);
mockSession.setUserId(1); mockSession.setUserId(1);
mockSession.setLastLoginTime(new Date()); mockSession.setLastLoginTime(new Date());
} }
@Test @Test
public void testAuthenticate() { public void testAuthenticate() {
when(sessionService.createSession(Mockito.any(User.class), Mockito.eq(ip))).thenReturn(mockSession.getId());
when(ldapService.ldapLogin(ldapUid, ldapUserPwd)).thenReturn(ldapEmail); when(ldapService.ldapLogin(ldapUid, ldapUserPwd)).thenReturn(ldapEmail);
when(sessionService.createSession(Mockito.any(User.class), Mockito.eq(ip))).thenReturn(mockSession.getId());
Result result = ldapAuthenticator.authenticate(ldapUid, ldapUserPwd, ip); // test username pwd correct and user not exist, config user not exist action deny, so login denied
when(ldapService.getLdapUserNotExistAction()).thenReturn(LdapUserNotExistActionType.DENY);
when(ldapService.createIfUserNotExists()).thenReturn(false);
Result<Map<String, String>> result = ldapAuthenticator.authenticate(ldapUid, ldapUserPwd, ip);
Assert.assertEquals(Status.USER_NAME_PASSWD_ERROR.getCode(), (int) result.getCode());
// test username pwd correct and user not exist, config user not exist action create, so login success
when(ldapService.getLdapUserNotExistAction()).thenReturn(LdapUserNotExistActionType.CREATE);
when(ldapService.createIfUserNotExists()).thenReturn(true);
result = ldapAuthenticator.authenticate(ldapUid, ldapUserPwd, ip);
Assert.assertEquals(Status.SUCCESS.getCode(), (int) result.getCode()); Assert.assertEquals(Status.SUCCESS.getCode(), (int) result.getCode());
logger.info(result.toString()); logger.info(result.toString());
// test username pwd correct and user not exist, config action create but can't create session, so login failed
when(sessionService.createSession(Mockito.any(User.class), Mockito.eq(ip))).thenReturn(null); when(sessionService.createSession(Mockito.any(User.class), Mockito.eq(ip))).thenReturn(null);
result = ldapAuthenticator.authenticate(ldapUid, ldapUserPwd, ip); result = ldapAuthenticator.authenticate(ldapUid, ldapUserPwd, ip);
Assert.assertEquals(Status.LOGIN_SESSION_FAILED.getCode(), (int) result.getCode()); Assert.assertEquals(Status.LOGIN_SESSION_FAILED.getCode(), (int) result.getCode());
// test username pwd error, login failed
when(ldapService.ldapLogin(ldapUid, ldapUserPwd)).thenReturn(null); when(ldapService.ldapLogin(ldapUid, ldapUserPwd)).thenReturn(null);
result = ldapAuthenticator.authenticate(ldapUid, ldapUserPwd, ip); result = ldapAuthenticator.authenticate(ldapUid, ldapUserPwd, ip);
Assert.assertEquals(Status.USER_NAME_PASSWD_ERROR.getCode(), (int) result.getCode()); Assert.assertEquals(Status.USER_NAME_PASSWD_ERROR.getCode(), (int) result.getCode());

7
dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/security/impl/ldap/LdapServiceTest.java

@ -42,11 +42,12 @@ import org.springframework.test.context.junit4.SpringRunner;
"security.authentication.type=LDAP", "security.authentication.type=LDAP",
"security.authentication.ldap.user.admin=read-only-admin", "security.authentication.ldap.user.admin=read-only-admin",
"security.authentication.ldap.urls=ldap://ldap.forumsys.com:389/", "security.authentication.ldap.urls=ldap://ldap.forumsys.com:389/",
"security.authentication.ldap.base.dn=dc=example,dc=com", "security.authentication.ldap.base-dn=dc=example,dc=com",
"security.authentication.ldap.username=cn=read-only-admin,dc=example,dc=com", "security.authentication.ldap.username=cn=read-only-admin,dc=example,dc=com",
"security.authentication.ldap.password=password", "security.authentication.ldap.password=password",
"security.authentication.ldap.user.identity.attribute=uid", "security.authentication.ldap.user.identity-attribute=uid",
"security.authentication.ldap.user.email.attribute=mail", "security.authentication.ldap.user.email-attribute=mail",
"security.authentication.ldap.user.not-exist-action=CREATE",
}) })
public class LdapServiceTest { public class LdapServiceTest {
@Autowired @Autowired

13
dolphinscheduler-standalone-server/src/main/resources/application.yaml

@ -92,15 +92,18 @@ security:
type: PASSWORD type: PASSWORD
# IF you set type `LDAP`, below config will be effective # IF you set type `LDAP`, below config will be effective
ldap: ldap:
# admin userId
user.admin: read-only-admin
# ldap server config # ldap server config
urls: ldap://ldap.forumsys.com:389/ urls: ldap://ldap.forumsys.com:389/
base.dn: dc=example,dc=com base-dn: dc=example,dc=com
username: cn=read-only-admin,dc=example,dc=com username: cn=read-only-admin,dc=example,dc=com
password: password password: password
user.identity.attribute: uid user:
user.email.attribute: mail # admin userId when you use LDAP login
admin: read-only-admin
identity-attribute: uid
email-attribute: mail
# action when ldap user is not exist (supported types: CREATE,DENY)
not-exist-action: CREATE
master: master:
listen-port: 5678 listen-port: 5678

Loading…
Cancel
Save