NIFI-4382: Adding support for Apache Knox SSO#2177
NIFI-4382: Adding support for Apache Knox SSO#2177mcgilman wants to merge 4 commits intoapache:masterfrom
Conversation
- Adding support for KnoxSSO.
|
I just ran a test with audiences set in Knox, and if there's a space after one of the commas in the KnoxSSO config, it will end up sending that space as part of the audience value. For example, <param>
<name>knoxsso.token.audiences</name>
<value>foo,bar, baz</value>
</param>With that config, NiFi will see three audiences, "foo", "bar", and " baz". Notice the space in front of baz. I filed an Apache Knox JIRA for this issue: KNOX-1069 |
|
Add "/access/knox/**" to webSecurity.ignoring().antMatchers in NiFiWebApiSecurityConfiguration.java |
| */ | ||
| public Set<String> getKnoxAudiences() { | ||
| final String rawAudiences = getProperty(SECURITY_USER_KNOX_AUDIENCES); | ||
| if (StringUtils.isBlank(rawAudiences)) { |
There was a problem hiding this comment.
Does this need to be null or could it be an empty Set to allow for simpler iteration on the consuming end?
There was a problem hiding this comment.
While it's not possible to realize the distinction when configuring the properties file and using isBlank, I typically use null for unset while an empty Set would indicate the value is configured with no values. I'm happy to make this change if you want me to.
There was a problem hiding this comment.
When I made the comment, I didn't realize that intentionally setting this value to empty was valid. We can leave this as is.
| * Returns the path to the Knox public key. | ||
| * | ||
| * @return path to the Knox public key | ||
| */ |
There was a problem hiding this comment.
Could this property name include the word Path so it's clear that the return value is not the key content (if the consumer doesn't read the API docs)?
| During Apache Knox authentication, NiFi will redirect users to login with Apache Knox before returning to NiFi. NiFi will verify the Apache Knox | ||
| token during authentication. | ||
|
|
||
| NOTE: NiFi can only be configured for username/password, OpenId Connect, or Apache Knox at a given time. It does not support running each of |
There was a problem hiding this comment.
Maybe explicitly note that "username/password" includes both LDAP and Kerberos.
There was a problem hiding this comment.
I've updated the part in the guide where username/password is associated with the pluggable Login Identity Provider (a couple paragraphs above this NOTE) to include the supported options. Thereafter, its referred to as username/password.
| } | ||
| } | ||
|
|
||
| public String getJwtFromCookie(final HttpServletRequest request) { |
There was a problem hiding this comment.
Not a big deal, but I could see this method being reused in the future, so accepting the cookieName as a parameter and providing it from the Knox method might be useful. Not a blocker for this PR though.
| } | ||
|
|
||
| @Override | ||
| public String toString() { |
There was a problem hiding this comment.
The toString() doesn't contain any unique identifying information, so overriding this removes the hashcode that is usually present. Is this a security concern, or does it simply make debugging more difficult?
There was a problem hiding this comment.
This toString() implementation was motivated by a recent change to the logging of the NiFi native JWT tokens here [1].
[1]
| } | ||
|
|
||
| /** | ||
| * Returns whether OpenId Connect is enabled. |
There was a problem hiding this comment.
Think this might be a copy/paste error.
- Addressing PR review comments.
|
I did not see the |
|
A new commit has been pushed that addresses the comments received thus far. Thanks for reviewing @jtstorck and @alopresto! |
- Updating the docs for nifi.security.user.knox.audiences.
|
@alopresto I just rebuilt and the properties in |
|
@mcgilman the I am encountering these checkstyle warnings though (they cause a build failure): |
|
Is there a way to sign out of NiFi once the Knox SSO cookie is present in the browser? |
|
Ok, here are my thoughts on this PR:
To me, neither issue is a blocker for this PR but I do think they should be resolved in a future release. +1, LGTM (with the checkstyle violation resolutions pending). |
|
Do you think that we should support logout in this case? If yes, I’ll need to figure out the best way to handle this as currently logging out is entirely client side and I believe this would require some server side action. |
|
Yeah, I don't have deep enough Knox familiarity to judge the best use case for communicating back that the logout command has occurred. If we treated receiving the |
|
Thanks again @alopresto for the review. I had observed the same behavior where the user is redirected back to the login page when the token could not be validated. I think a good path forward here may be to support multiple login mechanisms concurrently (ldap, oidc, and knox for instance). When this is the case, the NiFi login page would likely offer buttons for the user to initiate the desired SSO login sequence. The reason this is awkward currently is because the redirection happens automatically. This could also give us an opportunity to provide some sort of error message to the end user. Let's consider this option and the logout concern is separate follow on JIRAs. |
|
Thanks Matt. I agree that a "multiple login option splash page" would be a good feature when necessary -- old Stack Overflow comes to mind for me. Looking forward to this code getting in and the follow-on enhancements. |
|
JIRAs for logout [1] and login splash screen [2]. [1] https://issues.apache.org/jira/browse/NIFI-4430 |
- Addressing checkstyle issues. - Ensuring the cookie is removed prior to request replication.
|
@mcgilman Merged your PR to master. Thanks for the contribution! Also, thanks to @alopresto for reviewing! |
NIFI-4382:
High Level Description
This PR facilitates Apache Knox SSO. It can support both cases where the users directly access NiFi and simply use Knox SSO for authentication and where Knox is proxying access to NiFi.
In the direct access case when an unauthenticated user attempts to go to NiFi, NiFi will redirect the user to Knox log in. After successfully logging in, Knox will generate a JWT and put it in an HTTP Cookie and redirect back to NiFi. NiFi will consider the JWT and verify it by validating the signature, audience, and expiration. The signature is validated using a configured public key from Knox. Acceptable audiences can also be configured but are not required. If the JWT is validated, the user identity is extracted from the token.
In the proxying case when an unauthenticated user attempts to go to NiFi through Knox, Knox will redirect the user to Knox log in. After successfully logging in, Knox will generate a JWT and put it in an HTTP Cookie and redirect back to NiFi through Knox. If the requests from Knox to NiFi are made over two-way SSL the JWT in the HTTP Cookie is validated at Knox and the user identity will be placed in the proxied entities chain. When the requests from Knox to NiFi are made over one-way SSL, the Knox Cookie is relayed to the request to NiFi allowing NiFi to validate it with the same logic described above in the direct access case.
For the proxying case, the only new capabilities introduced here are also part of the direct access case (JWT token validation). Because of this, all of the capabilities should be able to be tested using direct NiFi access with Knox SSO.
Testing
To test Knox SSO when directly accessing NiFi, install both Knox and NiFi. Knox SSO configuration is described here [1]. In NiFi four new properties have been introduced:
These properties assume that Knox is running locally on 8443 and NiFi is secured and running on another port. The publicKey can be exported from Knox using the following command:
<knox-install-dir>/bin/knoxcli.sh export-certThe cookieName property would need to align with what is configured in Knox. The audience property is used to only accept tokens from a particular audience. The audience value is configured as part of Knox SSO [1].
[1] http://knox.apache.org/books/knox-0-13-0/user-guide.html#KnoxSSO+Configuration+Parameters