Skip to content

Commit

Permalink
Merge pull request #89 from ava-labs/ssh-priv-key-path
Browse files Browse the repository at this point in the history
Ssh priv key path
  • Loading branch information
sukantoraymond authored Jun 27, 2024
2 parents f8222c9 + 0dd22db commit e9c1f8c
Show file tree
Hide file tree
Showing 3 changed files with 122 additions and 10 deletions.
73 changes: 70 additions & 3 deletions examples/aws.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,87 @@ import (
"time"

"github.com/ava-labs/avalanche-tooling-sdk-go/avalanche"
awsAPI "github.com/ava-labs/avalanche-tooling-sdk-go/cloud/aws"
"github.com/ava-labs/avalanche-tooling-sdk-go/node"
"github.com/ava-labs/avalanche-tooling-sdk-go/utils"
)

// createSecurityGroup creates a new security group in AWS using the specified AWS profile and region.
//
// ctx: The context.Context object for the request.
// awsProfile: The AWS profile to use for the request.
// awsRegion: The AWS region to use for the request.
// Returns the ID of the created security group and an error, if any.
func createSecurityGroup(ctx context.Context, awsProfile string, awsRegion string) (string, error) {
ec2Svc, err := awsAPI.NewAwsCloud(
ctx,
awsProfile,
awsRegion,
)
if err != nil {
return "", err
}
// detect user IP address
userIPAddress, err := utils.GetUserIPAddress()
if err != nil {
return "", err
}
const securityGroupName = "avalanche-tooling-sdk-go"
return ec2Svc.SetupSecurityGroup(userIPAddress, securityGroupName)
}

// createSSHKeyPair creates an SSH key pair for AWS.
//
// ctx: The context for the request.
// awsProfile: The AWS profile to use for the request.
// awsRegion: The AWS region to use for the request.
// sshPrivateKeyPath: The path to save the SSH private key.
// Returns an error if unable to create the key pair.
func createSSHKeyPair(ctx context.Context, awsProfile string, awsRegion string, keyPairName string, sshPrivateKeyPath string) error {
if utils.FileExists(sshPrivateKeyPath) {
return fmt.Errorf("ssh private key %s already exists", sshPrivateKeyPath)
}
ec2Svc, err := awsAPI.NewAwsCloud(
ctx,
awsProfile,
awsRegion,
)
if err != nil {
return err
}
return ec2Svc.CreateAndDownloadKeyPair(keyPairName, sshPrivateKeyPath)
}

func main() {
ctx := context.Background()

// Get the default cloud parameters for AWS
cp, err := node.GetDefaultCloudParams(ctx, node.AWSCloud)
if err != nil {
panic(err)
}
// Set the cloud parameters for AWS non provided by the default
// Please set your own values for the following fields
cp.AWSConfig.AWSProfile = "default"
cp.AWSConfig.AWSSecurityGroupID = "sg-0e198c427f8f0616b"
cp.AWSConfig.AWSKeyPair = "artur-us-east-1-avalanche-cli"
// For example cp.AWSConfig.AWSProfile = "default" and so on

// Create security group or you can provide your own by setting cp.AWSConfig.AWSSecurityGroupID
sgID, err := createSecurityGroup(ctx, cp.AWSConfig.AWSProfile, cp.Region)
if err != nil {
panic(err)
}
cp.AWSConfig.AWSSecurityGroupID = sgID

// Change to your own path
sshPrivateKey := utils.ExpandHome("~/.ssh/avalanche-tooling-sdk-go.pem")

// Create aws ssh key pair or you can provide your own by setting cp.AWSConfig.AWSKeyPair.
// Make sure that ssh private key matches AWSKeyPair
keyPairName := "avalanche-tooling-sdk-go"
if err := createSSHKeyPair(ctx, cp.AWSConfig.AWSProfile, cp.Region, keyPairName, sshPrivateKey); err != nil {
panic(err)
}
cp.AWSConfig.AWSKeyPair = keyPairName

// Create a new host instance. Count is 1 so only one host will be created
const (
avalanchegoVersion = "v1.11.8"
Expand All @@ -38,6 +104,7 @@ func main() {
AvalancheGoVersion: avalanchegoVersion,
AvalancheCliVersion: avalancheCliVersion,
UseStaticIP: false,
SSHPrivateKey: sshPrivateKey,
})
if err != nil {
panic(err)
Expand Down
18 changes: 12 additions & 6 deletions node/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ type NodeParams struct {
Count int
Roles []SupportedRole
Network avalanche.Network
SSHPrivateKey string
AvalancheGoVersion string
AvalancheCliVersion string
UseStaticIP bool
Expand All @@ -31,7 +32,7 @@ func CreateNodes(
ctx context.Context,
nodeParams *NodeParams,
) ([]Node, error) {
nodes, err := createCloudInstances(ctx, *nodeParams.CloudParams, nodeParams.Count, nodeParams.UseStaticIP)
nodes, err := createCloudInstances(ctx, *nodeParams.CloudParams, nodeParams.Count, nodeParams.UseStaticIP, nodeParams.SSHPrivateKey)
if err != nil {
return nil, err
}
Expand All @@ -58,19 +59,22 @@ func CreateNodes(
}

// preCreateCheck checks if the cloud parameters are valid.
func preCreateCheck(cp CloudParams, count int) error {
func preCreateCheck(cp CloudParams, count int, sshPrivateKeyPath string) error {
if count < 1 {
return fmt.Errorf("count must be at least 1")
}
if err := cp.Validate(); err != nil {
return err
}
if sshPrivateKeyPath != "" && !utils.FileExists(sshPrivateKeyPath) {
return fmt.Errorf("ssh private key path %s does not exist", sshPrivateKeyPath)
}
return nil
}

// createCloudInstances launches the specified number of instances on the selected cloud platform.
func createCloudInstances(ctx context.Context, cp CloudParams, count int, useStaticIP bool) ([]Node, error) {
if err := preCreateCheck(cp, count); err != nil {
func createCloudInstances(ctx context.Context, cp CloudParams, count int, useStaticIP bool, sshPrivateKeyPath string) ([]Node, error) {
if err := preCreateCheck(cp, count, sshPrivateKeyPath); err != nil {
return nil, err
}
nodes := make([]Node, 0, count)
Expand Down Expand Up @@ -131,7 +135,8 @@ func createCloudInstances(ctx context.Context, cp CloudParams, count int, useSta
Cloud: cp.Cloud(),
CloudConfig: cp,
SSHConfig: SSHConfig{
User: constants.AnsibleSSHUser,
User: constants.AnsibleSSHUser,
PrivateKeyPath: sshPrivateKeyPath,
},
Roles: nil,
})
Expand Down Expand Up @@ -176,7 +181,8 @@ func createCloudInstances(ctx context.Context, cp CloudParams, count int, useSta
Cloud: cp.Cloud(),
CloudConfig: cp,
SSHConfig: SSHConfig{
User: constants.AnsibleSSHUser,
User: constants.AnsibleSSHUser,
PrivateKeyPath: sshPrivateKeyPath,
},
Roles: nil,
})
Expand Down
41 changes: 40 additions & 1 deletion utils/net.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,47 @@

package utils

import "net"
import (
"encoding/json"
"errors"
"io"
"net"
"net/http"
)

func IsValidIP(ipStr string) bool {
return net.ParseIP(ipStr) != nil
}

// GetUserIPAddress retrieves the IP address of the user.
func GetUserIPAddress() (string, error) {
resp, err := http.Get("https://api.ipify.org?format=json")
if err != nil {
return "", err
}
defer resp.Body.Close()

if resp.StatusCode != http.StatusOK {
return "", errors.New("HTTP request failed")
}

body, err := io.ReadAll(resp.Body)
if err != nil {
return "", err
}

var result map[string]interface{}
if err := json.Unmarshal(body, &result); err != nil {
return "", err
}

ipAddress, ok := result["ip"].(string)
if ok {
if net.ParseIP(ipAddress) == nil {
return "", errors.New("invalid IP address")
}
return ipAddress, nil
}

return "", errors.New("no IP address found")
}

0 comments on commit e9c1f8c

Please sign in to comment.