[
https://issues.apache.org/jira/browse/NIFI-1952?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15329404#comment-15329404
]
ASF GitHub Bot commented on NIFI-1952:
--------------------------------------
Github user mcgilman commented on a diff in the pull request:
https://github.com/apache/nifi/pull/526#discussion_r66959598
--- Diff:
nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/AccessPolicyResource.java
---
@@ -0,0 +1,376 @@
+/*
+ * 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.web.api;
+
+import com.wordnik.swagger.annotations.Api;
+import com.wordnik.swagger.annotations.ApiOperation;
+import com.wordnik.swagger.annotations.ApiParam;
+import com.wordnik.swagger.annotations.ApiResponse;
+import com.wordnik.swagger.annotations.ApiResponses;
+import com.wordnik.swagger.annotations.Authorization;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.nifi.authorization.Authorizer;
+import org.apache.nifi.authorization.RequestAction;
+import org.apache.nifi.authorization.resource.Authorizable;
+import org.apache.nifi.web.NiFiServiceFacade;
+import org.apache.nifi.web.Revision;
+import org.apache.nifi.web.UpdateResult;
+import org.apache.nifi.web.api.dto.AccessPolicyDTO;
+import org.apache.nifi.web.api.entity.AccessPolicyEntity;
+import org.apache.nifi.web.api.request.ClientIdParameter;
+import org.apache.nifi.web.api.request.LongParameter;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.DefaultValue;
+import javax.ws.rs.GET;
+import javax.ws.rs.HttpMethod;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import java.net.URI;
+
+/**
+ * RESTful endpoint for managing access policies.
+ */
+@Path("/policies")
+@Api(
+ value = "/policies",
+ description = "Endpoint for managing access policies."
+)
+public class AccessPolicyResource extends ApplicationResource {
+
+ final private NiFiServiceFacade serviceFacade;
+ final private Authorizer authorizer;
+
+ public AccessPolicyResource(NiFiServiceFacade serviceFacade,
Authorizer authorizer) {
+ this.serviceFacade = serviceFacade;
+ this.authorizer = authorizer;
+ }
+
+ /**
+ * Populates the uri for the specified access policy.
+ *
+ * @param accessPolicyEntity accessPolicyEntity
+ * @return accessPolicyEntity
+ */
+ public AccessPolicyEntity
populateRemainingAccessPolicyEntityContent(AccessPolicyEntity
accessPolicyEntity) {
+ if (accessPolicyEntity.getComponent() != null) {
+
populateRemainingAccessPolicyContent(accessPolicyEntity.getComponent());
+ }
+ return accessPolicyEntity;
+ }
+
+ /**
+ * Populates the uri for the specified accessPolicy.
+ */
+ public AccessPolicyDTO
populateRemainingAccessPolicyContent(AccessPolicyDTO accessPolicy) {
+ // populate the access policy href
+ accessPolicy.setUri(generateResourceUri("policies",
accessPolicy.getId()));
+ return accessPolicy;
+ }
+
+ /**
+ * Creates a new access policy.
+ *
+ * @param httpServletRequest request
+ * @param accessPolicyEntity An accessPolicyEntity.
+ * @return An accessPolicyEntity.
+ */
+ @POST
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Produces(MediaType.APPLICATION_JSON)
+ // TODO - @PreAuthorize("hasRole('ROLE_DFM')")
+ @ApiOperation(
+ value = "Creates an access policy",
+ response = AccessPolicyEntity.class,
+ authorizations = {
+ @Authorization(value = "Data Flow Manager", type =
"ROLE_DFM")
+ }
+ )
+ @ApiResponses(
+ value = {
+ @ApiResponse(code = 400, message = "NiFi was unable to
complete the request because it was invalid. The request should not be retried
without modification."),
+ @ApiResponse(code = 401, message = "Client could not
be authenticated."),
+ @ApiResponse(code = 403, message = "Client is not
authorized to make this request."),
+ @ApiResponse(code = 404, message = "The specified
resource could not be found."),
+ @ApiResponse(code = 409, message = "The request was
valid but NiFi was not in the appropriate state to process it. Retrying the
same request later may be successful.")
+ }
+ )
+ public Response createAccessPolicy(
+ @Context final HttpServletRequest httpServletRequest,
+ @ApiParam(
+ value = "The access policy configuration details.",
+ required = true
+ ) final AccessPolicyEntity accessPolicyEntity) {
+
+ if (accessPolicyEntity == null ||
accessPolicyEntity.getComponent() == null) {
+ throw new IllegalArgumentException("Access policy details must
be specified.");
+ }
+
+ if (accessPolicyEntity.getComponent().getId() != null) {
+ throw new IllegalArgumentException("Access policy ID cannot be
specified.");
+ }
+
+ if (isReplicateRequest()) {
+ return replicate(HttpMethod.POST, accessPolicyEntity);
+ }
+
+ // handle expects request (usually from the cluster manager)
+ final boolean validationPhase =
isValidationPhase(httpServletRequest);
+ if (validationPhase || !isTwoPhaseRequest(httpServletRequest)) {
+ // authorize access
+ serviceFacade.authorizeAccess(lookup -> {
+ final Authorizable accessPolicies =
lookup.getAccessPoliciesAuthorizable();
+ accessPolicies.authorize(authorizer, RequestAction.WRITE);
+ });
+ }
+ if (validationPhase) {
+ return generateContinueResponse().build();
+ }
+
+ // set the access policy id as appropriate
+ accessPolicyEntity.getComponent().setId(generateUuid());
+
+ // create the access policy and generate the json
+ final AccessPolicyEntity entity =
serviceFacade.createAccessPolicy(accessPolicyEntity.getComponent());
+ populateRemainingAccessPolicyEntityContent(entity);
+
+ // build the response
+ return
clusterContext(generateCreatedResponse(URI.create(entity.getComponent().getUri()),
entity)).build();
+ }
+
+ /**
+ * Retrieves the specified access policy.
+ *
+ * @param id The id of the access policy to retrieve
+ * @return An accessPolicyEntity.
+ */
+ @GET
+ @Consumes(MediaType.WILDCARD)
+ @Produces(MediaType.APPLICATION_JSON)
+ @Path("{id}")
+ // TODO - @PreAuthorize("hasAnyRole('ROLE_MONITOR', 'ROLE_DFM',
'ROLE_ADMIN')")
+ @ApiOperation(
+ value = "Gets an access policy",
+ response = AccessPolicyEntity.class,
+ authorizations = {
+ @Authorization(value = "Read Only", type =
"ROLE_MONITOR"),
+ @Authorization(value = "Data Flow Manager", type =
"ROLE_DFM"),
+ @Authorization(value = "Administrator", type =
"ROLE_ADMIN")
+ }
+ )
+ @ApiResponses(
+ value = {
+ @ApiResponse(code = 400, message = "NiFi was unable to
complete the request because it was invalid. The request should not be retried
without modification."),
+ @ApiResponse(code = 401, message = "Client could not
be authenticated."),
+ @ApiResponse(code = 403, message = "Client is not
authorized to make this request."),
+ @ApiResponse(code = 404, message = "The specified
resource could not be found."),
+ @ApiResponse(code = 409, message = "The request was
valid but NiFi was not in the appropriate state to process it. Retrying the
same request later may be successful.")
+ }
+ )
+ public Response getAccessPolicy(
+ @ApiParam(
+ value = "The access policy id.",
+ required = true
+ )
+ @PathParam("id") final String id) {
+
+ if (isReplicateRequest()) {
+ return replicate(HttpMethod.GET);
+ }
+
+ // authorize access
+ serviceFacade.authorizeAccess(lookup -> {
+ final Authorizable accessPolicy =
lookup.getAccessPolicyAuthorizable(id);
+ accessPolicy.authorize(authorizer, RequestAction.READ);
+ });
+
+ // get the access policy
+ final AccessPolicyEntity entity =
serviceFacade.getAccessPolicy(id);
+ populateRemainingAccessPolicyEntityContent(entity);
+
+ return clusterContext(generateOkResponse(entity)).build();
+ }
+
+ /**
+ * Updates an access policy.
+ *
+ * @param httpServletRequest request
+ * @param id The id of the access policy to update.
+ * @param accessPolicyEntity An accessPolicyEntity.
+ * @return An accessPolicyEntity.
+ */
+ @PUT
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Produces(MediaType.APPLICATION_JSON)
+ @Path("{id}")
+ // TODO - @PreAuthorize("hasRole('ROLE_DFM')")
+ @ApiOperation(
+ value = "Updates a access policy",
+ response = AccessPolicyEntity.class,
+ authorizations = {
+ @Authorization(value = "Data Flow Manager", type =
"ROLE_DFM")
+ }
+ )
+ @ApiResponses(
+ value = {
+ @ApiResponse(code = 400, message = "NiFi was unable to
complete the request because it was invalid. The request should not be retried
without modification."),
+ @ApiResponse(code = 401, message = "Client could not
be authenticated."),
+ @ApiResponse(code = 403, message = "Client is not
authorized to make this request."),
+ @ApiResponse(code = 404, message = "The specified
resource could not be found."),
+ @ApiResponse(code = 409, message = "The request was
valid but NiFi was not in the appropriate state to process it. Retrying the
same request later may be successful.")
+ }
+ )
+ public Response updateAccessPolicy(
+ @Context final HttpServletRequest httpServletRequest,
+ @ApiParam(
+ value = "The access policy id.",
+ required = true
+ )
+ @PathParam("id") final String id,
+ @ApiParam(
+ value = "The access policy configuration details.",
+ required = true
+ ) final AccessPolicyEntity accessPolicyEntity) {
+
+ if (accessPolicyEntity == null ||
accessPolicyEntity.getComponent() == null) {
+ throw new IllegalArgumentException("Access policy details must
be specified.");
+ }
+
+ if (accessPolicyEntity.getRevision() == null) {
+ throw new IllegalArgumentException("Revision must be
specified.");
+ }
+
+ // ensure the ids are the same
+ final AccessPolicyDTO accessPolicyDTO =
accessPolicyEntity.getComponent();
+ if (!id.equals(accessPolicyDTO.getId())) {
+ throw new IllegalArgumentException(String.format("The access
policy id (%s) in the request body does not equal the "
+ + "access policy id of the requested resource (%s).",
accessPolicyDTO.getId(), id));
+ }
+
+ if (isReplicateRequest()) {
+ return replicate(HttpMethod.PUT, accessPolicyEntity);
+ }
+
+ // Extract the revision
+ final Revision revision = getRevision(accessPolicyEntity, id);
+ return withWriteLock(
+ serviceFacade,
+ revision,
+ lookup -> {
+ final Authorizable accessPolicy =
lookup.getAccessPolicyAuthorizable(id);
+ accessPolicy.authorize(authorizer,
RequestAction.WRITE);
+ },
+ null,
+ () -> {
+ // update the access policy
+ final UpdateResult<AccessPolicyEntity> updateResult =
serviceFacade.updateAccessPolicy(revision, accessPolicyDTO);
+
+ // get the results
+ final AccessPolicyEntity entity =
updateResult.getResult();
+ populateRemainingAccessPolicyEntityContent(entity);
+
+ if (updateResult.isNew()) {
+ return
clusterContext(generateCreatedResponse(URI.create(entity.getComponent().getUri()),
entity)).build();
+ } else {
+ return
clusterContext(generateOkResponse(entity)).build();
+ }
+ }
+ );
+ }
+
+ /**
+ * Removes the specified access policy.
+ *
+ * @param httpServletRequest request
+ * @param version The revision is used to verify the client is working
with
+ * the latest version of the flow.
+ * @param clientId Optional client id. If the client id is not
specified, a
+ * new one will be generated. This value (whether specified or
generated) is
+ * included in the response.
+ * @param id The id of the access policy to remove.
+ * @return A entity containing the client id and an updated revision.
+ */
+ @DELETE
+ @Consumes(MediaType.WILDCARD)
+ @Produces(MediaType.APPLICATION_JSON)
+ @Path("{id}")
+ // TODO - @PreAuthorize("hasRole('ROLE_DFM')")
+ @ApiOperation(
+ value = "Deletes an access policy",
+ response = AccessPolicyEntity.class,
+ authorizations = {
+ @Authorization(value = "Data Flow Manager", type =
"ROLE_DFM")
+ }
+ )
+ @ApiResponses(
+ value = {
+ @ApiResponse(code = 400, message = "NiFi was unable to
complete the request because it was invalid. The request should not be retried
without modification."),
+ @ApiResponse(code = 401, message = "Client could not
be authenticated."),
+ @ApiResponse(code = 403, message = "Client is not
authorized to make this request."),
+ @ApiResponse(code = 404, message = "The specified
resource could not be found."),
+ @ApiResponse(code = 409, message = "The request was
valid but NiFi was not in the appropriate state to process it. Retrying the
same request later may be successful.")
+ }
+ )
+ public Response removeAccessPolicy(
+ @Context final HttpServletRequest httpServletRequest,
+ @ApiParam(
+ value = "The revision is used to verify the client is
working with the latest version of the flow.",
+ required = false
+ )
+ @QueryParam(VERSION) final LongParameter version,
+ @ApiParam(
+ value = "If the client id is not specified, new one
will be generated. This value (whether specified or generated) is included in
the response.",
+ required = false
+ )
+ @QueryParam(CLIENT_ID) @DefaultValue(StringUtils.EMPTY) final
ClientIdParameter clientId,
+ @ApiParam(
+ value = "The access policy id.",
+ required = true
+ )
+ @PathParam("id") final String id) {
+
+ if (isReplicateRequest()) {
+ return replicate(HttpMethod.DELETE);
+ }
+
+ // handle expects request (usually from the cluster manager)
+ final Revision revision = new Revision(version == null ? null :
version.getLong(), clientId.getClientId(), id);
+ return withWriteLock(
+ serviceFacade,
+ revision,
+ lookup -> {
+ final Authorizable accessPolicy =
lookup.getAccessPolicyAuthorizable(id);
+ accessPolicy.authorize(authorizer, RequestAction.READ);
+ },
+ () -> {},
--- End diff --
Can pass in null for the verifier.
> Create REST endpoints for user/group/policy management
> ------------------------------------------------------
>
> Key: NIFI-1952
> URL: https://issues.apache.org/jira/browse/NIFI-1952
> Project: Apache NiFi
> Issue Type: Sub-task
> Components: Core Framework
> Affects Versions: 1.0.0
> Reporter: Jeff Storck
> Assignee: Jeff Storck
> Fix For: 1.0.0
>
>
> REST endpoints are needed to provide CRUD capability for mutable authorizers
> (extensions of AbstractPolicyBasedAuthorizer) to manage users, groups, and
> policies.
--
This message was sent by Atlassian JIRA
(v6.3.4#6332)