-
Notifications
You must be signed in to change notification settings - Fork 1
/
string.go
99 lines (79 loc) · 2.06 KB
/
string.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
package age
import (
"bytes"
"fmt"
"io"
"strings"
"filippo.io/age"
"filippo.io/age/armor"
"sylr.dev/yaml/v3"
)
// NewString takes a string to encrypt and the targeted recipients then
// returns a String ready to be Marshalled.
func NewString(str string, recipients []age.Recipient) String {
s := String{}
s.Recipients = recipients
s.Node = &yaml.Node{}
s.SetString(str)
s.Tag = YAMLTag
return s
}
// NewStringFromNode takes a *yaml.Node and recipients and returns a String.
func NewStringFromNode(node *yaml.Node, recipients []age.Recipient) String {
s := String{}
s.Recipients = recipients
s.Node = node
return s
}
// String holds a string to encrypt and the targeted recipients.
// It embeds *yaml.Node.
type String struct {
*yaml.Node
Recipients []age.Recipient
}
// String implements the Stringer interface.
func (s *String) String() string {
return s.Value
}
// UnmarshalYAML pushes the yaml.Node in the String.Node.
func (s *String) UnmarshalYAML(value *yaml.Node) error {
s.Node = value
return nil
}
// MarshalYAML encrypts the String and marshals it to YAML. If Recipients
// is empty then the Value is kept unencrypted.
func (s String) MarshalYAML() (interface{}, error) {
node := yaml.Node{
Kind: s.Kind,
Style: s.Style,
Tag: s.Tag,
Value: s.Value,
Anchor: s.Anchor,
HeadComment: s.HeadComment,
LineComment: s.LineComment,
FootComment: s.FootComment,
Line: s.Line,
Column: s.Column,
}
// If no recipients then do not encrypt.
if len(s.Recipients) == 0 {
node.Value = s.Value
return &node, nil
}
// Force yaml literal string for encrypted data
node.Style = yaml.LiteralStyle
buf := &bytes.Buffer{}
armorWriter := armor.NewWriter(buf)
encryptWriter, err := age.Encrypt(armorWriter, s.Recipients...)
if err != nil {
return nil, fmt.Errorf("%w: %s", ErrUpstreamAgeError, err)
}
_, err = io.WriteString(encryptWriter, s.Value)
if err != nil {
return nil, err
}
encryptWriter.Close()
armorWriter.Close()
node.Value = strings.TrimSuffix(buf.String(), "\n")
return &node, nil
}