Skip to content

Commit

Permalink
OCM-13040 | test: Bastion proxy support username and password
Browse files Browse the repository at this point in the history
  • Loading branch information
jameszwang committed Dec 23, 2024
1 parent 0ebf08b commit 5604e86
Show file tree
Hide file tree
Showing 4 changed files with 140 additions and 45 deletions.
7 changes: 7 additions & 0 deletions pkg/aws/consts/consts.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,13 @@ const (
InstanceKeyNamePrefix = "ocm-ci"
AWSInstanceUser = "ec2-user"
BastionName = "ocm-bastion"

SSHPort = "22"

// Squid related
SquidConfigFilePath = "/etc/squid/squid.conf"
SquidPasswordFilePath = "/etc/squid/passwords"
SquidProxyPort = "3128"
)

var AmazonName = "amazon"
Expand Down
9 changes: 9 additions & 0 deletions pkg/aws/utils/utils.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package utils

import (
"fmt"
"github.com/openshift-online/ocm-common/pkg/log"
"path"
"strings"

"github.com/aws/aws-sdk-go-v2/aws/arn"
Expand All @@ -25,3 +28,9 @@ func GetPathFromArn(arnStr string) (string, error) {
func TruncateRoleName(name string) string {
return commonUtils.Truncate(name, commonUtils.MaxByteSize)
}

func GetPrivateKeyName(privateKeyPath string, keypairName string) string {
privateKeyName := fmt.Sprintf("%s-%s", path.Join(privateKeyPath, keypairName), "keyPair.pem")
log.LogInfo("Get private key name finished.")
return privateKeyName
}
134 changes: 89 additions & 45 deletions pkg/test/vpc_client/bastion.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,14 @@ 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"
"net/url"
"time"

CON "github.com/openshift-online/ocm-common/pkg/aws/consts"
awsUtils "github.com/openshift-online/ocm-common/pkg/aws/utils"
"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 +97,37 @@ 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) {
encodeUserData := generateShellCommand()
instance, err := vpc.LaunchBastion("", zone, encodeUserData, keypairName, privateKeyPath)
if err != nil {
return nil, err
return "", err
log.LogError("Launch bastion failed")

Check failure on line 106 in pkg/test/vpc_client/bastion.go

View workflow job for this annotation

GitHub Actions / Lint

unreachable: unreachable code (govet)
}
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)

privateKeyName := awsUtils.GetPrivateKeyName(privateKeyPath, keypairName)
hostName := fmt.Sprintf("%s:%s", *instance.PublicIpAddress, CON.SSHPort)
SSHExecuteCMDs, username, password, err := generateWriteSquidPasswordFileCommand()
if err != nil {
return "", err
}
for _, cmd := range SSHExecuteCMDs {
_, err = Exec_CMD(CON.AWSInstanceUser, privateKeyName, hostName, cmd)
if err != nil {
log.LogError("CIDR IP address format is invalid")
return nil, err
log.LogError("SSH execute command failed")
return "", 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)

encodeUserData := base64.StdEncoding.EncodeToString([]byte(userData))
return vpc.LaunchBastion("", zone, encodeUserData, keypairName, privateKeyPath)

}
log.LogInfo("Found existing bastion: %s", *insts[0].InstanceId)
return &insts[0], nil

// construct proxy url
proxy := &url.URL{
Scheme: "http",
Host: fmt.Sprintf("%s:%s", *instance.PublicIpAddress, CON.SquidProxyPort),
User: url.UserPassword(username, password),
}
proxyUrl = proxy.String()
return proxyUrl, nil
}

func (vpc *VPC) DestroyBastionProxy(instance types.Instance) error {
Expand All @@ -155,3 +140,62 @@ 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
}
log.LogInfo("Generate hashed password finished.")
return string(hashedPassword), nil
}

func generateShellCommand() string {
userData := fmt.Sprintf(`#!/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 %s >> %s
echo auth_param basic program /usr/lib64/squid/basic_ncsa_auth %s >> %s
echo auth_param basic realm Squid Proxy Server >> %s
echo acl authenticated proxy_auth REQUIRED >> %s
echo http_access allow authenticated >> %s
echo http_access deny all >> %s
systemctl start squid
systemctl enable squid`, CON.SquidProxyPort, CON.SquidConfigFilePath, CON.SquidPasswordFilePath,
CON.SquidConfigFilePath, CON.SquidConfigFilePath, CON.SquidConfigFilePath, CON.SquidConfigFilePath,
CON.SquidConfigFilePath)

encodeUserData := base64.StdEncoding.EncodeToString([]byte(userData))
log.LogInfo("Generate user data to creating squid proxy successfully.")

return encodeUserData
}

func generateWriteSquidPasswordFileCommand() (SSHExecuteCMDs []string, username string,
password string, err error) {
username = utils.RandomLabel(5)
password = utils.GeneratePassword(10)

hashedPassword, err := generateBcryptPassword(password)
if err != nil {
log.LogError("Generate bcrypt password failed.")
return []string{}, "", "", err
}

line := fmt.Sprintf("%s:%s\n", username, hashedPassword)
remoteFilePath := CON.SquidPasswordFilePath

createFileCMD := fmt.Sprintf("sudo touch %s", remoteFilePath)
copyPasswordCMD := fmt.Sprintf("echo '%s' | sudo tee %s > /dev/null", line, remoteFilePath)
SSHExecuteCMDs = []string{
createFileCMD,
copyPasswordCMD,
}

log.LogInfo("Generate write squid password file command finished.")
return SSHExecuteCMDs, username, password, nil
}
35 changes: 35 additions & 0 deletions pkg/utils/utils.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package utils

import (
"github.com/openshift-online/ocm-common/pkg/log"
"math/rand"
"time"
)
Expand Down Expand Up @@ -45,3 +46,37 @@ func Truncate(s string, truncateLength int) string {
}
return s
}

func GeneratePassword(length int) string {
lowercase := "abcdefghijklmnopqrstuvwxyz"
uppercase := "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
digits := "0123456789"
special := "!#$^&*()-_=+{}|;:,.<>?/~`"
allChars := lowercase + uppercase + digits + special

var password []rune

password = append(password, rune(lowercase[randInt(len(lowercase))]))
password = append(password, rune(uppercase[randInt(len(uppercase))]))
password = append(password, rune(digits[randInt(len(digits))]))
password = append(password, rune(special[randInt(len(special))]))

for len(password) < length {
password = append(password, rune(allChars[randInt(len(allChars))]))
}

shuffleStrings(password)
log.LogInfo("Generate squid password finished.")
return string(password)
}

func randInt(max int) int {
return rand.Intn(max)
}

func shuffleStrings(s []rune) {
for i := len(s) - 1; i > 0; i-- {
j := randInt(i + 1)
s[i], s[j] = s[j], s[i]
}
}

0 comments on commit 5604e86

Please sign in to comment.