Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unboundid #167

Merged
merged 10 commits into from
Jun 14, 2018
Merged

Unboundid #167

merged 10 commits into from
Jun 14, 2018

Conversation

dvoet
Copy link
Collaborator

@dvoet dvoet commented Jun 11, 2018

implemented new version of directory and access policy daos using unboundid. I did not touch the schema dao, it still uses jndi. But I did turn off the jndi connection pool (schema dao is the only one to use it now and it just runs at the beginning)

Have you read CONTRIBUTING.md lately? If not, do that first.

I, the developer opening this PR, do solemnly pinky swear that:

  • I've followed the instructions if I've made any changes to the API, especially if they're breaking changes
  • I've updated the RC_XXX release ticket with any manual steps required to release this change
  • I've updated the FISMA documentation if I've made any security-related changes, including auth, encryption, or auditing

In all cases:

  • Get two thumbsworth of review and PO signoff if necessary
  • Verify all tests go green
  • Squash and merge; you can delete your branch after this unless it's for a hotfix. In that case, don't delete it!
  • Test this change deployed correctly and works on dev environment after deployment


/**
* Created by dvoet on 6/6/17.
*/
trait DirectorySubjectNameSupport extends JndiSupport {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the additions to this trait moved from JndiSupport

@@ -40,8 +45,17 @@ object Boot extends App with LazyLogging {
implicit val materializer = ActorMaterializer()
import scala.concurrent.ExecutionContext.Implicits.global

val accessPolicyDAO = new JndiAccessPolicyDAO(directoryConfig)
val directoryDAO = new JndiDirectoryDAO(directoryConfig)
val dirURI = new URI(directoryConfig.directoryUrl)
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

jndi supports a ldap url which is what we have in conifg. Unboundid does not so here is a little tap dance to figure it out.

@@ -88,7 +88,8 @@ package object config {
config.getString("user"),
config.getString("password"),
config.getString("baseDn"),
config.getString("enabledUsersGroupDn")
config.getString("enabledUsersGroupDn"),
config.as[Option[Int]]("connectionPoolSize").getOrElse(20)
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

default value for backwards compatibility

Copy link
Contributor

@gpolumbo-broad gpolumbo-broad left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did not go over LdapDirectoryDAO and LdapPolicyDAO in terribly close detail. I scanned them quickly, but otherwise am counting on the tests and the coverage results from Coveralls to verify these classes. @dvoet if you want me to go over them in closer detail, just let me know.

case unsupported => throw new WorkbenchException(s"unsupported directory url scheme: $unsupported")
}
val port = if (dirURI.getPort > 0) dirURI.getPort else defaultPort
val ldapConnectionPool = new LDAPConnectionPool(new LDAPConnection(socketFactory, dirURI.getHost, port, directoryConfig.user, directoryConfig.password), directoryConfig.connectionPoolSize)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we don't want to do anything now, but going off of @MatthewBemis's observation last week about setting the TTL on the connections, we might consider throwing in a call to https://docs.ldap.com/ldap-sdk/docs/javadoc/com/unboundid/ldap/sdk/LDAPConnectionPool.html#setMaxConnectionAgeMillis() at some point.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not ready to do anything yet... let's keep with current behavior and see how it goes

protected def dnMatcher(matchAttributeNames: Seq[String], baseDn: String): Regex = {
val partStrings = matchAttributeNames.map { attrName => s"$attrName=([^,]+)" }
partStrings.mkString("(?i)", ",", s",$baseDn").r
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are there tests for this?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this code was just moved, not changed. I don't know if there are specific tests but it is tested.

@@ -62,4 +80,7 @@ trait DirectorySubjectNameSupport extends JndiSupport {
case _ => throw new WorkbenchException(s"not a group dn [$dn]")
}
}

protected def formattedDate(date: Date) = new SimpleDateFormat("yyyyMMddHHmmss.SSSZ").format(date)
protected def parseDate(date: String) = new SimpleDateFormat("yyyyMMddHHmmss.SSSZ").parse(date)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit, but extract string. Maybe add just a couple of basic tests.

} recover {
case _: NoSuchAttributeException => () // don't fail if the member is already not in the group
case _: NoSuchAttributeException => false
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this what we want? If I am trying to remove User1 from group foo and the user is already not present in the group, maybe that should be OK and just return true. In other words, I'm interpreting the method contract as: "When I return, the subject specified will no longer be a member of the group and I will return True. I will throw an exception if the group doesn't exist or some other error occurs while trying to remove the user from the group."

Alternatively, instead of just returning false, should we return an ErrorReport?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

look in the DirectoryDAO trait for the docs of how this should work. In general though, if at the end of the call the user is not in the group the function is successful. The boolean output signifies whether or not the user as actually removed during the course of the function call. This is a common pattern (https://docs.oracle.com/javase/7/docs/api/java/util/Set.html#remove(java.lang.Object)).

It is not an error so no ErrorReport.

case Success(_) => true
case Failure(_: AttributeInUseException) => false
case Failure(regrets) => throw regrets
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method uses a Try block, whereas removeGroupMember uses just a withContext{...}recover{...}. Is there a reason why the alternative approaches are used? Since these methods are a matching pair, I think it makes sense for them to be consistent in implementation.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this class is on the chopping block anyway, the change was only made because it made sense to change the return type

directoryDAO.addGroupMember(resourceAndPolicyName, subject) recover {
case _: AttributeInUseException => // subject is already there
} andThen {
directoryDAO.addGroupMember(resourceAndPolicyName, subject).map(_ => ()) andThen {
case Success(_) => fireGroupUpdateNotification(resourceAndPolicyName)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is possible that addGroupMember returns Success(false), in which case, we probably don't need to call fireGroupUpdateNotification because nothing changed. Furthermore, the fact that the user wasn't added, is not bubbled up in any way here, which means addSubjectToPolicy did not successfully perform its task and that's not reported out in any way.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

at the end of this function the subject is in the policy which is the desired result so everything is ok. I think you misunderstand what Success(false) means, it is not an error, it means the user was already there.

Technically we don't need to fireGroupUpdateNotification on Success(false) but I think that is needless complexity

directoryDAO.removeGroupMember(resourceAndPolicyName, subject) recover {
case _: NoSuchAttributeException => // subject already gone
} andThen {
directoryDAO.removeGroupMember(resourceAndPolicyName, subject).map(_ => ()) andThen {
case Success(_) => fireGroupUpdateNotification(resourceAndPolicyName)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See comment for addSubjectToPolicy above. I'm not sure we want to treat Success(true) and Success(false) the same way.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we do, none of this is new functionality

@@ -58,20 +58,6 @@ trait JndiSupport {
t.get
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should we mark this method and/or class as deprecated and identify that it is still permitted to be used by the JndiSchemaDAO only.

Do we have a longer term task to refactor the JndiSchemaDAO to use unboundid? Or are we just going to leave it using JNDI?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

deprecated

@@ -48,6 +53,11 @@ class JndiDirectoryDAOSpec extends FlatSpec with Matchers with TestSupport with
runAndWait(dao.createGroup(group))
}

val conflict = intercept[WorkbenchExceptionWithErrorReport] {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The name of the spec is "JndiGroupDirectoryDAO" should "create... should be renamed to LdapGroupDirectoryDAO

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

@dvoet
Copy link
Collaborator Author

dvoet commented Jun 13, 2018

jenkins retest with leo fix merged

@dvoet
Copy link
Collaborator Author

dvoet commented Jun 14, 2018

jenkins retest

@dvoet dvoet merged commit 99af22d into develop Jun 14, 2018
@dvoet dvoet deleted the unboundid branch June 14, 2018 19:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants