Skip to content
This repository has been archived by the owner on Jan 12, 2024. It is now read-only.

Commit

Permalink
Merge branch 'master' into dep/dependency_upgrade_staging
Browse files Browse the repository at this point in the history
  • Loading branch information
jharen committed Sep 7, 2021
2 parents 69d5dbc + 8645ef3 commit 56b9f60
Show file tree
Hide file tree
Showing 7 changed files with 430 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,14 @@ public enum DefaultApiError implements ApiError {
/** Push notification challenges have not been implemented for OneLogin MFA */
OKTA_PUSH_MFA_REJECTED(99249, "Push notification request was rejected by user", SC_UNAUTHORIZED),

/** Owner AD Group does not match approved specification */
SDB_OWNER_NOT_VALID(
99250, "Owner AD Group does not match approved specification!", SC_BAD_REQUEST),

/** User AD group does not match approved specification */
SDB_USER_GROUP_NOT_VALID(
99251, "User AD Group does not match approved specification!", SC_BAD_REQUEST),

/** Generic not found error. */
ENTITY_NOT_FOUND(99996, "Not found", SC_NOT_FOUND),

Expand Down
9 changes: 9 additions & 0 deletions cerberus-dashboard/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,15 @@ node {
}

task buildDashboard(type: NpmTask, dependsOn: npmInstall) {

doFirst {
if (System.getenv("FRONTEND_ENV_FILE_PATH")) {
String file_path = System.getenv("FRONTEND_ENV_FILE_PATH")
assert file(file_path).exists()
new File("${project.projectDir.absolutePath}", ".env").text = file(file_path).text
}
}

group 'build'
args = ["run", "build"]
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ const validate = values => {

if (!values.owner) {
errors.owner = 'You must select an owning user group';
} else if (process.env.REACT_APP_AD_GROUP_NAME_PREFIX) {
validateOwner(values.owner, process.env.REACT_APP_AD_GROUP_NAME_PREFIX, errors);
}

if (values.userGroupPermissions) {
Expand All @@ -60,6 +62,12 @@ const validate = values => {
return errors;
};

const validateOwner = (owner, ownerPrefix, errors) => {
if (!owner.toLowerCase().startsWith(ownerPrefix.toLowerCase())) {
errors.owner = 'This AD Group name does not match your organizations specified naming pattern: ' + ownerPrefix;
}
}

const validateUserGroupPermissions = (permission, index, errors) => {
errors.userGroupPermissions[`${index}`] = {};
if (!permission.name) {
Expand Down
12 changes: 10 additions & 2 deletions cerberus-dashboard/src/components/GroupSelect/GroupsSelect.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,16 @@ export default class GroupsSelect extends Component {
render() {
const { userGroups, allowCustomValues, value, onChange, handleBeingTouched, touched, error } = this.props;

var options = userGroups.map(function (group) {
return { label: group, value: group };
var options = [];
userGroups.forEach(group => {
if (process.env.REACT_APP_AD_GROUP_NAME_PREFIX) {
let groupNamingPattern = process.env.REACT_APP_AD_GROUP_NAME_PREFIX.toLowerCase()
if (group.toLowerCase().startsWith(groupNamingPattern)) {
options.push({ label: group, value: group });
}
} else {
options.push({ label: group, value: group });
}
});

var containsValue = false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,12 @@ public String currentRegionAsString() {
return currentRegion().getName();
}

@Bean(name = "adGroupNamePrefix")
public String ADGroupNamePrefix(
@Value("${cerberus.adGroupNamePrefix:}") String adGroupNamePrefix) {
return adGroupNamePrefix.toLowerCase();
}

@Bean("encryptCryptoMaterialsManager")
public CryptoMaterialsManager encryptCryptoMaterialsManager(
@Value("${cerberus.encryption.cmk.arns}") String cmkArns,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import com.nike.cerberus.security.CerberusPrincipal;
import com.nike.cerberus.util.*;
import java.time.OffsetDateTime;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
Expand Down Expand Up @@ -64,6 +65,7 @@ public class SafeDepositBoxService {
private final SecureDataVersionDao secureDataVersionDao;
private final Boolean userGroupsCaseSensitive;
private final AuditLoggingFilterDetails auditLoggingFilterDetails;
public String adGroupNamePrefix;

@Autowired
public SafeDepositBoxService(
Expand All @@ -81,7 +83,8 @@ public SafeDepositBoxService(
SecureDataVersionDao secureDataVersionDao,
@Value(USER_GROUPS_CASE_SENSITIVE) Boolean userGroupsCaseSensitive,
SdbAccessRequest sdbAccessRequest,
AuditLoggingFilterDetails auditLoggingFilterDetails) {
AuditLoggingFilterDetails auditLoggingFilterDetails,
String adGroupNamePrefix) {

this.safeDepositBoxDao = safeDepositBoxDao;
this.userGroupDao = userGroupDao;
Expand All @@ -97,6 +100,7 @@ public SafeDepositBoxService(
this.secureDataVersionDao = secureDataVersionDao;
this.userGroupsCaseSensitive = userGroupsCaseSensitive;
this.auditLoggingFilterDetails = auditLoggingFilterDetails;
this.adGroupNamePrefix = adGroupNamePrefix;
}

/**
Expand Down Expand Up @@ -230,6 +234,90 @@ public String createSafeDepositBoxV1(final SafeDepositBoxV1 safeDepositBox, fina
return createSafeDepositBoxV2(safeDepositBoxV2, user).getId();
}

/**
* Validates the owner AD group name of safe deposit box with the approved specification
*
* @param safeDepositBox Safe deposit box to check
*/
public void validateSDBOwnerName(SafeDepositBoxV2 safeDepositBox) {
String ownerName = safeDepositBox.getOwner();
if (!ownerName.toLowerCase().startsWith(this.adGroupNamePrefix)) {
String errorMessage =
String.format(
"Owner '%s' is not valid! AD group prefix must start with: '%s'",
ownerName, this.adGroupNamePrefix);
throw ApiException.newBuilder()
.withApiErrors(
CustomApiError.createCustomApiError(
DefaultApiError.SDB_OWNER_NOT_VALID, errorMessage))
.withExceptionMessage(errorMessage)
.build();
}
}

/**
* Validates the user group AD group names of safe deposit box with the approved specification
*
* @param safeDepositBox safe deposit box to check
*/
public void validateUserGroupName(SafeDepositBoxV2 safeDepositBox) {
List<String> invalidUserGroups = new ArrayList<>();
for (UserGroupPermission permission : safeDepositBox.getUserGroupPermissions()) {
String userGroupName = permission.getName();
if (!userGroupName.toLowerCase().startsWith(this.adGroupNamePrefix)) {
invalidUserGroups.add(userGroupName);
}
}
if (!invalidUserGroups.isEmpty()) {
generateUserGroupPermissionError(invalidUserGroups);
}
}

/**
* Gets new user group permissions added to an SDB
*
* @param currentBox The record of the SDB
* @param newSafeDepositBox The new box constructed from the update
*/
public void validateNewUserGroupPermissions(
SafeDepositBoxV2 currentBox, SafeDepositBoxV2 newSafeDepositBox) {
Set<UserGroupPermission> newUserGroupPermissions = newSafeDepositBox.getUserGroupPermissions();
List<String> invalidUserGroups = new ArrayList<>();
for (UserGroupPermission permission : newUserGroupPermissions) {
if (!currentBox.getUserGroupPermissions().contains(permission)) {
String userGroupName = permission.getName();
if (!userGroupName.toLowerCase().startsWith(this.adGroupNamePrefix)) {
invalidUserGroups.add(userGroupName);
}
}
}
if (!invalidUserGroups.isEmpty()) {
generateUserGroupPermissionError(invalidUserGroups);
}
}
;

/**
* Generates the error message and throws the error if AD groups do not match specification
*
* @param invalidUserGroups list of names of invalid user groups
*/
private void generateUserGroupPermissionError(List<String> invalidUserGroups) {
String errorPreamble =
String.format("The following groups are invalid: %s. ", invalidUserGroups);
String errorMessage =
String.format("AD group prefix must start with: '%s'", this.adGroupNamePrefix);

errorMessage = errorPreamble + errorMessage;

throw ApiException.newBuilder()
.withApiErrors(
CustomApiError.createCustomApiError(
DefaultApiError.SDB_USER_GROUP_NOT_VALID, errorMessage))
.withExceptionMessage(errorMessage)
.build();
}

/**
* Creates a safe deposit box and all the appropriate permissions.
*
Expand All @@ -240,6 +328,11 @@ public String createSafeDepositBoxV1(final SafeDepositBoxV1 safeDepositBox, fina
@Transactional
public SafeDepositBoxV2 createSafeDepositBoxV2(
final SafeDepositBoxV2 safeDepositBox, final String user) {

// Validate AD Group names against specification
validateSDBOwnerName(safeDepositBox);
validateUserGroupName(safeDepositBox);

final OffsetDateTime now = dateTimeSupplier.get();
final SafeDepositBoxRecord boxRecordToStore = buildBoxToStore(safeDepositBox, user, now);
final Set<UserGroupPermission> userGroupPermissionSet =
Expand Down Expand Up @@ -301,6 +394,17 @@ public SafeDepositBoxV2 updateSafeDepositBoxV2(
final String id) {

final SafeDepositBoxV2 currentBox = getSDBAndValidatePrincipalAssociationV2(id);

// If owner has changed, validate the new owner name
if (!currentBox.getOwner().equals(safeDepositBox.getOwner())) {
validateSDBOwnerName(safeDepositBox);
}

// If user groups have changed, validate the new additions
if (!currentBox.getUserGroupPermissions().equals(safeDepositBox.getUserGroupPermissions())) {
validateNewUserGroupPermissions(currentBox, safeDepositBox);
}

String principalName = authPrincipal.getName();
final OffsetDateTime now = dateTimeSupplier.get();
final SafeDepositBoxRecord boxToUpdate =
Expand Down
Loading

0 comments on commit 56b9f60

Please sign in to comment.