Skip to content

Commit 362202b

Browse files
authored
Merge pull request #44 from veraison/cowbon-patch-6
Enable attester selections from the request
2 parents ab2da20 + 2f0320d commit 362202b

File tree

5 files changed

+77
-17
lines changed

5 files changed

+77
-17
lines changed

README.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,3 +53,24 @@ Ratsd currently supports the Trusted Secure Module `tsm` attester. You can speci
5353
```bash
5454
curl -X POST http://localhost:8895/ratsd/chares -H "Content-type: application/vnd.veraison.chares+json" -d '{"nonce": "TUlEQk5IMjhpaW9pc2pQeXh4eHh4eHh4eHh4eHh4eHhNSURCTkgyOGlpb2lzalB5eHh4eHh4eHh4eHh4eHh4eA", tsm-report:{"privilege_level": "$level"}}' # Replace $level with a number from 0 to 3
5555
```
56+
57+
## Get evidence from the selected attester only
58+
59+
If more than one leaf attesters present, ratsd adds the evidence generated by all attesters to the response of `/ratsd/chares`. To limit the output to the selected attester, add `list-options: selected` to config.yaml,
60+
then specify the name of each attester along with the associated options in `attester-selection`. If the user does not wish to specify the attester-specific option, "$attester_name": "null" should be specified. The following is an example of the request:
61+
```
62+
"nonce": "base64urlencoded",
63+
64+
"attester-selection": {
65+
"attester-id-1": {
66+
"param11name": "param11value",
67+
"param12name": "param12value"
68+
},
69+
"attester-id-2": {
70+
"param21name": "param21value"
71+
},
72+
"attester-id-3": null
73+
}
74+
```
75+
76+
If `list-options` is not set, or if it's set to `all` in config.yaml, ratsd populates the EAT with CMW from all available attesters as the default behavior.

api/server.go

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,14 @@ const (
2424
type Server struct {
2525
logger *zap.SugaredLogger
2626
manager plugin.IManager
27+
options string
2728
}
2829

29-
func NewServer(logger *zap.SugaredLogger, manager plugin.IManager) *Server {
30+
func NewServer(logger *zap.SugaredLogger, manager plugin.IManager, options string) *Server {
3031
return &Server{
3132
logger: logger,
3233
manager: manager,
34+
options: options,
3335
}
3436
}
3537

@@ -124,19 +126,28 @@ func (s *Server) RatsdChares(w http.ResponseWriter, r *http.Request, param Ratsd
124126
Status: http.StatusBadRequest,
125127
}
126128
s.reportProblem(w, p)
127-
fmt.Println(errMsg)
128129
return
129130
}
131+
} else if s.options == "selected" {
132+
errMsg := "attester-selection must contain at least one attester"
133+
p := &problems.DefaultProblem{
134+
Type: string(TagGithubCom2024VeraisonratsdErrorInvalidrequest),
135+
Title: string(InvalidRequest),
136+
Detail: errMsg,
137+
Status: http.StatusBadRequest,
138+
}
139+
s.reportProblem(w, p)
140+
return
130141
}
131142

132-
for _, pn := range pl {
143+
getCMW := func (pn string) bool {
133144
attester, err := s.manager.LookupByName(pn)
134145
if err != nil {
135146
errMsg := fmt.Sprintf(
136147
"failed to get handle from %s: %s", pn, err.Error())
137148
p := problems.NewDetailedProblem(http.StatusInternalServerError, errMsg)
138149
s.reportProblem(w, p)
139-
return
150+
return false
140151
}
141152

142153
formatOut := attester.GetSupportedFormats()
@@ -145,11 +156,11 @@ func (s *Server) RatsdChares(w http.ResponseWriter, r *http.Request, param Ratsd
145156
pn, formatOut.Status.Error)
146157
p := problems.NewDetailedProblem(http.StatusInternalServerError, errMsg)
147158
s.reportProblem(w, p)
148-
return
159+
return false
149160
}
150161

151162
params, hasOption := options[pn]
152-
if !hasOption {
163+
if !hasOption || string(params) == "null" {
153164
params = json.RawMessage{}
154165
}
155166

@@ -166,11 +177,26 @@ func (s *Server) RatsdChares(w http.ResponseWriter, r *http.Request, param Ratsd
166177
"failed to get attestation report from %s: %s ", pn, out.Status.Error)
167178
p := problems.NewDetailedProblem(http.StatusInternalServerError, errMsg)
168179
s.reportProblem(w, p)
169-
return
180+
return false
170181
}
171182

172183
c := cmw.NewMonad(in.ContentType, out.Evidence)
173184
collection.AddCollectionItem(pn, c)
185+
return true
186+
}
187+
188+
if s.options == "all" {
189+
for _, pn := range pl {
190+
if !getCMW(pn) {
191+
return
192+
}
193+
}
194+
} else {
195+
for pn, _ := range options {
196+
if !getCMW(pn) {
197+
return
198+
}
199+
}
174200
}
175201

176202
serialized, err := collection.MarshalJSON()

api/server_test.go

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -89,12 +89,12 @@ func TestRatsdChares_invalid_body(t *testing.T) {
8989
params.Accept = &param
9090
logger := log.Named("test")
9191

92-
pluginList := []string{"mock-tsm"}
92+
pluginList := []string{"mock-tsm", "tsm-report"}
9393
dm := mock_deps.NewMockIManager(ctrl)
9494
dm.EXPECT().GetPluginList().Return(pluginList).AnyTimes()
9595
dm.EXPECT().LookupByName("mock-tsm").Return(mocktsm.GetPlugin(), nil).AnyTimes()
9696

97-
s := NewServer(logger, dm)
97+
s := NewServer(logger, dm, "selected")
9898
tests := []struct{ name, body, msg string }{
9999
{"missing nonce", `{"noncee": "MIDBNH28iioisjPy"}`,
100100
"fail to retrieve nonce from the request"},
@@ -103,6 +103,8 @@ func TestRatsdChares_invalid_body(t *testing.T) {
103103
"attester-selection": "attester-slection"}`, validNonce),
104104
"failed to parse attester selection: json: cannot unmarshal string into" +
105105
` Go value of type map[string]json.RawMessage`},
106+
{"no attester specified in selected mode", fmt.Sprintf(`{"nonce": "%s"}`, validNonce),
107+
"attester-selection must contain at least one attester"},
106108
}
107109

108110
for _, tt := range tests {
@@ -146,7 +148,7 @@ func TestRatsdChares_valid_request_no_available_attester(t *testing.T) {
146148
dm := mock_deps.NewMockIManager(ctrl)
147149
dm.EXPECT().GetPluginList().Return(pluginList)
148150

149-
s := NewServer(logger, dm)
151+
s := NewServer(logger, dm, "all")
150152
w := httptest.NewRecorder()
151153
rs := fmt.Sprintf(`{"nonce": "%s"}`, validNonce)
152154
rb := strings.NewReader(rs)
@@ -182,7 +184,7 @@ func TestRatsdChares_valid_request(t *testing.T) {
182184
dm.EXPECT().GetPluginList().Return(pluginList).AnyTimes()
183185
dm.EXPECT().LookupByName("mock-tsm").Return(mocktsm.GetPlugin(), nil).AnyTimes()
184186

185-
s := NewServer(logger, dm)
187+
s := NewServer(logger, dm, "all")
186188
realNonce, _ := base64.RawURLEncoding.DecodeString(validNonce)
187189

188190
tests := []struct {
@@ -194,6 +196,15 @@ func TestRatsdChares_valid_request(t *testing.T) {
194196
fmt.Sprintf(`{"nonce": "%s"}`, validNonce),
195197
0,
196198
},
199+
{
200+
"with null as params",
201+
fmt.Sprintf(`{"nonce": "%s",
202+
"attester-selection":{
203+
"mock-tsm": null
204+
}
205+
}`, validNonce),
206+
0,
207+
},
197208
{
198209
"with params",
199210
fmt.Sprintf(`{"nonce": "%s",

cmd/main.go

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,12 @@ var (
1818
)
1919

2020
type cfg struct {
21-
ListenAddr string `mapstructure:"listen-addr" valid:"dialstring"`
22-
Protocol string `mapstructure:"protocol" valid:"in(http|https)"`
23-
Cert string `mapstructure:"cert" config:"zerodefault"`
24-
CertKey string `mapstructure:"cert-key" config:"zerodefault"`
25-
PluginDir string `mapstructure:"plugin-dir" config:"zerodefault"`
21+
ListenAddr string `mapstructure:"listen-addr" valid:"dialstring"`
22+
Protocol string `mapstructure:"protocol" valid:"in(http|https)"`
23+
Cert string `mapstructure:"cert" config:"zerodefault"`
24+
CertKey string `mapstructure:"cert-key" config:"zerodefault"`
25+
PluginDir string `mapstructure:"plugin-dir" config:"zerodefault"`
26+
ListOptions string `mapstructure:"list-options" valid:"in(all|selected)"`
2627
}
2728

2829
func (o cfg) Validate() error {
@@ -84,7 +85,7 @@ func main() {
8485

8586
log.Info("Loaded sub-attesters:", pluginManager.GetPluginList())
8687

87-
svr := api.NewServer(log.Named("api"), pluginManager)
88+
svr := api.NewServer(log.Named("api"), pluginManager, cfg.ListOptions)
8889
r := http.NewServeMux()
8990
options := api.StdHTTPServerOptions{
9091
BaseRouter: r,

config.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@ ratsd:
44
listen-addr: 0.0.0.0:8895
55
protocol: http
66
plugin-dir: attesters/bin
7+
list-options: all

0 commit comments

Comments
 (0)