-
Notifications
You must be signed in to change notification settings - Fork 3
/
run.go
217 lines (184 loc) · 6.08 KB
/
run.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
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
206
207
208
209
210
211
212
213
214
215
216
217
package cmd
import (
"bytes"
"encoding/hex"
"fmt"
"io"
"os"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"github.com/capeprivacy/cli/entities"
"github.com/capeprivacy/cli/sdk"
)
// runCmd represents the run command
var runCmd = &cobra.Command{
Use: "run function_id [input data]",
Short: "Run a deployed function with data",
Long: "Run a deployed function with data, takes function id, path to data, and (optional) checksum.\n" +
"Run will also read input data from stdin, example: \"echo '1234' | cape run id\".\n" +
"Results are output to stdout so you can easily pipe them elsewhere.",
RunE: func(cmd *cobra.Command, args []string) error {
err := run(cmd, args)
if _, ok := err.(UserError); !ok {
cmd.SilenceUsage = true
}
return err
},
}
type RunResponse struct {
Type string `json:"type"`
Message []byte `json:"message"`
}
type AttestationResponse struct {
AttestationDoc string `json:"attestation_doc"`
}
type Message struct {
Type string `json:"type"`
Message []byte `json:"message"`
}
type ErrorRunResponse struct {
Message string `json:"message"`
}
func init() {
rootCmd.AddCommand(runCmd)
runCmd.PersistentFlags().StringP("token", "t", "", "function token to use")
runCmd.PersistentFlags().StringP("file", "f", "", "input data file")
runCmd.PersistentFlags().StringP("function-checksum", "", "", "function checksum to attest")
runCmd.PersistentFlags().StringP("function-hash", "", "", "function hash to attest")
runCmd.PersistentFlags().StringP("key-policy-hash", "", "", "key policy hash to attest")
runCmd.PersistentFlags().StringP("key-policy-checksum", "", "", "key policy checksum to attest")
runCmd.PersistentFlags().StringSliceP("pcr", "p", []string{""}, "pass multiple PCRs to validate against")
err := runCmd.PersistentFlags().MarkDeprecated("function-hash", "this flag has been deprecated for renaming, use 'function-checksum' instead")
if err != nil {
log.WithError(err).Error("unable to set flag 'function-hash' as deprecated")
}
err = runCmd.PersistentFlags().MarkDeprecated("key-policy-hash", "this flag has been deprecated for renaming, use 'key-policy-checksum' instead")
if err != nil {
log.WithError(err).Error("unable to set flag 'key-policy-hash' as deprecated")
}
}
func run(cmd *cobra.Command, args []string) error {
u := C.EnclaveHost
insecure := C.Insecure
if len(args) < 1 {
return UserError{Msg: "you must pass a function ID", Err: fmt.Errorf("invalid number of input arguments")}
}
if len(args) > 2 {
return UserError{Msg: "you must pass in only one input data (stdin, string or filename)", Err: fmt.Errorf("invalid number of input arguments")}
}
functionID := args[0]
var input []byte
file, err := cmd.Flags().GetString("file")
if err != nil {
return UserError{Msg: "error retrieving file flag", Err: err}
}
funcChecksumArg, err := cmd.Flags().GetString("function-checksum")
if err != nil {
return UserError{Msg: "error retrieving function-checksum flag", Err: err}
}
// Deprecated
funcHashArg, err := cmd.Flags().GetString("function-hash")
if err != nil {
return UserError{Msg: "error retrieving function_hash flag", Err: err}
}
var funcChecksum []byte
if funcChecksumArg != "" {
funcChecksum, err = hex.DecodeString(funcChecksumArg)
if err != nil {
return UserError{Msg: "error reading in checksum", Err: err}
}
} else {
funcChecksum, err = hex.DecodeString(funcHashArg)
if err != nil {
return UserError{Msg: "error reading function hash", Err: err}
}
}
pcrSlice, err := cmd.Flags().GetStringSlice("pcr")
if err != nil {
return UserError{Msg: "error retrieving pcr flags", Err: err}
}
keyChecksumArg, err := cmd.Flags().GetString("key-policy-checksum")
if err != nil {
return UserError{Msg: "error retrieving key_checksum flag", Err: err}
}
// Deprecated
keyPolicyHashArg, err := cmd.Flags().GetString("key-policy-hash")
if err != nil {
return UserError{Msg: "error retrieving key_policy_hash flag", Err: err}
}
var keyChecksum []byte
if keyChecksumArg != "" {
keyChecksum, err = hex.DecodeString(keyChecksumArg)
if err != nil {
return UserError{Msg: "error reading in key policy checksum", Err: err}
}
} else {
keyChecksum, err = hex.DecodeString(keyPolicyHashArg)
if err != nil {
return UserError{Msg: "error reading in key policy checksum", Err: err}
}
}
functionToken, _ := cmd.Flags().GetString("token")
switch {
case file != "":
// input file was provided
input, err = os.ReadFile(file)
if err != nil {
return UserError{Msg: "unable to read data file", Err: err}
}
case len(args) == 2:
// read input from command line string
input = []byte(args[1])
default:
// read input from stdin
buf := new(bytes.Buffer)
if _, err := io.Copy(buf, cmd.InOrStdin()); err != nil {
return UserError{Msg: "unable to read data from stdin", Err: err}
}
input = buf.Bytes()
}
t, err := getAuthToken()
if err != nil {
return err
}
auth := entities.FunctionAuth{Type: entities.AuthenticationTypeAuth0, Token: t}
if functionToken != "" {
auth.Type = entities.AuthenticationTypeFunctionToken
auth.Token = functionToken
}
results, err := sdk.Run(sdk.RunRequest{
URL: u,
FunctionID: functionID,
Data: input,
Insecure: insecure,
FuncChecksum: funcChecksum,
KeyChecksum: keyChecksum,
PcrSlice: pcrSlice,
FunctionAuth: auth,
})
if err != nil {
return fmt.Errorf("error processing data: %w", err)
}
fmt.Println(string(results))
return nil
}
// TODO: This function is exported for tuner to use. Remove once tuner is using sdk.Run directly
func Run(url string, auth entities.FunctionAuth, functionID string, file string, insecure bool) ([]byte, error) {
input, err := os.ReadFile(file)
if err != nil {
return nil, fmt.Errorf("unable to read data file: %w", err)
}
// TODO: Tuner may want to verify function checksum later.
res, err := sdk.Run(sdk.RunRequest{
URL: url,
FunctionID: functionID,
Data: input,
Insecure: insecure,
PcrSlice: []string{},
FunctionAuth: auth,
})
if err != nil {
return nil, fmt.Errorf("error processing data: %w", err)
}
return res, nil
}