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

DEVOPS-3141 teleport changes #118

Merged
merged 24 commits into from
Nov 4, 2022
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
d6140ae
make ridectl compatible with teleport
shubhindia Dec 16, 2021
72f0473
remove vpn check since we are going via teleport
shubhindia Dec 16, 2021
21a7ff4
Merge branch 'master' into ridectl-teleport-compatibility
vivekjainx86 Jul 18, 2022
1b406f6
add teleport changes
vivekjainx86 Jul 25, 2022
cb5407d
fix lint error
vivekjainx86 Jul 25, 2022
c120737
remove vpn check
vivekjainx86 Jul 25, 2022
1655be7
allow input from user incase of tsh login
vivekjainx86 Jul 26, 2022
b7d3bd5
add tsh login check
vivekjainx86 Aug 8, 2022
251215c
embed tsh into binary
vivekjainx86 Aug 10, 2022
eee31bd
fix lint errors
vivekjainx86 Aug 10, 2022
02d5ff1
remove overwrite flag
vivekjainx86 Aug 10, 2022
959aa32
some more fixes
vivekjainx86 Aug 16, 2022
7754bc2
rewrite execute command code
vivekjainx86 Aug 17, 2022
638338a
check tsh version using md5
vivekjainx86 Aug 24, 2022
d78e798
improved md5sum value injection
vivekjainx86 Aug 29, 2022
66921c2
add cluster name as prefix to rdsInstanceName
vivekjainx86 Sep 6, 2022
2dca9ee
add comment for using prefix for rds name
vivekjainx86 Sep 7, 2022
966c6a7
add help command in password and some changes
vivekjainx86 Sep 8, 2022
ba06b7d
upgrade tsh version to 10.2.4
vivekjainx86 Sep 27, 2022
bb6f498
upgrade tsh version
vivekjainx86 Oct 6, 2022
f746cf7
copy tsh binary using sudo
vivekjainx86 Oct 14, 2022
c0a911e
Modify makefile to use build script
vivekjainx86 Nov 3, 2022
afc521e
add bin/bash shebang
vivekjainx86 Nov 3, 2022
f5dbf19
updte teleport faq link
vivekjainx86 Nov 4, 2022
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
13 changes: 12 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,22 @@
# See the License for the specific language governing permissions and
# limitations under the License.

TSH_VERSION = 10.1.4

# Build command binary, for macOS
build_macos:
wget https://get.gravitational.com/teleport-v$(TSH_VERSION)-darwin-amd64-bin.tar.gz
tar -xf teleport-v$(TSH_VERSION)-darwin-amd64-bin.tar.gz
cp teleport/tsh pkg/exec/bin/
# Adding double $ in awk command to escape single $
md5sum teleport/tsh | awk '{ print $$1 }'| tr -d '\n' > pkg/exec/bin/tsh.md5
GOOS=darwin GOARCH=amd64 go build -o bin/ridectl.macos -ldflags "-X github.com/Ridecell/ridectl/pkg/cmd.version=$(shell git describe --tags)" -tags release github.com/Ridecell/ridectl/cmd/ridectl

# Build command binary, for Linux
build_linux:
wget https://get.gravitational.com/teleport-v$(TSH_VERSION)-linux-amd64-bin.tar.gz
tar -xf teleport-v$(TSH_VERSION)-linux-amd64-bin.tar.gz
cp teleport/tsh pkg/exec/bin/
# Adding double $ in awk command to escape single $
md5sum teleport/tsh | awk '{ print $$1 }'| tr -d '\n' > pkg/exec/bin/tsh.md5
GOOS=linux GOARCH=amd64 go build -o bin/ridectl.linux -ldflags "-X github.com/Ridecell/ridectl/pkg/cmd.version=$(shell git describe --tags)" -tags release github.com/Ridecell/ridectl/cmd/ridectl

31 changes: 18 additions & 13 deletions pkg/cmd/dbshell.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ package cmd
import (
"context"
"fmt"
"os"
"reflect"
"strings"

"github.com/Ridecell/ridectl/pkg/exec"
"github.com/pterm/pterm"
Expand Down Expand Up @@ -49,8 +49,7 @@ var dbShellCmd = &cobra.Command{
return nil
},
PreRunE: func(cmd *cobra.Command, args []string) error {

utils.CheckVPN()
utils.CheckTshLogin()
utils.CheckPsql()
return nil
},
Expand All @@ -59,23 +58,29 @@ var dbShellCmd = &cobra.Command{
kubeconfig := utils.GetKubeconfig()
target, err := kubernetes.ParseSubject(args[0])
if err != nil {
pterm.Error.Println(err, "Its not a valid Summonplatform or Microservice")
os.Exit(1)
return fmt.Errorf("Its not a valid Summonplatform or Microservice: %s", err)
}
kubeObj := kubernetes.GetAppropriateObjectWithContext(*kubeconfig, args[0], target, inCluster)
if reflect.DeepEqual(kubeObj, kubernetes.Kubeobject{}) {
pterm.Error.Printf("No instance found %s\n", args[0])
os.Exit(1)
return fmt.Errorf("No instance found %s\n", args[0])
}
secretObj := &corev1.Secret{}
err = kubeObj.Client.Get(context.Background(), types.NamespacedName{Name: target.Name + ".postgres-user-password", Namespace: target.Namespace}, secretObj)
err = kubeObj.Client.Get(context.Background(), types.NamespacedName{Name: target.Name + "-rdsiam-readonly.postgres-user-password", Namespace: target.Namespace}, secretObj)
if err != nil {
pterm.Error.Printf("instance not found in %s", kubeObj.Context.Cluster)
os.Exit(1)
return fmt.Errorf("Error getting secret for instance %s", err)
}

psqlCmd := []string{"psql", "-h", string(secretObj.Data["host"]), "-U", string(secretObj.Data["username"]), string(secretObj.Data["dbname"])}
os.Setenv("PGPASSWORD", string(secretObj.Data["password"]))
return exec.Exec(psqlCmd)
// Derive RDS instance name using hostname
rdsInstanceName := strings.Split(string(secretObj.Data["host"]), ".")[0]

pterm.Info.Println("Getting database login credentials")
dbLoginArgs := []string{"db", "login", "--db-user=" + string(secretObj.Data["username"]), "--db-name=" + string(secretObj.Data["dbname"]), rdsInstanceName}
err = exec.ExecuteCommand("tsh", dbLoginArgs, false)
if err != nil {
return fmt.Errorf("Could not login to database, %s", err)
}
pterm.Info.Println("Logging in into database")
dbConnectCmd := []string{"db", "connect", rdsInstanceName}
return exec.ExecuteCommand("tsh", dbConnectCmd, true)
},
}
3 changes: 2 additions & 1 deletion pkg/cmd/password.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ var passwordCmd = &cobra.Command{
},

PreRunE: func(cmd *cobra.Command, args []string) error {
utils.CheckVPN()
utils.CheckTshLogin()
return nil
},
RunE: func(cmd *cobra.Command, args []string) error {
Expand Down Expand Up @@ -94,6 +94,7 @@ var passwordCmd = &cobra.Command{
}

pterm.Success.Printf("Password for %s: %s\n", args[0], string(secret.Data["password"]))
pterm.Warning.Printf("If someone has changed or reset the password manually, then above password will not work.\n")

case "postgresql":
// get a list of secrets which have readonly in their name
Expand Down
2 changes: 1 addition & 1 deletion pkg/cmd/postgresdump.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ var postgresdumpCMD = &cobra.Command{
return nil
},
PreRunE: func(cmd *cobra.Command, args []string) error {
utils.CheckVPN()
utils.CheckTshLogin()
return nil
},
RunE: func(cmd *cobra.Command, args []string) error {
Expand Down
13 changes: 6 additions & 7 deletions pkg/cmd/pyshell.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,7 @@ var pyShellCmd = &cobra.Command{
return nil
},
PreRunE: func(cmd *cobra.Command, args []string) error {

utils.CheckVPN()
utils.CheckTshLogin()
utils.CheckKubectl()
return nil
},
Expand Down Expand Up @@ -95,11 +94,11 @@ var pyShellCmd = &cobra.Command{
podList := &corev1.PodList{}
err = kubeObj.Client.List(context.Background(), podList, listOptions)
if err != nil {
pterm.Error.Printf("instance not found in %s", kubeObj.Context.Cluster)
pterm.Error.Printf("instance not found in %s", kubeObj.Context)
os.Exit(1)
}
if len(podList.Items) < 1 {
pterm.Error.Printf("instance not found in %s", kubeObj.Context.Cluster)
pterm.Error.Printf("instance not found in %s", kubeObj.Context)
os.Exit(1)
}

Expand All @@ -112,7 +111,7 @@ var pyShellCmd = &cobra.Command{
}
}
if pod.Name == "" {
pterm.Error.Printf("no running pod found in %s", kubeObj.Context.Cluster)
pterm.Error.Printf("no running pod found in %s", kubeObj.Context)
os.Exit(1)
}

Expand All @@ -122,8 +121,8 @@ var pyShellCmd = &cobra.Command{
// Warn people that this is a container.
pterm.Warning.Printf("Remember that this is a container and most changes will have no effect\n")

kubectlArgs := []string{"kubectl", "exec", "-it", "-n", pod.Namespace, pod.Name, "--context", kubeObj.Context.Cluster, "--", "bash", "-l", "-c", "python manage.py shell"}
return exec.Exec(kubectlArgs)
kubectlArgs := []string{"exec", "-it", "-n", pod.Namespace, pod.Name, "--context", kubeObj.Context, "--", "bash", "-l", "-c", "python manage.py shell"}
return exec.ExecuteCommand("kubectl", kubectlArgs, true)

},
}
2 changes: 1 addition & 1 deletion pkg/cmd/restart.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ var rollingRestartCmd = &cobra.Command{
return nil
},
PreRunE: func(cmd *cobra.Command, args []string) error {
utils.CheckVPN()
utils.CheckTshLogin()
return nil
},
RunE: func(cmd *cobra.Command, args []string) error {
Expand Down
13 changes: 6 additions & 7 deletions pkg/cmd/shell.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,7 @@ var shellCmd = &cobra.Command{
return nil
},
PreRunE: func(cmd *cobra.Command, args []string) error {

utils.CheckVPN()
utils.CheckTshLogin()
utils.CheckKubectl()
return nil
},
Expand Down Expand Up @@ -95,11 +94,11 @@ var shellCmd = &cobra.Command{
podList := &corev1.PodList{}
err = kubeObj.Client.List(context.Background(), podList, listOptions)
if err != nil {
pterm.Error.Printf("instance not found in %s", kubeObj.Context.Cluster)
pterm.Error.Printf("instance not found in %s", kubeObj.Context)
os.Exit(1)
}
if len(podList.Items) < 1 {
pterm.Error.Printf("instance not found in %s", kubeObj.Context.Cluster)
pterm.Error.Printf("instance not found in %s", kubeObj.Context)
os.Exit(1)
}

Expand All @@ -112,7 +111,7 @@ var shellCmd = &cobra.Command{
}
}
if pod.Name == "" {
pterm.Error.Printf("no running pod found in %s", kubeObj.Context.Cluster)
pterm.Error.Printf("no running pod found in %s", kubeObj.Context)
os.Exit(1)
}

Expand All @@ -122,8 +121,8 @@ var shellCmd = &cobra.Command{
// Warn people that this is a container.
pterm.Warning.Printf("Remember that this is a container and most changes will have no effect\n")

kubectlArgs := []string{"kubectl", "exec", "-it", "-n", pod.Namespace, pod.Name, "--context", kubeObj.Context.Cluster, "--", "bash", "-l"}
return exec.Exec(kubectlArgs)
kubectlArgs := []string{"exec", "-it", "-n", pod.Namespace, pod.Name, "--context", kubeObj.Context, "--", "bash", "-l"}
return exec.ExecuteCommand("kubectl", kubectlArgs, true)

},
}
14 changes: 7 additions & 7 deletions pkg/cmd/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ var statusCmd = &cobra.Command{
return nil
},
PreRunE: func(cmd *cobra.Command, args []string) error {
utils.CheckVPN()
utils.CheckTshLogin()
utils.CheckKubectl()
return nil
},
Expand Down Expand Up @@ -138,16 +138,16 @@ var statusCmd = &cobra.Command{

var sData, dData, pData string
if statusType == "Summon Platform" {
sData, err = getData("summon", kubeObj.Context.Cluster, target.Namespace, name)
sData, err = getData("summon", kubeObj.Context, target.Namespace, name)
if err != nil {
return err
}
dData, err = getData("deployment", kubeObj.Context.Cluster, target.Namespace, name)
dData, err = getData("deployment", kubeObj.Context, target.Namespace, name)
if err != nil {
return err
}
} else {
pData, err = getData("postgresdump", kubeObj.Context.Cluster, target.Namespace, name)
pData, err = getData("postgresdump", kubeObj.Context, target.Namespace, name)
if err != nil {
return err
}
Expand All @@ -163,13 +163,13 @@ var statusCmd = &cobra.Command{
area.Update(sData, "\n", dData)
_, _ = p.Start()
p.Title = "Fetching data"
sData, err = getData("summon", kubeObj.Context.Cluster, target.Namespace, name)
sData, err = getData("summon", kubeObj.Context, target.Namespace, name)
if err != nil {
return err
}
p.Increment()

dData, err = getData("deployment", kubeObj.Context.Cluster, target.Namespace, name)
dData, err = getData("deployment", kubeObj.Context, target.Namespace, name)
if err != nil {
return err
}
Expand All @@ -179,7 +179,7 @@ var statusCmd = &cobra.Command{
area.Update(pData)
_, _ = p.Start()
p.Title = "Fetching data"
pData, err = getData("posgtresdump", kubeObj.Context.Cluster, target.Namespace, name)
pData, err = getData("posgtresdump", kubeObj.Context, target.Namespace, name)
if err != nil {
return err
}
Expand Down
Empty file added pkg/exec/bin/tsh
Empty file.
Empty file added pkg/exec/bin/tsh.md5
Empty file.
67 changes: 61 additions & 6 deletions pkg/exec/exec.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,72 @@ limitations under the License.
package exec

import (
"bytes"
_ "embed"
"fmt"
"os"
"os/exec"
"syscall"
"path/filepath"
)

func Exec(command []string) error {
binary, err := exec.LookPath(command[0])
var (
//go:embed bin/tsh
tsh []byte
//go:embed bin/tsh.md5
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of embedding the md5 hash file into the binary, we can set md5Sum string value at build time using -ldflags, something like shubhindia/go-m1temperature@1d0084b. Embedding the file will unnecessarily increase the overall binary size. 😁

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @shubhindia for suggestion, also we are already using -ldflags for version, we can use that for md5 hash too.

tshMD5 string
)

func InstallTsh() error {
executablePath, _ := os.Executable()
dir, err := filepath.Abs(filepath.Dir(executablePath))
if err != nil {
return err
}
err = syscall.Exec(binary, command, os.Environ())
// Panic rather than returning since this should never happen.
panic(err)
return os.WriteFile(dir+"/tsh", tsh, 0755)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This might cause issue in m1 where after executing the command it just returns zsh: killed because of some gatekeeper issues in macOS. This can be solved by running codesign after binary is copied so binary doesn't get quarantined. codesign --sign - --force --preserve-metadata=entitlements,requirements,flags,runtime <binary-path> should do the trick.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm.. I will check on it. 👍

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you face above issue with a binary built-for arm or x86_64? We are not planning to build an arm-based binary but relaying on rosetta to the job on m1/2 macs. 🤞

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope. There is no issue with x86_64. Using Rosetta would mean people will have to install it. The issue occurs on arm machines only. Even homebrew guys had to implement a workaround. Homebrew/brew@4c19d67
I found the above command from there only 🤪

Copy link
Contributor

@shubhindia shubhindia Aug 25, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or installation can be manual. Like it is done for kubectl right now. We just check if its installed and ask people to install it if it isn't

}

func GetTshMd5Hash() string {
return tshMD5
}

func CheckBinary(binary string) (string, bool) {
binaryPath, err := exec.LookPath(binary)
return binaryPath, err == nil
}

// ExecuteCommand uses os/exec Command fucntion to execute command,
// which returns the process output/error to parent process,
// If detachProcess flag set to true, then ridectl will exit with
// no error irrespective of given command's exit code.
func ExecuteCommand(binary string, args []string, detachProcess bool) error {
binaryPath, err := exec.LookPath(binary)
if err != nil {
return err
}

c := exec.Command(binaryPath, args...)
c.Stdin = os.Stdin

// Execute a process by seperating it's Stderr and Stdout streams from ridectl code
// Here we will just execute the command, and complete ridectl command with no error
// Mainly used by "kubectl exec" and "psql" commands
if detachProcess {
c.Stdout = os.Stdout
c.Stderr = os.Stderr
_ = c.Run()
return nil
}

// Here we will capture Stderr from given command output
// Mainly used by "tsh status" and "tsh db login" commands
var stderr bytes.Buffer
c.Stderr = &stderr
err = c.Run()
if err != nil {
if stderr.String() != "" {
return fmt.Errorf(stderr.String())
}
return fmt.Errorf("Error while executing command: %s", err.Error())
}
return nil
}
Loading