This repository has been archived by the owner on Jan 12, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Create command to allow Cerberus operators to speficy allowed IAM pri…
…ncipals that can use the CMK's associated with backups
- Loading branch information
Showing
7 changed files
with
243 additions
and
35 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
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,4 +16,4 @@ | |
|
||
group=com.nike | ||
artifactId=cerberus-lifecycle-cli | ||
version=3.1.1 | ||
version=3.2.0 |
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
70 changes: 70 additions & 0 deletions
70
src/main/java/com/nike/cerberus/command/core/SetBackupAdminPrincipalsCommand.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,70 @@ | ||
/* | ||
* Copyright (c) 2017 Nike, Inc. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
package com.nike.cerberus.command.core; | ||
|
||
import com.beust.jcommander.Parameter; | ||
import com.beust.jcommander.Parameters; | ||
import com.nike.cerberus.command.Command; | ||
import com.nike.cerberus.operation.Operation; | ||
import com.nike.cerberus.operation.core.SetBackupAdminPrincipalsOperation; | ||
|
||
import java.util.ArrayList; | ||
import java.util.List; | ||
|
||
import static com.nike.cerberus.command.core.SetBackupAdminPrincipalsCommand.COMMAND_NAME; | ||
|
||
/** | ||
* Command to update which principals besides for the root account will have permissions to use the backup cmk, | ||
* AKA create and restore backups. | ||
*/ | ||
@Parameters( | ||
commandNames = COMMAND_NAME, | ||
commandDescription = "Update the IAM Principals that are allowed to create and restore backups. " + | ||
"This command automatically adds by default the root user and configured admin user arn, " + | ||
"but you can use this command to add iam principals such as CI systems and additional user principals " + | ||
"that will have access to encrypt and decrypt backup data" | ||
) | ||
public class SetBackupAdminPrincipalsCommand implements Command { | ||
|
||
public static final String COMMAND_NAME = "set-backup-principals"; | ||
|
||
public static final String PRINCIPAL_LONG_ARG = "--principal"; | ||
public static final String PRINCIPAL_SHORT_ARG = "-p"; | ||
|
||
@Parameter( | ||
names = { | ||
PRINCIPAL_LONG_ARG, | ||
PRINCIPAL_SHORT_ARG | ||
}, | ||
description = "One or more additional principals to grant access to." | ||
) | ||
private List<String> additionalPrincipals = new ArrayList<>(); | ||
|
||
public List<String> getAdditionalPrincipals() { | ||
return additionalPrincipals; | ||
} | ||
|
||
@Override | ||
public String getCommandName() { | ||
return COMMAND_NAME; | ||
} | ||
|
||
@Override | ||
public Class<? extends Operation<?>> getOperationClass() { | ||
return SetBackupAdminPrincipalsOperation.class; | ||
} | ||
} |
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
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
119 changes: 119 additions & 0 deletions
119
src/main/java/com/nike/cerberus/operation/core/SetBackupAdminPrincipalsOperation.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,119 @@ | ||
/* | ||
* Copyright (c) 2017 Nike, Inc. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
package com.nike.cerberus.operation.core; | ||
|
||
import com.amazonaws.auth.policy.Policy; | ||
import com.amazonaws.auth.policy.Principal; | ||
import com.amazonaws.auth.policy.Resource; | ||
import com.amazonaws.auth.policy.Statement; | ||
import com.amazonaws.auth.policy.actions.KMSActions; | ||
import com.amazonaws.services.kms.AWSKMS; | ||
import com.amazonaws.services.kms.AWSKMSClient; | ||
import com.amazonaws.services.kms.model.PutKeyPolicyRequest; | ||
import com.amazonaws.services.securitytoken.AWSSecurityTokenService; | ||
import com.amazonaws.services.securitytoken.model.GetCallerIdentityRequest; | ||
import com.amazonaws.services.securitytoken.model.GetCallerIdentityResult; | ||
import com.nike.cerberus.command.core.SetBackupAdminPrincipalsCommand; | ||
import com.nike.cerberus.operation.Operation; | ||
import com.nike.cerberus.store.ConfigStore; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
import javax.inject.Inject; | ||
import java.util.*; | ||
|
||
import static com.nike.cerberus.module.CerberusModule.getAWSCredentialsProviderChain; | ||
|
||
/** | ||
* Operation to update which principals besides for the root account will have permissions to use the backup cmk, | ||
* AKA create and restore backups | ||
*/ | ||
public class SetBackupAdminPrincipalsOperation implements Operation<SetBackupAdminPrincipalsCommand> { | ||
|
||
private final Logger log = LoggerFactory.getLogger(getClass()); | ||
|
||
private static final String AWS_PROVIDER = "AWS"; | ||
|
||
private final ConfigStore configStore; | ||
private final AWSSecurityTokenService sts; | ||
|
||
@Inject | ||
public SetBackupAdminPrincipalsOperation(ConfigStore configStore, | ||
AWSSecurityTokenService sts) { | ||
|
||
this.configStore = configStore; | ||
this.sts = sts; | ||
} | ||
|
||
@Override | ||
public void run(SetBackupAdminPrincipalsCommand command) { | ||
GetCallerIdentityResult identityResult = sts.getCallerIdentity(new GetCallerIdentityRequest()); | ||
String accountId = identityResult.getAccount(); | ||
String rootArn = String.format("arn:aws:iam::%s:root", accountId); | ||
String adminRoleArn = configStore.getAccountAdminArn().get(); | ||
|
||
Set<String> principals = new HashSet<>(); | ||
principals.add(rootArn); | ||
principals.add(adminRoleArn); | ||
principals.addAll(command.getAdditionalPrincipals()); | ||
|
||
configStore.storeBackupAdminIamPrincipals(principals); | ||
|
||
if (! configStore.getRegionBackupBucketMap().isEmpty()) { | ||
configStore.getRegionBackupBucketMap().forEach((region, backupRegionInfo) -> { | ||
final List<Statement> statements = new LinkedList<>(); | ||
principals.forEach( principal -> { | ||
log.debug("Adding principal: {} to the CMK Policy for region {}", principal, region); | ||
statements.add(new Statement(Statement.Effect.Allow) | ||
.withId("Principal " + principal + " Has All Actions") | ||
.withPrincipals(new Principal(AWS_PROVIDER, principal, false)) | ||
.withActions(KMSActions.AllKMSActions) | ||
.withResources(new Resource("*"))); | ||
}); | ||
|
||
Policy kmsPolicy = new Policy(); | ||
kmsPolicy.setStatements(statements); | ||
String policyString = kmsPolicy.toJson(); | ||
|
||
log.debug("Updating key {} for region {} with policy {}", backupRegionInfo.getKmsCmkId(), region, policyString); | ||
|
||
AWSKMS kms = AWSKMSClient.builder().withCredentials(getAWSCredentialsProviderChain()).withRegion(region).build(); | ||
PutKeyPolicyRequest request = new PutKeyPolicyRequest() | ||
.withKeyId(backupRegionInfo.getKmsCmkId()) | ||
.withPolicyName("default") | ||
.withBypassPolicyLockoutSafetyCheck(true) | ||
.withPolicy(policyString); | ||
|
||
kms.putKeyPolicy(request); | ||
|
||
log.info("Successfully updated key {} in region {} to allow the following principals access {}", | ||
backupRegionInfo.getKmsCmkId(), region, String.join(", ", principals)); | ||
}); | ||
} | ||
} | ||
|
||
@Override | ||
public boolean isRunnable(SetBackupAdminPrincipalsCommand command) { | ||
Optional<String> adminIamPrincipalArn = configStore.getAccountAdminArn(); | ||
if (! adminIamPrincipalArn.isPresent()) { | ||
log.error("The admin IAM principal must be set for this environment"); | ||
return false; | ||
} | ||
return true; | ||
} | ||
|
||
} |
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