Skip to content

Commit

Permalink
Bruker signaturedetails fra cpa med signaturvalidering og generering
Browse files Browse the repository at this point in the history
  • Loading branch information
thburnett committed Oct 23, 2023
1 parent b056239 commit fe8fa43
Show file tree
Hide file tree
Showing 14 changed files with 129 additions and 133 deletions.
17 changes: 10 additions & 7 deletions cpa-repo/src/main/kotlin/no/nav/emottak/cpa/App.kt
Original file line number Diff line number Diff line change
Expand Up @@ -38,30 +38,33 @@ fun Application.myApplicationModule() {
call.respond(HttpStatusCode.OK,ValidationResult(true))
}

get("/cpa/{$CPA_ID}/her/{$HER_ID}/encryption/certificate") {
get("/cpa/{$CPA_ID}/party/{$PARTY_TYPE}/{$PARTY_ID}encryption/certificate") {
val cpaId = call.parameters[CPA_ID] ?: throw BadRequestException("Mangler $CPA_ID")
val herId = call.parameters[HER_ID] ?: throw BadRequestException("Mangler $HER_ID")
val partyType = call.parameters[PARTY_TYPE] ?: throw BadRequestException("Mangler $PARTY_TYPE")
val partyId = call.parameters[PARTY_ID] ?: throw BadRequestException("Mangler $PARTY_ID")
val cpa = getCpa(cpaId) ?: throw NotFoundException("Ingen CPA med ID $cpaId funnet")
val partyInfo = cpa.getHERPartyInfo(herId)
val partyInfo = cpa.getPartyInfoByTypeAndID(partyType, partyId)
call.respond(partyInfo.getCertificateForEncryption())
}

get("/cpa/{$CPA_ID}/her/{$HER_ID}/signing/certificate/{$ROLE}/{$SERVICE}/{$ACTION}/") {
get("/cpa/{$CPA_ID}/party/{$PARTY_TYPE}/{$PARTY_ID}/signing/certificate/{$ROLE}/{$SERVICE}/{$ACTION}") {
val cpaId = call.parameters[CPA_ID] ?: throw BadRequestException("Mangler $CPA_ID")
val herId = call.parameters[HER_ID] ?: throw BadRequestException("Mangler $HER_ID")
val partyType = call.parameters[PARTY_TYPE] ?: throw BadRequestException("Mangler $PARTY_TYPE")
val partyId = call.parameters[PARTY_ID] ?: throw BadRequestException("Mangler $PARTY_ID")
val role = call.parameters[ROLE] ?: throw BadRequestException("Mangler $ROLE")
val service = call.parameters[SERVICE] ?: throw BadRequestException("Mangler $SERVICE")
val action = call.parameters[ACTION] ?: throw BadRequestException("Mangler $ACTION")
val cpa = getCpa(cpaId) ?: throw NotFoundException("Ingen CPA med ID $cpaId funnet")
val partyInfo = cpa.getHERPartyInfo(herId)
val partyInfo = cpa.getPartyInfoByTypeAndID(partyType, partyId)

call.respond(partyInfo.getCertificateForSignatureValidation(role, service, action))
}
}
}

private const val CPA_ID = "cpaId"
private const val HER_ID = "herId"
private const val PARTY_TYPE = "partyType"
private const val PARTY_ID = "partyId"
private const val ROLE = "role"
private const val SERVICE = "service"
private const val ACTION = "action"
8 changes: 4 additions & 4 deletions cpa-repo/src/main/kotlin/no/nav/emottak/cpa/CPAUtil.kt
Original file line number Diff line number Diff line change
Expand Up @@ -104,13 +104,13 @@ fun DeliveryChannel.getHashFunction(): String
throw BadRequestException("Hash Function eksisterer ikke for DeliveryChannel")
}

fun CollaborationProtocolAgreement.getHERPartyInfo(herId: String): PartyInfo
fun CollaborationProtocolAgreement.getPartyInfoByTypeAndID(partyType: String, partyId: String): PartyInfo
{
return this.partyInfo.firstOrNull { partyInfo ->
partyInfo.partyId.any { partyId ->
partyId.type == "HER" && partyId.value == herId
partyInfo.partyId.any { party ->
party.type == partyType && party.value == partyId
}
} ?: throw NotFoundException("HER ID $herId eksisterer ikke i CPA")
} ?: throw NotFoundException("PartyID med type $partyType og id $partyId eksisterer ikke i CPA")
}

fun Certificate.getX509Certificate(): ByteArray {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,37 +15,24 @@ import no.nav.emottak.melding.model.PayloadRequest
import no.nav.emottak.melding.model.PayloadResponse
import no.nav.emottak.melding.model.SignatureDetails
import no.nav.emottak.melding.model.ValidationResult
import no.nav.emottak.util.createX509Certificate
import no.nav.emottak.util.decodeBase64
import org.apache.xml.security.algorithms.MessageDigestAlgorithm
import org.apache.xml.security.signature.XMLSignature
import org.oasis_open.committees.ebxml_msg.schema.msg_header_2_0.MessageHeader
import java.security.cert.X509Certificate


private val httpClientUtil = HttpClientUtil()
private const val payloadProcessorEndpoint = "http://payload-processor/payload"
private const val validatorEndpoint = "https://cpa-repo.intern.dev.nav.no/validate"
private const val cpaRepoEndpoint = "http://cpa-repo"
private const val validatorEndpoint = "$cpaRepoEndpoint/validate"

fun postPayloadRequest(payloadRequest: PayloadRequest): PayloadResponse = runBlocking {
httpClientUtil.postPayloadRequest(payloadRequest)
}


fun SignatureDetails.getPublicSigningCertificate(): X509Certificate {
return createX509Certificate(this.certificate)
fun getPublicSigningDetails(messageHeader: MessageHeader): SignatureDetails = runBlocking {
getPublicSigningDetails(messageHeader.cpaId, messageHeader.from.partyId[0].type, messageHeader.from.partyId[0].value, messageHeader.service.value, messageHeader.action, messageHeader.from.role)
}

fun MessageHeader.getPublicSigningDetails(): SignatureDetails {
//TODO hent og valider sertifikat
val cert = decodeBase64("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".toByteArray())
//val timestamp = messageHeader.messageData.timestamp
//SecurityUtils.validateCertificate(trustStore, certificate, timestamp)
return SignatureDetails(
certificate = cert,
signatureAlgorithm = XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA256,
hashFunction = MessageDigestAlgorithm.ALGO_ID_DIGEST_SHA256
)
suspend fun getPublicSigningDetails(cpaId: String, partyType: String, partyId: String, service: String, action: String, role: String): SignatureDetails {
return httpClientUtil.makeHttpRequest("/cpa/$cpaId/party/$partyType/$partyId/signing/certificate/$role/$service/$action").body<SignatureDetails>()
}

class HttpClientUtil {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
*/
package no.nav.emottak.ebms.model

import no.nav.emottak.ebms.processing.SignatursjekkProcessor
import no.nav.emottak.ebms.processing.SignaturValidator
import no.nav.emottak.ebms.xml.xmlMarshaller
import no.nav.emottak.melding.model.SignatureDetails
import no.nav.emottak.util.marker
Expand Down Expand Up @@ -48,7 +48,7 @@ enum class DokumentType {
}

fun EbMSDocument.sjekkSignature(signatureDetails: SignatureDetails) {
SignatursjekkProcessor().validate(signatureDetails, this.dokument, this.attachments)
SignaturValidator().validate(signatureDetails, this.dokument, this.attachments)
}


Expand All @@ -67,13 +67,9 @@ fun EbMSDocument.buildEbmMessage(): EbMSBaseMessage {
}
}

fun EbMSDocument.checkSignature(signatureDetails: SignatureDetails, dokument: Document, attachments: List<EbMSAttachment>) {
SignatursjekkProcessor().validate(signatureDetails, dokument, attachments)
}

fun EbMSDocument.sendResponse(messageHeader: MessageHeader) {
log.info(messageHeader.marker(), "TODO return response message")
}
fun EbMSDocument.sendErrorResponse(messageHeader: MessageHeader) {
log.error(messageHeader.marker(), "TODO return response message")
log.warn(messageHeader.marker(), "TODO return error response message")
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
package no.nav.emottak.ebms.model

import no.nav.emottak.ebms.getPublicSigningDetails
import no.nav.emottak.ebms.processing.CPAValidationProcessor
import no.nav.emottak.ebms.processing.SertifikatsjekkProcessor
import no.nav.emottak.ebms.processing.SignatursjekkProcessor
import no.nav.emottak.ebms.processing.SignaturValidator
import no.nav.emottak.ebms.processing.signer
import no.nav.emottak.ebms.xml.xmlMarshaller
import no.nav.emottak.util.marker
Expand All @@ -25,14 +26,15 @@ class EbmsAcknowledgment(override val messageHeader: MessageHeader,
SertifikatsjekkProcessor(this)
)
.forEach { it.processWithEvents() }

val signatureDetails = getPublicSigningDetails(messageHeader)
SignaturValidator().validate(signatureDetails, this.dokument!!, emptyList())
}catch (ex: Exception) {
return
}
}

fun toEbmsDokument(): EbMSDocument {
log.info(this.messageHeader.marker(), "Oppretter Acknowledgment soap response")
log.info(this.messageHeader.marker(), "Oppretter Acknowledgment")
return ObjectFactory().createEnvelope()!!.also {
it.header = Header().also {
it.any.add(this.messageHeader)
Expand All @@ -41,8 +43,9 @@ class EbmsAcknowledgment(override val messageHeader: MessageHeader,
}.let {
xmlMarshaller.marshal(it)
}.let {
log.info(this.messageHeader.marker(), "Signerer Acknowledgment soap response")
EbMSDocument("contentID",it, emptyList()).signer(this.messageHeader)
log.info(this.messageHeader.marker(), "Signerer Acknowledgment (TODO)")
val signatureDetails = getPublicSigningDetails(this.messageHeader)
EbMSDocument("contentID",it, emptyList()).signer(signatureDetails)
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
package no.nav.emottak.ebms.model

import no.nav.emottak.ebms.getPublicSigningDetails
import no.nav.emottak.ebms.processing.CPAValidationProcessor
import no.nav.emottak.ebms.processing.SertifikatsjekkProcessor
import no.nav.emottak.ebms.processing.SignatursjekkProcessor
import no.nav.emottak.ebms.processing.SignaturValidator
import no.nav.emottak.ebms.processing.signer
import no.nav.emottak.ebms.xml.xmlMarshaller
import no.nav.emottak.util.marker
import org.oasis_open.committees.ebxml_msg.schema.msg_header_2_0.ErrorList
import org.oasis_open.committees.ebxml_msg.schema.msg_header_2_0.MessageHeader
import org.w3._2000._09.xmldsig_.SignatureType
import org.w3c.dom.Document
import org.xmlsoap.schemas.soap.envelope.Header
import org.xmlsoap.schemas.soap.envelope.ObjectFactory
Expand All @@ -23,15 +24,18 @@ class EbMSMessageError(
try {
listOf(
CPAValidationProcessor(this),
SertifikatsjekkProcessor(this),
SertifikatsjekkProcessor(this)
)
.forEach { it.processWithEvents() }
val signatureDetails = getPublicSigningDetails(messageHeader)
SignaturValidator().validate(signatureDetails, this.dokument!!, emptyList())
}catch (ex: Exception) {
return
}
}

fun toEbmsDokument(): EbMSDocument {
log.warn(this.messageHeader.marker(), "Oppretter ErrorList")
return ObjectFactory().createEnvelope()!!.also {
it.header = Header().also {
it.any.add(this.messageHeader)
Expand All @@ -40,7 +44,9 @@ class EbMSMessageError(
}.let {
xmlMarshaller.marshal(it)
}.let {
EbMSDocument("contentID",it, emptyList()).signer(this.messageHeader)
log.info(this.messageHeader.marker(), "Signerer ErrorList (TODO)")
val signatureDetails = getPublicSigningDetails(this.messageHeader)
EbMSDocument("contentID",it, emptyList()).signer(signatureDetails)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,20 @@ package no.nav.emottak.ebms.processing

import no.nav.emottak.ebms.model.EbMSDocument
import no.nav.emottak.ebms.xml.EbMSSigning
import no.nav.emottak.melding.model.SignatureDetails
import no.nav.emottak.util.marker
import no.nav.emottak.util.signatur.SignatureException
import org.apache.xml.security.exceptions.XMLSecurityException
import org.oasis_open.committees.ebxml_msg.schema.msg_header_2_0.MessageHeader
import org.slf4j.LoggerFactory

private val ebMSSigning = EbMSSigning()
val log = LoggerFactory.getLogger("no.nav.emottak.ebms.processing")
fun EbMSDocument.signer(messageHeader: MessageHeader): EbMSDocument {
fun EbMSDocument.signer(signatureDetails: SignatureDetails): EbMSDocument {
try {
//TODO Do something with signed document
ebMSSigning.sign(this.dokument, messageHeader, this.attachments)
ebMSSigning.sign(this, signatureDetails)
return this
} catch (e: XMLSecurityException) {
log.error(messageHeader.marker(), "Signering av ebms envelope feilet", e)
log.error(this.messageHeader().marker(), "Signering av ebms envelope feilet", e)
throw SignatureException("Signering av ebms envelope feilet", e)
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
package no.nav.emottak.ebms.processing

import no.nav.emottak.ebms.getPublicSigningCertificate
import no.nav.emottak.ebms.model.EbMSAttachment
import no.nav.emottak.ebms.model.EbMSBaseMessage
import no.nav.emottak.ebms.model.EbMSDocument
import no.nav.emottak.ebms.model.EbMSPayloadMessage
import no.nav.emottak.ebms.validation.CID_PREFIX
import no.nav.emottak.ebms.validation.EbMSAttachmentResolver
import no.nav.emottak.melding.model.SignatureDetails
Expand All @@ -19,7 +15,6 @@ import org.apache.xml.security.signature.SignedInfo
import org.apache.xml.security.signature.XMLSignature
import org.apache.xml.security.transforms.Transforms
import org.apache.xml.security.utils.Constants
import org.oasis_open.committees.ebxml_msg.schema.msg_header_2_0.MessageHeader
import org.w3c.dom.Document
import java.security.cert.X509Certificate

Expand All @@ -31,22 +26,22 @@ import java.security.cert.X509Certificate
* Mangler: 104 (sertifikatsjekk), 105 (sertifikatsjekk) //TODO
*
*/
class SignatursjekkProcessor() {
class SignaturValidator() {

init {
org.apache.xml.security.Init.init()
}

@Throws(SignatureException::class)
public fun validate(signatureDetails: SignatureDetails, dokument: Document, attachments: List<EbMSAttachment>) {
fun validate(signatureDetails: SignatureDetails, dokument: Document, attachments: List<EbMSAttachment>) {
//TODO Sjekk isNonRepudiation?
val xmlSignature = retrieveSignatureElement(dokument)
val certificateFraCPA = signatureDetails.getPublicSigningCertificate()
val certificateFraSignatur = xmlSignature.retrievePublicX509Certificate()
if (certificateFraSignatur != certificateFraCPA) throw SignatureException("Signert med annet sertifikat enn definert i CPA")
val xmlSignature = dokument.retrieveSignatureElement()
val sertfikatFraCPA = signatureDetails.retrievePublicX509Certificate()
val sertifikatFraSignatur = xmlSignature.retrievePublicX509Certificate()
if (sertifikatFraSignatur != sertfikatFraCPA) throw SignatureException("Signert med annet sertifikat enn definert i CPA")
try {
if (!verify(
certificateFraSignatur,
sertifikatFraSignatur,
xmlSignature,
attachments
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class DokumentValidator {
fun validate(dokument: EbMSDocument) {

val messageHeader = dokument.messageHeader()
val signaturedetails: SignatureDetails = messageHeader.getPublicSigningDetails()
val signaturedetails: SignatureDetails = getPublicSigningDetails(messageHeader)
val header = Header(messageHeader.messageData.messageId,
messageHeader.conversationId,
messageHeader.cpaId,
Expand All @@ -30,9 +30,5 @@ class DokumentValidator {
}
dokument.sjekkSignature(signaturedetails)





}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
package no.nav.emottak.ebms.xml

import jakarta.xml.soap.SOAPConstants
import no.nav.emottak.ebms.getPublicSigningDetails
import no.nav.emottak.ebms.model.EbMSAttachment
import no.nav.emottak.ebms.model.EbMSDocument
import no.nav.emottak.ebms.validation.CID_PREFIX
import no.nav.emottak.ebms.validation.EbMSAttachmentResolver
import no.nav.emottak.melding.model.SignatureDetails
import no.nav.emottak.util.createX509Certificate
import no.nav.emottak.util.crypto.getCertificateAlias
import no.nav.emottak.util.crypto.getKeyPair
Expand All @@ -14,7 +15,6 @@ import org.apache.xml.security.exceptions.XMLSecurityException
import org.apache.xml.security.signature.XMLSignature
import org.apache.xml.security.transforms.Transforms
import org.apache.xml.security.transforms.params.XPathContainer
import org.oasis_open.committees.ebxml_msg.schema.msg_header_2_0.MessageHeader
import org.w3c.dom.Document
import org.w3c.dom.NodeList
import java.security.cert.X509Certificate
Expand All @@ -25,14 +25,13 @@ class EbMSSigning {
private val SOAP_ENVELOPE = SOAPConstants.URI_NS_SOAP_1_1_ENVELOPE
private val SOAP_NEXT_ACTOR = SOAPConstants.URI_SOAP_ACTOR_NEXT

fun sign(document: Document, messageHeader: MessageHeader, attachments: List<EbMSAttachment> = emptyList()) {
val certificateDetails = messageHeader.getPublicSigningDetails()
fun sign(ebMSDocument: EbMSDocument, signatureDetails: SignatureDetails) {
sign(
document,
attachments,
createX509Certificate(certificateDetails.certificate),
certificateDetails.signatureAlgorithm,
certificateDetails.hashFunction
ebMSDocument.dokument,
ebMSDocument.attachments,
createX509Certificate(signatureDetails.certificate),
signatureDetails.signatureAlgorithm,
signatureDetails.hashFunction
)
}

Expand Down
Loading

0 comments on commit fe8fa43

Please sign in to comment.