Support LDAP authentication/authorization#6972
Conversation
|
Hi @mohammadjkhan - thanks for the contribution!! We are in the midst of discussing a template for proposals, that we haven't settled on yet but it seems that we will be able to soon. Would you mind writing one up to help reviewers understand what your patch is doing? I don't know what the final template will be, so feel free to make up your own template for now. Or if you want a suggested template, try this one:
|
|
Oops, nevermind, you did it already!!! I just saw it in: #6416. Thanks, I'll go check that out. In the meantime, it looks like the integration tests are having trouble passing if you would like to take a look at that. |
|
Thanks @gianm. I'm taking a look at failing integration tests right now. I see them falling for me with the same errors/issue even for the master branch that doesn't have my changes. I'm following steps described in integration-tests and executing mvn verify -P integration-tests under the integration-tests module (with docker installed on my machine). |
|
A very useful feature, Thanks for the contribution @mohammadjkhan |
|
I'm also looking into the Travis CI build errors related to the druid-security module |
9729492 to
417b9f2
Compare
|
I unknowingly did pull -rebase on branch 6972 from upstream master while my PR was open, that resulted in my PR tracking other/unrelated changes from upstream master. So I had to reset and force push to clean it up. |
# Conflicts: # docs/content/development/extensions-core/druid-basic-security.md
|
Hi @jon-wei Thanks, |
|
@mohammadjkhan Sorry for the delay, I will start reviewing this week. |
|
I am still reviewing and testing out this patch, I will have more comments on it this week. |
| { | ||
| cacheNotifier = new CommonCacheNotifier( | ||
| userCacheNotifier = new CommonCacheNotifier( | ||
| initAuthenticatorConfigMap(authenticatorMapper), |
There was a problem hiding this comment.
should this be initAuthenticatorUserMap instead of configMap ?
There was a problem hiding this comment.
No, initAuthenticatorConfigMap has nothing to do with user map per say. initAuthenticatorConfigMap is unchanged and just returns the map of authenticator prefix and authenticator configuration (BasicAuthDBConfig) that the CommonCacheNotifier (userCacheNotifier) needs too reference configuration properties like isEnableCacheNotifications
nishantmonu51
left a comment
There was a problem hiding this comment.
did an initial pass through the code, left few comments, Havn't tested the feature myself yet.
few more general comments, not a blocker for this PR and can also be done in subsequent PRs -
- Would be nice to add a tutorial on how to get this feature working would be helpful for new users.
- Druid has integration-tests that run on docker containers, would like to see some basic test for ldap security added as well, so as to ensure this feature does not break with subsequent changes.
| private final Set<BasicAuthorizerRole> roles; | ||
|
|
||
| @JsonCreator | ||
| public BasicAuthorizerGroupMappingFull( |
There was a problem hiding this comment.
this class looks almost duplicate to BasicAuthorizerGroupMapping,
Can we remove duplicates ? Or are there any differences ?
There was a problem hiding this comment.
I modeled BasicAuthorizerGroupMapping and BasicAuthorizerGroupMappingFull entities similar to already existing BasicAuthorizerUser and BasicAuthorizerUserFull entities.
BasicAuthorizerGroupMapping contains a set of role names whereas BasicAuthorizerGroupMappingFull contains a set of role objects, which contains the role name and list of permission objects associated with the role name.
BasicAuthorizerResource getUser and getGroupMapping rest endpoints allows for query parameter "full" that's used to decide whether to just return the role names or the "full" role object in the response.
Please let me know what you think.
|
Given that the metadata store-backed and LDAP implementations have such different configurations, I would structure this as follows:
|
|
Regarding my earlier comment (#6972 (comment)), after more thought I now feel it would be better to split LDAP into a separate contrib extension and leave the existing basic auth extension unchanged.
|
|
| this.enableCacheNotifications = enableCacheNotifications; | ||
| this.cacheNotificationTimeout = cacheNotificationTimeout; | ||
| this.iterations = iterations; | ||
| this.iterations = credentialIterations; |
There was a problem hiding this comment.
nit: Suggest renaming iterations and its getter as well here
| this.itemConfig = null; | ||
| } | ||
|
|
||
| public CommonCacheNotifier( |
There was a problem hiding this comment.
This constructor is unused
| } | ||
|
|
||
| private List<ListenableFuture<StatusResponseHolder>> sendUpdate(String updatedAuthorizerPrefix, byte[] serializedUserMap) | ||
| public void addUpdate(byte[] updatedItemData) |
| BasicAuthDBConfig authorizerConfig = itemConfigMap.get(update.lhs); | ||
| if (!authorizerConfig.isEnableCacheNotifications()) { | ||
|
|
||
| BasicAuthDBConfig dbConfig = itemConfigMap == null ? itemConfig : itemConfigMap.get(update.lhs); |
There was a problem hiding this comment.
This line should be reverted back to BasicAuthDBConfig authorizerConfig = itemConfigMap.get(update.lhs); since the constructor that sets itemConfig is not used anymore
There was a problem hiding this comment.
Done, reverted
| serializedMap | ||
| ); | ||
| List<ListenableFuture<StatusResponseHolder>> futures; | ||
| if (authorizer != null) { |
There was a problem hiding this comment.
The authorizer will always be non-null here, the addUpdate method that would have allowed it to be null is not used
| } | ||
|
|
||
| private URL getListenerURL(DruidNode druidNode, String baseUrl, String itemName) | ||
| private List<ListenableFuture<StatusResponseHolder>> sendUpdate(byte[] serializedEntity) |
There was a problem hiding this comment.
This sendUpdate method should be removed as a result of deleting the unused codepaths in this class
| import java.util.concurrent.atomic.AtomicReference; | ||
| import java.util.stream.Collectors; | ||
|
|
||
| public class BasicAuthenticatorUserPrincipal implements Principal |
There was a problem hiding this comment.
Suggest LdapUserPrincipal classname instead since only the LDAP validator uses this
There was a problem hiding this comment.
Done, renamed
| { | ||
| long now = System.currentTimeMillis(); | ||
| long cutoff = now - (duration * 1000L); | ||
| if (this.lastVerified.get().toEpochMilli() < cutoff) { |
There was a problem hiding this comment.
From the docs, the maxDuration expiring should override the result of any last verified checks, the maxCutoff check should always happen and only if it passes should last verified time be checked
There was a problem hiding this comment.
Done, fixed. Changes are in the new renamed LdapUserPrincipal class
|
|
||
| @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type", defaultImpl = DBCredentialsValidator.class) | ||
| @JsonSubTypes(value = { | ||
| @JsonSubTypes.Type(name = "db", value = DBCredentialsValidator.class), |
There was a problem hiding this comment.
Suggest renaming the type here to metadata and the credentials validator to MetadataStoreCredentialsValidator
There was a problem hiding this comment.
Done, renamed
| { | ||
| Set<LdapName> groups; | ||
| LdapName userDn; | ||
| Map<String, Object> contexMap = new HashMap<>(); |
There was a problem hiding this comment.
Done, renamed
| return null; | ||
| } | ||
| userDn = new LdapName(userResult.getNameInNamespace()); | ||
| groups = getGroupsFromLdap(this.ldapConfig, userResult); |
There was a problem hiding this comment.
I think the group lookup should be moved to the LDAPRoleProvider, since the groups aren't needed to validate the user/password
There was a problem hiding this comment.
Done. This change required a bit more work/effort than I had expected but I agree that moving it to the LDAPRoleProvider makes more sense. Now there's no group related properties or operations within LDAPCredentialsValidator
With this change I also had to move the groupFilters property to ldap authorizer
druid.auth.authorizer.MyBasicLDAPAuthorizer.roleProvider.groupFilters
| import java.util.Set; | ||
|
|
||
| @JsonTypeName("db") | ||
| public class DBRoleProvider implements RoleProvider |
There was a problem hiding this comment.
Suggest renaming to MetadataStoreRoleProvider
There was a problem hiding this comment.
Done. renamed
|
@mohammadjkhan I'm done reviewing, can you fix conflicts and address comments? Thanks! |
# Conflicts: # docs/development/extensions-core/druid-basic-security.md
|
This pull request introduces 1 alert when merging 3db3c05 into 75978e5 - view on LGTM.com new alerts:
|
|
@mohammadjkhan Just checking in again, I think this is ready to merge after final round of comments are addressed. I'm really looking forward to Druid finally supporting LDAP! |
|
@mohammadjkhan Please help us fix this new LGTM alert to maintain the A+ quality. |
|
@mohammadjkhan : Any updates here ? were you able to look into final review comments ? |
|
This pull request introduces 1 alert when merging 0bca543 into 1d42551 - view on LGTM.com new alerts:
|
|
@mohammadjkhan CI is failing on spellcheck, can you add exclusions to https://github.com/apache/incubator-druid/blob/master/website/.spelling, and can you address the 1 new alert from LGTM? |
|
This pull request introduces 1 alert when merging d4a051d into 1d42551 - view on LGTM.com new alerts:
|
|
@jon-wei @asdf2014 @nishantmonu51 fixed spellcheck and LGTM alerts. All requested changes/updates are now complete. Thank you. |
|
LGTM, thanks for the contribution! |
|
Thanks @jon-wei, @nishantmonu51, and @gianm; I really appreciate all your guys help, support, and direction with introducing this feature, and I hope the Druid community makes the most of it and gets benefited from it! |
* Support LDAP authentication/authorization * fixed integration-tests * fixed Travis CI build errors related to druid-security module * fixed failing test * fixed failing test header * added comments, force build * fixes for strict compilation spotbugs checks * removed authenticator rolling credential update feature * removed escalator rolling credential update feature * fixed teamcity inspection deprecated API usage error * fixed checkstyle execution error, removed unused import * removed cached config as part of removing authenticator rolling credential update feature * removed config bundle entity as part of removing authenticator rolling credential update feature * refactored ldao configuration * added support for SSLContext configuration and TLSCertificateChecker * removed check to return authentication failure when user has no group assigned, will be checked and handled by the authorizer * Separate out authorizer checks between metadata-backed store user and LDAP user/groups * refactored BasicSecuritySSLSocketFactory usage to fix strict compilation spotbugs checks * fixes build issue * final review comments updates * final review comments updates * fixed LGTM and spellcheck alerts * Fixed Avatica auth failure error message check * Updated metadata credentials validator exception message string, replaced DB with metadata store

Proposal for LDAP authentication/authorization within Druid
Issues/limitations with the existing Druid Basic Security extension:
Goals:
Proposal:
Fixes #6416