age

package module
v3.0.0-...-eb6b46d Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 3, 2022 License: BSD-3-Clause Imports: 7 Imported by: 5

README

go-yaml-age

pkg.go.dev codecov

Wrapper for sylr.dev/yaml/v3 which allows to encrypt/decrypt YAML data in place using the AGE encryption tool.

Documentation

You'll find the documentation and examples on pkg.go.dev.

Applications

This wrapper has been written in order to bring YAML support to @FiloSottile's age cli implementation.

The ultimate goals are to provide AGE support in kustomize and @fluxcd's kustomize-controller.

You can find unofficial binaries of age and kustomize with AGE support at https://github.com/sylr/kustomize-age.

Documentation

Overview

Package age provides a wrapper for `sylr.dev/yaml/v3` which allows to encrypt/decrypt YAML values in place using AGE.

It only supports encrypting/decrypting strings, it will treat any other YAML type like bool, int, float ... etc as strings.

Index

Examples

Constants

View Source
const (
	// YAMLTag tag that is used to identify data to encrypt/decrypt
	YAMLTag       = "!crypto/age"
	YAMLTagPrefix = "!crypto/age:"
)

Variables

View Source
var (
	ErrUnknownAttribute          = fmt.Errorf("unknown attribute")
	ErrMoreThanOneStyleAttribute = fmt.Errorf("can't use more than one style attribute")
	ErrUpstreamAgeError          = fmt.Errorf("age")
	ErrUnsupportedValueType      = fmt.Errorf("unsupported Value type")
)

Functions

This section is empty.

Types

type String

type String struct {
	*yaml.Node
	Recipients []age.Recipient
}

String holds a string to encrypt and the targeted recipients. It embeds *yaml.Node.

Example (Encode)
package main

import (
	"bytes"
	"fmt"

	"filippo.io/age"
	yamlage "sylr.dev/yaml/age/v3"

	yaml "sylr.dev/yaml/v3"
)

func main() {
	rec, err := age.NewScryptRecipient("point-adjust-member-tip-tiger-limb-honey-prefer-copy-issue")

	if err != nil {
		panic(err)
	}

	node := struct {
		Password yamlage.String `yaml:"password"`
	}{
		Password: yamlage.NewString("ThisIsMyReallyEncryptedPassword", []age.Recipient{rec}),
	}

	buf := bytes.NewBuffer(nil)
	encoder := yaml.NewEncoder(buf)
	encoder.SetIndent(2)
	err = encoder.Encode(&node)

	if err != nil {
		panic(err)
	}

	fmt.Printf("%s", buf.String())
}
Output:

func NewString

func NewString(str string, recipients []age.Recipient) String

NewString takes a string to encrypt and the targeted recipients then returns a String ready to be Marshalled.

func NewStringFromNode

func NewStringFromNode(node *yaml.Node, recipients []age.Recipient) String

NewStringFromNode takes a *yaml.Node and recipients and returns a String.

func (String) MarshalYAML

func (s String) MarshalYAML() (interface{}, error)

MarshalYAML encrypts the String and marshals it to YAML. If Recipients is empty then the Value is kept unencrypted.

func (*String) String

func (s *String) String() string

String implements the Stringer interface.

func (*String) UnmarshalYAML

func (s *String) UnmarshalYAML(value *yaml.Node) error

UnmarshalYAML pushes the yaml.Node in the String.Node.

type Wrapper

type Wrapper struct {
	// Value holds the struct that will either be decrypted with the given
	// Identities or encrypted with the given Recipients.
	Value interface{}

	// Identities that will be used to try decrypting encrypted Value.
	Identities []age.Identity

	// Recipients that will be used for encrypting un-encrypted Value.
	Recipients []age.Recipient

	// DiscardNoTag instructs the Unmarshaler to not honour the NoTag
	// `!crypto/age` tag attribute. This is useful when re-keying data.
	DiscardNoTag bool

	// ForceNoTag strip the `!crypto/age` tags from the Marshaler output.
	ForceNoTag bool

	// NoDecrypt inscruts the Unmarshaler to leave encrypted data encrypted.
	// This is useful when you want to Marshal new un-encrytped data in a
	// document already containing encrypted data.
	NoDecrypt bool
}

Wrapper is a struct used as a wrapper for yaml.Marshal and yaml.Unmarshal.

Example
package main

import (
	"bytes"
	"fmt"

	"filippo.io/age"
	yamlage "sylr.dev/yaml/age/v3"

	yaml "sylr.dev/yaml/v3"
)

func main() {
	yamlString := `password: !crypto/age |
  -----BEGIN AGE ENCRYPTED FILE-----
  YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNjcnlwdCB4c3VtbURKYlhNclZORExq
  cVdyM1RnIDE4ClJ3ejBxU292WGJpQWtLQ1NXMnN4THk5VWQvLzVzKzBmWTQvOVp5
  MTQrak0KLS0tIFI1U1RnZXFDVU5YbGJTU3lpNnBOdEVybDdtQmUrM1VkcHV4OElN
  Zm1aZ1kKvhgBDqN8umSS+EmwRwAKj9wNicvbWuynN7W0wxu6apXn57icXGgxiFK0
  8zlxcVRSeplPrnuRdOUBgjoNtdUt
  -----END AGE ENCRYPTED FILE-----`

	rbuf := bytes.NewBufferString(yamlString)
	wbuf := bytes.NewBuffer(nil)

	node := struct {
		Password yamlage.String `yaml:"password"`
	}{}

	id, err := age.NewScryptIdentity("point-adjust-member-tip-tiger-limb-honey-prefer-copy-issue")

	if err != nil {
		panic(err)
	}

	w := yamlage.Wrapper{
		Value:      &node,
		Identities: []age.Identity{id},
	}

	decoder := yaml.NewDecoder(rbuf)
	encoder := yaml.NewEncoder(wbuf)
	encoder.SetIndent(2)

	err = decoder.Decode(&w)

	if err != nil {
		panic(err)
	}

	err = encoder.Encode(&node)

	if err != nil {
		panic(err)
	}

	fmt.Printf("%s", wbuf.String())
}
Output:

password: !crypto/age ThisIsMyReallyEncryptedPassword
Example (Anonymous)
package main

import (
	"bytes"
	"fmt"
	"io"

	"filippo.io/age"
	yamlage "sylr.dev/yaml/age/v3"

	yaml "sylr.dev/yaml/v3"
)

func main() {
	yamlString := `
password: !crypto/age:DoubleQuoted |
  -----BEGIN AGE ENCRYPTED FILE-----
  YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNjcnlwdCB4c3VtbURKYlhNclZORExq
  cVdyM1RnIDE4ClJ3ejBxU292WGJpQWtLQ1NXMnN4THk5VWQvLzVzKzBmWTQvOVp5
  MTQrak0KLS0tIFI1U1RnZXFDVU5YbGJTU3lpNnBOdEVybDdtQmUrM1VkcHV4OElN
  Zm1aZ1kKvhgBDqN8umSS+EmwRwAKj9wNicvbWuynN7W0wxu6apXn57icXGgxiFK0
  8zlxcVRSeplPrnuRdOUBgjoNtdUt
  -----END AGE ENCRYPTED FILE-----
---
password: !crypto/age:SingleQuoted |
  -----BEGIN AGE ENCRYPTED FILE-----
  YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNjcnlwdCB4c3VtbURKYlhNclZORExq
  cVdyM1RnIDE4ClJ3ejBxU292WGJpQWtLQ1NXMnN4THk5VWQvLzVzKzBmWTQvOVp5
  MTQrak0KLS0tIFI1U1RnZXFDVU5YbGJTU3lpNnBOdEVybDdtQmUrM1VkcHV4OElN
  Zm1aZ1kKvhgBDqN8umSS+EmwRwAKj9wNicvbWuynN7W0wxu6apXn57icXGgxiFK0
  8zlxcVRSeplPrnuRdOUBgjoNtdUt
  -----END AGE ENCRYPTED FILE-----
---
password: !crypto/age:DoubleQuoted,NoTag |
  -----BEGIN AGE ENCRYPTED FILE-----
  YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNjcnlwdCB4c3VtbURKYlhNclZORExq
  cVdyM1RnIDE4ClJ3ejBxU292WGJpQWtLQ1NXMnN4THk5VWQvLzVzKzBmWTQvOVp5
  MTQrak0KLS0tIFI1U1RnZXFDVU5YbGJTU3lpNnBOdEVybDdtQmUrM1VkcHV4OElN
  Zm1aZ1kKvhgBDqN8umSS+EmwRwAKj9wNicvbWuynN7W0wxu6apXn57icXGgxiFK0
  8zlxcVRSeplPrnuRdOUBgjoNtdUt
  -----END AGE ENCRYPTED FILE-----`

	rbuf := bytes.NewBufferString(yamlString)
	wbuf := bytes.NewBuffer(nil)

	id, err := age.NewScryptIdentity("point-adjust-member-tip-tiger-limb-honey-prefer-copy-issue")

	if err != nil {
		panic(err)
	}

	node := &yaml.Node{}

	w := yamlage.Wrapper{
		Value:      node,
		Identities: []age.Identity{id},
	}

	decoder := yaml.NewDecoder(rbuf)
	encoder := yaml.NewEncoder(wbuf)
	encoder.SetIndent(2)

	for {
		err = decoder.Decode(&w)

		if err == io.EOF {
			break
		} else if err != nil {
			panic(err)
		}

		err = encoder.Encode(&node)

		if err != nil {
			panic(err)
		}
	}

	fmt.Printf("%s", wbuf.String())
}
Output:

password: !crypto/age:DoubleQuoted "ThisIsMyReallyEncryptedPassword"
---
password: !crypto/age:SingleQuoted 'ThisIsMyReallyEncryptedPassword'
---
password: "ThisIsMyReallyEncryptedPassword"

func (Wrapper) MarshalYAML

func (w Wrapper) MarshalYAML() (interface{}, error)

MarshalYAML recursively encrypts Value.

func (Wrapper) UnmarshalYAML

func (w Wrapper) UnmarshalYAML(value *yaml.Node) error

UnmarshalYAML takes a yaml.Node and recursively decrypt nodes marked with the `!crypto/age` YAML tag.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL