-
Notifications
You must be signed in to change notification settings - Fork 258
Expand file tree
/
Copy pathprovisioner.go
More file actions
205 lines (167 loc) · 6.91 KB
/
provisioner.go
File metadata and controls
205 lines (167 loc) · 6.91 KB
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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
package sdk
import (
"context"
"encoding/json"
"path/filepath"
"time"
)
// Provisioner provides hooks before and after the plugin's executable runs to provision
// and deprovision secrets or other means of authentication required for the executable to run.
type Provisioner interface {
// Description describes what this provisioner does.
Description() string
// Provision gets called before running the plugin's executable to provision the necessary fields
// from the 1Password item in a way that the executable understands.
Provision(ctx context.Context, input ProvisionInput, output *ProvisionOutput)
// Deprovision gets called after the plugin's executable exits, so that the plugin can clean up and
// wipe any sensitive material created in the provision phase.
Deprovision(ctx context.Context, input DeprovisionInput, output *DeprovisionOutput)
}
// ProvisionInput contains info that provisioners can use to provision credentials.
type ProvisionInput struct {
// HomeDir is the path to current user's home directory.
HomeDir string
// TempDir is the path to a temporary directory that the provisioner can use to add files to.
// This directory will automatically be deleted after the executable exits.
TempDir string
// DryRun can be used to opt out
DryRun bool
// Cache can contain data that got added in the provision step from previous runs for this credential.
Cache CacheState
// ItemFields contains the field names and their corresponding (sensitive) values.
ItemFields map[FieldName]string
}
// DeprovisionInput contains info that provisioners can use to deprovision credentials.
type DeprovisionInput struct {
HomeDir string
TempDir string
DryRun bool
}
// ProvisionOutput contains the sensitive values that the Provisioner outputs.
type ProvisionOutput struct {
// Environment can be used to provision credentials as environment variable. The result of this will be added to the executable's environment.
// The expected mapping is: environment variable name to (possibly sensitive) value.
Environment map[string]string
// CommandLine can be used provision credentials as command-line args. The result of this will be the actual (possibly sensitive) command
// line that will be executed.
CommandLine []string
// Files can be used to provision credentials as files. The result of this will be automatically written to disk and deleted when the executable
// exits. The expected mapping is: absolute file path to (possibly sensitive) file contents.
Files map[string]OutputFile
// Cache can be used to make data generated in this provision step available to the provision step of consecutive runs for this credential.
// The data added to the cache will be encrypted and stored locally on disk, so it can be used to store sensitive data. To access the cached
// data from previous runs, use Cache on ProvisionInput.
Cache CacheOperations
// Diagnostics can be used to report errors.
Diagnostics Diagnostics
}
type DeprovisionOutput struct {
Diagnostics Diagnostics
}
// OutputFile contains the sensitive file info and contents that the provisioner outputs.
type OutputFile struct {
Contents []byte
}
// CacheState represents the state of the encrypted cache for a given plugin and item.
type CacheState map[string]CacheEntry
// CacheOperations can be used to modify the state of the encrypted cache, through
// put or remove operations. Good to note: remove operations are executed before
// put operations.
type CacheOperations struct {
Puts map[string]CacheEntry
Removes []string
}
// CacheEntry contains data persisted between consecutive provision runs
type CacheEntry struct {
Data []byte
ExpiresAt time.Time
}
// AddEnvVar adds an environment variable to the provision output.
func (out *ProvisionOutput) AddEnvVar(name string, value string) {
out.Environment[name] = value
}
// AddArgs can be used to add additional arguments to the command line of the provision output.
func (out *ProvisionOutput) AddArgs(args ...string) {
out.CommandLine = append(out.CommandLine, args...)
}
// PrependArgs can be used to insert additional arguments at the beginning of the command line of the provision output.
func (out *ProvisionOutput) PrependArgs(args ...string) {
out.CommandLine = append(out.CommandLine[:1], append(args, out.CommandLine[1:]...)...)
}
// AddSecretFile can be used to add a file containing secrets to the provision output.
func (out *ProvisionOutput) AddSecretFile(path string, contents []byte) {
out.AddFile(path, OutputFile{
Contents: contents,
})
}
// AddNonSecretFile can be used to add a file that does not contain secrets to the provision output.
func (out *ProvisionOutput) AddNonSecretFile(path string, contents []byte) {
out.AddFile(path, OutputFile{
Contents: contents,
})
}
// AddFile can be used to add a file to the provision output.
func (out *ProvisionOutput) AddFile(path string, file OutputFile) {
out.Files[path] = file
}
// AddError can be used to report an error to the provision output. If the provision output contains one
// or more errors, provisioning is considered failed.
func (out *ProvisionOutput) AddError(err error) {
out.Diagnostics.Errors = append(out.Diagnostics.Errors, Error{err.Error()})
}
// FromHomeDir returns a path with the user's home directory prepended.
func (in *ProvisionInput) FromHomeDir(path ...string) string {
return filepath.Join(append([]string{in.HomeDir}, path...)...)
}
// FromTempDir returns a path with the current execution's temp directory prepended.
func (in *ProvisionInput) FromTempDir(path ...string) string {
return filepath.Join(append([]string{in.TempDir}, path...)...)
}
// Get returns the cached value at the specified key if it exists. The data can be returned either as a []byte
// or unmarshaled as JSON.
func (c CacheState) Get(key string, out any) (ok bool) {
entry, ok := c[key]
if !ok {
return false
}
data := entry.Data
switch out := out.(type) {
case *[]byte:
copy(*out, data)
default:
err := json.Unmarshal(data, out)
if err != nil {
return false
}
}
return true
}
// Has returns whether the specified key is present in the cache.
func (c CacheState) Has(key string) (ok bool) {
_, ok = c[key]
return ok
}
// Put puts data into the cache at the specified key and with the specified TTL, which will be applied to the provision step of
// all consecutive runs, until the TTL is met or Remove is called. The data will be stored as a []byte or marshaled as JSON.
func (c *CacheOperations) Put(key string, data any, expiresAt time.Time) error {
var marshaled []byte
var err error
switch data := data.(type) {
case []byte:
marshaled = data
default:
marshaled, err = json.Marshal(data)
if err != nil {
return err
}
}
c.Puts[key] = CacheEntry{
ExpiresAt: expiresAt,
Data: marshaled,
}
return nil
}
// Remove removes data from the cache at the specified key, which will be applied to the provision step of all consecutive runs.
func (c *CacheOperations) Remove(key string) {
c.Removes = append(c.Removes, key)
}