2021-04-08 20:54:32 -04:00
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
2023-02-02 17:15:17 -08:00
2021-04-08 20:54:32 -04:00
package oidc
import (
"context"
"fmt"
"net/http"
"net/url"
"sort"
"testing"
"time"
"github.com/google/go-cmp/cmp"
"github.com/hashicorp/boundary/internal/auth/oidc/store"
"github.com/hashicorp/boundary/internal/db"
"github.com/hashicorp/boundary/internal/errors"
"github.com/hashicorp/boundary/internal/iam"
"github.com/hashicorp/boundary/internal/kms"
"github.com/hashicorp/boundary/internal/oplog"
"github.com/hashicorp/boundary/sdk/testutil"
"github.com/hashicorp/cap/oidc"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"google.golang.org/protobuf/testing/protocmp"
)
func Test_UpdateAuthMethod ( t * testing . T ) {
t . Parallel ()
ctx := context . Background ()
conn , _ := db . TestSetup ( t , "postgres" )
wrapper := db . TestWrapper ( t )
kmsCache := kms . TestKms ( t , conn , wrapper )
tp := oidc . StartTestProvider ( t )
tpClientId := "alice-rp"
tpClientSecret := "her-dog's-name"
tp . SetClientCreds ( tpClientId , tpClientSecret )
_ , _ , tpAlg , _ := tp . SigningKeys ()
2021-07-29 18:52:56 -06:00
tpCert , err := ParseCertificates ( ctx , tp . CACert ())
2021-04-08 20:54:32 -04:00
require . NoError ( t , err )
require . Equal ( t , 1 , len ( tpCert ))
rw := db . New ( conn )
2021-07-29 18:52:56 -06:00
repo , err := NewRepository ( ctx , rw , rw , kmsCache )
2021-04-08 20:54:32 -04:00
require . NoError ( t , err )
tests := [] struct {
name string
setup func () * AuthMethod
updateWith func ( orig * AuthMethod ) * AuthMethod
fieldMasks [] string
version uint32
opt [] Option
want func ( orig , updateWith * AuthMethod ) * AuthMethod
wantErrMatch * errors . Template
wantNoRowsUpdate bool
}{
{
name : "very-simple" ,
setup : func () * AuthMethod {
org , _ := iam . TestScopes ( t , iam . TestRepo ( t , conn , wrapper ))
databaseWrapper , err := kmsCache . GetWrapper ( context . Background (), org . PublicId , kms . KeyPurposeDatabase )
require . NoError ( t , err )
return TestAuthMethod ( t ,
conn , databaseWrapper ,
org . PublicId ,
InactiveState ,
"alice-rp" , "alice-secret" ,
WithCertificates ( tpCert [ 0 ]),
WithSigningAlgs ( Alg ( tpAlg )),
2021-04-28 06:53:13 -04:00
WithClaimsScopes ( "email" , "profile" ),
2021-05-04 08:41:04 -04:00
WithAccountClaimMap ( map [ string ] AccountToClaim { "display_name" : "name" }),
2021-04-08 20:54:32 -04:00
WithApiUrl ( TestConvertToUrls ( t , "https://www.alice.com/callback" )[ 0 ]),
)
},
updateWith : func ( orig * AuthMethod ) * AuthMethod {
am := AllocAuthMethod ()
am . PublicId = orig . PublicId
am . Name = "alice's restaurant"
am . Description = "the best place to eat"
am . AudClaims = [] string { "www.alice.com" , "www.alice.com/admin" }
2021-04-09 15:33:21 -04:00
am . ClientSecret = "This is a new secret"
2021-05-04 08:41:04 -04:00
am . AccountClaimMaps = [] string { "preferred_name=name" }
2021-04-08 20:54:32 -04:00
return & am
},
2021-05-04 08:41:04 -04:00
fieldMasks : [] string { NameField , DescriptionField , AudClaimsField , ClientSecretField , AccountClaimMapsField },
2021-04-08 20:54:32 -04:00
version : 1 ,
want : func ( orig , updateWith * AuthMethod ) * AuthMethod {
am := orig . Clone ()
am . Name = updateWith . Name
am . Description = updateWith . Description
am . AudClaims = updateWith . AudClaims
2021-04-09 15:33:21 -04:00
am . ClientSecret = updateWith . ClientSecret
am . CtClientSecret = updateWith . CtClientSecret
am . ClientSecretHmac = updateWith . ClientSecretHmac
2021-05-04 08:41:04 -04:00
am . AccountClaimMaps = updateWith . AccountClaimMaps
2021-04-08 20:54:32 -04:00
return am
},
},
{
name : "with-force-all-value-objects" ,
setup : func () * AuthMethod {
org , _ := iam . TestScopes ( t , iam . TestRepo ( t , conn , wrapper ))
databaseWrapper , err := kmsCache . GetWrapper ( context . Background (), org . PublicId , kms . KeyPurposeDatabase )
require . NoError ( t , err )
return TestAuthMethod ( t ,
conn , databaseWrapper ,
org . PublicId ,
InactiveState ,
"alice-rp" , "alice-secret" ,
WithAudClaims ( "www.alice.com" ),
WithCertificates ( tpCert [ 0 ]),
WithSigningAlgs ( Alg ( tpAlg )),
2021-04-28 06:53:13 -04:00
WithClaimsScopes ( "email" , "profile" ),
2021-04-08 20:54:32 -04:00
WithApiUrl ( TestConvertToUrls ( t , "https://www.alice.com/callback" )[ 0 ]),
)
},
updateWith : func ( orig * AuthMethod ) * AuthMethod {
_ , pem := testGenerateCA ( t , "127.0.0.1" )
am := AllocAuthMethod ()
am . PublicId = orig . PublicId
am . Name = "alice's restaurant"
am . Description = "the best place to eat"
am . ApiUrl = "https://www.bob.com/callback"
am . AudClaims = [] string { "www.alice.com/admin" }
am . SigningAlgs = [] string { string ( ES384 ), string ( ES512 )}
am . Certificates = [] string { pem }
2021-04-28 06:53:13 -04:00
am . ClaimsScopes = [] string { "custom-scope1" , "email" }
2021-04-08 20:54:32 -04:00
return & am
},
2021-04-28 06:53:13 -04:00
fieldMasks : [] string { NameField , DescriptionField , AudClaimsField , ApiUrlField , SigningAlgsField , CertificatesField , ClaimsScopesField },
2021-04-08 20:54:32 -04:00
version : 1 ,
opt : [] Option { WithForce ()},
want : func ( orig , updateWith * AuthMethod ) * AuthMethod {
am := orig . Clone ()
am . Name = updateWith . Name
am . Description = updateWith . Description
am . ApiUrl = updateWith . ApiUrl
am . AudClaims = updateWith . AudClaims
am . SigningAlgs = updateWith . SigningAlgs
am . Certificates = updateWith . Certificates
2021-04-28 06:53:13 -04:00
am . ClaimsScopes = updateWith . ClaimsScopes
2021-04-08 20:54:32 -04:00
am . DisableDiscoveredConfigValidation = true
return am
},
},
{
name : "null-name-description" ,
setup : func () * AuthMethod {
org , _ := iam . TestScopes ( t , iam . TestRepo ( t , conn , wrapper ))
databaseWrapper , err := kmsCache . GetWrapper ( context . Background (), org . PublicId , kms . KeyPurposeDatabase )
require . NoError ( t , err )
return TestAuthMethod ( t , conn , databaseWrapper , org . PublicId , InactiveState , "alice-rp" , "alice-secret" , WithName ( "alice's restaurant" ), WithDescription ( "the best place to eat" ), WithCertificates ( tpCert [ 0 ]), WithSigningAlgs ( Alg ( tpAlg )), WithApiUrl ( TestConvertToUrls ( t , "https://www.alice.com/callback" )[ 0 ]))
},
updateWith : func ( orig * AuthMethod ) * AuthMethod {
am := AllocAuthMethod ()
am . PublicId = orig . PublicId
am . Name = ""
am . Description = ""
return & am
},
2021-04-28 06:53:13 -04:00
fieldMasks : [] string { NameField , DescriptionField },
2021-04-08 20:54:32 -04:00
version : 1 ,
want : func ( orig , updateWith * AuthMethod ) * AuthMethod {
am := orig . Clone ()
am . Name = ""
am . Description = ""
return am
},
},
{
name : "null-signing-algs" ,
setup : func () * AuthMethod {
org , _ := iam . TestScopes ( t , iam . TestRepo ( t , conn , wrapper ))
databaseWrapper , err := kmsCache . GetWrapper ( context . Background (), org . PublicId , kms . KeyPurposeDatabase )
require . NoError ( t , err )
return TestAuthMethod ( t , conn , databaseWrapper , org . PublicId , InactiveState , "alice-rp" , "alice-secret" , WithCertificates ( tpCert [ 0 ]), WithSigningAlgs ( Alg ( tpAlg )), WithApiUrl ( TestConvertToUrls ( t , "https://www.alice.com/callback" )[ 0 ]))
},
updateWith : func ( orig * AuthMethod ) * AuthMethod {
am := AllocAuthMethod ()
am . PublicId = orig . PublicId
return & am
},
2021-04-28 06:53:13 -04:00
fieldMasks : [] string { SigningAlgsField },
2021-04-08 20:54:32 -04:00
version : 1 ,
want : func ( orig , updateWith * AuthMethod ) * AuthMethod {
am := orig . Clone ()
am . SigningAlgs = nil
return am
},
},
2021-04-28 06:53:13 -04:00
{
name : "null-claims-scope" ,
setup : func () * AuthMethod {
org , _ := iam . TestScopes ( t , iam . TestRepo ( t , conn , wrapper ))
databaseWrapper , err := kmsCache . GetWrapper ( context . Background (), org . PublicId , kms . KeyPurposeDatabase )
require . NoError ( t , err )
return TestAuthMethod ( t , conn , databaseWrapper , org . PublicId , InactiveState , "alice-rp" , "alice-secret" ,
WithCertificates ( tpCert [ 0 ]),
WithSigningAlgs ( Alg ( tpAlg )),
WithClaimsScopes ( "email" , "profile" ),
WithApiUrl ( TestConvertToUrls ( t , "https://www.alice.com/callback" )[ 0 ]))
},
updateWith : func ( orig * AuthMethod ) * AuthMethod {
am := AllocAuthMethod ()
am . PublicId = orig . PublicId
return & am
},
fieldMasks : [] string { ClaimsScopesField },
version : 1 ,
want : func ( orig , updateWith * AuthMethod ) * AuthMethod {
am := orig . Clone ()
am . ClaimsScopes = nil
return am
},
},
2021-04-08 20:54:32 -04:00
{
name : "change-callback-url" ,
setup : func () * AuthMethod {
org , _ := iam . TestScopes ( t , iam . TestRepo ( t , conn , wrapper ))
databaseWrapper , err := kmsCache . GetWrapper ( context . Background (), org . PublicId , kms . KeyPurposeDatabase )
require . NoError ( t , err )
return TestAuthMethod ( t , conn , databaseWrapper , org . PublicId , InactiveState , "alice-rp" , "alice-secret" , WithCertificates ( tpCert [ 0 ]), WithSigningAlgs ( Alg ( tpAlg )), WithApiUrl ( TestConvertToUrls ( t , "https://www.alice.com/callback" )[ 0 ]))
},
updateWith : func ( orig * AuthMethod ) * AuthMethod {
am := AllocAuthMethod ()
am . PublicId = orig . PublicId
am . ApiUrl = "https://www.updated.com/callback"
return & am
},
2021-04-28 06:53:13 -04:00
fieldMasks : [] string { ApiUrlField },
2021-04-08 20:54:32 -04:00
version : 1 ,
want : func ( orig , updateWith * AuthMethod ) * AuthMethod {
am := orig . Clone ()
am . ApiUrl = updateWith . ApiUrl
return am
},
},
{
name : "no-changes" ,
setup : func () * AuthMethod {
org , _ := iam . TestScopes ( t , iam . TestRepo ( t , conn , wrapper ))
databaseWrapper , err := kmsCache . GetWrapper ( context . Background (), org . PublicId , kms . KeyPurposeDatabase )
require . NoError ( t , err )
2021-04-28 06:53:13 -04:00
return TestAuthMethod ( t , conn , databaseWrapper , org . PublicId , InactiveState , "alice-rp" , "alice-secret" ,
WithCertificates ( tpCert [ 0 ]),
WithSigningAlgs ( Alg ( tpAlg )),
WithApiUrl ( TestConvertToUrls ( t , "https://www.alice.com/callback" )[ 0 ]))
2021-04-08 20:54:32 -04:00
},
updateWith : func ( orig * AuthMethod ) * AuthMethod {
am := AllocAuthMethod ()
am . PublicId = orig . PublicId
am . SigningAlgs = [] string { string ( tpAlg )}
return & am
},
2021-04-28 06:53:13 -04:00
fieldMasks : [] string { SigningAlgsField },
2021-04-08 20:54:32 -04:00
version : 1 ,
want : func ( orig , updateWith * AuthMethod ) * AuthMethod {
am := orig . Clone ()
return am
},
wantNoRowsUpdate : true ,
},
{
name : "inactive-not-complete-no-with-force" ,
setup : func () * AuthMethod {
org , _ := iam . TestScopes ( t , iam . TestRepo ( t , conn , wrapper ))
databaseWrapper , err := kmsCache . GetWrapper ( context . Background (), org . PublicId , kms . KeyPurposeDatabase )
require . NoError ( t , err )
return TestAuthMethod ( t , conn , databaseWrapper , org . PublicId , InactiveState , "alice-rp" , "alice-secret" , WithCertificates ( tpCert [ 0 ]), WithApiUrl ( TestConvertToUrls ( t , "https://www.alice.com/callback" )[ 0 ]))
},
updateWith : func ( orig * AuthMethod ) * AuthMethod {
am := AllocAuthMethod ()
am . PublicId = orig . PublicId
am . Name = "alice's restaurant"
am . Description = "the best place to eat"
am . AudClaims = [] string { "www.alice.com" , "www.alice.com/admin" }
return & am
},
2021-04-28 06:53:13 -04:00
fieldMasks : [] string { NameField , DescriptionField , AudClaimsField },
2021-04-08 20:54:32 -04:00
version : 1 ,
want : func ( orig , updateWith * AuthMethod ) * AuthMethod {
am := orig . Clone ()
am . Name = updateWith . Name
am . Description = updateWith . Description
am . AudClaims = updateWith . AudClaims
return am
},
},
{
name : "with-dry-run" ,
setup : func () * AuthMethod {
org , _ := iam . TestScopes ( t , iam . TestRepo ( t , conn , wrapper ))
databaseWrapper , err := kmsCache . GetWrapper ( context . Background (), org . PublicId , kms . KeyPurposeDatabase )
require . NoError ( t , err )
return TestAuthMethod ( t ,
conn , databaseWrapper ,
org . PublicId ,
InactiveState ,
"alice-rp" , "alice-secret" ,
WithAudClaims ( "www.alice.com" ),
WithCertificates ( tpCert [ 0 ]),
WithSigningAlgs ( Alg ( tpAlg )),
2021-04-28 06:53:13 -04:00
WithClaimsScopes ( "email" , "profile" ),
2021-04-08 20:54:32 -04:00
WithIssuer ( TestConvertToUrls ( t , tp . Addr ())[ 0 ]),
WithApiUrl ( TestConvertToUrls ( t , "https://www.alice.com/callback" )[ 0 ]),
)
},
updateWith : func ( orig * AuthMethod ) * AuthMethod {
am := AllocAuthMethod ()
am . PublicId = orig . PublicId
am . Name = "alice's restaurant"
am . Description = "the best place to eat"
am . AudClaims = [] string { "www.alice.com/admin" }
am . ApiUrl = "https://www.bob.com/callback"
2021-04-28 06:53:13 -04:00
am . ClaimsScopes = [] string { "custom-scope1" }
2021-04-08 20:54:32 -04:00
am . SigningAlgs = [] string { string ( ES384 ), string ( ES512 )}
return & am
},
2021-04-28 06:53:13 -04:00
fieldMasks : [] string { NameField , DescriptionField , AudClaimsField , ApiUrlField , SigningAlgsField , ClaimsScopesField },
2021-04-08 20:54:32 -04:00
version : 1 ,
opt : [] Option { WithDryRun ()},
want : func ( orig , updateWith * AuthMethod ) * AuthMethod {
am := orig . Clone ()
am . Name = updateWith . Name
am . Description = updateWith . Description
am . AudClaims = updateWith . AudClaims
am . ApiUrl = updateWith . ApiUrl
am . SigningAlgs = updateWith . SigningAlgs
2021-04-28 06:53:13 -04:00
am . ClaimsScopes = updateWith . ClaimsScopes
2021-04-08 20:54:32 -04:00
return am
},
wantErrMatch : errors . T ( errors . InvalidParameter ),
},
{
name : "with-dry-run-on-validated-authmethod" ,
setup : func () * AuthMethod {
org , _ := iam . TestScopes ( t , iam . TestRepo ( t , conn , wrapper ))
databaseWrapper , err := kmsCache . GetWrapper ( context . Background (), org . PublicId , kms . KeyPurposeDatabase )
require . NoError ( t , err )
return TestAuthMethod ( t ,
conn , databaseWrapper ,
org . PublicId ,
InactiveState ,
"alice-rp" , "alice-secret" ,
WithAudClaims ( "www.alice.com" ),
WithCertificates ( tpCert [ 0 ]),
WithSigningAlgs ( Alg ( tpAlg )),
2021-04-28 06:53:13 -04:00
WithClaimsScopes ( "email" , "profile" ),
2021-04-08 20:54:32 -04:00
WithIssuer ( TestConvertToUrls ( t , tp . Addr ())[ 0 ]),
WithApiUrl ( TestConvertToUrls ( t , "https://www.alice.com/callback" )[ 0 ]),
)
},
updateWith : func ( orig * AuthMethod ) * AuthMethod {
am := AllocAuthMethod ()
am . PublicId = orig . PublicId
am . Name = "alice's restaurant"
am . Description = "the best place to eat"
am . AudClaims = [] string { "www.alice.com/admin" }
am . ApiUrl = "https://www.bob.com/callback"
return & am
},
2021-04-28 06:53:13 -04:00
fieldMasks : [] string { NameField , DescriptionField , AudClaimsField , ApiUrlField },
2021-04-08 20:54:32 -04:00
version : 1 ,
opt : [] Option { WithDryRun ()},
want : func ( orig , updateWith * AuthMethod ) * AuthMethod {
am := orig . Clone ()
am . Name = updateWith . Name
am . Description = updateWith . Description
am . AudClaims = updateWith . AudClaims
am . ApiUrl = updateWith . ApiUrl
return am
},
},
2021-05-04 08:41:04 -04:00
{
name : "attempt-to-update-sub-account-claim-map" ,
setup : func () * AuthMethod {
org , _ := iam . TestScopes ( t , iam . TestRepo ( t , conn , wrapper ))
databaseWrapper , err := kmsCache . GetWrapper ( context . Background (), org . PublicId , kms . KeyPurposeDatabase )
require . NoError ( t , err )
return TestAuthMethod ( t ,
conn , databaseWrapper ,
org . PublicId ,
InactiveState ,
"alice-rp" , "alice-secret" ,
WithCertificates ( tpCert [ 0 ]),
WithSigningAlgs ( Alg ( tpAlg )),
WithClaimsScopes ( "email" , "profile" ),
WithAccountClaimMap ( map [ string ] AccountToClaim { "oid" : "sub" }),
WithApiUrl ( TestConvertToUrls ( t , "https://www.alice.com/callback" )[ 0 ]),
)
},
updateWith : func ( orig * AuthMethod ) * AuthMethod {
am := AllocAuthMethod ()
am . PublicId = orig . PublicId
am . AccountClaimMaps = [] string { "uid=sub" }
return & am
},
fieldMasks : [] string { AccountClaimMapsField },
version : 1 ,
wantErrMatch : errors . T ( errors . InvalidParameter ),
},
2021-04-08 20:54:32 -04:00
{
name : "nil-authMethod" ,
setup : func () * AuthMethod { return nil },
updateWith : func ( orig * AuthMethod ) * AuthMethod { return nil },
2021-04-28 06:53:13 -04:00
fieldMasks : [] string { NameField },
2021-04-08 20:54:32 -04:00
version : 1 ,
wantErrMatch : errors . T ( errors . InvalidParameter ),
},
{
name : "nil-authMethod-store" ,
setup : func () * AuthMethod { return nil },
updateWith : func ( orig * AuthMethod ) * AuthMethod { return & AuthMethod {} },
2021-04-28 06:53:13 -04:00
fieldMasks : [] string { NameField },
2021-04-08 20:54:32 -04:00
version : 1 ,
wantErrMatch : errors . T ( errors . InvalidParameter ),
},
{
name : "missing-public-id" ,
setup : func () * AuthMethod { return nil },
updateWith : func ( orig * AuthMethod ) * AuthMethod { a := AllocAuthMethod (); return & a },
2021-04-28 06:53:13 -04:00
fieldMasks : [] string { NameField },
2021-04-08 20:54:32 -04:00
version : 1 ,
wantErrMatch : errors . T ( errors . InvalidParameter ),
},
{
name : "bad-field-mask" ,
setup : func () * AuthMethod { return nil },
updateWith : func ( orig * AuthMethod ) * AuthMethod {
a := AllocAuthMethod ()
2021-07-29 18:52:56 -06:00
id , _ := newAuthMethodId ( ctx )
2021-04-08 20:54:32 -04:00
a . PublicId = id
return & a
},
fieldMasks : [] string { "CreateTime" },
version : 1 ,
wantErrMatch : errors . T ( errors . InvalidParameter ),
},
{
name : "no-mask-or-null-fields" ,
setup : func () * AuthMethod { return nil },
updateWith : func ( orig * AuthMethod ) * AuthMethod {
a := AllocAuthMethod ()
2021-07-29 18:52:56 -06:00
id , _ := newAuthMethodId ( ctx )
2021-04-08 20:54:32 -04:00
a . PublicId = id
return & a
},
version : 1 ,
wantErrMatch : errors . T ( errors . EmptyFieldMask ),
},
{
name : "not-found" ,
setup : func () * AuthMethod { return nil },
updateWith : func ( orig * AuthMethod ) * AuthMethod {
a := AllocAuthMethod ()
2021-07-29 18:52:56 -06:00
id , _ := newAuthMethodId ( ctx )
2021-04-08 20:54:32 -04:00
a . PublicId = id
return & a
},
2021-04-28 06:53:13 -04:00
fieldMasks : [] string { NameField },
2021-04-08 20:54:32 -04:00
version : 1 ,
wantErrMatch : errors . T ( errors . RecordNotFound ),
},
{
name : "bad-version" ,
setup : func () * AuthMethod {
org , _ := iam . TestScopes ( t , iam . TestRepo ( t , conn , wrapper ))
databaseWrapper , err := kmsCache . GetWrapper ( context . Background (), org . PublicId , kms . KeyPurposeDatabase )
require . NoError ( t , err )
return TestAuthMethod ( t , conn , databaseWrapper , org . PublicId , InactiveState , "alice-rp" , "alice-secret" , WithAudClaims ( "www.alice.com" ), WithCertificates ( tpCert [ 0 ]), WithSigningAlgs ( Alg ( tpAlg )), WithApiUrl ( TestConvertToUrls ( t , "https://www.alice.com/callback" )[ 0 ]))
},
updateWith : func ( orig * AuthMethod ) * AuthMethod {
am := AllocAuthMethod ()
am . PublicId = orig . PublicId
am . Name = "alice's restaurant"
return & am
},
2021-04-28 06:53:13 -04:00
fieldMasks : [] string { NameField },
2021-04-08 20:54:32 -04:00
version : 100 ,
wantErrMatch : errors . T ( errors . VersionMismatch ),
},
{
name : "not-valid-auth-method" ,
setup : func () * AuthMethod {
org , _ := iam . TestScopes ( t , iam . TestRepo ( t , conn , wrapper ))
databaseWrapper , err := kmsCache . GetWrapper ( context . Background (), org . PublicId , kms . KeyPurposeDatabase )
require . NoError ( t , err )
return TestAuthMethod ( t ,
conn , databaseWrapper ,
org . PublicId ,
InactiveState ,
"alice-rp" , "alice-secret" ,
WithAudClaims ( "www.alice.com" ),
WithCertificates ( tpCert [ 0 ]),
WithSigningAlgs ( Alg ( tpAlg )),
WithIssuer ( TestConvertToUrls ( t , tp . Addr ())[ 0 ]),
WithApiUrl ( TestConvertToUrls ( t , "https://www.alice.com/callback" )[ 0 ]),
)
},
updateWith : func ( orig * AuthMethod ) * AuthMethod {
am := AllocAuthMethod ()
am . PublicId = orig . PublicId
am . Name = "alice's restaurant"
am . Description = "the best place to eat"
am . SigningAlgs = [] string { string ( ES384 ), string ( ES512 )}
return & am
},
2021-04-28 06:53:13 -04:00
fieldMasks : [] string { NameField , DescriptionField , SigningAlgsField },
2021-04-08 20:54:32 -04:00
version : 1 ,
wantErrMatch : errors . T ( errors . InvalidParameter ),
},
{
name : "active-with-update-to-incomplete" ,
setup : func () * AuthMethod {
org , _ := iam . TestScopes ( t , iam . TestRepo ( t , conn , wrapper ))
databaseWrapper , err := kmsCache . GetWrapper ( context . Background (), org . PublicId , kms . KeyPurposeDatabase )
require . NoError ( t , err )
return TestAuthMethod ( t , conn , databaseWrapper , org . PublicId , ActivePublicState , "alice-rp" , "alice-secret" , WithCertificates ( tpCert [ 0 ]), WithSigningAlgs ( Alg ( tpAlg )), WithApiUrl ( TestConvertToUrls ( t , "https://www.alice.com/callback" )[ 0 ]))
},
updateWith : func ( orig * AuthMethod ) * AuthMethod {
am := AllocAuthMethod ()
am . PublicId = orig . PublicId
return & am
},
2021-04-28 06:53:13 -04:00
fieldMasks : [] string { SigningAlgsField },
2021-04-08 20:54:32 -04:00
version : 2 , // since TestAuthMethod(...) did an update to get it to ActivePublicState
wantErrMatch : errors . T ( errors . InvalidParameter ),
},
2023-11-21 11:30:02 -05:00
{
name : "update-with-prompt" ,
setup : func () * AuthMethod {
org , _ := iam . TestScopes ( t , iam . TestRepo ( t , conn , wrapper ))
databaseWrapper , err := kmsCache . GetWrapper ( context . Background (), org . PublicId , kms . KeyPurposeDatabase )
require . NoError ( t , err )
return TestAuthMethod (
t ,
conn ,
databaseWrapper ,
org . PublicId ,
InactiveState ,
"alice-rp" ,
"alice-secret" ,
WithCertificates ( tpCert [ 0 ]),
WithSigningAlgs ( Alg ( tpAlg )),
)
},
updateWith : func ( orig * AuthMethod ) * AuthMethod {
am := AllocAuthMethod ()
am . PublicId = orig . PublicId
am . Prompts = [] string { string ( SelectAccount )}
return & am
},
fieldMasks : [] string { PromptsField },
version : 1 ,
want : func ( orig , updateWith * AuthMethod ) * AuthMethod {
am := orig . Clone ()
am . Prompts = updateWith . Prompts
return am
},
},
{
name : "update-with-existing-prompt" ,
setup : func () * AuthMethod {
org , _ := iam . TestScopes ( t , iam . TestRepo ( t , conn , wrapper ))
databaseWrapper , err := kmsCache . GetWrapper ( context . Background (), org . PublicId , kms . KeyPurposeDatabase )
require . NoError ( t , err )
return TestAuthMethod (
t ,
conn ,
databaseWrapper ,
org . PublicId ,
InactiveState ,
"alice-rp" ,
"alice-secret" ,
WithCertificates ( tpCert [ 0 ]),
WithSigningAlgs ( Alg ( tpAlg )),
WithPrompts ( Consent ),
)
},
updateWith : func ( orig * AuthMethod ) * AuthMethod {
am := AllocAuthMethod ()
am . PublicId = orig . PublicId
am . Prompts = [] string { string ( SelectAccount )}
return & am
},
fieldMasks : [] string { PromptsField },
version : 1 ,
want : func ( orig , updateWith * AuthMethod ) * AuthMethod {
am := orig . Clone ()
am . Prompts = updateWith . Prompts
return am
},
},
2021-04-08 20:54:32 -04:00
}
for _ , tt := range tests {
t . Run ( tt . name , func ( t * testing . T ) {
assert , require := assert . New ( t ), require . New ( t )
orig := tt . setup ()
updateWith := tt . updateWith ( orig )
updated , rowsUpdated , err := repo . UpdateAuthMethod ( ctx , updateWith , tt . version , tt . fieldMasks , tt . opt ... )
opts := getOpts ( tt . opt ... )
if tt . wantErrMatch != nil && ! opts . withDryRun {
require . Error ( err )
assert . Equal ( 0 , rowsUpdated )
assert . Nil ( updated )
assert . Truef ( errors . Match ( tt . wantErrMatch , err ), "want err code: %q got: %q" , tt . wantErrMatch . Code , err )
if updateWith != nil && updateWith . AuthMethod != nil && updateWith . PublicId != "" {
err := db . TestVerifyOplog ( t , rw , updateWith . PublicId , db . WithOperation ( oplog . OpType_OP_TYPE_UPDATE ), db . WithCreateNotBefore ( 10 * time . Second ))
require . Errorf ( err , "should not have found oplog entry for %s" , updateWith . PublicId )
}
return
}
switch opts . withDryRun {
case true :
assert . Equal ( 0 , rowsUpdated )
switch tt . wantErrMatch != nil {
case true :
require . Error ( err )
default :
require . NoError ( err )
}
require . NotNil ( updated )
want := tt . want ( orig , updateWith )
want . CreateTime = orig . CreateTime
want . UpdateTime = orig . UpdateTime
want . Version = orig . Version
TestSortAuthMethods ( t , [] * AuthMethod { want , updated })
assert . Equal ( want , updated )
err := db . TestVerifyOplog ( t , rw , updateWith . PublicId , db . WithOperation ( oplog . OpType_OP_TYPE_UPDATE ), db . WithCreateNotBefore ( 10 * time . Second ))
require . Errorf ( err , "should not have found oplog entry for %s" , updateWith . PublicId )
default :
require . NoError ( err )
require . NotNil ( updated )
want := tt . want ( orig , updateWith )
want . CreateTime = updated . CreateTime
want . UpdateTime = updated . UpdateTime
want . Version = updated . Version
TestSortAuthMethods ( t , [] * AuthMethod { want , updated })
assert . Empty ( cmp . Diff ( updated . AuthMethod , want . AuthMethod , protocmp . Transform ()))
if ! tt . wantNoRowsUpdate {
assert . Equal ( 1 , rowsUpdated )
err = db . TestVerifyOplog ( t , rw , updateWith . PublicId , db . WithOperation ( oplog . OpType_OP_TYPE_UPDATE ), db . WithCreateNotBefore ( 10 * time . Second ))
require . NoErrorf ( err , "unexpected error verifying oplog entry: %s" , err )
}
2021-05-04 08:41:04 -04:00
found , err := repo . LookupAuthMethod ( ctx , want . PublicId )
require . NoError ( err )
TestSortAuthMethods ( t , [] * AuthMethod { found })
assert . Empty ( cmp . Diff ( found . AuthMethod , want . AuthMethod , protocmp . Transform ()))
2021-04-08 20:54:32 -04:00
}
})
}
}
func Test_DisableDiscoveredConfigValidation ( t * testing . T ) {
t . Parallel ()
assert , require := assert . New ( t ), require . New ( t )
ctx := context . Background ()
conn , _ := db . TestSetup ( t , "postgres" )
wrapper := db . TestWrapper ( t )
kmsCache := kms . TestKms ( t , conn , wrapper )
tp := oidc . StartTestProvider ( t )
tpClientId := "alice-rp"
tpClientSecret := "her-dog's-name"
tp . SetClientCreds ( tpClientId , tpClientSecret )
_ , _ , tpAlg , _ := tp . SigningKeys ()
2021-07-29 18:52:56 -06:00
tpCert , err := ParseCertificates ( ctx , tp . CACert ())
2021-04-08 20:54:32 -04:00
require . NoError ( err )
require . Equal ( 1 , len ( tpCert ))
rw := db . New ( conn )
2021-07-29 18:52:56 -06:00
repo , err := NewRepository ( ctx , rw , rw , kmsCache )
2021-04-08 20:54:32 -04:00
require . NoError ( err )
org , _ := iam . TestScopes ( t , iam . TestRepo ( t , conn , wrapper ))
databaseWrapper , err := kmsCache . GetWrapper ( context . Background (), org . PublicId , kms . KeyPurposeDatabase )
require . NoError ( err )
am := TestAuthMethod ( t ,
conn , databaseWrapper ,
org . PublicId ,
InactiveState ,
"alice-rp" , "alice-secret" ,
WithAudClaims ( "www.alice.com" ),
WithCertificates ( tpCert [ 0 ]),
WithSigningAlgs ( Alg ( tpAlg )),
WithIssuer ( TestConvertToUrls ( t , tp . Addr ())[ 0 ]),
WithApiUrl ( TestConvertToUrls ( t , "https://www.alice.com/callback" )[ 0 ]),
)
updateWith := am . Clone ()
updateWith . Name = "alice's restaurant"
2021-04-28 06:53:13 -04:00
updatedWithForce , rowsUpdated , err := repo . UpdateAuthMethod ( ctx , updateWith , updateWith . Version , [] string { NameField }, WithForce ())
2021-04-08 20:54:32 -04:00
require . NoError ( err )
assert . Equal ( 1 , rowsUpdated )
assert . Equal ( true , updatedWithForce . DisableDiscoveredConfigValidation )
updateWith . Name = "alice and eve's restaurant"
2021-04-28 06:53:13 -04:00
updatedWithoutForce , rowsUpdated , err := repo . UpdateAuthMethod ( ctx , updatedWithForce , updatedWithForce . Version , [] string { NameField })
2021-04-08 20:54:32 -04:00
require . NoError ( err )
assert . Equal ( 1 , rowsUpdated )
assert . Equal ( false , updatedWithoutForce . DisableDiscoveredConfigValidation )
privWithForce , err := repo . MakePrivate ( ctx , updatedWithForce . PublicId , updatedWithoutForce . Version , WithForce ())
require . NoError ( err )
assert . Equal ( true , privWithForce . DisableDiscoveredConfigValidation )
privWithoutForce , err := repo . MakePrivate ( ctx , privWithForce . PublicId , privWithForce . Version )
require . NoError ( err )
assert . Equal ( false , privWithoutForce . DisableDiscoveredConfigValidation )
pubWithForce , err := repo . MakePublic ( ctx , privWithoutForce . PublicId , privWithoutForce . Version , WithForce ())
require . NoError ( err )
assert . Equal ( true , pubWithForce . DisableDiscoveredConfigValidation )
pubWithoutForce , err := repo . MakePrivate ( ctx , pubWithForce . PublicId , pubWithForce . Version )
require . NoError ( err )
assert . Equal ( false , pubWithoutForce . DisableDiscoveredConfigValidation )
}
func Test_ValidateDiscoveryInfo ( t * testing . T ) {
// do not run these tests with t.Parallel()
ctx := context . Background ()
2024-09-19 08:55:27 -07:00
tp := oidc . StartTestProvider ( t , oidc . WithTestHost ( "::1" ))
2021-04-08 20:54:32 -04:00
tpClientId := "alice-rp"
tpClientSecret := "her-dog's-name"
tp . SetClientCreds ( tpClientId , tpClientSecret )
_ , _ , tpAlg , _ := tp . SigningKeys ()
2021-07-29 18:52:56 -06:00
tpCert , err := ParseCertificates ( ctx , tp . CACert ())
2021-04-08 20:54:32 -04:00
require . NoError ( t , err )
require . Equal ( t , 1 , len ( tpCert ))
conn , _ := db . TestSetup ( t , "postgres" )
wrapper := db . TestWrapper ( t )
kmsCache := kms . TestKms ( t , conn , wrapper )
org , _ := iam . TestScopes ( t , iam . TestRepo ( t , conn , wrapper ))
rw := db . New ( conn )
2021-07-29 18:52:56 -06:00
repo , err := NewRepository ( ctx , rw , rw , kmsCache )
2021-04-08 20:54:32 -04:00
require . NoError ( t , err )
databaseWrapper , err := kmsCache . GetWrapper ( context . Background (), org . PublicId , kms . KeyPurposeDatabase )
require . NoError ( t , err )
port := testutil . TestFreePort ( t )
2024-09-19 08:55:27 -07:00
testAuthMethodCallback , err := url . Parse ( fmt . Sprintf ( "http://[::1]:%d/callback" , port ))
2021-04-08 20:54:32 -04:00
require . NoError ( t , err )
testAuthMethod := TestAuthMethod ( t ,
conn , databaseWrapper ,
org . PublicId ,
ActivePrivateState ,
tpClientId , ClientSecret ( tpClientSecret ),
WithCertificates ( tpCert [ 0 ]),
WithSigningAlgs ( Alg ( tpAlg )),
WithIssuer ( TestConvertToUrls ( t , tp . Addr ())[ 0 ]),
WithApiUrl ( testAuthMethodCallback ),
)
tests := [] struct {
name string
setup func ()
cleanup func ()
authMethod * AuthMethod
withAuthMethod bool
withPublicId bool
wantErrMatch * errors . Template
wantErrContains string
}{
{
name : "simple-and-valid" ,
authMethod : testAuthMethod ,
withAuthMethod : true ,
},
{
name : "simple-and-valid" ,
authMethod : testAuthMethod ,
withPublicId : true ,
},
{
name : "missing-withPublicId-or-withAuthMethod" ,
authMethod : testAuthMethod ,
wantErrMatch : errors . T ( errors . InvalidParameter ),
},
{
name : "not-complete" ,
authMethod : func () * AuthMethod { cp := testAuthMethod . Clone (); cp . SigningAlgs = nil ; return cp }(),
withAuthMethod : true ,
wantErrMatch : errors . T ( errors . InvalidParameter ),
wantErrContains : " missing signing algorithms" ,
},
{
name : "no-discovery" ,
authMethod : func () * AuthMethod {
cp := testAuthMethod . Clone ()
port := testutil . TestFreePort ( t )
2024-09-19 08:55:27 -07:00
cp . Issuer = fmt . Sprintf ( "http://[::1]:%d" , port )
2021-04-08 20:54:32 -04:00
return cp
}(),
withAuthMethod : true ,
wantErrMatch : errors . T ( errors . InvalidParameter ),
wantErrContains : "AuthMethod cannot be converted to a valid OIDC Provider" ,
},
{
name : "fail-jwks" ,
setup : func () { tp . SetDisableJWKs ( true ) },
cleanup : func () { tp . SetDisableJWKs ( false ) },
authMethod : testAuthMethod ,
withAuthMethod : true ,
wantErrMatch : errors . T ( errors . Unknown ),
wantErrContains : "non-200" ,
},
}
for _ , tt := range tests {
t . Run ( tt . name , func ( t * testing . T ) {
assert , require := assert . New ( t ), require . New ( t )
var opts [] Option
switch {
case tt . withAuthMethod :
opts = append ( opts , WithAuthMethod ( tt . authMethod ))
case tt . withPublicId :
opts = append ( opts , WithPublicId ( tt . authMethod . PublicId ))
}
if tt . setup != nil {
tt . setup ()
defer tt . cleanup ()
}
err := repo . ValidateDiscoveryInfo ( ctx , opts ... )
if tt . wantErrMatch != nil {
require . Error ( err )
assert . Truef ( errors . Match ( tt . wantErrMatch , err ), "want err code: %q got: %q" , tt . wantErrMatch . Code , err )
if tt . wantErrContains != "" {
assert . Containsf ( err . Error (), tt . wantErrContains , "want err to contain %s got: %s" , tt . wantErrContains , err . Error ())
}
return
}
require . NoError ( err )
})
}
}
func Test_valueObjectChanges ( t * testing . T ) {
t . Parallel ()
2021-07-29 18:52:56 -06:00
ctx := context . TODO ()
2021-04-08 20:54:32 -04:00
_ , pem1 := testGenerateCA ( t , "localhost" )
_ , pem2 := testGenerateCA ( t , "127.0.0.1" )
_ , pem3 := testGenerateCA ( t , "www.example.com" )
tests := [] struct {
name string
id string
voName voName
new [] string
old [] string
dbMask [] string
nullFields [] string
2022-10-25 18:29:38 -05:00
wantAdd [] any
wantDel [] any
2021-04-08 20:54:32 -04:00
wantErrMatch * errors . Template
}{
{
name : string ( SigningAlgVO ),
id : "am-public-id" ,
voName : SigningAlgVO ,
new : [] string { "ES256" , "ES384" },
old : [] string { "RS256" , "RS384" , "RS512" },
dbMask : [] string { string ( SigningAlgVO )},
2022-10-25 18:29:38 -05:00
wantAdd : func () [] any {
2021-07-29 18:52:56 -06:00
a , err := NewSigningAlg ( ctx , "am-public-id" , ES256 )
2021-04-08 20:54:32 -04:00
require . NoError ( t , err )
2021-07-29 18:52:56 -06:00
a2 , err := NewSigningAlg ( ctx , "am-public-id" , ES384 )
2021-04-08 20:54:32 -04:00
require . NoError ( t , err )
2022-10-25 18:29:38 -05:00
return [] any { a , a2 }
2021-04-08 20:54:32 -04:00
}(),
2022-10-25 18:29:38 -05:00
wantDel : func () [] any {
2021-07-29 18:52:56 -06:00
a , err := NewSigningAlg ( ctx , "am-public-id" , RS256 )
2021-04-08 20:54:32 -04:00
require . NoError ( t , err )
2021-07-29 18:52:56 -06:00
a2 , err := NewSigningAlg ( ctx , "am-public-id" , RS384 )
2021-04-08 20:54:32 -04:00
require . NoError ( t , err )
2021-07-29 18:52:56 -06:00
a3 , err := NewSigningAlg ( ctx , "am-public-id" , RS512 )
2021-04-08 20:54:32 -04:00
require . NoError ( t , err )
2022-10-25 18:29:38 -05:00
return [] any { a , a2 , a3 }
2021-04-08 20:54:32 -04:00
}(),
},
{
name : string ( CertificateVO ),
id : "am-public-id" ,
voName : CertificateVO ,
new : [] string { pem1 , pem2 },
old : [] string { pem3 },
dbMask : [] string { string ( CertificateVO )},
2022-10-25 18:29:38 -05:00
wantAdd : func () [] any {
2021-07-29 18:52:56 -06:00
c , err := NewCertificate ( ctx , "am-public-id" , pem1 )
2021-04-08 20:54:32 -04:00
require . NoError ( t , err )
2021-07-29 18:52:56 -06:00
c2 , err := NewCertificate ( ctx , "am-public-id" , pem2 )
2021-04-08 20:54:32 -04:00
require . NoError ( t , err )
2022-10-25 18:29:38 -05:00
return [] any { c , c2 }
2021-04-08 20:54:32 -04:00
}(),
2022-10-25 18:29:38 -05:00
wantDel : func () [] any {
2021-07-29 18:52:56 -06:00
c , err := NewCertificate ( ctx , "am-public-id" , pem3 )
2021-04-08 20:54:32 -04:00
require . NoError ( t , err )
2022-10-25 18:29:38 -05:00
return [] any { c }
2021-04-08 20:54:32 -04:00
}(),
},
{
name : string ( AudClaimVO ),
id : "am-public-id" ,
voName : AudClaimVO ,
new : [] string { "new-aud1" , "new-aud2" },
old : [] string { "old-aud1" , "old-aud2" , "old-aud3" },
dbMask : [] string { string ( AudClaimVO )},
2022-10-25 18:29:38 -05:00
wantAdd : func () [] any {
2021-07-29 18:52:56 -06:00
a , err := NewAudClaim ( ctx , "am-public-id" , "new-aud1" )
2021-04-08 20:54:32 -04:00
require . NoError ( t , err )
2021-07-29 18:52:56 -06:00
a2 , err := NewAudClaim ( ctx , "am-public-id" , "new-aud2" )
2021-04-08 20:54:32 -04:00
require . NoError ( t , err )
2022-10-25 18:29:38 -05:00
return [] any { a , a2 }
2021-04-08 20:54:32 -04:00
}(),
2022-10-25 18:29:38 -05:00
wantDel : func () [] any {
2021-07-29 18:52:56 -06:00
a , err := NewAudClaim ( ctx , "am-public-id" , "old-aud1" )
2021-04-08 20:54:32 -04:00
require . NoError ( t , err )
2021-07-29 18:52:56 -06:00
a2 , err := NewAudClaim ( ctx , "am-public-id" , "old-aud2" )
2021-04-08 20:54:32 -04:00
require . NoError ( t , err )
2021-07-29 18:52:56 -06:00
a3 , err := NewAudClaim ( ctx , "am-public-id" , "old-aud3" )
2021-04-08 20:54:32 -04:00
require . NoError ( t , err )
2022-10-25 18:29:38 -05:00
return [] any { a , a2 , a3 }
2021-04-08 20:54:32 -04:00
}(),
},
{
name : string ( AudClaimVO ) + "-null-fields" ,
id : "am-public-id" ,
voName : AudClaimVO ,
new : nil ,
old : [] string { "old-aud1" , "old-aud2" , "old-aud3" },
nullFields : [] string { string ( AudClaimVO )},
2022-10-25 18:29:38 -05:00
wantDel : func () [] any {
2021-07-29 18:52:56 -06:00
a , err := NewAudClaim ( ctx , "am-public-id" , "old-aud1" )
2021-04-08 20:54:32 -04:00
require . NoError ( t , err )
2021-07-29 18:52:56 -06:00
a2 , err := NewAudClaim ( ctx , "am-public-id" , "old-aud2" )
2021-04-08 20:54:32 -04:00
require . NoError ( t , err )
2021-07-29 18:52:56 -06:00
a3 , err := NewAudClaim ( ctx , "am-public-id" , "old-aud3" )
2021-04-08 20:54:32 -04:00
require . NoError ( t , err )
2022-10-25 18:29:38 -05:00
return [] any { a , a2 , a3 }
2021-04-08 20:54:32 -04:00
}(),
},
2021-04-28 06:53:13 -04:00
{
name : string ( ClaimsScopesVO ),
id : "am-public-id" ,
voName : ClaimsScopesVO ,
new : [] string { "new-scope1" , "new-scope2" },
old : [] string { "old-scope1" , "old-scope2" , "old-scope3" },
dbMask : [] string { string ( ClaimsScopesVO )},
2022-10-25 18:29:38 -05:00
wantAdd : func () [] any {
2021-07-29 18:52:56 -06:00
cs , err := NewClaimsScope ( ctx , "am-public-id" , "new-scope1" )
2021-04-28 06:53:13 -04:00
require . NoError ( t , err )
2021-07-29 18:52:56 -06:00
cs2 , err := NewClaimsScope ( ctx , "am-public-id" , "new-scope2" )
2021-04-28 06:53:13 -04:00
require . NoError ( t , err )
2022-10-25 18:29:38 -05:00
return [] any { cs , cs2 }
2021-04-28 06:53:13 -04:00
}(),
2022-10-25 18:29:38 -05:00
wantDel : func () [] any {
2021-07-29 18:52:56 -06:00
cs , err := NewClaimsScope ( ctx , "am-public-id" , "old-scope1" )
2021-04-28 06:53:13 -04:00
require . NoError ( t , err )
2021-07-29 18:52:56 -06:00
cs2 , err := NewClaimsScope ( ctx , "am-public-id" , "old-scope2" )
2021-04-28 06:53:13 -04:00
require . NoError ( t , err )
2021-07-29 18:52:56 -06:00
cs3 , err := NewClaimsScope ( ctx , "am-public-id" , "old-scope3" )
2021-04-28 06:53:13 -04:00
require . NoError ( t , err )
2022-10-25 18:29:38 -05:00
return [] any { cs , cs2 , cs3 }
2021-04-28 06:53:13 -04:00
}(),
},
{
name : string ( ClaimsScopesVO ) + "-null-fields" ,
id : "am-public-id" ,
voName : ClaimsScopesVO ,
new : nil ,
old : [] string { "old-scope1" , "old-scope2" , "old-scope3" },
nullFields : [] string { string ( ClaimsScopesVO )},
2022-10-25 18:29:38 -05:00
wantDel : func () [] any {
2021-07-29 18:52:56 -06:00
cs , err := NewClaimsScope ( ctx , "am-public-id" , "old-scope1" )
2021-04-28 06:53:13 -04:00
require . NoError ( t , err )
2021-07-29 18:52:56 -06:00
cs2 , err := NewClaimsScope ( ctx , "am-public-id" , "old-scope2" )
2021-04-28 06:53:13 -04:00
require . NoError ( t , err )
2021-07-29 18:52:56 -06:00
cs3 , err := NewClaimsScope ( ctx , "am-public-id" , "old-scope3" )
2021-04-28 06:53:13 -04:00
require . NoError ( t , err )
2022-10-25 18:29:38 -05:00
return [] any { cs , cs2 , cs3 }
2021-04-28 06:53:13 -04:00
}(),
},
2021-04-08 20:54:32 -04:00
{
name : "missing-public-id" ,
voName : AudClaimVO ,
new : nil ,
old : [] string { "old-aud1" , "old-aud2" , "old-aud3" },
nullFields : [] string { string ( AudClaimVO )},
2022-10-25 18:29:38 -05:00
wantDel : func () [] any {
2021-07-29 18:52:56 -06:00
a , err := NewAudClaim ( ctx , "am-public-id" , "old-aud1" )
2021-04-08 20:54:32 -04:00
require . NoError ( t , err )
2021-07-29 18:52:56 -06:00
a2 , err := NewAudClaim ( ctx , "am-public-id" , "old-aud2" )
2021-04-08 20:54:32 -04:00
require . NoError ( t , err )
2021-07-29 18:52:56 -06:00
a3 , err := NewAudClaim ( ctx , "am-public-id" , "old-aud3" )
2021-04-08 20:54:32 -04:00
require . NoError ( t , err )
2022-10-25 18:29:38 -05:00
return [] any { a , a2 , a3 }
2021-04-08 20:54:32 -04:00
}(),
wantErrMatch : errors . T ( errors . InvalidParameter ),
},
{
name : "invalid-vo-name" ,
voName : voName ( "invalid-name" ),
id : "am-public-id" ,
new : nil ,
old : [] string { "old-aud1" , "old-aud2" , "old-aud3" },
nullFields : [] string { string ( AudClaimVO )},
2022-10-25 18:29:38 -05:00
wantDel : func () [] any {
2021-07-29 18:52:56 -06:00
a , err := NewAudClaim ( ctx , "am-public-id" , "old-aud1" )
2021-04-08 20:54:32 -04:00
require . NoError ( t , err )
2021-07-29 18:52:56 -06:00
a2 , err := NewAudClaim ( ctx , "am-public-id" , "old-aud2" )
2021-04-08 20:54:32 -04:00
require . NoError ( t , err )
2021-07-29 18:52:56 -06:00
a3 , err := NewAudClaim ( ctx , "am-public-id" , "old-aud3" )
2021-04-08 20:54:32 -04:00
require . NoError ( t , err )
2022-10-25 18:29:38 -05:00
return [] any { a , a2 , a3 }
2021-04-08 20:54:32 -04:00
}(),
wantErrMatch : errors . T ( errors . InvalidParameter ),
},
{
name : "dup-new" ,
id : "am-public-id" ,
voName : SigningAlgVO ,
new : [] string { "ES256" , "ES256" },
old : [] string { "RS256" , "RS384" , "RS512" },
dbMask : [] string { string ( SigningAlgVO )},
2022-10-25 18:29:38 -05:00
wantAdd : func () [] any {
2021-07-29 18:52:56 -06:00
a , err := NewSigningAlg ( ctx , "am-public-id" , ES256 )
2021-04-08 20:54:32 -04:00
require . NoError ( t , err )
2021-07-29 18:52:56 -06:00
a2 , err := NewSigningAlg ( ctx , "am-public-id" , ES384 )
2021-04-08 20:54:32 -04:00
require . NoError ( t , err )
2022-10-25 18:29:38 -05:00
return [] any { a , a2 }
2021-04-08 20:54:32 -04:00
}(),
2022-10-25 18:29:38 -05:00
wantDel : func () [] any {
2021-07-29 18:52:56 -06:00
a , err := NewSigningAlg ( ctx , "am-public-id" , RS256 )
2021-04-08 20:54:32 -04:00
require . NoError ( t , err )
2021-07-29 18:52:56 -06:00
a2 , err := NewSigningAlg ( ctx , "am-public-id" , RS384 )
2021-04-08 20:54:32 -04:00
require . NoError ( t , err )
2021-07-29 18:52:56 -06:00
a3 , err := NewSigningAlg ( ctx , "am-public-id" , RS512 )
2021-04-08 20:54:32 -04:00
require . NoError ( t , err )
2022-10-25 18:29:38 -05:00
return [] any { a , a2 , a3 }
2021-04-08 20:54:32 -04:00
}(),
wantErrMatch : errors . T ( errors . InvalidParameter ),
},
{
name : "dup-old" ,
id : "am-public-id" ,
voName : SigningAlgVO ,
new : [] string { "ES256" , "ES384" },
old : [] string { "RS256" , "RS256" , "RS512" },
dbMask : [] string { string ( SigningAlgVO )},
2022-10-25 18:29:38 -05:00
wantAdd : func () [] any {
2021-07-29 18:52:56 -06:00
a , err := NewSigningAlg ( ctx , "am-public-id" , ES256 )
2021-04-08 20:54:32 -04:00
require . NoError ( t , err )
2021-07-29 18:52:56 -06:00
a2 , err := NewSigningAlg ( ctx , "am-public-id" , ES384 )
2021-04-08 20:54:32 -04:00
require . NoError ( t , err )
2022-10-25 18:29:38 -05:00
return [] any { a , a2 }
2021-04-08 20:54:32 -04:00
}(),
2022-10-25 18:29:38 -05:00
wantDel : func () [] any {
2021-07-29 18:52:56 -06:00
a , err := NewSigningAlg ( ctx , "am-public-id" , RS256 )
2021-04-08 20:54:32 -04:00
require . NoError ( t , err )
2021-07-29 18:52:56 -06:00
a2 , err := NewSigningAlg ( ctx , "am-public-id" , RS384 )
2021-04-08 20:54:32 -04:00
require . NoError ( t , err )
2021-07-29 18:52:56 -06:00
a3 , err := NewSigningAlg ( ctx , "am-public-id" , RS512 )
2021-04-08 20:54:32 -04:00
require . NoError ( t , err )
2022-10-25 18:29:38 -05:00
return [] any { a , a2 , a3 }
2021-04-08 20:54:32 -04:00
}(),
wantErrMatch : errors . T ( errors . InvalidParameter ),
},
}
for _ , tt := range tests {
t . Run ( tt . name , func ( t * testing . T ) {
assert , require := assert . New ( t ), require . New ( t )
2021-07-29 18:52:56 -06:00
gotAdd , gotDel , err := valueObjectChanges ( context . TODO (), tt . id , tt . voName , tt . new , tt . old , tt . dbMask , tt . nullFields )
2021-04-08 20:54:32 -04:00
if tt . wantErrMatch != nil {
require . Error ( err )
assert . Truef ( errors . Match ( tt . wantErrMatch , err ), "want err code: %q got: %q" , tt . wantErrMatch . Code , err )
return
}
require . NoError ( err )
assert . Equal ( tt . wantAdd , gotAdd )
switch tt . voName {
case CertificateVO :
sort . Slice ( gotDel , func ( a , b int ) bool {
aa := gotDel [ a ]
bb := gotDel [ b ]
return aa .( * Certificate ). Cert < bb .( * Certificate ). Cert
})
case SigningAlgVO :
sort . Slice ( gotDel , func ( a , b int ) bool {
aa := gotDel [ a ]
bb := gotDel [ b ]
return aa .( * SigningAlg ). Alg < bb .( * SigningAlg ). Alg
})
case AudClaimVO :
sort . Slice ( gotDel , func ( a , b int ) bool {
aa := gotDel [ a ]
bb := gotDel [ b ]
return aa .( * AudClaim ). Aud < bb .( * AudClaim ). Aud
})
2021-04-28 06:53:13 -04:00
case ClaimsScopesVO :
sort . Slice ( gotDel , func ( a , b int ) bool {
aa := gotDel [ a ]
bb := gotDel [ b ]
return aa .( * ClaimsScope ). Scope < bb .( * ClaimsScope ). Scope
})
2021-04-08 20:54:32 -04:00
}
assert . Equalf ( tt . wantDel , gotDel , "wantDel: %s\ngotDel: %s\n" , tt . wantDel , gotDel )
})
}
}
func Test_validateFieldMask ( t * testing . T ) {
t . Parallel ()
tests := [] struct {
name string
fieldMask [] string
wantErr bool
}{
{
name : "all-valid-fields" ,
fieldMask : [] string {
2021-04-28 06:53:13 -04:00
NameField ,
DescriptionField ,
IssuerField ,
ClientIdField ,
ClientSecretField ,
MaxAgeField ,
SigningAlgsField ,
ApiUrlField ,
AudClaimsField ,
CertificatesField ,
ClaimsScopesField ,
2023-11-21 11:30:02 -05:00
PromptsField ,
2021-04-08 20:54:32 -04:00
},
},
{
name : "invalid" ,
2021-04-28 06:53:13 -04:00
fieldMask : [] string { "Invalid" , NameField },
2021-04-08 20:54:32 -04:00
wantErr : true ,
},
}
for _ , tt := range tests {
t . Run ( tt . name , func ( t * testing . T ) {
require := require . New ( t )
2021-07-29 18:52:56 -06:00
err := validateFieldMask ( context . TODO (), tt . fieldMask )
2021-04-08 20:54:32 -04:00
if tt . wantErr {
require . Error ( err )
return
}
require . NoError ( err )
})
}
}
func Test_applyUpdate ( t * testing . T ) {
t . Parallel ()
tests := [] struct {
name string
new * AuthMethod
orig * AuthMethod
fieldMask [] string
want * AuthMethod
}{
{
name : "valid-all-fields" ,
new : & AuthMethod {
AuthMethod : & store . AuthMethod {
Name : "new-name" ,
Description : "new-description" ,
OperationalState : string ( ActivePublicState ),
Issuer : "new-issuer" ,
ClientId : "new-client-id" ,
ClientSecret : "new-client-secret" ,
MaxAge : 100 ,
SigningAlgs : [] string { "new-alg1" , "new-alg2" },
ApiUrl : "new-callback-1" ,
AudClaims : [] string { "new-aud-1" , "new-aud-2" },
Certificates : [] string { "new-pem1" , "new-pem-2" },
2021-04-28 06:53:13 -04:00
ClaimsScopes : [] string { "new-scope1" , "new-scope2" },
2023-11-21 11:30:02 -05:00
Prompts : [] string { string ( SelectAccount )},
2021-04-08 20:54:32 -04:00
},
},
orig : & AuthMethod {
AuthMethod : & store . AuthMethod {
Name : "orig-name" ,
Description : "orig-description" ,
OperationalState : string ( InactiveState ),
Issuer : "orig-issuer" ,
ClientId : "orig-client-id" ,
ClientSecret : "orig-client-secret" ,
MaxAge : 100 ,
SigningAlgs : [] string { "orig-alg1" , "orig-alg2" },
ApiUrl : "orig-callback-1" ,
AudClaims : [] string { "orig-aud-1" , "orig-aud-2" },
Certificates : [] string { "orig-pem1" , "orig-pem-2" },
2021-04-28 06:53:13 -04:00
ClaimsScopes : [] string { "orig-scope1" , "orig-scope2" },
2023-11-21 11:30:02 -05:00
Prompts : [] string { string ( None )},
2021-04-08 20:54:32 -04:00
},
},
want : & AuthMethod {
AuthMethod : & store . AuthMethod {
Name : "new-name" ,
Description : "new-description" ,
OperationalState : string ( InactiveState ),
Issuer : "new-issuer" ,
ClientId : "new-client-id" ,
ClientSecret : "new-client-secret" ,
MaxAge : 100 ,
SigningAlgs : [] string { "new-alg1" , "new-alg2" },
ApiUrl : "new-callback-1" ,
AudClaims : [] string { "new-aud-1" , "new-aud-2" },
Certificates : [] string { "new-pem1" , "new-pem-2" },
2021-04-28 06:53:13 -04:00
ClaimsScopes : [] string { "new-scope1" , "new-scope2" },
2023-11-21 11:30:02 -05:00
Prompts : [] string { string ( SelectAccount )},
2021-04-08 20:54:32 -04:00
},
},
fieldMask : [] string {
2021-04-28 06:53:13 -04:00
NameField ,
DescriptionField ,
IssuerField ,
ClientIdField ,
ClientSecretField ,
MaxAgeField ,
SigningAlgsField ,
ApiUrlField ,
AudClaimsField ,
CertificatesField ,
ClaimsScopesField ,
2023-11-21 11:30:02 -05:00
PromptsField ,
2021-04-08 20:54:32 -04:00
},
},
{
name : "nil-value-objects" ,
new : & AuthMethod {
AuthMethod : & store . AuthMethod {
Name : "new-name" ,
Description : "new-description" ,
OperationalState : string ( ActivePublicState ),
Issuer : "new-issuer" ,
ClientId : "new-client-id" ,
ClientSecret : "new-client-secret" ,
MaxAge : 100 ,
},
},
orig : & AuthMethod {
AuthMethod : & store . AuthMethod {
Name : "orig-name" ,
Description : "orig-description" ,
OperationalState : string ( InactiveState ),
Issuer : "orig-issuer" ,
ClientId : "orig-client-id" ,
ClientSecret : "orig-client-secret" ,
MaxAge : 100 ,
SigningAlgs : [] string { "orig-alg1" , "orig-alg2" },
ApiUrl : "orig-callback-1" ,
AudClaims : [] string { "orig-aud-1" , "orig-aud-2" },
Certificates : [] string { "orig-pem1" , "orig-pem-2" },
2021-04-28 06:53:13 -04:00
ClaimsScopes : [] string { "orig-scope1" , "orig-scope2" },
2023-11-21 11:30:02 -05:00
Prompts : [] string { string ( SelectAccount )},
2021-04-08 20:54:32 -04:00
},
},
want : & AuthMethod {
AuthMethod : & store . AuthMethod {
Name : "new-name" ,
Description : "new-description" ,
OperationalState : string ( InactiveState ),
Issuer : "new-issuer" ,
ClientId : "new-client-id" ,
ClientSecret : "new-client-secret" ,
MaxAge : 100 ,
},
},
fieldMask : [] string {
2021-04-28 06:53:13 -04:00
NameField ,
DescriptionField ,
IssuerField ,
ClientIdField ,
ClientSecretField ,
MaxAgeField ,
SigningAlgsField ,
ApiUrlField ,
AudClaimsField ,
CertificatesField ,
ClaimsScopesField ,
2023-11-21 11:30:02 -05:00
PromptsField ,
2021-04-08 20:54:32 -04:00
},
},
}
for _ , tt := range tests {
t . Run ( tt . name , func ( t * testing . T ) {
assert := assert . New ( t )
got := applyUpdate ( tt . new , tt . orig , tt . fieldMask )
2022-08-11 17:24:14 -07:00
assert . Empty ( cmp . Diff ( got , tt . want , protocmp . Transform ()))
2021-04-08 20:54:32 -04:00
})
}
}
type mockClient struct {
mockDo func ( req * http . Request ) ( * http . Response , error )
}
// Overriding what the Do function should "do" in our MockClient
func ( m * mockClient ) Do ( req * http . Request ) ( * http . Response , error ) {
return m . mockDo ( req )
}
func Test_pingEndpoint ( t * testing . T ) {
t . Parallel ()
ctx := context . Background ()
tests := [] struct {
name string
setup func () ( HTTPClient , string , string )
wantStatus int
wantErr bool
}{
{
name : "valid-endpoint" ,
setup : func () ( HTTPClient , string , string ) {
client := & mockClient {
mockDo : func ( * http . Request ) ( * http . Response , error ) {
return & http . Response {
StatusCode : 200 ,
}, nil
},
}
2024-09-19 08:55:27 -07:00
return client , http . MethodGet , "http://[::1]/get"
2021-04-08 20:54:32 -04:00
},
wantStatus : 200 ,
},
{
name : "valid-500" ,
setup : func () ( HTTPClient , string , string ) {
client := & mockClient {
mockDo : func ( * http . Request ) ( * http . Response , error ) {
return & http . Response {
StatusCode : 500 ,
}, nil
},
}
2024-09-19 08:55:27 -07:00
return client , http . MethodGet , "http://[::1]/get"
2021-04-08 20:54:32 -04:00
},
wantStatus : 500 ,
},
{
name : "failed" ,
setup : func () ( HTTPClient , string , string ) {
client := & mockClient {
mockDo : func ( * http . Request ) ( * http . Response , error ) {
return nil , fmt . Errorf ( "invalid request" )
},
}
2024-09-19 08:55:27 -07:00
return client , http . MethodGet , "http://[::1]/get"
2021-04-08 20:54:32 -04:00
},
wantErr : true ,
},
}
for _ , tt := range tests {
t . Run ( tt . name , func ( t * testing . T ) {
assert , require := assert . New ( t ), require . New ( t )
client , method , url := tt . setup ()
gotStatus , err := pingEndpoint ( ctx , client , tt . name , method , url )
assert . Equal ( gotStatus , tt . wantStatus )
if tt . wantErr {
require . Error ( err )
return
}
require . NoError ( err )
})
}
}