diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 45865fc96..48e82a1a2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -46,19 +46,20 @@ jobs: MAVEN_USERNAME: ${{ secrets.MAVEN_USERNAME }} MAVEN_PASSWORD: ${{ secrets.MAVEN_PASSWORD }} with: - arguments: build publish --no-daemon - - name: Docker Build and Push SNAPSHOT - uses: philpotisk/github-action-docker-build-push@master - env: - DOCKER_USERNAME: ${{secrets.DOCKER_USERNAME}} - DOCKER_PASSWORD: ${{secrets.DOCKER_PASSWORD}} - DOCKER_FILE: Dockerfile - CONTAINER_TAG: waltid/ssikit:latest - - name: Prepare CD K8S - run: sed "s/_DEFAULT_DEPLOYMENT_/$GITHUB_SHA/g" k8s/deployment-dev.yaml > k8s/deployment-dev_mod.yaml - - name: Continuous deployment K8S - uses: actions-hub/kubectl@master - env: - KUBE_CONFIG: ${{ secrets.KUBE_CONFIG }} - with: - args: apply -n dev -f k8s/deployment-dev_mod.yaml + arguments: build --no-daemon +# arguments: build publish --no-daemon +# - name: Docker Build and Push SNAPSHOT +# uses: philpotisk/github-action-docker-build-push@master +# env: +# DOCKER_USERNAME: ${{secrets.DOCKER_USERNAME}} +# DOCKER_PASSWORD: ${{secrets.DOCKER_PASSWORD}} +# DOCKER_FILE: Dockerfile +# CONTAINER_TAG: waltid/ssikit:latest +# - name: Prepare CD K8S +# run: sed "s/_DEFAULT_DEPLOYMENT_/$GITHUB_SHA/g" k8s/deployment-dev.yaml > k8s/deployment-dev_mod.yaml +# - name: Continuous deployment K8S +# uses: actions-hub/kubectl@master +# env: +# KUBE_CONFIG: ${{ secrets.KUBE_CONFIG }} +# with: +# args: apply -n dev -f k8s/deployment-dev_mod.yaml diff --git a/src/main/kotlin/id/walt/auditor/Auditor.kt b/src/main/kotlin/id/walt/auditor/Auditor.kt index 1d3f132cd..094ce98d8 100644 --- a/src/main/kotlin/id/walt/auditor/Auditor.kt +++ b/src/main/kotlin/id/walt/auditor/Auditor.kt @@ -41,18 +41,18 @@ class WaltIdAuditor : Auditor() { log.debug { "Verifying vc with ${policy.id} ..." } val vcResult = policy.verify(vc) - val success = AtomicBoolean(vcResult.result) + val success = AtomicBoolean(vcResult.isSuccess) val allErrors = vcResult.errors.toMutableList() if (allErrors.isEmpty() && vc is VerifiablePresentation) { vc.verifiableCredential?.forEach { cred -> log.debug { "Verifying ${cred.type.last()} in VP with ${policy.id}..." } val vpResult = policy.verify(cred) allErrors.addAll(vpResult.errors) - success.compareAndSet(true, vpResult.result) + success.compareAndSet(true, vpResult.isSuccess) } } allErrors.forEach { log.error { "${policy.id}: $it" } } - VerificationPolicyResult(success.get(), allErrors) + success.get().takeIf { it }?.let { VerificationPolicyResult.success() } ?: VerificationPolicyResult.failure(*allErrors.toTypedArray()) } return VerificationResult(allAccepted(policyResults), policyResults) diff --git a/src/main/kotlin/id/walt/auditor/VerificationPolicy.kt b/src/main/kotlin/id/walt/auditor/VerificationPolicy.kt index 08bbc1658..577b45a1f 100644 --- a/src/main/kotlin/id/walt/auditor/VerificationPolicy.kt +++ b/src/main/kotlin/id/walt/auditor/VerificationPolicy.kt @@ -56,21 +56,26 @@ data class VerificationPolicyMetadata( val isMutable: Boolean ) -data class VerificationPolicyResult(val result: Boolean, @JsonIgnore val errors: List = listOf()) { +class VerificationPolicyResult private constructor( + private val result: Boolean, + @JsonIgnore + private val errorList: List = emptyList() +) { + companion object { fun success() = VerificationPolicyResult(true) - fun failure(error: Throwable): VerificationPolicyResult { - log.debug { "VerificationPolicy failed: ${error.stackTraceToString()}" } - return VerificationPolicyResult(false, listOf(error)) + fun failure(vararg error: Throwable): VerificationPolicyResult { + log.debug { "VerificationPolicy failed: ${error.joinToString { it.localizedMessage }}" } + return VerificationPolicyResult(false, error.asList()) } - - fun failure(errors: List = listOf()) = VerificationPolicyResult(false, errors.toList()) } val isSuccess = result val isFailure = !result + @JsonIgnore + val errors = errorList - fun getErrorString() = errors.mapIndexed { index, throwable -> + private fun getErrorString() = errorList.mapIndexed { index, throwable -> "#${index + 1}: ${throwable::class.simpleName ?: "Error"} - ${throwable.message}" }.joinToString() diff --git a/src/main/kotlin/id/walt/auditor/dynamic/OPAPolicyEngine.kt b/src/main/kotlin/id/walt/auditor/dynamic/OPAPolicyEngine.kt index 822dc1361..b7193a6a6 100644 --- a/src/main/kotlin/id/walt/auditor/dynamic/OPAPolicyEngine.kt +++ b/src/main/kotlin/id/walt/auditor/dynamic/OPAPolicyEngine.kt @@ -1,14 +1,9 @@ package id.walt.auditor.dynamic -import com.beust.klaxon.JsonObject import com.beust.klaxon.Klaxon -import com.beust.klaxon.Parser import id.walt.auditor.VerificationPolicyResult import id.walt.common.resolveContentToFile -import id.walt.credentials.w3c.JsonConverter -import kotlinx.serialization.json.buildJsonObject import mu.KotlinLogging -import java.io.File object OPAPolicyEngine : PolicyEngine { private val log = KotlinLogging.logger {} @@ -37,7 +32,8 @@ object OPAPolicyEngine : PolicyEngine { val output = p.inputStream.reader().use { it.readText() } p.waitFor() log.debug("rego eval output: {}", output) - return VerificationPolicyResult(Klaxon().parseArray(output)?.all { it } ?: false) + return (Klaxon().parseArray(output)?.all { it } ?: false).takeIf { it } + ?.let { VerificationPolicyResult.success() } ?: VerificationPolicyResult.failure() } finally { if (regoFile.exists() && regoFile.name.startsWith(TEMP_PREFIX)) { regoFile.delete() diff --git a/src/main/kotlin/id/walt/auditor/policies/CredentialPropertyVerificationPolicies.kt b/src/main/kotlin/id/walt/auditor/policies/CredentialPropertyVerificationPolicies.kt index e19b45db0..f6300cd95 100644 --- a/src/main/kotlin/id/walt/auditor/policies/CredentialPropertyVerificationPolicies.kt +++ b/src/main/kotlin/id/walt/auditor/policies/CredentialPropertyVerificationPolicies.kt @@ -18,30 +18,30 @@ private val dateFormatter = class IssuedDateBeforePolicy : SimpleVerificationPolicy() { override val description: String = "Verify by issuance date" override fun doVerify(vc: VerifiableCredential): VerificationPolicyResult { - return VerificationPolicyResult(when (vc) { + return when (vc) { is VerifiablePresentation -> true else -> parseDate(vc.issued).let { it != null && it.before(Date()) } - }) + }.takeIf { it }?.let { VerificationPolicyResult.success() } ?: VerificationPolicyResult.failure() } } class ValidFromBeforePolicy : SimpleVerificationPolicy() { override val description: String = "Verify by valid from" override fun doVerify(vc: VerifiableCredential): VerificationPolicyResult { - return VerificationPolicyResult(when (vc) { + return when (vc) { is VerifiablePresentation -> true else -> parseDate(vc.validFrom).let { it != null && it.before(Date()) } - }) + }.takeIf { it }?.let { VerificationPolicyResult.success() } ?: VerificationPolicyResult.failure() } } class ExpirationDateAfterPolicy : SimpleVerificationPolicy() { override val description: String = "Verify by expiration date" override fun doVerify(vc: VerifiableCredential): VerificationPolicyResult { - return VerificationPolicyResult(when (vc) { + return when (vc) { is VerifiablePresentation -> true else -> parseDate(vc.expirationDate).let { it == null || it.after(Date()) } - }) + }.takeIf { it }?.let { VerificationPolicyResult.success() } ?: VerificationPolicyResult.failure() } } @@ -92,7 +92,8 @@ class ChallengePolicy(challengeArg: ChallengePolicyArg) : override val description: String = "Verify challenge" override fun doVerify(vc: VerifiableCredential): VerificationPolicyResult { - return VerificationPolicyResult(vc.challenge?.let { argument.challenges.contains(it) } ?: false) + return (vc.challenge?.let { argument.challenges.contains(it) } ?: false).takeIf { it } + ?.let { VerificationPolicyResult.success() } ?: VerificationPolicyResult.failure() } override val applyToVC: Boolean diff --git a/src/main/kotlin/id/walt/auditor/policies/EbsiVerificationPolicies.kt b/src/main/kotlin/id/walt/auditor/policies/EbsiVerificationPolicies.kt index 937c9db15..3cb19c837 100644 --- a/src/main/kotlin/id/walt/auditor/policies/EbsiVerificationPolicies.kt +++ b/src/main/kotlin/id/walt/auditor/policies/EbsiVerificationPolicies.kt @@ -52,7 +52,8 @@ class EbsiTrustedIssuerDidPolicy : SimpleVerificationPolicy() { override val description: String = "Verify by trusted issuer did" override fun doVerify(vc: VerifiableCredential): VerificationPolicyResult { return try { - VerificationPolicyResult(DidService.loadOrResolveAnyDid(vc.issuerId!!) != null) + DidService.loadOrResolveAnyDid(vc.issuerId!!)?.let { VerificationPolicyResult.success() } + ?: VerificationPolicyResult.failure() } catch (e: ClientRequestException) { VerificationPolicyResult.failure( IllegalArgumentException( @@ -147,7 +148,7 @@ class EbsiTrustedIssuerRegistryPolicy(registryArg: EbsiTrustedIssuerRegistryPoli class EbsiTrustedSubjectDidPolicy : SimpleVerificationPolicy() { override val description: String = "Verify by trusted subject did" override fun doVerify(vc: VerifiableCredential): VerificationPolicyResult { - return VerificationPolicyResult(vc.subjectId?.let { + return (vc.subjectId?.let { if (it.isEmpty()) true else try { DidService.loadOrResolveAnyDid(it) != null @@ -155,7 +156,7 @@ class EbsiTrustedSubjectDidPolicy : SimpleVerificationPolicy() { if (!e.message.contains("did must be a valid DID") && !e.message.contains("Identifier Not Found")) throw e false } - } ?: false) + } ?: false).takeIf { it }?.let { VerificationPolicyResult.success() } ?: VerificationPolicyResult.failure() } } diff --git a/src/main/kotlin/id/walt/auditor/policies/SignaturePolicy.kt b/src/main/kotlin/id/walt/auditor/policies/SignaturePolicy.kt index b173dba08..dc5e1d5c1 100644 --- a/src/main/kotlin/id/walt/auditor/policies/SignaturePolicy.kt +++ b/src/main/kotlin/id/walt/auditor/policies/SignaturePolicy.kt @@ -16,12 +16,10 @@ class SignaturePolicy : SimpleVerificationPolicy() { override fun doVerify(vc: VerifiableCredential) = runCatching { log.debug { "is jwt: ${vc.jwt != null}" } - VerificationPolicyResult( - vc.verifyByFormatType( - { jwtCredentialService.verify(it) }, - { jsonLdCredentialService.verify(it) } - ).verified - ) + vc.verifyByFormatType( + { jwtCredentialService.verify(it) }, + { jsonLdCredentialService.verify(it) } + ).verified.takeIf { it }?.let { VerificationPolicyResult.success() } ?: VerificationPolicyResult.failure() }.getOrElse { VerificationPolicyResult.failure(it) } diff --git a/src/main/kotlin/id/walt/auditor/policies/VerifiablePresentationsPolicies.kt b/src/main/kotlin/id/walt/auditor/policies/VerifiablePresentationsPolicies.kt index c0776378c..2a8bda838 100644 --- a/src/main/kotlin/id/walt/auditor/policies/VerifiablePresentationsPolicies.kt +++ b/src/main/kotlin/id/walt/auditor/policies/VerifiablePresentationsPolicies.kt @@ -11,11 +11,11 @@ class PresentationDefinitionPolicy(presentationDefinition: PresentationDefinitio ParameterizedVerificationPolicy(presentationDefinition) { override val description: String = "Verify that verifiable presentation complies with presentation definition" override fun doVerify(vc: VerifiableCredential): VerificationPolicyResult { - return VerificationPolicyResult(if (vc is VerifiablePresentation) { + return (if (vc is VerifiablePresentation) { argument.input_descriptors.all { desc -> vc.verifiableCredential?.any { cred -> OIDCUtils.matchesInputDescriptor(cred, desc) } ?: false } - } else false) + } else false).takeIf { it }?.let { VerificationPolicyResult.success() } ?: VerificationPolicyResult.failure() } override var applyToVC: Boolean = false diff --git a/src/main/kotlin/id/walt/credentials/w3c/schema/NetworkntSchemaValidator.kt b/src/main/kotlin/id/walt/credentials/w3c/schema/NetworkntSchemaValidator.kt index c8ef7ce7c..3e5ffb0ed 100644 --- a/src/main/kotlin/id/walt/credentials/w3c/schema/NetworkntSchemaValidator.kt +++ b/src/main/kotlin/id/walt/credentials/w3c/schema/NetworkntSchemaValidator.kt @@ -19,6 +19,8 @@ class NetworkntSchemaValidator(versionFlag: SpecVersion.VersionFlag, schema: Str log.debug { "Could not validate vc against schema. The validation errors are:" } errors.forEach { log.debug { it } } } - return VerificationPolicyResult(errors.isEmpty(), errors.map { SchemaViolationException(it.toString()) }) + return errors.takeIf { it.isEmpty() }?.let { + VerificationPolicyResult.success() + } ?: VerificationPolicyResult.failure(*errors.map { SchemaViolationException(it.toString()) }.toTypedArray()) } } diff --git a/src/main/kotlin/id/walt/credentials/w3c/schema/PWallSchemaValidator.kt b/src/main/kotlin/id/walt/credentials/w3c/schema/PWallSchemaValidator.kt index d376c4a28..f279c90df 100644 --- a/src/main/kotlin/id/walt/credentials/w3c/schema/PWallSchemaValidator.kt +++ b/src/main/kotlin/id/walt/credentials/w3c/schema/PWallSchemaValidator.kt @@ -16,8 +16,10 @@ class PWallSchemaValidator(schema: String) : SchemaValidator { log.debug { "Could not validate vc against schema. The validation errors are:" } errors.forEach { log.debug { it } } } - return VerificationPolicyResult(errors.isEmpty(), errors.map { - SchemaViolationException(it.error) - }) + return errors.takeIf { it.isEmpty() }?.let { VerificationPolicyResult.success() } ?: VerificationPolicyResult.failure( + *errors.map { + SchemaViolationException(it.error) + }.toTypedArray() + ) } } diff --git a/src/test/kotlin/id/walt/auditor/AuditorTest.kt b/src/test/kotlin/id/walt/auditor/AuditorTest.kt index ff9fda737..e26017dd9 100644 --- a/src/test/kotlin/id/walt/auditor/AuditorTest.kt +++ b/src/test/kotlin/id/walt/auditor/AuditorTest.kt @@ -93,7 +93,7 @@ class AuditorCommandTest : StringSpec() { res.policyResults.keys shouldContainAll policyList.map { it.id } - res.policyResults.values.forEach { it.result shouldBe true } + res.policyResults.values.forEach { it.isSuccess shouldBe true } } "2. verify vc" { @@ -107,7 +107,7 @@ class AuditorCommandTest : StringSpec() { res.policyResults.keys shouldContainAll listOf(SignaturePolicy()).map { it.id } - res.policyResults.values.forEach { it.result shouldBe true } + res.policyResults.values.forEach { it.isSuccess shouldBe true } } "3. verify vc jwt" { @@ -121,7 +121,7 @@ class AuditorCommandTest : StringSpec() { res.policyResults.keys shouldContainAll listOf(SignaturePolicy()).map { it.id } - res.policyResults.values.forEach { it.result shouldBe true } + res.policyResults.values.forEach { it.isSuccess shouldBe true } } "4. verify vp jwt" { @@ -136,7 +136,7 @@ class AuditorCommandTest : StringSpec() { res.policyResults.keys shouldContainAll listOf(SignaturePolicy()).map { it.id } - res.policyResults.values.forEach { it.result shouldBe true } + res.policyResults.values.forEach { it.isSuccess shouldBe true } } // CLI call for testing VerifiableMandatePolicy diff --git a/src/test/kotlin/id/walt/services/vc/WaltIdJsonLdCredentialServiceTest.kt b/src/test/kotlin/id/walt/services/vc/WaltIdJsonLdCredentialServiceTest.kt index 8a3ab2336..08f2b9ea6 100644 --- a/src/test/kotlin/id/walt/services/vc/WaltIdJsonLdCredentialServiceTest.kt +++ b/src/test/kotlin/id/walt/services/vc/WaltIdJsonLdCredentialServiceTest.kt @@ -234,10 +234,10 @@ class WaltIdJsonLdCredentialServiceTest : AnnotationSpec() { ) val notParsableVc = "" - credentialService.validateSchemaTsr(noSchemaVc).result shouldBe false - credentialService.validateSchemaTsr(validVc).result shouldBe true - credentialService.validateSchemaTsr(invalidDataVc).result shouldBe false - credentialService.validateSchemaTsr(notParsableVc).result shouldBe false + credentialService.validateSchemaTsr(noSchemaVc).isSuccess shouldBe false + credentialService.validateSchemaTsr(validVc).isSuccess shouldBe true + credentialService.validateSchemaTsr(invalidDataVc).isSuccess shouldBe false + credentialService.validateSchemaTsr(notParsableVc).isSuccess shouldBe false } /*@Test diff --git a/src/test/kotlin/id/walt/services/vc/WaltIdJwtCredentialServiceTest.kt b/src/test/kotlin/id/walt/services/vc/WaltIdJwtCredentialServiceTest.kt index 599fbf202..89f83b3a0 100644 --- a/src/test/kotlin/id/walt/services/vc/WaltIdJwtCredentialServiceTest.kt +++ b/src/test/kotlin/id/walt/services/vc/WaltIdJwtCredentialServiceTest.kt @@ -142,10 +142,10 @@ class WaltIdJwtCredentialServiceTest : AnnotationSpec() { ) val notParsableVc = "" - credentialService.validateSchemaTsr(noSchemaVc).result shouldBe true - credentialService.validateSchemaTsr(validVc).result shouldBe true - credentialService.validateSchemaTsr(invalidDataVc).result shouldBe false - credentialService.validateSchemaTsr(notParsableVc).result shouldBe false + credentialService.validateSchemaTsr(noSchemaVc).isSuccess shouldBe true + credentialService.validateSchemaTsr(validVc).isSuccess shouldBe true + credentialService.validateSchemaTsr(invalidDataVc).isSuccess shouldBe false + credentialService.validateSchemaTsr(notParsableVc).isSuccess shouldBe false } @Test