-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* ✨ Add push secret * 👷 Increase job timeout --------- Co-authored-by: DUBOIS Charles <[email protected]>
- Loading branch information
1 parent
9f23a91
commit 65b65b2
Showing
5 changed files
with
194 additions
and
84 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
package cmd | ||
|
||
import ( | ||
"fmt" | ||
vault "github.com/hashicorp/vault/api" | ||
"github.com/spf13/cobra" | ||
"github.com/spf13/viper" | ||
) | ||
|
||
var vaultPushEnv = &cobra.Command{ | ||
Use: "push-secret", | ||
Short: "Push secret to vault", | ||
PreRun: func(cmd *cobra.Command, args []string) { | ||
|
||
for _, flag := range []string{"vault-addr", "vault-secret", "vault-secret-prefix", "vault-push-secret-key", "vault-push-secret-value"} { | ||
|
||
// Bind viper to flag | ||
err := viper.BindPFlag(flag, cmd.Flags().Lookup(flag)) | ||
if err != nil { | ||
ErrorToEval(fmt.Errorf("failed to bind flag %s to viper: %s", flag, err)) | ||
return | ||
} | ||
} | ||
|
||
for _, flag := range []string{"vault-addr", "vault-secret", "vault-push-secret-key", "vault-push-secret-value"} { | ||
|
||
// Check flag has a value | ||
if viper.GetString(flag) == "" { | ||
ErrorToEval(fmt.Errorf("flag %s must be defined", flag)) | ||
return | ||
} | ||
} | ||
}, | ||
Run: func(cmd *cobra.Command, args []string) { | ||
|
||
// Create vault client | ||
vc, err := vault.NewClient(&vault.Config{Address: viper.GetString("vault-addr")}) | ||
if err != nil { | ||
ErrorToEval(fmt.Errorf("failed to create vault client: %s", err)) | ||
return | ||
} | ||
|
||
// Read vault token from env | ||
|
||
// Read vault token from env | ||
token, err := getVaultToken() | ||
if err != nil { | ||
ErrorToEval(fmt.Errorf("failed to get token: %s", err)) | ||
return | ||
} | ||
// Set token to Vault client | ||
vc.SetToken(string(token)) | ||
|
||
secretPath, err := getSecretPath() | ||
if err != nil { | ||
ErrorToEval(fmt.Errorf("failed to get secret path: %s", err)) | ||
return | ||
} | ||
|
||
// Get Vault secret data | ||
data, err := getSecretData(vc, secretPath) | ||
if err != nil { | ||
ErrorToEval(fmt.Errorf("failed to get secret from Vault: %s", err)) | ||
return | ||
} | ||
|
||
key := viper.GetString("vault-push-secret-key") | ||
if key == "" { | ||
ErrorToEval(fmt.Errorf("failed to get key to push: %s", err)) | ||
return | ||
} | ||
value := viper.GetString("vault-push-secret-value") | ||
if value == "" { | ||
ErrorToEval(fmt.Errorf("failed to get value to push: %s", err)) | ||
return | ||
} | ||
|
||
//merge entries | ||
data[key] = value | ||
|
||
// Get Vault secret | ||
_, err = vc.Logical().Write(secretPath, map[string]interface{}{"data": data}) | ||
if err != nil { | ||
ErrorToEval(fmt.Errorf("failed to push secret to Vault: %s", err)) | ||
return | ||
} | ||
}, | ||
} | ||
|
||
func init() { | ||
vaultPushEnv.Flags().String("vault-addr", "", "Vault server address [GOGCI_VAULT_ADDR]") | ||
vaultPushEnv.Flags().String("vault-secret", "", "Vault secret path [GOGCI_VAULT_SECRET]") | ||
vaultPushEnv.Flags().String("vault-secret-prefix", "", "Vault secret path prefix [GOGCI_VAULT_SECRET_PREFIX]") | ||
vaultPushEnv.Flags().String("vault-push-secret-key", "", "Key of the secret to push [GOGCI_VAULT_PUSH_SECRET_KEY]") | ||
vaultPushEnv.Flags().String("vault-push-secret-value", "", "Value of the secret to push [GOGCI_VAULT_PUSH_SECRET_VALUE]") | ||
|
||
vaultCmd.AddCommand(vaultPushEnv) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
package cmd | ||
|
||
import ( | ||
"bytes" | ||
"fmt" | ||
"github.com/Masterminds/sprig/v3" | ||
"github.com/hashicorp/vault/api" | ||
"github.com/mitchellh/go-homedir" | ||
"github.com/spf13/viper" | ||
"io/ioutil" | ||
"os" | ||
"text/template" | ||
) | ||
|
||
func getVaultToken() (string, error) { | ||
|
||
token := os.Getenv("VAULT_TOKEN") | ||
|
||
if token == "" { | ||
// Read vault token on disk | ||
tokenPath, err := homedir.Expand("~/.vault-token") | ||
if err != nil { | ||
return "", fmt.Errorf("failed to construct vault token path: %s", err) | ||
} | ||
|
||
tokenFile, err := ioutil.ReadFile(tokenPath) | ||
if err != nil { | ||
return "", fmt.Errorf("failed to read token: %s", err) | ||
} | ||
|
||
token = string(tokenFile) | ||
} | ||
|
||
return token, nil | ||
} | ||
|
||
func getSecretPath() (string, error) { | ||
// Template prefix | ||
prefixTmpl, err := template.New("prefix").Funcs(sprig.TxtFuncMap()).Parse(viper.GetString("vault-secret-prefix")) | ||
if err != nil { | ||
return "", fmt.Errorf("failed to create prefix template: %s", err) | ||
} | ||
|
||
var prefix bytes.Buffer | ||
if err := prefixTmpl.Execute(&prefix, nil); err != nil { | ||
return "", fmt.Errorf("failed to execute prefix template: %s", err) | ||
} | ||
|
||
// Template secret | ||
secretPathTmpl, err := template.New("secret").Funcs(sprig.TxtFuncMap()).Parse(viper.GetString("vault-secret")) | ||
if err != nil { | ||
return "", fmt.Errorf("failed to create secretPath template: %s", err) | ||
} | ||
|
||
var secretPath bytes.Buffer | ||
if err := secretPathTmpl.Execute(&secretPath, nil); err != nil { | ||
return "", fmt.Errorf("failed to execute secretPath template: %s", err) | ||
} | ||
|
||
return fmt.Sprintf("%s/%s", prefix.String(), secretPath.String()), nil | ||
} | ||
|
||
func getSecretData(vc *api.Client, secretPath string) (map[string]interface{}, error) { | ||
// Get Vault secret | ||
secret, err := vc.Logical().Read(secretPath) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to get secret from Vault: %s", err) | ||
} | ||
|
||
// Check if secret exists | ||
if secret == nil { | ||
return nil, fmt.Errorf("no secret found at path %s", secretPath) | ||
} | ||
|
||
// Check if data entry exists | ||
data, ok := secret.Data["data"].(map[string]interface{}) | ||
if !ok { | ||
return nil, fmt.Errorf("no data found at path %s", secretPath) | ||
} | ||
|
||
return data, nil | ||
} |