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

Updated vault init to support auto-unseal scenario #211

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
12 changes: 9 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM golang:1.11-stretch as builder
FROM golang:1.16-stretch as builder


ENV CGO_ENABLED=0
Expand All @@ -18,10 +18,16 @@ RUN go build -a -ldflags '-w -s' .

# Runtime image
FROM alpine AS base
RUN apk update && apk add ca-certificates && rm -rf /var/cache/apk/*


RUN apk update && apk add ca-certificates unzip && rm -rf /var/cache/apk/*

ADD https://releases.hashicorp.com/vault/1.8.1/vault_1.8.1_linux_amd64.zip .

RUN unzip vault_1.8.1_linux_amd64.zip -d /usr/bin

COPY --from=builder /bosun/bosun /bin/bosun

COPY examples/bosun.yaml /root/.bosun/bosun.yaml

CMD ["/bin/bosun"]
ENTRYPOINT ["/bin/bosun"]
1 change: 1 addition & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ func init() {
rootCmd.PersistentFlags().Bool(ArgGlobalDryRun, false, "Display rendered plans, but do not actually execute (not supported by all commands).")
rootCmd.PersistentFlags().Bool(ArgGlobalForce, false, "Force the requested command to be executed even if heuristics indicate it should not be.")
rootCmd.PersistentFlags().Bool(ArgGlobalNoReport, false, "Disable reporting of deploys to github.")
rootCmd.PersistentFlags().Bool(ArgGlobalNoEnv, false, "Disables loading of the environment.")
rootCmd.PersistentFlags().Bool(ArgGlobalSudo, false, "Use sudo when running commands like docker.")
rootCmd.PersistentFlags().String(ArgGlobalConfirmedEnv, "", "Set to confirm that the environment is correct when targeting a protected environment.")
rootCmd.PersistentFlags().String(ArgGlobalCluster, "", "Set to target a specific cluster.")
Expand Down
58 changes: 37 additions & 21 deletions cmd/vault.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,36 +170,43 @@ Otherwise, this will do nothing.
return err
}

b := MustGetBosun()

env := b.GetCurrentEnvironment()

p, err := b.GetCurrentPlatform()
if err != nil {
return err
}

platformApps := p.GetKnownAppMap()

namespace := "default"

if len(args) > 0 {
namespace = args[1]
} else {
}

vaultPlatformApp, ok := platformApps["vault"]
if !viper.GetBool(ArgGlobalNoEnv) {

if !ok {
return errors.New("vault not found in platform apps")
b := MustGetBosun()

env := b.GetCurrentEnvironment()

p, err := b.GetCurrentPlatform()
if err != nil {
return err
}

stack := env.Stack()
platformApps := p.GetKnownAppMap()

if len(args) > 0 {
namespace = args[1]
} else {

vaultPlatformApp, ok := platformApps["vault"]

if !ok {
return errors.New("vault not found in platform apps")
}

stack := env.Stack()

for _, requestedNamespaceRole := range vaultPlatformApp.NamespaceRoles {
for namespaceRole, namespaceConfig := range stack.StackTemplate.Namespaces {
if namespaceRole == requestedNamespaceRole {
namespace = namespaceConfig.Name
break
for _, requestedNamespaceRole := range vaultPlatformApp.NamespaceRoles {
for namespaceRole, namespaceConfig := range stack.StackTemplate.Namespaces {
if namespaceRole == requestedNamespaceRole {
namespace = namespaceConfig.Name
break
}
}
}
}
Expand All @@ -210,6 +217,9 @@ Otherwise, this will do nothing.
initializer := vault.VaultInitializer{
Client: vaultClient,
VaultNamespace: namespace,
AutoUnseal: viper.GetBool(ArgVaultAutoUnseal),
DisableJoseInstall: viper.GetBool(ArgVaultDisableJoseInstall),
DisableDevRootTokenCreation: viper.GetBool(ArgVaultDisableDevRootToken),
}

err = initializer.Init()
Expand Down Expand Up @@ -418,6 +428,9 @@ const (
ArgVaultSecretDefault = "default"
ArgVaultNamespace = "vault-namespace"
ArgVaultCluster = "cluster"
ArgVaultAutoUnseal = "auto-unseal"
ArgVaultDisableJoseInstall = "disable-jose-install"
ArgVaultDisableDevRootToken = "disable-dev-root-token"
)

func init() {
Expand All @@ -437,6 +450,9 @@ func init() {
addVaultFlags(vaultJWTCmd)
vaultCmd.AddCommand(vaultJWTCmd)

vaultInitCmd.Flags().Bool(ArgVaultAutoUnseal, false, "Disables the capture of the unseal keys.")
vaultInitCmd.Flags().Bool(ArgVaultDisableJoseInstall, false, "Disables the install of the Jose plugin.")
vaultInitCmd.Flags().Bool(ArgVaultDisableDevRootToken, false, "Disables the creation of the dev root token (ID `root`).")
addVaultFlags(vaultInitCmd)
vaultCmd.AddCommand(vaultInitCmd)

Expand Down
107 changes: 65 additions & 42 deletions pkg/vault/vault_init.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,16 @@ import (
type VaultInitializer struct {
Client *api.Client
VaultNamespace string

// Whether or not vault is using auto unseal. If it is we don't need
// to capture the unseal keys, since they will be sent to the target location
// for storage.
AutoUnseal bool

// Overrides the prompting of the user to create root token
DisableDevRootTokenCreation bool

DisableJoseInstall bool
}

func (v VaultInitializer) Init() error {
Expand All @@ -38,12 +48,16 @@ func (v VaultInitializer) Init() error {
fmt.Printf("Vault at %q is already initialized.\n", vaultClient.Address())
}

err = v.Unseal()
if err != nil {
return errors.Wrap(err, "unseal")
if !v.AutoUnseal {
err = v.Unseal()
if err != nil {
return errors.Wrap(err, "unseal")
}
}

err = v.InstallJose()
if !v.DisableJoseInstall {
err = v.InstallJose()
}

return err

Expand Down Expand Up @@ -147,6 +161,8 @@ func (v VaultInitializer) initialize() error {
initResp, initErr = vaultClient.Sys().Init(&api.InitRequest{
SecretShares: 1,
SecretThreshold: 1,
RecoveryThreshold: 1,
RecoveryShares: 1,
})
if initErr != nil {
return initErr
Expand All @@ -161,42 +177,45 @@ func (v VaultInitializer) initialize() error {
return err
}

log.Info("Storing unseal keys in k8s")

secretsClient := kubeClient.CoreV1().Secrets(v.VaultNamespace)
unsealKeysSecret, err := secretsClient.Get("vault-unseal-keys", metav1.GetOptions{})
if kerrors.IsNotFound(err) {
unsealKeysSecret, err = secretsClient.Create(&v1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: "vault-unseal-keys",
},
Type: v1.SecretTypeOpaque,
})
if err != nil {

if !v.AutoUnseal {
log.Info("Storing unseal keys in k8s")

unsealKeysSecret, err := secretsClient.Get("vault-unseal-keys", metav1.GetOptions{})
if kerrors.IsNotFound(err) {
unsealKeysSecret, err = secretsClient.Create(&v1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: "vault-unseal-keys",
},
Type: v1.SecretTypeOpaque,
})
if err != nil {
return err
}
} else if err != nil {
return err
}
} else if err != nil {
return err
}

unsealKeysSecret.StringData = map[string]string{}
unsealKeysSecret.StringData = map[string]string{}

for i, key := range initResp.Keys {
fmt.Printf("Seal Key %d: %q", i, key)
unsealKeysSecret.StringData[fmt.Sprintf("Key%d", i)] = key
}
for i, key := range initResp.Keys {
fmt.Printf("Seal Key %d: %q", i, key)
unsealKeysSecret.StringData[fmt.Sprintf("Key%d", i)] = key
}

_, err = secretsClient.Update(unsealKeysSecret)
if err != nil {
return errors.Wrap(err, "save unseal keys secret")
_, err = secretsClient.Update(unsealKeysSecret)
if err != nil {
return errors.Wrap(err, "save unseal keys secret")
}
}

log.Info("Storing root token in k8s")
fmt.Printf("Initial root token: %s", initResp.RootToken)

vaultRootTokenSecret, err := secretsClient.Get("vault-root-token", metav1.GetOptions{})
if kerrors.IsNotFound(err) {
unsealKeysSecret, err = secretsClient.Create(&v1.Secret{
vaultRootTokenSecret, err = secretsClient.Create(&v1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: "vault-root-token",
},
Expand Down Expand Up @@ -227,28 +246,32 @@ func (v VaultInitializer) initialize() error {
return errors.Wrap(storeErr, "could not store unseal keys and initial root token; you will need to uninstall vault, destroy the pvc, and re-install")
}

log.Info("Unsealing vault")
if !v.AutoUnseal {
log.Info("Unsealing vault")

err := v.Unseal()
if err != nil {
return err
err := v.Unseal()
if err != nil {
return err
}
}

vaultClient.SetToken(rootToken)
if !v.DisableDevRootTokenCreation {
vaultClient.SetToken(rootToken)

createRootToken := cli.RequestConfirmFromUser("Should we create a root token named `root`")
createRootToken := cli.RequestConfirmFromUser("Should we create a root token named `root`")

if createRootToken {
log.Info("Creating token `root` (DELETE THIS TOKEN IN PRODUCTION!)")
if createRootToken {
log.Info("Creating token `root` (DELETE THIS TOKEN IN PRODUCTION!)")

_, err = vaultClient.Auth().Token().Create(&api.TokenCreateRequest{
ID: "root",
Policies: []string{"root"},
})
if err != nil {
return err
}
_, err := vaultClient.Auth().Token().Create(&api.TokenCreateRequest{
ID: "root",
Policies: []string{"root"},
})
if err != nil {
return err
}

}
}

log.Info("Init completed")
Expand Down