NIFI-1551:

- Removing the AuthorityProvider.
- Refactoring REST API in preparation for introduction of the Authorizer.
- Updating UI accordingly.
- Removing unneeded properties from nifi.properties.
- Addressing comments from PR.
- This closes #359.
This commit is contained in:
Matt Gilman 2016-04-15 15:53:47 -04:00 committed by Mark Payne
parent 7db78e87a5
commit 153f63ef43
284 changed files with 4804 additions and 20562 deletions

View File

@ -18,8 +18,8 @@ package org.apache.nifi.authentication;
import org.apache.nifi.authentication.exception.IdentityAccessException; import org.apache.nifi.authentication.exception.IdentityAccessException;
import org.apache.nifi.authentication.exception.InvalidLoginCredentialsException; import org.apache.nifi.authentication.exception.InvalidLoginCredentialsException;
import org.apache.nifi.authorization.exception.ProviderCreationException; import org.apache.nifi.authentication.exception.ProviderCreationException;
import org.apache.nifi.authorization.exception.ProviderDestructionException; import org.apache.nifi.authentication.exception.ProviderDestructionException;
/** /**
* Identity provider that is able to authentication a user with username/password credentials. * Identity provider that is able to authentication a user with username/password credentials.

View File

@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.apache.nifi.authorization.exception; package org.apache.nifi.authentication.exception;
/** /**
* Represents the exceptional case when an AuthorityProvider fails instantiated. * Represents the exceptional case when an AuthorityProvider fails instantiated.

View File

@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.apache.nifi.authorization.exception; package org.apache.nifi.authentication.exception;
/** /**
* Represents the exceptional case when an AuthorityProvider fails destruction. * Represents the exceptional case when an AuthorityProvider fails destruction.

View File

@ -1,93 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.authorization;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;
/**
* Authorities that can be assigned to NiFi users.
*/
public enum Authority {
ROLE_MONITOR,
ROLE_DFM,
ROLE_ADMIN,
ROLE_PROVENANCE,
ROLE_PROXY,
ROLE_NIFI;
/**
* @param rawAuthority string form of authority
* @return the matching role or null if the specified role does not match
* any roles
*/
public static Authority valueOfAuthority(String rawAuthority) {
Authority desiredAuthority = null;
for (Authority authority : values()) {
if (authority.toString().equals(rawAuthority)) {
desiredAuthority = authority;
break;
}
}
return desiredAuthority;
}
/**
* @return the string value of each authority
*/
public static Set<String> getRawAuthorities() {
Set<String> authorities = new LinkedHashSet<>();
for (Authority authority : values()) {
authorities.add(authority.toString());
}
return authorities;
}
public static Set<String> convertAuthorities(Set<Authority> authorities) {
if (authorities == null) {
throw new IllegalArgumentException("No authorities have been specified.");
}
// convert the set
Set<String> rawAuthorities = new HashSet<>(authorities.size());
for (Authority authority : authorities) {
rawAuthorities.add(authority.toString());
}
return rawAuthorities;
}
public static EnumSet<Authority> convertRawAuthorities(Set<String> rawAuthorities) {
if (rawAuthorities == null) {
throw new IllegalArgumentException("No authorities have been specified.");
}
// convert the set
EnumSet<Authority> authorities = EnumSet.noneOf(Authority.class);
for (String rawAuthority : rawAuthorities) {
Authority authority = Authority.valueOfAuthority(rawAuthority);
if (authority != null) {
authorities.add(authority);
}
}
return authorities;
}
}

View File

@ -1,182 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.authorization;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.nifi.authorization.exception.AuthorityAccessException;
import org.apache.nifi.authorization.exception.IdentityAlreadyExistsException;
import org.apache.nifi.authorization.exception.ProviderCreationException;
import org.apache.nifi.authorization.exception.ProviderDestructionException;
import org.apache.nifi.authorization.exception.UnknownIdentityException;
/**
* This class allows clients to retrieve the authorities for a given DN.
*/
public interface AuthorityProvider {
/**
* @param identity of the user. The identity may be a dn, an email, a username, or any string that identities the user.
* @return whether the user with the specified identity is known to this authority
* provider. It is not necessary for the user to have any authorities
*/
boolean doesDnExist(String identity) throws AuthorityAccessException;
/**
* Get the authorities for the specified user. If the specified user exists
* but does not have any authorities, an empty set should be returned.
*
* @param identity of the user. The identity may be a dn, an email, a username, or any string that identities the user.
* @return the authorities for the specified user. If the specified user
* exists but does not have any authorities, an empty set should be returned
* @throws UnknownIdentityException if identity is not known
* @throws AuthorityAccessException if unable to access authorities
*/
Set<Authority> getAuthorities(String identity) throws UnknownIdentityException, AuthorityAccessException;
/**
* Sets the specified authorities for the specified user.
*
* @param identity of the user. The identity may be a dn, an email, a username, or any string that identities the user.
* @param authorities the new authorities for the user
* @throws UnknownIdentityException if identity is not known
* @throws AuthorityAccessException if unable to access authorities
*/
void setAuthorities(String identity, Set<Authority> authorities) throws UnknownIdentityException, AuthorityAccessException;
/**
* Gets the users for the specified authority.
*
* @param authority for which to determine membership of
* @return all users with the specified authority
* @throws AuthorityAccessException if unable to access authorities
*/
Set<String> getUsers(Authority authority) throws AuthorityAccessException;
/**
* Revokes the specified user. Its up to the implementor to determine the
* semantics of revocation.
*
* @param identity of the user. The identity may be a dn, an email, a username, or any string that identities the user.
* @throws UnknownIdentityException if the user is not known
* @throws AuthorityAccessException if unable to access the authorities
*/
void revokeUser(String identity) throws UnknownIdentityException, AuthorityAccessException;
/**
* Add the specified user.
*
* @param identity of the user. The identity may be a dn, an email, a username, or any string that identities the user.
* @param group Optional
* @throws UnknownIdentityException if the user is not known
* @throws AuthorityAccessException if unable to access the authorities
*/
void addUser(String identity, String group) throws IdentityAlreadyExistsException, AuthorityAccessException;
/**
* Gets the group for the specified user. Return null if the user does not
* belong to a group.
*
* @param identity of the user. The identity may be a dn, an email, a username, or any string that identities the user.
* @return the group of the given user
* @throws UnknownIdentityException if the user is not known
* @throws AuthorityAccessException if unable to access the authorities
*/
String getGroupForUser(String identity) throws UnknownIdentityException, AuthorityAccessException;
/**
* Revokes all users for a specified group. Its up to the implementor to
* determine the semantics of revocation.
*
* @param group to revoke the users of
* @throws UnknownIdentityException if the user is not known
* @throws AuthorityAccessException if unable to access the authorities
*/
void revokeGroup(String group) throws UnknownIdentityException, AuthorityAccessException;
/**
* Adds the specified users to the specified group.
*
* @param identity of the user. The identity may be a dn, an email, a username, or any string that identities the user.
* @param group to add users to
* @throws UnknownIdentityException if the user is not known
* @throws AuthorityAccessException if unable to access the authorities
*/
void setUsersGroup(Set<String> identity, String group) throws UnknownIdentityException, AuthorityAccessException;
/**
* Ungroups the specified user.
*
* @param identity of the user. The identity may be a dn, an email, a username, or any string that identities the user.
* @throws UnknownIdentityException if the user is not known
* @throws AuthorityAccessException if unable to access the authorities
*/
void ungroupUser(String identity) throws UnknownIdentityException, AuthorityAccessException;
/**
* Ungroups the specified group. Since the semantics of revocation is up to
* the implementor, this method should do nothing if the specified group
* does not exist. If an admin revoked this group before calling ungroup, it
* may or may not exist.
*
* @param group to ungroup
* @throws AuthorityAccessException if unable to access the authorities
*/
void ungroup(String group) throws AuthorityAccessException;
/**
* Determines whether the user in the specified dnChain should be able to
* download the content for the flowfile with the specified attributes.
*
* The first identity in the chain is the end user that the request was issued on
* behalf of. The subsequent identities in the chain represent entities proxying
* the user's request with the last being the proxy that sent the current
* request.
*
* @param proxyChain proxy chain of user identities that for the download request
* @param attributes of the flowfile being requested
* @return the authorization result
* @throws UnknownIdentityException if the user is not known
* @throws AuthorityAccessException if unable to access the authorities
*/
DownloadAuthorization authorizeDownload(List<String> proxyChain, Map<String, String> attributes) throws UnknownIdentityException, AuthorityAccessException;
/**
* Called immediately after instance creation for implementers to perform
* additional setup
*
* @param initializationContext in which to initialize
*/
void initialize(AuthorityProviderInitializationContext initializationContext) throws ProviderCreationException;
/**
* Called to configure the AuthorityProvider.
*
* @param configurationContext at the time of configuration
* @throws ProviderCreationException for any issues configuring the provider
*/
void onConfigured(AuthorityProviderConfigurationContext configurationContext) throws ProviderCreationException;
/**
* Called immediately before instance destruction for implementers to
* release resources.
*
* @throws ProviderDestructionException If pre-destruction fails.
*/
void preDestruction() throws ProviderDestructionException;
}

View File

@ -1,48 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.authorization;
import java.util.Map;
/**
*
*/
public interface AuthorityProviderConfigurationContext {
/**
* @return identifier for the authority provider
*/
String getIdentifier();
/**
* Retrieves all properties the component currently understands regardless
* of whether a value has been set for them or not. If no value is present
* then its value is null and thus any registered default for the property
* descriptor applies.
*
* @return Map of all properties
*/
Map<String, String> getProperties();
/**
* @param property to lookup the descriptor and value of
* @return the value the component currently understands for the given
* PropertyDescriptor. This method does not substitute default
* PropertyDescriptor values, so the value returned will be null if not set
*/
String getProperty(String property);
}

View File

@ -1,27 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.authorization;
/**
*
*/
public interface AuthorityProviderInitializationContext {
public String getIdentifier();
public AuthorityProviderLookup getAuthorityProviderLookup();
}

View File

@ -1,25 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.authorization;
/**
*
*/
public interface AuthorityProviderLookup {
AuthorityProvider getAuthorityProvider(String identifier);
}

View File

@ -29,17 +29,22 @@ public class AuthorizationRequest {
private final Resource resource; private final Resource resource;
private final String identity; private final String identity;
private final RequestAction action; private final RequestAction action;
private final boolean isAccessAttempt;
private final boolean isAnonymous;
private final Map<String, String> context; private final Map<String, String> context;
private final Map<String, String> eventAttributes; private final Map<String, String> eventAttributes;
private AuthorizationRequest(final Builder builder) { private AuthorizationRequest(final Builder builder) {
Objects.requireNonNull(builder.resource, "The resource is required when creating an authorization request"); Objects.requireNonNull(builder.resource, "The resource is required when creating an authorization request");
Objects.requireNonNull(builder.identity, "The identity of the user is required when creating an authorization request");
Objects.requireNonNull(builder.action, "The action is required when creating an authorization request"); Objects.requireNonNull(builder.action, "The action is required when creating an authorization request");
Objects.requireNonNull(builder.isAccessAttempt, "Whether this request is an access attempt is request");
Objects.requireNonNull(builder.isAnonymous, "Whether this request is being performed by an anonymous user is required");
this.resource = builder.resource; this.resource = builder.resource;
this.identity = builder.identity; this.identity = builder.identity;
this.action = builder.action; this.action = builder.action;
this.isAccessAttempt = builder.isAccessAttempt;
this.isAnonymous = builder.isAnonymous;
this.context = builder.context == null ? null : Collections.unmodifiableMap(builder.context); this.context = builder.context == null ? null : Collections.unmodifiableMap(builder.context);
this.eventAttributes = builder.context == null ? null : Collections.unmodifiableMap(builder.eventAttributes); this.eventAttributes = builder.context == null ? null : Collections.unmodifiableMap(builder.eventAttributes);
} }
@ -54,7 +59,7 @@ public class AuthorizationRequest {
} }
/** /**
* The identity accessing the Resource. Not null. * The identity accessing the Resource. May be null if the user could not authenticate.
* *
* @return The identity * @return The identity
*/ */
@ -62,6 +67,24 @@ public class AuthorizationRequest {
return identity; return identity;
} }
/**
* Whether this is a direct access attempt of the Resource if if it's being checked as part of another response.
*
* @return if this is a direct access attempt
*/
public boolean isAccessAttempt() {
return isAccessAttempt;
}
/**
* Whether the entity accessing is anonymous.
*
* @return whether the entity is anonymous
*/
public boolean isAnonymous() {
return isAnonymous;
}
/** /**
* The action being taken against the Resource. Not null. * The action being taken against the Resource. Not null.
* *
@ -96,6 +119,8 @@ public class AuthorizationRequest {
private Resource resource; private Resource resource;
private String identity; private String identity;
private Boolean isAnonymous;
private Boolean isAccessAttempt;
private RequestAction action; private RequestAction action;
private Map<String, String> context; private Map<String, String> context;
private Map<String, String> eventAttributes; private Map<String, String> eventAttributes;
@ -110,6 +135,16 @@ public class AuthorizationRequest {
return this; return this;
} }
public Builder anonymous(final Boolean isAnonymous) {
this.isAnonymous = isAnonymous;
return this;
}
public Builder accessAttempt(final Boolean isAccessAttempt) {
this.isAccessAttempt = isAccessAttempt;
return this;
}
public Builder action(final RequestAction action) { public Builder action(final RequestAction action) {
this.action = action; this.action = action;
return this; return this;

View File

@ -16,7 +16,6 @@
*/ */
package org.apache.nifi.authorization; package org.apache.nifi.authorization;
import org.apache.nifi.authorization.exception.AuthorityAccessException;
import org.apache.nifi.authorization.exception.AuthorizationAccessException; import org.apache.nifi.authorization.exception.AuthorizationAccessException;
import org.apache.nifi.authorization.exception.AuthorizerCreationException; import org.apache.nifi.authorization.exception.AuthorizerCreationException;
import org.apache.nifi.authorization.exception.AuthorizerDestructionException; import org.apache.nifi.authorization.exception.AuthorizerDestructionException;
@ -31,7 +30,7 @@ public interface Authorizer {
* *
* @param request The authorization request * @param request The authorization request
* @return the authorization result * @return the authorization result
* @throws AuthorityAccessException if unable to access the authorities * @throws AuthorizationAccessException if unable to access the authorities
*/ */
AuthorizationResult authorize(AuthorizationRequest request) throws AuthorizationAccessException; AuthorizationResult authorize(AuthorizationRequest request) throws AuthorizationAccessException;

View File

@ -1,83 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.authorization;
/**
* Represents a decision whether authorization is granted to download content.
*/
public class DownloadAuthorization {
private static enum Result {
Approved,
Denied;
}
private static final DownloadAuthorization APPROVED = new DownloadAuthorization(Result.Approved, null);
private final Result result;
private final String explanation;
/**
* Creates a new DownloadAuthorization with the specified result and
* explanation.
*
* @param result of the authorization
* @param explanation for the authorization attempt
*/
private DownloadAuthorization(Result result, String explanation) {
if (Result.Denied.equals(result) && explanation == null) {
throw new IllegalArgumentException("An explanation is required when the download request is denied.");
}
this.result = result;
this.explanation = explanation;
}
/**
* @return Whether or not the download request is approved
*/
public boolean isApproved() {
return Result.Approved.equals(result);
}
/**
* @return If the download request is denied, the reason why. Null otherwise
*/
public String getExplanation() {
return explanation;
}
/**
* @return a new approved DownloadAuthorization
*/
public static DownloadAuthorization approved() {
return APPROVED;
}
/**
* Creates a new denied DownloadAuthorization with the specified
* explanation.
*
* @param explanation for why it was denied
* @return a new denied DownloadAuthorization with the specified explanation
* @throws IllegalArgumentException if explanation is null
*/
public static DownloadAuthorization denied(String explanation) {
return new DownloadAuthorization(Result.Denied, explanation);
}
}

View File

@ -1,35 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.authorization.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
*
*
*/
@Documented
@Target({ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface AuthorityProviderContext {
}

View File

@ -1,33 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.authorization.exception;
/**
* Represents the case when the DN could not be confirmed because it was unable
* to access the data store.
*/
public class AuthorityAccessException extends RuntimeException {
public AuthorityAccessException(String message, Throwable cause) {
super(message, cause);
}
public AuthorityAccessException(String message) {
super(message);
}
}

View File

@ -1,32 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.authorization.exception;
/**
* Represents the case when the user identity already exists.
*/
public class IdentityAlreadyExistsException extends RuntimeException {
public IdentityAlreadyExistsException(String message, Throwable cause) {
super(message, cause);
}
public IdentityAlreadyExistsException(String message) {
super(message);
}
}

View File

@ -1,32 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.authorization.exception;
/**
* Represents the case when an identity cannot be confirmed.
*/
public class UnknownIdentityException extends RuntimeException {
public UnknownIdentityException(String message, Throwable cause) {
super(message, cause);
}
public UnknownIdentityException(String message) {
super(message);
}
}

View File

@ -325,7 +325,7 @@ language governing permissions and limitations under the License. -->
<nifi.flow.configuration.file>./conf/flow.xml.gz</nifi.flow.configuration.file> <nifi.flow.configuration.file>./conf/flow.xml.gz</nifi.flow.configuration.file>
<nifi.flow.configuration.archive.dir>./conf/archive/</nifi.flow.configuration.archive.dir> <nifi.flow.configuration.archive.dir>./conf/archive/</nifi.flow.configuration.archive.dir>
<nifi.login.identity.provider.configuration.file>./conf/login-identity-providers.xml</nifi.login.identity.provider.configuration.file> <nifi.login.identity.provider.configuration.file>./conf/login-identity-providers.xml</nifi.login.identity.provider.configuration.file>
<nifi.authority.provider.configuration.file>./conf/authority-providers.xml</nifi.authority.provider.configuration.file> <nifi.authorizer.configuration.file>./conf/authorizers.xml</nifi.authorizer.configuration.file>
<nifi.templates.directory>./conf/templates</nifi.templates.directory> <nifi.templates.directory>./conf/templates</nifi.templates.directory>
<nifi.database.directory>./database_repository</nifi.database.directory> <nifi.database.directory>./database_repository</nifi.database.directory>
@ -413,13 +413,9 @@ language governing permissions and limitations under the License. -->
<nifi.security.truststoreType /> <nifi.security.truststoreType />
<nifi.security.truststorePasswd /> <nifi.security.truststorePasswd />
<nifi.security.needClientAuth /> <nifi.security.needClientAuth />
<nifi.security.authorizedUsers.file>./conf/authorized-users.xml</nifi.security.authorizedUsers.file> <nifi.security.user.authorizer>file-provider</nifi.security.user.authorizer>
<nifi.security.user.credential.cache.duration>24 hours</nifi.security.user.credential.cache.duration>
<nifi.security.user.authority.provider>file-provider</nifi.security.user.authority.provider>
<nifi.security.user.login.identity.provider /> <nifi.security.user.login.identity.provider />
<nifi.security.x509.principal.extractor /> <nifi.security.x509.principal.extractor />
<nifi.security.support.new.account.requests />
<nifi.security.anonymous.authorities />
<nifi.security.ocsp.responder.url /> <nifi.security.ocsp.responder.url />
<nifi.security.ocsp.responder.certificate /> <nifi.security.ocsp.responder.certificate />

View File

@ -28,14 +28,10 @@ import java.nio.file.InvalidPathException;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Properties; import java.util.Properties;
import java.util.Set;
public class NiFiProperties extends Properties { public class NiFiProperties extends Properties {
@ -48,7 +44,7 @@ public class NiFiProperties extends Properties {
public static final String PROPERTIES_FILE_PATH = "nifi.properties.file.path"; public static final String PROPERTIES_FILE_PATH = "nifi.properties.file.path";
public static final String FLOW_CONFIGURATION_FILE = "nifi.flow.configuration.file"; public static final String FLOW_CONFIGURATION_FILE = "nifi.flow.configuration.file";
public static final String FLOW_CONFIGURATION_ARCHIVE_FILE = "nifi.flow.configuration.archive.file"; public static final String FLOW_CONFIGURATION_ARCHIVE_FILE = "nifi.flow.configuration.archive.file";
public static final String AUTHORITY_PROVIDER_CONFIGURATION_FILE = "nifi.authority.provider.configuration.file"; public static final String AUTHORIZER_CONFIGURATION_FILE = "nifi.authorizer.configuration.file";
public static final String LOGIN_IDENTITY_PROVIDER_CONFIGURATION_FILE = "nifi.login.identity.provider.configuration.file"; public static final String LOGIN_IDENTITY_PROVIDER_CONFIGURATION_FILE = "nifi.login.identity.provider.configuration.file";
public static final String REPOSITORY_DATABASE_DIRECTORY = "nifi.database.directory"; public static final String REPOSITORY_DATABASE_DIRECTORY = "nifi.database.directory";
public static final String RESTORE_DIRECTORY = "nifi.restore.directory"; public static final String RESTORE_DIRECTORY = "nifi.restore.directory";
@ -131,13 +127,10 @@ public class NiFiProperties extends Properties {
public static final String SECURITY_TRUSTSTORE_TYPE = "nifi.security.truststoreType"; public static final String SECURITY_TRUSTSTORE_TYPE = "nifi.security.truststoreType";
public static final String SECURITY_TRUSTSTORE_PASSWD = "nifi.security.truststorePasswd"; public static final String SECURITY_TRUSTSTORE_PASSWD = "nifi.security.truststorePasswd";
public static final String SECURITY_NEED_CLIENT_AUTH = "nifi.security.needClientAuth"; public static final String SECURITY_NEED_CLIENT_AUTH = "nifi.security.needClientAuth";
public static final String SECURITY_USER_AUTHORITY_PROVIDER = "nifi.security.user.authority.provider"; public static final String SECURITY_USER_AUTHORIZER = "nifi.security.user.authorizer";
public static final String SECURITY_USER_LOGIN_IDENTITY_PROVIDER = "nifi.security.user.login.identity.provider"; public static final String SECURITY_USER_LOGIN_IDENTITY_PROVIDER = "nifi.security.user.login.identity.provider";
public static final String SECURITY_CLUSTER_AUTHORITY_PROVIDER_PORT = "nifi.security.cluster.authority.provider.port"; public static final String SECURITY_CLUSTER_AUTHORITY_PROVIDER_PORT = "nifi.security.cluster.authority.provider.port";
public static final String SECURITY_CLUSTER_AUTHORITY_PROVIDER_THREADS = "nifi.security.cluster.authority.provider.threads"; public static final String SECURITY_CLUSTER_AUTHORITY_PROVIDER_THREADS = "nifi.security.cluster.authority.provider.threads";
public static final String SECURITY_USER_CREDENTIAL_CACHE_DURATION = "nifi.security.user.credential.cache.duration";
public static final String SECURITY_SUPPORT_NEW_ACCOUNT_REQUESTS = "nifi.security.support.new.account.requests";
public static final String SECURITY_ANONYMOUS_AUTHORITIES = "nifi.security.anonymous.authorities";
public static final String SECURITY_OCSP_RESPONDER_URL = "nifi.security.ocsp.responder.url"; public static final String SECURITY_OCSP_RESPONDER_URL = "nifi.security.ocsp.responder.url";
public static final String SECURITY_OCSP_RESPONDER_CERTIFICATE = "nifi.security.ocsp.responder.certificate"; public static final String SECURITY_OCSP_RESPONDER_CERTIFICATE = "nifi.security.ocsp.responder.certificate";
@ -504,10 +497,10 @@ public class NiFiProperties extends Properties {
} }
/** /**
* @return the user authorities file * @return the user authorizers file
*/ */
public File getAuthorityProviderConfiguraitonFile() { public File getAuthorizerConfiguraitonFile() {
final String value = getProperty(AUTHORITY_PROVIDER_CONFIGURATION_FILE); final String value = getProperty(AUTHORIZER_CONFIGURATION_FILE);
if (StringUtils.isBlank(value)) { if (StringUtils.isBlank(value)) {
return new File(DEFAULT_AUTHORITY_PROVIDER_CONFIGURATION_FILE); return new File(DEFAULT_AUTHORITY_PROVIDER_CONFIGURATION_FILE);
} else { } else {
@ -541,40 +534,6 @@ public class NiFiProperties extends Properties {
return needClientAuth; return needClientAuth;
} }
public String getUserCredentialCacheDuration() {
return getProperty(SECURITY_USER_CREDENTIAL_CACHE_DURATION,
DEFAULT_USER_CREDENTIAL_CACHE_DURATION);
}
public boolean getSupportNewAccountRequests() {
boolean shouldSupport = true;
String rawShouldSupport = getProperty(SECURITY_SUPPORT_NEW_ACCOUNT_REQUESTS);
if ("false".equalsIgnoreCase(rawShouldSupport)) {
shouldSupport = false;
}
return shouldSupport;
}
@SuppressWarnings("unchecked")
public Set<String> getAnonymousAuthorities() {
final Set<String> authorities;
final String rawAnonymousAuthorities = getProperty(SECURITY_ANONYMOUS_AUTHORITIES);
if (!StringUtils.isEmpty(rawAnonymousAuthorities)) {
authorities = new HashSet<>();
// parse the raw authorities and trim them
final List<String> authoritiesList = Arrays.asList(rawAnonymousAuthorities.split(","));
for (final String authority : authoritiesList) {
authorities.add(authority.trim());
}
} else {
authorities = Collections.EMPTY_SET;
}
return authorities;
}
// getters for web properties // // getters for web properties //
public Integer getPort() { public Integer getPort() {
Integer port = null; Integer port = null;
@ -922,7 +881,7 @@ public class NiFiProperties extends Properties {
* @return true if client certificates are required for access to the REST API * @return true if client certificates are required for access to the REST API
*/ */
public boolean isClientAuthRequiredForRestApi() { public boolean isClientAuthRequiredForRestApi() {
return StringUtils.isBlank(getProperty(NiFiProperties.SECURITY_USER_LOGIN_IDENTITY_PROVIDER)) && getAnonymousAuthorities().isEmpty() && !isKerberosServiceSupportEnabled(); return StringUtils.isBlank(getProperty(NiFiProperties.SECURITY_USER_LOGIN_IDENTITY_PROVIDER)) && !isKerberosServiceSupportEnabled();
} }
public InetSocketAddress getNodeApiAddress() { public InetSocketAddress getNodeApiAddress() {

View File

@ -83,11 +83,7 @@ nifi.security.truststore=
nifi.security.truststoreType= nifi.security.truststoreType=
nifi.security.truststorePasswd= nifi.security.truststorePasswd=
nifi.security.needClientAuth= nifi.security.needClientAuth=
nifi.security.authorizedUsers.file=./target/conf/authorized-users.xml nifi.security.user.authorizer=
nifi.security.user.credential.cache.duration=24 hours
nifi.security.user.authority.provider=nifi.authorization.FileAuthorizationProvider
nifi.security.support.new.account.requests=
nifi.security.default.user.roles=
# cluster common properties (cluster manager and nodes must have same values) # # cluster common properties (cluster manager and nodes must have same values) #
nifi.cluster.protocol.heartbeat.interval=5 sec nifi.cluster.protocol.heartbeat.interval=5 sec

View File

@ -81,11 +81,7 @@ nifi.security.truststore=
nifi.security.truststoreType= nifi.security.truststoreType=
nifi.security.truststorePasswd= nifi.security.truststorePasswd=
nifi.security.needClientAuth= nifi.security.needClientAuth=
nifi.security.authorizedUsers.file=./target/conf/authorized-users.xml nifi.security.user.authorizer=
nifi.security.user.credential.cache.duration=24 hours
nifi.security.user.authority.provider=nifi.authorization.FileAuthorizationProvider
nifi.security.support.new.account.requests=
nifi.security.default.user.roles=
# cluster common properties (cluster manager and nodes must have same values) # # cluster common properties (cluster manager and nodes must have same values) #
nifi.cluster.protocol.heartbeat.interval=5 sec nifi.cluster.protocol.heartbeat.interval=5 sec

View File

@ -83,11 +83,7 @@ nifi.security.truststore=
nifi.security.truststoreType= nifi.security.truststoreType=
nifi.security.truststorePasswd= nifi.security.truststorePasswd=
nifi.security.needClientAuth= nifi.security.needClientAuth=
nifi.security.authorizedUsers.file=./target/conf/authorized-users.xml nifi.security.user.authorizer=
nifi.security.user.credential.cache.duration=24 hours
nifi.security.user.authority.provider=nifi.authorization.FileAuthorizationProvider
nifi.security.support.new.account.requests=
nifi.security.default.user.roles=
# cluster common properties (cluster manager and nodes must have same values) # # cluster common properties (cluster manager and nodes must have same values) #
nifi.cluster.protocol.heartbeat.interval=5 sec nifi.cluster.protocol.heartbeat.interval=5 sec

View File

@ -154,9 +154,6 @@ NiFi provides several different configuration options for security purposes. The
by the NiFi cluster protocol. If the Truststore properties are not set, this must be `false`. Otherwise, a value by the NiFi cluster protocol. If the Truststore properties are not set, this must be `false`. Otherwise, a value
of `true` indicates that nodes in the cluster will be authenticated and must have certificates that are trusted of `true` indicates that nodes in the cluster will be authenticated and must have certificates that are trusted
by the Truststores. by the Truststores.
|`nifi.security.anonymous.authorities` | Specifies the roles that should be granted to users that connect over HTTPS anonymously. All users can make
use of anonymous access, however if they have been granted a particular level of access by an administrator
it will take precedence if they access NiFi using a client certificate or once they have logged in.
|================================================================================================================================================== |==================================================================================================================================================
Once the above properties have been configured, we can enable the User Interface to be accessed over HTTPS instead of HTTP. This is accomplished Once the above properties have been configured, we can enable the User Interface to be accessed over HTTPS instead of HTTP. This is accomplished
@ -167,10 +164,10 @@ be accessible from all network interfaces, a value of `0.0.0.0` should be used.
NOTE: It is important when enabling HTTPS that the `nifi.web.http.port` property be unset. NOTE: It is important when enabling HTTPS that the `nifi.web.http.port` property be unset.
Similar to `nifi.security.needClientAuth`, the web server can be configured to require certificate based client authentication for users accessing Similar to `nifi.security.needClientAuth`, the web server can be configured to require certificate based client authentication for users accessing
the User Interface. In order to do this it must be configured to not support username/password authentication (see below) and not grant access to the User Interface. In order to do this it must be configured to not support username/password authentication (see below). Either of these options
anonymous users (see `nifi.security.anonymous.authorities` above). Either of these options will configure the web server to WANT certificate based client will configure the web server to WANT certificate based client authentication. This will allow it to support users with certificates and those without
authentication. This will allow it to support users with certificates and those without that may be logging in with their credentials or those accessing that may be logging in with their credentials or those accessing anonymously. If username/password authentication and anonymous access are not configured,
anonymously. If username/password authentication and anonymous access are not configured, the web server will REQUIRE certificate based client authentication. the web server will REQUIRE certificate based client authentication.
Now that the User Interface has been secured, we can easily secure Site-to-Site connections and inner-cluster communications, as well. This is Now that the User Interface has been secured, we can easily secure Site-to-Site connections and inner-cluster communications, as well. This is
accomplished by setting the `nifi.remote.input.secure` and `nifi.cluster.protocol.is.secure` properties, respectively, to `true`. accomplished by setting the `nifi.remote.input.secure` and `nifi.cluster.protocol.is.secure` properties, respectively, to `true`.
@ -289,127 +286,6 @@ nifi.security.user.login.identity.provider=kerberos-provider
See also <<kerberos_service>> to allow single sign-on access via client Kerberos tickets. See also <<kerberos_service>> to allow single sign-on access via client Kerberos tickets.
Controlling Levels of Access
----------------------------
Once NiFi is configured to run securely and an authentication mechanism is configured, it is necessary
to configure who will have access to the system and what types of access those people will have.
NiFi controls this through the user of an 'Authority Provider.' The Authority Provider is a pluggable
mechanism for providing authorizations to different users. Which Authority Provider to use is configured
using two properties in the _nifi.properties_ file.
The `nifi.authority.provider.configuration.file` property specifies the configuration file for Authority Providers.
The `nifi.security.user.authority.provider` property indicates which of the configured Authority Providers should be
used.
By default, the `file-provider` Authority Provider is selected and is configured to use the permissions granted in
the _authorized-users.xml_ file. This is typically sufficient for instances of NiFi that are run in "standalone" mode.
If the NiFi instance is configured to run in a cluster, the node will typically use the `cluster-node-provider`
Provider and the Cluster Manager will typically use the `cluster-ncm-provider` Provider. Both of these Providers
have a default configuration in the _authority-providers.xml_ file but are commented out.
When using the `cluster-node-provider` Provider, all of the authorization is provided by the Cluster Manager. In this
way, the configuration only has to be maintained in one place and will be consistent across the entire cluster.
When configuring the Cluster Manager or a standalone node, it is necessary to manually designate an ADMIN user
in the _authorized-users.xml_ file, which is located in the root installation's conf directory.
After this ADMIN user has been added, s/he may grant access
to other users, systems, and other instances of NiFi, through the User Interface (UI) without having to manually edit the _authorized-users.xml_
file. If you are the administrator, you would add yourself as the ADMIN user in this file.
Open the _authorized-users.xml_ file in a text editor. You will notice that it includes a template
to guide you, with example entries that are commented out.
It is only necessary to manually add one user, the ADMIN user, to this file.
So, at a minimum, the following example entry should be included and contain the user Distinguished Name (DN)
in place of "user dn - read only and admin":
----
<users>
<user dn="[user dn - read only and admin]">
<role name="ROLE_ADMIN"/>
</user>
</users>
----
Here is an LDAP example entry using the name John Smith:
----
<users>
<user dn="cn=John Smith,ou=people,dc=example,dc=com">
<role name="ROLE_ADMIN"/>
</user>
</users>
----
Here is a Kerberos example entry using the name John Smith and realm `NIFI.APACHE.ORG`:
----
<users>
<user dn="johnsmith@NIFI.APACHE.ORG">
<role name="ROLE_ADMIN"/>
</user>
</users>
----
After the _authorized-users.xml_ file has been edited and saved, restart NiFi.
Once the application starts, the ADMIN user is
able to access the UI at the HTTPS URL that is configured in the _nifi.properties_ file.
From the UI, click on the Users icon ( image:iconUsers.png["Users", width=32] ) in the
Management Toolbar (upper-right corner of the UI), and the User Management Page opens.
The ADMIN user should be listed. Click on the pencil icon to see this user's role(s). You may edit the
roles by selecting the appropriate checkboxes.
The following roles are available in NiFi:
[options="header,footer"]
|========================================================================================================
| Role Name | Description
| Administrator | Administrator is able to configure thread pool sizes and user accounts as well as
purge the dataflow change history.
| Data Flow Manager | Data Flow Manager is given the ability to manipulate the dataflow. S/he is able to
add, remove, and manipulate components on the graph; add, remove, and manipulate
Controller Services and Reporting Tasks; create and manage templates;
view statistics; and view the bulletin board.
| Read Only | Users with Read Only access are able to view the dataflow but are unable to change anything.
| Provenance | Users with Provenance access are able to query the Data Provenance repository and view
the lineage of data. Additionally, this role provides the ability to view or download
the content of a FlowFile from a Provenance event (assuming that the content is still
available in the Content Repository and that the Authority Provider also grants access).
This access is not provided to users with Read Only
(unless the user has both Read Only and Provenance roles) because the information provided
to users with this role can potentially be very sensitive in nature, as all FlowFile attributes
and data are exposed. In order to Replay a Provenance event, a user is required to have both
the Provenance role as well as the Data Flow Manager role.
| NiFi | The NiFi Role is intended to be assigned to machines that will interact with an instance of NiFi
via Site-to-Site. This role provides the ability to send data to or retrieve data from Root
Group Ports (but only those that they are given permissions to interact with - see the User Guide
for more information on providing access to specific Ports) as well as obtain information about
which Ports exist. Note that this role allows the client to know only about the Ports that it
has permissions to interact with.
| Proxy | The Proxy Role is assigned to a system in order to grant that system permission to make requests
on behalf of a user. For instance, if an HTTP proxy service is used to gain access to the system,
the certificate being used by that service can be given the Proxy Role.
|========================================================================================================
When users want access to the NiFi UI, they navigate to the configured URL and are
prompted to request access. When someone has requested access, the ADMIN user sees a star
on the Users icon in the Management Toolbar, alerting the ADMIN to the fact that a request is
pending. Upon opening the User Management Page, the pending request is visible, and the ADMIN
can grant access and click on the pencil icon to set the user's roles appropriately.
The ADMIN may also select multiple users and add them to a "Group". Hold down the Shift key and select
multiple users, then click the `Group` button in the upper-right corner of the User Management Page.
Then, provide a name for the group.
The group feature is especially useful when a remote NiFi cluster is connecting to this NiFi using
a Remote Process Group. In that scenario, all the nodes
in the remote cluster can be included in the same group. When the ADMIN wants to grant port access to the remote
cluster, s/he can grant it to the group and avoid having to grant it individually to each node in the cluster.
[[encryption]] [[encryption]]
Encryption Configuration Encryption Configuration
------------------------ ------------------------
@ -1454,15 +1330,8 @@ Security Configuration section of this Administrator's Guide.
|nifi.security.truststoreType|The truststore type. It is blank by default. |nifi.security.truststoreType|The truststore type. It is blank by default.
|nifi.security.truststorePasswd|The truststore password. It is blank by default. |nifi.security.truststorePasswd|The truststore password. It is blank by default.
|nifi.security.needClientAuth|This indicates whether client authentication in the cluster protocol. It is blank by default. |nifi.security.needClientAuth|This indicates whether client authentication in the cluster protocol. It is blank by default.
|nifi.security.user.credential.cache.duration|The length of time to cache user credentials. The default value is 24 hours.
|nifi.security.user.authority.provider|This indicates what type of authority provider to use. The default value is file-provider, which refers to the file
configured in the core property `nifi.authority.provider.configuration.file`. Another authority provider may be used, such as when the NiFi instance is part of a cluster. But the default value of file-provider is fine for a standalone instance of NiFi.
|nifi.security.user.login.identity.provider|This indicates what type of login identity provider to use. The default value is blank, can be set to the identifier from a provider |nifi.security.user.login.identity.provider|This indicates what type of login identity provider to use. The default value is blank, can be set to the identifier from a provider
in the file specified in `nifi.login.identity.provider.configuration.file`. Setting this property will trigger NiFi to support username/password authentication. in the file specified in `nifi.login.identity.provider.configuration.file`. Setting this property will trigger NiFi to support username/password authentication.
|nifi.security.support.new.account.requests|This indicates whether a secure NiFi is configured to allow users to request access. It is blank by default.
|nifi.security.anonymous.authorities|This indicates what roles to grant to anonymous users accessing NiFi over HTTPS. It is blank by default, but could be
set to any combination of ROLE_MONITOR, ROLE_DFM, ROLE_ADMIN, ROLE_PROVENANCE, ROLE_NIFI. Leaving this property blank will require that users accessing NiFi
over HTTPS be authenticated either using a client certificate or their credentials against the configured log identity provider.
|nifi.security.ocsp.responder.url|This is the URL for the Online Certificate Status Protocol (OCSP) responder if one is being used. It is blank by default. |nifi.security.ocsp.responder.url|This is the URL for the Online Certificate Status Protocol (OCSP) responder if one is being used. It is blank by default.
|nifi.security.ocsp.responder.certificate|This is the location of the OCSP responder certificate if one is being used. It is blank by default. |nifi.security.ocsp.responder.certificate|This is the location of the OCSP responder certificate if one is being used. It is blank by default.
|==== |====

View File

@ -26,7 +26,7 @@ import com.datastax.driver.core.Session;
import org.apache.avro.Schema; import org.apache.avro.Schema;
import org.apache.avro.SchemaBuilder; import org.apache.avro.SchemaBuilder;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.nifi.authorization.exception.ProviderCreationException; import org.apache.nifi.authentication.exception.ProviderCreationException;
import org.apache.nifi.components.PropertyDescriptor; import org.apache.nifi.components.PropertyDescriptor;
import org.apache.nifi.components.PropertyValue; import org.apache.nifi.components.PropertyValue;
import org.apache.nifi.components.ValidationContext; import org.apache.nifi.components.ValidationContext;

View File

@ -22,7 +22,7 @@ import com.datastax.driver.core.DataType;
import com.datastax.driver.core.Metadata; import com.datastax.driver.core.Metadata;
import com.datastax.driver.core.Row; import com.datastax.driver.core.Row;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import org.apache.nifi.authorization.exception.ProviderCreationException; import org.apache.nifi.authentication.exception.ProviderCreationException;
import org.apache.nifi.components.PropertyDescriptor; import org.apache.nifi.components.PropertyDescriptor;
import org.apache.nifi.processor.ProcessContext; import org.apache.nifi.processor.ProcessContext;
import org.apache.nifi.processor.ProcessSession; import org.apache.nifi.processor.ProcessSession;

View File

@ -31,14 +31,6 @@
<groupId>org.apache.nifi</groupId> <groupId>org.apache.nifi</groupId>
<artifactId>nifi-jetty</artifactId> <artifactId>nifi-jetty</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.apache.nifi</groupId>
<artifactId>nifi-cluster-authorization-provider</artifactId>
</dependency>
<dependency>
<groupId>org.apache.nifi</groupId>
<artifactId>nifi-file-authorization-provider</artifactId>
</dependency>
<!-- mark these nifi artifacts as provided since it is included in the lib --> <!-- mark these nifi artifacts as provided since it is included in the lib -->
<dependency> <dependency>

View File

@ -0,0 +1,147 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.admin;
import org.apache.commons.lang3.StringUtils;
import org.apache.nifi.util.NiFiProperties;
import org.h2.jdbcx.JdbcConnectionPool;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.FactoryBean;
import java.io.File;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class KeyDataSourceFactoryBean implements FactoryBean {
private static final Logger logger = LoggerFactory.getLogger(KeyDataSourceFactoryBean.class);
private static final String NF_USERNAME_PASSWORD = "nf";
private static final int MAX_CONNECTIONS = 5;
// database file name
private static final String USER_KEYS_DATABASE_FILE_NAME = "nifi-user-keys";
// ----------
// keys table
// ----------
private static final String CREATE_KEY_TABLE = "CREATE TABLE KEY ("
+ "ID INT NOT NULL PRIMARY KEY AUTO_INCREMENT, "
+ "IDENTITY VARCHAR2(4096) NOT NULL UNIQUE, "
+ "KEY VARCHAR2(100) NOT NULL"
+ ")";
private JdbcConnectionPool connectionPool;
private NiFiProperties properties;
@Override
public Object getObject() throws Exception {
if (connectionPool == null) {
// locate the repository directory
String repositoryDirectoryPath = properties.getProperty(NiFiProperties.REPOSITORY_DATABASE_DIRECTORY);
// ensure the repository directory is specified
if (repositoryDirectoryPath == null) {
throw new NullPointerException("Database directory must be specified.");
}
// create a handle to the repository directory
File repositoryDirectory = new File(repositoryDirectoryPath);
// create a handle to the database directory and file
File databaseFile = new File(repositoryDirectory, USER_KEYS_DATABASE_FILE_NAME);
String databaseUrl = getDatabaseUrl(databaseFile);
// create the pool
connectionPool = JdbcConnectionPool.create(databaseUrl, NF_USERNAME_PASSWORD, NF_USERNAME_PASSWORD);
connectionPool.setMaxConnections(MAX_CONNECTIONS);
Connection connection = null;
ResultSet rs = null;
Statement statement = null;
try {
// get a connection
connection = connectionPool.getConnection();
connection.setAutoCommit(false);
// create a statement for creating/updating the database
statement = connection.createStatement();
// determine if the key table need to be created
rs = connection.getMetaData().getTables(null, null, "KEY", null);
if (!rs.next()) {
statement.execute(CREATE_KEY_TABLE);
}
// commit any changes
connection.commit();
} catch (SQLException sqle) {
RepositoryUtils.rollback(connection, logger);
throw sqle;
} finally {
RepositoryUtils.closeQuietly(rs);
RepositoryUtils.closeQuietly(statement);
RepositoryUtils.closeQuietly(connection);
}
}
return connectionPool;
}
private String getDatabaseUrl(File databaseFile) {
String databaseUrl = "jdbc:h2:" + databaseFile + ";AUTOCOMMIT=OFF;DB_CLOSE_ON_EXIT=FALSE;LOCK_MODE=3";
String databaseUrlAppend = properties.getProperty(NiFiProperties.H2_URL_APPEND);
if (StringUtils.isNotBlank(databaseUrlAppend)) {
databaseUrl += databaseUrlAppend;
}
return databaseUrl;
}
@Override
public Class getObjectType() {
return JdbcConnectionPool.class;
}
@Override
public boolean isSingleton() {
return true;
}
public void setProperties(NiFiProperties properties) {
this.properties = properties;
}
public void shutdown() {
// shutdown the connection pool
if (connectionPool != null) {
try {
connectionPool.dispose();
} catch (Exception e) {
logger.warn("Unable to dispose of connection pool: " + e.getMessage());
if (logger.isDebugEnabled()) {
logger.warn(StringUtils.EMPTY, e);
}
}
}
}
}

View File

@ -1,244 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.admin;
import java.io.File;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import org.apache.commons.lang3.StringUtils;
import org.apache.nifi.authorization.Authority;
import org.h2.jdbcx.JdbcConnectionPool;
import org.apache.nifi.user.NiFiUser;
import org.apache.nifi.util.NiFiProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.FactoryBean;
public class UserDataSourceFactoryBean implements FactoryBean {
private static final Logger logger = LoggerFactory.getLogger(UserDataSourceFactoryBean.class);
private static final String NF_USERNAME_PASSWORD = "nf";
private static final int MAX_CONNECTIONS = 5;
// database file name
private static final String AUDIT_DATABASE_FILE_NAME = "nifi-users";
private static final String CREATE_USER_TABLE = "CREATE TABLE USER ("
+ "ID VARCHAR2(100) NOT NULL PRIMARY KEY, "
+ "IDENTITY VARCHAR2(4096) NOT NULL UNIQUE, "
+ "USER_NAME VARCHAR2(4096) NOT NULL, "
+ "USER_GROUP VARCHAR2(100), "
+ "CREATION TIMESTAMP NOT NULL, "
+ "LAST_ACCESSED TIMESTAMP, "
+ "LAST_VERIFIED TIMESTAMP, "
+ "JUSTIFICATION VARCHAR2(500) NOT NULL, "
+ "STATUS VARCHAR2(10) NOT NULL"
+ ")";
private static final String CREATE_AUTHORITY_TABLE = "CREATE TABLE AUTHORITY ("
+ "ID INT NOT NULL PRIMARY KEY AUTO_INCREMENT, "
+ "USER_ID VARCHAR2(100) NOT NULL, "
+ "ROLE VARCHAR2(50) NOT NULL, "
+ "FOREIGN KEY (USER_ID) REFERENCES USER (ID), "
+ "CONSTRAINT USER_ROLE_UNIQUE_CONSTRAINT UNIQUE (USER_ID, ROLE)"
+ ")";
private static final String INSERT_ANONYMOUS_USER = "INSERT INTO USER ("
+ "ID, IDENTITY, USER_NAME, CREATION, LAST_VERIFIED, JUSTIFICATION, STATUS"
+ ") VALUES ("
+ "'" + UUID.randomUUID().toString() + "', "
+ "'" + NiFiUser.ANONYMOUS_USER_IDENTITY + "', "
+ "'" + NiFiUser.ANONYMOUS_USER_IDENTITY + "', "
+ "NOW(), "
+ "NOW(), "
+ "'Anonymous user needs no justification', "
+ "'ACTIVE'"
+ ")";
private static final String INSERT_ANONYMOUS_AUTHORITY = "INSERT INTO AUTHORITY ("
+ "USER_ID, ROLE"
+ ") VALUES ("
+ "(SELECT ID FROM USER WHERE IDENTITY = '" + NiFiUser.ANONYMOUS_USER_IDENTITY + "'), "
+ "'%s'"
+ ")";
private static final String DELETE_ANONYMOUS_AUTHORITIES = "DELETE FROM AUTHORITY "
+ "WHERE USER_ID = (SELECT ID FROM USER WHERE IDENTITY = '" + NiFiUser.ANONYMOUS_USER_IDENTITY + "')";
private static final String RENAME_DN_COLUMN = "ALTER TABLE USER ALTER COLUMN DN RENAME TO IDENTITY";
private static final String RESIZE_IDENTITY_COLUMN = "ALTER TABLE USER MODIFY IDENTITY VARCHAR(4096)";
private static final String RESIZE_USER_NAME_COLUMN = "ALTER TABLE USER MODIFY USER_NAME VARCHAR(4096)";
// ----------
// keys table
// ----------
private static final String CREATE_KEY_TABLE = "CREATE TABLE KEY ("
+ "ID INT NOT NULL PRIMARY KEY AUTO_INCREMENT, "
+ "IDENTITY VARCHAR2(4096) NOT NULL UNIQUE, "
+ "KEY VARCHAR2(100) NOT NULL"
+ ")";
private JdbcConnectionPool connectionPool;
private NiFiProperties properties;
@Override
public Object getObject() throws Exception {
if (connectionPool == null) {
// locate the repository directory
String repositoryDirectoryPath = properties.getProperty(NiFiProperties.REPOSITORY_DATABASE_DIRECTORY);
// ensure the repository directory is specified
if (repositoryDirectoryPath == null) {
throw new NullPointerException("Database directory must be specified.");
}
// get the roles being granted to anonymous users
final Set<String> rawAnonymousAuthorities = new HashSet<>(properties.getAnonymousAuthorities());
final Set<Authority> anonymousAuthorities = Authority.convertRawAuthorities(rawAnonymousAuthorities);
// ensure every authorities was recognized
if (rawAnonymousAuthorities.size() != anonymousAuthorities.size()) {
final Set<String> validAuthorities = Authority.convertAuthorities(anonymousAuthorities);
rawAnonymousAuthorities.removeAll(validAuthorities);
throw new IllegalStateException(String.format("Invalid authorities specified for anonymous access: [%s]. Valid values are: [%s].",
StringUtils.join(rawAnonymousAuthorities, ", "), StringUtils.join(Authority.values(), ", ")));
}
// create a handle to the repository directory
File repositoryDirectory = new File(repositoryDirectoryPath);
// create a handle to the database directory and file
File databaseFile = new File(repositoryDirectory, AUDIT_DATABASE_FILE_NAME);
String databaseUrl = getDatabaseUrl(databaseFile);
// create the pool
connectionPool = JdbcConnectionPool.create(databaseUrl, NF_USERNAME_PASSWORD, NF_USERNAME_PASSWORD);
connectionPool.setMaxConnections(MAX_CONNECTIONS);
Connection connection = null;
ResultSet rs = null;
Statement statement = null;
try {
// get a connection
connection = connectionPool.getConnection();
connection.setAutoCommit(false);
// create a statement for creating/updating the database
statement = connection.createStatement();
// determine if the tables need to be created
rs = connection.getMetaData().getTables(null, null, "USER", null);
if (!rs.next()) {
logger.info("Database not built for repository: " + databaseUrl + ". Building now...");
// create the tables
statement.execute(CREATE_USER_TABLE);
statement.execute(CREATE_AUTHORITY_TABLE);
// seed the anonymous user
statement.execute(INSERT_ANONYMOUS_USER);
} else {
logger.info("Existing database found and connected to at: " + databaseUrl);
RepositoryUtils.closeQuietly(rs);
// if the DN column exists, transform the table
rs = connection.getMetaData().getColumns(null, null, "USER", "DN");
if (rs.next()) {
statement.execute(RENAME_DN_COLUMN);
statement.execute(RESIZE_IDENTITY_COLUMN);
statement.execute(RESIZE_USER_NAME_COLUMN);
}
// remove all authorities for the anonymous user
statement.execute(DELETE_ANONYMOUS_AUTHORITIES);
}
// add all authorities for the anonymous user
for (final Authority authority : anonymousAuthorities) {
statement.execute(String.format(INSERT_ANONYMOUS_AUTHORITY, authority.name()));
}
RepositoryUtils.closeQuietly(rs);
// determine if the key table need to be created
rs = connection.getMetaData().getTables(null, null, "KEY", null);
if (!rs.next()) {
statement.execute(CREATE_KEY_TABLE);
}
// commit any changes
connection.commit();
} catch (SQLException sqle) {
RepositoryUtils.rollback(connection, logger);
throw sqle;
} finally {
RepositoryUtils.closeQuietly(rs);
RepositoryUtils.closeQuietly(statement);
RepositoryUtils.closeQuietly(connection);
}
}
return connectionPool;
}
private String getDatabaseUrl(File databaseFile) {
String databaseUrl = "jdbc:h2:" + databaseFile + ";AUTOCOMMIT=OFF;DB_CLOSE_ON_EXIT=FALSE;LOCK_MODE=3";
String databaseUrlAppend = properties.getProperty(NiFiProperties.H2_URL_APPEND);
if (StringUtils.isNotBlank(databaseUrlAppend)) {
databaseUrl += databaseUrlAppend;
}
return databaseUrl;
}
@Override
public Class getObjectType() {
return JdbcConnectionPool.class;
}
@Override
public boolean isSingleton() {
return true;
}
public void setProperties(NiFiProperties properties) {
this.properties = properties;
}
public void shutdown() {
// shutdown the connection pool
if (connectionPool != null) {
try {
connectionPool.dispose();
} catch (Exception e) {
logger.warn("Unable to dispose of connection pool: " + e.getMessage());
if (logger.isDebugEnabled()) {
logger.warn(StringUtils.EMPTY, e);
}
}
}
}
}

View File

@ -1,59 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.admin.dao;
import java.util.Set;
import org.apache.nifi.authorization.Authority;
/**
* Authority data access.
*/
public interface AuthorityDAO {
/**
* Finds all Authority for the specified user.
*
* @param userId identifier of user
* @return authorities
*/
Set<Authority> findAuthoritiesByUserId(String userId) throws DataAccessException;
/**
* Creates new Authorities for the specified user in addition to authorities
* they already have.
*
* @param authorities to add to the given user
* @param userId identifier of user
*/
void createAuthorities(Set<Authority> authorities, String userId) throws DataAccessException;
/**
* Removes all Authorities for the specified user.
*
* @param userId user identifier
* @throws DataAccessException if unable to access authorities
*/
void deleteAuthorities(String userId) throws DataAccessException;
/**
* Removes the specified Authority.
*
* @param authorities to remove
* @param userId user id
*/
void deleteAuthorities(Set<Authority> authorities, String userId) throws DataAccessException;
}

View File

@ -21,11 +21,7 @@ package org.apache.nifi.admin.dao;
*/ */
public interface DAOFactory { public interface DAOFactory {
UserDAO getUserDAO();
ActionDAO getActionDAO(); ActionDAO getActionDAO();
AuthorityDAO getAuthorityDAO();
KeyDAO getKeyDAO(); KeyDAO getKeyDAO();
} }

View File

@ -1,128 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.admin.dao;
import java.util.Date;
import java.util.Set;
import org.apache.nifi.user.AccountStatus;
import org.apache.nifi.user.NiFiUser;
/**
* Defines the user data access object.
*/
public interface UserDAO {
/**
* Determines whether there are any PENDING user accounts.
*
* @return true if pending
* @throws DataAccessException dae
*/
Boolean hasPendingUserAccounts() throws DataAccessException;
/**
* Returns all users.
*
* @return all users
* @throws DataAccessException dae
*/
Set<NiFiUser> findUsers() throws DataAccessException;
/**
* Returns all user groups.
*
* @return all group names
* @throws DataAccessException dae
*/
Set<String> findUserGroups() throws DataAccessException;
/**
* Returns all users for the specified group.
*
* @param group group
* @return users in group
* @throws DataAccessException dae
*/
Set<NiFiUser> findUsersForGroup(String group) throws DataAccessException;
/**
* Returns the user with the specified id.
*
* @param id user id
* @return user for the given id
* @throws DataAccessException dae
*/
NiFiUser findUserById(String id) throws DataAccessException;
/**
* Returns the user with the specified DN.
*
* @param dn user dn
* @return user
*/
NiFiUser findUserByDn(String dn) throws DataAccessException;
/**
* Creates a new user based off the specified NiFiUser.
*
* @param user to create
* @return the created user with it's id
*/
NiFiUser createUser(NiFiUser user) throws DataAccessException;
/**
* Updates the specified NiFiUser.
*
* @param user to update
*/
void updateUser(NiFiUser user) throws DataAccessException;
/**
* Deletes the specified user.
*
* @param id user identifier
* @throws DataAccessException dae
*/
void deleteUser(String id) throws DataAccessException;
/**
* Sets the status of the specified group.
*
* @param group group
* @param status status
* @throws DataAccessException dae
*/
void updateGroupStatus(String group, AccountStatus status) throws DataAccessException;
/**
* Sets the last verified time for all users in the specified group.
*
* @param group group
* @param lastVerified date last verified
* @throws DataAccessException dae
*/
void updateGroupVerification(String group, Date lastVerified) throws DataAccessException;
/**
* Ungroups the specified group.
*
* @param group to ungroup
* @throws DataAccessException dae
*/
void ungroup(String group) throws DataAccessException;
}

View File

@ -18,10 +18,8 @@ package org.apache.nifi.admin.dao.impl;
import java.sql.Connection; import java.sql.Connection;
import org.apache.nifi.admin.dao.ActionDAO; import org.apache.nifi.admin.dao.ActionDAO;
import org.apache.nifi.admin.dao.AuthorityDAO;
import org.apache.nifi.admin.dao.DAOFactory; import org.apache.nifi.admin.dao.DAOFactory;
import org.apache.nifi.admin.dao.KeyDAO; import org.apache.nifi.admin.dao.KeyDAO;
import org.apache.nifi.admin.dao.UserDAO;
/** /**
* *
@ -39,16 +37,6 @@ public class DAOFactoryImpl implements DAOFactory {
return new StandardActionDAO(connection); return new StandardActionDAO(connection);
} }
@Override
public AuthorityDAO getAuthorityDAO() {
return new StandardAuthorityDAO(connection);
}
@Override
public UserDAO getUserDAO() {
return new StandardUserDAO(connection);
}
@Override @Override
public KeyDAO getKeyDAO() { public KeyDAO getKeyDAO() {
return new StandardKeyDAO(connection); return new StandardKeyDAO(connection);

View File

@ -1,172 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.admin.dao.impl;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.EnumSet;
import java.util.Set;
import org.apache.nifi.admin.RepositoryUtils;
import org.apache.nifi.admin.dao.AuthorityDAO;
import org.apache.nifi.admin.dao.DataAccessException;
import org.apache.nifi.authorization.Authority;
/**
*
*/
public class StandardAuthorityDAO implements AuthorityDAO {
private static final String SELECT_AUTHORITIES_FOR_USER = "SELECT ID, ROLE "
+ "FROM AUTHORITY "
+ "WHERE USER_ID = ?";
private static final String INSERT_AUTHORITY = "INSERT INTO AUTHORITY ("
+ "USER_ID, ROLE"
+ ") VALUES ("
+ "?, ?"
+ ")";
private static final String DELETE_AUTHORITY = "DELETE FROM AUTHORITY "
+ "WHERE USER_ID = ? AND ROLE = ?";
private static final String DELETE_AUTHORITIES_FOR_USER = "DELETE FROM AUTHORITY "
+ "WHERE USER_ID = ?";
private final Connection connection;
public StandardAuthorityDAO(Connection connection) {
this.connection = connection;
}
@Override
public void createAuthorities(Set<Authority> authorities, String userId) throws DataAccessException {
if (authorities == null) {
throw new IllegalArgumentException("Specified authorities cannot be null.");
}
// ensure there are some authorities to create
if (!authorities.isEmpty()) {
PreparedStatement statement = null;
try {
// add each authority for the specified user
statement = connection.prepareStatement(INSERT_AUTHORITY);
statement.setString(1, userId);
for (Authority authority : authorities) {
statement.setString(2, authority.toString());
statement.addBatch();
}
// insert the authorities
int[] updateCounts = statement.executeBatch();
for (int updateCount : updateCounts) {
if (updateCount != 1) {
throw new DataAccessException("Unable to insert user authorities.");
}
}
} catch (SQLException sqle) {
throw new DataAccessException(sqle);
} catch (DataAccessException dae) {
throw dae;
} finally {
RepositoryUtils.closeQuietly(statement);
}
}
}
@Override
public void deleteAuthorities(String userId) throws DataAccessException {
// ensure there are some authorities to create
PreparedStatement statement = null;
try {
// add each authority for the specified user
statement = connection.prepareStatement(DELETE_AUTHORITIES_FOR_USER);
statement.setString(1, userId);
// insert the authorities
statement.executeUpdate();
} catch (SQLException sqle) {
throw new DataAccessException(sqle);
} finally {
RepositoryUtils.closeQuietly(statement);
}
}
@Override
public void deleteAuthorities(Set<Authority> authorities, String userId) throws DataAccessException {
if (authorities == null) {
throw new IllegalArgumentException("Specified authorities cannot be null.");
}
// ensure there are some authorities to create
if (!authorities.isEmpty()) {
PreparedStatement statement = null;
try {
// add each authority for the specified user
statement = connection.prepareStatement(DELETE_AUTHORITY);
statement.setString(1, userId);
for (Authority authority : authorities) {
statement.setString(2, authority.toString());
statement.addBatch();
}
// insert the authorities
int[] updateCounts = statement.executeBatch();
for (int updateCount : updateCounts) {
if (updateCount != 1) {
throw new DataAccessException("Unable to remove user authorities.");
}
}
} catch (SQLException sqle) {
throw new DataAccessException(sqle);
} catch (DataAccessException dae) {
throw dae;
} finally {
RepositoryUtils.closeQuietly(statement);
}
}
}
@Override
public Set<Authority> findAuthoritiesByUserId(String userId) throws DataAccessException {
Set<Authority> authorities = EnumSet.noneOf(Authority.class);
PreparedStatement statement = null;
ResultSet rs = null;
try {
// add each authority for the specified user
statement = connection.prepareStatement(SELECT_AUTHORITIES_FOR_USER);
statement.setString(1, userId);
// execute the query
rs = statement.executeQuery();
// create each corresponding authority
while (rs.next()) {
authorities.add(Authority.valueOfAuthority(rs.getString("ROLE")));
}
} catch (SQLException sqle) {
throw new DataAccessException(sqle);
} finally {
RepositoryUtils.closeQuietly(rs);
RepositoryUtils.closeQuietly(statement);
}
return authorities;
}
}

View File

@ -1,641 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.admin.dao.impl;
import java.nio.charset.StandardCharsets;
import java.sql.Connection;
import org.apache.nifi.admin.dao.UserDAO;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Types;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import org.apache.nifi.admin.RepositoryUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.nifi.admin.dao.DataAccessException;
import org.apache.nifi.authorization.Authority;
import org.apache.nifi.user.AccountStatus;
import org.apache.nifi.user.NiFiUser;
/**
* Responsible for loading and persisting NiFiUsers.
*/
public class StandardUserDAO implements UserDAO {
private static final String SELECT_PENDING_ACCOUNTS_COUNT = "SELECT "
+ "COUNT(*) as PENDING_ACCOUNTS "
+ "FROM USER U "
+ "WHERE U.STATUS = 'PENDING'";
private static final String SELECT_USER_BY_USER = "SELECT "
+ "U.ID, "
+ "U.IDENTITY, "
+ "U.USER_NAME, "
+ "U.USER_GROUP, "
+ "U.CREATION, "
+ "U.LAST_ACCESSED, "
+ "U.LAST_VERIFIED, "
+ "U.JUSTIFICATION, "
+ "U.STATUS, "
+ "A.ROLE "
+ "FROM USER U "
+ "LEFT JOIN AUTHORITY A " // ensures that users without authorities are still matched
+ "ON U.ID = A.USER_ID "
+ "WHERE U.IDENTITY = ?";
private static final String SELECT_USER_BY_ID = "SELECT "
+ "U.ID, "
+ "U.IDENTITY, "
+ "U.USER_NAME, "
+ "U.USER_GROUP, "
+ "U.CREATION, "
+ "U.LAST_ACCESSED, "
+ "U.LAST_VERIFIED, "
+ "U.JUSTIFICATION, "
+ "U.STATUS, "
+ "A.ROLE "
+ "FROM USER U "
+ "LEFT JOIN AUTHORITY A " // ensures that users without authorities are still matched
+ "ON U.ID = A.USER_ID "
+ "WHERE U.ID = ?";
private static final String SELECT_USERS = "SELECT "
+ "U.ID, "
+ "U.IDENTITY, "
+ "U.USER_NAME, "
+ "U.USER_GROUP, "
+ "U.CREATION, "
+ "U.LAST_ACCESSED, "
+ "U.LAST_VERIFIED, "
+ "U.JUSTIFICATION, "
+ "U.STATUS, "
+ "A.ROLE "
+ "FROM USER U "
+ "LEFT JOIN AUTHORITY A " // ensures that users without authorities are still matched
+ "ON U.ID = A.USER_ID "
+ "WHERE U.IDENTITY <> ?";
private static final String SELECT_USER_GROUPS = "SELECT DISTINCT "
+ "U.USER_GROUP "
+ "FROM USER U";
private static final String SELECT_USER_GROUP = "SELECT "
+ "U.ID, "
+ "U.IDENTITY, "
+ "U.USER_NAME, "
+ "U.USER_GROUP, "
+ "U.CREATION, "
+ "U.LAST_ACCESSED, "
+ "U.LAST_VERIFIED, "
+ "U.JUSTIFICATION, "
+ "U.STATUS, "
+ "A.ROLE "
+ "FROM USER U "
+ "LEFT JOIN AUTHORITY A " // ensures that users without authorities are still matched
+ "ON U.ID = A.USER_ID "
+ "WHERE U.IDENTITY <> ? AND U.USER_GROUP = ?";
private static final String INSERT_USER = "INSERT INTO USER ("
+ "ID, IDENTITY, USER_NAME, USER_GROUP, CREATION, LAST_VERIFIED, JUSTIFICATION, STATUS"
+ ") VALUES ("
+ "?, "
+ "?, "
+ "?, "
+ "?, "
+ "NOW(), "
+ "?, "
+ "?, "
+ "?"
+ ")";
private static final String UPDATE_USER = "UPDATE USER SET "
+ "IDENTITY = ?, "
+ "USER_NAME = ?, "
+ "USER_GROUP = ?, "
+ "LAST_ACCESSED = ?, "
+ "LAST_VERIFIED = ?, "
+ "JUSTIFICATION = ?, "
+ "STATUS = ? "
+ "WHERE ID = ?";
private static final String UPDATE_USER_GROUP_STATUS = "UPDATE USER SET "
+ "STATUS = ?,"
+ "USER_GROUP = NULL "
+ "WHERE USER_GROUP = ?";
private static final String UPDATE_USER_GROUP_VERIFICATION = "UPDATE USER SET "
+ "LAST_VERIFIED = ? "
+ "WHERE USER_GROUP = ?";
private static final String UNGROUP_GROUP = "UPDATE USER SET "
+ "USER_GROUP = NULL "
+ "WHERE USER_GROUP = ?";
private static final String DELETE_USER = "DELETE FROM USER "
+ "WHERE ID = ?";
private final Connection connection;
public StandardUserDAO(Connection connection) {
this.connection = connection;
}
@Override
public Boolean hasPendingUserAccounts() throws DataAccessException {
PreparedStatement statement = null;
ResultSet rs = null;
try {
// create the connection and obtain a statement
statement = connection.prepareStatement(SELECT_PENDING_ACCOUNTS_COUNT);
// execute the query
rs = statement.executeQuery();
// get the first row which will contain the number of pending accounts
if (rs.next()) {
int pendingAccounts = rs.getInt("PENDING_ACCOUNTS");
return pendingAccounts > 0;
}
// query returned no results?
return false;
} catch (SQLException sqle) {
throw new DataAccessException(sqle);
} finally {
RepositoryUtils.closeQuietly(rs);
RepositoryUtils.closeQuietly(statement);
}
}
@Override
public Set<NiFiUser> findUsers() throws DataAccessException {
Set<NiFiUser> users = new HashSet<>();
PreparedStatement statement = null;
ResultSet rs = null;
try {
// create the connection and obtain a statement
statement = connection.prepareStatement(SELECT_USERS);
statement.setString(1, NiFiUser.ANONYMOUS_USER_IDENTITY);
// execute the query
rs = statement.executeQuery();
// create the user
NiFiUser user = null;
// go through the user and its roles
while (rs.next()) {
// get the user id for the current record
String userId = rs.getString("ID");
// create the user during the first iteration
if (user == null || !userId.equals(user.getId())) {
user = new NiFiUser();
user.setId(userId);
user.setIdentity(rs.getString("IDENTITY"));
user.setUserName(rs.getString("USER_NAME"));
user.setUserGroup(rs.getString("USER_GROUP"));
user.setJustification(rs.getString("JUSTIFICATION"));
user.setStatus(AccountStatus.valueOfStatus(rs.getString("STATUS")));
// set the creation date
user.setCreation(new Date(rs.getTimestamp("CREATION").getTime()));
// get the last accessed date
if (rs.getTimestamp("LAST_ACCESSED") != null) {
user.setLastAccessed(new Date(rs.getTimestamp("LAST_ACCESSED").getTime()));
}
// get the last verified date
if (rs.getTimestamp("LAST_VERIFIED") != null) {
user.setLastVerified(new Date(rs.getTimestamp("LAST_VERIFIED").getTime()));
}
// add the user
users.add(user);
}
// the select statement performs a left join since the desired
// user may not have any authorities
String authority = rs.getString("ROLE");
if (StringUtils.isNotBlank(authority)) {
user.getAuthorities().add(Authority.valueOfAuthority(authority));
}
}
return users;
} catch (SQLException sqle) {
throw new DataAccessException(sqle);
} finally {
RepositoryUtils.closeQuietly(rs);
RepositoryUtils.closeQuietly(statement);
}
}
@Override
public Set<String> findUserGroups() throws DataAccessException {
Set<String> userGroups = new HashSet<>();
PreparedStatement statement = null;
ResultSet rs = null;
try {
// create the connection and obtain a statement
statement = connection.prepareStatement(SELECT_USER_GROUPS);
// execute the query
rs = statement.executeQuery();
// get each user group
while (rs.next()) {
userGroups.add(rs.getString("USER_GROUP"));
}
return userGroups;
} catch (SQLException sqle) {
throw new DataAccessException(sqle);
} finally {
RepositoryUtils.closeQuietly(rs);
RepositoryUtils.closeQuietly(statement);
}
}
@Override
public Set<NiFiUser> findUsersForGroup(String group) throws DataAccessException {
Set<NiFiUser> users = new HashSet<>();
PreparedStatement statement = null;
ResultSet rs = null;
try {
// create the connection and obtain a statement
statement = connection.prepareStatement(SELECT_USER_GROUP);
statement.setString(1, NiFiUser.ANONYMOUS_USER_IDENTITY);
statement.setString(2, group);
// execute the query
rs = statement.executeQuery();
// create the user
NiFiUser user = null;
// go through the user and its roles
while (rs.next()) {
// get the user id for the current record
String userId = rs.getString("ID");
// create the user during the first iteration
if (user == null || !userId.equals(user.getId())) {
user = new NiFiUser();
user.setId(userId);
user.setIdentity(rs.getString("IDENTITY"));
user.setUserName(rs.getString("USER_NAME"));
user.setUserGroup(rs.getString("USER_GROUP"));
user.setJustification(rs.getString("JUSTIFICATION"));
user.setStatus(AccountStatus.valueOfStatus(rs.getString("STATUS")));
// set the creation date
user.setCreation(new Date(rs.getTimestamp("CREATION").getTime()));
// get the last accessed date
if (rs.getTimestamp("LAST_ACCESSED") != null) {
user.setLastAccessed(new Date(rs.getTimestamp("LAST_ACCESSED").getTime()));
}
// get the last verified date
if (rs.getTimestamp("LAST_VERIFIED") != null) {
user.setLastVerified(new Date(rs.getTimestamp("LAST_VERIFIED").getTime()));
}
// add the user
users.add(user);
}
// the select statement performs a left join since the desired
// user may not have any authorities
String authority = rs.getString("ROLE");
if (StringUtils.isNotBlank(authority)) {
user.getAuthorities().add(Authority.valueOfAuthority(authority));
}
}
return users;
} catch (SQLException sqle) {
throw new DataAccessException(sqle);
} finally {
RepositoryUtils.closeQuietly(rs);
RepositoryUtils.closeQuietly(statement);
}
}
@Override
public NiFiUser findUserById(String id) throws DataAccessException {
PreparedStatement statement = null;
ResultSet rs = null;
try {
// create the connection and obtain a statement
statement = connection.prepareStatement(SELECT_USER_BY_ID);
statement.setString(1, id);
// execute the query
rs = statement.executeQuery();
// create the user
NiFiUser user = null;
// go through the user and its roles
while (rs.next()) {
// create the user during the first iteration
if (user == null) {
user = new NiFiUser();
user.setId(rs.getString("ID"));
user.setIdentity(rs.getString("IDENTITY"));
user.setUserName(rs.getString("USER_NAME"));
user.setUserGroup(rs.getString("USER_GROUP"));
user.setJustification(rs.getString("JUSTIFICATION"));
user.setStatus(AccountStatus.valueOfStatus(rs.getString("STATUS")));
// set the creation date
user.setCreation(new Date(rs.getTimestamp("CREATION").getTime()));
// get the last accessed date
if (rs.getTimestamp("LAST_ACCESSED") != null) {
user.setLastAccessed(new Date(rs.getTimestamp("LAST_ACCESSED").getTime()));
}
// get the last verified date
if (rs.getTimestamp("LAST_VERIFIED") != null) {
user.setLastVerified(new Date(rs.getTimestamp("LAST_VERIFIED").getTime()));
}
}
// the select statement performs a left join since the desired
// user may not have any authorities
String authority = rs.getString("ROLE");
if (StringUtils.isNotBlank(authority)) {
user.getAuthorities().add(Authority.valueOfAuthority(authority));
}
}
return user;
} catch (SQLException sqle) {
throw new DataAccessException(sqle);
} finally {
RepositoryUtils.closeQuietly(rs);
RepositoryUtils.closeQuietly(statement);
}
}
@Override
public NiFiUser findUserByDn(String dn) throws DataAccessException {
PreparedStatement statement = null;
ResultSet rs = null;
try {
// create the connection and obtain a statement
statement = connection.prepareStatement(SELECT_USER_BY_USER);
statement.setString(1, dn);
// execute the query
rs = statement.executeQuery();
// create the user
NiFiUser user = null;
// go through the user and its roles
while (rs.next()) {
// create the user during the first iteration
if (user == null) {
user = new NiFiUser();
user.setId(rs.getString("ID"));
user.setIdentity(rs.getString("IDENTITY"));
user.setUserName(rs.getString("USER_NAME"));
user.setUserGroup(rs.getString("USER_GROUP"));
user.setJustification(rs.getString("JUSTIFICATION"));
user.setStatus(AccountStatus.valueOfStatus(rs.getString("STATUS")));
// set the creation date
user.setCreation(new Date(rs.getTimestamp("CREATION").getTime()));
// get the last accessed date
if (rs.getTimestamp("LAST_ACCESSED") != null) {
user.setLastAccessed(new Date(rs.getTimestamp("LAST_ACCESSED").getTime()));
}
// get the last verified date
if (rs.getTimestamp("LAST_VERIFIED") != null) {
user.setLastVerified(new Date(rs.getTimestamp("LAST_VERIFIED").getTime()));
}
}
// the select statement performs a left join since the desired
// user may not have any authorities
String authority = rs.getString("ROLE");
if (StringUtils.isNotBlank(authority)) {
user.getAuthorities().add(Authority.valueOfAuthority(authority));
}
}
return user;
} catch (SQLException sqle) {
throw new DataAccessException(sqle);
} finally {
RepositoryUtils.closeQuietly(rs);
RepositoryUtils.closeQuietly(statement);
}
}
@Override
public NiFiUser createUser(NiFiUser user) throws DataAccessException {
if (user.getIdentity() == null) {
throw new IllegalArgumentException("User identity must be specified.");
}
// ensure the user identity is not too lengthy
if (user.getIdentity().length() > 4096) {
throw new IllegalArgumentException("User identity must be less than 4096 characters.");
}
PreparedStatement statement = null;
ResultSet rs = null;
try {
final String id = UUID.nameUUIDFromBytes(user.getIdentity().getBytes(StandardCharsets.UTF_8)).toString();
// create a statement
statement = connection.prepareStatement(INSERT_USER, Statement.RETURN_GENERATED_KEYS);
statement.setString(1, id);
statement.setString(2, StringUtils.left(user.getIdentity(), 4096));
statement.setString(3, StringUtils.left(user.getUserName(), 4096));
statement.setString(4, StringUtils.left(user.getUserGroup(), 100));
if (user.getLastVerified() != null) {
statement.setTimestamp(5, new java.sql.Timestamp(user.getLastVerified().getTime()));
} else {
statement.setTimestamp(5, null);
}
statement.setString(6, StringUtils.left(user.getJustification(), 500));
statement.setString(7, user.getStatus().toString());
// insert the user
int updateCount = statement.executeUpdate();
if (updateCount == 1) {
user.setId(id);
} else {
throw new DataAccessException("Unable to insert user.");
}
return user;
} catch (SQLException sqle) {
throw new DataAccessException(sqle);
} catch (DataAccessException dae) {
throw dae;
} finally {
RepositoryUtils.closeQuietly(rs);
RepositoryUtils.closeQuietly(statement);
}
}
@Override
public void deleteUser(String id) throws DataAccessException {
// ensure there are some authorities to create
PreparedStatement statement = null;
try {
// add each authority for the specified user
statement = connection.prepareStatement(DELETE_USER);
statement.setString(1, id);
// insert the authorities
statement.executeUpdate();
} catch (SQLException sqle) {
throw new DataAccessException(sqle);
} catch (DataAccessException dae) {
throw dae;
} finally {
RepositoryUtils.closeQuietly(statement);
}
}
@Override
public void updateUser(NiFiUser user) throws DataAccessException {
PreparedStatement statement = null;
try {
// create a statement
statement = connection.prepareStatement(UPDATE_USER);
statement.setString(1, StringUtils.left(user.getIdentity(), 4096));
statement.setString(2, StringUtils.left(user.getUserName(), 4096));
statement.setString(3, StringUtils.left(user.getUserGroup(), 100));
statement.setString(6, StringUtils.left(user.getJustification(), 500));
statement.setString(7, user.getStatus().toString());
statement.setString(8, user.getId());
// set the last accessed time accordingly
if (user.getLastAccessed() == null) {
statement.setNull(4, Types.TIMESTAMP);
} else {
statement.setTimestamp(4, new java.sql.Timestamp(user.getLastAccessed().getTime()));
}
// set the last verified time accordingly
if (user.getLastVerified() == null) {
statement.setNull(5, Types.TIMESTAMP);
} else {
statement.setTimestamp(5, new java.sql.Timestamp(user.getLastVerified().getTime()));
}
// perform the update
int updateCount = statement.executeUpdate();
if (updateCount != 1) {
throw new DataAccessException("Unable to update user.");
}
} catch (SQLException sqle) {
throw new DataAccessException(sqle);
} catch (DataAccessException dae) {
throw dae;
} finally {
RepositoryUtils.closeQuietly(statement);
}
}
@Override
public void updateGroupStatus(String group, AccountStatus status) throws DataAccessException {
PreparedStatement statement = null;
try {
// create a statement
statement = connection.prepareStatement(UPDATE_USER_GROUP_STATUS);
statement.setString(1, status.toString());
statement.setString(2, group);
// perform the update
statement.executeUpdate();
} catch (SQLException sqle) {
throw new DataAccessException(sqle);
} catch (DataAccessException dae) {
throw dae;
} finally {
RepositoryUtils.closeQuietly(statement);
}
}
@Override
public void updateGroupVerification(String group, Date lastVerified) throws DataAccessException {
PreparedStatement statement = null;
try {
// create a statement
statement = connection.prepareStatement(UPDATE_USER_GROUP_VERIFICATION);
// set the last verified time accordingly
if (lastVerified == null) {
statement.setNull(1, Types.TIMESTAMP);
} else {
statement.setTimestamp(1, new java.sql.Timestamp(lastVerified.getTime()));
}
// set the group
statement.setString(2, group);
// perform the update
statement.executeUpdate();
} catch (SQLException sqle) {
throw new DataAccessException(sqle);
} catch (DataAccessException dae) {
throw dae;
} finally {
RepositoryUtils.closeQuietly(statement);
}
}
@Override
public void ungroup(String group) throws DataAccessException {
PreparedStatement statement = null;
try {
// create a statement
statement = connection.prepareStatement(UNGROUP_GROUP);
statement.setString(1, group);
// perform the update
statement.executeUpdate();
} catch (SQLException sqle) {
throw new DataAccessException(sqle);
} catch (DataAccessException dae) {
throw dae;
} finally {
RepositoryUtils.closeQuietly(statement);
}
}
}

View File

@ -1,40 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.admin.service;
/**
* Exception to indicate that the user account is disabled.
*/
public class AccountNotFoundException extends RuntimeException {
public AccountNotFoundException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
public AccountNotFoundException(Throwable cause) {
super(cause);
}
public AccountNotFoundException(String message, Throwable cause) {
super(message, cause);
}
public AccountNotFoundException(String message) {
super(message);
}
}

View File

@ -1,41 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.admin.service;
/**
* Exception to indicate that the user has already submitting an account request
* and that request is still pending.
*/
public class AccountPendingException extends RuntimeException {
public AccountPendingException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
public AccountPendingException(Throwable cause) {
super(cause);
}
public AccountPendingException(String message, Throwable cause) {
super(message, cause);
}
public AccountPendingException(String message) {
super(message);
}
}

View File

@ -16,25 +16,34 @@
*/ */
package org.apache.nifi.admin.service; package org.apache.nifi.admin.service;
import org.apache.nifi.key.Key;
/** /**
* Exception to indicate that the user account is disabled. * Manages NiFi user keys.
*/ */
public class AccountDisabledException extends RuntimeException { public interface KeyService {
public AccountDisabledException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { /**
super(message, cause, enableSuppression, writableStackTrace); * Gets a key for the specified user identity. Returns null if the user has not had a key issued
} *
* @param id The key id
* @return The key or null
*/
Key getKey(int id);
public AccountDisabledException(Throwable cause) { /**
super(cause); * Gets a key for the specified user identity. If a key does not exist, one will be created.
} *
* @param identity The user identity
public AccountDisabledException(String message, Throwable cause) { * @return The key
super(message, cause); * @throws AdministrationException if it failed to get/create the key
} */
Key getOrCreateKey(String identity);
public AccountDisabledException(String message) {
super(message);
}
/**
* Deletes keys for the specified identity.
*
* @param identity The user identity
*/
void deleteKey(String identity);
} }

View File

@ -1,180 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.admin.service;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.nifi.authorization.Authority;
import org.apache.nifi.authorization.DownloadAuthorization;
import org.apache.nifi.key.Key;
import org.apache.nifi.user.NiFiUser;
import org.apache.nifi.user.NiFiUserGroup;
/**
* Manages NiFi user accounts.
*/
public interface UserService {
/**
* Creates a new user account using the specified dn and justification.
*
* @param dn user dn
* @param justification why the account is necessary
* @return the created NiFiUser
*/
NiFiUser createPendingUserAccount(String dn, String justification);
/**
* @return Determines if there are any PENDING user accounts present
*/
Boolean hasPendingUserAccount();
/**
* @param dnChain user dn chain
* @param attributes attributes for authorization request
* @return Determines if the users in the dnChain are authorized to download content with the specified attributes
*/
DownloadAuthorization authorizeDownload(List<String> dnChain, Map<String, String> attributes);
/**
* Updates a user group using the specified group comprised of the specified users. Returns all the users that are currently in the specified group.
*
* @param group group
* @param userIds users
* @param authorities auths
* @return a user group
*/
NiFiUserGroup updateGroup(String group, Set<String> userIds, Set<Authority> authorities);
/**
* Authorizes the user specified.
*
* @param dn user dn
* @return the user for the given dn if found
*/
NiFiUser checkAuthorization(String dn);
/**
* Deletes the user with the specified id.
*
* @param id user identifier
*/
void deleteUser(String id);
/**
* Disables the specified users account.
*
* @param id user identifier
* @return user for the given identifier
*/
NiFiUser disable(String id);
/**
* Disables the specified user group.
*
* @param group to disable
* @return user group
*/
NiFiUserGroup disableGroup(String group);
/**
* Updates the specified user with the specified authorities.
*
* @param id identifier of user
* @param authorities auths to set
* @return the updated user
*/
NiFiUser update(String id, Set<Authority> authorities);
/**
* Invalidates the specified user account.
*
* @param id identifier of user account to invalidate
*/
void invalidateUserAccount(String id);
/**
* Invalidates the user accounts associated with the specified user group.
*
* @param group to invalidate user accounts on
*/
void invalidateUserGroupAccount(String group);
/**
* Ungroups the specified group.
*
* @param group to split up
*/
void ungroup(String group);
/**
* Ungroups the specified user.
*
* @param id user to ungroup
*/
void ungroupUser(String id);
/**
* Returns a collection of all NiFiUsers.
*
* @return Collection of users
*/
Collection<NiFiUser> getUsers();
/**
* Finds the specified user by id.
*
* @param id of the user
* @return the user object
*/
NiFiUser getUserById(String id);
/**
* Finds the specified user by dn.
*
* @param dn the user dn
* @return the newly created user
* @throws AdministrationException ae
*/
NiFiUser getUserByDn(String dn);
/**
* Gets a key for the specified user identity. Returns null if the user has not had a key issued
*
* @param id The key id
* @return The key or null
*/
Key getKey(int id);
/**
* Gets a key for the specified user identity. If a key does not exist, one will be created.
*
* @param identity The user identity
* @return The key
* @throws AdministrationException if it failed to get/create the key
*/
Key getOrCreateKey(String identity);
/**
* Deletes keys for the specified identity.
*
* @param identity The user identity
*/
void deleteKey(String identity);
}

View File

@ -1,97 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.admin.service.action;
import java.util.Date;
import java.util.EnumSet;
import java.util.Set;
import org.apache.nifi.authorization.Authority;
import org.apache.nifi.authorization.AuthorityProvider;
import org.apache.nifi.user.AccountStatus;
import org.apache.nifi.user.NiFiUser;
/**
*
* @param <T> type of user action
*/
public abstract class AbstractUserAction<T> implements AdministrationAction<T> {
/**
* Determines the authorities that need to be added to the specified user.
*
* @param user user
* @param authorities auths
* @return authorities to add
*/
protected Set<Authority> determineAuthoritiesToAdd(NiFiUser user, Set<Authority> authorities) {
// not using copyOf since authorities may be empty and copyOf can throw an IllegalArgumentException when empty
Set<Authority> authoritiesToAdd = EnumSet.noneOf(Authority.class);
authoritiesToAdd.addAll(authorities);
// identify the authorities that need to be inserted
authoritiesToAdd.removeAll(user.getAuthorities());
// return the desired authorities
return authoritiesToAdd;
}
/**
* Determines the authorities that need to be removed from the specified
* user.
*
* @param user user
* @param authorities auths
* @return auths to remove
*/
protected Set<Authority> determineAuthoritiesToRemove(NiFiUser user, Set<Authority> authorities) {
Set<Authority> authoritiesToRemove = EnumSet.copyOf(user.getAuthorities());
// identify the authorities that need to be removed
authoritiesToRemove.removeAll(authorities);
// return the desired authorities
return authoritiesToRemove;
}
/**
* Verifies the specified users account. Includes obtaining the authorities
* and group according to the specified authority provider.
*
* @param authorityProvider provider
* @param user user to verify
*/
protected void verifyAccount(AuthorityProvider authorityProvider, NiFiUser user) {
// load the roles for the user
Set<Authority> authorities = authorityProvider.getAuthorities(user.getIdentity());
// update the user's authorities
user.getAuthorities().clear();
user.getAuthorities().addAll(authorities);
// get the user group
user.setUserGroup(authorityProvider.getGroupForUser(user.getIdentity()));
// update the users status in case they were previously pending or disabled
user.setStatus(AccountStatus.ACTIVE);
// update the users last verified time - this timestampt shouldn't be record
// until the both the user's authorities and group have been synced
Date now = new Date();
user.setLastVerified(now);
}
}

View File

@ -19,7 +19,6 @@ package org.apache.nifi.admin.service.action;
import org.apache.nifi.action.Action; import org.apache.nifi.action.Action;
import org.apache.nifi.admin.dao.ActionDAO; import org.apache.nifi.admin.dao.ActionDAO;
import org.apache.nifi.admin.dao.DAOFactory; import org.apache.nifi.admin.dao.DAOFactory;
import org.apache.nifi.authorization.AuthorityProvider;
import java.util.Collection; import java.util.Collection;
@ -35,7 +34,7 @@ public class AddActionsAction implements AdministrationAction<Void> {
} }
@Override @Override
public Void execute(DAOFactory daoFactory, AuthorityProvider authorityProvider) { public Void execute(DAOFactory daoFactory) {
ActionDAO actionDao = daoFactory.getActionDAO(); ActionDAO actionDao = daoFactory.getActionDAO();
// add each action // add each action

View File

@ -17,7 +17,6 @@
package org.apache.nifi.admin.service.action; package org.apache.nifi.admin.service.action;
import org.apache.nifi.admin.dao.DAOFactory; import org.apache.nifi.admin.dao.DAOFactory;
import org.apache.nifi.authorization.AuthorityProvider;
/** /**
* Defines the administration action. Actions are provided a DAO factory and * Defines the administration action. Actions are provided a DAO factory and
@ -31,8 +30,7 @@ public interface AdministrationAction<T> {
* Performs an action using the specified DAOFactory and AuthorityProvider. * Performs an action using the specified DAOFactory and AuthorityProvider.
* *
* @param daoFactory factory * @param daoFactory factory
* @param authorityProvider provider
* @return action result * @return action result
*/ */
T execute(DAOFactory daoFactory, AuthorityProvider authorityProvider); T execute(DAOFactory daoFactory);
} }

View File

@ -1,54 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.admin.service.action;
import java.util.List;
import java.util.Map;
import org.apache.nifi.admin.dao.DAOFactory;
import org.apache.nifi.admin.service.AccountNotFoundException;
import org.apache.nifi.admin.service.AdministrationException;
import org.apache.nifi.authorization.AuthorityProvider;
import org.apache.nifi.authorization.DownloadAuthorization;
import org.apache.nifi.authorization.exception.AuthorityAccessException;
import org.apache.nifi.authorization.exception.UnknownIdentityException;
/**
* Attempts to obtain authorization to download the content with the specified
* attributes for the specified user.
*/
public class AuthorizeDownloadAction implements AdministrationAction<DownloadAuthorization> {
private final List<String> dnChain;
private final Map<String, String> attributes;
public AuthorizeDownloadAction(List<String> dnChain, Map<String, String> attributes) {
this.dnChain = dnChain;
this.attributes = attributes;
}
@Override
public DownloadAuthorization execute(DAOFactory daoFactory, AuthorityProvider authorityProvider) {
try {
return authorityProvider.authorizeDownload(dnChain, attributes);
} catch (UnknownIdentityException uie) {
throw new AccountNotFoundException(uie.getMessage(), uie);
} catch (AuthorityAccessException aae) {
throw new AdministrationException(aae.getMessage(), aae);
}
}
}

View File

@ -1,173 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.admin.service.action;
import java.util.Calendar;
import java.util.Date;
import org.apache.nifi.admin.dao.DAOFactory;
import org.apache.nifi.admin.dao.DataAccessException;
import org.apache.nifi.admin.dao.UserDAO;
import org.apache.nifi.admin.service.AccountDisabledException;
import org.apache.nifi.admin.service.AccountNotFoundException;
import org.apache.nifi.admin.service.AccountPendingException;
import org.apache.nifi.admin.service.AdministrationException;
import org.apache.nifi.authorization.AuthorityProvider;
import org.apache.nifi.authorization.exception.AuthorityAccessException;
import org.apache.nifi.authorization.exception.UnknownIdentityException;
import org.apache.nifi.security.util.CertificateUtils;
import org.apache.nifi.user.AccountStatus;
import org.apache.nifi.user.NiFiUser;
/**
*
*/
public class AuthorizeUserAction extends AbstractUserAction<NiFiUser> {
private final String identity;
private final int cacheDurationSeconds;
public AuthorizeUserAction(String identity, int cacheDurationSeconds) {
this.identity = identity;
this.cacheDurationSeconds = cacheDurationSeconds;
}
@Override
public NiFiUser execute(DAOFactory daoFactory, AuthorityProvider authorityProvider) throws DataAccessException {
UserDAO userDao = daoFactory.getUserDAO();
// get the user
NiFiUser user = userDao.findUserByDn(identity);
// verify the user was found
if (user == null) {
// determine whether this users exists
boolean doesDnExist = false;
try {
doesDnExist = authorityProvider.doesDnExist(identity);
} catch (AuthorityAccessException aae) {
throw new AdministrationException(String.format("Unable to access authority details: %s", aae.getMessage()), aae);
}
// if the authority provider has the details for this user, create the account
if (doesDnExist) {
// create the user
user = new NiFiUser();
user.setIdentity(identity);
user.setUserName(CertificateUtils.extractUsername(identity));
user.setJustification("User details specified by authority provider.");
try {
// verify the users account
verifyAccount(authorityProvider, user);
// get the date used for verification
Date now = user.getLastVerified();
// update the last accessed field
user.setLastAccessed(now);
user.setCreation(now);
// create the new user account
CreateUserAction createUser = new CreateUserAction(user);
createUser.execute(daoFactory, authorityProvider);
} catch (UnknownIdentityException uie) {
// strange since the provider just reported this dn existed but handleing anyways...
throw new AccountNotFoundException(String.format("Unable to verify access for %s.", identity));
} catch (AuthorityAccessException aae) {
throw new AdministrationException(String.format("Unable to access authority details: %s", aae.getMessage()), aae);
}
} else {
throw new AccountNotFoundException(String.format("Unable to verify access for %s.", identity));
}
} else {
Throwable providerError = null;
// verify the users account if necessary
if (isAccountVerificationRequired(user)) {
try {
// verify the users account
verifyAccount(authorityProvider, user);
// update the last accessed field
user.setLastAccessed(user.getLastVerified());
} catch (UnknownIdentityException uie) {
// check the account status before attempting to update the account - depending on the account
// status we might not need to update the account
checkAccountStatus(user);
// the user is currently active and they were not found in the providers - disable the account...
user.setStatus(AccountStatus.DISABLED);
// record the exception
providerError = uie;
} catch (AuthorityAccessException aae) {
throw new AdministrationException(String.format("Unable to access authority details: %s", aae.getMessage()), aae);
}
} else {
// verfiy the users account status before allowing access.
checkAccountStatus(user);
// update the users last accessed time
user.setLastAccessed(new Date());
}
// persist the user's updates
UpdateUserCacheAction updateUser = new UpdateUserCacheAction(user);
updateUser.execute(daoFactory, authorityProvider);
// persist the user's authorities
UpdateUserAuthoritiesCacheAction updateUserAuthorities = new UpdateUserAuthoritiesCacheAction(user);
updateUserAuthorities.execute(daoFactory, authorityProvider);
if (providerError != null) {
throw new AccountDisabledException(String.format("User credentials for %s were not found. This account has been disabled.", user.getIdentity()), providerError);
}
}
return user;
}
/**
* @return Determines if account verification is required
*/
private boolean isAccountVerificationRequired(NiFiUser user) {
// accounts that have never been verified obviously needs to be re-verified
if (user.getLastVerified() == null) {
return true;
}
// create a calendar and substract the threshold - anything
// before this time will need to be re-verified
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.SECOND, -cacheDurationSeconds);
return user.getLastVerified().before(calendar.getTime());
}
/**
* Checks the account status of the specified user.
*
* @param user to check
*/
private void checkAccountStatus(NiFiUser user) {
if (AccountStatus.DISABLED.equals(user.getStatus())) {
throw new AccountDisabledException(String.format("The account for %s has been disabled.", user.getIdentity()));
} else if (AccountStatus.PENDING.equals(user.getStatus())) {
throw new AccountPendingException(String.format("The account for %s is currently pending approval.", user.getIdentity()));
}
}
}

View File

@ -1,53 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.admin.service.action;
import java.util.Set;
import org.apache.nifi.admin.dao.AuthorityDAO;
import org.apache.nifi.admin.dao.DAOFactory;
import org.apache.nifi.admin.dao.DataAccessException;
import org.apache.nifi.admin.dao.UserDAO;
import org.apache.nifi.authorization.Authority;
import org.apache.nifi.authorization.AuthorityProvider;
import org.apache.nifi.user.NiFiUser;
/**
* Action for creating a NiFiUser account.
*/
public class CreateUserAction extends AbstractUserAction<Void> {
private final NiFiUser user;
public CreateUserAction(NiFiUser user) {
this.user = user;
}
@Override
public Void execute(DAOFactory daoFactory, AuthorityProvider authorityProvider) throws DataAccessException {
UserDAO userDao = daoFactory.getUserDAO();
AuthorityDAO authorityDao = daoFactory.getAuthorityDAO();
// create the user entry
userDao.createUser(user);
// create the authorities
Set<Authority> authorities = user.getAuthorities();
authorityDao.createAuthorities(authorities, user.getId());
return null;
}
}

View File

@ -19,7 +19,6 @@ package org.apache.nifi.admin.service.action;
import org.apache.nifi.admin.dao.DAOFactory; import org.apache.nifi.admin.dao.DAOFactory;
import org.apache.nifi.admin.dao.DataAccessException; import org.apache.nifi.admin.dao.DataAccessException;
import org.apache.nifi.admin.dao.KeyDAO; import org.apache.nifi.admin.dao.KeyDAO;
import org.apache.nifi.authorization.AuthorityProvider;
/** /**
* *
@ -38,7 +37,7 @@ public class DeleteKeysAction implements AdministrationAction<Void> {
} }
@Override @Override
public Void execute(DAOFactory daoFactory, AuthorityProvider authorityProvider) throws DataAccessException { public Void execute(DAOFactory daoFactory) throws DataAccessException {
final KeyDAO keyDao = daoFactory.getKeyDAO(); final KeyDAO keyDao = daoFactory.getKeyDAO();
keyDao.deleteKeys(identity); keyDao.deleteKeys(identity);
return null; return null;

View File

@ -1,73 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.admin.service.action;
import org.apache.nifi.admin.dao.AuthorityDAO;
import org.apache.nifi.admin.dao.DAOFactory;
import org.apache.nifi.admin.dao.DataAccessException;
import org.apache.nifi.admin.dao.KeyDAO;
import org.apache.nifi.admin.dao.UserDAO;
import org.apache.nifi.admin.service.AccountNotFoundException;
import org.apache.nifi.authorization.AuthorityProvider;
import org.apache.nifi.user.AccountStatus;
import org.apache.nifi.user.NiFiUser;
/**
*
*/
public class DeleteUserAction implements AdministrationAction<Void> {
private final String userId;
/**
* Creates a new transactions for deleting the specified user.
*
* @param userId user identifier
*/
public DeleteUserAction(String userId) {
this.userId = userId;
}
@Override
public Void execute(DAOFactory daoFactory, AuthorityProvider authorityProvider) throws DataAccessException {
final AuthorityDAO authorityDAO = daoFactory.getAuthorityDAO();
final UserDAO userDAO = daoFactory.getUserDAO();
// find the user and ensure they are currently revoked
final NiFiUser user = userDAO.findUserById(userId);
// ensure the user was found
if (user == null) {
throw new AccountNotFoundException(String.format("Unable to find account with ID %s.", userId));
}
// ensure the user is in the appropriate state
if (AccountStatus.ACTIVE.equals(user.getStatus())) {
throw new IllegalStateException(String.format("An active user cannot be removed. Revoke user access before attempting to remove."));
}
// remove the user's keys
final KeyDAO keyDao = daoFactory.getKeyDAO();
keyDao.deleteKeys(user.getIdentity());
// remove the user and their authorities
authorityDAO.deleteAuthorities(userId);
userDAO.deleteUser(userId);
return null;
}
}

View File

@ -1,81 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.admin.service.action;
import org.apache.nifi.admin.dao.DAOFactory;
import org.apache.nifi.admin.dao.DataAccessException;
import org.apache.nifi.admin.dao.KeyDAO;
import org.apache.nifi.admin.dao.UserDAO;
import org.apache.nifi.admin.service.AccountNotFoundException;
import org.apache.nifi.admin.service.AdministrationException;
import org.apache.nifi.authorization.AuthorityProvider;
import org.apache.nifi.authorization.exception.AuthorityAccessException;
import org.apache.nifi.authorization.exception.UnknownIdentityException;
import org.apache.nifi.user.AccountStatus;
import org.apache.nifi.user.NiFiUser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
*/
public class DisableUserAction implements AdministrationAction<NiFiUser> {
private static final Logger logger = LoggerFactory.getLogger(DisableUserAction.class);
private final String id;
public DisableUserAction(String id) {
this.id = id;
}
@Override
public NiFiUser execute(DAOFactory daoFactory, AuthorityProvider authorityProvider) throws DataAccessException {
UserDAO userDao = daoFactory.getUserDAO();
// get the user
NiFiUser user = userDao.findUserById(id);
// ensure the user exists
if (user == null) {
throw new AccountNotFoundException(String.format("Unable to find account with ID %s.", id));
}
// update the account
user.setStatus(AccountStatus.DISABLED);
user.setUserGroup(null);
// update the user locally
userDao.updateUser(user);
// remove the user's keys
KeyDAO keyDao = daoFactory.getKeyDAO();
keyDao.deleteKeys(user.getIdentity());
try {
// revoke the user in the authority provider
authorityProvider.revokeUser(user.getIdentity());
} catch (UnknownIdentityException uie) {
// user identity is not known
logger.info(String.format("User %s has already been removed from the authority provider.", user.getIdentity()));
} catch (AuthorityAccessException aae) {
throw new AdministrationException(String.format("Unable to revoke user '%s': %s", user.getIdentity(), aae.getMessage()), aae);
}
return user;
}
}

View File

@ -1,78 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.admin.service.action;
import java.util.Set;
import org.apache.nifi.admin.dao.DAOFactory;
import org.apache.nifi.admin.dao.DataAccessException;
import org.apache.nifi.admin.dao.KeyDAO;
import org.apache.nifi.admin.dao.UserDAO;
import org.apache.nifi.admin.service.AdministrationException;
import org.apache.nifi.authorization.AuthorityProvider;
import org.apache.nifi.authorization.exception.AuthorityAccessException;
import org.apache.nifi.authorization.exception.UnknownIdentityException;
import org.apache.nifi.user.AccountStatus;
import org.apache.nifi.user.NiFiUser;
import org.apache.nifi.user.NiFiUserGroup;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
*/
public class DisableUserGroupAction implements AdministrationAction<NiFiUserGroup> {
private static final Logger logger = LoggerFactory.getLogger(DisableUserGroupAction.class);
private final String group;
public DisableUserGroupAction(final String group) {
this.group = group;
}
@Override
public NiFiUserGroup execute(DAOFactory daoFactory, AuthorityProvider authorityProvider) throws DataAccessException {
final UserDAO userDao = daoFactory.getUserDAO();
final Set<NiFiUser> users = userDao.findUsersForGroup(group);
// delete the keys for each user
final KeyDAO keyDao = daoFactory.getKeyDAO();
for (final NiFiUser user : users) {
keyDao.deleteKeys(user.getIdentity());
}
// update the user group locally
userDao.updateGroupStatus(group, AccountStatus.DISABLED);
// populate the group details
final NiFiUserGroup userGroup = new NiFiUserGroup();
userGroup.setGroup(group);
userGroup.setUsers(userDao.findUsersForGroup(group));
try {
// revoke the user in the authority provider
authorityProvider.revokeGroup(group);
} catch (UnknownIdentityException uie) {
// user identity is not known
logger.info(String.format("User group %s has already been removed from the authority provider.", group));
} catch (AuthorityAccessException aae) {
throw new AdministrationException(String.format("Unable to revoke user group '%s': %s", group, aae.getMessage()), aae);
}
return userGroup;
}
}

View File

@ -1,49 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.admin.service.action;
import org.apache.nifi.admin.dao.DAOFactory;
import org.apache.nifi.admin.dao.DataAccessException;
import org.apache.nifi.admin.dao.UserDAO;
import org.apache.nifi.authorization.AuthorityProvider;
import org.apache.nifi.user.NiFiUser;
/**
*
*/
public class FindUserByDnAction implements AdministrationAction<NiFiUser> {
private final String dn;
/**
* Creates a new transactions for getting a user with the specified DN.
*
* @param dn The DN of the user to obtain
*/
public FindUserByDnAction(String dn) {
this.dn = dn;
}
@Override
public NiFiUser execute(DAOFactory daoFactory, AuthorityProvider authorityProvider) throws DataAccessException {
// get a UserDAO
UserDAO userDAO = daoFactory.getUserDAO();
// return the desired user
return userDAO.findUserByDn(dn);
}
}

View File

@ -1,46 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.admin.service.action;
import org.apache.nifi.admin.dao.DAOFactory;
import org.apache.nifi.admin.dao.DataAccessException;
import org.apache.nifi.admin.dao.UserDAO;
import org.apache.nifi.authorization.AuthorityProvider;
import org.apache.nifi.user.NiFiUser;
public class FindUserByIdAction implements AdministrationAction<NiFiUser> {
private final String id;
/**
* Creates a new transactions for getting a user with the specified id.
*
* @param id of user
*/
public FindUserByIdAction(String id) {
this.id = id;
}
@Override
public NiFiUser execute(DAOFactory daoFactory, AuthorityProvider authorityProvider) throws DataAccessException {
// get a UserDAO
UserDAO userDAO = daoFactory.getUserDAO();
// return the desired user
return userDAO.findUserById(id);
}
}

View File

@ -19,7 +19,6 @@ package org.apache.nifi.admin.service.action;
import org.apache.nifi.action.Action; import org.apache.nifi.action.Action;
import org.apache.nifi.admin.dao.ActionDAO; import org.apache.nifi.admin.dao.ActionDAO;
import org.apache.nifi.admin.dao.DAOFactory; import org.apache.nifi.admin.dao.DAOFactory;
import org.apache.nifi.authorization.AuthorityProvider;
/** /**
* Gets the action with the specified id. * Gets the action with the specified id.
@ -33,7 +32,7 @@ public class GetActionAction implements AdministrationAction<Action> {
} }
@Override @Override
public Action execute(DAOFactory daoFactory, AuthorityProvider authorityProvider) { public Action execute(DAOFactory daoFactory) {
ActionDAO actionDao = daoFactory.getActionDAO(); ActionDAO actionDao = daoFactory.getActionDAO();
return actionDao.getAction(id); return actionDao.getAction(id);
} }

View File

@ -16,13 +16,13 @@
*/ */
package org.apache.nifi.admin.service.action; package org.apache.nifi.admin.service.action;
import java.util.Date;
import org.apache.nifi.admin.dao.ActionDAO; import org.apache.nifi.admin.dao.ActionDAO;
import org.apache.nifi.admin.dao.DAOFactory; import org.apache.nifi.admin.dao.DAOFactory;
import org.apache.nifi.authorization.AuthorityProvider;
import org.apache.nifi.history.History; import org.apache.nifi.history.History;
import org.apache.nifi.history.HistoryQuery; import org.apache.nifi.history.HistoryQuery;
import java.util.Date;
/** /**
* Get all actions that match the specified query. * Get all actions that match the specified query.
*/ */
@ -35,7 +35,7 @@ public class GetActionsAction implements AdministrationAction<History> {
} }
@Override @Override
public History execute(DAOFactory daoFactory, AuthorityProvider authorityProvider) { public History execute(DAOFactory daoFactory) {
ActionDAO actionDao = daoFactory.getActionDAO(); ActionDAO actionDao = daoFactory.getActionDAO();
// find all matching history // find all matching history

View File

@ -17,8 +17,6 @@
package org.apache.nifi.admin.service.action; package org.apache.nifi.admin.service.action;
import org.apache.nifi.admin.dao.DAOFactory; import org.apache.nifi.admin.dao.DAOFactory;
import org.apache.nifi.authorization.AuthorityProvider;
import org.apache.nifi.admin.dao.KeyDAO; import org.apache.nifi.admin.dao.KeyDAO;
import org.apache.nifi.key.Key; import org.apache.nifi.key.Key;
@ -34,7 +32,7 @@ public class GetKeyByIdAction implements AdministrationAction<Key> {
} }
@Override @Override
public Key execute(DAOFactory daoFactory, AuthorityProvider authorityProvider) { public Key execute(DAOFactory daoFactory) {
final KeyDAO keyDao = daoFactory.getKeyDAO(); final KeyDAO keyDao = daoFactory.getKeyDAO();
return keyDao.findKeyById(id); return keyDao.findKeyById(id);
} }

View File

@ -17,8 +17,6 @@
package org.apache.nifi.admin.service.action; package org.apache.nifi.admin.service.action;
import org.apache.nifi.admin.dao.DAOFactory; import org.apache.nifi.admin.dao.DAOFactory;
import org.apache.nifi.authorization.AuthorityProvider;
import org.apache.nifi.admin.dao.KeyDAO; import org.apache.nifi.admin.dao.KeyDAO;
import org.apache.nifi.key.Key; import org.apache.nifi.key.Key;
@ -34,7 +32,7 @@ public class GetKeyByIdentityAction implements AdministrationAction<Key> {
} }
@Override @Override
public Key execute(DAOFactory daoFactory, AuthorityProvider authorityProvider) { public Key execute(DAOFactory daoFactory) {
final KeyDAO keyDao = daoFactory.getKeyDAO(); final KeyDAO keyDao = daoFactory.getKeyDAO();
return keyDao.findLatestKeyByIdentity(identity); return keyDao.findLatestKeyByIdentity(identity);
} }

View File

@ -17,8 +17,6 @@
package org.apache.nifi.admin.service.action; package org.apache.nifi.admin.service.action;
import org.apache.nifi.admin.dao.DAOFactory; import org.apache.nifi.admin.dao.DAOFactory;
import org.apache.nifi.authorization.AuthorityProvider;
import org.apache.nifi.admin.dao.KeyDAO; import org.apache.nifi.admin.dao.KeyDAO;
import org.apache.nifi.key.Key; import org.apache.nifi.key.Key;
@ -34,7 +32,7 @@ public class GetOrCreateKeyAction implements AdministrationAction<Key> {
} }
@Override @Override
public Key execute(DAOFactory daoFactory, AuthorityProvider authorityProvider) { public Key execute(DAOFactory daoFactory) {
final KeyDAO keyDao = daoFactory.getKeyDAO(); final KeyDAO keyDao = daoFactory.getKeyDAO();
Key key = keyDao.findLatestKeyByIdentity(identity); Key key = keyDao.findLatestKeyByIdentity(identity);

View File

@ -16,13 +16,13 @@
*/ */
package org.apache.nifi.admin.service.action; package org.apache.nifi.admin.service.action;
import java.util.List;
import java.util.Map;
import org.apache.nifi.admin.dao.ActionDAO; import org.apache.nifi.admin.dao.ActionDAO;
import org.apache.nifi.admin.dao.DAOFactory; import org.apache.nifi.admin.dao.DAOFactory;
import org.apache.nifi.authorization.AuthorityProvider;
import org.apache.nifi.history.PreviousValue; import org.apache.nifi.history.PreviousValue;
import java.util.List;
import java.util.Map;
/** /**
* Gets the action with the specified id. * Gets the action with the specified id.
*/ */
@ -35,7 +35,7 @@ public class GetPreviousValues implements AdministrationAction<Map<String, List<
} }
@Override @Override
public Map<String, List<PreviousValue>> execute(DAOFactory daoFactory, AuthorityProvider authorityProvider) { public Map<String, List<PreviousValue>> execute(DAOFactory daoFactory) {
ActionDAO actionDao = daoFactory.getActionDAO(); ActionDAO actionDao = daoFactory.getActionDAO();
return actionDao.getPreviousValues(componentId); return actionDao.getPreviousValues(componentId);
} }

View File

@ -1,50 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.admin.service.action;
import org.apache.nifi.admin.dao.DAOFactory;
import org.apache.nifi.admin.dao.DataAccessException;
import org.apache.nifi.admin.dao.UserDAO;
import org.apache.nifi.authorization.AuthorityProvider;
import org.apache.nifi.user.NiFiUserGroup;
/**
*
*/
public class GetUserGroupAction implements AdministrationAction<NiFiUserGroup> {
private final String group;
public GetUserGroupAction(String group) {
this.group = group;
}
@Override
public NiFiUserGroup execute(DAOFactory daoFactory, AuthorityProvider authorityProvider) throws DataAccessException {
final UserDAO userDAO = daoFactory.getUserDAO();
final NiFiUserGroup userGroup = new NiFiUserGroup();
// set the group
userGroup.setGroup(group);
// get the users in this group
userGroup.setUsers(userDAO.findUsersForGroup(group));
// return the group
return userGroup;
}
}

View File

@ -1,39 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.admin.service.action;
import java.util.Collection;
import org.apache.nifi.admin.dao.DAOFactory;
import org.apache.nifi.admin.dao.DataAccessException;
import org.apache.nifi.admin.dao.UserDAO;
import org.apache.nifi.authorization.AuthorityProvider;
import org.apache.nifi.user.NiFiUser;
/**
*
*/
public class GetUsersAction implements AdministrationAction<Collection<NiFiUser>> {
@Override
public Collection<NiFiUser> execute(DAOFactory daoFactory, AuthorityProvider authorityProvider) throws DataAccessException {
// get a UserDAO
UserDAO userDAO = daoFactory.getUserDAO();
// return the desired user
return userDAO.findUsers();
}
}

View File

@ -1,34 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.admin.service.action;
import org.apache.nifi.admin.dao.DAOFactory;
import org.apache.nifi.admin.dao.DataAccessException;
import org.apache.nifi.admin.dao.UserDAO;
import org.apache.nifi.authorization.AuthorityProvider;
/**
* Action for creating a NiFiUser account.
*/
public class HasPendingUserAccounts extends AbstractUserAction<Boolean> {
@Override
public Boolean execute(DAOFactory daoFactory, AuthorityProvider authorityProvider) throws DataAccessException {
UserDAO userDao = daoFactory.getUserDAO();
return userDao.hasPendingUserAccounts();
}
}

View File

@ -1,58 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.admin.service.action;
import org.apache.nifi.admin.dao.DAOFactory;
import org.apache.nifi.admin.dao.DataAccessException;
import org.apache.nifi.admin.dao.UserDAO;
import org.apache.nifi.admin.service.AccountNotFoundException;
import org.apache.nifi.authorization.AuthorityProvider;
import org.apache.nifi.user.NiFiUser;
/**
* Invalidates a user account.
*/
public class InvalidateUserAccountAction implements AdministrationAction<Void> {
private final String id;
public InvalidateUserAccountAction(String id) {
this.id = id;
}
@Override
public Void execute(DAOFactory daoFactory, AuthorityProvider authorityProvider) throws DataAccessException {
UserDAO userDao = daoFactory.getUserDAO();
// get the current user details
NiFiUser user = userDao.findUserById(id);
// ensure the user exists
if (user == null) {
throw new AccountNotFoundException(String.format("Unable to find account with ID %s.", id));
}
// invalidate the user account
user.setLastVerified(null);
// create the user entry
userDao.updateUser(user);
return null;
}
}

View File

@ -1,45 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.admin.service.action;
import org.apache.nifi.admin.dao.DAOFactory;
import org.apache.nifi.admin.dao.DataAccessException;
import org.apache.nifi.admin.dao.UserDAO;
import org.apache.nifi.authorization.AuthorityProvider;
/**
* Invalidates a user account.
*/
public class InvalidateUserGroupAccountsAction implements AdministrationAction<Void> {
private final String group;
public InvalidateUserGroupAccountsAction(String group) {
this.group = group;
}
@Override
public Void execute(DAOFactory daoFactory, AuthorityProvider authorityProvider) throws DataAccessException {
UserDAO userDao = daoFactory.getUserDAO();
// create the user entry
userDao.updateGroupVerification(group, null);
return null;
}
}

View File

@ -19,7 +19,6 @@ package org.apache.nifi.admin.service.action;
import org.apache.nifi.action.Action; import org.apache.nifi.action.Action;
import org.apache.nifi.admin.dao.ActionDAO; import org.apache.nifi.admin.dao.ActionDAO;
import org.apache.nifi.admin.dao.DAOFactory; import org.apache.nifi.admin.dao.DAOFactory;
import org.apache.nifi.authorization.AuthorityProvider;
import java.util.Date; import java.util.Date;
@ -37,7 +36,7 @@ public class PurgeActionsAction implements AdministrationAction<Void> {
} }
@Override @Override
public Void execute(DAOFactory daoFactory, AuthorityProvider authorityProvider) { public Void execute(DAOFactory daoFactory) {
ActionDAO actionDao = daoFactory.getActionDAO(); ActionDAO actionDao = daoFactory.getActionDAO();
// remove the corresponding actions // remove the corresponding actions

View File

@ -1,67 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.admin.service.action;
import java.util.Date;
import org.apache.nifi.admin.dao.DAOFactory;
import org.apache.nifi.admin.dao.DataAccessException;
import org.apache.nifi.admin.dao.UserDAO;
import org.apache.nifi.authorization.AuthorityProvider;
import org.apache.nifi.security.util.CertificateUtils;
import org.apache.nifi.user.AccountStatus;
import org.apache.nifi.user.NiFiUser;
/**
*
*/
public class RequestUserAccountAction implements AdministrationAction<NiFiUser> {
private final String identity;
private final String justification;
public RequestUserAccountAction(String identity, String justification) {
this.identity = identity;
this.justification = justification;
}
@Override
public NiFiUser execute(DAOFactory daoFactory, AuthorityProvider authorityProvider) throws DataAccessException {
UserDAO userDao = daoFactory.getUserDAO();
// determine if this user already exists
NiFiUser user = userDao.findUserByDn(identity);
if (user != null) {
throw new IllegalArgumentException(String.format("User account for %s already exists.", identity));
}
// create the user
user = new NiFiUser();
user.setIdentity(identity);
user.setUserName(CertificateUtils.extractUsername(identity));
user.setJustification(justification);
user.setStatus(AccountStatus.PENDING);
// update user timestamps
Date now = new Date();
user.setCreation(now);
// create the new user account
userDao.createUser(user);
return user;
}
}

View File

@ -1,164 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.admin.service.action;
import java.util.HashSet;
import java.util.Set;
import org.apache.nifi.admin.dao.DAOFactory;
import org.apache.nifi.admin.dao.DataAccessException;
import org.apache.nifi.admin.dao.UserDAO;
import org.apache.nifi.admin.service.AdministrationException;
import org.apache.nifi.authorization.Authority;
import org.apache.nifi.authorization.AuthorityProvider;
import org.apache.nifi.authorization.exception.AuthorityAccessException;
import org.apache.nifi.authorization.exception.UnknownIdentityException;
import org.apache.nifi.security.util.CertificateUtils;
import org.apache.nifi.user.AccountStatus;
import org.apache.nifi.user.NiFiUser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Seeds the user accounts. This action is performed at start up because it
* takes the users specified in the authority provider and makes them available
* to be seen in the UI. This happens because the UI loads the users from the
* cache. Without pre loading the users, the table in the UI would only show a
* given user once they have visited the application.
*/
public class SeedUserAccountsAction extends AbstractUserAction<Void> {
private static final Logger logger = LoggerFactory.getLogger(SeedUserAccountsAction.class);
@Override
public Void execute(DAOFactory daoFactory, AuthorityProvider authorityProvider) throws DataAccessException {
UserDAO userDao = daoFactory.getUserDAO();
Set<String> authorizedIdentities = new HashSet<>();
// get the current user cache
final Set<NiFiUser> existingUsers;
try {
existingUsers = userDao.findUsers();
} catch (Exception e) {
// unable to access local cache... start up failure
logger.error(String.format("Unable to get existing user base. Cannot proceed until these users can be "
+ "verified against the current authority provider: %s", e));
throw new AdministrationException(e);
}
try {
// all users for all roles
for (final Authority authority : Authority.values()) {
authorizedIdentities.addAll(authorityProvider.getUsers(authority));
}
} catch (AuthorityAccessException aae) {
// unable to access the authority provider... honor the cache
logger.warn("Unable to access authority provider due to " + aae);
return null;
}
final Set<NiFiUser> accountsToRevoke = new HashSet<>(existingUsers);
// persist the users
for (String identity : authorizedIdentities) {
NiFiUser user = null;
try {
// locate the user for this dn
user = userDao.findUserByDn(identity);
boolean newAccount = false;
// if the user does not exist, create a new account
if (user == null) {
logger.info(String.format("Creating user account: %s", identity));
newAccount = true;
// create the user
user = new NiFiUser();
user.setIdentity(identity);
user.setUserName(CertificateUtils.extractUsername(identity));
user.setJustification("User details specified by authority provider.");
} else {
logger.info(String.format("User account already created: %s. Updating authorities...", identity));
}
// verify the account
verifyAccount(authorityProvider, user);
// persist the account accordingly
if (newAccount) {
CreateUserAction createUser = new CreateUserAction(user);
createUser.execute(daoFactory, authorityProvider);
} else {
// this is not a new user and we have just verified their
// account, do not revoke...
accountsToRevoke.remove(user);
// persist the user
UpdateUserCacheAction updateUser = new UpdateUserCacheAction(user);
updateUser.execute(daoFactory, authorityProvider);
// persist the user's authorities
UpdateUserAuthoritiesCacheAction updateUserAuthorities = new UpdateUserAuthoritiesCacheAction(user);
updateUserAuthorities.execute(daoFactory, authorityProvider);
}
} catch (DataAccessException dae) {
if (user != null) {
logger.warn(String.format("Unable to access account details in local cache for user %s: %s", user, dae.getMessage()));
} else {
logger.warn(String.format("Unable to access account details in local cache: %s", dae.getMessage()));
}
} catch (UnknownIdentityException uie) {
if (user != null) {
logger.warn(String.format("Unable to find account details in authority provider for user %s: %s", user, uie.getMessage()));
} else {
logger.warn(String.format("Unable to find account details in authority provider: %s", uie.getMessage()));
}
} catch (AuthorityAccessException aae) {
logger.warn("Unable to access authority provider due to " + aae);
// unable to access authority provider for this user, honor the cache for now
accountsToRevoke.remove(user);
}
}
// remove all users that are no longer in the provider
for (final NiFiUser user : accountsToRevoke) {
// allow pending requests to remain...
if (AccountStatus.PENDING.equals(user.getStatus())) {
continue;
}
try {
logger.info(String.format("User not authorized with configured provider: %s. Disabling account...", user.getIdentity()));
// disable the account and reset its last verified timestamp since it was not found
// in the current configured authority provider
user.setStatus(AccountStatus.DISABLED);
user.setLastVerified(null);
// update the user record
UpdateUserCacheAction updateUser = new UpdateUserCacheAction(user);
updateUser.execute(daoFactory, authorityProvider);
} catch (final Exception e) {
// unable to revoke access for someone we know is not authorized... fail start up
logger.error(String.format("Unable to revoke access for user %s that is no longer authorized: %s", user, e));
throw new AdministrationException(e);
}
}
return null;
}
}

View File

@ -1,69 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.admin.service.action;
import org.apache.nifi.admin.dao.DAOFactory;
import org.apache.nifi.admin.dao.UserDAO;
import org.apache.nifi.admin.service.AccountNotFoundException;
import org.apache.nifi.admin.service.AdministrationException;
import org.apache.nifi.authorization.AuthorityProvider;
import org.apache.nifi.authorization.exception.AuthorityAccessException;
import org.apache.nifi.authorization.exception.UnknownIdentityException;
import org.apache.nifi.user.NiFiUser;
/**
*
*/
public class UngroupUserAction extends AbstractUserAction<Void> {
private final String userId;
public UngroupUserAction(String userId) {
this.userId = userId;
}
@Override
public Void execute(DAOFactory daoFactory, AuthorityProvider authorityProvider) {
final UserDAO userDao = daoFactory.getUserDAO();
// get the user in question
final NiFiUser user = userDao.findUserById(userId);
// ensure the user exists
if (user == null) {
throw new AccountNotFoundException(String.format("Unable to find account with ID %s.", userId));
}
// set the user group
user.setUserGroup(null);
// update the user locally
userDao.updateUser(user);
try {
// update the authority provider
authorityProvider.ungroupUser(user.getIdentity());
} catch (UnknownIdentityException uie) {
throw new AccountNotFoundException(String.format("Unable to ungroup user '%s': %s", user.getIdentity(), uie.getMessage()), uie);
} catch (AuthorityAccessException aae) {
throw new AdministrationException(String.format("Unable to ungroup user '%s': %s", user.getIdentity(), aae.getMessage()), aae);
}
return null;
}
}

View File

@ -1,57 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.admin.service.action;
import org.apache.nifi.admin.dao.DAOFactory;
import org.apache.nifi.admin.dao.UserDAO;
import org.apache.nifi.admin.service.AccountNotFoundException;
import org.apache.nifi.admin.service.AdministrationException;
import org.apache.nifi.authorization.AuthorityProvider;
import org.apache.nifi.authorization.exception.AuthorityAccessException;
import org.apache.nifi.authorization.exception.UnknownIdentityException;
/**
*
*/
public class UngroupUserGroupAction extends AbstractUserAction<Void> {
private final String group;
public UngroupUserGroupAction(String group) {
this.group = group;
}
@Override
public Void execute(DAOFactory daoFactory, AuthorityProvider authorityProvider) {
final UserDAO userDao = daoFactory.getUserDAO();
// update the user locally
userDao.ungroup(group);
try {
// update the authority provider
authorityProvider.ungroup(group);
} catch (UnknownIdentityException uie) {
throw new AccountNotFoundException(String.format("Unable to ungroup '%s': %s", group, uie.getMessage()), uie);
} catch (AuthorityAccessException aae) {
throw new AdministrationException(String.format("Unable to ungroup '%s': %s", group, aae.getMessage()), aae);
}
return null;
}
}

View File

@ -1,124 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.admin.service.action;
import java.util.Date;
import java.util.Set;
import org.apache.nifi.admin.dao.DAOFactory;
import org.apache.nifi.admin.dao.DataAccessException;
import org.apache.nifi.admin.dao.UserDAO;
import org.apache.nifi.admin.service.AccountNotFoundException;
import org.apache.nifi.admin.service.AdministrationException;
import org.apache.nifi.authorization.Authority;
import org.apache.nifi.authorization.AuthorityProvider;
import org.apache.nifi.authorization.exception.AuthorityAccessException;
import org.apache.nifi.authorization.exception.IdentityAlreadyExistsException;
import org.apache.nifi.authorization.exception.UnknownIdentityException;
import org.apache.nifi.user.AccountStatus;
import org.apache.nifi.user.NiFiUser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Sets user authorities.
*/
public class UpdateUserAction extends AbstractUserAction<NiFiUser> {
private static final Logger logger = LoggerFactory.getLogger(UpdateUserAction.class);
private final String id;
private final Set<Authority> authorities;
public UpdateUserAction(String id, Set<Authority> authorities) {
this.id = id;
this.authorities = authorities;
}
@Override
public NiFiUser execute(DAOFactory daoFactory, AuthorityProvider authorityProvider) throws DataAccessException, AdministrationException {
UserDAO userDao = daoFactory.getUserDAO();
// get the user
NiFiUser user = userDao.findUserById(id);
// ensure the user exists
if (user == null) {
throw new AccountNotFoundException(String.format("Unable to find account with ID %s.", id));
}
// determine whether this users exists
boolean doesIdentityExist = false;
try {
doesIdentityExist = authorityProvider.doesDnExist(user.getIdentity());
} catch (AuthorityAccessException aae) {
throw new AdministrationException(String.format("Unable to access authority details: %s", aae.getMessage()), aae);
}
// if the user already doesn't exist, add them
if (!doesIdentityExist) {
try {
// add the account account and group if necessary
authorityProvider.addUser(user.getIdentity(), user.getUserGroup());
} catch (final IdentityAlreadyExistsException iaee) {
logger.warn(String.format("User '%s' already exists in the authority provider. Continuing with user update.", user.getIdentity()));
} catch (AuthorityAccessException aae) {
throw new AdministrationException(String.format("Unable to access authorities for '%s': %s", user.getIdentity(), aae.getMessage()), aae);
}
}
try {
// update the authority provider as approprivate
authorityProvider.setAuthorities(user.getIdentity(), authorities);
} catch (UnknownIdentityException uie) {
throw new AccountNotFoundException(String.format("Unable to modify authorities for '%s': %s.", user.getIdentity(), uie.getMessage()), uie);
} catch (AuthorityAccessException aae) {
throw new AdministrationException(String.format("Unable to access authorities for '%s': %s.", user.getIdentity(), aae.getMessage()), aae);
}
try {
// get the user group
user.setUserGroup(authorityProvider.getGroupForUser(user.getIdentity()));
} catch (UnknownIdentityException uie) {
throw new AccountNotFoundException(String.format("Unable to determine the group for '%s': %s.", user.getIdentity(), uie.getMessage()), uie);
} catch (AuthorityAccessException aae) {
throw new AdministrationException(String.format("Unable to access the group for '%s': %s.", user.getIdentity(), aae.getMessage()), aae);
}
// since all the authorities were updated accordingly, set the authorities
user.getAuthorities().clear();
user.getAuthorities().addAll(authorities);
// update the users status in case they were previously pending or disabled
user.setStatus(AccountStatus.ACTIVE);
// update the users last verified time - this timestamp shouldn't be recorded
// until the both the user's authorities and group have been synced
Date now = new Date();
user.setLastVerified(now);
// persist the user's updates
UpdateUserCacheAction updateUser = new UpdateUserCacheAction(user);
updateUser.execute(daoFactory, authorityProvider);
// persist the user's authorities
UpdateUserAuthoritiesCacheAction updateUserAuthorities = new UpdateUserAuthoritiesCacheAction(user);
updateUserAuthorities.execute(daoFactory, authorityProvider);
// return the user
return user;
}
}

View File

@ -1,73 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.admin.service.action;
import java.util.Set;
import org.apache.nifi.admin.dao.AuthorityDAO;
import org.apache.nifi.admin.dao.DAOFactory;
import org.apache.nifi.admin.dao.DataAccessException;
import org.apache.nifi.admin.dao.UserDAO;
import org.apache.nifi.admin.service.AccountNotFoundException;
import org.apache.nifi.authorization.Authority;
import org.apache.nifi.authorization.AuthorityProvider;
import org.apache.nifi.user.NiFiUser;
import org.apache.commons.collections4.CollectionUtils;
/**
* Updates a NiFiUser's authorities. Prior to invoking this action, the user's
* authorities should be set according to the business logic of the service in
* question. This should not be invoked directly when attempting to set user
* authorities as the authorityProvider is not called from this action.
*/
public class UpdateUserAuthoritiesCacheAction extends AbstractUserAction<Void> {
private final NiFiUser user;
public UpdateUserAuthoritiesCacheAction(NiFiUser user) {
this.user = user;
}
@Override
public Void execute(DAOFactory daoFactory, AuthorityProvider authorityProvider) throws DataAccessException {
UserDAO userDao = daoFactory.getUserDAO();
AuthorityDAO authorityDao = daoFactory.getAuthorityDAO();
// get the user
NiFiUser currentUser = userDao.findUserById(user.getId());
// ensure the user exists
if (currentUser == null) {
throw new AccountNotFoundException(String.format("Unable to find account with ID %s.", user.getId()));
}
// determine what authorities need to be added/removed
Set<Authority> authorities = user.getAuthorities();
Set<Authority> authoritiesToAdd = determineAuthoritiesToAdd(currentUser, authorities);
Set<Authority> authoritiesToRemove = determineAuthoritiesToRemove(currentUser, authorities);
// update the user authorities locally
if (CollectionUtils.isNotEmpty(authoritiesToAdd)) {
authorityDao.createAuthorities(authoritiesToAdd, user.getId());
}
if (CollectionUtils.isNotEmpty(authoritiesToRemove)) {
authorityDao.deleteAuthorities(authoritiesToRemove, user.getId());
}
return null;
}
}

View File

@ -1,47 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.admin.service.action;
import org.apache.nifi.admin.dao.DAOFactory;
import org.apache.nifi.admin.dao.DataAccessException;
import org.apache.nifi.admin.dao.UserDAO;
import org.apache.nifi.authorization.AuthorityProvider;
import org.apache.nifi.user.NiFiUser;
/**
* Updates a NiFiUser. This will not update the user authorities, they must be
* updated with the UpdateUserAuthoritiesAction.
*/
public class UpdateUserCacheAction extends AbstractUserAction<Void> {
private final NiFiUser user;
public UpdateUserCacheAction(NiFiUser user) {
this.user = user;
}
@Override
public Void execute(DAOFactory daoFactory, AuthorityProvider authorityProvider) throws DataAccessException {
UserDAO userDao = daoFactory.getUserDAO();
// update the user
userDao.updateUser(user);
return null;
}
}

View File

@ -1,171 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.admin.service.action;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import org.apache.nifi.admin.dao.DAOFactory;
import org.apache.nifi.admin.dao.DataAccessException;
import org.apache.nifi.admin.dao.UserDAO;
import org.apache.nifi.admin.service.AccountNotFoundException;
import org.apache.nifi.admin.service.AdministrationException;
import org.apache.nifi.authorization.Authority;
import org.apache.nifi.authorization.AuthorityProvider;
import org.apache.nifi.authorization.exception.AuthorityAccessException;
import org.apache.nifi.authorization.exception.UnknownIdentityException;
import org.apache.nifi.user.AccountStatus;
import org.apache.nifi.user.NiFiUser;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Updates all NiFiUser authorities in a specified group.
*/
public class UpdateUserGroupAction extends AbstractUserAction<Void> {
private static final Logger logger = LoggerFactory.getLogger(UpdateUserGroupAction.class);
private final String group;
private final Set<String> userIds;
private final Set<Authority> authorities;
public UpdateUserGroupAction(String group, Set<String> userIds, Set<Authority> authorities) {
this.group = group;
this.userIds = userIds;
this.authorities = authorities;
}
@Override
public Void execute(DAOFactory daoFactory, AuthorityProvider authorityProvider) throws DataAccessException {
if (userIds == null && authorities == null) {
throw new IllegalArgumentException("Must specify user Ids or authorities.");
}
UserDAO userDao = daoFactory.getUserDAO();
// record the new users being added to this group
final Set<NiFiUser> newUsers = new HashSet<>();
final Set<String> newUserIdentities = new HashSet<>();
// if the user ids have been specified we need to create/update a group using the specified group name
if (userIds != null) {
if (userIds.isEmpty()) {
throw new IllegalArgumentException("When creating a group, at least one user id must be specified.");
}
// going to create a group using the specified user ids
for (final String userId : userIds) {
// get the user in question
final NiFiUser user = userDao.findUserById(userId);
// ensure the user exists
if (user == null) {
throw new AccountNotFoundException(String.format("Unable to find account with ID %s.", userId));
}
try {
// if the user is unknown to the authority provider we cannot continue
if (!authorityProvider.doesDnExist(user.getIdentity()) || AccountStatus.DISABLED.equals(user.getStatus())) {
throw new IllegalStateException(String.format("Unable to group these users because access for '%s' is not %s.", user.getIdentity(), AccountStatus.ACTIVE.toString()));
}
// record the user being added to this group
newUsers.add(user);
newUserIdentities.add(user.getIdentity());
} catch (final AuthorityAccessException aae) {
throw new AdministrationException(String.format("Unable to access authority details: %s", aae.getMessage()), aae);
}
}
try {
// update the authority provider
authorityProvider.setUsersGroup(newUserIdentities, group);
} catch (UnknownIdentityException uie) {
throw new AccountNotFoundException(String.format("Unable to set user group '%s': %s", StringUtils.join(newUserIdentities, ", "), uie.getMessage()), uie);
} catch (AuthorityAccessException aae) {
throw new AdministrationException(String.format("Unable to set user group '%s': %s", StringUtils.join(newUserIdentities, ", "), aae.getMessage()), aae);
}
}
// get all the users that need to be updated
final Set<NiFiUser> users = new HashSet<>(userDao.findUsersForGroup(group));
users.addAll(newUsers);
// ensure the user exists
if (users.isEmpty()) {
throw new AccountNotFoundException(String.format("Unable to find user accounts with group id %s.", group));
}
// update each user in this group
for (final NiFiUser user : users) {
// if there are new authorities set them, otherwise refresh them according to the provider
if (authorities != null) {
try {
// update the authority provider as approprivate
authorityProvider.setAuthorities(user.getIdentity(), authorities);
// since all the authorities were updated accordingly, set the authorities
user.getAuthorities().clear();
user.getAuthorities().addAll(authorities);
} catch (UnknownIdentityException uie) {
throw new AccountNotFoundException(String.format("Unable to modify authorities for '%s': %s.", user.getIdentity(), uie.getMessage()), uie);
} catch (AuthorityAccessException aae) {
throw new AdministrationException(String.format("Unable to access authorities for '%s': %s.", user.getIdentity(), aae.getMessage()), aae);
}
} else {
try {
// refresh the authorities according to the provider
user.getAuthorities().clear();
user.getAuthorities().addAll(authorityProvider.getAuthorities(user.getIdentity()));
} catch (UnknownIdentityException uie) {
throw new AccountNotFoundException(String.format("Unable to determine the authorities for '%s': %s.", user.getIdentity(), uie.getMessage()), uie);
} catch (AuthorityAccessException aae) {
throw new AdministrationException(String.format("Unable to access authorities for '%s': %s.", user.getIdentity(), aae.getMessage()), aae);
}
}
try {
// get the user group
user.setUserGroup(authorityProvider.getGroupForUser(user.getIdentity()));
} catch (UnknownIdentityException uie) {
throw new AccountNotFoundException(String.format("Unable to determine the group for '%s': %s.", user.getIdentity(), uie.getMessage()), uie);
} catch (AuthorityAccessException aae) {
throw new AdministrationException(String.format("Unable to access the group for '%s': %s.", user.getIdentity(), aae.getMessage()), aae);
}
// update the users status in case they were previously pending or disabled
user.setStatus(AccountStatus.ACTIVE);
// update the users last verified time - this timestamp shouldn't be recorded
// until the both the user's authorities and group have been synced
Date now = new Date();
user.setLastVerified(now);
// persist the user's updates
UpdateUserCacheAction updateUser = new UpdateUserCacheAction(user);
updateUser.execute(daoFactory, authorityProvider);
// persist the user's authorities
UpdateUserAuthoritiesCacheAction updateUserAuthorities = new UpdateUserAuthoritiesCacheAction(user);
updateUserAuthorities.execute(daoFactory, authorityProvider);
}
return null;
}
}

View File

@ -0,0 +1,161 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.admin.service.impl;
import org.apache.nifi.admin.dao.DataAccessException;
import org.apache.nifi.admin.service.AdministrationException;
import org.apache.nifi.admin.service.KeyService;
import org.apache.nifi.admin.service.action.DeleteKeysAction;
import org.apache.nifi.admin.service.action.GetKeyByIdAction;
import org.apache.nifi.admin.service.action.GetOrCreateKeyAction;
import org.apache.nifi.admin.service.transaction.Transaction;
import org.apache.nifi.admin.service.transaction.TransactionBuilder;
import org.apache.nifi.admin.service.transaction.TransactionException;
import org.apache.nifi.key.Key;
import org.apache.nifi.util.NiFiProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
*
*/
public class StandardKeyService implements KeyService {
private static final Logger logger = LoggerFactory.getLogger(StandardKeyService.class);
private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
private final Lock readLock = lock.readLock();
private final Lock writeLock = lock.writeLock();
private TransactionBuilder transactionBuilder;
private NiFiProperties properties;
@Override
public Key getKey(int id) {
Transaction transaction = null;
Key key = null;
readLock.lock();
try {
// start the transaction
transaction = transactionBuilder.start();
// get the key
GetKeyByIdAction addActions = new GetKeyByIdAction(id);
key = transaction.execute(addActions);
// commit the transaction
transaction.commit();
} catch (TransactionException | DataAccessException te) {
rollback(transaction);
throw new AdministrationException(te);
} catch (Throwable t) {
rollback(transaction);
throw t;
} finally {
closeQuietly(transaction);
readLock.unlock();
}
return key;
}
@Override
public Key getOrCreateKey(String identity) {
Transaction transaction = null;
Key key = null;
writeLock.lock();
try {
// start the transaction
transaction = transactionBuilder.start();
// get or create a key
GetOrCreateKeyAction addActions = new GetOrCreateKeyAction(identity);
key = transaction.execute(addActions);
// commit the transaction
transaction.commit();
} catch (TransactionException | DataAccessException te) {
rollback(transaction);
throw new AdministrationException(te);
} catch (Throwable t) {
rollback(transaction);
throw t;
} finally {
closeQuietly(transaction);
writeLock.unlock();
}
return key;
}
@Override
public void deleteKey(String identity) {
Transaction transaction = null;
writeLock.lock();
try {
// start the transaction
transaction = transactionBuilder.start();
// delete the keys
DeleteKeysAction deleteKeys = new DeleteKeysAction(identity);
transaction.execute(deleteKeys);
// commit the transaction
transaction.commit();
} catch (TransactionException | DataAccessException te) {
rollback(transaction);
throw new AdministrationException(te);
} catch (Throwable t) {
rollback(transaction);
throw t;
} finally {
closeQuietly(transaction);
writeLock.unlock();
}
}
private void rollback(final Transaction transaction) {
if (transaction != null) {
transaction.rollback();
}
}
private void closeQuietly(final Transaction transaction) {
if (transaction != null) {
try {
transaction.close();
} catch (final IOException ioe) {
}
}
}
public void setTransactionBuilder(TransactionBuilder transactionBuilder) {
this.transactionBuilder = transactionBuilder;
}
public void setProperties(NiFiProperties properties) {
this.properties = properties;
}
}

View File

@ -1,731 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.admin.service.impl;
import java.io.IOException;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import org.apache.nifi.admin.dao.DataAccessException;
import org.apache.nifi.admin.service.AccountDisabledException;
import org.apache.nifi.admin.service.AccountPendingException;
import org.apache.nifi.admin.service.AdministrationException;
import org.apache.nifi.admin.service.UserService;
import org.apache.nifi.admin.service.action.AuthorizeDownloadAction;
import org.apache.nifi.admin.service.action.AuthorizeUserAction;
import org.apache.nifi.admin.service.action.DeleteKeysAction;
import org.apache.nifi.admin.service.action.DeleteUserAction;
import org.apache.nifi.admin.service.action.DisableUserAction;
import org.apache.nifi.admin.service.action.DisableUserGroupAction;
import org.apache.nifi.admin.service.action.FindUserByDnAction;
import org.apache.nifi.admin.service.action.FindUserByIdAction;
import org.apache.nifi.admin.service.action.GetKeyByIdAction;
import org.apache.nifi.admin.service.action.GetOrCreateKeyAction;
import org.apache.nifi.admin.service.action.GetUserGroupAction;
import org.apache.nifi.admin.service.action.GetUsersAction;
import org.apache.nifi.admin.service.action.HasPendingUserAccounts;
import org.apache.nifi.admin.service.action.InvalidateUserAccountAction;
import org.apache.nifi.admin.service.action.InvalidateUserGroupAccountsAction;
import org.apache.nifi.admin.service.action.RequestUserAccountAction;
import org.apache.nifi.admin.service.action.SeedUserAccountsAction;
import org.apache.nifi.admin.service.action.UpdateUserAction;
import org.apache.nifi.admin.service.action.UpdateUserGroupAction;
import org.apache.nifi.admin.service.action.UngroupUserAction;
import org.apache.nifi.admin.service.action.UngroupUserGroupAction;
import org.apache.nifi.admin.service.transaction.Transaction;
import org.apache.nifi.admin.service.transaction.TransactionBuilder;
import org.apache.nifi.admin.service.transaction.TransactionException;
import org.apache.nifi.authorization.Authority;
import org.apache.nifi.authorization.DownloadAuthorization;
import org.apache.nifi.key.Key;
import org.apache.nifi.user.NiFiUser;
import org.apache.nifi.user.NiFiUserGroup;
import org.apache.nifi.util.FormatUtils;
import org.apache.nifi.util.NiFiProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
*/
public class StandardUserService implements UserService {
private static final Logger logger = LoggerFactory.getLogger(StandardUserService.class);
private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
private final ReentrantReadWriteLock.ReadLock readLock = lock.readLock();
private final ReentrantReadWriteLock.WriteLock writeLock = lock.writeLock();
private TransactionBuilder transactionBuilder;
private NiFiProperties properties;
/**
* Seed any users from the authority provider that are not already present.
*/
public void seedUserAccounts() {
// do not seed node's user cache. when/if the node disconnects its
// cache will be populated lazily (as needed)
if (properties.isNode()) {
return;
}
Transaction transaction = null;
writeLock.lock();
try {
// start the transaction
transaction = transactionBuilder.start();
// seed the accounts
SeedUserAccountsAction seedUserAccounts = new SeedUserAccountsAction();
transaction.execute(seedUserAccounts);
// commit the transaction
transaction.commit();
} catch (AdministrationException ae) {
rollback(transaction);
throw ae;
} catch (Throwable t) {
rollback(transaction);
throw t;
} finally {
closeQuietly(transaction);
writeLock.unlock();
}
}
@Override
public NiFiUser createPendingUserAccount(String dn, String justification) {
Transaction transaction = null;
writeLock.lock();
try {
// start the transaction
transaction = transactionBuilder.start();
// create the account request
RequestUserAccountAction requestUserAccount = new RequestUserAccountAction(dn, justification);
NiFiUser user = transaction.execute(requestUserAccount);
// commit the transaction
transaction.commit();
// return the nifi user
return user;
} catch (TransactionException | DataAccessException te) {
rollback(transaction);
throw new AdministrationException(te);
} catch (Throwable t) {
rollback(transaction);
throw t;
} finally {
closeQuietly(transaction);
writeLock.unlock();
}
}
@Override
public NiFiUserGroup updateGroup(final String group, final Set<String> userIds, final Set<Authority> authorities) {
Transaction transaction = null;
writeLock.lock();
try {
// if user ids have been specified, invalidate the user accounts before performing
// the desired updates. if case of an error, this will ensure that these users are
// authorized the next time the access the application
if (userIds != null) {
for (final String userId : userIds) {
invalidateUserAccount(userId);
}
}
// start the transaction
transaction = transactionBuilder.start();
// set the authorities for each user in this group if specified
final UpdateUserGroupAction updateUserGroup = new UpdateUserGroupAction(group, userIds, authorities);
transaction.execute(updateUserGroup);
// get all the users that are now in this group
final GetUserGroupAction getUserGroup = new GetUserGroupAction(group);
final NiFiUserGroup userGroup = transaction.execute(getUserGroup);
// commit the transaction
transaction.commit();
return userGroup;
} catch (TransactionException | DataAccessException te) {
rollback(transaction);
throw new AdministrationException(te);
} catch (Throwable t) {
rollback(transaction);
throw t;
} finally {
closeQuietly(transaction);
writeLock.unlock();
}
}
@Override
public void ungroupUser(String id) {
Transaction transaction = null;
writeLock.lock();
try {
// start the transaction
transaction = transactionBuilder.start();
// ungroup the specified user
final UngroupUserAction ungroupUser = new UngroupUserAction(id);
transaction.execute(ungroupUser);
// commit the transaction
transaction.commit();
} catch (TransactionException | DataAccessException te) {
rollback(transaction);
throw new AdministrationException(te);
} catch (Throwable t) {
rollback(transaction);
throw t;
} finally {
closeQuietly(transaction);
writeLock.unlock();
}
}
@Override
public void ungroup(String group) {
Transaction transaction = null;
writeLock.lock();
try {
// start the transaction
transaction = transactionBuilder.start();
// ungroup the specified user
final UngroupUserGroupAction ungroupUserGroup = new UngroupUserGroupAction(group);
transaction.execute(ungroupUserGroup);
// commit the transaction
transaction.commit();
} catch (TransactionException | DataAccessException te) {
rollback(transaction);
throw new AdministrationException(te);
} catch (Throwable t) {
rollback(transaction);
throw t;
} finally {
closeQuietly(transaction);
writeLock.unlock();
}
}
@Override
public NiFiUser checkAuthorization(String dn) {
Transaction transaction = null;
writeLock.lock();
try {
// create the connection
transaction = transactionBuilder.start();
// determine how long the cache is valid for
final int cacheSeconds;
try {
cacheSeconds = (int) FormatUtils.getTimeDuration(properties.getUserCredentialCacheDuration(), TimeUnit.SECONDS);
} catch (IllegalArgumentException iae) {
throw new AdministrationException("User credential cache duration is not configured correctly.");
}
// attempt to authorize the user
AuthorizeUserAction authorizeUser = new AuthorizeUserAction(dn, cacheSeconds);
NiFiUser user = transaction.execute(authorizeUser);
// commit the transaction
transaction.commit();
// return the nifi user
return user;
} catch (DataAccessException | TransactionException dae) {
rollback(transaction);
throw new AdministrationException(dae);
} catch (AccountDisabledException | AccountPendingException ade) {
rollback(transaction);
throw ade;
} catch (Throwable t) {
rollback(transaction);
throw t;
} finally {
closeQuietly(transaction);
writeLock.unlock();
}
}
@Override
public void deleteUser(String id) {
Transaction transaction = null;
writeLock.lock();
try {
// create the connection
transaction = transactionBuilder.start();
// delete the user
DeleteUserAction deleteUser = new DeleteUserAction(id);
transaction.execute(deleteUser);
// commit the transaction
transaction.commit();
} catch (DataAccessException | TransactionException dae) {
rollback(transaction);
throw new AdministrationException(dae);
} catch (Throwable t) {
rollback(transaction);
throw t;
} finally {
closeQuietly(transaction);
writeLock.unlock();
}
}
@Override
public NiFiUser disable(String id) {
Transaction transaction = null;
writeLock.lock();
try {
// create the connection
transaction = transactionBuilder.start();
// disable the user
DisableUserAction disableUser = new DisableUserAction(id);
NiFiUser user = transaction.execute(disableUser);
// commit the transaction
transaction.commit();
// return the user
return user;
} catch (DataAccessException | TransactionException dae) {
rollback(transaction);
throw new AdministrationException(dae);
} catch (Throwable t) {
rollback(transaction);
throw t;
} finally {
closeQuietly(transaction);
writeLock.unlock();
}
}
@Override
public NiFiUserGroup disableGroup(String group) {
Transaction transaction = null;
writeLock.lock();
try {
// create the connection
transaction = transactionBuilder.start();
// disable the user
DisableUserGroupAction disableUser = new DisableUserGroupAction(group);
NiFiUserGroup userGroup = transaction.execute(disableUser);
// commit the transaction
transaction.commit();
// return the user
return userGroup;
} catch (DataAccessException | TransactionException dae) {
rollback(transaction);
throw new AdministrationException(dae);
} catch (Throwable t) {
rollback(transaction);
throw t;
} finally {
closeQuietly(transaction);
writeLock.unlock();
}
}
@Override
public NiFiUser update(String id, Set<Authority> authorities) {
Transaction transaction = null;
// may be empty but not null
if (authorities == null) {
throw new IllegalArgumentException("The specified authorities cannot be null.");
}
writeLock.lock();
try {
// invalidate the user account in preparation for potential subsequent errors
invalidateUserAccount(id);
// at this point the current user account has been invalidated so we will
// attempt to update the account. if any part fails we are assured the
// user will be need to be given approval before they access the system at
// a later time
// start the transaction
transaction = transactionBuilder.start();
// update the user authorities
UpdateUserAction setUserAuthorities = new UpdateUserAction(id, authorities);
NiFiUser user = transaction.execute(setUserAuthorities);
// commit the transaction
transaction.commit();
// return the user
return user;
} catch (TransactionException | DataAccessException e) {
rollback(transaction);
throw new AdministrationException(e);
} catch (Throwable t) {
rollback(transaction);
throw t;
} finally {
closeQuietly(transaction);
writeLock.unlock();
}
}
/**
* Invalidates the user with the specified id. This is done to ensure a user account will need to be re-validated in case an error occurs while modifying a user account. This method should only be
* invoked from within a write lock.
*
* @param id user account identifier
*/
@Override
public void invalidateUserAccount(String id) {
Transaction transaction = null;
writeLock.lock();
try {
// start the transaction
transaction = transactionBuilder.start();
// invalidate the user account
InvalidateUserAccountAction invalidateUserAccount = new InvalidateUserAccountAction(id);
transaction.execute(invalidateUserAccount);
// commit the transaction
transaction.commit();
} catch (TransactionException | DataAccessException te) {
rollback(transaction);
throw new AdministrationException(te);
} catch (Throwable t) {
rollback(transaction);
throw t;
} finally {
closeQuietly(transaction);
writeLock.unlock();
}
}
@Override
public void invalidateUserGroupAccount(String group) {
Transaction transaction = null;
writeLock.lock();
try {
// start the transaction
transaction = transactionBuilder.start();
// invalidate the user account
InvalidateUserGroupAccountsAction invalidateUserGroupAccounts = new InvalidateUserGroupAccountsAction(group);
transaction.execute(invalidateUserGroupAccounts);
// commit the transaction
transaction.commit();
} catch (TransactionException | DataAccessException te) {
rollback(transaction);
throw new AdministrationException(te);
} catch (Throwable t) {
rollback(transaction);
throw t;
} finally {
closeQuietly(transaction);
writeLock.unlock();
}
}
// -----------------
// read only methods
// -----------------
@Override
public Boolean hasPendingUserAccount() {
Transaction transaction = null;
readLock.lock();
try {
// start the transaction
transaction = transactionBuilder.start();
final HasPendingUserAccounts hasPendingAccounts = new HasPendingUserAccounts();
final Boolean hasPendingUserAccounts = transaction.execute(hasPendingAccounts);
// commit the transaction
transaction.commit();
return hasPendingUserAccounts;
} catch (TransactionException | DataAccessException te) {
rollback(transaction);
throw new AdministrationException(te);
} catch (Throwable t) {
rollback(transaction);
throw t;
} finally {
closeQuietly(transaction);
readLock.unlock();
}
}
@Override
public DownloadAuthorization authorizeDownload(final List<String> dnChain, final Map<String, String> attributes) {
Transaction transaction = null;
readLock.lock();
try {
// start the transaction
transaction = transactionBuilder.start();
// authorize the download
AuthorizeDownloadAction authorizeDownload = new AuthorizeDownloadAction(dnChain, attributes);
DownloadAuthorization downloadAuthorization = transaction.execute(authorizeDownload);
// commit the transaction
transaction.commit();
// return the authorization
return downloadAuthorization;
} catch (TransactionException | DataAccessException te) {
rollback(transaction);
throw new AdministrationException(te);
} catch (Throwable t) {
rollback(transaction);
throw t;
} finally {
closeQuietly(transaction);
readLock.unlock();
}
}
@Override
public Collection<NiFiUser> getUsers() {
Transaction transaction = null;
readLock.lock();
try {
// start the transaction
transaction = transactionBuilder.start();
// get all users
GetUsersAction getUsers = new GetUsersAction();
Collection<NiFiUser> users = transaction.execute(getUsers);
// commit the transaction
transaction.commit();
// return the users
return users;
} catch (TransactionException | DataAccessException te) {
rollback(transaction);
throw new AdministrationException(te);
} catch (Throwable t) {
rollback(transaction);
throw t;
} finally {
closeQuietly(transaction);
readLock.unlock();
}
}
@Override
public NiFiUser getUserById(String id) {
Transaction transaction = null;
readLock.lock();
try {
// start the transaction
transaction = transactionBuilder.start();
// return the desired user
FindUserByIdAction findUserById = new FindUserByIdAction(id);
NiFiUser user = transaction.execute(findUserById);
// commit the transaction
transaction.commit();
// return the user
return user;
} catch (TransactionException | DataAccessException te) {
rollback(transaction);
throw new AdministrationException(te);
} catch (Throwable t) {
rollback(transaction);
throw t;
} finally {
closeQuietly(transaction);
readLock.unlock();
}
}
@Override
public NiFiUser getUserByDn(String dn) {
Transaction transaction = null;
readLock.lock();
try {
// start the transaction
transaction = transactionBuilder.start();
// return the desired user
FindUserByDnAction findUserByDn = new FindUserByDnAction(dn);
NiFiUser user = transaction.execute(findUserByDn);
// commit the transaction
transaction.commit();
// return the user
return user;
} catch (TransactionException | DataAccessException te) {
rollback(transaction);
throw new AdministrationException(te);
} catch (Throwable t) {
rollback(transaction);
throw t;
} finally {
closeQuietly(transaction);
readLock.unlock();
}
}
@Override
public Key getKey(int id) {
Transaction transaction = null;
Key key = null;
readLock.lock();
try {
// start the transaction
transaction = transactionBuilder.start();
// get the key
GetKeyByIdAction addActions = new GetKeyByIdAction(id);
key = transaction.execute(addActions);
// commit the transaction
transaction.commit();
} catch (TransactionException | DataAccessException te) {
rollback(transaction);
throw new AdministrationException(te);
} catch (Throwable t) {
rollback(transaction);
throw t;
} finally {
closeQuietly(transaction);
readLock.unlock();
}
return key;
}
@Override
public Key getOrCreateKey(String identity) {
Transaction transaction = null;
Key key = null;
writeLock.lock();
try {
// start the transaction
transaction = transactionBuilder.start();
// get or create a key
GetOrCreateKeyAction addActions = new GetOrCreateKeyAction(identity);
key = transaction.execute(addActions);
// commit the transaction
transaction.commit();
} catch (TransactionException | DataAccessException te) {
rollback(transaction);
throw new AdministrationException(te);
} catch (Throwable t) {
rollback(transaction);
throw t;
} finally {
closeQuietly(transaction);
writeLock.unlock();
}
return key;
}
@Override
public void deleteKey(String identity) {
Transaction transaction = null;
writeLock.lock();
try {
// start the transaction
transaction = transactionBuilder.start();
// delete the keys
DeleteKeysAction deleteKeys = new DeleteKeysAction(identity);
transaction.execute(deleteKeys);
// commit the transaction
transaction.commit();
} catch (TransactionException | DataAccessException te) {
rollback(transaction);
throw new AdministrationException(te);
} catch (Throwable t) {
rollback(transaction);
throw t;
} finally {
closeQuietly(transaction);
writeLock.unlock();
}
}
private void rollback(final Transaction transaction) {
if (transaction != null) {
transaction.rollback();
}
}
private void closeQuietly(final Transaction transaction) {
if (transaction != null) {
try {
transaction.close();
} catch (final IOException ioe) {
}
}
}
public void setTransactionBuilder(TransactionBuilder transactionBuilder) {
this.transactionBuilder = transactionBuilder;
}
public void setProperties(NiFiProperties properties) {
this.properties = properties;
}
}

View File

@ -16,19 +16,19 @@
*/ */
package org.apache.nifi.admin.service.transaction.impl; package org.apache.nifi.admin.service.transaction.impl;
import java.io.IOException;
import java.sql.Connection;
import java.sql.SQLException;
import org.apache.nifi.admin.RepositoryUtils; import org.apache.nifi.admin.RepositoryUtils;
import org.apache.nifi.admin.dao.DAOFactory; import org.apache.nifi.admin.dao.DAOFactory;
import org.apache.nifi.admin.dao.impl.DAOFactoryImpl; import org.apache.nifi.admin.dao.impl.DAOFactoryImpl;
import org.apache.nifi.admin.service.action.AdministrationAction; import org.apache.nifi.admin.service.action.AdministrationAction;
import org.apache.nifi.admin.service.transaction.TransactionException;
import org.apache.nifi.admin.service.transaction.Transaction; import org.apache.nifi.admin.service.transaction.Transaction;
import org.apache.nifi.authorization.AuthorityProvider; import org.apache.nifi.admin.service.transaction.TransactionException;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.sql.Connection;
import java.sql.SQLException;
/** /**
* Transaction implementation that uses the specified SQL Connection and * Transaction implementation that uses the specified SQL Connection and
* AuthorityProvider. * AuthorityProvider.
@ -37,11 +37,9 @@ public class StandardTransaction implements Transaction {
private static final Logger logger = LoggerFactory.getLogger(StandardTransaction.class); private static final Logger logger = LoggerFactory.getLogger(StandardTransaction.class);
private final AuthorityProvider authorityProvider;
private Connection connection; private Connection connection;
public StandardTransaction(AuthorityProvider authorityProvider, Connection connection) { public StandardTransaction(Connection connection) {
this.authorityProvider = authorityProvider;
this.connection = connection; this.connection = connection;
} }
@ -56,7 +54,7 @@ public class StandardTransaction implements Transaction {
DAOFactory daoFactory = new DAOFactoryImpl(connection); DAOFactory daoFactory = new DAOFactoryImpl(connection);
// execute the specified action // execute the specified action
return action.execute(daoFactory, authorityProvider); return action.execute(daoFactory);
} }
@Override @Override

View File

@ -22,7 +22,6 @@ import javax.sql.DataSource;
import org.apache.nifi.admin.service.transaction.Transaction; import org.apache.nifi.admin.service.transaction.Transaction;
import org.apache.nifi.admin.service.transaction.TransactionBuilder; import org.apache.nifi.admin.service.transaction.TransactionBuilder;
import org.apache.nifi.admin.service.transaction.TransactionException; import org.apache.nifi.admin.service.transaction.TransactionException;
import org.apache.nifi.authorization.AuthorityProvider;
/** /**
* *
@ -30,7 +29,6 @@ import org.apache.nifi.authorization.AuthorityProvider;
public class StandardTransactionBuilder implements TransactionBuilder { public class StandardTransactionBuilder implements TransactionBuilder {
private DataSource dataSource; private DataSource dataSource;
private AuthorityProvider authorityProvider;
@Override @Override
public Transaction start() throws TransactionException { public Transaction start() throws TransactionException {
@ -40,7 +38,7 @@ public class StandardTransactionBuilder implements TransactionBuilder {
connection.setAutoCommit(false); connection.setAutoCommit(false);
// create a new transaction // create a new transaction
return new StandardTransaction(authorityProvider, connection); return new StandardTransaction(connection);
} catch (SQLException sqle) { } catch (SQLException sqle) {
throw new TransactionException(sqle.getMessage()); throw new TransactionException(sqle.getMessage());
} }
@ -50,8 +48,4 @@ public class StandardTransactionBuilder implements TransactionBuilder {
public void setDataSource(DataSource dataSource) { public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource; this.dataSource = dataSource;
} }
public void setAuthorityProvider(AuthorityProvider authorityProvider) {
this.authorityProvider = authorityProvider;
}
} }

View File

@ -1,491 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.authorization;
import org.apache.commons.lang3.StringUtils;
import org.apache.nifi.authorization.annotation.AuthorityProviderContext;
import org.apache.nifi.authorization.exception.AuthorityAccessException;
import org.apache.nifi.authorization.exception.IdentityAlreadyExistsException;
import org.apache.nifi.authorization.exception.ProviderCreationException;
import org.apache.nifi.authorization.exception.ProviderDestructionException;
import org.apache.nifi.authorization.exception.UnknownIdentityException;
import org.apache.nifi.authorization.generated.AuthorityProviderProperty;
import org.apache.nifi.authorization.generated.AuthorityProviders;
import org.apache.nifi.authorization.generated.Provider;
import org.apache.nifi.nar.ExtensionManager;
import org.apache.nifi.nar.NarCloseable;
import org.apache.nifi.util.NiFiProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.xml.sax.SAXException;
import javax.xml.XMLConstants;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Factory bean for loading the configured authority provider.
*/
public class AuthorityProviderFactoryBean implements FactoryBean, ApplicationContextAware, DisposableBean, AuthorityProviderLookup {
private static final Logger logger = LoggerFactory.getLogger(AuthorityProviderFactoryBean.class);
private static final String AUTHORITY_PROVIDERS_XSD = "/authority-providers.xsd";
private static final String JAXB_GENERATED_PATH = "org.apache.nifi.authorization.generated";
private static final JAXBContext JAXB_CONTEXT = initializeJaxbContext();
/**
* Load the JAXBContext.
*/
private static JAXBContext initializeJaxbContext() {
try {
return JAXBContext.newInstance(JAXB_GENERATED_PATH, AuthorityProviderFactoryBean.class.getClassLoader());
} catch (JAXBException e) {
throw new RuntimeException("Unable to create JAXBContext.");
}
}
private ApplicationContext applicationContext;
private AuthorityProvider authorityProvider;
private NiFiProperties properties;
private final Map<String, AuthorityProvider> authorityProviders = new HashMap<>();
@Override
public AuthorityProvider getAuthorityProvider(String identifier) {
return authorityProviders.get(identifier);
}
@Override
public Object getObject() throws Exception {
if (authorityProvider == null) {
// look up the authority provider to use
final String authorityProviderIdentifier = properties.getProperty(NiFiProperties.SECURITY_USER_AUTHORITY_PROVIDER);
// ensure the authority provider class name was specified
if (StringUtils.isBlank(authorityProviderIdentifier)) {
// if configured for ssl, the authority provider must be specified
if (properties.getSslPort() != null) {
throw new Exception("When running securely, the authority provider identifier must be specified in the nifi properties file.");
}
// use a default provider... only allowable when running not securely
authorityProvider = createDefaultProvider();
} else {
final AuthorityProviders authorityProviderConfiguration = loadAuthorityProvidersConfiguration();
// create each authority provider
for (final Provider provider : authorityProviderConfiguration.getProvider()) {
authorityProviders.put(provider.getIdentifier(), createAuthorityProvider(provider.getIdentifier(), provider.getClazz()));
}
// configure each authority provider
for (final Provider provider : authorityProviderConfiguration.getProvider()) {
final AuthorityProvider instance = authorityProviders.get(provider.getIdentifier());
instance.onConfigured(loadAuthorityProviderConfiguration(provider));
}
// get the authority provider instance
authorityProvider = getAuthorityProvider(authorityProviderIdentifier);
// ensure it was found
if (authorityProvider == null) {
throw new Exception(String.format("The specified authority provider '%s' could not be found.", authorityProviderIdentifier));
}
}
}
return authorityProvider;
}
private AuthorityProviders loadAuthorityProvidersConfiguration() throws Exception {
final File authorityProvidersConfigurationFile = properties.getAuthorityProviderConfiguraitonFile();
// load the users from the specified file
if (authorityProvidersConfigurationFile.exists()) {
try {
// find the schema
final SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
final Schema schema = schemaFactory.newSchema(AuthorityProviders.class.getResource(AUTHORITY_PROVIDERS_XSD));
// attempt to unmarshal
final Unmarshaller unmarshaller = JAXB_CONTEXT.createUnmarshaller();
unmarshaller.setSchema(schema);
final JAXBElement<AuthorityProviders> element = unmarshaller.unmarshal(new StreamSource(authorityProvidersConfigurationFile), AuthorityProviders.class);
return element.getValue();
} catch (SAXException | JAXBException e) {
throw new Exception("Unable to load the authority provider configuration file at: " + authorityProvidersConfigurationFile.getAbsolutePath());
}
} else {
throw new Exception("Unable to find the authority provider configuration file at " + authorityProvidersConfigurationFile.getAbsolutePath());
}
}
private AuthorityProvider createAuthorityProvider(final String identifier, final String authorityProviderClassName) throws Exception {
// get the classloader for the specified authority provider
final ClassLoader authorityProviderClassLoader = ExtensionManager.getClassLoader(authorityProviderClassName);
if (authorityProviderClassLoader == null) {
throw new Exception(String.format("The specified authority provider class '%s' is not known to this nifi.", authorityProviderClassName));
}
// get the current context classloader
final ClassLoader currentClassLoader = Thread.currentThread().getContextClassLoader();
final AuthorityProvider instance;
try {
// set the appropriate class loader
Thread.currentThread().setContextClassLoader(authorityProviderClassLoader);
// attempt to load the class
Class<?> rawAuthorityProviderClass = Class.forName(authorityProviderClassName, true, authorityProviderClassLoader);
Class<? extends AuthorityProvider> authorityProviderClass = rawAuthorityProviderClass.asSubclass(AuthorityProvider.class);
// otherwise create a new instance
Constructor constructor = authorityProviderClass.getConstructor();
instance = (AuthorityProvider) constructor.newInstance();
// method injection
performMethodInjection(instance, authorityProviderClass);
// field injection
performFieldInjection(instance, authorityProviderClass);
// call post construction lifecycle event
instance.initialize(new StandardAuthorityProviderInitializationContext(identifier, this));
} finally {
if (currentClassLoader != null) {
Thread.currentThread().setContextClassLoader(currentClassLoader);
}
}
return withNarLoader(instance);
}
private AuthorityProviderConfigurationContext loadAuthorityProviderConfiguration(final Provider provider) {
final Map<String, String> providerProperties = new HashMap<>();
for (final AuthorityProviderProperty property : provider.getProperty()) {
providerProperties.put(property.getName(), property.getValue());
}
return new StandardAuthorityProviderConfigurationContext(provider.getIdentifier(), providerProperties);
}
private void performMethodInjection(final AuthorityProvider instance, final Class authorityProviderClass) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
for (final Method method : authorityProviderClass.getMethods()) {
if (method.isAnnotationPresent(AuthorityProviderContext.class)) {
// make the method accessible
final boolean isAccessible = method.isAccessible();
method.setAccessible(true);
try {
final Class<?>[] argumentTypes = method.getParameterTypes();
// look for setters (single argument)
if (argumentTypes.length == 1) {
final Class<?> argumentType = argumentTypes[0];
// look for well known types
if (NiFiProperties.class.isAssignableFrom(argumentType)) {
// nifi properties injection
method.invoke(instance, properties);
} else if (ApplicationContext.class.isAssignableFrom(argumentType)) {
// spring application context injection
method.invoke(instance, applicationContext);
}
}
} finally {
method.setAccessible(isAccessible);
}
}
}
final Class parentClass = authorityProviderClass.getSuperclass();
if (parentClass != null && AuthorityProvider.class.isAssignableFrom(parentClass)) {
performMethodInjection(instance, parentClass);
}
}
private void performFieldInjection(final AuthorityProvider instance, final Class authorityProviderClass) throws IllegalArgumentException, IllegalAccessException {
for (final Field field : authorityProviderClass.getDeclaredFields()) {
if (field.isAnnotationPresent(AuthorityProviderContext.class)) {
// make the method accessible
final boolean isAccessible = field.isAccessible();
field.setAccessible(true);
try {
// get the type
final Class<?> fieldType = field.getType();
// only consider this field if it isn't set yet
if (field.get(instance) == null) {
// look for well known types
if (NiFiProperties.class.isAssignableFrom(fieldType)) {
// nifi properties injection
field.set(instance, properties);
} else if (ApplicationContext.class.isAssignableFrom(fieldType)) {
// spring application context injection
field.set(instance, applicationContext);
}
}
} finally {
field.setAccessible(isAccessible);
}
}
}
final Class parentClass = authorityProviderClass.getSuperclass();
if (parentClass != null && AuthorityProvider.class.isAssignableFrom(parentClass)) {
performFieldInjection(instance, parentClass);
}
}
/**
* @return a default provider to use when running unsecurely with no
* provider configured
*/
private AuthorityProvider createDefaultProvider() {
return new AuthorityProvider() {
@Override
public boolean doesDnExist(String dn) throws AuthorityAccessException {
return false;
}
@Override
public Set<Authority> getAuthorities(String dn) throws UnknownIdentityException, AuthorityAccessException {
return EnumSet.noneOf(Authority.class);
}
@Override
public void setAuthorities(String dn, Set<Authority> authorities) throws UnknownIdentityException, AuthorityAccessException {
}
@Override
public Set<String> getUsers(Authority authority) throws AuthorityAccessException {
return new HashSet<>();
}
@Override
public void revokeUser(String dn) throws UnknownIdentityException, AuthorityAccessException {
}
@Override
public void addUser(String dn, String group) throws IdentityAlreadyExistsException, AuthorityAccessException {
}
@Override
public String getGroupForUser(String dn) throws UnknownIdentityException, AuthorityAccessException {
return null;
}
@Override
public void revokeGroup(String group) throws UnknownIdentityException, AuthorityAccessException {
}
@Override
public void setUsersGroup(Set<String> dn, String group) throws UnknownIdentityException, AuthorityAccessException {
}
@Override
public void ungroupUser(String dn) throws UnknownIdentityException, AuthorityAccessException {
}
@Override
public void ungroup(String group) throws AuthorityAccessException {
}
@Override
public DownloadAuthorization authorizeDownload(List<String> dnChain, Map<String, String> attributes) throws UnknownIdentityException, AuthorityAccessException {
return DownloadAuthorization.approved();
}
@Override
public void initialize(AuthorityProviderInitializationContext initializationContext) throws ProviderCreationException {
}
@Override
public void onConfigured(AuthorityProviderConfigurationContext configurationContext) throws ProviderCreationException {
}
@Override
public void preDestruction() throws ProviderDestructionException {
}
};
}
/**
* Decorates the base provider to ensure the nar context classloader is used
* when invoking the underlying methods.
*
* @param baseProvider base provider
* @return provider
*/
public AuthorityProvider withNarLoader(final AuthorityProvider baseProvider) {
return new AuthorityProvider() {
@Override
public boolean doesDnExist(String dn) throws AuthorityAccessException {
try (final NarCloseable narCloseable = NarCloseable.withNarLoader()) {
return baseProvider.doesDnExist(dn);
}
}
@Override
public Set<Authority> getAuthorities(String dn) throws UnknownIdentityException, AuthorityAccessException {
try (final NarCloseable narCloseable = NarCloseable.withNarLoader()) {
return baseProvider.getAuthorities(dn);
}
}
@Override
public void setAuthorities(String dn, Set<Authority> authorities) throws UnknownIdentityException, AuthorityAccessException {
try (final NarCloseable narCloseable = NarCloseable.withNarLoader()) {
baseProvider.setAuthorities(dn, authorities);
}
}
@Override
public Set<String> getUsers(Authority authority) throws AuthorityAccessException {
try (final NarCloseable narCloseable = NarCloseable.withNarLoader()) {
return baseProvider.getUsers(authority);
}
}
@Override
public void revokeUser(String dn) throws UnknownIdentityException, AuthorityAccessException {
try (final NarCloseable narCloseable = NarCloseable.withNarLoader()) {
baseProvider.revokeUser(dn);
}
}
@Override
public void addUser(String dn, String group) throws IdentityAlreadyExistsException, AuthorityAccessException {
try (final NarCloseable narCloseable = NarCloseable.withNarLoader()) {
baseProvider.addUser(dn, group);
}
}
@Override
public String getGroupForUser(String dn) throws UnknownIdentityException, AuthorityAccessException {
try (final NarCloseable narCloseable = NarCloseable.withNarLoader()) {
return baseProvider.getGroupForUser(dn);
}
}
@Override
public void revokeGroup(String group) throws UnknownIdentityException, AuthorityAccessException {
try (final NarCloseable narCloseable = NarCloseable.withNarLoader()) {
baseProvider.revokeGroup(group);
}
}
@Override
public void setUsersGroup(Set<String> dns, String group) throws UnknownIdentityException, AuthorityAccessException {
try (final NarCloseable narCloseable = NarCloseable.withNarLoader()) {
baseProvider.setUsersGroup(dns, group);
}
}
@Override
public void ungroupUser(String dn) throws UnknownIdentityException, AuthorityAccessException {
try (final NarCloseable narCloseable = NarCloseable.withNarLoader()) {
baseProvider.ungroupUser(dn);
}
}
@Override
public void ungroup(String group) throws AuthorityAccessException {
try (final NarCloseable narCloseable = NarCloseable.withNarLoader()) {
baseProvider.ungroup(group);
}
}
@Override
public DownloadAuthorization authorizeDownload(List<String> dnChain, Map<String, String> attributes) throws UnknownIdentityException, AuthorityAccessException {
try (final NarCloseable narCloseable = NarCloseable.withNarLoader()) {
return baseProvider.authorizeDownload(dnChain, attributes);
}
}
@Override
public void initialize(AuthorityProviderInitializationContext initializationContext) throws ProviderCreationException {
try (final NarCloseable narCloseable = NarCloseable.withNarLoader()) {
baseProvider.initialize(initializationContext);
}
}
@Override
public void onConfigured(AuthorityProviderConfigurationContext configurationContext) throws ProviderCreationException {
try (final NarCloseable narCloseable = NarCloseable.withNarLoader()) {
baseProvider.onConfigured(configurationContext);
}
}
@Override
public void preDestruction() throws ProviderDestructionException {
try (final NarCloseable narCloseable = NarCloseable.withNarLoader()) {
baseProvider.preDestruction();
}
}
};
}
@Override
public Class getObjectType() {
return AuthorityProvider.class;
}
@Override
public boolean isSingleton() {
return true;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
@Override
public void destroy() throws Exception {
if (authorityProvider != null) {
authorityProvider.preDestruction();
}
}
public void setProperties(NiFiProperties properties) {
this.properties = properties;
}
}

View File

@ -21,7 +21,6 @@ import org.apache.nifi.authorization.annotation.AuthorizerContext;
import org.apache.nifi.authorization.exception.AuthorizationAccessException; import org.apache.nifi.authorization.exception.AuthorizationAccessException;
import org.apache.nifi.authorization.exception.AuthorizerCreationException; import org.apache.nifi.authorization.exception.AuthorizerCreationException;
import org.apache.nifi.authorization.exception.AuthorizerDestructionException; import org.apache.nifi.authorization.exception.AuthorizerDestructionException;
import org.apache.nifi.authorization.generated.AuthorityProviders;
import org.apache.nifi.authorization.generated.Authorizers; import org.apache.nifi.authorization.generated.Authorizers;
import org.apache.nifi.authorization.generated.Property; import org.apache.nifi.authorization.generated.Property;
import org.apache.nifi.nar.ExtensionManager; import org.apache.nifi.nar.ExtensionManager;
@ -83,7 +82,7 @@ public class AuthorizerFactoryBean implements FactoryBean, DisposableBean, Autho
public Object getObject() throws Exception { public Object getObject() throws Exception {
if (authorizer == null) { if (authorizer == null) {
// look up the authorizer to use // look up the authorizer to use
final String authorizerIdentifier = properties.getProperty(NiFiProperties.SECURITY_USER_AUTHORITY_PROVIDER); final String authorizerIdentifier = properties.getProperty(NiFiProperties.SECURITY_USER_AUTHORIZER);
// ensure the authorizer class name was specified // ensure the authorizer class name was specified
if (StringUtils.isBlank(authorizerIdentifier)) { if (StringUtils.isBlank(authorizerIdentifier)) {
@ -122,14 +121,14 @@ public class AuthorizerFactoryBean implements FactoryBean, DisposableBean, Autho
} }
private Authorizers loadAuthorizersConfiguration() throws Exception { private Authorizers loadAuthorizersConfiguration() throws Exception {
final File authorizersConfigurationFile = properties.getAuthorityProviderConfiguraitonFile(); final File authorizersConfigurationFile = properties.getAuthorizerConfiguraitonFile();
// load the authorizers from the specified file // load the authorizers from the specified file
if (authorizersConfigurationFile.exists()) { if (authorizersConfigurationFile.exists()) {
try { try {
// find the schema // find the schema
final SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); final SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
final Schema schema = schemaFactory.newSchema(AuthorityProviders.class.getResource(AUTHORIZERS_XSD)); final Schema schema = schemaFactory.newSchema(Authorizers.class.getResource(AUTHORIZERS_XSD));
// attempt to unmarshal // attempt to unmarshal
final Unmarshaller unmarshaller = JAXB_CONTEXT.createUnmarshaller(); final Unmarshaller unmarshaller = JAXB_CONTEXT.createUnmarshaller();
@ -221,7 +220,7 @@ public class AuthorizerFactoryBean implements FactoryBean, DisposableBean, Autho
} }
final Class parentClass = authorizerClass.getSuperclass(); final Class parentClass = authorizerClass.getSuperclass();
if (parentClass != null && AuthorityProvider.class.isAssignableFrom(parentClass)) { if (parentClass != null && Authorizer.class.isAssignableFrom(parentClass)) {
performMethodInjection(instance, parentClass); performMethodInjection(instance, parentClass);
} }
} }
@ -253,7 +252,7 @@ public class AuthorizerFactoryBean implements FactoryBean, DisposableBean, Autho
} }
final Class parentClass = authorizerClass.getSuperclass(); final Class parentClass = authorizerClass.getSuperclass();
if (parentClass != null && AuthorityProvider.class.isAssignableFrom(parentClass)) { if (parentClass != null && Authorizer.class.isAssignableFrom(parentClass)) {
performFieldInjection(instance, parentClass); performFieldInjection(instance, parentClass);
} }
} }

View File

@ -1,51 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.authorization;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
/**
*
*/
public class StandardAuthorityProviderConfigurationContext implements AuthorityProviderConfigurationContext {
private final String identifier;
private final Map<String, String> properties;
public StandardAuthorityProviderConfigurationContext(String identifier, Map<String, String> properties) {
this.identifier = identifier;
this.properties = Collections.unmodifiableMap(new HashMap<String, String>(properties));
}
@Override
public String getIdentifier() {
return identifier;
}
@Override
public Map<String, String> getProperties() {
return properties;
}
@Override
public String getProperty(String property) {
return properties.get(property);
}
}

View File

@ -1,42 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.authorization;
/**
*
*/
public class StandardAuthorityProviderInitializationContext implements AuthorityProviderInitializationContext {
private final String identifier;
private final AuthorityProviderLookup authorityProviderLookup;
public StandardAuthorityProviderInitializationContext(String identifier, AuthorityProviderLookup authorityProviderLookup) {
this.identifier = identifier;
this.authorityProviderLookup = authorityProviderLookup;
}
@Override
public String getIdentifier() {
return identifier;
}
@Override
public AuthorityProviderLookup getAuthorityProviderLookup() {
return authorityProviderLookup;
}
}

View File

@ -1,47 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.user;
/**
* Represents the status of a user's account.
*/
public enum AccountStatus {
ACTIVE,
PENDING,
DISABLED;
/**
* Returns the matching status or null if the specified status does not
* match any statuses.
*
* @param rawStatus string form of status
* @return account status object
*/
public static AccountStatus valueOfStatus(String rawStatus) {
AccountStatus desiredStatus = null;
for (AccountStatus status : values()) {
if (status.toString().equals(rawStatus)) {
desiredStatus = status;
break;
}
}
return desiredStatus;
}
}

View File

@ -17,121 +17,54 @@
package org.apache.nifi.user; package org.apache.nifi.user;
import java.io.Serializable; import java.io.Serializable;
import java.util.Date;
import java.util.EnumSet;
import java.util.Objects; import java.util.Objects;
import java.util.Set;
import org.apache.nifi.authorization.Authority;
import org.apache.commons.lang3.StringUtils;
/** /**
* An NiFiUser. * An NiFiUser.
*/ */
public class NiFiUser implements Serializable { public class NiFiUser implements Serializable {
public static final String ANONYMOUS_USER_IDENTITY = "anonymous"; public static final NiFiUser ANONYMOUS = new NiFiUser("anonymous");
private String id;
private String identity; private String identity;
private String userName; private String userName;
private String userGroup;
private String justification;
private Date creation;
private Date lastVerified;
private Date lastAccessed;
private AccountStatus status;
private EnumSet<Authority> authorities;
private NiFiUser chain; private NiFiUser chain;
/* getters / setters */ public NiFiUser(String identity) {
public Date getCreation() { this(identity, identity, null);
return creation;
} }
public void setCreation(Date creation) { public NiFiUser(String identity, String userName) {
this.creation = creation; this(identity, userName, null);
} }
public NiFiUser(String identity, NiFiUser chain) {
this(identity, identity, chain);
}
public NiFiUser(String identity, String userName, NiFiUser chain) {
this.identity = identity;
this.userName = userName;
this.chain = chain;
}
/* getters / setters */
public String getIdentity() { public String getIdentity() {
return identity; return identity;
} }
public void setIdentity(String identity) {
this.identity = identity;
}
public String getUserName() { public String getUserName() {
return userName; return userName;
} }
public void setUserName(String userName) {
this.userName = userName;
}
public String getUserGroup() {
return userGroup;
}
public void setUserGroup(String userGroup) {
this.userGroup = userGroup;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getJustification() {
return justification;
}
public void setJustification(String justification) {
this.justification = justification;
}
public AccountStatus getStatus() {
return status;
}
public void setStatus(AccountStatus status) {
this.status = status;
}
public Date getLastVerified() {
return lastVerified;
}
public void setLastVerified(Date lastVerified) {
this.lastVerified = lastVerified;
}
public Date getLastAccessed() {
return lastAccessed;
}
public void setLastAccessed(Date lastAccessed) {
this.lastAccessed = lastAccessed;
}
public NiFiUser getChain() { public NiFiUser getChain() {
return chain; return chain;
} }
public void setChain(NiFiUser chain) { public boolean isAnonymous() {
this.chain = chain; return this == ANONYMOUS;
}
public Set<Authority> getAuthorities() {
if (authorities == null) {
authorities = EnumSet.noneOf(Authority.class);
}
return authorities;
} }
@Override @Override
@ -158,7 +91,7 @@ public class NiFiUser implements Serializable {
@Override @Override
public String toString() { public String toString() {
return String.format("identity[%s], userName[%s], justification[%s], authorities[%s]", getIdentity(), getUserName(), getJustification(), StringUtils.join(getAuthorities(), ", ")); return String.format("identity[%s], userName[%s]", getIdentity(), getUserName(), ", ");
} }
} }

View File

@ -18,41 +18,34 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd"> xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
<!-- user authority provider -->
<bean id="authorityProvider" class="org.apache.nifi.authorization.AuthorityProviderFactoryBean" depends-on="clusterManager">
<property name="properties" ref="nifiProperties"/>
</bean>
<!-- user/entity authorizer --> <!-- user/entity authorizer -->
<bean id="authorizer" class="org.apache.nifi.authorization.AuthorizerFactoryBean" depends-on="clusterManager"> <bean id="authorizer" class="org.apache.nifi.authorization.AuthorizerFactoryBean">
<property name="properties" ref="nifiProperties"/> <property name="properties" ref="nifiProperties"/>
</bean> </bean>
<!-- initialize the user data source --> <!-- initialize the user key data source -->
<bean id="userDataSource" class="org.apache.nifi.admin.UserDataSourceFactoryBean" destroy-method="shutdown"> <bean id="keyDataSource" class="org.apache.nifi.admin.KeyDataSourceFactoryBean" destroy-method="shutdown">
<property name="properties" ref="nifiProperties"/> <property name="properties" ref="nifiProperties"/>
</bean> </bean>
<!-- initialize the data source --> <!-- initialize the audit data source -->
<bean id="auditDataSource" class="org.apache.nifi.admin.AuditDataSourceFactoryBean" destroy-method="shutdown" depends-on="userDataSource"> <bean id="auditDataSource" class="org.apache.nifi.admin.AuditDataSourceFactoryBean" destroy-method="shutdown">
<property name="properties" ref="nifiProperties"/> <property name="properties" ref="nifiProperties"/>
</bean> </bean>
<!-- initialize the user transaction builder --> <!-- initialize the user key transaction builder -->
<bean id="userTransactionBuilder" class="org.apache.nifi.admin.service.transaction.impl.StandardTransactionBuilder"> <bean id="keyTransactionBuilder" class="org.apache.nifi.admin.service.transaction.impl.StandardTransactionBuilder">
<property name="authorityProvider" ref="authorityProvider"/> <property name="dataSource" ref="keyDataSource"/>
<property name="dataSource" ref="userDataSource"/>
</bean> </bean>
<!-- initialize the audit transaction builder --> <!-- initialize the audit transaction builder -->
<bean id="auditTransactionBuilder" class="org.apache.nifi.admin.service.transaction.impl.StandardTransactionBuilder"> <bean id="auditTransactionBuilder" class="org.apache.nifi.admin.service.transaction.impl.StandardTransactionBuilder">
<property name="authorityProvider" ref="authorityProvider"/>
<property name="dataSource" ref="auditDataSource"/> <property name="dataSource" ref="auditDataSource"/>
</bean> </bean>
<!-- administration service --> <!-- administration service -->
<bean id="userService" class="org.apache.nifi.admin.service.impl.StandardUserService" init-method="seedUserAccounts"> <bean id="keyService" class="org.apache.nifi.admin.service.impl.StandardKeyService">
<property name="transactionBuilder" ref="userTransactionBuilder"/> <property name="transactionBuilder" ref="keyTransactionBuilder"/>
<property name="properties" ref="nifiProperties"/> <property name="properties" ref="nifiProperties"/>
</bean> </bean>

View File

@ -1,49 +0,0 @@
<?xml version="1.0"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- role -->
<xs:complexType name="Provider">
<xs:sequence>
<xs:element name="identifier" type="AuthorityProviderNonEmptyStringType"/>
<xs:element name="class" type="AuthorityProviderNonEmptyStringType"/>
<xs:element name="property" type="AuthorityProviderProperty" minOccurs="0" maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
<!-- Name/Value properties-->
<xs:complexType name="AuthorityProviderProperty">
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="name" type="AuthorityProviderNonEmptyStringType"></xs:attribute>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
<xs:simpleType name="AuthorityProviderNonEmptyStringType">
<xs:restriction base="xs:string">
<xs:minLength value="1"/>
</xs:restriction>
</xs:simpleType>
<!-- users -->
<xs:element name="authorityProviders">
<xs:complexType>
<xs:sequence>
<xs:element name="provider" type="Provider" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>

View File

@ -1,433 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.admin.service.action;
import java.util.Date;
import java.util.EnumSet;
import java.util.Set;
import org.apache.nifi.admin.dao.AuthorityDAO;
import org.apache.nifi.admin.dao.DAOFactory;
import org.apache.nifi.admin.dao.DataAccessException;
import org.apache.nifi.admin.dao.UserDAO;
import org.apache.nifi.admin.service.AccountDisabledException;
import org.apache.nifi.admin.service.AccountNotFoundException;
import org.apache.nifi.admin.service.AccountPendingException;
import org.apache.nifi.admin.service.AdministrationException;
import org.apache.nifi.authorization.Authority;
import org.apache.nifi.authorization.AuthorityProvider;
import org.apache.nifi.authorization.exception.AuthorityAccessException;
import org.apache.nifi.authorization.exception.UnknownIdentityException;
import org.apache.nifi.user.AccountStatus;
import org.apache.nifi.user.NiFiUser;
import org.apache.commons.lang3.StringUtils;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
/**
*
*/
public class AuthorizeUserActionTest {
private static final String USER_ID_6 = "6";
private static final String USER_ID_7 = "7";
private static final String USER_ID_8 = "8";
private static final String USER_ID_9 = "9";
private static final String USER_ID_10 = "10";
private static final String USER_ID_11 = "11";
private static final String USER_IDENTITY_1 = "authority access exception while searching for user";
private static final String USER_IDENTITY_2 = "unknown user";
private static final String USER_IDENTITY_3 = "user removed after checking existence";
private static final String USER_IDENTITY_4 = "access exception getting authorities";
private static final String USER_IDENTITY_5 = "error creating user account";
private static final String USER_IDENTITY_6 = "create user general sequence";
private static final String USER_IDENTITY_7 = "existing user requires verification";
private static final String USER_IDENTITY_8 = "existing user does not require verification";
private static final String USER_IDENTITY_9 = "existing pending user";
private static final String USER_IDENTITY_10 = "existing disabled user";
private static final String USER_IDENTITY_11 = "existing user is now unknown in the authority provider";
private DAOFactory daoFactory;
private UserDAO userDao;
private AuthorityDAO authorityDao;
private AuthorityProvider authorityProvider;
@Before
public void setup() throws Exception {
// mock the user dao
userDao = Mockito.mock(UserDAO.class);
Mockito.doAnswer(new Answer<NiFiUser>() {
@Override
public NiFiUser answer(InvocationOnMock invocation) throws Throwable {
Object[] args = invocation.getArguments();
String id = (String) args[0];
NiFiUser user = null;
if (USER_ID_7.equals(id)) {
user = new NiFiUser();
user.setId(USER_ID_7);
user.setIdentity(USER_IDENTITY_7);
user.getAuthorities().addAll(EnumSet.of(Authority.ROLE_MONITOR));
} else if (USER_ID_8.equals(id)) {
user = new NiFiUser();
user.setId(USER_ID_8);
user.setIdentity(USER_IDENTITY_8);
user.getAuthorities().addAll(EnumSet.of(Authority.ROLE_MONITOR));
user.setLastVerified(new Date());
} else if (USER_ID_11.equals(id)) {
user = new NiFiUser();
user.setId(USER_ID_11);
user.setIdentity(USER_IDENTITY_11);
user.getAuthorities().addAll(EnumSet.of(Authority.ROLE_MONITOR));
user.setStatus(AccountStatus.ACTIVE);
}
return user;
}
}).when(userDao).findUserById(Mockito.anyString());
Mockito.doAnswer(new Answer<NiFiUser>() {
@Override
public NiFiUser answer(InvocationOnMock invocation) throws Throwable {
Object[] args = invocation.getArguments();
String dn = (String) args[0];
NiFiUser user = null;
switch (dn) {
case USER_IDENTITY_7:
user = new NiFiUser();
user.setId(USER_ID_7);
user.setIdentity(USER_IDENTITY_7);
user.getAuthorities().addAll(EnumSet.of(Authority.ROLE_MONITOR));
break;
case USER_IDENTITY_8:
user = new NiFiUser();
user.setId(USER_ID_8);
user.setIdentity(USER_IDENTITY_8);
user.getAuthorities().addAll(EnumSet.of(Authority.ROLE_MONITOR));
user.setLastVerified(new Date());
break;
case USER_IDENTITY_9:
user = new NiFiUser();
user.setId(USER_ID_9);
user.setIdentity(USER_IDENTITY_9);
user.setStatus(AccountStatus.PENDING);
break;
case USER_IDENTITY_10:
user = new NiFiUser();
user.setId(USER_ID_10);
user.setIdentity(USER_IDENTITY_10);
user.setStatus(AccountStatus.DISABLED);
break;
case USER_IDENTITY_11:
user = new NiFiUser();
user.setId(USER_ID_11);
user.setIdentity(USER_IDENTITY_11);
user.getAuthorities().addAll(EnumSet.of(Authority.ROLE_MONITOR));
user.setStatus(AccountStatus.ACTIVE);
break;
}
return user;
}
}).when(userDao).findUserByDn(Mockito.anyString());
Mockito.doAnswer(new Answer<Void>() {
@Override
public Void answer(InvocationOnMock invocation) throws Throwable {
Object[] args = invocation.getArguments();
NiFiUser user = (NiFiUser) args[0];
switch (user.getIdentity()) {
case USER_IDENTITY_5:
throw new DataAccessException();
case USER_IDENTITY_6:
user.setId(USER_ID_6);
break;
}
// do nothing
return null;
}
}).when(userDao).createUser(Mockito.any(NiFiUser.class));
Mockito.doAnswer(new Answer<Void>() {
@Override
public Void answer(InvocationOnMock invocation) throws Throwable {
Object[] args = invocation.getArguments();
NiFiUser user = (NiFiUser) args[0];
// do nothing
return null;
}
}).when(userDao).updateUser(Mockito.any(NiFiUser.class));
// mock the authority dao
authorityDao = Mockito.mock(AuthorityDAO.class);
Mockito.doAnswer(new Answer<Void>() {
@Override
public Void answer(InvocationOnMock invocation) throws Throwable {
Object[] args = invocation.getArguments();
Set<Authority> authorities = (Set<Authority>) args[0];
String id = (String) args[1];
// do nothing
return null;
}
}).when(authorityDao).createAuthorities(Mockito.anySetOf(Authority.class), Mockito.anyString());
Mockito.doAnswer(new Answer<Void>() {
@Override
public Void answer(InvocationOnMock invocation) throws Throwable {
Object[] args = invocation.getArguments();
Set<Authority> authorities = (Set<Authority>) args[0];
String id = (String) args[1];
// do nothing
return null;
}
}).when(authorityDao).deleteAuthorities(Mockito.anySetOf(Authority.class), Mockito.anyString());
// mock the dao factory
daoFactory = Mockito.mock(DAOFactory.class);
Mockito.when(daoFactory.getUserDAO()).thenReturn(userDao);
Mockito.when(daoFactory.getAuthorityDAO()).thenReturn(authorityDao);
// mock the authority provider
authorityProvider = Mockito.mock(AuthorityProvider.class);
Mockito.doAnswer(new Answer<Boolean>() {
@Override
public Boolean answer(InvocationOnMock invocation) throws Throwable {
Object[] args = invocation.getArguments();
String dn = (String) args[0];
switch (dn) {
case USER_IDENTITY_1:
throw new AuthorityAccessException(StringUtils.EMPTY);
case USER_IDENTITY_2:
return false;
}
return true;
}
}).when(authorityProvider).doesDnExist(Mockito.anyString());
Mockito.doAnswer(new Answer<Set<Authority>>() {
@Override
public Set<Authority> answer(InvocationOnMock invocation) throws Throwable {
Object[] args = invocation.getArguments();
String dn = (String) args[0];
Set<Authority> authorities = EnumSet.noneOf(Authority.class);
switch (dn) {
case USER_IDENTITY_3:
throw new UnknownIdentityException(StringUtils.EMPTY);
case USER_IDENTITY_4:
throw new AuthorityAccessException(StringUtils.EMPTY);
case USER_IDENTITY_6:
authorities.add(Authority.ROLE_MONITOR);
break;
case USER_IDENTITY_7:
authorities.add(Authority.ROLE_DFM);
break;
case USER_IDENTITY_9:
throw new UnknownIdentityException(StringUtils.EMPTY);
case USER_IDENTITY_10:
throw new UnknownIdentityException(StringUtils.EMPTY);
case USER_IDENTITY_11:
throw new UnknownIdentityException(StringUtils.EMPTY);
}
return authorities;
}
}).when(authorityProvider).getAuthorities(Mockito.anyString());
Mockito.doAnswer(new Answer<Void>() {
@Override
public Void answer(InvocationOnMock invocation) throws Throwable {
Object[] args = invocation.getArguments();
String dn = (String) args[0];
Set<Authority> authorites = (Set<Authority>) args[1];
// do nothing
return null;
}
}).when(authorityProvider).setAuthorities(Mockito.anyString(), Mockito.anySet());
}
/**
* Tests AuthorityAccessException in doesDnExist.
*
* @throws Exception ex
*/
@Test(expected = AdministrationException.class)
public void testAuthorityAccessExceptionInDoesDnExist() throws Exception {
AuthorizeUserAction authorizeUser = new AuthorizeUserAction(USER_IDENTITY_1, 0);
authorizeUser.execute(daoFactory, authorityProvider);
}
/**
* Test unknown user in the authority provider.
*
* @throws Exception ex
*/
@Test(expected = AccountNotFoundException.class)
public void testUnknownUser() throws Exception {
AuthorizeUserAction authorizeUser = new AuthorizeUserAction(USER_IDENTITY_2, 0);
authorizeUser.execute(daoFactory, authorityProvider);
}
/**
* Test a user thats been removed after checking their existence.
*
* @throws Exception ex
*/
@Test(expected = AccountNotFoundException.class)
public void testUserRemovedAfterCheckingExistence() throws Exception {
AuthorizeUserAction authorizeUser = new AuthorizeUserAction(USER_IDENTITY_3, 0);
authorizeUser.execute(daoFactory, authorityProvider);
}
/**
* Testing AuthorityAccessException when getting authorities.
*
* @throws Exception ex
*/
@Test(expected = AdministrationException.class)
public void testAuthorityAccessException() throws Exception {
AuthorizeUserAction authorizeUser = new AuthorizeUserAction(USER_IDENTITY_4, 0);
authorizeUser.execute(daoFactory, authorityProvider);
}
/**
* Testing DataAccessException while creating user accounts.
*
* @throws Exception ex
*/
@Test(expected = DataAccessException.class)
public void testErrorCreatingUserAccount() throws Exception {
AuthorizeUserAction authorizeUser = new AuthorizeUserAction(USER_IDENTITY_5, 0);
authorizeUser.execute(daoFactory, authorityProvider);
}
/**
* Tests the general case when a user account is created.
*
* @throws Exception ex
*/
@Test
public void testAccountCreation() throws Exception {
AuthorizeUserAction authorizeUser = new AuthorizeUserAction(USER_IDENTITY_6, 0);
NiFiUser user = authorizeUser.execute(daoFactory, authorityProvider);
// verify the user
Assert.assertEquals(USER_IDENTITY_6, user.getIdentity());
Assert.assertEquals(1, user.getAuthorities().size());
Assert.assertTrue(user.getAuthorities().contains(Authority.ROLE_MONITOR));
// verify interaction with dao and provider
Mockito.verify(userDao, Mockito.times(1)).createUser(user);
}
/**
* Tests the general case when there is an existing user account that
* requires verification.
*
* @throws Exception ex
*/
@Test
public void testExistingUserRequiresVerification() throws Exception {
AuthorizeUserAction authorizeUser = new AuthorizeUserAction(USER_IDENTITY_7, 0);
NiFiUser user = authorizeUser.execute(daoFactory, authorityProvider);
// verify the user
Assert.assertEquals(USER_IDENTITY_7, user.getIdentity());
Assert.assertEquals(1, user.getAuthorities().size());
Assert.assertTrue(user.getAuthorities().contains(Authority.ROLE_DFM));
// verify interaction with dao and provider
Mockito.verify(userDao, Mockito.times(1)).updateUser(user);
Mockito.verify(authorityDao, Mockito.times(1)).createAuthorities(EnumSet.of(Authority.ROLE_DFM), USER_ID_7);
}
/**
* Tests the general case when there is an existing user account that does
* not require verification.
*
* @throws Exception ex
*/
@Test
public void testExistingUserNoVerification() throws Exception {
// disabling verification by passing in a large cache duration
AuthorizeUserAction authorizeUser = new AuthorizeUserAction(USER_IDENTITY_8, Integer.MAX_VALUE);
NiFiUser user = authorizeUser.execute(daoFactory, authorityProvider);
// verify the user
Assert.assertEquals(USER_IDENTITY_8, user.getIdentity());
Assert.assertEquals(1, user.getAuthorities().size());
Assert.assertTrue(user.getAuthorities().contains(Authority.ROLE_MONITOR));
// verify interaction with dao and provider
Mockito.verify(userDao, Mockito.times(1)).updateUser(user);
Mockito.verify(authorityDao, Mockito.never()).createAuthorities(Mockito.anySet(), Mockito.eq(USER_ID_8));
Mockito.verify(authorityDao, Mockito.never()).deleteAuthorities(Mockito.anySet(), Mockito.eq(USER_ID_8));
}
/**
* Tests existing users whose accounts are in a pending status.
*
* @throws Exception ex
*/
@Test(expected = AccountPendingException.class)
public void testExistingPendingUser() throws Exception {
// disabling verification by passing in a large cache duration
AuthorizeUserAction authorizeUser = new AuthorizeUserAction(USER_IDENTITY_9, Integer.MAX_VALUE);
authorizeUser.execute(daoFactory, authorityProvider);
}
/**
* Tests existing users whose accounts are in a disabled status.
*
* @throws Exception ex
*/
@Test(expected = AccountDisabledException.class)
public void testExistingDisabledUser() throws Exception {
// disabling verification by passing in a large cache duration
AuthorizeUserAction authorizeUser = new AuthorizeUserAction(USER_IDENTITY_10, Integer.MAX_VALUE);
authorizeUser.execute(daoFactory, authorityProvider);
}
/**
* Tests the general case where there is an active user that has been
* removed from the authority provider.
*
* @throws Exception ex
*/
@Test
public void testExistingActiveUserNotFoundInProvider() throws Exception {
try {
AuthorizeUserAction authorizeUser = new AuthorizeUserAction(USER_IDENTITY_11, 0);
authorizeUser.execute(daoFactory, authorityProvider);
Assert.fail();
} catch (AccountDisabledException ade) {
ArgumentCaptor<NiFiUser> user = ArgumentCaptor.forClass(NiFiUser.class);
// verify interaction with dao
Mockito.verify(userDao, Mockito.times(1)).updateUser(user.capture());
// verify user
Assert.assertEquals(AccountStatus.DISABLED, user.getValue().getStatus());
}
}
}

View File

@ -1,144 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.admin.service.action;
import java.util.EnumSet;
import java.util.Set;
import org.apache.nifi.admin.dao.AuthorityDAO;
import org.apache.nifi.admin.dao.DAOFactory;
import org.apache.nifi.admin.dao.DataAccessException;
import org.apache.nifi.admin.dao.UserDAO;
import org.apache.nifi.authorization.Authority;
import org.apache.nifi.user.NiFiUser;
import org.apache.commons.lang3.StringUtils;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
/**
* Test cases for creating a user.
*/
public class CreateUserActionTest {
private final String USER_ID_2 = "2";
private final String USER_ID_3 = "3";
private final String USER_IDENTITY_1 = "data access exception when creating user";
private final String USER_IDENTITY_3 = "general create user case";
private DAOFactory daoFactory;
private UserDAO userDao;
private AuthorityDAO authorityDao;
@Before
public void setup() throws Exception {
// mock the user dao
userDao = Mockito.mock(UserDAO.class);
Mockito.doAnswer(new Answer<Void>() {
@Override
public Void answer(InvocationOnMock invocation) throws Throwable {
Object[] args = invocation.getArguments();
NiFiUser user = (NiFiUser) args[0];
if (USER_IDENTITY_1.equals(user.getIdentity())) {
throw new DataAccessException();
} else if (USER_IDENTITY_3.equals(user.getIdentity())) {
user.setId(USER_ID_3);
}
// do nothing
return null;
}
}).when(userDao).createUser(Mockito.any(NiFiUser.class));
// mock the authority dao
authorityDao = Mockito.mock(AuthorityDAO.class);
Mockito.doAnswer(new Answer<Void>() {
@Override
public Void answer(InvocationOnMock invocation) throws Throwable {
Object[] args = invocation.getArguments();
Set<Authority> authorities = (Set<Authority>) args[0];
String id = (String) args[1];
if (USER_ID_2.equals(id)) {
throw new DataAccessException(StringUtils.EMPTY);
}
// do nothing
return null;
}
}).when(authorityDao).createAuthorities(Mockito.anySetOf(Authority.class), Mockito.anyString());
// mock the dao factory
daoFactory = Mockito.mock(DAOFactory.class);
Mockito.when(daoFactory.getUserDAO()).thenReturn(userDao);
Mockito.when(daoFactory.getAuthorityDAO()).thenReturn(authorityDao);
}
/**
* Tests DataAccessExceptions that occur while creating user accounts.
*
* @throws Exception ex
*/
@Test(expected = DataAccessException.class)
public void testExceptionCreatingUser() throws Exception {
NiFiUser user = new NiFiUser();
user.setIdentity(USER_IDENTITY_1);
CreateUserAction createUser = new CreateUserAction(user);
createUser.execute(daoFactory, null);
}
/**
* Tests DataAccessExceptions that occur while create user authorities.
*
* @throws Exception ex
*/
@Test(expected = DataAccessException.class)
public void testExceptionCreatingAuthoroties() throws Exception {
NiFiUser user = new NiFiUser();
user.setId(USER_ID_2);
CreateUserAction createUser = new CreateUserAction(user);
createUser.execute(daoFactory, null);
}
/**
* General case for creating a user.
*
* @throws Exception ex
*/
@Test
public void testCreateUserAccount() throws Exception {
NiFiUser user = new NiFiUser();
user.setIdentity(USER_IDENTITY_3);
user.getAuthorities().addAll(EnumSet.of(Authority.ROLE_DFM, Authority.ROLE_ADMIN));
CreateUserAction createUser = new CreateUserAction(user);
createUser.execute(daoFactory, null);
// verify the user
Assert.assertEquals(USER_ID_3, user.getId());
// verify interaction with dao
Mockito.verify(userDao, Mockito.times(1)).createUser(user);
Mockito.verify(authorityDao, Mockito.times(1)).createAuthorities(user.getAuthorities(), USER_ID_3);
}
}

View File

@ -1,176 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.admin.service.action;
import org.apache.nifi.admin.dao.DAOFactory;
import org.apache.nifi.admin.dao.DataAccessException;
import org.apache.nifi.admin.dao.UserDAO;
import org.apache.nifi.admin.service.AccountNotFoundException;
import org.apache.nifi.admin.service.AdministrationException;
import org.apache.nifi.authorization.AuthorityProvider;
import org.apache.nifi.authorization.exception.AuthorityAccessException;
import org.apache.nifi.user.AccountStatus;
import org.apache.nifi.user.NiFiUser;
import org.apache.commons.lang3.StringUtils;
import org.apache.nifi.admin.dao.KeyDAO;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Matchers;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
public class DisableUserActionTest {
private static final String USER_ID_1 = "1";
private static final String USER_ID_2 = "2";
private static final String USER_ID_3 = "3";
private static final String USER_ID_4 = "4";
private static final String USER_IDENTITY_3 = "authority access exception";
private static final String USER_IDENTITY_4 = "general disable user case";
private DAOFactory daoFactory;
private UserDAO userDao;
private KeyDAO keyDao;
private AuthorityProvider authorityProvider;
@Before
public void setup() throws Exception {
// mock the user dao
userDao = Mockito.mock(UserDAO.class);
Mockito.doAnswer(new Answer<NiFiUser>() {
@Override
public NiFiUser answer(InvocationOnMock invocation) throws Throwable {
Object[] args = invocation.getArguments();
String id = (String) args[0];
NiFiUser user = null;
if (USER_ID_1.equals(id)) {
// leave user uninitialized
} else if (USER_ID_2.equals(id)) {
user = new NiFiUser();
user.setId(id);
} else if (USER_ID_3.equals(id)) {
user = new NiFiUser();
user.setId(id);
user.setIdentity(USER_IDENTITY_3);
} else if (USER_ID_4.equals(id)) {
user = new NiFiUser();
user.setId(id);
user.setIdentity(USER_IDENTITY_4);
user.setStatus(AccountStatus.ACTIVE);
}
return user;
}
}).when(userDao).findUserById(Mockito.anyString());
Mockito.doAnswer(new Answer<Void>() {
@Override
public Void answer(InvocationOnMock invocation) throws Throwable {
Object[] args = invocation.getArguments();
NiFiUser user = (NiFiUser) args[0];
if (USER_ID_2.equals(user.getId())) {
throw new DataAccessException(StringUtils.EMPTY);
}
// do nothing
return null;
}
}).when(userDao).updateUser(Mockito.any(NiFiUser.class));
// mock the dao factory
keyDao = Mockito.mock(KeyDAO.class);
Mockito.doNothing().when(keyDao).deleteKeys(Matchers.anyString());
// mock the dao factory
daoFactory = Mockito.mock(DAOFactory.class);
Mockito.when(daoFactory.getUserDAO()).thenReturn(userDao);
Mockito.when(daoFactory.getKeyDAO()).thenReturn(keyDao);
// mock the authority provider
authorityProvider = Mockito.mock(AuthorityProvider.class);
Mockito.doAnswer(new Answer<Void>() {
@Override
public Void answer(InvocationOnMock invocation) throws Throwable {
Object[] args = invocation.getArguments();
String dn = (String) args[0];
if (USER_IDENTITY_3.equals(dn)) {
throw new AuthorityAccessException(StringUtils.EMPTY);
}
// do nothing
return null;
}
}).when(authorityProvider).revokeUser(Mockito.anyString());
}
/**
* Tests the case when the user account is unknown.
*
* @throws Exception ex
*/
@Test(expected = AccountNotFoundException.class)
public void testUnknownUserAccount() throws Exception {
DisableUserAction disableUser = new DisableUserAction(USER_ID_1);
disableUser.execute(daoFactory, authorityProvider);
}
/**
* Tests the case when a DataAccessException is thrown by the userDao.
*
* @throws Exception ex
*/
@Test(expected = DataAccessException.class)
public void testDataAccessExceptionInUserDao() throws Exception {
DisableUserAction disableUser = new DisableUserAction(USER_ID_2);
disableUser.execute(daoFactory, authorityProvider);
}
/**
* Tests the case when a AuthorityAccessException is thrown by the provider.
*
* @throws Exception ex
*/
@Test(expected = AdministrationException.class)
public void testAuthorityAccessExceptionInProvider() throws Exception {
DisableUserAction disableUser = new DisableUserAction(USER_ID_3);
disableUser.execute(daoFactory, authorityProvider);
}
/**
* Tests the general case when the user is disabled.
*
* @throws Exception ex
*/
@Test
public void testDisableUser() throws Exception {
DisableUserAction disableUser = new DisableUserAction(USER_ID_4);
NiFiUser user = disableUser.execute(daoFactory, authorityProvider);
// verify the user
Assert.assertEquals(USER_ID_4, user.getId());
Assert.assertEquals(USER_IDENTITY_4, user.getIdentity());
Assert.assertEquals(AccountStatus.DISABLED, user.getStatus());
// verify the interaction with the dao and provider
Mockito.verify(userDao, Mockito.times(1)).updateUser(user);
Mockito.verify(authorityProvider, Mockito.times(1)).revokeUser(USER_IDENTITY_4);
}
}

View File

@ -1,126 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.admin.service.action;
import java.util.Date;
import org.junit.Assert;
import org.apache.nifi.admin.dao.DAOFactory;
import org.apache.nifi.admin.dao.DataAccessException;
import org.apache.nifi.admin.dao.UserDAO;
import org.apache.nifi.admin.service.AccountNotFoundException;
import org.apache.nifi.user.NiFiUser;
import org.apache.commons.lang3.StringUtils;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
/**
* Test case for InvalidateUserAccountAction.
*/
public class InvalidateUserAccountActionTest {
private static final String USER_ID_1 = "1";
private static final String USER_ID_2 = "2";
private static final String USER_ID_3 = "3";
private DAOFactory daoFactory;
private UserDAO userDao;
@Before
public void setup() throws Exception {
// mock the user dao
userDao = Mockito.mock(UserDAO.class);
Mockito.doAnswer(new Answer<NiFiUser>() {
@Override
public NiFiUser answer(InvocationOnMock invocation) throws Throwable {
Object[] args = invocation.getArguments();
String id = (String) args[0];
NiFiUser user = null;
if (USER_ID_1.equals(id)) {
// leave uninitialized
} else if (USER_ID_2.equals(id)) {
user = new NiFiUser();
user.setId(USER_ID_2);
} else if (USER_ID_3.equals(id)) {
user = new NiFiUser();
user.setId(USER_ID_3);
user.setLastVerified(new Date());
}
return user;
}
}).when(userDao).findUserById(Mockito.anyString());
Mockito.doAnswer(new Answer<Void>() {
@Override
public Void answer(InvocationOnMock invocation) throws Throwable {
Object[] args = invocation.getArguments();
NiFiUser user = (NiFiUser) args[0];
if (USER_ID_2.equals(user.getId())) {
throw new DataAccessException(StringUtils.EMPTY);
}
// do nothing
return null;
}
}).when(userDao).updateUser(Mockito.any(NiFiUser.class));
// mock the dao factory
daoFactory = Mockito.mock(DAOFactory.class);
Mockito.when(daoFactory.getUserDAO()).thenReturn(userDao);
}
@Test(expected = AccountNotFoundException.class)
public void testAccountNotFoundException() throws Exception {
InvalidateUserAccountAction invalidateUserAccount = new InvalidateUserAccountAction(USER_ID_1);
invalidateUserAccount.execute(daoFactory, null);
}
/**
* Tests when a data access exception occurs when updating the user record.
*
* @throws Exception ex
*/
@Test(expected = DataAccessException.class)
public void testDataAccessException() throws Exception {
InvalidateUserAccountAction invalidateUserAccount = new InvalidateUserAccountAction(USER_ID_2);
invalidateUserAccount.execute(daoFactory, null);
}
/**
* Tests the general case of invalidating a user.
*
* @throws Exception ex
*/
@Test
public void testInvalidateUser() throws Exception {
InvalidateUserAccountAction invalidateUserAccount = new InvalidateUserAccountAction(USER_ID_3);
invalidateUserAccount.execute(daoFactory, null);
// verify the interaction with the dao
ArgumentCaptor<NiFiUser> userCaptor = ArgumentCaptor.forClass(NiFiUser.class);
Mockito.verify(userDao, Mockito.times(1)).updateUser(userCaptor.capture());
// verify the user
NiFiUser user = userCaptor.getValue();
Assert.assertEquals(USER_ID_3, user.getId());
Assert.assertNull(user.getLastVerified());
}
}

View File

@ -1,127 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.admin.service.action;
import org.apache.nifi.admin.dao.DAOFactory;
import org.apache.nifi.admin.dao.DataAccessException;
import org.apache.nifi.admin.dao.UserDAO;
import org.apache.nifi.user.AccountStatus;
import org.apache.nifi.user.NiFiUser;
import org.apache.commons.lang3.StringUtils;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
/**
* Test case for RequestUserAccountAction.
*/
public class RequestUserAccountActionTest {
private static final String USER_ID_3 = "3";
private static final String USER_IDENTITY_1 = "existing user account";
private static final String USER_IDENTITY_2 = "data access exception";
private static final String USER_IDENTITY_3 = "new account request";
private DAOFactory daoFactory;
private UserDAO userDao;
@Before
public void setup() throws Exception {
// mock the user dao
userDao = Mockito.mock(UserDAO.class);
Mockito.doAnswer(new Answer<NiFiUser>() {
@Override
public NiFiUser answer(InvocationOnMock invocation) throws Throwable {
Object[] args = invocation.getArguments();
String dn = (String) args[0];
NiFiUser user = null;
if (USER_IDENTITY_1.equals(dn)) {
user = new NiFiUser();
}
return user;
}
}).when(userDao).findUserByDn(Mockito.anyString());
Mockito.doAnswer(new Answer<Void>() {
@Override
public Void answer(InvocationOnMock invocation) throws Throwable {
Object[] args = invocation.getArguments();
NiFiUser user = (NiFiUser) args[0];
switch (user.getIdentity()) {
case USER_IDENTITY_2:
throw new DataAccessException();
case USER_IDENTITY_3:
user.setId(USER_ID_3);
break;
}
// do nothing
return null;
}
}).when(userDao).createUser(Mockito.any(NiFiUser.class));
// mock the dao factory
daoFactory = Mockito.mock(DAOFactory.class);
Mockito.when(daoFactory.getUserDAO()).thenReturn(userDao);
}
/**
* Tests when a user account already exists.
*
* @throws Exception ex
*/
@Test(expected = IllegalArgumentException.class)
public void testExistingAccount() throws Exception {
RequestUserAccountAction requestUserAccount = new RequestUserAccountAction(USER_IDENTITY_1, StringUtils.EMPTY);
requestUserAccount.execute(daoFactory, null);
}
/**
* Tests when a DataAccessException occurs while saving the new account
* request.
*
* @throws Exception ex
*/
@Test(expected = DataAccessException.class)
public void testDataAccessException() throws Exception {
RequestUserAccountAction requestUserAccount = new RequestUserAccountAction(USER_IDENTITY_2, StringUtils.EMPTY);
requestUserAccount.execute(daoFactory, null);
}
/**
* Tests the general case for requesting a new user account.
*
* @throws Exception ex
*/
@Test
public void testRequestUserAccountAction() throws Exception {
RequestUserAccountAction requestUserAccount = new RequestUserAccountAction(USER_IDENTITY_3, StringUtils.EMPTY);
NiFiUser user = requestUserAccount.execute(daoFactory, null);
// verfiy the user
Assert.assertEquals(USER_ID_3, user.getId());
Assert.assertEquals(USER_IDENTITY_3, user.getIdentity());
Assert.assertEquals(AccountStatus.PENDING, user.getStatus());
// verify interaction with dao
Mockito.verify(userDao, Mockito.times(1)).createUser(user);
}
}

View File

@ -1,262 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.admin.service.action;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.Set;
import org.apache.nifi.admin.dao.AuthorityDAO;
import org.apache.nifi.admin.dao.DAOFactory;
import org.apache.nifi.admin.dao.UserDAO;
import org.apache.nifi.authorization.Authority;
import org.apache.nifi.authorization.AuthorityProvider;
import org.apache.nifi.user.AccountStatus;
import org.apache.nifi.user.NiFiUser;
import org.hamcrest.Matcher;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentMatcher;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
/**
*
*/
public class SeedUserAccountsActionTest {
private static final String USER_ID_1 = "1";
private static final String USER_ID_2 = "2";
private static final String USER_ID_3 = "3";
private static final String USER_ID_4 = "4";
private static final String USER_IDENTITY_1 = "user 1 - active user - remove monitor and operator, add dfm";
private static final String USER_IDENTITY_2 = "user 2 - active user - no action";
private static final String USER_IDENTITY_3 = "user 3 - pending user - add operator";
private static final String USER_IDENTITY_4 = "user 4 - new user - add monitor";
private DAOFactory daoFactory;
private UserDAO userDao;
private AuthorityDAO authorityDao;
private AuthorityProvider authorityProvider;
@Before
public void setup() throws Exception {
// mock the user dao
userDao = Mockito.mock(UserDAO.class);
Mockito.doAnswer(new Answer<NiFiUser>() {
@Override
public NiFiUser answer(InvocationOnMock invocation) throws Throwable {
Object[] args = invocation.getArguments();
String id = (String) args[0];
NiFiUser user = null;
if (USER_ID_1.equals(id)) {
user = new NiFiUser();
user.setId(USER_ID_1);
user.setIdentity(USER_IDENTITY_1);
user.getAuthorities().addAll(EnumSet.of(Authority.ROLE_MONITOR));
user.setStatus(AccountStatus.ACTIVE);
} else if (USER_ID_2.equals(id)) {
user = new NiFiUser();
user.setId(USER_ID_2);
user.setIdentity(USER_IDENTITY_2);
user.getAuthorities().addAll(EnumSet.of(Authority.ROLE_ADMIN));
user.setStatus(AccountStatus.ACTIVE);
} else if (USER_ID_3.equals(id)) {
user = new NiFiUser();
user.setId(USER_ID_3);
user.setIdentity(USER_IDENTITY_3);
user.setStatus(AccountStatus.PENDING);
}
return user;
}
}).when(userDao).findUserById(Mockito.anyString());
Mockito.doAnswer(new Answer<NiFiUser>() {
@Override
public NiFiUser answer(InvocationOnMock invocation) throws Throwable {
Object[] args = invocation.getArguments();
String dn = (String) args[0];
NiFiUser user = null;
if (USER_IDENTITY_1.equals(dn)) {
user = new NiFiUser();
user.setId(USER_ID_1);
user.setIdentity(USER_IDENTITY_1);
user.getAuthorities().addAll(EnumSet.of(Authority.ROLE_MONITOR));
user.setStatus(AccountStatus.ACTIVE);
} else if (USER_IDENTITY_2.equals(dn)) {
user = new NiFiUser();
user.setId(USER_ID_2);
user.setIdentity(USER_IDENTITY_2);
user.getAuthorities().addAll(EnumSet.of(Authority.ROLE_ADMIN));
user.setStatus(AccountStatus.ACTIVE);
} else if (USER_IDENTITY_3.equals(dn)) {
user = new NiFiUser();
user.setId(USER_ID_3);
user.setIdentity(USER_IDENTITY_3);
user.setStatus(AccountStatus.PENDING);
}
return user;
}
}).when(userDao).findUserByDn(Mockito.anyString());
Mockito.doAnswer(new Answer<Void>() {
@Override
public Void answer(InvocationOnMock invocation) throws Throwable {
Object[] args = invocation.getArguments();
NiFiUser user = (NiFiUser) args[0];
if (USER_IDENTITY_4.equals(user.getIdentity())) {
user.setId(USER_ID_4);
}
return null;
}
}).when(userDao).createUser(Mockito.any(NiFiUser.class));
// mock the authority dao
authorityDao = Mockito.mock(AuthorityDAO.class);
// mock the authority provider
authorityProvider = Mockito.mock(AuthorityProvider.class);
Mockito.doAnswer(new Answer<Set<String>>() {
@Override
public Set<String> answer(InvocationOnMock invocation) throws Throwable {
Object[] args = invocation.getArguments();
Authority role = (Authority) args[0];
Set<String> users = new HashSet<>();
if (Authority.ROLE_DFM.equals(role)) {
users.add(USER_IDENTITY_1);
} else if (Authority.ROLE_ADMIN.equals(role)) {
users.add(USER_IDENTITY_2);
} else if (Authority.ROLE_PROXY.equals(role)) {
users.add(USER_IDENTITY_3);
} else if (Authority.ROLE_MONITOR.equals(role)) {
users.add(USER_IDENTITY_4);
}
return users;
}
}).when(authorityProvider).getUsers(Mockito.any(Authority.class));
Mockito.doAnswer(new Answer<Set<Authority>>() {
@Override
public Set<Authority> answer(InvocationOnMock invocation) throws Throwable {
Object[] args = invocation.getArguments();
String dn = (String) args[0];
Set<Authority> authorities = EnumSet.noneOf(Authority.class);
switch (dn) {
case USER_IDENTITY_1:
authorities.add(Authority.ROLE_DFM);
break;
case USER_IDENTITY_2:
authorities.add(Authority.ROLE_ADMIN);
break;
case USER_IDENTITY_3:
authorities.add(Authority.ROLE_PROXY);
break;
case USER_IDENTITY_4:
authorities.add(Authority.ROLE_MONITOR);
break;
}
return authorities;
}
}).when(authorityProvider).getAuthorities(Mockito.anyString());
// mock the dao factory
daoFactory = Mockito.mock(DAOFactory.class);
Mockito.when(daoFactory.getUserDAO()).thenReturn(userDao);
Mockito.when(daoFactory.getAuthorityDAO()).thenReturn(authorityDao);
}
/**
* Tests seeding the user accounts.
*
* @throws Exception ex
*/
@Test
public void testSeedUsers() throws Exception {
SeedUserAccountsAction seedUserAccounts = new SeedUserAccountsAction();
seedUserAccounts.execute(daoFactory, authorityProvider);
// matcher for user 1
Matcher<NiFiUser> matchesUser1 = new ArgumentMatcher<NiFiUser>() {
@Override
public boolean matches(Object argument) {
NiFiUser user = (NiFiUser) argument;
return USER_ID_1.equals(user.getId());
}
};
// verify user 1 - active existing user - remove monitor, operator, add dfm
Mockito.verify(userDao, Mockito.times(1)).updateUser(Mockito.argThat(matchesUser1));
Mockito.verify(userDao, Mockito.never()).createUser(Mockito.argThat(matchesUser1));
Mockito.verify(authorityDao, Mockito.times(1)).createAuthorities(EnumSet.of(Authority.ROLE_DFM), USER_ID_1);
// matcher for user 2
Matcher<NiFiUser> matchesUser2 = new ArgumentMatcher<NiFiUser>() {
@Override
public boolean matches(Object argument) {
NiFiUser user = (NiFiUser) argument;
return USER_ID_2.equals(user.getId());
}
};
// verify user 2 - active existing user - no actions
Mockito.verify(userDao, Mockito.times(1)).updateUser(Mockito.argThat(matchesUser2));
Mockito.verify(userDao, Mockito.never()).createUser(Mockito.argThat(matchesUser2));
Mockito.verify(authorityDao, Mockito.never()).createAuthorities(Mockito.anySet(), Mockito.eq(USER_ID_2));
Mockito.verify(authorityDao, Mockito.never()).deleteAuthorities(Mockito.anySet(), Mockito.eq(USER_ID_2));
// matchers for user 3
Matcher<NiFiUser> matchesPendingUser3 = new ArgumentMatcher<NiFiUser>() {
@Override
public boolean matches(Object argument) {
NiFiUser user = (NiFiUser) argument;
return USER_ID_3.equals(user.getId()) && AccountStatus.ACTIVE.equals(user.getStatus());
}
};
Matcher<NiFiUser> matchesUser3 = new ArgumentMatcher<NiFiUser>() {
@Override
public boolean matches(Object argument) {
NiFiUser user = (NiFiUser) argument;
return USER_ID_3.equals(user.getId());
}
};
// verify user 3 - pending user - add operator
Mockito.verify(userDao, Mockito.times(1)).updateUser(Mockito.argThat(matchesPendingUser3));
Mockito.verify(userDao, Mockito.never()).createUser(Mockito.argThat(matchesUser3));
Mockito.verify(authorityDao, Mockito.times(1)).createAuthorities(EnumSet.of(Authority.ROLE_PROXY), USER_ID_3);
Mockito.verify(authorityDao, Mockito.never()).deleteAuthorities(Mockito.anySet(), Mockito.eq(USER_ID_3));
// matcher for user 4
Matcher<NiFiUser> matchesUser4 = new ArgumentMatcher<NiFiUser>() {
@Override
public boolean matches(Object argument) {
NiFiUser user = (NiFiUser) argument;
return USER_ID_4.equals(user.getId());
}
};
// verify user 4 - new user - add monitor
Mockito.verify(userDao, Mockito.never()).updateUser(Mockito.argThat(matchesUser4));
Mockito.verify(userDao, Mockito.times(1)).createUser(Mockito.argThat(matchesUser4));
Mockito.verify(authorityDao, Mockito.times(1)).createAuthorities(EnumSet.of(Authority.ROLE_MONITOR), USER_ID_4);
Mockito.verify(authorityDao, Mockito.never()).deleteAuthorities(Mockito.anySet(), Mockito.eq(USER_ID_4));
}
}

View File

@ -1,223 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.admin.service.action;
import java.util.Collections;
import java.util.EnumSet;
import java.util.Set;
import org.apache.nifi.admin.dao.AuthorityDAO;
import org.apache.nifi.admin.dao.DAOFactory;
import org.apache.nifi.admin.dao.UserDAO;
import org.apache.nifi.admin.service.AccountNotFoundException;
import org.apache.nifi.admin.service.AdministrationException;
import org.apache.nifi.authorization.Authority;
import org.apache.nifi.authorization.AuthorityProvider;
import org.apache.nifi.authorization.exception.AuthorityAccessException;
import org.apache.nifi.user.AccountStatus;
import org.apache.nifi.user.NiFiUser;
import org.apache.commons.lang3.StringUtils;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
/**
* Test case for SetUserAuthoritiesAction.
*/
public class SetUserAuthoritiesActionTest {
private static final String USER_ID_1 = "1";
private static final String USER_ID_2 = "2";
private static final String USER_ID_3 = "3";
private static final String USER_IDENTITY_2 = "user 2";
private static final String USER_IDENTITY_3 = "user 3";
private DAOFactory daoFactory;
private UserDAO userDao;
private AuthorityDAO authorityDao;
private AuthorityProvider authorityProvider;
@Before
public void setup() throws Exception {
// mock the user dao
userDao = Mockito.mock(UserDAO.class);
Mockito.doAnswer(new Answer<NiFiUser>() {
@Override
public NiFiUser answer(InvocationOnMock invocation) throws Throwable {
Object[] args = invocation.getArguments();
String id = (String) args[0];
NiFiUser user = null;
if (USER_ID_1.equals(id)) {
// leave user uninitialized
} else if (USER_ID_2.equals(id)) {
user = new NiFiUser();
user.setId(USER_ID_2);
user.setIdentity(USER_IDENTITY_2);
} else if (USER_ID_3.equals(id)) {
user = new NiFiUser();
user.setId(USER_ID_3);
user.setIdentity(USER_IDENTITY_3);
user.getAuthorities().addAll(EnumSet.of(Authority.ROLE_MONITOR));
user.setStatus(AccountStatus.ACTIVE);
}
return user;
}
}).when(userDao).findUserById(Mockito.anyString());
Mockito.doAnswer(new Answer<NiFiUser>() {
@Override
public NiFiUser answer(InvocationOnMock invocation) throws Throwable {
Object[] args = invocation.getArguments();
String dn = (String) args[0];
NiFiUser user = null;
if (USER_IDENTITY_3.equals(dn)) {
user = new NiFiUser();
user.setId(USER_ID_3);
user.setIdentity(USER_IDENTITY_3);
user.getAuthorities().addAll(EnumSet.of(Authority.ROLE_MONITOR));
user.setStatus(AccountStatus.ACTIVE);
}
return user;
}
}).when(userDao).findUserByDn(Mockito.anyString());
Mockito.doAnswer(new Answer<Void>() {
@Override
public Void answer(InvocationOnMock invocation) throws Throwable {
Object[] args = invocation.getArguments();
NiFiUser user = (NiFiUser) args[0];
// do nothing
return null;
}
}).when(userDao).updateUser(Mockito.any(NiFiUser.class));
// mock the authority dao
authorityDao = Mockito.mock(AuthorityDAO.class);
Mockito.doAnswer(new Answer<Void>() {
@Override
public Void answer(InvocationOnMock invocation) throws Throwable {
Object[] args = invocation.getArguments();
Set<Authority> authorities = (Set<Authority>) args[0];
String id = (String) args[1];
// do nothing
return null;
}
}).when(authorityDao).createAuthorities(Mockito.anySetOf(Authority.class), Mockito.anyString());
Mockito.doAnswer(new Answer<Void>() {
@Override
public Void answer(InvocationOnMock invocation) throws Throwable {
Object[] args = invocation.getArguments();
Set<Authority> authorities = (Set<Authority>) args[0];
String id = (String) args[1];
// do nothing
return null;
}
}).when(authorityDao).deleteAuthorities(Mockito.anySetOf(Authority.class), Mockito.anyString());
// mock the dao factory
daoFactory = Mockito.mock(DAOFactory.class);
Mockito.when(daoFactory.getUserDAO()).thenReturn(userDao);
Mockito.when(daoFactory.getAuthorityDAO()).thenReturn(authorityDao);
// mock the authority provider
authorityProvider = Mockito.mock(AuthorityProvider.class);
Mockito.doAnswer(new Answer<Set<Authority>>() {
@Override
public Set<Authority> answer(InvocationOnMock invocation) throws Throwable {
Object[] args = invocation.getArguments();
String dn = (String) args[0];
Set<Authority> authorities = EnumSet.noneOf(Authority.class);
if (USER_IDENTITY_3.equals(dn)) {
authorities.add(Authority.ROLE_DFM);
}
return authorities;
}
}).when(authorityProvider).getAuthorities(Mockito.anyString());
Mockito.doAnswer(new Answer<Void>() {
@Override
public Void answer(InvocationOnMock invocation) throws Throwable {
Object[] args = invocation.getArguments();
String dn = (String) args[0];
Set<Authority> authorites = (Set<Authority>) args[1];
if (USER_IDENTITY_2.equals(dn)) {
throw new AuthorityAccessException(StringUtils.EMPTY);
}
// do nothing
return null;
}
}).when(authorityProvider).setAuthorities(Mockito.anyString(), Mockito.anySet());
}
/**
* Test activating an unknown user account. User accounts are unknown then
* there is no pending account for the user.
*
* @throws Exception ex
*/
@Test(expected = AccountNotFoundException.class)
public void testUnknownUser() throws Exception {
UpdateUserAction setUserAuthorities = new UpdateUserAction(USER_ID_1, Collections.EMPTY_SET);
setUserAuthorities.execute(daoFactory, authorityProvider);
}
/**
* Testing case then an AuthorityAccessException occurs while setting a
* users authorities.
*
* @throws Exception ex
*/
@Test(expected = AdministrationException.class)
public void testAuthorityAccessException() throws Exception {
UpdateUserAction setUserAuthorities = new UpdateUserAction(USER_ID_2, Collections.EMPTY_SET);
setUserAuthorities.execute(daoFactory, authorityProvider);
}
/**
* Tests general case of setting user authorities.
*
* @throws Exception ex
*/
@Test
public void testSetAuthorities() throws Exception {
UpdateUserAction setUserAuthorities = new UpdateUserAction(USER_ID_3, EnumSet.of(Authority.ROLE_ADMIN));
NiFiUser user = setUserAuthorities.execute(daoFactory, authorityProvider);
// verify user
Assert.assertEquals(USER_ID_3, user.getId());
Assert.assertEquals(1, user.getAuthorities().size());
Assert.assertTrue(user.getAuthorities().contains(Authority.ROLE_ADMIN));
// verify interaction with dao
Mockito.verify(userDao, Mockito.times(1)).updateUser(user);
Mockito.verify(authorityDao, Mockito.times(1)).createAuthorities(EnumSet.of(Authority.ROLE_ADMIN), USER_ID_3);
Set<Authority> authoritiesAddedToProvider = EnumSet.of(Authority.ROLE_ADMIN);
// verify interaction with provider
Mockito.verify(authorityProvider, Mockito.times(1)).setAuthorities(USER_IDENTITY_3, authoritiesAddedToProvider);
}
}

View File

@ -18,6 +18,7 @@ package org.apache.nifi.web.api.dto;
import com.wordnik.swagger.annotations.ApiModelProperty; import com.wordnik.swagger.annotations.ApiModelProperty;
import javax.xml.bind.annotation.XmlType; import javax.xml.bind.annotation.XmlType;
import java.util.UUID;
/** /**
* Current revision for this NiFi. * Current revision for this NiFi.
@ -41,6 +42,9 @@ public class RevisionDTO {
+ "nature of requests/responses this was implemented to allow the client to make numerous requests without having to wait for the previous response to come back" + "nature of requests/responses this was implemented to allow the client to make numerous requests without having to wait for the previous response to come back"
) )
public String getClientId() { public String getClientId() {
if (clientId == null || clientId.trim().isEmpty()) {
clientId = UUID.randomUUID().toString();
}
return clientId; return clientId;
} }

View File

@ -38,8 +38,6 @@ public class ControllerStatusDTO implements Cloneable {
private Integer connectedNodeCount = 0; private Integer connectedNodeCount = 0;
private Integer totalNodeCount = 0; private Integer totalNodeCount = 0;
private Boolean hasPendingAccounts;
private Integer runningCount = 0; private Integer runningCount = 0;
private Integer stoppedCount = 0; private Integer stoppedCount = 0;
private Integer invalidCount = 0; private Integer invalidCount = 0;
@ -126,18 +124,6 @@ public class ControllerStatusDTO implements Cloneable {
this.reportingTaskBulletins = reportingTaskBulletins; this.reportingTaskBulletins = reportingTaskBulletins;
} }
/**
* @return whether or not there are pending user requests
*/
@ApiModelProperty("Whether there are any pending user account requests.")
public Boolean getHasPendingAccounts() {
return hasPendingAccounts;
}
public void setHasPendingAccounts(Boolean hasPendingAccounts) {
this.hasPendingAccounts = hasPendingAccounts;
}
/** /**
* @return number of running components in this controller * @return number of running components in this controller
*/ */
@ -256,7 +242,6 @@ public class ControllerStatusDTO implements Cloneable {
other.setConnectedNodes(getConnectedNodes()); other.setConnectedNodes(getConnectedNodes());
other.setConnectedNodeCount(getConnectedNodeCount()); other.setConnectedNodeCount(getConnectedNodeCount());
other.setTotalNodeCount(getTotalNodeCount()); other.setTotalNodeCount(getTotalNodeCount());
other.setHasPendingAccounts(getHasPendingAccounts());
other.setRunningCount(getRunningCount()); other.setRunningCount(getRunningCount());
other.setStoppedCount(getStoppedCount()); other.setStoppedCount(getStoppedCount());
other.setInvalidCount(getInvalidCount()); other.setInvalidCount(getInvalidCount());

View File

@ -35,7 +35,11 @@ public class Entity {
value = "The revision for this request/response. The revision is required for any mutable flow requests and is included in all responses." value = "The revision for this request/response. The revision is required for any mutable flow requests and is included in all responses."
) )
public RevisionDTO getRevision() { public RevisionDTO getRevision() {
return revision; if (revision == null) {
return new RevisionDTO();
} else {
return revision;
}
} }
public void setRevision(RevisionDTO revision) { public void setRevision(RevisionDTO revision) {

View File

@ -14,41 +14,41 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.apache.nifi.cluster.authorization.protocol.message; package org.apache.nifi.web.api.entity;
import com.wordnik.swagger.annotations.ApiModelProperty;
import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlRootElement;
/** /**
* A serialized representation of this class can be placed in the entity body of a request to the API.
*/ */
@XmlRootElement(name = "getGroupForUserMessage") @XmlRootElement(name = "updateControllerServiceReferenceRequestEntity")
public class GetGroupForUserMessage extends ProtocolMessage { public class UpdateControllerServiceReferenceRequestEntity extends Entity {
private String dn; private String id;
private String state;
private String response; @ApiModelProperty(
value = "The identifier of the Controller Service."
public GetGroupForUserMessage() { )
public String getId() {
return id;
} }
@Override public void setId(String id) {
public MessageType getType() { this.id = id;
return MessageType.GET_GROUP_FOR_USER;
} }
public String getDn() { @ApiModelProperty(
return dn; value = "The new state of the references for the controller service.",
allowableValues = "ENABLED, DISABLED, RUNNING, STOPPED"
)
public String getState() {
return state;
} }
public void setDn(String dn) { public void setState(String state) {
this.dn = dn; this.state = state;
} }
public String getResponse() {
return response;
}
public void setResponse(String response) {
this.response = response;
}
} }

View File

@ -1,46 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.apache.nifi</groupId>
<artifactId>nifi-framework</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<artifactId>nifi-cluster-authorization-provider</artifactId>
<dependencies>
<dependency>
<groupId>org.apache.nifi</groupId>
<artifactId>nifi-api</artifactId>
</dependency>
<dependency>
<groupId>org.apache.nifi</groupId>
<artifactId>nifi-file-authorization-provider</artifactId>
</dependency>
<dependency>
<groupId>org.apache.nifi</groupId>
<artifactId>nifi-framework-cluster-protocol</artifactId>
</dependency>
<dependency>
<groupId>org.apache.nifi</groupId>
<artifactId>nifi-framework-cluster</artifactId>
</dependency>
<dependency>
<groupId>org.apache.nifi</groupId>
<artifactId>nifi-socket-utils</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -1,225 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.cluster.authorization;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import org.apache.nifi.authorization.AuthorityProvider;
import org.apache.nifi.authorization.AuthorityProviderConfigurationContext;
import org.apache.nifi.authorization.AuthorityProviderInitializationContext;
import org.apache.nifi.authorization.FileAuthorizationProvider;
import org.apache.nifi.authorization.annotation.AuthorityProviderContext;
import org.apache.nifi.authorization.exception.ProviderCreationException;
import org.apache.nifi.authorization.exception.ProviderDestructionException;
import org.apache.nifi.cluster.authorization.protocol.message.DoesDnExistMessage;
import org.apache.nifi.cluster.authorization.protocol.message.GetAuthoritiesMessage;
import org.apache.nifi.cluster.authorization.protocol.message.GetGroupForUserMessage;
import org.apache.nifi.cluster.authorization.protocol.message.ProtocolMessage;
import static org.apache.nifi.cluster.authorization.protocol.message.ProtocolMessage.MessageType.DOES_DN_EXIST;
import static org.apache.nifi.cluster.authorization.protocol.message.ProtocolMessage.MessageType.GET_AUTHORITIES;
import static org.apache.nifi.cluster.authorization.protocol.message.ProtocolMessage.MessageType.GET_GROUP_FOR_USER;
import org.apache.nifi.cluster.authorization.protocol.message.jaxb.JaxbProtocolUtils;
import org.apache.nifi.cluster.manager.impl.WebClusterManager;
import org.apache.nifi.cluster.protocol.ProtocolContext;
import org.apache.nifi.cluster.protocol.ProtocolMessageMarshaller;
import org.apache.nifi.cluster.protocol.ProtocolMessageUnmarshaller;
import org.apache.nifi.cluster.protocol.jaxb.JaxbProtocolContext;
import org.apache.nifi.io.socket.ServerSocketConfiguration;
import org.apache.nifi.io.socket.SocketListener;
import org.apache.nifi.io.socket.SocketUtils;
import org.apache.nifi.io.socket.multicast.DiscoverableService;
import org.apache.nifi.io.socket.multicast.DiscoverableServiceImpl;
import org.apache.nifi.logging.NiFiLog;
import org.apache.nifi.util.NiFiProperties;
import static org.apache.nifi.util.NiFiProperties.CLUSTER_MANAGER_ADDRESS;
import org.apache.nifi.util.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
/**
* Provides authorities for the NCM in clustered environments. Communication
* occurs over TCP/IP sockets. All method calls are deferred to the
* FileAuthorizationProvider.
*/
public class ClusterManagerAuthorizationProvider extends FileAuthorizationProvider implements AuthorityProvider, ApplicationContextAware {
public static final String AUTHORITY_PROVIDER_SERVIVE_NAME = "cluster-authority-provider";
private static final Logger logger = new NiFiLog(LoggerFactory.getLogger(ClusterManagerAuthorizationProvider.class));
private static final String CLUSTER_MANAGER_AUTHORITY_PROVIDER_PORT = "Authority Provider Port";
private static final String CLUSTER_MANAGER_AUTHORITY_PROVIDER_THREADS = "Authority Provider Threads";
private static final int DEFAULT_CLUSTER_MANAGER_AUTHORITY_PROVIDER_THREADS = 10;
private WebClusterManager clusterManager;
private ProtocolContext<ProtocolMessage> authorityProviderProtocolContext;
private SocketListener socketListener;
private NiFiProperties properties;
private ApplicationContext applicationContext;
@Override
public void initialize(final AuthorityProviderInitializationContext initializationContext) throws ProviderCreationException {
super.initialize(initializationContext);
}
@Override
public void onConfigured(final AuthorityProviderConfigurationContext configurationContext) throws ProviderCreationException {
super.onConfigured(configurationContext);
// get the socket address of the cluster authority provider
final InetSocketAddress clusterAuthorityProviderAddress = getClusterManagerAuthorityProviderAddress(configurationContext);
// get the cluster manager
clusterManager = applicationContext.getBean("clusterManager", WebClusterManager.class);
// if using multicast, then the authority provider's service is broadcasted
if (properties.getClusterProtocolUseMulticast()) {
// create the authority provider service for discovery
final DiscoverableService clusterAuthorityProviderService = new DiscoverableServiceImpl(AUTHORITY_PROVIDER_SERVIVE_NAME, clusterAuthorityProviderAddress);
// register the authority provider service with the cluster manager
clusterManager.addBroadcastedService(clusterAuthorityProviderService);
}
// get the number of protocol listening thread
final int numThreads = getClusterManagerAuthorityProviderThreads(configurationContext);
// the server socket configuration
final ServerSocketConfiguration configuration = applicationContext.getBean("protocolServerSocketConfiguration", ServerSocketConfiguration.class);
// the authority provider listens for node messages
socketListener = new SocketListener(numThreads, clusterAuthorityProviderAddress.getPort(), configuration) {
@Override
public void dispatchRequest(final Socket socket) {
ClusterManagerAuthorizationProvider.this.dispatchRequest(socket);
}
};
// start the socket listener
if (socketListener != null && !socketListener.isRunning()) {
try {
socketListener.start();
} catch (final IOException ioe) {
throw new ProviderCreationException("Failed to start Cluster Manager Authorization Provider due to: " + ioe, ioe);
}
}
// initialize the protocol context
authorityProviderProtocolContext = new JaxbProtocolContext<ProtocolMessage>(JaxbProtocolUtils.JAXB_CONTEXT);
}
@Override
public void preDestruction() throws ProviderDestructionException {
if (socketListener != null && socketListener.isRunning()) {
try {
socketListener.stop();
} catch (final IOException ioe) {
throw new ProviderDestructionException("Failed to stop Cluster Manager Authorization Provider due to: " + ioe, ioe);
}
}
super.preDestruction();
}
private int getClusterManagerAuthorityProviderThreads(final AuthorityProviderConfigurationContext configurationContext) {
try {
return Integer.parseInt(configurationContext.getProperty(CLUSTER_MANAGER_AUTHORITY_PROVIDER_THREADS));
} catch (NumberFormatException nfe) {
return DEFAULT_CLUSTER_MANAGER_AUTHORITY_PROVIDER_THREADS;
}
}
private InetSocketAddress getClusterManagerAuthorityProviderAddress(final AuthorityProviderConfigurationContext configurationContext) {
try {
String socketAddress = properties.getProperty(CLUSTER_MANAGER_ADDRESS);
if (StringUtils.isBlank(socketAddress)) {
socketAddress = "localhost";
}
return InetSocketAddress.createUnresolved(socketAddress, getClusterManagerAuthorityProviderPort(configurationContext));
} catch (Exception ex) {
throw new RuntimeException("Invalid manager authority provider address/port due to: " + ex, ex);
}
}
private Integer getClusterManagerAuthorityProviderPort(final AuthorityProviderConfigurationContext configurationContext) {
final String authorityProviderPort = configurationContext.getProperty(CLUSTER_MANAGER_AUTHORITY_PROVIDER_PORT);
if (authorityProviderPort == null || authorityProviderPort.trim().isEmpty()) {
throw new ProviderCreationException("The authority provider port must be specified.");
}
return Integer.parseInt(authorityProviderPort);
}
private void dispatchRequest(final Socket socket) {
try {
// unmarshall message
final ProtocolMessageUnmarshaller<ProtocolMessage> unmarshaller = authorityProviderProtocolContext.createUnmarshaller();
final ProtocolMessage request = unmarshaller.unmarshal(socket.getInputStream());
final ProtocolMessage response = request;
try {
switch (request.getType()) {
case DOES_DN_EXIST: {
final DoesDnExistMessage castedMsg = (DoesDnExistMessage) request;
castedMsg.setResponse(doesDnExist(castedMsg.getDn()));
break;
}
case GET_AUTHORITIES: {
final GetAuthoritiesMessage castedMsg = (GetAuthoritiesMessage) request;
castedMsg.setResponse(getAuthorities(castedMsg.getDn()));
break;
}
case GET_GROUP_FOR_USER: {
final GetGroupForUserMessage castedMsg = (GetGroupForUserMessage) request;
castedMsg.setResponse(getGroupForUser(castedMsg.getDn()));
break;
}
default: {
throw new Exception("Unsupported Message Type: " + request.getType());
}
}
} catch (final Exception ex) {
response.setExceptionClass(ex.getClass().getName());
response.setExceptionMessage(ex.getMessage());
}
final ProtocolMessageMarshaller<ProtocolMessage> marshaller = authorityProviderProtocolContext.createMarshaller();
marshaller.marshal(response, socket.getOutputStream());
} catch (final Exception e) {
logger.warn("Failed processing Socket Authorization Provider protocol message due to " + e, e);
} finally {
SocketUtils.closeQuietly(socket);
}
}
@Override
@AuthorityProviderContext
public void setApplicationContext(final ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
@Override
@AuthorityProviderContext
public void setNiFiProperties(NiFiProperties properties) {
super.setNiFiProperties(properties);
this.properties = properties;
}
}

View File

@ -1,389 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.cluster.authorization;
import org.apache.nifi.cluster.authorization.protocol.message.DoesDnExistMessage;
import org.apache.nifi.cluster.authorization.protocol.message.GetAuthoritiesMessage;
import org.apache.nifi.cluster.authorization.protocol.message.ProtocolMessage;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.apache.nifi.authorization.Authority;
import org.apache.nifi.authorization.AuthorityProvider;
import org.apache.nifi.authorization.AuthorityProviderConfigurationContext;
import org.apache.nifi.authorization.AuthorityProviderInitializationContext;
import org.apache.nifi.authorization.DownloadAuthorization;
import org.apache.nifi.authorization.annotation.AuthorityProviderContext;
import org.apache.nifi.authorization.exception.AuthorityAccessException;
import org.apache.nifi.authorization.exception.IdentityAlreadyExistsException;
import org.apache.nifi.authorization.exception.ProviderCreationException;
import org.apache.nifi.authorization.exception.ProviderDestructionException;
import org.apache.nifi.authorization.exception.UnknownIdentityException;
import org.apache.nifi.cluster.authorization.protocol.message.GetGroupForUserMessage;
import org.apache.nifi.cluster.authorization.protocol.message.jaxb.JaxbProtocolUtils;
import org.apache.nifi.io.socket.SocketConfiguration;
import org.apache.nifi.io.socket.SocketUtils;
import org.apache.nifi.io.socket.multicast.DiscoverableService;
import org.apache.nifi.cluster.protocol.ProtocolContext;
import org.apache.nifi.cluster.protocol.ProtocolMessageMarshaller;
import org.apache.nifi.cluster.protocol.ProtocolMessageUnmarshaller;
import org.apache.nifi.cluster.protocol.impl.ClusterServiceDiscovery;
import org.apache.nifi.cluster.protocol.impl.ClusterServiceLocator;
import org.apache.nifi.cluster.protocol.jaxb.JaxbProtocolContext;
import org.apache.nifi.io.socket.multicast.DiscoverableServiceImpl;
import org.apache.nifi.io.socket.multicast.MulticastConfiguration;
import org.apache.nifi.logging.NiFiLog;
import org.apache.nifi.util.NiFiProperties;
import static org.apache.nifi.util.NiFiProperties.CLUSTER_NODE_UNICAST_MANAGER_ADDRESS;
import org.apache.nifi.util.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
/**
* Provides authorities for nodes in clustered environments. Communication
* occurs over TCP/IP sockets. All method calls are communicated to the cluster
* manager provider via socket.
*/
public class NodeAuthorizationProvider implements AuthorityProvider, ApplicationContextAware {
private static final Logger logger = new NiFiLog(LoggerFactory.getLogger(NodeAuthorizationProvider.class));
private static final String CLUSTER_NODE_MANAGER_AUTHORITY_PROVIDER_PORT = "Cluster Manager Authority Provider Port";
private ProtocolContext<ProtocolMessage> authorityProviderProtocolContext;
private SocketConfiguration socketConfiguration;
private ClusterServiceLocator serviceLocator;
private ApplicationContext applicationContext;
private NiFiProperties properties;
@Override
public void initialize(AuthorityProviderInitializationContext initializationContext) throws ProviderCreationException {
}
@Override
public void onConfigured(final AuthorityProviderConfigurationContext configurationContext) throws ProviderCreationException {
// TODO clear user cache?
// if using multicast, then the authority provider's service is broadcasted
if (properties.getClusterProtocolUseMulticast()) {
// create the service discovery
final ClusterServiceDiscovery serviceDiscovery = new ClusterServiceDiscovery(
ClusterManagerAuthorizationProvider.AUTHORITY_PROVIDER_SERVIVE_NAME,
properties.getClusterProtocolMulticastAddress(),
applicationContext.getBean("protocolMulticastConfiguration", MulticastConfiguration.class),
applicationContext.getBean("protocolContext", ProtocolContext.class));
// create service location configuration
final ClusterServiceLocator.AttemptsConfig config = new ClusterServiceLocator.AttemptsConfig();
config.setNumAttempts(3);
config.setTimeBetweenAttempts(1);
config.setTimeBetweenAttempsUnit(TimeUnit.SECONDS);
serviceLocator = new ClusterServiceLocator(serviceDiscovery);
serviceLocator.setAttemptsConfig(config);
} else {
final InetSocketAddress serviceAddress = getClusterNodeManagerAuthorityProviderAddress(configurationContext);
final DiscoverableService service = new DiscoverableServiceImpl(ClusterManagerAuthorizationProvider.AUTHORITY_PROVIDER_SERVIVE_NAME, serviceAddress);
serviceLocator = new ClusterServiceLocator(service);
}
try {
// start the service locator
serviceLocator.start();
} catch (final IOException ioe) {
throw new ProviderCreationException(ioe);
}
// the socket configuration
socketConfiguration = applicationContext.getBean("protocolSocketConfiguration", SocketConfiguration.class);
// initialize the protocol context
authorityProviderProtocolContext = new JaxbProtocolContext<ProtocolMessage>(JaxbProtocolUtils.JAXB_CONTEXT);
}
private InetSocketAddress getClusterNodeManagerAuthorityProviderAddress(final AuthorityProviderConfigurationContext configurationContext) {
try {
String socketAddress = properties.getProperty(CLUSTER_NODE_UNICAST_MANAGER_ADDRESS);
if (StringUtils.isBlank(socketAddress)) {
socketAddress = "localhost";
}
return InetSocketAddress.createUnresolved(socketAddress, getClusterNodeManagerAuthorityProviderPort(configurationContext));
} catch (Exception ex) {
throw new ProviderCreationException("Invalid cluster manager authority provider address/port due to: " + ex, ex);
}
}
private Integer getClusterNodeManagerAuthorityProviderPort(final AuthorityProviderConfigurationContext configurationContext) {
final String nodeAuthorityProviderPort = configurationContext.getProperty(CLUSTER_NODE_MANAGER_AUTHORITY_PROVIDER_PORT);
if (nodeAuthorityProviderPort == null || nodeAuthorityProviderPort.trim().isEmpty()) {
throw new ProviderCreationException("The cluster manager authority provider port must be specified.");
}
return Integer.parseInt(nodeAuthorityProviderPort);
}
@Override
public void setAuthorities(String dn, Set<Authority> authorities) throws AuthorityAccessException {
throw new AuthorityAccessException("Nodes are not allowed to set user authorities.");
}
@Override
public void addUser(String dn, String group) throws IdentityAlreadyExistsException, AuthorityAccessException {
throw new AuthorityAccessException("Nodes are not allowed to add users.");
}
@Override
public boolean doesDnExist(String dn) throws AuthorityAccessException {
// create message
final DoesDnExistMessage msg = new DoesDnExistMessage();
msg.setDn(dn);
Socket socket = null;
try {
final InetSocketAddress socketAddress = getServiceAddress();
if (socketAddress == null) {
throw new AuthorityAccessException("Cluster Authority Provider's address is not known.");
}
try {
// create a socket
socket = SocketUtils.createSocket(socketAddress, socketConfiguration);
} catch (final IOException ioe) {
throw new AuthorityAccessException("Failed to create socket due to: " + ioe, ioe);
}
try {
// marshal message to output stream
final ProtocolMessageMarshaller marshaller = authorityProviderProtocolContext.createMarshaller();
marshaller.marshal(msg, socket.getOutputStream());
} catch (final IOException ioe) {
throw new AuthorityAccessException("Failed marshalling '" + msg.getType() + "' protocol message due to: " + ioe, ioe);
}
try {
// unmarshall response and return
final ProtocolMessageUnmarshaller<ProtocolMessage> unmarshaller = authorityProviderProtocolContext.createUnmarshaller();
final DoesDnExistMessage response = (DoesDnExistMessage) unmarshaller.unmarshal(socket.getInputStream());
// check if there was an exception
if (response.wasException()) {
throw new AuthorityAccessException(response.getExceptionMessage());
}
// return provider's response
return response.getResponse();
} catch (final IOException ioe) {
throw new AuthorityAccessException("Failed unmarshalling '" + msg.getType() + "' response protocol message due to: " + ioe, ioe);
}
} finally {
SocketUtils.closeQuietly(socket);
}
}
@Override
public Set<Authority> getAuthorities(String dn) throws UnknownIdentityException, AuthorityAccessException {
// create message
final GetAuthoritiesMessage msg = new GetAuthoritiesMessage();
msg.setDn(dn);
Socket socket = null;
try {
final InetSocketAddress socketAddress = getServiceAddress();
if (socketAddress == null) {
throw new AuthorityAccessException("Cluster Authority Provider's address is not known.");
}
try {
// create a socket
socket = SocketUtils.createSocket(socketAddress, socketConfiguration);
} catch (final IOException ioe) {
throw new AuthorityAccessException("Failed to create socket due to: " + ioe, ioe);
}
try {
// marshal message to output stream
final ProtocolMessageMarshaller marshaller = authorityProviderProtocolContext.createMarshaller();
marshaller.marshal(msg, socket.getOutputStream());
} catch (final IOException ioe) {
throw new AuthorityAccessException("Failed marshalling '" + msg.getType() + "' protocol message due to: " + ioe, ioe);
}
try {
// unmarshall response and return
final ProtocolMessageUnmarshaller<ProtocolMessage> unmarshaller = authorityProviderProtocolContext.createUnmarshaller();
final GetAuthoritiesMessage response = (GetAuthoritiesMessage) unmarshaller.unmarshal(socket.getInputStream());
// check if there was an exception
if (response.wasException()) {
if (isException(UnknownIdentityException.class, response)) {
throw new UnknownIdentityException(response.getExceptionMessage());
} else {
throw new AuthorityAccessException(response.getExceptionMessage());
}
}
// return provider's response
return response.getResponse();
} catch (final IOException ioe) {
throw new AuthorityAccessException("Failed unmarshalling '" + msg.getType() + "' response protocol message due to: " + ioe, ioe);
}
} finally {
SocketUtils.closeQuietly(socket);
}
}
@Override
public Set<String> getUsers(Authority authority) throws AuthorityAccessException {
throw new AuthorityAccessException("Nodes are not allowed to get users for a given authority.");
}
@Override
public void revokeUser(String dn) throws UnknownIdentityException, AuthorityAccessException {
throw new AuthorityAccessException("Nodes are not allowed to revoke users.");
}
@Override
public void setUsersGroup(Set<String> dns, String group) throws UnknownIdentityException, AuthorityAccessException {
throw new AuthorityAccessException("Nodes are not allowed to set user groups.");
}
@Override
public void ungroupUser(String dn) throws UnknownIdentityException, AuthorityAccessException {
throw new AuthorityAccessException("Nodes are not allowed to ungroup users.");
}
@Override
public void ungroup(String group) throws AuthorityAccessException {
throw new AuthorityAccessException("Nodes are not allowed to ungroup.");
}
@Override
public DownloadAuthorization authorizeDownload(List<String> dnChain, Map<String, String> attributes) throws UnknownIdentityException, AuthorityAccessException {
return DownloadAuthorization.approved();
}
@Override
public String getGroupForUser(String dn) throws UnknownIdentityException, AuthorityAccessException {
// create message
final GetGroupForUserMessage msg = new GetGroupForUserMessage();
msg.setDn(dn);
Socket socket = null;
try {
final InetSocketAddress socketAddress = getServiceAddress();
if (socketAddress == null) {
throw new AuthorityAccessException("Cluster Authority Provider's address is not known.");
}
try {
// create a socket
socket = SocketUtils.createSocket(socketAddress, socketConfiguration);
} catch (final IOException ioe) {
throw new AuthorityAccessException("Failed to create socket due to: " + ioe, ioe);
}
try {
// marshal message to output stream
final ProtocolMessageMarshaller marshaller = authorityProviderProtocolContext.createMarshaller();
marshaller.marshal(msg, socket.getOutputStream());
} catch (final IOException ioe) {
throw new AuthorityAccessException("Failed marshalling '" + msg.getType() + "' protocol message due to: " + ioe, ioe);
}
try {
// unmarshall response and return
final ProtocolMessageUnmarshaller<ProtocolMessage> unmarshaller = authorityProviderProtocolContext.createUnmarshaller();
final GetGroupForUserMessage response = (GetGroupForUserMessage) unmarshaller.unmarshal(socket.getInputStream());
// check if there was an exception
if (response.wasException()) {
if (isException(UnknownIdentityException.class, response)) {
throw new UnknownIdentityException(response.getExceptionMessage());
} else {
throw new AuthorityAccessException(response.getExceptionMessage());
}
}
return response.getResponse();
} catch (final IOException ioe) {
throw new AuthorityAccessException("Failed unmarshalling '" + msg.getType() + "' response protocol message due to: " + ioe, ioe);
}
} finally {
SocketUtils.closeQuietly(socket);
}
}
@Override
public void revokeGroup(String group) throws UnknownIdentityException, AuthorityAccessException {
throw new AuthorityAccessException("Nodes are not allowed to revoke groups.");
}
@Override
public void preDestruction() throws ProviderDestructionException {
try {
if (serviceLocator != null && serviceLocator.isRunning()) {
serviceLocator.stop();
}
} catch (final IOException ioe) {
throw new ProviderDestructionException(ioe);
}
}
@Override
@AuthorityProviderContext
public void setApplicationContext(final ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
@AuthorityProviderContext
public void setNiFiProperties(NiFiProperties properties) {
this.properties = properties;
}
private InetSocketAddress getServiceAddress() {
final DiscoverableService service = serviceLocator.getService();
if (service != null) {
return service.getServiceAddress();
}
return null;
}
private boolean isException(final Class<? extends Exception> exception, final ProtocolMessage protocolMessage) {
if (protocolMessage.wasException()) {
return exception.getName().equals(protocolMessage.getExceptionClass());
} else {
return false;
}
}
}

View File

@ -1,55 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.cluster.authorization.protocol.message;
import javax.xml.bind.annotation.XmlRootElement;
import org.apache.nifi.cluster.authorization.protocol.message.ProtocolMessage.MessageType;
/**
*/
@XmlRootElement(name = "doesDnExistMessage")
public class DoesDnExistMessage extends ProtocolMessage {
private String dn;
private boolean response;
public DoesDnExistMessage() {
}
@Override
public MessageType getType() {
return MessageType.DOES_DN_EXIST;
}
public String getDn() {
return dn;
}
public void setDn(String dn) {
this.dn = dn;
}
public boolean getResponse() {
return response;
}
public void setResponse(boolean response) {
this.response = response;
}
}

View File

@ -1,57 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.cluster.authorization.protocol.message;
import java.util.HashSet;
import java.util.Set;
import javax.xml.bind.annotation.XmlRootElement;
import org.apache.nifi.authorization.Authority;
/**
*/
@XmlRootElement(name = "getAuthoritiesMessage")
public class GetAuthoritiesMessage extends ProtocolMessage {
private String dn;
private Set<Authority> response = new HashSet<>();
public GetAuthoritiesMessage() {
}
@Override
public MessageType getType() {
return MessageType.GET_AUTHORITIES;
}
public String getDn() {
return dn;
}
public void setDn(String dn) {
this.dn = dn;
}
public Set<Authority> getResponse() {
return response;
}
public void setResponse(Set<Authority> response) {
this.response = response;
}
}

View File

@ -1,56 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.cluster.authorization.protocol.message;
/**
*/
public abstract class ProtocolMessage {
private String exceptionClass;
private String exceptionMessage;
public static enum MessageType {
DOES_DN_EXIST,
GET_AUTHORITIES,
GET_USERS,
GET_GROUP_FOR_USER
}
public abstract MessageType getType();
public boolean wasException() {
return exceptionClass != null;
}
public String getExceptionMessage() {
return exceptionMessage;
}
public void setExceptionMessage(final String exceptionMessage) {
this.exceptionMessage = exceptionMessage;
}
public String getExceptionClass() {
return exceptionClass;
}
public void setExceptionClass(String exceptionClass) {
this.exceptionClass = exceptionClass;
}
}

View File

@ -1,41 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.cluster.authorization.protocol.message.jaxb;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
/**
*/
public final class JaxbProtocolUtils {
public static final String JAXB_CONTEXT_PATH = ObjectFactory.class.getPackage().getName();
public static final JAXBContext JAXB_CONTEXT = initializeJaxbContext();
/**
* Load the JAXBContext version.
*/
private static JAXBContext initializeJaxbContext() {
try {
return JAXBContext.newInstance(JAXB_CONTEXT_PATH);
} catch (JAXBException e) {
throw new RuntimeException("Unable to create JAXBContext.");
}
}
}

View File

@ -1,44 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.cluster.authorization.protocol.message.jaxb;
import javax.xml.bind.annotation.XmlRegistry;
import org.apache.nifi.cluster.authorization.protocol.message.DoesDnExistMessage;
import org.apache.nifi.cluster.authorization.protocol.message.GetAuthoritiesMessage;
import org.apache.nifi.cluster.authorization.protocol.message.GetGroupForUserMessage;
/**
*/
@XmlRegistry
public class ObjectFactory {
public ObjectFactory() {
}
public DoesDnExistMessage createDoesDnExistMessage() {
return new DoesDnExistMessage();
}
public GetAuthoritiesMessage createGetAuthoritiesMessage() {
return new GetAuthoritiesMessage();
}
public GetGroupForUserMessage createGetGroupForUserMessage() {
return new GetGroupForUserMessage();
}
}

Some files were not shown because too many files have changed in this diff Show More