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

OCM-13040 | test: Bastion proxy support username and password #81

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
106 changes: 62 additions & 44 deletions pkg/test/vpc_client/bastion.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@ import (
"fmt"
"github.com/aws/aws-sdk-go-v2/service/ec2/types"
"github.com/openshift-online/ocm-common/pkg/file"
"net"
"golang.org/x/crypto/bcrypt"
"path"
"time"

CON "github.com/openshift-online/ocm-common/pkg/aws/consts"
"github.com/openshift-online/ocm-common/pkg/log"
"github.com/openshift-online/ocm-common/pkg/utils"
)

// LaunchBastion will launch a bastion instance on the indicated zone.
Expand Down Expand Up @@ -94,55 +96,45 @@ func (vpc *VPC) LaunchBastion(imageID string, zone string, userData string, keyp
return inst, nil
}

func (vpc *VPC) PrepareBastionProxy(zone string, cidrBlock string, keypairName string,
privateKeyPath string) (*types.Instance, error) {
filters := []map[string][]string{
{
"vpc-id": {
vpc.VpcID,
},
},
{
"tag:Name": {
CON.BastionName,
},
},
}

insts, err := vpc.AWSClient.ListInstances([]string{}, filters...)
// PrepareBastionProxy will launch a bastion instance with squid proxy on the indicated zone and return the proxy url.
func (vpc *VPC) PrepareBastionProxy(zone string, keypairName string, privateKeyPath string) (proxyUrl string, err error) {
userData := generateShellCommand()

encodeUserData := base64.StdEncoding.EncodeToString([]byte(userData))
instance, err := vpc.LaunchBastion("", zone, encodeUserData, keypairName, privateKeyPath)
if err != nil {
return nil, err
log.LogError("Launch bastion failed")
}
if len(insts) == 0 {
log.LogInfo("Didn't found an existing bastion, going to launch one")
if cidrBlock == "" {
cidrBlock = CON.RouteDestinationCidrBlock
}
_, _, err = net.ParseCIDR(cidrBlock)
if err != nil {
log.LogError("CIDR IP address format is invalid")
return nil, err
}

userData := fmt.Sprintf(`#!/bin/bash
yum update -y
yum install -y squid
cd /etc/squid/
sudo mv ./squid.conf ./squid.conf.bak
sudo touch squid.conf
echo http_port 3128 >> /etc/squid/squid.conf
echo acl allowed_ips src %s >> /etc/squid/squid.conf
echo http_access allow allowed_ips >> /etc/squid/squid.conf
echo http_access deny all >> /etc/squid/squid.conf
systemctl start squid
systemctl enable squid`, cidrBlock)
username := utils.RandomLabel(5)
password := utils.RandomLabel(10)

hashedPassword, err := generateBcryptPassword(password)
if err != nil {
return "", err
}

encodeUserData := base64.StdEncoding.EncodeToString([]byte(userData))
return vpc.LaunchBastion("", zone, encodeUserData, keypairName, privateKeyPath)
line := fmt.Sprintf("%s:%s\n", username, hashedPassword)
remoteFilePath := "/etc/squid/passwords"
hostName := fmt.Sprintf("%s:22", *instance.PublicIpAddress)
createFileCMD := fmt.Sprintf("sudo touch %s", remoteFilePath)
copyPasswordCMD := fmt.Sprintf("echo '%s' | sudo tee %s > /dev/null", line, remoteFilePath)
SSHExecuteCMDs := []string{
createFileCMD,
copyPasswordCMD,
}
privateKeyName := fmt.Sprintf("%s-%s", path.Join(privateKeyPath, keypairName), "keyPair.pem")

for _, cmd := range SSHExecuteCMDs {
_, err = Exec_CMD(CON.AWSInstanceUser, privateKeyName, hostName, cmd)
if err != nil {
log.LogError("SSH execute command failed")
return "", err
}
}
log.LogInfo("Found existing bastion: %s", *insts[0].InstanceId)
return &insts[0], nil

proxyUrl = fmt.Sprintf("http://%s:%s@%s:3128", username, password, *instance.PublicIpAddress)
return proxyUrl, nil
}

func (vpc *VPC) DestroyBastionProxy(instance types.Instance) error {
Expand All @@ -155,3 +147,29 @@ func (vpc *VPC) DestroyBastionProxy(instance types.Instance) error {
}
return nil
}

func generateBcryptPassword(plainPassword string) (string, error) {
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(plainPassword), bcrypt.DefaultCost)
if err != nil {
log.LogError("Generate hashed password failed")
return "", nil
}
return string(hashedPassword), nil
}

func generateShellCommand() string {
return `#!/bin/bash
yum update -y
sudo dnf install squid -y
cd /etc/squid/
sudo mv ./squid.conf ./squid.conf.bak
sudo touch squid.conf
echo http_port 3128 >> /etc/squid/squid.conf
echo auth_param basic program /usr/lib64/squid/basic_ncsa_auth /etc/squid/passwords >> /etc/squid/squid.conf
echo auth_param basic realm Squid Proxy Server >> /etc/squid/squid.conf
echo acl authenticated proxy_auth REQUIRED >> /etc/squid/squid.conf
echo http_access allow authenticated >> /etc/squid/squid.conf
echo http_access deny all >> /etc/squid/squid.conf
systemctl start squid
systemctl enable squid`
}
Loading