Skip to content

Commit

Permalink
test: add oid4vci negative scenario tests (#1380)
Browse files Browse the repository at this point in the history
Signed-off-by: Allain Magyar <[email protected]>
Signed-off-by: Hyperledger Bot <[email protected]>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Hyperledger Bot <[email protected]>
  • Loading branch information
3 people authored Oct 2, 2024
1 parent ad946cf commit 7b4a9c1
Show file tree
Hide file tree
Showing 12 changed files with 280 additions and 69 deletions.
4 changes: 0 additions & 4 deletions tests/integration-tests/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,10 +116,6 @@ The configuration files are divided into the following sections:
* `agents`: contains the configuration for the agents (ICA) that will be started. By default, all agents will be destroyed after the test run is finished.
* `roles`: contains the configuration for the roles (Issuer, Holder, Verifier, Admin). A role can be assigned to one or more agents that we set in `agents` section or already running locally or in the cloud.

> You could keep services and agents running for debugging purposes
> by specifying `keep_running = true` for the service or agent
> in the configuration file and setting `TESTCONTAINERS_RYUK_DISABLED` variable to `true`.
Please, check [test/resources/configs/basic.conf](./src/test/resources/configs/basic.conf) for a quick example of a basic configuration.

You could explore the `configs` directory for more complex examples.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ data class Agent(
@ConfigAlias("prism_node") val prismNode: VerifiableDataRegistry?,
val keycloak: Keycloak?,
val vault: Vault?,
@ConfigAlias("keep_running") override val keepRunning: Boolean = false,
) : ServiceBase() {

override val logServices = listOf("identus-cloud-agent")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ data class Keycloak(
val realm: String = "atala-demo",
@ConfigAlias("client_id") val clientId: String = "cloud-agent",
@ConfigAlias("client_secret") val clientSecret: String = "cloud-agent-secret",
@ConfigAlias("keep_running") override val keepRunning: Boolean = false,
@ConfigAlias("compose_file") val keycloakComposeFile: String = "src/test/resources/containers/keycloak.yml",
@ConfigAlias("logger_name") val loggerName: String = "keycloak",
@ConfigAlias("extra_envs") val extraEnvs: Map<String, String> = emptyMap(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ abstract class ServiceBase : Startable {
}

abstract val container: ComposeContainer
abstract val keepRunning: Boolean

open val logServices: List<String> = emptyList()
private val logWriters: MutableList<Writer> = mutableListOf()
Expand All @@ -41,8 +40,6 @@ abstract class ServiceBase : Startable {
logWriters.forEach {
it.close()
}
if (!keepRunning) {
container.stop()
}
container.stop()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import java.io.File
data class Vault(
@ConfigAlias("http_port") val httpPort: Int,
@ConfigAlias("vault_auth_type") val authType: VaultAuthType = VaultAuthType.APP_ROLE,
@ConfigAlias("keep_running") override val keepRunning: Boolean = false,
) : ServiceBase() {
private val logger = Logger.get<Vault>()
override val logServices: List<String> = listOf("vault")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import java.io.File
data class VerifiableDataRegistry(
@ConfigAlias("http_port") val httpPort: Int,
val version: String,
@ConfigAlias("keep_running") override val keepRunning: Boolean = false,
) : ServiceBase() {
override val logServices: List<String> = listOf("prism-node")
private val vdrComposeFile = "src/test/resources/containers/vdr.yml"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import com.nimbusds.jose.JWSAlgorithm
import com.nimbusds.jose.jwk.JWK
import eu.europa.ec.eudi.openid4vci.*
import interactions.Post
import interactions.body
import io.cucumber.java.en.Then
import io.cucumber.java.en.When
import io.iohk.atala.automation.extensions.get
Expand Down Expand Up @@ -40,16 +41,13 @@ class IssueCredentialSteps {
issuer.recall("longFormDid")
}
issuer.attemptsTo(
Post.to("/oid4vci/issuers/${credentialIssuer.id}/credential-offers")
.with {
it.body(
CredentialOfferRequest(
credentialConfigurationId = configurationId,
issuingDID = did,
claims = claims,
),
)
},
Post.to("/oid4vci/issuers/${credentialIssuer.id}/credential-offers").body(
CredentialOfferRequest(
credentialConfigurationId = configurationId,
issuingDID = did,
claims = claims,
),
),
Ensure.thatTheLastResponse().statusCode().isEqualTo(HttpStatus.SC_CREATED),
)
val offerUri = SerenityRest.lastResponse().get<CredentialOfferResponse>().credentialOffer
Expand Down
Original file line number Diff line number Diff line change
@@ -1,38 +1,53 @@
package steps.oid4vci

import com.google.gson.JsonObject
import common.CredentialSchema
import interactions.*
import io.cucumber.java.en.*
import interactions.Delete
import interactions.Get
import interactions.Post
import interactions.body
import io.cucumber.java.en.Given
import io.cucumber.java.en.Then
import io.cucumber.java.en.When
import io.iohk.atala.automation.extensions.get
import io.iohk.atala.automation.serenity.ensure.Ensure
import net.serenitybdd.rest.SerenityRest
import net.serenitybdd.screenplay.Actor
import org.apache.http.HttpStatus
import org.hyperledger.identus.client.models.*
import org.apache.http.HttpStatus.SC_OK
import org.hyperledger.identus.client.models.CreateCredentialConfigurationRequest
import org.hyperledger.identus.client.models.CredentialFormat
import org.hyperledger.identus.client.models.CredentialIssuer
import org.hyperledger.identus.client.models.IssuerMetadata
import java.util.UUID

class ManageCredentialConfigSteps {
@Given("{actor} has {string} credential configuration created from {}")
fun issuerHasExistingCredentialConfig(issuer: Actor, configurationId: String, schema: CredentialSchema) {
ManageIssuerSteps().issuerHasExistingCredentialIssuer(issuer)
issuerCreateCredentialConfiguration(issuer, schema, configurationId)
val credentialIssuer = issuer.recall<CredentialIssuer>("oid4vciCredentialIssuer")
issuer.attemptsTo(
Get("/oid4vci/issuers/${credentialIssuer.id}/credential-configurations/$configurationId"),
)
if (SerenityRest.lastResponse().statusCode != SC_OK) {
issuerCreateCredentialConfiguration(issuer, schema, configurationId)
}
}

@When("{actor} uses {} to create a credential configuration {string}")
fun issuerCreateCredentialConfiguration(issuer: Actor, schema: CredentialSchema, configurationId: String) {
val credentialIssuer = issuer.recall<CredentialIssuer>("oid4vciCredentialIssuer")
val schemaGuid = issuer.recall<String>(schema.name)
val baseUrl = issuer.recall<String>("baseUrl")

issuer.attemptsTo(
Post.to("/oid4vci/issuers/${credentialIssuer.id}/credential-configurations")
.with {
it.body(
CreateCredentialConfigurationRequest(
configurationId = configurationId,
format = CredentialFormat.JWT_VC_JSON,
schemaId = "$baseUrl/schema-registry/schemas/$schemaGuid/schema",
),
)
},
Post.to("/oid4vci/issuers/${credentialIssuer.id}/credential-configurations").body(
CreateCredentialConfigurationRequest(
configurationId = configurationId,
format = CredentialFormat.JWT_VC_JSON,
schemaId = "$baseUrl/schema-registry/schemas/$schemaGuid/schema",
),
),
Ensure.thatTheLastResponse().statusCode().isEqualTo(HttpStatus.SC_CREATED),
)
}
Expand All @@ -42,7 +57,75 @@ class ManageCredentialConfigSteps {
val credentialIssuer = issuer.recall<CredentialIssuer>("oid4vciCredentialIssuer")
issuer.attemptsTo(
Delete("/oid4vci/issuers/${credentialIssuer.id}/credential-configurations/$configurationId"),
Ensure.thatTheLastResponse().statusCode().isEqualTo(HttpStatus.SC_OK),
Ensure.thatTheLastResponse().statusCode().isEqualTo(SC_OK),
)
}

@When("{actor} deletes a non existent {} credential configuration")
fun issuerDeletesANonExistentCredentialConfiguration(issuer: Actor, configurationId: String) {
val credentialIssuer = issuer.recall<CredentialIssuer>("oid4vciCredentialIssuer")
issuer.attemptsTo(
Delete("/oid4vci/issuers/${credentialIssuer.id}/credential-configurations/$configurationId"),
)
}

@When("{actor} creates a new credential configuration request")
fun issuerCreatesANewConfigurationRequest(issuer: Actor) {
val credentialConfiguration = JsonObject()
issuer.remember("credentialConfiguration", credentialConfiguration)
}

@When("{actor} uses {} issuer id for credential configuration")
fun issuerUsesIssuerId(issuer: Actor, issuerId: String) {
if (issuerId == "existing") {
val credentialIssuer = issuer.recall<CredentialIssuer>("oid4vciCredentialIssuer")
issuer.remember("credentialConfigurationId", credentialIssuer.id)
} else if (issuerId == "wrong") {
issuer.remember("credentialConfigurationId", UUID.randomUUID().toString())
}
}

@When("{actor} adds '{}' configuration id for credential configuration request")
fun issuerAddsConfigurationIdToCredentialConfigurationRequest(issuer: Actor, configurationId: String) {
val credentialIssuer = issuer.recall<JsonObject>("credentialConfiguration")
val configurationIdProperty = if (configurationId == "null") {
null
} else {
configurationId
}
credentialIssuer.addProperty("configurationId", configurationIdProperty)
}

@When("{actor} adds '{}' format for credential configuration request")
fun issuerAddsFormatToCredentialConfigurationRequest(issuer: Actor, format: String) {
val credentialIssuer = issuer.recall<JsonObject>("credentialConfiguration")
val formatProperty = if (format == "null") {
null
} else {
format
}
credentialIssuer.addProperty("format", formatProperty)
}

@When("{actor} adds '{}' schemaId for credential configuration request")
fun issuerAddsSchemaIdToCredentialConfigurationRequest(issuer: Actor, schema: String) {
val credentialIssuer = issuer.recall<JsonObject>("credentialConfiguration")
val schemaIdProperty = if (schema == "null") {
null
} else {
val baseUrl = issuer.recall<String>("baseUrl")
val schemaGuid = issuer.recall<String>(schema)
"$baseUrl/schema-registry/schemas/$schemaGuid/schema"
}
credentialIssuer.addProperty("schemaId", schemaIdProperty)
}

@When("{actor} sends the create a credential configuration request")
fun issuerSendsTheCredentialConfigurationRequest(issuer: Actor) {
val credentialConfiguration = issuer.recall<JsonObject>("credentialConfiguration")
val credentialIssuerId = issuer.recall<String>("credentialConfigurationId").toString()
issuer.attemptsTo(
Post.to("/oid4vci/issuers/$credentialIssuerId/credential-configurations").body(credentialConfiguration),
)
}

Expand All @@ -51,7 +134,7 @@ class ManageCredentialConfigSteps {
val credentialIssuer = issuer.recall<CredentialIssuer>("oid4vciCredentialIssuer")
issuer.attemptsTo(
Get("/oid4vci/issuers/${credentialIssuer.id}/.well-known/openid-credential-issuer"),
Ensure.thatTheLastResponse().statusCode().isEqualTo(HttpStatus.SC_OK),
Ensure.thatTheLastResponse().statusCode().isEqualTo(SC_OK),
)
val metadata = SerenityRest.lastResponse().get<IssuerMetadata>()
val credConfig = metadata.credentialConfigurationsSupported[configurationId]!!
Expand All @@ -65,11 +148,19 @@ class ManageCredentialConfigSteps {
val credentialIssuer = issuer.recall<CredentialIssuer>("oid4vciCredentialIssuer")
issuer.attemptsTo(
Get("/oid4vci/issuers/${credentialIssuer.id}/.well-known/openid-credential-issuer"),
Ensure.thatTheLastResponse().statusCode().isEqualTo(HttpStatus.SC_OK),
Ensure.thatTheLastResponse().statusCode().isEqualTo(SC_OK),
)
val metadata = SerenityRest.lastResponse().get<IssuerMetadata>()
issuer.attemptsTo(
Ensure.that(metadata.credentialConfigurationsSupported.keys).doesNotContain(configurationId),
)
}

@Then("{actor} should see that create credential configuration has failed with '{}' status code and '{}' detail")
fun issuerShouldSeeCredentialConfigurationRequestHasFailed(issuer: Actor, statusCode: Int, errorDetail: String) {
issuer.attemptsTo(
Ensure.thatTheLastResponse().statusCode().isEqualTo(statusCode),
Ensure.that(SerenityRest.lastResponse().body.asString()).contains(errorDetail),
)
}
}
Loading

0 comments on commit 7b4a9c1

Please sign in to comment.