From bf86980e19d233fc93b10364a475a6ff0bf492ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Magnus=20B=C3=A4ck?= Date: Tue, 25 Jun 2024 16:49:52 +0200 Subject: [PATCH 1/2] signature: Make AuthorIdentity implement {Marshal,Unmarshal}Text This makes it easier to e.g. put AuthorIdentity values in configuration and API structs and have the values properly marshaled to/from string. Since the type has grown we extracted it to a file of its own to keep the clutter in verifier.go down. --- signature/authoridentity.go | 50 ++++++++++++++++++++++++++++++++ signature/authoridentity_test.go | 17 +++++++++++ signature/verifier.go | 30 ------------------- 3 files changed, 67 insertions(+), 30 deletions(-) create mode 100644 signature/authoridentity.go create mode 100644 signature/authoridentity_test.go diff --git a/signature/authoridentity.go b/signature/authoridentity.go new file mode 100644 index 0000000..a7fa696 --- /dev/null +++ b/signature/authoridentity.go @@ -0,0 +1,50 @@ +package signature + +import ( + "fmt" + + "github.com/go-ldap/ldap" +) + +// AuthorIdentity is a representation of the distinguished name +// in the meta.security.authorIdentity field of an Eiffel event. +// It can be compared to other values of the same type. +type AuthorIdentity struct { + dn *ldap.DN + original string +} + +func NewAuthorIdentity(s string) (*AuthorIdentity, error) { + dn, err := ldap.ParseDN(s) + if err != nil { + return nil, fmt.Errorf("error parsing author identity %q: %w", s, err) + } + return &AuthorIdentity{ + dn: dn, + original: s, + }, nil +} + +// Equal returns true if the provided *AuthorIdentity is equal to this one, +// igoring differences in whitespace etc. +func (ai AuthorIdentity) Equal(other *AuthorIdentity) bool { + return ai.dn.Equal(other.dn) +} + +func (ai AuthorIdentity) String() string { + return ai.original +} + +func (ai AuthorIdentity) MarshalText() (text []byte, err error) { + return []byte(ai.original), nil +} + +func (ai *AuthorIdentity) UnmarshalText(text []byte) error { + i, err := NewAuthorIdentity(string(text)) + if err != nil { + return err + } + ai.dn = i.dn + ai.original = i.original + return nil +} diff --git a/signature/authoridentity_test.go b/signature/authoridentity_test.go new file mode 100644 index 0000000..321bea6 --- /dev/null +++ b/signature/authoridentity_test.go @@ -0,0 +1,17 @@ +package signature + +import ( + "encoding/json" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestAuthorIdentity_UnmarshalText(t *testing.T) { + var data struct { + Identity *AuthorIdentity `json:"identity"` + } + require.NoError(t, json.Unmarshal([]byte(`{"identity": "CN=foo,DC=example,DC=com"}`), &data)) + assert.Equal(t, "CN=foo,DC=example,DC=com", data.Identity.String()) +} diff --git a/signature/verifier.go b/signature/verifier.go index 3dc2c13..2d36b2c 100644 --- a/signature/verifier.go +++ b/signature/verifier.go @@ -27,7 +27,6 @@ import ( "errors" "fmt" - "github.com/go-ldap/ldap" "github.com/gowebpki/jcs" "github.com/tidwall/gjson" "github.com/tidwall/sjson" @@ -44,35 +43,6 @@ type PublicKeyLocator interface { Locate(ctx context.Context, identity *AuthorIdentity) ([]crypto.PublicKey, error) } -// AuthorIdentity is a representation of the distinguished name -// in the meta.security.authorIdentity field of an Eiffel event. -// It can be compared to other values of the same type. -type AuthorIdentity struct { - dn *ldap.DN - original string -} - -func NewAuthorIdentity(s string) (*AuthorIdentity, error) { - dn, err := ldap.ParseDN(s) - if err != nil { - return nil, fmt.Errorf("error parsing author identity %q: %w", s, err) - } - return &AuthorIdentity{ - dn: dn, - original: s, - }, nil -} - -// Equal returns true if the provided *AuthorIdentity is equal to this one, -// igoring differences in whitespace etc. -func (ai *AuthorIdentity) Equal(other *AuthorIdentity) bool { - return ai.dn.Equal(other.dn) -} - -func (ai *AuthorIdentity) String() string { - return ai.original -} - // Verifier can verify whether the signature of a given Eiffel event matches // any of the keys known by the associated PublicKeyLocator. type Verifier struct { From da1580dc062378a29d4bac90e3b3d20bab576e72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Magnus=20B=C3=A4ck?= Date: Tue, 25 Jun 2024 22:27:13 +0200 Subject: [PATCH 2/2] Add missing copyright notices --- signature/authoridentity.go | 16 ++++++++++++++++ signature/authoridentity_test.go | 16 ++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/signature/authoridentity.go b/signature/authoridentity.go index a7fa696..fb9014c 100644 --- a/signature/authoridentity.go +++ b/signature/authoridentity.go @@ -1,3 +1,19 @@ +// Copyright Axis Communications AB. +// +// For a full list of individual contributors, please see the commit history. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package signature import ( diff --git a/signature/authoridentity_test.go b/signature/authoridentity_test.go index 321bea6..0a1ce10 100644 --- a/signature/authoridentity_test.go +++ b/signature/authoridentity_test.go @@ -1,3 +1,19 @@ +// Copyright Axis Communications AB. +// +// For a full list of individual contributors, please see the commit history. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package signature import (