Merge pull request #61 from passbolt/v5-fix-jsonschema
Some checks failed
Go / test (push) Has been cancelled

V5 fix jsonschema
This commit is contained in:
Samuel Lorch 2025-08-18 15:08:24 +02:00 committed by GitHub
commit 58240d4bc1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 60 additions and 69 deletions

View file

@ -17,8 +17,8 @@ type ResourceType struct {
} }
type ResourceTypeSchema struct { type ResourceTypeSchema struct {
Resource json.RawMessage `json:"resource"` Resource map[string]any `json:"resource"`
Secret json.RawMessage `json:"secret"` Secret map[string]any `json:"secret"`
} }
// GetResourceTypesOptions is a placeholder for future options // GetResourceTypesOptions is a placeholder for future options

14
go.mod
View file

@ -3,16 +3,16 @@ module github.com/passbolt/go-passbolt
go 1.23.0 go 1.23.0
require ( require (
github.com/ProtonMail/gopenpgp/v3 v3.1.3 github.com/ProtonMail/gopenpgp/v3 v3.3.0
github.com/google/go-querystring v1.1.0 github.com/google/go-querystring v1.1.0
github.com/google/uuid v1.6.0 github.com/google/uuid v1.6.0
github.com/santhosh-tekuri/jsonschema v1.2.4 github.com/santhosh-tekuri/jsonschema/v6 v6.0.2
) )
require ( require (
github.com/ProtonMail/go-crypto v1.1.6 // indirect github.com/ProtonMail/go-crypto v1.3.0 // indirect
github.com/cloudflare/circl v1.6.0 // indirect github.com/cloudflare/circl v1.6.1 // indirect
github.com/pkg/errors v0.9.1 // indirect golang.org/x/crypto v0.41.0 // indirect
golang.org/x/crypto v0.35.0 // indirect golang.org/x/sys v0.35.0 // indirect
golang.org/x/sys v0.30.0 // indirect golang.org/x/text v0.28.0 // indirect
) )

42
go.sum
View file

@ -1,29 +1,31 @@
github.com/ProtonMail/go-crypto v1.1.6 h1:ZcV+Ropw6Qn0AX9brlQLAUXfqLBc7Bl+f/DmNxpLfdw= github.com/ProtonMail/go-crypto v1.3.0 h1:ILq8+Sf5If5DCpHQp4PbZdS1J7HDFRXz/+xKBiRGFrw=
github.com/ProtonMail/go-crypto v1.1.6/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE= github.com/ProtonMail/go-crypto v1.3.0/go.mod h1:9whxjD8Rbs29b4XWbB8irEcE8KHMqaR2e7GWU1R+/PE=
github.com/ProtonMail/gopenpgp/v3 v3.1.3 h1:nxUd0Na4MeElx0sA1t6U8/IxmjmCv3MKnTJGhEUK+qY= github.com/ProtonMail/gopenpgp/v3 v3.3.0 h1:N6rHCH5PWwB6zSRMgRj1EbAMQHUAAHxH3Oo4KibsPwY=
github.com/ProtonMail/gopenpgp/v3 v3.1.3/go.mod h1:Ve9JYzwGau9DT0F9C9gsuEBU/T3Zbk0j1/+mPpWBogc= github.com/ProtonMail/gopenpgp/v3 v3.3.0/go.mod h1:J+iNPt0/5EO9wRt7Eit9dRUlzyu3hiGX3zId6iuaKOk=
github.com/cloudflare/circl v1.6.0 h1:cr5JKic4HI+LkINy2lg3W2jF8sHCVTBncJr5gIIq7qk= github.com/cloudflare/circl v1.6.1 h1:zqIqSPIndyBh1bjLVVDHMPpVKqp8Su/V+6MeDzzQBQ0=
github.com/cloudflare/circl v1.6.0/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs= github.com/cloudflare/circl v1.6.1/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI=
github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM= github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/santhosh-tekuri/jsonschema v1.2.4 h1:hNhW8e7t+H1vgY+1QeEQpveR6D4+OwKPXCfD2aieJis= github.com/santhosh-tekuri/jsonschema/v6 v6.0.2 h1:KRzFb2m7YtdldCEkzs6KqmJw4nqEVZGK7IN2kJkjTuQ=
github.com/santhosh-tekuri/jsonschema v1.2.4/go.mod h1:TEAUOeZSmIxTTuHatJzrvARHiuO9LYd+cIxzgEHCQI4= github.com/santhosh-tekuri/jsonschema/v6 v6.0.2/go.mod h1:JXeL+ps8p7/KNMjDQk3TCwPpBy0wYklyWTfbkIzdIFU=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs= golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4=
golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ= golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc=
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=
golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

View file

@ -1,15 +1,13 @@
package helper package helper
import ( import (
"bytes"
"context" "context"
"encoding/json" "encoding/json"
"fmt" "fmt"
"strings"
"github.com/ProtonMail/gopenpgp/v3/crypto" "github.com/ProtonMail/gopenpgp/v3/crypto"
"github.com/passbolt/go-passbolt/api" "github.com/passbolt/go-passbolt/api"
"github.com/santhosh-tekuri/jsonschema" "github.com/santhosh-tekuri/jsonschema/v6"
) )
func GetResourceMetadata(ctx context.Context, c *api.Client, resource *api.Resource, rType *api.ResourceType) (string, error) { func GetResourceMetadata(ctx context.Context, c *api.Client, resource *api.Resource, rType *api.ResourceType) (string, error) {
@ -75,7 +73,7 @@ func validateMetadata(rType *api.ResourceType, metadata string) error {
comp := jsonschema.NewCompiler() comp := jsonschema.NewCompiler()
err = comp.AddResource("metadata.json", bytes.NewReader(schemaDefinition.Resource)) err = comp.AddResource("metadata.json", schemaDefinition.Resource)
if err != nil { if err != nil {
return fmt.Errorf("Adding Json Schema: %w", err) return fmt.Errorf("Adding Json Schema: %w", err)
} }
@ -85,7 +83,13 @@ func validateMetadata(rType *api.ResourceType, metadata string) error {
return fmt.Errorf("Compiling Json Schema: %w", err) return fmt.Errorf("Compiling Json Schema: %w", err)
} }
err = schema.Validate(strings.NewReader(metadata)) var parsedMetadata map[string]any
err = json.Unmarshal([]byte(metadata), &parsedMetadata)
if err != nil {
return fmt.Errorf("Unmarshal Secret: %w", err)
}
err = schema.Validate(parsedMetadata)
if err != nil { if err != nil {
return fmt.Errorf("Validating Metadata with Schema: %w", err) return fmt.Errorf("Validating Metadata with Schema: %w", err)
} }

View file

@ -37,23 +37,24 @@ func GetResourceFromData(c *api.Client, resource api.Resource, secret api.Secret
ctx := context.TODO() ctx := context.TODO()
switch rType.Slug {
case "password-string":
var err error
pw, err = c.DecryptMessage(secret.Data)
if err != nil {
return "", "", "", "", "", "", fmt.Errorf("Decrypting Secret Data: %w", err)
}
name = resource.Name
username = resource.Username
uri = resource.URI
desc = resource.Description
case "password-and-description":
rawSecretData, err := c.DecryptMessage(secret.Data) rawSecretData, err := c.DecryptMessage(secret.Data)
if err != nil { if err != nil {
return "", "", "", "", "", "", fmt.Errorf("Decrypting Secret Data: %w", err) return "", "", "", "", "", "", fmt.Errorf("Decrypting Secret Data: %w", err)
} }
err = validateSecretData(&rType, rawSecretData)
if err != nil {
return "", "", "", "", "", "", fmt.Errorf("Validate Secret Data: %w", err)
}
switch rType.Slug {
case "password-string":
pw = rawSecretData
name = resource.Name
username = resource.Username
uri = resource.URI
desc = resource.Description
case "password-and-description":
var secretData api.SecretDataTypePasswordAndDescription var secretData api.SecretDataTypePasswordAndDescription
err = json.Unmarshal([]byte(rawSecretData), &secretData) err = json.Unmarshal([]byte(rawSecretData), &secretData)
if err != nil { if err != nil {
@ -65,11 +66,6 @@ func GetResourceFromData(c *api.Client, resource api.Resource, secret api.Secret
pw = secretData.Password pw = secretData.Password
desc = secretData.Description desc = secretData.Description
case "password-description-totp": case "password-description-totp":
rawSecretData, err := c.DecryptMessage(secret.Data)
if err != nil {
return "", "", "", "", "", "", fmt.Errorf("Decrypting Secret Data: %w", err)
}
var secretData api.SecretDataTypePasswordDescriptionTOTP var secretData api.SecretDataTypePasswordDescriptionTOTP
err = json.Unmarshal([]byte(rawSecretData), &secretData) err = json.Unmarshal([]byte(rawSecretData), &secretData)
if err != nil { if err != nil {
@ -103,11 +99,6 @@ func GetResourceFromData(c *api.Client, resource api.Resource, secret api.Secret
uri = metadata.URIs[0] uri = metadata.URIs[0]
} }
rawSecretData, err := c.DecryptMessage(secret.Data)
if err != nil {
return "", "", "", "", "", "", fmt.Errorf("Decrypting Secret Data: %w", err)
}
var secretData api.SecretDataTypeV5Default var secretData api.SecretDataTypeV5Default
err = json.Unmarshal([]byte(rawSecretData), &secretData) err = json.Unmarshal([]byte(rawSecretData), &secretData)
if err != nil { if err != nil {
@ -133,11 +124,6 @@ func GetResourceFromData(c *api.Client, resource api.Resource, secret api.Secret
uri = metadata.URIs[0] uri = metadata.URIs[0]
} }
rawSecretData, err := c.DecryptMessage(secret.Data)
if err != nil {
return "", "", "", "", "", "", fmt.Errorf("Decrypting Secret Data: %w", err)
}
var secretData api.SecretDataTypeV5DefaultWithTOTP var secretData api.SecretDataTypeV5DefaultWithTOTP
err = json.Unmarshal([]byte(rawSecretData), &secretData) err = json.Unmarshal([]byte(rawSecretData), &secretData)
if err != nil { if err != nil {
@ -166,11 +152,6 @@ func GetResourceFromData(c *api.Client, resource api.Resource, secret api.Secret
// Not available in the Secret // Not available in the Secret
desc = metadata.Description desc = metadata.Description
rawSecretData, err := c.DecryptMessage(secret.Data)
if err != nil {
return "", "", "", "", "", "", fmt.Errorf("Decrypting Secret Data: %w", err)
}
pw = rawSecretData pw = rawSecretData
case "v5-totp-standalone": case "v5-totp-standalone":
rawMetadata, err := GetResourceMetadata(ctx, c, &resource, &rType) rawMetadata, err := GetResourceMetadata(ctx, c, &resource, &rType)

View file

@ -1,13 +1,11 @@
package helper package helper
import ( import (
"bytes"
"encoding/json" "encoding/json"
"fmt" "fmt"
"strings"
"github.com/passbolt/go-passbolt/api" "github.com/passbolt/go-passbolt/api"
"github.com/santhosh-tekuri/jsonschema" "github.com/santhosh-tekuri/jsonschema/v6"
) )
func validateSecretData(rType *api.ResourceType, secretData string) error { func validateSecretData(rType *api.ResourceType, secretData string) error {
@ -54,7 +52,7 @@ func validateSecretData(rType *api.ResourceType, secretData string) error {
comp := jsonschema.NewCompiler() comp := jsonschema.NewCompiler()
err = comp.AddResource("secret.json", bytes.NewReader(schemaDefinition.Secret)) err = comp.AddResource("secret.json", schemaDefinition.Secret)
if err != nil { if err != nil {
return fmt.Errorf("Adding Json Schema: %w", err) return fmt.Errorf("Adding Json Schema: %w", err)
} }
@ -64,7 +62,13 @@ func validateSecretData(rType *api.ResourceType, secretData string) error {
return fmt.Errorf("Compiling Json Schema: %w", err) return fmt.Errorf("Compiling Json Schema: %w", err)
} }
err = schema.Validate(strings.NewReader(secretData)) var parsedSecretData map[string]any
err = json.Unmarshal([]byte(secretData), &parsedSecretData)
if err != nil {
return fmt.Errorf("Unmarshal Secret: %w", err)
}
err = schema.Validate(parsedSecretData)
if err != nil { if err != nil {
return fmt.Errorf("Validating Secret Data with Schema: %w", err) return fmt.Errorf("Validating Secret Data with Schema: %w", err)
} }