Skip to content
This repository was archived by the owner on Jul 22, 2021. It is now read-only.

NIFIREG-9: Initial Auth Implementation - #14

Closed
kevdoran wants to merge 3 commits into
apache:masterfrom
kevdoran:NIFIREG-9
Closed

NIFIREG-9: Initial Auth Implementation#14
kevdoran wants to merge 3 commits into
apache:masterfrom
kevdoran:NIFIREG-9

Conversation

@kevdoran

@kevdoran kevdoran commented Oct 3, 2017

Copy link
Copy Markdown
Contributor

This is a rather large PR, including:

  • Authentication and authorization enforcement for web API, largely based on NiFi.
  • This adds interfaces, framework, and file-based authorizer providers (file access policy provider, file user group provider).
  • Authentication of identities is currently based on certificates in two-way SSL (HTTPS). Alternative identity strategies (user&pass, JWT) will be added later building upon the foundation in this commit.

For reviewers, a good place to start is AuthorizationService.java. That is called by Resources (web api endpoints) for authorizing requests. It makes use of authorizer providers (access policy provider and user group provider), which are interfaces and implementations heavily based in NiFi.

To run this, see the instructions in included authorizers.xml file. Configure that with your initial admin identity (must be certificate based) and configure your properties file to use your configured authorizers.

This functionality has been verified through manual testing. Documentation on proper configuration (aside what is in the provided in comment ins the included authorizers.xml example file) is in progress. Automated tests cases (unit, integration, etc.) are in progress and will likely be added to the PR during the time it is reviewed, but opening it now to get initial feedback, especially where it defines/modifies key interfaces.

As part of this feature, some changes were made to the RegistryService interface and the providers it utilizes. @bbende please review these changes when you get a change to make sure they are consistent with your design and intentions for the service and provider layers. Thanks!

Authentication and authorization enforcement for web API, largely based on NiFi.
This commit adds interfaces, framework, and file-based authorizer providers (file access policy provider, file user group provider).
Authentication of identities is currently based on certificates in two-way SSL (HTTPS). Alternative identity strategies (user&pass, JWT) will
be added later building upon the foundation in this commit.

As part of this feature, some changes were made to the RegistryService interface and the providers it utilizes.
@bbende

bbende commented Oct 3, 2017

Copy link
Copy Markdown
Contributor

Reviewing...

@bbende bbende left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Overall looks great! Was able to secure the app and verify the REST endpoints blocked access when my user wasn't added to a policy. Just a few minor comments/suggestions.

// call post construction lifecycle event
instance.initialize(new StandardAuthorizerInitializationContext(identifier, this, this, this));

// if (StringUtils.isNotEmpty(classpathResources)) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Should be fine to leave this out for now, but we may need to revisit this if/when we add support for Ranger... this was done so someone can configure additional libraries to be on the classpath of the authorizer, specifically for Ranger to know where the Hadoop client JARs were if wanting to send audit logs to HDFS.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yeah hadn't gotten that far :)

Its a good point. I'll capture the outstanding work in a JIRA ticket and some in-line TODOs.

verifyAccessPolicyProviderIsConfigurable();

// Don't allow changing action or resource of existing policy (should only be adding/removing users/groups)
org.apache.nifi.registry.authorization.AccessPolicy currentAccessPolicy =

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Should this be within the write lock?

I'm thinking if two people tried to update at the same time, they could both retrieve the initial policy, then assuming user1 obtains the write lock and makes changes, now user2 gets the write lock but is making changes to the initial version and doesn't have user1's changes.

@kevdoran kevdoran Oct 3, 2017

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The idea here is that no user can change the accessPolicy identifier, resource, or action fields on update. They can only change groups or users that have an access policy. To change resource or action, they would have to delete and create a new access policy.

So in your example, user1 and user2 both get the initial version, but those should be guaranteed to match for the fields we want to read. Unless I'm making a mistake in my logic...

That said, I think I'll move it to inside the write lock anyway, as it won't hurt and would protect this code block from future changes that break the expectation I had.


readLock.lock();
try {
final Set<BucketEntity> filterBuckets = bucketIdentifiers.stream()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Should we create a method in metadataService to retrieve all the buckets for the set of ids in one call?

I'm just slightly concerned making an individual DB retrieval for each id if there are a lot of ids passed in.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yeah I agree that would be a better approach. Will make that change, thanks.

Comment thread nifi-registry-provider-api/pom.xml Outdated
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think we can get rid of this, doing a quick test the build still passed without it

</goals>
<configuration>
<packageName>org.apache.nifi.registry.user.generated</packageName>
<sources>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I noticed this file showed errors in my IDE, even though technically it built fine... seems like bumping the jaxb2-maven-plugin to 2.3.1 in the root pom pluginManagement cleared this up

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Good find, will update that plugin version.

/**
* Defines a policy for a set of userIdentifiers to perform a set of actions on a given resource.
*/
public class AccessPolicy {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I know this would be a tedious change, but what do you think about splitting out all of the interfaces/domain objects from nifi-registry-security into nifi-registry-security-api?

My thinking is that nifi-registry-security-api would live in the lib directory and be something that other people would implement against, where as nifi-registry-security would be bundled under the WAR for nifi-registry-web-api.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

It's a good suggestion. I wasn't thrilled with the current organization. Your approach both distinguishes interfaces from implementation and adds extensibility. Will make that change, thanks!

Comment thread nifi-registry-web-api/pom.xml Outdated
<artifactId>spring-boot-starter-web</artifactId>
<version>${spring.boot.version}</version>
</dependency>
<dependency>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

If we make the change in one of the previous comments where we use spring-boot-starter-security in the nifi-registry-security pom, then we probably don't need to directly reference it here because it will be brought in transitively

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yep.

Comment thread nifi-registry.properties Outdated
@@ -0,0 +1,47 @@
# Licensed to the Apache Software Foundation (ASF) under one or more

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think this was maybe left-over from testing and not meant to be checked in?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

yeah this was a test file. will remove

Comment thread nifi-registry-assembly/pom.xml Outdated
<nifi.registry.security.truststorePasswd />
<nifi.registry.security.needClientAuth />
<nifi.registry.security.authorized.users>./conf/authorized-users.xml</nifi.registry.security.authorized.users>
<nifi.security.user.authorizer>managed-authorizer</nifi.security.user.authorizer>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Is the nifi.registry.security.authorized.users still needed?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

nope. neither is login.identity.provider. will remove unused properties and fix the prefixes to be consistent. good catch!

nifi.registry.security.truststorePasswd=${nifi.registry.security.truststorePasswd}
nifi.registry.security.needClientAuth=${nifi.registry.security.needClientAuth}
nifi.registry.security.authorized.users=${nifi.registry.security.authorized.users}
nifi.security.user.authorizer=${nifi.security.user.authorizer}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Is nifi.registry.security.authorized.users still needed?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

same as above. removed in the next update

@kevdoran

kevdoran commented Oct 3, 2017

Copy link
Copy Markdown
Contributor Author

Thanks a lot for the review @bbende! Great suggestions. Will make those changes and update.

@scottyaslan

Copy link
Copy Markdown
Contributor

@kevdoran With this PR when I try to GET http://localhost:8080/nifi-registry-api/items I am getting a "400 Bad Request: Bucket Identifiers cannot be null or empty"...

@kevdoran

kevdoran commented Oct 5, 2017

Copy link
Copy Markdown
Contributor Author

Good catch @scottyaslan - will update with a fix.

@kevdoran

kevdoran commented Oct 5, 2017

Copy link
Copy Markdown
Contributor Author

@bbende I restructured the modules based on your suggestion. I now have the following modules:

nifi-registry-security                 // just a container module, packaged as pom
  +--nifi-registry-security-api        // gets placed in lib dir for others to implement against
  +--nifi-registry-security-api-impl   // NiFi Registry's implementation of security-api
  +--nifi-registry-security-framework  // extends registry-framework to add security

Let me know if you agree with this or if it is overkill for what we need. Technically nifi-registry-security-api-impl and nifi-registry-security-framework can be combined (technically, they could even be part of nifi-registry-framework). I can consolidate some of these if you'd rather keep a flatter, more condensed module structure. Let me know.

@bbende

bbende commented Oct 5, 2017

Copy link
Copy Markdown
Contributor

Thanks for the update! Everything is looking good.

I'm thinking maybe we can fold nifi-registry-security-framework into nifi-registry-framework, and then move nifi-registry-security-api-impl and nifi-registry-security-api to top-level modules, just to keep it a little flatter.

@bbende

bbende commented Oct 5, 2017

Copy link
Copy Markdown
Contributor

+1 Latest update looks good, going to merge shortly, thanks!

@asfgit asfgit closed this in 785cb81 Oct 5, 2017
@kevdoran
kevdoran deleted the NIFIREG-9 branch October 25, 2017 14:38
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants