Add example and small CLI
Signed-off-by: jolheiser <john.olheiser@gmail.com>main v0.0.2
parent
fcfe79244f
commit
eb0d378523
|
@ -0,0 +1,23 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"go.jolheiser.com/confage"
|
||||||
|
|
||||||
|
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fs := flag.NewFlagSet("confage", flag.ExitOnError)
|
||||||
|
secretKeyFlag := fs.String("secret-key", "", "Age secret key")
|
||||||
|
fs.StringVar(secretKeyFlag, "s", *secretKeyFlag, "--secret-key")
|
||||||
|
if err := fs.Parse(os.Args[1:]); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
t := confage.MustNew(*secretKeyFlag, fs.Arg(0))
|
||||||
|
fmt.Println(t.String())
|
||||||
|
}
|
22
confage.go
22
confage.go
|
@ -38,8 +38,7 @@ func New[T any](key string, val T) (v Type[T], err error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return v, err
|
return v, err
|
||||||
}
|
}
|
||||||
i = ii
|
i, r = ii, ii.Recipient()
|
||||||
r = ii.Recipient()
|
|
||||||
default:
|
default:
|
||||||
i, err = age.NewScryptIdentity(key)
|
i, err = age.NewScryptIdentity(key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -65,40 +64,47 @@ func (t Type[T]) String() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
// MarshalText implements encoding.MarshalText
|
// MarshalText implements encoding.MarshalText
|
||||||
func (v Type[T]) MarshalText() ([]byte, error) {
|
func (t Type[T]) MarshalText() ([]byte, error) {
|
||||||
var b bytes.Buffer
|
var b bytes.Buffer
|
||||||
w, err := age.Encrypt(&b, v.r)
|
w, err := age.Encrypt(&b, t.r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if err := json.NewEncoder(w).Encode(v.Value); err != nil {
|
|
||||||
|
if err := json.NewEncoder(w).Encode(t.Value); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := w.Close(); err != nil {
|
if err := w.Close(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
out := base64.StdEncoding.EncodeToString(b.Bytes())
|
out := base64.StdEncoding.EncodeToString(b.Bytes())
|
||||||
return []byte(out), nil
|
return []byte(out), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalText implements encoding.UnmarshalText
|
// UnmarshalText implements encoding.UnmarshalText
|
||||||
func (v *Type[T]) UnmarshalText(text []byte) error {
|
func (t *Type[T]) UnmarshalText(text []byte) error {
|
||||||
b, err := base64.StdEncoding.DecodeString(string(text))
|
b, err := base64.StdEncoding.DecodeString(string(text))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
r, err := age.Decrypt(bytes.NewBuffer(b), v.i)
|
|
||||||
|
r, err := age.Decrypt(bytes.NewBuffer(b), t.i)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
var out bytes.Buffer
|
var out bytes.Buffer
|
||||||
if _, err := io.Copy(&out, r); err != nil {
|
if _, err := io.Copy(&out, r); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
var val T
|
var val T
|
||||||
if err := json.Unmarshal(out.Bytes(), &val); err != nil {
|
if err := json.Unmarshal(out.Bytes(), &val); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
(*v).Value = val
|
|
||||||
|
(*t).Value = val
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
package confage_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"go.jolheiser.com/confage"
|
||||||
|
|
||||||
|
|
||||||
|
)
|
||||||
|
|
||||||
|
func Example_config() {
|
||||||
|
const secretKey = "AGE-SECRET-KEY-1AN83H8JECDKHSD2RN70WU8RQYYH3C309UUYQQ0EPQNJR3ZXRDHESTUCCM4" // age1ynmpzgvrqj3r6z39kp3p852afe3nkc3neem80vgq96jt2zhesezq8yhn02
|
||||||
|
|
||||||
|
cfg := &Config{
|
||||||
|
Password: confage.MustNew(secretKey, ""),
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := json.Unmarshal(config, &cfg); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println(cfg.Password.Value)
|
||||||
|
// Output:
|
||||||
|
// bar
|
||||||
|
}
|
||||||
|
|
||||||
|
// Example config struct
|
||||||
|
type Config struct {
|
||||||
|
Username string
|
||||||
|
Password confage.Type[string]
|
||||||
|
}
|
||||||
|
|
||||||
|
// config.json living on disk
|
||||||
|
var config = []byte(`{
|
||||||
|
"username": "foo",
|
||||||
|
"password": "YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB0b3pzdTVtcnBBUFV3bnNsa2RIYlhTVGVYeXlHcHpIbEpMR3ZwcWxHMmtjClc5ald4MHZhdFFKY3NmS0R5bFpXY1VGa1RKeWxHaGVzR3FhS1B1NHgydUkKLS0tIEJYRnhMNm12aE14bUU5bGNPVFBJcHBWZDJBeWFMMVdMUGdyVXErOVFuaWsK3F0DfPH+Ud50XIBoDR2D/+/PMoqNp9O2R6BdBLTLyiENJYrxGxo="
|
||||||
|
}`)
|
|
@ -7,29 +7,82 @@ import (
|
||||||
"github.com/matryer/is"
|
"github.com/matryer/is"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestTypeScrypt(t *testing.T) {
|
const (
|
||||||
assert := is.New(t)
|
passphrase = "passphrase"
|
||||||
|
secretKey = "AGE-SECRET-KEY-1F7SU7MXLVHU0SWQ3L2ZMW7G2NN2YTH88NLU6LVDHENTZLMCT3M5S799RDK"
|
||||||
|
)
|
||||||
|
|
||||||
enc := MustNew("passphrase", 0)
|
type Struct struct {
|
||||||
enc.Value = 100
|
String string
|
||||||
|
Int int
|
||||||
|
Bool bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestType(t *testing.T) {
|
||||||
|
t.Run("string", func(t *testing.T) {
|
||||||
|
assert := is.New(t)
|
||||||
|
val := "foo"
|
||||||
|
testEncryption(assert, passphrase, val)
|
||||||
|
testEncryption(assert, secretKey, val)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("int", func(t *testing.T) {
|
||||||
|
assert := is.New(t)
|
||||||
|
val := 123
|
||||||
|
testEncryption(assert, passphrase, val)
|
||||||
|
testEncryption(assert, secretKey, val)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("bool", func(t *testing.T) {
|
||||||
|
assert := is.New(t)
|
||||||
|
val := true
|
||||||
|
testEncryption(assert, passphrase, val)
|
||||||
|
testEncryption(assert, secretKey, val)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("map", func(t *testing.T) {
|
||||||
|
assert := is.New(t)
|
||||||
|
val := map[string]any{
|
||||||
|
"foo": "bar",
|
||||||
|
"baz": 123.0,
|
||||||
|
"bux": false,
|
||||||
|
}
|
||||||
|
testEncryption(assert, passphrase, val)
|
||||||
|
testEncryption(assert, secretKey, val)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("struct", func(t *testing.T) {
|
||||||
|
assert := is.New(t)
|
||||||
|
val := Struct{
|
||||||
|
String: "string",
|
||||||
|
Int: 123,
|
||||||
|
Bool: true,
|
||||||
|
}
|
||||||
|
testEncryption(assert, passphrase, val)
|
||||||
|
testEncryption(assert, secretKey, val)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("pointer", func(t *testing.T) {
|
||||||
|
assert := is.New(t)
|
||||||
|
val := &Struct{
|
||||||
|
String: "string",
|
||||||
|
Int: 123,
|
||||||
|
Bool: true,
|
||||||
|
}
|
||||||
|
testEncryption(assert, passphrase, val)
|
||||||
|
testEncryption(assert, secretKey, val)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func testEncryption[T any](assert *is.I, key string, value T) {
|
||||||
|
assert.Helper()
|
||||||
|
|
||||||
|
enc := MustNew(key, value)
|
||||||
payload, err := json.Marshal(enc)
|
payload, err := json.Marshal(enc)
|
||||||
assert.NoErr(err) // Should be able to marshal JSON
|
assert.NoErr(err) // Should be able to marshal JSON
|
||||||
|
|
||||||
dec := MustNew("passphrase", 0)
|
var t T
|
||||||
err = json.Unmarshal(payload, &dec)
|
dec := MustNew(key, t)
|
||||||
assert.NoErr(err) // Should be able to unmarshal JSON
|
|
||||||
|
|
||||||
assert.Equal(enc.Value, dec.Value) // Values should match
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTypeX25519(t *testing.T) {
|
|
||||||
assert := is.New(t)
|
|
||||||
|
|
||||||
enc := MustNew("AGE-SECRET-KEY-1F7SU7MXLVHU0SWQ3L2ZMW7G2NN2YTH88NLU6LVDHENTZLMCT3M5S799RDK", 100)
|
|
||||||
payload, err := json.Marshal(enc)
|
|
||||||
assert.NoErr(err) // Should be able to marshal JSON
|
|
||||||
|
|
||||||
dec := MustNew("AGE-SECRET-KEY-1F7SU7MXLVHU0SWQ3L2ZMW7G2NN2YTH88NLU6LVDHENTZLMCT3M5S799RDK", 0)
|
|
||||||
err = json.Unmarshal(payload, &dec)
|
err = json.Unmarshal(payload, &dec)
|
||||||
assert.NoErr(err) // Should be able to unmarshal JSON
|
assert.NoErr(err) // Should be able to unmarshal JSON
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue