From 6515c662089fa322fa3aeb2e52368f237afe9fe4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=97=BA=E9=98=B3?= Date: Fri, 17 Jun 2022 14:18:05 +0800 Subject: [PATCH] [Improve] Add LDAP user not exsitst action config (#10451) --- docs/docs/en/architecture/configuration.md | 7 ++-- docs/docs/zh/architecture/configuration.md | 8 ++-- .../security/LdapUserNotExistActionType.java | 39 +++++++++++++++++++ .../security/impl/ldap/LdapAuthenticator.java | 2 +- .../api/security/impl/ldap/LdapService.java | 25 ++++++++++-- .../src/main/resources/application.yaml | 13 ++++--- .../api/security/SecurityConfigLDAPTest.java | 14 +++++++ .../impl/ldap/LdapAuthenticatorTest.java | 26 +++++++++---- .../security/impl/ldap/LdapServiceTest.java | 7 ++-- .../src/main/resources/application.yaml | 13 ++++--- 10 files changed, 123 insertions(+), 31 deletions(-) create mode 100644 dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/security/LdapUserNotExistActionType.java diff --git a/docs/docs/en/architecture/configuration.md b/docs/docs/en/architecture/configuration.md index eb97e8fa60..7fb176219f 100644 --- a/docs/docs/en/architecture/configuration.md +++ b/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.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.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.password|password|LDAP password -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.identity-attribute|uid|LDAP user identity 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] diff --git a/docs/docs/zh/architecture/configuration.md b/docs/docs/zh/architecture/configuration.md index 6adde902ac..ec413b5404 100644 --- a/docs/docs/zh/architecture/configuration.md +++ b/docs/docs/zh/architecture/configuration.md @@ -212,12 +212,12 @@ spring.messages.basename|i18n/messages|i18n配置 security.authentication.type|PASSWORD|权限校验类型 security.authentication.ldap.user.admin|read-only-admin|LDAP登陆时,系统管理员账号 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.password|password|LDAP密码 -security.authentication.ldap.user.identity.attribute|uid|LDAP用户身份标识字段名 -security.authentication.ldap.user.email.attribute|mail|LDAP邮箱字段名 - +security.authentication.ldap.user.identity-attribute|uid|LDAP用户身份标识字段名 +security.authentication.ldap.user.email-attribute|mail|LDAP邮箱字段名 +security.authentication.ldap.user.not-exist-action|CREATE|当LDAP用户不存在时执行的操作。CREATE:当用户不存在时自动新建用户, DENY:当用户不存在时拒绝登陆 ## 6.master.properties [Master服务配置] |参数 |默认值| 描述| diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/security/LdapUserNotExistActionType.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/security/LdapUserNotExistActionType.java new file mode 100644 index 0000000000..1e96ef2954 --- /dev/null +++ b/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; +} diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/security/impl/ldap/LdapAuthenticator.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/security/impl/ldap/LdapAuthenticator.java index 1604b79b6a..f8247aa8e6 100644 --- a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/security/impl/ldap/LdapAuthenticator.java +++ b/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) { //check if user exist user = usersService.getUserByUserName(userId); - if (user == null) { + if (user == null && ldapService.createIfUserNotExists()) { user = usersService.createUser(ldapService.getUserType(userId), userId, ldapEmail); } } diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/security/impl/ldap/LdapService.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/security/impl/ldap/LdapService.java index 35abb11479..6dac2f71d2 100644 --- a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/security/impl/ldap/LdapService.java +++ b/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; +import org.apache.dolphinscheduler.api.security.LdapUserNotExistActionType; import org.apache.dolphinscheduler.common.enums.UserType; +import org.apache.commons.lang3.StringUtils; + import java.util.Properties; import javax.naming.Context; @@ -48,7 +51,7 @@ public class LdapService { @Value("${security.authentication.ldap.urls:null}") private String ldapUrls; - @Value("${security.authentication.ldap.base.dn:null}") + @Value("${security.authentication.ldap.base-dn:null}") private String ldapBaseDn; @Value("${security.authentication.ldap.username:null}") @@ -57,12 +60,15 @@ public class LdapService { @Value("${security.authentication.ldap.password:null}") private String ldapPrincipalPassword; - @Value("${security.authentication.ldap.user.identity.attribute:null}") + @Value("${security.authentication.ldap.user.identity-attribute:null}") private String ldapUserIdentifyingAttribute; - @Value("${security.authentication.ldap.user.email.attribute:null}") + @Value("${security.authentication.ldap.user.email-attribute:null}") private String ldapEmailAttribute; + @Value("${security.authentication.ldap.user.not-exist-action:CREATE}") + private String ldapUserNotExistAction; + /*** * get user type by configured admin userId * @param userId login userId @@ -130,4 +136,17 @@ public class LdapService { env.put(Context.PROVIDER_URL, ldapUrls); 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; + } } diff --git a/dolphinscheduler-api/src/main/resources/application.yaml b/dolphinscheduler-api/src/main/resources/application.yaml index 542b8048ed..e367a32b2a 100644 --- a/dolphinscheduler-api/src/main/resources/application.yaml +++ b/dolphinscheduler-api/src/main/resources/application.yaml @@ -134,15 +134,18 @@ security: type: PASSWORD # IF you set type `LDAP`, below config will be effective ldap: - # admin userId - user.admin: read-only-admin # ldap server config 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 password: password - user.identity.attribute: uid - user.email.attribute: mail + user: + # 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 diff --git a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/security/SecurityConfigLDAPTest.java b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/security/SecurityConfigLDAPTest.java index d1f1d8ebce..910e5d812e 100644 --- a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/security/SecurityConfigLDAPTest.java +++ b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/security/SecurityConfigLDAPTest.java @@ -18,6 +18,7 @@ package org.apache.dolphinscheduler.api.security; import org.apache.dolphinscheduler.api.controller.AbstractControllerTest; +import org.apache.dolphinscheduler.api.security.impl.ldap.LdapService; import org.junit.Assert; import org.junit.Test; @@ -32,9 +33,22 @@ public class SecurityConfigLDAPTest extends AbstractControllerTest { @Autowired private SecurityConfig securityConfig; + @Autowired + private LdapService ldapService; + @Test public void testAuthenticator() { Authenticator authenticator = securityConfig.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); + } } + diff --git a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/security/impl/ldap/LdapAuthenticatorTest.java b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/security/impl/ldap/LdapAuthenticatorTest.java index ba0f72a039..f3835a560a 100644 --- a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/security/impl/ldap/LdapAuthenticatorTest.java +++ b/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.enums.Status; +import org.apache.dolphinscheduler.api.security.LdapUserNotExistActionType; import org.apache.dolphinscheduler.api.service.SessionService; import org.apache.dolphinscheduler.api.service.UsersService; 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 java.util.Date; +import java.util.Map; import java.util.UUID; import javax.servlet.http.HttpServletRequest; @@ -51,11 +53,12 @@ import org.springframework.test.context.TestPropertySource; "security.authentication.type=LDAP", "security.authentication.ldap.user.admin=read-only-admin", "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.password=password", - "security.authentication.ldap.user.identity.attribute=uid", - "security.authentication.ldap.user.email.attribute=mail", + "security.authentication.ldap.user.identity-attribute=uid", + "security.authentication.ldap.user.email-attribute=mail", + "security.authentication.ldap.user.not-exist-action=CREATE", }) public class LdapAuthenticatorTest extends AbstractControllerTest { private static Logger logger = LoggerFactory.getLogger(LdapAuthenticatorTest.class); @@ -98,23 +101,32 @@ public class LdapAuthenticatorTest extends AbstractControllerTest { mockSession.setIp(ip); mockSession.setUserId(1); mockSession.setLastLoginTime(new Date()); - } @Test public void testAuthenticate() { - when(sessionService.createSession(Mockito.any(User.class), Mockito.eq(ip))).thenReturn(mockSession.getId()); 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> 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()); 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); - result = ldapAuthenticator.authenticate(ldapUid, ldapUserPwd, ip); Assert.assertEquals(Status.LOGIN_SESSION_FAILED.getCode(), (int) result.getCode()); + // test username pwd error, login failed when(ldapService.ldapLogin(ldapUid, ldapUserPwd)).thenReturn(null); result = ldapAuthenticator.authenticate(ldapUid, ldapUserPwd, ip); Assert.assertEquals(Status.USER_NAME_PASSWD_ERROR.getCode(), (int) result.getCode()); diff --git a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/security/impl/ldap/LdapServiceTest.java b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/security/impl/ldap/LdapServiceTest.java index 54e25f4f0e..ecda46d13f 100644 --- a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/security/impl/ldap/LdapServiceTest.java +++ b/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.ldap.user.admin=read-only-admin", "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.password=password", - "security.authentication.ldap.user.identity.attribute=uid", - "security.authentication.ldap.user.email.attribute=mail", + "security.authentication.ldap.user.identity-attribute=uid", + "security.authentication.ldap.user.email-attribute=mail", + "security.authentication.ldap.user.not-exist-action=CREATE", }) public class LdapServiceTest { @Autowired diff --git a/dolphinscheduler-standalone-server/src/main/resources/application.yaml b/dolphinscheduler-standalone-server/src/main/resources/application.yaml index 945cae26bb..8e36546db7 100644 --- a/dolphinscheduler-standalone-server/src/main/resources/application.yaml +++ b/dolphinscheduler-standalone-server/src/main/resources/application.yaml @@ -92,15 +92,18 @@ security: type: PASSWORD # IF you set type `LDAP`, below config will be effective ldap: - # admin userId - user.admin: read-only-admin # ldap server config 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 password: password - user.identity.attribute: uid - user.email.attribute: mail + user: + # 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: listen-port: 5678