diff --git a/lxd/certificates.go b/lxd/certificates.go index b0643cf31705..02937913709b 100644 --- a/lxd/certificates.go +++ b/lxd/certificates.go @@ -1,6 +1,7 @@ package main import ( + "bytes" "context" "crypto/rsa" "crypto/x509" @@ -449,9 +450,26 @@ func certificatesPost(d *Daemon, r *http.Request) response.Response { return response.Forbidden(fmt.Errorf("No matching certificate add operation found")) } - tokenReq, ok := joinOp.Metadata["request"].(api.CertificatesPost) + tokenReqAny, ok := joinOp.Metadata["request"] if !ok { - return response.InternalError(fmt.Errorf("Bad certificate add operation data")) + return response.InternalError(fmt.Errorf(`Missing "request" key in certificate add operation data`)) + } + + tokenReq, ok := tokenReqAny.(api.CertificatesPost) + if !ok { + // If the operation is running on another member, the returned metadata will have been unmarshalled + // into a map[string]any. Rather than wrangling type assertions, just marshal and unmarshal the data into + // the correct type. + buf := bytes.NewBuffer(nil) + err := json.NewEncoder(buf).Encode(tokenReqAny) + if err != nil { + return response.InternalError(fmt.Errorf("Bad certificate add operation data: %w", err)) + } + + err = json.NewDecoder(buf).Decode(&tokenReq) + if err != nil { + return response.InternalError(fmt.Errorf("Bad certificate add operation data: %w", err)) + } } // Create a new request from the token data as the user isn't allowed to override anything.