Skip to content

Commit

Permalink
Merge pull request #29 from budimanjojo/next
Browse files Browse the repository at this point in the history
feat!: different gensecret output and talsecret.yaml inclusion
  • Loading branch information
budimanjojo authored Sep 4, 2022
2 parents 1e3d313 + 3e39109 commit 08ac990
Show file tree
Hide file tree
Showing 12 changed files with 131 additions and 147 deletions.
25 changes: 13 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ You can also use this tool to generate Talos secrets with `talhelper gensecret`

This tool will:
* Read your `talconfig.yaml`
* Read and decrypt your `talsecret.yaml` or `talsecret.sops.yaml` with [SOPS](https://github.com/mozilla/sops)
* Read and decrypt your `talenv.yaml` or `talenv.sops.yaml` with [SOPS](https://github.com/mozilla/sops)
* Do [envsubst](https://linux.die.net/man/1/envsubst) if needed
* Validate config file is good for talosctl
Expand All @@ -61,15 +62,15 @@ Any input and suggestion will be highly appreciated.

Scenario 1 (You already have your talos config but not GitOps it yet):
1. Create a `talconfig.yaml` based on your current cluster, an example [template](./test/talconfig.yaml) is provided.
2. Run `talhelper gensecret -f <your-talos-controlplane.yaml> --patch-configfile > talenv.yaml`. This will create a `talenv.yaml` file with all your current cluster secrets and patch your `talconfig.yaml` to get values from it.
3. Encrypt the secret with SOPS: `sops -e -i talenv.yaml`.
2. Run `talhelper gensecret -f <your-talos-controlplane.yaml> > talsecret.sops.yaml`. This will create a `talsecret.sops.yaml` file with all your current cluster secrets.
3. Encrypt the secret with SOPS: `sops -e -i talsecret.sops.yaml`.
4. Run `talhelper genconfig` and the output files will be in `./clusterconfig` by default. Make sure the generated files are identical with your current machine config files.
5. Commit your `talconfig.yaml` and `talenv.yaml` in Git repository.
5. Commit your `talconfig.yaml` and `talsecret.sops.yaml` in Git repository.

Scenario 2 (You want talhelper to create from scratch):
1. Create a `talconfig.yaml`, an example [template](./test/talconfig.yaml) is provided.
2. Run `talhelper gensecret --patch-configfile > talenv.sops.yaml`.
3. Encrypt the secret with SOPS: `sops -e -i talenv.sops.yaml`.
2. Run `talhelper gensecret > talsecret.sops.yaml`.
3. Encrypt the secret with SOPS: `sops -e -i talsecret.sops.yaml`.
4. Run `talhelper genconfig` and the output files will be in `./clusterconfig` by default.
5. Commit your `talconfig.yaml` and `talenv.sops.yaml` in Git repository.

Expand Down Expand Up @@ -102,12 +103,13 @@ Available Commands:
talhelper genconfig [flags]
Flags:
-c, --config-file string File containing configurations for nodes (default "talconfig.yaml")
-e, --env-file strings List of files containing env variables for config file (default [talenv.yaml,talenv.sops.yaml,talenv.yml,talenv.sops.yml])
-h, --help help for genconfig
--no-gitignore Create/update gitignore file too
-o, --out-dir string Directory where to dump the generated files (default "./clusterconfig")
-m, --talos-mode string Talos runtime mode to validate generated config (default "metal")
-c, --config-file string File containing configurations for talhelper (default "talconfig.yaml")
-e, --env-file strings List of files containing env variables for config file (default [talenv.yaml,talenv.sops.yaml,talenv.yml,talenv.sops.yml])
-h, --help help for genconfig
--no-gitignore Create/update gitignore file too
-o, --out-dir string Directory where to dump the generated files (default "./clusterconfig")
-s, --secret-file strings List of files containing secrets for the cluster (default [talsecret.yaml,talsecret.sops.yaml,talsecret.yml,talsecret.sops.yml])
-m, --talos-mode string Talos runtime mode to validate generated config (default "metal")
```

```
Expand All @@ -118,7 +120,6 @@ Flags:
-c, --config-file string File containing configurations for talhelper (default "talconfig.yaml")
-f, --from-configfile string Talos cluster node configuration file to generate secret from
-h, --help help for gensecret
-p, --patch-configfile Whether to generate inline patches into config file
```

```
Expand Down
25 changes: 23 additions & 2 deletions cmd/genconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,14 @@ var (
genconfigTalosMode string
genconfigNoGitignore bool
genconfigEnvFile []string
genconfigSecretFile []string
)

var (
genconfigCmd = &cobra.Command{
Use: "genconfig",
Short: "Generate Talos cluster config YAML files",
Args: cobra.NoArgs,
Args: cobra.NoArgs,
Run: func(cmd *cobra.Command, args []string) {
cf, err := os.ReadFile(genconfigCfgFile)
if err != nil {
Expand Down Expand Up @@ -77,7 +78,26 @@ var (
log.Fatalf("failed to unmarshal data: %s", err)
}

err = generate.GenerateConfig(&m, genconfigOutDir, genconfigTalosMode)
var secretFile string
for _, file := range genconfigSecretFile {
if _, err := os.Stat(file); err == nil {
secret, err := decrypt.DecryptYamlWithSops(file)
if err != nil {
log.Fatalf("failed to decrypt/read secret file %s: %s", file, err)
}
err = os.WriteFile("/tmp/talsecret.yaml", secret, 0600)
if err != nil {
log.Fatalf("failed to write temp file to /tmp directory: %s", err)
}
secretFile = "/tmp/talsecret.yaml"
} else if errors.Is(err, os.ErrNotExist) {
continue
} else {
log.Fatalf("failed to stat secret file %s: %s ", file, err)
}
}

err = generate.GenerateConfig(&m, genconfigOutDir, secretFile, genconfigTalosMode)
if err != nil {
log.Fatalf("failed to generate talos config: %s", err)
}
Expand All @@ -98,6 +118,7 @@ func init() {
genconfigCmd.Flags().StringVarP(&genconfigOutDir, "out-dir", "o", "./clusterconfig", "Directory where to dump the generated files")
genconfigCmd.Flags().StringVarP(&genconfigCfgFile, "config-file", "c", "talconfig.yaml", "File containing configurations for talhelper")
genconfigCmd.Flags().StringSliceVarP(&genconfigEnvFile, "env-file", "e", []string{"talenv.yaml", "talenv.sops.yaml", "talenv.yml", "talenv.sops.yml"}, "List of files containing env variables for config file")
genconfigCmd.Flags().StringSliceVarP(&genconfigSecretFile, "secret-file", "s", []string{"talsecret.yaml", "talsecret.sops.yaml", "talsecret.yml", "talsecret.sops.yml"}, "List of files containing secrets for the cluster")
genconfigCmd.Flags().StringVarP(&genconfigTalosMode, "talos-mode", "m", "metal", "Talos runtime mode to validate generated config")
genconfigCmd.Flags().BoolVar(&genconfigNoGitignore, "no-gitignore", false, "Create/update gitignore file too")
}
9 changes: 0 additions & 9 deletions cmd/gensecret.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import (
)

var (
gensecretPatchCfg bool
gensecretFromCfg string
gensecretCfgFile string
)
Expand All @@ -22,13 +21,6 @@ var gensecretCmd = &cobra.Command{
if err != nil {
log.Fatalf("failed to generate secret bundle: %s", err)
}

if gensecretPatchCfg {
err := generate.PatchTalhelperConfig(gensecretCfgFile)
if err != nil {
log.Fatalf("failed to patch talhelper config %s: %s", genconfigCfgFile, err)
}
}
},
}

Expand All @@ -37,5 +29,4 @@ func init() {

gensecretCmd.Flags().StringVarP(&gensecretCfgFile, "config-file", "c", "talconfig.yaml", "File containing configurations for talhelper")
gensecretCmd.Flags().StringVarP(&gensecretFromCfg, "from-configfile", "f", "", "Talos cluster node configuration file to generate secret from")
gensecretCmd.Flags().BoolVarP(&gensecretPatchCfg, "patch-configfile", "p", false, "Whether to generate inline patches into config file")
}
4 changes: 2 additions & 2 deletions pkg/generate/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ import (
"github.com/talos-systems/talos/pkg/machinery/config/types/v1alpha1"
)

func GenerateConfig(c *config.TalhelperConfig, outDir, mode string) error {
func GenerateConfig(c *config.TalhelperConfig, outDir, secretFile, mode string) error {
var cfg []byte
var cfgDump tconfig.Provider
input, err := talos.NewClusterInput(c)
input, err := talos.NewClusterInput(c, secretFile)
if err != nil {
return err
}
Expand Down
31 changes: 1 addition & 30 deletions pkg/generate/secret.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
package generate

import (
"os"

"github.com/budimanjojo/talhelper/pkg/config"
"github.com/budimanjojo/talhelper/pkg/secret"
"github.com/budimanjojo/talhelper/pkg/talos"
"github.com/talos-systems/talos/pkg/machinery/config/types/v1alpha1/generate"
"gopkg.in/yaml.v3"
)

func GenerateOutput(cfg string) error {
Expand All @@ -27,32 +23,7 @@ func GenerateOutput(cfg string) error {
s = talos.NewSecretFromCfg(generate.NewClock(), cfg)
}

secret.PrintSortedSecrets(s)
return nil
}

func PatchTalhelperConfig(cfgFile string) error {
cfg, err := os.ReadFile(cfgFile)
if err != nil {
return err
}

var m config.TalhelperConfig
if err := yaml.Unmarshal(cfg, &m); err != nil {
return err
}

cfg, err = m.ApplyInlinePatch([]byte(secret.SecretPatch))
if err != nil {
return err
}

cfg, err = m.Encode(cfg)
if err != nil {
return err
}

err = os.WriteFile(cfgFile, cfg, 0700)
err = secret.PrintSecretBundle(s)
if err != nil {
return err
}
Expand Down
40 changes: 0 additions & 40 deletions pkg/secret/const.go

This file was deleted.

38 changes: 27 additions & 11 deletions pkg/secret/print.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,30 @@
package secret

import (
"bytes"
"encoding/base64"
"fmt"
"sort"

"github.com/fatih/color"
"github.com/talos-systems/talos/pkg/machinery/config/types/v1alpha1/generate"
"gopkg.in/yaml.v3"
)

func PrintSecretBundle(secret *generate.SecretsBundle) error {
buf := new(bytes.Buffer)
encoder := yaml.NewEncoder(buf)
encoder.SetIndent(2)

err := encoder.Encode(secret)
if err != nil {
return err
}

fmt.Print(buf.String())
return nil
}

func PrintSortedSecrets(secret *generate.SecretsBundle) {
unsorted := getSecrets(secret)

Expand All @@ -27,19 +43,19 @@ func PrintSortedSecrets(secret *generate.SecretsBundle) {

func getSecrets(secret *generate.SecretsBundle) map[string]string {
secrets := map[string]string{
"etcdCert": getEtcdCert(secret, "cert"),
"etcdCertKey": getEtcdCert(secret, "key"),
"etcdCert": getEtcdCert(secret, "cert"),
"etcdCertKey": getEtcdCert(secret, "key"),
"k8sServiceAccountKey": getK8sServiceAccountKey(secret),
"k8sAggregatorCert": getK8sAggregatorCert(secret, "cert"),
"k8sAggregatorCert": getK8sAggregatorCert(secret, "cert"),
"k8sAggregatorCertKey": getK8sAggregatorCert(secret, "key"),
"clusterToken": getClusterToken(secret),
"aescbcEncryptionKey": getAescbcEncryptionKey(secret),
"clusterSecret": getClusterSecret(secret),
"machineToken": getMachineToken(secret),
"machineCert": getMachineCert(secret, "cert"),
"machineCertKey": getMachineCert(secret, "key"),
"clusterCert": getClusterCert(secret, "cert"),
"clusterCertKey": getClusterCert(secret, "key"),
"clusterToken": getClusterToken(secret),
"aescbcEncryptionKey": getAescbcEncryptionKey(secret),
"clusterSecret": getClusterSecret(secret),
"machineToken": getMachineToken(secret),
"machineCert": getMachineCert(secret, "cert"),
"machineCertKey": getMachineCert(secret, "key"),
"clusterCert": getClusterCert(secret, "cert"),
"clusterCertKey": getClusterCert(secret, "key"),
}

return secrets
Expand Down
24 changes: 20 additions & 4 deletions pkg/talos/input.go
Original file line number Diff line number Diff line change
@@ -1,23 +1,39 @@
package talos

import (
"os"

"github.com/budimanjojo/talhelper/pkg/config"
tconfig "github.com/talos-systems/talos/pkg/machinery/config"
"github.com/talos-systems/talos/pkg/machinery/config/types/v1alpha1"
"github.com/talos-systems/talos/pkg/machinery/config/types/v1alpha1/generate"
)

func NewClusterInput(c *config.TalhelperConfig) (*generate.Input, error) {
func NewClusterInput(c *config.TalhelperConfig, secretFile string) (*generate.Input, error) {
kubernetesVersion := c.GetK8sVersion()

versionContract, err := tconfig.ParseContractFromVersion(c.GetTalosVersion())
if err != nil {
return nil, err
}

secrets, err := NewSecretBundle(generate.NewClock(), generate.WithVersionContract(versionContract))
if err != nil {
return nil, err
var secrets *generate.SecretsBundle

if secretFile != "" {
secrets, err = NewSecretBundle(generate.NewClock(), generate.WithVersionContract(versionContract), generate.WithSecrets(secretFile))
if err != nil {
return nil, err
}

err = os.Remove(secretFile)
if err != nil {
return nil, err
}
} else {
secrets, err = NewSecretBundle(generate.NewClock(), generate.WithVersionContract(versionContract))
if err != nil {
return nil, err
}
}

opts := parseOptions(c, versionContract)
Expand Down
2 changes: 1 addition & 1 deletion pkg/talos/input_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ endpoint: https://1.1.1.1:6443`)
t.Fatal(err)
}

result, err := NewClusterInput(&m)
result, err := NewClusterInput(&m, "")
if err != nil {
t.Fatal(err)
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/talos/nodeconfig_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ nodes:
t.Fatal(err)
}

input, err := NewClusterInput(&m)
input, err := NewClusterInput(&m, "")
if err != nil {
t.Fatal(err)
}
Expand Down
Loading

0 comments on commit 08ac990

Please sign in to comment.