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

Commit

Permalink
Allow IAM Principals to perform full CRUD on SBDs (#50)
Browse files Browse the repository at this point in the history
Allow IAM Principals to list and delete sdbs so that they can perform full CRUD on SDBs
  • Loading branch information
fieldju authored Jun 28, 2017
1 parent 9263e90 commit 53d82e4
Show file tree
Hide file tree
Showing 13 changed files with 165 additions and 110 deletions.
4 changes: 4 additions & 0 deletions src/main/java/com/nike/cerberus/dao/SafeDepositBoxDao.java
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ public List<SafeDepositBoxRecord> getUserAssociatedSafeDepositBoxes(final Set<St
return safeDepositBoxMapper.getUserAssociatedSafeDepositBoxes(userGroups);
}

public List<SafeDepositBoxRecord> getIamPrincipalAssociatedSafeDepositBoxes(final String iamPrincipalArn) {
return safeDepositBoxMapper.getIamPrincipalAssociatedSafeDepositBoxes(iamPrincipalArn);
}

public List<SafeDepositBoxRecord> getSafeDepositBoxes(final int limit, final int offset) {
return safeDepositBoxMapper.getSafeDepositBoxes(limit, offset);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ private ResponseInfo<Void> deleteSafeDepositBox(final RequestInfo<Void> request)
log.info("Delete SDB Event: the principal: {} is attempting to delete sdb name: '{}' and id: '{}'",
vaultAuthPrincipal.getName(), sdbName, sdbId);

safeDepositBoxService.deleteSafeDepositBox(vaultAuthPrincipal.getUserGroups(), sdbId);
safeDepositBoxService.deleteSafeDepositBox(vaultAuthPrincipal, sdbId);
return ResponseInfo.<Void>newBuilder().withHttpStatusCode(HttpResponseStatus.OK.code())
.withHeaders(new DefaultHttpHeaders().set(HEADER_X_REFRESH_TOKEN, Boolean.TRUE.toString()))
.build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@

package com.nike.cerberus.endpoints.sdb;

import com.nike.backstopper.apierror.sample.SampleCoreApiError;
import com.nike.backstopper.exception.ApiException;
import com.nike.cerberus.domain.SafeDepositBoxV1;
import com.nike.cerberus.error.DefaultApiError;
Expand Down Expand Up @@ -79,16 +78,12 @@ public ResponseInfo<SafeDepositBoxV1> getSafeDepositBox(final RequestInfo<Void>
log.info("Read SDB Event: the principal: {} is attempting to read sdb name: '{}' and id: '{}'",
vaultAuthPrincipal.getName(), sdbName, sdbId);

final Optional<SafeDepositBoxV1> safeDepositBox =
safeDepositBoxService.getAssociatedSafeDepositBoxV1(
vaultAuthPrincipal.getUserGroups(),
final SafeDepositBoxV1 safeDepositBox =
safeDepositBoxService.getSDBAndValidatePrincipalAssociationV1(
vaultAuthPrincipal,
sdbId);

if (safeDepositBox.isPresent()) {
return ResponseInfo.newBuilder(safeDepositBox.get()).build();
}

throw ApiException.newBuilder().withApiErrors(SampleCoreApiError.NOT_FOUND).build();
return ResponseInfo.newBuilder(safeDepositBox).build();
}

throw ApiException.newBuilder().withApiErrors(DefaultApiError.AUTH_BAD_CREDENTIALS).build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,7 @@

package com.nike.cerberus.endpoints.sdb;

import com.nike.backstopper.apierror.sample.SampleCoreApiError;
import com.nike.backstopper.exception.ApiException;
import com.nike.cerberus.domain.SafeDepositBoxV1;
import com.nike.cerberus.domain.SafeDepositBoxV2;
import com.nike.cerberus.error.DefaultApiError;
import com.nike.cerberus.security.CmsRequestSecurityValidator;
Expand Down Expand Up @@ -80,16 +78,12 @@ public ResponseInfo<SafeDepositBoxV2> getSafeDepositBox(final RequestInfo<Void>
log.info("Read SDB Event: the principal: {} is attempting to read sdb name: '{}' and id: '{}'",
vaultAuthPrincipal.getName(), sdbName, sdbId);

final Optional<SafeDepositBoxV2> safeDepositBox =
safeDepositBoxService.getAssociatedSafeDepositBoxV2(
vaultAuthPrincipal.getUserGroups(),
final SafeDepositBoxV2 safeDepositBox =
safeDepositBoxService.getSDBAndValidatePrincipalAssociationV2(
vaultAuthPrincipal,
sdbId);

if (safeDepositBox.isPresent()) {
return ResponseInfo.newBuilder(safeDepositBox.get()).build();
}

throw ApiException.newBuilder().withApiErrors(SampleCoreApiError.NOT_FOUND).build();
return ResponseInfo.newBuilder(safeDepositBox).build();
}

throw ApiException.newBuilder().withApiErrors(DefaultApiError.AUTH_BAD_CREDENTIALS).build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ public ResponseInfo<List<SafeDepositBoxSummary>> getSafeDepositBoxes(final Reque
vaultAuthPrincipal.getName());

return ResponseInfo.newBuilder(
safeDepositBoxService.getAssociatedSafeDepositBoxes(vaultAuthPrincipal.getUserGroups())).build();
safeDepositBoxService.getAssociatedSafeDepositBoxes(vaultAuthPrincipal)).build();
}

throw ApiException.newBuilder().withApiErrors(DefaultApiError.AUTH_BAD_CREDENTIALS).build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,14 +77,12 @@ private ResponseInfo<Void> updateSafeDepositBox(final RequestInfo<SafeDepositBox

String sdbId = request.getPathParam("id");
Optional<String> sdbNameOptional = safeDepositBoxService.getSafeDepositBoxNameById(sdbId);
String sdbName = sdbNameOptional.isPresent() ? sdbNameOptional.get() :
String.format("(Failed to lookup name from id: %s)", sdbId);
String sdbName = sdbNameOptional.orElseGet(() -> String.format("(Failed to lookup name from id: %s)", sdbId));
log.info("Update SDB Event: the principal: {} is attempting to update sdb name: '{}' and id: '{}'",
vaultAuthPrincipal.getName(), sdbName, sdbId);

safeDepositBoxService.updateSafeDepositBoxV1(request.getContent(),
vaultAuthPrincipal.getUserGroups(),
vaultAuthPrincipal.getName(),
vaultAuthPrincipal,
sdbId);
return ResponseInfo.<Void>newBuilder().withHttpStatusCode(HttpResponseStatus.NO_CONTENT.code())
.withHeaders(new DefaultHttpHeaders().set(HEADER_X_REFRESH_TOKEN, Boolean.TRUE.toString()))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,7 @@ private ResponseInfo<SafeDepositBoxV2> updateSafeDepositBox(final RequestInfo<Sa
if (securityContext.isPresent()) {
final VaultAuthPrincipal vaultAuthPrincipal = (VaultAuthPrincipal) securityContext.get().getUserPrincipal();
SafeDepositBoxV2 safeDepositBoxV2 = safeDepositBoxService.updateSafeDepositBoxV2(request.getContent(),
vaultAuthPrincipal.getUserGroups(),
vaultAuthPrincipal.getName(),
vaultAuthPrincipal,
request.getPathParam("id"));
return ResponseInfo.newBuilder(safeDepositBoxV2)
.withHeaders(new DefaultHttpHeaders().set(HEADER_X_REFRESH_TOKEN, Boolean.TRUE.toString()))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ public interface SafeDepositBoxMapper {

List<SafeDepositBoxRecord> getUserAssociatedSafeDepositBoxes(@Param("userGroups") Set<String> userGroups);

List<SafeDepositBoxRecord> getIamPrincipalAssociatedSafeDepositBoxes(@Param("iamPrincipalArn") final String iamPrincipalArn);

SafeDepositBoxRecord getSafeDepositBox(@Param("id") String id);

int countByPath(@Param("path") String path);
Expand Down
16 changes: 16 additions & 0 deletions src/main/java/com/nike/cerberus/security/VaultAuthPrincipal.java
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ public class VaultAuthPrincipal implements Principal {

public static final String METADATA_KEY_AWS_IAM_PRINCIPAL_ARN = "aws_iam_principal_arn";

public static final String METADATA_KEY_IS_IAM_PRINCIPAL = "is_iam_principal";

public static final String METADATA_KEY_AWS_REGION = "aws_region";

private final VaultClientTokenResponse clientToken;
Expand All @@ -57,11 +59,21 @@ public class VaultAuthPrincipal implements Principal {

private final Set<String> roles;

private final boolean isIamPrincipal;

public VaultAuthPrincipal(VaultClientTokenResponse clientToken) {
this.clientToken = clientToken;
this.roles = buildRoles(clientToken);
this.userGroupSet = extractUserGroups(clientToken);
this.username = extractUsername(clientToken);
this.isIamPrincipal = extractIsIamPrincipal(clientToken);
}

private boolean extractIsIamPrincipal(VaultClientTokenResponse clientToken) {
final Map<String, String> meta = clientToken.getMeta();
// if a Token that is the root token or created outside of CMS,
// then meta might be null and there will be no value set
return meta == null ? false : Boolean.valueOf(meta.get(METADATA_KEY_IS_IAM_PRINCIPAL));
}

private Set<String> buildRoles(VaultClientTokenResponse clientToken) {
Expand Down Expand Up @@ -114,4 +126,8 @@ public boolean hasRole(final String role) {
public Set<String> getUserGroups() {
return userGroupSet;
}

public boolean isIamPrincipal() {
return isIamPrincipal;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ public IamRoleAuthResponse authenticate(IamRoleCredentials credentials) {
iamPrincipalCredentials.setIamPrincipalArn(iamPrincipalArn);
iamPrincipalCredentials.setRegion(region);

final Map<String, String> vaultAuthPrincipalMetadata = generateCommonVaultPrincipalAuthMetadata(iamPrincipalArn, region);
final Map<String, String> vaultAuthPrincipalMetadata = generateCommonIamPrincipalAuthMetadata(iamPrincipalArn, region);
vaultAuthPrincipalMetadata.put(VaultAuthPrincipal.METADATA_KEY_AWS_ACCOUNT_ID, awsIamRoleArnParser.getAccountId(iamPrincipalArn));
vaultAuthPrincipalMetadata.put(VaultAuthPrincipal.METADATA_KEY_AWS_IAM_ROLE_NAME, awsIamRoleArnParser.getRoleName(iamPrincipalArn));

Expand All @@ -207,7 +207,7 @@ public IamRoleAuthResponse authenticate(IamRoleCredentials credentials) {
public IamRoleAuthResponse authenticate(IamPrincipalCredentials credentials) {

final String iamPrincipalArn = credentials.getIamPrincipalArn();
final Map<String, String> vaultAuthPrincipalMetadata = generateCommonVaultPrincipalAuthMetadata(iamPrincipalArn, credentials.getRegion());
final Map<String, String> vaultAuthPrincipalMetadata = generateCommonIamPrincipalAuthMetadata(iamPrincipalArn, credentials.getRegion());
vaultAuthPrincipalMetadata.put(VaultAuthPrincipal.METADATA_KEY_AWS_IAM_PRINCIPAL_ARN, iamPrincipalArn);

return authenticate(credentials, vaultAuthPrincipalMetadata);
Expand Down Expand Up @@ -534,10 +534,11 @@ private Set<String> getAdminRoleArnSet() {
* @param region - The AWS region
* @return - Map of token metadata
*/
protected Map<String, String> generateCommonVaultPrincipalAuthMetadata(final String iamPrincipalArn, final String region) {
protected Map<String, String> generateCommonIamPrincipalAuthMetadata(final String iamPrincipalArn, final String region) {
Map<String, String> metadata = Maps.newHashMap();
metadata.put(VaultAuthPrincipal.METADATA_KEY_AWS_REGION, region);
metadata.put(VaultAuthPrincipal.METADATA_KEY_USERNAME, iamPrincipalArn);
metadata.put(VaultAuthPrincipal.METADATA_KEY_IS_IAM_PRINCIPAL, Boolean.TRUE.toString());

Set<String> groups = new HashSet<>();
groups.add("registered-iam-principals");
Expand Down
Loading

0 comments on commit 53d82e4

Please sign in to comment.