Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to get through authentication process using hasPactsFromPactBroker? #1787

Open
vbutlerovskyi opened this issue Apr 7, 2024 · 7 comments
Labels
question Indicates that an issue, pull request, or discussion needs more information

Comments

@vbutlerovskyi
Copy link

Hi there,

I'm a beginner in PACT testing and I was given a challenge to have one up and running so I accepted it, albeit it's not going smoothly. Basically I'm trying to validate the JSON contract from our running broker between two of our services using hasPactsFromPactBroker() and it keeps giving me 401 no matter what.

I tried something like this:

@Property(name = "micronaut.server.port", value = "8080")
@MicronautTest(environments = ["test"])
class ProviderPactSpec extends Specification {

    @Shared
    ProviderInfo serviceProvider

    ProviderVerifier verifier

    def setupSpec() {
        serviceProvider = new ProviderInfo('service1')
        serviceProvider.protocol = 'https'
        serviceProvider.host = 'https://pact-broker.com'
        serviceProvider.port = 443
        serviceProvider.path = ''
        serviceProvider.insecure = true
        serviceProvider.hasPactsFromPactBroker('https://pact-broker.com/pacts/my_pact', Authorization: ['Bearer', 'token'])
        }

    def setup() {
        verifier = new ProviderVerifier()
    }
        
        @Unroll
    def "Provider Pact - With Consumer #consumer"() {
        expect:
        verifyConsumerPact(consumer) instanceof VerificationResult.Ok

        where:
        consumer << serviceProvider.consumers
    }

    private VerificationResult verifyConsumerPact(ConsumerInfo consumer) {
        verifier.initialiseReporters(serviceProvider)
        def result = verifier.runVerificationForConsumer([:], serviceProvider, consumer)

        if (result instanceof VerificationResult.Failed) {
            verifier.displayFailures([result])
        }

        result
    }

As a result, I keep getting 401 Unauthorized:

{"message":"Established active environments: [test]","timestamp":1712518131867,"log.level":"INFO","logger.name":"io.micronaut.context.DefaultApplicationContext$RuntimeConfiguredEnvironment","thread.name":"Test worker","class.name":"io.micronaut.test.extensions.spock.MicronautSpockExtension","method.name":"lambda$visitSpecAnnotation$3","line.number":108}
{"message":"Failed to fetch the root HAL document","timestamp":1712518133239,"log.level":"WARN","logger.name":"au.com.dius.pact.core.pactbroker.HalClient$Companion","thread.name":"Test worker","class.name":"au.com.dius.pact.provider.ProviderInfo","method.name":"hasPactsFromPactBroker","line.number":68}

java.lang.RuntimeException: Call to fetch pacts from Pact Broker failed with an exception
	at au.com.dius.pact.provider.ProviderInfo.hasPactsFromPactBrokerWithSelectorsV2(ProviderInfo.kt:140)
	at au.com.dius.pact.provider.ProviderInfo.hasPactsFromPactBrokerWithSelectorsV2(ProviderInfo.kt:105)
	at au.com.dius.pact.provider.ProviderInfo.hasPactsFromPactBrokerWithSelectors(ProviderInfo.kt:76)
	at au.com.dius.pact.provider.ProviderInfo.hasPactsFromPactBroker(ProviderInfo.kt:68)
Caused by: au.com.dius.pact.core.pactbroker.InvalidNavigationRequest: Failed to fetch the root HAL document
	at au.com.dius.pact.core.pactbroker.HalClient.navigate(HalClient.kt:255)
	at au.com.dius.pact.core.pactbroker.PactBrokerClient$fetchConsumersWithSelectorsV2$halClient$navigateResult$1.invoke(PactBrokerClient.kt:494)
	at au.com.dius.pact.core.support.KotlinLanguageSupportKt.handleWith(KotlinLanguageSupport.kt:35)
	at au.com.dius.pact.core.pactbroker.PactBrokerClient.fetchConsumersWithSelectorsV2(PactBrokerClient.kt:494)
	at au.com.dius.pact.provider.ProviderInfo.hasPactsFromPactBrokerWithSelectorsV2(ProviderInfo.kt:129)
	... 4 more
Caused by: au.com.dius.pact.core.pactbroker.RequestFailedException: Request to path '/' failed with response 401
	at au.com.dius.pact.core.pactbroker.HalClient.handleHalResponse(HalClient.kt:347)
	at au.com.dius.pact.core.pactbroker.HalClient.access$handleHalResponse(HalClient.kt:164)
	at au.com.dius.pact.core.pactbroker.HalClient$getJson$1.invoke$lambda$0(HalClient.kt:318)
	at org.apache.hc.client5.http.impl.classic.CloseableHttpClient.execute(CloseableHttpClient.java:247)
	at org.apache.hc.client5.http.impl.classic.CloseableHttpClient.execute(CloseableHttpClient.java:188)
	at au.com.dius.pact.core.pactbroker.HalClient$getJson$1.invoke(HalClient.kt:317)
	at au.com.dius.pact.core.support.KotlinLanguageSupportKt.handleWith(KotlinLanguageSupport.kt:35)
	at au.com.dius.pact.core.pactbroker.HalClient.getJson(HalClient.kt:312)
	at au.com.dius.pact.core.pactbroker.HalClient.fetch(HalClient.kt:276)
	at au.com.dius.pact.core.pactbroker.HalClient.fetch(HalClient.kt:271)
	at au.com.dius.pact.core.pactbroker.HalClient.navigate(HalClient.kt:251)
	... 8 more

I also tried another way using username and password plus specifying the path attribute deliberately:

    def setupSpec() {
        serviceProvider = new ProviderInfo('consumer')
        serviceProvider.protocol = 'https'
        serviceProvider.host = 'https://pact-broker.com'
        serviceProvider.port = 443
        serviceProvider.path = '/pacts/my_pact'
        serviceProvider.insecure = true
        serviceProvider.hasPactsFromPactBroker('https://pact-broker.com', authentication: ['Basic', 'username', 'password'])
}

And then the error looks slightly different yet the same:

Condition failed with Exception:

verifyConsumerPact(consumer) instanceof VerificationResult.Ok
|                  |         |
|                  |         class au.com.dius.pact.provider.VerificationResult$Ok
|                  ConsumerInfo(name='consumer', stateChange=null, stateChangeUsesBody=true, packagesToScan=[], verificationType=null, pactSource=BrokerUrlSource(url=https://pact-broker.com/pacts/my_pact, pactBrokerUrl=https://pact-broker.com, attributes={}, options={}, tag=null, result=PactBrokerResult(name=consumer, source=https://pact-broker.com/pacts/my_pact, pactBrokerUrl=https://pact-broker.com, pactFileAuthentication=[], notices=[], pending=false, tag=null, wip=false, usedNewEndpoint=false, auth=null)), notices=[], pending=false, wip=false)
au.com.dius.pact.core.pactbroker.RequestFailedException: Request to path 'https://pact-broker.com/pacts/my_pact' failed with response 401

I'm using these versions of dependencies in my build.gradle:

testImplementation("au.com.dius.pact.provider:junit5spring:4.6.8")
testImplementation "au.com.dius.pact.consumer:groovy:4.3.19"

It's worth mentioning that the very first version of request works well in Postman, here's the cURL:

curl --location 'https://pact-broker.com/pacts/my_pact' \
--header 'Authorization: Basic ${token}'

I believe I tried everything possible so any hint would be really appreciated!

Thanks in advance!

@rholshausen
Copy link
Contributor

You're mixing versions, that may be causing the issue

testImplementation("au.com.dius.pact.provider:junit5spring:4.6.8")
testImplementation "au.com.dius.pact.consumer:groovy:4.3.19"

@rholshausen rholshausen added the question Indicates that an issue, pull request, or discussion needs more information label Apr 22, 2024
@vbutlerovskyi
Copy link
Author

vbutlerovskyi commented Apr 30, 2024

Hey @rholshausen, thanks for turnaround. Do you suggest to use either 4.6.8 or 4.3.19 in both places?

@rholshausen
Copy link
Contributor

Yes, I would recommend 4.6.8 as 4.3.x is not maintained anymore.

@vbutlerovskyi
Copy link
Author

Thanks again, I will try and write down my findings here

@vbutlerovskyi
Copy link
Author

Hey @rholshausen, I tried what you suggested but unfortunately nothing changed... Do you end up having any other ideas? Thank you in advance for your time

@rholshausen
Copy link
Contributor

The service provider is your service not the pact broker, so this is wrong (but not what is causing the issue)

serviceProvider.protocol = 'https'
        serviceProvider.host = 'https://pact-broker.com'
        serviceProvider.port = 443
        serviceProvider.path = '/pacts/my_pact'
        serviceProvider.insecure = true

Ah! this should be lower case Authorization:

@vbutlerovskyi
Copy link
Author

Thanks for the hint, but unfortunately nothing changed... I tried:
serviceProvider.hasPactsFromPactBroker('https://pact-broker.com', authorization: ['Bearer', 'bSwVWhZbdQ7EI9M6PwCp3Olx1DQ'])

serviceProvider.hasPactsFromPactBroker('https://pact-broker.com', authorization: ['Basic', 'bSwVWhZbdQ7EI9M6PwCp3Olx1DQ'])

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Indicates that an issue, pull request, or discussion needs more information
Projects
None yet
Development

No branches or pull requests

2 participants