parsing objectGUID as human-readable string version
This commit is contained in:
parent
287a5d225a
commit
bbaa820278
1
go.mod
1
go.mod
@ -15,6 +15,7 @@ require (
|
|||||||
github.com/golang/mock v1.6.0
|
github.com/golang/mock v1.6.0
|
||||||
github.com/google/go-cmp v0.5.6
|
github.com/google/go-cmp v0.5.6
|
||||||
github.com/google/gofuzz v1.2.0
|
github.com/google/gofuzz v1.2.0
|
||||||
|
github.com/google/uuid v1.1.2 // indirect
|
||||||
github.com/gorilla/securecookie v1.1.1
|
github.com/gorilla/securecookie v1.1.1
|
||||||
github.com/gorilla/websocket v1.4.2
|
github.com/gorilla/websocket v1.4.2
|
||||||
github.com/onsi/ginkgo v1.13.0 // indirect
|
github.com/onsi/ginkgo v1.13.0 // indirect
|
||||||
|
@ -307,6 +307,7 @@ func (c *activeDirectoryWatcherController) validateUpstream(ctx context.Context,
|
|||||||
GroupNameAttribute: adUpstreamImpl.Spec().GroupSearch().GroupNameAttribute(),
|
GroupNameAttribute: adUpstreamImpl.Spec().GroupSearch().GroupNameAttribute(),
|
||||||
},
|
},
|
||||||
Dialer: c.ldapDialer,
|
Dialer: c.ldapDialer,
|
||||||
|
UIDAttributeParsingOverrides: []upstreamldap.AttributeParsingOverride{{AttributeName: "objectGUID", OverrideFunc: upstreamldap.MicrosoftUUIDFromBinary}},
|
||||||
}
|
}
|
||||||
|
|
||||||
conditions := upstreamwatchers.ValidateGenericLDAP(ctx, &adUpstreamImpl, c.secretInformer, c.validatedSecretVersionsCache, config)
|
conditions := upstreamwatchers.ValidateGenericLDAP(ctx, &adUpstreamImpl, c.secretInformer, c.validatedSecretVersionsCache, config)
|
||||||
|
@ -8,6 +8,7 @@ import (
|
|||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"reflect"
|
||||||
"sort"
|
"sort"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
@ -217,6 +218,7 @@ func TestActiveDirectoryUpstreamWatcherControllerSync(t *testing.T) {
|
|||||||
Filter: testGroupSearchFilter,
|
Filter: testGroupSearchFilter,
|
||||||
GroupNameAttribute: testGroupNameAttrName,
|
GroupNameAttribute: testGroupNameAttrName,
|
||||||
},
|
},
|
||||||
|
UIDAttributeParsingOverrides: []upstreamldap.AttributeParsingOverride{{AttributeName: "objectGUID", OverrideFunc: upstreamldap.MicrosoftUUIDFromBinary}},
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make a copy with targeted changes.
|
// Make a copy with targeted changes.
|
||||||
@ -531,6 +533,7 @@ func TestActiveDirectoryUpstreamWatcherControllerSync(t *testing.T) {
|
|||||||
Filter: testGroupSearchFilter,
|
Filter: testGroupSearchFilter,
|
||||||
GroupNameAttribute: testGroupNameAttrName,
|
GroupNameAttribute: testGroupNameAttrName,
|
||||||
},
|
},
|
||||||
|
UIDAttributeParsingOverrides: []upstreamldap.AttributeParsingOverride{{AttributeName: "objectGUID", OverrideFunc: upstreamldap.MicrosoftUUIDFromBinary}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
wantResultingUpstreams: []v1alpha1.ActiveDirectoryIdentityProvider{{
|
wantResultingUpstreams: []v1alpha1.ActiveDirectoryIdentityProvider{{
|
||||||
@ -588,6 +591,7 @@ func TestActiveDirectoryUpstreamWatcherControllerSync(t *testing.T) {
|
|||||||
Filter: testGroupSearchFilter,
|
Filter: testGroupSearchFilter,
|
||||||
GroupNameAttribute: testGroupNameAttrName,
|
GroupNameAttribute: testGroupNameAttrName,
|
||||||
},
|
},
|
||||||
|
UIDAttributeParsingOverrides: []upstreamldap.AttributeParsingOverride{{AttributeName: "objectGUID", OverrideFunc: upstreamldap.MicrosoftUUIDFromBinary}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
wantResultingUpstreams: []v1alpha1.ActiveDirectoryIdentityProvider{{
|
wantResultingUpstreams: []v1alpha1.ActiveDirectoryIdentityProvider{{
|
||||||
@ -645,6 +649,7 @@ func TestActiveDirectoryUpstreamWatcherControllerSync(t *testing.T) {
|
|||||||
Filter: testGroupSearchFilter,
|
Filter: testGroupSearchFilter,
|
||||||
GroupNameAttribute: testGroupNameAttrName,
|
GroupNameAttribute: testGroupNameAttrName,
|
||||||
},
|
},
|
||||||
|
UIDAttributeParsingOverrides: []upstreamldap.AttributeParsingOverride{{AttributeName: "objectGUID", OverrideFunc: upstreamldap.MicrosoftUUIDFromBinary}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
wantErr: controllerlib.ErrSyntheticRequeue.Error(),
|
wantErr: controllerlib.ErrSyntheticRequeue.Error(),
|
||||||
@ -701,6 +706,7 @@ func TestActiveDirectoryUpstreamWatcherControllerSync(t *testing.T) {
|
|||||||
Filter: testGroupSearchFilter,
|
Filter: testGroupSearchFilter,
|
||||||
GroupNameAttribute: testGroupNameAttrName,
|
GroupNameAttribute: testGroupNameAttrName,
|
||||||
},
|
},
|
||||||
|
UIDAttributeParsingOverrides: []upstreamldap.AttributeParsingOverride{{AttributeName: "objectGUID", OverrideFunc: upstreamldap.MicrosoftUUIDFromBinary}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
wantResultingUpstreams: []v1alpha1.ActiveDirectoryIdentityProvider{{
|
wantResultingUpstreams: []v1alpha1.ActiveDirectoryIdentityProvider{{
|
||||||
@ -824,6 +830,7 @@ func TestActiveDirectoryUpstreamWatcherControllerSync(t *testing.T) {
|
|||||||
Filter: testGroupSearchFilter,
|
Filter: testGroupSearchFilter,
|
||||||
GroupNameAttribute: testGroupNameAttrName,
|
GroupNameAttribute: testGroupNameAttrName,
|
||||||
},
|
},
|
||||||
|
UIDAttributeParsingOverrides: []upstreamldap.AttributeParsingOverride{{AttributeName: "objectGUID", OverrideFunc: upstreamldap.MicrosoftUUIDFromBinary}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
wantResultingUpstreams: []v1alpha1.ActiveDirectoryIdentityProvider{{
|
wantResultingUpstreams: []v1alpha1.ActiveDirectoryIdentityProvider{{
|
||||||
@ -943,6 +950,7 @@ func TestActiveDirectoryUpstreamWatcherControllerSync(t *testing.T) {
|
|||||||
Filter: testGroupSearchFilter,
|
Filter: testGroupSearchFilter,
|
||||||
GroupNameAttribute: testGroupNameAttrName,
|
GroupNameAttribute: testGroupNameAttrName,
|
||||||
},
|
},
|
||||||
|
UIDAttributeParsingOverrides: []upstreamldap.AttributeParsingOverride{{AttributeName: "objectGUID", OverrideFunc: upstreamldap.MicrosoftUUIDFromBinary}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
wantResultingUpstreams: []v1alpha1.ActiveDirectoryIdentityProvider{{
|
wantResultingUpstreams: []v1alpha1.ActiveDirectoryIdentityProvider{{
|
||||||
@ -992,6 +1000,7 @@ func TestActiveDirectoryUpstreamWatcherControllerSync(t *testing.T) {
|
|||||||
Filter: testGroupSearchFilter,
|
Filter: testGroupSearchFilter,
|
||||||
GroupNameAttribute: testGroupNameAttrName,
|
GroupNameAttribute: testGroupNameAttrName,
|
||||||
},
|
},
|
||||||
|
UIDAttributeParsingOverrides: []upstreamldap.AttributeParsingOverride{{AttributeName: "objectGUID", OverrideFunc: upstreamldap.MicrosoftUUIDFromBinary}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
wantResultingUpstreams: []v1alpha1.ActiveDirectoryIdentityProvider{{
|
wantResultingUpstreams: []v1alpha1.ActiveDirectoryIdentityProvider{{
|
||||||
@ -1181,6 +1190,7 @@ func TestActiveDirectoryUpstreamWatcherControllerSync(t *testing.T) {
|
|||||||
Filter: "(&(objectClass=group)(member:1.2.840.113556.1.4.1941:={}))",
|
Filter: "(&(objectClass=group)(member:1.2.840.113556.1.4.1941:={}))",
|
||||||
GroupNameAttribute: "sAMAccountName",
|
GroupNameAttribute: "sAMAccountName",
|
||||||
},
|
},
|
||||||
|
UIDAttributeParsingOverrides: []upstreamldap.AttributeParsingOverride{{AttributeName: "objectGUID", OverrideFunc: upstreamldap.MicrosoftUUIDFromBinary}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
wantResultingUpstreams: []v1alpha1.ActiveDirectoryIdentityProvider{{
|
wantResultingUpstreams: []v1alpha1.ActiveDirectoryIdentityProvider{{
|
||||||
@ -1230,6 +1240,7 @@ func TestActiveDirectoryUpstreamWatcherControllerSync(t *testing.T) {
|
|||||||
Filter: testGroupSearchFilter,
|
Filter: testGroupSearchFilter,
|
||||||
GroupNameAttribute: testGroupNameAttrName,
|
GroupNameAttribute: testGroupNameAttrName,
|
||||||
},
|
},
|
||||||
|
UIDAttributeParsingOverrides: []upstreamldap.AttributeParsingOverride{{AttributeName: "objectGUID", OverrideFunc: upstreamldap.MicrosoftUUIDFromBinary}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
wantResultingUpstreams: []v1alpha1.ActiveDirectoryIdentityProvider{{
|
wantResultingUpstreams: []v1alpha1.ActiveDirectoryIdentityProvider{{
|
||||||
@ -1278,6 +1289,7 @@ func TestActiveDirectoryUpstreamWatcherControllerSync(t *testing.T) {
|
|||||||
Filter: testGroupSearchFilter,
|
Filter: testGroupSearchFilter,
|
||||||
GroupNameAttribute: testGroupNameAttrName,
|
GroupNameAttribute: testGroupNameAttrName,
|
||||||
},
|
},
|
||||||
|
UIDAttributeParsingOverrides: []upstreamldap.AttributeParsingOverride{{AttributeName: "objectGUID", OverrideFunc: upstreamldap.MicrosoftUUIDFromBinary}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
wantResultingUpstreams: []v1alpha1.ActiveDirectoryIdentityProvider{{
|
wantResultingUpstreams: []v1alpha1.ActiveDirectoryIdentityProvider{{
|
||||||
@ -1326,6 +1338,7 @@ func TestActiveDirectoryUpstreamWatcherControllerSync(t *testing.T) {
|
|||||||
Filter: testGroupSearchFilter,
|
Filter: testGroupSearchFilter,
|
||||||
GroupNameAttribute: testGroupNameAttrName,
|
GroupNameAttribute: testGroupNameAttrName,
|
||||||
},
|
},
|
||||||
|
UIDAttributeParsingOverrides: []upstreamldap.AttributeParsingOverride{{AttributeName: "objectGUID", OverrideFunc: upstreamldap.MicrosoftUUIDFromBinary}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
wantResultingUpstreams: []v1alpha1.ActiveDirectoryIdentityProvider{{
|
wantResultingUpstreams: []v1alpha1.ActiveDirectoryIdentityProvider{{
|
||||||
@ -1561,7 +1574,20 @@ func TestActiveDirectoryUpstreamWatcherControllerSync(t *testing.T) {
|
|||||||
// The dialer that was passed in to the controller's constructor should always have been
|
// The dialer that was passed in to the controller's constructor should always have been
|
||||||
// passed through to the provider.
|
// passed through to the provider.
|
||||||
copyOfExpectedValueForResultingCache.Dialer = dialer
|
copyOfExpectedValueForResultingCache.Dialer = dialer
|
||||||
require.Equal(t, copyOfExpectedValueForResultingCache, actualIDP.GetConfig())
|
|
||||||
|
// function equality is awkward. Do the check for equality separately from the rest of the config.
|
||||||
|
expectedUIDAttributeParsingOverrides := copyOfExpectedValueForResultingCache.UIDAttributeParsingOverrides
|
||||||
|
actualConfig := actualIDP.GetConfig()
|
||||||
|
actualUIDAttributeParsingOverrides := actualConfig.UIDAttributeParsingOverrides
|
||||||
|
copyOfExpectedValueForResultingCache.UIDAttributeParsingOverrides = []upstreamldap.AttributeParsingOverride{}
|
||||||
|
actualConfig.UIDAttributeParsingOverrides = []upstreamldap.AttributeParsingOverride{}
|
||||||
|
|
||||||
|
require.Len(t, actualUIDAttributeParsingOverrides, 1)
|
||||||
|
require.Len(t, expectedUIDAttributeParsingOverrides, 1)
|
||||||
|
require.Equal(t, expectedUIDAttributeParsingOverrides[0].AttributeName, actualUIDAttributeParsingOverrides[0].AttributeName)
|
||||||
|
require.Equal(t, reflect.ValueOf(expectedUIDAttributeParsingOverrides[0].OverrideFunc).Pointer(), reflect.ValueOf(actualUIDAttributeParsingOverrides[0].OverrideFunc).Pointer())
|
||||||
|
|
||||||
|
require.Equal(t, copyOfExpectedValueForResultingCache, actualConfig)
|
||||||
}
|
}
|
||||||
|
|
||||||
actualUpstreams, err := fakePinnipedClient.IDPV1alpha1().ActiveDirectoryIdentityProviders(testNamespace).List(ctx, metav1.ListOptions{})
|
actualUpstreams, err := fakePinnipedClient.IDPV1alpha1().ActiveDirectoryIdentityProviders(testNamespace).List(ctx, metav1.ListOptions{})
|
||||||
|
@ -17,6 +17,8 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
|
|
||||||
"github.com/go-ldap/ldap/v3"
|
"github.com/go-ldap/ldap/v3"
|
||||||
"k8s.io/apiserver/pkg/authentication/authenticator"
|
"k8s.io/apiserver/pkg/authentication/authenticator"
|
||||||
"k8s.io/apiserver/pkg/authentication/user"
|
"k8s.io/apiserver/pkg/authentication/user"
|
||||||
@ -103,6 +105,15 @@ type ProviderConfig struct {
|
|||||||
|
|
||||||
// Dialer exists to enable testing. When nil, will use a default appropriate for production use.
|
// Dialer exists to enable testing. When nil, will use a default appropriate for production use.
|
||||||
Dialer LDAPDialer
|
Dialer LDAPDialer
|
||||||
|
|
||||||
|
// UIDAttributeParsingOverrides are mappings between an attribute name and a way to parse it when
|
||||||
|
// it comes out of LDAP.
|
||||||
|
UIDAttributeParsingOverrides []AttributeParsingOverride
|
||||||
|
}
|
||||||
|
|
||||||
|
type AttributeParsingOverride struct {
|
||||||
|
AttributeName string
|
||||||
|
OverrideFunc func([]byte) (string, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// UserSearchConfig contains information about how to search for users in the upstream LDAP IDP.
|
// UserSearchConfig contains information about how to search for users in the upstream LDAP IDP.
|
||||||
@ -610,6 +621,12 @@ func (p *Provider) getSearchResultAttributeRawValueEncoded(attributeName string,
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for _, override := range p.c.UIDAttributeParsingOverrides {
|
||||||
|
if attributeName == override.AttributeName {
|
||||||
|
return override.OverrideFunc(attributeValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return base64.RawURLEncoding.EncodeToString(attributeValue), nil
|
return base64.RawURLEncoding.EncodeToString(attributeValue), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -653,3 +670,16 @@ func (p *Provider) traceSearchBaseDiscoveryFailure(t *trace.Trace, err error) {
|
|||||||
t.Step("search base discovery failed",
|
t.Step("search base discovery failed",
|
||||||
trace.Field{Key: "reason", Value: err.Error()})
|
trace.Field{Key: "reason", Value: err.Error()})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func MicrosoftUUIDFromBinary(binaryUUID []byte) (string, error) {
|
||||||
|
uuidVal, err := uuid.FromBytes(binaryUUID) // start out with the RFC4122 version
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
// then swap it because AD stores the first 3 fields little-endian rather than the expected
|
||||||
|
// big-endian.
|
||||||
|
uuidVal[0], uuidVal[1], uuidVal[2], uuidVal[3] = uuidVal[3], uuidVal[2], uuidVal[1], uuidVal[0]
|
||||||
|
uuidVal[4], uuidVal[5] = uuidVal[5], uuidVal[4]
|
||||||
|
uuidVal[6], uuidVal[7] = uuidVal[7], uuidVal[6]
|
||||||
|
return uuidVal.String(), nil
|
||||||
|
}
|
||||||
|
@ -506,6 +506,64 @@ func TestEndUserAuthentication(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "override UID parsing to work with microsoft style objectGUIDs",
|
||||||
|
username: testUpstreamUsername,
|
||||||
|
password: testUpstreamPassword,
|
||||||
|
providerConfig: providerConfig(func(p *ProviderConfig) {
|
||||||
|
p.UIDAttributeParsingOverrides = []AttributeParsingOverride{{
|
||||||
|
AttributeName: "objectGUID",
|
||||||
|
OverrideFunc: MicrosoftUUIDFromBinary,
|
||||||
|
}}
|
||||||
|
p.UserSearch.UIDAttribute = "objectGUID"
|
||||||
|
}),
|
||||||
|
searchMocks: func(conn *mockldapconn.MockConn) {
|
||||||
|
conn.EXPECT().Bind(testBindUsername, testBindPassword).Times(1)
|
||||||
|
conn.EXPECT().Search(expectedUserSearch(func(r *ldap.SearchRequest) {
|
||||||
|
r.Attributes = []string{testUserSearchUsernameAttribute, "objectGUID"}
|
||||||
|
})).Return(&ldap.SearchResult{
|
||||||
|
Entries: []*ldap.Entry{
|
||||||
|
{
|
||||||
|
DN: testUserSearchResultDNValue,
|
||||||
|
Attributes: []*ldap.EntryAttribute{
|
||||||
|
ldap.NewEntryAttribute(testUserSearchUsernameAttribute, []string{testUserSearchResultUsernameAttributeValue}),
|
||||||
|
ldap.NewEntryAttribute("objectGUID", []string{"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x10\x11\x12\x13\x14\x15\x16"}),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}}, nil).Times(1)
|
||||||
|
conn.EXPECT().SearchWithPaging(expectedGroupSearch(nil), expectedGroupSearchPageSize).
|
||||||
|
Return(exampleGroupSearchResult, nil).Times(1)
|
||||||
|
conn.EXPECT().Close().Times(1)
|
||||||
|
},
|
||||||
|
bindEndUserMocks: func(conn *mockldapconn.MockConn) {
|
||||||
|
conn.EXPECT().Bind(testUserSearchResultDNValue, testUpstreamPassword).Times(1)
|
||||||
|
},
|
||||||
|
wantAuthResponse: expectedAuthResponse(func(r *user.DefaultInfo) {
|
||||||
|
r.UID = "04030201-0605-0807-0910-111213141516"
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "override UID parsing when the attribute name doesn't match what's returned does default parsing",
|
||||||
|
username: testUpstreamUsername,
|
||||||
|
password: testUpstreamPassword,
|
||||||
|
providerConfig: providerConfig(func(p *ProviderConfig) {
|
||||||
|
p.UIDAttributeParsingOverrides = []AttributeParsingOverride{{
|
||||||
|
AttributeName: "objectGUID",
|
||||||
|
OverrideFunc: MicrosoftUUIDFromBinary,
|
||||||
|
}}
|
||||||
|
}),
|
||||||
|
searchMocks: func(conn *mockldapconn.MockConn) {
|
||||||
|
conn.EXPECT().Bind(testBindUsername, testBindPassword).Times(1)
|
||||||
|
conn.EXPECT().Search(expectedUserSearch(nil)).Return(exampleUserSearchResult, nil).Times(1)
|
||||||
|
conn.EXPECT().SearchWithPaging(expectedGroupSearch(nil), expectedGroupSearchPageSize).
|
||||||
|
Return(exampleGroupSearchResult, nil).Times(1)
|
||||||
|
conn.EXPECT().Close().Times(1)
|
||||||
|
},
|
||||||
|
bindEndUserMocks: func(conn *mockldapconn.MockConn) {
|
||||||
|
conn.EXPECT().Bind(testUserSearchResultDNValue, testUpstreamPassword).Times(1)
|
||||||
|
},
|
||||||
|
wantAuthResponse: expectedAuthResponse(nil),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "when dial fails",
|
name: "when dial fails",
|
||||||
username: testUpstreamUsername,
|
username: testUpstreamUsername,
|
||||||
@ -1297,3 +1355,36 @@ func TestRealTLSDialing(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGetMicrosoftFormattedUUID(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
binaryUUID []byte
|
||||||
|
wantString string
|
||||||
|
wantErr string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "happy path",
|
||||||
|
binaryUUID: []byte("\x01\x02\x03\x04\x05\x06\x07\x08\x09\x10\x11\x12\x13\x14\x15\x16"),
|
||||||
|
wantString: "04030201-0605-0807-0910-111213141516",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "not the right length",
|
||||||
|
binaryUUID: []byte("2\xf8\xb0\xaa\xb6V\xb1D\x8b(\xee"),
|
||||||
|
wantErr: "invalid UUID (got 11 bytes)",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
tt := test
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
actualUUIDString, err := MicrosoftUUIDFromBinary(tt.binaryUUID)
|
||||||
|
if tt.wantErr != "" {
|
||||||
|
require.EqualError(t, err, tt.wantErr)
|
||||||
|
} else {
|
||||||
|
require.NoError(t, err)
|
||||||
|
}
|
||||||
|
require.Equal(t, tt.wantString, actualUUIDString)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user