Search in sources :

Example 21 with AccessDeniedException

use of org.apache.nifi.authorization.AccessDeniedException in project nifi by apache.

the class AccessResource method createAccessTokenFromTicket.

/**
 * Creates a token for accessing the REST API via Kerberos ticket exchange / SPNEGO negotiation.
 *
 * @param httpServletRequest the servlet request
 * @return A JWT (string)
 */
@POST
@Consumes(MediaType.TEXT_PLAIN)
@Produces(MediaType.TEXT_PLAIN)
@Path("/kerberos")
@ApiOperation(value = "Creates a token for accessing the REST API via Kerberos ticket exchange / SPNEGO negotiation", notes = "The token returned is formatted as a JSON Web Token (JWT). The token is base64 encoded and comprised of three parts. The header, " + "the body, and the signature. The expiration of the token is a contained within the body. The token can be used in the Authorization header " + "in the format 'Authorization: Bearer <token>'.", response = String.class)
@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 = "NiFi was unable to complete the request because it did not contain a valid Kerberos " + "ticket in the Authorization header. Retry this request after initializing a ticket with kinit and " + "ensuring your browser is configured to support SPNEGO."), @ApiResponse(code = 409, message = "Unable to create access token because NiFi is not in the appropriate state. (i.e. may not be configured to support Kerberos login."), @ApiResponse(code = 500, message = "Unable to create access token because an unexpected error occurred.") })
public Response createAccessTokenFromTicket(@Context HttpServletRequest httpServletRequest) {
    // only support access tokens when communicating over HTTPS
    if (!httpServletRequest.isSecure()) {
        throw new IllegalStateException("Access tokens are only issued over HTTPS.");
    }
    // If Kerberos Service Principal and keytab location not configured, throws exception
    if (!properties.isKerberosSpnegoSupportEnabled() || kerberosService == null) {
        throw new IllegalStateException("Kerberos ticket login not supported by this NiFi.");
    }
    String authorizationHeaderValue = httpServletRequest.getHeader(KerberosService.AUTHORIZATION_HEADER_NAME);
    if (!kerberosService.isValidKerberosHeader(authorizationHeaderValue)) {
        final Response response = generateNotAuthorizedResponse().header(KerberosService.AUTHENTICATION_CHALLENGE_HEADER_NAME, KerberosService.AUTHORIZATION_NEGOTIATE).build();
        return response;
    } else {
        try {
            // attempt to authenticate
            Authentication authentication = kerberosService.validateKerberosTicket(httpServletRequest);
            if (authentication == null) {
                throw new IllegalArgumentException("Request is not HTTPS or Kerberos ticket missing or malformed");
            }
            final String expirationFromProperties = properties.getKerberosAuthenticationExpiration();
            long expiration = FormatUtils.getTimeDuration(expirationFromProperties, TimeUnit.MILLISECONDS);
            final String identity = authentication.getName();
            expiration = validateTokenExpiration(expiration, identity);
            // create the authentication token
            final LoginAuthenticationToken loginAuthenticationToken = new LoginAuthenticationToken(identity, expiration, "KerberosService");
            // generate JWT for response
            final String token = jwtService.generateSignedToken(loginAuthenticationToken);
            // build the response
            final URI uri = URI.create(generateResourceUri("access", "kerberos"));
            return generateCreatedResponse(uri, token).build();
        } catch (final AuthenticationException e) {
            throw new AccessDeniedException(e.getMessage(), e);
        }
    }
}
Also used : Response(javax.ws.rs.core.Response) AuthenticationResponse(org.apache.nifi.authentication.AuthenticationResponse) AuthenticationSuccessResponse(com.nimbusds.openid.connect.sdk.AuthenticationSuccessResponse) AuthenticationErrorResponse(com.nimbusds.openid.connect.sdk.AuthenticationErrorResponse) HttpServletResponse(javax.servlet.http.HttpServletResponse) ApiResponse(io.swagger.annotations.ApiResponse) AccessDeniedException(org.apache.nifi.authorization.AccessDeniedException) AuthenticationException(org.springframework.security.core.AuthenticationException) InvalidAuthenticationException(org.apache.nifi.web.security.InvalidAuthenticationException) Authentication(org.springframework.security.core.Authentication) LoginAuthenticationToken(org.apache.nifi.web.security.token.LoginAuthenticationToken) URI(java.net.URI) Path(javax.ws.rs.Path) POST(javax.ws.rs.POST) Consumes(javax.ws.rs.Consumes) Produces(javax.ws.rs.Produces) ApiOperation(io.swagger.annotations.ApiOperation) ApiResponses(io.swagger.annotations.ApiResponses)

Example 22 with AccessDeniedException

use of org.apache.nifi.authorization.AccessDeniedException in project nifi by apache.

the class AccessResource method createDownloadToken.

/**
 * Creates a single use access token for downloading FlowFile content.
 *
 * @param httpServletRequest the servlet request
 * @return A token (string)
 */
@POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@Produces(MediaType.TEXT_PLAIN)
@Path("/download-token")
@ApiOperation(value = "Creates a single use access token for downloading FlowFile content.", notes = "The token returned is a base64 encoded string. It is valid for a single request up to five minutes from being issued. " + "It is used as a query parameter name 'access_token'.", response = String.class)
@ApiResponses(value = { @ApiResponse(code = 403, message = "Client is not authorized to make this request."), @ApiResponse(code = 409, message = "Unable to create the download token because NiFi is not in the appropriate state. " + "(i.e. may not have any tokens to grant or be configured to support username/password login)"), @ApiResponse(code = 500, message = "Unable to create download token because an unexpected error occurred.") })
public Response createDownloadToken(@Context HttpServletRequest httpServletRequest) {
    // only support access tokens when communicating over HTTPS
    if (!httpServletRequest.isSecure()) {
        throw new IllegalStateException("Download tokens are only issued over HTTPS.");
    }
    final NiFiUser user = NiFiUserUtils.getNiFiUser();
    if (user == null) {
        throw new AccessDeniedException("No user authenticated in the request.");
    }
    final OtpAuthenticationToken authenticationToken = new OtpAuthenticationToken(user.getIdentity());
    // generate otp for response
    final String token = otpService.generateDownloadToken(authenticationToken);
    // build the response
    final URI uri = URI.create(generateResourceUri("access", "download-token"));
    return generateCreatedResponse(uri, token).build();
}
Also used : AccessDeniedException(org.apache.nifi.authorization.AccessDeniedException) OtpAuthenticationToken(org.apache.nifi.web.security.token.OtpAuthenticationToken) NiFiUser(org.apache.nifi.authorization.user.NiFiUser) URI(java.net.URI) Path(javax.ws.rs.Path) POST(javax.ws.rs.POST) Consumes(javax.ws.rs.Consumes) Produces(javax.ws.rs.Produces) ApiOperation(io.swagger.annotations.ApiOperation) ApiResponses(io.swagger.annotations.ApiResponses)

Example 23 with AccessDeniedException

use of org.apache.nifi.authorization.AccessDeniedException in project nifi by apache.

the class AccessResource method getAccessStatus.

/**
 * Gets the status the client's access.
 *
 * @param httpServletRequest the servlet request
 * @return A accessStatusEntity
 */
@GET
@Consumes(MediaType.WILDCARD)
@Produces(MediaType.APPLICATION_JSON)
@Path("")
@ApiOperation(value = "Gets the status the client's access", notes = NON_GUARANTEED_ENDPOINT, response = AccessStatusEntity.class)
@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 = "Unable to determine access status because the client could not be authenticated."), @ApiResponse(code = 403, message = "Unable to determine access status because the client is not authorized to make this request."), @ApiResponse(code = 409, message = "Unable to determine access status because NiFi is not in the appropriate state."), @ApiResponse(code = 500, message = "Unable to determine access status because an unexpected error occurred.") })
public Response getAccessStatus(@Context HttpServletRequest httpServletRequest) {
    // only consider user specific access over https
    if (!httpServletRequest.isSecure()) {
        throw new IllegalStateException("User authentication/authorization is only supported when running over HTTPS.");
    }
    final AccessStatusDTO accessStatus = new AccessStatusDTO();
    try {
        final X509Certificate[] certificates = certificateExtractor.extractClientCertificate(httpServletRequest);
        // if there is not certificate, consider a token
        if (certificates == null) {
            // look for an authorization token
            final String authorization = httpServletRequest.getHeader(JwtAuthenticationFilter.AUTHORIZATION);
            // if there is no authorization header, we don't know the user
            if (authorization == null) {
                accessStatus.setStatus(AccessStatusDTO.Status.UNKNOWN.name());
                accessStatus.setMessage("No credentials supplied, unknown user.");
            } else {
                try {
                    // Extract the Base64 encoded token from the Authorization header
                    final String token = StringUtils.substringAfterLast(authorization, " ");
                    final JwtAuthenticationRequestToken jwtRequest = new JwtAuthenticationRequestToken(token, httpServletRequest.getRemoteAddr());
                    final NiFiAuthenticationToken authenticationResponse = (NiFiAuthenticationToken) jwtAuthenticationProvider.authenticate(jwtRequest);
                    final NiFiUser nifiUser = ((NiFiUserDetails) authenticationResponse.getDetails()).getNiFiUser();
                    // set the user identity
                    accessStatus.setIdentity(nifiUser.getIdentity());
                    // attempt authorize to /flow
                    accessStatus.setStatus(AccessStatusDTO.Status.ACTIVE.name());
                    accessStatus.setMessage("You are already logged in.");
                } catch (JwtException e) {
                    throw new InvalidAuthenticationException(e.getMessage(), e);
                }
            }
        } else {
            try {
                final X509AuthenticationRequestToken x509Request = new X509AuthenticationRequestToken(httpServletRequest.getHeader(ProxiedEntitiesUtils.PROXY_ENTITIES_CHAIN), principalExtractor, certificates, httpServletRequest.getRemoteAddr());
                final NiFiAuthenticationToken authenticationResponse = (NiFiAuthenticationToken) x509AuthenticationProvider.authenticate(x509Request);
                final NiFiUser nifiUser = ((NiFiUserDetails) authenticationResponse.getDetails()).getNiFiUser();
                // set the user identity
                accessStatus.setIdentity(nifiUser.getIdentity());
                // attempt authorize to /flow
                accessStatus.setStatus(AccessStatusDTO.Status.ACTIVE.name());
                accessStatus.setMessage("You are already logged in.");
            } catch (final IllegalArgumentException iae) {
                throw new InvalidAuthenticationException(iae.getMessage(), iae);
            }
        }
    } catch (final UntrustedProxyException upe) {
        throw new AccessDeniedException(upe.getMessage(), upe);
    } catch (final AuthenticationServiceException ase) {
        throw new AdministrationException(ase.getMessage(), ase);
    }
    // create the entity
    final AccessStatusEntity entity = new AccessStatusEntity();
    entity.setAccessStatus(accessStatus);
    return generateOkResponse(entity).build();
}
Also used : AccessDeniedException(org.apache.nifi.authorization.AccessDeniedException) AccessStatusEntity(org.apache.nifi.web.api.entity.AccessStatusEntity) NiFiUser(org.apache.nifi.authorization.user.NiFiUser) JwtAuthenticationRequestToken(org.apache.nifi.web.security.jwt.JwtAuthenticationRequestToken) AccessStatusDTO(org.apache.nifi.web.api.dto.AccessStatusDTO) AdministrationException(org.apache.nifi.admin.service.AdministrationException) X509AuthenticationRequestToken(org.apache.nifi.web.security.x509.X509AuthenticationRequestToken) X509Certificate(java.security.cert.X509Certificate) InvalidAuthenticationException(org.apache.nifi.web.security.InvalidAuthenticationException) AuthenticationServiceException(org.springframework.security.authentication.AuthenticationServiceException) NiFiAuthenticationToken(org.apache.nifi.web.security.token.NiFiAuthenticationToken) UntrustedProxyException(org.apache.nifi.web.security.UntrustedProxyException) JwtException(io.jsonwebtoken.JwtException) NiFiUserDetails(org.apache.nifi.authorization.user.NiFiUserDetails) Path(javax.ws.rs.Path) Consumes(javax.ws.rs.Consumes) Produces(javax.ws.rs.Produces) GET(javax.ws.rs.GET) ApiOperation(io.swagger.annotations.ApiOperation) ApiResponses(io.swagger.annotations.ApiResponses)

Example 24 with AccessDeniedException

use of org.apache.nifi.authorization.AccessDeniedException in project nifi by apache.

the class SnippetResource method createSnippet.

/**
 * Creates a snippet based off the specified configuration.
 *
 * @param httpServletRequest request
 * @param requestSnippetEntity      A snippetEntity
 * @return A snippetEntity
 */
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(value = "Creates a snippet. The snippet will be automatically discarded if not used in a subsequent request after 1 minute.", response = SnippetEntity.class, authorizations = { @Authorization(value = "Read or Write - /{component-type}/{uuid} - For every component (all Read or all Write) in the Snippet and their descendant components") })
@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 createSnippet(@Context HttpServletRequest httpServletRequest, @ApiParam(value = "The snippet configuration details.", required = true) final SnippetEntity requestSnippetEntity) {
    if (requestSnippetEntity == null || requestSnippetEntity.getSnippet() == null) {
        throw new IllegalArgumentException("Snippet details must be specified.");
    }
    if (requestSnippetEntity.getSnippet().getId() != null) {
        throw new IllegalArgumentException("Snippet ID cannot be specified.");
    }
    if (requestSnippetEntity.getSnippet().getParentGroupId() == null) {
        throw new IllegalArgumentException("The parent Process Group of the snippet must be specified.");
    }
    if (isReplicateRequest()) {
        return replicate(HttpMethod.POST, requestSnippetEntity);
    }
    return withWriteLock(serviceFacade, requestSnippetEntity, lookup -> {
        final SnippetDTO snippetRequest = requestSnippetEntity.getSnippet();
        try {
            authorizeSnippetRequest(snippetRequest, authorizer, lookup, RequestAction.READ);
        } catch (final AccessDeniedException e) {
            authorizeSnippetRequest(snippetRequest, authorizer, lookup, RequestAction.WRITE);
        }
    }, null, (snippetEntity) -> {
        // set the processor id as appropriate
        snippetEntity.getSnippet().setId(generateUuid());
        // create the snippet
        final SnippetEntity entity = serviceFacade.createSnippet(snippetEntity.getSnippet());
        populateRemainingSnippetEntityContent(entity);
        // build the response
        return generateCreatedResponse(URI.create(entity.getSnippet().getUri()), entity).build();
    });
}
Also used : SnippetDTO(org.apache.nifi.web.api.dto.SnippetDTO) AccessDeniedException(org.apache.nifi.authorization.AccessDeniedException) SnippetEntity(org.apache.nifi.web.api.entity.SnippetEntity) POST(javax.ws.rs.POST) Consumes(javax.ws.rs.Consumes) Produces(javax.ws.rs.Produces) ApiOperation(io.swagger.annotations.ApiOperation) ApiResponses(io.swagger.annotations.ApiResponses)

Example 25 with AccessDeniedException

use of org.apache.nifi.authorization.AccessDeniedException in project nifi by apache.

the class VersionsResource method updateVersionControlRequest.

@PUT
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@Path("active-requests/{id}")
@ApiOperation(value = "Updates the request with the given ID", response = VersionControlInformationEntity.class, notes = NON_GUARANTEED_ENDPOINT, authorizations = { @Authorization(value = "Only the user that submitted the request can update it") })
@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 updateVersionControlRequest(@ApiParam("The request ID.") @PathParam("id") final String requestId, @ApiParam(value = "The version control component mapping.", required = true) final VersionControlComponentMappingEntity requestEntity) {
    // Verify request
    final RevisionDTO revisionDto = requestEntity.getProcessGroupRevision();
    if (revisionDto == null) {
        throw new IllegalArgumentException("Process Group Revision must be specified");
    }
    final VersionControlInformationDTO versionControlInfo = requestEntity.getVersionControlInformation();
    if (versionControlInfo == null) {
        throw new IllegalArgumentException("Version Control Information must be supplied");
    }
    if (versionControlInfo.getGroupId() == null) {
        throw new IllegalArgumentException("Version Control Information must supply Process Group ID");
    }
    if (versionControlInfo.getBucketId() == null) {
        throw new IllegalArgumentException("Version Control Information must supply Bucket ID");
    }
    if (versionControlInfo.getFlowId() == null) {
        throw new IllegalArgumentException("Version Control Information must supply Flow ID");
    }
    if (versionControlInfo.getRegistryId() == null) {
        throw new IllegalArgumentException("Version Control Information must supply Registry ID");
    }
    if (versionControlInfo.getVersion() == null) {
        throw new IllegalArgumentException("Version Control Information must supply Version");
    }
    final Map<String, String> mapping = requestEntity.getVersionControlComponentMapping();
    if (mapping == null) {
        throw new IllegalArgumentException("Version Control Component Mapping must be supplied");
    }
    // Replicate if necessary
    if (isReplicateRequest()) {
        return replicate(HttpMethod.PUT, requestEntity);
    }
    // Perform the update
    synchronized (activeRequestMonitor) {
        if (activeRequest == null) {
            throw new IllegalStateException("No Version Control Request with ID " + requestId + " is currently active");
        }
        if (!requestId.equals(activeRequest.getRequestId())) {
            throw new IllegalStateException("No Version Control Request with ID " + requestId + " is currently active");
        }
        if (activeRequest.isExpired()) {
            throw new IllegalStateException("Version Control Request with ID " + requestId + " has already expired");
        }
        if (activeRequest.isUpdatePerformed()) {
            throw new IllegalStateException("Version Control Request with ID " + requestId + " has already been performed");
        }
        final String groupId = requestEntity.getVersionControlInformation().getGroupId();
        if (!activeRequest.getProcessGroupId().equals(groupId)) {
            throw new IllegalStateException("Version Control Request with ID " + requestId + " was created for a different process group id");
        }
        final Revision groupRevision = new Revision(revisionDto.getVersion(), revisionDto.getClientId(), groupId);
        return withWriteLock(serviceFacade, requestEntity, groupRevision, lookup -> {
            final NiFiUser user = NiFiUserUtils.getNiFiUser();
            if (user == null) {
                throw new AccessDeniedException("Unknown user.");
            }
            if (!user.equals(activeRequest.getUser())) {
                throw new AccessDeniedException("Only the user that creates the Version Control Request can use it.");
            }
        }, null, (rev, mappingEntity) -> {
            // set the version control information
            final VersionControlInformationEntity responseEntity = serviceFacade.setVersionControlInformation(rev, groupId, mappingEntity.getVersionControlInformation(), mappingEntity.getVersionControlComponentMapping());
            // indicate that the active request has performed the update
            activeRequest.updatePerformed();
            return generateOkResponse(responseEntity).build();
        });
    }
}
Also used : AccessDeniedException(org.apache.nifi.authorization.AccessDeniedException) VersionControlInformationEntity(org.apache.nifi.web.api.entity.VersionControlInformationEntity) Revision(org.apache.nifi.web.Revision) NiFiUser(org.apache.nifi.authorization.user.NiFiUser) RevisionDTO(org.apache.nifi.web.api.dto.RevisionDTO) VersionControlInformationDTO(org.apache.nifi.web.api.dto.VersionControlInformationDTO) Path(javax.ws.rs.Path) Consumes(javax.ws.rs.Consumes) Produces(javax.ws.rs.Produces) ApiOperation(io.swagger.annotations.ApiOperation) PUT(javax.ws.rs.PUT) ApiResponses(io.swagger.annotations.ApiResponses)

Aggregations

AccessDeniedException (org.apache.nifi.authorization.AccessDeniedException)26 NiFiUser (org.apache.nifi.authorization.user.NiFiUser)12 ApiOperation (io.swagger.annotations.ApiOperation)6 ApiResponses (io.swagger.annotations.ApiResponses)6 QuerySubmission (org.apache.nifi.provenance.search.QuerySubmission)6 Test (org.junit.Test)6 URI (java.net.URI)5 ArrayList (java.util.ArrayList)5 HashMap (java.util.HashMap)5 Consumes (javax.ws.rs.Consumes)5 Produces (javax.ws.rs.Produces)5 ProvenanceEventRecord (org.apache.nifi.provenance.ProvenanceEventRecord)5 RepositoryConfiguration (org.apache.nifi.provenance.RepositoryConfiguration)5 StandardProvenanceEventRecord (org.apache.nifi.provenance.StandardProvenanceEventRecord)5 EventAuthorizer (org.apache.nifi.provenance.authorization.EventAuthorizer)5 IOException (java.io.IOException)4 Path (javax.ws.rs.Path)4 Collections (java.util.Collections)3 List (java.util.List)3 Map (java.util.Map)3