From 1cf5acc5d35cb861063bc73956c7ddcd35cf4568 Mon Sep 17 00:00:00 2001 From: Victoria Jeffrey Date: Wed, 13 Sep 2023 21:30:46 -0600 Subject: [PATCH] hook up the aws ebs connection --- providers/aws/config/config.go | 3 +- .../aws/connection/awsec2ebsconn/provider.go | 76 +++++++++++++------ providers/aws/provider/provider.go | 28 ++++--- .../aws/resources/discovery_conversion.go | 36 +++++++++ 4 files changed, 109 insertions(+), 34 deletions(-) diff --git a/providers/aws/config/config.go b/providers/aws/config/config.go index 64cfa9c676..2d045d9279 100644 --- a/providers/aws/config/config.go +++ b/providers/aws/config/config.go @@ -6,6 +6,7 @@ package config import ( "go.mondoo.com/cnquery/providers-sdk/v1/plugin" "go.mondoo.com/cnquery/providers/aws/connection" + "go.mondoo.com/cnquery/providers/aws/connection/awsec2ebsconn" "go.mondoo.com/cnquery/providers/aws/provider" ) @@ -13,7 +14,7 @@ var Config = plugin.Provider{ Name: "aws", ID: "go.mondoo.com/cnquery/providers/aws", Version: "9.0.0", - ConnectionTypes: []string{provider.DefaultConnectionType}, + ConnectionTypes: []string{provider.DefaultConnectionType, string(awsec2ebsconn.EBSConnectionType)}, Connectors: []plugin.Connector{ { Name: "aws", diff --git a/providers/aws/connection/awsec2ebsconn/provider.go b/providers/aws/connection/awsec2ebsconn/provider.go index 3534b87b56..c5e84c0cfd 100644 --- a/providers/aws/connection/awsec2ebsconn/provider.go +++ b/providers/aws/connection/awsec2ebsconn/provider.go @@ -21,6 +21,7 @@ import ( "go.mondoo.com/cnquery/providers/os/connection" "go.mondoo.com/cnquery/providers/os/connection/shared" "go.mondoo.com/cnquery/providers/os/connection/snapshot" + "go.mondoo.com/cnquery/providers/os/detector" ) const ( @@ -28,6 +29,8 @@ const ( ) type AwsEbsConnection struct { + id uint32 + asset *inventory.Asset FsProvider *connection.FileSystemConnection scannerRegionEc2svc *ec2.Client targetRegionEc2svc *ec2.Client @@ -40,17 +43,13 @@ type AwsEbsConnection struct { volumeMounter *snapshot.VolumeMounter } -/* -TODOS -// TODO: validate the expected permissions here -// TODO allow custom aws config - -*/ - // New creates a new aws-ec2-ebs provider // It expects to be running on an ec2 instance with ssm iam role and // permissions for copy snapshot, create snapshot, create volume, attach volume, detach volume func NewAwsEbsConnection(id uint32, conf *inventory.Config, asset *inventory.Asset) (*AwsEbsConnection, error) { + log.Debug().Msg("new aws ebs connection") + // TODO: validate the expected permissions here + // TODO: allow custom aws config // 1. validate; load cfg, err := config.LoadDefaultConfig(context.Background()) if err != nil { @@ -79,7 +78,6 @@ func NewAwsEbsConnection(id uint32, conf *inventory.Config, asset *inventory.Ass opts: conf.Options, target: awsec2ebstypes.TargetInfo{ PlatformId: conf.PlatformId, - AccountId: conf.Options["account"], Region: conf.Options["region"], Id: conf.Options["id"], }, @@ -93,6 +91,7 @@ func NewAwsEbsConnection(id uint32, conf *inventory.Config, asset *inventory.Ass targetRegionEc2svc: targetSvc, scannerRegionEc2svc: scannerSvc, volumeMounter: volumeMounter, + asset: asset, } log.Debug().Interface("info", c.target).Str("type", c.targetType).Msg("target") @@ -145,23 +144,26 @@ func NewAwsEbsConnection(id uint32, conf *inventory.Config, asset *inventory.Ass Backend: "fs", PlatformId: conf.PlatformId, Options: conf.Options, - }, nil) // TODO ASSET..? + }, asset) if err != nil { return nil, err } c.FsProvider = fsConn + var ok bool + asset.Platform, ok = detector.DetectOS(fsConn) + if !ok { + return nil, errors.New("failed to detect OS") + } + asset.Id = conf.Type + asset.Platform.Runtime = c.Runtime() return c, nil } -func (c *AwsEbsConnection) RunCommand(command string) (*shared.Command, error) { - return nil, errors.New("RunCommand not implemented") -} - func (c *AwsEbsConnection) FileInfo(path string) (shared.FileInfoDetails, error) { return shared.FileInfoDetails{}, errors.New("FileInfo not implemented") } -func (c *AwsEbsConnection) FS() afero.Fs { +func (c *AwsEbsConnection) FileSystem() afero.Fs { return c.FsProvider.FileSystem() } @@ -198,16 +200,6 @@ func (c *AwsEbsConnection) Close() { } } -// func (c *AwsEbsConnection) Capabilities() providers.Capabilities { -// return providers.Capabilities{ -// providers.Capability_Aws_Ebs, -// } -// } - -func (c *AwsEbsConnection) Runtime() string { - return "aws-ec2-ebs" -} - func RawInstanceInfo(cfg aws.Config) (*imds.InstanceIdentityDocument, error) { metadata := imds.NewFromConfig(cfg) ctx := context.Background() @@ -296,3 +288,39 @@ func ParseEbsTransportUrl(path string) (*awsec2ebstypes.EbsTransportTarget, erro return &awsec2ebstypes.EbsTransportTarget{Account: keyValues[1], Region: keyValues[3], Id: keyValues[5], Type: itemType}, nil } + +func (c *AwsEbsConnection) Name() string { + return "aws ebs" +} + +func (c *AwsEbsConnection) ID() uint32 { + return c.id +} + +func (c *AwsEbsConnection) Asset() *inventory.Asset { + return c.asset +} + +func (c *AwsEbsConnection) Capabilities() shared.Capabilities { + return shared.Capability_RunCommand // not true, update to nothing +} + +func (c *AwsEbsConnection) RunCommand(command string) (*shared.Command, error) { + return nil, errors.New("unimplemented") +} + +func (c *AwsEbsConnection) Type() shared.ConnectionType { + return EBSConnectionType +} + +func (c *AwsEbsConnection) Runtime() string { + return "aws-ebs" +} + +func (c *AwsEbsConnection) PlatformInfo() *inventory.Platform { + return &inventory.Platform{ + Name: "aws-ebs", + Title: "aws-ebs", + Runtime: c.Runtime(), + } +} diff --git a/providers/aws/provider/provider.go b/providers/aws/provider/provider.go index 74a19b9aba..0ddeb6d04b 100644 --- a/providers/aws/provider/provider.go +++ b/providers/aws/provider/provider.go @@ -12,6 +12,7 @@ import ( "go.mondoo.com/cnquery/providers-sdk/v1/plugin" "go.mondoo.com/cnquery/providers-sdk/v1/upstream" "go.mondoo.com/cnquery/providers/aws/connection" + "go.mondoo.com/cnquery/providers/aws/connection/awsec2ebsconn" "go.mondoo.com/cnquery/providers/aws/resources" osconnection "go.mondoo.com/cnquery/providers/os/connection" "go.mondoo.com/cnquery/providers/os/connection/shared" @@ -44,7 +45,7 @@ func (s *Service) ParseCLI(req *plugin.ParseCLIReq) (*plugin.ParseCLIRes, error) opts := parseFlagsToOptions(flags) // handle aws subcommands - if len(req.Args) == 3 && req.Args[0] == "ec2" { + if len(req.Args) >= 3 && req.Args[0] == "ec2" { return &plugin.ParseCLIRes{Asset: handleAwsEc2Subcommands(req.Args, opts)}, nil } @@ -63,7 +64,7 @@ func (s *Service) ParseCLI(req *plugin.ParseCLIReq) (*plugin.ParseCLIRes, error) inventoryConfig.Discover = &inventory.Discovery{Targets: discoverTargets} asset := inventory.Asset{ Connections: []*inventory.Config{inventoryConfig}, - Options: parseFlagsToOptions(flags), + Options: opts, } return &plugin.ParseCLIRes{Asset: &asset}, nil } @@ -76,6 +77,7 @@ func handleAwsEc2Subcommands(args []string, opts map[string]string) *inventory.A case "ssm": return resources.SSMConnectAsset(args, opts) case "ebs": + return resources.EbsConnectAsset(args, opts) } return asset } @@ -83,7 +85,7 @@ func handleAwsEc2Subcommands(args []string, opts map[string]string) *inventory.A func parseFlagsToOptions(m map[string]*llx.Primitive) map[string]string { o := make(map[string]string, 0) for k, v := range m { - if k == "profile" || k == "region" || k == "role" || k == "endpoint-url" { + if k == "profile" || k == "region" || k == "role" || k == "endpoint-url" || k == "no-setup" { if val := string(v.Value); val != "" { o[k] = string(v.Value) } @@ -161,6 +163,11 @@ func (s *Service) connect(req *plugin.ConnectReq, callback plugin.ProviderCallba case osprovider.RegistryImageConnectionType: s.lastConnectionID++ conn, err = osconnection.NewContainerRegistryImage(s.lastConnectionID, conf, asset) + + case string(awsec2ebsconn.EBSConnectionType): + s.lastConnectionID++ + conn, err = awsec2ebsconn.NewAwsEbsConnection(s.lastConnectionID, conf, asset) + default: s.lastConnectionID++ conn, err = connection.NewAwsConnection(s.lastConnectionID, asset, conf) @@ -190,12 +197,15 @@ func (s *Service) connect(req *plugin.ConnectReq, callback plugin.ProviderCallba } func (s *Service) detect(asset *inventory.Asset, conn plugin.Connection) error { - c := conn.(*connection.AwsConnection) - asset.Id = c.Conf.Type + "://" + c.AccountId() - asset.Name = c.Conf.Host - asset.Platform = c.PlatformInfo() - asset.PlatformIds = []string{"//platformid.api.mondoo.app/runtime/aws/accounts" + c.AccountId()} - + if c, ok := conn.(*connection.AwsConnection); ok { + asset.Id = c.Conf.Type + "://" + c.AccountId() + asset.Name = c.Conf.Host + asset.Platform = c.PlatformInfo() + asset.PlatformIds = []string{"//platformid.api.mondoo.app/runtime/aws/accounts" + c.AccountId()} + } + if c, ok := conn.(*awsec2ebsconn.AwsEbsConnection); ok { + asset.Platform = c.PlatformInfo() + } return nil } diff --git a/providers/aws/resources/discovery_conversion.go b/providers/aws/resources/discovery_conversion.go index 6d82e73d62..7c0aa78c88 100644 --- a/providers/aws/resources/discovery_conversion.go +++ b/providers/aws/resources/discovery_conversion.go @@ -15,6 +15,8 @@ import ( "go.mondoo.com/cnquery/providers-sdk/v1/inventory" "go.mondoo.com/cnquery/providers-sdk/v1/vault" "go.mondoo.com/cnquery/providers/aws/connection" + "go.mondoo.com/cnquery/providers/aws/connection/awsec2ebsconn" + awsec2ebstypes "go.mondoo.com/cnquery/providers/aws/connection/awsec2ebsconn/types" "go.mondoo.com/cnquery/providers/os/id/awsec2" "go.mondoo.com/cnquery/providers/os/id/containerid" ) @@ -685,3 +687,37 @@ func InstanceConnectAsset(args []string, opts map[string]string) *inventory.Asse }} return asset } + +func EbsConnectAsset(args []string, opts map[string]string) *inventory.Asset { + var target, targetType string + if len(args) >= 3 { + if args[0] == "ec2" && args[1] == "ebs" { + // parse for target type: instance, volume, snapshot + switch args[2] { + case awsec2ebstypes.EBSTargetVolume: + target = args[3] + targetType = awsec2ebstypes.EBSTargetVolume + case awsec2ebstypes.EBSTargetSnapshot: + target = args[3] + targetType = awsec2ebstypes.EBSTargetSnapshot + default: + // in the case of an instance target, this is the instance id + target = args[2] + targetType = awsec2ebstypes.EBSTargetInstance + } + } + } + asset := &inventory.Asset{} + opts["type"] = targetType + opts["id"] = target + asset.Name = target + asset.Connections = []*inventory.Config{{ + Backend: string(awsec2ebsconn.EBSConnectionType), + Type: string(awsec2ebsconn.EBSConnectionType), + Host: target, + Insecure: true, + Runtime: "aws-ebs", + Options: opts, + }} + return asset +}