From 3964125d47dedcfb068429dd130b6aa4610bf627 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Wed, 22 Jul 2020 13:04:05 -0700 Subject: [PATCH] Fix unmarshaling of Subject and Issuer. --- x509util/name.go | 24 +++++++++- x509util/name_test.go | 100 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 123 insertions(+), 1 deletion(-) diff --git a/x509util/name.go b/x509util/name.go index abfdf29e..f290de63 100644 --- a/x509util/name.go +++ b/x509util/name.go @@ -23,7 +23,7 @@ type Name struct { } // UnmarshalJSON implements the json.Unmarshal interface and unmarshals a JSON -// object in the Subject struct or a string as just the subject common name. +// object in the Name struct or a string as just the subject common name. func (n *Name) UnmarshalJSON(data []byte) error { if cn, ok := maybeString(data); ok { n.CommonName = cn @@ -56,6 +56,17 @@ func newSubject(n pkix.Name) Subject { } } +// UnmarshalJSON implements the json.Unmarshal interface and unmarshals a JSON +// object in the Subject struct or a string as just the subject common name. +func (s *Subject) UnmarshalJSON(data []byte) error { + var name Name + if err := name.UnmarshalJSON(data); err != nil { + return err + } + *s = Subject(name) + return nil +} + // Set sets the subject in the given certificate. func (s Subject) Set(c *x509.Certificate) { c.Subject = pkix.Name{ @@ -89,6 +100,17 @@ func newIssuer(n pkix.Name) Issuer { } } +// UnmarshalJSON implements the json.Unmarshal interface and unmarshals a JSON +// object in the Issuer struct or a string as just the subject common name. +func (i *Issuer) UnmarshalJSON(data []byte) error { + var name Name + if err := name.UnmarshalJSON(data); err != nil { + return err + } + *i = Issuer(name) + return nil +} + // Set sets the issuer in the given certificate. func (i Issuer) Set(c *x509.Certificate) { c.Issuer = pkix.Name{ diff --git a/x509util/name_test.go b/x509util/name_test.go index 1000f19a..e2c88a46 100644 --- a/x509util/name_test.go +++ b/x509util/name_test.go @@ -97,6 +97,56 @@ func Test_newSubject(t *testing.T) { } } +func TestSubject_UnmarshalJSON(t *testing.T) { + type args struct { + data []byte + } + tests := []struct { + name string + args args + want Subject + wantErr bool + }{ + {"null", args{[]byte("null")}, Subject{}, false}, + {"empty", args{[]byte("{}")}, Subject{}, false}, + {"commonName", args{[]byte(`"commonName"`)}, Subject{CommonName: "commonName"}, false}, + {"object", args{[]byte(`{ + "country": "The country", + "organization": "The organization", + "organizationalUnit": ["The organizationalUnit 1", "The organizationalUnit 2"], + "locality": ["The locality 1", "The locality 2"], + "province": "The province", + "streetAddress": "The streetAddress", + "postalCode": "The postalCode", + "serialNumber": "The serialNumber", + "commonName": "The commonName" + }`)}, Subject{ + Country: []string{"The country"}, + Organization: []string{"The organization"}, + OrganizationalUnit: []string{"The organizationalUnit 1", "The organizationalUnit 2"}, + Locality: []string{"The locality 1", "The locality 2"}, + Province: []string{"The province"}, + StreetAddress: []string{"The streetAddress"}, + PostalCode: []string{"The postalCode"}, + SerialNumber: "The serialNumber", + CommonName: "The commonName", + }, false}, + {"number", args{[]byte("1234")}, Subject{}, true}, + {"badJSON", args{[]byte("'badJSON'")}, Subject{}, true}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + var got Subject + if err := got.UnmarshalJSON(tt.args.data); (err != nil) != tt.wantErr { + t.Errorf("Subject.UnmarshalJSON() error = %v, wantErr %v", err, tt.wantErr) + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("Subject.UnmarshalJSON() = %v, want %v", got, tt.want) + } + }) + } +} + func TestSubject_Set(t *testing.T) { type fields struct { Country MultiString @@ -210,6 +260,56 @@ func Test_newIssuer(t *testing.T) { } } +func TestIssuer_UnmarshalJSON(t *testing.T) { + type args struct { + data []byte + } + tests := []struct { + name string + args args + want Issuer + wantErr bool + }{ + {"null", args{[]byte("null")}, Issuer{}, false}, + {"empty", args{[]byte("{}")}, Issuer{}, false}, + {"commonName", args{[]byte(`"commonName"`)}, Issuer{CommonName: "commonName"}, false}, + {"object", args{[]byte(`{ + "country": "The country", + "organization": "The organization", + "organizationalUnit": ["The organizationalUnit 1", "The organizationalUnit 2"], + "locality": ["The locality 1", "The locality 2"], + "province": "The province", + "streetAddress": "The streetAddress", + "postalCode": "The postalCode", + "serialNumber": "The serialNumber", + "commonName": "The commonName" + }`)}, Issuer{ + Country: []string{"The country"}, + Organization: []string{"The organization"}, + OrganizationalUnit: []string{"The organizationalUnit 1", "The organizationalUnit 2"}, + Locality: []string{"The locality 1", "The locality 2"}, + Province: []string{"The province"}, + StreetAddress: []string{"The streetAddress"}, + PostalCode: []string{"The postalCode"}, + SerialNumber: "The serialNumber", + CommonName: "The commonName", + }, false}, + {"number", args{[]byte("1234")}, Issuer{}, true}, + {"badJSON", args{[]byte("'badJSON'")}, Issuer{}, true}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + var got Issuer + if err := got.UnmarshalJSON(tt.args.data); (err != nil) != tt.wantErr { + t.Errorf("Issuer.UnmarshalJSON() error = %v, wantErr %v", err, tt.wantErr) + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("Issuer.UnmarshalJSON() = %v, want %v", got, tt.want) + } + }) + } +} + func TestIssuer_Set(t *testing.T) { type fields struct { Country MultiString