Skip to content
This repository has been archived by the owner on Mar 16, 2024. It is now read-only.

Commit

Permalink
Merge pull request #2250 from njhale/gen-secret-sugar
Browse files Browse the repository at this point in the history
Add range syntax sugar for secret generation
  • Loading branch information
njhale authored Oct 16, 2023
2 parents 8e91874 + 13e1586 commit 2be8a30
Show file tree
Hide file tree
Showing 2 changed files with 135 additions and 0 deletions.
52 changes: 52 additions & 0 deletions pkg/secrets/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ package secrets
import (
"crypto/rand"
"math/big"
"sort"

"k8s.io/apimachinery/pkg/util/sets"
)

const (
Expand All @@ -20,6 +23,8 @@ func GenerateRandomSecret(length int, characterSet string) (string, error) {
}
if characterSet == "" {
characterSet = defaultCharacterSet
} else {
characterSet = inflateRanges(characterSet)
}

// Generate a random secret by randomly selecting characters from the given character set.
Expand All @@ -34,3 +39,50 @@ func GenerateRandomSecret(length int, characterSet string) (string, error) {

return string(secret), nil
}

// inflateRanges inflates a character set by expanding any ranges (e.g. `A-z`) into the full set of characters they represent.
func inflateRanges(characterSet string) string {
var (
runeSet = []rune(characterSet)
inflated = sets.New[rune]()
)
for i := 0; i < len(runeSet); i++ {
cur := runeSet[i]
if alphanumeric(cur) {
// Alphanumeric character detected
if i+2 < len(runeSet) && runeSet[i+1] == '-' && alphanumeric(runeSet[i+2]) {
// Range detected, convert to full set of characters
start, end := cur, runeSet[i+2]
if start > end {
// Swap start and end if they're out of order
start, end = end, start
}

for c := start; c <= end; c++ {
if alphanumeric(c) {
inflated.Insert(c)
}
}

// Skip the next two characters since we've already processed them
i += 2
continue
}
}

inflated.Insert(cur)
}

sorted := inflated.UnsortedList()
sort.Slice(sorted, func(i, j int) bool {
return sorted[i] < sorted[j]
})

return string(sorted)
}

// alphanumeric returns true IFF the given rune is alphanumeric; e.g. [A-z0-9] .
func alphanumeric(r rune) bool {
cv := int(r)
return (cv >= int('A') && cv <= int('Z')) || (cv >= int('a') && cv <= int('z')) || (cv >= int('0') && cv <= int('9'))
}
83 changes: 83 additions & 0 deletions pkg/secrets/generate_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package secrets

import (
"testing"

"github.com/stretchr/testify/assert"
)

func TestInflateRanges(t *testing.T) {
for _, tt := range []struct {
name string
want string
}{
{
name: "",
want: "",
},
{
name: "-",
want: "-",
},
{
name: "A-",
want: "-A",
},
{
name: "A-A",
want: "A",
},
{
name: "A-Z",
want: "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
},
{
name: "Z-A",
want: "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
},
{
name: "A-z",
want: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
},
{
name: "z-A",
want: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
},
{
name: "a-z",
want: "abcdefghijklmnopqrstuvwxyz",
},
{
name: "z-a",
want: "abcdefghijklmnopqrstuvwxyz",
},
{
name: "0-9",
want: "0123456789",
},
{
name: "9-0",
want: "0123456789",
},
{
name: "0-9A-Z",
want: "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ",
},
{
name: "A-Z0-9",
want: "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ",
},
{
name: "A-Za-z0-9",
want: "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
},
{
name: "!#$%&*+-0123456789=ABCDEFGHIJKLMNOPQRSTUVWXYZ^_abcdefghijklmnopqrstuvwxyz",
want: "!#$%&*+-0123456789=ABCDEFGHIJKLMNOPQRSTUVWXYZ^_abcdefghijklmnopqrstuvwxyz",
},
} {
t.Run(tt.name, func(t *testing.T) {
assert.Equal(t, tt.want, inflateRanges(tt.name))
})
}
}

0 comments on commit 2be8a30

Please sign in to comment.