Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add --scan-all option to ECS snapshot command #322

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion cmd/kosli/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,8 +157,9 @@ The service principal needs to have the following permissions:
resultsDirFlag = "[defaulted] The path to a directory with JUnit test results. By default, the directory will be uploaded to Kosli's evidence vault."
snykJsonResultsFileFlag = "The path to Snyk SARIF or JSON scan results file from 'snyk test' and 'snyk container test'. By default, the Snyk results will be uploaded to Kosli's evidence vault."
snykSarifResultsFileFlag = "The path to Snyk scan SARIF results file from 'snyk test' and 'snyk container test'. By default, the Snyk results will be uploaded to Kosli's evidence vault."
ecsClusterFlag = "The name of the ECS cluster."
ecsClusterFlag = "[exclusive] The name of the ECS cluster. Can't be used together with --scan-all."
ecsServiceFlag = "[optional] The name of the ECS service."
ecsScanAllFlag = "[exclusive] Scan all ECS clusters. Can't be used together with --cluster."
kubeconfigFlag = "[defaulted] The kubeconfig path for the target cluster."
namespaceFlag = "[conditional] The comma separated list of namespaces regex patterns to report artifacts info from. Can't be used together with --exclude-namespace."
excludeNamespaceFlag = "[conditional] The comma separated list of namespaces regex patterns NOT to report artifacts info from. Can't be used together with --namespace."
Expand Down
59 changes: 48 additions & 11 deletions cmd/kosli/snapshotECS.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,16 @@ kosli snapshot ecs yourEnvironmentName \
--api-token yourAPIToken \
--org yourOrgName

# report what is running in all AWS ECS clusters to a single Kosli environment:
export AWS_REGION=yourAWSRegion
export AWS_ACCESS_KEY_ID=yourAWSAccessKeyID
export AWS_SECRET_ACCESS_KEY=yourAWSSecretAccessKey

kosli snapshot ecs yourEnvironmentName \
--scan-all \
--api-token yourAPIToken \
--org yourOrgName

# report what is running in a specific AWS ECS service within a cluster:
export AWS_REGION=yourAWSRegion
export AWS_ACCESS_KEY_ID=yourAWSAccessKeyID
Expand All @@ -51,6 +61,7 @@ type snapshotECSOptions struct {
cluster string
serviceName string
awsStaticCreds *aws.AWSStaticCreds
scanAll bool
}

func newSnapshotECSCmd(out io.Writer) *cobra.Command {
Expand All @@ -67,6 +78,11 @@ func newSnapshotECSCmd(out io.Writer) *cobra.Command {
if err != nil {
return ErrorBeforePrintingUsage(cmd, err.Error())
}

err = MuXRequiredFlags(cmd, []string{"cluster", "scan-all"}, true)
if err != nil {
return err
}
return nil
},
RunE: func(cmd *cobra.Command, args []string) error {
Expand All @@ -76,28 +92,49 @@ func newSnapshotECSCmd(out io.Writer) *cobra.Command {

cmd.Flags().StringVarP(&o.cluster, "cluster", "C", "", ecsClusterFlag)
cmd.Flags().StringVarP(&o.serviceName, "service-name", "s", "", ecsServiceFlag)
cmd.Flags().BoolVarP(&o.scanAll, "scan-all", "A", false, ecsScanAllFlag)
addAWSAuthFlags(cmd, o.awsStaticCreds)
addDryRunFlag(cmd)

err := RequireFlags(cmd, []string{"cluster"})
if err != nil {
logger.Error("failed to configure required flags: %v", err)
}

return cmd
}

func (o *snapshotECSOptions) run(args []string) error {
envName := args[0]
url := fmt.Sprintf("%s/api/v2/environments/%s/%s/report/ECS", global.Host, global.Org, envName)

tasksData, err := o.awsStaticCreds.GetEcsTasksData(o.cluster, o.serviceName)
if err != nil {
return err
logger.Debug("ECS Snapshot parameters: scan-all: %t, cluster: %s", o.scanAll, o.cluster)

tasksDataList := []*aws.EcsTaskData{}

if o.scanAll {
logger.Debug("Attempting to find ECS clusters")
clusters, err := o.awsStaticCreds.GetECSClusters()
if err != nil {
logger.Error("Failed to get ECS clusters: %v", err)
return err
}

logger.Debug("Found %d ECS clusters.", len(clusters))
for _, cluster := range clusters {
logger.Debug("Processing ECS cluster with ARN: %s", cluster)
tasksData, err := o.awsStaticCreds.GetEcsTasksData(cluster, o.serviceName)
if err != nil {
return err
}
// append to EcsTaskDataList
tasksDataList = append(tasksDataList, tasksData...)

}
} else {
tasksData, err := o.awsStaticCreds.GetEcsTasksData(o.cluster, o.serviceName)
if err != nil {
return err
}
tasksDataList = append(tasksDataList, tasksData...)
}

payload := &aws.EcsEnvRequest{
Artifacts: tasksData,
Artifacts: tasksDataList,
}

reqParams := &requests.RequestParams{
Expand All @@ -107,7 +144,7 @@ func (o *snapshotECSOptions) run(args []string) error {
DryRun: global.DryRun,
Password: global.ApiToken,
}
_, err = kosliClient.Do(reqParams)
_, err := kosliClient.Do(reqParams)
if err == nil && !global.DryRun {
logger.Info("[%d] containers were reported to environment %s", len(payload.Artifacts), envName)
}
Expand Down
11 changes: 9 additions & 2 deletions cmd/kosli/snapshotECS_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,16 @@ func (suite *SnapshotECSTestSuite) TestSnapshotECSCmd() {
tests := []cmdTestCase{
{
wantError: true,
name: "snapshot ECS fails if --cluster is missing",
name: "snapshot ECS fails if --cluster and --scan-all is missing",
cmd: fmt.Sprintf(`snapshot ecs %s %s`, suite.envName, suite.defaultKosliArguments),
golden: "Error: required flag(s) \"cluster\" not set\n",
golden: "Error: at least one of --cluster, --scan-all is required\n",
// golden: "Error: required flag(s) \"cluster\" not set\n",
},
{
wantError: true,
name: "snapshot ECS fails if both --cluster and --scan-all is set",
cmd: fmt.Sprintf(`snapshot ecs %s %s --cluster sss --scan-all`, suite.envName, suite.defaultKosliArguments),
golden: "Error: only one of --cluster, --scan-all is allowed\n",
},
{
wantError: true,
Expand Down
18 changes: 18 additions & 0 deletions internal/aws/aws.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,24 @@ func (staticCreds *AWSStaticCreds) NewECSClient() (*ecs.Client, error) {
return ecs.NewFromConfig(cfg), nil
}

func (staticCreds *AWSStaticCreds) GetECSClusters() ([]string, error) {
ecsClient, err := staticCreds.NewECSClient()
if err != nil {
return []string{}, err
}
clusters := []string{}
params := &ecs.ListClustersInput{}
paginator := ecs.NewListClustersPaginator(ecsClient, params)
for paginator.HasMorePages() {
output, err := paginator.NextPage(context.Background())
if err != nil {
return clusters, err
}
clusters = append(clusters, output.ClusterArns...)
}
return clusters, nil
}

// getAllLambdaFuncs fetches all lambda functions recursively (50 at a time) and returns a list of FunctionConfiguration
func getAllLambdaFuncs(client *lambda.Client, nextMarker *string, allFunctions *[]types.FunctionConfiguration) (*[]types.FunctionConfiguration, error) {
params := &lambda.ListFunctionsInput{}
Expand Down