...
1
16
17 package action
18
19 import (
20 "bufio"
21 "fmt"
22 "os"
23 "syscall"
24
25 "github.com/Masterminds/semver/v3"
26 "github.com/pkg/errors"
27 "golang.org/x/term"
28
29 "helm.sh/helm/v3/pkg/chart/loader"
30 "helm.sh/helm/v3/pkg/chartutil"
31 "helm.sh/helm/v3/pkg/provenance"
32 )
33
34
35
36
37 type Package struct {
38 Sign bool
39 Key string
40 Keyring string
41 PassphraseFile string
42 Version string
43 AppVersion string
44 Destination string
45 DependencyUpdate bool
46
47 RepositoryConfig string
48 RepositoryCache string
49 }
50
51
52 func NewPackage() *Package {
53 return &Package{}
54 }
55
56
57 func (p *Package) Run(path string, _ map[string]interface{}) (string, error) {
58 ch, err := loader.LoadDir(path)
59 if err != nil {
60 return "", err
61 }
62
63
64 if p.Version != "" {
65 ch.Metadata.Version = p.Version
66 }
67
68 if err := validateVersion(ch.Metadata.Version); err != nil {
69 return "", err
70 }
71
72 if p.AppVersion != "" {
73 ch.Metadata.AppVersion = p.AppVersion
74 }
75
76 if reqs := ch.Metadata.Dependencies; reqs != nil {
77 if err := CheckDependencies(ch, reqs); err != nil {
78 return "", err
79 }
80 }
81
82 var dest string
83 if p.Destination == "." {
84
85 dest, err = os.Getwd()
86 if err != nil {
87 return "", err
88 }
89 } else {
90
91 dest = p.Destination
92 }
93
94 name, err := chartutil.Save(ch, dest)
95 if err != nil {
96 return "", errors.Wrap(err, "failed to save")
97 }
98
99 if p.Sign {
100 err = p.Clearsign(name)
101 }
102
103 return name, err
104 }
105
106
107 func validateVersion(ver string) error {
108 if _, err := semver.NewVersion(ver); err != nil {
109 return err
110 }
111 return nil
112 }
113
114
115 func (p *Package) Clearsign(filename string) error {
116
117 signer, err := provenance.NewFromKeyring(p.Keyring, p.Key)
118 if err != nil {
119 return err
120 }
121
122 passphraseFetcher := promptUser
123 if p.PassphraseFile != "" {
124 passphraseFetcher, err = passphraseFileFetcher(p.PassphraseFile, os.Stdin)
125 if err != nil {
126 return err
127 }
128 }
129
130 if err := signer.DecryptKey(passphraseFetcher); err != nil {
131 return err
132 }
133
134 sig, err := signer.ClearSign(filename)
135 if err != nil {
136 return err
137 }
138
139 return os.WriteFile(filename+".prov", []byte(sig), 0644)
140 }
141
142
143 func promptUser(name string) ([]byte, error) {
144 fmt.Printf("Password for key %q > ", name)
145
146
147 pw, err := term.ReadPassword(int(syscall.Stdin))
148 fmt.Println()
149 return pw, err
150 }
151
152 func passphraseFileFetcher(passphraseFile string, stdin *os.File) (provenance.PassphraseFetcher, error) {
153 file, err := openPassphraseFile(passphraseFile, stdin)
154 if err != nil {
155 return nil, err
156 }
157 defer file.Close()
158
159 reader := bufio.NewReader(file)
160 passphrase, _, err := reader.ReadLine()
161 if err != nil {
162 return nil, err
163 }
164 return func(_ string) ([]byte, error) {
165 return passphrase, nil
166 }, nil
167 }
168
169 func openPassphraseFile(passphraseFile string, stdin *os.File) (*os.File, error) {
170 if passphraseFile == "-" {
171 stat, err := stdin.Stat()
172 if err != nil {
173 return nil, err
174 }
175 if (stat.Mode() & os.ModeNamedPipe) == 0 {
176 return nil, errors.New("specified reading passphrase from stdin, without input on stdin")
177 }
178 return stdin, nil
179 }
180 return os.Open(passphraseFile)
181 }
182
View as plain text