Skip to content

Commit

Permalink
Merge pull request #91 from padok-team/oussama/feat-checks
Browse files Browse the repository at this point in the history
Oussama/feat checks
  • Loading branch information
StanGirard committed Apr 10, 2023
2 parents 6299dae + 43d6de3 commit 8a507f5
Show file tree
Hide file tree
Showing 16 changed files with 620 additions and 5 deletions.
9 changes: 7 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ The available log levels are: `debug`, `info`, `warn`, `error`, `fatal`, `panic`

<!-- BEGIN_YATAS -->

## AWS - 63 Checks
## AWS - 68 Checks

### AWS Certificate Manager
- AWS_ACM_001 ACM certificates are valid
Expand Down Expand Up @@ -165,6 +165,7 @@ The available log levels are: `debug`, `info`, `warn`, `error`, `fatal`, `panic`

### Cognito
- AWS_COG_001 Cognito allows unauthenticated users
- AWS_COG_002 Cognito allows self-registration

### DynamoDB
- AWS_DYN_001 Dynamodbs are encrypted
Expand Down Expand Up @@ -193,12 +194,15 @@ The available log levels are: `debug`, `info`, `warn`, `error`, `fatal`, `panic`
- AWS_IAM_001 IAM Users have 2FA activated
- AWS_IAM_002 IAM access key younger than 90 days
- AWS_IAM_003 IAM User can't elevate rights
- AWS_IAM_004 IAM Users have not used their password for 120 days
- AWS_IAM_004 IAM Role can't elevate rights
- AWS_IAM_005 IAM Users have not used their password for 120 days

### Lambda
- AWS_LMD_001 Lambdas are private
- AWS_LMD_002 Lambdas are in a security group
- AWS_LMD_003 Lambdas are not with errors
- AWS_LMD_004 Lambdas has no hard-coded secrets in environment
- AWS_LMD_005 Lambdas has no public URL access

### RDS
- AWS_RDS_001 RDS are encrypted
Expand Down Expand Up @@ -233,6 +237,7 @@ The available log levels are: `debug`, `info`, `warn`, `error`, `fatal`, `panic`
- AWS_VPC_003 VPC only have one Gateway
- AWS_VPC_004 VPC Flow Logs are activated
- AWS_VPC_005 VPC have at least 2 subnets
- AWS_VPC_006 VPC's Subnets are in different zones

<!-- END_YATAS -->

Expand Down
3 changes: 3 additions & 0 deletions aws/cognito/cognito.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,11 @@ func RunChecks(wa *sync.WaitGroup, s aws.Config, c *commons.Config, queue chan [
var checks []commons.Check
cognitoPools := GetCognitoPools(s)
cognitoPoolsDetailed := GetDetailedCognitoPool(s, cognitoPools)
cognitoUserPools := GetCognitoUserPools(s)
cognitoUserPoolsDetailed := GetDetailedCognitoUserPool(s, cognitoUserPools)

go commons.CheckTest(checkConfig.Wg, c, "AWS_COG_001", CheckIfCognitoAllowsUnauthenticated)(checkConfig, cognitoPoolsDetailed, "AWS_COG_001")
go commons.CheckTest(checkConfig.Wg, c, "AWS_COG_002", CheckIfCognitoSelfRegistration)(checkConfig, cognitoUserPoolsDetailed, "AWS_COG_002")

go func() {
for t := range checkConfig.Queue {
Expand Down
23 changes: 23 additions & 0 deletions aws/cognito/cognitoPoolSelfRegistration.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package cognito

import (
"github.com/aws/aws-sdk-go-v2/service/cognitoidentityprovider"
"github.com/padok-team/yatas/plugins/commons"
)

func CheckIfCognitoSelfRegistration(checkConfig commons.CheckConfig, cognitoUserPools []cognitoidentityprovider.DescribeUserPoolOutput, testName string) {
var check commons.Check
check.InitCheck("Cognito allows self-registration", "Check if Cognito allows self-registration", testName, []string{"Security", "Good Practice"})
for _, c := range cognitoUserPools {
if !c.UserPool.AdminCreateUserConfig.AllowAdminCreateUserOnly {
Message := "Cognito allows self-registration on " + *c.UserPool.Name
result := commons.Result{Status: "FAIL", Message: Message, ResourceID: *c.UserPool.Arn}
check.AddResult(result)
} else {
Message := "Cognito does not allow self-registration on " + *c.UserPool.Name
result := commons.Result{Status: "OK", Message: Message, ResourceID: *c.UserPool.Arn}
check.AddResult(result)
}
}
checkConfig.Queue <- check
}
99 changes: 99 additions & 0 deletions aws/cognito/cognitoPoolSelfRegistration_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package cognito

import (
"sync"
"testing"

"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/service/cognitoidentityprovider"
"github.com/aws/aws-sdk-go-v2/service/cognitoidentityprovider/types"
"github.com/padok-team/yatas/plugins/commons"
)

func TestCheckIfCognitoSelfRegistration(t *testing.T) {
type args struct {
checkConfig commons.CheckConfig
cognitoUserPools []cognitoidentityprovider.DescribeUserPoolOutput
testName string
}
tests := []struct {
name string
args args
}{
{
name: "TestCheckIfCognitoSelfRegistration",
args: args{
checkConfig: commons.CheckConfig{Queue: make(chan commons.Check, 1), Wg: &sync.WaitGroup{}},
cognitoUserPools: []cognitoidentityprovider.DescribeUserPoolOutput{
{
UserPool: &types.UserPoolType{
Name: aws.String("test"),
Arn: aws.String("arn:aws:cognito-idp:us-east-1:123456789012:userpool/us-east-1_test"),
AdminCreateUserConfig: &types.AdminCreateUserConfigType{AllowAdminCreateUserOnly: true},
},
},
},
},
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
CheckIfCognitoSelfRegistration(tt.args.checkConfig, tt.args.cognitoUserPools, tt.args.testName)
tt.args.checkConfig.Wg.Add(1)
go func() {
for check := range tt.args.checkConfig.Queue {
if check.Status != "OK" {
t.Errorf("CheckIfCognitoSelfRegistration() = %v, want %v", check.Status, "OK")
}
tt.args.checkConfig.Wg.Done()
}
}()
tt.args.checkConfig.Wg.Wait()
})
}
}

func TestCheckIfCognitoSelfRegistrationFail(t *testing.T) {
type args struct {
checkConfig commons.CheckConfig
cognitoUserPools []cognitoidentityprovider.DescribeUserPoolOutput
testName string
}
tests := []struct {
name string
args args
}{
{
name: "TestCheckIfCognitoSelfRegistration",
args: args{
checkConfig: commons.CheckConfig{Queue: make(chan commons.Check, 1), Wg: &sync.WaitGroup{}},
cognitoUserPools: []cognitoidentityprovider.DescribeUserPoolOutput{
{
UserPool: &types.UserPoolType{
Name: aws.String("test"),
Arn: aws.String("arn:aws:cognito-idp:us-east-1:123456789012:userpool/us-east-1_test"),
AdminCreateUserConfig: &types.AdminCreateUserConfigType{AllowAdminCreateUserOnly: false},
},
},
},
},
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
CheckIfCognitoSelfRegistration(tt.args.checkConfig, tt.args.cognitoUserPools, tt.args.testName)
tt.args.checkConfig.Wg.Add(1)
go func() {
for check := range tt.args.checkConfig.Queue {
if check.Status != "FAIL" {
t.Errorf("CheckIfCognitoSelfRegistration() = %v, want %v", check.Status, "FAIL")
}
tt.args.checkConfig.Wg.Done()
}
}()
tt.args.checkConfig.Wg.Wait()
})
}
}
4 changes: 2 additions & 2 deletions aws/cognito/cognitoPoolUnauthenticated.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ func CheckIfCognitoAllowsUnauthenticated(checkConfig commons.CheckConfig, cognit
for _, c := range cognitoPools {
if c.AllowUnauthenticatedIdentities {
Message := "Cognito allows unauthenticated users on " + *c.IdentityPoolName
result := commons.Result{Status: "FAIL", Message: Message, ResourceID: *c.IdentityPoolName}
result := commons.Result{Status: "FAIL", Message: Message, ResourceID: *c.IdentityPoolId}
check.AddResult(result)
} else {
Message := "Cognito does not allow unauthenticated users on " + *c.IdentityPoolName
result := commons.Result{Status: "OK", Message: Message, ResourceID: *c.IdentityPoolName}
result := commons.Result{Status: "OK", Message: Message, ResourceID: *c.IdentityPoolId}
check.AddResult(result)
}
}
Expand Down
94 changes: 94 additions & 0 deletions aws/cognito/cognitoPoolUnauthenticated_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package cognito

import (
"sync"
"testing"

"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/service/cognitoidentity"
"github.com/padok-team/yatas/plugins/commons"
)

func TestCheckIfCognitoAllowsUnauthenticated(t *testing.T) {
type args struct {
checkConfig commons.CheckConfig
cognitoPools []cognitoidentity.DescribeIdentityPoolOutput
testName string
}
tests := []struct {
name string
args args
}{
{
name: "TestCheckIfCognitoAllowsUnauthenticated",
args: args{
checkConfig: commons.CheckConfig{Queue: make(chan commons.Check, 1), Wg: &sync.WaitGroup{}},
cognitoPools: []cognitoidentity.DescribeIdentityPoolOutput{
{
IdentityPoolName: aws.String("test"),
IdentityPoolId: aws.String("us-east-1:cb21213c-a931-11ed-afa1-0242ac120002"),
AllowUnauthenticatedIdentities: false,
},
},
},
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
CheckIfCognitoAllowsUnauthenticated(tt.args.checkConfig, tt.args.cognitoPools, tt.args.testName)
tt.args.checkConfig.Wg.Add(1)
go func() {
for check := range tt.args.checkConfig.Queue {
if check.Status != "OK" {
t.Errorf("CheckIfCognitoAllowsUnauthenticated() = %v, want %v", check.Status, "OK")
}
tt.args.checkConfig.Wg.Done()
}
}()
tt.args.checkConfig.Wg.Wait()
})
}
}

func TestCheckIfCognitoAllowsUnauthenticatedFail(t *testing.T) {
type args struct {
checkConfig commons.CheckConfig
cognitoPools []cognitoidentity.DescribeIdentityPoolOutput
testName string
}
tests := []struct {
name string
args args
}{
{
name: "TestCheckIfCognitoAllowsUnauthenticated",
args: args{
checkConfig: commons.CheckConfig{Queue: make(chan commons.Check, 1), Wg: &sync.WaitGroup{}},
cognitoPools: []cognitoidentity.DescribeIdentityPoolOutput{
{
IdentityPoolName: aws.String("test"),
IdentityPoolId: aws.String("us-east-1:cb21213c-a931-11ed-afa1-0242ac120002"),
AllowUnauthenticatedIdentities: true,
},
},
},
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
CheckIfCognitoAllowsUnauthenticated(tt.args.checkConfig, tt.args.cognitoPools, tt.args.testName)
tt.args.checkConfig.Wg.Add(1)
go func() {
for check := range tt.args.checkConfig.Queue {
if check.Status != "FAIL" {
t.Errorf("CheckIfCognitoAllowsUnauthenticated() = %v, want %v", check.Status, "FAIL")
}
tt.args.checkConfig.Wg.Done()
}
}()
tt.args.checkConfig.Wg.Wait()
})
}
}
36 changes: 35 additions & 1 deletion aws/cognito/getter.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import (
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/service/cognitoidentity"
"github.com/aws/aws-sdk-go-v2/service/cognitoidentity/types"
"github.com/aws/aws-sdk-go-v2/service/cognitoidentityprovider"
ciptypes "github.com/aws/aws-sdk-go-v2/service/cognitoidentityprovider/types"
"github.com/padok-team/yatas-aws/logger"
)

Expand All @@ -21,7 +23,6 @@ func GetCognitoPools(s aws.Config) []types.IdentityPoolShortDescription {
// Return an empty list of certificates
return []types.IdentityPoolShortDescription{}
}
fmt.Println("Hello")
return result.IdentityPools
}

Expand All @@ -42,3 +43,36 @@ func GetDetailedCognitoPool(s aws.Config, pools []types.IdentityPoolShortDescrip
}
return detailedPools
}

func GetCognitoUserPools(s aws.Config) []ciptypes.UserPoolDescriptionType {
svc := cognitoidentityprovider.NewFromConfig(s)
logger.Logger.Info(fmt.Sprintf("Getting Cognito User Pools"))
cognitoInput := &cognitoidentityprovider.ListUserPoolsInput{
MaxResults: 50,
}
result, err := svc.ListUserPools(context.TODO(), cognitoInput)
if err != nil {
logger.Logger.Error(err.Error())
// Return an empty list of certificates
return []ciptypes.UserPoolDescriptionType{}
}
return result.UserPools
}

func GetDetailedCognitoUserPool(s aws.Config, userPools []ciptypes.UserPoolDescriptionType) []cognitoidentityprovider.DescribeUserPoolOutput {
svc := cognitoidentityprovider.NewFromConfig(s)
var detailedUserPools []cognitoidentityprovider.DescribeUserPoolOutput
for _, userPool := range userPools {
cognitoInput := &cognitoidentityprovider.DescribeUserPoolInput{
UserPoolId: userPool.Id,
}
result, err := svc.DescribeUserPool(context.TODO(), cognitoInput)
if err != nil {
logger.Logger.Error(err.Error())
// Return an empty list of certificates
continue
}
detailedUserPools = append(detailedUserPools, *result)
}
return detailedUserPools
}
21 changes: 21 additions & 0 deletions aws/lambda/getter.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,24 @@ func GetLambdas(s aws.Config) []types.FunctionConfiguration {
}
return lambdas
}

func GetLambdaUrlConfigs(s aws.Config, lambdas []types.FunctionConfiguration) []LambdaUrlConfig {
svc := lambda.NewFromConfig(s)
lambdaUrlConfigs := []LambdaUrlConfig{}
for _, function := range lambdas {
input := &lambda.ListFunctionUrlConfigsInput{
FunctionName: function.FunctionName,
}
result, err := svc.ListFunctionUrlConfigs(context.TODO(), input)
if err != nil {
logger.Logger.Error(err.Error())
return []LambdaUrlConfig{}
}
lambdaUrlConfigs = append(lambdaUrlConfigs, LambdaUrlConfig{
LambdaName: *function.FunctionName,
LambdaArn: *function.FunctionArn,
UrlConfigs: result.FunctionUrlConfigs,
})
}
return lambdaUrlConfigs
}
3 changes: 3 additions & 0 deletions aws/lambda/lambda.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,13 @@ func RunChecks(wa *sync.WaitGroup, s aws.Config, c *commons.Config, queue chan [
checkConfig.Init(c)
var checks []commons.Check
lambdas := GetLambdas(s)
lambdaUrlConfigs := GetLambdaUrlConfigs(s, lambdas)

go commons.CheckTest(checkConfig.Wg, c, "AWS_LMD_001", CheckIfLambdaPrivate)(checkConfig, lambdas, "AWS_LMD_001")
go commons.CheckTest(checkConfig.Wg, c, "AWS_LMD_002", CheckIfLambdaInSecurityGroup)(checkConfig, lambdas, "AWS_LMD_002")
go commons.CheckTest(checkConfig.Wg, c, "AWS_LMD_003", CheckIfLambdaNoErrors)(checkConfig, lambdas, "AWS_LMD_003")
go commons.CheckTest(checkConfig.Wg, c, "AWS_LMD_004", CheckIfLambdaNoSecrets)(checkConfig, lambdas, "AWS_LMD_004")
go commons.CheckTest(checkConfig.Wg, c, "AWS_LMD_005", CheckIfLambdaUrlAuth)(checkConfig, lambdaUrlConfigs, "AWS_LMD_005")
go func() {
for t := range checkConfig.Queue {
t.EndCheck()
Expand Down
Loading

0 comments on commit 8a507f5

Please sign in to comment.