Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,15 @@ By default, ratsd core listens on port 8895. Use `POST /ratsd/chares` to retriev
$ curl -X POST http://localhost:8895/ratsd/chares -H "Content-type: application/vnd.veraison.chares+json" -d '{"nonce": "TUlEQk5IMjhpaW9pc2pQeXh4eHh4eHh4eHh4eHh4eHhNSURCTkgyOGlpb2lzalB5eHh4eHh4eHh4eHh4eHh4eA"}'
{"cmw":"eyJfX2Ntd2NfdCI6InRhZzpnaXRodWIuY29tLDIwMjU6dmVyYWlzb24vcmF0c2QvY213IiwibW9jay10c20iOlsiYXBwbGljYXRpb24vdm5kLnZlcmFpc29uLmNvbmZpZ2ZzLXRzbStqc29uIiwiZXlKaGRYaGliRzlpSWpvaVdWaFdORmx0ZUhaWlp5SXNJbTkxZEdKc2IySWlPaUpqU0Vwd1pHMTRiR1J0Vm5OUGFVRjNRMjFzZFZsdGVIWlphbTluVGtkUk1FOVVVVEJPUkVrd1dsUlJORTE2U1hwUFJGazFUbXByTWxwcVdUVk9lazB5V1ZSVmQwNTZhek5QUkdNMFRucG5NMDlFWXpST2VtY3pUMFJqTkU1Nlp6TlBSR00wVG5wbk0wOUVZelJPZW1jelQwUlNhMDVFYXpCT1JGRjVUa2RWTUU5RVRYbE5lbWN5VDFSWk5VNXRXVEpQVkdONlRtMUZNVTFFWXpWT2VtY3pUMFJqTkU1Nlp6TlBSR00wVG5wbk0wOUVZelJPZW1jelQwUmpORTU2WnpOUFJHTTBUbnBuSWl3aWNISnZkbWxrWlhJaU9pSm1ZV3RsWEc0aWZRIl19","eat_nonce":"TUlEQk5IMjhpaW9pc2pQeXh4eHh4eHh4eHh4eHh4eHhNSURCTkgyOGlpb2lzalB5eHh4eHh4eHh4eHh4eHh4eA","eat_profile":"tag:github.com,2024:veraison/ratsd"}
```

To request the CBOR token defined as token v2 in `docs/ratsd-token.cddl`, set `"token-version": 2` in the request body. The response body is raw CBOR:
```bash
$ curl -X POST http://localhost:8895/ratsd/chares \
-H 'Content-type: application/vnd.veraison.chares+json' \
-H 'Accept: application/cmw+cbor; cmwct="tag:github.com,2026:veraison/ratsd/v2"' \
-d '{"nonce": "TUlEQk5IMjhpaW9pc2pQeXh4eHh4eHh4eHh4eHh4eHhNSURCTkgyOGlpb2lzalB5eHh4eHh4eHh4eHh4eHh4eA", "token-version": 2}' \
--output ratsd-token-v2.cbor
```
## Get available attesters
Use endpoint `GET /ratsd/subattesters` to query all available leaf attesters and their available options. The usage can be found in the following
```console
Expand Down
44 changes: 26 additions & 18 deletions api/api.gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

115 changes: 97 additions & 18 deletions api/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ import (
"net/http"

"github.com/moogar0880/problems"
"github.com/veraison/cmw"
"github.com/veraison/ratsd/plugin"
"github.com/veraison/ratsd/proto/compositor"
"github.com/veraison/ratsd/tokens"
"go.uber.org/zap"
)

Expand All @@ -23,9 +23,11 @@ const (
)

type Server struct {
logger *zap.SugaredLogger
manager plugin.IManager
options string
logger *zap.SugaredLogger
manager plugin.IManager
options string
certPath string
certKeyPath string
}

func responseCodeToHTTP(responseCode uint32) int {
Expand All @@ -48,6 +50,13 @@ func NewServer(logger *zap.SugaredLogger, manager plugin.IManager, options strin
}
}

func NewServerWithSigner(logger *zap.SugaredLogger, manager plugin.IManager, options, certPath, certKeyPath string) *Server {
s := NewServer(logger, manager, options)
s.certPath = certPath
s.certKeyPath = certKeyPath
return s
}

func (s *Server) reportProblem(w http.ResponseWriter, prob *problems.DefaultProblem) {
s.logger.Error(prob.Detail)
w.Header().Set("Content-Type", problems.ProblemMediaType)
Expand All @@ -70,7 +79,18 @@ func (s *Server) RatsdChares(w http.ResponseWriter, r *http.Request, param Ratsd
return
}

respCt := fmt.Sprintf(`application/eat-ucs+json; eat_profile=%q`, TagGithubCom2024Veraisonratsd)
payload, _ := io.ReadAll(r.Body)

tokenVersion := tokens.RATSDTokenVersionLegacy
var tokenVersionProbe struct {
TokenVersion *int `json:"token-version,omitempty"`
}
if len(payload) > 0 {
if err := json.Unmarshal(payload, &tokenVersionProbe); err == nil && tokenVersionProbe.TokenVersion != nil {
tokenVersion = *tokenVersionProbe.TokenVersion
}
}
respCt := tokens.ResponseMediaType(tokenVersion)
if param.Accept != nil {
s.logger.Info("request media type: ", *(param.Accept))
if *(param.Accept) != respCt && *(param.Accept) != "*/*" {
Expand All @@ -82,7 +102,6 @@ func (s *Server) RatsdChares(w http.ResponseWriter, r *http.Request, param Ratsd
}
}

payload, _ := io.ReadAll(r.Body)
requestFields := make(map[string]json.RawMessage)
err := json.Unmarshal(payload, &requestFields)
if err != nil {
Expand Down Expand Up @@ -124,6 +143,33 @@ func (s *Server) RatsdChares(w http.ResponseWriter, r *http.Request, param Ratsd
}
delete(requestFields, "nonce")

if rawTokenVersion, ok := requestFields["token-version"]; ok {
if err := json.Unmarshal(rawTokenVersion, &tokenVersion); err != nil {
errMsg := "fail to retrieve token-version from the request"
p := &problems.DefaultProblem{
Type: string(TagGithubCom2024VeraisonratsdErrorInvalidrequest),
Title: string(InvalidRequest),
Detail: errMsg,
Status: http.StatusBadRequest,
}
s.reportProblem(w, p)
return
}
delete(requestFields, "token-version")
}
if tokenVersion != tokens.RATSDTokenVersionLegacy &&
tokenVersion != tokens.RATSDTokenVersionV2 {
errMsg := fmt.Sprintf("unsupported token version %d", tokenVersion)
p := &problems.DefaultProblem{
Type: string(TagGithubCom2024VeraisonratsdErrorInvalidrequest),
Title: string(InvalidRequest),
Detail: errMsg,
Status: http.StatusBadRequest,
}
s.reportProblem(w, p)
return
}

selectedAttesters := []string{}
hasSelection := false
if rawSelection, ok := requestFields["attester-selection"]; ok {
Expand Down Expand Up @@ -168,13 +214,34 @@ func (s *Server) RatsdChares(w http.ResponseWriter, r *http.Request, param Ratsd
return
}
s.logger.Info("request nonce: ", requestNonce)
s.logger.Info("request media type: ", *(param.Accept))

// Use a map until we finalize ratsd output format
eat := make(map[string]interface{})
collection := cmw.NewCollection("tag:github.com,2025:veraison/ratsd/cmw")
eat["eat_profile"] = TagGithubCom2024Veraisonratsd
eat["eat_nonce"] = requestNonce
evidenceOptions := []tokens.EvidenceOption{}
if tokenVersion == tokens.RATSDTokenVersionV2 {
evidenceOptions = append(evidenceOptions, tokens.WithSignerPaths(s.certPath, s.certKeyPath))
}

evidence, err := tokens.NewEvidence(tokenVersion, evidenceOptions...)
if err != nil {
p := &problems.DefaultProblem{
Type: string(TagGithubCom2024VeraisonratsdErrorInvalidrequest),
Title: string(InvalidRequest),
Detail: err.Error(),
Status: http.StatusBadRequest,
}
s.reportProblem(w, p)
return
}
if err := evidence.AddNonce(nonce); err != nil {
p := &problems.DefaultProblem{
Type: string(TagGithubCom2024VeraisonratsdErrorInvalidrequest),
Title: string(InvalidRequest),
Detail: err.Error(),
Status: http.StatusBadRequest,
}
s.reportProblem(w, p)
return
}

pl := s.manager.GetPluginList()
if len(pl) == 0 {
errMsg := "no sub-attester available"
Expand Down Expand Up @@ -264,8 +331,12 @@ func (s *Server) RatsdChares(w http.ResponseWriter, r *http.Request, param Ratsd
return false
}

c := cmw.NewMonad(in.ContentType, out.Evidence)
collection.AddCollectionItem(pn, c)
if err := evidence.AddToken(pn, in.ContentType, out.Evidence); err != nil {
errMsg := err.Error()
p := problems.NewDetailedProblem(http.StatusInternalServerError, errMsg)
s.reportProblem(w, p)
return false
}
return true
}

Expand All @@ -288,17 +359,25 @@ func (s *Server) RatsdChares(w http.ResponseWriter, r *http.Request, param Ratsd
}
}

serialized, err := collection.MarshalJSON()
token, err := evidence.Marshal()
if err != nil {
errMsg := fmt.Sprintf("failed to serialize CMW collection: %s", err.Error())
if tokenVersion == tokens.RATSDTokenVersionV2 {
errMsg := fmt.Sprintf("failed to create token version 2: %s", err.Error())
p := problems.NewDetailedProblem(http.StatusInternalServerError, errMsg)
s.reportProblem(w, p)
return
}

errMsg := fmt.Sprintf("failed to serialize legacy token: %s", err.Error())
p := problems.NewDetailedProblem(http.StatusInternalServerError, errMsg)
s.reportProblem(w, p)
return
}
eat["cmw"] = serialized
w.Header().Set("Content-Type", respCt)
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(eat)
if _, err := w.Write(token); err != nil {
s.logger.Error("failed to write token response: ", err)
}
}

func (s *Server) RatsdSubattesters(w http.ResponseWriter, r *http.Request) {
Expand Down
Loading
Loading