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

LDAP: Support Account Attribute Maps #4788

Merged
merged 3 commits into from May 20, 2024
Merged

LDAP: Support Account Attribute Maps #4788

merged 3 commits into from May 20, 2024

Conversation

hugoghx
Copy link
Collaborator

@hugoghx hugoghx commented May 9, 2024

This PR enables CLI support for account attribute maps and also takes the LDAP server's user attributes into account when authenticating with an LDAP auth method

@hugoghx hugoghx requested review from jimlambrt and kheina May 9, 2024 13:48
@hugoghx hugoghx self-assigned this May 9, 2024
@hugoghx hugoghx requested a review from louisruch May 9, 2024 13:52
Copy link
Collaborator

@louisruch louisruch left a comment

Choose a reason for hiding this comment

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

One nit, otherwise this looks great. Please also add a changelog entry for this

Comment on lines 118 to 123
if aam.ToAttribute == DefaultEmailAttribute {
emailAttr = aam.FromAttribute
}
if aam.ToAttribute == DefaultFullNameAttribute {
fullNameAttr = aam.FromAttribute
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: have a switch here, possibly even include a default that returns an error

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 don't think we should error if we get an unexpected attribute from the LDAP server - We should just ignore it, otherwise we could get into a situation where, for example, an LDAP setup for multiple downstream services could be incompatible with Boundary.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I believe convertAccountAttributeMaps calls ConvertToAccountToAttribute
which will validate the attribs and error if there's an unexpected one.

There's also a column constraint to_attribute_valid_values that validates the
valid values in the db.

Given these two constraints, it seems reasonable for us to have a switch here that
explicity returns an error before sending an invalid transaction to the db.

Comment on lines 118 to 123
if aam.ToAttribute == DefaultEmailAttribute {
emailAttr = aam.FromAttribute
}
if aam.ToAttribute == DefaultFullNameAttribute {
fullNameAttr = aam.FromAttribute
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

I believe convertAccountAttributeMaps calls ConvertToAccountToAttribute
which will validate the attribs and error if there's an unexpected one.

There's also a column constraint to_attribute_valid_values that validates the
valid values in the db.

Given these two constraints, it seems reasonable for us to have a switch here that
explicity returns an error before sending an invalid transaction to the db.

@hugoghx
Copy link
Collaborator Author

hugoghx commented May 15, 2024

@jimlambrt Wouldn't that default case essentially be dead code? The pre-requisite for this new code to run is that err == nil from convertAccountAttributeMaps (https://github.com/hashicorp/boundary/pull/4788/files#diff-bcf83b5283886c98fc45b6435fdc94d87d545b2768c6beac8acd14eb9d6b13f1R115). If we error in convertAccountAttributeMaps, this code will never run - Maybe we could surface the error instead of ignoring it here?

@hugoghx hugoghx requested a review from jimlambrt May 15, 2024 15:24
@jimlambrt
Copy link
Collaborator

A few things come to mind. First, you have no tests which ensure that Authenticate returns an error before sending an invalid transaction to the db. Next, the current implementation of Authenticate is ambiguous in how it handles the invariant which is easily demonstrable given the discourse between you and Louis. Additionally, depth and defense is a well known and accepted practice when it comes to enforcing domain invariants. Finally, I'm not sure I totally agree with your use of dead code in this situation since it relies on data-flow analysis which can easily change unexpectedly in the future (see the previously referenced depth and defense pattern).

@hugoghx
Copy link
Collaborator Author

hugoghx commented May 15, 2024

@jimlambrt

First, you have no tests which ensure that Authenticate returns an error before sending an invalid transaction to the db.

I wasn't able to write a test to this unfortunately. The account map test state required to produce an error is invalid at multiple levels (TestAuthMethod errors when you pass in invalid account attributes, and even if we bypassed that, we'd get a DB error as you mentioned the to_attribute_valid_values constraint in the DB which enforces that any to_attribute be either email or fullname), so I'm unsure how to produce a test with the required state for an error. Do you have any ideas on how we could produce the invalid state for the test?

Next, the current implementation of Authenticate is ambiguous in how it handles the invariant which is easily demonstrable given the discourse between you and Louis. Additionally, depth and defense is a well known and accepted practice when it comes to enforcing domain invariants. Finally, I'm not sure I totally agree with your use of dead code in this situation since it relies on data-flow analysis which can easily change unexpectedly in the future (see the previously referenced depth and defense pattern).

This is very fair - With depth and defense patterns in mind, should we handle and surface the error from convertAccountAttributeMaps and, in addition, ensure a switch default case that throws an error exists?

ie:

attrMaps, err := am.convertAccountAttributeMaps(ctx)
		if err != nil {
			return nil, errors.Wrap(ctx, err, op, errors.WithMsg("failed to convert account attribute maps"))
		}

		for _, attrMap := range attrMaps {
			aam := attrMap.(*AccountAttributeMap)
			switch aam.ToAttribute {
			case DefaultEmailAttribute:
				emailAttr = aam.FromAttribute
			case DefaultFullNameAttribute:
				fullNameAttr = aam.FromAttribute
			default:
				return nil, errors.New(ctx, errors.InvalidParameter, op, fmt.Sprintf("invalid to attribute %q", aam.ToAttribute))
			}
		}

@hugoghx
Copy link
Collaborator Author

hugoghx commented May 15, 2024

@jimlambrt See changes with 6d8dd73

@jimlambrt
Copy link
Collaborator

@jimlambrt See changes with 6d8dd73

Let me know when you're ready for re-review.

@hugoghx
Copy link
Collaborator Author

hugoghx commented May 17, 2024

@jimlambrt Ready to re-review - I was able to write that test we talked about using sqlmock

Copy link
Collaborator

@jimlambrt jimlambrt left a comment

Choose a reason for hiding this comment

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

ty!

@hugoghx hugoghx merged commit 9b44974 into main May 20, 2024
15 of 16 checks passed
@hugoghx hugoghx deleted the hugo-ldap-attrs branch May 20, 2024 15:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants