Skip to content

Commit

Permalink
WIP: allow adding region info when simulating permissions
Browse files Browse the repository at this point in the history
allow providing an aws region to be used when performing the simulations
  • Loading branch information
Joel Diaz committed Oct 14, 2019
1 parent 541d5a0 commit a59421c
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 12 deletions.
2 changes: 1 addition & 1 deletion pkg/aws/actuator/actuator.go
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ func (a *AWSActuator) needsUpdate(ctx context.Context, cr *minterv1.CredentialsR

} else {
// for passthrough creds, just see if we have the permissions requested in the credentialsrequest
goodEnough, err := ccaws.CheckPermissionsUsingQueryClient(readAWSClient, awsClient, awsSpec.StatementEntries, logger)
goodEnough, err := ccaws.CheckPermissionsUsingQueryClient(readAWSClient, awsClient, awsSpec.StatementEntries, ccaws.QueryParams{}, logger)
if err != nil {
return true, fmt.Errorf("error validating whether current creds are good enough: %v", err)
}
Expand Down
35 changes: 26 additions & 9 deletions pkg/aws/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,9 +106,15 @@ func init() {
}
}

// SimulateParams captures any additional details that should be used
// when simulating permissions.
type SimulateParams struct {
Region string
}

// CheckCloudCredCreation will see whether we have enough permissions to create new sub-creds
func CheckCloudCredCreation(awsClient Client, logger log.FieldLogger) (bool, error) {
return CheckPermissionsAgainstActions(awsClient, credMintingActions, logger)
func CheckCloudCredCreation(awsClient Client, params SimulateParams, logger log.FieldLogger) (bool, error) {
return CheckPermissionsAgainstActions(awsClient, credMintingActions, params, logger)
}

// getClientDetails will return the *iam.User associated with the provided client's credentials,
Expand Down Expand Up @@ -136,7 +142,8 @@ func getClientDetails(awsClient Client) (*iam.User, bool, error) {

// CheckPermissionsUsingQueryClient will use queryClient to query whether the credentials in targetClient can perform the actions
// listed in the statementEntries. queryClient will need iam:GetUser and iam:SimulatePrincipalPolicy
func CheckPermissionsUsingQueryClient(queryClient, targetClient Client, statementEntries []minterv1.StatementEntry, logger log.FieldLogger) (bool, error) {
func CheckPermissionsUsingQueryClient(queryClient, targetClient Client, statementEntries []minterv1.StatementEntry,
params SimulateParams, logger log.FieldLogger) (bool, error) {
targetUser, isRoot, err := getClientDetails(targetClient)
if err != nil {
return false, fmt.Errorf("error gathering AWS credentials details: %v", err)
Expand All @@ -157,6 +164,15 @@ func CheckPermissionsUsingQueryClient(queryClient, targetClient Client, statemen
input := &iam.SimulatePrincipalPolicyInput{
PolicySourceArn: targetUser.Arn,
ActionNames: allowList,
ContextEntries: []*iam.ContextEntry{},
}

if params.Region != "" {
input.ContextEntries = append(input.ContextEntries, &iam.ContextEntry{
ContextKeyName: aws.String("aws:RequestedRegion"),
ContextKeyType: aws.String("string"),
ContextKeyValues: []*string{aws.String(params.Region)},
})
}

// Either all actions are allowed and we'll return 'true', or it's a failure
Expand Down Expand Up @@ -189,14 +205,15 @@ func CheckPermissionsUsingQueryClient(queryClient, targetClient Client, statemen

// CheckPermissionsAgainstStatementList will test to see whether the list of actions in the provided
// list of StatementEntries can work with the credentials used by the passed-in awsClient
func CheckPermissionsAgainstStatementList(awsClient Client, statementEntries []minterv1.StatementEntry, logger log.FieldLogger) (bool, error) {
return CheckPermissionsUsingQueryClient(awsClient, awsClient, statementEntries, logger)
func CheckPermissionsAgainstStatementList(awsClient Client, statementEntries []minterv1.StatementEntry,
params SimulateParams, logger log.FieldLogger) (bool, error) {
return CheckPermissionsUsingQueryClient(awsClient, awsClient, statementEntries, params, logger)
}

// CheckPermissionsAgainstActions will take the static list of Actions to check whether the provided
// awsClient creds have sufficient permissions to perform the actions.
// Will return true/false indicating whether the permissions are sufficient.
func CheckPermissionsAgainstActions(awsClient Client, actionList []string, logger log.FieldLogger) (bool, error) {
func CheckPermissionsAgainstActions(awsClient Client, actionList []string, params SimulateParams, logger log.FieldLogger) (bool, error) {
statementList := []minterv1.StatementEntry{
{
Action: actionList,
Expand All @@ -205,15 +222,15 @@ func CheckPermissionsAgainstActions(awsClient Client, actionList []string, logge
},
}

return CheckPermissionsAgainstStatementList(awsClient, statementList, logger)
return CheckPermissionsAgainstStatementList(awsClient, statementList, params, logger)
}

// CheckCloudCredPassthrough will see if the provided creds are good enough to pass through
// to other components as-is based on the static list of permissions needed by the various
// users of CredentialsRequests
// TODO: move away from static list (to dynamic passthrough validation?)
func CheckCloudCredPassthrough(awsClient Client, logger log.FieldLogger) (bool, error) {
return CheckPermissionsAgainstActions(awsClient, credPassthroughActions, logger)
func CheckCloudCredPassthrough(awsClient Client, params SimulateParams, logger log.FieldLogger) (bool, error) {
return CheckPermissionsAgainstActions(awsClient, credPassthroughActions, params, logger)
}

func readCredentialRequest(cr []byte) (*minterv1.CredentialsRequest, error) {
Expand Down
4 changes: 2 additions & 2 deletions pkg/controller/secretannotator/aws/reconciler.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ func (r *ReconcileCloudCredSecret) validateCloudCredsSecret(secret *corev1.Secre
}

// Can we mint new creds?
cloudCheckResult, err := ccaws.CheckCloudCredCreation(awsClient, r.Logger)
cloudCheckResult, err := ccaws.CheckCloudCredCreation(awsClient, ccaws.QueryParams{}, r.Logger)
if err != nil {
r.updateSecretAnnotations(secret, constants.InsufficientAnnotation)
return fmt.Errorf("failed checking create cloud creds: %v", err)
Expand All @@ -146,7 +146,7 @@ func (r *ReconcileCloudCredSecret) validateCloudCredsSecret(secret *corev1.Secre
}

// Else, can we just pass through the current creds?
cloudCheckResult, err = ccaws.CheckCloudCredPassthrough(awsClient, r.Logger)
cloudCheckResult, err = ccaws.CheckCloudCredPassthrough(awsClient, ccaws.QueryParams{}, r.Logger)
if err != nil {
r.updateSecretAnnotations(secret, constants.InsufficientAnnotation)
return fmt.Errorf("failed checking passthrough cloud creds: %v", err)
Expand Down

0 comments on commit a59421c

Please sign in to comment.