Merge "Refactoring masterpassphrase cmd to encryptionkey"
This commit is contained in:
commit
e14314b624
cmd/secret/generate
encryptionkey
generate.godocs/source/cli
pkg/secret/generate
@ -12,28 +12,27 @@
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package generate
|
||||
package encryptionkey
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"opendev.org/airship/airshipctl/pkg/secret"
|
||||
"opendev.org/airship/airshipctl/pkg/secret/generate"
|
||||
)
|
||||
|
||||
// NewGenerateMasterPassphraseCommand creates a new command for generating secret information
|
||||
func NewGenerateMasterPassphraseCommand() *cobra.Command {
|
||||
masterPassphraseCmd := &cobra.Command{
|
||||
Use: "masterpassphrase",
|
||||
// TODO(howell): Make this more expressive
|
||||
Short: "Generates a secure master passphrase",
|
||||
// NewGenerateEncryptionKeyCommand creates a new command for generating secret information
|
||||
func NewGenerateEncryptionKeyCommand() *cobra.Command {
|
||||
encryptionKeyCmd := &cobra.Command{
|
||||
Use: "encryptionkey",
|
||||
Short: "Generates a secure encryption key or passphrase",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
engine := secret.NewPassphraseEngine(nil)
|
||||
masterPassphrase := engine.GeneratePassphrase()
|
||||
fmt.Fprintln(cmd.OutOrStdout(), masterPassphrase)
|
||||
engine := generate.NewEncryptionKeyEngine(nil)
|
||||
encryptionKey := engine.GenerateEncryptionKey()
|
||||
fmt.Fprintln(cmd.OutOrStdout(), encryptionKey)
|
||||
},
|
||||
}
|
||||
|
||||
return masterPassphraseCmd
|
||||
return encryptionKeyCmd
|
||||
}
|
36
cmd/secret/generate/encryptionkey/encryptionkey_test.go
Normal file
36
cmd/secret/generate/encryptionkey/encryptionkey_test.go
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package encryptionkey_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"opendev.org/airship/airshipctl/cmd/secret/generate/encryptionkey"
|
||||
"opendev.org/airship/airshipctl/testutil"
|
||||
)
|
||||
|
||||
func TestGenerateEncryptionKey(t *testing.T) {
|
||||
cmdTests := []*testutil.CmdTest{
|
||||
{
|
||||
Name: "generate-encryptionkey-cmd-with-help",
|
||||
CmdLine: "--help",
|
||||
Cmd: encryptionkey.NewGenerateEncryptionKeyCommand(),
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range cmdTests {
|
||||
testutil.RunTest(t, tt)
|
||||
}
|
||||
}
|
7
cmd/secret/generate/encryptionkey/testdata/TestGenerateEncryptionKeyGoldenOutput/generate-encryptionkey-cmd-with-help.golden
vendored
Normal file
7
cmd/secret/generate/encryptionkey/testdata/TestGenerateEncryptionKeyGoldenOutput/generate-encryptionkey-cmd-with-help.golden
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
Generates a secure encryption key or passphrase
|
||||
|
||||
Usage:
|
||||
encryptionkey [flags]
|
||||
|
||||
Flags:
|
||||
-h, --help help for encryptionkey
|
@ -14,7 +14,11 @@
|
||||
|
||||
package generate
|
||||
|
||||
import "github.com/spf13/cobra"
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"opendev.org/airship/airshipctl/cmd/secret/generate/encryptionkey"
|
||||
)
|
||||
|
||||
// NewGenerateCommand creates a new command for generating secret information
|
||||
func NewGenerateCommand() *cobra.Command {
|
||||
@ -24,7 +28,7 @@ func NewGenerateCommand() *cobra.Command {
|
||||
Short: "Generate various secrets",
|
||||
}
|
||||
|
||||
generateRootCmd.AddCommand(NewGenerateMasterPassphraseCommand())
|
||||
generateRootCmd.AddCommand(encryptionkey.NewGenerateEncryptionKeyCommand())
|
||||
|
||||
return generateRootCmd
|
||||
}
|
||||
|
@ -22,5 +22,5 @@ Generate various secrets
|
||||
### SEE ALSO
|
||||
|
||||
* [airshipctl secret](airshipctl_secret.md) - Manage secrets
|
||||
* [airshipctl secret generate masterpassphrase](airshipctl_secret_generate_masterpassphrase.md) - Generates a secure master passphrase
|
||||
* [airshipctl secret generate encryptionkey](airshipctl_secret_generate_encryptionkey.md) - Generates a secure encryption key or passphrase
|
||||
|
||||
|
@ -1,19 +1,19 @@
|
||||
## airshipctl secret generate masterpassphrase
|
||||
## airshipctl secret generate encryptionkey
|
||||
|
||||
Generates a secure master passphrase
|
||||
Generates a secure encryption key or passphrase
|
||||
|
||||
### Synopsis
|
||||
|
||||
Generates a secure master passphrase
|
||||
Generates a secure encryption key or passphrase
|
||||
|
||||
```
|
||||
airshipctl secret generate masterpassphrase [flags]
|
||||
airshipctl secret generate encryptionkey [flags]
|
||||
```
|
||||
|
||||
### Options
|
||||
|
||||
```
|
||||
-h, --help help for masterpassphrase
|
||||
-h, --help help for encryptionkey
|
||||
```
|
||||
|
||||
### Options inherited from parent commands
|
@ -12,7 +12,7 @@
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package secret
|
||||
package generate
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
@ -41,59 +41,59 @@ func init() {
|
||||
pool = append(pool, []byte(asciiSymbols)...)
|
||||
}
|
||||
|
||||
// PassphraseEngine is used to generate secure random passphrases
|
||||
type PassphraseEngine struct {
|
||||
// EncryptionKeyEngine is used to generate secure random passphrases
|
||||
type EncryptionKeyEngine struct {
|
||||
rng *rand.Rand
|
||||
pool []byte
|
||||
}
|
||||
|
||||
// NewPassphraseEngine creates an PassphraseEngine using src. If src is nil,
|
||||
// NewEncryptionKeyEngine creates an PassphraseEngine using src. If src is nil,
|
||||
// the returned PassphraseEngine will use the default Source
|
||||
func NewPassphraseEngine(src rand.Source) *PassphraseEngine {
|
||||
func NewEncryptionKeyEngine(src rand.Source) *EncryptionKeyEngine {
|
||||
if src == nil {
|
||||
src = &Source{}
|
||||
}
|
||||
return &PassphraseEngine{
|
||||
return &EncryptionKeyEngine{
|
||||
rng: rand.New(src),
|
||||
pool: pool,
|
||||
}
|
||||
}
|
||||
|
||||
// GeneratePassphrase returns a secure random string of length 24,
|
||||
// GenerateEncryptionKey returns a secure random string of length 24,
|
||||
// containing at least one of each from the following sets:
|
||||
// [0-9]
|
||||
// [a-z]
|
||||
// [A-Z]
|
||||
// [@#&-+=?]
|
||||
func (e *PassphraseEngine) GeneratePassphrase() string {
|
||||
return e.GeneratePassphraseN(defaultLength)
|
||||
func (e *EncryptionKeyEngine) GenerateEncryptionKey() string {
|
||||
return e.GenerateEncryptionKeyN(defaultLength)
|
||||
}
|
||||
|
||||
// GeneratePassphraseN returns a secure random string containing at least
|
||||
// GenerateEncryptionKeyN returns a secure random string containing at least
|
||||
// one of each from the following sets. Its length will be max(length, 24)
|
||||
// [0-9]
|
||||
// [a-z]
|
||||
// [A-Z]
|
||||
// [@#&-+=?]
|
||||
func (e *PassphraseEngine) GeneratePassphraseN(length int) string {
|
||||
func (e *EncryptionKeyEngine) GenerateEncryptionKeyN(length int) string {
|
||||
if length < defaultLength {
|
||||
length = defaultLength
|
||||
}
|
||||
var passPhrase string
|
||||
for !e.isValidPassphrase(passPhrase) {
|
||||
var encryptionkey string
|
||||
for !e.isValidEncryptionKey(encryptionkey) {
|
||||
var sb strings.Builder
|
||||
for i := 0; i < length; i++ {
|
||||
randIndex := e.rng.Intn(len(e.pool))
|
||||
randChar := e.pool[randIndex]
|
||||
sb.WriteString(string(randChar))
|
||||
}
|
||||
passPhrase = sb.String()
|
||||
encryptionkey = sb.String()
|
||||
}
|
||||
return passPhrase
|
||||
return encryptionkey
|
||||
}
|
||||
|
||||
func (e *PassphraseEngine) isValidPassphrase(passPhrase string) bool {
|
||||
if len(passPhrase) < defaultLength {
|
||||
func (e *EncryptionKeyEngine) isValidEncryptionKey(encryptionkey string) bool {
|
||||
if len(encryptionkey) < defaultLength {
|
||||
return false
|
||||
}
|
||||
|
||||
@ -104,7 +104,7 @@ func (e *PassphraseEngine) isValidPassphrase(passPhrase string) bool {
|
||||
asciiSymbols,
|
||||
}
|
||||
for _, charSet := range charSets {
|
||||
if !strings.ContainsAny(passPhrase, charSet) {
|
||||
if !strings.ContainsAny(encryptionkey, charSet) {
|
||||
return false
|
||||
}
|
||||
}
|
@ -12,7 +12,7 @@
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package secret_test
|
||||
package generate_test
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
@ -21,7 +21,7 @@ import (
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"opendev.org/airship/airshipctl/pkg/secret"
|
||||
"opendev.org/airship/airshipctl/pkg/secret/generate"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -33,13 +33,13 @@ const (
|
||||
defaultLength = 24
|
||||
)
|
||||
|
||||
func TestDeterministicGenerateValidPassphrase(t *testing.T) {
|
||||
func TestDeterministicGenerateValidEncryptionKey(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
testSource := rand.NewSource(42)
|
||||
engine := secret.NewPassphraseEngine(testSource)
|
||||
engine := generate.NewEncryptionKeyEngine(testSource)
|
||||
|
||||
// pre-calculated for rand.NewSource(42)
|
||||
expectedPassphrases := []string{
|
||||
expectedEncryptionKey := []string{
|
||||
"erx&97vfqd7LN3HJ?t@oPhds",
|
||||
"##Xeuvf5Njy@hNWSaRoleFkf",
|
||||
"jB=kirg7acIt-=fx1Fb-tZ+7",
|
||||
@ -52,13 +52,13 @@ func TestDeterministicGenerateValidPassphrase(t *testing.T) {
|
||||
"XC?bDaHTa3mrBYLMG@#B=Q0B",
|
||||
}
|
||||
|
||||
for i, expected := range expectedPassphrases {
|
||||
actual := engine.GeneratePassphrase()
|
||||
for i, expected := range expectedEncryptionKey {
|
||||
actual := engine.GenerateEncryptionKey()
|
||||
assert.Equal(expected, actual, "Test #%d failed", i)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNondeterministicGenerateValidPassphrase(t *testing.T) {
|
||||
func TestNondeterministicGenerateValidEncryptionKey(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
// Due to the nondeterminism of random number generators, this
|
||||
// functionality is impossible to fully test. Let's just generate
|
||||
@ -72,9 +72,9 @@ func TestNondeterministicGenerateValidPassphrase(t *testing.T) {
|
||||
asciiSymbols,
|
||||
}
|
||||
|
||||
engine := secret.NewPassphraseEngine(nil)
|
||||
engine := generate.NewEncryptionKeyEngine(nil)
|
||||
for i := 0; i < 10000; i++ {
|
||||
passphrase := engine.GeneratePassphrase()
|
||||
passphrase := engine.GenerateEncryptionKey()
|
||||
assert.Truef(len(passphrase) >= defaultLength,
|
||||
"%s does not meet the length requirement", passphrase)
|
||||
|
||||
@ -86,10 +86,10 @@ func TestNondeterministicGenerateValidPassphrase(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestGenerateValidPassphraseN(t *testing.T) {
|
||||
func TestGenerateValidEncryptionKeyN(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
testSource := rand.NewSource(42)
|
||||
engine := secret.NewPassphraseEngine(testSource)
|
||||
engine := generate.NewEncryptionKeyEngine(testSource)
|
||||
tests := []struct {
|
||||
inputLegth int
|
||||
expectedLength int
|
||||
@ -109,7 +109,7 @@ func TestGenerateValidPassphraseN(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
passphrase := engine.GeneratePassphraseN(tt.inputLegth)
|
||||
passphrase := engine.GenerateEncryptionKeyN(tt.inputLegth)
|
||||
assert.Len(passphrase, tt.expectedLength)
|
||||
}
|
||||
}
|
@ -12,7 +12,7 @@
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package secret
|
||||
package generate
|
||||
|
||||
import (
|
||||
crypto "crypto/rand"
|
Loading…
x
Reference in New Issue
Block a user