2021-08-02 01:10:41 +00:00
|
|
|
package app
|
|
|
|
|
|
|
|
import (
|
2021-08-30 15:02:08 +00:00
|
|
|
"context"
|
|
|
|
"errors"
|
2021-08-02 01:10:41 +00:00
|
|
|
"fmt"
|
2021-08-30 15:02:08 +00:00
|
|
|
"strconv"
|
2021-08-02 01:10:41 +00:00
|
|
|
|
2021-08-30 15:02:08 +00:00
|
|
|
abraFormatter "coopcloud.tech/abra/cli/formatter"
|
2021-08-02 01:10:41 +00:00
|
|
|
"coopcloud.tech/abra/cli/internal"
|
2021-08-30 15:02:08 +00:00
|
|
|
"coopcloud.tech/abra/client"
|
|
|
|
"coopcloud.tech/abra/config"
|
2021-08-02 01:10:41 +00:00
|
|
|
"coopcloud.tech/abra/secret"
|
2021-08-30 15:02:08 +00:00
|
|
|
"github.com/docker/docker/api/types"
|
|
|
|
"github.com/docker/docker/api/types/filters"
|
2021-08-02 01:10:41 +00:00
|
|
|
"github.com/sirupsen/logrus"
|
|
|
|
"github.com/urfave/cli/v2"
|
|
|
|
)
|
|
|
|
|
2021-08-02 06:36:35 +00:00
|
|
|
var allSecrets bool
|
|
|
|
var allSecretsFlag = &cli.BoolFlag{
|
|
|
|
Name: "all",
|
|
|
|
Value: false,
|
|
|
|
Destination: &allSecrets,
|
|
|
|
Usage: "Generate all secrets",
|
|
|
|
}
|
|
|
|
|
2021-08-30 15:02:08 +00:00
|
|
|
var appSecretGenerateCommand = &cli.Command{
|
2021-08-31 09:59:07 +00:00
|
|
|
Name: "generate",
|
|
|
|
Usage: "Generate secrets",
|
|
|
|
ArgsUsage: "<secret> <version>",
|
|
|
|
Flags: []cli.Flag{allSecretsFlag, internal.PassFlag},
|
2021-08-30 15:02:08 +00:00
|
|
|
Action: func(c *cli.Context) error {
|
2021-08-31 09:59:07 +00:00
|
|
|
appName := c.Args().First()
|
|
|
|
if appName == "" {
|
|
|
|
internal.ShowSubcommandHelpAndError(c, errors.New("no app name provided"))
|
|
|
|
}
|
|
|
|
|
|
|
|
if c.Args().Get(1) != "" && allSecrets {
|
|
|
|
internal.ShowSubcommandHelpAndError(c, errors.New("cannot use '<secret> <version>' and '--all' together"))
|
|
|
|
}
|
|
|
|
|
|
|
|
appFiles, err := config.LoadAppFiles("")
|
|
|
|
if err != nil {
|
|
|
|
logrus.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
appEnv, err := config.GetApp(appFiles, appName)
|
|
|
|
if err != nil {
|
|
|
|
logrus.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
secretsToCreate := make(map[string]string)
|
|
|
|
host := appFiles[appName].Server
|
|
|
|
secretEnvVars := secret.ReadSecretEnvVars(appEnv.Env)
|
|
|
|
if allSecrets {
|
|
|
|
secretsToCreate = secretEnvVars
|
|
|
|
} else {
|
|
|
|
secretName := c.Args().Get(1)
|
|
|
|
secretVersion := c.Args().Get(2)
|
|
|
|
for sec, _ := range secretEnvVars {
|
|
|
|
parsed := secret.ParseSecretEnvVarName(sec)
|
|
|
|
if secretName == parsed {
|
|
|
|
secretsToCreate[sec] = secretVersion
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
secretVals, err := secret.GenerateSecrets(secretsToCreate, appEnv.StackName(), host)
|
|
|
|
if err != nil {
|
|
|
|
logrus.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if internal.Pass {
|
|
|
|
for name, data := range secretVals {
|
|
|
|
if err := secret.PassInsertSecret(data, name, appEnv.StackName(), host); err != nil {
|
|
|
|
logrus.Fatal(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-08-30 15:02:08 +00:00
|
|
|
return nil
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
var appSecretInsertCommand = &cli.Command{
|
2021-08-31 08:50:02 +00:00
|
|
|
Name: "insert",
|
|
|
|
Usage: "Insert secret",
|
|
|
|
Flags: []cli.Flag{internal.PassFlag},
|
|
|
|
ArgsUsage: "<secret> <version> <data>",
|
2021-08-30 15:02:08 +00:00
|
|
|
Action: func(c *cli.Context) error {
|
2021-08-31 08:50:02 +00:00
|
|
|
appName := c.Args().First()
|
|
|
|
if appName == "" {
|
|
|
|
internal.ShowSubcommandHelpAndError(c, errors.New("no app name provided"))
|
|
|
|
}
|
|
|
|
|
|
|
|
if c.Args().Len() != 4 {
|
|
|
|
internal.ShowSubcommandHelpAndError(c, errors.New("missing arguments?"))
|
|
|
|
}
|
|
|
|
|
|
|
|
name := c.Args().Get(1)
|
|
|
|
version := c.Args().Get(2)
|
|
|
|
data := c.Args().Get(3)
|
|
|
|
|
|
|
|
appFiles, err := config.LoadAppFiles("")
|
|
|
|
if err != nil {
|
|
|
|
logrus.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
appEnv, err := config.GetApp(appFiles, appName)
|
|
|
|
if err != nil {
|
|
|
|
logrus.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
host := appFiles[appName].Server
|
|
|
|
secretName := fmt.Sprintf("%s_%s_%s", appEnv.StackName(), name, version)
|
|
|
|
if err := client.StoreSecret(secretName, data, host); err != nil {
|
|
|
|
logrus.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if internal.Pass {
|
|
|
|
if err := secret.PassInsertSecret(data, name, appEnv.StackName(), host); err != nil {
|
|
|
|
logrus.Fatal(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-08-30 15:02:08 +00:00
|
|
|
return nil
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
var appSecretRmCommand = &cli.Command{
|
2021-08-31 08:31:54 +00:00
|
|
|
Name: "remove",
|
|
|
|
Usage: "Remove a secret",
|
|
|
|
Aliases: []string{"rm"},
|
|
|
|
Flags: []cli.Flag{allSecretsFlag, internal.PassFlag},
|
|
|
|
ArgsUsage: "<secret>",
|
2021-08-30 15:02:08 +00:00
|
|
|
Action: func(c *cli.Context) error {
|
2021-08-31 08:31:54 +00:00
|
|
|
appName := c.Args().First()
|
|
|
|
if appName == "" {
|
|
|
|
internal.ShowSubcommandHelpAndError(c, errors.New("no app name provided"))
|
|
|
|
}
|
|
|
|
|
|
|
|
if c.Args().Get(1) != "" && allSecrets {
|
|
|
|
internal.ShowSubcommandHelpAndError(c, errors.New("cannot use '<secret>' and '--all' together"))
|
|
|
|
}
|
|
|
|
|
|
|
|
if c.Args().Get(1) == "" && !allSecrets {
|
|
|
|
internal.ShowSubcommandHelpAndError(c, errors.New("no secret(s) specified?"))
|
|
|
|
}
|
|
|
|
|
|
|
|
appFiles, err := config.LoadAppFiles("")
|
|
|
|
if err != nil {
|
|
|
|
logrus.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
appEnv, err := config.GetApp(appFiles, appName)
|
|
|
|
if err != nil {
|
|
|
|
logrus.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
host := appFiles[appName].Server
|
|
|
|
ctx := context.Background()
|
|
|
|
cl, err := client.NewClientWithContext(host)
|
|
|
|
if err != nil {
|
|
|
|
logrus.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
filters := filters.NewArgs()
|
|
|
|
filters.Add("name", appEnv.StackName())
|
|
|
|
secretList, err := cl.SecretList(ctx, types.SecretListOptions{Filters: filters})
|
|
|
|
if err != nil {
|
|
|
|
logrus.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
secretToRm := c.Args().Get(1)
|
|
|
|
for _, cont := range secretList {
|
|
|
|
secretName := cont.Spec.Annotations.Name
|
|
|
|
parsed := secret.ParseGeneratedSecretName(secretName, appEnv)
|
|
|
|
if allSecrets {
|
|
|
|
if err := cl.SecretRemove(ctx, secretName); err != nil {
|
|
|
|
logrus.Fatal(err)
|
|
|
|
}
|
|
|
|
if internal.Pass {
|
|
|
|
secret.PassRmSecret(parsed, appEnv.StackName(), host)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if parsed == secretToRm {
|
|
|
|
if err := cl.SecretRemove(ctx, secretName); err != nil {
|
|
|
|
logrus.Fatal(err)
|
|
|
|
}
|
|
|
|
if internal.Pass {
|
|
|
|
secret.PassRmSecret(parsed, appEnv.StackName(), host)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-08-30 15:02:08 +00:00
|
|
|
return nil
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
var appSecretLsCommand = &cli.Command{
|
|
|
|
Name: "list",
|
|
|
|
Usage: "List all secrets",
|
|
|
|
Aliases: []string{"ls"},
|
2021-08-02 01:10:41 +00:00
|
|
|
Action: func(c *cli.Context) error {
|
2021-08-30 15:02:08 +00:00
|
|
|
appName := c.Args().First()
|
|
|
|
if appName == "" {
|
|
|
|
internal.ShowSubcommandHelpAndError(c, errors.New("no app name provided"))
|
|
|
|
}
|
|
|
|
appFiles, err := config.LoadAppFiles("")
|
|
|
|
if err != nil {
|
|
|
|
logrus.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
appEnv, err := config.GetApp(appFiles, appName)
|
|
|
|
if err != nil {
|
|
|
|
logrus.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
secrets := secret.ReadSecretEnvVars(appEnv.Env)
|
|
|
|
|
|
|
|
tableCol := []string{"Name", "Version", "Generated Name", "Created On Server"}
|
|
|
|
table := abraFormatter.CreateTable(tableCol)
|
|
|
|
|
|
|
|
host := appFiles[appName].Server
|
|
|
|
ctx := context.Background()
|
|
|
|
cl, err := client.NewClientWithContext(host)
|
|
|
|
if err != nil {
|
|
|
|
logrus.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
filters := filters.NewArgs()
|
|
|
|
filters.Add("name", appEnv.StackName())
|
|
|
|
secretList, err := cl.SecretList(ctx, types.SecretListOptions{Filters: filters})
|
2021-08-02 01:10:41 +00:00
|
|
|
if err != nil {
|
|
|
|
logrus.Fatal(err)
|
|
|
|
}
|
2021-08-30 15:02:08 +00:00
|
|
|
|
|
|
|
remoteSecretNames := make(map[string]bool)
|
|
|
|
for _, cont := range secretList {
|
|
|
|
remoteSecretNames[cont.Spec.Annotations.Name] = true
|
|
|
|
}
|
|
|
|
|
|
|
|
for sec := range secrets {
|
|
|
|
createdRemote := false
|
|
|
|
secretName := secret.ParseSecretEnvVarName(sec)
|
|
|
|
secVal, err := secret.ParseSecretEnvVarValue(secrets[sec])
|
|
|
|
if err != nil {
|
|
|
|
logrus.Fatal(err)
|
|
|
|
}
|
|
|
|
secretRemoteName := fmt.Sprintf("%s_%s_%s", appEnv.StackName(), secretName, secVal.Version)
|
|
|
|
if _, ok := remoteSecretNames[secretRemoteName]; ok {
|
|
|
|
createdRemote = true
|
|
|
|
}
|
|
|
|
tableRow := []string{secretName, secVal.Version, secretRemoteName, strconv.FormatBool(createdRemote)}
|
|
|
|
table.Append(tableRow)
|
|
|
|
}
|
|
|
|
|
|
|
|
table.Render()
|
2021-08-02 01:10:41 +00:00
|
|
|
return nil
|
|
|
|
},
|
|
|
|
}
|
2021-08-30 15:02:08 +00:00
|
|
|
|
|
|
|
var appSecretCommand = &cli.Command{
|
|
|
|
Name: "secret",
|
|
|
|
Usage: "Manage app secrets",
|
|
|
|
ArgsUsage: "<command>",
|
|
|
|
Subcommands: []*cli.Command{
|
|
|
|
appSecretGenerateCommand,
|
|
|
|
appSecretInsertCommand,
|
|
|
|
appSecretRmCommand,
|
|
|
|
appSecretLsCommand,
|
|
|
|
},
|
|
|
|
}
|