-
Notifications
You must be signed in to change notification settings - Fork 283
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add user id validation for create and update API (#533)
- Loading branch information
1 parent
7370eee
commit a9c816f
Showing
6 changed files
with
281 additions
and
121 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
34 changes: 34 additions & 0 deletions
34
metacat-main/src/main/java/com/netflix/metacat/main/services/OwnerValidationService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
package com.netflix.metacat.main.services; | ||
|
||
import com.netflix.metacat.common.QualifiedName; | ||
import com.netflix.metacat.common.dto.TableDto; | ||
import lombok.NonNull; | ||
|
||
import javax.annotation.Nullable; | ||
|
||
/** | ||
* Interface for validating table owner attribute. | ||
*/ | ||
public interface OwnerValidationService { | ||
/** | ||
* Checks whether the given owner is valid against a registry. | ||
* | ||
* @param user the user | ||
* @return true if the owner is valid, else false | ||
*/ | ||
boolean isUserValid(@Nullable String user); | ||
|
||
/** | ||
* Enforces valid table owner attribute. Implementations are free to | ||
* handle it as needed - throw exceptions or ignore. The owner attribute | ||
* in the DTO may or may not be valid so implementations should check for validity | ||
* before enforcement. | ||
* | ||
* @param operationName the name of the metacat API, useful for logging | ||
* @param tableName the name of the table | ||
* @param tableDto the table dto containing the owner in the definition metadata field | ||
*/ | ||
void enforceOwnerValidation(@NonNull String operationName, | ||
@NonNull QualifiedName tableName, | ||
@NonNull TableDto tableDto); | ||
} |
136 changes: 136 additions & 0 deletions
136
...n/src/main/java/com/netflix/metacat/main/services/impl/DefaultOwnerValidationService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
package com.netflix.metacat.main.services.impl; | ||
|
||
import com.google.common.collect.ImmutableSet; | ||
import com.netflix.metacat.common.MetacatRequestContext; | ||
import com.netflix.metacat.common.QualifiedName; | ||
import com.netflix.metacat.common.dto.TableDto; | ||
import com.netflix.metacat.common.server.util.MetacatContextManager; | ||
import com.netflix.metacat.main.services.OwnerValidationService; | ||
import com.netflix.spectator.api.Registry; | ||
import lombok.NonNull; | ||
import lombok.RequiredArgsConstructor; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.apache.commons.lang3.StringUtils; | ||
import org.springframework.web.context.request.RequestAttributes; | ||
import org.springframework.web.context.request.RequestContextHolder; | ||
import org.springframework.web.context.request.ServletRequestAttributes; | ||
|
||
import javax.annotation.Nullable; | ||
import javax.servlet.http.HttpServletRequest; | ||
import java.util.Enumeration; | ||
import java.util.HashMap; | ||
import java.util.Map; | ||
import java.util.Set; | ||
|
||
/** | ||
* A default implementation of Ownership validation service that check for srs against | ||
* known invalid userIds. | ||
*/ | ||
@Slf4j | ||
@RequiredArgsConstructor | ||
public class DefaultOwnerValidationService implements OwnerValidationService { | ||
private static final Set<String> KNOWN_INVALID_OWNERS = ImmutableSet.of( | ||
"root", "metacat", "metacat-thrift-interface"); | ||
|
||
private final Registry registry; | ||
|
||
@Override | ||
public boolean isUserValid(@Nullable final String user) { | ||
return !isKnownInvalidUser(user); | ||
} | ||
|
||
@Override | ||
public void enforceOwnerValidation(@NonNull final String operationName, | ||
@NonNull final QualifiedName tableName, | ||
@NonNull final TableDto tableDto) { | ||
final String tableOwner = tableDto.getTableOwner().orElse(null); | ||
final MetacatRequestContext context = MetacatContextManager.getContext(); | ||
final Map<String, String> requestHeaders = getHttpHeaders(); | ||
|
||
final boolean tableOwnerValid = isUserValid(tableOwner); | ||
|
||
logOwnershipDiagnosticDetails( | ||
operationName, tableName, tableDto, tableOwner, | ||
context, tableOwnerValid, requestHeaders); | ||
} | ||
|
||
/** | ||
* Checks if the user is from a know list of invalid users. Subclasses can use | ||
* this method before attempting to check againt remote servies to save on latency. | ||
* | ||
* @param userId the user id | ||
* @return true if the user id is a known invalid user, else false | ||
*/ | ||
protected boolean isKnownInvalidUser(@Nullable final String userId) { | ||
return StringUtils.isBlank(userId) || knownInvalidOwners().contains(userId); | ||
} | ||
|
||
/** | ||
* Returns set of known invalid users. Subclasses can override to provide | ||
* a list fetched from a dynamic source. | ||
* | ||
* @return set of known invalid users | ||
*/ | ||
protected Set<String> knownInvalidOwners() { | ||
return KNOWN_INVALID_OWNERS; | ||
} | ||
|
||
/** | ||
* Logs diagnostic data for debugging invalid owners. Subclasses can use this to log | ||
* diagnostic data when owners are found to be invalid. | ||
*/ | ||
protected void logOwnershipDiagnosticDetails(final String operationName, | ||
final QualifiedName name, | ||
final TableDto tableDto, | ||
@Nullable final String tableOwner, | ||
final MetacatRequestContext context, | ||
final boolean tableOwnerValid, | ||
final Map<String, String> requestHeaders) { | ||
try { | ||
if (!tableOwnerValid) { | ||
registry.counter( | ||
"metacat.table.owner.invalid", | ||
"operation", operationName, | ||
"catalogAndDb", name.getCatalogName() + "_" + name.getDatabaseName() | ||
).increment(); | ||
|
||
log.info("Operation: {}, invalid owner: {}. name: {}, table-dto: {}, context: {}, headers: {}", | ||
operationName, tableOwner, name, tableDto, context, requestHeaders); | ||
} | ||
} catch (final Exception ex) { | ||
log.warn("Error when logging diagnostic data for invalid owner for operation: {}, name: {}, table: {}", | ||
operationName, name, tableDto, ex); | ||
} | ||
} | ||
|
||
/** | ||
* Returns all the Http headers for the current request. Subclasses can use it to | ||
* log diagnostic data. | ||
* | ||
* @return the Http headers | ||
*/ | ||
protected Map<String, String> getHttpHeaders() { | ||
final Map<String, String> requestHeaders = new HashMap<>(); | ||
|
||
final RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes(); | ||
|
||
if (requestAttributes instanceof ServletRequestAttributes) { | ||
final ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) requestAttributes; | ||
|
||
final HttpServletRequest servletRequest = servletRequestAttributes.getRequest(); | ||
|
||
if (servletRequest != null) { | ||
final Enumeration<String> headerNames = servletRequest.getHeaderNames(); | ||
|
||
if (headerNames != null) { | ||
while (headerNames.hasMoreElements()) { | ||
final String header = headerNames.nextElement(); | ||
requestHeaders.put(header, servletRequest.getHeader(header)); | ||
} | ||
} | ||
} | ||
} | ||
|
||
return requestHeaders; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.