Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion cmd/cli/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@ package main
import (
"bytes"
"encoding/json"
"github.com/OpenBankingUK/conformance-dcr/pkg/compliant"
"io"
"io/ioutil"
"os"

"github.com/OpenBankingUK/conformance-dcr/pkg/compliant"

"github.com/pkg/errors"
)

Expand All @@ -29,6 +30,7 @@ type Config struct {
DeleteImplemented bool `json:"delete_implemented"`
Environment string `json:"environment"`
Brand string `json:"brand"`
SSAs []string `json:"ssas"`
}

func LoadConfig(configFilePath string) (Config, error) {
Expand Down
1 change: 1 addition & 0 deletions cmd/cli/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ func runCmd(flags flags) {
cfg.DeleteImplemented,
flags.tlsSkipVerify,
cfg.SpecVersion,
cfg.SSAs,
)
exitOnError(err)

Expand Down
39 changes: 39 additions & 0 deletions pkg/compliant/auth/authoriser_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ type AuthoriserBuilder struct {
jwtExpiration time.Duration
transportCert *x509.Certificate
transportCertSubjectDn string
ssas []string
}

func NewAuthoriserBuilder() AuthoriserBuilder {
Expand Down Expand Up @@ -48,6 +49,11 @@ func (b AuthoriserBuilder) WithSSA(ssa string) AuthoriserBuilder {
return b
}

func (b AuthoriserBuilder) WithSSAs(ssas []string) AuthoriserBuilder {
b.ssas = ssas
return b
}

func (b AuthoriserBuilder) WithIssuer(issuer string) AuthoriserBuilder {
b.issuer = issuer
return b
Expand Down Expand Up @@ -88,6 +94,39 @@ func (b AuthoriserBuilder) WithJwtExpiration(jwtExpiration time.Duration) Author
return b
}

func (b AuthoriserBuilder) popSsas(ssas *[]string) AuthoriserBuilder {
b.ssa = (*ssas)[0]
if len(*ssas) > 1 {
*ssas = (*ssas)[1:]
} else {
*ssas = []string{}
}
b.ssas = *ssas
return b
}

// UpdateSsa - update the main ssa of the AuthoriserBuilder by popping the first one from ssas
func (b AuthoriserBuilder) UpdateSsa(ssas *[]string) AuthoriserBuilder {
// if ssas list is empty/doesn't exist then just return not modified AuthoriserBuilder
// if there are not enough ssas it's checked before at the early stage of dcr 32/33
if len(*ssas) == 0 {
return b
} else {
b = b.popSsas(ssas)
return b
}
}

// UpdateSsaAndGetSlice - UpdateSsa n times and return the generated slice of AuthoriserBuilders
func (b AuthoriserBuilder) UpdateSsaAndGetSlice(n int, ssas *[]string) []AuthoriserBuilder {
var authoriserBuilders []AuthoriserBuilder
for i := 0; i < n; i++ {
newAuthoriserBuilder := b.UpdateSsa(ssas)
authoriserBuilders = append(authoriserBuilders, newAuthoriserBuilder)
}
return authoriserBuilders
}

func (b AuthoriserBuilder) Build() (Authoriser, error) {
if b.ssa == "" {
return none{}, errors.New("missing ssa from authoriser")
Expand Down
82 changes: 62 additions & 20 deletions pkg/compliant/dcr32.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package compliant

import (
"errors"
"fmt"
"github.com/OpenBankingUK/conformance-dcr/pkg/compliant/step"
"github.com/dgrijalva/jwt-go"
"net/http"
"time"

"github.com/OpenBankingUK/conformance-dcr/pkg/compliant/step"
"github.com/dgrijalva/jwt-go"

"github.com/OpenBankingUK/conformance-dcr/pkg/compliant/auth"
"github.com/OpenBankingUK/conformance-dcr/pkg/compliant/schema"
)
Expand All @@ -18,29 +20,43 @@ const (
specLinkDeleteSoftware = "https://openbanking.atlassian.net/wiki/spaces/DZ/pages/1078034771/Dynamic+Client+Registration+-+v3.2#DynamicClientRegistration-v3.2-DELETE/register/{ClientId}"
specLinkRetrieveSoftware = "https://openbanking.atlassian.net/wiki/spaces/DZ/pages/1078034771/Dynamic+Client+Registration+-+v3.2#DynamicClientRegistration-v3.2-GET/register/{ClientId}"
specLinkUpdateSoftware = "https://openbanking.atlassian.net/wiki/spaces/DZ/pages/1078034771/Dynamic+Client+Registration+-+v3.2#DynamicClientRegistration-v3.2-PUT/register/{ClientId}"
expectedSSAsLen32 = 15
)

func NewDCR32(cfg DCR32Config) (Manifest, error) {
secureClient := cfg.SecureClient
authoriserBuilder := cfg.AuthoriserBuilder
validator := cfg.SchemaValidator

ssas := &cfg.SSAs
if err := validateSSAsLen(*ssas, expectedSSAsLen32); err != nil {
return nil, err
}

scenarios := Scenarios{
DCR32ValidateOIDCConfigRegistrationURL(cfg),
DCR32CreateSoftwareClient(cfg, secureClient, authoriserBuilder),
DCR32DeleteSoftwareClient(cfg, secureClient, authoriserBuilder),
DCR32CreateInvalidRegistrationRequest(cfg, secureClient, authoriserBuilder),
DCR32RetrieveSoftwareClient(cfg, secureClient, authoriserBuilder, validator),
DCR32RetrieveWithInvalidCredentials(cfg, secureClient, authoriserBuilder),
DCR32UpdateSoftwareClient(cfg, secureClient, authoriserBuilder),
DCR32UpdateSoftwareClientWithWrongId(cfg, secureClient, authoriserBuilder),
DCR32RetrieveSoftwareClientWrongId(cfg, secureClient, authoriserBuilder),
DCR32RegisterSoftwareWrongResponseType(cfg, secureClient, authoriserBuilder),
DCR32CreateSoftwareClient(cfg, secureClient, authoriserBuilder, ssas),
DCR32DeleteSoftwareClient(cfg, secureClient, authoriserBuilder, ssas),
DCR32CreateInvalidRegistrationRequest(cfg, secureClient, authoriserBuilder, ssas),
DCR32RetrieveSoftwareClient(cfg, secureClient, authoriserBuilder, validator, ssas),
DCR32RetrieveWithInvalidCredentials(cfg, secureClient, authoriserBuilder, ssas),
DCR32UpdateSoftwareClient(cfg, secureClient, authoriserBuilder, ssas),
DCR32UpdateSoftwareClientWithWrongId(cfg, secureClient, authoriserBuilder, ssas),
DCR32RetrieveSoftwareClientWrongId(cfg, secureClient, authoriserBuilder, ssas),
DCR32RegisterSoftwareWrongResponseType(cfg, secureClient, authoriserBuilder, ssas),
}

return NewManifest("DCR32", "1.0", scenarios)
}

func validateSSAsLen(ssas []string, expectedLen int) error {
ssasLen := len(ssas)
if ssasLen != 0 && ssasLen < expectedLen {
return errors.New("invalid amout of SSAs provided in the config")
}
return nil
}

func DCR32ValidateOIDCConfigRegistrationURL(cfg DCR32Config) Scenario {
return NewBuilder(
"DCR-001",
Expand All @@ -57,7 +73,9 @@ func DCR32CreateSoftwareClient(
cfg DCR32Config,
secureClient *http.Client,
authoriserBuilder auth.AuthoriserBuilder,
ssas *[]string,
) Scenario {
authoriserBuilder = authoriserBuilder.UpdateSsa(ssas)
return NewBuilder(
"DCR-002",
"Dynamically create a new software client",
Expand Down Expand Up @@ -109,6 +127,7 @@ func DCR32DeleteSoftwareClient(
cfg DCR32Config,
secureClient *http.Client,
authoriserBuilder auth.AuthoriserBuilder,
ssas *[]string,
) Scenario {
id := "DCR-003"
name := "Delete software is supported"
Expand All @@ -121,6 +140,8 @@ func DCR32DeleteSoftwareClient(
).Build()
}

authoriserBuilder = authoriserBuilder.UpdateSsa(ssas)

return NewBuilder(
id,
name,
Expand All @@ -141,7 +162,10 @@ func DCR32CreateInvalidRegistrationRequest(
cfg DCR32Config,
secureClient *http.Client,
authoriserBuilder auth.AuthoriserBuilder,
ssas *[]string,
) Scenario {
authoriserBuilders := authoriserBuilder.UpdateSsaAndGetSlice(5, ssas)

return NewBuilder(
"DCR-004",
"Dynamically create a new software client will fail on invalid registration request",
Expand All @@ -151,7 +175,7 @@ func DCR32CreateInvalidRegistrationRequest(
NewTestCaseBuilder("Register software client fails on expired claims").
WithHttpClient(secureClient).
GenerateSignedClaims(
authoriserBuilder.
authoriserBuilders[0].
WithJwtExpiration(-time.Hour),
).
PostClientRegister(cfg.OpenIDConfig.RegistrationEndpointAsString()).
Expand All @@ -162,7 +186,7 @@ func DCR32CreateInvalidRegistrationRequest(
NewTestCaseBuilder("Register software client fails on invalid issuer").
WithHttpClient(secureClient).
GenerateSignedClaims(
authoriserBuilder.
authoriserBuilders[1].
WithIssuer("foo.is/invalid"),
).
PostClientRegister(cfg.OpenIDConfig.RegistrationEndpointAsString()).
Expand All @@ -173,7 +197,7 @@ func DCR32CreateInvalidRegistrationRequest(
NewTestCaseBuilder("Register software client fails on invalid issuer too short").
WithHttpClient(secureClient).
GenerateSignedClaims(
authoriserBuilder.
authoriserBuilders[2].
WithIssuer(""),
).
PostClientRegister(cfg.OpenIDConfig.RegistrationEndpointAsString()).
Expand All @@ -184,7 +208,7 @@ func DCR32CreateInvalidRegistrationRequest(
NewTestCaseBuilder("Register software client fails on invalid issuer too long").
WithHttpClient(secureClient).
GenerateSignedClaims(
authoriserBuilder.
authoriserBuilders[3].
WithIssuer("123456789012345678901234567890"),
).
PostClientRegister(cfg.OpenIDConfig.RegistrationEndpointAsString()).
Expand All @@ -194,7 +218,7 @@ func DCR32CreateInvalidRegistrationRequest(
TestCase(
NewTestCaseBuilder("Register software client will fail with token endpoint auth method RS256").
WithHttpClient(secureClient).
GenerateSignedClaims(authoriserBuilder.WithTokenEndpointAuthMethod(jwt.SigningMethodRS256)).
GenerateSignedClaims(authoriserBuilders[4].WithTokenEndpointAuthMethod(jwt.SigningMethodRS256)).
PostClientRegister(cfg.OpenIDConfig.RegistrationEndpointAsString()).
AssertStatusCodeBadRequest().
Build(),
Expand All @@ -206,7 +230,10 @@ func DCR32RetrieveSoftwareClient(
secureClient *http.Client,
authoriserBuilder auth.AuthoriserBuilder,
validator schema.Validator,
ssas *[]string,
) Scenario {
authoriserBuilder = authoriserBuilder.UpdateSsa(ssas)

return NewBuilder(
"DCR-005",
"Dynamically retrieve a new software client",
Expand Down Expand Up @@ -243,7 +270,10 @@ func DCR32RetrieveWithInvalidCredentials(
cfg DCR32Config,
secureClient *http.Client,
authoriserBuilder auth.AuthoriserBuilder,
ssas *[]string,
) Scenario {
authoriserBuilder = authoriserBuilder.UpdateSsa(ssas)

return NewBuilder(
"DCR-007",
"I should not be able to retrieve a software client with invalid credentials",
Expand Down Expand Up @@ -280,7 +310,10 @@ func DCR32UpdateSoftwareClient(
cfg DCR32Config,
secureClient *http.Client,
authoriserBuilder auth.AuthoriserBuilder,
ssas *[]string,
) Scenario {
authoriserBuilders := authoriserBuilder.UpdateSsaAndGetSlice(2, ssas)

id := "DCR-008"
const name = "I should be able update a registered software"

Expand All @@ -297,11 +330,11 @@ func DCR32UpdateSoftwareClient(
name,
specLinkUpdateSoftware,
).
TestCase(DCR32CreateSoftwareClientTestCases(cfg, secureClient, authoriserBuilder)...).
TestCase(DCR32CreateSoftwareClientTestCases(cfg, secureClient, authoriserBuilders[0])...).
TestCase(
NewTestCaseBuilder("Update an existing software client").
WithHttpClient(secureClient).
GenerateSignedClaims(authoriserBuilder).
GenerateSignedClaims(authoriserBuilders[1]).
ClientUpdate(cfg.OpenIDConfig.RegistrationEndpointAsString()).
AssertStatusCodeOk().
Build(),
Expand All @@ -314,7 +347,10 @@ func DCR32UpdateSoftwareClientWithWrongId(
cfg DCR32Config,
secureClient *http.Client,
authoriserBuilder auth.AuthoriserBuilder,
ssas *[]string,
) Scenario {
authoriserBuilders := authoriserBuilder.UpdateSsaAndGetSlice(2, ssas)

id := "DCR-009"
const name = "When I try to update a non existing software client I should be unauthorized"

Expand All @@ -331,12 +367,12 @@ func DCR32UpdateSoftwareClientWithWrongId(
name,
specLinkUpdateSoftware,
).
TestCase(DCR32CreateSoftwareClientTestCases(cfg, secureClient, authoriserBuilder)...).
TestCase(DCR32CreateSoftwareClientTestCases(cfg, secureClient, authoriserBuilders[0])...).
TestCase(DCR32DeleteSoftwareClientTestCase(cfg, secureClient)).
TestCase(
NewTestCaseBuilder("Update a deleted software client").
WithHttpClient(secureClient).
GenerateSignedClaims(authoriserBuilder).
GenerateSignedClaims(authoriserBuilders[1]).
ClientUpdate(cfg.OpenIDConfig.RegistrationEndpointAsString()).
AssertStatusCodeUnauthorized().
Build(),
Expand All @@ -347,10 +383,13 @@ func DCR32RetrieveSoftwareClientWrongId(
cfg DCR32Config,
secureClient *http.Client,
authoriserBuilder auth.AuthoriserBuilder,
ssas *[]string,
) Scenario {
id := "DCR-010"
const name = "When I try to retrieve a non existing software client I should be unauthorized"

authoriserBuilder = authoriserBuilder.UpdateSsa(ssas)

return NewBuilder(
id,
name,
Expand All @@ -371,10 +410,13 @@ func DCR32RegisterSoftwareWrongResponseType(
cfg DCR32Config,
secureClient *http.Client,
authoriserBuilder auth.AuthoriserBuilder,
ssas *[]string,
) Scenario {
id := "DCR-011"
const name = "When I try to register a software with invalid response_types it should be fail"

authoriserBuilder = authoriserBuilder.UpdateSsa(ssas)

return NewBuilder(
id,
name,
Expand Down
Loading