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);
}
}
}
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();
}
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();
}
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();
});
}
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();
});
}
}
Aggregations