go.mondoo.com/cnquery@v0.0.0-20231005093811-59568235f6ea/providers/os/connection/ssh/awsinstanceconnect/ec2instanceconnect.go (about) 1 // Copyright (c) Mondoo, Inc. 2 // SPDX-License-Identifier: BUSL-1.1 3 4 package awsinstanceconnect 5 6 import ( 7 "context" 8 "net" 9 10 "github.com/aws/aws-sdk-go-v2/aws" 11 "github.com/aws/aws-sdk-go-v2/service/ec2" 12 ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" 13 "github.com/aws/aws-sdk-go-v2/service/ec2instanceconnect" 14 "github.com/cockroachdb/errors" 15 "github.com/sethvargo/go-password/password" 16 "go.mondoo.com/cnquery/providers/os/connection/ssh/keypair" 17 ) 18 19 type generator struct { 20 cfg aws.Config 21 } 22 23 func New(cfg aws.Config) *generator { 24 return &generator{cfg: cfg} 25 } 26 27 type InstanceCredentials struct { 28 InstanceId string 29 KeyPair *keypair.SSH 30 PublicDnsName string 31 PrivateDnsName string 32 PublicIpAddress string 33 } 34 35 // Note: target can either be the IP (ipv4) address or the instance id of the machine 36 func (c *generator) GenerateCredentials(target string, user string) (*InstanceCredentials, error) { 37 ctx := context.Background() 38 ec2srv := ec2.NewFromConfig(c.cfg) 39 input := &ec2.DescribeInstancesInput{} 40 ip := net.ParseIP(target) 41 if ip != nil && ip.To4() != nil { 42 filter := "ip-address" 43 input.Filters = []ec2types.Filter{ 44 { 45 Name: &filter, 46 Values: []string{target}, 47 }, 48 } 49 } else { 50 input.InstanceIds = []string{target} 51 } 52 resp, err := ec2srv.DescribeInstances(ctx, input) 53 if err != nil { 54 return nil, err 55 } 56 57 if len(resp.Reservations) != 1 || len(resp.Reservations[0].Instances) != 1 { 58 return nil, errors.New("could not find the instance") 59 } 60 61 instance := resp.Reservations[0].Instances[0] 62 63 // generate random passphrase 64 passphrase, err := password.Generate(64, 10, 10, false, false) 65 if err != nil { 66 return nil, err 67 } 68 69 sshkeypair, err := keypair.NewRSAKeys(keypair.DefaultRsaBits, []byte(passphrase)) 70 if err != nil { 71 return nil, err 72 } 73 74 ec2ic := ec2instanceconnect.NewFromConfig(c.cfg) 75 _, err = ec2ic.SendSSHPublicKey(ctx, &ec2instanceconnect.SendSSHPublicKeyInput{ 76 InstanceId: instance.InstanceId, 77 AvailabilityZone: instance.Placement.AvailabilityZone, 78 InstanceOSUser: aws.String(user), 79 SSHPublicKey: aws.String(string(sshkeypair.PublicKey)), 80 }) 81 if err != nil { 82 return nil, err 83 } 84 85 ic := &InstanceCredentials{ 86 KeyPair: sshkeypair, 87 } 88 89 if instance.PublicDnsName != nil { 90 ic.PublicDnsName = *instance.PublicDnsName 91 } 92 93 if instance.PrivateDnsName != nil { 94 ic.PrivateDnsName = *instance.PrivateDnsName 95 } 96 97 if instance.PublicIpAddress != nil { 98 ic.PublicIpAddress = *instance.PublicIpAddress 99 } 100 101 if instance.InstanceId != nil { 102 ic.InstanceId = *instance.InstanceId 103 } 104 105 return ic, nil 106 }