Skip to content

Commit

Permalink
Merge pull request #20 from Optum/Feature/MoveUserPolicyToFile
Browse files Browse the repository at this point in the history
Load Redbox Principal Policy from a S3 file
  • Loading branch information
kddejong authored Sep 9, 2019
2 parents e9d9bb9 + 7455bb2 commit 1176672
Show file tree
Hide file tree
Showing 33 changed files with 8,416 additions and 11,957 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
## vNext

- Added variable for specifying an IAM policy template (GO Template)
- Update IAM Policy for the principal every time the account is unlocked

## v0.14.0

- Added rds backup delete to nuke
Expand Down
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ Response:
"accountStatus": "NotReady",
"adminRoleArn": "arn:aws:iam::1234567890123:role/adminRole",
"principalRoleArn": "arn:aws:iam::1234567890123:role/RedboxPrincipal",
"principalPolicyHash": "",
"createdOn": 1560306008,
"lastModifiedOn": 1560306008,
"metadata": {}
Expand Down Expand Up @@ -199,6 +200,10 @@ terraform output api_access_policy_name
terraform output api_access_policy_arn
```

#### IAM Policy for Redbox Accounts

The Terraform module will come with a sane starting policy that is applied to the IAM principal. This policy is applied when a new account is added or when a lease is unlocked. It is possible to change the policy to what is needed by providing the Terraform variable `redbox_principal_policy`. The value of this variable is a location of a policy file that can be a Go template. It is uploaded into S3 and is read from there as the policy is applied.

#### Signing requests in Go

The AWS SDK for Go exposes a [`signer/v4` package](https://docs.aws.amazon.com/sdk-for-go/api/aws/signer/v4/), which may be used to sign API requests. For example:
Expand Down Expand Up @@ -276,6 +281,7 @@ Example:
"accountStatus": "NotReady",
"adminRoleArn": "arn:aws:iam::1234567890123:role/adminRole",
"principalRoleArn": "arn:aws:iam::1234567890123:role/RedboxPrincipal",
"principalPolicyHash": "\"d41d8cd98f00b204e9800998ecf8427e-38\"",
"createdOn": 1560306008,
"lastModifiedOn": 1560306008,
"metadata": {}
Expand Down Expand Up @@ -655,4 +661,4 @@ Some variables used in notification templates (conatined in modules/variables.tf
- Lease.AccountID : The Account number of the AWS account in use
- Lease.BudgetAmount : The configured budget amount for the lease
- ActualSpend : The calculated spend on the account at time of notification
- ThresholdPercentile : The conigured threshold percentage for the notification, prior to exhaustion
- ThresholdPercentile : The conigured threshold percentage for the notification, prior to exhaustion
13 changes: 9 additions & 4 deletions cmd/lambda/accounts/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@ import (
"context"
"encoding/json"
"errors"
"github.com/Optum/Redbox/pkg/rolemanager"
"github.com/aws/aws-sdk-go/service/iam"
"log"
"net/http"
"strings"
"time"

"github.com/Optum/Redbox/pkg/rolemanager"
"github.com/aws/aws-sdk-go/service/iam"

"github.com/Optum/Redbox/pkg/api/response"
"github.com/Optum/Redbox/pkg/common"
"github.com/Optum/Redbox/pkg/db"
Expand All @@ -28,6 +29,7 @@ type createController struct {
AccountCreatedTopicArn string
AWSSession session.Session
TokenService common.TokenService
StoragerService common.Storager
RoleManager rolemanager.RoleManager
PrincipalRoleName string
PrincipalPolicyName string
Expand All @@ -36,7 +38,9 @@ type createController struct {
// to resources with these tags leased
PrincipalIAMDenyTags []string
// Tags to apply to AWS resources created by this controller
Tags []*iam.Tag
Tags []*iam.Tag
ArtifactsBucket string
PrincipalPolicyS3Key string
}

// Call - Function to validate the account request to add into the pool and
Expand Down Expand Up @@ -89,12 +93,13 @@ func (c createController) Call(ctx context.Context, req *events.APIGatewayProxyR
}

// Create an IAM Role for the Redbox principal (end-user) to login to
createRolRes, err := c.createPrincipalRole(account)
createRolRes, policyHash, err := c.createPrincipalRole(account)
if err != nil {
log.Printf("failed to create principal role for %s: %s", request.ID, err)
return response.ServerError(), nil
}
account.PrincipalRoleArn = createRolRes.RoleArn
account.PrincipalPolicyHash = policyHash

// Write the Account to the DB
err = c.Dao.PutAccount(account)
Expand Down
38 changes: 20 additions & 18 deletions cmd/lambda/accounts/create_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,15 @@ import (
"encoding/json"
"errors"
"fmt"
"strings"
"testing"

awsMocks "github.com/Optum/Redbox/pkg/awsiface/mocks"
"github.com/Optum/Redbox/pkg/rolemanager"
roleManagerMocks "github.com/Optum/Redbox/pkg/rolemanager/mocks"
"github.com/aws/aws-sdk-go/aws/client"
"github.com/aws/aws-sdk-go/service/iam"
"github.com/stretchr/testify/assert"
"strings"
"testing"

"github.com/Optum/Redbox/pkg/api/response"
"github.com/Optum/Redbox/pkg/common"
Expand Down Expand Up @@ -388,15 +389,6 @@ func TestCreate(t *testing.T) {
}
`)

// Setup expected policy
expectedPolicy, err := redboxPrincipalPolicy(redboxPrincipalPolicyInput{
PrincipalPolicyArn: "arn:aws:iam::1234567890:policy/RedboxPrincipalDefaultPolicy",
PrincipalRoleArn: "arn:aws:iam::1234567890:role/RedboxPrincipal",
PrincipalIAMDenyTags: []string{"Redbox", "CantTouchThis"},
AdminRoleArn: "arn:mockAdmin",
})
require.Nil(t, err)

// Mock the RoleManager, to create an IAM Role for the Redbox Principal
roleManager.On("CreateRoleWithPolicy",
mock.MatchedBy(func(input *rolemanager.CreateRoleWithPolicyInput) bool {
Expand All @@ -411,14 +403,14 @@ func TestCreate(t *testing.T) {
{Key: aws.String("Name"), Value: aws.String("RedboxPrincipal")},
}, input.Tags)
assert.Equal(t, true, input.IgnoreAlreadyExistsErrors)
assert.Equal(t, expectedPolicy, input.PolicyDocument)
assert.Equal(t, "", "")

return true
}),
).Return(&rolemanager.CreateRoleWithPolicyOutput{}, nil)

// Call the controller with the account
_, err = controller.Call(
_, err := controller.Call(
context.TODO(),
createAccountAPIRequest(t, createRequest{
ID: "1234567890",
Expand Down Expand Up @@ -504,6 +496,15 @@ func tokenServiceStub() common.TokenService {
return tokenServiceMock
}

func StoragerMock() common.Storager {
storagerMock := &commonMocks.Storager{}

storagerMock.On("GetTemplateObject", mock.Anything, mock.Anything, mock.Anything).
Return("", "", nil)

return storagerMock
}

func roleManagerStub() *roleManagerMocks.RoleManager {
roleManagerMock := &roleManagerMocks.RoleManager{}
roleManagerMock.On("SetIAMClient", mock.Anything)
Expand Down Expand Up @@ -549,10 +550,11 @@ func unmarshal(t *testing.T, jsonStr string) map[string]interface{} {

func newCreateController() createController {
return createController{
Dao: dbStub(),
Queue: queueStub(),
SNS: snsStub(),
TokenService: tokenServiceStub(),
RoleManager: roleManagerStub(),
Dao: dbStub(),
Queue: queueStub(),
SNS: snsStub(),
TokenService: tokenServiceStub(),
RoleManager: roleManagerStub(),
StoragerService: StoragerMock(),
}
}
16 changes: 13 additions & 3 deletions cmd/lambda/accounts/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,16 @@ package main
import (
"context"
"fmt"
"github.com/Optum/Redbox/pkg/rolemanager"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/iam"
"log"
"net/http"
"strings"

"github.com/Optum/Redbox/pkg/rolemanager"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/iam"
"github.com/aws/aws-sdk-go/service/s3"
"github.com/aws/aws-sdk-go/service/s3/s3manager"

"github.com/Optum/Redbox/pkg/common"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/sns"
Expand Down Expand Up @@ -63,6 +66,10 @@ func main() {
queue := common.SQSQueue{Client: sqs.New(awsSession)}
snsSvc := &common.SNS{Client: sns.New(awsSession)}
tokenSvc := common.STS{Client: sts.New(awsSession)}
storageSvc := &common.S3{
Client: s3.New(awsSession),
Manager: s3manager.NewDownloader(awsSession),
}

// Configure the Router + Controllers
router := &Router{
Expand All @@ -88,11 +95,14 @@ func main() {
AccountCreatedTopicArn: common.RequireEnv("ACCOUNT_CREATED_TOPIC_ARN"),
AWSSession: *awsSession,
TokenService: tokenSvc,
StoragerService: storageSvc,
RoleManager: &rolemanager.IAMRoleManager{},
PrincipalRoleName: common.RequireEnv("PRINCIPAL_ROLE_NAME"),
PrincipalPolicyName: common.RequireEnv("PRINCIPAL_POLICY_NAME"),
PrincipalIAMDenyTags: strings.Split(common.RequireEnv("PRINCIPAL_IAM_DENY_TAGS"), ","),
PrincipalMaxSessionDuration: int64(common.RequireEnvInt("PRINCIPAL_MAX_SESSION_DURATION")),
ArtifactsBucket: common.RequireEnv("ARTIFACTS_BUCKET"),
PrincipalPolicyS3Key: common.RequireEnv("PRINCIPAL_POLICY_S3_KEY"),
Tags: []*iam.Tag{
{Key: aws.String("Terraform"), Value: aws.String("False")},
{Key: aws.String("Source"), Value: aws.String("github.com/Optum/Redbox//cmd/lambda/accounts")},
Expand Down
Loading

0 comments on commit 1176672

Please sign in to comment.