From d161e0f60fde5b1c4bff4c717d6dd0474268e042 Mon Sep 17 00:00:00 2001 From: ballerina-bot Date: Mon, 14 Aug 2023 12:12:10 +0000 Subject: [PATCH 001/189] Move dependencies to stable version --- gradle.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle.properties b/gradle.properties index 3d64c9d..a82c272 100644 --- a/gradle.properties +++ b/gradle.properties @@ -18,7 +18,7 @@ stdlibUrlVersion=2.3.0 stdlibConstraintVersion=1.3.0 stdlibCryptoVersion=2.4.0 -stdlibLogVersion=2.8.1-20230718-085900-36c385c +stdlibLogVersion=2.8.1 stdlibOsVersion=1.7.0 stdlibTaskVersion=2.4.0 @@ -31,7 +31,7 @@ stdlibAuthVersion=2.9.0 stdlibJwtVersion=2.9.0 stdlibOAuth2Version=2.9.0 -stdlibHttpVersion=2.9.1-20230712-161400-d16a019 +stdlibHttpVersion=2.9.1 # Ballerinax Observer observeVersion=1.1.0 From 1cbf4b066bbe07fc9076fd431e8abc99291b3716 Mon Sep 17 00:00:00 2001 From: ballerina-bot Date: Mon, 14 Aug 2023 12:12:47 +0000 Subject: [PATCH 002/189] [Gradle Release Plugin] - pre tag commit: 'v0.1.0'. --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index a82c272..debe0b2 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,6 +1,6 @@ org.gradle.caching=true group=io.ballerina.stdlib -version=0.1.0-SNAPSHOT +version=0.1.0 checkstylePluginVersion=8.18 spotbugsPluginVersion=4.5.1 From 06fe3739641abc3226c53a9659b995e2d1c94a6c Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Fri, 15 Sep 2023 10:15:40 +0530 Subject: [PATCH 003/189] [Automated] Update the native jar versions --- ballerina/Dependencies.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index 4903bb7..b7a9802 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -5,7 +5,7 @@ [ballerina] dependencies-toml-version = "2" -distribution-version = "2201.8.0-20230726-145300-b2bdf796" +distribution-version = "2201.8.0-20230908-135700-74a59dff" [[package]] org = "ballerina" From 6d37464cdba6518a86198d3433975db6457bb7ba Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Fri, 15 Sep 2023 10:17:17 +0530 Subject: [PATCH 004/189] [Automated] Update the native jar versions --- ballerina/Dependencies.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index 79ca10a..b855a7c 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -41,7 +41,7 @@ dependencies = [ [[package]] org = "ballerina" name = "crypto" -version = "2.4.0" +version = "2.4.1" dependencies = [ {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "time"} @@ -50,7 +50,7 @@ dependencies = [ [[package]] org = "ballerina" name = "file" -version = "1.8.0" +version = "1.8.1" dependencies = [ {org = "ballerina", name = "io"}, {org = "ballerina", name = "jballerina.java"}, @@ -61,7 +61,7 @@ dependencies = [ [[package]] org = "ballerina" name = "http" -version = "2.9.1" +version = "2.9.3" dependencies = [ {org = "ballerina", name = "auth"}, {org = "ballerina", name = "cache"}, From f184394d5ae82a4460444da6b1ac739f72d5890e Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Fri, 15 Sep 2023 10:18:39 +0530 Subject: [PATCH 005/189] [Automated] Update the native jar versions --- ballerina/Dependencies.toml | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index b855a7c..5f871af 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -201,17 +201,6 @@ dependencies = [ {org = "ballerina", name = "jballerina.java"} ] -[[package]] -org = "ballerina" -name = "lang.xml" -version = "0.0.0" -dependencies = [ - {org = "ballerina", name = "jballerina.java"} -] -modules = [ - {org = "ballerina", packageName = "lang.xml", moduleName = "lang.xml"} -] - [[package]] org = "ballerina" name = "log" @@ -272,7 +261,6 @@ name = "soap" version = "0.1.0" dependencies = [ {org = "ballerina", name = "http"}, - {org = "ballerina", name = "lang.xml"}, {org = "ballerina", name = "mime"}, {org = "ballerina", name = "test"} ] From 2c01c3a4a6595a57d7e84d81f4d60c0cd49436d3 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Fri, 15 Sep 2023 10:22:16 +0530 Subject: [PATCH 006/189] [Automated] Update the native jar versions --- ballerina/Ballerina.toml | 4 ++-- ballerina/Dependencies.toml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ballerina/Ballerina.toml b/ballerina/Ballerina.toml index a3dfcde..567551d 100644 --- a/ballerina/Ballerina.toml +++ b/ballerina/Ballerina.toml @@ -1,10 +1,10 @@ [package] org = "ballerina" name = "soap" -version = "0.1.0" +version = "0.1.1" authors = ["Ballerina"] keywords = ["soap"] repository = "https://github.com/ballerina-platform/module-ballerina-soap" icon = "icon.png" license = ["Apache-2.0"] -distribution = "2201.5.0" +distribution = "2201.7.2" diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index 5f871af..de8298b 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -5,7 +5,7 @@ [ballerina] dependencies-toml-version = "2" -distribution-version = "2201.7.0" +distribution-version = "2201.7.2" [[package]] org = "ballerina" @@ -258,7 +258,7 @@ dependencies = [ [[package]] org = "ballerina" name = "soap" -version = "0.1.0" +version = "0.1.1" dependencies = [ {org = "ballerina", name = "http"}, {org = "ballerina", name = "mime"}, From c064aced34543776e1e23998af64c4a5ba86f875 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Fri, 15 Sep 2023 10:24:05 +0530 Subject: [PATCH 007/189] Update lang version to 2201.7.2 --- build-config/resources/Ballerina.toml | 2 +- gradle.properties | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/build-config/resources/Ballerina.toml b/build-config/resources/Ballerina.toml index f99a1fc..e41a025 100644 --- a/build-config/resources/Ballerina.toml +++ b/build-config/resources/Ballerina.toml @@ -7,4 +7,4 @@ keywords = ["soap"] repository = "https://github.com/ballerina-platform/module-ballerina-soap" icon = "icon.png" license = ["Apache-2.0"] -distribution = "2201.5.0" +distribution = "2201.7.2" diff --git a/gradle.properties b/gradle.properties index debe0b2..5930551 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,6 +1,6 @@ org.gradle.caching=true group=io.ballerina.stdlib -version=0.1.0 +version=0.1.1-SNAPSHOT checkstylePluginVersion=8.18 spotbugsPluginVersion=4.5.1 @@ -9,7 +9,7 @@ downloadPluginVersion=4.0.4 releasePluginVersion=2.6.0 ballerinaGradlePluginVersion=1.0.0 -ballerinaLangVersion=2201.7.0 +ballerinaLangVersion=2201.7.2 #stdlib dependencies stdlibIoVersion=1.5.0 From 1f6bdf3a189a38af2133b57012cccf665586a5d3 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Fri, 15 Sep 2023 10:26:10 +0530 Subject: [PATCH 008/189] Refactor APIs to accept SOAP action as a parameter --- ballerina/soap.bal | 22 ++++--- ballerina/soap_utils.bal | 124 ++++++++++----------------------------- 2 files changed, 44 insertions(+), 102 deletions(-) diff --git a/ballerina/soap.bal b/ballerina/soap.bal index 5bd7ebe..61e4e25 100644 --- a/ballerina/soap.bal +++ b/ballerina/soap.bal @@ -29,8 +29,8 @@ public enum SoapVersion { # # + soapVersion - SOAP version public type ClientConfiguration record {| - *http:ClientConfiguration; - SoapVersion soapVersion = SOAP11; + *http:ClientConfiguration; + SoapVersion soapVersion = SOAP11; |}; # Object for the basic SOAP client endpoint. @@ -46,7 +46,7 @@ public isolated client class Client { public function init(string url, *ClientConfiguration config) returns Error? { self.soapVersion = config.soapVersion; do { - self.soapClient = check new (url,retrieveHttpClientConfig(config)); + self.soapClient = check new (url, retrieveHttpClientConfig(config)); } on fail var err { return error Error("Failed to initialize soap client", err); } @@ -54,24 +54,28 @@ public isolated client class Client { # Sends SOAP request and expects a response. # ```ballerina - # xml|mime:Entity[] response = check soapClient->sendReceive(body); + # xml|mime:Entity[] response = check soapClient->sendReceive(body, action); # ``` # # + body - SOAP request body as an `XML` or `mime:Entity[]` to work with SOAP attachments + # + action - SOAP action as a `string` + # + headers - SOAP headers as a `map` # + return - If successful, returns the response. Else, returns an error - remote function sendReceive(xml|mime:Entity[] body) returns xml|mime:Entity[]|Error { - return sendReceive(self.soapVersion, body, self.soapClient); + remote function sendReceive(xml|mime:Entity[] body, string action, map headers = {}) returns xml|mime:Entity[]|Error { + return sendReceive(self.soapVersion, body, self.soapClient, action, headers); } # Fires and forgets requests. Sends the request without the possibility of any response from the # service (even an error). # ```ballerina - # check soapClient->sendOnly(body); + # check soapClient->sendOnly(body, action); # ``` # # + body - SOAP request body as an `XML` or `mime:Entity[]` to work with SOAP attachments + # + action - SOAP action as a `string` + # + headers - SOAP headers as a `map` # + return - If successful, returns `nil`. Else, returns an error - remote function sendOnly(xml|mime:Entity[] body) returns Error? { - return sendOnly(self.soapVersion, body, self.soapClient); + remote function sendOnly(xml|mime:Entity[] body, string action, map headers = {}) returns Error? { + return sendOnly(self.soapVersion, body, self.soapClient, action, headers); } } diff --git a/ballerina/soap_utils.bal b/ballerina/soap_utils.bal index 0f36273..7567ff5 100644 --- a/ballerina/soap_utils.bal +++ b/ballerina/soap_utils.bal @@ -15,96 +15,39 @@ // under the License. import ballerina/http; -import ballerina/lang.'xml as xmllib; import ballerina/mime; -# Provides an empty SOAP envelope for the given SOAP version. -# -# + soapVersion - The SOAP version of the request -# + return - XML with the empty SOAP envelope -function createSoapEnvelop(SoapVersion soapVersion) returns xmllib:Element { - if soapVersion == SOAP11 { - return xml ` - `; - } else { - return xml ` - `; - } -} - -# Provides the SOAP headers in the request as XML. -# -# + soapVersion - The SOAP version of the request -# + return - XML with the empty SOAP header -function createSoapHeader(SoapVersion soapVersion) returns xml { - xmllib:Element headersRoot; - if soapVersion == SOAP11 { - headersRoot = xml ``; - } else { - headersRoot = xml ``; - } - return headersRoot; -} - -# Provides the SOAP body in the request as XML. -# -# + payload - The payload to be sent -# + soapVersion - The SOAP version of the request -# + return - XML with the SOAP body -function createSoapBody(xml payload, SoapVersion soapVersion) returns xml { - xmllib:Element bodyRoot; - if soapVersion == SOAP11 { - bodyRoot = xml ``; - } else { - bodyRoot = xml ``; - } - bodyRoot.setChildren(payload); - return bodyRoot; -} - -# Prepares a SOAP envelope with the XML to be sent. +# Creates a SOAP Request as an `http:Request` # # + soapAction - SOAP action # + body - SOAP request body as an `XML` or `mime:Entity[]` to work with soap attachments # + soapVersion - The SOAP version of the request -# + return - The SOAP Request sent as `http:Request` with the SOAP envelope -function fillSoapEnvelope(SoapVersion soapVersion, xml | mime:Entity[] body, string? soapAction = ()) +# + headers - SOAP headers as a `map` +# + return - The SOAP Request sent as `http:Request` +function createHttpRequest(SoapVersion soapVersion, xml|mime:Entity[] body, string soapAction, map headers = {}) returns http:Request { - xml soapPayload = createSoapHeader(soapVersion); http:Request req = new; - var requestPayload = body; - if requestPayload is xml { - xml bodyPayload = createSoapBody(requestPayload, soapVersion); - soapPayload = soapPayload + bodyPayload; - - xmllib:Element soapEnv = createSoapEnvelop(soapVersion); - soapEnv.setChildren(soapPayload); - req.setXmlPayload(soapEnv); + if body is xml { + req.setXmlPayload(body); } else { - req.setBodyParts(requestPayload); + req.setBodyParts(body); } if soapVersion == SOAP11 { req.setHeader(mime:CONTENT_TYPE, mime:TEXT_XML); - if soapAction is string { - req.addHeader("SOAPAction", soapAction); - } + req.addHeader("SOAPAction", soapAction); } else { - if soapAction is string { - map stringMap = {}; - stringMap["action"] = "\"" + soapAction + "\""; - var mediaType = mime:getMediaType(mime:APPLICATION_SOAP_XML); - if mediaType is mime:MediaType { - mediaType.parameters = stringMap; - req.setHeader(mime:CONTENT_TYPE, mediaType.toString()); - } - } else { - req.setHeader(mime:CONTENT_TYPE, mime:APPLICATION_SOAP_XML); + map stringMap = {}; + stringMap["action"] = "\"" + soapAction + "\""; + var mediaType = mime:getMediaType(mime:APPLICATION_SOAP_XML); + if mediaType is mime:MediaType { + mediaType.parameters = stringMap; + req.setHeader(mime:CONTENT_TYPE, mediaType.toString()); } } + foreach string key in headers.keys() { + req.addHeader(key, headers[key].toBalString()); + } + return req; } @@ -113,42 +56,37 @@ returns http:Request { # + response - The request to be sent # + soapVersion - The SOAP version of the request # + return - The SOAP response created from the `http:Response` or the `error` object when reading the payload -function createSoapResponse(http:Response response, SoapVersion soapVersion) returns xml | error { +function createSoapResponse(http:Response response, SoapVersion soapVersion) returns xml|error { xml payload = check response.getXmlPayload(); xmlns "http://schemas.xmlsoap.org/soap/envelope/" as soap11; xmlns "http://www.w3.org/2003/05/soap-envelope" as soap12; - xml soapResponsePayload; - if soapVersion == SOAP11 { - soapResponsePayload = payload/; - } else { - soapResponsePayload = payload/; - } - return soapResponsePayload; + return soapVersion == SOAP11 ? payload/ : payload/; } string path = ""; -function sendReceive(SoapVersion soapVersion, xml|mime:Entity[] body, http:Client httpClient, string? soapAction = ()) returns xml|Error { - http:Request req = fillSoapEnvelope(soapVersion, body, soapAction = soapAction); +function sendReceive(SoapVersion soapVersion, xml|mime:Entity[] body, http:Client httpClient, string soapAction, map headers = {}) returns xml|Error { + http:Request req = createHttpRequest(soapVersion, body, soapAction, headers); http:Response response; do { - response = check httpClient->post(path, req); + response = check httpClient->post(path, req); } on fail var err { - return error Error("Failed to receive soap response", err); + return error Error("Failed to receive soap response", err); } do { - return check createSoapResponse(response, soapVersion); + return check createSoapResponse(response, soapVersion); } on fail var err { - return error Error("Failed to create soap response", err); + return error Error("Failed to create soap response", err); } } -function sendOnly(SoapVersion soapVersion, xml|mime:Entity[] body, http:Client httpClient, string? soapAction = ()) returns Error? { - http:Request req = fillSoapEnvelope(SOAP11, body, soapAction = soapAction); + +function sendOnly(SoapVersion soapVersion, xml|mime:Entity[] body, http:Client httpClient, string soapAction, map headers = {}) returns Error? { + http:Request req = createHttpRequest(SOAP11, body, soapAction, headers); do { - http:Response _ = check httpClient->post(path, req); + http:Response _ = check httpClient->post(path, req); } on fail var err { - return error Error("Failed to create soap response", err); + return error Error("Failed to create soap response", err); } } From 5d28d3cd5f99eb8583447c12445487670af4cffa Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Fri, 15 Sep 2023 10:27:24 +0530 Subject: [PATCH 009/189] Update test cases for compatibility with modified APIs --- ballerina/tests/basic_client_test.bal | 118 ++++++++++++++++++++------ 1 file changed, 92 insertions(+), 26 deletions(-) diff --git a/ballerina/tests/basic_client_test.bal b/ballerina/tests/basic_client_test.bal index cce0d92..db15011 100644 --- a/ballerina/tests/basic_client_test.bal +++ b/ballerina/tests/basic_client_test.bal @@ -19,54 +19,120 @@ import ballerina/mime; @test:Config {} function testSendReceive11() returns error? { - Client soapClient = check new("http://ws.cdyne.com/phoneverify/phoneverify.asmx?wsdl"); + Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL"); - xml body = xml ` - 18006785432 - 0 - `; + xml body = xml ` + + + 2 + 3 + + + `; - xml|mime:Entity[] response = check soapClient->sendReceive(body); + xml|mime:Entity[] response = check soapClient->sendReceive(body, "http://tempuri.org/Add"); - xml expected = xml `Toll FreetrueAssigned to a code holder for normal use.TF180067854328006785432United StatesLandlineLandlineUnknownTFfalse`; + xml expected = xml `5`; test:assertEquals(response, expected); } @test:Config {} function testSendReceive12() returns error? { - Client soapClient = check new("http://ws.cdyne.com/phoneverify/phoneverify.asmx?wsdl", soapVersion = SOAP12); + Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL", soapVersion = SOAP12); - xml body = xml ` - 18006785432 - 0 - `; + xml body = xml ` + + + 2 + 3 + + + `; - xml|mime:Entity[] response = check soapClient->sendReceive(body); + xml|mime:Entity[] response = check soapClient->sendReceive(body, "http://tempuri.org/Add"); - xml expected = xml `Toll FreetrueAssigned to a code holder for normal use.TF180067854328006785432United StatesLandlineLandlineUnknownTFfalse`; + xml expected = xml `5`; test:assertEquals(response, expected); } @test:Config {} function testSendOnly11() returns error? { - Client soapClient = check new("http://ws.cdyne.com/phoneverify/phoneverify.asmx?wsdl"); + Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL"); - xml body = xml ` - 18006785432 - 0 - `; + xml body = xml ` + + + 2 + 3 + + + `; - _ = check soapClient->sendOnly(body); + _ = check soapClient->sendOnly(body, "http://tempuri.org/Add"); } @test:Config {} function testSendOnly12() returns error? { - Client soapClient = check new("http://ws.cdyne.com/phoneverify/phoneverify.asmx?wsdl", soapVersion = SOAP12); + Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL", soapVersion = SOAP12); - xml body = xml ` - 18006785432 - 0 - `; + xml body = xml ` + + + 2 + 3 + + + `; - _ = check soapClient->sendOnly(body); + _ = check soapClient->sendOnly(body, "http://tempuri.org/Add"); +} + +@test:Config {} +function testSendReceive11WithHeaders() returns error? { + Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL"); + + xml body = xml ` + + + 2 + 3 + + + `; + + xml|mime:Entity[] response = check soapClient->sendReceive(body, "http://tempuri.org/Add", {foo: ["bar1", "bar2"]}); + + xml expected = xml `5`; + test:assertEquals(response, expected); +} + +@test:Config {} +function testSendReceive12WithHeaders() returns error? { + Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL", soapVersion = SOAP12); + + xml body = xml ` + + + 2 + 3 + + + `; + + xml|mime:Entity[] response = check soapClient->sendReceive(body, "http://tempuri.org/Add", {foo: ["bar1", "bar2"]}); + + xml expected = xml `5`; + test:assertEquals(response, expected); } From f14011ab148b1641417a6b7972ddef60b8962d93 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Fri, 15 Sep 2023 10:41:28 +0530 Subject: [PATCH 010/189] [Automated] Update the native jar versions --- ballerina/Dependencies.toml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index de8298b..f9a3b72 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -98,6 +98,9 @@ dependencies = [ {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "lang.value"} ] +modules = [ + {org = "ballerina", packageName = "io", moduleName = "io"} +] [[package]] org = "ballerina" @@ -261,6 +264,7 @@ name = "soap" version = "0.1.1" dependencies = [ {org = "ballerina", name = "http"}, + {org = "ballerina", name = "io"}, {org = "ballerina", name = "mime"}, {org = "ballerina", name = "test"} ] From 22f1571d9be39b43645f6f39a13cb45101f29dd2 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Fri, 15 Sep 2023 11:06:32 +0530 Subject: [PATCH 011/189] [Automated] Update the native jar versions --- ballerina/Dependencies.toml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index f9a3b72..de8298b 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -98,9 +98,6 @@ dependencies = [ {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "lang.value"} ] -modules = [ - {org = "ballerina", packageName = "io", moduleName = "io"} -] [[package]] org = "ballerina" @@ -264,7 +261,6 @@ name = "soap" version = "0.1.1" dependencies = [ {org = "ballerina", name = "http"}, - {org = "ballerina", name = "io"}, {org = "ballerina", name = "mime"}, {org = "ballerina", name = "test"} ] From a951771cddf0e33375849bf9501d9b4ff35f747a Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Fri, 15 Sep 2023 11:24:05 +0530 Subject: [PATCH 012/189] [Automated] Update the native jar versions --- ballerina/Dependencies.toml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index de8298b..f9a3b72 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -98,6 +98,9 @@ dependencies = [ {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "lang.value"} ] +modules = [ + {org = "ballerina", packageName = "io", moduleName = "io"} +] [[package]] org = "ballerina" @@ -261,6 +264,7 @@ name = "soap" version = "0.1.1" dependencies = [ {org = "ballerina", name = "http"}, + {org = "ballerina", name = "io"}, {org = "ballerina", name = "mime"}, {org = "ballerina", name = "test"} ] From 7f332ea7127bb42d89893d02ea237b70f4df3190 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Fri, 15 Sep 2023 12:41:08 +0530 Subject: [PATCH 013/189] [Automated] Update the native jar versions --- ballerina/Dependencies.toml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index f9a3b72..de8298b 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -98,9 +98,6 @@ dependencies = [ {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "lang.value"} ] -modules = [ - {org = "ballerina", packageName = "io", moduleName = "io"} -] [[package]] org = "ballerina" @@ -264,7 +261,6 @@ name = "soap" version = "0.1.1" dependencies = [ {org = "ballerina", name = "http"}, - {org = "ballerina", name = "io"}, {org = "ballerina", name = "mime"}, {org = "ballerina", name = "test"} ] From 318e44caacc4de678eb6677c4a5f2714f0ae9eb2 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Fri, 15 Sep 2023 13:26:44 +0530 Subject: [PATCH 014/189] Set the SOAP action parameter defaultable --- ballerina/soap.bal | 8 ++++---- ballerina/soap_utils.bal | 26 ++++++++++++++++---------- 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/ballerina/soap.bal b/ballerina/soap.bal index 61e4e25..9cf4139 100644 --- a/ballerina/soap.bal +++ b/ballerina/soap.bal @@ -54,28 +54,28 @@ public isolated client class Client { # Sends SOAP request and expects a response. # ```ballerina - # xml|mime:Entity[] response = check soapClient->sendReceive(body, action); + # xml|mime:Entity[] response = check soapClient->sendReceive(body); # ``` # # + body - SOAP request body as an `XML` or `mime:Entity[]` to work with SOAP attachments # + action - SOAP action as a `string` # + headers - SOAP headers as a `map` # + return - If successful, returns the response. Else, returns an error - remote function sendReceive(xml|mime:Entity[] body, string action, map headers = {}) returns xml|mime:Entity[]|Error { + remote function sendReceive(xml|mime:Entity[] body, string? action = (), map headers = {})returns xml|mime:Entity[]|Error { return sendReceive(self.soapVersion, body, self.soapClient, action, headers); } # Fires and forgets requests. Sends the request without the possibility of any response from the # service (even an error). # ```ballerina - # check soapClient->sendOnly(body, action); + # check soapClient->sendOnly(body); # ``` # # + body - SOAP request body as an `XML` or `mime:Entity[]` to work with SOAP attachments # + action - SOAP action as a `string` # + headers - SOAP headers as a `map` # + return - If successful, returns `nil`. Else, returns an error - remote function sendOnly(xml|mime:Entity[] body, string action, map headers = {}) returns Error? { + remote function sendOnly(xml|mime:Entity[] body, string? action = (), map headers = {}) returns Error? { return sendOnly(self.soapVersion, body, self.soapClient, action, headers); } } diff --git a/ballerina/soap_utils.bal b/ballerina/soap_utils.bal index 7567ff5..be26325 100644 --- a/ballerina/soap_utils.bal +++ b/ballerina/soap_utils.bal @@ -24,7 +24,7 @@ import ballerina/mime; # + soapVersion - The SOAP version of the request # + headers - SOAP headers as a `map` # + return - The SOAP Request sent as `http:Request` -function createHttpRequest(SoapVersion soapVersion, xml|mime:Entity[] body, string soapAction, map headers = {}) +function createHttpRequest(SoapVersion soapVersion, xml|mime:Entity[] body, string? soapAction, map headers = {}) returns http:Request { http:Request req = new; if body is xml { @@ -34,14 +34,20 @@ returns http:Request { } if soapVersion == SOAP11 { req.setHeader(mime:CONTENT_TYPE, mime:TEXT_XML); - req.addHeader("SOAPAction", soapAction); + if soapAction is string { + req.addHeader("SOAPAction", soapAction); + } } else { - map stringMap = {}; - stringMap["action"] = "\"" + soapAction + "\""; - var mediaType = mime:getMediaType(mime:APPLICATION_SOAP_XML); - if mediaType is mime:MediaType { - mediaType.parameters = stringMap; - req.setHeader(mime:CONTENT_TYPE, mediaType.toString()); + if soapAction is string { + map stringMap = {}; + stringMap["action"] = "\"" + soapAction + "\""; + var mediaType = mime:getMediaType(mime:APPLICATION_SOAP_XML); + if mediaType is mime:MediaType { + mediaType.parameters = stringMap; + req.setHeader(mime:CONTENT_TYPE, mediaType.toString()); + } + } else { + req.setHeader(mime:CONTENT_TYPE, mime:APPLICATION_SOAP_XML); } } foreach string key in headers.keys() { @@ -66,7 +72,7 @@ function createSoapResponse(http:Response response, SoapVersion soapVersion) ret string path = ""; -function sendReceive(SoapVersion soapVersion, xml|mime:Entity[] body, http:Client httpClient, string soapAction, map headers = {}) returns xml|Error { +function sendReceive(SoapVersion soapVersion, xml|mime:Entity[] body, http:Client httpClient, string? soapAction = (), map headers = {}) returns xml|Error { http:Request req = createHttpRequest(soapVersion, body, soapAction, headers); http:Response response; do { @@ -81,7 +87,7 @@ function sendReceive(SoapVersion soapVersion, xml|mime:Entity[] body, http:Clien } } -function sendOnly(SoapVersion soapVersion, xml|mime:Entity[] body, http:Client httpClient, string soapAction, map headers = {}) returns Error? { +function sendOnly(SoapVersion soapVersion, xml|mime:Entity[] body, http:Client httpClient, string? soapAction = (), map headers = {}) returns Error? { http:Request req = createHttpRequest(SOAP11, body, soapAction, headers); do { http:Response _ = check httpClient->post(path, req); From 0c9253031999bec6b7c5df29cadd1d0444920f27 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Fri, 15 Sep 2023 13:29:30 +0530 Subject: [PATCH 015/189] Add test cases for SOAP 1.2 requests without the action parameter --- ballerina/tests/basic_client_test.bal | 59 +++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/ballerina/tests/basic_client_test.bal b/ballerina/tests/basic_client_test.bal index db15011..528d223 100644 --- a/ballerina/tests/basic_client_test.bal +++ b/ballerina/tests/basic_client_test.bal @@ -136,3 +136,62 @@ function testSendReceive12WithHeaders() returns error? { xml expected = xml `5`; test:assertEquals(response, expected); } + +@test:Config {} +function testSendReceive12WithoutSoapAction() returns error? { + Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL", soapVersion = SOAP12); + + xml body = xml ` + + + 2 + 3 + + + `; + + xml|mime:Entity[] response = check soapClient->sendReceive(body); + + xml expected = xml `5`; + test:assertEquals(response, expected); +} + +@test:Config {} +function testSendOnly12WithoutSoapAction() returns error? { + Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL", soapVersion = SOAP12); + + xml body = xml ` + + + 2 + 3 + + + `; + + _ = check soapClient->sendOnly(body); +} + +@test:Config {} +function testSendReceive12IncludingHeadersWithoutSoapAction() returns error? { + Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL", soapVersion = SOAP12); + + xml body = xml ` + + + 2 + 3 + + + `; + + xml|mime:Entity[] response = check soapClient->sendReceive(body, (), {foo: ["bar1", "bar2"]}); + xml expected = xml `5`; + test:assertEquals(response, expected); +} From 8ab5a6ad37a4daa70dedf7c28db8799aa9da8a0a Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Fri, 15 Sep 2023 13:42:34 +0530 Subject: [PATCH 016/189] [Automated] Update the native jar versions --- ballerina/Ballerina.toml | 2 +- ballerina/Dependencies.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ballerina/Ballerina.toml b/ballerina/Ballerina.toml index 567551d..a0e2bc4 100644 --- a/ballerina/Ballerina.toml +++ b/ballerina/Ballerina.toml @@ -1,7 +1,7 @@ [package] org = "ballerina" name = "soap" -version = "0.1.1" +version = "0.2.0" authors = ["Ballerina"] keywords = ["soap"] repository = "https://github.com/ballerina-platform/module-ballerina-soap" diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index de8298b..211acc9 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -258,7 +258,7 @@ dependencies = [ [[package]] org = "ballerina" name = "soap" -version = "0.1.1" +version = "0.2.0" dependencies = [ {org = "ballerina", name = "http"}, {org = "ballerina", name = "mime"}, From 259f52d6c8cbd4b9b59dfdc6efdd47b9fd0eb0cc Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Fri, 15 Sep 2023 13:44:46 +0530 Subject: [PATCH 017/189] Format the code according to the coding conventions --- ballerina/soap.bal | 6 ++++-- ballerina/soap_utils.bal | 11 ++++++----- ballerina/tests/basic_client_test.bal | 6 ++++-- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/ballerina/soap.bal b/ballerina/soap.bal index 9cf4139..1bc1296 100644 --- a/ballerina/soap.bal +++ b/ballerina/soap.bal @@ -61,7 +61,8 @@ public isolated client class Client { # + action - SOAP action as a `string` # + headers - SOAP headers as a `map` # + return - If successful, returns the response. Else, returns an error - remote function sendReceive(xml|mime:Entity[] body, string? action = (), map headers = {})returns xml|mime:Entity[]|Error { + remote function sendReceive(xml|mime:Entity[] body, string? action = (), + map headers = {})returns xml|mime:Entity[]|Error { return sendReceive(self.soapVersion, body, self.soapClient, action, headers); } @@ -75,7 +76,8 @@ public isolated client class Client { # + action - SOAP action as a `string` # + headers - SOAP headers as a `map` # + return - If successful, returns `nil`. Else, returns an error - remote function sendOnly(xml|mime:Entity[] body, string? action = (), map headers = {}) returns Error? { + remote function sendOnly(xml|mime:Entity[] body, string? action = (), + map headers = {}) returns Error? { return sendOnly(self.soapVersion, body, self.soapClient, action, headers); } } diff --git a/ballerina/soap_utils.bal b/ballerina/soap_utils.bal index be26325..c9af392 100644 --- a/ballerina/soap_utils.bal +++ b/ballerina/soap_utils.bal @@ -24,8 +24,8 @@ import ballerina/mime; # + soapVersion - The SOAP version of the request # + headers - SOAP headers as a `map` # + return - The SOAP Request sent as `http:Request` -function createHttpRequest(SoapVersion soapVersion, xml|mime:Entity[] body, string? soapAction, map headers = {}) -returns http:Request { +function createHttpRequest(SoapVersion soapVersion, xml|mime:Entity[] body, + string? soapAction, map headers = {}) returns http:Request { http:Request req = new; if body is xml { req.setXmlPayload(body); @@ -53,7 +53,6 @@ returns http:Request { foreach string key in headers.keys() { req.addHeader(key, headers[key].toBalString()); } - return req; } @@ -72,7 +71,8 @@ function createSoapResponse(http:Response response, SoapVersion soapVersion) ret string path = ""; -function sendReceive(SoapVersion soapVersion, xml|mime:Entity[] body, http:Client httpClient, string? soapAction = (), map headers = {}) returns xml|Error { +function sendReceive(SoapVersion soapVersion, xml|mime:Entity[] body, http:Client httpClient, + string? soapAction = (), map headers = {}) returns xml|Error { http:Request req = createHttpRequest(soapVersion, body, soapAction, headers); http:Response response; do { @@ -87,7 +87,8 @@ function sendReceive(SoapVersion soapVersion, xml|mime:Entity[] body, http:Clien } } -function sendOnly(SoapVersion soapVersion, xml|mime:Entity[] body, http:Client httpClient, string? soapAction = (), map headers = {}) returns Error? { +function sendOnly(SoapVersion soapVersion, xml|mime:Entity[] body, http:Client httpClient, + string? soapAction = (), map headers = {}) returns Error? { http:Request req = createHttpRequest(SOAP11, body, soapAction, headers); do { http:Response _ = check httpClient->post(path, req); diff --git a/ballerina/tests/basic_client_test.bal b/ballerina/tests/basic_client_test.bal index 528d223..843ef05 100644 --- a/ballerina/tests/basic_client_test.bal +++ b/ballerina/tests/basic_client_test.bal @@ -110,7 +110,8 @@ function testSendReceive11WithHeaders() returns error? { `; - xml|mime:Entity[] response = check soapClient->sendReceive(body, "http://tempuri.org/Add", {foo: ["bar1", "bar2"]}); + xml|mime:Entity[] response = check soapClient->sendReceive(body, "http://tempuri.org/Add", + {foo: ["bar1", "bar2"]}); xml expected = xml `5`; test:assertEquals(response, expected); @@ -131,7 +132,8 @@ function testSendReceive12WithHeaders() returns error? { `; - xml|mime:Entity[] response = check soapClient->sendReceive(body, "http://tempuri.org/Add", {foo: ["bar1", "bar2"]}); + xml|mime:Entity[] response = check soapClient->sendReceive(body, "http://tempuri.org/Add", + {foo: ["bar1", "bar2"]}); xml expected = xml `5`; test:assertEquals(response, expected); From 99693da653c8def8ea3811460a60330ef976df4b Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Fri, 15 Sep 2023 13:45:45 +0530 Subject: [PATCH 018/189] Change the package version to 0.2.0 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 5930551..750a078 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,6 +1,6 @@ org.gradle.caching=true group=io.ballerina.stdlib -version=0.1.1-SNAPSHOT +version=0.2.0-SNAPSHOT checkstylePluginVersion=8.18 spotbugsPluginVersion=4.5.1 From d152751e1a60c4e1694d0710fde341b92666b386 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Fri, 15 Sep 2023 17:02:21 +0530 Subject: [PATCH 019/189] [Automated] Update the native jar versions --- ballerina/Dependencies.toml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index 211acc9..8440eb8 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -98,6 +98,9 @@ dependencies = [ {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "lang.value"} ] +modules = [ + {org = "ballerina", packageName = "io", moduleName = "io"} +] [[package]] org = "ballerina" @@ -261,6 +264,7 @@ name = "soap" version = "0.2.0" dependencies = [ {org = "ballerina", name = "http"}, + {org = "ballerina", name = "io"}, {org = "ballerina", name = "mime"}, {org = "ballerina", name = "test"} ] From 3d37a40748d13ac7fb9cdb937c20046e8d15a38a Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Mon, 18 Sep 2023 11:41:40 +0530 Subject: [PATCH 020/189] Change branch name `main` to `master` in github workflow files --- .github/workflows/build-timestamped-master.yml | 2 +- .github/workflows/publish-release.yml | 2 +- .github/workflows/update_specs.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-timestamped-master.yml b/.github/workflows/build-timestamped-master.yml index 2f425b4..0171582 100644 --- a/.github/workflows/build-timestamped-master.yml +++ b/.github/workflows/build-timestamped-master.yml @@ -3,7 +3,7 @@ name: Build on: push: branches: - - main + - master paths-ignore: - '*.md' workflow_dispatch: diff --git a/.github/workflows/publish-release.yml b/.github/workflows/publish-release.yml index aadc54e..4a74f20 100644 --- a/.github/workflows/publish-release.yml +++ b/.github/workflows/publish-release.yml @@ -64,4 +64,4 @@ jobs: GITHUB_TOKEN: ${{ secrets.BALLERINA_BOT_TOKEN }} run: | gh release create v$VERSION --title "module-ballerina-soap-v$VERSION" - gh pr create --base main --title "[Automated] Sync main after $VERSION release" --body "Sync main after $VERSION release" + gh pr create --base master --title "[Automated] Sync master after $VERSION release" --body "Sync master after $VERSION release" diff --git a/.github/workflows/update_specs.yml b/.github/workflows/update_specs.yml index 44c6f66..3af6d4a 100644 --- a/.github/workflows/update_specs.yml +++ b/.github/workflows/update_specs.yml @@ -7,7 +7,7 @@ on: workflow_dispatch: push: branches: - - main + - master paths: - 'docs/spec/**' From a83e084cec710bec3e8e45c7b4c83baffe21b223 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Mon, 18 Sep 2023 11:48:14 +0530 Subject: [PATCH 021/189] Remove `ballerina/io` dependency --- ballerina/Dependencies.toml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index 8440eb8..211acc9 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -98,9 +98,6 @@ dependencies = [ {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "lang.value"} ] -modules = [ - {org = "ballerina", packageName = "io", moduleName = "io"} -] [[package]] org = "ballerina" @@ -264,7 +261,6 @@ name = "soap" version = "0.2.0" dependencies = [ {org = "ballerina", name = "http"}, - {org = "ballerina", name = "io"}, {org = "ballerina", name = "mime"}, {org = "ballerina", name = "test"} ] From 0924bba5d6df15ff45999c078c3b3d60fa36d2f2 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Mon, 18 Sep 2023 12:16:09 +0530 Subject: [PATCH 022/189] Change branch name `master` to `2201.7.x` in github workflow files --- .github/workflows/build-timestamped-master.yml | 2 +- .github/workflows/publish-release.yml | 2 +- .github/workflows/update_specs.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-timestamped-master.yml b/.github/workflows/build-timestamped-master.yml index 0171582..bef3042 100644 --- a/.github/workflows/build-timestamped-master.yml +++ b/.github/workflows/build-timestamped-master.yml @@ -3,7 +3,7 @@ name: Build on: push: branches: - - master + - 2201.7.x paths-ignore: - '*.md' workflow_dispatch: diff --git a/.github/workflows/publish-release.yml b/.github/workflows/publish-release.yml index 4a74f20..0bd44a8 100644 --- a/.github/workflows/publish-release.yml +++ b/.github/workflows/publish-release.yml @@ -64,4 +64,4 @@ jobs: GITHUB_TOKEN: ${{ secrets.BALLERINA_BOT_TOKEN }} run: | gh release create v$VERSION --title "module-ballerina-soap-v$VERSION" - gh pr create --base master --title "[Automated] Sync master after $VERSION release" --body "Sync master after $VERSION release" + gh pr create --base 2201.7.x --title "[Automated] Sync 2201.7.x after $VERSION release" --body "Sync 2201.7.x after $VERSION release" diff --git a/.github/workflows/update_specs.yml b/.github/workflows/update_specs.yml index 3af6d4a..7e8bf49 100644 --- a/.github/workflows/update_specs.yml +++ b/.github/workflows/update_specs.yml @@ -7,7 +7,7 @@ on: workflow_dispatch: push: branches: - - master + - 2201.7.x paths: - 'docs/spec/**' From ff465599eb3b01fe690243399844eee61b880f51 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Sun, 24 Sep 2023 23:21:04 +0530 Subject: [PATCH 023/189] [Automated] Update the native jar versions --- ballerina/Ballerina.toml | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/ballerina/Ballerina.toml b/ballerina/Ballerina.toml index a0e2bc4..5141716 100644 --- a/ballerina/Ballerina.toml +++ b/ballerina/Ballerina.toml @@ -3,8 +3,30 @@ org = "ballerina" name = "soap" version = "0.2.0" authors = ["Ballerina"] +export=["soap.wssec"] keywords = ["soap"] repository = "https://github.com/ballerina-platform/module-ballerina-soap" icon = "icon.png" license = ["Apache-2.0"] distribution = "2201.7.2" + +[build-options] +observabilityIncluded = true + +[platform.java17] +graalvmCompatible = true + +[[platform.java17.dependency]] +path = "../native/build/libs/wssec-native-0.0.1-SNAPSHOT.jar" + +[[platform.java17.dependency]] +path = "./lib/wss4j-ws-security-dom-3.0.1.jar" + +[[platform.java17.dependency]] +path = "./lib/wss4j-ws-security-common-3.0.1.jar" + +[[platform.java17.dependency]] +groupId = "org.apache.santuario" +artifactId = "xmlsec" +version = "3.0.2" +path = "./lib/xmlsec-3.0.2.jar" From 067fceb2887040ae5bdf412b84de9f8de94b3e3f Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Sun, 24 Sep 2023 23:23:02 +0530 Subject: [PATCH 024/189] [Automated] Update the native jar versions --- ballerina/Ballerina.toml | 10 +++++----- ballerina/Dependencies.toml | 40 +++++++++++++++++++++++++++++++++++-- 2 files changed, 43 insertions(+), 7 deletions(-) diff --git a/ballerina/Ballerina.toml b/ballerina/Ballerina.toml index 5141716..0219156 100644 --- a/ballerina/Ballerina.toml +++ b/ballerina/Ballerina.toml @@ -13,19 +13,19 @@ distribution = "2201.7.2" [build-options] observabilityIncluded = true -[platform.java17] +[platform.java11] graalvmCompatible = true -[[platform.java17.dependency]] +[[platform.java11.dependency]] path = "../native/build/libs/wssec-native-0.0.1-SNAPSHOT.jar" -[[platform.java17.dependency]] +[[platform.java11.dependency]] path = "./lib/wss4j-ws-security-dom-3.0.1.jar" -[[platform.java17.dependency]] +[[platform.java11.dependency]] path = "./lib/wss4j-ws-security-common-3.0.1.jar" -[[platform.java17.dependency]] +[[platform.java11.dependency]] groupId = "org.apache.santuario" artifactId = "xmlsec" version = "3.0.2" diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index 211acc9..c33b33e 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -46,6 +46,9 @@ dependencies = [ {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "time"} ] +modules = [ + {org = "ballerina", packageName = "crypto", moduleName = "crypto"} +] [[package]] org = "ballerina" @@ -103,6 +106,9 @@ dependencies = [ org = "ballerina" name = "jballerina.java" version = "0.0.0" +modules = [ + {org = "ballerina", packageName = "jballerina.java", moduleName = "jballerina.java"} +] [[package]] org = "ballerina" @@ -255,17 +261,35 @@ dependencies = [ {org = "ballerina", name = "jballerina.java"} ] +[[package]] +org = "ballerina" +name = "regex" +version = "1.4.3" +dependencies = [ + {org = "ballerina", name = "jballerina.java"}, + {org = "ballerina", name = "lang.string"} +] +modules = [ + {org = "ballerina", packageName = "regex", moduleName = "regex"} +] + [[package]] org = "ballerina" name = "soap" version = "0.2.0" dependencies = [ + {org = "ballerina", name = "crypto"}, {org = "ballerina", name = "http"}, + {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "mime"}, - {org = "ballerina", name = "test"} + {org = "ballerina", name = "regex"}, + {org = "ballerina", name = "test"}, + {org = "ballerinai", name = "observe"} ] modules = [ - {org = "ballerina", packageName = "soap", moduleName = "soap"} + {org = "ballerina", packageName = "soap", moduleName = "soap"}, + {org = "ballerina", packageName = "soap", moduleName = "soap.soap11"}, + {org = "ballerina", packageName = "soap", moduleName = "soap.wssec"} ] [[package]] @@ -306,3 +330,15 @@ dependencies = [ {org = "ballerina", name = "jballerina.java"} ] +[[package]] +org = "ballerinai" +name = "observe" +version = "0.0.0" +dependencies = [ + {org = "ballerina", name = "jballerina.java"}, + {org = "ballerina", name = "observe"} +] +modules = [ + {org = "ballerinai", packageName = "observe", moduleName = "observe"} +] + From 5b6937a16069d182b1ee19aa1b2cd6a6dc0d579a Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Mon, 25 Sep 2023 00:30:45 +0530 Subject: [PATCH 025/189] [Automated] Update the native jar versions --- ballerina/Ballerina.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ballerina/Ballerina.toml b/ballerina/Ballerina.toml index 0219156..11d491d 100644 --- a/ballerina/Ballerina.toml +++ b/ballerina/Ballerina.toml @@ -3,7 +3,7 @@ org = "ballerina" name = "soap" version = "0.2.0" authors = ["Ballerina"] -export=["soap.wssec"] +export=["soap.wssec", "soap.soap11"] keywords = ["soap"] repository = "https://github.com/ballerina-platform/module-ballerina-soap" icon = "icon.png" From d7f26d98e00bbf7abb6ce20fde121208c71bc8f9 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Mon, 25 Sep 2023 00:35:27 +0530 Subject: [PATCH 026/189] [Automated] Update the native jar versions --- ballerina/Dependencies.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index c33b33e..62cd4d3 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -289,6 +289,7 @@ dependencies = [ modules = [ {org = "ballerina", packageName = "soap", moduleName = "soap"}, {org = "ballerina", packageName = "soap", moduleName = "soap.soap11"}, + {org = "ballerina", packageName = "soap", moduleName = "soap.soap12"}, {org = "ballerina", packageName = "soap", moduleName = "soap.wssec"} ] From 00b2c9a63eb2a6093fa8c56b383ede668c4e4b07 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Mon, 25 Sep 2023 07:49:12 +0530 Subject: [PATCH 027/189] Refactor SOAP 1.1 and 1.2 versions into separate sub modules --- ballerina/{ => modules/soap11}/error.bal | 0 ballerina/modules/soap11/soap11.bal | 71 ++++++++++++++ ballerina/modules/soap11/soap_utils.bal | 95 +++++++++++++++++++ .../soap11/tests/soap11_client_test.bal | 79 +++++++++++++++ ballerina/modules/soap12/error.bal | 18 ++++ .../{soap.bal => modules/soap12/soap12.bal} | 18 +--- ballerina/{ => modules/soap12}/soap_utils.bal | 44 ++++----- .../soap12/tests/soap12_client_test.bal} | 73 ++------------ build-config/resources/Ballerina.toml | 1 + 9 files changed, 290 insertions(+), 109 deletions(-) rename ballerina/{ => modules/soap11}/error.bal (100%) create mode 100644 ballerina/modules/soap11/soap11.bal create mode 100644 ballerina/modules/soap11/soap_utils.bal create mode 100644 ballerina/modules/soap11/tests/soap11_client_test.bal create mode 100644 ballerina/modules/soap12/error.bal rename ballerina/{soap.bal => modules/soap12/soap12.bal} (83%) rename ballerina/{ => modules/soap12}/soap_utils.bal (66%) rename ballerina/{tests/basic_client_test.bal => modules/soap12/tests/soap12_client_test.bal} (67%) diff --git a/ballerina/error.bal b/ballerina/modules/soap11/error.bal similarity index 100% rename from ballerina/error.bal rename to ballerina/modules/soap11/error.bal diff --git a/ballerina/modules/soap11/soap11.bal b/ballerina/modules/soap11/soap11.bal new file mode 100644 index 0000000..52b4568 --- /dev/null +++ b/ballerina/modules/soap11/soap11.bal @@ -0,0 +1,71 @@ +// Copyright (c) 2023, WSO2 LLC. (http://www.wso2.org) All Rights Reserved. +// +// WSO2 LLC. licenses this file to you under the Apache License, +// Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +import ballerina/http; +import ballerina/mime; + +# Soap client configurations. +# +public type ClientConfiguration record {| + *http:ClientConfiguration; +|}; + +# Object for the basic SOAP client endpoint. +public isolated client class Client { + private final http:Client soapClient; + + # Gets invoked during object initialization. + # + # + url - URL endpoint + # + config - Configurations for SOAP client + # + return - `error` in case of errors or `()` otherwise + public function init(string url, *ClientConfiguration config) returns Error? { + do { + self.soapClient = check new (url, retrieveHttpClientConfig(config)); + } on fail var err { + return error Error("Failed to initialize soap client", err); + } + } + + # Sends SOAP request and expects a response. + # ```ballerina + # xml|mime:Entity[] response = check soapClient->sendReceive(body); + # ``` + # + # + body - SOAP request body as an `XML` or `mime:Entity[]` to work with SOAP attachments + # + action - SOAP action as a `string` + # + headers - SOAP headers as a `map` + # + return - If successful, returns the response. Else, returns an error + remote function sendReceive(xml|mime:Entity[] body, string action, + map headers = {}) returns xml|mime:Entity[]|Error { + return sendReceive(body, self.soapClient, action, headers); + } + + # Fires and forgets requests. Sends the request without the possibility of any response from the + # service (even an error). + # ```ballerina + # check soapClient->sendOnly(body); + # ``` + # + # + body - SOAP request body as an `XML` or `mime:Entity[]` to work with SOAP attachments + # + action - SOAP action as a `string` + # + headers - SOAP headers as a `map` + # + return - If successful, returns `nil`. Else, returns an error + remote function sendOnly(xml|mime:Entity[] body, string action, + map headers = {}) returns Error? { + return sendOnly(body, self.soapClient, action, headers); + } +} diff --git a/ballerina/modules/soap11/soap_utils.bal b/ballerina/modules/soap11/soap_utils.bal new file mode 100644 index 0000000..6683934 --- /dev/null +++ b/ballerina/modules/soap11/soap_utils.bal @@ -0,0 +1,95 @@ +// Copyright (c) 2018, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +// +// WSO2 Inc. licenses this file to you under the Apache License, +// Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +import ballerina/http; +import ballerina/mime; + +# Creates a SOAP Request as an `http:Request` +# +# + soapAction - SOAP action +# + body - SOAP request body as an `XML` or `mime:Entity[]` to work with soap attachments +# + headers - SOAP headers as a `map` +# + return - The SOAP Request sent as `http:Request` +function createHttpRequest(xml|mime:Entity[] body, + string? soapAction, map headers = {}) returns http:Request { + http:Request req = new; + if body is xml { + req.setXmlPayload(body); + } else { + req.setBodyParts(body); + } + req.setHeader(mime:CONTENT_TYPE, mime:TEXT_XML); + if soapAction is string { + req.addHeader("SOAPAction", soapAction); + } + foreach string key in headers.keys() { + req.addHeader(key, headers[key].toBalString()); + } + return req; +} + +# Creates the SOAP response from the HTTP Response. +# +# + response - The request to be sent +# + return - The SOAP response created from the `http:Response` or the `error` object when reading the payload +function createSoapResponse(http:Response response) returns xml|error { + xml payload = check response.getXmlPayload(); + xmlns "http://schemas.xmlsoap.org/soap/envelope/" as soap11; + return payload/; +} + +string path = ""; + +function sendReceive(xml|mime:Entity[] body, http:Client httpClient, + string soapAction, map headers = {}) returns xml|Error { + http:Request req = createHttpRequest(body, soapAction, headers); + http:Response response; + do { + response = check httpClient->post(path, req); + } on fail var err { + return error Error("Failed to receive soap response", err); + } + do { + return check createSoapResponse(response); + } on fail var err { + return error Error("Failed to create soap response", err); + } +} + +function sendOnly(xml|mime:Entity[] body, http:Client httpClient, + string? soapAction = (), map headers = {}) returns Error? { + http:Request req = createHttpRequest(body, soapAction, headers); + do { + http:Response _ = check httpClient->post(path, req); + } on fail var err { + return error Error("Failed to create soap response", err); + } +} + +function retrieveHttpClientConfig(ClientConfiguration config) returns http:ClientConfiguration { + return { + httpVersion: config.httpVersion, + http1Settings: config.http1Settings, + http2Settings: config.http2Settings, + timeout: config.timeout, + poolConfig: config?.poolConfig, + auth: config?.auth, + retryConfig: config?.retryConfig, + responseLimits: config.responseLimits, + secureSocket: config?.secureSocket, + circuitBreaker: config?.circuitBreaker + }; +} diff --git a/ballerina/modules/soap11/tests/soap11_client_test.bal b/ballerina/modules/soap11/tests/soap11_client_test.bal new file mode 100644 index 0000000..7a9f04b --- /dev/null +++ b/ballerina/modules/soap11/tests/soap11_client_test.bal @@ -0,0 +1,79 @@ +// Copyright (c) 2023, WSO2 LLC. (http://www.wso2.org) All Rights Reserved. +// +// WSO2 LLC. licenses this file to you under the Apache License, +// Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +import ballerina/test; +import ballerina/mime; + +@test:Config {} +function testSendReceive11() returns error? { + Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL"); + + xml body = xml ` + + + 2 + 3 + + + `; + + xml|mime:Entity[] response = check soapClient->sendReceive(body, "http://tempuri.org/Add"); + + xml expected = xml `5`; + test:assertEquals(response, expected); +} + +@test:Config {} +function testSendOnly11() returns error? { + Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL"); + + xml body = xml ` + + + 2 + 3 + + + `; + + _ = check soapClient->sendOnly(body, "http://tempuri.org/Add"); +} + +@test:Config {} +function testSendReceive11WithHeaders() returns error? { + Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL"); + + xml body = xml ` + + + 2 + 3 + + + `; + + xml|mime:Entity[] response = check soapClient->sendReceive(body, "http://tempuri.org/Add", + {foo: ["bar1", "bar2"]}); + + xml expected = xml `5`; + test:assertEquals(response, expected); +} diff --git a/ballerina/modules/soap12/error.bal b/ballerina/modules/soap12/error.bal new file mode 100644 index 0000000..3795222 --- /dev/null +++ b/ballerina/modules/soap12/error.bal @@ -0,0 +1,18 @@ +// Copyright (c) 2023, WSO2 LLC. (http://www.wso2.org) All Rights Reserved. +// +// WSO2 LLC. licenses this file to you under the Apache License, +// Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +# Defines the common error type for the module. +public type Error distinct error; diff --git a/ballerina/soap.bal b/ballerina/modules/soap12/soap12.bal similarity index 83% rename from ballerina/soap.bal rename to ballerina/modules/soap12/soap12.bal index 1bc1296..f212273 100644 --- a/ballerina/soap.bal +++ b/ballerina/modules/soap12/soap12.bal @@ -17,26 +17,15 @@ import ballerina/http; import ballerina/mime; -# Defines the supported SOAP versions. -public enum SoapVersion { - # Represents SOAP 1.1 version - SOAP11, - # Represents SOAP 1.2 version - SOAP12 -} - # Soap client configurations. # -# + soapVersion - SOAP version public type ClientConfiguration record {| *http:ClientConfiguration; - SoapVersion soapVersion = SOAP11; |}; # Object for the basic SOAP client endpoint. public isolated client class Client { private final http:Client soapClient; - private final SoapVersion soapVersion; # Gets invoked during object initialization. # @@ -44,7 +33,6 @@ public isolated client class Client { # + config - Configurations for SOAP client # + return - `error` in case of errors or `()` otherwise public function init(string url, *ClientConfiguration config) returns Error? { - self.soapVersion = config.soapVersion; do { self.soapClient = check new (url, retrieveHttpClientConfig(config)); } on fail var err { @@ -62,8 +50,8 @@ public isolated client class Client { # + headers - SOAP headers as a `map` # + return - If successful, returns the response. Else, returns an error remote function sendReceive(xml|mime:Entity[] body, string? action = (), - map headers = {})returns xml|mime:Entity[]|Error { - return sendReceive(self.soapVersion, body, self.soapClient, action, headers); + map headers = {}) returns xml|mime:Entity[]|Error { + return sendReceive(body, self.soapClient, action, headers); } # Fires and forgets requests. Sends the request without the possibility of any response from the @@ -78,6 +66,6 @@ public isolated client class Client { # + return - If successful, returns `nil`. Else, returns an error remote function sendOnly(xml|mime:Entity[] body, string? action = (), map headers = {}) returns Error? { - return sendOnly(self.soapVersion, body, self.soapClient, action, headers); + return sendOnly(body, self.soapClient, action, headers); } } diff --git a/ballerina/soap_utils.bal b/ballerina/modules/soap12/soap_utils.bal similarity index 66% rename from ballerina/soap_utils.bal rename to ballerina/modules/soap12/soap_utils.bal index c9af392..a785089 100644 --- a/ballerina/soap_utils.bal +++ b/ballerina/modules/soap12/soap_utils.bal @@ -19,12 +19,11 @@ import ballerina/mime; # Creates a SOAP Request as an `http:Request` # -# + soapAction - SOAP action # + body - SOAP request body as an `XML` or `mime:Entity[]` to work with soap attachments -# + soapVersion - The SOAP version of the request +# + soapAction - SOAP action # + headers - SOAP headers as a `map` # + return - The SOAP Request sent as `http:Request` -function createHttpRequest(SoapVersion soapVersion, xml|mime:Entity[] body, +function createHttpRequest(xml|mime:Entity[] body, string? soapAction, map headers = {}) returns http:Request { http:Request req = new; if body is xml { @@ -32,23 +31,16 @@ function createHttpRequest(SoapVersion soapVersion, xml|mime:Entity[] body, } else { req.setBodyParts(body); } - if soapVersion == SOAP11 { - req.setHeader(mime:CONTENT_TYPE, mime:TEXT_XML); - if soapAction is string { - req.addHeader("SOAPAction", soapAction); + if soapAction is string { + map stringMap = {}; + stringMap["action"] = "\"" + soapAction + "\""; + var mediaType = mime:getMediaType(mime:APPLICATION_SOAP_XML); + if mediaType is mime:MediaType { + mediaType.parameters = stringMap; + req.setHeader(mime:CONTENT_TYPE, mediaType.toString()); } } else { - if soapAction is string { - map stringMap = {}; - stringMap["action"] = "\"" + soapAction + "\""; - var mediaType = mime:getMediaType(mime:APPLICATION_SOAP_XML); - if mediaType is mime:MediaType { - mediaType.parameters = stringMap; - req.setHeader(mime:CONTENT_TYPE, mediaType.toString()); - } - } else { - req.setHeader(mime:CONTENT_TYPE, mime:APPLICATION_SOAP_XML); - } + req.setHeader(mime:CONTENT_TYPE, mime:APPLICATION_SOAP_XML); } foreach string key in headers.keys() { req.addHeader(key, headers[key].toBalString()); @@ -59,21 +51,19 @@ function createHttpRequest(SoapVersion soapVersion, xml|mime:Entity[] body, # Creates the SOAP response from the HTTP Response. # # + response - The request to be sent -# + soapVersion - The SOAP version of the request # + return - The SOAP response created from the `http:Response` or the `error` object when reading the payload -function createSoapResponse(http:Response response, SoapVersion soapVersion) returns xml|error { +function createSoapResponse(http:Response response) returns xml|error { xml payload = check response.getXmlPayload(); - xmlns "http://schemas.xmlsoap.org/soap/envelope/" as soap11; xmlns "http://www.w3.org/2003/05/soap-envelope" as soap12; - return soapVersion == SOAP11 ? payload/ : payload/; + return payload/; } string path = ""; -function sendReceive(SoapVersion soapVersion, xml|mime:Entity[] body, http:Client httpClient, +function sendReceive(xml|mime:Entity[] body, http:Client httpClient, string? soapAction = (), map headers = {}) returns xml|Error { - http:Request req = createHttpRequest(soapVersion, body, soapAction, headers); + http:Request req = createHttpRequest(body, soapAction, headers); http:Response response; do { response = check httpClient->post(path, req); @@ -81,15 +71,15 @@ function sendReceive(SoapVersion soapVersion, xml|mime:Entity[] body, http:Clien return error Error("Failed to receive soap response", err); } do { - return check createSoapResponse(response, soapVersion); + return check createSoapResponse(response); } on fail var err { return error Error("Failed to create soap response", err); } } -function sendOnly(SoapVersion soapVersion, xml|mime:Entity[] body, http:Client httpClient, +function sendOnly(xml|mime:Entity[] body, http:Client httpClient, string? soapAction = (), map headers = {}) returns Error? { - http:Request req = createHttpRequest(SOAP11, body, soapAction, headers); + http:Request req = createHttpRequest(body, soapAction, headers); do { http:Response _ = check httpClient->post(path, req); } on fail var err { diff --git a/ballerina/tests/basic_client_test.bal b/ballerina/modules/soap12/tests/soap12_client_test.bal similarity index 67% rename from ballerina/tests/basic_client_test.bal rename to ballerina/modules/soap12/tests/soap12_client_test.bal index 843ef05..0f52751 100644 --- a/ballerina/tests/basic_client_test.bal +++ b/ballerina/modules/soap12/tests/soap12_client_test.bal @@ -17,30 +17,9 @@ import ballerina/test; import ballerina/mime; -@test:Config {} -function testSendReceive11() returns error? { - Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL"); - - xml body = xml ` - - - 2 - 3 - - - `; - - xml|mime:Entity[] response = check soapClient->sendReceive(body, "http://tempuri.org/Add"); - - xml expected = xml `5`; - test:assertEquals(response, expected); -} - @test:Config {} function testSendReceive12() returns error? { - Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL", soapVersion = SOAP12); + Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL"); xml body = xml ` - - - 2 - 3 - - - `; - - _ = check soapClient->sendOnly(body, "http://tempuri.org/Add"); -} - @test:Config {} function testSendOnly12() returns error? { - Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL", soapVersion = SOAP12); + Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL"); xml body = xml `sendOnly(body, "http://tempuri.org/Add"); } -@test:Config {} -function testSendReceive11WithHeaders() returns error? { - Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL"); - - xml body = xml ` - - - 2 - 3 - - - `; - - xml|mime:Entity[] response = check soapClient->sendReceive(body, "http://tempuri.org/Add", - {foo: ["bar1", "bar2"]}); - - xml expected = xml `5`; - test:assertEquals(response, expected); -} - @test:Config {} function testSendReceive12WithHeaders() returns error? { - Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL", soapVersion = SOAP12); + Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL"); xml body = xml ` Date: Mon, 25 Sep 2023 07:50:22 +0530 Subject: [PATCH 028/189] [Automated] Update the native jar versions --- ballerina/Ballerina.toml | 2 +- ballerina/Dependencies.toml | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/ballerina/Ballerina.toml b/ballerina/Ballerina.toml index 11d491d..57eecc2 100644 --- a/ballerina/Ballerina.toml +++ b/ballerina/Ballerina.toml @@ -3,7 +3,7 @@ org = "ballerina" name = "soap" version = "0.2.0" authors = ["Ballerina"] -export=["soap.wssec", "soap.soap11"] +export=["soap.wssec", "soap.soap11", "soap.soap11"] keywords = ["soap"] repository = "https://github.com/ballerina-platform/module-ballerina-soap" icon = "icon.png" diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index 62cd4d3..5e513b3 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -288,6 +288,7 @@ dependencies = [ ] modules = [ {org = "ballerina", packageName = "soap", moduleName = "soap"}, + {org = "ballerina", packageName = "soap", moduleName = "soap.common"}, {org = "ballerina", packageName = "soap", moduleName = "soap.soap11"}, {org = "ballerina", packageName = "soap", moduleName = "soap.soap12"}, {org = "ballerina", packageName = "soap", moduleName = "soap.wssec"} From 56059d2fc173628e287d351d80cb3c185a31cd26 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Mon, 25 Sep 2023 10:31:25 +0530 Subject: [PATCH 029/189] [Automated] Update the native jar versions --- ballerina/Dependencies.toml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index 5e513b3..cf6f374 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -101,6 +101,9 @@ dependencies = [ {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "lang.value"} ] +modules = [ + {org = "ballerina", packageName = "io", moduleName = "io"} +] [[package]] org = "ballerina" @@ -280,6 +283,7 @@ version = "0.2.0" dependencies = [ {org = "ballerina", name = "crypto"}, {org = "ballerina", name = "http"}, + {org = "ballerina", name = "io"}, {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "mime"}, {org = "ballerina", name = "regex"}, From 157275a2749ba16084201f370729d55f851ee5ed Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Mon, 25 Sep 2023 14:09:42 +0530 Subject: [PATCH 030/189] [Automated] Update the native jar versions --- ballerina/Dependencies.toml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index cf6f374..5e513b3 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -101,9 +101,6 @@ dependencies = [ {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "lang.value"} ] -modules = [ - {org = "ballerina", packageName = "io", moduleName = "io"} -] [[package]] org = "ballerina" @@ -283,7 +280,6 @@ version = "0.2.0" dependencies = [ {org = "ballerina", name = "crypto"}, {org = "ballerina", name = "http"}, - {org = "ballerina", name = "io"}, {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "mime"}, {org = "ballerina", name = "regex"}, From 67371eb39bdd39041c797912a7c02e2ec346d6f3 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Mon, 25 Sep 2023 14:10:21 +0530 Subject: [PATCH 031/189] [Automated] Update the native jar versions --- ballerina/Dependencies.toml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index 5e513b3..cf6f374 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -101,6 +101,9 @@ dependencies = [ {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "lang.value"} ] +modules = [ + {org = "ballerina", packageName = "io", moduleName = "io"} +] [[package]] org = "ballerina" @@ -280,6 +283,7 @@ version = "0.2.0" dependencies = [ {org = "ballerina", name = "crypto"}, {org = "ballerina", name = "http"}, + {org = "ballerina", name = "io"}, {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "mime"}, {org = "ballerina", name = "regex"}, From 2450c2a891450833245f8f4e402ad7cf610b7f83 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Mon, 25 Sep 2023 14:13:54 +0530 Subject: [PATCH 032/189] [Automated] Update the native jar versions --- ballerina/Dependencies.toml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index cf6f374..5e513b3 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -101,9 +101,6 @@ dependencies = [ {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "lang.value"} ] -modules = [ - {org = "ballerina", packageName = "io", moduleName = "io"} -] [[package]] org = "ballerina" @@ -283,7 +280,6 @@ version = "0.2.0" dependencies = [ {org = "ballerina", name = "crypto"}, {org = "ballerina", name = "http"}, - {org = "ballerina", name = "io"}, {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "mime"}, {org = "ballerina", name = "regex"}, From 49a226b8258a085e65f91cb4e69eaf534e6f3835 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Mon, 25 Sep 2023 16:07:42 +0530 Subject: [PATCH 033/189] [Automated] Update the native jar versions --- ballerina/Ballerina.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ballerina/Ballerina.toml b/ballerina/Ballerina.toml index 57eecc2..6345713 100644 --- a/ballerina/Ballerina.toml +++ b/ballerina/Ballerina.toml @@ -3,7 +3,7 @@ org = "ballerina" name = "soap" version = "0.2.0" authors = ["Ballerina"] -export=["soap.wssec", "soap.soap11", "soap.soap11"] +export=["soap.soap11", "soap.soap12"] keywords = ["soap"] repository = "https://github.com/ballerina-platform/module-ballerina-soap" icon = "icon.png" From 46db1939749dfa0e60ed5b30c530fc9ac793331d Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Mon, 25 Sep 2023 17:06:21 +0530 Subject: [PATCH 034/189] [Automated] Update the native jar versions --- ballerina/Dependencies.toml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index 5e513b3..cf6f374 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -101,6 +101,9 @@ dependencies = [ {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "lang.value"} ] +modules = [ + {org = "ballerina", packageName = "io", moduleName = "io"} +] [[package]] org = "ballerina" @@ -280,6 +283,7 @@ version = "0.2.0" dependencies = [ {org = "ballerina", name = "crypto"}, {org = "ballerina", name = "http"}, + {org = "ballerina", name = "io"}, {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "mime"}, {org = "ballerina", name = "regex"}, From 73cabce8b3b546902a1d383d0a353e3ccbff3807 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Tue, 26 Sep 2023 00:30:53 +0530 Subject: [PATCH 035/189] [Automated] Update the native jar versions --- ballerina/Dependencies.toml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index cf6f374..5e513b3 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -101,9 +101,6 @@ dependencies = [ {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "lang.value"} ] -modules = [ - {org = "ballerina", packageName = "io", moduleName = "io"} -] [[package]] org = "ballerina" @@ -283,7 +280,6 @@ version = "0.2.0" dependencies = [ {org = "ballerina", name = "crypto"}, {org = "ballerina", name = "http"}, - {org = "ballerina", name = "io"}, {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "mime"}, {org = "ballerina", name = "regex"}, From 3ed8f7c8f6b92746a2ffc9948206294b751979d2 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Tue, 26 Sep 2023 02:32:40 +0530 Subject: [PATCH 036/189] [Automated] Update the native jar versions --- ballerina/Ballerina.toml | 12 ++++++------ ballerina/Dependencies.toml | 36 ++++++++++++++++++------------------ 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/ballerina/Ballerina.toml b/ballerina/Ballerina.toml index 6345713..3ead5e8 100644 --- a/ballerina/Ballerina.toml +++ b/ballerina/Ballerina.toml @@ -8,24 +8,24 @@ keywords = ["soap"] repository = "https://github.com/ballerina-platform/module-ballerina-soap" icon = "icon.png" license = ["Apache-2.0"] -distribution = "2201.7.2" +distribution = "2201.8.0" [build-options] observabilityIncluded = true -[platform.java11] +[platform.java17] graalvmCompatible = true -[[platform.java11.dependency]] +[[platform.java17.dependency]] path = "../native/build/libs/wssec-native-0.0.1-SNAPSHOT.jar" -[[platform.java11.dependency]] +[[platform.java17.dependency]] path = "./lib/wss4j-ws-security-dom-3.0.1.jar" -[[platform.java11.dependency]] +[[platform.java17.dependency]] path = "./lib/wss4j-ws-security-common-3.0.1.jar" -[[platform.java11.dependency]] +[[platform.java17.dependency]] groupId = "org.apache.santuario" artifactId = "xmlsec" version = "3.0.2" diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index 5e513b3..5b48046 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -5,12 +5,12 @@ [ballerina] dependencies-toml-version = "2" -distribution-version = "2201.7.2" +distribution-version = "2201.8.0-20230830-220400-8a7556d8" [[package]] org = "ballerina" name = "auth" -version = "2.9.0" +version = "2.10.0" dependencies = [ {org = "ballerina", name = "crypto"}, {org = "ballerina", name = "jballerina.java"}, @@ -22,7 +22,7 @@ dependencies = [ [[package]] org = "ballerina" name = "cache" -version = "3.6.0" +version = "3.7.1" dependencies = [ {org = "ballerina", name = "constraint"}, {org = "ballerina", name = "jballerina.java"}, @@ -33,7 +33,7 @@ dependencies = [ [[package]] org = "ballerina" name = "constraint" -version = "1.3.0" +version = "1.4.0" dependencies = [ {org = "ballerina", name = "jballerina.java"} ] @@ -41,7 +41,7 @@ dependencies = [ [[package]] org = "ballerina" name = "crypto" -version = "2.4.1" +version = "2.5.0" dependencies = [ {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "time"} @@ -53,7 +53,7 @@ modules = [ [[package]] org = "ballerina" name = "file" -version = "1.8.1" +version = "1.9.0" dependencies = [ {org = "ballerina", name = "io"}, {org = "ballerina", name = "jballerina.java"}, @@ -64,7 +64,7 @@ dependencies = [ [[package]] org = "ballerina" name = "http" -version = "2.9.3" +version = "2.10.0" dependencies = [ {org = "ballerina", name = "auth"}, {org = "ballerina", name = "cache"}, @@ -96,7 +96,7 @@ modules = [ [[package]] org = "ballerina" name = "io" -version = "1.5.0" +version = "1.6.0" dependencies = [ {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "lang.value"} @@ -113,7 +113,7 @@ modules = [ [[package]] org = "ballerina" name = "jwt" -version = "2.9.0" +version = "2.10.0" dependencies = [ {org = "ballerina", name = "cache"}, {org = "ballerina", name = "crypto"}, @@ -210,7 +210,7 @@ dependencies = [ [[package]] org = "ballerina" name = "log" -version = "2.8.1" +version = "2.9.0" dependencies = [ {org = "ballerina", name = "io"}, {org = "ballerina", name = "jballerina.java"}, @@ -221,7 +221,7 @@ dependencies = [ [[package]] org = "ballerina" name = "mime" -version = "2.8.0" +version = "2.9.0" dependencies = [ {org = "ballerina", name = "io"}, {org = "ballerina", name = "jballerina.java"}, @@ -234,7 +234,7 @@ modules = [ [[package]] org = "ballerina" name = "oauth2" -version = "2.9.0" +version = "2.10.0" dependencies = [ {org = "ballerina", name = "cache"}, {org = "ballerina", name = "crypto"}, @@ -247,7 +247,7 @@ dependencies = [ [[package]] org = "ballerina" name = "observe" -version = "1.1.0" +version = "1.2.0" dependencies = [ {org = "ballerina", name = "jballerina.java"} ] @@ -255,7 +255,7 @@ dependencies = [ [[package]] org = "ballerina" name = "os" -version = "1.7.0" +version = "1.8.0" dependencies = [ {org = "ballerina", name = "io"}, {org = "ballerina", name = "jballerina.java"} @@ -276,7 +276,7 @@ modules = [ [[package]] org = "ballerina" name = "soap" -version = "0.2.0" +version = "0.3.0" dependencies = [ {org = "ballerina", name = "crypto"}, {org = "ballerina", name = "http"}, @@ -297,7 +297,7 @@ modules = [ [[package]] org = "ballerina" name = "task" -version = "2.4.0" +version = "2.5.0" dependencies = [ {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "time"} @@ -319,7 +319,7 @@ modules = [ [[package]] org = "ballerina" name = "time" -version = "2.3.0" +version = "2.4.0" dependencies = [ {org = "ballerina", name = "jballerina.java"} ] @@ -327,7 +327,7 @@ dependencies = [ [[package]] org = "ballerina" name = "url" -version = "2.3.0" +version = "2.4.0" dependencies = [ {org = "ballerina", name = "jballerina.java"} ] From a19a09a6c5f27287e0b70aff629a0b3f1f498e9d Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Tue, 26 Sep 2023 02:36:41 +0530 Subject: [PATCH 037/189] [Automated] Update the native jar versions --- ballerina/Dependencies.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index 5b48046..db910f6 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -5,7 +5,7 @@ [ballerina] dependencies-toml-version = "2" -distribution-version = "2201.8.0-20230830-220400-8a7556d8" +distribution-version = "2201.8.0" [[package]] org = "ballerina" @@ -276,7 +276,7 @@ modules = [ [[package]] org = "ballerina" name = "soap" -version = "0.3.0" +version = "0.2.0" dependencies = [ {org = "ballerina", name = "crypto"}, {org = "ballerina", name = "http"}, From 58674cbc6d14e4d1ee826fdc604211593084155c Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Tue, 26 Sep 2023 03:57:32 +0530 Subject: [PATCH 038/189] [Automated] Update the native jar versions --- ballerina/Ballerina.toml | 2 +- ballerina/Dependencies.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ballerina/Ballerina.toml b/ballerina/Ballerina.toml index 3ead5e8..8e8c985 100644 --- a/ballerina/Ballerina.toml +++ b/ballerina/Ballerina.toml @@ -1,7 +1,7 @@ [package] org = "ballerina" name = "soap" -version = "0.2.0" +version = "0.3.0" authors = ["Ballerina"] export=["soap.soap11", "soap.soap12"] keywords = ["soap"] diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index db910f6..feb73d2 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -276,7 +276,7 @@ modules = [ [[package]] org = "ballerina" name = "soap" -version = "0.2.0" +version = "0.3.0" dependencies = [ {org = "ballerina", name = "crypto"}, {org = "ballerina", name = "http"}, From 415602cee03a3826d8b40af495af044bbbaefa78 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Tue, 26 Sep 2023 10:10:35 +0530 Subject: [PATCH 039/189] [Automated] Update the native jar versions --- ballerina/Ballerina.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ballerina/Ballerina.toml b/ballerina/Ballerina.toml index 8e8c985..3ead5e8 100644 --- a/ballerina/Ballerina.toml +++ b/ballerina/Ballerina.toml @@ -1,7 +1,7 @@ [package] org = "ballerina" name = "soap" -version = "0.3.0" +version = "0.2.0" authors = ["Ballerina"] export=["soap.soap11", "soap.soap12"] keywords = ["soap"] From 0d9fe8afee4617e740615b0a8d31bb2a3fe0df6c Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Tue, 26 Sep 2023 10:11:34 +0530 Subject: [PATCH 040/189] [Automated] Update the native jar versions --- ballerina/Ballerina.toml | 2 +- ballerina/Dependencies.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ballerina/Ballerina.toml b/ballerina/Ballerina.toml index 3ead5e8..0f7b3f9 100644 --- a/ballerina/Ballerina.toml +++ b/ballerina/Ballerina.toml @@ -17,7 +17,7 @@ observabilityIncluded = true graalvmCompatible = true [[platform.java17.dependency]] -path = "../native/build/libs/wssec-native-0.0.1-SNAPSHOT.jar" +path = "../native/build/libs/soap-native-0.0.1-SNAPSHOT.jar" [[platform.java17.dependency]] path = "./lib/wss4j-ws-security-dom-3.0.1.jar" diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index feb73d2..db910f6 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -276,7 +276,7 @@ modules = [ [[package]] org = "ballerina" name = "soap" -version = "0.3.0" +version = "0.2.0" dependencies = [ {org = "ballerina", name = "crypto"}, {org = "ballerina", name = "http"}, From 2aefe1ce206ee7215585e404d2dd728e176512d4 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Tue, 26 Sep 2023 11:48:35 +0530 Subject: [PATCH 041/189] [Automated] Update the native jar versions --- ballerina/Ballerina.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ballerina/Ballerina.toml b/ballerina/Ballerina.toml index 0f7b3f9..59dcfea 100644 --- a/ballerina/Ballerina.toml +++ b/ballerina/Ballerina.toml @@ -17,7 +17,7 @@ observabilityIncluded = true graalvmCompatible = true [[platform.java17.dependency]] -path = "../native/build/libs/soap-native-0.0.1-SNAPSHOT.jar" +path = "../native/build/libs/soap-native-0.2.0-SNAPSHOT.jar" [[platform.java17.dependency]] path = "./lib/wss4j-ws-security-dom-3.0.1.jar" From 7082ef57c6dc85bf7a56c79f761527c2a498ddb7 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Tue, 26 Sep 2023 14:12:15 +0530 Subject: [PATCH 042/189] [Automated] Update the native jar versions --- ballerina/Dependencies.toml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index db910f6..fb4d9fc 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -101,6 +101,9 @@ dependencies = [ {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "lang.value"} ] +modules = [ + {org = "ballerina", packageName = "io", moduleName = "io"} +] [[package]] org = "ballerina" @@ -280,6 +283,7 @@ version = "0.2.0" dependencies = [ {org = "ballerina", name = "crypto"}, {org = "ballerina", name = "http"}, + {org = "ballerina", name = "io"}, {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "mime"}, {org = "ballerina", name = "regex"}, From c2df86ee6ac1cef4aea7cf20f1859430e7cb5b35 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Wed, 27 Sep 2023 12:10:04 +0530 Subject: [PATCH 043/189] [Automated] Update the native jar versions --- ballerina/Dependencies.toml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index fb4d9fc..db910f6 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -101,9 +101,6 @@ dependencies = [ {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "lang.value"} ] -modules = [ - {org = "ballerina", packageName = "io", moduleName = "io"} -] [[package]] org = "ballerina" @@ -283,7 +280,6 @@ version = "0.2.0" dependencies = [ {org = "ballerina", name = "crypto"}, {org = "ballerina", name = "http"}, - {org = "ballerina", name = "io"}, {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "mime"}, {org = "ballerina", name = "regex"}, From b64da47ef82f07413be8e9f654dfcffabf453ba5 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Sun, 1 Oct 2023 16:12:47 +0530 Subject: [PATCH 044/189] [Automated] Update the native jar versions --- ballerina/Dependencies.toml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index db910f6..fb4d9fc 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -101,6 +101,9 @@ dependencies = [ {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "lang.value"} ] +modules = [ + {org = "ballerina", packageName = "io", moduleName = "io"} +] [[package]] org = "ballerina" @@ -280,6 +283,7 @@ version = "0.2.0" dependencies = [ {org = "ballerina", name = "crypto"}, {org = "ballerina", name = "http"}, + {org = "ballerina", name = "io"}, {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "mime"}, {org = "ballerina", name = "regex"}, From 3d196cc11a7ba5f7b7d10c42423fdcf0de5eaa6c Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Sun, 1 Oct 2023 18:22:12 +0530 Subject: [PATCH 045/189] [Automated] Update the native jar versions --- ballerina/Dependencies.toml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index fb4d9fc..db910f6 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -101,9 +101,6 @@ dependencies = [ {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "lang.value"} ] -modules = [ - {org = "ballerina", packageName = "io", moduleName = "io"} -] [[package]] org = "ballerina" @@ -283,7 +280,6 @@ version = "0.2.0" dependencies = [ {org = "ballerina", name = "crypto"}, {org = "ballerina", name = "http"}, - {org = "ballerina", name = "io"}, {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "mime"}, {org = "ballerina", name = "regex"}, From 8ce19aaa3e9bbed45e79c66e91f6cf227ab4fe0b Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Sun, 1 Oct 2023 20:25:50 +0530 Subject: [PATCH 046/189] [Automated] Update the native jar versions --- ballerina/Dependencies.toml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index db910f6..fb4d9fc 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -101,6 +101,9 @@ dependencies = [ {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "lang.value"} ] +modules = [ + {org = "ballerina", packageName = "io", moduleName = "io"} +] [[package]] org = "ballerina" @@ -280,6 +283,7 @@ version = "0.2.0" dependencies = [ {org = "ballerina", name = "crypto"}, {org = "ballerina", name = "http"}, + {org = "ballerina", name = "io"}, {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "mime"}, {org = "ballerina", name = "regex"}, From 521f5d0ce33c7ce69bd902d75f772b58ff36174a Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Sun, 1 Oct 2023 23:29:33 +0530 Subject: [PATCH 047/189] [Automated] Update the native jar versions --- ballerina/Dependencies.toml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index fb4d9fc..db910f6 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -101,9 +101,6 @@ dependencies = [ {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "lang.value"} ] -modules = [ - {org = "ballerina", packageName = "io", moduleName = "io"} -] [[package]] org = "ballerina" @@ -283,7 +280,6 @@ version = "0.2.0" dependencies = [ {org = "ballerina", name = "crypto"}, {org = "ballerina", name = "http"}, - {org = "ballerina", name = "io"}, {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "mime"}, {org = "ballerina", name = "regex"}, From 54af277c4a1a625ad0a86b72198eeecbbcf2696a Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Sun, 1 Oct 2023 23:52:31 +0530 Subject: [PATCH 048/189] [Automated] Update the native jar versions --- ballerina/Dependencies.toml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index db910f6..fb4d9fc 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -101,6 +101,9 @@ dependencies = [ {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "lang.value"} ] +modules = [ + {org = "ballerina", packageName = "io", moduleName = "io"} +] [[package]] org = "ballerina" @@ -280,6 +283,7 @@ version = "0.2.0" dependencies = [ {org = "ballerina", name = "crypto"}, {org = "ballerina", name = "http"}, + {org = "ballerina", name = "io"}, {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "mime"}, {org = "ballerina", name = "regex"}, From fdcf4629c007459ac83f8b284ea8d466662e1f75 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Mon, 2 Oct 2023 00:00:44 +0530 Subject: [PATCH 049/189] [Automated] Update the native jar versions --- ballerina/Dependencies.toml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index fb4d9fc..db910f6 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -101,9 +101,6 @@ dependencies = [ {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "lang.value"} ] -modules = [ - {org = "ballerina", packageName = "io", moduleName = "io"} -] [[package]] org = "ballerina" @@ -283,7 +280,6 @@ version = "0.2.0" dependencies = [ {org = "ballerina", name = "crypto"}, {org = "ballerina", name = "http"}, - {org = "ballerina", name = "io"}, {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "mime"}, {org = "ballerina", name = "regex"}, From 50c4ba199f18af9f5806c5234d546267f55f3976 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Mon, 2 Oct 2023 00:01:47 +0530 Subject: [PATCH 050/189] [Automated] Update the native jar versions --- ballerina/Dependencies.toml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index db910f6..fb4d9fc 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -101,6 +101,9 @@ dependencies = [ {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "lang.value"} ] +modules = [ + {org = "ballerina", packageName = "io", moduleName = "io"} +] [[package]] org = "ballerina" @@ -280,6 +283,7 @@ version = "0.2.0" dependencies = [ {org = "ballerina", name = "crypto"}, {org = "ballerina", name = "http"}, + {org = "ballerina", name = "io"}, {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "mime"}, {org = "ballerina", name = "regex"}, From 1c4bbbc356536116aa2cbfb8df785f25ee06992b Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Mon, 2 Oct 2023 10:31:25 +0530 Subject: [PATCH 051/189] [Automated] Update the native jar versions --- ballerina/Dependencies.toml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index fb4d9fc..db910f6 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -101,9 +101,6 @@ dependencies = [ {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "lang.value"} ] -modules = [ - {org = "ballerina", packageName = "io", moduleName = "io"} -] [[package]] org = "ballerina" @@ -283,7 +280,6 @@ version = "0.2.0" dependencies = [ {org = "ballerina", name = "crypto"}, {org = "ballerina", name = "http"}, - {org = "ballerina", name = "io"}, {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "mime"}, {org = "ballerina", name = "regex"}, From 77631131770fd87603471b078575627c85244610 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Mon, 2 Oct 2023 11:49:58 +0530 Subject: [PATCH 052/189] [Automated] Update the native jar versions --- ballerina/Dependencies.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index db910f6..8fe54a9 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -64,7 +64,7 @@ dependencies = [ [[package]] org = "ballerina" name = "http" -version = "2.10.0" +version = "2.10.1" dependencies = [ {org = "ballerina", name = "auth"}, {org = "ballerina", name = "cache"}, From a4f612a945c1be4d3b43cbdea8f338a99d5f581c Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Mon, 2 Oct 2023 11:50:16 +0530 Subject: [PATCH 053/189] [Automated] Update the native jar versions --- ballerina/Dependencies.toml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index 8fe54a9..d942a5e 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -101,6 +101,9 @@ dependencies = [ {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "lang.value"} ] +modules = [ + {org = "ballerina", packageName = "io", moduleName = "io"} +] [[package]] org = "ballerina" @@ -280,6 +283,7 @@ version = "0.2.0" dependencies = [ {org = "ballerina", name = "crypto"}, {org = "ballerina", name = "http"}, + {org = "ballerina", name = "io"}, {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "mime"}, {org = "ballerina", name = "regex"}, From 5d2a84c4abd9c667a0121b568e56ac06062a3c9b Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Mon, 2 Oct 2023 12:05:27 +0530 Subject: [PATCH 054/189] [Automated] Update the native jar versions --- ballerina/Dependencies.toml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index d942a5e..8fe54a9 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -101,9 +101,6 @@ dependencies = [ {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "lang.value"} ] -modules = [ - {org = "ballerina", packageName = "io", moduleName = "io"} -] [[package]] org = "ballerina" @@ -283,7 +280,6 @@ version = "0.2.0" dependencies = [ {org = "ballerina", name = "crypto"}, {org = "ballerina", name = "http"}, - {org = "ballerina", name = "io"}, {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "mime"}, {org = "ballerina", name = "regex"}, From 5405b8f233b01da45d577be4f2ff92742b750009 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Mon, 2 Oct 2023 15:13:40 +0530 Subject: [PATCH 055/189] [Automated] Update the native jar versions --- ballerina/Dependencies.toml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index 8fe54a9..d942a5e 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -101,6 +101,9 @@ dependencies = [ {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "lang.value"} ] +modules = [ + {org = "ballerina", packageName = "io", moduleName = "io"} +] [[package]] org = "ballerina" @@ -280,6 +283,7 @@ version = "0.2.0" dependencies = [ {org = "ballerina", name = "crypto"}, {org = "ballerina", name = "http"}, + {org = "ballerina", name = "io"}, {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "mime"}, {org = "ballerina", name = "regex"}, From 271d2503b48b1a3ccfd10046e279dea89a86fbda Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Mon, 2 Oct 2023 15:21:55 +0530 Subject: [PATCH 056/189] [Automated] Update the native jar versions --- ballerina/Dependencies.toml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index d942a5e..8fe54a9 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -101,9 +101,6 @@ dependencies = [ {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "lang.value"} ] -modules = [ - {org = "ballerina", packageName = "io", moduleName = "io"} -] [[package]] org = "ballerina" @@ -283,7 +280,6 @@ version = "0.2.0" dependencies = [ {org = "ballerina", name = "crypto"}, {org = "ballerina", name = "http"}, - {org = "ballerina", name = "io"}, {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "mime"}, {org = "ballerina", name = "regex"}, From a3871d6759670403c1649e8866a2aaf34193373a Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Mon, 2 Oct 2023 15:40:24 +0530 Subject: [PATCH 057/189] [Automated] Update the native jar versions --- ballerina/Dependencies.toml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index 8fe54a9..d942a5e 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -101,6 +101,9 @@ dependencies = [ {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "lang.value"} ] +modules = [ + {org = "ballerina", packageName = "io", moduleName = "io"} +] [[package]] org = "ballerina" @@ -280,6 +283,7 @@ version = "0.2.0" dependencies = [ {org = "ballerina", name = "crypto"}, {org = "ballerina", name = "http"}, + {org = "ballerina", name = "io"}, {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "mime"}, {org = "ballerina", name = "regex"}, From 9af7de6e8e6dd08e40394f1f2291a613afd60efa Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Mon, 2 Oct 2023 16:05:33 +0530 Subject: [PATCH 058/189] [Automated] Update the native jar versions --- ballerina/Dependencies.toml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index d942a5e..8fe54a9 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -101,9 +101,6 @@ dependencies = [ {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "lang.value"} ] -modules = [ - {org = "ballerina", packageName = "io", moduleName = "io"} -] [[package]] org = "ballerina" @@ -283,7 +280,6 @@ version = "0.2.0" dependencies = [ {org = "ballerina", name = "crypto"}, {org = "ballerina", name = "http"}, - {org = "ballerina", name = "io"}, {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "mime"}, {org = "ballerina", name = "regex"}, From dfeaa3e67768820186281b8db584917655d4480c Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Mon, 2 Oct 2023 16:23:08 +0530 Subject: [PATCH 059/189] [Automated] Update the native jar versions --- ballerina/Dependencies.toml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index 8fe54a9..d942a5e 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -101,6 +101,9 @@ dependencies = [ {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "lang.value"} ] +modules = [ + {org = "ballerina", packageName = "io", moduleName = "io"} +] [[package]] org = "ballerina" @@ -280,6 +283,7 @@ version = "0.2.0" dependencies = [ {org = "ballerina", name = "crypto"}, {org = "ballerina", name = "http"}, + {org = "ballerina", name = "io"}, {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "mime"}, {org = "ballerina", name = "regex"}, From ab1466354c4e1a195fed99214d6ea780e4af6aab Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Mon, 2 Oct 2023 16:29:12 +0530 Subject: [PATCH 060/189] [Automated] Update the native jar versions --- ballerina/Dependencies.toml | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index d942a5e..3b2c69d 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -101,9 +101,6 @@ dependencies = [ {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "lang.value"} ] -modules = [ - {org = "ballerina", packageName = "io", moduleName = "io"} -] [[package]] org = "ballerina" @@ -264,6 +261,19 @@ dependencies = [ {org = "ballerina", name = "jballerina.java"} ] +[[package]] +org = "ballerina" +name = "random" +version = "1.4.0" +scope = "testOnly" +dependencies = [ + {org = "ballerina", name = "jballerina.java"}, + {org = "ballerina", name = "time"} +] +modules = [ + {org = "ballerina", packageName = "random", moduleName = "random"} +] + [[package]] org = "ballerina" name = "regex" @@ -283,9 +293,9 @@ version = "0.2.0" dependencies = [ {org = "ballerina", name = "crypto"}, {org = "ballerina", name = "http"}, - {org = "ballerina", name = "io"}, {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "mime"}, + {org = "ballerina", name = "random"}, {org = "ballerina", name = "regex"}, {org = "ballerina", name = "test"}, {org = "ballerinai", name = "observe"} From 91a93f1b95d193bb45aa21357770d0d8bd856822 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Mon, 2 Oct 2023 16:30:44 +0530 Subject: [PATCH 061/189] [Automated] Update the native jar versions --- ballerina/Dependencies.toml | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index 3b2c69d..d942a5e 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -101,6 +101,9 @@ dependencies = [ {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "lang.value"} ] +modules = [ + {org = "ballerina", packageName = "io", moduleName = "io"} +] [[package]] org = "ballerina" @@ -261,19 +264,6 @@ dependencies = [ {org = "ballerina", name = "jballerina.java"} ] -[[package]] -org = "ballerina" -name = "random" -version = "1.4.0" -scope = "testOnly" -dependencies = [ - {org = "ballerina", name = "jballerina.java"}, - {org = "ballerina", name = "time"} -] -modules = [ - {org = "ballerina", packageName = "random", moduleName = "random"} -] - [[package]] org = "ballerina" name = "regex" @@ -293,9 +283,9 @@ version = "0.2.0" dependencies = [ {org = "ballerina", name = "crypto"}, {org = "ballerina", name = "http"}, + {org = "ballerina", name = "io"}, {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "mime"}, - {org = "ballerina", name = "random"}, {org = "ballerina", name = "regex"}, {org = "ballerina", name = "test"}, {org = "ballerinai", name = "observe"} From d50adb298630343d22f73fc881216d85108f6442 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Mon, 2 Oct 2023 16:37:56 +0530 Subject: [PATCH 062/189] [Automated] Update the native jar versions --- ballerina/Dependencies.toml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index d942a5e..8fe54a9 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -101,9 +101,6 @@ dependencies = [ {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "lang.value"} ] -modules = [ - {org = "ballerina", packageName = "io", moduleName = "io"} -] [[package]] org = "ballerina" @@ -283,7 +280,6 @@ version = "0.2.0" dependencies = [ {org = "ballerina", name = "crypto"}, {org = "ballerina", name = "http"}, - {org = "ballerina", name = "io"}, {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "mime"}, {org = "ballerina", name = "regex"}, From 4624297006e42cecee96a29ad16c8eed248d701e Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Mon, 2 Oct 2023 20:07:15 +0530 Subject: [PATCH 063/189] [Automated] Update the native jar versions --- ballerina/Dependencies.toml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index 8fe54a9..d942a5e 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -101,6 +101,9 @@ dependencies = [ {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "lang.value"} ] +modules = [ + {org = "ballerina", packageName = "io", moduleName = "io"} +] [[package]] org = "ballerina" @@ -280,6 +283,7 @@ version = "0.2.0" dependencies = [ {org = "ballerina", name = "crypto"}, {org = "ballerina", name = "http"}, + {org = "ballerina", name = "io"}, {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "mime"}, {org = "ballerina", name = "regex"}, From 4d9d0af5ec1b88633be7634e7a5303e614fffbed Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Mon, 2 Oct 2023 20:56:22 +0530 Subject: [PATCH 064/189] [Automated] Update the native jar versions --- ballerina/Dependencies.toml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index d942a5e..8fe54a9 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -101,9 +101,6 @@ dependencies = [ {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "lang.value"} ] -modules = [ - {org = "ballerina", packageName = "io", moduleName = "io"} -] [[package]] org = "ballerina" @@ -283,7 +280,6 @@ version = "0.2.0" dependencies = [ {org = "ballerina", name = "crypto"}, {org = "ballerina", name = "http"}, - {org = "ballerina", name = "io"}, {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "mime"}, {org = "ballerina", name = "regex"}, From 3a57e92ccbaf8829079c1039a79f8cc30ac50548 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Tue, 3 Oct 2023 00:29:41 +0530 Subject: [PATCH 065/189] [Automated] Update the native jar versions --- ballerina/Dependencies.toml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index 8fe54a9..d942a5e 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -101,6 +101,9 @@ dependencies = [ {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "lang.value"} ] +modules = [ + {org = "ballerina", packageName = "io", moduleName = "io"} +] [[package]] org = "ballerina" @@ -280,6 +283,7 @@ version = "0.2.0" dependencies = [ {org = "ballerina", name = "crypto"}, {org = "ballerina", name = "http"}, + {org = "ballerina", name = "io"}, {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "mime"}, {org = "ballerina", name = "regex"}, From a8c585ba34ba17f8eae7bc0e8260d7e8417edf97 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Tue, 3 Oct 2023 00:34:58 +0530 Subject: [PATCH 066/189] [Automated] Update the native jar versions --- ballerina/Dependencies.toml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index d942a5e..8fe54a9 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -101,9 +101,6 @@ dependencies = [ {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "lang.value"} ] -modules = [ - {org = "ballerina", packageName = "io", moduleName = "io"} -] [[package]] org = "ballerina" @@ -283,7 +280,6 @@ version = "0.2.0" dependencies = [ {org = "ballerina", name = "crypto"}, {org = "ballerina", name = "http"}, - {org = "ballerina", name = "io"}, {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "mime"}, {org = "ballerina", name = "regex"}, From f0f1cd0d78aab76749a1168fcbca71217d219595 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Tue, 3 Oct 2023 00:38:53 +0530 Subject: [PATCH 067/189] [Automated] Update the native jar versions --- ballerina/Dependencies.toml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index 8fe54a9..d942a5e 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -101,6 +101,9 @@ dependencies = [ {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "lang.value"} ] +modules = [ + {org = "ballerina", packageName = "io", moduleName = "io"} +] [[package]] org = "ballerina" @@ -280,6 +283,7 @@ version = "0.2.0" dependencies = [ {org = "ballerina", name = "crypto"}, {org = "ballerina", name = "http"}, + {org = "ballerina", name = "io"}, {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "mime"}, {org = "ballerina", name = "regex"}, From 32837df39671a48dc3334cf33163e9c4326ceb7c Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Tue, 3 Oct 2023 10:35:37 +0530 Subject: [PATCH 068/189] [Automated] Update the native jar versions --- ballerina/Dependencies.toml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index d942a5e..8fe54a9 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -101,9 +101,6 @@ dependencies = [ {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "lang.value"} ] -modules = [ - {org = "ballerina", packageName = "io", moduleName = "io"} -] [[package]] org = "ballerina" @@ -283,7 +280,6 @@ version = "0.2.0" dependencies = [ {org = "ballerina", name = "crypto"}, {org = "ballerina", name = "http"}, - {org = "ballerina", name = "io"}, {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "mime"}, {org = "ballerina", name = "regex"}, From 4e243ddfda81119fb4feb9b1811122790a1f9b02 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Tue, 3 Oct 2023 11:26:51 +0530 Subject: [PATCH 069/189] Apply changes to support the 2201.8.0 lang version --- ballerina/build.gradle | 4 +- build-config/checkstyle/build.gradle | 5 +- build-config/resources/Ballerina.toml | 23 ++- build.gradle | 16 ++ gradle.properties | 69 ++++--- gradlew | 282 ++++++++++++++++---------- gradlew.bat | 15 +- native/build.gradle | 93 +++++++++ settings.gradle | 2 + 9 files changed, 357 insertions(+), 152 deletions(-) create mode 100644 native/build.gradle diff --git a/ballerina/build.gradle b/ballerina/build.gradle index 2b64e91..e2b0be7 100644 --- a/ballerina/build.gradle +++ b/ballerina/build.gradle @@ -32,7 +32,7 @@ buildscript { } -description = 'Ballerina - SOAP module' +description = 'Ballerina - SOAP Java Utils' def packageName = "soap" def packageOrg = "ballerina" @@ -106,6 +106,8 @@ publishing { updateTomlFiles.dependsOn copyStdlibs +test.dependsOn ":${packageName}-native:build" build.dependsOn "generatePomFileForMavenPublication" +build.dependsOn ":${packageName}-native:build" publishToMavenLocal.dependsOn build publish.dependsOn build diff --git a/build-config/checkstyle/build.gradle b/build-config/checkstyle/build.gradle index acc3047..b68a637 100644 --- a/build-config/checkstyle/build.gradle +++ b/build-config/checkstyle/build.gradle @@ -14,7 +14,6 @@ * limitations under the License. * */ - plugins { id "de.undercouch.download" } @@ -23,8 +22,8 @@ apply plugin: 'java' task downloadCheckstyleRuleFiles(type: Download) { src([ - 'https://raw.githubusercontent.com/wso2/code-quality-tools/v1.3/checkstyle/checkstyle.xml', - 'https://raw.githubusercontent.com/wso2/code-quality-tools/v1.3/checkstyle/suppressions.xml' + 'https://raw.githubusercontent.com/wso2/code-quality-tools/v1.4/checkstyle/jdk-17/checkstyle.xml', + 'https://raw.githubusercontent.com/wso2/code-quality-tools/v1.4/checkstyle/jdk-17/suppressions.xml' ]) overwrite false onlyIfNewer true diff --git a/build-config/resources/Ballerina.toml b/build-config/resources/Ballerina.toml index 4fdfb6e..d073da3 100644 --- a/build-config/resources/Ballerina.toml +++ b/build-config/resources/Ballerina.toml @@ -8,4 +8,25 @@ keywords = ["soap"] repository = "https://github.com/ballerina-platform/module-ballerina-soap" icon = "icon.png" license = ["Apache-2.0"] -distribution = "2201.7.2" +distribution = "2201.8.0" + +[build-options] +observabilityIncluded = true + +[platform.java17] +graalvmCompatible = true + +[[platform.java17.dependency]] +path = "../native/build/libs/soap-native-0.2.0-SNAPSHOT.jar" + +[[platform.java17.dependency]] +path = "./lib/wss4j-ws-security-dom-3.0.1.jar" + +[[platform.java17.dependency]] +path = "./lib/wss4j-ws-security-common-3.0.1.jar" + +[[platform.java17.dependency]] +groupId = "org.apache.santuario" +artifactId = "xmlsec" +version = "3.0.2" +path = "./lib/xmlsec-3.0.2.jar" diff --git a/build.gradle b/build.gradle index f35aa80..20f5ce9 100644 --- a/build.gradle +++ b/build.gradle @@ -63,10 +63,15 @@ allprojects { subprojects { configurations { + externalJars ballerinaStdLibs + jbalTools } dependencies { + jbalTools ("org.ballerinalang:jballerina-tools:${ballerinaLangVersion}") { + transitive = false + } /* Standard libraries */ ballerinaStdLibs "io.ballerina.stdlib:http-ballerina:${project.stdlibHttpVersion}" ballerinaStdLibs "io.ballerina.stdlib:mime-ballerina:${project.stdlibMimeVersion}" @@ -87,6 +92,16 @@ subprojects { ballerinaStdLibs "io.ballerina.stdlib:os-ballerina:${project.stdlibOsVersion}" ballerinaStdLibs "io.ballerina.stdlib:url-ballerina:${project.stdlibUrlVersion}" ballerinaStdLibs "io.ballerina.stdlib:io-ballerina:${project.stdlibIoVersion}" + + externalJars (group: 'org.apache.wss4j', name: 'wss4j-ws-security-dom', version: "${wsSecurityDomVersion}") { + transitive = false + } + externalJars (group: 'org.apache.wss4j', name: 'wss4j-ws-security-common', version: "${wsSecurityDomVersion}") { + transitive = false + } + externalJars (group: 'org.apache.santuario', name: 'xmlsec', version: "${xmlSecVersion}") { + transitive = false + } } } @@ -107,5 +122,6 @@ release { } task build { + dependsOn('soap-native:build') dependsOn('soap-ballerina:build') } diff --git a/gradle.properties b/gradle.properties index 750a078..09e7561 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,37 +2,42 @@ org.gradle.caching=true group=io.ballerina.stdlib version=0.2.0-SNAPSHOT -checkstylePluginVersion=8.18 -spotbugsPluginVersion=4.5.1 -shadowJarPluginVersion=5.2.0 -downloadPluginVersion=4.0.4 -releasePluginVersion=2.6.0 -ballerinaGradlePluginVersion=1.0.0 - -ballerinaLangVersion=2201.7.2 - -#stdlib dependencies -stdlibIoVersion=1.5.0 -stdlibTimeVersion=2.3.0 -stdlibUrlVersion=2.3.0 - -stdlibConstraintVersion=1.3.0 -stdlibCryptoVersion=2.4.0 -stdlibLogVersion=2.8.1 -stdlibOsVersion=1.7.0 -stdlibTaskVersion=2.4.0 - -stdlibCacheVersion=3.6.0 -stdlibFileVersion=1.8.0 -stdlibMimeVersion=2.8.0 -stdlibUuidVersion=1.6.0 - -stdlibAuthVersion=2.9.0 -stdlibJwtVersion=2.9.0 -stdlibOAuth2Version=2.9.0 - -stdlibHttpVersion=2.9.1 +checkstylePluginVersion=10.12.0 +spotbugsPluginVersion=5.0.14 +shadowJarPluginVersion=8.1.1 +downloadPluginVersion=5.4.0 +releasePluginVersion=2.8.0 +ballerinaGradlePluginVersion=2.0.1 + +ballerinaLangVersion=2201.8.0 + +stdlibIoVersion=1.6.0 +stdlibTimeVersion=2.4.0 +stdlibUrlVersion=2.4.0 + +stdlibConstraintVersion=1.4.0 +stdlibCryptoVersion=2.5.0 +stdlibLogVersion=2.9.0 +stdlibOsVersion=1.8.0 +stdlibRandomVersion=1.5.0 +stdlibTaskVersion=2.5.0 + +stdlibCacheVersion=3.7.0 +stdlibFileVersion=1.9.0 +stdlibMimeVersion=2.9.0 +stdlibUuidVersion=1.7.0 + +stdlibAuthVersion=2.10.0 +stdlibJwtVersion=2.10.0 +stdlibOAuth2Version=2.10.0 + +stdlibHttpVersion=2.10.0 + +stdlibTransactionVersion=1.8.0 +wsSecurityDomVersion=3.0.1 +wsSecurityCommonVersion=3.0.1 +xmlSecVersion=3.0.2 # Ballerinax Observer -observeVersion=1.1.0 -observeInternalVersion=1.1.0 +observeVersion=1.2.0 +observeInternalVersion=1.2.0 diff --git a/gradlew b/gradlew index 744e882..0adc8e1 100755 --- a/gradlew +++ b/gradlew @@ -1,7 +1,7 @@ -#!/usr/bin/env sh +#!/bin/sh # -# Copyright 2015 the original author or authors. +# Copyright © 2015-2021 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -17,67 +17,99 @@ # ############################################################################## -## -## Gradle start up script for UN*X -## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# ############################################################################## # Attempt to set APP_HOME + # Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null -APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" +MAX_FD=maximum warn () { echo "$*" -} +} >&2 die () { echo echo "$*" echo exit 1 -} +} >&2 # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MSYS* | MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar @@ -87,9 +119,9 @@ CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACMD=$JAVA_HOME/jre/sh/java else - JAVACMD="$JAVA_HOME/bin/java" + JAVACMD=$JAVA_HOME/bin/java fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME @@ -98,88 +130,120 @@ Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else - JAVACMD="java" - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." + fi fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac fi -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. # For Cygwin or MSYS, switch paths to Windows format before running java -if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) fi - i=`expr $i + 1` + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg done - case $i in - 0) set -- ;; - 1) set -- "$args0" ;; - 2) set -- "$args0" "$args1" ;; - 3) set -- "$args0" "$args1" "$args2" ;; - 4) set -- "$args0" "$args1" "$args2" "$args3" ;; - 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac fi -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=`save "$@"` -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat index ac1b06f..6689b85 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -14,7 +14,7 @@ @rem limitations under the License. @rem -@if "%DEBUG%" == "" @echo off +@if "%DEBUG%"=="" @echo off @rem ########################################################################## @rem @rem Gradle startup script for Windows @@ -25,7 +25,8 @@ if "%OS%"=="Windows_NT" setlocal set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% @@ -40,7 +41,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto execute +if %ERRORLEVEL% equ 0 goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -75,13 +76,15 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar :end @rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd +if %ERRORLEVEL% equ 0 goto mainEnd :fail rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% :mainEnd if "%OS%"=="Windows_NT" endlocal diff --git a/native/build.gradle b/native/build.gradle new file mode 100644 index 0000000..8784812 --- /dev/null +++ b/native/build.gradle @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2023, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +plugins { + id 'java' + id 'checkstyle' + id 'com.github.spotbugs' +} + +description = 'Ballerina - SOAP Java Utils' + +dependencies { + checkstyle project(':checkstyle') + checkstyle "com.puppycrawl.tools:checkstyle:${checkstylePluginVersion}" + + implementation group: 'org.ballerinalang', name: 'ballerina-runtime', version: "${ballerinaLangVersion}" + implementation 'com.google.guava:guava:32.1.1-jre' + implementation 'org.apache.wss4j:wss4j-ws-security-dom:3.0.1' + implementation 'org.apache.santuario:xmlsec:3.0.2' + implementation 'org.apache.wss4j:wss4j-ws-security-common:3.0.1' +} + +checkstyle { + toolVersion "${project.checkstylePluginVersion}" + configFile rootProject.file("build-config/checkstyle/build/checkstyle.xml") + configProperties = ["suppressionFile" : file("${rootDir}/build-config/checkstyle/build/suppressions.xml")] +} + +checkstyleMain.dependsOn(":checkstyle:downloadCheckstyleRuleFiles") + +spotbugsMain { + effort "max" + reportLevel "low" + reportsDir = file("$project.buildDir/reports/spotbugs") + reports { + html.enabled true + text.enabled = true + } + def excludeFile = file("${rootDir}/spotbugs-exclude.xml") + if(excludeFile.exists()) { + excludeFilter = excludeFile + } +} + +def excludePattern = '**/module-info.java' +tasks.withType(Checkstyle) { + exclude excludePattern +} + +publishing { + publications { + mavenJava(MavenPublication) { + groupId project.group + artifactId "soap-native" + version = project.version + artifact jar + } + } + + repositories { + maven { + name = "GitHubPackages" + url = uri("https://maven.pkg.github.com/ballerina-platform/module-ballerina-constraint") + credentials { + username = System.getenv("publishUser") + password = System.getenv("publishPAT") + } + } + } +} + +compileJava { + doFirst { + options.compilerArgs = [ + '--module-path', classpath.asPath, + ] + classpath = files() + } +} diff --git a/settings.gradle b/settings.gradle index 1084706..4c5eff2 100644 --- a/settings.gradle +++ b/settings.gradle @@ -21,9 +21,11 @@ plugins { } include ':checkstyle' +include ':soap-native' include ':soap-ballerina' project(':checkstyle').projectDir = file("build-config${File.separator}checkstyle") +project(':soap-native').projectDir = file('native') project(':soap-ballerina').projectDir = file('ballerina') gradleEnterprise { From d5c5c17e5fc75a5929cacc1ca9792013fb60f492 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Tue, 3 Oct 2023 11:28:32 +0530 Subject: [PATCH 070/189] Add gradle wrapper files to the package --- gradle/wrapper/gradle-wrapper.jar | Bin 58910 -> 63721 bytes gradle/wrapper/gradle-wrapper.properties | 4 +++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 62d4c053550b91381bbd28b1afc82d634bf73a8a..7f93135c49b765f8051ef9d0a6055ff8e46073d8 100644 GIT binary patch delta 44733 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

Ca%uA05UTpm-fb`()QYj+OI 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 b7hw`Bw4~VJY{0;{1OBXmt|7YjKmPh31Up)j diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 69a9715..ac72c34 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip +networkTimeout=10000 +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From 13b08b96013fd9f7c25fa951a53591cc11e1d225 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Tue, 3 Oct 2023 11:28:45 +0530 Subject: [PATCH 071/189] Update the .gitignore file --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 2fe7e94..8376c1c 100644 --- a/.gitignore +++ b/.gitignore @@ -38,3 +38,5 @@ target # Ballerina velocity.log* *Ballerina.lock + +.vscode From 8e7f6c73d0d24a443bec9e29056c1cdee8ee4351 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Tue, 3 Oct 2023 11:46:25 +0530 Subject: [PATCH 072/189] Update checkstyle and suppression files --- build-config/checkstyle/build/checkstyle.xml | 93 +++++++++---------- .../checkstyle/build/suppressions.xml | 2 + 2 files changed, 46 insertions(+), 49 deletions(-) diff --git a/build-config/checkstyle/build/checkstyle.xml b/build-config/checkstyle/build/checkstyle.xml index f36d997..31c8451 100644 --- a/build-config/checkstyle/build/checkstyle.xml +++ b/build-config/checkstyle/build/checkstyle.xml @@ -63,15 +63,42 @@ page at http://checkstyle.sourceforge.net/config.html --> + + + + + + + + + + + + - - - + + + + + + + + + + - - + + + + + + + - - @@ -124,18 +154,12 @@ page at http://checkstyle.sourceforge.net/config.html --> - - - - - - @@ -177,8 +201,7 @@ page at http://checkstyle.sourceforge.net/config.html --> - + @@ -230,28 +253,6 @@ page at http://checkstyle.sourceforge.net/config.html --> - - - - - - - - - - - - - @@ -295,8 +296,7 @@ page at http://checkstyle.sourceforge.net/config.html --> on the last non-blank line preceding the fallen-into case contains 'fall through' (or some other variants which we don't publicized to promote consistency). --> - + @@ -328,8 +328,7 @@ page at http://checkstyle.sourceforge.net/config.html --> This includes most binary operators and keywords followed by regular or curly braces. --> - - - - - - - - - + + diff --git a/build-config/checkstyle/build/suppressions.xml b/build-config/checkstyle/build/suppressions.xml index b8d04df..69bff56 100644 --- a/build-config/checkstyle/build/suppressions.xml +++ b/build-config/checkstyle/build/suppressions.xml @@ -42,4 +42,6 @@ + + From a2f9c6d6bb1ede8de57d50eee9b0f12e6248f57e Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Tue, 3 Oct 2023 11:47:43 +0530 Subject: [PATCH 073/189] Add dependencies to native files --- native/src/main/java/module-info.java | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 native/src/main/java/module-info.java diff --git a/native/src/main/java/module-info.java b/native/src/main/java/module-info.java new file mode 100644 index 0000000..c5c33dc --- /dev/null +++ b/native/src/main/java/module-info.java @@ -0,0 +1,25 @@ +// Copyright (c) 2023, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +// +// WSO2 Inc. licenses this file to you under the Apache License, +// Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +module soap { + requires io.ballerina.runtime; + requires org.apache.wss4j.dom; + requires org.apache.wss4j.common; + requires org.apache.santuario.xmlsec; + requires java.xml; + requires java.xml.crypto; + requires org.apache.commons.codec; +} From c6a057e33cb2c536bc15ada8bad98e6d623ae344 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Tue, 3 Oct 2023 11:49:23 +0530 Subject: [PATCH 074/189] Add changes to return module specific errors --- ballerina/modules/wssec/error.bal | 18 ++++++++ ballerina/modules/wssec/init.bal | 24 +++++++++++ .../src/main/java/org/wssec/ModuleUtils.java | 35 ++++++++++++++++ native/src/main/java/org/wssec/Utils.java | 41 +++++++++++++++++++ 4 files changed, 118 insertions(+) create mode 100644 ballerina/modules/wssec/error.bal create mode 100644 ballerina/modules/wssec/init.bal create mode 100644 native/src/main/java/org/wssec/ModuleUtils.java create mode 100644 native/src/main/java/org/wssec/Utils.java diff --git a/ballerina/modules/wssec/error.bal b/ballerina/modules/wssec/error.bal new file mode 100644 index 0000000..036f086 --- /dev/null +++ b/ballerina/modules/wssec/error.bal @@ -0,0 +1,18 @@ +// Copyright (c) 2023, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +// +// WSO2 Inc. licenses this file to you under the Apache License, +// Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +# Represents any error related to the wssec module. +public type Error distinct error; diff --git a/ballerina/modules/wssec/init.bal b/ballerina/modules/wssec/init.bal new file mode 100644 index 0000000..f2f54b3 --- /dev/null +++ b/ballerina/modules/wssec/init.bal @@ -0,0 +1,24 @@ +// Copyright (c) 2023, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +// +// WSO2 Inc. licenses this file to you under the Apache License, +// Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +import ballerina/jballerina.java; + +isolated function init() { + setModule(); +} + +isolated function setModule() = @java:Method { + 'class: "org.wssec.ModuleUtils" +} external; diff --git a/native/src/main/java/org/wssec/ModuleUtils.java b/native/src/main/java/org/wssec/ModuleUtils.java new file mode 100644 index 0000000..16d1cbb --- /dev/null +++ b/native/src/main/java/org/wssec/ModuleUtils.java @@ -0,0 +1,35 @@ +// Copyright (c) 2023, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +// +// WSO2 Inc. licenses this file to you under the Apache License, +// Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.wssec; + +import io.ballerina.runtime.api.Environment; +import io.ballerina.runtime.api.Module; + +public class ModuleUtils { + + private static Module module; + + private ModuleUtils() {} + + public static void setModule(Environment environment) { + module = environment.getCurrentModule(); + } + + public static Module getModule() { + return module; + } +} diff --git a/native/src/main/java/org/wssec/Utils.java b/native/src/main/java/org/wssec/Utils.java new file mode 100644 index 0000000..a18431b --- /dev/null +++ b/native/src/main/java/org/wssec/Utils.java @@ -0,0 +1,41 @@ +// Copyright (c) 2023, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +// +// WSO2 Inc. licenses this file to you under the Apache License, +// Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.wssec; + +import io.ballerina.runtime.api.creators.ErrorCreator; +import io.ballerina.runtime.api.utils.StringUtils; +import io.ballerina.runtime.api.values.BError; + +import static org.wssec.ModuleUtils.getModule; + +public class Utils { + + private Utils() { + } + + public static final String ERROR_TYPE = "Error"; + public static final String POLICY_NOT_SUPPORTED_ERROR = "Given ws security policy is currently not supported"; + + public static BError createError(String message) { + return ErrorCreator.createError(getModule(), ERROR_TYPE, + StringUtils.fromString(message), null, null); + } + + public static BError createError(String message, BError cause) { + return ErrorCreator.createError(getModule(), ERROR_TYPE, StringUtils.fromString(message), cause, null); + } +} From cd5ee700ebc2da2a34c9046492b40b643169dc8b Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Tue, 3 Oct 2023 11:51:30 +0530 Subject: [PATCH 075/189] Create APIs to support signatures in SOAP envelopes --- ballerina/modules/wssec/signature.bal | 93 +++++++++++++++++++ native/src/main/java/org/wssec/Signature.java | 66 +++++++++++++ 2 files changed, 159 insertions(+) create mode 100644 ballerina/modules/wssec/signature.bal create mode 100644 native/src/main/java/org/wssec/Signature.java diff --git a/ballerina/modules/wssec/signature.bal b/ballerina/modules/wssec/signature.bal new file mode 100644 index 0000000..f050249 --- /dev/null +++ b/ballerina/modules/wssec/signature.bal @@ -0,0 +1,93 @@ +// Copyright (c) 2023, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +// +// WSO2 Inc. licenses this file to you under the Apache License, +// Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +import ballerina/crypto; +import ballerina/jballerina.java; + +class Signature { + private handle nativeSignature; + + function init() returns Error? { + self.nativeSignature = newSignature(); + } + + public function signData(string dataString, SignatureAlgorithm signatureAlgorithm, + crypto:PrivateKey privateKey) returns byte[]|Error { + byte[] data = dataString.toBytes(); + do { + match signatureAlgorithm { + RSA_SHA1 => { + return check crypto:signRsaSha1(data, privateKey); + } + RSA_SHA256 => { + return check crypto:signRsaSha256(data, privateKey); + } + RSA_SHA384 => { + return check crypto:signRsaSha384(data, privateKey); + } + RSA_SHA512 => { + return check crypto:signRsaSha512(data, privateKey); + } + _ => { + return error Error("Invalid signature algorithm!"); + } + } + } on fail var e { + return error Error(e.message()); + } + } + + public function verifySignature(byte[] data, byte[] signature, crypto:PublicKey publicKey, + SignatureAlgorithm signatureAlgorithm = RSA_SHA256) returns boolean|Error { + do { + match signatureAlgorithm { + RSA_SHA1 => { + return check crypto:verifyRsaSha1Signature(data, signature, publicKey); + } + RSA_SHA256 => { + return check crypto:verifyRsaSha256Signature(data, signature, publicKey); + } + RSA_SHA384 => { + return check crypto:verifyRsaSha384Signature(data, signature, publicKey); + } + RSA_SHA512 => { + return check crypto:verifyRsaSha512Signature(data, signature, publicKey); + } + _ => { + return error Error("Invalid signature algorithm!"); + } + } + + } on fail var e { + return error Error(e.message()); + } + } + + public function setSignatureAlgorithm(string signatureAlgorithm) = @java:Method { + 'class: "org.wssec.Signature" + } external; + + public function setSignatureValue(byte[] signatureValue) = @java:Method { + 'class: "org.wssec.Signature" + } external; + + public function getSignatureValue() returns byte[] = @java:Method { + 'class: "org.wssec.Signature" + } external; +} + +function newSignature() returns handle = @java:Constructor { + 'class: "org.wssec.Signature" +} external; diff --git a/native/src/main/java/org/wssec/Signature.java b/native/src/main/java/org/wssec/Signature.java new file mode 100644 index 0000000..c16e86b --- /dev/null +++ b/native/src/main/java/org/wssec/Signature.java @@ -0,0 +1,66 @@ +// Copyright (c) 2023, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +// +// WSO2 Inc. licenses this file to you under the Apache License, +// Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.wssec; + +import io.ballerina.runtime.api.creators.ValueCreator; +import io.ballerina.runtime.api.utils.StringUtils; +import io.ballerina.runtime.api.values.BArray; +import io.ballerina.runtime.api.values.BHandle; +import io.ballerina.runtime.api.values.BObject; +import io.ballerina.runtime.api.values.BString; + +import static org.wssec.Constants.NATIVE_SIGNATURE; + +public class Signature { + + private String signatureAlgorithm; + private byte[] signatureValue; + + public static void setSignatureAlgorithm(BObject sign, BString signatureAlgorithm) { + BHandle handle = (BHandle) sign.get(StringUtils.fromString(NATIVE_SIGNATURE)); + Signature signature = (Signature) handle.getValue(); + signature.setSignatureAlgorithm(signatureAlgorithm.getValue()); + } + + public static void setSignatureValue(BObject sign, BArray signatureValue) { + BHandle handle = (BHandle) sign.get(StringUtils.fromString(NATIVE_SIGNATURE)); + Signature signature = (Signature) handle.getValue(); + signature.setSignatureValue(signatureValue.getByteArray()); + } + + public static BArray getSignatureValue(BObject sign) { + BHandle handle = (BHandle) sign.get(StringUtils.fromString(NATIVE_SIGNATURE)); + Signature signature = (Signature) handle.getValue(); + return ValueCreator.createArrayValue(signature.getSignatureValue()); + } + + protected String getSignatureAlgorithm() { + return signatureAlgorithm; + } + + protected void setSignatureAlgorithm(String signatureAlgorithm) { + this.signatureAlgorithm = signatureAlgorithm; + } + + protected byte[] getSignatureValue() { + return signatureValue; + } + + protected void setSignatureValue(byte[] signatureValue) { + this.signatureValue = signatureValue; + } +} From 1dd24f516ba63351b0949fd6d9a74e685e59fb42 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Tue, 3 Oct 2023 11:52:13 +0530 Subject: [PATCH 076/189] Create APIs to support encryptions in SOAP envelopes --- ballerina/modules/wssec/encryption.bal | 105 ++++++++++++++++++ .../src/main/java/org/wssec/Encryption.java | 75 +++++++++++++ 2 files changed, 180 insertions(+) create mode 100644 ballerina/modules/wssec/encryption.bal create mode 100644 native/src/main/java/org/wssec/Encryption.java diff --git a/ballerina/modules/wssec/encryption.bal b/ballerina/modules/wssec/encryption.bal new file mode 100644 index 0000000..4a9b390 --- /dev/null +++ b/ballerina/modules/wssec/encryption.bal @@ -0,0 +1,105 @@ +// Copyright (c) 2023, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +// +// WSO2 Inc. licenses this file to you under the Apache License, +// Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +import ballerina/crypto; +import ballerina/jballerina.java; + +class Encryption { + + private handle nativeEncryption; + + function init() returns Error? { + self.nativeEncryption = newEncryption(); + } + + function encryptData(string dataString, EncryptionAlgorithm encryptionAlgorithm, + byte[]|crypto:PublicKey|crypto:PrivateKey key, byte[]? initialVector = ()) + returns byte[]|Error { + byte[] data = dataString.toBytes(); + do { + match encryptionAlgorithm { + AES_128|AES_192|AES_256 if key is byte[] && initialVector is byte[] => { + return check crypto:encryptAesCbc(data, key, initialVector); + } + AES_128_ECB|AES_192_ECB|AES_256_ECB if key is byte[] && initialVector is byte[] => { + return check crypto:encryptAesEcb(data, key); + } + AES_128_GCM|AES_192_GCM|AES_256_GCM if key is byte[] && initialVector is byte[] => { + return check crypto:encryptAesGcm(data, key, initialVector, crypto:NONE); + } + RSA_ECB if key is crypto:PublicKey|crypto:PrivateKey => { + return check crypto:encryptRsaEcb(data, key); + } + _ if key !is crypto:PublicKey|crypto:PrivateKey => { + return error Error("Invalid/Missing key!"); + } + _ if initialVector !is byte[] => { + return error Error("Initialization vector is empty!"); + } + _ => { + return error Error("Encryption Algorithm is not supported"); + } + } + } on fail var e { + return error(e.message()); + } + } + + public function decryptData(byte[] cipherText, EncryptionAlgorithm encryptionAlgorithm, + byte[]|crypto:PublicKey|crypto:PrivateKey key, byte[]? initialVector = ()) + returns byte[]|Error { + do { + match encryptionAlgorithm { + AES_128|AES_192|AES_256 if key is byte[] && initialVector is byte[] => { + return check crypto:decryptAesCbc(cipherText, key, initialVector); + } + AES_128_GCM|AES_192_GCM|AES_256_GCM if key is byte[] && initialVector is byte[]=> { + return check crypto:decryptAesGcm(cipherText, key, initialVector, crypto:NONE); + } + RSA_ECB if key is crypto:PublicKey|crypto:PrivateKey => { + return check crypto:decryptRsaEcb(cipherText, key); + } + _ if key !is crypto:PublicKey|crypto:PrivateKey => { + return error Error("Invalid/Missing key!"); + } + _ => { + return error Error("Decryption Algorithm is not supported"); + } + } + } on fail var e { + return error Error(e.message()); + } + } + + public function setEncryptionAlgorithm(string encryptionAlgorithm) = @java:Method { + 'class: "org.wssec.Encryption" + } external; + + public function setEncryptedData(byte[] encryptedData) = @java:Method { + 'class: "org.wssec.Encryption" + } external; + + public function getEncryptedKeyElements(byte[] encryptedKey) returns string|Error = @java:Method { + 'class: "org.wssec.Encryption" + } external; + + public function getEncryptedData() returns byte[] = @java:Method { + 'class: "org.wssec.Encryption" + } external; +} + +function newEncryption() returns handle = @java:Constructor { + 'class: "org.wssec.Encryption" +} external; diff --git a/native/src/main/java/org/wssec/Encryption.java b/native/src/main/java/org/wssec/Encryption.java new file mode 100644 index 0000000..ea61174 --- /dev/null +++ b/native/src/main/java/org/wssec/Encryption.java @@ -0,0 +1,75 @@ +// Copyright (c) 2023, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +// +// WSO2 Inc. licenses this file to you under the Apache License, +// Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.wssec; + +import io.ballerina.runtime.api.creators.ValueCreator; +import io.ballerina.runtime.api.utils.StringUtils; +import io.ballerina.runtime.api.values.BArray; +import io.ballerina.runtime.api.values.BHandle; +import io.ballerina.runtime.api.values.BObject; +import io.ballerina.runtime.api.values.BString; + +import static org.wssec.Constants.NATIVE_ENCRYPTION; +import static org.wssec.Utils.createError; + +public class Encryption { + + private String encryptionAlgorithm; + private byte[] encryptedData; + + public static void setEncryptionAlgorithm(BObject encrypt, BString encryptionAlgorithm) { + BHandle handle = (BHandle) encrypt.get(StringUtils.fromString(NATIVE_ENCRYPTION)); + Encryption encryption = (Encryption) handle.getValue(); + encryption.setEncryptionAlgorithm(encryptionAlgorithm.getValue()); + } + + public static void setEncryptedData(BObject encrypt, BArray encryptedData) { + BHandle handle = (BHandle) encrypt.get(StringUtils.fromString(NATIVE_ENCRYPTION)); + Encryption encryption = (Encryption) handle.getValue(); + encryption.setEncryptedData(encryptedData.getByteArray()); + } + + public static BArray getEncryptedData(BObject encrypt) { + BHandle handle = (BHandle) encrypt.get(StringUtils.fromString(NATIVE_ENCRYPTION)); + Encryption encryption = (Encryption) handle.getValue(); + return ValueCreator.createArrayValue(encryption.getEncryptedData()); + } + + public static Object getEncryptedKeyElements(BArray encryptedData) { + try { + return WsSecurityUtils.getEncryptedKeyElement(encryptedData.getByteArray()); + } catch (Exception e) { + return createError(e.getMessage()); + } + } + + protected String getEncryptionAlgorithm() { + return encryptionAlgorithm; + } + + protected byte[] getEncryptedData() { + return encryptedData; + } + + protected void setEncryptionAlgorithm(String encryptionAlgorithm) { + this.encryptionAlgorithm = encryptionAlgorithm; + } + + protected void setEncryptedData(byte[] encryptedData) { + this.encryptedData = encryptedData; + } +} From 56e6c7098b3cf2cab480db454a3a8e26f437378f Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Tue, 3 Oct 2023 11:54:37 +0530 Subject: [PATCH 077/189] Create APIs to access data in SOAP envelopes --- ballerina/modules/wssec/document.bal | 45 +++++++++++ .../main/java/org/wssec/DocumentBuilder.java | 75 +++++++++++++++++++ 2 files changed, 120 insertions(+) create mode 100644 ballerina/modules/wssec/document.bal create mode 100644 native/src/main/java/org/wssec/DocumentBuilder.java diff --git a/ballerina/modules/wssec/document.bal b/ballerina/modules/wssec/document.bal new file mode 100644 index 0000000..62b8694 --- /dev/null +++ b/ballerina/modules/wssec/document.bal @@ -0,0 +1,45 @@ +// Copyright (c) 2023, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +// +// WSO2 Inc. licenses this file to you under the Apache License, +// Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +import ballerina/jballerina.java; + +class Document { + private handle nativeDocumentBuilder; + + public function init(xml xmlPayload) returns Error? { + handle|error documentBuilder = newDocument(xmlPayload); + if documentBuilder is error { + return error Error(documentBuilder.message()); + } else { + self.nativeDocumentBuilder = documentBuilder; + } + } + + public function getDocument() returns string|Error = @java:Method { + 'class: "org.wssec.DocumentBuilder" + } external; + + public function getEncryptedData() returns byte[] = @java:Method { + 'class: "org.wssec.DocumentBuilder" + } external; + + public function getSignatureData() returns byte[] = @java:Method { + 'class: "org.wssec.DocumentBuilder" + } external; +} + +function newDocument(xml xmlPayload) returns handle|error = @java:Constructor { + 'class: "org.wssec.DocumentBuilder" +} external; diff --git a/native/src/main/java/org/wssec/DocumentBuilder.java b/native/src/main/java/org/wssec/DocumentBuilder.java new file mode 100644 index 0000000..4fc4894 --- /dev/null +++ b/native/src/main/java/org/wssec/DocumentBuilder.java @@ -0,0 +1,75 @@ +// Copyright (c) 2023, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +// +// WSO2 Inc. licenses this file to you under the Apache License, +// Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.wssec; + +import io.ballerina.runtime.api.creators.ErrorCreator; +import io.ballerina.runtime.api.creators.ValueCreator; +import io.ballerina.runtime.api.utils.StringUtils; +import io.ballerina.runtime.api.values.BArray; +import io.ballerina.runtime.api.values.BHandle; +import io.ballerina.runtime.api.values.BObject; +import io.ballerina.runtime.api.values.BXml; +import org.w3c.dom.Document; +import org.xml.sax.InputSource; + +import java.io.StringReader; + +import javax.xml.parsers.DocumentBuilderFactory; + +import static org.wssec.Constants.NATIVE_DOCUMENT; + +public class DocumentBuilder { + + private final Document document; + + public DocumentBuilder(BXml xmlPayload) throws Exception { + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + factory.setNamespaceAware(true); + this.document = factory.newDocumentBuilder().parse(new InputSource(new StringReader(xmlPayload.toString()))); + } + + protected DocumentBuilder(Document document) { + this.document = document; + } + + public static Object getDocument(BObject documentBuilder) { + BHandle handle = (BHandle) documentBuilder.get(StringUtils.fromString(NATIVE_DOCUMENT)); + DocumentBuilder docBuilder = (DocumentBuilder) handle.getValue(); + Document document = docBuilder.getNativeDocument(); + try { + return WsSecurityUtils.convertDocumentToString(document); + } catch (Exception e) { + return ErrorCreator.createError(StringUtils.fromString(e.getMessage())); + } + } + + public static BArray getSignatureData(BObject document) { + BHandle handle = (BHandle) document.get(StringUtils.fromString(NATIVE_DOCUMENT)); + DocumentBuilder docBuilder = (DocumentBuilder) handle.getValue(); + return ValueCreator.createArrayValue(WsSecurityUtils.getSignatureValue(docBuilder.getNativeDocument())); + } + + public static BArray getEncryptedData(BObject document) { + BHandle handle = (BHandle) document.get(StringUtils.fromString(NATIVE_DOCUMENT)); + DocumentBuilder docBuilder = (DocumentBuilder) handle.getValue(); + return ValueCreator.createArrayValue(WsSecurityUtils.getEncryptedData(docBuilder.getNativeDocument())); + } + + protected Document getNativeDocument() { + return this.document; + } +} From a12e29dcf2c58e65e016581b38d236cfccc13e17 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Tue, 3 Oct 2023 11:55:53 +0530 Subject: [PATCH 078/189] Create APIs to add security headers in SOAP envelopes --- ballerina/modules/wssec/sec_header.bal | 32 ++++++++++ .../main/java/org/wssec/WsSecurityHeader.java | 59 +++++++++++++++++++ 2 files changed, 91 insertions(+) create mode 100644 ballerina/modules/wssec/sec_header.bal create mode 100644 native/src/main/java/org/wssec/WsSecurityHeader.java diff --git a/ballerina/modules/wssec/sec_header.bal b/ballerina/modules/wssec/sec_header.bal new file mode 100644 index 0000000..e3f0537 --- /dev/null +++ b/ballerina/modules/wssec/sec_header.bal @@ -0,0 +1,32 @@ +// Copyright (c) 2023, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +// +// WSO2 Inc. licenses this file to you under the Apache License, +// Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +import ballerina/jballerina.java; + +class WSSecurityHeader { + private handle nativeSecHeader; + + function init(Document document) returns Error? { + self.nativeSecHeader = newSecHeader(document); + } + + function insertSecHeader() returns Error? = @java:Method { + 'class: "org.wssec.WsSecurityHeader" + } external; +} + +function newSecHeader(Document document) returns handle = @java:Constructor { + 'class: "org.wssec.WsSecurityHeader" +} external; diff --git a/native/src/main/java/org/wssec/WsSecurityHeader.java b/native/src/main/java/org/wssec/WsSecurityHeader.java new file mode 100644 index 0000000..e5724b5 --- /dev/null +++ b/native/src/main/java/org/wssec/WsSecurityHeader.java @@ -0,0 +1,59 @@ +// Copyright (c) 2023, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +// +// WSO2 Inc. licenses this file to you under the Apache License, +// Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.wssec; + +import io.ballerina.runtime.api.utils.StringUtils; +import io.ballerina.runtime.api.values.BHandle; +import io.ballerina.runtime.api.values.BObject; +import org.apache.wss4j.common.ext.WSSecurityException; +import org.apache.wss4j.dom.message.WSSecHeader; +import org.w3c.dom.Document; + +import static org.wssec.Constants.NATIVE_DOCUMENT; +import static org.wssec.Constants.NATIVE_SEC_HEADER; +import static org.wssec.Utils.createError; + +public class WsSecurityHeader { + + private final WSSecHeader wsSecHeader; + private final Document document; + + public WsSecurityHeader(BObject documentBuilder) { + BHandle handle = (BHandle) documentBuilder.get(StringUtils.fromString(NATIVE_DOCUMENT)); + DocumentBuilder docBuilder = (DocumentBuilder) handle.getValue(); + this.wsSecHeader = new WSSecHeader(docBuilder.getNativeDocument()); + this.document = docBuilder.getNativeDocument(); + } + + protected Document getDocument() { + return document; + } + + protected WSSecHeader getWsSecHeader() { + return wsSecHeader; + } + + public static void insertSecHeader(BObject secHeader) { + BHandle handle = (BHandle) secHeader.get(StringUtils.fromString(NATIVE_SEC_HEADER)); + WsSecurityHeader wsSecurityHeader = (WsSecurityHeader) handle.getValue(); + try { + wsSecurityHeader.getWsSecHeader().insertSecurityHeader(); + } catch (WSSecurityException e) { + throw createError(e.getMessage()); + } + } +} From 8c877d17cdc82f7ed67b1c2d73d792ea8da16d9b Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Tue, 3 Oct 2023 12:02:19 +0530 Subject: [PATCH 079/189] Apply changes to support username token security policy --- ballerina/modules/wssec/ws_security.bal | 23 +++++ .../modules/wssec/ws_security_methods.bal | 30 +++++++ .../main/java/org/wssec/WSSecurityUtils.java | 90 +++++++++++++++++++ .../src/main/java/org/wssec/WsSecurity.java | 80 +++++++++++++++++ 4 files changed, 223 insertions(+) create mode 100644 ballerina/modules/wssec/ws_security.bal create mode 100644 ballerina/modules/wssec/ws_security_methods.bal create mode 100644 native/src/main/java/org/wssec/WSSecurityUtils.java create mode 100644 native/src/main/java/org/wssec/WsSecurity.java diff --git a/ballerina/modules/wssec/ws_security.bal b/ballerina/modules/wssec/ws_security.bal new file mode 100644 index 0000000..b055768 --- /dev/null +++ b/ballerina/modules/wssec/ws_security.bal @@ -0,0 +1,23 @@ +// Copyright (c) 2023, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +// +// WSO2 Inc. licenses this file to you under the Apache License, +// Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +import ballerina/jballerina.java; + +class WsSecurity { + function applyUsernameTokenPolicy(WSSecurityHeader wsSecurityHeader, string username, + string password, string pwType) returns string|Error = @java:Method { + 'class: "org.wssec.WsSecurity" + } external; +} diff --git a/ballerina/modules/wssec/ws_security_methods.bal b/ballerina/modules/wssec/ws_security_methods.bal new file mode 100644 index 0000000..d017977 --- /dev/null +++ b/ballerina/modules/wssec/ws_security_methods.bal @@ -0,0 +1,30 @@ +// Copyright (c) 2023, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +// +// WSO2 Inc. licenses this file to you under the Apache License, +// Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +import ballerina/crypto; +import ballerina/regex; +# Apply username token security policy to the SOAP envelope. +# +# + envelope - The SOAP envelope +# + usernameToken - The `UsernameTokenConfig` record with the required parameters +# + return - A `xml` type of SOAP envelope if the security binding is successfully added or else `wssec:Error` +public function applyUsernameToken(xml envelope, *UsernameTokenConfig usernameToken) returns xml|Error { + Document document = check new (envelope); + WSSecurityHeader wsSecurityHeader = check addSecurityHeader(document); + WsSecurity wsSecurity = new; + string securedEnvelope = check wsSecurity.applyUsernameTokenPolicy(wsSecurityHeader, usernameToken.username, + usernameToken.password, usernameToken.passwordType); + return convertStringToXml(securedEnvelope); +} diff --git a/native/src/main/java/org/wssec/WSSecurityUtils.java b/native/src/main/java/org/wssec/WSSecurityUtils.java new file mode 100644 index 0000000..8fff3b0 --- /dev/null +++ b/native/src/main/java/org/wssec/WSSecurityUtils.java @@ -0,0 +1,90 @@ +// Copyright (c) 2023, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +// +// WSO2 Inc. licenses this file to you under the Apache License, +// Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.wssec; + +import io.ballerina.runtime.api.creators.ErrorCreator; +import io.ballerina.runtime.api.utils.StringUtils; +import org.apache.wss4j.common.WSEncryptionPart; +import org.apache.wss4j.dom.handler.RequestData; +import org.apache.wss4j.dom.message.WSSecSignature; +import org.apache.wss4j.dom.message.WSSecUsernameToken; +import org.apache.wss4j.dom.util.WSSecurityUtil; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; +import org.w3c.dom.Text; + +import java.io.StringWriter; +import java.util.ArrayList; +import java.util.Base64; +import java.util.List; +import java.util.Objects; + +import javax.xml.crypto.dsig.Reference; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + +import static org.apache.wss4j.common.WSS4JConstants.ENC_NS; +import static org.apache.wss4j.common.WSS4JConstants.KEYTRANSPORT_RSA15; +import static org.apache.wss4j.common.WSS4JConstants.PASSWORD_DIGEST; +import static org.apache.wss4j.common.WSS4JConstants.PASSWORD_TEXT; +import static org.apache.wss4j.common.WSS4JConstants.SIG_NS; +import static org.wssec.Constants.ALGORITHM; +import static org.wssec.Constants.CIPHER_DATA_TAG; +import static org.wssec.Constants.CIPHER_VALUE_TAG; +import static org.wssec.Constants.DERIVED_KEY_DIGEST; +import static org.wssec.Constants.DIGEST; +import static org.wssec.Constants.EMPTY_XML_DOCUMENT_ERROR; +import static org.wssec.Constants.ENCRYPTED_KEY_TAG; +import static org.wssec.Constants.ENCRYPTION_METHOD_TAG; +import static org.wssec.Constants.KEY_INFO_TAG; +import static org.wssec.Constants.NAMESPACE_URI_ENC; +import static org.wssec.Constants.SIGNATURE_METHOD_TAG; +import static org.wssec.Constants.SIGNATURE_VALUE_TAG; +import static org.wssec.Constants.XML_DS_NS; +import static org.wssec.Constants.XML_ENC_NS; + +public class WsSecurityUtils { + + public static void setUTChildElements(WSSecUsernameToken usernameToken, String passwordType, + String username, String password) { + if (Objects.equals(passwordType, DIGEST) + || Objects.equals(passwordType, DERIVED_KEY_DIGEST)) { + usernameToken.setPasswordType(PASSWORD_DIGEST); + usernameToken.setUserInfo(username, password); + usernameToken.addCreated(); + usernameToken.addNonce(); + } else { + usernameToken.setPasswordType(PASSWORD_TEXT); + usernameToken.setUserInfo(username, password); + } + } + + public static Object convertDocumentToString(Document document) throws Exception { + if (document == null) { + return ErrorCreator.createError(StringUtils.fromString(EMPTY_XML_DOCUMENT_ERROR)); + } + TransformerFactory transformerFactory = TransformerFactory.newInstance(); + Transformer transformer = transformerFactory.newTransformer(); + StringWriter writer = new StringWriter(); + transformer.transform(new DOMSource(document), new StreamResult(writer)); + return StringUtils.fromString(writer.toString()); + } +} diff --git a/native/src/main/java/org/wssec/WsSecurity.java b/native/src/main/java/org/wssec/WsSecurity.java new file mode 100644 index 0000000..58b5ecf --- /dev/null +++ b/native/src/main/java/org/wssec/WsSecurity.java @@ -0,0 +1,80 @@ +// Copyright (c) 2023, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +// +// WSO2 Inc. licenses this file to you under the Apache License, +// Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.wssec; + +import io.ballerina.runtime.api.utils.StringUtils; +import io.ballerina.runtime.api.values.BHandle; +import io.ballerina.runtime.api.values.BObject; +import io.ballerina.runtime.api.values.BString; +import org.apache.wss4j.common.ext.WSSecurityException; +import org.apache.wss4j.common.util.UsernameTokenUtil; +import org.apache.wss4j.dom.WSDocInfo; +import org.apache.wss4j.dom.engine.WSSConfig; +import org.apache.wss4j.dom.handler.RequestData; +import org.apache.wss4j.dom.message.WSSecDKEncrypt; +import org.apache.wss4j.dom.message.WSSecSignature; +import org.apache.wss4j.dom.message.WSSecTimestamp; +import org.apache.wss4j.dom.message.WSSecUsernameToken; +import org.apache.xml.security.Init; +import org.apache.xml.security.algorithms.JCEMapper; +import org.w3c.dom.Document; + +import java.io.FileInputStream; +import java.io.IOException; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; + +import static org.apache.wss4j.common.WSS4JConstants.AES_128_GCM; +import static org.apache.wss4j.common.WSS4JConstants.HMAC_SHA1; +import static org.apache.wss4j.dom.WSConstants.CUSTOM_KEY_IDENTIFIER; +import static org.apache.wss4j.dom.WSConstants.X509_KEY_IDENTIFIER; +import static org.wssec.Constants.DERIVED_KEY_DIGEST; +import static org.wssec.Constants.DERIVED_KEY_TEXT; +import static org.wssec.Constants.ITERATION; +import static org.wssec.Constants.NATIVE_ENCRYPTION; +import static org.wssec.Constants.NATIVE_SEC_HEADER; +import static org.wssec.Constants.NATIVE_SIGNATURE; +import static org.wssec.Constants.X509; +import static org.wssec.Utils.createError; +import static org.wssec.WsSecurityUtils.convertDocumentToString; +import static org.wssec.WsSecurityUtils.setUTChildElements; + +public class WsSecurity { + + public static Object applyUsernameTokenPolicy(BObject wsSecHeader, BString username, + BString password, BString passwordType) { + BHandle handle = (BHandle) wsSecHeader.get(StringUtils.fromString(NATIVE_SEC_HEADER)); + WsSecurityHeader wsSecurityHeader = (WsSecurityHeader) handle.getValue(); + WSSecUsernameToken usernameToken = new WSSecUsernameToken(wsSecurityHeader.getWsSecHeader()); + setUTChildElements(usernameToken, passwordType.getValue(), username.getValue(), password.getValue()); + Document xmlDocument; + switch (passwordType.getValue()) { + case DERIVED_KEY_TEXT, DERIVED_KEY_DIGEST -> { + usernameToken.addDerivedKey(Constants.ITERATION); + xmlDocument = usernameToken.build(UsernameTokenUtil.generateSalt(true)); + } + default -> xmlDocument = usernameToken.build(); + } + try { + return convertDocumentToString(xmlDocument); + } catch (Exception e) { + return createError(e.getMessage()); + } + } + +} From e65dc4f1da990d507225a27007b7e71d3aea5806 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Tue, 3 Oct 2023 12:04:37 +0530 Subject: [PATCH 080/189] Apply changes to support timestamp token security policy --- ballerina/modules/wssec/records.bal | 33 +++++++++++++++++++ ballerina/modules/wssec/ws_security.bal | 5 +++ .../modules/wssec/ws_security_methods.bal | 27 +++++++++++++++ .../src/main/java/org/wssec/WsSecurity.java | 11 +++++++ 4 files changed, 76 insertions(+) create mode 100644 ballerina/modules/wssec/records.bal diff --git a/ballerina/modules/wssec/records.bal b/ballerina/modules/wssec/records.bal new file mode 100644 index 0000000..1a1750a --- /dev/null +++ b/ballerina/modules/wssec/records.bal @@ -0,0 +1,33 @@ +// Copyright (c) 2023, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +// +// WSO2 Inc. licenses this file to you under the Apache License, +// Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +import ballerina/crypto; +# Represents the record for Username Token policy. +# +# + username - The name of the user +# + password - The password of the user +# + passwordType - The password type of the username token +public type UsernameTokenConfig record {| + string username; + string password; + PasswordType passwordType; +|}; + +# Represents the record for Timestamp Token policy. +# +# + timeToLive - The time to get expired +public type TimestampTokenConfig record {| + int timeToLive = 300; +|}; diff --git a/ballerina/modules/wssec/ws_security.bal b/ballerina/modules/wssec/ws_security.bal index b055768..e0f4777 100644 --- a/ballerina/modules/wssec/ws_security.bal +++ b/ballerina/modules/wssec/ws_security.bal @@ -20,4 +20,9 @@ class WsSecurity { string password, string pwType) returns string|Error = @java:Method { 'class: "org.wssec.WsSecurity" } external; + + function applyTimestampPolicy(WSSecurityHeader wsSecurityHeader, int timeToLive) + returns string|Error = @java:Method { + 'class: "org.wssec.WsSecurity" + } external; } diff --git a/ballerina/modules/wssec/ws_security_methods.bal b/ballerina/modules/wssec/ws_security_methods.bal index d017977..efbe65d 100644 --- a/ballerina/modules/wssec/ws_security_methods.bal +++ b/ballerina/modules/wssec/ws_security_methods.bal @@ -15,6 +15,33 @@ // under the License. import ballerina/crypto; import ballerina/regex; + +xmlns "http://schemas.xmlsoap.org/soap/envelope/" as soap; +xmlns "http://www.w3.org/2000/09/xmldsig#" as ds; +function addSecurityHeader(Document document) returns WSSecurityHeader|Error { + WSSecurityHeader wsSecHeader = check new (document); + Error? insertHeader = wsSecHeader.insertSecHeader(); + if insertHeader is () { + return wsSecHeader; + } + return insertHeader; +} +# Apply timestamp token security policy to the SOAP envelope. +# +# + envelope - The SOAP envelope +# + timestampToken - The `TSRecord` record with the required parameters +# + return - A `xml` type of SOAP envelope if the security binding is successfully added or else `wssec:Error` +public function applyTimestampToken(xml envelope, *TimestampTokenConfig timestampToken) returns xml|Error { + if timestampToken.timeToLive <= 0 { + return error Error("Invalid value for `timeToLive`"); + } + Document document = check new (envelope); + WSSecurityHeader wsSecurityHeader = check addSecurityHeader(document); + WsSecurity wsSecurity = new; + string securedEnvelope = check wsSecurity.applyTimestampPolicy(wsSecurityHeader, timestampToken.timeToLive); + return convertStringToXml(securedEnvelope); +} + # Apply username token security policy to the SOAP envelope. # # + envelope - The SOAP envelope diff --git a/native/src/main/java/org/wssec/WsSecurity.java b/native/src/main/java/org/wssec/WsSecurity.java index 58b5ecf..007ca1d 100644 --- a/native/src/main/java/org/wssec/WsSecurity.java +++ b/native/src/main/java/org/wssec/WsSecurity.java @@ -77,4 +77,15 @@ public static Object applyUsernameTokenPolicy(BObject wsSecHeader, BString usern } } + public static Object applyTimestampPolicy(BObject wsSecHeader, int timeToLive) { + BHandle handle = (BHandle) wsSecHeader.get(StringUtils.fromString(NATIVE_SEC_HEADER)); + WsSecurityHeader wsSecurityHeader = (WsSecurityHeader) handle.getValue(); + WSSecTimestamp timestamp = new WSSecTimestamp(wsSecurityHeader.getWsSecHeader()); + timestamp.setTimeToLive(timeToLive); + try { + return convertDocumentToString(timestamp.build()); + } catch (Exception e) { + return createError(e.getMessage()); + } + } } From 41eabf7cdcf320516db36b5e75150a2c6b06c3a8 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Tue, 3 Oct 2023 12:06:46 +0530 Subject: [PATCH 081/189] Apply changes to support symmetric binding security policy --- ballerina/modules/wssec/records.bal | 16 +++ ballerina/modules/wssec/ws_security.bal | 10 ++ .../modules/wssec/ws_security_methods.bal | 104 ++++++++++++++++++ .../src/main/java/org/wssec/WsSecurity.java | 76 +++++++++++++ 4 files changed, 206 insertions(+) diff --git a/ballerina/modules/wssec/records.bal b/ballerina/modules/wssec/records.bal index 1a1750a..5b542da 100644 --- a/ballerina/modules/wssec/records.bal +++ b/ballerina/modules/wssec/records.bal @@ -31,3 +31,19 @@ public type UsernameTokenConfig record {| public type TimestampTokenConfig record {| int timeToLive = 300; |}; + +# Represents the record for Symmetric Binding policy. +# +# + symmetricKey - The key to sign and encrypt the SOAP envelope +# + servicePublicKey - The key to encrypt the symmetric key +# + signatureAlgorithm - The algorithm to sign the SOAP envelope +# + encryptionAlgorithm - The algorithm to encrypt the SOAP envelope +# + x509Token - The path or token of the X509 certificate +public type SymmetricBindingConfig record {| + crypto:PrivateKey symmetricKey; + crypto:PublicKey servicePublicKey; + SignatureAlgorithm signatureAlgorithm?; + EncryptionAlgorithm encryptionAlgorithm?; + string x509Token?; +|}; + diff --git a/ballerina/modules/wssec/ws_security.bal b/ballerina/modules/wssec/ws_security.bal index e0f4777..036ce95 100644 --- a/ballerina/modules/wssec/ws_security.bal +++ b/ballerina/modules/wssec/ws_security.bal @@ -25,4 +25,14 @@ class WsSecurity { returns string|Error = @java:Method { 'class: "org.wssec.WsSecurity" } external; + + function applySignatureOnlyPolicy(WSSecurityHeader wsSecurityPolicy, Signature signature, string? x509FilePath) + returns string|Error = @java:Method { + 'class: "org.wssec.WsSecurity" + } external; + + function applyEncryptionOnlyPolicy(WSSecurityHeader wsSecurityPolicy, Encryption encryption) + returns string|Error = @java:Method { + 'class: "org.wssec.WsSecurity" + } external; } diff --git a/ballerina/modules/wssec/ws_security_methods.bal b/ballerina/modules/wssec/ws_security_methods.bal index efbe65d..54e6d95 100644 --- a/ballerina/modules/wssec/ws_security_methods.bal +++ b/ballerina/modules/wssec/ws_security_methods.bal @@ -26,6 +26,73 @@ function addSecurityHeader(Document document) returns WSSecurityHeader|Error { } return insertHeader; } + +public function decryptData(byte[] cipherText, EncryptionAlgorithm encryptionAlgorithm, + byte[]|crypto:PublicKey|crypto:PrivateKey key) returns byte[]|Error { + Encryption encrypt = check new (); + return encrypt.decryptData(cipherText, encryptionAlgorithm, key); +} + +function addSignature(Signature sign, string signatureAlgorithm, byte[] signature) returns Signature|Error { + sign.setSignatureAlgorithm(signatureAlgorithm); + sign.setSignatureValue(signature); + return sign; +} + +function addEncryption(Encryption encrypt, string encryptionAlgorithm, byte[] encryption) returns Encryption|Error { + encrypt.setEncryptionAlgorithm(encryptionAlgorithm); + encrypt.setEncryptedData(encryption); + return encrypt; +} + +function applyEncryptedKey(string envelopeString, crypto:PrivateKey symmetricKey, crypto:PublicKey encryptKey) returns string|Error { + string securedEnvelope = envelopeString; + do { + Encryption encryption = check new (); + byte[] encryptedKey = check crypto:encryptRsaEcb(symmetricKey.toBalString().toBytes(), encryptKey); + string encryptedKeyElements = check encryption.getEncryptedKeyElements(encryptedKey); + string replace = regex:replace(encryptedKeyElements, string `<`, "<"); + if securedEnvelope.includesMatch(re``) { + securedEnvelope = regex:replace(securedEnvelope, string``, replace); + } + else if securedEnvelope.includesMatch(re``) { + securedEnvelope = regex:replace(securedEnvelope, string``, replace); + } + else if securedEnvelope.includesMatch(re`.*`) { + securedEnvelope = regex:replace(securedEnvelope, string`.*`, replace); + } + return securedEnvelope; + } on fail var e { + return error Error(e.message()); + } +} + +function convertStringToXml(string envelope) returns xml|Error { + do { + return check xml:fromString(regex:replace(envelope, string `<`, "<")); + } on fail var e { + return error Error(e.message()); + } +} + +# Returns the encrypted data of the SOAP envelope. +# +# + envelope - The SOAP envelope +# + return - A `byte[]` if the encrypted data is successfully decoded or else `wssec:Error` +public function getEncryptedData(xml envelope) returns byte[]|Error { + Document document = check new (envelope); + return document.getEncryptedData(); +} + +# Returns the signed data of the SOAP envelope. +# +# + envelope - The SOAP envelope +# + return - A `byte[]` if the signed data is successfully decoded or else `wssec:Error` +public function getSignatureData(xml envelope) returns byte[]|Error { + Document document = check new (envelope); + return document.getSignatureData(); +} + # Apply timestamp token security policy to the SOAP envelope. # # + envelope - The SOAP envelope @@ -55,3 +122,40 @@ public function applyUsernameToken(xml envelope, *UsernameTokenConfig usernameTo usernameToken.password, usernameToken.passwordType); return convertStringToXml(securedEnvelope); } + +# Apply symmetric binding security policy with username token to the SOAP envelope. +# +# + envelope - The SOAP envelope +# + symmetricBinding - The `SymmetricBindingConfig` record with the required parameters +# + return - A `xml` type of SOAP envelope if the security binding is successfully added or else `wssec:Error` +public function applySymmetricBinding(xml envelope, *SymmetricBindingConfig symmetricBinding) returns xml|Error { + Document document = check new (envelope); + WSSecurityHeader wsSecurityHeader = check addSecurityHeader(document); + string securedEnvelope = envelope.toBalString(); + if symmetricBinding.signatureAlgorithm !is () { + Signature signature = check new (); + byte[] signedData = check signature.signData((envelope//*).toString(), + symmetricBinding.signatureAlgorithm, + symmetricBinding.symmetricKey); + Signature signatureResult = check addSignature(signature, + symmetricBinding.signatureAlgorithm, + signedData); + WsSecurity wsSecurity = new; + securedEnvelope = check wsSecurity.applySignatureOnlyPolicy(wsSecurityHeader, signatureResult, + symmetricBinding.x509Token); + } + if symmetricBinding.encryptionAlgorithm !is () { + Encryption encryption = check new (); + byte[] encryptData = check encryption.encryptData((envelope//*).toString(), + symmetricBinding.encryptionAlgorithm, + symmetricBinding.symmetricKey); + Encryption encryptionResult = check addEncryption(encryption, + symmetricBinding.encryptionAlgorithm, + encryptData); + WsSecurity wsSecurity = new; + securedEnvelope = check wsSecurity.applyEncryptionOnlyPolicy(wsSecurityHeader, encryptionResult); + } + securedEnvelope = check applyEncryptedKey(securedEnvelope, symmetricBinding.symmetricKey, symmetricBinding.servicePublicKey); + return convertStringToXml(securedEnvelope); +} + diff --git a/native/src/main/java/org/wssec/WsSecurity.java b/native/src/main/java/org/wssec/WsSecurity.java index 007ca1d..d3bfcee 100644 --- a/native/src/main/java/org/wssec/WsSecurity.java +++ b/native/src/main/java/org/wssec/WsSecurity.java @@ -88,4 +88,80 @@ public static Object applyTimestampPolicy(BObject wsSecHeader, int timeToLive) { return createError(e.getMessage()); } } + + public static Object applySignatureOnlyPolicy(BObject wsSecHeader, BObject balSignature, Object x509FilePath) { + BHandle handle = (BHandle) wsSecHeader.get(StringUtils.fromString(NATIVE_SEC_HEADER)); + WsSecurityHeader wsSecurityHeader = (WsSecurityHeader) handle.getValue(); + handle = (BHandle) balSignature.get(StringUtils.fromString(NATIVE_SIGNATURE)); + Signature signature = (Signature) handle.getValue(); + try { + Document xmlDocument = createSignatureTags(wsSecurityHeader, x509FilePath); + WsSecurityUtils.setSignatureValue(xmlDocument, signature.getSignatureValue(), + signature.getSignatureAlgorithm()); + return convertDocumentToString(xmlDocument); + } catch (Exception e) { + return createError(e.getMessage()); + } + } + + public static Object applyEncryptionOnlyPolicy(BObject wsSecHeader, BObject balEncryption) { + BHandle handle = (BHandle) wsSecHeader.get(StringUtils.fromString(NATIVE_SEC_HEADER)); + WsSecurityHeader wsSecurityHeader = (WsSecurityHeader) handle.getValue(); + handle = (BHandle) balEncryption.get(StringUtils.fromString(NATIVE_ENCRYPTION)); + Encryption encryption = (Encryption) handle.getValue(); + try { + byte[] key = UsernameTokenUtil.generateDerivedKey("password", + UsernameTokenUtil.generateSalt(true), ITERATION); + Document xmlDocument = encryptEnvelope(wsSecurityHeader, key); + WsSecurityUtils.setEncryptedData(xmlDocument, encryption.getEncryptedData(), + encryption.getEncryptionAlgorithm()); + return convertDocumentToString(xmlDocument); + } catch (Exception e) { + return createError(e.getMessage()); + } + } + + public static Document encryptEnvelope(WsSecurityHeader wsSecurityHeader, byte[] rawKey) + throws WSSecurityException { + Init.init(); + JCEMapper.registerDefaultAlgorithms(); + WSSecDKEncrypt encryptionBuilder = new WSSecDKEncrypt(wsSecurityHeader.getWsSecHeader()); + encryptionBuilder.setSymmetricEncAlgorithm(AES_128_GCM); + return encryptionBuilder.build(rawKey); + } + + public static Document createSignatureTags(WsSecurityHeader wsSecurityHeader, + Object x509FilePath) throws Exception { + RequestData reqData = new RequestData(); + reqData.setSecHeader(wsSecurityHeader.getWsSecHeader()); + reqData.setWssConfig(WSSConfig.getNewInstance()); + reqData.setWsDocInfo(new WSDocInfo(wsSecurityHeader.getDocument())); + WSSecSignature wsSecSignature = prepareSignature(reqData, x509FilePath); + WsSecurityUtils.buildSignature(reqData, wsSecSignature); + return wsSecSignature.build(null); + } + + public static WSSecSignature prepareSignature(RequestData reqData, Object x509FilePath) { + WSSecSignature sign = new WSSecSignature(reqData.getSecHeader()); + try { + byte[] key = UsernameTokenUtil.generateDerivedKey("password", + UsernameTokenUtil.generateSalt(true), ITERATION); + sign.setSecretKey(key); + sign.setWsDocInfo(reqData.getWsDocInfo()); + sign.setSignatureAlgorithm(HMAC_SHA1); + sign.setKeyIdentifierType(CUSTOM_KEY_IDENTIFIER); + if (x509FilePath != null) { + FileInputStream fis = new FileInputStream(x509FilePath.toString()); + CertificateFactory certificateFactory = CertificateFactory.getInstance(X509); + X509Certificate x509Certificate = (X509Certificate) certificateFactory.generateCertificate(fis); + sign.setKeyIdentifierType(X509_KEY_IDENTIFIER); + sign.setX509Certificate(x509Certificate); + fis.close(); + } + sign.prepare(null); + } catch (CertificateException | WSSecurityException | IOException e) { + throw createError(e.getMessage()); + } + return sign; + } } From 0581d697b85ab9898510d1f4cb06a0b0de63822c Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Tue, 3 Oct 2023 12:07:32 +0530 Subject: [PATCH 082/189] Add necessary APIs to encrypt and sign SOAP envelopes --- .../main/java/org/wssec/WSSecurityUtils.java | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/native/src/main/java/org/wssec/WSSecurityUtils.java b/native/src/main/java/org/wssec/WSSecurityUtils.java index 8fff3b0..977fd20 100644 --- a/native/src/main/java/org/wssec/WSSecurityUtils.java +++ b/native/src/main/java/org/wssec/WSSecurityUtils.java @@ -63,6 +63,61 @@ public class WsSecurityUtils { + public static void buildSignature(RequestData reqData, WSSecSignature sign) throws Exception { + List parts; + parts = new ArrayList<>(1); + Document doc = reqData.getSecHeader().getSecurityHeaderElement().getOwnerDocument(); + parts.add(WSSecurityUtil.getDefaultEncryptionPart(doc)); + List referenceList = sign.addReferencesToSign(parts); + sign.computeSignature(referenceList); + reqData.getSignatureValues().add(sign.getSignatureValue()); + } + + public static void setSignatureValue(Document doc, byte[] signature, String algorithm) { + doc.getElementsByTagName(SIGNATURE_METHOD_TAG) + .item(0).getAttributes().item(0).setNodeValue(algorithm); + NodeList digestValueList = doc.getElementsByTagName(SIGNATURE_VALUE_TAG); + digestValueList.item(0).getFirstChild().setNodeValue(Base64.getEncoder().encodeToString(signature)); + } + + public static byte[] getSignatureValue(Document doc) { + String signature = doc.getElementsByTagName(SIGNATURE_VALUE_TAG).item(0).getFirstChild().getNodeValue(); + return Base64.getDecoder().decode(signature); + } + + public static void setEncryptedData(Document doc, byte[] encryptedData, String algorithm) { + Element cipherDataElement = (Element) doc + .getElementsByTagNameNS(NAMESPACE_URI_ENC, CIPHER_VALUE_TAG).item(0); + cipherDataElement.getFirstChild().setNodeValue(Base64.getEncoder().encodeToString(encryptedData)); + doc.getElementsByTagName(ENCRYPTION_METHOD_TAG).item(0).getAttributes().item(0) + .setNodeValue(algorithm); + } + + public static byte[] getEncryptedData(Document document) { + String encryptedText = document + .getElementsByTagNameNS(NAMESPACE_URI_ENC, CIPHER_VALUE_TAG).item(0) + .getFirstChild().getNodeValue(); + return Base64.getDecoder().decode(encryptedText); + } + + public static Object getEncryptedKeyElement(byte[] encryptKey) throws Exception { + Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument(); + Element encryptedKey = document.createElement(ENCRYPTED_KEY_TAG); + encryptedKey.setAttribute(XML_ENC_NS, ENC_NS); + Element encryptionMethod = document.createElement(ENCRYPTION_METHOD_TAG); + encryptionMethod.setAttribute(ALGORITHM, KEYTRANSPORT_RSA15); + encryptedKey.appendChild(encryptionMethod); + Element keyInfo = document.createElement(KEY_INFO_TAG); + keyInfo.setAttribute(XML_DS_NS, SIG_NS); + encryptedKey.appendChild(keyInfo); + Element cipherData = document.createElement(CIPHER_DATA_TAG); + Text cipherText = document.createTextNode(Base64.getEncoder().encodeToString(encryptKey)); + cipherData.appendChild(cipherText); + encryptedKey.appendChild(cipherData); + document.appendChild(encryptedKey); + return convertDocumentToString(document); + } + public static void setUTChildElements(WSSecUsernameToken usernameToken, String passwordType, String username, String password) { if (Objects.equals(passwordType, DIGEST) From 4faef3088c537963c447125ab69de1909a7b75b4 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Tue, 3 Oct 2023 12:08:31 +0530 Subject: [PATCH 083/189] Apply changes to support asymmetric binding security policy --- ballerina/modules/wssec/records.bal | 14 ++++++++ .../modules/wssec/ws_security_methods.bal | 34 +++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/ballerina/modules/wssec/records.bal b/ballerina/modules/wssec/records.bal index 5b542da..791ab98 100644 --- a/ballerina/modules/wssec/records.bal +++ b/ballerina/modules/wssec/records.bal @@ -47,3 +47,17 @@ public type SymmetricBindingConfig record {| string x509Token?; |}; +# Represents the record for Username Token with Asymmetric Binding policy. +# +# + signatureKey - The private key to sign the SOAP envelope +# + encryptionKey - The public key to encrypt the SOAP body +# + signatureAlgorithm - The algorithm to sign the SOAP envelope +# + encryptionAlgorithm - The algorithm to encrypt the SOAP body +# + x509Token - field description +public type AsymmetricBindingConfig record {| + crypto:PrivateKey signatureKey?; + crypto:PublicKey encryptionKey?; + SignatureAlgorithm signatureAlgorithm?; + EncryptionAlgorithm encryptionAlgorithm?; + string x509Token?; +|}; diff --git a/ballerina/modules/wssec/ws_security_methods.bal b/ballerina/modules/wssec/ws_security_methods.bal index 54e6d95..3189010 100644 --- a/ballerina/modules/wssec/ws_security_methods.bal +++ b/ballerina/modules/wssec/ws_security_methods.bal @@ -159,3 +159,37 @@ public function applySymmetricBinding(xml envelope, *SymmetricBindingConfig symm return convertStringToXml(securedEnvelope); } +# Apply asymmetric binding security policy with X509 token to the SOAP envelope. +# +# + envelope - The SOAP envelope +# + asymmetricBinding - The `AsymmetricBindingConfig` record with the required parameters +# + return - A `xml` type of SOAP envelope if the security binding is successfully added or else `wssec:Error` +public function applyAsymmetricBinding(xml envelope, *AsymmetricBindingConfig asymmetricBinding) returns xml|Error { + Document document = check new (envelope); + WSSecurityHeader wsSecurityHeader = check addSecurityHeader(document); + string securedEnvelope = envelope.toBalString(); + if asymmetricBinding.signatureAlgorithm !is () { + Signature signature = check new (); + byte[] signedData = check signature.signData((envelope//*).toString(), + asymmetricBinding.signatureAlgorithm, + asymmetricBinding.signatureKey); + Signature signatureResult = check addSignature(signature, + asymmetricBinding.signatureAlgorithm, + signedData); + WsSecurity wsSecurity = new; + securedEnvelope = check wsSecurity.applySignatureOnlyPolicy(wsSecurityHeader, signatureResult, + asymmetricBinding.x509Token); + } + if asymmetricBinding.encryptionAlgorithm !is () { + Encryption encryption = check new (); + byte[] encryptData = check encryption.encryptData((envelope//*).toString(), + asymmetricBinding.encryptionAlgorithm, + asymmetricBinding.encryptionKey); + Encryption encryptionResult = check addEncryption(encryption, + asymmetricBinding.encryptionAlgorithm, + encryptData); + WsSecurity wsSecurity = new; + securedEnvelope = check wsSecurity.applyEncryptionOnlyPolicy(wsSecurityHeader, encryptionResult); + } + return convertStringToXml(securedEnvelope); +} From 42b23255f5a21d3a660f09e411f0399cb2de9b3d Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Tue, 3 Oct 2023 12:09:20 +0530 Subject: [PATCH 084/189] Add static variables for string constants --- native/src/main/java/org/wssec/Constants.java | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 native/src/main/java/org/wssec/Constants.java diff --git a/native/src/main/java/org/wssec/Constants.java b/native/src/main/java/org/wssec/Constants.java new file mode 100644 index 0000000..3b7ebdd --- /dev/null +++ b/native/src/main/java/org/wssec/Constants.java @@ -0,0 +1,42 @@ +// Copyright (c) 2023, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +// +// WSO2 Inc. licenses this file to you under the Apache License, +// Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.wssec; + +public class Constants { + + public static final int ITERATION = 1000; + public static final String DIGEST = "DIGEST"; + public static final String DERIVED_KEY_TEXT = "DERIVED_KEY_TEXT"; + public static final String DERIVED_KEY_DIGEST = "DERIVED_KEY_DIGEST"; + public static final String NATIVE_SEC_HEADER = "nativeSecHeader"; + public static final String NATIVE_DOCUMENT = "nativeDocumentBuilder"; + public static final String NATIVE_SIGNATURE = "nativeSignature"; + public static final String NATIVE_ENCRYPTION = "nativeEncryption"; + public static final String SIGNATURE_VALUE_TAG = "ds:SignatureValue"; + public static final String SIGNATURE_METHOD_TAG = "ds:SignatureMethod"; + public static final String ALGORITHM = "Algorithm"; + public static final String KEY_INFO_TAG = "ds:KeyInfo"; + public static final String CIPHER_DATA_TAG = "xenc:CipherData"; + public static final String XML_ENC_NS = "xmlns:xenc"; + public static final String XML_DS_NS = "xmlns:ds"; + public static final String ENCRYPTED_KEY_TAG = "xenc:EncryptedKey"; + public static final String ENCRYPTION_METHOD_TAG = "xenc:EncryptionMethod"; + public static final String NAMESPACE_URI_ENC = "http://www.w3.org/2001/04/xmlenc#"; + public static final String CIPHER_VALUE_TAG = "CipherValue"; + public static final String X509 = "X.509"; + public static final String EMPTY_XML_DOCUMENT_ERROR = "XML Document is empty"; +} From c3fea3050e3a0f2cef717f0069ed09b965e568d3 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Tue, 3 Oct 2023 12:12:37 +0530 Subject: [PATCH 085/189] Create a separate module for SOAP 1.1 --- ballerina/modules/soap11/error.bal | 5 +- ballerina/modules/soap11/soap11.bal | 43 ++++++++--- ballerina/modules/soap11/soap_utils.bal | 95 ------------------------- 3 files changed, 37 insertions(+), 106 deletions(-) delete mode 100644 ballerina/modules/soap11/soap_utils.bal diff --git a/ballerina/modules/soap11/error.bal b/ballerina/modules/soap11/error.bal index 3795222..2fd8412 100644 --- a/ballerina/modules/soap11/error.bal +++ b/ballerina/modules/soap11/error.bal @@ -14,5 +14,8 @@ // specific language governing permissions and limitations // under the License. -# Defines the common error type for the module. +# Defines the common error type for the SOAP 1.1 module. public type Error distinct error; + +const SOAP_RESPONSE_ERROR = "Failed to create SOAP response."; +const SOAP_CLIENT_ERROR = "Failed to initialize SOAP 1.1 client."; diff --git a/ballerina/modules/soap11/soap11.bal b/ballerina/modules/soap11/soap11.bal index 52b4568..5a101f8 100644 --- a/ballerina/modules/soap11/soap11.bal +++ b/ballerina/modules/soap11/soap11.bal @@ -13,18 +13,16 @@ // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. +import soap.common; +import soap.wssec; import ballerina/http; import ballerina/mime; -# Soap client configurations. -# -public type ClientConfiguration record {| - *http:ClientConfiguration; -|}; +xmlns "http://schemas.xmlsoap.org/soap/envelope/" as soap; # Object for the basic SOAP client endpoint. -public isolated client class Client { +public client class Client { private final http:Client soapClient; # Gets invoked during object initialization. @@ -32,11 +30,14 @@ public isolated client class Client { # + url - URL endpoint # + config - Configurations for SOAP client # + return - `error` in case of errors or `()` otherwise - public function init(string url, *ClientConfiguration config) returns Error? { + public function init(string url, *common:ClientConfig config) returns Error? { do { self.soapClient = check new (url, retrieveHttpClientConfig(config)); + self.soapClient = check new (url, common:retrieveHttpClientConfig(config)); + self.inboundSecurity = config.inboundSecurity; + self.outboundSecurity = config.outboundSecurity; } on fail var err { - return error Error("Failed to initialize soap client", err); + return error Error(SOAP_CLIENT_ERROR, err); } } @@ -51,7 +52,17 @@ public isolated client class Client { # + return - If successful, returns the response. Else, returns an error remote function sendReceive(xml|mime:Entity[] body, string action, map headers = {}) returns xml|mime:Entity[]|Error { + do { + if body is xml { + xml applySecurityPoliciesResult = check common:applySecurityPolicies(self.inboundSecurity, body); + xml response = check common:sendReceive(applySecurityPoliciesResult, self.soapClient, + action, headers, false); return sendReceive(body, self.soapClient, action, headers); + } + return check common:sendReceive(body, self.soapClient, action, headers, false); + } on fail var e { + return error Error(e.message()); + } } # Fires and forgets requests. Sends the request without the possibility of any response from the @@ -65,7 +76,19 @@ public isolated client class Client { # + headers - SOAP headers as a `map` # + return - If successful, returns `nil`. Else, returns an error remote function sendOnly(xml|mime:Entity[] body, string action, - map headers = {}) returns Error? { - return sendOnly(body, self.soapClient, action, headers); + map headers = {}) returns Error? { + if body is xml { + do { + xml applySecurityPoliciesResult = check common:applySecurityPolicies(self.inboundSecurity, body); + return check common:sendOnly(applySecurityPoliciesResult, self.soapClient, action, headers, false); + } on fail var e { + return error Error(e.message()); + } + } + do { + return check common:sendOnly(body, self.soapClient, action, headers, false); + } on fail var e { + return error Error(e.message()); + } } } diff --git a/ballerina/modules/soap11/soap_utils.bal b/ballerina/modules/soap11/soap_utils.bal deleted file mode 100644 index 6683934..0000000 --- a/ballerina/modules/soap11/soap_utils.bal +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright (c) 2018, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. -// -// WSO2 Inc. licenses this file to you under the Apache License, -// Version 2.0 (the "License"); you may not use this file except -// in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -import ballerina/http; -import ballerina/mime; - -# Creates a SOAP Request as an `http:Request` -# -# + soapAction - SOAP action -# + body - SOAP request body as an `XML` or `mime:Entity[]` to work with soap attachments -# + headers - SOAP headers as a `map` -# + return - The SOAP Request sent as `http:Request` -function createHttpRequest(xml|mime:Entity[] body, - string? soapAction, map headers = {}) returns http:Request { - http:Request req = new; - if body is xml { - req.setXmlPayload(body); - } else { - req.setBodyParts(body); - } - req.setHeader(mime:CONTENT_TYPE, mime:TEXT_XML); - if soapAction is string { - req.addHeader("SOAPAction", soapAction); - } - foreach string key in headers.keys() { - req.addHeader(key, headers[key].toBalString()); - } - return req; -} - -# Creates the SOAP response from the HTTP Response. -# -# + response - The request to be sent -# + return - The SOAP response created from the `http:Response` or the `error` object when reading the payload -function createSoapResponse(http:Response response) returns xml|error { - xml payload = check response.getXmlPayload(); - xmlns "http://schemas.xmlsoap.org/soap/envelope/" as soap11; - return payload/; -} - -string path = ""; - -function sendReceive(xml|mime:Entity[] body, http:Client httpClient, - string soapAction, map headers = {}) returns xml|Error { - http:Request req = createHttpRequest(body, soapAction, headers); - http:Response response; - do { - response = check httpClient->post(path, req); - } on fail var err { - return error Error("Failed to receive soap response", err); - } - do { - return check createSoapResponse(response); - } on fail var err { - return error Error("Failed to create soap response", err); - } -} - -function sendOnly(xml|mime:Entity[] body, http:Client httpClient, - string? soapAction = (), map headers = {}) returns Error? { - http:Request req = createHttpRequest(body, soapAction, headers); - do { - http:Response _ = check httpClient->post(path, req); - } on fail var err { - return error Error("Failed to create soap response", err); - } -} - -function retrieveHttpClientConfig(ClientConfiguration config) returns http:ClientConfiguration { - return { - httpVersion: config.httpVersion, - http1Settings: config.http1Settings, - http2Settings: config.http2Settings, - timeout: config.timeout, - poolConfig: config?.poolConfig, - auth: config?.auth, - retryConfig: config?.retryConfig, - responseLimits: config.responseLimits, - secureSocket: config?.secureSocket, - circuitBreaker: config?.circuitBreaker - }; -} From a55b735a90eb338bc32c89f0a5be6178d7b40e49 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Tue, 3 Oct 2023 12:13:39 +0530 Subject: [PATCH 086/189] Create a separate module for SOAP 1.2 --- ballerina/modules/soap12/error.bal | 5 +- ballerina/modules/soap12/soap12.bal | 39 ++++++--- ballerina/modules/soap12/soap_utils.bal | 103 ------------------------ 3 files changed, 33 insertions(+), 114 deletions(-) delete mode 100644 ballerina/modules/soap12/soap_utils.bal diff --git a/ballerina/modules/soap12/error.bal b/ballerina/modules/soap12/error.bal index 3795222..f25d859 100644 --- a/ballerina/modules/soap12/error.bal +++ b/ballerina/modules/soap12/error.bal @@ -14,5 +14,8 @@ // specific language governing permissions and limitations // under the License. -# Defines the common error type for the module. +# Defines the common error type for the SOAP 1.2 module. public type Error distinct error; + +const SOAP_RESPONSE_ERROR = "Failed to create SOAP response."; +const SOAP_CLIENT_ERROR = "Failed to initialize SOAP 1.2 client."; diff --git a/ballerina/modules/soap12/soap12.bal b/ballerina/modules/soap12/soap12.bal index f212273..1776b97 100644 --- a/ballerina/modules/soap12/soap12.bal +++ b/ballerina/modules/soap12/soap12.bal @@ -13,18 +13,15 @@ // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. - import ballerina/http; import ballerina/mime; +import soap.wssec; +import soap.common; -# Soap client configurations. -# -public type ClientConfiguration record {| - *http:ClientConfiguration; -|}; +xmlns "http://www.w3.org/2003/05/soap-envelope" as soap; # Object for the basic SOAP client endpoint. -public isolated client class Client { +public client class Client { private final http:Client soapClient; # Gets invoked during object initialization. @@ -32,11 +29,11 @@ public isolated client class Client { # + url - URL endpoint # + config - Configurations for SOAP client # + return - `error` in case of errors or `()` otherwise - public function init(string url, *ClientConfiguration config) returns Error? { + public function init(string url, *common:ClientConfig config) returns Error? { do { self.soapClient = check new (url, retrieveHttpClientConfig(config)); } on fail var err { - return error Error("Failed to initialize soap client", err); + return error Error(SOAP_CLIENT_ERROR, err); } } @@ -51,7 +48,17 @@ public isolated client class Client { # + return - If successful, returns the response. Else, returns an error remote function sendReceive(xml|mime:Entity[] body, string? action = (), map headers = {}) returns xml|mime:Entity[]|Error { + do { + if body is xml { + xml applySecurityPoliciesResult = check common:applySecurityPolicies(self.inboundSecurity, body); + xml response = check common:sendReceive(applySecurityPoliciesResult, self.soapClient, action, headers); return sendReceive(body, self.soapClient, action, headers); + return response; + } + return check common:sendReceive(body, self.soapClient, action, headers); + } on fail var e { + return error Error(e.message()); + } } # Fires and forgets requests. Sends the request without the possibility of any response from the @@ -66,6 +73,18 @@ public isolated client class Client { # + return - If successful, returns `nil`. Else, returns an error remote function sendOnly(xml|mime:Entity[] body, string? action = (), map headers = {}) returns Error? { - return sendOnly(body, self.soapClient, action, headers); + if body is xml { + do { + xml applySecurityPoliciesResult = check common:applySecurityPolicies(self.inboundSecurity, body); + return check common:sendOnly(applySecurityPoliciesResult, self.soapClient, action, headers); + } on fail var e { + return error Error(e.message()); + } + } + do { + return check common:sendOnly(body, self.soapClient, action, headers); + } on fail var e { + return error Error(e.message()); + } } } diff --git a/ballerina/modules/soap12/soap_utils.bal b/ballerina/modules/soap12/soap_utils.bal deleted file mode 100644 index a785089..0000000 --- a/ballerina/modules/soap12/soap_utils.bal +++ /dev/null @@ -1,103 +0,0 @@ -// Copyright (c) 2018, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. -// -// WSO2 Inc. licenses this file to you under the Apache License, -// Version 2.0 (the "License"); you may not use this file except -// in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -import ballerina/http; -import ballerina/mime; - -# Creates a SOAP Request as an `http:Request` -# -# + body - SOAP request body as an `XML` or `mime:Entity[]` to work with soap attachments -# + soapAction - SOAP action -# + headers - SOAP headers as a `map` -# + return - The SOAP Request sent as `http:Request` -function createHttpRequest(xml|mime:Entity[] body, - string? soapAction, map headers = {}) returns http:Request { - http:Request req = new; - if body is xml { - req.setXmlPayload(body); - } else { - req.setBodyParts(body); - } - if soapAction is string { - map stringMap = {}; - stringMap["action"] = "\"" + soapAction + "\""; - var mediaType = mime:getMediaType(mime:APPLICATION_SOAP_XML); - if mediaType is mime:MediaType { - mediaType.parameters = stringMap; - req.setHeader(mime:CONTENT_TYPE, mediaType.toString()); - } - } else { - req.setHeader(mime:CONTENT_TYPE, mime:APPLICATION_SOAP_XML); - } - foreach string key in headers.keys() { - req.addHeader(key, headers[key].toBalString()); - } - return req; -} - -# Creates the SOAP response from the HTTP Response. -# -# + response - The request to be sent -# + return - The SOAP response created from the `http:Response` or the `error` object when reading the payload -function createSoapResponse(http:Response response) returns xml|error { - xml payload = check response.getXmlPayload(); - xmlns "http://www.w3.org/2003/05/soap-envelope" as soap12; - - return payload/; -} - -string path = ""; - -function sendReceive(xml|mime:Entity[] body, http:Client httpClient, - string? soapAction = (), map headers = {}) returns xml|Error { - http:Request req = createHttpRequest(body, soapAction, headers); - http:Response response; - do { - response = check httpClient->post(path, req); - } on fail var err { - return error Error("Failed to receive soap response", err); - } - do { - return check createSoapResponse(response); - } on fail var err { - return error Error("Failed to create soap response", err); - } -} - -function sendOnly(xml|mime:Entity[] body, http:Client httpClient, - string? soapAction = (), map headers = {}) returns Error? { - http:Request req = createHttpRequest(body, soapAction, headers); - do { - http:Response _ = check httpClient->post(path, req); - } on fail var err { - return error Error("Failed to create soap response", err); - } -} - -function retrieveHttpClientConfig(ClientConfiguration config) returns http:ClientConfiguration { - return { - httpVersion: config.httpVersion, - http1Settings: config.http1Settings, - http2Settings: config.http2Settings, - timeout: config.timeout, - poolConfig: config?.poolConfig, - auth: config?.auth, - retryConfig: config?.retryConfig, - responseLimits: config.responseLimits, - secureSocket: config?.secureSocket, - circuitBreaker: config?.circuitBreaker - }; -} From 5ab5fa6febf8554963b79f7633125d00b26a0fde Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Tue, 3 Oct 2023 12:16:12 +0530 Subject: [PATCH 087/189] Apply changes to support transport binding security policy --- ballerina/modules/soap11/soap11.bal | 2 +- ballerina/modules/soap12/soap12.bal | 3 ++- ballerina/modules/wssec/records.bal | 5 +++++ 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/ballerina/modules/soap11/soap11.bal b/ballerina/modules/soap11/soap11.bal index 5a101f8..96fb943 100644 --- a/ballerina/modules/soap11/soap11.bal +++ b/ballerina/modules/soap11/soap11.bal @@ -32,7 +32,7 @@ public client class Client { # + return - `error` in case of errors or `()` otherwise public function init(string url, *common:ClientConfig config) returns Error? { do { - self.soapClient = check new (url, retrieveHttpClientConfig(config)); + check common:validateTransportBindingPolicy(config); self.soapClient = check new (url, common:retrieveHttpClientConfig(config)); self.inboundSecurity = config.inboundSecurity; self.outboundSecurity = config.outboundSecurity; diff --git a/ballerina/modules/soap12/soap12.bal b/ballerina/modules/soap12/soap12.bal index 1776b97..6497a0f 100644 --- a/ballerina/modules/soap12/soap12.bal +++ b/ballerina/modules/soap12/soap12.bal @@ -31,7 +31,8 @@ public client class Client { # + return - `error` in case of errors or `()` otherwise public function init(string url, *common:ClientConfig config) returns Error? { do { - self.soapClient = check new (url, retrieveHttpClientConfig(config)); + check common:validateTransportBindingPolicy(config); + self.soapClient = check new (url, common:retrieveHttpClientConfig(config)); } on fail var err { return error Error(SOAP_CLIENT_ERROR, err); } diff --git a/ballerina/modules/wssec/records.bal b/ballerina/modules/wssec/records.bal index 791ab98..a94a156 100644 --- a/ballerina/modules/wssec/records.bal +++ b/ballerina/modules/wssec/records.bal @@ -61,3 +61,8 @@ public type AsymmetricBindingConfig record {| EncryptionAlgorithm encryptionAlgorithm?; string x509Token?; |}; + +# Represents the record for Transport Binding policy. +# + protocol - Protocol of the endpoint +public type TransportBindingConfig "TransportBinding"; + From 0c6db3cec28b1614a7d406bdec5a1d529dd35a76 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Tue, 3 Oct 2023 12:18:35 +0530 Subject: [PATCH 088/189] Add inbound and outbound security configs for SOAP clients --- ballerina/modules/soap11/soap11.bal | 11 ++++++++++- ballerina/modules/soap12/soap12.bal | 13 ++++++++++++- ballerina/modules/wssec/records.bal | 20 ++++++++++++++++++++ 3 files changed, 42 insertions(+), 2 deletions(-) diff --git a/ballerina/modules/soap11/soap11.bal b/ballerina/modules/soap11/soap11.bal index 96fb943..51c6765 100644 --- a/ballerina/modules/soap11/soap11.bal +++ b/ballerina/modules/soap11/soap11.bal @@ -24,6 +24,8 @@ xmlns "http://schemas.xmlsoap.org/soap/envelope/" as soap; # Object for the basic SOAP client endpoint. public client class Client { private final http:Client soapClient; + private wssec:InboundSecurityConfig|wssec:InboundSecurityConfig[] inboundSecurity; + private wssec:OutboundSecurityConfig? outboundSecurity; # Gets invoked during object initialization. # @@ -57,7 +59,14 @@ public client class Client { xml applySecurityPoliciesResult = check common:applySecurityPolicies(self.inboundSecurity, body); xml response = check common:sendReceive(applySecurityPoliciesResult, self.soapClient, action, headers, false); - return sendReceive(body, self.soapClient, action, headers); + wssec:OutboundSecurityConfig? outboundSecurity = self.outboundSecurity; + do { + if outboundSecurity !is () { + return check common:applyOutboundConfig(outboundSecurity, response); + } + } on fail var e { + return error Error("Outbound security configurations do not match with the SOAP response. ", e.cause()); + } } return check common:sendReceive(body, self.soapClient, action, headers, false); } on fail var e { diff --git a/ballerina/modules/soap12/soap12.bal b/ballerina/modules/soap12/soap12.bal index 6497a0f..6f4275e 100644 --- a/ballerina/modules/soap12/soap12.bal +++ b/ballerina/modules/soap12/soap12.bal @@ -23,6 +23,8 @@ xmlns "http://www.w3.org/2003/05/soap-envelope" as soap; # Object for the basic SOAP client endpoint. public client class Client { private final http:Client soapClient; + private wssec:InboundSecurityConfig|wssec:InboundSecurityConfig[] inboundSecurity; + private wssec:OutboundSecurityConfig? outboundSecurity; # Gets invoked during object initialization. # @@ -33,6 +35,8 @@ public client class Client { do { check common:validateTransportBindingPolicy(config); self.soapClient = check new (url, common:retrieveHttpClientConfig(config)); + self.inboundSecurity = config.inboundSecurity; + self.outboundSecurity = config.outboundSecurity; } on fail var err { return error Error(SOAP_CLIENT_ERROR, err); } @@ -53,7 +57,14 @@ public client class Client { if body is xml { xml applySecurityPoliciesResult = check common:applySecurityPolicies(self.inboundSecurity, body); xml response = check common:sendReceive(applySecurityPoliciesResult, self.soapClient, action, headers); - return sendReceive(body, self.soapClient, action, headers); + wssec:OutboundSecurityConfig? outboundSecurity = self.outboundSecurity; + do { + if outboundSecurity !is () { + return check common:applyOutboundConfig(outboundSecurity, response); + } + } on fail var e { + return error Error("Outbound security configurations do not match with the SOAP response. ", e.cause()); + } return response; } return check common:sendReceive(body, self.soapClient, action, headers); diff --git a/ballerina/modules/wssec/records.bal b/ballerina/modules/wssec/records.bal index a94a156..8bea0e9 100644 --- a/ballerina/modules/wssec/records.bal +++ b/ballerina/modules/wssec/records.bal @@ -14,6 +14,24 @@ // specific language governing permissions and limitations // under the License. import ballerina/crypto; + +# Union type of all the inbound web service security configurations. +public type InboundSecurityConfig NoPolicy|UsernameTokenConfig|TimestampTokenConfig|SymmetricBindingConfig + |AsymmetricBindingConfig|TransportBindingConfig; + +# Represents the record for outbound security configurations to verify and decrypt SOAP envelopes. +# +# + verificationKey - The public key to verify the signature of the SOAP envelope +# + decryptionKey - The private key to decrypt the SOAP envelope +# + signatureAlgorithm - The algorithm to verify the SOAP envelope +# + decryptionAlgorithm - The algorithm to decrypt the SOAP body +public type OutboundSecurityConfig record {| + crypto:PublicKey verificationKey?; + crypto:PrivateKey|crypto:PublicKey decryptionKey?; + SignatureAlgorithm signatureAlgorithm?; + EncryptionAlgorithm decryptionAlgorithm?; +|}; + # Represents the record for Username Token policy. # # + username - The name of the user @@ -66,3 +84,5 @@ public type AsymmetricBindingConfig record {| # + protocol - Protocol of the endpoint public type TransportBindingConfig "TransportBinding"; +# Represents the record to send SOAP envelopes with no security policy. +public type NoPolicy "NoPolicy"; From b39e65b203fabedd6f8be6356c5750624cc744d6 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Tue, 3 Oct 2023 12:19:09 +0530 Subject: [PATCH 089/189] Add common APIs and configs into a separate module --- ballerina/modules/common/configs.bal | 29 ++++ ballerina/modules/common/constants.bal | 20 +++ ballerina/modules/common/error.bal | 20 +++ ballerina/modules/common/soap_utils.bal | 197 ++++++++++++++++++++++++ 4 files changed, 266 insertions(+) create mode 100644 ballerina/modules/common/configs.bal create mode 100644 ballerina/modules/common/constants.bal create mode 100644 ballerina/modules/common/error.bal create mode 100644 ballerina/modules/common/soap_utils.bal diff --git a/ballerina/modules/common/configs.bal b/ballerina/modules/common/configs.bal new file mode 100644 index 0000000..95edb18 --- /dev/null +++ b/ballerina/modules/common/configs.bal @@ -0,0 +1,29 @@ +// Copyright (c) 2023, WSO2 LLC. (http://www.wso2.org) All Rights Reserved. +// +// WSO2 LLC. licenses this file to you under the Apache License, +// Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +import soap.wssec; + +import ballerina/http; + +# SOAP client configurations. +# +# + httpConfig - HTTP Configuration +# + inboundSecurity - Web service security configurations for SOAP requests +# + outboundSecurity - Web service security configurations to decrypt and verify SOAP responses +public type ClientConfig record {| + http:ClientConfiguration httpConfig = {}; + wssec:InboundSecurityConfig|wssec:InboundSecurityConfig[] inboundSecurity = NO_POLICY; + wssec:OutboundSecurityConfig outboundSecurity = {}; +|}; diff --git a/ballerina/modules/common/constants.bal b/ballerina/modules/common/constants.bal new file mode 100644 index 0000000..92eb34c --- /dev/null +++ b/ballerina/modules/common/constants.bal @@ -0,0 +1,20 @@ +// Copyright (c) 2023, WSO2 LLC. (http://www.wso2.org) All Rights Reserved. +// +// WSO2 LLC. licenses this file to you under the Apache License, +// Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +import soap.wssec; + +const SOAP_ACTION = "SOAPAction"; +const ACTION = "action"; +const wssec:NoPolicy NO_POLICY = "NoPolicy"; diff --git a/ballerina/modules/common/error.bal b/ballerina/modules/common/error.bal new file mode 100644 index 0000000..87e420b --- /dev/null +++ b/ballerina/modules/common/error.bal @@ -0,0 +1,20 @@ +// Copyright (c) 2023, WSO2 LLC. (http://www.wso2.org) All Rights Reserved. +// +// WSO2 LLC. licenses this file to you under the Apache License, +// Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +# Defines the common error type for the module. +public type Error distinct error; + +const SOAP_RESPONSE_ERROR = "Failed to create SOAP response."; diff --git a/ballerina/modules/common/soap_utils.bal b/ballerina/modules/common/soap_utils.bal new file mode 100644 index 0000000..8478551 --- /dev/null +++ b/ballerina/modules/common/soap_utils.bal @@ -0,0 +1,197 @@ +// Copyright (c) 2023, WSO2 LLC. (http://www.wso2.org) All Rights Reserved. +// +// WSO2 LLC. licenses this file to you under the Apache License, +// Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +import soap.wssec; + +import ballerina/crypto; +import ballerina/http; +import ballerina/mime; +import ballerina/regex; + +public function validateTransportBindingPolicy(ClientConfig config) returns Error? { + if config.httpConfig.secureSocket is () { + wssec:InboundSecurityConfig|wssec:InboundSecurityConfig[] securityPolicy = config.inboundSecurity; + if securityPolicy is wssec:TransportBindingConfig { + return error Error("Invalid protocol detected: Please use the `https` protocol instead of `http`."); + } else if securityPolicy is wssec:InboundSecurityConfig[] { + foreach wssec:InboundSecurityConfig policy in securityPolicy { + if policy is wssec:TransportBindingConfig { + return error Error("Invalid protocol detected: Please use the `https` protocol instead of `http`."); + } + } + } + } +} + +public function retrieveHttpClientConfig(ClientConfig config) returns http:ClientConfiguration { + return { + httpVersion: config.httpConfig.httpVersion, + http1Settings: config.httpConfig.http1Settings, + http2Settings: config.httpConfig.http2Settings, + timeout: config.httpConfig.timeout, + poolConfig: config.httpConfig?.poolConfig, + auth: config.httpConfig?.auth, + retryConfig: config.httpConfig?.retryConfig, + responseLimits: config.httpConfig.responseLimits, + secureSocket: config.httpConfig?.secureSocket, + circuitBreaker: config.httpConfig?.circuitBreaker + }; +} + +public function applySecurityPolicies(wssec:InboundSecurityConfig|wssec:InboundSecurityConfig[] inboundSecurity, xml envelope) + returns xml|wssec:Error { + wssec:InboundSecurityConfig|wssec:InboundSecurityConfig[] securityPolicy = inboundSecurity; + xml securedEnvelope; + if securityPolicy is wssec:InboundSecurityConfig { + if securityPolicy is wssec:TimestampTokenConfig { + securedEnvelope = check wssec:applyTimestampToken(envelope, securityPolicy); + } else if securityPolicy is wssec:UsernameTokenConfig { + securedEnvelope = check wssec:applyUsernameToken(envelope, securityPolicy); + } else if securityPolicy is wssec:SymmetricBindingConfig { + securedEnvelope = check wssec:applySymmetricBinding(envelope, securityPolicy); + } else if securityPolicy is wssec:AsymmetricBindingConfig { + securedEnvelope = check wssec:applyAsymmetricBinding(envelope, securityPolicy); + } else { + securedEnvelope = envelope; + } + } else { + foreach wssec:InboundSecurityConfig policy in securityPolicy { + securedEnvelope = check applySecurityPolicies(policy, envelope); + } + } + return securedEnvelope; +} + +public function applyOutboundConfig(wssec:OutboundSecurityConfig outboundSecurity, xml envelope) returns xml|Error { + xmlns "http://schemas.xmlsoap.org/soap/envelope/" as soap; + xml soapEnvelope = envelope; + do { + if outboundSecurity.decryptionAlgorithm !is () { + crypto:PrivateKey|crypto:PublicKey? clientPrivateKey = outboundSecurity.decryptionKey; + if clientPrivateKey !is () { + byte[] encData = check wssec:getEncryptedData(soapEnvelope); + byte[] decryptDataResult = check wssec:decryptData(encData, wssec:RSA_ECB, clientPrivateKey); + string decryptedBody = "" + check string:fromBytes(decryptDataResult) + ""; + string decryptedEnv = regex:replace(soapEnvelope.toString(), string `.*`, decryptedBody); + soapEnvelope = check xml:fromString(decryptedEnv); + } + } + if outboundSecurity.signatureAlgorithm !is () { + crypto:PublicKey? serverPublicKey = outboundSecurity.verificationKey; + if serverPublicKey !is () { + byte[] signatureData = check wssec:getSignatureData(soapEnvelope); + boolean verify = check crypto:verifyRsaSha256Signature((soapEnvelope//*).toBalString().toBytes(), + signatureData, serverPublicKey); + if !verify { + return error Error("Signature verification of the SOAP envelope has been failed"); + } + } + } + return soapEnvelope; + } on fail var e { + return error Error("Outbound security configurations do not match with the SOAP response. ", e.cause()); + } +} + +string path = ""; + +public function sendReceive(xml|mime:Entity[] body, http:Client httpClient, string? soapAction = (), + map headers = {}, boolean soap12 = true) returns xml|Error { + http:Request req; + if soap12 { + req = createSoap12HttpRequest(body, soapAction, headers); + } else { + req = createSoap11HttpRequest(body, soapAction, headers); + } + http:Response response; + do { + response = check httpClient->post(path, req); + if soap12 { + return check createSoap12Response(response); + } + return check createSoap11Response(response); + } on fail var err { + return error Error(SOAP_RESPONSE_ERROR, err); + } +} + +public function sendOnly(xml|mime:Entity[] body, http:Client httpClient, string? soapAction = (), + map headers = {}, boolean soap12 = true) returns Error? { + http:Request req; + if soap12 { + req = createSoap12HttpRequest(body, soapAction, headers); + } else { + req = createSoap11HttpRequest(body, soapAction, headers); + } + do { + http:Response _ = check httpClient->post(path, req); + } on fail var err { + return error Error(SOAP_RESPONSE_ERROR, err); + } +} + +function createSoap11HttpRequest(xml|mime:Entity[] body, + string soapAction, map headers = {}) returns http:Request { + http:Request req = new; + if body is xml { + req.setXmlPayload(body); + } else { + req.setBodyParts(body); + } + req.setHeader(mime:CONTENT_TYPE, mime:TEXT_XML); + req.addHeader(SOAP_ACTION, soapAction); + foreach string key in headers.keys() { + req.addHeader(key, headers[key].toBalString()); + } + return req; +} + +function createSoap12HttpRequest(xml|mime:Entity[] body, string? soapAction, + map headers = {}) returns http:Request { + http:Request req = new; + if body is xml { + req.setXmlPayload(body); + } else { + req.setBodyParts(body); + } + if soapAction is string { + map stringMap = {}; + stringMap[ACTION] = "\"" + soapAction + "\""; + var mediaType = mime:getMediaType(mime:APPLICATION_SOAP_XML); + if mediaType is mime:MediaType { + mediaType.parameters = stringMap; + req.setHeader(mime:CONTENT_TYPE, mediaType.toString()); + } + } else { + req.setHeader(mime:CONTENT_TYPE, mime:APPLICATION_SOAP_XML); + } + foreach string key in headers.keys() { + req.addHeader(key, headers[key].toBalString()); + } + return req; +} + +function createSoap12Response(http:Response response) returns xml|error { + xml payload = check response.getXmlPayload(); + xmlns "http://www.w3.org/2003/05/soap-envelope" as soap12; + + return payload/; +} + +function createSoap11Response(http:Response response) returns xml|error { + xml payload = check response.getXmlPayload(); + xmlns "http://schemas.xmlsoap.org/soap/envelope/" as soap11; + return payload/; +} From 2fc579c7f059a96f5ea2434ed06081928aaeec96 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Tue, 3 Oct 2023 12:19:44 +0530 Subject: [PATCH 090/189] Add enumerations for signature, encryption and password types --- ballerina/modules/wssec/types.bal | 46 +++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 ballerina/modules/wssec/types.bal diff --git a/ballerina/modules/wssec/types.bal b/ballerina/modules/wssec/types.bal new file mode 100644 index 0000000..a582f6e --- /dev/null +++ b/ballerina/modules/wssec/types.bal @@ -0,0 +1,46 @@ +// Copyright (c) 2023, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +// +// WSO2 Inc. licenses this file to you under the Apache License, +// Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +public enum PasswordType { + TEXT, + DIGEST, + DERIVED_KEY_TEXT, + DERIVED_KEY_DIGEST +} + +public enum SignatureAlgorithm { + RSA_SHA1 = "http://www.w3.org/2000/09/xmldsig#rsa-sha1", + RSA_SHA256 = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256", + RSA_SHA384 = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha384", + RSA_SHA512 = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha512", + HMAC_SHA1 = "http://www.w3.org/2000/09/xmldsig#hmac-sha1", + HMAC_SHA256 = "http://www.w3.org/2001/04/xmldsig-more#hmac-sha256", + HMAC_SHA384 = "http://www.w3.org/2001/04/xmldsig-more#hmac-sha384", + HMAC_SHA512 = "http://www.w3.org/2001/04/xmldsig-more#hmac-sha512" +} + +public enum EncryptionAlgorithm { + RSA_ECB = "http://www.w3.org/2001/04/xmlenc#rsa-1_5", + AES_128 = "http://www.w3.org/2001/04/xmlenc#aes128-cbc", + AES_192 = "http://www.w3.org/2001/04/xmlenc#aes192-cbc", + AES_256 = "http://www.w3.org/2001/04/xmlenc#aes256-cbc", + AES_128_ECB = "http://www.w3.org/2009/xmlenc11#aes128-ecb", + AES_192_ECB = "http://www.w3.org/2009/xmlenc11#aes192-ecb", + AES_256_ECB = "http://www.w3.org/2009/xmlenc11#aes256-ecb", + AES_128_GCM = "http://www.w3.org/2009/xmlenc11#aes128-gcm", + AES_192_GCM = "http://www.w3.org/2009/xmlenc11#aes192-gcm", + AES_256_GCM = "http://www.w3.org/2009/xmlenc11#aes256-gcm" +} From ec5737ac33a41ff9d73f8621d42c64d442fb9e4a Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Tue, 3 Oct 2023 12:20:27 +0530 Subject: [PATCH 091/189] Modify the code to only export SOAP 1.1 and 1.2 modules --- build-config/resources/Ballerina.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build-config/resources/Ballerina.toml b/build-config/resources/Ballerina.toml index d073da3..5fdaee2 100644 --- a/build-config/resources/Ballerina.toml +++ b/build-config/resources/Ballerina.toml @@ -3,7 +3,7 @@ org = "ballerina" name = "soap" version = "@toml.version@" authors = ["Ballerina"] -export=["soap.soap11", "soap.soap11"] +export=["soap.soap11", "soap.soap12"] keywords = ["soap"] repository = "https://github.com/ballerina-platform/module-ballerina-soap" icon = "icon.png" From 865417f4ca5d5cc9774ec56aba3d0d6c932e1777 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Tue, 3 Oct 2023 12:20:54 +0530 Subject: [PATCH 092/189] Add cryptographic files for test purposes --- .../wssec/tests/resources/private_key.pem | Bin 0 -> 2373 bytes .../modules/wssec/tests/resources/wss40.p12 | Bin 0 -> 2557 bytes .../tests/resources/x509_certificate.crt | 21 ++++++++++++++++++ .../tests/resources/x509_certificate.p12 | Bin 0 -> 2590 bytes .../tests/resources/x509_certificate_2.crt | 19 ++++++++++++++++ .../tests/resources/x509_certificate_2.p12 | Bin 0 -> 2590 bytes 6 files changed, 40 insertions(+) create mode 100644 ballerina/modules/wssec/tests/resources/private_key.pem create mode 100644 ballerina/modules/wssec/tests/resources/wss40.p12 create mode 100644 ballerina/modules/wssec/tests/resources/x509_certificate.crt create mode 100644 ballerina/modules/wssec/tests/resources/x509_certificate.p12 create mode 100644 ballerina/modules/wssec/tests/resources/x509_certificate_2.crt create mode 100644 ballerina/modules/wssec/tests/resources/x509_certificate_2.p12 diff --git a/ballerina/modules/wssec/tests/resources/private_key.pem b/ballerina/modules/wssec/tests/resources/private_key.pem new file mode 100644 index 0000000000000000000000000000000000000000..3ce412384318ce361b8575bad6e27617de657683 GIT binary patch literal 2373 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 literal 0 HcmV?d00001 diff --git a/ballerina/modules/wssec/tests/resources/wss40.p12 b/ballerina/modules/wssec/tests/resources/wss40.p12 new file mode 100644 index 0000000000000000000000000000000000000000..40b3924ff80dad29f84177477bb1e3e51f62dd06 GIT binary patch literal 2557 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 C(6@8| literal 0 HcmV?d00001 diff --git a/ballerina/modules/wssec/tests/resources/x509_certificate.crt b/ballerina/modules/wssec/tests/resources/x509_certificate.crt new file mode 100644 index 0000000..251c423 --- /dev/null +++ b/ballerina/modules/wssec/tests/resources/x509_certificate.crt @@ -0,0 +1,21 @@ +-----BEGIN CERTIFICATE----- +MIIDazCCAlOgAwIBAgIUHYnC3ALHIdLNO+JlFu/8usNrq2owDQYJKoZIhvcNAQEL +BQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM +GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0yMzA4MjUwNzE5NDVaFw0yNDA4 +MjQwNzE5NDVaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEw +HwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwggEiMA0GCSqGSIb3DQEB +AQUAA4IBDwAwggEKAoIBAQDdfueteXm2iSP+Pjr0+tK4G5pCxshqq0Z/ldDRpMzx +vCAOFWIDS/ewcigUx5gMM7KHZfSzVXjlxahF5gqDbriunTSymFPfAQHimM13q1XZ +uBCdHh1ayKmXuP4H/T1zp35rfElyGlfocWNx/Lef4y5ZFJN0BMScVdtue4+vCtst +5NLOBaFBoZU3DGk7muu6+7+ml8P4WqSW7CR0usTvrmPssDHUqXCA7vARlGoGgTHy +trp7e7epNf5AZD3QjSWpLEIb6DuY9LyQYeC2Yry6GGN129lNJjh4HsXG6ldu0QQU +rCkma6oP9JSCHI0Dm0i0lDVTFYLjJ60tap7r5dXEKBXRAgMBAAGjUzBRMB0GA1Ud +DgQWBBTEWR0+4AmZuo10dDXp0D9bVeDGlDAfBgNVHSMEGDAWgBTEWR0+4AmZuo10 +dDXp0D9bVeDGlDAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAi +NlCjK/OQaKPanfyacR+v8k3RU4qs7CJJ78el8iN7ZWAQn9Z3o5VIwnHWCNYIBZr9 +CWSzV72EO7j9qXSLkbQL594a6+lDSxF7vwsEx8N1ktxz4Dkg0GPyrViBDTlcloOG +g5/ZNKsP++QczspdnJuyOTCL3DLd/P1d3WzfJF+NefvtDhmcpZxZL1YPKpeAobqf +nRLQVeWhZbNn/XbiWnrwx4LfN+r8aQh5kiO4xl31lPzg9cflPGhTHqG3Undeis9k +upnsjgsfBNas54lgYpOadP0f8Ooc0nJvT7ry0LbUgbkk7dGkWm9Qh2eu2e5v7Fw8 +0qWPT/H83ANtk/4Y5XCA +-----END CERTIFICATE----- diff --git a/ballerina/modules/wssec/tests/resources/x509_certificate.p12 b/ballerina/modules/wssec/tests/resources/x509_certificate.p12 new file mode 100644 index 0000000000000000000000000000000000000000..2b3eddbcd03e964a67e41d160b1fc861417d9af5 GIT binary patch literal 2590 zcmai$c{CJ?7st(*v5b*@8q3JDFO9|$BeEpfN169RvX_v37oo|PEko9^3=fGBjck#z z6dHRHS@Ij($WmEHmi)Z)`>VH+`|A_A8HEG!{bW-+yI{=i`uLjJCGC|4xZlNd<5SxXH zfGDCs1q}qUF`=L=Z2#K^WCt^$5G?GDaYlgK%pia~h&v{%8n>P!<5-+4tLS;-98)xo zIgM4>%n3*_(0@qNJWU{(CAlOhmG;WD@kfO=tIxYKhSGWz9PnB`4T`s1%ALbf#Rnrf zJr9*8E2p!I6vf5dF(Xk!hx&~@6J2q6)*k{%Ow7>_W$&~~KHef*f&*!m`5H@-qPqx_ zLDJ}vsXDkNirDPwol(d4^5 zHN$x5S+_%ker5;EnYn#q_iF){DNYMUN^r@)zq@^LHX}5rGr`V_@}5}ic!c!4ZdG{x zirUfj0^{O0*L394-L?|eEC;gSH4U_9I4@^sgExdHHsfA<*28EONBAC4=R-zUw+G^f z-RPTW%d#Uw^Hvw?Gu6JopxRmJ2lOB4CS;K zf1t2f4s|Ao1hVzzh2~H5za4jUNbWf<>Xz7lON#8-v-;)%U3THRiOEu2BrU*EtlHWi zJFoj_EqK&7_8Yh$%ia>A^%7;z^#(TU(xeW3AGO;TE4r^9JnBzy3jXdeeuRkB@Q7Pv z?&Q^od*jD9bC1+rnz;b5%`H~D_JUR~|Az`|j?wy`SU7@XJ@Nrfy=6aiqpNql5r0@} ziA0M8b+j}oi%%nw_#km}SsV_+Hl%hTJN@W`1eEl!9s1uUn1Mx15BP^~HDk59fB?YqyEdr_Q=i z!Tqq2+a=v;f-k_&H0-SHWfrc{gF3Y9`if-dIuG8-s^7@l{^Q}?rP&ydQ}kly2@Cn_ z-ci|$1Sc6iz4A1kj6n>v?qNXPHSe#%*4JiDa}pcUqaHHiqsxWm&_KvE*QC9O{k~)bkaliJf7z8s^ zUkz$$5v`EqrB91rCy%gJ@RXRP;8+y(U6YMoH(DsAXIM-%};6Wc7-xE z4HvH8a(g#Qftiol7$r9#UU6WP;u(s#tLz>q9JuJ$eg6Xta2f~)PCk(nPBMmt9dh6}Tz)!?u zq}NfXZ+6XDZuoMev4ccJ!^}EC+K;cT)u&v8(-bluForr~=2UKe5a4%A5X|mr+QvA} z3Pa^OpA)#{mPUtN1aK7uRA%jqcg$J|*`|_it78UH;$e+3QP{#ARtl6$^Lw|Lrk?KU zTVLi)RVDIK36M}C{d7dq{cCEA#sCEk^wdJrtp5yVN8F`v|5SfwFMd0jb5K75d&T*W zNZqHFB8mIeJqWIIOK-;o0}pI>!!N@B_H}4Ix;K#}YBZtqoXaCaX~TIulFiT5NHaNQeden z;oFMXtfP1(dx~~*(EKpx=oA;+K2g@h;`1hGva>c6PIx7Aw*FB&956Wq=%?XR4yz2P zwy{W!>@x)t>fSoZb$kc^#X5J*YlXh{lN4i=l1 zx_O&m$Uuk^Y53Dk_0bN?LXZxDtH=n1ZngT@{djRP8Q3K8aq4bHMT)zN`j%9y#bzTbkqA?aT(5H<1fbINCk*+A)h4(H5|6~g*%0||LFcKObv;=z?8 zQiN4X7#)6P^J}H1HWSIR_C3#0^r_<9v3`3`pK>=~UE7viy?sF5Odk{~&KIdXE9Hu; zRAX#nd5Smgyc}DwExi&O@LDx(r`)WMOIYOV=aLG-YrVix8?(JCwBBjSqE~{I!{qt) zj!{b8?oLn^56th@cQ>KaF*p8`(z;GvTlCscF>Fzt{FY1K6mceY_3l&F;?O=9xZJgz z)YJZI`KX*xqVAK7Yz=bIftK%++B4+Dc(yjT>Q)} zBK=eIsOl(|EM6KRI_EEDpuI^p#oqL_2+>^*%s^vU(#CP#a#;6a6$z(@5%OMLWx?qN z4$LMY(1U(8&eE=cuoC)~+lm`8qJ~AA+(=e*M21W~lZ`+W`kFXzfvw#8CW3|f3NG7W zVY+3mfllc+pC-e;hL|b;?Kc;p;m!I}l6NOJ>}T-4UoBbFLaJG+iu~FDmgd<;G2F;* zYCH2iOdY3CA{WFvU1i4Bpw9_a#flbIZgZ+VAypS7hkif6Coa}mKJBaNNw3vu>}r}c z@;!b!h$kHE$A#ROo%yju+Z#>7n7&(1DW0k=nJ#L4Zi~&C$U-LaKkX$<^D0KyxX|VH zqNiYYpWK9;{b}CW+)N$Qva3tKC=z7%RxeY-<5gB5HT*)a$%AR8uH5oa&&b`2)36w8 z+qJGQS1%_ko3;Y%G>~qC2^M3s7nO8Tg1-RE&aVU&g)oIM1)PK`6AC5q+Y(TMf%sX~ zf4~eyRav689?+wjSY+p1t)@|WC?yo039s!`P5TD#Rp31YrR zD{2*$D&^6ZR`Ghy`=0jWbMCq4p8NmbbMB}6I~R$g=cWQuBXM+-U^+wsI^mEBNDC~% z(e;CHbiL*P>N6@J;Jh6Daezph-wh2D(hw>3r)5O)f*=~NU612t zH;kyLAOIvI81lbuRCF`|Bp;X#lYj=^q6PsGAgJj}kBRl5u2*!ltX8-TOP^RAb%ykQ z+$dH>#rd>gV{?}2FWbG5BgMrSI0N7Xk(PiCX?Qe)}o+)HdsuB}dA|$ZI!8Mb?vy+DeC=c<; zg-^nNFP1DAsTsATEonwv??P@KY6!8!4k&u#Rpgo{;S}A9Imh`Mik=Tx`$|XCVuCOiBA; z_u0@F!l|DqOm+bk+!le6J52pHqv1b#7XBGROb?c4AfLL1H^yNyNja|JF`j^#Cjqa3 zg;8rhMCw>kGP{YAn6QBMR%n11@hJ-llSS~L5!|w7o}soG6PLUrAsZPgM1p=qZbZ>V zjQw!DI1`go@({_$UL)@DoZGCyQ5;pZ*|%fx^-RRHCYwx^a-iU4MM2;K-_fVUyBXc+ z%{aI(vpWa~On)@pw1tRz=@OO^Ab;=pupnf`HXM`0C*CAkbMF!M*-eZPS&TwB7Ms_d zi=h@F;wP&m0A_sb^Wnd;ol-|7V&50>lf+xeM<*+Eu3n{YdA;L0P_(T&1piLHJ-_ag z)+wl+YJ7l8-GiZb11UdtN{--@1j|i5;auH8q|FX=3PqmA%r~v`iF6FAG24BhnKE$`{~56%Vb5FNKRg~o*~dXy>k zESg&qJhxZXQv`ua-!^5@D2VC^IuMDYDgJ%m{{Vv~1B9bVJ(mgRi3cT@g)V;r3 z4H>{;4-rm<9LovQLopqKsW+SA(8`w-w_+FgTX~+T5smNcKHS=(&U#Ko`U+bLM_fJR z6<+?pt{X2j(I#u5dZ&sIHfgn+n;Gu+e)4XUR1wx{m7MXEf5+1g?9(i=Dw%MlTdz`X z$k4U8AT~eetwr>3sdcdj$yvJT!`tO`yDlv+%#W7ED%(TljGFCpCF{`vNB-ONJ~ zuf}WBIKAt@Vt*gbAVKRQlUIBBk=s_sVzUT$tE_^C z5@)tR13oK;x%K&nnRs z_FLEs`Wy0I0og;%b~?BG+g0pFA5!mG?TAh4VspayHdbXlXUXc>Cj| z#`>d%teM6H@^pjTjnNb}#l93Nk}4O1q@a1mQnY6LZBM`M$L&{*CZ6emVGSIW%Z_7? z>Q24!dN=sDbQ)pDju`o4CT}f>FKloN{?~4yvW?$f=F0cX3oe6Gq43KCJZXqZ-$N;1+gCpT~X7`ed$`r$sT9To?Ym*a$3LkqN)tM37JlO1y(ci4BOH$MuMLO-Poun8#%i0N^!dc%9D=mMD#Y()RXjkVHj9}7>Q!^`O zWiP&7U?m=G*Qak|m1omt4{biR9L+n3nzwPF{V#H3n^QS}ag{OE&3a+E-bqrAeSv9r z++DmB<)ZB;J9;kMlbIKBz^Q>Nl3R-c4$SW4GLe-`mHnqEqkV(*0_EA}f&6X#bagDJ zNX}}8D$i?p-`o*~^-D;n`ZmsQ5R)v3RK4rtxUUD4LfHwCsW6ZH4_Gt5 z5Qi}qcHkick1J*B18hA@gu_9+4v23WUE-JT-+|C|0){m9F@daP{oW zp3zI%?-=&&6CU+>TczqLy(?$Ycf0ygXtiI3F9XWch`Qg&_Y56>L7O#pf=wz-Vz_47 zl0;INc6{J3QFgohEQgV6Z`k}SyJR2xujQ-6>2VuWu4*pmx9haG zSG>y;+$JP)+z1s9CGZgRhoG!@8BHYDZ@|*A$uPp`0U>~(^N<4|kwSkgb{P&3n|Z_> z^>d5a;&ATqNKx!6P2hm*Go%($2FdjMv!Vjh06=g97Pm6f@Hwzv^&A`Xml+BfU?Lv+ cM!Qxh!ejiWkbNx(a(ZmHMrDwK_=m#(1;jX)GXMYp literal 0 HcmV?d00001 From ec4c306030dbb03116f937f2e3f561f04bbec798 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Tue, 3 Oct 2023 12:21:31 +0530 Subject: [PATCH 093/189] Add test cases for the wssec module --- .../modules/wssec/tests/ws_security_tests.bal | 906 ++++++++++++++++++ 1 file changed, 906 insertions(+) create mode 100644 ballerina/modules/wssec/tests/ws_security_tests.bal diff --git a/ballerina/modules/wssec/tests/ws_security_tests.bal b/ballerina/modules/wssec/tests/ws_security_tests.bal new file mode 100644 index 0000000..960ceac --- /dev/null +++ b/ballerina/modules/wssec/tests/ws_security_tests.bal @@ -0,0 +1,906 @@ +import ballerina/crypto; +// Copyright (c) 2023, WSO2 LLC. (http://www.wso2.org) All Rights Reserved. +// +// WSO2 LLC. licenses this file to you under the Apache License, +// Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +import ballerina/test; +import ballerina/regex; + +@test:Config { + groups: ["timestamp_token"] +} +function testTimestampToken() returns error? { + xml envelope = + xml ` + + + John Doe + 30 +

+ New York + USA +
+ + +
`; + + xmlns "http://schemas.xmlsoap.org/soap/envelope/" as soap; + xml securedEnvelope = check applyTimestampToken(envelope = envelope, timeToLive = 600); + string envelopeString = (securedEnvelope//*).toString(); + assertTimestampToken(envelopeString); +} + +@test:Config { + groups: ["timestamp_token", "error"] +} +function testTimestampTokenWithIncorrectTimeError() returns error? { + xml envelope = + xml ` + + + John Doe + 30 +
+ New York + USA +
+
+
+
`; + xmlns "http://schemas.xmlsoap.org/soap/envelope/" as soap; + TimestampTokenConfig tsRecord = { + timeToLive: -1 + }; + xml|Error generateEnvelope = applyTimestampToken(envelope, tsRecord); + test:assertTrue(generateEnvelope is Error); + if generateEnvelope is Error { + test:assertEquals(generateEnvelope.message(), "Invalid value for `timeToLive`"); + } +} + +@test:Config { + groups: ["username_token", "password_text"] +} +function testUsernameTokenWithPlaintextPassword() returns error? { + xml envelope = + xml ` + + + John Doe + 30 +
+ New York + USA +
+
+
+
`; + xmlns "http://schemas.xmlsoap.org/soap/envelope/" as soap; + + UsernameTokenConfig utRecord = { + username: USERNAME, + password: PASSWORD, + passwordType: TEXT + }; + xml securedEnvelope = check applyUsernameToken(envelope, utRecord); + string envelopeString = securedEnvelope.toString(); + assertUsernameToken(envelopeString, TEXT); +} + +@test:Config { + groups: ["username_token", "password_text", "derived_key"] +} +function testUsernameTokenWithPlaintextPasswordWithDerivedKey() returns error? { + xml envelope = + xml ` + + + John Doe + 30 +
+ New York + USA +
+
+
+
`; + xmlns "http://schemas.xmlsoap.org/soap/envelope/" as soap; + UsernameTokenConfig utRecord = { + username: USERNAME, + password: PASSWORD, + passwordType: DERIVED_KEY_TEXT + }; + xml securedEnvelope = check applyUsernameToken(envelope, utRecord); + string envelopeString = securedEnvelope.toString(); + + assertUsernameToken(envelopeString, DERIVED_KEY_TEXT); +} + +@test:Config { + groups: ["username_token", "password_digest"] +} +function testUsernameTokenWithHashedPasword() returns error? { + xml envelope = + xml ` + + + John Doe + 30 +
+ New York + USA +
+
+
+
`; + xmlns "http://schemas.xmlsoap.org/soap/envelope/" as soap; + UsernameTokenConfig utRecord = { + username: USERNAME, + password: PASSWORD, + passwordType: DIGEST + }; + xml securedEnvelope = check applyUsernameToken(envelope, utRecord); + string envelopeString = securedEnvelope.toString(); + + assertUsernameToken(envelopeString, DIGEST); +} + +@test:Config { + groups: ["username_token", "password_digest", "derived_key"] +} +function testUsernameTokenWithHashedPaswordWithDerivedKey() returns error? { + xml envelope = + xml ` + + + John Doe + 30 +
+ New York + USA +
+
+
+
`; + xmlns "http://schemas.xmlsoap.org/soap/envelope/" as soap; + UsernameTokenConfig utRecord = { + username: USERNAME, + password: PASSWORD, + passwordType: DERIVED_KEY_DIGEST + }; + xml securedEnvelope = check applyUsernameToken(envelope, utRecord); + string envelopeString = securedEnvelope.toString(); + + assertUsernameToken(envelopeString, DERIVED_KEY_DIGEST); +} + +@test:Config { + groups: ["username_token", "signature", "symmetric_binding"] +} +function testSymmetricBindingPolicyWithSignatureOnly() returns error? { + xml envelope = + xml ` + + + John Doe + 30 +
+ New York + USA +
+
+
+
`; + xmlns "http://schemas.xmlsoap.org/soap/envelope/" as soap; + + crypto:KeyStore serverKeyStore = { + path: X509_KEY_STORE_PATH, + password: KEY_PASSWORD + }; + crypto:PublicKey serverPublicKey = check crypto:decodeRsaPublicKeyFromTrustStore(serverKeyStore, KEY_ALIAS); + + crypto:KeyStore keyStore = { + path: KEY_STORE_PATH, + password: KEY_PASSWORD + }; + crypto:PrivateKey symmetricKey = check crypto:decodeRsaPrivateKeyFromKeyStore(keyStore, KEY_ALIAS, KEY_PASSWORD); + crypto:PublicKey publicKey = check crypto:decodeRsaPublicKeyFromTrustStore(keyStore, KEY_ALIAS); + + SymmetricBindingConfig utSymmetricBinding = { + signatureAlgorithm: RSA_SHA256, + symmetricKey: symmetricKey, + servicePublicKey: serverPublicKey + }; + + xml securedEnvelope = check applySymmetricBinding(envelope, utSymmetricBinding); + string envelopeString = securedEnvelope.toString(); + byte[] signedData = check getSignatureData(securedEnvelope); + + boolean validity = check crypto:verifyRsaSha256Signature((envelope//*).toString().toBytes(), signedData, publicKey); + test:assertTrue(validity); + + assertEncryptedSymmetricKey(envelopeString); + assertSignatureWithoutX509(envelopeString); +} + +@test:Config { + groups: ["username_token", "signature", "symmetric_binding"] +} +function testSymmetricBindingPolicyEncryptionOnly() returns error? { + xml envelope = + xml ` + + `; + xmlns "http://schemas.xmlsoap.org/soap/envelope/" as soap; + + crypto:KeyStore serverKeyStore = { + path: X509_KEY_STORE_PATH, + password: KEY_PASSWORD + }; + crypto:PublicKey serverPublicKey = check crypto:decodeRsaPublicKeyFromTrustStore(serverKeyStore, KEY_ALIAS); + + crypto:KeyStore keyStore = { + path: KEY_STORE_PATH, + password: KEY_PASSWORD + }; + crypto:PrivateKey symmetricKey = check crypto:decodeRsaPrivateKeyFromKeyStore(keyStore, KEY_ALIAS, KEY_PASSWORD); + crypto:PublicKey publicKey = check crypto:decodeRsaPublicKeyFromTrustStore(keyStore, KEY_ALIAS); + + SymmetricBindingConfig utSymmetricBinding = { + encryptionAlgorithm: RSA_ECB, + symmetricKey: symmetricKey, + servicePublicKey: serverPublicKey + }; + + xml securedEnvelope = check applySymmetricBinding(envelope, utSymmetricBinding); + string envelopeString = securedEnvelope.toString(); + + byte[] encData = check getEncryptedData(securedEnvelope); + byte[] decryptDataResult = check decryptData(encData, RSA_ECB, publicKey); + test:assertEquals((envelope//*).toString(), check string:fromBytes(decryptDataResult)); + + assertEncryptedSymmetricKey(envelopeString); + assertEncryptedPart(envelopeString); +} + +@test:Config { + groups: ["username_token", "signature", "symmetric_binding"] +} +function testSymmetricBindingWithSignatureAndEncryption() returns error? { + xml envelope = + xml ` + + `; + xmlns "http://schemas.xmlsoap.org/soap/envelope/" as soap; + + crypto:KeyStore serverKeyStore = { + path: X509_KEY_STORE_PATH, + password: KEY_PASSWORD + }; + crypto:PublicKey serverPublicKey = check crypto:decodeRsaPublicKeyFromTrustStore(serverKeyStore, KEY_ALIAS); + + crypto:KeyStore keyStore = { + path: KEY_STORE_PATH, + password: KEY_PASSWORD + }; + crypto:PrivateKey symmetricKey = check crypto:decodeRsaPrivateKeyFromKeyStore(keyStore, KEY_ALIAS, KEY_PASSWORD); + crypto:PublicKey publicKey = check crypto:decodeRsaPublicKeyFromTrustStore(keyStore, KEY_ALIAS); + + SymmetricBindingConfig utSymmetricBinding = { + signatureAlgorithm: RSA_SHA256, + encryptionAlgorithm: RSA_ECB, + symmetricKey: symmetricKey, + servicePublicKey: serverPublicKey + }; + xml securedEnvelope = check applySymmetricBinding(envelope, utSymmetricBinding); + string envelopeString = securedEnvelope.toString(); + + byte[] signedData = check getSignatureData(securedEnvelope); + + boolean validity = check crypto:verifyRsaSha256Signature((envelope//*).toString().toBytes(), signedData, publicKey); + test:assertTrue(validity); + + byte[] encData = check getEncryptedData(securedEnvelope); + byte[] decryptDataResult = check decryptData(encData, RSA_ECB, publicKey); + test:assertEquals((envelope//*).toString(), check string:fromBytes(decryptDataResult)); + + assertEncryptedSymmetricKey(envelopeString); + assertSignatureWithoutX509(envelopeString); + assertEncryptedPart(envelopeString); +} + +@test:Config { + groups: ["username_token", "signature", "symmetric_binding"] +} +function testSymmetricBindingPolicyWithX509SignatureAndEncryption() returns error? { + xml envelope = + xml ` + + `; + xmlns "http://schemas.xmlsoap.org/soap/envelope/" as soap; + + crypto:KeyStore serverKeyStore = { + path: X509_KEY_STORE_PATH, + password: KEY_PASSWORD + }; + crypto:PublicKey serverPublicKey = check crypto:decodeRsaPublicKeyFromTrustStore(serverKeyStore, KEY_ALIAS); + + crypto:KeyStore keyStore = { + path: KEY_STORE_PATH, + password: KEY_PASSWORD + }; + crypto:PrivateKey symmetricKey = check crypto:decodeRsaPrivateKeyFromKeyStore(keyStore, KEY_ALIAS, KEY_PASSWORD); + crypto:PublicKey publicKey = check crypto:decodeRsaPublicKeyFromTrustStore(keyStore, KEY_ALIAS); + + SymmetricBindingConfig utSymmetricBinding = { + signatureAlgorithm: RSA_SHA256, + encryptionAlgorithm: RSA_ECB, + symmetricKey: symmetricKey, + servicePublicKey: serverPublicKey, + x509Token: X509_PUBLIC_CERT_PATH_2 + }; + + xml securedEnvelope = check applySymmetricBinding(envelope, utSymmetricBinding); + string envelopeString = securedEnvelope.toString(); + + byte[] signedData = check getSignatureData(securedEnvelope); + + boolean validity = check crypto:verifyRsaSha256Signature((envelope//*).toString().toBytes(), signedData, publicKey); + test:assertTrue(validity); + + byte[] encData = check getEncryptedData(securedEnvelope); + byte[] decryptDataResult = check decryptData(encData, RSA_ECB, publicKey); + test:assertEquals((envelope//*).toString(), check string:fromBytes(decryptDataResult)); + + assertEncryptedSymmetricKey(envelopeString); + assertSignatureWithX509(envelopeString); + assertEncryptedPart(envelopeString); +} + +@test:Config { + groups: ["username_token", "signature", "symmetric_binding"] +} +function testUsernameTokenWithSymmetricBinding() returns error? { + xml envelope = + xml ` + + `; + xmlns "http://schemas.xmlsoap.org/soap/envelope/" as soap; + + UsernameTokenConfig utRecord = { + username: USERNAME, + password: PASSWORD, + passwordType: DIGEST + }; + + envelope = check applyUsernameToken(envelope, utRecord); + + crypto:KeyStore serverKeyStore = { + path: X509_KEY_STORE_PATH, + password: KEY_PASSWORD + }; + crypto:PublicKey serverPublicKey = check crypto:decodeRsaPublicKeyFromTrustStore(serverKeyStore, KEY_ALIAS); + + crypto:KeyStore keyStore = { + path: KEY_STORE_PATH, + password: KEY_PASSWORD + }; + crypto:PrivateKey symmetricKey = check crypto:decodeRsaPrivateKeyFromKeyStore(keyStore, KEY_ALIAS, KEY_PASSWORD); + crypto:PublicKey publicKey = check crypto:decodeRsaPublicKeyFromTrustStore(keyStore, KEY_ALIAS); + + SymmetricBindingConfig utSymmetricBinding = { + signatureAlgorithm: RSA_SHA256, + encryptionAlgorithm: RSA_ECB, + symmetricKey: symmetricKey, + servicePublicKey: serverPublicKey + }; + xml securedEnvelope = check applySymmetricBinding(envelope, utSymmetricBinding); + string envelopeString = securedEnvelope.toString(); + + byte[] signedData = check getSignatureData(securedEnvelope); + + boolean validity = check crypto:verifyRsaSha256Signature((envelope//*).toString().toBytes(), signedData, publicKey); + test:assertTrue(validity); + + byte[] encData = check getEncryptedData(securedEnvelope); + byte[] decryptDataResult = check decryptData(encData, RSA_ECB, publicKey); + test:assertEquals((envelope//*).toString(), check string:fromBytes(decryptDataResult)); + + assertEncryptedSymmetricKey(envelopeString); + assertUsernameToken(envelopeString, DIGEST); + assertSignatureWithoutX509(envelopeString); + assertEncryptedPart(envelopeString); +} + +@test:Config { + groups: ["username_token", "signature", "symmetric_binding"] +} +function testUsernameTokenTimestampWithSymmetricBindingAndX509Token() returns error? { + xml envelope = + xml ` + + `; + xmlns "http://schemas.xmlsoap.org/soap/envelope/" as soap; + + UsernameTokenConfig utRecord = { + username: USERNAME, + password: PASSWORD, + passwordType: DIGEST + }; + + envelope = check applyUsernameToken(envelope, utRecord); + envelope = check applyTimestampToken(envelope = envelope, timeToLive = 600); + + crypto:KeyStore serverKeyStore = { + path: X509_KEY_STORE_PATH, + password: KEY_PASSWORD + }; + crypto:PublicKey serverPublicKey = check crypto:decodeRsaPublicKeyFromTrustStore(serverKeyStore, KEY_ALIAS); + + crypto:KeyStore keyStore = { + path: KEY_STORE_PATH, + password: KEY_PASSWORD + }; + crypto:PrivateKey symmetricKey = check crypto:decodeRsaPrivateKeyFromKeyStore(keyStore, KEY_ALIAS, KEY_PASSWORD); + crypto:PublicKey publicKey = check crypto:decodeRsaPublicKeyFromTrustStore(keyStore, KEY_ALIAS); + + SymmetricBindingConfig utSymmetricBinding = { + signatureAlgorithm: RSA_SHA256, + encryptionAlgorithm: RSA_ECB, + symmetricKey: symmetricKey, + servicePublicKey: serverPublicKey, + x509Token: X509_PUBLIC_CERT_PATH_2 + }; + + xml securedEnvelope = check applySymmetricBinding(envelope, utSymmetricBinding); + string envelopeString = securedEnvelope.toString(); + byte[] signedData = check getSignatureData(securedEnvelope); + + boolean validity = check crypto:verifyRsaSha256Signature((envelope//*).toString().toBytes(), signedData, publicKey); + test:assertTrue(validity); + + byte[] encData = check getEncryptedData(securedEnvelope); + byte[] decryptDataResult = check decryptData(encData, RSA_ECB, publicKey); + test:assertEquals((envelope//*).toString(), check string:fromBytes(decryptDataResult)); + + assertEncryptedSymmetricKey(envelopeString); + assertUsernameToken(envelopeString, DIGEST); + assertTimestampToken(envelopeString); + assertSignatureWithoutX509(envelopeString); + assertEncryptedPart(envelopeString); +} + +@test:Config { + groups: ["username_token", "signature", "symmetric_binding", "outbound_config"] +} +function testSymmetricBindingWithOutboundConfig() returns error? { + xml envelope = + xml ` + + `; + xmlns "http://schemas.xmlsoap.org/soap/envelope/" as soap; + + crypto:KeyStore serverKeyStore = { + path: X509_KEY_STORE_PATH, + password: KEY_PASSWORD + }; + crypto:PublicKey serverPublicKey = check crypto:decodeRsaPublicKeyFromTrustStore(serverKeyStore, KEY_ALIAS); + + crypto:KeyStore keyStore = { + path: KEY_STORE_PATH, + password: KEY_PASSWORD + }; + crypto:PrivateKey symmetricKey = check crypto:decodeRsaPrivateKeyFromKeyStore(keyStore, KEY_ALIAS, KEY_PASSWORD); + crypto:PublicKey publicKey = check crypto:decodeRsaPublicKeyFromTrustStore(keyStore, KEY_ALIAS); + + SymmetricBindingConfig utSymmetricBinding = { + signatureAlgorithm: RSA_SHA256, + encryptionAlgorithm: RSA_ECB, + symmetricKey: symmetricKey, + servicePublicKey: serverPublicKey + }; + + xml securedEnvelope = check applySymmetricBinding(envelope, utSymmetricBinding); + string envelopeString = securedEnvelope.toString(); + + OutboundSecurityConfig outboundConfig = { + verificationKey: publicKey, + signatureAlgorithm: RSA_SHA256, + decryptionAlgorithm: RSA_ECB, + decryptionKey: publicKey + }; + + crypto:PrivateKey|crypto:PublicKey? privateKey = outboundConfig.decryptionKey; + if privateKey !is () { + byte[] encData = check getEncryptedData(securedEnvelope); + byte[] decryptDataResult = check decryptData(encData, RSA_ECB, privateKey); + string decryptedBody = "" + check string:fromBytes(decryptDataResult) + ""; + envelopeString = regex:replace(envelopeString, string`.*`, decryptedBody); + securedEnvelope = check xml:fromString(envelopeString); + } + byte[] signedData = check getSignatureData(securedEnvelope); + + boolean validity = check crypto:verifyRsaSha256Signature((envelope//*).toString().toBytes(), signedData, publicKey); + test:assertTrue(validity); +} + +@test:Config { + groups: ["username_token", "signature", "asymmetric_binding"] +} +function testAsymmetricBindingWithSignature() returns error? { + xml envelope = + xml ` + + `; + xmlns "http://schemas.xmlsoap.org/soap/envelope/" as soap; + + crypto:KeyStore serverKeyStore = { + path: X509_KEY_STORE_PATH, + password: KEY_PASSWORD + }; + crypto:PublicKey serverPublicKey = check crypto:decodeRsaPublicKeyFromTrustStore(serverKeyStore, KEY_ALIAS); + + crypto:KeyStore clientKeyStore = { + path: X509_KEY_STORE_PATH_2, + password: KEY_PASSWORD + }; + crypto:PrivateKey clientPrivateKey = check crypto:decodeRsaPrivateKeyFromKeyStore(clientKeyStore, KEY_ALIAS, KEY_PASSWORD); + crypto:PublicKey clientPublicKey = check crypto:decodeRsaPublicKeyFromTrustStore(clientKeyStore, KEY_ALIAS); + + AsymmetricBindingConfig utAsymmBinding = { + signatureAlgorithm: RSA_SHA256, + signatureKey: clientPrivateKey, + encryptionKey: serverPublicKey + }; + xml securedEnvelope = check applyAsymmetricBinding(envelope, utAsymmBinding); + string envelopeString = securedEnvelope.toString(); + byte[] signedData = check getSignatureData(securedEnvelope); + boolean validity = check crypto:verifyRsaSha256Signature((envelope//*).toString().toBytes(), signedData, clientPublicKey); + test:assertTrue(validity); + + assertSignatureWithoutX509(envelopeString); +} + +@test:Config { + groups: ["username_token", "signature", "asymmetric_binding"] +} +function testAsymmetricBindingWithX509Signature() returns error? { + xml envelope = + xml ` + + `; + xmlns "http://schemas.xmlsoap.org/soap/envelope/" as soap; + + crypto:KeyStore serverKeyStore = { + path: X509_KEY_STORE_PATH, + password: KEY_PASSWORD + }; + crypto:PublicKey serverPublicKey = check crypto:decodeRsaPublicKeyFromTrustStore(serverKeyStore, KEY_ALIAS); + + crypto:KeyStore clientKeyStore = { + path: X509_KEY_STORE_PATH_2, + password: KEY_PASSWORD + }; + crypto:PrivateKey clientPrivateKey = check crypto:decodeRsaPrivateKeyFromKeyStore(clientKeyStore, KEY_ALIAS, KEY_PASSWORD); + crypto:PublicKey clientPublicKey = check crypto:decodeRsaPublicKeyFromTrustStore(clientKeyStore, KEY_ALIAS); + + AsymmetricBindingConfig utAsymmBinding = { + signatureAlgorithm: RSA_SHA256, + signatureKey: clientPrivateKey, + encryptionKey: serverPublicKey, + x509Token: X509_PUBLIC_CERT_PATH_2 + }; + xml securedEnvelope = check applyAsymmetricBinding(envelope, utAsymmBinding); + string envelopeString = securedEnvelope.toString(); + + byte[] signedData = check getSignatureData(securedEnvelope); + boolean validity = check crypto:verifyRsaSha256Signature((envelope//*).toString().toBytes(), signedData, clientPublicKey); + test:assertTrue(validity); + + assertSignatureWithX509(envelopeString); +} + +@test:Config { + groups: ["username_token", "signature", "asymmetric_binding"] +} +function testAsymmetricBindingWithEncryption() returns error? { + xml envelope = + xml ` + + `; + xmlns "http://schemas.xmlsoap.org/soap/envelope/" as soap; + + crypto:KeyStore serverKeyStore = { + path: X509_KEY_STORE_PATH, + password: KEY_PASSWORD + }; + crypto:PrivateKey serverPrivateKey = check crypto:decodeRsaPrivateKeyFromKeyStore(serverKeyStore, KEY_ALIAS, KEY_PASSWORD); + crypto:PublicKey serverPublicKey = check crypto:decodeRsaPublicKeyFromTrustStore(serverKeyStore, KEY_ALIAS); + + crypto:KeyStore clientKeyStore = { + path: X509_KEY_STORE_PATH_2, + password: KEY_PASSWORD + }; + crypto:PrivateKey clientPrivateKey = check crypto:decodeRsaPrivateKeyFromKeyStore(clientKeyStore, KEY_ALIAS, KEY_PASSWORD); + + AsymmetricBindingConfig utAsymmBinding = { + encryptionAlgorithm: RSA_ECB, + signatureKey: clientPrivateKey, + encryptionKey: serverPublicKey + }; + xml securedEnvelope = check applyAsymmetricBinding(envelope, utAsymmBinding); + string envelopeString = securedEnvelope.toString(); + + byte[] encData = check getEncryptedData(securedEnvelope); + byte[] decryptDataResult = check decryptData(encData, RSA_ECB, serverPrivateKey); + test:assertEquals(check string:fromBytes(decryptDataResult), (envelope//*).toString()); + + assertEncryptedPart(envelopeString); +} + +@test:Config { + groups: ["username_token", "signature", "asymmetric_binding", "rr"] +} +function testAsymmetricBindingWithSignatureAndEncryption() returns error? { + xml envelope = + xml ` + John Doe + `; + xmlns "http://schemas.xmlsoap.org/soap/envelope/" as soap; + + crypto:KeyStore serverKeyStore = { + path: X509_KEY_STORE_PATH, + password: KEY_PASSWORD + }; + crypto:PrivateKey serverPrivateKey = check crypto:decodeRsaPrivateKeyFromKeyStore(serverKeyStore, KEY_ALIAS, KEY_PASSWORD); + crypto:PublicKey serverPublicKey = check crypto:decodeRsaPublicKeyFromTrustStore(serverKeyStore, KEY_ALIAS); + + crypto:KeyStore clientKeyStore = { + path: X509_KEY_STORE_PATH_2, + password: KEY_PASSWORD + }; + crypto:PrivateKey clientPrivateKey = check crypto:decodeRsaPrivateKeyFromKeyStore(clientKeyStore, KEY_ALIAS, KEY_PASSWORD); + crypto:PublicKey clientPublicKey = check crypto:decodeRsaPublicKeyFromTrustStore(clientKeyStore, KEY_ALIAS); + + AsymmetricBindingConfig utAsymmBinding = { + signatureAlgorithm: RSA_SHA256, + encryptionAlgorithm: RSA_ECB, + signatureKey: clientPrivateKey, + encryptionKey: serverPublicKey + }; + + xml securedEnvelope = check applyAsymmetricBinding(envelope, utAsymmBinding); + string envelopeString = securedEnvelope.toString(); + + byte[] signedData = check getSignatureData(securedEnvelope); + boolean validity = check crypto:verifyRsaSha256Signature((envelope//*).toString().toBytes(), signedData, clientPublicKey); + test:assertTrue(validity); + + byte[] encData = check getEncryptedData(securedEnvelope); + byte[] decryptDataResult = check decryptData(encData, RSA_ECB, serverPrivateKey); + test:assertEquals(check string:fromBytes(decryptDataResult), (envelope//*).toString()); + + assertSignatureWithoutX509(envelopeString); + assertEncryptedPart(envelopeString); +} + +@test:Config { + groups: ["username_token", "signature", "asymmetric_binding"] +} +function testAsymmetricBindingWithX509SignatureAndEncryption() returns error? { + xml envelope = + xml ` + + `; + xmlns "http://schemas.xmlsoap.org/soap/envelope/" as soap; + + crypto:KeyStore serverKeyStore = { + path: X509_KEY_STORE_PATH, + password: KEY_PASSWORD + }; + crypto:PrivateKey serverPrivateKey = check crypto:decodeRsaPrivateKeyFromKeyStore(serverKeyStore, KEY_ALIAS, KEY_PASSWORD); + crypto:PublicKey serverPublicKey = check crypto:decodeRsaPublicKeyFromTrustStore(serverKeyStore, KEY_ALIAS); + + crypto:KeyStore clientKeyStore = { + path: X509_KEY_STORE_PATH_2, + password: KEY_PASSWORD + }; + crypto:PrivateKey clientPrivateKey = check crypto:decodeRsaPrivateKeyFromKeyStore(clientKeyStore, KEY_ALIAS, KEY_PASSWORD); + crypto:PublicKey clientPublicKey = check crypto:decodeRsaPublicKeyFromTrustStore(clientKeyStore, KEY_ALIAS); + + AsymmetricBindingConfig utAsymmBinding = { + signatureAlgorithm: RSA_SHA256, + encryptionAlgorithm: RSA_ECB, + signatureKey: clientPrivateKey, + encryptionKey: serverPublicKey, + x509Token: X509_PUBLIC_CERT_PATH_2 + }; + xml securedEnvelope = check applyAsymmetricBinding(envelope, utAsymmBinding); + string envelopeString = securedEnvelope.toString(); + + byte[] signedData = check getSignatureData(securedEnvelope); + boolean validity = check crypto:verifyRsaSha256Signature((envelope//*).toString().toBytes(), signedData, clientPublicKey); + test:assertTrue(validity); + + byte[] encData = check getEncryptedData(securedEnvelope); + byte[] decryptDataResult = check decryptData(encData, RSA_ECB, serverPrivateKey); + test:assertEquals((envelope//*).toString(), check string:fromBytes(decryptDataResult)); + + assertSignatureWithX509(envelopeString); + assertEncryptedPart(envelopeString); +} + +@test:Config { + groups: ["username_token", "signature", "asymmetric_binding"] +} +function testUsernameTokenWithAsymmetricBindingAndX509() returns error? { + xml envelope = + xml ` + + `; + xmlns "http://schemas.xmlsoap.org/soap/envelope/" as soap; + + UsernameTokenConfig utRecord = { + username: USERNAME, + password: PASSWORD, + passwordType: DIGEST + }; + envelope = check applyUsernameToken(envelope, utRecord); + + crypto:KeyStore serverKeyStore = { + path: X509_KEY_STORE_PATH, + password: KEY_PASSWORD + }; + crypto:PrivateKey serverPrivateKey = check crypto:decodeRsaPrivateKeyFromKeyStore(serverKeyStore, KEY_ALIAS, KEY_PASSWORD); + crypto:PublicKey serverPublicKey = check crypto:decodeRsaPublicKeyFromTrustStore(serverKeyStore, KEY_ALIAS); + + crypto:KeyStore clientKeyStore = { + path: X509_KEY_STORE_PATH_2, + password: KEY_PASSWORD + }; + crypto:PrivateKey clientPrivateKey = check crypto:decodeRsaPrivateKeyFromKeyStore(clientKeyStore, KEY_ALIAS, KEY_PASSWORD); + crypto:PublicKey clientPublicKey = check crypto:decodeRsaPublicKeyFromTrustStore(clientKeyStore, KEY_ALIAS); + + AsymmetricBindingConfig utAsymmBinding = { + signatureAlgorithm: RSA_SHA256, + encryptionAlgorithm: RSA_ECB, + signatureKey: clientPrivateKey, + encryptionKey: serverPublicKey, + x509Token: X509_PUBLIC_CERT_PATH_2 + }; + xml securedEnvelope = check applyAsymmetricBinding(envelope, utAsymmBinding); + string envelopeString = securedEnvelope.toString(); + + byte[] signedData = check getSignatureData(securedEnvelope); + boolean validity = check crypto:verifyRsaSha256Signature((envelope//*).toString().toBytes(), signedData, clientPublicKey); + test:assertTrue(validity); + + byte[] encData = check getEncryptedData(securedEnvelope); + byte[] decryptDataResult = check decryptData(encData, RSA_ECB, serverPrivateKey); + test:assertEquals((envelope//*).toString(), check string:fromBytes(decryptDataResult)); + + assertUsernameToken(envelopeString, DIGEST); + assertSignatureWithX509(envelopeString); + assertEncryptedPart(envelopeString); +} + +@test:Config { + groups: ["username_token", "signature", "asymmetric_binding"] +} +function testUsernameTokenTimestampWithAsymmetricBindingAndX509() returns error? { + xml envelope = + xml ` + + `; + xmlns "http://schemas.xmlsoap.org/soap/envelope/" as soap; + + UsernameTokenConfig utRecord = { + username: USERNAME, + password: PASSWORD, + passwordType: DIGEST + }; + envelope = check applyUsernameToken(envelope, utRecord); + envelope = check applyTimestampToken(envelope = envelope, timeToLive = 600); + + crypto:KeyStore serverKeyStore = { + path: X509_KEY_STORE_PATH, + password: KEY_PASSWORD + }; + crypto:PrivateKey serverPrivateKey = check crypto:decodeRsaPrivateKeyFromKeyStore(serverKeyStore, KEY_ALIAS, KEY_PASSWORD); + crypto:PublicKey serverPublicKey = check crypto:decodeRsaPublicKeyFromTrustStore(serverKeyStore, KEY_ALIAS); + + crypto:KeyStore clientKeyStore = { + path: X509_KEY_STORE_PATH_2, + password: KEY_PASSWORD + }; + crypto:PrivateKey clientPrivateKey = check crypto:decodeRsaPrivateKeyFromKeyStore(clientKeyStore, KEY_ALIAS, KEY_PASSWORD); + crypto:PublicKey clientPublicKey = check crypto:decodeRsaPublicKeyFromTrustStore(clientKeyStore, KEY_ALIAS); + + AsymmetricBindingConfig utAsymmBinding = { + signatureAlgorithm: RSA_SHA256, + encryptionAlgorithm: RSA_ECB, + signatureKey: clientPrivateKey, + encryptionKey: serverPublicKey, + x509Token: X509_PUBLIC_CERT_PATH_2 + }; + xml securedEnvelope = check applyAsymmetricBinding(envelope, utAsymmBinding); + string envelopeString = securedEnvelope.toString(); + + byte[] signedData = check getSignatureData(securedEnvelope); + boolean validity = check crypto:verifyRsaSha256Signature((envelope//*).toString().toBytes(), signedData, clientPublicKey); + test:assertTrue(validity); + + byte[] encData = check getEncryptedData(securedEnvelope); + byte[] decryptDataResult = check decryptData(encData, RSA_ECB, serverPrivateKey); + test:assertEquals((envelope//*).toString(), check string:fromBytes(decryptDataResult)); + + assertUsernameToken(envelopeString, DIGEST); + assertTimestampToken(envelopeString); + assertSignatureWithX509(envelopeString); + assertEncryptedPart(envelopeString); +} + + +@test:Config { + groups: ["username_token", "signature", "asymmetric_binding", "outbound_config"] +} +function testAsymmetricBindingWithOutboundConfig() returns error? { + xml envelope = + xml ` + John Doe + `; + xmlns "http://schemas.xmlsoap.org/soap/envelope/" as soap; + + crypto:KeyStore serverKeyStore = { + path: X509_KEY_STORE_PATH, + password: KEY_PASSWORD + }; + crypto:PrivateKey serverPrivateKey = check crypto:decodeRsaPrivateKeyFromKeyStore(serverKeyStore, KEY_ALIAS, KEY_PASSWORD); + crypto:PublicKey serverPublicKey = check crypto:decodeRsaPublicKeyFromTrustStore(serverKeyStore, KEY_ALIAS); + + crypto:KeyStore clientKeyStore = { + path: X509_KEY_STORE_PATH_2, + password: KEY_PASSWORD + }; + crypto:PrivateKey clientPrivateKey = check crypto:decodeRsaPrivateKeyFromKeyStore(clientKeyStore, KEY_ALIAS, KEY_PASSWORD); + crypto:PublicKey clientPublicKey = check crypto:decodeRsaPublicKeyFromTrustStore(clientKeyStore, KEY_ALIAS); + + AsymmetricBindingConfig utAsymmBinding = { + signatureAlgorithm: RSA_SHA256, + encryptionAlgorithm: RSA_ECB, + signatureKey: clientPrivateKey, + encryptionKey: serverPublicKey + }; + + OutboundSecurityConfig outboundConfig = { + verificationKey: clientPublicKey, + signatureAlgorithm: RSA_SHA256, + decryptionAlgorithm: RSA_ECB, + decryptionKey: serverPrivateKey + }; + + xml securedEnvelope = check applyAsymmetricBinding(envelope, utAsymmBinding); + string envelopeString = securedEnvelope.toString(); + crypto:PrivateKey|crypto:PublicKey? privateKey = outboundConfig.decryptionKey; + if privateKey !is () { + byte[] encData = check getEncryptedData(securedEnvelope); + byte[] decryptDataResult = check decryptData(encData, RSA_ECB, privateKey); + string decryptedBody = "" + check string:fromBytes(decryptDataResult) + ""; + envelopeString = regex:replace(envelopeString, string`.*`, decryptedBody); + securedEnvelope = check xml:fromString(envelopeString); + } + byte[] signedData = check getSignatureData(securedEnvelope); + boolean validity = check crypto:verifyRsaSha256Signature((envelope//*).toString().toBytes(), signedData, clientPublicKey); + test:assertTrue(validity); +} From 6211477242d018f61f85842686dbc848768c73f1 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Tue, 3 Oct 2023 12:21:45 +0530 Subject: [PATCH 094/189] Add test cases for the SOAP 1.1 module --- .../soap11/tests/soap11_client_test.bal | 80 +++++++++++++++---- 1 file changed, 63 insertions(+), 17 deletions(-) diff --git a/ballerina/modules/soap11/tests/soap11_client_test.bal b/ballerina/modules/soap11/tests/soap11_client_test.bal index 7a9f04b..41cd6b0 100644 --- a/ballerina/modules/soap11/tests/soap11_client_test.bal +++ b/ballerina/modules/soap11/tests/soap11_client_test.bal @@ -13,14 +13,24 @@ // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. +import soap.wssec; -import ballerina/test; import ballerina/mime; +import ballerina/test; -@test:Config {} -function testSendReceive11() returns error? { - Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL"); +const wssec:TransportBindingConfig TRANSPORT_BINDING = "TransportBinding"; +const wssec:NoPolicy NO_POLICY = "NoPolicy"; +const string KEY_ALIAS = "wss40"; +const string KEY_PASSWORD = "security"; +const string X509_PUBLIC_CERT_PATH = "modules/wssec/tests/resources/x509_certificate.crt"; +const string X509_PUBLIC_CERT_PATH_2 = "modules/wssec/tests/resources/x509_certificate_2.crt"; +const string X509_KEY_STORE_PATH = "modules/wssec/tests/resources/x509_certificate.p12"; +const string X509_KEY_STORE_PATH_2 = "modules/wssec/tests/resources/x509_certificate_2.p12"; +@test:Config { + groups: ["soap11", "send_only"] +} +function testSendOnly11() returns error? { xml body = xml ` @@ -32,15 +42,20 @@ function testSendReceive11() returns error? {
`; - xml|mime:Entity[] response = check soapClient->sendReceive(body, "http://tempuri.org/Add"); - - xml expected = xml `5`; - test:assertEquals(response, expected); + Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL"); + _ = check soapClient->sendOnly(body, "http://tempuri.org/Add"); } -@test:Config {} -function testSendOnly11() returns error? { - Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL"); +@test:Config { + groups: ["soap11", "send_receive"] +} +function testSendReceive11() returns error? { + Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL", + { + inboundSecurity: NO_POLICY, + outboundSecurity: {} + } + ); xml body = xml ` `; - - _ = check soapClient->sendOnly(body, "http://tempuri.org/Add"); + xml|mime:Entity[] response = check soapClient->sendReceive(body, "http://tempuri.org/Add"); + xml expected = xml `5`; + test:assertEquals(response, expected); } -@test:Config {} +@test:Config { + groups: ["soap11", "send_receive"] +} function testSendReceive11WithHeaders() returns error? { - Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL"); - xml body = xml ` @@ -71,9 +87,39 @@ function testSendReceive11WithHeaders() returns error? { `; + Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL"); + xml|mime:Entity[] response = check soapClient->sendReceive(body, "http://tempuri.org/Add", {foo: ["bar1", "bar2"]}); - xml expected = xml `5`; test:assertEquals(response, expected); } + +@test:Config { + groups: ["soap11"] +} +function testTransportBindingError() returns error? { + Client|Error soapClient = new ("http://www.dneonline.com/calculator.asmx?WSDL", inboundSecurity = TRANSPORT_BINDING); + test:assertTrue(soapClient is Error); + test:assertEquals((soapClient).message(), SOAP_CLIENT_ERROR); +} + +@test:Config { + groups: ["soap11", "send_receive"] +} +function testSendReceiveError() returns error? { + Client soapClient = check new ("http://www.dneonline.com/invalidcalculator.asmx?WSDL"); + xml body = xml ` + + + 2 + 3 + + + `; + xml|mime:Entity[]|Error response = soapClient->sendReceive(body, "http://tempuri.org/Add"); + test:assertTrue(response is Error); + test:assertEquals((response).message(), SOAP_RESPONSE_ERROR); +} From bc383ca4b4f5a84f1190e1a40468b0c34b86ba77 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Tue, 3 Oct 2023 12:21:56 +0530 Subject: [PATCH 095/189] Add test cases for SOAP 1.2 module --- .../soap12/tests/soap12_client_test.bal | 108 ++++++++++++------ 1 file changed, 76 insertions(+), 32 deletions(-) diff --git a/ballerina/modules/soap12/tests/soap12_client_test.bal b/ballerina/modules/soap12/tests/soap12_client_test.bal index 0f52751..d5abf45 100644 --- a/ballerina/modules/soap12/tests/soap12_client_test.bal +++ b/ballerina/modules/soap12/tests/soap12_client_test.bal @@ -13,14 +13,18 @@ // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. +import soap.wssec; -import ballerina/test; import ballerina/mime; +import ballerina/test; -@test:Config {} -function testSendReceive12() returns error? { - Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL"); +const wssec:TransportBindingConfig TRANSPORT_BINDING = "TransportBinding"; +const wssec:NoPolicy NO_POLICY = "NoPolicy"; +@test:Config { + groups: ["soap12", "send_only"] +} +function testSendOnly12() returns error? { xml body = xml ` @@ -32,34 +36,37 @@ function testSendReceive12() returns error? { `; - xml|mime:Entity[] response = check soapClient->sendReceive(body, "http://tempuri.org/Add"); + Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL"); - xml expected = xml `5`; - test:assertEquals(response, expected); + _ = check soapClient->sendOnly(body, "http://tempuri.org/Add"); } -@test:Config {} -function testSendOnly12() returns error? { +@test:Config { + groups: ["soap12", "send_receive"] +} +function testSendReceive12() returns error? { Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL"); xml body = xml ` - - - 2 - 3 - - - `; + xmlns:soap="http://www.w3.org/2003/05/soap-envelope" + soap:encodingStyle="http://www.w3.org/2003/05/soap-encoding"> + + + 2 + 3 + + + `; + xml|mime:Entity[] response = check soapClient->sendReceive(body, "http://tempuri.org/Add"); - _ = check soapClient->sendOnly(body, "http://tempuri.org/Add"); + xml expected = xml `5`; + test:assertEquals(response, expected); } -@test:Config {} +@test:Config { + groups: ["soap12", "send_receive"] +} function testSendReceive12WithHeaders() returns error? { - Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL"); - xml body = xml ` @@ -71,17 +78,19 @@ function testSendReceive12WithHeaders() returns error? { `; + Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL"); + xml|mime:Entity[] response = check soapClient->sendReceive(body, "http://tempuri.org/Add", - {foo: ["bar1", "bar2"]}); + {foo: ["bar1", "bar2"]}); xml expected = xml `5`; test:assertEquals(response, expected); } -@test:Config {} +@test:Config { + groups: ["soap12", "send_receive"] +} function testSendReceive12WithoutSoapAction() returns error? { - Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL"); - xml body = xml ` @@ -93,16 +102,18 @@ function testSendReceive12WithoutSoapAction() returns error? { `; + Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL"); + xml|mime:Entity[] response = check soapClient->sendReceive(body); xml expected = xml `5`; test:assertEquals(response, expected); } -@test:Config {} +@test:Config { + groups: ["soap12", "send_only"] +} function testSendOnly12WithoutSoapAction() returns error? { - Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL"); - xml body = xml ` @@ -114,13 +125,15 @@ function testSendOnly12WithoutSoapAction() returns error? { `; + Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL"); + _ = check soapClient->sendOnly(body); } -@test:Config {} +@test:Config { + groups: ["soap12", "send_receive"] +} function testSendReceive12IncludingHeadersWithoutSoapAction() returns error? { - Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL"); - xml body = xml ` @@ -132,7 +145,38 @@ function testSendReceive12IncludingHeadersWithoutSoapAction() returns error? { `; + Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL"); + xml|mime:Entity[] response = check soapClient->sendReceive(body, (), {foo: ["bar1", "bar2"]}); xml expected = xml `5`; test:assertEquals(response, expected); } + +@test:Config { + groups: ["soap12"] +} +function testTransportBindingError() returns error? { + Client|Error soapClient = new ("http://www.dneonline.com/calculator.asmx?WSDL", inboundSecurity = TRANSPORT_BINDING); + test:assertTrue(soapClient is Error); + test:assertEquals((soapClient).message(), SOAP_CLIENT_ERROR); +} + +@test:Config { + groups: ["soap12", "send_receive"] +} +function testSendReceiveError() returns error? { + Client soapClient = check new ("http://www.dneonline.com/invalidcalculator.asmx?WSDL"); + xml body = xml ` + + + 2 + 3 + + + `; + xml|mime:Entity[]|Error response = soapClient->sendReceive(body, "http://tempuri.org/Add"); + test:assertTrue(response is Error); + test:assertEquals((response).message(), SOAP_RESPONSE_ERROR); +} From bc93dcb23ab22e64a384de12f5a1e0c7986160ce Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Tue, 3 Oct 2023 12:22:35 +0530 Subject: [PATCH 096/189] Add utility functions to verify SOAP envelopes --- ballerina/modules/wssec/tests/test_utils.bal | 115 +++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 ballerina/modules/wssec/tests/test_utils.bal diff --git a/ballerina/modules/wssec/tests/test_utils.bal b/ballerina/modules/wssec/tests/test_utils.bal new file mode 100644 index 0000000..4881ff4 --- /dev/null +++ b/ballerina/modules/wssec/tests/test_utils.bal @@ -0,0 +1,115 @@ +// Copyright (c) 2023, WSO2 LLC. (http://www.wso2.org) All Rights Reserved. +// +// WSO2 LLC. licenses this file to you under the Apache License, +// Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +import ballerina/test; + +const string USERNAME = "username"; +const string PASSWORD = "password"; + +const string KEY_ALIAS = "wss40"; +const string KEY_PASSWORD = "security"; + +const string PUBLIC_KEY_PATH = "modules/wssec/tests/resources/public_key.cer"; +const string PRIVATE_KEY_PATH = "modules/wssec/tests/resources/private_key.pem"; +const string KEY_STORE_PATH = "modules/wssec/tests/resources/wss40.p12"; +const string X509_PUBLIC_CERT_PATH = "modules/wssec/tests/resources/x509_certificate.crt"; +const string X509_PUBLIC_CERT_PATH_2 = "modules/wssec/tests/resources/x509_certificate_2.crt"; +const string X509_KEY_STORE_PATH = "modules/wssec/tests/resources/x509_certificate.p12"; +const string X509_KEY_STORE_PATH_2 = "modules/wssec/tests/resources/x509_certificate_2.p12"; + +function assertTimestampToken(string envelopeString) { + string:RegExp ts_token = re ``; + string:RegExp created = re `.*`; + string:RegExp expires = re `.*`; + test:assertTrue(envelopeString.includesMatch(ts_token)); + test:assertTrue(envelopeString.includesMatch(created)); + test:assertTrue(envelopeString.includesMatch(expires)); +} +function assertUsernameToken(string envelopeString, PasswordType passwordType) { + string:RegExp usernameTokenTag = re `.*`; + string:RegExp usernameTag = re `${USERNAME}`; + test:assertTrue(envelopeString.includesMatch(usernameTokenTag)); + test:assertTrue(envelopeString.includesMatch(usernameTag)); + match passwordType { + TEXT => { + string:RegExp passwordTag = re `${PASSWORD}`; + test:assertTrue(envelopeString.includesMatch(passwordTag)); + } + DIGEST => { + string:RegExp passwordTag = re `.*`; + string:RegExp nonce = re `.*`; + string:RegExp created = re `.*`; + test:assertTrue(envelopeString.includesMatch(passwordTag)); + test:assertTrue(envelopeString.includesMatch(nonce)); + test:assertTrue(envelopeString.includesMatch(created)); + } + _ => { + string:RegExp salt = re `.*`; + string:RegExp iteration = re `.*`; + test:assertTrue(envelopeString.includesMatch(salt)); + test:assertTrue(envelopeString.includesMatch(iteration)); + } + } +} +function assertSignatureWithX509(string securedEnvelope) { + string:RegExp keyIdentifier = re `.*`; + test:assertTrue(securedEnvelope.includesMatch(keyIdentifier)); + assertSignatureWithoutX509(securedEnvelope); +} + +function assertSignatureWithoutX509(string securedEnvelope) { + string:RegExp signature = re `.*`; + string:RegExp signatureInfo = re `.*`; + string:RegExp canonicalizationMethod = re ``; + string:RegExp signatureMethod = re ``; + string:RegExp transformMethod = re ``; + string:RegExp digestMethod = re ``; + string:RegExp signatureValue = re `.*`; + + test:assertTrue(securedEnvelope.includesMatch(signature)); + test:assertTrue(securedEnvelope.includesMatch(signatureInfo)); + test:assertTrue(securedEnvelope.includesMatch(canonicalizationMethod)); + test:assertTrue(securedEnvelope.includesMatch(signatureMethod)); + test:assertTrue(securedEnvelope.includesMatch(transformMethod)); + test:assertTrue(securedEnvelope.includesMatch(digestMethod)); + test:assertTrue(securedEnvelope.includesMatch(signatureValue)); +} + +function assertEncryptedSymmetricKey(string securedEnvelope) { + string:RegExp encryptedKey = re `.*`; + string:RegExp encryptionMethod = re ``; + string:RegExp keyInfo = re ``; + string:RegExp cipherData = re `.*`; + + test:assertTrue(securedEnvelope.includesMatch(encryptedKey)); + test:assertTrue(securedEnvelope.includesMatch(encryptionMethod)); + test:assertTrue(securedEnvelope.includesMatch(keyInfo)); + test:assertTrue(securedEnvelope.includesMatch(cipherData)); +} + +function assertEncryptedPart(string securedEnvelope) { + string:RegExp encryptedData = re ``; + string:RegExp keyInfo = re ``; + string:RegExp cipherData = re `.*`; + string:RegExp cipherValue = re `.*`; + + test:assertTrue(securedEnvelope.includesMatch(encryptedData)); + test:assertTrue(securedEnvelope.includesMatch(encMethod)); + test:assertTrue(securedEnvelope.includesMatch(keyInfo)); + test:assertTrue(securedEnvelope.includesMatch(cipherData)); + test:assertTrue(securedEnvelope.includesMatch(cipherValue)); +} From 241e0c866efbc32f48a3a6bb1f86264580fd438f Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Tue, 3 Oct 2023 14:24:43 +0530 Subject: [PATCH 097/189] Rename the file to `WsSecurityUtils` --- .../java/org/wssec/{WSSecurityUtils.java => WsSecurityUtils.java} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename native/src/main/java/org/wssec/{WSSecurityUtils.java => WsSecurityUtils.java} (100%) diff --git a/native/src/main/java/org/wssec/WSSecurityUtils.java b/native/src/main/java/org/wssec/WsSecurityUtils.java similarity index 100% rename from native/src/main/java/org/wssec/WSSecurityUtils.java rename to native/src/main/java/org/wssec/WsSecurityUtils.java From 1e57ac70c6f078ae56cbfb553f3b9d7c42e3d849 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Tue, 3 Oct 2023 14:44:53 +0530 Subject: [PATCH 098/189] Add the .gitattributes file --- .gitattributes | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..1bb96bb --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# Ensure all Java files use LF. +*.java eol=lf From f47b937b0fec14ad772019fd23d54d1a26a0d639 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Tue, 3 Oct 2023 14:45:28 +0530 Subject: [PATCH 099/189] Add the ballerina `regex` dependency --- build.gradle | 2 +- gradle.properties | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 20f5ce9..51ac0aa 100644 --- a/build.gradle +++ b/build.gradle @@ -79,7 +79,7 @@ subprojects { ballerinaStdLibs "io.ballerina.stdlib:crypto-ballerina:${project.stdlibCryptoVersion}" ballerinaStdLibs "io.ballerina.stdlib:time-ballerina:${project.stdlibTimeVersion}" ballerinaStdLibs "io.ballerina.stdlib:uuid-ballerina:${project.stdlibUuidVersion}" - + ballerinaStdLibs "io.ballerina.stdlib:regex-ballerina:${project.stdlibRegexVersion}" ballerinaStdLibs "io.ballerina.stdlib:auth-ballerina:${project.stdlibAuthVersion}" ballerinaStdLibs "io.ballerina.stdlib:jwt-ballerina:${project.stdlibJwtVersion}" ballerinaStdLibs "io.ballerina.stdlib:oauth2-ballerina:${project.stdlibOAuth2Version}" diff --git a/gradle.properties b/gradle.properties index 09e7561..bbc5708 100644 --- a/gradle.properties +++ b/gradle.properties @@ -20,6 +20,7 @@ stdlibCryptoVersion=2.5.0 stdlibLogVersion=2.9.0 stdlibOsVersion=1.8.0 stdlibRandomVersion=1.5.0 +stdlibRegexVersion=1.4.3 stdlibTaskVersion=2.5.0 stdlibCacheVersion=3.7.0 From 7c36e75c7020c0cc840239f4bd5eea09b5279908 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Tue, 3 Oct 2023 16:23:52 +0530 Subject: [PATCH 100/189] Improve signature and verification methods --- ballerina/modules/common/soap_utils.bal | 14 ++++++++------ ballerina/modules/wssec/signature.bal | 14 ++++---------- ballerina/modules/wssec/ws_security_methods.bal | 6 ++++++ 3 files changed, 18 insertions(+), 16 deletions(-) diff --git a/ballerina/modules/common/soap_utils.bal b/ballerina/modules/common/soap_utils.bal index 8478551..9f3b472 100644 --- a/ballerina/modules/common/soap_utils.bal +++ b/ballerina/modules/common/soap_utils.bal @@ -74,26 +74,28 @@ public function applySecurityPolicies(wssec:InboundSecurityConfig|wssec:InboundS return securedEnvelope; } -public function applyOutboundConfig(wssec:OutboundSecurityConfig outboundSecurity, xml envelope) returns xml|Error { +public function applyOutboundConfig(wssec:OutboundSecurityConfig outboundSecurity, xml envelope) returns xml|wssec:Error|Error { xmlns "http://schemas.xmlsoap.org/soap/envelope/" as soap; xml soapEnvelope = envelope; do { - if outboundSecurity.decryptionAlgorithm !is () { + wssec:EncryptionAlgorithm? encryptionAlgorithm = outboundSecurity.decryptionAlgorithm; + if encryptionAlgorithm !is () { crypto:PrivateKey|crypto:PublicKey? clientPrivateKey = outboundSecurity.decryptionKey; if clientPrivateKey !is () { byte[] encData = check wssec:getEncryptedData(soapEnvelope); - byte[] decryptDataResult = check wssec:decryptData(encData, wssec:RSA_ECB, clientPrivateKey); + byte[] decryptDataResult = check wssec:decryptData(encData, encryptionAlgorithm, clientPrivateKey); string decryptedBody = "" + check string:fromBytes(decryptDataResult) + ""; string decryptedEnv = regex:replace(soapEnvelope.toString(), string `.*`, decryptedBody); soapEnvelope = check xml:fromString(decryptedEnv); } } - if outboundSecurity.signatureAlgorithm !is () { + wssec:SignatureAlgorithm? signatureAlgorithm = outboundSecurity.signatureAlgorithm; + if signatureAlgorithm !is () { crypto:PublicKey? serverPublicKey = outboundSecurity.verificationKey; if serverPublicKey !is () { byte[] signatureData = check wssec:getSignatureData(soapEnvelope); - boolean verify = check crypto:verifyRsaSha256Signature((soapEnvelope//*).toBalString().toBytes(), - signatureData, serverPublicKey); + boolean verify = check wssec:verifyData((soapEnvelope//*).toString().toBytes(), + signatureData, serverPublicKey, signatureAlgorithm); if !verify { return error Error("Signature verification of the SOAP envelope has been failed"); } diff --git a/ballerina/modules/wssec/signature.bal b/ballerina/modules/wssec/signature.bal index f050249..a801573 100644 --- a/ballerina/modules/wssec/signature.bal +++ b/ballerina/modules/wssec/signature.bal @@ -24,7 +24,7 @@ class Signature { } public function signData(string dataString, SignatureAlgorithm signatureAlgorithm, - crypto:PrivateKey privateKey) returns byte[]|Error { + crypto:PrivateKey privateKey) returns byte[]|Error { byte[] data = dataString.toBytes(); do { match signatureAlgorithm { @@ -37,11 +37,8 @@ class Signature { RSA_SHA384 => { return check crypto:signRsaSha384(data, privateKey); } - RSA_SHA512 => { - return check crypto:signRsaSha512(data, privateKey); - } _ => { - return error Error("Invalid signature algorithm!"); + return check crypto:signRsaSha512(data, privateKey); } } } on fail var e { @@ -50,7 +47,7 @@ class Signature { } public function verifySignature(byte[] data, byte[] signature, crypto:PublicKey publicKey, - SignatureAlgorithm signatureAlgorithm = RSA_SHA256) returns boolean|Error { + SignatureAlgorithm signatureAlgorithm) returns boolean|Error { do { match signatureAlgorithm { RSA_SHA1 => { @@ -62,11 +59,8 @@ class Signature { RSA_SHA384 => { return check crypto:verifyRsaSha384Signature(data, signature, publicKey); } - RSA_SHA512 => { - return check crypto:verifyRsaSha512Signature(data, signature, publicKey); - } _ => { - return error Error("Invalid signature algorithm!"); + return check crypto:verifyRsaSha512Signature(data, signature, publicKey); } } diff --git a/ballerina/modules/wssec/ws_security_methods.bal b/ballerina/modules/wssec/ws_security_methods.bal index 3189010..26e5a96 100644 --- a/ballerina/modules/wssec/ws_security_methods.bal +++ b/ballerina/modules/wssec/ws_security_methods.bal @@ -33,6 +33,12 @@ public function decryptData(byte[] cipherText, EncryptionAlgorithm encryptionAlg return encrypt.decryptData(cipherText, encryptionAlgorithm, key); } +public function verifyData(byte[] data, byte[] signature, crypto:PublicKey publicKey, + SignatureAlgorithm signatureAlgorithm) returns boolean|Error { + Signature sign = check new (); + return sign.verifySignature(data, signature, publicKey, signatureAlgorithm); +} + function addSignature(Signature sign, string signatureAlgorithm, byte[] signature) returns Signature|Error { sign.setSignatureAlgorithm(signatureAlgorithm); sign.setSignatureValue(signature); From 3b29eb1a6099b9a21874f977fda6067522605fd6 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Tue, 3 Oct 2023 16:24:12 +0530 Subject: [PATCH 101/189] Improve the API to decrypt data --- ballerina/modules/wssec/encryption.bal | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/ballerina/modules/wssec/encryption.bal b/ballerina/modules/wssec/encryption.bal index 4a9b390..b531609 100644 --- a/ballerina/modules/wssec/encryption.bal +++ b/ballerina/modules/wssec/encryption.bal @@ -71,11 +71,8 @@ class Encryption { RSA_ECB if key is crypto:PublicKey|crypto:PrivateKey => { return check crypto:decryptRsaEcb(cipherText, key); } - _ if key !is crypto:PublicKey|crypto:PrivateKey => { - return error Error("Invalid/Missing key!"); - } _ => { - return error Error("Decryption Algorithm is not supported"); + return error Error("Invalid/Missing key!"); } } } on fail var e { From 473f51d4d46560fc5f3831e84fdf1e9a3fa1d669 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Tue, 3 Oct 2023 16:24:40 +0530 Subject: [PATCH 102/189] Add test cases to support all the signature algorithms --- .../modules/wssec/tests/ws_security_tests.bal | 173 ++++++++++++++---- 1 file changed, 142 insertions(+), 31 deletions(-) diff --git a/ballerina/modules/wssec/tests/ws_security_tests.bal b/ballerina/modules/wssec/tests/ws_security_tests.bal index 960ceac..91b4cd8 100644 --- a/ballerina/modules/wssec/tests/ws_security_tests.bal +++ b/ballerina/modules/wssec/tests/ws_security_tests.bal @@ -217,13 +217,13 @@ function testSymmetricBindingPolicyWithSignatureOnly() returns error? { crypto:PrivateKey symmetricKey = check crypto:decodeRsaPrivateKeyFromKeyStore(keyStore, KEY_ALIAS, KEY_PASSWORD); crypto:PublicKey publicKey = check crypto:decodeRsaPublicKeyFromTrustStore(keyStore, KEY_ALIAS); - SymmetricBindingConfig utSymmetricBinding = { + SymmetricBindingConfig symmetricBinding = { signatureAlgorithm: RSA_SHA256, symmetricKey: symmetricKey, servicePublicKey: serverPublicKey }; - xml securedEnvelope = check applySymmetricBinding(envelope, utSymmetricBinding); + xml securedEnvelope = check applySymmetricBinding(envelope, symmetricBinding); string envelopeString = securedEnvelope.toString(); byte[] signedData = check getSignatureData(securedEnvelope); @@ -257,13 +257,13 @@ function testSymmetricBindingPolicyEncryptionOnly() returns error? { crypto:PrivateKey symmetricKey = check crypto:decodeRsaPrivateKeyFromKeyStore(keyStore, KEY_ALIAS, KEY_PASSWORD); crypto:PublicKey publicKey = check crypto:decodeRsaPublicKeyFromTrustStore(keyStore, KEY_ALIAS); - SymmetricBindingConfig utSymmetricBinding = { + SymmetricBindingConfig symmetricBinding = { encryptionAlgorithm: RSA_ECB, symmetricKey: symmetricKey, servicePublicKey: serverPublicKey }; - xml securedEnvelope = check applySymmetricBinding(envelope, utSymmetricBinding); + xml securedEnvelope = check applySymmetricBinding(envelope, symmetricBinding); string envelopeString = securedEnvelope.toString(); byte[] encData = check getEncryptedData(securedEnvelope); @@ -297,13 +297,13 @@ function testSymmetricBindingWithSignatureAndEncryption() returns error? { crypto:PrivateKey symmetricKey = check crypto:decodeRsaPrivateKeyFromKeyStore(keyStore, KEY_ALIAS, KEY_PASSWORD); crypto:PublicKey publicKey = check crypto:decodeRsaPublicKeyFromTrustStore(keyStore, KEY_ALIAS); - SymmetricBindingConfig utSymmetricBinding = { + SymmetricBindingConfig symmetricBinding = { signatureAlgorithm: RSA_SHA256, encryptionAlgorithm: RSA_ECB, symmetricKey: symmetricKey, servicePublicKey: serverPublicKey }; - xml securedEnvelope = check applySymmetricBinding(envelope, utSymmetricBinding); + xml securedEnvelope = check applySymmetricBinding(envelope, symmetricBinding); string envelopeString = securedEnvelope.toString(); byte[] signedData = check getSignatureData(securedEnvelope); @@ -343,7 +343,7 @@ function testSymmetricBindingPolicyWithX509SignatureAndEncryption() returns erro crypto:PrivateKey symmetricKey = check crypto:decodeRsaPrivateKeyFromKeyStore(keyStore, KEY_ALIAS, KEY_PASSWORD); crypto:PublicKey publicKey = check crypto:decodeRsaPublicKeyFromTrustStore(keyStore, KEY_ALIAS); - SymmetricBindingConfig utSymmetricBinding = { + SymmetricBindingConfig symmetricBinding = { signatureAlgorithm: RSA_SHA256, encryptionAlgorithm: RSA_ECB, symmetricKey: symmetricKey, @@ -351,7 +351,7 @@ function testSymmetricBindingPolicyWithX509SignatureAndEncryption() returns erro x509Token: X509_PUBLIC_CERT_PATH_2 }; - xml securedEnvelope = check applySymmetricBinding(envelope, utSymmetricBinding); + xml securedEnvelope = check applySymmetricBinding(envelope, symmetricBinding); string envelopeString = securedEnvelope.toString(); byte[] signedData = check getSignatureData(securedEnvelope); @@ -399,13 +399,13 @@ function testUsernameTokenWithSymmetricBinding() returns error? { crypto:PrivateKey symmetricKey = check crypto:decodeRsaPrivateKeyFromKeyStore(keyStore, KEY_ALIAS, KEY_PASSWORD); crypto:PublicKey publicKey = check crypto:decodeRsaPublicKeyFromTrustStore(keyStore, KEY_ALIAS); - SymmetricBindingConfig utSymmetricBinding = { + SymmetricBindingConfig symmetricBinding = { signatureAlgorithm: RSA_SHA256, encryptionAlgorithm: RSA_ECB, symmetricKey: symmetricKey, servicePublicKey: serverPublicKey }; - xml securedEnvelope = check applySymmetricBinding(envelope, utSymmetricBinding); + xml securedEnvelope = check applySymmetricBinding(envelope, symmetricBinding); string envelopeString = securedEnvelope.toString(); byte[] signedData = check getSignatureData(securedEnvelope); @@ -455,7 +455,7 @@ function testUsernameTokenTimestampWithSymmetricBindingAndX509Token() returns er crypto:PrivateKey symmetricKey = check crypto:decodeRsaPrivateKeyFromKeyStore(keyStore, KEY_ALIAS, KEY_PASSWORD); crypto:PublicKey publicKey = check crypto:decodeRsaPublicKeyFromTrustStore(keyStore, KEY_ALIAS); - SymmetricBindingConfig utSymmetricBinding = { + SymmetricBindingConfig symmetricBinding = { signatureAlgorithm: RSA_SHA256, encryptionAlgorithm: RSA_ECB, symmetricKey: symmetricKey, @@ -463,7 +463,7 @@ function testUsernameTokenTimestampWithSymmetricBindingAndX509Token() returns er x509Token: X509_PUBLIC_CERT_PATH_2 }; - xml securedEnvelope = check applySymmetricBinding(envelope, utSymmetricBinding); + xml securedEnvelope = check applySymmetricBinding(envelope, symmetricBinding); string envelopeString = securedEnvelope.toString(); byte[] signedData = check getSignatureData(securedEnvelope); @@ -504,14 +504,14 @@ function testSymmetricBindingWithOutboundConfig() returns error? { crypto:PrivateKey symmetricKey = check crypto:decodeRsaPrivateKeyFromKeyStore(keyStore, KEY_ALIAS, KEY_PASSWORD); crypto:PublicKey publicKey = check crypto:decodeRsaPublicKeyFromTrustStore(keyStore, KEY_ALIAS); - SymmetricBindingConfig utSymmetricBinding = { + SymmetricBindingConfig symmetricBinding = { signatureAlgorithm: RSA_SHA256, encryptionAlgorithm: RSA_ECB, symmetricKey: symmetricKey, servicePublicKey: serverPublicKey }; - xml securedEnvelope = check applySymmetricBinding(envelope, utSymmetricBinding); + xml securedEnvelope = check applySymmetricBinding(envelope, symmetricBinding); string envelopeString = securedEnvelope.toString(); OutboundSecurityConfig outboundConfig = { @@ -558,15 +558,15 @@ function testAsymmetricBindingWithSignature() returns error? { crypto:PrivateKey clientPrivateKey = check crypto:decodeRsaPrivateKeyFromKeyStore(clientKeyStore, KEY_ALIAS, KEY_PASSWORD); crypto:PublicKey clientPublicKey = check crypto:decodeRsaPublicKeyFromTrustStore(clientKeyStore, KEY_ALIAS); - AsymmetricBindingConfig utAsymmBinding = { + AsymmetricBindingConfig asymmetricBinding = { signatureAlgorithm: RSA_SHA256, signatureKey: clientPrivateKey, encryptionKey: serverPublicKey }; - xml securedEnvelope = check applyAsymmetricBinding(envelope, utAsymmBinding); + xml securedEnvelope = check applyAsymmetricBinding(envelope, asymmetricBinding); string envelopeString = securedEnvelope.toString(); byte[] signedData = check getSignatureData(securedEnvelope); - boolean validity = check crypto:verifyRsaSha256Signature((envelope//*).toString().toBytes(), signedData, clientPublicKey); + boolean validity = check verifyData((envelope//*).toString().toBytes(), signedData, clientPublicKey, RSA_SHA256); test:assertTrue(validity); assertSignatureWithoutX509(envelopeString); @@ -595,13 +595,13 @@ function testAsymmetricBindingWithX509Signature() returns error? { crypto:PrivateKey clientPrivateKey = check crypto:decodeRsaPrivateKeyFromKeyStore(clientKeyStore, KEY_ALIAS, KEY_PASSWORD); crypto:PublicKey clientPublicKey = check crypto:decodeRsaPublicKeyFromTrustStore(clientKeyStore, KEY_ALIAS); - AsymmetricBindingConfig utAsymmBinding = { + AsymmetricBindingConfig asymmetricBinding = { signatureAlgorithm: RSA_SHA256, signatureKey: clientPrivateKey, encryptionKey: serverPublicKey, x509Token: X509_PUBLIC_CERT_PATH_2 }; - xml securedEnvelope = check applyAsymmetricBinding(envelope, utAsymmBinding); + xml securedEnvelope = check applyAsymmetricBinding(envelope, asymmetricBinding); string envelopeString = securedEnvelope.toString(); byte[] signedData = check getSignatureData(securedEnvelope); @@ -634,12 +634,12 @@ function testAsymmetricBindingWithEncryption() returns error? { }; crypto:PrivateKey clientPrivateKey = check crypto:decodeRsaPrivateKeyFromKeyStore(clientKeyStore, KEY_ALIAS, KEY_PASSWORD); - AsymmetricBindingConfig utAsymmBinding = { + AsymmetricBindingConfig asymmetricBinding = { encryptionAlgorithm: RSA_ECB, signatureKey: clientPrivateKey, encryptionKey: serverPublicKey }; - xml securedEnvelope = check applyAsymmetricBinding(envelope, utAsymmBinding); + xml securedEnvelope = check applyAsymmetricBinding(envelope, asymmetricBinding); string envelopeString = securedEnvelope.toString(); byte[] encData = check getEncryptedData(securedEnvelope); @@ -673,14 +673,14 @@ function testAsymmetricBindingWithSignatureAndEncryption() returns error? { crypto:PrivateKey clientPrivateKey = check crypto:decodeRsaPrivateKeyFromKeyStore(clientKeyStore, KEY_ALIAS, KEY_PASSWORD); crypto:PublicKey clientPublicKey = check crypto:decodeRsaPublicKeyFromTrustStore(clientKeyStore, KEY_ALIAS); - AsymmetricBindingConfig utAsymmBinding = { + AsymmetricBindingConfig asymmetricBinding = { signatureAlgorithm: RSA_SHA256, encryptionAlgorithm: RSA_ECB, signatureKey: clientPrivateKey, encryptionKey: serverPublicKey }; - xml securedEnvelope = check applyAsymmetricBinding(envelope, utAsymmBinding); + xml securedEnvelope = check applyAsymmetricBinding(envelope, asymmetricBinding); string envelopeString = securedEnvelope.toString(); byte[] signedData = check getSignatureData(securedEnvelope); @@ -719,14 +719,14 @@ function testAsymmetricBindingWithX509SignatureAndEncryption() returns error? { crypto:PrivateKey clientPrivateKey = check crypto:decodeRsaPrivateKeyFromKeyStore(clientKeyStore, KEY_ALIAS, KEY_PASSWORD); crypto:PublicKey clientPublicKey = check crypto:decodeRsaPublicKeyFromTrustStore(clientKeyStore, KEY_ALIAS); - AsymmetricBindingConfig utAsymmBinding = { + AsymmetricBindingConfig asymmetricBinding = { signatureAlgorithm: RSA_SHA256, encryptionAlgorithm: RSA_ECB, signatureKey: clientPrivateKey, encryptionKey: serverPublicKey, x509Token: X509_PUBLIC_CERT_PATH_2 }; - xml securedEnvelope = check applyAsymmetricBinding(envelope, utAsymmBinding); + xml securedEnvelope = check applyAsymmetricBinding(envelope, asymmetricBinding); string envelopeString = securedEnvelope.toString(); byte[] signedData = check getSignatureData(securedEnvelope); @@ -772,14 +772,14 @@ function testUsernameTokenWithAsymmetricBindingAndX509() returns error? { crypto:PrivateKey clientPrivateKey = check crypto:decodeRsaPrivateKeyFromKeyStore(clientKeyStore, KEY_ALIAS, KEY_PASSWORD); crypto:PublicKey clientPublicKey = check crypto:decodeRsaPublicKeyFromTrustStore(clientKeyStore, KEY_ALIAS); - AsymmetricBindingConfig utAsymmBinding = { + AsymmetricBindingConfig asymmetricBinding = { signatureAlgorithm: RSA_SHA256, encryptionAlgorithm: RSA_ECB, signatureKey: clientPrivateKey, encryptionKey: serverPublicKey, x509Token: X509_PUBLIC_CERT_PATH_2 }; - xml securedEnvelope = check applyAsymmetricBinding(envelope, utAsymmBinding); + xml securedEnvelope = check applyAsymmetricBinding(envelope, asymmetricBinding); string envelopeString = securedEnvelope.toString(); byte[] signedData = check getSignatureData(securedEnvelope); @@ -827,14 +827,14 @@ function testUsernameTokenTimestampWithAsymmetricBindingAndX509() returns error? crypto:PrivateKey clientPrivateKey = check crypto:decodeRsaPrivateKeyFromKeyStore(clientKeyStore, KEY_ALIAS, KEY_PASSWORD); crypto:PublicKey clientPublicKey = check crypto:decodeRsaPublicKeyFromTrustStore(clientKeyStore, KEY_ALIAS); - AsymmetricBindingConfig utAsymmBinding = { + AsymmetricBindingConfig asymmetricBinding = { signatureAlgorithm: RSA_SHA256, encryptionAlgorithm: RSA_ECB, signatureKey: clientPrivateKey, encryptionKey: serverPublicKey, x509Token: X509_PUBLIC_CERT_PATH_2 }; - xml securedEnvelope = check applyAsymmetricBinding(envelope, utAsymmBinding); + xml securedEnvelope = check applyAsymmetricBinding(envelope, asymmetricBinding); string envelopeString = securedEnvelope.toString(); byte[] signedData = check getSignatureData(securedEnvelope); @@ -876,7 +876,7 @@ function testAsymmetricBindingWithOutboundConfig() returns error? { crypto:PrivateKey clientPrivateKey = check crypto:decodeRsaPrivateKeyFromKeyStore(clientKeyStore, KEY_ALIAS, KEY_PASSWORD); crypto:PublicKey clientPublicKey = check crypto:decodeRsaPublicKeyFromTrustStore(clientKeyStore, KEY_ALIAS); - AsymmetricBindingConfig utAsymmBinding = { + AsymmetricBindingConfig asymmetricBinding = { signatureAlgorithm: RSA_SHA256, encryptionAlgorithm: RSA_ECB, signatureKey: clientPrivateKey, @@ -890,7 +890,7 @@ function testAsymmetricBindingWithOutboundConfig() returns error? { decryptionKey: serverPrivateKey }; - xml securedEnvelope = check applyAsymmetricBinding(envelope, utAsymmBinding); + xml securedEnvelope = check applyAsymmetricBinding(envelope, asymmetricBinding); string envelopeString = securedEnvelope.toString(); crypto:PrivateKey|crypto:PublicKey? privateKey = outboundConfig.decryptionKey; if privateKey !is () { @@ -904,3 +904,114 @@ function testAsymmetricBindingWithOutboundConfig() returns error? { boolean validity = check crypto:verifyRsaSha256Signature((envelope//*).toString().toBytes(), signedData, clientPublicKey); test:assertTrue(validity); } + +@test:Config { + groups: ["username_token", "signature", "asymmetric_binding"] +} +function testAsymmetricBindingWithSignatureWithRsaSha1() returns error? { + xml envelope = + xml ` + + `; + xmlns "http://schemas.xmlsoap.org/soap/envelope/" as soap; + + crypto:KeyStore serverKeyStore = { + path: X509_KEY_STORE_PATH, + password: KEY_PASSWORD + }; + crypto:PublicKey serverPublicKey = check crypto:decodeRsaPublicKeyFromTrustStore(serverKeyStore, KEY_ALIAS); + + crypto:KeyStore clientKeyStore = { + path: X509_KEY_STORE_PATH_2, + password: KEY_PASSWORD + }; + crypto:PrivateKey clientPrivateKey = check crypto:decodeRsaPrivateKeyFromKeyStore(clientKeyStore, KEY_ALIAS, KEY_PASSWORD); + crypto:PublicKey clientPublicKey = check crypto:decodeRsaPublicKeyFromTrustStore(clientKeyStore, KEY_ALIAS); + + AsymmetricBindingConfig asymmetricBinding = { + signatureAlgorithm: RSA_SHA1, + signatureKey: clientPrivateKey, + encryptionKey: serverPublicKey + }; + xml securedEnvelope = check applyAsymmetricBinding(envelope, asymmetricBinding); + string envelopeString = securedEnvelope.toString(); + byte[] signedData = check getSignatureData(securedEnvelope); + boolean validity = check verifyData((envelope//*).toString().toBytes(), signedData, clientPublicKey, RSA_SHA1); + test:assertTrue(validity); + + assertSignatureWithoutX509(envelopeString); +} + +@test:Config { + groups: ["username_token", "signature", "asymmetric_binding"] +} +function testAsymmetricBindingWithSignatureWithRsaSha384() returns error? { + xml envelope = + xml ` + + `; + xmlns "http://schemas.xmlsoap.org/soap/envelope/" as soap; + + crypto:KeyStore serverKeyStore = { + path: X509_KEY_STORE_PATH, + password: KEY_PASSWORD + }; + crypto:PublicKey serverPublicKey = check crypto:decodeRsaPublicKeyFromTrustStore(serverKeyStore, KEY_ALIAS); + + crypto:KeyStore clientKeyStore = { + path: X509_KEY_STORE_PATH_2, + password: KEY_PASSWORD + }; + crypto:PrivateKey clientPrivateKey = check crypto:decodeRsaPrivateKeyFromKeyStore(clientKeyStore, KEY_ALIAS, KEY_PASSWORD); + crypto:PublicKey clientPublicKey = check crypto:decodeRsaPublicKeyFromTrustStore(clientKeyStore, KEY_ALIAS); + + AsymmetricBindingConfig asymmetricBinding = { + signatureAlgorithm: RSA_SHA384, + signatureKey: clientPrivateKey, + encryptionKey: serverPublicKey + }; + xml securedEnvelope = check applyAsymmetricBinding(envelope, asymmetricBinding); + string envelopeString = securedEnvelope.toString(); + byte[] signedData = check getSignatureData(securedEnvelope); + boolean validity = check verifyData((envelope//*).toString().toBytes(), signedData, clientPublicKey, RSA_SHA384); + test:assertTrue(validity); + + assertSignatureWithoutX509(envelopeString); +} + +@test:Config { + groups: ["username_token", "signature", "asymmetric_binding"] +} +function testAsymmetricBindingWithSignatureWithRsaSha512() returns error? { + xml envelope = + xml ` + + `; + xmlns "http://schemas.xmlsoap.org/soap/envelope/" as soap; + + crypto:KeyStore serverKeyStore = { + path: X509_KEY_STORE_PATH, + password: KEY_PASSWORD + }; + crypto:PublicKey serverPublicKey = check crypto:decodeRsaPublicKeyFromTrustStore(serverKeyStore, KEY_ALIAS); + + crypto:KeyStore clientKeyStore = { + path: X509_KEY_STORE_PATH_2, + password: KEY_PASSWORD + }; + crypto:PrivateKey clientPrivateKey = check crypto:decodeRsaPrivateKeyFromKeyStore(clientKeyStore, KEY_ALIAS, KEY_PASSWORD); + crypto:PublicKey clientPublicKey = check crypto:decodeRsaPublicKeyFromTrustStore(clientKeyStore, KEY_ALIAS); + + AsymmetricBindingConfig asymmetricBinding = { + signatureAlgorithm: RSA_SHA512, + signatureKey: clientPrivateKey, + encryptionKey: serverPublicKey + }; + xml securedEnvelope = check applyAsymmetricBinding(envelope, asymmetricBinding); + string envelopeString = securedEnvelope.toString(); + byte[] signedData = check getSignatureData(securedEnvelope); + boolean validity = check verifyData((envelope//*).toString().toBytes(), signedData, clientPublicKey, RSA_SHA512); + test:assertTrue(validity); + + assertSignatureWithoutX509(envelopeString); +} From 893d50106edddc00ceb14f520da6b140bf1cbd5e Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Tue, 3 Oct 2023 16:34:58 +0530 Subject: [PATCH 103/189] [Automated] Update the native jar versions --- ballerina/Dependencies.toml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index 8fe54a9..d942a5e 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -101,6 +101,9 @@ dependencies = [ {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "lang.value"} ] +modules = [ + {org = "ballerina", packageName = "io", moduleName = "io"} +] [[package]] org = "ballerina" @@ -280,6 +283,7 @@ version = "0.2.0" dependencies = [ {org = "ballerina", name = "crypto"}, {org = "ballerina", name = "http"}, + {org = "ballerina", name = "io"}, {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "mime"}, {org = "ballerina", name = "regex"}, From 247f60f8c5f3a8818bb3bc43e94ac2bb9776ce62 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Tue, 3 Oct 2023 16:36:44 +0530 Subject: [PATCH 104/189] [Automated] Update the native jar versions --- ballerina/Dependencies.toml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index d942a5e..8fe54a9 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -101,9 +101,6 @@ dependencies = [ {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "lang.value"} ] -modules = [ - {org = "ballerina", packageName = "io", moduleName = "io"} -] [[package]] org = "ballerina" @@ -283,7 +280,6 @@ version = "0.2.0" dependencies = [ {org = "ballerina", name = "crypto"}, {org = "ballerina", name = "http"}, - {org = "ballerina", name = "io"}, {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "mime"}, {org = "ballerina", name = "regex"}, From 282eb88c9d3371e0f4d3e89596a0a165358c295e Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Tue, 3 Oct 2023 16:58:07 +0530 Subject: [PATCH 105/189] Add test cases for transport binding security --- .../modules/soap11/tests/soap11_client_test.bal | 17 ++++++++++++++++- .../modules/soap12/tests/soap12_client_test.bal | 13 +++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/ballerina/modules/soap11/tests/soap11_client_test.bal b/ballerina/modules/soap11/tests/soap11_client_test.bal index 41cd6b0..f6a3dd5 100644 --- a/ballerina/modules/soap11/tests/soap11_client_test.bal +++ b/ballerina/modules/soap11/tests/soap11_client_test.bal @@ -99,7 +99,22 @@ function testSendReceive11WithHeaders() returns error? { groups: ["soap11"] } function testTransportBindingError() returns error? { - Client|Error soapClient = new ("http://www.dneonline.com/calculator.asmx?WSDL", inboundSecurity = TRANSPORT_BINDING); + Client|Error soapClient = new ("http://www.dneonline.com/calculator.asmx?WSDL", + inboundSecurity = TRANSPORT_BINDING + ); + test:assertTrue(soapClient is Error); + test:assertEquals((soapClient).message(), SOAP_CLIENT_ERROR); +} + +@test:Config { + groups: ["soap11"] +} +function testTransportBindingError2() returns error? { + Client|Error soapClient = new ("http://www.dneonline.com/calculator.asmx?WSDL", + inboundSecurity = [ + TRANSPORT_BINDING + ] + ); test:assertTrue(soapClient is Error); test:assertEquals((soapClient).message(), SOAP_CLIENT_ERROR); } diff --git a/ballerina/modules/soap12/tests/soap12_client_test.bal b/ballerina/modules/soap12/tests/soap12_client_test.bal index d5abf45..414db04 100644 --- a/ballerina/modules/soap12/tests/soap12_client_test.bal +++ b/ballerina/modules/soap12/tests/soap12_client_test.bal @@ -161,6 +161,19 @@ function testTransportBindingError() returns error? { test:assertEquals((soapClient).message(), SOAP_CLIENT_ERROR); } +@test:Config { + groups: ["soap12"] +} +function testTransportBindingError2() returns error? { + Client|Error soapClient = new ("http://www.dneonline.com/calculator.asmx?WSDL", + inboundSecurity = [ + TRANSPORT_BINDING + ] + ); + test:assertTrue(soapClient is Error); + test:assertEquals((soapClient).message(), SOAP_CLIENT_ERROR); +} + @test:Config { groups: ["soap12", "send_receive"] } From 9e98facf04637b0d736a778bd4cb419ecc68a531 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Tue, 3 Oct 2023 16:59:39 +0530 Subject: [PATCH 106/189] Add test cases for SOAP envelopes with ws securities --- .../soap11/tests/soap11_client_test.bal | 188 ++++++++++++++++-- 1 file changed, 173 insertions(+), 15 deletions(-) diff --git a/ballerina/modules/soap11/tests/soap11_client_test.bal b/ballerina/modules/soap11/tests/soap11_client_test.bal index f6a3dd5..3f58960 100644 --- a/ballerina/modules/soap11/tests/soap11_client_test.bal +++ b/ballerina/modules/soap11/tests/soap11_client_test.bal @@ -15,6 +15,7 @@ // under the License. import soap.wssec; +import ballerina/crypto; import ballerina/mime; import ballerina/test; @@ -22,15 +23,16 @@ const wssec:TransportBindingConfig TRANSPORT_BINDING = "TransportBinding"; const wssec:NoPolicy NO_POLICY = "NoPolicy"; const string KEY_ALIAS = "wss40"; const string KEY_PASSWORD = "security"; +const string KEY_STORE_PATH = "modules/wssec/tests/resources/wss40.p12"; const string X509_PUBLIC_CERT_PATH = "modules/wssec/tests/resources/x509_certificate.crt"; const string X509_PUBLIC_CERT_PATH_2 = "modules/wssec/tests/resources/x509_certificate_2.crt"; const string X509_KEY_STORE_PATH = "modules/wssec/tests/resources/x509_certificate.p12"; const string X509_KEY_STORE_PATH_2 = "modules/wssec/tests/resources/x509_certificate_2.p12"; @test:Config { - groups: ["soap11", "send_only"] + groups: ["soap11", "send_only"] } -function testSendOnly11() returns error? { +function testSendOnly() returns error? { xml body = xml ` @@ -47,9 +49,9 @@ function testSendOnly11() returns error? { } @test:Config { - groups: ["soap11", "send_receive"] + groups: ["soap11", "send_receive"] } -function testSendReceive11() returns error? { +function testSendReceive() returns error? { Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL", { inboundSecurity: NO_POLICY, @@ -73,9 +75,9 @@ function testSendReceive11() returns error? { } @test:Config { - groups: ["soap11", "send_receive"] + groups: ["soap11", "send_receive"] } -function testSendReceive11WithHeaders() returns error? { +function testSendReceiveWithHeaders() returns error? { xml body = xml ` @@ -90,37 +92,37 @@ function testSendReceive11WithHeaders() returns error? { Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL"); xml|mime:Entity[] response = check soapClient->sendReceive(body, "http://tempuri.org/Add", - {foo: ["bar1", "bar2"]}); + {foo: ["bar1", "bar2"]}); xml expected = xml `5`; test:assertEquals(response, expected); } @test:Config { - groups: ["soap11"] + groups: ["soap11"] } function testTransportBindingError() returns error? { - Client|Error soapClient = new ("http://www.dneonline.com/calculator.asmx?WSDL", - inboundSecurity = TRANSPORT_BINDING + Client|Error soapClient = new ("http://www.dneonline.com/calculator.asmx?WSDL", + inboundSecurity = TRANSPORT_BINDING ); test:assertTrue(soapClient is Error); test:assertEquals((soapClient).message(), SOAP_CLIENT_ERROR); } @test:Config { - groups: ["soap11"] + groups: ["soap11"] } function testTransportBindingError2() returns error? { Client|Error soapClient = new ("http://www.dneonline.com/calculator.asmx?WSDL", - inboundSecurity = [ - TRANSPORT_BINDING - ] + inboundSecurity = [ + TRANSPORT_BINDING + ] ); test:assertTrue(soapClient is Error); test:assertEquals((soapClient).message(), SOAP_CLIENT_ERROR); } @test:Config { - groups: ["soap11", "send_receive"] + groups: ["soap11", "send_receive"] } function testSendReceiveError() returns error? { Client soapClient = check new ("http://www.dneonline.com/invalidcalculator.asmx?WSDL"); @@ -138,3 +140,159 @@ function testSendReceiveError() returns error? { test:assertTrue(response is Error); test:assertEquals((response).message(), SOAP_RESPONSE_ERROR); } + +@test:Config { + groups: ["soap11", "send_receive"] +} +function testSendReceiveWithTimestampTokenSecurity() returns error? { + Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL", + { + inboundSecurity: [ + { + timeToLive: 600 + } + ] + } + ); + xml body = xml ` + + + 2 + 3 + + + `; + xml|mime:Entity[] response = check soapClient->sendReceive(body, "http://tempuri.org/Add"); + xml expected = xml `soap:MustUnderstandSystem.Web.Services.Protocols.SoapHeaderException: SOAP header Security was not understood. + at System.Web.Services.Protocols.SoapHeaderHandling.SetHeaderMembers(SoapHeaderCollection headers, Object target, SoapHeaderMapping[] mappings, SoapHeaderDirection direction, Boolean client) + at System.Web.Services.Protocols.SoapServerProtocol.CreateServerInstance() + at System.Web.Services.Protocols.WebServiceHandler.Invoke() + at System.Web.Services.Protocols.WebServiceHandler.CoreProcessRequest()`; + test:assertEquals(response, expected); +} + +@test:Config { + groups: ["soap11", "send_receive"] +} +function testSendReceiveWithUsernameTokenSecurity() returns error? { + Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL", + { + inboundSecurity: { + username: "user", + password: "password", + passwordType: wssec:TEXT + }, + outboundSecurity: {} + } + ); + xml body = xml ` + + + 2 + 3 + + + `; + xml|mime:Entity[] response = check soapClient->sendReceive(body, "http://tempuri.org/Add"); + xml expected = xml `soap:MustUnderstandSystem.Web.Services.Protocols.SoapHeaderException: SOAP header Security was not understood. + at System.Web.Services.Protocols.SoapHeaderHandling.SetHeaderMembers(SoapHeaderCollection headers, Object target, SoapHeaderMapping[] mappings, SoapHeaderDirection direction, Boolean client) + at System.Web.Services.Protocols.SoapServerProtocol.CreateServerInstance() + at System.Web.Services.Protocols.WebServiceHandler.Invoke() + at System.Web.Services.Protocols.WebServiceHandler.CoreProcessRequest()`; + test:assertEquals(response, expected); +} + +@test:Config { + groups: ["soap11", "send_receive"] +} +function testSendReceiveWithAsymmetricBindingSecurity() returns error? { + crypto:KeyStore serverKeyStore = { + path: X509_KEY_STORE_PATH, + password: KEY_PASSWORD + }; + + crypto:PublicKey serverPublicKey = check crypto:decodeRsaPublicKeyFromTrustStore(serverKeyStore, KEY_ALIAS); + + crypto:KeyStore clientKeyStore = { + path: X509_KEY_STORE_PATH_2, + password: KEY_PASSWORD + }; + crypto:PrivateKey clientPrivateKey = check crypto:decodeRsaPrivateKeyFromKeyStore(clientKeyStore, KEY_ALIAS, KEY_PASSWORD); + + Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL", + { + inboundSecurity: { + signatureAlgorithm: wssec:RSA_SHA256, + encryptionAlgorithm: wssec:RSA_ECB, + signatureKey: clientPrivateKey, + encryptionKey: serverPublicKey + } + } + ); + xml body = xml ` + + + 2 + 3 + + + `; + xml|mime:Entity[] response = check soapClient->sendReceive(body, "http://tempuri.org/Add"); + xml expected = xml `soap:MustUnderstandSystem.Web.Services.Protocols.SoapHeaderException: SOAP header Security was not understood. + at System.Web.Services.Protocols.SoapHeaderHandling.SetHeaderMembers(SoapHeaderCollection headers, Object target, SoapHeaderMapping[] mappings, SoapHeaderDirection direction, Boolean client) + at System.Web.Services.Protocols.SoapServerProtocol.CreateServerInstance() + at System.Web.Services.Protocols.WebServiceHandler.Invoke() + at System.Web.Services.Protocols.WebServiceHandler.CoreProcessRequest()`; + test:assertEquals(response, expected); +} + +@test:Config { + groups: ["soap11", "send_receive"] +} +function testSendReceiveWithSymmetricBindingSecurity() returns error? { + crypto:KeyStore serverKeyStore = { + path: X509_KEY_STORE_PATH, + password: KEY_PASSWORD + }; + crypto:PublicKey serverPublicKey = check crypto:decodeRsaPublicKeyFromTrustStore(serverKeyStore, KEY_ALIAS); + + crypto:KeyStore keyStore = { + path: KEY_STORE_PATH, + password: KEY_PASSWORD + }; + crypto:PrivateKey symmetricKey = check crypto:decodeRsaPrivateKeyFromKeyStore(keyStore, KEY_ALIAS, KEY_PASSWORD); + + Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL", + { + inboundSecurity: { + signatureAlgorithm: wssec:RSA_SHA256, + encryptionAlgorithm: wssec:RSA_ECB, + symmetricKey: symmetricKey, + servicePublicKey: serverPublicKey + } + } + ); + xml body = xml ` + + + 2 + 3 + + + `; + xml|mime:Entity[] response = check soapClient->sendReceive(body, "http://tempuri.org/Add"); + xml expected = xml `soap:MustUnderstandSystem.Web.Services.Protocols.SoapHeaderException: SOAP header Security was not understood. + at System.Web.Services.Protocols.SoapHeaderHandling.SetHeaderMembers(SoapHeaderCollection headers, Object target, SoapHeaderMapping[] mappings, SoapHeaderDirection direction, Boolean client) + at System.Web.Services.Protocols.SoapServerProtocol.CreateServerInstance() + at System.Web.Services.Protocols.WebServiceHandler.Invoke() + at System.Web.Services.Protocols.WebServiceHandler.CoreProcessRequest()`; + test:assertEquals(response, expected); +} From 812cdc7e37f8924892a87d89e1f60640dd0d7d33 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Tue, 3 Oct 2023 17:14:34 +0530 Subject: [PATCH 107/189] Remove unnecessary code segments and APIs --- ballerina/modules/wssec/document.bal | 4 --- ballerina/modules/wssec/encryption.bal | 35 +++---------------- ballerina/modules/wssec/signature.bal | 4 --- .../modules/wssec/ws_security_methods.bal | 5 +-- 4 files changed, 6 insertions(+), 42 deletions(-) diff --git a/ballerina/modules/wssec/document.bal b/ballerina/modules/wssec/document.bal index 62b8694..5a284a6 100644 --- a/ballerina/modules/wssec/document.bal +++ b/ballerina/modules/wssec/document.bal @@ -27,10 +27,6 @@ class Document { } } - public function getDocument() returns string|Error = @java:Method { - 'class: "org.wssec.DocumentBuilder" - } external; - public function getEncryptedData() returns byte[] = @java:Method { 'class: "org.wssec.DocumentBuilder" } external; diff --git a/ballerina/modules/wssec/encryption.bal b/ballerina/modules/wssec/encryption.bal index b531609..e673b54 100644 --- a/ballerina/modules/wssec/encryption.bal +++ b/ballerina/modules/wssec/encryption.bal @@ -25,31 +25,16 @@ class Encryption { } function encryptData(string dataString, EncryptionAlgorithm encryptionAlgorithm, - byte[]|crypto:PublicKey|crypto:PrivateKey key, byte[]? initialVector = ()) + crypto:PublicKey|crypto:PrivateKey key) returns byte[]|Error { byte[] data = dataString.toBytes(); do { match encryptionAlgorithm { - AES_128|AES_192|AES_256 if key is byte[] && initialVector is byte[] => { - return check crypto:encryptAesCbc(data, key, initialVector); - } - AES_128_ECB|AES_192_ECB|AES_256_ECB if key is byte[] && initialVector is byte[] => { - return check crypto:encryptAesEcb(data, key); - } - AES_128_GCM|AES_192_GCM|AES_256_GCM if key is byte[] && initialVector is byte[] => { - return check crypto:encryptAesGcm(data, key, initialVector, crypto:NONE); - } - RSA_ECB if key is crypto:PublicKey|crypto:PrivateKey => { + RSA_ECB => { return check crypto:encryptRsaEcb(data, key); } - _ if key !is crypto:PublicKey|crypto:PrivateKey => { - return error Error("Invalid/Missing key!"); - } - _ if initialVector !is byte[] => { - return error Error("Initialization vector is empty!"); - } _ => { - return error Error("Encryption Algorithm is not supported"); + return error Error("Invalid/Missing key!"); } } } on fail var e { @@ -58,17 +43,11 @@ class Encryption { } public function decryptData(byte[] cipherText, EncryptionAlgorithm encryptionAlgorithm, - byte[]|crypto:PublicKey|crypto:PrivateKey key, byte[]? initialVector = ()) + crypto:PublicKey|crypto:PrivateKey key) returns byte[]|Error { do { match encryptionAlgorithm { - AES_128|AES_192|AES_256 if key is byte[] && initialVector is byte[] => { - return check crypto:decryptAesCbc(cipherText, key, initialVector); - } - AES_128_GCM|AES_192_GCM|AES_256_GCM if key is byte[] && initialVector is byte[]=> { - return check crypto:decryptAesGcm(cipherText, key, initialVector, crypto:NONE); - } - RSA_ECB if key is crypto:PublicKey|crypto:PrivateKey => { + RSA_ECB => { return check crypto:decryptRsaEcb(cipherText, key); } _ => { @@ -91,10 +70,6 @@ class Encryption { public function getEncryptedKeyElements(byte[] encryptedKey) returns string|Error = @java:Method { 'class: "org.wssec.Encryption" } external; - - public function getEncryptedData() returns byte[] = @java:Method { - 'class: "org.wssec.Encryption" - } external; } function newEncryption() returns handle = @java:Constructor { diff --git a/ballerina/modules/wssec/signature.bal b/ballerina/modules/wssec/signature.bal index a801573..1023f5a 100644 --- a/ballerina/modules/wssec/signature.bal +++ b/ballerina/modules/wssec/signature.bal @@ -76,10 +76,6 @@ class Signature { public function setSignatureValue(byte[] signatureValue) = @java:Method { 'class: "org.wssec.Signature" } external; - - public function getSignatureValue() returns byte[] = @java:Method { - 'class: "org.wssec.Signature" - } external; } function newSignature() returns handle = @java:Constructor { diff --git a/ballerina/modules/wssec/ws_security_methods.bal b/ballerina/modules/wssec/ws_security_methods.bal index 26e5a96..502d60a 100644 --- a/ballerina/modules/wssec/ws_security_methods.bal +++ b/ballerina/modules/wssec/ws_security_methods.bal @@ -28,7 +28,7 @@ function addSecurityHeader(Document document) returns WSSecurityHeader|Error { } public function decryptData(byte[] cipherText, EncryptionAlgorithm encryptionAlgorithm, - byte[]|crypto:PublicKey|crypto:PrivateKey key) returns byte[]|Error { + crypto:PublicKey|crypto:PrivateKey key) returns byte[]|Error { Encryption encrypt = check new (); return encrypt.decryptData(cipherText, encryptionAlgorithm, key); } @@ -64,9 +64,6 @@ function applyEncryptedKey(string envelopeString, crypto:PrivateKey symmetricKey else if securedEnvelope.includesMatch(re``) { securedEnvelope = regex:replace(securedEnvelope, string``, replace); } - else if securedEnvelope.includesMatch(re`.*`) { - securedEnvelope = regex:replace(securedEnvelope, string`.*`, replace); - } return securedEnvelope; } on fail var e { return error Error(e.message()); From 2a322611aa429eec602666f0a49bb9f541de9f1a Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Tue, 3 Oct 2023 17:15:02 +0530 Subject: [PATCH 108/189] Update error handling in SOAP clients --- ballerina/modules/soap11/soap11.bal | 8 ++------ ballerina/modules/soap12/soap12.bal | 16 ++++++++-------- 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/ballerina/modules/soap11/soap11.bal b/ballerina/modules/soap11/soap11.bal index 51c6765..e2f015e 100644 --- a/ballerina/modules/soap11/soap11.bal +++ b/ballerina/modules/soap11/soap11.bal @@ -86,15 +86,11 @@ public client class Client { # + return - If successful, returns `nil`. Else, returns an error remote function sendOnly(xml|mime:Entity[] body, string action, map headers = {}) returns Error? { - if body is xml { - do { + do { + if body is xml { xml applySecurityPoliciesResult = check common:applySecurityPolicies(self.inboundSecurity, body); return check common:sendOnly(applySecurityPoliciesResult, self.soapClient, action, headers, false); - } on fail var e { - return error Error(e.message()); } - } - do { return check common:sendOnly(body, self.soapClient, action, headers, false); } on fail var e { return error Error(e.message()); diff --git a/ballerina/modules/soap12/soap12.bal b/ballerina/modules/soap12/soap12.bal index 6f4275e..bf9954b 100644 --- a/ballerina/modules/soap12/soap12.bal +++ b/ballerina/modules/soap12/soap12.bal @@ -85,15 +85,15 @@ public client class Client { # + return - If successful, returns `nil`. Else, returns an error remote function sendOnly(xml|mime:Entity[] body, string? action = (), map headers = {}) returns Error? { - if body is xml { - do { - xml applySecurityPoliciesResult = check common:applySecurityPolicies(self.inboundSecurity, body); - return check common:sendOnly(applySecurityPoliciesResult, self.soapClient, action, headers); - } on fail var e { - return error Error(e.message()); - } - } do { + if body is xml { + do { + xml applySecurityPoliciesResult = check common:applySecurityPolicies(self.inboundSecurity, body); + return check common:sendOnly(applySecurityPoliciesResult, self.soapClient, action, headers); + } on fail var e { + return error Error(e.message()); + } + } return check common:sendOnly(body, self.soapClient, action, headers); } on fail var e { return error Error(e.message()); From b65d5c5fede69b434c757caed257f3b6c9839187 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Wed, 4 Oct 2023 09:38:12 +0530 Subject: [PATCH 109/189] [Automated] Update the native jar versions --- ballerina/Dependencies.toml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index 8fe54a9..d942a5e 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -101,6 +101,9 @@ dependencies = [ {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "lang.value"} ] +modules = [ + {org = "ballerina", packageName = "io", moduleName = "io"} +] [[package]] org = "ballerina" @@ -280,6 +283,7 @@ version = "0.2.0" dependencies = [ {org = "ballerina", name = "crypto"}, {org = "ballerina", name = "http"}, + {org = "ballerina", name = "io"}, {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "mime"}, {org = "ballerina", name = "regex"}, From d6369126600dba67c3b58a844f77a0d615f2d154 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Wed, 4 Oct 2023 10:08:38 +0530 Subject: [PATCH 110/189] [Automated] Update the native jar versions --- ballerina/Dependencies.toml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index d942a5e..8fe54a9 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -101,9 +101,6 @@ dependencies = [ {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "lang.value"} ] -modules = [ - {org = "ballerina", packageName = "io", moduleName = "io"} -] [[package]] org = "ballerina" @@ -283,7 +280,6 @@ version = "0.2.0" dependencies = [ {org = "ballerina", name = "crypto"}, {org = "ballerina", name = "http"}, - {org = "ballerina", name = "io"}, {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "mime"}, {org = "ballerina", name = "regex"}, From 3dba1970db027f979d01b0af506924529fbb88b3 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Wed, 4 Oct 2023 10:17:46 +0530 Subject: [PATCH 111/189] [Automated] Update the native jar versions --- ballerina/Dependencies.toml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index 8fe54a9..d942a5e 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -101,6 +101,9 @@ dependencies = [ {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "lang.value"} ] +modules = [ + {org = "ballerina", packageName = "io", moduleName = "io"} +] [[package]] org = "ballerina" @@ -280,6 +283,7 @@ version = "0.2.0" dependencies = [ {org = "ballerina", name = "crypto"}, {org = "ballerina", name = "http"}, + {org = "ballerina", name = "io"}, {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "mime"}, {org = "ballerina", name = "regex"}, From ffd57a4af64ae1e2bb27c822dc3e78cf11fc4cec Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Wed, 4 Oct 2023 10:18:55 +0530 Subject: [PATCH 112/189] [Automated] Update the native jar versions --- ballerina/Dependencies.toml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index d942a5e..8fe54a9 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -101,9 +101,6 @@ dependencies = [ {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "lang.value"} ] -modules = [ - {org = "ballerina", packageName = "io", moduleName = "io"} -] [[package]] org = "ballerina" @@ -283,7 +280,6 @@ version = "0.2.0" dependencies = [ {org = "ballerina", name = "crypto"}, {org = "ballerina", name = "http"}, - {org = "ballerina", name = "io"}, {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "mime"}, {org = "ballerina", name = "regex"}, From 3680256c8b34895f33cb6f4d30200b67597445c2 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Wed, 4 Oct 2023 14:01:45 +0530 Subject: [PATCH 113/189] Apply changes to adhere code coventions --- ballerina/modules/common/error.bal | 1 + ballerina/modules/common/soap_utils.bal | 25 +++++++++---------- ballerina/modules/soap11/soap11.bal | 6 ++--- ballerina/modules/soap12/soap12.bal | 8 +++--- ballerina/modules/wssec/types.bal | 17 ++----------- .../modules/wssec/ws_security_methods.bal | 23 ++++++++++------- .../main/java/org/wssec/WsSecurityHeader.java | 6 +++-- .../main/java/org/wssec/WsSecurityUtils.java | 7 ++---- 8 files changed, 43 insertions(+), 50 deletions(-) diff --git a/ballerina/modules/common/error.bal b/ballerina/modules/common/error.bal index 87e420b..0be7565 100644 --- a/ballerina/modules/common/error.bal +++ b/ballerina/modules/common/error.bal @@ -18,3 +18,4 @@ public type Error distinct error; const SOAP_RESPONSE_ERROR = "Failed to create SOAP response."; +const INVALID_PROTOCOL_ERROR = "Invalid protocol detected: Please use the `https` protocol instead of `http`."; diff --git a/ballerina/modules/common/soap_utils.bal b/ballerina/modules/common/soap_utils.bal index 9f3b472..c1b27af 100644 --- a/ballerina/modules/common/soap_utils.bal +++ b/ballerina/modules/common/soap_utils.bal @@ -24,11 +24,11 @@ public function validateTransportBindingPolicy(ClientConfig config) returns Erro if config.httpConfig.secureSocket is () { wssec:InboundSecurityConfig|wssec:InboundSecurityConfig[] securityPolicy = config.inboundSecurity; if securityPolicy is wssec:TransportBindingConfig { - return error Error("Invalid protocol detected: Please use the `https` protocol instead of `http`."); + return error Error(INVALID_PROTOCOL_ERROR); } else if securityPolicy is wssec:InboundSecurityConfig[] { foreach wssec:InboundSecurityConfig policy in securityPolicy { if policy is wssec:TransportBindingConfig { - return error Error("Invalid protocol detected: Please use the `https` protocol instead of `http`."); + return error Error(INVALID_PROTOCOL_ERROR); } } } @@ -50,8 +50,8 @@ public function retrieveHttpClientConfig(ClientConfig config) returns http:Clien }; } -public function applySecurityPolicies(wssec:InboundSecurityConfig|wssec:InboundSecurityConfig[] inboundSecurity, xml envelope) - returns xml|wssec:Error { +public function applySecurityPolicies(wssec:InboundSecurityConfig|wssec:InboundSecurityConfig[] inboundSecurity, + xml envelope) returns xml|wssec:Error { wssec:InboundSecurityConfig|wssec:InboundSecurityConfig[] securityPolicy = inboundSecurity; xml securedEnvelope; if securityPolicy is wssec:InboundSecurityConfig { @@ -74,7 +74,8 @@ public function applySecurityPolicies(wssec:InboundSecurityConfig|wssec:InboundS return securedEnvelope; } -public function applyOutboundConfig(wssec:OutboundSecurityConfig outboundSecurity, xml envelope) returns xml|wssec:Error|Error { +public function applyOutboundConfig(wssec:OutboundSecurityConfig outboundSecurity, xml envelope) + returns xml|wssec:Error|Error { xmlns "http://schemas.xmlsoap.org/soap/envelope/" as soap; xml soapEnvelope = envelope; do { @@ -85,7 +86,8 @@ public function applyOutboundConfig(wssec:OutboundSecurityConfig outboundSecurit byte[] encData = check wssec:getEncryptedData(soapEnvelope); byte[] decryptDataResult = check wssec:decryptData(encData, encryptionAlgorithm, clientPrivateKey); string decryptedBody = "" + check string:fromBytes(decryptDataResult) + ""; - string decryptedEnv = regex:replace(soapEnvelope.toString(), string `.*`, decryptedBody); + string decryptedEnv = regex:replace(soapEnvelope.toString(), string `.*`, + decryptedBody); soapEnvelope = check xml:fromString(decryptedEnv); } } @@ -117,9 +119,8 @@ public function sendReceive(xml|mime:Entity[] body, http:Client httpClient, stri } else { req = createSoap11HttpRequest(body, soapAction, headers); } - http:Response response; do { - response = check httpClient->post(path, req); + http:Response response = check httpClient->post(path, req); if soap12 { return check createSoap12Response(response); } @@ -137,10 +138,9 @@ public function sendOnly(xml|mime:Entity[] body, http:Client httpClient, string? } else { req = createSoap11HttpRequest(body, soapAction, headers); } - do { - http:Response _ = check httpClient->post(path, req); - } on fail var err { - return error Error(SOAP_RESPONSE_ERROR, err); + http:Response|http:ClientError response = httpClient->post(path, req); + if response is http:ClientError { + return error Error(response.message()); } } @@ -188,7 +188,6 @@ function createSoap12HttpRequest(xml|mime:Entity[] body, string? soapAction, function createSoap12Response(http:Response response) returns xml|error { xml payload = check response.getXmlPayload(); xmlns "http://www.w3.org/2003/05/soap-envelope" as soap12; - return payload/; } diff --git a/ballerina/modules/soap11/soap11.bal b/ballerina/modules/soap11/soap11.bal index e2f015e..bb89ce8 100644 --- a/ballerina/modules/soap11/soap11.bal +++ b/ballerina/modules/soap11/soap11.bal @@ -65,7 +65,8 @@ public client class Client { return check common:applyOutboundConfig(outboundSecurity, response); } } on fail var e { - return error Error("Outbound security configurations do not match with the SOAP response. ", e.cause()); + return error Error("Outbound security configurations do not match with the SOAP response. ", + e.cause()); } } return check common:sendReceive(body, self.soapClient, action, headers, false); @@ -84,8 +85,7 @@ public client class Client { # + action - SOAP action as a `string` # + headers - SOAP headers as a `map` # + return - If successful, returns `nil`. Else, returns an error - remote function sendOnly(xml|mime:Entity[] body, string action, - map headers = {}) returns Error? { + remote function sendOnly(xml|mime:Entity[] body, string action, map headers = {}) returns Error? { do { if body is xml { xml applySecurityPoliciesResult = check common:applySecurityPolicies(self.inboundSecurity, body); diff --git a/ballerina/modules/soap12/soap12.bal b/ballerina/modules/soap12/soap12.bal index bf9954b..1c56975 100644 --- a/ballerina/modules/soap12/soap12.bal +++ b/ballerina/modules/soap12/soap12.bal @@ -13,10 +13,11 @@ // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. +import soap.common; +import soap.wssec; + import ballerina/http; import ballerina/mime; -import soap.wssec; -import soap.common; xmlns "http://www.w3.org/2003/05/soap-envelope" as soap; @@ -63,7 +64,8 @@ public client class Client { return check common:applyOutboundConfig(outboundSecurity, response); } } on fail var e { - return error Error("Outbound security configurations do not match with the SOAP response. ", e.cause()); + return error Error("Outbound security configurations do not match with the SOAP response. ", + e.cause()); } return response; } diff --git a/ballerina/modules/wssec/types.bal b/ballerina/modules/wssec/types.bal index a582f6e..a7eb41f 100644 --- a/ballerina/modules/wssec/types.bal +++ b/ballerina/modules/wssec/types.bal @@ -25,22 +25,9 @@ public enum SignatureAlgorithm { RSA_SHA1 = "http://www.w3.org/2000/09/xmldsig#rsa-sha1", RSA_SHA256 = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256", RSA_SHA384 = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha384", - RSA_SHA512 = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha512", - HMAC_SHA1 = "http://www.w3.org/2000/09/xmldsig#hmac-sha1", - HMAC_SHA256 = "http://www.w3.org/2001/04/xmldsig-more#hmac-sha256", - HMAC_SHA384 = "http://www.w3.org/2001/04/xmldsig-more#hmac-sha384", - HMAC_SHA512 = "http://www.w3.org/2001/04/xmldsig-more#hmac-sha512" + RSA_SHA512 = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha512" } public enum EncryptionAlgorithm { - RSA_ECB = "http://www.w3.org/2001/04/xmlenc#rsa-1_5", - AES_128 = "http://www.w3.org/2001/04/xmlenc#aes128-cbc", - AES_192 = "http://www.w3.org/2001/04/xmlenc#aes192-cbc", - AES_256 = "http://www.w3.org/2001/04/xmlenc#aes256-cbc", - AES_128_ECB = "http://www.w3.org/2009/xmlenc11#aes128-ecb", - AES_192_ECB = "http://www.w3.org/2009/xmlenc11#aes192-ecb", - AES_256_ECB = "http://www.w3.org/2009/xmlenc11#aes256-ecb", - AES_128_GCM = "http://www.w3.org/2009/xmlenc11#aes128-gcm", - AES_192_GCM = "http://www.w3.org/2009/xmlenc11#aes192-gcm", - AES_256_GCM = "http://www.w3.org/2009/xmlenc11#aes256-gcm" + RSA_ECB = "http://www.w3.org/2001/04/xmlenc#rsa-1_5" } diff --git a/ballerina/modules/wssec/ws_security_methods.bal b/ballerina/modules/wssec/ws_security_methods.bal index 502d60a..e479b65 100644 --- a/ballerina/modules/wssec/ws_security_methods.bal +++ b/ballerina/modules/wssec/ws_security_methods.bal @@ -18,6 +18,7 @@ import ballerina/regex; xmlns "http://schemas.xmlsoap.org/soap/envelope/" as soap; xmlns "http://www.w3.org/2000/09/xmldsig#" as ds; + function addSecurityHeader(Document document) returns WSSecurityHeader|Error { WSSecurityHeader wsSecHeader = check new (document); Error? insertHeader = wsSecHeader.insertSecHeader(); @@ -51,18 +52,21 @@ function addEncryption(Encryption encrypt, string encryptionAlgorithm, byte[] en return encrypt; } -function applyEncryptedKey(string envelopeString, crypto:PrivateKey symmetricKey, crypto:PublicKey encryptKey) returns string|Error { +function applyEncryptedKey(string envelopeString, crypto:PrivateKey symmetricKey, crypto:PublicKey encryptKey) + returns string|Error { string securedEnvelope = envelopeString; do { Encryption encryption = check new (); byte[] encryptedKey = check crypto:encryptRsaEcb(symmetricKey.toBalString().toBytes(), encryptKey); string encryptedKeyElements = check encryption.getEncryptedKeyElements(encryptedKey); string replace = regex:replace(encryptedKeyElements, string `<`, "<"); - if securedEnvelope.includesMatch(re``) { - securedEnvelope = regex:replace(securedEnvelope, string``, replace); + string:RegExp securityToken = + re ``; + if securedEnvelope.includesMatch(securityToken) { + securedEnvelope = regex:replace(securedEnvelope, securityToken.toString(), replace); } - else if securedEnvelope.includesMatch(re``) { - securedEnvelope = regex:replace(securedEnvelope, string``, replace); + else if securedEnvelope.includesMatch(re ``) { + securedEnvelope = regex:replace(securedEnvelope, string ``, replace); } return securedEnvelope; } on fail var e { @@ -145,7 +149,7 @@ public function applySymmetricBinding(xml envelope, *SymmetricBindingConfig symm signedData); WsSecurity wsSecurity = new; securedEnvelope = check wsSecurity.applySignatureOnlyPolicy(wsSecurityHeader, signatureResult, - symmetricBinding.x509Token); + symmetricBinding.x509Token); } if symmetricBinding.encryptionAlgorithm !is () { Encryption encryption = check new (); @@ -158,7 +162,8 @@ public function applySymmetricBinding(xml envelope, *SymmetricBindingConfig symm WsSecurity wsSecurity = new; securedEnvelope = check wsSecurity.applyEncryptionOnlyPolicy(wsSecurityHeader, encryptionResult); } - securedEnvelope = check applyEncryptedKey(securedEnvelope, symmetricBinding.symmetricKey, symmetricBinding.servicePublicKey); + securedEnvelope = check applyEncryptedKey(securedEnvelope, symmetricBinding.symmetricKey, + symmetricBinding.servicePublicKey); return convertStringToXml(securedEnvelope); } @@ -175,13 +180,13 @@ public function applyAsymmetricBinding(xml envelope, *AsymmetricBindingConfig as Signature signature = check new (); byte[] signedData = check signature.signData((envelope//*).toString(), asymmetricBinding.signatureAlgorithm, - asymmetricBinding.signatureKey); + asymmetricBinding.signatureKey); Signature signatureResult = check addSignature(signature, asymmetricBinding.signatureAlgorithm, signedData); WsSecurity wsSecurity = new; securedEnvelope = check wsSecurity.applySignatureOnlyPolicy(wsSecurityHeader, signatureResult, - asymmetricBinding.x509Token); + asymmetricBinding.x509Token); } if asymmetricBinding.encryptionAlgorithm !is () { Encryption encryption = check new (); diff --git a/native/src/main/java/org/wssec/WsSecurityHeader.java b/native/src/main/java/org/wssec/WsSecurityHeader.java index e5724b5..5d4f035 100644 --- a/native/src/main/java/org/wssec/WsSecurityHeader.java +++ b/native/src/main/java/org/wssec/WsSecurityHeader.java @@ -17,6 +17,7 @@ package org.wssec; import io.ballerina.runtime.api.utils.StringUtils; +import io.ballerina.runtime.api.values.BError; import io.ballerina.runtime.api.values.BHandle; import io.ballerina.runtime.api.values.BObject; import org.apache.wss4j.common.ext.WSSecurityException; @@ -47,13 +48,14 @@ protected WSSecHeader getWsSecHeader() { return wsSecHeader; } - public static void insertSecHeader(BObject secHeader) { + public static BError insertSecHeader(BObject secHeader) { BHandle handle = (BHandle) secHeader.get(StringUtils.fromString(NATIVE_SEC_HEADER)); WsSecurityHeader wsSecurityHeader = (WsSecurityHeader) handle.getValue(); try { wsSecurityHeader.getWsSecHeader().insertSecurityHeader(); } catch (WSSecurityException e) { - throw createError(e.getMessage()); + return createError(e.getMessage()); } + return null; } } diff --git a/native/src/main/java/org/wssec/WsSecurityUtils.java b/native/src/main/java/org/wssec/WsSecurityUtils.java index 977fd20..69b1f0f 100644 --- a/native/src/main/java/org/wssec/WsSecurityUtils.java +++ b/native/src/main/java/org/wssec/WsSecurityUtils.java @@ -26,7 +26,6 @@ import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NodeList; -import org.w3c.dom.Text; import java.io.StringWriter; import java.util.ArrayList; @@ -111,8 +110,7 @@ public static Object getEncryptedKeyElement(byte[] encryptKey) throws Exception keyInfo.setAttribute(XML_DS_NS, SIG_NS); encryptedKey.appendChild(keyInfo); Element cipherData = document.createElement(CIPHER_DATA_TAG); - Text cipherText = document.createTextNode(Base64.getEncoder().encodeToString(encryptKey)); - cipherData.appendChild(cipherText); + cipherData.appendChild(document.createTextNode(Base64.getEncoder().encodeToString(encryptKey))); encryptedKey.appendChild(cipherData); document.appendChild(encryptedKey); return convertDocumentToString(document); @@ -136,8 +134,7 @@ public static Object convertDocumentToString(Document document) throws Exception if (document == null) { return ErrorCreator.createError(StringUtils.fromString(EMPTY_XML_DOCUMENT_ERROR)); } - TransformerFactory transformerFactory = TransformerFactory.newInstance(); - Transformer transformer = transformerFactory.newTransformer(); + Transformer transformer = TransformerFactory.newInstance().newTransformer(); StringWriter writer = new StringWriter(); transformer.transform(new DOMSource(document), new StreamResult(writer)); return StringUtils.fromString(writer.toString()); From ddbb1a93c0f3b6dd21d8d8daa02ffd9269ee39c5 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Wed, 4 Oct 2023 14:04:22 +0530 Subject: [PATCH 114/189] Remove unnecessary string consts --- ballerina/modules/soap11/tests/soap11_client_test.bal | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/ballerina/modules/soap11/tests/soap11_client_test.bal b/ballerina/modules/soap11/tests/soap11_client_test.bal index 3f58960..1e86834 100644 --- a/ballerina/modules/soap11/tests/soap11_client_test.bal +++ b/ballerina/modules/soap11/tests/soap11_client_test.bal @@ -19,15 +19,13 @@ import ballerina/crypto; import ballerina/mime; import ballerina/test; -const wssec:TransportBindingConfig TRANSPORT_BINDING = "TransportBinding"; -const wssec:NoPolicy NO_POLICY = "NoPolicy"; const string KEY_ALIAS = "wss40"; const string KEY_PASSWORD = "security"; const string KEY_STORE_PATH = "modules/wssec/tests/resources/wss40.p12"; -const string X509_PUBLIC_CERT_PATH = "modules/wssec/tests/resources/x509_certificate.crt"; -const string X509_PUBLIC_CERT_PATH_2 = "modules/wssec/tests/resources/x509_certificate_2.crt"; const string X509_KEY_STORE_PATH = "modules/wssec/tests/resources/x509_certificate.p12"; const string X509_KEY_STORE_PATH_2 = "modules/wssec/tests/resources/x509_certificate_2.p12"; +const wssec:TransportBindingConfig TRANSPORT_BINDING = "TransportBinding"; +const wssec:NoPolicy NO_POLICY = "NoPolicy"; @test:Config { groups: ["soap11", "send_only"] From b1e8339baf50354b1d944c8220ae94f1240e6b51 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Wed, 4 Oct 2023 14:04:37 +0530 Subject: [PATCH 115/189] Add test cases for SOAP 1.2 client with security --- .../soap12/tests/soap12_client_test.bal | 167 ++++++++++++++++++ 1 file changed, 167 insertions(+) diff --git a/ballerina/modules/soap12/tests/soap12_client_test.bal b/ballerina/modules/soap12/tests/soap12_client_test.bal index 414db04..ccb90ea 100644 --- a/ballerina/modules/soap12/tests/soap12_client_test.bal +++ b/ballerina/modules/soap12/tests/soap12_client_test.bal @@ -17,7 +17,13 @@ import soap.wssec; import ballerina/mime; import ballerina/test; +import ballerina/crypto; +const string KEY_ALIAS = "wss40"; +const string KEY_PASSWORD = "security"; +const string KEY_STORE_PATH = "modules/wssec/tests/resources/wss40.p12"; +const string X509_KEY_STORE_PATH = "modules/wssec/tests/resources/x509_certificate.p12"; +const string X509_KEY_STORE_PATH_2 = "modules/wssec/tests/resources/x509_certificate_2.p12"; const wssec:TransportBindingConfig TRANSPORT_BINDING = "TransportBinding"; const wssec:NoPolicy NO_POLICY = "NoPolicy"; @@ -193,3 +199,164 @@ function testSendReceiveError() returns error? { test:assertTrue(response is Error); test:assertEquals((response).message(), SOAP_RESPONSE_ERROR); } + + +@test:Config { + groups: ["soap12", "send_receive"] +} +function testSendReceiveWithTimestampTokenSecurity() returns error? { + Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL", + { + inboundSecurity: [ + { + timeToLive: 600 + } + ] + } + ); + xml body = xml ` + + + 2 + 3 + + + `; + xml|mime:Entity[] response = check soapClient->sendReceive(body, "http://tempuri.org/Add"); + xml expected = xml `soap:MustUnderstandSystem.Web.Services.Protocols.SoapHeaderException: SOAP header Security was not understood. + at System.Web.Services.Protocols.SoapHeaderHandling.SetHeaderMembers(SoapHeaderCollection headers, Object target, SoapHeaderMapping[] mappings, SoapHeaderDirection direction, Boolean client) + at System.Web.Services.Protocols.SoapServerProtocol.CreateServerInstance() + at System.Web.Services.Protocols.WebServiceHandler.Invoke() + at System.Web.Services.Protocols.WebServiceHandler.CoreProcessRequest()`; + + test:assertEquals(response.toString(), expected.toString()); +} + +@test:Config { + groups: ["soap12", "send_receive"] +} +function testSendReceiveWithUsernameTokenSecurity() returns error? { + Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL", + { + inboundSecurity: { + username: "user", + password: "password", + passwordType: wssec:TEXT + }, + outboundSecurity: {} + } + ); + xml body = xml ` + + + 2 + 3 + + + `; + xml|mime:Entity[] response = check soapClient->sendReceive(body, "http://tempuri.org/Add"); + xml expected = xml `soap:MustUnderstandSystem.Web.Services.Protocols.SoapHeaderException: SOAP header Security was not understood. + at System.Web.Services.Protocols.SoapHeaderHandling.SetHeaderMembers(SoapHeaderCollection headers, Object target, SoapHeaderMapping[] mappings, SoapHeaderDirection direction, Boolean client) + at System.Web.Services.Protocols.SoapServerProtocol.CreateServerInstance() + at System.Web.Services.Protocols.WebServiceHandler.Invoke() + at System.Web.Services.Protocols.WebServiceHandler.CoreProcessRequest()`; + + test:assertEquals(response.toString(), expected.toString()); +} + +@test:Config { + groups: ["soap12", "send_receive"] +} +function testSendReceiveWithAsymmetricBindingSecurity() returns error? { + crypto:KeyStore serverKeyStore = { + path: X509_KEY_STORE_PATH, + password: KEY_PASSWORD + }; + + crypto:PublicKey serverPublicKey = check crypto:decodeRsaPublicKeyFromTrustStore(serverKeyStore, KEY_ALIAS); + + crypto:KeyStore clientKeyStore = { + path: X509_KEY_STORE_PATH_2, + password: KEY_PASSWORD + }; + crypto:PrivateKey clientPrivateKey = check crypto:decodeRsaPrivateKeyFromKeyStore(clientKeyStore, KEY_ALIAS, KEY_PASSWORD); + + Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL", + { + inboundSecurity: { + signatureAlgorithm: wssec:RSA_SHA256, + encryptionAlgorithm: wssec:RSA_ECB, + signatureKey: clientPrivateKey, + encryptionKey: serverPublicKey + } + } + ); + xml body = xml ` + + + 2 + 3 + + + `; + xml|mime:Entity[] response = check soapClient->sendReceive(body, "http://tempuri.org/Add"); + xml expected = xml `soap:MustUnderstandSystem.Web.Services.Protocols.SoapHeaderException: SOAP header Security was not understood. + at System.Web.Services.Protocols.SoapHeaderHandling.SetHeaderMembers(SoapHeaderCollection headers, Object target, SoapHeaderMapping[] mappings, SoapHeaderDirection direction, Boolean client) + at System.Web.Services.Protocols.SoapServerProtocol.CreateServerInstance() + at System.Web.Services.Protocols.WebServiceHandler.Invoke() + at System.Web.Services.Protocols.WebServiceHandler.CoreProcessRequest()`; + + test:assertEquals(response.toString(), expected.toString()); +} + +@test:Config { + groups: ["soap12", "send_receive"] +} +function testSendReceiveWithSymmetricBindingSecurity() returns error? { + crypto:KeyStore serverKeyStore = { + path: X509_KEY_STORE_PATH, + password: KEY_PASSWORD + }; + crypto:PublicKey serverPublicKey = check crypto:decodeRsaPublicKeyFromTrustStore(serverKeyStore, KEY_ALIAS); + + crypto:KeyStore keyStore = { + path: KEY_STORE_PATH, + password: KEY_PASSWORD + }; + crypto:PrivateKey symmetricKey = check crypto:decodeRsaPrivateKeyFromKeyStore(keyStore, KEY_ALIAS, KEY_PASSWORD); + + Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL", + { + inboundSecurity: { + signatureAlgorithm: wssec:RSA_SHA256, + encryptionAlgorithm: wssec:RSA_ECB, + symmetricKey: symmetricKey, + servicePublicKey: serverPublicKey + } + } + ); + xml body = xml ` + + + 2 + 3 + + + `; + xml|mime:Entity[] response = check soapClient->sendReceive(body, "http://tempuri.org/Add"); + xml expected = xml `soap:MustUnderstandSystem.Web.Services.Protocols.SoapHeaderException: SOAP header Security was not understood. + at System.Web.Services.Protocols.SoapHeaderHandling.SetHeaderMembers(SoapHeaderCollection headers, Object target, SoapHeaderMapping[] mappings, SoapHeaderDirection direction, Boolean client) + at System.Web.Services.Protocols.SoapServerProtocol.CreateServerInstance() + at System.Web.Services.Protocols.WebServiceHandler.Invoke() + at System.Web.Services.Protocols.WebServiceHandler.CoreProcessRequest()`; + + test:assertEquals(response.toString(), expected.toString()); +} From 984abe62cc9d59793a67f3ac1e53853e6d0c4436 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Wed, 4 Oct 2023 14:30:29 +0530 Subject: [PATCH 116/189] Apply changes to adhere code conventions --- ballerina/modules/wssec/document.bal | 1 + ballerina/modules/wssec/sec_header.bal | 1 + ballerina/modules/wssec/signature.bal | 1 + ballerina/modules/wssec/tests/test_utils.bal | 3 ++- 4 files changed, 5 insertions(+), 1 deletion(-) diff --git a/ballerina/modules/wssec/document.bal b/ballerina/modules/wssec/document.bal index 5a284a6..f467a4a 100644 --- a/ballerina/modules/wssec/document.bal +++ b/ballerina/modules/wssec/document.bal @@ -16,6 +16,7 @@ import ballerina/jballerina.java; class Document { + private handle nativeDocumentBuilder; public function init(xml xmlPayload) returns Error? { diff --git a/ballerina/modules/wssec/sec_header.bal b/ballerina/modules/wssec/sec_header.bal index e3f0537..92f4deb 100644 --- a/ballerina/modules/wssec/sec_header.bal +++ b/ballerina/modules/wssec/sec_header.bal @@ -16,6 +16,7 @@ import ballerina/jballerina.java; class WSSecurityHeader { + private handle nativeSecHeader; function init(Document document) returns Error? { diff --git a/ballerina/modules/wssec/signature.bal b/ballerina/modules/wssec/signature.bal index 1023f5a..f9fc76d 100644 --- a/ballerina/modules/wssec/signature.bal +++ b/ballerina/modules/wssec/signature.bal @@ -17,6 +17,7 @@ import ballerina/crypto; import ballerina/jballerina.java; class Signature { + private handle nativeSignature; function init() returns Error? { diff --git a/ballerina/modules/wssec/tests/test_utils.bal b/ballerina/modules/wssec/tests/test_utils.bal index 4881ff4..2e99abe 100644 --- a/ballerina/modules/wssec/tests/test_utils.bal +++ b/ballerina/modules/wssec/tests/test_utils.bal @@ -13,7 +13,6 @@ // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. - import ballerina/test; const string USERNAME = "username"; @@ -38,6 +37,7 @@ function assertTimestampToken(string envelopeString) { test:assertTrue(envelopeString.includesMatch(created)); test:assertTrue(envelopeString.includesMatch(expires)); } + function assertUsernameToken(string envelopeString, PasswordType passwordType) { string:RegExp usernameTokenTag = re `.*`; string:RegExp usernameTag = re `${USERNAME}`; @@ -64,6 +64,7 @@ function assertUsernameToken(string envelopeString, PasswordType passwordType) { } } } + function assertSignatureWithX509(string securedEnvelope) { string:RegExp keyIdentifier = re `.*`; test:assertTrue(securedEnvelope.includesMatch(keyIdentifier)); From e5a872efdf77211e2b5fb930f6584790db344736 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Wed, 4 Oct 2023 14:37:08 +0530 Subject: [PATCH 117/189] Remove unnecessary code segments --- ballerina/modules/wssec/encryption.bal | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/ballerina/modules/wssec/encryption.bal b/ballerina/modules/wssec/encryption.bal index e673b54..107a6fd 100644 --- a/ballerina/modules/wssec/encryption.bal +++ b/ballerina/modules/wssec/encryption.bal @@ -29,14 +29,7 @@ class Encryption { returns byte[]|Error { byte[] data = dataString.toBytes(); do { - match encryptionAlgorithm { - RSA_ECB => { - return check crypto:encryptRsaEcb(data, key); - } - _ => { - return error Error("Invalid/Missing key!"); - } - } + return check crypto:encryptRsaEcb(data, key); } on fail var e { return error(e.message()); } @@ -46,14 +39,7 @@ class Encryption { crypto:PublicKey|crypto:PrivateKey key) returns byte[]|Error { do { - match encryptionAlgorithm { - RSA_ECB => { - return check crypto:decryptRsaEcb(cipherText, key); - } - _ => { - return error Error("Invalid/Missing key!"); - } - } + return check crypto:decryptRsaEcb(cipherText, key); } on fail var e { return error Error(e.message()); } From 449d48845dbd7d134dcf437fb3f2a1c8e44a27d1 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Wed, 4 Oct 2023 16:43:45 +0530 Subject: [PATCH 118/189] Fix test case issue --- ballerina/modules/soap11/tests/soap11_client_test.bal | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ballerina/modules/soap11/tests/soap11_client_test.bal b/ballerina/modules/soap11/tests/soap11_client_test.bal index 1e86834..88d5da7 100644 --- a/ballerina/modules/soap11/tests/soap11_client_test.bal +++ b/ballerina/modules/soap11/tests/soap11_client_test.bal @@ -168,7 +168,7 @@ function testSendReceiveWithTimestampTokenSecurity() returns error? { at System.Web.Services.Protocols.SoapServerProtocol.CreateServerInstance() at System.Web.Services.Protocols.WebServiceHandler.Invoke() at System.Web.Services.Protocols.WebServiceHandler.CoreProcessRequest()`; - test:assertEquals(response, expected); + test:assertEquals(response.toString(), expected.toString()); } @test:Config { @@ -201,7 +201,7 @@ function testSendReceiveWithUsernameTokenSecurity() returns error? { at System.Web.Services.Protocols.SoapServerProtocol.CreateServerInstance() at System.Web.Services.Protocols.WebServiceHandler.Invoke() at System.Web.Services.Protocols.WebServiceHandler.CoreProcessRequest()`; - test:assertEquals(response, expected); + test:assertEquals(response.toString(), expected.toString()); } @test:Config { @@ -247,7 +247,7 @@ function testSendReceiveWithAsymmetricBindingSecurity() returns error? { at System.Web.Services.Protocols.SoapServerProtocol.CreateServerInstance() at System.Web.Services.Protocols.WebServiceHandler.Invoke() at System.Web.Services.Protocols.WebServiceHandler.CoreProcessRequest()`; - test:assertEquals(response, expected); + test:assertEquals(response.toString(), expected.toString()); } @test:Config { @@ -292,5 +292,5 @@ function testSendReceiveWithSymmetricBindingSecurity() returns error? { at System.Web.Services.Protocols.SoapServerProtocol.CreateServerInstance() at System.Web.Services.Protocols.WebServiceHandler.Invoke() at System.Web.Services.Protocols.WebServiceHandler.CoreProcessRequest()`; - test:assertEquals(response, expected); + test:assertEquals(response.toString(), expected.toString()); } From f822ac8f6148e9a29b2dd2c24791472880c31b99 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Thu, 5 Oct 2023 10:15:09 +0530 Subject: [PATCH 119/189] Add const variable for a SOAP client error --- ballerina/modules/soap11/error.bal | 1 + ballerina/modules/soap11/soap11.bal | 3 +-- ballerina/modules/soap12/error.bal | 1 + ballerina/modules/soap12/soap12.bal | 3 +-- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ballerina/modules/soap11/error.bal b/ballerina/modules/soap11/error.bal index 2fd8412..29a6fad 100644 --- a/ballerina/modules/soap11/error.bal +++ b/ballerina/modules/soap11/error.bal @@ -19,3 +19,4 @@ public type Error distinct error; const SOAP_RESPONSE_ERROR = "Failed to create SOAP response."; const SOAP_CLIENT_ERROR = "Failed to initialize SOAP 1.1 client."; +const INVALID_OUTBOUND_SECURITY_ERROR = "Outbound security configurations do not match with the SOAP response."; diff --git a/ballerina/modules/soap11/soap11.bal b/ballerina/modules/soap11/soap11.bal index bb89ce8..c1f3241 100644 --- a/ballerina/modules/soap11/soap11.bal +++ b/ballerina/modules/soap11/soap11.bal @@ -65,8 +65,7 @@ public client class Client { return check common:applyOutboundConfig(outboundSecurity, response); } } on fail var e { - return error Error("Outbound security configurations do not match with the SOAP response. ", - e.cause()); + return error Error(INVALID_OUTBOUND_SECURITY_ERROR, e.cause()); } } return check common:sendReceive(body, self.soapClient, action, headers, false); diff --git a/ballerina/modules/soap12/error.bal b/ballerina/modules/soap12/error.bal index f25d859..cbdf10a 100644 --- a/ballerina/modules/soap12/error.bal +++ b/ballerina/modules/soap12/error.bal @@ -19,3 +19,4 @@ public type Error distinct error; const SOAP_RESPONSE_ERROR = "Failed to create SOAP response."; const SOAP_CLIENT_ERROR = "Failed to initialize SOAP 1.2 client."; +const INVALID_OUTBOUND_SECURITY_ERROR = "Outbound security configurations do not match with the SOAP response."; diff --git a/ballerina/modules/soap12/soap12.bal b/ballerina/modules/soap12/soap12.bal index 1c56975..8fd5c9a 100644 --- a/ballerina/modules/soap12/soap12.bal +++ b/ballerina/modules/soap12/soap12.bal @@ -64,8 +64,7 @@ public client class Client { return check common:applyOutboundConfig(outboundSecurity, response); } } on fail var e { - return error Error("Outbound security configurations do not match with the SOAP response. ", - e.cause()); + return error Error(INVALID_OUTBOUND_SECURITY_ERROR, e.cause()); } return response; } From 439be7c8fe5e56de317d0a179ead2cda7d513dd6 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Thu, 5 Oct 2023 10:15:33 +0530 Subject: [PATCH 120/189] Change test case name --- ballerina/modules/wssec/tests/ws_security_tests.bal | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ballerina/modules/wssec/tests/ws_security_tests.bal b/ballerina/modules/wssec/tests/ws_security_tests.bal index 91b4cd8..cc3b23d 100644 --- a/ballerina/modules/wssec/tests/ws_security_tests.bal +++ b/ballerina/modules/wssec/tests/ws_security_tests.bal @@ -538,7 +538,7 @@ function testSymmetricBindingWithOutboundConfig() returns error? { @test:Config { groups: ["username_token", "signature", "asymmetric_binding"] } -function testAsymmetricBindingWithSignature() returns error? { +function testAsymmetricBindingWithSignatureRsaSha256() returns error? { xml envelope = xml ` From cc42bc9ef1d5571b2d46ef06e489fe14bc32ff5c Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Thu, 5 Oct 2023 11:20:43 +0530 Subject: [PATCH 121/189] Add security support for mime:Entity --- ballerina/modules/soap11/soap11.bal | 37 ++++++++++++++++------------- ballerina/modules/soap12/soap12.bal | 36 ++++++++++++++-------------- 2 files changed, 39 insertions(+), 34 deletions(-) diff --git a/ballerina/modules/soap11/soap11.bal b/ballerina/modules/soap11/soap11.bal index c1f3241..a06bfc5 100644 --- a/ballerina/modules/soap11/soap11.bal +++ b/ballerina/modules/soap11/soap11.bal @@ -45,7 +45,7 @@ public client class Client { # Sends SOAP request and expects a response. # ```ballerina - # xml|mime:Entity[] response = check soapClient->sendReceive(body); + # xml|mime:Entity[] response = check soapClient->sendReceive(body, action); # ``` # # + body - SOAP request body as an `XML` or `mime:Entity[]` to work with SOAP attachments @@ -55,20 +55,23 @@ public client class Client { remote function sendReceive(xml|mime:Entity[] body, string action, map headers = {}) returns xml|mime:Entity[]|Error { do { + xml securedBody; if body is xml { - xml applySecurityPoliciesResult = check common:applySecurityPolicies(self.inboundSecurity, body); - xml response = check common:sendReceive(applySecurityPoliciesResult, self.soapClient, - action, headers, false); - wssec:OutboundSecurityConfig? outboundSecurity = self.outboundSecurity; - do { - if outboundSecurity !is () { - return check common:applyOutboundConfig(outboundSecurity, response); - } - } on fail var e { - return error Error(INVALID_OUTBOUND_SECURITY_ERROR, e.cause()); + securedBody = check common:applySecurityPolicies(self.inboundSecurity, body); + } else { + securedBody = check common:applySecurityPolicies(self.inboundSecurity, check body[0].getXml()); + } + xml response = check common:sendReceive(securedBody, self.soapClient, + action, headers, false); + wssec:OutboundSecurityConfig? outboundSecurity = self.outboundSecurity; + do { + if outboundSecurity !is () { + return check common:applyOutboundConfig(outboundSecurity, response); } + } on fail var e { + return error Error(INVALID_OUTBOUND_SECURITY_ERROR, e.cause()); } - return check common:sendReceive(body, self.soapClient, action, headers, false); + return response; } on fail var e { return error Error(e.message()); } @@ -77,7 +80,7 @@ public client class Client { # Fires and forgets requests. Sends the request without the possibility of any response from the # service (even an error). # ```ballerina - # check soapClient->sendOnly(body); + # check soapClient->sendOnly(body, action); # ``` # # + body - SOAP request body as an `XML` or `mime:Entity[]` to work with SOAP attachments @@ -86,11 +89,13 @@ public client class Client { # + return - If successful, returns `nil`. Else, returns an error remote function sendOnly(xml|mime:Entity[] body, string action, map headers = {}) returns Error? { do { + xml securedBody; if body is xml { - xml applySecurityPoliciesResult = check common:applySecurityPolicies(self.inboundSecurity, body); - return check common:sendOnly(applySecurityPoliciesResult, self.soapClient, action, headers, false); + securedBody = check common:applySecurityPolicies(self.inboundSecurity, body); + } else { + securedBody = check common:applySecurityPolicies(self.inboundSecurity, check body[0].getXml()); } - return check common:sendOnly(body, self.soapClient, action, headers, false); + return check common:sendOnly(securedBody, self.soapClient, action, headers, false); } on fail var e { return error Error(e.message()); } diff --git a/ballerina/modules/soap12/soap12.bal b/ballerina/modules/soap12/soap12.bal index 8fd5c9a..0b98783 100644 --- a/ballerina/modules/soap12/soap12.bal +++ b/ballerina/modules/soap12/soap12.bal @@ -55,20 +55,22 @@ public client class Client { remote function sendReceive(xml|mime:Entity[] body, string? action = (), map headers = {}) returns xml|mime:Entity[]|Error { do { + xml securedBody; if body is xml { - xml applySecurityPoliciesResult = check common:applySecurityPolicies(self.inboundSecurity, body); - xml response = check common:sendReceive(applySecurityPoliciesResult, self.soapClient, action, headers); - wssec:OutboundSecurityConfig? outboundSecurity = self.outboundSecurity; - do { - if outboundSecurity !is () { - return check common:applyOutboundConfig(outboundSecurity, response); - } - } on fail var e { - return error Error(INVALID_OUTBOUND_SECURITY_ERROR, e.cause()); + securedBody = check common:applySecurityPolicies(self.inboundSecurity, body); + } else { + securedBody = check common:applySecurityPolicies(self.inboundSecurity, check body[0].getXml()); + } + xml response = check common:sendReceive(securedBody, self.soapClient, action, headers); + wssec:OutboundSecurityConfig? outboundSecurity = self.outboundSecurity; + do { + if outboundSecurity !is () { + return check common:applyOutboundConfig(outboundSecurity, response); } - return response; + } on fail var e { + return error Error(INVALID_OUTBOUND_SECURITY_ERROR, e.cause()); } - return check common:sendReceive(body, self.soapClient, action, headers); + return response; } on fail var e { return error Error(e.message()); } @@ -87,15 +89,13 @@ public client class Client { remote function sendOnly(xml|mime:Entity[] body, string? action = (), map headers = {}) returns Error? { do { + xml securedBody; if body is xml { - do { - xml applySecurityPoliciesResult = check common:applySecurityPolicies(self.inboundSecurity, body); - return check common:sendOnly(applySecurityPoliciesResult, self.soapClient, action, headers); - } on fail var e { - return error Error(e.message()); - } + securedBody = check common:applySecurityPolicies(self.inboundSecurity, body); + } else { + securedBody = check common:applySecurityPolicies(self.inboundSecurity, check body[0].getXml()); } - return check common:sendOnly(body, self.soapClient, action, headers); + return check common:sendOnly(securedBody, self.soapClient, action, headers); } on fail var e { return error Error(e.message()); } From b9ee921fb583b2200cf1583190629649bc278ab1 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Thu, 5 Oct 2023 11:27:27 +0530 Subject: [PATCH 122/189] [Automated] Update the native jar versions --- ballerina/Dependencies.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index 8fe54a9..71ac60d 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -288,7 +288,6 @@ dependencies = [ ] modules = [ {org = "ballerina", packageName = "soap", moduleName = "soap"}, - {org = "ballerina", packageName = "soap", moduleName = "soap.common"}, {org = "ballerina", packageName = "soap", moduleName = "soap.soap11"}, {org = "ballerina", packageName = "soap", moduleName = "soap.soap12"}, {org = "ballerina", packageName = "soap", moduleName = "soap.wssec"} From 9ebde887292a1c79c6d28092bb39aa7b90c20f52 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Thu, 5 Oct 2023 11:30:40 +0530 Subject: [PATCH 123/189] Migrate `soap:common` module into the `soap` module --- ballerina/{modules/common => }/configs.bal | 0 ballerina/{modules/common => }/constants.bal | 0 ballerina/{modules/common => }/error.bal | 0 ballerina/modules/soap11/soap11.bal | 24 +++++++------- .../soap11/tests/soap11_client_test.bal | 13 ++++---- ballerina/modules/soap12/soap12.bal | 24 +++++++------- .../soap12/tests/soap12_client_test.bal | 13 ++++---- ballerina/{modules/common => }/soap_utils.bal | 0 ballerina/types.bal | 33 +++++++++++++++++++ 9 files changed, 69 insertions(+), 38 deletions(-) rename ballerina/{modules/common => }/configs.bal (100%) rename ballerina/{modules/common => }/constants.bal (100%) rename ballerina/{modules/common => }/error.bal (100%) rename ballerina/{modules/common => }/soap_utils.bal (100%) create mode 100644 ballerina/types.bal diff --git a/ballerina/modules/common/configs.bal b/ballerina/configs.bal similarity index 100% rename from ballerina/modules/common/configs.bal rename to ballerina/configs.bal diff --git a/ballerina/modules/common/constants.bal b/ballerina/constants.bal similarity index 100% rename from ballerina/modules/common/constants.bal rename to ballerina/constants.bal diff --git a/ballerina/modules/common/error.bal b/ballerina/error.bal similarity index 100% rename from ballerina/modules/common/error.bal rename to ballerina/error.bal diff --git a/ballerina/modules/soap11/soap11.bal b/ballerina/modules/soap11/soap11.bal index a06bfc5..4a31e66 100644 --- a/ballerina/modules/soap11/soap11.bal +++ b/ballerina/modules/soap11/soap11.bal @@ -13,14 +13,12 @@ // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -import soap.common; +import soap; import soap.wssec; import ballerina/http; import ballerina/mime; -xmlns "http://schemas.xmlsoap.org/soap/envelope/" as soap; - # Object for the basic SOAP client endpoint. public client class Client { private final http:Client soapClient; @@ -32,10 +30,10 @@ public client class Client { # + url - URL endpoint # + config - Configurations for SOAP client # + return - `error` in case of errors or `()` otherwise - public function init(string url, *common:ClientConfig config) returns Error? { + public function init(string url, *soap:ClientConfig config) returns Error? { do { - check common:validateTransportBindingPolicy(config); - self.soapClient = check new (url, common:retrieveHttpClientConfig(config)); + check soap:validateTransportBindingPolicy(config); + self.soapClient = check new (url, soap:retrieveHttpClientConfig(config)); self.inboundSecurity = config.inboundSecurity; self.outboundSecurity = config.outboundSecurity; } on fail var err { @@ -57,16 +55,16 @@ public client class Client { do { xml securedBody; if body is xml { - securedBody = check common:applySecurityPolicies(self.inboundSecurity, body); + securedBody = check soap:applySecurityPolicies(self.inboundSecurity, body); } else { - securedBody = check common:applySecurityPolicies(self.inboundSecurity, check body[0].getXml()); + securedBody = check soap:applySecurityPolicies(self.inboundSecurity, check body[0].getXml()); } - xml response = check common:sendReceive(securedBody, self.soapClient, + xml response = check soap:sendReceive(securedBody, self.soapClient, action, headers, false); wssec:OutboundSecurityConfig? outboundSecurity = self.outboundSecurity; do { if outboundSecurity !is () { - return check common:applyOutboundConfig(outboundSecurity, response); + return check soap:applyOutboundConfig(outboundSecurity, response); } } on fail var e { return error Error(INVALID_OUTBOUND_SECURITY_ERROR, e.cause()); @@ -91,11 +89,11 @@ public client class Client { do { xml securedBody; if body is xml { - securedBody = check common:applySecurityPolicies(self.inboundSecurity, body); + securedBody = check soap:applySecurityPolicies(self.inboundSecurity, body); } else { - securedBody = check common:applySecurityPolicies(self.inboundSecurity, check body[0].getXml()); + securedBody = check soap:applySecurityPolicies(self.inboundSecurity, check body[0].getXml()); } - return check common:sendOnly(securedBody, self.soapClient, action, headers, false); + return check soap:sendOnly(securedBody, self.soapClient, action, headers, false); } on fail var e { return error Error(e.message()); } diff --git a/ballerina/modules/soap11/tests/soap11_client_test.bal b/ballerina/modules/soap11/tests/soap11_client_test.bal index 88d5da7..23fa5f4 100644 --- a/ballerina/modules/soap11/tests/soap11_client_test.bal +++ b/ballerina/modules/soap11/tests/soap11_client_test.bal @@ -13,11 +13,12 @@ // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -import soap.wssec; +import soap; import ballerina/crypto; import ballerina/mime; import ballerina/test; +import soap.wssec; const string KEY_ALIAS = "wss40"; const string KEY_PASSWORD = "security"; @@ -180,7 +181,7 @@ function testSendReceiveWithUsernameTokenSecurity() returns error? { inboundSecurity: { username: "user", password: "password", - passwordType: wssec:TEXT + passwordType: soap:TEXT }, outboundSecurity: {} } @@ -224,8 +225,8 @@ function testSendReceiveWithAsymmetricBindingSecurity() returns error? { Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL", { inboundSecurity: { - signatureAlgorithm: wssec:RSA_SHA256, - encryptionAlgorithm: wssec:RSA_ECB, + signatureAlgorithm: soap:RSA_SHA256, + encryptionAlgorithm: soap:RSA_ECB, signatureKey: clientPrivateKey, encryptionKey: serverPublicKey } @@ -269,8 +270,8 @@ function testSendReceiveWithSymmetricBindingSecurity() returns error? { Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL", { inboundSecurity: { - signatureAlgorithm: wssec:RSA_SHA256, - encryptionAlgorithm: wssec:RSA_ECB, + signatureAlgorithm: soap:RSA_SHA256, + encryptionAlgorithm: soap:RSA_ECB, symmetricKey: symmetricKey, servicePublicKey: serverPublicKey } diff --git a/ballerina/modules/soap12/soap12.bal b/ballerina/modules/soap12/soap12.bal index 0b98783..d5214ba 100644 --- a/ballerina/modules/soap12/soap12.bal +++ b/ballerina/modules/soap12/soap12.bal @@ -13,14 +13,12 @@ // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -import soap.common; +import soap; import soap.wssec; import ballerina/http; import ballerina/mime; -xmlns "http://www.w3.org/2003/05/soap-envelope" as soap; - # Object for the basic SOAP client endpoint. public client class Client { private final http:Client soapClient; @@ -32,10 +30,10 @@ public client class Client { # + url - URL endpoint # + config - Configurations for SOAP client # + return - `error` in case of errors or `()` otherwise - public function init(string url, *common:ClientConfig config) returns Error? { + public function init(string url, *soap:ClientConfig config) returns Error? { do { - check common:validateTransportBindingPolicy(config); - self.soapClient = check new (url, common:retrieveHttpClientConfig(config)); + check soap:validateTransportBindingPolicy(config); + self.soapClient = check new (url, soap:retrieveHttpClientConfig(config)); self.inboundSecurity = config.inboundSecurity; self.outboundSecurity = config.outboundSecurity; } on fail var err { @@ -57,15 +55,15 @@ public client class Client { do { xml securedBody; if body is xml { - securedBody = check common:applySecurityPolicies(self.inboundSecurity, body); + securedBody = check soap:applySecurityPolicies(self.inboundSecurity, body); } else { - securedBody = check common:applySecurityPolicies(self.inboundSecurity, check body[0].getXml()); + securedBody = check soap:applySecurityPolicies(self.inboundSecurity, check body[0].getXml()); } - xml response = check common:sendReceive(securedBody, self.soapClient, action, headers); + xml response = check soap:sendReceive(securedBody, self.soapClient, action, headers); wssec:OutboundSecurityConfig? outboundSecurity = self.outboundSecurity; do { if outboundSecurity !is () { - return check common:applyOutboundConfig(outboundSecurity, response); + return check soap:applyOutboundConfig(outboundSecurity, response); } } on fail var e { return error Error(INVALID_OUTBOUND_SECURITY_ERROR, e.cause()); @@ -91,11 +89,11 @@ public client class Client { do { xml securedBody; if body is xml { - securedBody = check common:applySecurityPolicies(self.inboundSecurity, body); + securedBody = check soap:applySecurityPolicies(self.inboundSecurity, body); } else { - securedBody = check common:applySecurityPolicies(self.inboundSecurity, check body[0].getXml()); + securedBody = check soap:applySecurityPolicies(self.inboundSecurity, check body[0].getXml()); } - return check common:sendOnly(securedBody, self.soapClient, action, headers); + return check soap:sendOnly(securedBody, self.soapClient, action, headers); } on fail var e { return error Error(e.message()); } diff --git a/ballerina/modules/soap12/tests/soap12_client_test.bal b/ballerina/modules/soap12/tests/soap12_client_test.bal index ccb90ea..df7c512 100644 --- a/ballerina/modules/soap12/tests/soap12_client_test.bal +++ b/ballerina/modules/soap12/tests/soap12_client_test.bal @@ -13,11 +13,12 @@ // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -import soap.wssec; +import soap; import ballerina/mime; import ballerina/test; import ballerina/crypto; +import soap.wssec; const string KEY_ALIAS = "wss40"; const string KEY_PASSWORD = "security"; @@ -243,7 +244,7 @@ function testSendReceiveWithUsernameTokenSecurity() returns error? { inboundSecurity: { username: "user", password: "password", - passwordType: wssec:TEXT + passwordType: soap:TEXT }, outboundSecurity: {} } @@ -288,8 +289,8 @@ function testSendReceiveWithAsymmetricBindingSecurity() returns error? { Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL", { inboundSecurity: { - signatureAlgorithm: wssec:RSA_SHA256, - encryptionAlgorithm: wssec:RSA_ECB, + signatureAlgorithm: soap:RSA_SHA256, + encryptionAlgorithm: soap:RSA_ECB, signatureKey: clientPrivateKey, encryptionKey: serverPublicKey } @@ -334,8 +335,8 @@ function testSendReceiveWithSymmetricBindingSecurity() returns error? { Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL", { inboundSecurity: { - signatureAlgorithm: wssec:RSA_SHA256, - encryptionAlgorithm: wssec:RSA_ECB, + signatureAlgorithm: soap:RSA_SHA256, + encryptionAlgorithm: soap:RSA_ECB, symmetricKey: symmetricKey, servicePublicKey: serverPublicKey } diff --git a/ballerina/modules/common/soap_utils.bal b/ballerina/soap_utils.bal similarity index 100% rename from ballerina/modules/common/soap_utils.bal rename to ballerina/soap_utils.bal diff --git a/ballerina/types.bal b/ballerina/types.bal new file mode 100644 index 0000000..a7eb41f --- /dev/null +++ b/ballerina/types.bal @@ -0,0 +1,33 @@ +// Copyright (c) 2023, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +// +// WSO2 Inc. licenses this file to you under the Apache License, +// Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +public enum PasswordType { + TEXT, + DIGEST, + DERIVED_KEY_TEXT, + DERIVED_KEY_DIGEST +} + +public enum SignatureAlgorithm { + RSA_SHA1 = "http://www.w3.org/2000/09/xmldsig#rsa-sha1", + RSA_SHA256 = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256", + RSA_SHA384 = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha384", + RSA_SHA512 = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha512" +} + +public enum EncryptionAlgorithm { + RSA_ECB = "http://www.w3.org/2001/04/xmlenc#rsa-1_5" +} From 4551c29c48d0bb0a79cad202c9f021cd8e6e0ad6 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Fri, 6 Oct 2023 11:22:23 +0530 Subject: [PATCH 124/189] Update the `http` version to 2.10.1 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index bbc5708..ee4df37 100644 --- a/gradle.properties +++ b/gradle.properties @@ -32,7 +32,7 @@ stdlibAuthVersion=2.10.0 stdlibJwtVersion=2.10.0 stdlibOAuth2Version=2.10.0 -stdlibHttpVersion=2.10.0 +stdlibHttpVersion=2.10.1 stdlibTransactionVersion=1.8.0 wsSecurityDomVersion=3.0.1 From 99b3fbee433ce9bbd91d5b86e231a90361ecdd7c Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Fri, 6 Oct 2023 11:23:30 +0530 Subject: [PATCH 125/189] Add configuration files for GraalVM checks --- .../soap-native/jni-config.json | 14 +++++++++++++ .../predefined-classes-config.json | 8 +++++++ .../soap-native/proxy-config.json | 2 ++ .../soap-native/reflect-config.json | 21 +++++++++++++++++++ .../soap-native/resource-config.json | 9 ++++++++ .../soap-native/serialization-config.json | 8 +++++++ 6 files changed, 62 insertions(+) create mode 100644 native/src/main/resources/META-INF/native-image/io.ballerina.stdlib/soap-native/jni-config.json create mode 100644 native/src/main/resources/META-INF/native-image/io.ballerina.stdlib/soap-native/predefined-classes-config.json create mode 100644 native/src/main/resources/META-INF/native-image/io.ballerina.stdlib/soap-native/proxy-config.json create mode 100644 native/src/main/resources/META-INF/native-image/io.ballerina.stdlib/soap-native/reflect-config.json create mode 100644 native/src/main/resources/META-INF/native-image/io.ballerina.stdlib/soap-native/resource-config.json create mode 100644 native/src/main/resources/META-INF/native-image/io.ballerina.stdlib/soap-native/serialization-config.json diff --git a/native/src/main/resources/META-INF/native-image/io.ballerina.stdlib/soap-native/jni-config.json b/native/src/main/resources/META-INF/native-image/io.ballerina.stdlib/soap-native/jni-config.json new file mode 100644 index 0000000..c58277c --- /dev/null +++ b/native/src/main/resources/META-INF/native-image/io.ballerina.stdlib/soap-native/jni-config.json @@ -0,0 +1,14 @@ +[ +{ + "name":"ballerina.soap.0.$_init", + "methods":[{"name":"main","parameterTypes":["java.lang.String[]"] }] +}, +{ + "name":"java.lang.String", + "methods":[{"name":"lastIndexOf","parameterTypes":["int"] }, {"name":"substring","parameterTypes":["int"] }] +}, +{ + "name":"java.lang.System", + "methods":[{"name":"getProperty","parameterTypes":["java.lang.String"] }, {"name":"setProperty","parameterTypes":["java.lang.String","java.lang.String"] }] +} +] diff --git a/native/src/main/resources/META-INF/native-image/io.ballerina.stdlib/soap-native/predefined-classes-config.json b/native/src/main/resources/META-INF/native-image/io.ballerina.stdlib/soap-native/predefined-classes-config.json new file mode 100644 index 0000000..0e79b2c --- /dev/null +++ b/native/src/main/resources/META-INF/native-image/io.ballerina.stdlib/soap-native/predefined-classes-config.json @@ -0,0 +1,8 @@ +[ + { + "type":"agent-extracted", + "classes":[ + ] + } +] + diff --git a/native/src/main/resources/META-INF/native-image/io.ballerina.stdlib/soap-native/proxy-config.json b/native/src/main/resources/META-INF/native-image/io.ballerina.stdlib/soap-native/proxy-config.json new file mode 100644 index 0000000..0d4f101 --- /dev/null +++ b/native/src/main/resources/META-INF/native-image/io.ballerina.stdlib/soap-native/proxy-config.json @@ -0,0 +1,2 @@ +[ +] diff --git a/native/src/main/resources/META-INF/native-image/io.ballerina.stdlib/soap-native/reflect-config.json b/native/src/main/resources/META-INF/native-image/io.ballerina.stdlib/soap-native/reflect-config.json new file mode 100644 index 0000000..4b59c10 --- /dev/null +++ b/native/src/main/resources/META-INF/native-image/io.ballerina.stdlib/soap-native/reflect-config.json @@ -0,0 +1,21 @@ +[ +{ + "name":"java.security.SecureRandomParameters" +}, +{ + "name":"java.util.concurrent.atomic.AtomicBoolean", + "fields":[{"name":"value"}] +}, +{ + "name":"java.util.concurrent.atomic.AtomicReference", + "fields":[{"name":"value"}] +}, +{ + "name":"sun.security.provider.NativePRNG", + "methods":[{"name":"","parameterTypes":[] }, {"name":"","parameterTypes":["java.security.SecureRandomParameters"] }] +}, +{ + "name":"sun.security.provider.SHA", + "methods":[{"name":"","parameterTypes":[] }] +} +] diff --git a/native/src/main/resources/META-INF/native-image/io.ballerina.stdlib/soap-native/resource-config.json b/native/src/main/resources/META-INF/native-image/io.ballerina.stdlib/soap-native/resource-config.json new file mode 100644 index 0000000..09cabe1 --- /dev/null +++ b/native/src/main/resources/META-INF/native-image/io.ballerina.stdlib/soap-native/resource-config.json @@ -0,0 +1,9 @@ +{ + "resources":{ + "includes":[{ + "pattern":"\\QMETA-INF/services/org.slf4j.spi.SLF4JServiceProvider\\E" + }, { + "pattern":"\\Qlogging.properties\\E" + }]}, + "bundles":[] +} diff --git a/native/src/main/resources/META-INF/native-image/io.ballerina.stdlib/soap-native/serialization-config.json b/native/src/main/resources/META-INF/native-image/io.ballerina.stdlib/soap-native/serialization-config.json new file mode 100644 index 0000000..f3d7e06 --- /dev/null +++ b/native/src/main/resources/META-INF/native-image/io.ballerina.stdlib/soap-native/serialization-config.json @@ -0,0 +1,8 @@ +{ + "types":[ + ], + "lambdaCapturingTypes":[ + ], + "proxies":[ + ] +} From dff060d97e6d1bd8692bb568c0837a94b83c5bec Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Fri, 6 Oct 2023 14:53:17 +0530 Subject: [PATCH 126/189] Fix description name of the build.gradle file --- ballerina/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ballerina/build.gradle b/ballerina/build.gradle index e2b0be7..c112a14 100644 --- a/ballerina/build.gradle +++ b/ballerina/build.gradle @@ -32,7 +32,7 @@ buildscript { } -description = 'Ballerina - SOAP Java Utils' +description = 'Ballerina - SOAP Module' def packageName = "soap" def packageOrg = "ballerina" From 3c0fc41547c3f3b349ad44ed6ac334ce562378ba Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Fri, 6 Oct 2023 14:56:28 +0530 Subject: [PATCH 127/189] Add GraalVM native image dependency --- native/build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/native/build.gradle b/native/build.gradle index 8784812..2a861fb 100644 --- a/native/build.gradle +++ b/native/build.gradle @@ -32,6 +32,7 @@ dependencies { implementation 'org.apache.wss4j:wss4j-ws-security-dom:3.0.1' implementation 'org.apache.santuario:xmlsec:3.0.2' implementation 'org.apache.wss4j:wss4j-ws-security-common:3.0.1' + compileOnly group: 'org.graalvm.nativeimage', name: 'svm', version: '22.2.0' } checkstyle { From 74f1b931c80fd1397aaa0a76d57eba5da68b5e53 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Fri, 6 Oct 2023 15:12:00 +0530 Subject: [PATCH 128/189] Apply changes to adhere code conventions --- ballerina/modules/soap11/soap11.bal | 5 +++-- ballerina/modules/wssec/encryption.bal | 6 ++---- ballerina/modules/wssec/signature.bal | 1 - ballerina/modules/wssec/ws_security_methods.bal | 5 +++-- ballerina/soap_utils.bal | 2 +- 5 files changed, 9 insertions(+), 10 deletions(-) diff --git a/ballerina/modules/soap11/soap11.bal b/ballerina/modules/soap11/soap11.bal index 4a31e66..d1b34eb 100644 --- a/ballerina/modules/soap11/soap11.bal +++ b/ballerina/modules/soap11/soap11.bal @@ -60,7 +60,7 @@ public client class Client { securedBody = check soap:applySecurityPolicies(self.inboundSecurity, check body[0].getXml()); } xml response = check soap:sendReceive(securedBody, self.soapClient, - action, headers, false); + action, headers, false); wssec:OutboundSecurityConfig? outboundSecurity = self.outboundSecurity; do { if outboundSecurity !is () { @@ -85,7 +85,8 @@ public client class Client { # + action - SOAP action as a `string` # + headers - SOAP headers as a `map` # + return - If successful, returns `nil`. Else, returns an error - remote function sendOnly(xml|mime:Entity[] body, string action, map headers = {}) returns Error? { + remote function sendOnly(xml|mime:Entity[] body, string action, + map headers = {}) returns Error? { do { xml securedBody; if body is xml { diff --git a/ballerina/modules/wssec/encryption.bal b/ballerina/modules/wssec/encryption.bal index 107a6fd..b9f2a8c 100644 --- a/ballerina/modules/wssec/encryption.bal +++ b/ballerina/modules/wssec/encryption.bal @@ -25,8 +25,7 @@ class Encryption { } function encryptData(string dataString, EncryptionAlgorithm encryptionAlgorithm, - crypto:PublicKey|crypto:PrivateKey key) - returns byte[]|Error { + crypto:PublicKey|crypto:PrivateKey key) returns byte[]|Error { byte[] data = dataString.toBytes(); do { return check crypto:encryptRsaEcb(data, key); @@ -36,8 +35,7 @@ class Encryption { } public function decryptData(byte[] cipherText, EncryptionAlgorithm encryptionAlgorithm, - crypto:PublicKey|crypto:PrivateKey key) - returns byte[]|Error { + crypto:PublicKey|crypto:PrivateKey key) returns byte[]|Error { do { return check crypto:decryptRsaEcb(cipherText, key); } on fail var e { diff --git a/ballerina/modules/wssec/signature.bal b/ballerina/modules/wssec/signature.bal index f9fc76d..560a36e 100644 --- a/ballerina/modules/wssec/signature.bal +++ b/ballerina/modules/wssec/signature.bal @@ -64,7 +64,6 @@ class Signature { return check crypto:verifyRsaSha512Signature(data, signature, publicKey); } } - } on fail var e { return error Error(e.message()); } diff --git a/ballerina/modules/wssec/ws_security_methods.bal b/ballerina/modules/wssec/ws_security_methods.bal index e479b65..5daa6ce 100644 --- a/ballerina/modules/wssec/ws_security_methods.bal +++ b/ballerina/modules/wssec/ws_security_methods.bal @@ -125,8 +125,9 @@ public function applyUsernameToken(xml envelope, *UsernameTokenConfig usernameTo Document document = check new (envelope); WSSecurityHeader wsSecurityHeader = check addSecurityHeader(document); WsSecurity wsSecurity = new; - string securedEnvelope = check wsSecurity.applyUsernameTokenPolicy(wsSecurityHeader, usernameToken.username, - usernameToken.password, usernameToken.passwordType); + string securedEnvelope = check wsSecurity + .applyUsernameTokenPolicy(wsSecurityHeader, usernameToken.username, usernameToken.password, + usernameToken.passwordType); return convertStringToXml(securedEnvelope); } diff --git a/ballerina/soap_utils.bal b/ballerina/soap_utils.bal index c1b27af..67faca8 100644 --- a/ballerina/soap_utils.bal +++ b/ballerina/soap_utils.bal @@ -75,7 +75,7 @@ public function applySecurityPolicies(wssec:InboundSecurityConfig|wssec:InboundS } public function applyOutboundConfig(wssec:OutboundSecurityConfig outboundSecurity, xml envelope) - returns xml|wssec:Error|Error { + returns xml|Error { xmlns "http://schemas.xmlsoap.org/soap/envelope/" as soap; xml soapEnvelope = envelope; do { From 032432d974b0b1a790edac8f8ec94f434a5f5e1a Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Mon, 9 Oct 2023 11:04:48 +0530 Subject: [PATCH 129/189] Add necessary configurations for GraalVM checks --- .gitignore | 1 + .../soap-native/jni-config.json | 14 -------------- .../soap-native/predefined-classes-config.json | 8 -------- .../soap-native/proxy-config.json | 2 -- .../soap-native/reflect-config.json | 18 +++++++----------- .../soap-native/resource-config.json | 10 +++++++--- .../soap-native/serialization-config.json | 8 -------- 7 files changed, 15 insertions(+), 46 deletions(-) delete mode 100644 native/src/main/resources/META-INF/native-image/io.ballerina.stdlib/soap-native/jni-config.json delete mode 100644 native/src/main/resources/META-INF/native-image/io.ballerina.stdlib/soap-native/predefined-classes-config.json delete mode 100644 native/src/main/resources/META-INF/native-image/io.ballerina.stdlib/soap-native/proxy-config.json delete mode 100644 native/src/main/resources/META-INF/native-image/io.ballerina.stdlib/soap-native/serialization-config.json diff --git a/.gitignore b/.gitignore index 8376c1c..1272c57 100644 --- a/.gitignore +++ b/.gitignore @@ -40,3 +40,4 @@ velocity.log* *Ballerina.lock .vscode +config-dir diff --git a/native/src/main/resources/META-INF/native-image/io.ballerina.stdlib/soap-native/jni-config.json b/native/src/main/resources/META-INF/native-image/io.ballerina.stdlib/soap-native/jni-config.json deleted file mode 100644 index c58277c..0000000 --- a/native/src/main/resources/META-INF/native-image/io.ballerina.stdlib/soap-native/jni-config.json +++ /dev/null @@ -1,14 +0,0 @@ -[ -{ - "name":"ballerina.soap.0.$_init", - "methods":[{"name":"main","parameterTypes":["java.lang.String[]"] }] -}, -{ - "name":"java.lang.String", - "methods":[{"name":"lastIndexOf","parameterTypes":["int"] }, {"name":"substring","parameterTypes":["int"] }] -}, -{ - "name":"java.lang.System", - "methods":[{"name":"getProperty","parameterTypes":["java.lang.String"] }, {"name":"setProperty","parameterTypes":["java.lang.String","java.lang.String"] }] -} -] diff --git a/native/src/main/resources/META-INF/native-image/io.ballerina.stdlib/soap-native/predefined-classes-config.json b/native/src/main/resources/META-INF/native-image/io.ballerina.stdlib/soap-native/predefined-classes-config.json deleted file mode 100644 index 0e79b2c..0000000 --- a/native/src/main/resources/META-INF/native-image/io.ballerina.stdlib/soap-native/predefined-classes-config.json +++ /dev/null @@ -1,8 +0,0 @@ -[ - { - "type":"agent-extracted", - "classes":[ - ] - } -] - diff --git a/native/src/main/resources/META-INF/native-image/io.ballerina.stdlib/soap-native/proxy-config.json b/native/src/main/resources/META-INF/native-image/io.ballerina.stdlib/soap-native/proxy-config.json deleted file mode 100644 index 0d4f101..0000000 --- a/native/src/main/resources/META-INF/native-image/io.ballerina.stdlib/soap-native/proxy-config.json +++ /dev/null @@ -1,2 +0,0 @@ -[ -] diff --git a/native/src/main/resources/META-INF/native-image/io.ballerina.stdlib/soap-native/reflect-config.json b/native/src/main/resources/META-INF/native-image/io.ballerina.stdlib/soap-native/reflect-config.json index 4b59c10..3cfa8bd 100644 --- a/native/src/main/resources/META-INF/native-image/io.ballerina.stdlib/soap-native/reflect-config.json +++ b/native/src/main/resources/META-INF/native-image/io.ballerina.stdlib/soap-native/reflect-config.json @@ -1,21 +1,17 @@ [ { - "name":"java.security.SecureRandomParameters" + "name":"org.apache.commons.pool.impl.EvictionTimer" }, { - "name":"java.util.concurrent.atomic.AtomicBoolean", - "fields":[{"name":"value"}] -}, -{ - "name":"java.util.concurrent.atomic.AtomicReference", - "fields":[{"name":"value"}] + "name":"org.apache.wss4j.dom.transform.AttachmentCiphertextTransform", + "methods":[{"name":"","parameterTypes":[] }] }, { - "name":"sun.security.provider.NativePRNG", - "methods":[{"name":"","parameterTypes":[] }, {"name":"","parameterTypes":["java.security.SecureRandomParameters"] }] + "name":"org.apache.xml.security.c14n.implementations.CanonicalizerPhysical", + "methods":[{"name":"","parameterTypes":[] }] }, { - "name":"sun.security.provider.SHA", - "methods":[{"name":"","parameterTypes":[] }] + "name":"org.apache.xml.security.utils.XMLUtils", + "fields":[{"name":"ignoreLineBreaks"}] } ] diff --git a/native/src/main/resources/META-INF/native-image/io.ballerina.stdlib/soap-native/resource-config.json b/native/src/main/resources/META-INF/native-image/io.ballerina.stdlib/soap-native/resource-config.json index 09cabe1..f9fda78 100644 --- a/native/src/main/resources/META-INF/native-image/io.ballerina.stdlib/soap-native/resource-config.json +++ b/native/src/main/resources/META-INF/native-image/io.ballerina.stdlib/soap-native/resource-config.json @@ -2,8 +2,12 @@ "resources":{ "includes":[{ "pattern":"\\QMETA-INF/services/org.slf4j.spi.SLF4JServiceProvider\\E" - }, { - "pattern":"\\Qlogging.properties\\E" }]}, - "bundles":[] + "bundles":[{ + "name":"messages.wss4j_errors", + "locales":[""] + }, { + "name":"org/apache/xml/security/resource/xmlsecurity", + "locales":["en"] + }] } diff --git a/native/src/main/resources/META-INF/native-image/io.ballerina.stdlib/soap-native/serialization-config.json b/native/src/main/resources/META-INF/native-image/io.ballerina.stdlib/soap-native/serialization-config.json deleted file mode 100644 index f3d7e06..0000000 --- a/native/src/main/resources/META-INF/native-image/io.ballerina.stdlib/soap-native/serialization-config.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "types":[ - ], - "lambdaCapturingTypes":[ - ], - "proxies":[ - ] -} From c5e5991bdb78b7cb6f5b6766c518a869d362da88 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Mon, 9 Oct 2023 17:03:47 +0530 Subject: [PATCH 130/189] Apply changes according to suggestions --- ballerina/Ballerina.toml | 11 ++++++++++- build-config/resources/Ballerina.toml | 11 ++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/ballerina/Ballerina.toml b/ballerina/Ballerina.toml index 59dcfea..2b70fd9 100644 --- a/ballerina/Ballerina.toml +++ b/ballerina/Ballerina.toml @@ -3,7 +3,7 @@ org = "ballerina" name = "soap" version = "0.2.0" authors = ["Ballerina"] -export=["soap.soap11", "soap.soap12"] +export=["soap", "soap.soap11", "soap.soap12"] keywords = ["soap"] repository = "https://github.com/ballerina-platform/module-ballerina-soap" icon = "icon.png" @@ -17,12 +17,21 @@ observabilityIncluded = true graalvmCompatible = true [[platform.java17.dependency]] +groupId = "io.ballerina.stdlib" +artifactId = "soap-native" +version = "0.2.0" path = "../native/build/libs/soap-native-0.2.0-SNAPSHOT.jar" [[platform.java17.dependency]] +groupId = "org.apache.wss4j" +artifactId = "wss4j-ws-security-dom" +version = "3.0.1" path = "./lib/wss4j-ws-security-dom-3.0.1.jar" [[platform.java17.dependency]] +groupId = "org.apache.wss4j" +artifactId = "wss4j-ws-security-common" +version = "3.0.1" path = "./lib/wss4j-ws-security-common-3.0.1.jar" [[platform.java17.dependency]] diff --git a/build-config/resources/Ballerina.toml b/build-config/resources/Ballerina.toml index 5fdaee2..948bf50 100644 --- a/build-config/resources/Ballerina.toml +++ b/build-config/resources/Ballerina.toml @@ -3,7 +3,7 @@ org = "ballerina" name = "soap" version = "@toml.version@" authors = ["Ballerina"] -export=["soap.soap11", "soap.soap12"] +export=["soap", "soap.soap11", "soap.soap12"] keywords = ["soap"] repository = "https://github.com/ballerina-platform/module-ballerina-soap" icon = "icon.png" @@ -17,12 +17,21 @@ observabilityIncluded = true graalvmCompatible = true [[platform.java17.dependency]] +groupId = "io.ballerina.stdlib" +artifactId = "soap-native" +version = "0.2.0" path = "../native/build/libs/soap-native-0.2.0-SNAPSHOT.jar" [[platform.java17.dependency]] +groupId = "org.apache.wss4j" +artifactId = "wss4j-ws-security-dom" +version = "3.0.1" path = "./lib/wss4j-ws-security-dom-3.0.1.jar" [[platform.java17.dependency]] +groupId = "org.apache.wss4j" +artifactId = "wss4j-ws-security-common" +version = "3.0.1" path = "./lib/wss4j-ws-security-common-3.0.1.jar" [[platform.java17.dependency]] From 927c3fae18a882edc1dcb0b8b46bc40ea689fb01 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Mon, 9 Oct 2023 17:04:31 +0530 Subject: [PATCH 131/189] Add documentations for the public modules --- README.md | 198 ++++++++++++++++++++++++++- ballerina/Module.md | 206 ++++++++++++++++++++++++++++- ballerina/Package.md | 197 ++++++++++++++++++++++++++- ballerina/modules/soap11/Module.md | 166 +++++++++++++++++++++++ ballerina/modules/soap12/Module.md | 166 +++++++++++++++++++++++ ballerina/types.bal | 6 + 6 files changed, 932 insertions(+), 7 deletions(-) create mode 100644 ballerina/modules/soap11/Module.md create mode 100644 ballerina/modules/soap12/Module.md diff --git a/README.md b/README.md index c196deb..6b65853 100644 --- a/README.md +++ b/README.md @@ -9,9 +9,203 @@ Ballerina SOAP Library [![Github issues](https://img.shields.io/github/issues/ballerina-platform/ballerina-standard-library/module/soap.svg?label=Open%20Issues)](https://github.com/ballerina-platform/ballerina-standard-library/labels/module%2Fyaml) [![codecov](https://codecov.io/gh/ballerina-platform/module-ballerina-soap/branch/master/graph/badge.svg)](https://codecov.io/gh/ballerina-platform/module-ballerina-soap) -This library provides APIs to send an ordinary XML request to a SOAP backend by specifying the necessary details to construct a SOAP envelope. +This module offers a set of APIs that facilitate the transmission of XML requests to a SOAP backend. It excels in managing security policies within SOAP requests, ensuring the transmission of secured SOAP envelopes. Moreover, it possesses the capability to efficiently extract data from security-applied SOAP responses. -Soap module abstracts out the details of the creation of a SOAP envelope, headers, and the body in a SOAP message. +SOAP module abstracts out the details of the creation of a SOAP envelope, headers, and the body in a SOAP message. + +## Client + +The `Client` is used to connect to and interact with `SOAP` endpoints. + +### SOAP 1.1 Client + +```ballerina +import ballerina/soap:soap11; + +soap11:Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL"); +``` + +### SOAP 1.2 Client + +```ballerina +import ballerina/soap:soap12; + +soap12:Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL"); +``` + +## APIs associated with SOAP + +- **Send & Receive**: Sends SOAP request and receives a response. +- **Send Only**: Fires and forgets requests. Sends the request without the possibility of any response from the service. + +The SOAP 1.1 specification requires the inclusion of the `action` parameter as a mandatory component within its APIs. In contrast, SOAP 1.2 relaxes this requirement, making the action parameter optional. + +### Example: Send & Receive + +```ballerina +import ballerina/soap:soap11; + +public function main() returns error? { + soap11:Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL"); + + xml envelope = xml ` + + + 2 + 3 + + + `; + xml|mime:Entity[] response = check soapClient->sendReceive(envelope, "http://tempuri.org/Add"); +} +``` + +### Example: Send Only + +```ballerina +import ballerina/soap:soap11; + +public function main() returns error? { + soap11:Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL"); + + xml envelope = xml ` + + + 2 + 3 + + + `; + xml|mime:Entity[] response = check soapClient->sendOnly(envelope, "http://tempuri.org/Add"); +} +``` + +## Security + +The SOAP client module introduces a robust framework for configuring security measures in SOAP communication. Security is a critical concern when exchanging data via web services, and this module offers comprehensive options to fortify SOAP requests and responses. + +There are two primary security configurations available for SOAP clients: + +- `inboundSecurity`: This configuration is applied to the SOAP envelope when a request is made. It includes various ws security policies such as Username Token, Timestamp Token, X509 Token, Symmetric Binding, Asymmetric Binding, and Transport Binding, either individually or in combination with each other. + +- `outboundSecurity`: This configuration is applied to the SOAP envelope when a response is received. Its purpose is to decrypt the data within the envelope and verify the digital signature for security validation. + +### Policies + +This library currently supports the following WS Security policies: + +- **Username Token**: Provides authentication through username and password credentials. +- **Timestamp Token**: Enhances message integrity by incorporating timestamp information. +- **X509 Token**: Allows the use of X.509 certificates for secure communication. +- **Symmetric Binding**: Enables symmetric key-based security mechanisms. +- **Asymmetric Binding**: Facilitates the use of asymmetric cryptography for enhanced security. + +These policies empower SOAP clients to enhance the security of their web service communications by selecting and implementing the appropriate security mechanisms to safeguard their SOAP envelopes. + +### Security Policy Configuration Types + +#### Inbound Security Configurations + +- `TimestampTokenConfig`: Represents the record for Timestamp Token policy. + - Fields: + - `int` timeToLive : The time to get expired + +- `UsernameTokenConfig`: Represents the record for Username Token policy. + - Fields: + - `string` username : The name of the user + - `string` password : The password of the user + - `PasswordType` passwordType : The password type of the username token + +- `SymmetricBindingConfig`: Represents the record for Symmetric Binding policy. + - Fields: + - `crypto:PrivateKey` symmetricKey : The key to sign and encrypt the SOAP envelope + - `crypto:PublicKey` servicePublicKey : The key to encrypt the symmetric key + - `SignatureAlgorithm` signatureAlgorithm : The algorithm to sign the SOAP envelope + - `EncryptionAlgorithm` encryptionAlgorithm : The algorithm to encrypt the SOAP envelope + - `string` x509Token : The path or token of the X509 certificate + +- `AsymmetricBindingConfig`: Represents the record for Username Token with Asymmetric Binding policy. + - Fields: + - `crypto:PrivateKey` signatureKey : The private key to sign the SOAP envelope + - `crypto:PublicKey` encryptionKey : The public key to encrypt the SOAP body + - `SignatureAlgorithm` signatureAlgorithm : The algorithm to sign the SOAP envelope + - `EncryptionAlgorithm` encryptionAlgorithm : The algorithm to encrypt the SOAP body + - `string` x509Token : field description + +#### Outbound Security Configurations + +- `OutboundSecurityConfig`: Represents the record for outbound security configurations to verify and decrypt SOAP envelopes. + - Fields: + - `crypto:PublicKey` verificationKey : The public key to verify the signature of the SOAP envelope + - `crypto:PrivateKey`|`crypto:PublicKey` decryptionKey : The private key to decrypt the SOAP envelope + - `SignatureAlgorithm` signatureAlgorithm : The algorithm to verify the SOAP envelope + - `EncryptionAlgorithm` decryptionAlgorithm : The algorithm to decrypt the SOAP body + +### Apply Security Policies + +#### SOAP 1.1 Client: UsernameToken and TranportBinding Policy + +``` +import ballerina/crypto; +import ballerina/mime; +import ballerina/soap; +import ballerina/soap:soap11; + +public function main() returns error? { + soap11:Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL", + { + inboundSecurity: [ + { + username: "username", + password: "password", + passwordType: soap:TEXT + }, + TRANSPORT_BINDING + ] + }); + + xml envelope = xml ` + + + 2 + 3 + + + `; + xml|mime:Entity[] response = check soapClient->sendReceive(envelope, "http://tempuri.org/Add"); +} +``` + +#### SOAP 1.2 Client with Asymmetric Binding and Outbound Security Configuration + +```ballerina +import ballerina/crypto; +import ballerina/mime; +import ballerina/soap; +import ballerina/soap:soap12; + +public function main() returns error? { + crypto:PrivateKey clientPrivateKey = ...// + crypto:PublicKey clientPublicKey = ...// + ​​crypto:PublicKey serverPublicKey = ...// + + soap12:Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL", + { + inboundSecurity: { + signatureAlgorithm: soap:RSA_SHA256, + encryptionAlgorithm: soap:RSA_ECB, + signatureKey: clientPrivateKey, + encryptionKey: serverPublicKey, + }, + outboundSecurity: { + verificationKey: serverPublicKey, + signatureAlgorithm: soap:RSA_SHA256, + decryptionKey: clientPrivateKey, + decryptionAlgorithm: soap:RSA_ECB + } + }); +} +``` ## Issues and projects diff --git a/ballerina/Module.md b/ballerina/Module.md index a096113..116be7e 100644 --- a/ballerina/Module.md +++ b/ballerina/Module.md @@ -1,7 +1,207 @@ ## Overview -This module provides APIs to send an ordinary XML request to a SOAP backend by specifying the necessary details to construct a SOAP envelope. +This module offers a set of APIs that facilitate the transmission of XML requests to a SOAP backend. It excels in managing security policies within SOAP requests, ensuring the transmission of secured SOAP envelopes. Moreover, it possesses the capability to efficiently extract data from security-applied SOAP responses. -Soap module abstracts out the details of the creation of a SOAP envelope, headers, and the body in a SOAP message. +SOAP module abstracts out the details of the creation of a SOAP envelope, headers, and the body in a SOAP message. -For information on the operations, which you can perform with the `soap` module, see the below **Functions**. +## Client + +The `Client` is used to connect to and interact with `SOAP` endpoints. + +### SOAP 1.1 Client + +```ballerina +import ballerina/soap:soap11; + +soap11:Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL"); +``` + +### SOAP 1.2 Client + +```ballerina +import ballerina/soap:soap12; + +soap12:Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL"); +``` + +## APIs associated with SOAP + +- **Send & Receive**: Sends SOAP request and receives a response. +- **Send Only**: Fires and forgets requests. Sends the request without the possibility of any response from the service. + +The SOAP 1.1 specification requires the inclusion of the `action` parameter as a mandatory component within its APIs. In contrast, SOAP 1.2 relaxes this requirement, making the action parameter optional. + +### Example: Send & Receive + +```ballerina +import ballerina/soap:soap11; + +public function main() returns error? { + soap11:Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL"); + + xml envelope = xml ` + + + 2 + 3 + + + `; + xml|mime:Entity[] response = check soapClient->sendReceive(envelope, "http://tempuri.org/Add"); +} +``` + +### Example: Send Only + +```ballerina +import ballerina/soap:soap11; + +public function main() returns error? { + soap11:Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL"); + + xml envelope = xml ` + + + 2 + 3 + + + `; + xml|mime:Entity[] response = check soapClient->sendOnly(envelope, "http://tempuri.org/Add"); +} +``` +## Security + +The SOAP client module introduces a robust framework for configuring security measures in SOAP communication. Security is a critical concern when exchanging data via web services, and this module offers comprehensive options to fortify SOAP requests and responses. + +There are two primary security configurations available for SOAP clients: + +- `inboundSecurity`: This configuration is applied to the SOAP envelope when a request is made. It includes various ws security policies such as Username Token, Timestamp Token, X509 Token, Symmetric Binding, Asymmetric Binding, and Transport Binding, either individually or in combination with each other. + +- `outboundSecurity`: This configuration is applied to the SOAP envelope when a response is received. Its purpose is to decrypt the data within the envelope and verify the digital signature for security validation. + +### Policies + +This library currently supports the following WS Security policies: + +- **Username Token**: Provides authentication through username and password credentials. +- **Timestamp Token**: Enhances message integrity by incorporating timestamp information. +- **X509 Token**: Allows the use of X.509 certificates for secure communication. +- **Symmetric Binding**: Enables symmetric key-based security mechanisms. +- **Asymmetric Binding**: Facilitates the use of asymmetric cryptography for enhanced security. + +These policies empower SOAP clients to enhance the security of their web service communications by selecting and implementing the appropriate security mechanisms to safeguard their SOAP envelopes. + +### Security Policy Configuration Types + +#### Inbound Security Configurations + +- `TimestampTokenConfig`: Represents the record for Timestamp Token policy. + - Fields: + - `int` timeToLive : The time to get expired + +- `UsernameTokenConfig`: Represents the record for Username Token policy. + - Fields: + - `string` username : The name of the user + - `string` password : The password of the user + - `PasswordType` passwordType : The password type of the username token + +- `SymmetricBindingConfig`: Represents the record for Symmetric Binding policy. + - Fields: + - `crypto:PrivateKey` symmetricKey : The key to sign and encrypt the SOAP envelope + - `crypto:PublicKey` servicePublicKey : The key to encrypt the symmetric key + - `SignatureAlgorithm` signatureAlgorithm : The algorithm to sign the SOAP envelope + - `EncryptionAlgorithm` encryptionAlgorithm : The algorithm to encrypt the SOAP envelope + - `string` x509Token : The path or token of the X509 certificate + +- `AsymmetricBindingConfig`: Represents the record for Username Token with Asymmetric Binding policy. + - Fields: + - `crypto:PrivateKey` signatureKey : The private key to sign the SOAP envelope + - `crypto:PublicKey` encryptionKey : The public key to encrypt the SOAP body + - `SignatureAlgorithm` signatureAlgorithm : The algorithm to sign the SOAP envelope + - `EncryptionAlgorithm` encryptionAlgorithm : The algorithm to encrypt the SOAP body + - `string` x509Token : field description + +#### Outbound Security Configurations + +- `OutboundSecurityConfig`: Represents the record for outbound security configurations to verify and decrypt SOAP envelopes. + - Fields: + - `crypto:PublicKey` verificationKey : The public key to verify the signature of the SOAP envelope + - `crypto:PrivateKey`|`crypto:PublicKey` decryptionKey : The private key to decrypt the SOAP envelope + - `SignatureAlgorithm` signatureAlgorithm : The algorithm to verify the SOAP envelope + - `EncryptionAlgorithm` decryptionAlgorithm : The algorithm to decrypt the SOAP body + +### Apply Security Policies + +#### SOAP 1.1 Client: UsernameToken and TranportBinding Policy + +``` +import ballerina/crypto; +import ballerina/mime; +import ballerina/soap; +import ballerina/soap:soap11; + +public function main() returns error? { + soap11:Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL", + { + inboundSecurity: [ + { + username: "username", + password: "password", + passwordType: soap:TEXT + }, + TRANSPORT_BINDING + ] + }); + + xml envelope = xml ` + + + 2 + 3 + + + `; + xml|mime:Entity[] response = check soapClient->sendReceive(envelope, "http://tempuri.org/Add"); +} +``` + +#### SOAP 1.2 Client with Asymmetric Binding and Outbound Security Configuration + +```ballerina +import ballerina/crypto; +import ballerina/mime; +import ballerina/soap; +import ballerina/soap:soap12; + +public function main() returns error? { + crypto:PrivateKey clientPrivateKey = ...// + crypto:PublicKey clientPublicKey = ...// + ​​crypto:PublicKey serverPublicKey = ...// + + soap12:Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL", + { + inboundSecurity: { + signatureAlgorithm: soap:RSA_SHA256, + encryptionAlgorithm: soap:RSA_ECB, + signatureKey: clientPrivateKey, + encryptionKey: serverPublicKey, + }, + outboundSecurity: { + verificationKey: serverPublicKey, + signatureAlgorithm: soap:RSA_SHA256, + decryptionKey: clientPrivateKey, + decryptionAlgorithm: soap:RSA_ECB + } + }); +} +``` + +## Report issues + +To report bugs, request new features, start new discussions, view project boards, etc., go to the [Ballerina standard library parent repository](https://github.com/ballerina-platform/ballerina-standard-library). + +## Useful links + +- Chat live with us via our [Discord server](https://discord.gg/ballerinalang). +- Post all technical questions on Stack Overflow with the [#ballerina](https://stackoverflow.com/questions/tagged/ballerina) tag. diff --git a/ballerina/Package.md b/ballerina/Package.md index 1a43586..6b690af 100644 --- a/ballerina/Package.md +++ b/ballerina/Package.md @@ -1,8 +1,201 @@ ## Package overview -This module provides APIs to send an ordinary XML request to a SOAP backend by specifying the necessary details to construct a SOAP envelope. +This module offers a set of APIs that facilitate the transmission of XML requests to a SOAP backend. It excels in managing security policies within SOAP requests, ensuring the transmission of secured SOAP envelopes. Moreover, it possesses the capability to efficiently extract data from security-applied SOAP responses. -Soap module abstracts out the details of the creation of a SOAP envelope, headers, and the body in a SOAP message. +SOAP module abstracts out the details of the creation of a SOAP envelope, headers, and the body in a SOAP message. + +## Client + +The `Client` is used to connect to and interact with `SOAP` endpoints. + +### SOAP 1.1 Client + +```ballerina +import ballerina/soap:soap11; + +soap11:Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL"); +``` + +### SOAP 1.2 Client + +```ballerina +import ballerina/soap:soap12; + +soap12:Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL"); +``` + +## APIs associated with SOAP + +- **Send & Receive**: Sends SOAP request and receives a response. +- **Send Only**: Fires and forgets requests. Sends the request without the possibility of any response from the service. + +The SOAP 1.1 specification requires the inclusion of the `action` parameter as a mandatory component within its APIs. In contrast, SOAP 1.2 relaxes this requirement, making the action parameter optional. + +### Example: Send & Receive + +```ballerina +import ballerina/soap:soap11; + +public function main() returns error? { + soap11:Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL"); + + xml envelope = xml ` + + + 2 + 3 + + + `; + xml|mime:Entity[] response = check soapClient->sendReceive(envelope, "http://tempuri.org/Add"); +} +``` + +### Example: Send Only + +```ballerina +import ballerina/soap:soap11; + +public function main() returns error? { + soap11:Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL"); + + xml envelope = xml ` + + + 2 + 3 + + + `; + xml|mime:Entity[] response = check soapClient->sendOnly(envelope, "http://tempuri.org/Add"); +} +``` +## Security + +The SOAP client module introduces a robust framework for configuring security measures in SOAP communication. Security is a critical concern when exchanging data via web services, and this module offers comprehensive options to fortify SOAP requests and responses. + +There are two primary security configurations available for SOAP clients: + +- `inboundSecurity`: This configuration is applied to the SOAP envelope when a request is made. It includes various ws security policies such as Username Token, Timestamp Token, X509 Token, Symmetric Binding, Asymmetric Binding, and Transport Binding, either individually or in combination with each other. + +- `outboundSecurity`: This configuration is applied to the SOAP envelope when a response is received. Its purpose is to decrypt the data within the envelope and verify the digital signature for security validation. + +### Policies + +This library currently supports the following WS Security policies: + +- **Username Token**: Provides authentication through username and password credentials. +- **Timestamp Token**: Enhances message integrity by incorporating timestamp information. +- **X509 Token**: Allows the use of X.509 certificates for secure communication. +- **Symmetric Binding**: Enables symmetric key-based security mechanisms. +- **Asymmetric Binding**: Facilitates the use of asymmetric cryptography for enhanced security. + +These policies empower SOAP clients to enhance the security of their web service communications by selecting and implementing the appropriate security mechanisms to safeguard their SOAP envelopes. + +### Security Policy Configuration Types + +#### Inbound Security Configurations + +- `TimestampTokenConfig`: Represents the record for Timestamp Token policy. + - Fields: + - `int` timeToLive : The time to get expired + +- `UsernameTokenConfig`: Represents the record for Username Token policy. + - Fields: + - `string` username : The name of the user + - `string` password : The password of the user + - `PasswordType` passwordType : The password type of the username token + +- `SymmetricBindingConfig`: Represents the record for Symmetric Binding policy. + - Fields: + - `crypto:PrivateKey` symmetricKey : The key to sign and encrypt the SOAP envelope + - `crypto:PublicKey` servicePublicKey : The key to encrypt the symmetric key + - `SignatureAlgorithm` signatureAlgorithm : The algorithm to sign the SOAP envelope + - `EncryptionAlgorithm` encryptionAlgorithm : The algorithm to encrypt the SOAP envelope + - `string` x509Token : The path or token of the X509 certificate + +- `AsymmetricBindingConfig`: Represents the record for Username Token with Asymmetric Binding policy. + - Fields: + - `crypto:PrivateKey` signatureKey : The private key to sign the SOAP envelope + - `crypto:PublicKey` encryptionKey : The public key to encrypt the SOAP body + - `SignatureAlgorithm` signatureAlgorithm : The algorithm to sign the SOAP envelope + - `EncryptionAlgorithm` encryptionAlgorithm : The algorithm to encrypt the SOAP body + - `string` x509Token : field description + +#### Outbound Security Configurations + +- `OutboundSecurityConfig`: Represents the record for outbound security configurations to verify and decrypt SOAP envelopes. + - Fields: + - `crypto:PublicKey` verificationKey : The public key to verify the signature of the SOAP envelope + - `crypto:PrivateKey`|`crypto:PublicKey` decryptionKey : The private key to decrypt the SOAP envelope + - `SignatureAlgorithm` signatureAlgorithm : The algorithm to verify the SOAP envelope + - `EncryptionAlgorithm` decryptionAlgorithm : The algorithm to decrypt the SOAP body + +### Apply Security Policies + +#### SOAP 1.1 Client: UsernameToken and TranportBinding Policy + +``` +import ballerina/crypto; +import ballerina/mime; +import ballerina/soap; +import ballerina/soap:soap11; + +public function main() returns error? { + soap11:Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL", + { + inboundSecurity: [ + { + username: "username", + password: "password", + passwordType: soap:TEXT + }, + TRANSPORT_BINDING + ] + }); + + xml envelope = xml ` + + + 2 + 3 + + + `; + xml|mime:Entity[] response = check soapClient->sendReceive(envelope, "http://tempuri.org/Add"); +} +``` + +#### SOAP 1.2 Client with Asymmetric Binding and Outbound Security Configuration + +```ballerina +import ballerina/crypto; +import ballerina/mime; +import ballerina/soap; +import ballerina/soap:soap12; + +public function main() returns error? { + crypto:PrivateKey clientPrivateKey = ...// + crypto:PublicKey clientPublicKey = ...// + ​​crypto:PublicKey serverPublicKey = ...// + + soap12:Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL", + { + inboundSecurity: { + signatureAlgorithm: soap:RSA_SHA256, + encryptionAlgorithm: soap:RSA_ECB, + signatureKey: clientPrivateKey, + encryptionKey: serverPublicKey, + }, + outboundSecurity: { + verificationKey: serverPublicKey, + signatureAlgorithm: soap:RSA_SHA256, + decryptionKey: clientPrivateKey, + decryptionAlgorithm: soap:RSA_ECB + } + }); +} +``` ## Report issues diff --git a/ballerina/modules/soap11/Module.md b/ballerina/modules/soap11/Module.md new file mode 100644 index 0000000..0b541f0 --- /dev/null +++ b/ballerina/modules/soap11/Module.md @@ -0,0 +1,166 @@ +## Overview + +This module offers a set of APIs that facilitate the transmission of XML requests to a SOAP 1.1 backend. It excels in managing security policies within SOAP requests, ensuring the transmission of secured SOAP envelopes. Moreover, it possesses the capability to efficiently extract data from security-applied SOAP responses. + +SOAP module abstracts out the details of the creation of a SOAP envelope, headers, and the body in a SOAP message. + +## Client + +The `Client` is used to connect to and interact with `SOAP` 1.1 endpoints. + +### SOAP 1.1 Client + +```ballerina +import ballerina/soap:soap11; + +soap11:Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL"); +``` + +## APIs associated with SOAP + +- **Send & Receive**: Sends SOAP request and receives a response. +- **Send Only**: Fires and forgets requests. Sends the request without the possibility of any response from the service. + +The SOAP 1.1 specification requires the inclusion of the `action` parameter as a mandatory component within its APIs. In contrast, SOAP 1.2 relaxes this requirement, making the action parameter optional. + +### Example: Send & Receive + +```ballerina +import ballerina/soap:soap11; + +public function main() returns error? { + soap11:Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL"); + + xml envelope = xml ` + + + 2 + 3 + + + `; + xml|mime:Entity[] response = check soapClient->sendReceive(envelope, "http://tempuri.org/Add"); +} +``` + +### Example: Send Only + +```ballerina +import ballerina/soap:soap11; + +public function main() returns error? { + soap11:Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL"); + + xml envelope = xml ` + + + 2 + 3 + + + `; + xml|mime:Entity[] response = check soapClient->sendOnly(envelope, "http://tempuri.org/Add"); +} +``` +## Security + +The SOAP client module introduces a robust framework for configuring security measures in SOAP communication. Security is a critical concern when exchanging data via web services, and this module offers comprehensive options to fortify SOAP requests and responses. + +There are two primary security configurations available for SOAP clients: + +- `inboundSecurity`: This configuration is applied to the SOAP envelope when a request is made. It includes various ws security policies such as Username Token, Timestamp Token, X509 Token, Symmetric Binding, Asymmetric Binding, and Transport Binding, either individually or in combination with each other. + +- `outboundSecurity`: This configuration is applied to the SOAP envelope when a response is received. Its purpose is to decrypt the data within the envelope and verify the digital signature for security validation. + +### Policies + +This library currently supports the following WS Security policies: + +- **Username Token**: Provides authentication through username and password credentials. +- **Timestamp Token**: Enhances message integrity by incorporating timestamp information. +- **X509 Token**: Allows the use of X.509 certificates for secure communication. +- **Symmetric Binding**: Enables symmetric key-based security mechanisms. +- **Asymmetric Binding**: Facilitates the use of asymmetric cryptography for enhanced security. + +These policies empower SOAP clients to enhance the security of their web service communications by selecting and implementing the appropriate security mechanisms to safeguard their SOAP envelopes. + +### Security Policy Configuration Types + +#### Inbound Security Configurations + +- `TimestampTokenConfig`: Represents the record for Timestamp Token policy. + - Fields: + - `int` timeToLive : The time to get expired + +- `UsernameTokenConfig`: Represents the record for Username Token policy. + - Fields: + - `string` username : The name of the user + - `string` password : The password of the user + - `PasswordType` passwordType : The password type of the username token + +- `SymmetricBindingConfig`: Represents the record for Symmetric Binding policy. + - Fields: + - `crypto:PrivateKey` symmetricKey : The key to sign and encrypt the SOAP envelope + - `crypto:PublicKey` servicePublicKey : The key to encrypt the symmetric key + - `SignatureAlgorithm` signatureAlgorithm : The algorithm to sign the SOAP envelope + - `EncryptionAlgorithm` encryptionAlgorithm : The algorithm to encrypt the SOAP envelope + - `string` x509Token : The path or token of the X509 certificate + +- `AsymmetricBindingConfig`: Represents the record for Username Token with Asymmetric Binding policy. + - Fields: + - `crypto:PrivateKey` signatureKey : The private key to sign the SOAP envelope + - `crypto:PublicKey` encryptionKey : The public key to encrypt the SOAP body + - `SignatureAlgorithm` signatureAlgorithm : The algorithm to sign the SOAP envelope + - `EncryptionAlgorithm` encryptionAlgorithm : The algorithm to encrypt the SOAP body + - `string` x509Token : field description + +#### Outbound Security Configurations + +- `OutboundSecurityConfig`: Represents the record for outbound security configurations to verify and decrypt SOAP envelopes. + - Fields: + - `crypto:PublicKey` verificationKey : The public key to verify the signature of the SOAP envelope + - `crypto:PrivateKey`|`crypto:PublicKey` decryptionKey : The private key to decrypt the SOAP envelope + - `SignatureAlgorithm` signatureAlgorithm : The algorithm to verify the SOAP envelope + - `EncryptionAlgorithm` decryptionAlgorithm : The algorithm to decrypt the SOAP body + +### Apply Security Policies + +#### SOAP 1.1 Client with Asymmetric Binding and Outbound Security Configuration + +```ballerina +import ballerina/crypto; +import ballerina/mime; +import ballerina/soap; +import ballerina/soap:soap11; + +public function main() returns error? { + crypto:PrivateKey clientPrivateKey = ...// + crypto:PublicKey clientPublicKey = ...// + ​​crypto:PublicKey serverPublicKey = ...// + + soap11:Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL", + { + inboundSecurity: { + signatureAlgorithm: soap:RSA_SHA256, + encryptionAlgorithm: soap:RSA_ECB, + signatureKey: clientPrivateKey, + encryptionKey: serverPublicKey, + }, + outboundSecurity: { + verificationKey: serverPublicKey, + signatureAlgorithm: soap:RSA_SHA256, + decryptionKey: clientPrivateKey, + decryptionAlgorithm: soap:RSA_ECB + } + }); +} +``` + +## Report issues + +To report bugs, request new features, start new discussions, view project boards, etc., go to the [Ballerina standard library parent repository](https://github.com/ballerina-platform/ballerina-standard-library). + +## Useful links + +- Chat live with us via our [Discord server](https://discord.gg/ballerinalang). +- Post all technical questions on Stack Overflow with the [#ballerina](https://stackoverflow.com/questions/tagged/ballerina) tag. diff --git a/ballerina/modules/soap12/Module.md b/ballerina/modules/soap12/Module.md new file mode 100644 index 0000000..d8d6a01 --- /dev/null +++ b/ballerina/modules/soap12/Module.md @@ -0,0 +1,166 @@ +## Overview + +This module offers a set of APIs that facilitate the transmission of XML requests to a SOAP 1.2 backend. It excels in managing security policies within SOAP requests, ensuring the transmission of secured SOAP envelopes. Moreover, it possesses the capability to efficiently extract data from security-applied SOAP responses. + +SOAP module abstracts out the details of the creation of a SOAP envelope, headers, and the body in a SOAP message. + +## Client + +The `Client` is used to connect to and interact with `SOAP` 1.2 endpoints. + +### SOAP 1.2 Client + +```ballerina +import ballerina/soap:soap12; + +soap12:Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL"); +``` + +## APIs associated with SOAP + +- **Send & Receive**: Sends SOAP request and receives a response. +- **Send Only**: Fires and forgets requests. Sends the request without the possibility of any response from the service. + +The SOAP 1.1 specification requires the inclusion of the `action` parameter as a mandatory component within its APIs. In contrast, SOAP 1.2 relaxes this requirement, making the action parameter optional. + +### Example: Send & Receive + +```ballerina +import ballerina/soap:soap12; + +public function main() returns error? { + soap12:Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL"); + + xml envelope = xml ` + + + 2 + 3 + + + `; + xml|mime:Entity[] response = check soapClient->sendReceive(envelope, "http://tempuri.org/Add"); +} +``` + +### Example: Send Only + +```ballerina +import ballerina/soap:soap12; + +public function main() returns error? { + soap12:Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL"); + + xml envelope = xml ` + + + 2 + 3 + + + `; + xml|mime:Entity[] response = check soapClient->sendOnly(envelope, "http://tempuri.org/Add"); +} +``` +## Security + +The SOAP client module introduces a robust framework for configuring security measures in SOAP communication. Security is a critical concern when exchanging data via web services, and this module offers comprehensive options to fortify SOAP requests and responses. + +There are two primary security configurations available for SOAP clients: + +- `inboundSecurity`: This configuration is applied to the SOAP envelope when a request is made. It includes various ws security policies such as Username Token, Timestamp Token, X509 Token, Symmetric Binding, Asymmetric Binding, and Transport Binding, either individually or in combination with each other. + +- `outboundSecurity`: This configuration is applied to the SOAP envelope when a response is received. Its purpose is to decrypt the data within the envelope and verify the digital signature for security validation. + +### Policies + +This library currently supports the following WS Security policies: + +- **Username Token**: Provides authentication through username and password credentials. +- **Timestamp Token**: Enhances message integrity by incorporating timestamp information. +- **X509 Token**: Allows the use of X.509 certificates for secure communication. +- **Symmetric Binding**: Enables symmetric key-based security mechanisms. +- **Asymmetric Binding**: Facilitates the use of asymmetric cryptography for enhanced security. + +These policies empower SOAP clients to enhance the security of their web service communications by selecting and implementing the appropriate security mechanisms to safeguard their SOAP envelopes. + +### Security Policy Configuration Types + +#### Inbound Security Configurations + +- `TimestampTokenConfig`: Represents the record for Timestamp Token policy. + - Fields: + - `int` timeToLive : The time to get expired + +- `UsernameTokenConfig`: Represents the record for Username Token policy. + - Fields: + - `string` username : The name of the user + - `string` password : The password of the user + - `PasswordType` passwordType : The password type of the username token + +- `SymmetricBindingConfig`: Represents the record for Symmetric Binding policy. + - Fields: + - `crypto:PrivateKey` symmetricKey : The key to sign and encrypt the SOAP envelope + - `crypto:PublicKey` servicePublicKey : The key to encrypt the symmetric key + - `SignatureAlgorithm` signatureAlgorithm : The algorithm to sign the SOAP envelope + - `EncryptionAlgorithm` encryptionAlgorithm : The algorithm to encrypt the SOAP envelope + - `string` x509Token : The path or token of the X509 certificate + +- `AsymmetricBindingConfig`: Represents the record for Username Token with Asymmetric Binding policy. + - Fields: + - `crypto:PrivateKey` signatureKey : The private key to sign the SOAP envelope + - `crypto:PublicKey` encryptionKey : The public key to encrypt the SOAP body + - `SignatureAlgorithm` signatureAlgorithm : The algorithm to sign the SOAP envelope + - `EncryptionAlgorithm` encryptionAlgorithm : The algorithm to encrypt the SOAP body + - `string` x509Token : field description + +#### Outbound Security Configurations + +- `OutboundSecurityConfig`: Represents the record for outbound security configurations to verify and decrypt SOAP envelopes. + - Fields: + - `crypto:PublicKey` verificationKey : The public key to verify the signature of the SOAP envelope + - `crypto:PrivateKey`|`crypto:PublicKey` decryptionKey : The private key to decrypt the SOAP envelope + - `SignatureAlgorithm` signatureAlgorithm : The algorithm to verify the SOAP envelope + - `EncryptionAlgorithm` decryptionAlgorithm : The algorithm to decrypt the SOAP body + +### Apply Security Policies + +#### SOAP 1.2 Client with Asymmetric Binding and Outbound Security Configuration + +```ballerina +import ballerina/crypto; +import ballerina/mime; +import ballerina/soap; +import ballerina/soap:soap12; + +public function main() returns error? { + crypto:PrivateKey clientPrivateKey = ...// + crypto:PublicKey clientPublicKey = ...// + ​​crypto:PublicKey serverPublicKey = ...// + + soap12:Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL", + { + inboundSecurity: { + signatureAlgorithm: soap:RSA_SHA256, + encryptionAlgorithm: soap:RSA_ECB, + signatureKey: clientPrivateKey, + encryptionKey: serverPublicKey, + }, + outboundSecurity: { + verificationKey: serverPublicKey, + signatureAlgorithm: soap:RSA_SHA256, + decryptionKey: clientPrivateKey, + decryptionAlgorithm: soap:RSA_ECB + } + }); +} +``` + +## Report issues + +To report bugs, request new features, start new discussions, view project boards, etc., go to the [Ballerina standard library parent repository](https://github.com/ballerina-platform/ballerina-standard-library). + +## Useful links + +- Chat live with us via our [Discord server](https://discord.gg/ballerinalang). +- Post all technical questions on Stack Overflow with the [#ballerina](https://stackoverflow.com/questions/tagged/ballerina) tag. diff --git a/ballerina/types.bal b/ballerina/types.bal index a7eb41f..94ac981 100644 --- a/ballerina/types.bal +++ b/ballerina/types.bal @@ -14,6 +14,8 @@ // specific language governing permissions and limitations // under the License. +# Represents enums for all the supported password types. +# public enum PasswordType { TEXT, DIGEST, @@ -21,6 +23,8 @@ public enum PasswordType { DERIVED_KEY_DIGEST } +# Represents enums for all the supported signature algorithms. +# public enum SignatureAlgorithm { RSA_SHA1 = "http://www.w3.org/2000/09/xmldsig#rsa-sha1", RSA_SHA256 = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256", @@ -28,6 +32,8 @@ public enum SignatureAlgorithm { RSA_SHA512 = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha512" } +# Represents enums for all the supported encryption algorithms. +# public enum EncryptionAlgorithm { RSA_ECB = "http://www.w3.org/2001/04/xmlenc#rsa-1_5" } From 3d11e9e02d9abc13f93b1d49db7a730165aea75d Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Mon, 9 Oct 2023 20:39:33 +0530 Subject: [PATCH 132/189] Fix documentation issue --- README.md | 12 +++++++++++- ballerina/Module.md | 11 ++++++++++- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 6b65853..4ee3896 100644 --- a/README.md +++ b/README.md @@ -145,7 +145,7 @@ These policies empower SOAP clients to enhance the security of their web service #### SOAP 1.1 Client: UsernameToken and TranportBinding Policy -``` +```ballerina import ballerina/crypto; import ballerina/mime; import ballerina/soap; @@ -204,6 +204,16 @@ public function main() returns error? { decryptionAlgorithm: soap:RSA_ECB } }); + + xml envelope = xml ` + + + 2 + 3 + + + `; + xml|mime:Entity[] response = check soapClient->sendReceive(envelope, "http://tempuri.org/Add"); } ``` diff --git a/ballerina/Module.md b/ballerina/Module.md index 116be7e..56d15e4 100644 --- a/ballerina/Module.md +++ b/ballerina/Module.md @@ -135,7 +135,7 @@ These policies empower SOAP clients to enhance the security of their web service #### SOAP 1.1 Client: UsernameToken and TranportBinding Policy -``` +```ballerina import ballerina/crypto; import ballerina/mime; import ballerina/soap; @@ -194,6 +194,15 @@ public function main() returns error? { decryptionAlgorithm: soap:RSA_ECB } }); + xml envelope = xml ` + + + 2 + 3 + + + `; + xml|mime:Entity[] response = check soapClient->sendReceive(envelope, "http://tempuri.org/Add"); } ``` From fe486c3ccb1fba7a1e58d305166cd46d8ea39613 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Tue, 10 Oct 2023 12:22:27 +0530 Subject: [PATCH 133/189] [Automated] Update the native jar versions --- ballerina/Dependencies.toml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index 71ac60d..b3aa790 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -283,6 +283,7 @@ dependencies = [ {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "mime"}, {org = "ballerina", name = "regex"}, + {org = "ballerina", name = "tcp"}, {org = "ballerina", name = "test"}, {org = "ballerinai", name = "observe"} ] @@ -302,6 +303,18 @@ dependencies = [ {org = "ballerina", name = "time"} ] +[[package]] +org = "ballerina" +name = "tcp" +version = "1.9.0" +dependencies = [ + {org = "ballerina", name = "crypto"}, + {org = "ballerina", name = "jballerina.java"} +] +modules = [ + {org = "ballerina", packageName = "tcp", moduleName = "tcp"} +] + [[package]] org = "ballerina" name = "test" From 73563e5cf3a99fb325cec9badd9d03edc85dbde6 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Tue, 10 Oct 2023 15:26:02 +0530 Subject: [PATCH 134/189] [Automated] Update the native jar versions --- ballerina/Dependencies.toml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index b3aa790..4b977a0 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -101,6 +101,9 @@ dependencies = [ {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "lang.value"} ] +modules = [ + {org = "ballerina", packageName = "io", moduleName = "io"} +] [[package]] org = "ballerina" @@ -280,6 +283,7 @@ version = "0.2.0" dependencies = [ {org = "ballerina", name = "crypto"}, {org = "ballerina", name = "http"}, + {org = "ballerina", name = "io"}, {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "mime"}, {org = "ballerina", name = "regex"}, From 0634a1f6f9bb16877e192f221320a07a49896176 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Tue, 10 Oct 2023 17:06:13 +0530 Subject: [PATCH 135/189] [Automated] Update the native jar versions --- ballerina/Dependencies.toml | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index 4b977a0..71ac60d 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -101,9 +101,6 @@ dependencies = [ {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "lang.value"} ] -modules = [ - {org = "ballerina", packageName = "io", moduleName = "io"} -] [[package]] org = "ballerina" @@ -283,11 +280,9 @@ version = "0.2.0" dependencies = [ {org = "ballerina", name = "crypto"}, {org = "ballerina", name = "http"}, - {org = "ballerina", name = "io"}, {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "mime"}, {org = "ballerina", name = "regex"}, - {org = "ballerina", name = "tcp"}, {org = "ballerina", name = "test"}, {org = "ballerinai", name = "observe"} ] @@ -307,18 +302,6 @@ dependencies = [ {org = "ballerina", name = "time"} ] -[[package]] -org = "ballerina" -name = "tcp" -version = "1.9.0" -dependencies = [ - {org = "ballerina", name = "crypto"}, - {org = "ballerina", name = "jballerina.java"} -] -modules = [ - {org = "ballerina", packageName = "tcp", moduleName = "tcp"} -] - [[package]] org = "ballerina" name = "test" From c331a85d2258d054c39ef92e615fdb4d674860e3 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Wed, 11 Oct 2023 09:29:55 +0530 Subject: [PATCH 136/189] [Automated] Update the native jar versions --- ballerina/Dependencies.toml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index 71ac60d..4b977a0 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -101,6 +101,9 @@ dependencies = [ {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "lang.value"} ] +modules = [ + {org = "ballerina", packageName = "io", moduleName = "io"} +] [[package]] org = "ballerina" @@ -280,9 +283,11 @@ version = "0.2.0" dependencies = [ {org = "ballerina", name = "crypto"}, {org = "ballerina", name = "http"}, + {org = "ballerina", name = "io"}, {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "mime"}, {org = "ballerina", name = "regex"}, + {org = "ballerina", name = "tcp"}, {org = "ballerina", name = "test"}, {org = "ballerinai", name = "observe"} ] @@ -302,6 +307,18 @@ dependencies = [ {org = "ballerina", name = "time"} ] +[[package]] +org = "ballerina" +name = "tcp" +version = "1.9.0" +dependencies = [ + {org = "ballerina", name = "crypto"}, + {org = "ballerina", name = "jballerina.java"} +] +modules = [ + {org = "ballerina", packageName = "tcp", moduleName = "tcp"} +] + [[package]] org = "ballerina" name = "test" From d061f16d36e4d3cf1807aae7e0c7a8749136faf8 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Wed, 11 Oct 2023 09:57:21 +0530 Subject: [PATCH 137/189] [Automated] Update the native jar versions --- ballerina/Dependencies.toml | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index 4b977a0..6c8c629 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -287,7 +287,6 @@ dependencies = [ {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "mime"}, {org = "ballerina", name = "regex"}, - {org = "ballerina", name = "tcp"}, {org = "ballerina", name = "test"}, {org = "ballerinai", name = "observe"} ] @@ -307,18 +306,6 @@ dependencies = [ {org = "ballerina", name = "time"} ] -[[package]] -org = "ballerina" -name = "tcp" -version = "1.9.0" -dependencies = [ - {org = "ballerina", name = "crypto"}, - {org = "ballerina", name = "jballerina.java"} -] -modules = [ - {org = "ballerina", packageName = "tcp", moduleName = "tcp"} -] - [[package]] org = "ballerina" name = "test" From c0eded952be333ea8c616677788959b7d509e094 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Wed, 11 Oct 2023 09:59:34 +0530 Subject: [PATCH 138/189] [Automated] Update the native jar versions --- ballerina/Dependencies.toml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index 6c8c629..71ac60d 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -101,9 +101,6 @@ dependencies = [ {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "lang.value"} ] -modules = [ - {org = "ballerina", packageName = "io", moduleName = "io"} -] [[package]] org = "ballerina" @@ -283,7 +280,6 @@ version = "0.2.0" dependencies = [ {org = "ballerina", name = "crypto"}, {org = "ballerina", name = "http"}, - {org = "ballerina", name = "io"}, {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "mime"}, {org = "ballerina", name = "regex"}, From a9b1208daac66786f01b0bfeaa50484c87c90c8f Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Wed, 11 Oct 2023 12:19:59 +0530 Subject: [PATCH 139/189] [Automated] Update the native jar versions --- ballerina/Dependencies.toml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index 71ac60d..f04f6e9 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -217,6 +217,9 @@ dependencies = [ {org = "ballerina", name = "lang.value"}, {org = "ballerina", name = "observe"} ] +modules = [ + {org = "ballerina", packageName = "log", moduleName = "log"} +] [[package]] org = "ballerina" @@ -281,6 +284,7 @@ dependencies = [ {org = "ballerina", name = "crypto"}, {org = "ballerina", name = "http"}, {org = "ballerina", name = "jballerina.java"}, + {org = "ballerina", name = "log"}, {org = "ballerina", name = "mime"}, {org = "ballerina", name = "regex"}, {org = "ballerina", name = "test"}, From f7dbd30ec1720ed04a742d8cf906040d2389e4bf Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Wed, 11 Oct 2023 12:46:59 +0530 Subject: [PATCH 140/189] [Automated] Update the native jar versions --- ballerina/Dependencies.toml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index f04f6e9..71ac60d 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -217,9 +217,6 @@ dependencies = [ {org = "ballerina", name = "lang.value"}, {org = "ballerina", name = "observe"} ] -modules = [ - {org = "ballerina", packageName = "log", moduleName = "log"} -] [[package]] org = "ballerina" @@ -284,7 +281,6 @@ dependencies = [ {org = "ballerina", name = "crypto"}, {org = "ballerina", name = "http"}, {org = "ballerina", name = "jballerina.java"}, - {org = "ballerina", name = "log"}, {org = "ballerina", name = "mime"}, {org = "ballerina", name = "regex"}, {org = "ballerina", name = "test"}, From 69055c810e21d00382f304ad2e471eea6cfcea75 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Wed, 11 Oct 2023 12:53:41 +0530 Subject: [PATCH 141/189] [Automated] Update the native jar versions --- ballerina/Dependencies.toml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index 71ac60d..f04f6e9 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -217,6 +217,9 @@ dependencies = [ {org = "ballerina", name = "lang.value"}, {org = "ballerina", name = "observe"} ] +modules = [ + {org = "ballerina", packageName = "log", moduleName = "log"} +] [[package]] org = "ballerina" @@ -281,6 +284,7 @@ dependencies = [ {org = "ballerina", name = "crypto"}, {org = "ballerina", name = "http"}, {org = "ballerina", name = "jballerina.java"}, + {org = "ballerina", name = "log"}, {org = "ballerina", name = "mime"}, {org = "ballerina", name = "regex"}, {org = "ballerina", name = "test"}, From 641ee071dab5be163c1d5484bde5d0d1d4d56e17 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Wed, 11 Oct 2023 13:13:26 +0530 Subject: [PATCH 142/189] [Automated] Update the native jar versions --- ballerina/Dependencies.toml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index f04f6e9..65ec01b 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -101,6 +101,9 @@ dependencies = [ {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "lang.value"} ] +modules = [ + {org = "ballerina", packageName = "io", moduleName = "io"} +] [[package]] org = "ballerina" @@ -283,6 +286,7 @@ version = "0.2.0" dependencies = [ {org = "ballerina", name = "crypto"}, {org = "ballerina", name = "http"}, + {org = "ballerina", name = "io"}, {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "log"}, {org = "ballerina", name = "mime"}, From d88f5eada97579bf351acbbcc6bf34cbbb30b297 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Wed, 11 Oct 2023 14:01:54 +0530 Subject: [PATCH 143/189] [Automated] Update the native jar versions --- ballerina/Dependencies.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index 65ec01b..9ee973e 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -64,7 +64,7 @@ dependencies = [ [[package]] org = "ballerina" name = "http" -version = "2.10.1" +version = "2.10.2" dependencies = [ {org = "ballerina", name = "auth"}, {org = "ballerina", name = "cache"}, From c00947770722f754d214c37bc64f32e4acff8397 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Wed, 11 Oct 2023 21:52:38 +0530 Subject: [PATCH 144/189] [Automated] Update the native jar versions --- ballerina/Dependencies.toml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index 9ee973e..2e7a40d 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -220,9 +220,6 @@ dependencies = [ {org = "ballerina", name = "lang.value"}, {org = "ballerina", name = "observe"} ] -modules = [ - {org = "ballerina", packageName = "log", moduleName = "log"} -] [[package]] org = "ballerina" @@ -288,7 +285,6 @@ dependencies = [ {org = "ballerina", name = "http"}, {org = "ballerina", name = "io"}, {org = "ballerina", name = "jballerina.java"}, - {org = "ballerina", name = "log"}, {org = "ballerina", name = "mime"}, {org = "ballerina", name = "regex"}, {org = "ballerina", name = "test"}, From 6c2dcdf1b1c7b1d0c0c621797c0037bdd32e2cd8 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Wed, 11 Oct 2023 21:54:43 +0530 Subject: [PATCH 145/189] [Automated] Update the native jar versions --- ballerina/Dependencies.toml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index 2e7a40d..037d0d4 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -101,9 +101,6 @@ dependencies = [ {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "lang.value"} ] -modules = [ - {org = "ballerina", packageName = "io", moduleName = "io"} -] [[package]] org = "ballerina" @@ -283,7 +280,6 @@ version = "0.2.0" dependencies = [ {org = "ballerina", name = "crypto"}, {org = "ballerina", name = "http"}, - {org = "ballerina", name = "io"}, {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "mime"}, {org = "ballerina", name = "regex"}, From 86b8cf555be2a0259f505abeb137655f459501db Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Thu, 12 Oct 2023 06:04:24 +0530 Subject: [PATCH 146/189] Remove variable assignment from the `sendOnly` method --- README.md | 2 +- ballerina/Module.md | 2 +- ballerina/Package.md | 2 +- ballerina/modules/soap11/Module.md | 2 +- ballerina/modules/soap11/tests/soap11_client_test.bal | 2 +- ballerina/modules/soap12/Module.md | 2 +- ballerina/modules/soap12/tests/soap12_client_test.bal | 4 ++-- docs/spec/spec.md | 2 +- 8 files changed, 9 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 4ee3896..4508ae9 100644 --- a/README.md +++ b/README.md @@ -76,7 +76,7 @@ public function main() returns error? { `; - xml|mime:Entity[] response = check soapClient->sendOnly(envelope, "http://tempuri.org/Add"); + check soapClient->sendOnly(envelope, "http://tempuri.org/Add"); } ``` diff --git a/ballerina/Module.md b/ballerina/Module.md index 56d15e4..dfeaea0 100644 --- a/ballerina/Module.md +++ b/ballerina/Module.md @@ -67,7 +67,7 @@ public function main() returns error? { `; - xml|mime:Entity[] response = check soapClient->sendOnly(envelope, "http://tempuri.org/Add"); + check soapClient->sendOnly(envelope, "http://tempuri.org/Add"); } ``` ## Security diff --git a/ballerina/Package.md b/ballerina/Package.md index 6b690af..c4b0467 100644 --- a/ballerina/Package.md +++ b/ballerina/Package.md @@ -67,7 +67,7 @@ public function main() returns error? { `; - xml|mime:Entity[] response = check soapClient->sendOnly(envelope, "http://tempuri.org/Add"); + check soapClient->sendOnly(envelope, "http://tempuri.org/Add"); } ``` ## Security diff --git a/ballerina/modules/soap11/Module.md b/ballerina/modules/soap11/Module.md index 0b541f0..ea56f06 100644 --- a/ballerina/modules/soap11/Module.md +++ b/ballerina/modules/soap11/Module.md @@ -59,7 +59,7 @@ public function main() returns error? { `; - xml|mime:Entity[] response = check soapClient->sendOnly(envelope, "http://tempuri.org/Add"); + check soapClient->sendOnly(envelope, "http://tempuri.org/Add"); } ``` ## Security diff --git a/ballerina/modules/soap11/tests/soap11_client_test.bal b/ballerina/modules/soap11/tests/soap11_client_test.bal index 23fa5f4..a3532a3 100644 --- a/ballerina/modules/soap11/tests/soap11_client_test.bal +++ b/ballerina/modules/soap11/tests/soap11_client_test.bal @@ -44,7 +44,7 @@ function testSendOnly() returns error? { `; Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL"); - _ = check soapClient->sendOnly(body, "http://tempuri.org/Add"); + check soapClient->sendOnly(body, "http://tempuri.org/Add"); } @test:Config { diff --git a/ballerina/modules/soap12/Module.md b/ballerina/modules/soap12/Module.md index d8d6a01..97751d7 100644 --- a/ballerina/modules/soap12/Module.md +++ b/ballerina/modules/soap12/Module.md @@ -59,7 +59,7 @@ public function main() returns error? { `; - xml|mime:Entity[] response = check soapClient->sendOnly(envelope, "http://tempuri.org/Add"); + check soapClient->sendOnly(envelope, "http://tempuri.org/Add"); } ``` ## Security diff --git a/ballerina/modules/soap12/tests/soap12_client_test.bal b/ballerina/modules/soap12/tests/soap12_client_test.bal index df7c512..261a451 100644 --- a/ballerina/modules/soap12/tests/soap12_client_test.bal +++ b/ballerina/modules/soap12/tests/soap12_client_test.bal @@ -45,7 +45,7 @@ function testSendOnly12() returns error? { Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL"); - _ = check soapClient->sendOnly(body, "http://tempuri.org/Add"); + check soapClient->sendOnly(body, "http://tempuri.org/Add"); } @test:Config { @@ -134,7 +134,7 @@ function testSendOnly12WithoutSoapAction() returns error? { Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL"); - _ = check soapClient->sendOnly(body); + check soapClient->sendOnly(body); } @test:Config { diff --git a/docs/spec/spec.md b/docs/spec/spec.md index 1f0cffe..e7469af 100644 --- a/docs/spec/spec.md +++ b/docs/spec/spec.md @@ -85,7 +85,7 @@ public function main () returns error? { 0 `; - _ = check soapClient->sendOnly(body); + check soapClient->sendOnly(body); } ``` From 4181acf7a5edf41326bc3a8834389dc801d0cbb6 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Thu, 12 Oct 2023 06:06:19 +0530 Subject: [PATCH 147/189] [Automated] Update the native jar versions --- ballerina/Dependencies.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index 71ac60d..037d0d4 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -64,7 +64,7 @@ dependencies = [ [[package]] org = "ballerina" name = "http" -version = "2.10.1" +version = "2.10.2" dependencies = [ {org = "ballerina", name = "auth"}, {org = "ballerina", name = "cache"}, From 38f46414d4a763202aaad2b7b0e4a745e5077af9 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Thu, 12 Oct 2023 06:40:35 +0530 Subject: [PATCH 148/189] [Automated] Update the native jar versions --- ballerina/Dependencies.toml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index 037d0d4..2b101f8 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -181,6 +181,9 @@ version = "0.0.0" dependencies = [ {org = "ballerina", name = "jballerina.java"} ] +modules = [ + {org = "ballerina", packageName = "lang.regexp", moduleName = "lang.regexp"} +] [[package]] org = "ballerina" @@ -281,6 +284,7 @@ dependencies = [ {org = "ballerina", name = "crypto"}, {org = "ballerina", name = "http"}, {org = "ballerina", name = "jballerina.java"}, + {org = "ballerina", name = "lang.regexp"}, {org = "ballerina", name = "mime"}, {org = "ballerina", name = "regex"}, {org = "ballerina", name = "test"}, From 4d1ab49b5ea6a54a1655cf2238ddd2a95e92c676 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Thu, 12 Oct 2023 06:43:32 +0530 Subject: [PATCH 149/189] [Automated] Update the native jar versions --- ballerina/Dependencies.toml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index 2b101f8..037d0d4 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -181,9 +181,6 @@ version = "0.0.0" dependencies = [ {org = "ballerina", name = "jballerina.java"} ] -modules = [ - {org = "ballerina", packageName = "lang.regexp", moduleName = "lang.regexp"} -] [[package]] org = "ballerina" @@ -284,7 +281,6 @@ dependencies = [ {org = "ballerina", name = "crypto"}, {org = "ballerina", name = "http"}, {org = "ballerina", name = "jballerina.java"}, - {org = "ballerina", name = "lang.regexp"}, {org = "ballerina", name = "mime"}, {org = "ballerina", name = "regex"}, {org = "ballerina", name = "test"}, From 6a649b796c4b9dcd2ad13915f08526e306f60788 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Thu, 12 Oct 2023 06:46:21 +0530 Subject: [PATCH 150/189] [Automated] Update the native jar versions --- ballerina/Dependencies.toml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index 037d0d4..2b101f8 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -181,6 +181,9 @@ version = "0.0.0" dependencies = [ {org = "ballerina", name = "jballerina.java"} ] +modules = [ + {org = "ballerina", packageName = "lang.regexp", moduleName = "lang.regexp"} +] [[package]] org = "ballerina" @@ -281,6 +284,7 @@ dependencies = [ {org = "ballerina", name = "crypto"}, {org = "ballerina", name = "http"}, {org = "ballerina", name = "jballerina.java"}, + {org = "ballerina", name = "lang.regexp"}, {org = "ballerina", name = "mime"}, {org = "ballerina", name = "regex"}, {org = "ballerina", name = "test"}, From bddc0eac862a12b08c9b38ebf99f823a39c16a97 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Thu, 12 Oct 2023 06:56:32 +0530 Subject: [PATCH 151/189] [Automated] Update the native jar versions --- ballerina/Dependencies.toml | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index 2b101f8..e35d7a7 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -264,18 +264,6 @@ dependencies = [ {org = "ballerina", name = "jballerina.java"} ] -[[package]] -org = "ballerina" -name = "regex" -version = "1.4.3" -dependencies = [ - {org = "ballerina", name = "jballerina.java"}, - {org = "ballerina", name = "lang.string"} -] -modules = [ - {org = "ballerina", packageName = "regex", moduleName = "regex"} -] - [[package]] org = "ballerina" name = "soap" @@ -286,7 +274,6 @@ dependencies = [ {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "lang.regexp"}, {org = "ballerina", name = "mime"}, - {org = "ballerina", name = "regex"}, {org = "ballerina", name = "test"}, {org = "ballerinai", name = "observe"} ] From e574841856a6d15505d585fb478757aed9138320 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Thu, 12 Oct 2023 07:37:58 +0530 Subject: [PATCH 152/189] Remove `string` keyword from `const` variables --- ballerina/modules/soap11/tests/soap11_client_test.bal | 10 +++++----- ballerina/modules/soap12/tests/soap12_client_test.bal | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/ballerina/modules/soap11/tests/soap11_client_test.bal b/ballerina/modules/soap11/tests/soap11_client_test.bal index a3532a3..99ee01f 100644 --- a/ballerina/modules/soap11/tests/soap11_client_test.bal +++ b/ballerina/modules/soap11/tests/soap11_client_test.bal @@ -20,11 +20,11 @@ import ballerina/mime; import ballerina/test; import soap.wssec; -const string KEY_ALIAS = "wss40"; -const string KEY_PASSWORD = "security"; -const string KEY_STORE_PATH = "modules/wssec/tests/resources/wss40.p12"; -const string X509_KEY_STORE_PATH = "modules/wssec/tests/resources/x509_certificate.p12"; -const string X509_KEY_STORE_PATH_2 = "modules/wssec/tests/resources/x509_certificate_2.p12"; +const KEY_ALIAS = "wss40"; +const KEY_PASSWORD = "security"; +const KEY_STORE_PATH = "modules/wssec/tests/resources/wss40.p12"; +const X509_KEY_STORE_PATH = "modules/wssec/tests/resources/x509_certificate.p12"; +const X509_KEY_STORE_PATH_2 = "modules/wssec/tests/resources/x509_certificate_2.p12"; const wssec:TransportBindingConfig TRANSPORT_BINDING = "TransportBinding"; const wssec:NoPolicy NO_POLICY = "NoPolicy"; diff --git a/ballerina/modules/soap12/tests/soap12_client_test.bal b/ballerina/modules/soap12/tests/soap12_client_test.bal index 261a451..878c94e 100644 --- a/ballerina/modules/soap12/tests/soap12_client_test.bal +++ b/ballerina/modules/soap12/tests/soap12_client_test.bal @@ -20,11 +20,11 @@ import ballerina/test; import ballerina/crypto; import soap.wssec; -const string KEY_ALIAS = "wss40"; -const string KEY_PASSWORD = "security"; -const string KEY_STORE_PATH = "modules/wssec/tests/resources/wss40.p12"; -const string X509_KEY_STORE_PATH = "modules/wssec/tests/resources/x509_certificate.p12"; -const string X509_KEY_STORE_PATH_2 = "modules/wssec/tests/resources/x509_certificate_2.p12"; +const KEY_ALIAS = "wss40"; +const KEY_PASSWORD = "security"; +const KEY_STORE_PATH = "modules/wssec/tests/resources/wss40.p12"; +const X509_KEY_STORE_PATH = "modules/wssec/tests/resources/x509_certificate.p12"; +const X509_KEY_STORE_PATH_2 = "modules/wssec/tests/resources/x509_certificate_2.p12"; const wssec:TransportBindingConfig TRANSPORT_BINDING = "TransportBinding"; const wssec:NoPolicy NO_POLICY = "NoPolicy"; From 1de6750f3a32d73e90b0ade50476774f2541fccf Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Thu, 12 Oct 2023 07:38:35 +0530 Subject: [PATCH 153/189] Apply suggestions from the review --- ballerina/modules/soap11/soap11.bal | 4 +- ballerina/modules/soap12/soap12.bal | 19 ++--- ballerina/modules/wssec/tests/test_utils.bal | 22 +++--- .../modules/wssec/tests/ws_security_tests.bal | 12 +-- .../modules/wssec/ws_security_methods.bal | 75 +++++++++---------- ballerina/soap_utils.bal | 29 ++----- native/src/main/java/org/wssec/Constants.java | 1 + .../src/main/java/org/wssec/WsSecurity.java | 3 +- .../main/java/org/wssec/WsSecurityUtils.java | 4 +- 9 files changed, 73 insertions(+), 96 deletions(-) diff --git a/ballerina/modules/soap11/soap11.bal b/ballerina/modules/soap11/soap11.bal index d1b34eb..c07c750 100644 --- a/ballerina/modules/soap11/soap11.bal +++ b/ballerina/modules/soap11/soap11.bal @@ -33,7 +33,7 @@ public client class Client { public function init(string url, *soap:ClientConfig config) returns Error? { do { check soap:validateTransportBindingPolicy(config); - self.soapClient = check new (url, soap:retrieveHttpClientConfig(config)); + self.soapClient = check new (url, config.httpConfig); self.inboundSecurity = config.inboundSecurity; self.outboundSecurity = config.outboundSecurity; } on fail var err { @@ -63,7 +63,7 @@ public client class Client { action, headers, false); wssec:OutboundSecurityConfig? outboundSecurity = self.outboundSecurity; do { - if outboundSecurity !is () { + if outboundSecurity is wssec:OutboundSecurityConfig { return check soap:applyOutboundConfig(outboundSecurity, response); } } on fail var e { diff --git a/ballerina/modules/soap12/soap12.bal b/ballerina/modules/soap12/soap12.bal index d5214ba..83b1254 100644 --- a/ballerina/modules/soap12/soap12.bal +++ b/ballerina/modules/soap12/soap12.bal @@ -33,7 +33,7 @@ public client class Client { public function init(string url, *soap:ClientConfig config) returns Error? { do { check soap:validateTransportBindingPolicy(config); - self.soapClient = check new (url, soap:retrieveHttpClientConfig(config)); + self.soapClient = check new (url, config.httpConfig); self.inboundSecurity = config.inboundSecurity; self.outboundSecurity = config.outboundSecurity; } on fail var err { @@ -53,20 +53,15 @@ public client class Client { remote function sendReceive(xml|mime:Entity[] body, string? action = (), map headers = {}) returns xml|mime:Entity[]|Error { do { - xml securedBody; - if body is xml { - securedBody = check soap:applySecurityPolicies(self.inboundSecurity, body); - } else { - securedBody = check soap:applySecurityPolicies(self.inboundSecurity, check body[0].getXml()); - } + xml envelope = body is xml ? body : check body[0].getXml(); + xml securedBody = check soap:applySecurityPolicies(self.inboundSecurity, envelope); xml response = check soap:sendReceive(securedBody, self.soapClient, action, headers); wssec:OutboundSecurityConfig? outboundSecurity = self.outboundSecurity; - do { - if outboundSecurity !is () { - return check soap:applyOutboundConfig(outboundSecurity, response); + if outboundSecurity is wssec:OutboundSecurityConfig { + xml|error security = soap:applyOutboundConfig(outboundSecurity, response); + if security is error { + return error Error(INVALID_OUTBOUND_SECURITY_ERROR, security.cause()); } - } on fail var e { - return error Error(INVALID_OUTBOUND_SECURITY_ERROR, e.cause()); } return response; } on fail var e { diff --git a/ballerina/modules/wssec/tests/test_utils.bal b/ballerina/modules/wssec/tests/test_utils.bal index 2e99abe..e691ef1 100644 --- a/ballerina/modules/wssec/tests/test_utils.bal +++ b/ballerina/modules/wssec/tests/test_utils.bal @@ -15,19 +15,19 @@ // under the License. import ballerina/test; -const string USERNAME = "username"; -const string PASSWORD = "password"; +const USERNAME = "username"; +const PASSWORD = "password"; -const string KEY_ALIAS = "wss40"; -const string KEY_PASSWORD = "security"; +const KEY_ALIAS = "wss40"; +const KEY_PASSWORD = "security"; -const string PUBLIC_KEY_PATH = "modules/wssec/tests/resources/public_key.cer"; -const string PRIVATE_KEY_PATH = "modules/wssec/tests/resources/private_key.pem"; -const string KEY_STORE_PATH = "modules/wssec/tests/resources/wss40.p12"; -const string X509_PUBLIC_CERT_PATH = "modules/wssec/tests/resources/x509_certificate.crt"; -const string X509_PUBLIC_CERT_PATH_2 = "modules/wssec/tests/resources/x509_certificate_2.crt"; -const string X509_KEY_STORE_PATH = "modules/wssec/tests/resources/x509_certificate.p12"; -const string X509_KEY_STORE_PATH_2 = "modules/wssec/tests/resources/x509_certificate_2.p12"; +const PUBLIC_KEY_PATH = "modules/wssec/tests/resources/public_key.cer"; +const PRIVATE_KEY_PATH = "modules/wssec/tests/resources/private_key.pem"; +const KEY_STORE_PATH = "modules/wssec/tests/resources/wss40.p12"; +const X509_PUBLIC_CERT_PATH = "modules/wssec/tests/resources/x509_certificate.crt"; +const X509_PUBLIC_CERT_PATH_2 = "modules/wssec/tests/resources/x509_certificate_2.crt"; +const X509_KEY_STORE_PATH = "modules/wssec/tests/resources/x509_certificate.p12"; +const X509_KEY_STORE_PATH_2 = "modules/wssec/tests/resources/x509_certificate_2.p12"; function assertTimestampToken(string envelopeString) { string:RegExp ts_token = re ``; diff --git a/ballerina/modules/wssec/tests/ws_security_tests.bal b/ballerina/modules/wssec/tests/ws_security_tests.bal index cc3b23d..055114b 100644 --- a/ballerina/modules/wssec/tests/ws_security_tests.bal +++ b/ballerina/modules/wssec/tests/ws_security_tests.bal @@ -1,4 +1,3 @@ -import ballerina/crypto; // Copyright (c) 2023, WSO2 LLC. (http://www.wso2.org) All Rights Reserved. // // WSO2 LLC. licenses this file to you under the Apache License, @@ -14,8 +13,9 @@ import ballerina/crypto; // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. +import ballerina/crypto; import ballerina/test; -import ballerina/regex; +import ballerina/lang.regexp; @test:Config { groups: ["timestamp_token"] @@ -522,11 +522,11 @@ function testSymmetricBindingWithOutboundConfig() returns error? { }; crypto:PrivateKey|crypto:PublicKey? privateKey = outboundConfig.decryptionKey; - if privateKey !is () { + if privateKey is crypto:PrivateKey|crypto:PublicKey { byte[] encData = check getEncryptedData(securedEnvelope); byte[] decryptDataResult = check decryptData(encData, RSA_ECB, privateKey); string decryptedBody = "" + check string:fromBytes(decryptDataResult) + ""; - envelopeString = regex:replace(envelopeString, string`.*`, decryptedBody); + envelopeString = regexp:replace(re `.*`, envelopeString, decryptedBody); securedEnvelope = check xml:fromString(envelopeString); } byte[] signedData = check getSignatureData(securedEnvelope); @@ -893,11 +893,11 @@ function testAsymmetricBindingWithOutboundConfig() returns error? { xml securedEnvelope = check applyAsymmetricBinding(envelope, asymmetricBinding); string envelopeString = securedEnvelope.toString(); crypto:PrivateKey|crypto:PublicKey? privateKey = outboundConfig.decryptionKey; - if privateKey !is () { + if privateKey is crypto:PrivateKey|crypto:PublicKey { byte[] encData = check getEncryptedData(securedEnvelope); byte[] decryptDataResult = check decryptData(encData, RSA_ECB, privateKey); string decryptedBody = "" + check string:fromBytes(decryptDataResult) + ""; - envelopeString = regex:replace(envelopeString, string`.*`, decryptedBody); + envelopeString = regexp:replace(re `.*`, envelopeString, decryptedBody); securedEnvelope = check xml:fromString(envelopeString); } byte[] signedData = check getSignatureData(securedEnvelope); diff --git a/ballerina/modules/wssec/ws_security_methods.bal b/ballerina/modules/wssec/ws_security_methods.bal index 5daa6ce..843a838 100644 --- a/ballerina/modules/wssec/ws_security_methods.bal +++ b/ballerina/modules/wssec/ws_security_methods.bal @@ -14,7 +14,7 @@ // specific language governing permissions and limitations // under the License. import ballerina/crypto; -import ballerina/regex; +import ballerina/lang.regexp; xmlns "http://schemas.xmlsoap.org/soap/envelope/" as soap; xmlns "http://www.w3.org/2000/09/xmldsig#" as ds; @@ -22,10 +22,7 @@ xmlns "http://www.w3.org/2000/09/xmldsig#" as ds; function addSecurityHeader(Document document) returns WSSecurityHeader|Error { WSSecurityHeader wsSecHeader = check new (document); Error? insertHeader = wsSecHeader.insertSecHeader(); - if insertHeader is () { - return wsSecHeader; - } - return insertHeader; + return insertHeader ?: wsSecHeader; } public function decryptData(byte[] cipherText, EncryptionAlgorithm encryptionAlgorithm, @@ -59,14 +56,14 @@ function applyEncryptedKey(string envelopeString, crypto:PrivateKey symmetricKey Encryption encryption = check new (); byte[] encryptedKey = check crypto:encryptRsaEcb(symmetricKey.toBalString().toBytes(), encryptKey); string encryptedKeyElements = check encryption.getEncryptedKeyElements(encryptedKey); - string replace = regex:replace(encryptedKeyElements, string `<`, "<"); + string replace = regexp:replace(re `<`, encryptedKeyElements, "<"); string:RegExp securityToken = re ``; if securedEnvelope.includesMatch(securityToken) { - securedEnvelope = regex:replace(securedEnvelope, securityToken.toString(), replace); + securedEnvelope = regexp:replace(securityToken, securedEnvelope, replace); } else if securedEnvelope.includesMatch(re ``) { - securedEnvelope = regex:replace(securedEnvelope, string ``, replace); + securedEnvelope = regexp:replace(re ``, securedEnvelope, replace); } return securedEnvelope; } on fail var e { @@ -75,11 +72,11 @@ function applyEncryptedKey(string envelopeString, crypto:PrivateKey symmetricKey } function convertStringToXml(string envelope) returns xml|Error { - do { - return check xml:fromString(regex:replace(envelope, string `<`, "<")); - } on fail var e { - return error Error(e.message()); + xml|error xmlEnvelope = xml:fromString(regexp:replace(re `<`, envelope, "<")); + if xmlEnvelope is error { + return error Error(xmlEnvelope.message()); } + return xmlEnvelope; } # Returns the encrypted data of the SOAP envelope. @@ -140,26 +137,22 @@ public function applySymmetricBinding(xml envelope, *SymmetricBindingConfig symm Document document = check new (envelope); WSSecurityHeader wsSecurityHeader = check addSecurityHeader(document); string securedEnvelope = envelope.toBalString(); - if symmetricBinding.signatureAlgorithm !is () { + SignatureAlgorithm? signatureAlgorithm = symmetricBinding.signatureAlgorithm; + EncryptionAlgorithm? encryptionAlgorithm = symmetricBinding.encryptionAlgorithm; + if signatureAlgorithm is SignatureAlgorithm { Signature signature = check new (); - byte[] signedData = check signature.signData((envelope//*).toString(), - symmetricBinding.signatureAlgorithm, - symmetricBinding.symmetricKey); - Signature signatureResult = check addSignature(signature, - symmetricBinding.signatureAlgorithm, - signedData); + byte[] signedData = check signature.signData((envelope//*).toString(), signatureAlgorithm + , symmetricBinding.symmetricKey); + Signature signatureResult = check addSignature(signature, signatureAlgorithm, signedData); WsSecurity wsSecurity = new; securedEnvelope = check wsSecurity.applySignatureOnlyPolicy(wsSecurityHeader, signatureResult, symmetricBinding.x509Token); } - if symmetricBinding.encryptionAlgorithm !is () { + if encryptionAlgorithm is EncryptionAlgorithm { Encryption encryption = check new (); - byte[] encryptData = check encryption.encryptData((envelope//*).toString(), - symmetricBinding.encryptionAlgorithm, - symmetricBinding.symmetricKey); - Encryption encryptionResult = check addEncryption(encryption, - symmetricBinding.encryptionAlgorithm, - encryptData); + byte[] encryptData = check encryption.encryptData((envelope//*).toString(), encryptionAlgorithm + , symmetricBinding.symmetricKey); + Encryption encryptionResult = check addEncryption(encryption, encryptionAlgorithm, encryptData); WsSecurity wsSecurity = new; securedEnvelope = check wsSecurity.applyEncryptionOnlyPolicy(wsSecurityHeader, encryptionResult); } @@ -177,26 +170,30 @@ public function applyAsymmetricBinding(xml envelope, *AsymmetricBindingConfig as Document document = check new (envelope); WSSecurityHeader wsSecurityHeader = check addSecurityHeader(document); string securedEnvelope = envelope.toBalString(); - if asymmetricBinding.signatureAlgorithm !is () { + SignatureAlgorithm? signatureAlgorithm = asymmetricBinding.signatureAlgorithm; + EncryptionAlgorithm? encryptionAlgorithm = asymmetricBinding.encryptionAlgorithm; + if signatureAlgorithm is SignatureAlgorithm { Signature signature = check new (); + crypto:PrivateKey? signatureKey = asymmetricBinding.signatureKey; + if signatureKey !is crypto:PrivateKey { + return error Error("Signature key cannot be nil"); + } byte[] signedData = check signature.signData((envelope//*).toString(), - asymmetricBinding.signatureAlgorithm, - asymmetricBinding.signatureKey); - Signature signatureResult = check addSignature(signature, - asymmetricBinding.signatureAlgorithm, - signedData); + signatureAlgorithm, signatureKey); + Signature signatureResult = check addSignature(signature, signatureAlgorithm, signedData); WsSecurity wsSecurity = new; securedEnvelope = check wsSecurity.applySignatureOnlyPolicy(wsSecurityHeader, signatureResult, asymmetricBinding.x509Token); } - if asymmetricBinding.encryptionAlgorithm !is () { + if encryptionAlgorithm is EncryptionAlgorithm { Encryption encryption = check new (); - byte[] encryptData = check encryption.encryptData((envelope//*).toString(), - asymmetricBinding.encryptionAlgorithm, - asymmetricBinding.encryptionKey); - Encryption encryptionResult = check addEncryption(encryption, - asymmetricBinding.encryptionAlgorithm, - encryptData); + crypto:PublicKey? encryptionKey = asymmetricBinding.encryptionKey; + if encryptionKey !is crypto:PublicKey { + return error Error("Encryption key cannot be nil"); + } + byte[] encryptData = check encryption.encryptData((envelope//*).toString(), encryptionAlgorithm, + encryptionKey); + Encryption encryptionResult = check addEncryption(encryption, encryptionAlgorithm, encryptData); WsSecurity wsSecurity = new; securedEnvelope = check wsSecurity.applyEncryptionOnlyPolicy(wsSecurityHeader, encryptionResult); } diff --git a/ballerina/soap_utils.bal b/ballerina/soap_utils.bal index 67faca8..ebe39b9 100644 --- a/ballerina/soap_utils.bal +++ b/ballerina/soap_utils.bal @@ -18,7 +18,7 @@ import soap.wssec; import ballerina/crypto; import ballerina/http; import ballerina/mime; -import ballerina/regex; +import ballerina/lang.regexp; public function validateTransportBindingPolicy(ClientConfig config) returns Error? { if config.httpConfig.secureSocket is () { @@ -35,21 +35,6 @@ public function validateTransportBindingPolicy(ClientConfig config) returns Erro } } -public function retrieveHttpClientConfig(ClientConfig config) returns http:ClientConfiguration { - return { - httpVersion: config.httpConfig.httpVersion, - http1Settings: config.httpConfig.http1Settings, - http2Settings: config.httpConfig.http2Settings, - timeout: config.httpConfig.timeout, - poolConfig: config.httpConfig?.poolConfig, - auth: config.httpConfig?.auth, - retryConfig: config.httpConfig?.retryConfig, - responseLimits: config.httpConfig.responseLimits, - secureSocket: config.httpConfig?.secureSocket, - circuitBreaker: config.httpConfig?.circuitBreaker - }; -} - public function applySecurityPolicies(wssec:InboundSecurityConfig|wssec:InboundSecurityConfig[] inboundSecurity, xml envelope) returns xml|wssec:Error { wssec:InboundSecurityConfig|wssec:InboundSecurityConfig[] securityPolicy = inboundSecurity; @@ -80,21 +65,21 @@ public function applyOutboundConfig(wssec:OutboundSecurityConfig outboundSecurit xml soapEnvelope = envelope; do { wssec:EncryptionAlgorithm? encryptionAlgorithm = outboundSecurity.decryptionAlgorithm; - if encryptionAlgorithm !is () { + if encryptionAlgorithm is wssec:EncryptionAlgorithm { crypto:PrivateKey|crypto:PublicKey? clientPrivateKey = outboundSecurity.decryptionKey; - if clientPrivateKey !is () { + if clientPrivateKey is crypto:PrivateKey|crypto:PublicKey { byte[] encData = check wssec:getEncryptedData(soapEnvelope); byte[] decryptDataResult = check wssec:decryptData(encData, encryptionAlgorithm, clientPrivateKey); string decryptedBody = "" + check string:fromBytes(decryptDataResult) + ""; - string decryptedEnv = regex:replace(soapEnvelope.toString(), string `.*`, - decryptedBody); + string decryptedEnv = regexp:replace(re `.*`, soapEnvelope.toString(), + decryptedBody); soapEnvelope = check xml:fromString(decryptedEnv); } } wssec:SignatureAlgorithm? signatureAlgorithm = outboundSecurity.signatureAlgorithm; - if signatureAlgorithm !is () { + if signatureAlgorithm is wssec:SignatureAlgorithm { crypto:PublicKey? serverPublicKey = outboundSecurity.verificationKey; - if serverPublicKey !is () { + if serverPublicKey is crypto:PublicKey { byte[] signatureData = check wssec:getSignatureData(soapEnvelope); boolean verify = check wssec:verifyData((soapEnvelope//*).toString().toBytes(), signatureData, serverPublicKey, signatureAlgorithm); diff --git a/native/src/main/java/org/wssec/Constants.java b/native/src/main/java/org/wssec/Constants.java index 3b7ebdd..c142901 100644 --- a/native/src/main/java/org/wssec/Constants.java +++ b/native/src/main/java/org/wssec/Constants.java @@ -22,6 +22,7 @@ public class Constants { public static final String DIGEST = "DIGEST"; public static final String DERIVED_KEY_TEXT = "DERIVED_KEY_TEXT"; public static final String DERIVED_KEY_DIGEST = "DERIVED_KEY_DIGEST"; + public static final String PASSWORD = "password"; public static final String NATIVE_SEC_HEADER = "nativeSecHeader"; public static final String NATIVE_DOCUMENT = "nativeDocumentBuilder"; public static final String NATIVE_SIGNATURE = "nativeSignature"; diff --git a/native/src/main/java/org/wssec/WsSecurity.java b/native/src/main/java/org/wssec/WsSecurity.java index d3bfcee..7df2ba8 100644 --- a/native/src/main/java/org/wssec/WsSecurity.java +++ b/native/src/main/java/org/wssec/WsSecurity.java @@ -49,6 +49,7 @@ import static org.wssec.Constants.NATIVE_ENCRYPTION; import static org.wssec.Constants.NATIVE_SEC_HEADER; import static org.wssec.Constants.NATIVE_SIGNATURE; +import static org.wssec.Constants.PASSWORD; import static org.wssec.Constants.X509; import static org.wssec.Utils.createError; import static org.wssec.WsSecurityUtils.convertDocumentToString; @@ -144,7 +145,7 @@ public static Document createSignatureTags(WsSecurityHeader wsSecurityHeader, public static WSSecSignature prepareSignature(RequestData reqData, Object x509FilePath) { WSSecSignature sign = new WSSecSignature(reqData.getSecHeader()); try { - byte[] key = UsernameTokenUtil.generateDerivedKey("password", + byte[] key = UsernameTokenUtil.generateDerivedKey(PASSWORD, UsernameTokenUtil.generateSalt(true), ITERATION); sign.setSecretKey(key); sign.setWsDocInfo(reqData.getWsDocInfo()); diff --git a/native/src/main/java/org/wssec/WsSecurityUtils.java b/native/src/main/java/org/wssec/WsSecurityUtils.java index 69b1f0f..ab3600c 100644 --- a/native/src/main/java/org/wssec/WsSecurityUtils.java +++ b/native/src/main/java/org/wssec/WsSecurityUtils.java @@ -31,7 +31,6 @@ import java.util.ArrayList; import java.util.Base64; import java.util.List; -import java.util.Objects; import javax.xml.crypto.dsig.Reference; import javax.xml.parsers.DocumentBuilderFactory; @@ -118,8 +117,7 @@ public static Object getEncryptedKeyElement(byte[] encryptKey) throws Exception public static void setUTChildElements(WSSecUsernameToken usernameToken, String passwordType, String username, String password) { - if (Objects.equals(passwordType, DIGEST) - || Objects.equals(passwordType, DERIVED_KEY_DIGEST)) { + if (DIGEST.equals(passwordType) || DERIVED_KEY_DIGEST.equals(passwordType)) { usernameToken.setPasswordType(PASSWORD_DIGEST); usernameToken.setUserInfo(username, password); usernameToken.addCreated(); From 6f98be1c6f54b1b38af287f7550eca152b247812 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Thu, 12 Oct 2023 10:38:05 +0530 Subject: [PATCH 154/189] FIx license headers --- ballerina/configs.bal | 2 +- ballerina/constants.bal | 2 +- ballerina/error.bal | 2 +- ballerina/modules/soap11/error.bal | 2 +- ballerina/modules/soap11/soap11.bal | 2 +- ballerina/modules/soap11/tests/soap11_client_test.bal | 2 +- ballerina/modules/soap12/error.bal | 2 +- ballerina/modules/soap12/soap12.bal | 2 +- ballerina/modules/soap12/tests/soap12_client_test.bal | 2 +- ballerina/modules/wssec/document.bal | 2 +- ballerina/modules/wssec/encryption.bal | 2 +- ballerina/modules/wssec/error.bal | 2 +- ballerina/modules/wssec/init.bal | 2 +- ballerina/modules/wssec/records.bal | 2 +- ballerina/modules/wssec/sec_header.bal | 2 +- ballerina/modules/wssec/signature.bal | 2 +- ballerina/modules/wssec/tests/test_utils.bal | 2 +- ballerina/modules/wssec/tests/ws_security_tests.bal | 2 +- ballerina/modules/wssec/types.bal | 2 +- ballerina/modules/wssec/ws_security.bal | 2 +- ballerina/modules/wssec/ws_security_methods.bal | 2 +- ballerina/soap_utils.bal | 2 +- ballerina/types.bal | 2 +- native/src/main/java/module-info.java | 2 +- native/src/main/java/org/wssec/Constants.java | 2 +- native/src/main/java/org/wssec/DocumentBuilder.java | 2 +- native/src/main/java/org/wssec/Encryption.java | 2 +- native/src/main/java/org/wssec/ModuleUtils.java | 2 +- native/src/main/java/org/wssec/Signature.java | 2 +- native/src/main/java/org/wssec/Utils.java | 2 +- native/src/main/java/org/wssec/WsSecurity.java | 2 +- native/src/main/java/org/wssec/WsSecurityHeader.java | 2 +- native/src/main/java/org/wssec/WsSecurityUtils.java | 2 +- 33 files changed, 33 insertions(+), 33 deletions(-) diff --git a/ballerina/configs.bal b/ballerina/configs.bal index 95edb18..fba33bf 100644 --- a/ballerina/configs.bal +++ b/ballerina/configs.bal @@ -1,4 +1,4 @@ -// Copyright (c) 2023, WSO2 LLC. (http://www.wso2.org) All Rights Reserved. +// Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com) All Rights Reserved. // // WSO2 LLC. licenses this file to you under the Apache License, // Version 2.0 (the "License"); you may not use this file except diff --git a/ballerina/constants.bal b/ballerina/constants.bal index 92eb34c..198ce0b 100644 --- a/ballerina/constants.bal +++ b/ballerina/constants.bal @@ -1,4 +1,4 @@ -// Copyright (c) 2023, WSO2 LLC. (http://www.wso2.org) All Rights Reserved. +// Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com) All Rights Reserved. // // WSO2 LLC. licenses this file to you under the Apache License, // Version 2.0 (the "License"); you may not use this file except diff --git a/ballerina/error.bal b/ballerina/error.bal index 0be7565..9fb3440 100644 --- a/ballerina/error.bal +++ b/ballerina/error.bal @@ -1,4 +1,4 @@ -// Copyright (c) 2023, WSO2 LLC. (http://www.wso2.org) All Rights Reserved. +// Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com) All Rights Reserved. // // WSO2 LLC. licenses this file to you under the Apache License, // Version 2.0 (the "License"); you may not use this file except diff --git a/ballerina/modules/soap11/error.bal b/ballerina/modules/soap11/error.bal index 29a6fad..60fa4ed 100644 --- a/ballerina/modules/soap11/error.bal +++ b/ballerina/modules/soap11/error.bal @@ -1,4 +1,4 @@ -// Copyright (c) 2023, WSO2 LLC. (http://www.wso2.org) All Rights Reserved. +// Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com) All Rights Reserved. // // WSO2 LLC. licenses this file to you under the Apache License, // Version 2.0 (the "License"); you may not use this file except diff --git a/ballerina/modules/soap11/soap11.bal b/ballerina/modules/soap11/soap11.bal index c07c750..6caae7d 100644 --- a/ballerina/modules/soap11/soap11.bal +++ b/ballerina/modules/soap11/soap11.bal @@ -1,4 +1,4 @@ -// Copyright (c) 2023, WSO2 LLC. (http://www.wso2.org) All Rights Reserved. +// Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com) All Rights Reserved. // // WSO2 LLC. licenses this file to you under the Apache License, // Version 2.0 (the "License"); you may not use this file except diff --git a/ballerina/modules/soap11/tests/soap11_client_test.bal b/ballerina/modules/soap11/tests/soap11_client_test.bal index 99ee01f..c17ee7c 100644 --- a/ballerina/modules/soap11/tests/soap11_client_test.bal +++ b/ballerina/modules/soap11/tests/soap11_client_test.bal @@ -1,4 +1,4 @@ -// Copyright (c) 2023, WSO2 LLC. (http://www.wso2.org) All Rights Reserved. +// Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com) All Rights Reserved. // // WSO2 LLC. licenses this file to you under the Apache License, // Version 2.0 (the "License"); you may not use this file except diff --git a/ballerina/modules/soap12/error.bal b/ballerina/modules/soap12/error.bal index cbdf10a..d19c1c1 100644 --- a/ballerina/modules/soap12/error.bal +++ b/ballerina/modules/soap12/error.bal @@ -1,4 +1,4 @@ -// Copyright (c) 2023, WSO2 LLC. (http://www.wso2.org) All Rights Reserved. +// Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com) All Rights Reserved. // // WSO2 LLC. licenses this file to you under the Apache License, // Version 2.0 (the "License"); you may not use this file except diff --git a/ballerina/modules/soap12/soap12.bal b/ballerina/modules/soap12/soap12.bal index 83b1254..0e8537e 100644 --- a/ballerina/modules/soap12/soap12.bal +++ b/ballerina/modules/soap12/soap12.bal @@ -1,4 +1,4 @@ -// Copyright (c) 2023, WSO2 LLC. (http://www.wso2.org) All Rights Reserved. +// Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com) All Rights Reserved. // // WSO2 LLC. licenses this file to you under the Apache License, // Version 2.0 (the "License"); you may not use this file except diff --git a/ballerina/modules/soap12/tests/soap12_client_test.bal b/ballerina/modules/soap12/tests/soap12_client_test.bal index 878c94e..5833f2d 100644 --- a/ballerina/modules/soap12/tests/soap12_client_test.bal +++ b/ballerina/modules/soap12/tests/soap12_client_test.bal @@ -1,4 +1,4 @@ -// Copyright (c) 2023, WSO2 LLC. (http://www.wso2.org) All Rights Reserved. +// Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com) All Rights Reserved. // // WSO2 LLC. licenses this file to you under the Apache License, // Version 2.0 (the "License"); you may not use this file except diff --git a/ballerina/modules/wssec/document.bal b/ballerina/modules/wssec/document.bal index f467a4a..efb0300 100644 --- a/ballerina/modules/wssec/document.bal +++ b/ballerina/modules/wssec/document.bal @@ -1,4 +1,4 @@ -// Copyright (c) 2023, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +// Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com) All Rights Reserved. // // WSO2 Inc. licenses this file to you under the Apache License, // Version 2.0 (the "License"); you may not use this file except diff --git a/ballerina/modules/wssec/encryption.bal b/ballerina/modules/wssec/encryption.bal index b9f2a8c..5e50970 100644 --- a/ballerina/modules/wssec/encryption.bal +++ b/ballerina/modules/wssec/encryption.bal @@ -1,4 +1,4 @@ -// Copyright (c) 2023, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +// Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com) All Rights Reserved. // // WSO2 Inc. licenses this file to you under the Apache License, // Version 2.0 (the "License"); you may not use this file except diff --git a/ballerina/modules/wssec/error.bal b/ballerina/modules/wssec/error.bal index 036f086..2c46083 100644 --- a/ballerina/modules/wssec/error.bal +++ b/ballerina/modules/wssec/error.bal @@ -1,4 +1,4 @@ -// Copyright (c) 2023, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +// Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com) All Rights Reserved. // // WSO2 Inc. licenses this file to you under the Apache License, // Version 2.0 (the "License"); you may not use this file except diff --git a/ballerina/modules/wssec/init.bal b/ballerina/modules/wssec/init.bal index f2f54b3..fe99617 100644 --- a/ballerina/modules/wssec/init.bal +++ b/ballerina/modules/wssec/init.bal @@ -1,4 +1,4 @@ -// Copyright (c) 2023, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +// Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com) All Rights Reserved. // // WSO2 Inc. licenses this file to you under the Apache License, // Version 2.0 (the "License"); you may not use this file except diff --git a/ballerina/modules/wssec/records.bal b/ballerina/modules/wssec/records.bal index 8bea0e9..f0f8f7e 100644 --- a/ballerina/modules/wssec/records.bal +++ b/ballerina/modules/wssec/records.bal @@ -1,4 +1,4 @@ -// Copyright (c) 2023, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +// Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com) All Rights Reserved. // // WSO2 Inc. licenses this file to you under the Apache License, // Version 2.0 (the "License"); you may not use this file except diff --git a/ballerina/modules/wssec/sec_header.bal b/ballerina/modules/wssec/sec_header.bal index 92f4deb..76b24ae 100644 --- a/ballerina/modules/wssec/sec_header.bal +++ b/ballerina/modules/wssec/sec_header.bal @@ -1,4 +1,4 @@ -// Copyright (c) 2023, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +// Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com) All Rights Reserved. // // WSO2 Inc. licenses this file to you under the Apache License, // Version 2.0 (the "License"); you may not use this file except diff --git a/ballerina/modules/wssec/signature.bal b/ballerina/modules/wssec/signature.bal index 560a36e..5c7b043 100644 --- a/ballerina/modules/wssec/signature.bal +++ b/ballerina/modules/wssec/signature.bal @@ -1,4 +1,4 @@ -// Copyright (c) 2023, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +// Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com) All Rights Reserved. // // WSO2 Inc. licenses this file to you under the Apache License, // Version 2.0 (the "License"); you may not use this file except diff --git a/ballerina/modules/wssec/tests/test_utils.bal b/ballerina/modules/wssec/tests/test_utils.bal index e691ef1..9724223 100644 --- a/ballerina/modules/wssec/tests/test_utils.bal +++ b/ballerina/modules/wssec/tests/test_utils.bal @@ -1,4 +1,4 @@ -// Copyright (c) 2023, WSO2 LLC. (http://www.wso2.org) All Rights Reserved. +// Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com) All Rights Reserved. // // WSO2 LLC. licenses this file to you under the Apache License, // Version 2.0 (the "License"); you may not use this file except diff --git a/ballerina/modules/wssec/tests/ws_security_tests.bal b/ballerina/modules/wssec/tests/ws_security_tests.bal index 055114b..6f03b90 100644 --- a/ballerina/modules/wssec/tests/ws_security_tests.bal +++ b/ballerina/modules/wssec/tests/ws_security_tests.bal @@ -1,4 +1,4 @@ -// Copyright (c) 2023, WSO2 LLC. (http://www.wso2.org) All Rights Reserved. +// Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com) All Rights Reserved. // // WSO2 LLC. licenses this file to you under the Apache License, // Version 2.0 (the "License"); you may not use this file except diff --git a/ballerina/modules/wssec/types.bal b/ballerina/modules/wssec/types.bal index a7eb41f..9b194e2 100644 --- a/ballerina/modules/wssec/types.bal +++ b/ballerina/modules/wssec/types.bal @@ -1,4 +1,4 @@ -// Copyright (c) 2023, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +// Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com) All Rights Reserved. // // WSO2 Inc. licenses this file to you under the Apache License, // Version 2.0 (the "License"); you may not use this file except diff --git a/ballerina/modules/wssec/ws_security.bal b/ballerina/modules/wssec/ws_security.bal index 036ce95..3b97597 100644 --- a/ballerina/modules/wssec/ws_security.bal +++ b/ballerina/modules/wssec/ws_security.bal @@ -1,4 +1,4 @@ -// Copyright (c) 2023, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +// Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com) All Rights Reserved. // // WSO2 Inc. licenses this file to you under the Apache License, // Version 2.0 (the "License"); you may not use this file except diff --git a/ballerina/modules/wssec/ws_security_methods.bal b/ballerina/modules/wssec/ws_security_methods.bal index 843a838..55f32b0 100644 --- a/ballerina/modules/wssec/ws_security_methods.bal +++ b/ballerina/modules/wssec/ws_security_methods.bal @@ -1,4 +1,4 @@ -// Copyright (c) 2023, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +// Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com) All Rights Reserved. // // WSO2 Inc. licenses this file to you under the Apache License, // Version 2.0 (the "License"); you may not use this file except diff --git a/ballerina/soap_utils.bal b/ballerina/soap_utils.bal index ebe39b9..7b07b70 100644 --- a/ballerina/soap_utils.bal +++ b/ballerina/soap_utils.bal @@ -1,4 +1,4 @@ -// Copyright (c) 2023, WSO2 LLC. (http://www.wso2.org) All Rights Reserved. +// Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com) All Rights Reserved. // // WSO2 LLC. licenses this file to you under the Apache License, // Version 2.0 (the "License"); you may not use this file except diff --git a/ballerina/types.bal b/ballerina/types.bal index 94ac981..187a507 100644 --- a/ballerina/types.bal +++ b/ballerina/types.bal @@ -1,4 +1,4 @@ -// Copyright (c) 2023, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +// Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com) All Rights Reserved. // // WSO2 Inc. licenses this file to you under the Apache License, // Version 2.0 (the "License"); you may not use this file except diff --git a/native/src/main/java/module-info.java b/native/src/main/java/module-info.java index c5c33dc..5ab9e36 100644 --- a/native/src/main/java/module-info.java +++ b/native/src/main/java/module-info.java @@ -1,4 +1,4 @@ -// Copyright (c) 2023, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +// Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com) All Rights Reserved. // // WSO2 Inc. licenses this file to you under the Apache License, // Version 2.0 (the "License"); you may not use this file except diff --git a/native/src/main/java/org/wssec/Constants.java b/native/src/main/java/org/wssec/Constants.java index c142901..20fffa1 100644 --- a/native/src/main/java/org/wssec/Constants.java +++ b/native/src/main/java/org/wssec/Constants.java @@ -1,4 +1,4 @@ -// Copyright (c) 2023, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +// Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com) All Rights Reserved. // // WSO2 Inc. licenses this file to you under the Apache License, // Version 2.0 (the "License"); you may not use this file except diff --git a/native/src/main/java/org/wssec/DocumentBuilder.java b/native/src/main/java/org/wssec/DocumentBuilder.java index 4fc4894..c6b15ad 100644 --- a/native/src/main/java/org/wssec/DocumentBuilder.java +++ b/native/src/main/java/org/wssec/DocumentBuilder.java @@ -1,4 +1,4 @@ -// Copyright (c) 2023, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +// Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com) All Rights Reserved. // // WSO2 Inc. licenses this file to you under the Apache License, // Version 2.0 (the "License"); you may not use this file except diff --git a/native/src/main/java/org/wssec/Encryption.java b/native/src/main/java/org/wssec/Encryption.java index ea61174..421096d 100644 --- a/native/src/main/java/org/wssec/Encryption.java +++ b/native/src/main/java/org/wssec/Encryption.java @@ -1,4 +1,4 @@ -// Copyright (c) 2023, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +// Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com) All Rights Reserved. // // WSO2 Inc. licenses this file to you under the Apache License, // Version 2.0 (the "License"); you may not use this file except diff --git a/native/src/main/java/org/wssec/ModuleUtils.java b/native/src/main/java/org/wssec/ModuleUtils.java index 16d1cbb..92a71bf 100644 --- a/native/src/main/java/org/wssec/ModuleUtils.java +++ b/native/src/main/java/org/wssec/ModuleUtils.java @@ -1,4 +1,4 @@ -// Copyright (c) 2023, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +// Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com) All Rights Reserved. // // WSO2 Inc. licenses this file to you under the Apache License, // Version 2.0 (the "License"); you may not use this file except diff --git a/native/src/main/java/org/wssec/Signature.java b/native/src/main/java/org/wssec/Signature.java index c16e86b..e10a566 100644 --- a/native/src/main/java/org/wssec/Signature.java +++ b/native/src/main/java/org/wssec/Signature.java @@ -1,4 +1,4 @@ -// Copyright (c) 2023, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +// Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com) All Rights Reserved. // // WSO2 Inc. licenses this file to you under the Apache License, // Version 2.0 (the "License"); you may not use this file except diff --git a/native/src/main/java/org/wssec/Utils.java b/native/src/main/java/org/wssec/Utils.java index a18431b..1fbf917 100644 --- a/native/src/main/java/org/wssec/Utils.java +++ b/native/src/main/java/org/wssec/Utils.java @@ -1,4 +1,4 @@ -// Copyright (c) 2023, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +// Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com) All Rights Reserved. // // WSO2 Inc. licenses this file to you under the Apache License, // Version 2.0 (the "License"); you may not use this file except diff --git a/native/src/main/java/org/wssec/WsSecurity.java b/native/src/main/java/org/wssec/WsSecurity.java index 7df2ba8..6a553a6 100644 --- a/native/src/main/java/org/wssec/WsSecurity.java +++ b/native/src/main/java/org/wssec/WsSecurity.java @@ -1,4 +1,4 @@ -// Copyright (c) 2023, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +// Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com) All Rights Reserved. // // WSO2 Inc. licenses this file to you under the Apache License, // Version 2.0 (the "License"); you may not use this file except diff --git a/native/src/main/java/org/wssec/WsSecurityHeader.java b/native/src/main/java/org/wssec/WsSecurityHeader.java index 5d4f035..cf01fed 100644 --- a/native/src/main/java/org/wssec/WsSecurityHeader.java +++ b/native/src/main/java/org/wssec/WsSecurityHeader.java @@ -1,4 +1,4 @@ -// Copyright (c) 2023, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +// Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com) All Rights Reserved. // // WSO2 Inc. licenses this file to you under the Apache License, // Version 2.0 (the "License"); you may not use this file except diff --git a/native/src/main/java/org/wssec/WsSecurityUtils.java b/native/src/main/java/org/wssec/WsSecurityUtils.java index ab3600c..286bfd8 100644 --- a/native/src/main/java/org/wssec/WsSecurityUtils.java +++ b/native/src/main/java/org/wssec/WsSecurityUtils.java @@ -1,4 +1,4 @@ -// Copyright (c) 2023, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +// Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com) All Rights Reserved. // // WSO2 Inc. licenses this file to you under the Apache License, // Version 2.0 (the "License"); you may not use this file except From 045914db9c2a3bf90797ce520d281b9572a9a20b Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Thu, 12 Oct 2023 16:42:45 +0530 Subject: [PATCH 155/189] [Automated] Update the native jar versions --- ballerina/Dependencies.toml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index 037d0d4..2e7a40d 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -101,6 +101,9 @@ dependencies = [ {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "lang.value"} ] +modules = [ + {org = "ballerina", packageName = "io", moduleName = "io"} +] [[package]] org = "ballerina" @@ -280,6 +283,7 @@ version = "0.2.0" dependencies = [ {org = "ballerina", name = "crypto"}, {org = "ballerina", name = "http"}, + {org = "ballerina", name = "io"}, {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "mime"}, {org = "ballerina", name = "regex"}, From 1b1fbc94afbf05811bd5a913b32929cf7402592f Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Fri, 13 Oct 2023 05:27:58 +0530 Subject: [PATCH 156/189] [Automated] Update the native jar versions --- ballerina/Dependencies.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index 2e7a40d..4582a0b 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -64,7 +64,7 @@ dependencies = [ [[package]] org = "ballerina" name = "http" -version = "2.10.2" +version = "2.10.3" dependencies = [ {org = "ballerina", name = "auth"}, {org = "ballerina", name = "cache"}, From 0cb949229eac23623763d89bd5c42b89ef7362bd Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Fri, 13 Oct 2023 07:04:17 +0530 Subject: [PATCH 157/189] [Automated] Update the native jar versions --- ballerina/Dependencies.toml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index 4582a0b..75c7f11 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -101,9 +101,6 @@ dependencies = [ {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "lang.value"} ] -modules = [ - {org = "ballerina", packageName = "io", moduleName = "io"} -] [[package]] org = "ballerina" @@ -283,7 +280,6 @@ version = "0.2.0" dependencies = [ {org = "ballerina", name = "crypto"}, {org = "ballerina", name = "http"}, - {org = "ballerina", name = "io"}, {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "mime"}, {org = "ballerina", name = "regex"}, From d269974f7d8dd51421ac606c6e8c72f8c8db4261 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Fri, 13 Oct 2023 07:04:55 +0530 Subject: [PATCH 158/189] [Automated] Update the native jar versions --- ballerina/Dependencies.toml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index 75c7f11..4582a0b 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -101,6 +101,9 @@ dependencies = [ {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "lang.value"} ] +modules = [ + {org = "ballerina", packageName = "io", moduleName = "io"} +] [[package]] org = "ballerina" @@ -280,6 +283,7 @@ version = "0.2.0" dependencies = [ {org = "ballerina", name = "crypto"}, {org = "ballerina", name = "http"}, + {org = "ballerina", name = "io"}, {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "mime"}, {org = "ballerina", name = "regex"}, From 2624834f6b95d7d49e0089737c671f88944eb272 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Fri, 13 Oct 2023 07:09:25 +0530 Subject: [PATCH 159/189] Remove `regex` dependency --- build.gradle | 1 - gradle.properties | 1 - 2 files changed, 2 deletions(-) diff --git a/build.gradle b/build.gradle index 51ac0aa..5d2e722 100644 --- a/build.gradle +++ b/build.gradle @@ -79,7 +79,6 @@ subprojects { ballerinaStdLibs "io.ballerina.stdlib:crypto-ballerina:${project.stdlibCryptoVersion}" ballerinaStdLibs "io.ballerina.stdlib:time-ballerina:${project.stdlibTimeVersion}" ballerinaStdLibs "io.ballerina.stdlib:uuid-ballerina:${project.stdlibUuidVersion}" - ballerinaStdLibs "io.ballerina.stdlib:regex-ballerina:${project.stdlibRegexVersion}" ballerinaStdLibs "io.ballerina.stdlib:auth-ballerina:${project.stdlibAuthVersion}" ballerinaStdLibs "io.ballerina.stdlib:jwt-ballerina:${project.stdlibJwtVersion}" ballerinaStdLibs "io.ballerina.stdlib:oauth2-ballerina:${project.stdlibOAuth2Version}" diff --git a/gradle.properties b/gradle.properties index ee4df37..1f9d13f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -20,7 +20,6 @@ stdlibCryptoVersion=2.5.0 stdlibLogVersion=2.9.0 stdlibOsVersion=1.8.0 stdlibRandomVersion=1.5.0 -stdlibRegexVersion=1.4.3 stdlibTaskVersion=2.5.0 stdlibCacheVersion=3.7.0 From 8f8331c91d2f878d38ccf4f90fdb18e055b591dc Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Fri, 13 Oct 2023 07:13:16 +0530 Subject: [PATCH 160/189] Make the modules isolated --- ballerina/modules/soap11/soap11.bal | 47 +++++++++++-------- ballerina/modules/soap12/soap12.bal | 47 +++++++++++++------ ballerina/modules/wssec/document.bal | 10 ++-- ballerina/modules/wssec/encryption.bal | 16 +++---- ballerina/modules/wssec/sec_header.bal | 8 ++-- ballerina/modules/wssec/signature.bal | 16 +++---- ballerina/modules/wssec/ws_security.bal | 10 ++-- .../modules/wssec/ws_security_methods.bal | 26 +++++----- ballerina/soap_utils.bal | 23 +++++---- .../src/main/java/org/wssec/WsSecurity.java | 6 +++ 10 files changed, 123 insertions(+), 86 deletions(-) diff --git a/ballerina/modules/soap11/soap11.bal b/ballerina/modules/soap11/soap11.bal index d1b34eb..cff2e07 100644 --- a/ballerina/modules/soap11/soap11.bal +++ b/ballerina/modules/soap11/soap11.bal @@ -20,22 +20,23 @@ import ballerina/http; import ballerina/mime; # Object for the basic SOAP client endpoint. -public client class Client { +public isolated client class Client { private final http:Client soapClient; - private wssec:InboundSecurityConfig|wssec:InboundSecurityConfig[] inboundSecurity; - private wssec:OutboundSecurityConfig? outboundSecurity; + private final readonly & wssec:InboundSecurityConfig|wssec:InboundSecurityConfig[] inboundSecurity; + private final readonly & wssec:OutboundSecurityConfig outboundSecurity; # Gets invoked during object initialization. # # + url - URL endpoint # + config - Configurations for SOAP client # + return - `error` in case of errors or `()` otherwise - public function init(string url, *soap:ClientConfig config) returns Error? { + public isolated function init(string url, *soap:ClientConfig config) returns Error? { do { check soap:validateTransportBindingPolicy(config); self.soapClient = check new (url, soap:retrieveHttpClientConfig(config)); - self.inboundSecurity = config.inboundSecurity; - self.outboundSecurity = config.outboundSecurity; + readonly & soap:ClientConfig readonlyConfig = soap:getReadOnlyRecords(config); + self.inboundSecurity = readonlyConfig.inboundSecurity; + self.outboundSecurity = readonlyConfig.outboundSecurity; } on fail var err { return error Error(SOAP_CLIENT_ERROR, err); } @@ -54,22 +55,30 @@ public client class Client { map headers = {}) returns xml|mime:Entity[]|Error { do { xml securedBody; + xml response; + xml mimeEntity = body is xml ? body : check body[0].getXml(); + lock { + xml envelope = body is xml ? body.clone() : mimeEntity.clone(); + securedBody = check soap:applySecurityPolicies(self.inboundSecurity.clone(), envelope.clone()); + } + if body is mime:Entity[] { + body[0].setXml(securedBody); if body is xml { securedBody = check soap:applySecurityPolicies(self.inboundSecurity, body); } else { securedBody = check soap:applySecurityPolicies(self.inboundSecurity, check body[0].getXml()); } - xml response = check soap:sendReceive(securedBody, self.soapClient, - action, headers, false); - wssec:OutboundSecurityConfig? outboundSecurity = self.outboundSecurity; - do { - if outboundSecurity !is () { - return check soap:applyOutboundConfig(outboundSecurity, response); + lock { + wssec:OutboundSecurityConfig? outboundSecurity = self.outboundSecurity.clone(); + do { + if outboundSecurity !is () { + return check soap:applyOutboundConfig(outboundSecurity.clone(), response.clone()); + } + } on fail var e { + return error Error(INVALID_OUTBOUND_SECURITY_ERROR, e.cause()); } - } on fail var e { - return error Error(INVALID_OUTBOUND_SECURITY_ERROR, e.cause()); + return response.clone(); } - return response; } on fail var e { return error Error(e.message()); } @@ -89,10 +98,10 @@ public client class Client { map headers = {}) returns Error? { do { xml securedBody; - if body is xml { - securedBody = check soap:applySecurityPolicies(self.inboundSecurity, body); - } else { - securedBody = check soap:applySecurityPolicies(self.inboundSecurity, check body[0].getXml()); + xml mimeEntity = body is xml ? body : check body[0].getXml(); + lock { + xml envelope = body is xml ? body.clone() : mimeEntity.clone(); + securedBody = check soap:applySecurityPolicies(self.inboundSecurity.clone(), envelope.clone()); } return check soap:sendOnly(securedBody, self.soapClient, action, headers, false); } on fail var e { diff --git a/ballerina/modules/soap12/soap12.bal b/ballerina/modules/soap12/soap12.bal index d5214ba..5f99c2f 100644 --- a/ballerina/modules/soap12/soap12.bal +++ b/ballerina/modules/soap12/soap12.bal @@ -20,22 +20,23 @@ import ballerina/http; import ballerina/mime; # Object for the basic SOAP client endpoint. -public client class Client { +public isolated client class Client { private final http:Client soapClient; - private wssec:InboundSecurityConfig|wssec:InboundSecurityConfig[] inboundSecurity; - private wssec:OutboundSecurityConfig? outboundSecurity; + private final readonly & wssec:InboundSecurityConfig|wssec:InboundSecurityConfig[] inboundSecurity; + private final readonly & wssec:OutboundSecurityConfig outboundSecurity; # Gets invoked during object initialization. # # + url - URL endpoint # + config - Configurations for SOAP client # + return - `error` in case of errors or `()` otherwise - public function init(string url, *soap:ClientConfig config) returns Error? { + public isolated function init(string url, *soap:ClientConfig config) returns Error? { do { check soap:validateTransportBindingPolicy(config); self.soapClient = check new (url, soap:retrieveHttpClientConfig(config)); - self.inboundSecurity = config.inboundSecurity; - self.outboundSecurity = config.outboundSecurity; + readonly & soap:ClientConfig readonlyConfig = soap:getReadOnlyRecords(config); + self.inboundSecurity = readonlyConfig.inboundSecurity; + self.outboundSecurity = readonlyConfig.outboundSecurity; } on fail var err { return error Error(SOAP_CLIENT_ERROR, err); } @@ -54,21 +55,30 @@ public client class Client { map headers = {}) returns xml|mime:Entity[]|Error { do { xml securedBody; + xml response; + xml mimeEntity = body is xml ? body : check body[0].getXml(); + lock { + securedBody = body is xml ? check soap:applySecurityPolicies(self.inboundSecurity.clone(), body.clone()) + : check soap:applySecurityPolicies(self.inboundSecurity.clone(), mimeEntity.clone()); + } + if body is mime:Entity[] { + body[0].setXml(securedBody); if body is xml { securedBody = check soap:applySecurityPolicies(self.inboundSecurity, body); } else { securedBody = check soap:applySecurityPolicies(self.inboundSecurity, check body[0].getXml()); } - xml response = check soap:sendReceive(securedBody, self.soapClient, action, headers); - wssec:OutboundSecurityConfig? outboundSecurity = self.outboundSecurity; - do { - if outboundSecurity !is () { - return check soap:applyOutboundConfig(outboundSecurity, response); + lock { + wssec:OutboundSecurityConfig? outboundSecurity = self.outboundSecurity.clone(); + do { + if outboundSecurity !is () { + return check soap:applyOutboundConfig(outboundSecurity.clone(), response.clone()); + } + } on fail var e { + return error Error(INVALID_OUTBOUND_SECURITY_ERROR, e.cause()); } - } on fail var e { - return error Error(INVALID_OUTBOUND_SECURITY_ERROR, e.cause()); + return response.clone(); } - return response; } on fail var e { return error Error(e.message()); } @@ -88,12 +98,19 @@ public client class Client { map headers = {}) returns Error? { do { xml securedBody; + xml mimeEntity = body is xml ? body : check body[0].getXml(); + lock { + securedBody = body is xml ? check soap:applySecurityPolicies(self.inboundSecurity.clone(), body.clone()) + : check soap:applySecurityPolicies(self.inboundSecurity.clone(), mimeEntity.clone()); + } + if body is mime:Entity[] { + body[0].setXml(securedBody); if body is xml { securedBody = check soap:applySecurityPolicies(self.inboundSecurity, body); } else { securedBody = check soap:applySecurityPolicies(self.inboundSecurity, check body[0].getXml()); } - return check soap:sendOnly(securedBody, self.soapClient, action, headers); + return check soap:sendOnly(securedBody, self.soapClient, action, headers, path); } on fail var e { return error Error(e.message()); } diff --git a/ballerina/modules/wssec/document.bal b/ballerina/modules/wssec/document.bal index f467a4a..515bb01 100644 --- a/ballerina/modules/wssec/document.bal +++ b/ballerina/modules/wssec/document.bal @@ -15,11 +15,11 @@ // under the License. import ballerina/jballerina.java; -class Document { +isolated class Document { private handle nativeDocumentBuilder; - public function init(xml xmlPayload) returns Error? { + public isolated function init(xml xmlPayload) returns Error? { handle|error documentBuilder = newDocument(xmlPayload); if documentBuilder is error { return error Error(documentBuilder.message()); @@ -28,15 +28,15 @@ class Document { } } - public function getEncryptedData() returns byte[] = @java:Method { + public isolated function getEncryptedData() returns byte[] = @java:Method { 'class: "org.wssec.DocumentBuilder" } external; - public function getSignatureData() returns byte[] = @java:Method { + public isolated function getSignatureData() returns byte[] = @java:Method { 'class: "org.wssec.DocumentBuilder" } external; } -function newDocument(xml xmlPayload) returns handle|error = @java:Constructor { +isolated function newDocument(xml xmlPayload) returns handle|error = @java:Constructor { 'class: "org.wssec.DocumentBuilder" } external; diff --git a/ballerina/modules/wssec/encryption.bal b/ballerina/modules/wssec/encryption.bal index b9f2a8c..f45f731 100644 --- a/ballerina/modules/wssec/encryption.bal +++ b/ballerina/modules/wssec/encryption.bal @@ -16,15 +16,15 @@ import ballerina/crypto; import ballerina/jballerina.java; -class Encryption { +isolated class Encryption { private handle nativeEncryption; - function init() returns Error? { + isolated function init() returns Error? { self.nativeEncryption = newEncryption(); } - function encryptData(string dataString, EncryptionAlgorithm encryptionAlgorithm, + isolated function encryptData(string dataString, EncryptionAlgorithm encryptionAlgorithm, crypto:PublicKey|crypto:PrivateKey key) returns byte[]|Error { byte[] data = dataString.toBytes(); do { @@ -34,7 +34,7 @@ class Encryption { } } - public function decryptData(byte[] cipherText, EncryptionAlgorithm encryptionAlgorithm, + public isolated function decryptData(byte[] cipherText, EncryptionAlgorithm encryptionAlgorithm, crypto:PublicKey|crypto:PrivateKey key) returns byte[]|Error { do { return check crypto:decryptRsaEcb(cipherText, key); @@ -43,19 +43,19 @@ class Encryption { } } - public function setEncryptionAlgorithm(string encryptionAlgorithm) = @java:Method { + public isolated function setEncryptionAlgorithm(string encryptionAlgorithm) = @java:Method { 'class: "org.wssec.Encryption" } external; - public function setEncryptedData(byte[] encryptedData) = @java:Method { + public isolated function setEncryptedData(byte[] encryptedData) = @java:Method { 'class: "org.wssec.Encryption" } external; - public function getEncryptedKeyElements(byte[] encryptedKey) returns string|Error = @java:Method { + public isolated function getEncryptedKeyElements(byte[] encryptedKey) returns string|Error = @java:Method { 'class: "org.wssec.Encryption" } external; } -function newEncryption() returns handle = @java:Constructor { +isolated function newEncryption() returns handle = @java:Constructor { 'class: "org.wssec.Encryption" } external; diff --git a/ballerina/modules/wssec/sec_header.bal b/ballerina/modules/wssec/sec_header.bal index 92f4deb..68d831b 100644 --- a/ballerina/modules/wssec/sec_header.bal +++ b/ballerina/modules/wssec/sec_header.bal @@ -15,19 +15,19 @@ // under the License. import ballerina/jballerina.java; -class WSSecurityHeader { +isolated class WSSecurityHeader { private handle nativeSecHeader; - function init(Document document) returns Error? { + isolated function init(Document document) returns Error? { self.nativeSecHeader = newSecHeader(document); } - function insertSecHeader() returns Error? = @java:Method { + isolated function insertSecHeader() returns Error? = @java:Method { 'class: "org.wssec.WsSecurityHeader" } external; } -function newSecHeader(Document document) returns handle = @java:Constructor { +isolated function newSecHeader(Document document) returns handle = @java:Constructor { 'class: "org.wssec.WsSecurityHeader" } external; diff --git a/ballerina/modules/wssec/signature.bal b/ballerina/modules/wssec/signature.bal index 560a36e..0bf11f6 100644 --- a/ballerina/modules/wssec/signature.bal +++ b/ballerina/modules/wssec/signature.bal @@ -16,16 +16,16 @@ import ballerina/crypto; import ballerina/jballerina.java; -class Signature { +isolated class Signature { private handle nativeSignature; - function init() returns Error? { + isolated function init() returns Error? { self.nativeSignature = newSignature(); } - public function signData(string dataString, SignatureAlgorithm signatureAlgorithm, - crypto:PrivateKey privateKey) returns byte[]|Error { + public isolated function signData(string dataString, SignatureAlgorithm signatureAlgorithm, + crypto:PrivateKey privateKey) returns byte[]|Error { byte[] data = dataString.toBytes(); do { match signatureAlgorithm { @@ -47,7 +47,7 @@ class Signature { } } - public function verifySignature(byte[] data, byte[] signature, crypto:PublicKey publicKey, + public isolated function verifySignature(byte[] data, byte[] signature, crypto:PublicKey publicKey, SignatureAlgorithm signatureAlgorithm) returns boolean|Error { do { match signatureAlgorithm { @@ -69,15 +69,15 @@ class Signature { } } - public function setSignatureAlgorithm(string signatureAlgorithm) = @java:Method { + public isolated function setSignatureAlgorithm(string signatureAlgorithm) = @java:Method { 'class: "org.wssec.Signature" } external; - public function setSignatureValue(byte[] signatureValue) = @java:Method { + public isolated function setSignatureValue(byte[] signatureValue) = @java:Method { 'class: "org.wssec.Signature" } external; } -function newSignature() returns handle = @java:Constructor { +isolated function newSignature() returns handle = @java:Constructor { 'class: "org.wssec.Signature" } external; diff --git a/ballerina/modules/wssec/ws_security.bal b/ballerina/modules/wssec/ws_security.bal index 036ce95..326ca3a 100644 --- a/ballerina/modules/wssec/ws_security.bal +++ b/ballerina/modules/wssec/ws_security.bal @@ -15,23 +15,23 @@ // under the License. import ballerina/jballerina.java; -class WsSecurity { - function applyUsernameTokenPolicy(WSSecurityHeader wsSecurityHeader, string username, +isolated class WsSecurity { + isolated function applyUsernameTokenPolicy(WSSecurityHeader wsSecurityHeader, string username, string password, string pwType) returns string|Error = @java:Method { 'class: "org.wssec.WsSecurity" } external; - function applyTimestampPolicy(WSSecurityHeader wsSecurityHeader, int timeToLive) + isolated function applyTimestampPolicy(WSSecurityHeader wsSecurityHeader, int timeToLive) returns string|Error = @java:Method { 'class: "org.wssec.WsSecurity" } external; - function applySignatureOnlyPolicy(WSSecurityHeader wsSecurityPolicy, Signature signature, string? x509FilePath) + isolated function applySignatureOnlyPolicy(WSSecurityHeader wsSecurityPolicy, Signature signature, string? x509FilePath) returns string|Error = @java:Method { 'class: "org.wssec.WsSecurity" } external; - function applyEncryptionOnlyPolicy(WSSecurityHeader wsSecurityPolicy, Encryption encryption) + isolated function applyEncryptionOnlyPolicy(WSSecurityHeader wsSecurityPolicy, Encryption encryption) returns string|Error = @java:Method { 'class: "org.wssec.WsSecurity" } external; diff --git a/ballerina/modules/wssec/ws_security_methods.bal b/ballerina/modules/wssec/ws_security_methods.bal index 5daa6ce..976df57 100644 --- a/ballerina/modules/wssec/ws_security_methods.bal +++ b/ballerina/modules/wssec/ws_security_methods.bal @@ -19,7 +19,7 @@ import ballerina/regex; xmlns "http://schemas.xmlsoap.org/soap/envelope/" as soap; xmlns "http://www.w3.org/2000/09/xmldsig#" as ds; -function addSecurityHeader(Document document) returns WSSecurityHeader|Error { +isolated function addSecurityHeader(Document document) returns WSSecurityHeader|Error { WSSecurityHeader wsSecHeader = check new (document); Error? insertHeader = wsSecHeader.insertSecHeader(); if insertHeader is () { @@ -28,31 +28,31 @@ function addSecurityHeader(Document document) returns WSSecurityHeader|Error { return insertHeader; } -public function decryptData(byte[] cipherText, EncryptionAlgorithm encryptionAlgorithm, +public isolated function decryptData(byte[] cipherText, EncryptionAlgorithm encryptionAlgorithm, crypto:PublicKey|crypto:PrivateKey key) returns byte[]|Error { Encryption encrypt = check new (); return encrypt.decryptData(cipherText, encryptionAlgorithm, key); } -public function verifyData(byte[] data, byte[] signature, crypto:PublicKey publicKey, +public isolated function verifyData(byte[] data, byte[] signature, crypto:PublicKey publicKey, SignatureAlgorithm signatureAlgorithm) returns boolean|Error { Signature sign = check new (); return sign.verifySignature(data, signature, publicKey, signatureAlgorithm); } -function addSignature(Signature sign, string signatureAlgorithm, byte[] signature) returns Signature|Error { +isolated function addSignature(Signature sign, string signatureAlgorithm, byte[] signature) returns Signature|Error { sign.setSignatureAlgorithm(signatureAlgorithm); sign.setSignatureValue(signature); return sign; } -function addEncryption(Encryption encrypt, string encryptionAlgorithm, byte[] encryption) returns Encryption|Error { +isolated function addEncryption(Encryption encrypt, string encryptionAlgorithm, byte[] encryption) returns Encryption|Error { encrypt.setEncryptionAlgorithm(encryptionAlgorithm); encrypt.setEncryptedData(encryption); return encrypt; } -function applyEncryptedKey(string envelopeString, crypto:PrivateKey symmetricKey, crypto:PublicKey encryptKey) +isolated function applyEncryptedKey(string envelopeString, crypto:PrivateKey symmetricKey, crypto:PublicKey encryptKey) returns string|Error { string securedEnvelope = envelopeString; do { @@ -74,7 +74,7 @@ function applyEncryptedKey(string envelopeString, crypto:PrivateKey symmetricKey } } -function convertStringToXml(string envelope) returns xml|Error { +isolated function convertStringToXml(string envelope) returns xml|Error { do { return check xml:fromString(regex:replace(envelope, string `<`, "<")); } on fail var e { @@ -86,7 +86,7 @@ function convertStringToXml(string envelope) returns xml|Error { # # + envelope - The SOAP envelope # + return - A `byte[]` if the encrypted data is successfully decoded or else `wssec:Error` -public function getEncryptedData(xml envelope) returns byte[]|Error { +public isolated function getEncryptedData(xml envelope) returns byte[]|Error { Document document = check new (envelope); return document.getEncryptedData(); } @@ -95,7 +95,7 @@ public function getEncryptedData(xml envelope) returns byte[]|Error { # # + envelope - The SOAP envelope # + return - A `byte[]` if the signed data is successfully decoded or else `wssec:Error` -public function getSignatureData(xml envelope) returns byte[]|Error { +public isolated function getSignatureData(xml envelope) returns byte[]|Error { Document document = check new (envelope); return document.getSignatureData(); } @@ -105,7 +105,7 @@ public function getSignatureData(xml envelope) returns byte[]|Error { # + envelope - The SOAP envelope # + timestampToken - The `TSRecord` record with the required parameters # + return - A `xml` type of SOAP envelope if the security binding is successfully added or else `wssec:Error` -public function applyTimestampToken(xml envelope, *TimestampTokenConfig timestampToken) returns xml|Error { +public isolated function applyTimestampToken(xml envelope, *TimestampTokenConfig timestampToken) returns xml|Error { if timestampToken.timeToLive <= 0 { return error Error("Invalid value for `timeToLive`"); } @@ -121,7 +121,7 @@ public function applyTimestampToken(xml envelope, *TimestampTokenConfig timestam # + envelope - The SOAP envelope # + usernameToken - The `UsernameTokenConfig` record with the required parameters # + return - A `xml` type of SOAP envelope if the security binding is successfully added or else `wssec:Error` -public function applyUsernameToken(xml envelope, *UsernameTokenConfig usernameToken) returns xml|Error { +public isolated function applyUsernameToken(xml envelope, *UsernameTokenConfig usernameToken) returns xml|Error { Document document = check new (envelope); WSSecurityHeader wsSecurityHeader = check addSecurityHeader(document); WsSecurity wsSecurity = new; @@ -136,7 +136,7 @@ public function applyUsernameToken(xml envelope, *UsernameTokenConfig usernameTo # + envelope - The SOAP envelope # + symmetricBinding - The `SymmetricBindingConfig` record with the required parameters # + return - A `xml` type of SOAP envelope if the security binding is successfully added or else `wssec:Error` -public function applySymmetricBinding(xml envelope, *SymmetricBindingConfig symmetricBinding) returns xml|Error { +public isolated function applySymmetricBinding(xml envelope, *SymmetricBindingConfig symmetricBinding) returns xml|Error { Document document = check new (envelope); WSSecurityHeader wsSecurityHeader = check addSecurityHeader(document); string securedEnvelope = envelope.toBalString(); @@ -173,7 +173,7 @@ public function applySymmetricBinding(xml envelope, *SymmetricBindingConfig symm # + envelope - The SOAP envelope # + asymmetricBinding - The `AsymmetricBindingConfig` record with the required parameters # + return - A `xml` type of SOAP envelope if the security binding is successfully added or else `wssec:Error` -public function applyAsymmetricBinding(xml envelope, *AsymmetricBindingConfig asymmetricBinding) returns xml|Error { +public isolated function applyAsymmetricBinding(xml envelope, *AsymmetricBindingConfig asymmetricBinding) returns xml|Error { Document document = check new (envelope); WSSecurityHeader wsSecurityHeader = check addSecurityHeader(document); string securedEnvelope = envelope.toBalString(); diff --git a/ballerina/soap_utils.bal b/ballerina/soap_utils.bal index 67faca8..ced66e2 100644 --- a/ballerina/soap_utils.bal +++ b/ballerina/soap_utils.bal @@ -19,8 +19,9 @@ import ballerina/crypto; import ballerina/http; import ballerina/mime; import ballerina/regex; +import ballerina/jballerina.java; -public function validateTransportBindingPolicy(ClientConfig config) returns Error? { +public isolated function validateTransportBindingPolicy(ClientConfig config) returns Error? { if config.httpConfig.secureSocket is () { wssec:InboundSecurityConfig|wssec:InboundSecurityConfig[] securityPolicy = config.inboundSecurity; if securityPolicy is wssec:TransportBindingConfig { @@ -35,7 +36,7 @@ public function validateTransportBindingPolicy(ClientConfig config) returns Erro } } -public function retrieveHttpClientConfig(ClientConfig config) returns http:ClientConfiguration { +public isolated function retrieveHttpClientConfig(ClientConfig config) returns http:ClientConfiguration { return { httpVersion: config.httpConfig.httpVersion, http1Settings: config.httpConfig.http1Settings, @@ -50,7 +51,11 @@ public function retrieveHttpClientConfig(ClientConfig config) returns http:Clien }; } -public function applySecurityPolicies(wssec:InboundSecurityConfig|wssec:InboundSecurityConfig[] inboundSecurity, +public isolated function getReadOnlyRecords(ClientConfig original) returns readonly & ClientConfig = @java:Method { + 'class: "org.wssec.WsSecurity" +} external; + +public isolated function applySecurityPolicies(wssec:InboundSecurityConfig|wssec:InboundSecurityConfig[] inboundSecurity, xml envelope) returns xml|wssec:Error { wssec:InboundSecurityConfig|wssec:InboundSecurityConfig[] securityPolicy = inboundSecurity; xml securedEnvelope; @@ -74,7 +79,7 @@ public function applySecurityPolicies(wssec:InboundSecurityConfig|wssec:InboundS return securedEnvelope; } -public function applyOutboundConfig(wssec:OutboundSecurityConfig outboundSecurity, xml envelope) +public isolated function applyOutboundConfig(wssec:OutboundSecurityConfig outboundSecurity, xml envelope) returns xml|Error { xmlns "http://schemas.xmlsoap.org/soap/envelope/" as soap; xml soapEnvelope = envelope; @@ -144,8 +149,8 @@ public function sendOnly(xml|mime:Entity[] body, http:Client httpClient, string? } } -function createSoap11HttpRequest(xml|mime:Entity[] body, - string soapAction, map headers = {}) returns http:Request { +isolated function createSoap11HttpRequest(xml|mime:Entity[] body, string soapAction, + map headers = {}) returns http:Request { http:Request req = new; if body is xml { req.setXmlPayload(body); @@ -160,7 +165,7 @@ function createSoap11HttpRequest(xml|mime:Entity[] body, return req; } -function createSoap12HttpRequest(xml|mime:Entity[] body, string? soapAction, +isolated function createSoap12HttpRequest(xml|mime:Entity[] body, string? soapAction, map headers = {}) returns http:Request { http:Request req = new; if body is xml { @@ -185,13 +190,13 @@ function createSoap12HttpRequest(xml|mime:Entity[] body, string? soapAction, return req; } -function createSoap12Response(http:Response response) returns xml|error { +isolated function createSoap12Response(http:Response response) returns xml|error { xml payload = check response.getXmlPayload(); xmlns "http://www.w3.org/2003/05/soap-envelope" as soap12; return payload/; } -function createSoap11Response(http:Response response) returns xml|error { +isolated function createSoap11Response(http:Response response) returns xml|error { xml payload = check response.getXmlPayload(); xmlns "http://schemas.xmlsoap.org/soap/envelope/" as soap11; return payload/; diff --git a/native/src/main/java/org/wssec/WsSecurity.java b/native/src/main/java/org/wssec/WsSecurity.java index d3bfcee..184b6d7 100644 --- a/native/src/main/java/org/wssec/WsSecurity.java +++ b/native/src/main/java/org/wssec/WsSecurity.java @@ -18,6 +18,7 @@ import io.ballerina.runtime.api.utils.StringUtils; import io.ballerina.runtime.api.values.BHandle; +import io.ballerina.runtime.api.values.BMap; import io.ballerina.runtime.api.values.BObject; import io.ballerina.runtime.api.values.BString; import org.apache.wss4j.common.ext.WSSecurityException; @@ -164,4 +165,9 @@ public static WSSecSignature prepareSignature(RequestData reqData, Object x509Fi } return sign; } + + public static BMap getReadOnlyRecords(BMap securityConfig) { + securityConfig.freezeDirect(); + return securityConfig; + } } From 5970f3c296456823f3776b0fc896f51cf76754f4 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Fri, 13 Oct 2023 07:13:58 +0530 Subject: [PATCH 161/189] Fix issues in supporting `mime:Entity[]` type requests --- ballerina/modules/soap11/soap11.bal | 17 ++-- .../soap11/tests/http_soap_service.bal | 25 +++++ .../soap11/tests/soap11_client_test.bal | 99 ++++++++++++++++++- ballerina/modules/soap12/soap12.bal | 20 ++-- ballerina/soap_utils.bal | 11 ++- 5 files changed, 146 insertions(+), 26 deletions(-) create mode 100644 ballerina/modules/soap11/tests/http_soap_service.bal diff --git a/ballerina/modules/soap11/soap11.bal b/ballerina/modules/soap11/soap11.bal index cff2e07..8aea210 100644 --- a/ballerina/modules/soap11/soap11.bal +++ b/ballerina/modules/soap11/soap11.bal @@ -50,9 +50,10 @@ public isolated client class Client { # + body - SOAP request body as an `XML` or `mime:Entity[]` to work with SOAP attachments # + action - SOAP action as a `string` # + headers - SOAP headers as a `map` + # + path - The resource path # + return - If successful, returns the response. Else, returns an error - remote function sendReceive(xml|mime:Entity[] body, string action, - map headers = {}) returns xml|mime:Entity[]|Error { + remote isolated function sendReceive(xml|mime:Entity[] body, string action, + map headers = {}, string path = "") returns xml|mime:Entity[]|Error { do { xml securedBody; xml response; @@ -63,10 +64,9 @@ public isolated client class Client { } if body is mime:Entity[] { body[0].setXml(securedBody); - if body is xml { - securedBody = check soap:applySecurityPolicies(self.inboundSecurity, body); + response = check soap:sendReceive(body, self.soapClient, action, headers, path, false); } else { - securedBody = check soap:applySecurityPolicies(self.inboundSecurity, check body[0].getXml()); + response = check soap:sendReceive(securedBody, self.soapClient, action, headers, path, false); } lock { wssec:OutboundSecurityConfig? outboundSecurity = self.outboundSecurity.clone(); @@ -93,9 +93,10 @@ public isolated client class Client { # + body - SOAP request body as an `XML` or `mime:Entity[]` to work with SOAP attachments # + action - SOAP action as a `string` # + headers - SOAP headers as a `map` + # + path - The resource path # + return - If successful, returns `nil`. Else, returns an error - remote function sendOnly(xml|mime:Entity[] body, string action, - map headers = {}) returns Error? { + remote isolated function sendOnly(xml|mime:Entity[] body, string action, + map headers = {}, string path = "") returns Error? { do { xml securedBody; xml mimeEntity = body is xml ? body : check body[0].getXml(); @@ -103,7 +104,7 @@ public isolated client class Client { xml envelope = body is xml ? body.clone() : mimeEntity.clone(); securedBody = check soap:applySecurityPolicies(self.inboundSecurity.clone(), envelope.clone()); } - return check soap:sendOnly(securedBody, self.soapClient, action, headers, false); + return check soap:sendOnly(securedBody, self.soapClient, action, headers, path, false); } on fail var e { return error Error(e.message()); } diff --git a/ballerina/modules/soap11/tests/http_soap_service.bal b/ballerina/modules/soap11/tests/http_soap_service.bal new file mode 100644 index 0000000..5dfa9f9 --- /dev/null +++ b/ballerina/modules/soap11/tests/http_soap_service.bal @@ -0,0 +1,25 @@ +// Copyright (c) 2023, WSO2 LLC. (http://www.wso2.org) All Rights Reserved. +// +// WSO2 LLC. licenses this file to you under the Apache License, +// Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +import ballerina/http; + +service / on new http:Listener(9090) { + + resource function post albums(http:Request request) returns http:Response|error { + http:Response response = new; + response.setPayload(check (check request.getBodyParts())[0].getXml()); + return response; + } +} diff --git a/ballerina/modules/soap11/tests/soap11_client_test.bal b/ballerina/modules/soap11/tests/soap11_client_test.bal index 23fa5f4..f5cc01c 100644 --- a/ballerina/modules/soap11/tests/soap11_client_test.bal +++ b/ballerina/modules/soap11/tests/soap11_client_test.bal @@ -19,15 +19,101 @@ import ballerina/crypto; import ballerina/mime; import ballerina/test; import soap.wssec; +import ballerina/io; const string KEY_ALIAS = "wss40"; const string KEY_PASSWORD = "security"; +const IMAGE_PATH = "../ballerina/icon.png"; +const FILE_PATH = "../ballerina/Module.md"; const string KEY_STORE_PATH = "modules/wssec/tests/resources/wss40.p12"; const string X509_KEY_STORE_PATH = "modules/wssec/tests/resources/x509_certificate.p12"; const string X509_KEY_STORE_PATH_2 = "modules/wssec/tests/resources/x509_certificate_2.p12"; const wssec:TransportBindingConfig TRANSPORT_BINDING = "TransportBinding"; const wssec:NoPolicy NO_POLICY = "NoPolicy"; +@test:Config { + groups: ["soap11", "send_receive", "mime", "aa"] +} +function testSendReceiveWithMime() returns error? { + Client soapClient = check new ("http://localhost:9090"); + xml body = xml ` + + + 2 + 3 + + + `; + + mime:Entity[] mtomMessage = []; + mime:Entity envelope = new; + check envelope.setContentType("application/xop+xml"); + envelope.setContentId(""); + envelope.setBody(body); + mtomMessage.push(envelope); + + mime:Entity bytesPart = new; + string readContent = check io:fileReadString(FILE_PATH); + bytesPart.setFileAsEntityBody(FILE_PATH); + string|byte[]|io:ReadableByteChannel|mime:EncodeError bytes = mime:base64Encode(readContent.toBytes()); + if bytes !is byte[] { + return error("error"); + } + bytesPart.setBody(bytes); + check bytesPart.setContentType("image/jpeg"); + bytesPart.setContentId(""); + mtomMessage.push(bytesPart); + + xml|mime:Entity[] response = check soapClient->sendReceive(mtomMessage, "http://tempuri.org/Add", path = "/albums"); + xml expected = xml ` + + 2 + 3 + + `; + test:assertEquals(response, expected); +} + +// @test:Config { +// groups: ["soap11", "send_only", "mime"] +// } +// function testSendOnlyWithMime() returns error? { +// xml body = xml ` +// +// +// 2 +// 3 +// +// +// `; + +// mime:Entity[] mtomMessage = []; +// mime:Entity envelope = new; +// check envelope.setContentType("application/xop+xml"); +// envelope.setContentId(""); +// envelope.setBody(body); +// mtomMessage.push(envelope); + +// mime:Entity bytesPart = new; +// string readContent = check io:fileReadString(FILE_PATH); +// bytesPart.setFileAsEntityBody(FILE_PATH); +// string|byte[]|io:ReadableByteChannel|mime:EncodeError bytes = mime:base64Encode(readContent.toBytes()); +// if bytes !is byte[] { +// return error("error"); +// } +// bytesPart.setBody(bytes); +// check bytesPart.setContentType("image/jpeg"); +// bytesPart.setContentId(""); +// mtomMessage.push(bytesPart); + +// Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL"); +// check soapClient->sendOnly(mtomMessage, "http://tempuri.org/Add"); +// } + @test:Config { groups: ["soap11", "send_only"] } @@ -44,7 +130,7 @@ function testSendOnly() returns error? { `; Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL"); - _ = check soapClient->sendOnly(body, "http://tempuri.org/Add"); + check soapClient->sendOnly(body, "http://tempuri.org/Add"); } @test:Config { @@ -141,7 +227,7 @@ function testSendReceiveError() returns error? { } @test:Config { - groups: ["soap11", "send_receive"] + groups: ["soap11", "send_receive", "kl"] } function testSendReceiveWithTimestampTokenSecurity() returns error? { Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL", @@ -222,6 +308,14 @@ function testSendReceiveWithAsymmetricBindingSecurity() returns error? { }; crypto:PrivateKey clientPrivateKey = check crypto:decodeRsaPrivateKeyFromKeyStore(clientKeyStore, KEY_ALIAS, KEY_PASSWORD); + // wssec:AsymmetricBindingConfig asymmetricConfig = { + // signatureAlgorithm: soap:RSA_SHA256, + // encryptionAlgorithm: soap:RSA_ECB, + // signatureKey: clientPrivateKey, + // encryptionKey: serverPublicKey + // }; + // wssec:AsymmetricBindingConfig & readonly asymmetricConfig2 = asymmetricConfig.clone(); + // readonly & wssec:AsymmetricBindingConfig immutableRecord = asymmetricConfig; Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL", { inboundSecurity: { @@ -232,6 +326,7 @@ function testSendReceiveWithAsymmetricBindingSecurity() returns error? { } } ); + xml body = xml ` diff --git a/ballerina/modules/soap12/soap12.bal b/ballerina/modules/soap12/soap12.bal index 5f99c2f..162da09 100644 --- a/ballerina/modules/soap12/soap12.bal +++ b/ballerina/modules/soap12/soap12.bal @@ -50,9 +50,10 @@ public isolated client class Client { # + body - SOAP request body as an `XML` or `mime:Entity[]` to work with SOAP attachments # + action - SOAP action as a `string` # + headers - SOAP headers as a `map` + # + path - The resource path # + return - If successful, returns the response. Else, returns an error - remote function sendReceive(xml|mime:Entity[] body, string? action = (), - map headers = {}) returns xml|mime:Entity[]|Error { + remote isolated function sendReceive(xml|mime:Entity[] body, string? action = (), + map headers = {}, string path = "") returns xml|mime:Entity[]|Error { do { xml securedBody; xml response; @@ -63,10 +64,9 @@ public isolated client class Client { } if body is mime:Entity[] { body[0].setXml(securedBody); - if body is xml { - securedBody = check soap:applySecurityPolicies(self.inboundSecurity, body); + response = check soap:sendReceive(body, self.soapClient, action, headers, path); } else { - securedBody = check soap:applySecurityPolicies(self.inboundSecurity, check body[0].getXml()); + response = check soap:sendReceive(securedBody, self.soapClient, action, headers, path); } lock { wssec:OutboundSecurityConfig? outboundSecurity = self.outboundSecurity.clone(); @@ -93,9 +93,10 @@ public isolated client class Client { # + body - SOAP request body as an `XML` or `mime:Entity[]` to work with SOAP attachments # + action - SOAP action as a `string` # + headers - SOAP headers as a `map` + # + path - The resource path # + return - If successful, returns `nil`. Else, returns an error - remote function sendOnly(xml|mime:Entity[] body, string? action = (), - map headers = {}) returns Error? { + remote isolated function sendOnly(xml|mime:Entity[] body, string? action = (), + map headers = {}, string path = "") returns Error? { do { xml securedBody; xml mimeEntity = body is xml ? body : check body[0].getXml(); @@ -105,10 +106,7 @@ public isolated client class Client { } if body is mime:Entity[] { body[0].setXml(securedBody); - if body is xml { - securedBody = check soap:applySecurityPolicies(self.inboundSecurity, body); - } else { - securedBody = check soap:applySecurityPolicies(self.inboundSecurity, check body[0].getXml()); + return check soap:sendOnly(body, self.soapClient, action, headers, path); } return check soap:sendOnly(securedBody, self.soapClient, action, headers, path); } on fail var e { diff --git a/ballerina/soap_utils.bal b/ballerina/soap_utils.bal index ced66e2..a0567e1 100644 --- a/ballerina/soap_utils.bal +++ b/ballerina/soap_utils.bal @@ -116,8 +116,8 @@ public isolated function applyOutboundConfig(wssec:OutboundSecurityConfig outbou string path = ""; -public function sendReceive(xml|mime:Entity[] body, http:Client httpClient, string? soapAction = (), - map headers = {}, boolean soap12 = true) returns xml|Error { +public isolated function sendReceive(xml|mime:Entity[] body, http:Client httpClient, string? soapAction = (), + map headers = {}, string path = "", boolean soap12 = true) returns xml|Error { http:Request req; if soap12 { req = createSoap12HttpRequest(body, soapAction, headers); @@ -135,8 +135,8 @@ public function sendReceive(xml|mime:Entity[] body, http:Client httpClient, stri } } -public function sendOnly(xml|mime:Entity[] body, http:Client httpClient, string? soapAction = (), - map headers = {}, boolean soap12 = true) returns Error? { +public isolated function sendOnly(xml|mime:Entity[] body, http:Client httpClient, string? soapAction = (), + map headers = {}, string path = "", boolean soap12 = true) returns Error? { http:Request req; if soap12 { req = createSoap12HttpRequest(body, soapAction, headers); @@ -154,10 +154,11 @@ isolated function createSoap11HttpRequest(xml|mime:Entity[] body, string soapAct http:Request req = new; if body is xml { req.setXmlPayload(body); + req.setHeader(mime:CONTENT_TYPE, mime:TEXT_XML); } else { req.setBodyParts(body); + req.setHeader(mime:CONTENT_TYPE, mime:MULTIPART_MIXED); } - req.setHeader(mime:CONTENT_TYPE, mime:TEXT_XML); req.addHeader(SOAP_ACTION, soapAction); foreach string key in headers.keys() { req.addHeader(key, headers[key].toBalString()); From 999d4d36857a460c4475c6ec0c9c7c5a6f8489e0 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Fri, 13 Oct 2023 08:13:40 +0530 Subject: [PATCH 162/189] Fix type checking in `if` statement --- ballerina/modules/soap11/soap11.bal | 2 +- ballerina/modules/soap12/soap12.bal | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ballerina/modules/soap11/soap11.bal b/ballerina/modules/soap11/soap11.bal index 0916a8d..6ae4d0a 100644 --- a/ballerina/modules/soap11/soap11.bal +++ b/ballerina/modules/soap11/soap11.bal @@ -71,7 +71,7 @@ public isolated client class Client { lock { wssec:OutboundSecurityConfig? outboundSecurity = self.outboundSecurity.clone(); do { - if outboundSecurity !is () { + if outboundSecurity is wssec:OutboundSecurityConfig { return check soap:applyOutboundConfig(outboundSecurity.clone(), response.clone()); } } on fail var e { diff --git a/ballerina/modules/soap12/soap12.bal b/ballerina/modules/soap12/soap12.bal index a99a3e4..030baee 100644 --- a/ballerina/modules/soap12/soap12.bal +++ b/ballerina/modules/soap12/soap12.bal @@ -71,7 +71,7 @@ public isolated client class Client { lock { wssec:OutboundSecurityConfig? outboundSecurity = self.outboundSecurity.clone(); do { - if outboundSecurity !is () { + if outboundSecurity is wssec:OutboundSecurityConfig { return check soap:applyOutboundConfig(outboundSecurity.clone(), response.clone()); } } on fail var e { From e9edbae0d08c22c3c596d9cb8a303631e3604514 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Fri, 13 Oct 2023 08:18:51 +0530 Subject: [PATCH 163/189] Remove unnecessary method --- ballerina/modules/soap11/soap11.bal | 2 +- ballerina/modules/soap12/soap12.bal | 2 +- ballerina/soap_utils.bal | 22 ++-------------------- 3 files changed, 4 insertions(+), 22 deletions(-) diff --git a/ballerina/modules/soap11/soap11.bal b/ballerina/modules/soap11/soap11.bal index 6ae4d0a..84c2dd2 100644 --- a/ballerina/modules/soap11/soap11.bal +++ b/ballerina/modules/soap11/soap11.bal @@ -33,7 +33,7 @@ public isolated client class Client { public isolated function init(string url, *soap:ClientConfig config) returns Error? { do { check soap:validateTransportBindingPolicy(config); - self.soapClient = check new (url, soap:retrieveHttpClientConfig(config)); + self.soapClient = check new (url, config.httpConfig); readonly & soap:ClientConfig readonlyConfig = soap:getReadOnlyRecords(config); self.inboundSecurity = readonlyConfig.inboundSecurity; self.outboundSecurity = readonlyConfig.outboundSecurity; diff --git a/ballerina/modules/soap12/soap12.bal b/ballerina/modules/soap12/soap12.bal index 030baee..c1eaeae 100644 --- a/ballerina/modules/soap12/soap12.bal +++ b/ballerina/modules/soap12/soap12.bal @@ -33,7 +33,7 @@ public isolated client class Client { public isolated function init(string url, *soap:ClientConfig config) returns Error? { do { check soap:validateTransportBindingPolicy(config); - self.soapClient = check new (url, soap:retrieveHttpClientConfig(config)); + self.soapClient = check new (url, config.httpConfig); readonly & soap:ClientConfig readonlyConfig = soap:getReadOnlyRecords(config); self.inboundSecurity = readonlyConfig.inboundSecurity; self.outboundSecurity = readonlyConfig.outboundSecurity; diff --git a/ballerina/soap_utils.bal b/ballerina/soap_utils.bal index 4a4f47e..cb8a723 100644 --- a/ballerina/soap_utils.bal +++ b/ballerina/soap_utils.bal @@ -36,21 +36,6 @@ public isolated function validateTransportBindingPolicy(ClientConfig config) ret } } -public isolated function retrieveHttpClientConfig(ClientConfig config) returns http:ClientConfiguration { - return { - httpVersion: config.httpConfig.httpVersion, - http1Settings: config.httpConfig.http1Settings, - http2Settings: config.httpConfig.http2Settings, - timeout: config.httpConfig.timeout, - poolConfig: config.httpConfig?.poolConfig, - auth: config.httpConfig?.auth, - retryConfig: config.httpConfig?.retryConfig, - responseLimits: config.httpConfig.responseLimits, - secureSocket: config.httpConfig?.secureSocket, - circuitBreaker: config.httpConfig?.circuitBreaker - }; -} - public isolated function getReadOnlyRecords(ClientConfig original) returns readonly & ClientConfig = @java:Method { 'class: "org.wssec.WsSecurity" } external; @@ -101,11 +86,8 @@ public isolated function applyOutboundConfig(wssec:OutboundSecurityConfig outbou crypto:PublicKey? serverPublicKey = outboundSecurity.verificationKey; if serverPublicKey is crypto:PublicKey { byte[] signatureData = check wssec:getSignatureData(soapEnvelope); - boolean verify = check wssec:verifyData((soapEnvelope//*).toString().toBytes(), - signatureData, serverPublicKey, signatureAlgorithm); - if !verify { - return error Error("Signature verification of the SOAP envelope has been failed"); - } + check wssec:verifyData((soapEnvelope//*).toString().toBytes(), + signatureData, serverPublicKey, signatureAlgorithm); } } return soapEnvelope; From d7b7abf894b23437dfb122a2303afdf16197a923 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Fri, 13 Oct 2023 08:19:15 +0530 Subject: [PATCH 164/189] Modify signature verification method --- .../modules/wssec/tests/ws_security_tests.bal | 16 ++++++++-------- ballerina/modules/wssec/ws_security_methods.bal | 7 +++++-- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/ballerina/modules/wssec/tests/ws_security_tests.bal b/ballerina/modules/wssec/tests/ws_security_tests.bal index 6f03b90..a5a47d5 100644 --- a/ballerina/modules/wssec/tests/ws_security_tests.bal +++ b/ballerina/modules/wssec/tests/ws_security_tests.bal @@ -566,8 +566,8 @@ function testAsymmetricBindingWithSignatureRsaSha256() returns error? { xml securedEnvelope = check applyAsymmetricBinding(envelope, asymmetricBinding); string envelopeString = securedEnvelope.toString(); byte[] signedData = check getSignatureData(securedEnvelope); - boolean validity = check verifyData((envelope//*).toString().toBytes(), signedData, clientPublicKey, RSA_SHA256); - test:assertTrue(validity); + Error? validity = check verifyData((envelope//*).toString().toBytes(), signedData, clientPublicKey, RSA_SHA256); + test:assertTrue(validity is ()); assertSignatureWithoutX509(envelopeString); } @@ -936,8 +936,8 @@ function testAsymmetricBindingWithSignatureWithRsaSha1() returns error? { xml securedEnvelope = check applyAsymmetricBinding(envelope, asymmetricBinding); string envelopeString = securedEnvelope.toString(); byte[] signedData = check getSignatureData(securedEnvelope); - boolean validity = check verifyData((envelope//*).toString().toBytes(), signedData, clientPublicKey, RSA_SHA1); - test:assertTrue(validity); + Error? validity = check verifyData((envelope//*).toString().toBytes(), signedData, clientPublicKey, RSA_SHA1); + test:assertTrue(validity is ()); assertSignatureWithoutX509(envelopeString); } @@ -973,8 +973,8 @@ function testAsymmetricBindingWithSignatureWithRsaSha384() returns error? { xml securedEnvelope = check applyAsymmetricBinding(envelope, asymmetricBinding); string envelopeString = securedEnvelope.toString(); byte[] signedData = check getSignatureData(securedEnvelope); - boolean validity = check verifyData((envelope//*).toString().toBytes(), signedData, clientPublicKey, RSA_SHA384); - test:assertTrue(validity); + Error? validity = check verifyData((envelope//*).toString().toBytes(), signedData, clientPublicKey, RSA_SHA384); + test:assertTrue(validity is ()); assertSignatureWithoutX509(envelopeString); } @@ -1010,8 +1010,8 @@ function testAsymmetricBindingWithSignatureWithRsaSha512() returns error? { xml securedEnvelope = check applyAsymmetricBinding(envelope, asymmetricBinding); string envelopeString = securedEnvelope.toString(); byte[] signedData = check getSignatureData(securedEnvelope); - boolean validity = check verifyData((envelope//*).toString().toBytes(), signedData, clientPublicKey, RSA_SHA512); - test:assertTrue(validity); + Error? validity = check verifyData((envelope//*).toString().toBytes(), signedData, clientPublicKey, RSA_SHA512); + test:assertTrue(validity is ()); assertSignatureWithoutX509(envelopeString); } diff --git a/ballerina/modules/wssec/ws_security_methods.bal b/ballerina/modules/wssec/ws_security_methods.bal index c349579..f00edec 100644 --- a/ballerina/modules/wssec/ws_security_methods.bal +++ b/ballerina/modules/wssec/ws_security_methods.bal @@ -32,9 +32,12 @@ public isolated function decryptData(byte[] cipherText, EncryptionAlgorithm encr } public isolated function verifyData(byte[] data, byte[] signature, crypto:PublicKey publicKey, - SignatureAlgorithm signatureAlgorithm) returns boolean|Error { + SignatureAlgorithm signatureAlgorithm) returns Error? { Signature sign = check new (); - return sign.verifySignature(data, signature, publicKey, signatureAlgorithm); + boolean verifySignature = check sign.verifySignature(data, signature, publicKey, signatureAlgorithm); + if !verifySignature { + return error Error("Signature verification of the SOAP envelope has been failed"); + } } isolated function addSignature(Signature sign, string signatureAlgorithm, byte[] signature) returns Signature|Error { From e505be0a3eea0e469582edc70458da1e1bfa61c2 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Fri, 13 Oct 2023 08:52:18 +0530 Subject: [PATCH 165/189] Apply string template for `soapAction` --- ballerina/soap_utils.bal | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ballerina/soap_utils.bal b/ballerina/soap_utils.bal index cb8a723..be15240 100644 --- a/ballerina/soap_utils.bal +++ b/ballerina/soap_utils.bal @@ -158,7 +158,7 @@ isolated function createSoap12HttpRequest(xml|mime:Entity[] body, string? soapAc } if soapAction is string { map stringMap = {}; - stringMap[ACTION] = "\"" + soapAction + "\""; + stringMap[ACTION] = string `${soapAction}`; var mediaType = mime:getMediaType(mime:APPLICATION_SOAP_XML); if mediaType is mime:MediaType { mediaType.parameters = stringMap; From d5fc6c724e4c4e665e68067f131344ffcc9e9f21 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Fri, 13 Oct 2023 09:56:28 +0530 Subject: [PATCH 166/189] Add private constructor to the Constants class --- native/src/main/java/org/wssec/Constants.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/native/src/main/java/org/wssec/Constants.java b/native/src/main/java/org/wssec/Constants.java index 20fffa1..bd9a0ef 100644 --- a/native/src/main/java/org/wssec/Constants.java +++ b/native/src/main/java/org/wssec/Constants.java @@ -18,6 +18,9 @@ public class Constants { + private Constants() { + } + public static final int ITERATION = 1000; public static final String DIGEST = "DIGEST"; public static final String DERIVED_KEY_TEXT = "DERIVED_KEY_TEXT"; From 181d7f503b1a6e0c6dd6387fd896d9ce1a40f558 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Fri, 13 Oct 2023 09:56:45 +0530 Subject: [PATCH 167/189] Remove unnecessary method --- native/src/main/java/org/wssec/DocumentBuilder.java | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/native/src/main/java/org/wssec/DocumentBuilder.java b/native/src/main/java/org/wssec/DocumentBuilder.java index c6b15ad..e73bf60 100644 --- a/native/src/main/java/org/wssec/DocumentBuilder.java +++ b/native/src/main/java/org/wssec/DocumentBuilder.java @@ -16,7 +16,6 @@ package org.wssec; -import io.ballerina.runtime.api.creators.ErrorCreator; import io.ballerina.runtime.api.creators.ValueCreator; import io.ballerina.runtime.api.utils.StringUtils; import io.ballerina.runtime.api.values.BArray; @@ -46,17 +45,6 @@ protected DocumentBuilder(Document document) { this.document = document; } - public static Object getDocument(BObject documentBuilder) { - BHandle handle = (BHandle) documentBuilder.get(StringUtils.fromString(NATIVE_DOCUMENT)); - DocumentBuilder docBuilder = (DocumentBuilder) handle.getValue(); - Document document = docBuilder.getNativeDocument(); - try { - return WsSecurityUtils.convertDocumentToString(document); - } catch (Exception e) { - return ErrorCreator.createError(StringUtils.fromString(e.getMessage())); - } - } - public static BArray getSignatureData(BObject document) { BHandle handle = (BHandle) document.get(StringUtils.fromString(NATIVE_DOCUMENT)); DocumentBuilder docBuilder = (DocumentBuilder) handle.getValue(); From 35a7188066f6d8ccee4b6cd4aa48f754baca1ed4 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Fri, 13 Oct 2023 09:58:25 +0530 Subject: [PATCH 168/189] Fix repeating same key variables --- ballerina/modules/wssec/tests/test_utils.bal | 24 ++ .../modules/wssec/tests/ws_security_tests.bal | 261 +++--------------- 2 files changed, 56 insertions(+), 229 deletions(-) diff --git a/ballerina/modules/wssec/tests/test_utils.bal b/ballerina/modules/wssec/tests/test_utils.bal index 9724223..cc39826 100644 --- a/ballerina/modules/wssec/tests/test_utils.bal +++ b/ballerina/modules/wssec/tests/test_utils.bal @@ -14,6 +14,7 @@ // specific language governing permissions and limitations // under the License. import ballerina/test; +import ballerina/crypto; const USERNAME = "username"; const PASSWORD = "password"; @@ -29,6 +30,29 @@ const X509_PUBLIC_CERT_PATH_2 = "modules/wssec/tests/resources/x509_certificate_ const X509_KEY_STORE_PATH = "modules/wssec/tests/resources/x509_certificate.p12"; const X509_KEY_STORE_PATH_2 = "modules/wssec/tests/resources/x509_certificate_2.p12"; +const crypto:KeyStore clientKeyStore = { + path: X509_KEY_STORE_PATH_2, + password: KEY_PASSWORD +}; +crypto:PrivateKey clientPrivateKey = check crypto:decodeRsaPrivateKeyFromKeyStore(clientKeyStore, KEY_ALIAS, + KEY_PASSWORD); +crypto:PublicKey clientPublicKey = check crypto:decodeRsaPublicKeyFromTrustStore(clientKeyStore, KEY_ALIAS); + +const crypto:KeyStore serverKeyStore = { + path: X509_KEY_STORE_PATH, + password: KEY_PASSWORD +}; +crypto:PrivateKey serverPrivateKey = check crypto:decodeRsaPrivateKeyFromKeyStore(serverKeyStore, KEY_ALIAS, + KEY_PASSWORD); +crypto:PublicKey serverPublicKey = check crypto:decodeRsaPublicKeyFromTrustStore(serverKeyStore, KEY_ALIAS); + +crypto:KeyStore keyStore = { + path: KEY_STORE_PATH, + password: KEY_PASSWORD +}; +crypto:PrivateKey symmetricKey = check crypto:decodeRsaPrivateKeyFromKeyStore(keyStore, KEY_ALIAS, KEY_PASSWORD); +crypto:PublicKey publicKey = check crypto:decodeRsaPublicKeyFromTrustStore(keyStore, KEY_ALIAS); + function assertTimestampToken(string envelopeString) { string:RegExp ts_token = re ``; string:RegExp created = re `.*`; diff --git a/ballerina/modules/wssec/tests/ws_security_tests.bal b/ballerina/modules/wssec/tests/ws_security_tests.bal index a5a47d5..2d1559a 100644 --- a/ballerina/modules/wssec/tests/ws_security_tests.bal +++ b/ballerina/modules/wssec/tests/ws_security_tests.bal @@ -204,19 +204,6 @@ function testSymmetricBindingPolicyWithSignatureOnly() returns error? { `; xmlns "http://schemas.xmlsoap.org/soap/envelope/" as soap; - crypto:KeyStore serverKeyStore = { - path: X509_KEY_STORE_PATH, - password: KEY_PASSWORD - }; - crypto:PublicKey serverPublicKey = check crypto:decodeRsaPublicKeyFromTrustStore(serverKeyStore, KEY_ALIAS); - - crypto:KeyStore keyStore = { - path: KEY_STORE_PATH, - password: KEY_PASSWORD - }; - crypto:PrivateKey symmetricKey = check crypto:decodeRsaPrivateKeyFromKeyStore(keyStore, KEY_ALIAS, KEY_PASSWORD); - crypto:PublicKey publicKey = check crypto:decodeRsaPublicKeyFromTrustStore(keyStore, KEY_ALIAS); - SymmetricBindingConfig symmetricBinding = { signatureAlgorithm: RSA_SHA256, symmetricKey: symmetricKey, @@ -227,7 +214,8 @@ function testSymmetricBindingPolicyWithSignatureOnly() returns error? { string envelopeString = securedEnvelope.toString(); byte[] signedData = check getSignatureData(securedEnvelope); - boolean validity = check crypto:verifyRsaSha256Signature((envelope//*).toString().toBytes(), signedData, publicKey); + boolean validity = check crypto:verifyRsaSha256Signature((envelope//*).toString().toBytes(), + signedData, publicKey); test:assertTrue(validity); assertEncryptedSymmetricKey(envelopeString); @@ -244,19 +232,6 @@ function testSymmetricBindingPolicyEncryptionOnly() returns error? { `; xmlns "http://schemas.xmlsoap.org/soap/envelope/" as soap; - crypto:KeyStore serverKeyStore = { - path: X509_KEY_STORE_PATH, - password: KEY_PASSWORD - }; - crypto:PublicKey serverPublicKey = check crypto:decodeRsaPublicKeyFromTrustStore(serverKeyStore, KEY_ALIAS); - - crypto:KeyStore keyStore = { - path: KEY_STORE_PATH, - password: KEY_PASSWORD - }; - crypto:PrivateKey symmetricKey = check crypto:decodeRsaPrivateKeyFromKeyStore(keyStore, KEY_ALIAS, KEY_PASSWORD); - crypto:PublicKey publicKey = check crypto:decodeRsaPublicKeyFromTrustStore(keyStore, KEY_ALIAS); - SymmetricBindingConfig symmetricBinding = { encryptionAlgorithm: RSA_ECB, symmetricKey: symmetricKey, @@ -284,19 +259,6 @@ function testSymmetricBindingWithSignatureAndEncryption() returns error? { `; xmlns "http://schemas.xmlsoap.org/soap/envelope/" as soap; - crypto:KeyStore serverKeyStore = { - path: X509_KEY_STORE_PATH, - password: KEY_PASSWORD - }; - crypto:PublicKey serverPublicKey = check crypto:decodeRsaPublicKeyFromTrustStore(serverKeyStore, KEY_ALIAS); - - crypto:KeyStore keyStore = { - path: KEY_STORE_PATH, - password: KEY_PASSWORD - }; - crypto:PrivateKey symmetricKey = check crypto:decodeRsaPrivateKeyFromKeyStore(keyStore, KEY_ALIAS, KEY_PASSWORD); - crypto:PublicKey publicKey = check crypto:decodeRsaPublicKeyFromTrustStore(keyStore, KEY_ALIAS); - SymmetricBindingConfig symmetricBinding = { signatureAlgorithm: RSA_SHA256, encryptionAlgorithm: RSA_ECB, @@ -308,7 +270,8 @@ function testSymmetricBindingWithSignatureAndEncryption() returns error? { byte[] signedData = check getSignatureData(securedEnvelope); - boolean validity = check crypto:verifyRsaSha256Signature((envelope//*).toString().toBytes(), signedData, publicKey); + boolean validity = check crypto:verifyRsaSha256Signature((envelope//*).toString().toBytes(), + signedData, publicKey); test:assertTrue(validity); byte[] encData = check getEncryptedData(securedEnvelope); @@ -330,19 +293,6 @@ function testSymmetricBindingPolicyWithX509SignatureAndEncryption() returns erro `; xmlns "http://schemas.xmlsoap.org/soap/envelope/" as soap; - crypto:KeyStore serverKeyStore = { - path: X509_KEY_STORE_PATH, - password: KEY_PASSWORD - }; - crypto:PublicKey serverPublicKey = check crypto:decodeRsaPublicKeyFromTrustStore(serverKeyStore, KEY_ALIAS); - - crypto:KeyStore keyStore = { - path: KEY_STORE_PATH, - password: KEY_PASSWORD - }; - crypto:PrivateKey symmetricKey = check crypto:decodeRsaPrivateKeyFromKeyStore(keyStore, KEY_ALIAS, KEY_PASSWORD); - crypto:PublicKey publicKey = check crypto:decodeRsaPublicKeyFromTrustStore(keyStore, KEY_ALIAS); - SymmetricBindingConfig symmetricBinding = { signatureAlgorithm: RSA_SHA256, encryptionAlgorithm: RSA_ECB, @@ -356,7 +306,8 @@ function testSymmetricBindingPolicyWithX509SignatureAndEncryption() returns erro byte[] signedData = check getSignatureData(securedEnvelope); - boolean validity = check crypto:verifyRsaSha256Signature((envelope//*).toString().toBytes(), signedData, publicKey); + boolean validity = check crypto:verifyRsaSha256Signature((envelope//*).toString().toBytes(), + signedData, publicKey); test:assertTrue(validity); byte[] encData = check getEncryptedData(securedEnvelope); @@ -386,19 +337,6 @@ function testUsernameTokenWithSymmetricBinding() returns error? { envelope = check applyUsernameToken(envelope, utRecord); - crypto:KeyStore serverKeyStore = { - path: X509_KEY_STORE_PATH, - password: KEY_PASSWORD - }; - crypto:PublicKey serverPublicKey = check crypto:decodeRsaPublicKeyFromTrustStore(serverKeyStore, KEY_ALIAS); - - crypto:KeyStore keyStore = { - path: KEY_STORE_PATH, - password: KEY_PASSWORD - }; - crypto:PrivateKey symmetricKey = check crypto:decodeRsaPrivateKeyFromKeyStore(keyStore, KEY_ALIAS, KEY_PASSWORD); - crypto:PublicKey publicKey = check crypto:decodeRsaPublicKeyFromTrustStore(keyStore, KEY_ALIAS); - SymmetricBindingConfig symmetricBinding = { signatureAlgorithm: RSA_SHA256, encryptionAlgorithm: RSA_ECB, @@ -410,7 +348,8 @@ function testUsernameTokenWithSymmetricBinding() returns error? { byte[] signedData = check getSignatureData(securedEnvelope); - boolean validity = check crypto:verifyRsaSha256Signature((envelope//*).toString().toBytes(), signedData, publicKey); + boolean validity = check crypto:verifyRsaSha256Signature((envelope//*).toString().toBytes(), + signedData, publicKey); test:assertTrue(validity); byte[] encData = check getEncryptedData(securedEnvelope); @@ -467,7 +406,8 @@ function testUsernameTokenTimestampWithSymmetricBindingAndX509Token() returns er string envelopeString = securedEnvelope.toString(); byte[] signedData = check getSignatureData(securedEnvelope); - boolean validity = check crypto:verifyRsaSha256Signature((envelope//*).toString().toBytes(), signedData, publicKey); + boolean validity = check crypto:verifyRsaSha256Signature((envelope//*).toString().toBytes(), + signedData, publicKey); test:assertTrue(validity); byte[] encData = check getEncryptedData(securedEnvelope); @@ -531,7 +471,8 @@ function testSymmetricBindingWithOutboundConfig() returns error? { } byte[] signedData = check getSignatureData(securedEnvelope); - boolean validity = check crypto:verifyRsaSha256Signature((envelope//*).toString().toBytes(), signedData, publicKey); + boolean validity = check crypto:verifyRsaSha256Signature((envelope//*).toString().toBytes(), + signedData, publicKey); test:assertTrue(validity); } @@ -545,19 +486,6 @@ function testAsymmetricBindingWithSignatureRsaSha256() returns error? { `; xmlns "http://schemas.xmlsoap.org/soap/envelope/" as soap; - crypto:KeyStore serverKeyStore = { - path: X509_KEY_STORE_PATH, - password: KEY_PASSWORD - }; - crypto:PublicKey serverPublicKey = check crypto:decodeRsaPublicKeyFromTrustStore(serverKeyStore, KEY_ALIAS); - - crypto:KeyStore clientKeyStore = { - path: X509_KEY_STORE_PATH_2, - password: KEY_PASSWORD - }; - crypto:PrivateKey clientPrivateKey = check crypto:decodeRsaPrivateKeyFromKeyStore(clientKeyStore, KEY_ALIAS, KEY_PASSWORD); - crypto:PublicKey clientPublicKey = check crypto:decodeRsaPublicKeyFromTrustStore(clientKeyStore, KEY_ALIAS); - AsymmetricBindingConfig asymmetricBinding = { signatureAlgorithm: RSA_SHA256, signatureKey: clientPrivateKey, @@ -566,7 +494,8 @@ function testAsymmetricBindingWithSignatureRsaSha256() returns error? { xml securedEnvelope = check applyAsymmetricBinding(envelope, asymmetricBinding); string envelopeString = securedEnvelope.toString(); byte[] signedData = check getSignatureData(securedEnvelope); - Error? validity = check verifyData((envelope//*).toString().toBytes(), signedData, clientPublicKey, RSA_SHA256); + Error? validity = check verifyData((envelope//*).toString().toBytes(), signedData, + clientPublicKey, RSA_SHA256); test:assertTrue(validity is ()); assertSignatureWithoutX509(envelopeString); @@ -582,19 +511,6 @@ function testAsymmetricBindingWithX509Signature() returns error? { `; xmlns "http://schemas.xmlsoap.org/soap/envelope/" as soap; - crypto:KeyStore serverKeyStore = { - path: X509_KEY_STORE_PATH, - password: KEY_PASSWORD - }; - crypto:PublicKey serverPublicKey = check crypto:decodeRsaPublicKeyFromTrustStore(serverKeyStore, KEY_ALIAS); - - crypto:KeyStore clientKeyStore = { - path: X509_KEY_STORE_PATH_2, - password: KEY_PASSWORD - }; - crypto:PrivateKey clientPrivateKey = check crypto:decodeRsaPrivateKeyFromKeyStore(clientKeyStore, KEY_ALIAS, KEY_PASSWORD); - crypto:PublicKey clientPublicKey = check crypto:decodeRsaPublicKeyFromTrustStore(clientKeyStore, KEY_ALIAS); - AsymmetricBindingConfig asymmetricBinding = { signatureAlgorithm: RSA_SHA256, signatureKey: clientPrivateKey, @@ -605,7 +521,8 @@ function testAsymmetricBindingWithX509Signature() returns error? { string envelopeString = securedEnvelope.toString(); byte[] signedData = check getSignatureData(securedEnvelope); - boolean validity = check crypto:verifyRsaSha256Signature((envelope//*).toString().toBytes(), signedData, clientPublicKey); + boolean validity = check crypto:verifyRsaSha256Signature((envelope//*).toString().toBytes(), + signedData, clientPublicKey); test:assertTrue(validity); assertSignatureWithX509(envelopeString); @@ -621,19 +538,6 @@ function testAsymmetricBindingWithEncryption() returns error? { `; xmlns "http://schemas.xmlsoap.org/soap/envelope/" as soap; - crypto:KeyStore serverKeyStore = { - path: X509_KEY_STORE_PATH, - password: KEY_PASSWORD - }; - crypto:PrivateKey serverPrivateKey = check crypto:decodeRsaPrivateKeyFromKeyStore(serverKeyStore, KEY_ALIAS, KEY_PASSWORD); - crypto:PublicKey serverPublicKey = check crypto:decodeRsaPublicKeyFromTrustStore(serverKeyStore, KEY_ALIAS); - - crypto:KeyStore clientKeyStore = { - path: X509_KEY_STORE_PATH_2, - password: KEY_PASSWORD - }; - crypto:PrivateKey clientPrivateKey = check crypto:decodeRsaPrivateKeyFromKeyStore(clientKeyStore, KEY_ALIAS, KEY_PASSWORD); - AsymmetricBindingConfig asymmetricBinding = { encryptionAlgorithm: RSA_ECB, signatureKey: clientPrivateKey, @@ -659,20 +563,6 @@ function testAsymmetricBindingWithSignatureAndEncryption() returns error? { `; xmlns "http://schemas.xmlsoap.org/soap/envelope/" as soap; - crypto:KeyStore serverKeyStore = { - path: X509_KEY_STORE_PATH, - password: KEY_PASSWORD - }; - crypto:PrivateKey serverPrivateKey = check crypto:decodeRsaPrivateKeyFromKeyStore(serverKeyStore, KEY_ALIAS, KEY_PASSWORD); - crypto:PublicKey serverPublicKey = check crypto:decodeRsaPublicKeyFromTrustStore(serverKeyStore, KEY_ALIAS); - - crypto:KeyStore clientKeyStore = { - path: X509_KEY_STORE_PATH_2, - password: KEY_PASSWORD - }; - crypto:PrivateKey clientPrivateKey = check crypto:decodeRsaPrivateKeyFromKeyStore(clientKeyStore, KEY_ALIAS, KEY_PASSWORD); - crypto:PublicKey clientPublicKey = check crypto:decodeRsaPublicKeyFromTrustStore(clientKeyStore, KEY_ALIAS); - AsymmetricBindingConfig asymmetricBinding = { signatureAlgorithm: RSA_SHA256, encryptionAlgorithm: RSA_ECB, @@ -684,7 +574,8 @@ function testAsymmetricBindingWithSignatureAndEncryption() returns error? { string envelopeString = securedEnvelope.toString(); byte[] signedData = check getSignatureData(securedEnvelope); - boolean validity = check crypto:verifyRsaSha256Signature((envelope//*).toString().toBytes(), signedData, clientPublicKey); + boolean validity = check crypto:verifyRsaSha256Signature((envelope//*).toString().toBytes(), + signedData, clientPublicKey); test:assertTrue(validity); byte[] encData = check getEncryptedData(securedEnvelope); @@ -705,20 +596,6 @@ function testAsymmetricBindingWithX509SignatureAndEncryption() returns error? { `; xmlns "http://schemas.xmlsoap.org/soap/envelope/" as soap; - crypto:KeyStore serverKeyStore = { - path: X509_KEY_STORE_PATH, - password: KEY_PASSWORD - }; - crypto:PrivateKey serverPrivateKey = check crypto:decodeRsaPrivateKeyFromKeyStore(serverKeyStore, KEY_ALIAS, KEY_PASSWORD); - crypto:PublicKey serverPublicKey = check crypto:decodeRsaPublicKeyFromTrustStore(serverKeyStore, KEY_ALIAS); - - crypto:KeyStore clientKeyStore = { - path: X509_KEY_STORE_PATH_2, - password: KEY_PASSWORD - }; - crypto:PrivateKey clientPrivateKey = check crypto:decodeRsaPrivateKeyFromKeyStore(clientKeyStore, KEY_ALIAS, KEY_PASSWORD); - crypto:PublicKey clientPublicKey = check crypto:decodeRsaPublicKeyFromTrustStore(clientKeyStore, KEY_ALIAS); - AsymmetricBindingConfig asymmetricBinding = { signatureAlgorithm: RSA_SHA256, encryptionAlgorithm: RSA_ECB, @@ -730,7 +607,8 @@ function testAsymmetricBindingWithX509SignatureAndEncryption() returns error? { string envelopeString = securedEnvelope.toString(); byte[] signedData = check getSignatureData(securedEnvelope); - boolean validity = check crypto:verifyRsaSha256Signature((envelope//*).toString().toBytes(), signedData, clientPublicKey); + boolean validity = check crypto:verifyRsaSha256Signature((envelope//*).toString().toBytes(), + signedData, clientPublicKey); test:assertTrue(validity); byte[] encData = check getEncryptedData(securedEnvelope); @@ -758,20 +636,6 @@ function testUsernameTokenWithAsymmetricBindingAndX509() returns error? { }; envelope = check applyUsernameToken(envelope, utRecord); - crypto:KeyStore serverKeyStore = { - path: X509_KEY_STORE_PATH, - password: KEY_PASSWORD - }; - crypto:PrivateKey serverPrivateKey = check crypto:decodeRsaPrivateKeyFromKeyStore(serverKeyStore, KEY_ALIAS, KEY_PASSWORD); - crypto:PublicKey serverPublicKey = check crypto:decodeRsaPublicKeyFromTrustStore(serverKeyStore, KEY_ALIAS); - - crypto:KeyStore clientKeyStore = { - path: X509_KEY_STORE_PATH_2, - password: KEY_PASSWORD - }; - crypto:PrivateKey clientPrivateKey = check crypto:decodeRsaPrivateKeyFromKeyStore(clientKeyStore, KEY_ALIAS, KEY_PASSWORD); - crypto:PublicKey clientPublicKey = check crypto:decodeRsaPublicKeyFromTrustStore(clientKeyStore, KEY_ALIAS); - AsymmetricBindingConfig asymmetricBinding = { signatureAlgorithm: RSA_SHA256, encryptionAlgorithm: RSA_ECB, @@ -783,7 +647,8 @@ function testUsernameTokenWithAsymmetricBindingAndX509() returns error? { string envelopeString = securedEnvelope.toString(); byte[] signedData = check getSignatureData(securedEnvelope); - boolean validity = check crypto:verifyRsaSha256Signature((envelope//*).toString().toBytes(), signedData, clientPublicKey); + boolean validity = check crypto:verifyRsaSha256Signature((envelope//*).toString().toBytes(), + signedData, clientPublicKey); test:assertTrue(validity); byte[] encData = check getEncryptedData(securedEnvelope); @@ -813,20 +678,6 @@ function testUsernameTokenTimestampWithAsymmetricBindingAndX509() returns error? envelope = check applyUsernameToken(envelope, utRecord); envelope = check applyTimestampToken(envelope = envelope, timeToLive = 600); - crypto:KeyStore serverKeyStore = { - path: X509_KEY_STORE_PATH, - password: KEY_PASSWORD - }; - crypto:PrivateKey serverPrivateKey = check crypto:decodeRsaPrivateKeyFromKeyStore(serverKeyStore, KEY_ALIAS, KEY_PASSWORD); - crypto:PublicKey serverPublicKey = check crypto:decodeRsaPublicKeyFromTrustStore(serverKeyStore, KEY_ALIAS); - - crypto:KeyStore clientKeyStore = { - path: X509_KEY_STORE_PATH_2, - password: KEY_PASSWORD - }; - crypto:PrivateKey clientPrivateKey = check crypto:decodeRsaPrivateKeyFromKeyStore(clientKeyStore, KEY_ALIAS, KEY_PASSWORD); - crypto:PublicKey clientPublicKey = check crypto:decodeRsaPublicKeyFromTrustStore(clientKeyStore, KEY_ALIAS); - AsymmetricBindingConfig asymmetricBinding = { signatureAlgorithm: RSA_SHA256, encryptionAlgorithm: RSA_ECB, @@ -838,7 +689,8 @@ function testUsernameTokenTimestampWithAsymmetricBindingAndX509() returns error? string envelopeString = securedEnvelope.toString(); byte[] signedData = check getSignatureData(securedEnvelope); - boolean validity = check crypto:verifyRsaSha256Signature((envelope//*).toString().toBytes(), signedData, clientPublicKey); + boolean validity = check crypto:verifyRsaSha256Signature((envelope//*).toString().toBytes(), + signedData, clientPublicKey); test:assertTrue(validity); byte[] encData = check getEncryptedData(securedEnvelope); @@ -862,20 +714,6 @@ function testAsymmetricBindingWithOutboundConfig() returns error? { `; xmlns "http://schemas.xmlsoap.org/soap/envelope/" as soap; - crypto:KeyStore serverKeyStore = { - path: X509_KEY_STORE_PATH, - password: KEY_PASSWORD - }; - crypto:PrivateKey serverPrivateKey = check crypto:decodeRsaPrivateKeyFromKeyStore(serverKeyStore, KEY_ALIAS, KEY_PASSWORD); - crypto:PublicKey serverPublicKey = check crypto:decodeRsaPublicKeyFromTrustStore(serverKeyStore, KEY_ALIAS); - - crypto:KeyStore clientKeyStore = { - path: X509_KEY_STORE_PATH_2, - password: KEY_PASSWORD - }; - crypto:PrivateKey clientPrivateKey = check crypto:decodeRsaPrivateKeyFromKeyStore(clientKeyStore, KEY_ALIAS, KEY_PASSWORD); - crypto:PublicKey clientPublicKey = check crypto:decodeRsaPublicKeyFromTrustStore(clientKeyStore, KEY_ALIAS); - AsymmetricBindingConfig asymmetricBinding = { signatureAlgorithm: RSA_SHA256, encryptionAlgorithm: RSA_ECB, @@ -901,7 +739,8 @@ function testAsymmetricBindingWithOutboundConfig() returns error? { securedEnvelope = check xml:fromString(envelopeString); } byte[] signedData = check getSignatureData(securedEnvelope); - boolean validity = check crypto:verifyRsaSha256Signature((envelope//*).toString().toBytes(), signedData, clientPublicKey); + boolean validity = check crypto:verifyRsaSha256Signature((envelope//*).toString().toBytes(), + signedData, clientPublicKey); test:assertTrue(validity); } @@ -915,19 +754,6 @@ function testAsymmetricBindingWithSignatureWithRsaSha1() returns error? { `; xmlns "http://schemas.xmlsoap.org/soap/envelope/" as soap; - crypto:KeyStore serverKeyStore = { - path: X509_KEY_STORE_PATH, - password: KEY_PASSWORD - }; - crypto:PublicKey serverPublicKey = check crypto:decodeRsaPublicKeyFromTrustStore(serverKeyStore, KEY_ALIAS); - - crypto:KeyStore clientKeyStore = { - path: X509_KEY_STORE_PATH_2, - password: KEY_PASSWORD - }; - crypto:PrivateKey clientPrivateKey = check crypto:decodeRsaPrivateKeyFromKeyStore(clientKeyStore, KEY_ALIAS, KEY_PASSWORD); - crypto:PublicKey clientPublicKey = check crypto:decodeRsaPublicKeyFromTrustStore(clientKeyStore, KEY_ALIAS); - AsymmetricBindingConfig asymmetricBinding = { signatureAlgorithm: RSA_SHA1, signatureKey: clientPrivateKey, @@ -936,7 +762,8 @@ function testAsymmetricBindingWithSignatureWithRsaSha1() returns error? { xml securedEnvelope = check applyAsymmetricBinding(envelope, asymmetricBinding); string envelopeString = securedEnvelope.toString(); byte[] signedData = check getSignatureData(securedEnvelope); - Error? validity = check verifyData((envelope//*).toString().toBytes(), signedData, clientPublicKey, RSA_SHA1); + Error? validity = check verifyData((envelope//*).toString().toBytes(), signedData, + clientPublicKey, RSA_SHA1); test:assertTrue(validity is ()); assertSignatureWithoutX509(envelopeString); @@ -952,19 +779,6 @@ function testAsymmetricBindingWithSignatureWithRsaSha384() returns error? { `; xmlns "http://schemas.xmlsoap.org/soap/envelope/" as soap; - crypto:KeyStore serverKeyStore = { - path: X509_KEY_STORE_PATH, - password: KEY_PASSWORD - }; - crypto:PublicKey serverPublicKey = check crypto:decodeRsaPublicKeyFromTrustStore(serverKeyStore, KEY_ALIAS); - - crypto:KeyStore clientKeyStore = { - path: X509_KEY_STORE_PATH_2, - password: KEY_PASSWORD - }; - crypto:PrivateKey clientPrivateKey = check crypto:decodeRsaPrivateKeyFromKeyStore(clientKeyStore, KEY_ALIAS, KEY_PASSWORD); - crypto:PublicKey clientPublicKey = check crypto:decodeRsaPublicKeyFromTrustStore(clientKeyStore, KEY_ALIAS); - AsymmetricBindingConfig asymmetricBinding = { signatureAlgorithm: RSA_SHA384, signatureKey: clientPrivateKey, @@ -973,7 +787,8 @@ function testAsymmetricBindingWithSignatureWithRsaSha384() returns error? { xml securedEnvelope = check applyAsymmetricBinding(envelope, asymmetricBinding); string envelopeString = securedEnvelope.toString(); byte[] signedData = check getSignatureData(securedEnvelope); - Error? validity = check verifyData((envelope//*).toString().toBytes(), signedData, clientPublicKey, RSA_SHA384); + Error? validity = check verifyData((envelope//*).toString().toBytes(), signedData, + clientPublicKey, RSA_SHA384); test:assertTrue(validity is ()); assertSignatureWithoutX509(envelopeString); @@ -989,19 +804,6 @@ function testAsymmetricBindingWithSignatureWithRsaSha512() returns error? { `; xmlns "http://schemas.xmlsoap.org/soap/envelope/" as soap; - crypto:KeyStore serverKeyStore = { - path: X509_KEY_STORE_PATH, - password: KEY_PASSWORD - }; - crypto:PublicKey serverPublicKey = check crypto:decodeRsaPublicKeyFromTrustStore(serverKeyStore, KEY_ALIAS); - - crypto:KeyStore clientKeyStore = { - path: X509_KEY_STORE_PATH_2, - password: KEY_PASSWORD - }; - crypto:PrivateKey clientPrivateKey = check crypto:decodeRsaPrivateKeyFromKeyStore(clientKeyStore, KEY_ALIAS, KEY_PASSWORD); - crypto:PublicKey clientPublicKey = check crypto:decodeRsaPublicKeyFromTrustStore(clientKeyStore, KEY_ALIAS); - AsymmetricBindingConfig asymmetricBinding = { signatureAlgorithm: RSA_SHA512, signatureKey: clientPrivateKey, @@ -1010,7 +812,8 @@ function testAsymmetricBindingWithSignatureWithRsaSha512() returns error? { xml securedEnvelope = check applyAsymmetricBinding(envelope, asymmetricBinding); string envelopeString = securedEnvelope.toString(); byte[] signedData = check getSignatureData(securedEnvelope); - Error? validity = check verifyData((envelope//*).toString().toBytes(), signedData, clientPublicKey, RSA_SHA512); + Error? validity = check verifyData((envelope//*).toString().toBytes(), signedData, + clientPublicKey, RSA_SHA512); test:assertTrue(validity is ()); assertSignatureWithoutX509(envelopeString); From 358ce76203191b0c51879091a128d6f0e6acef15 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Fri, 13 Oct 2023 09:59:18 +0530 Subject: [PATCH 169/189] Add configurable variables for crypto keys --- README.md | 6 +++--- ballerina/Module.md | 6 +++--- ballerina/Package.md | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 4508ae9..396d97f 100644 --- a/README.md +++ b/README.md @@ -185,9 +185,9 @@ import ballerina/soap; import ballerina/soap:soap12; public function main() returns error? { - crypto:PrivateKey clientPrivateKey = ...// - crypto:PublicKey clientPublicKey = ...// - ​​crypto:PublicKey serverPublicKey = ...// + configurable crypto:PrivateKey clientPrivateKey = ?; + configurable crypto:PublicKey clientPublicKey = ?; + configurable ​crypto:PublicKey serverPublicKey = ?; soap12:Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL", { diff --git a/ballerina/Module.md b/ballerina/Module.md index dfeaea0..5d724bc 100644 --- a/ballerina/Module.md +++ b/ballerina/Module.md @@ -175,9 +175,9 @@ import ballerina/soap; import ballerina/soap:soap12; public function main() returns error? { - crypto:PrivateKey clientPrivateKey = ...// - crypto:PublicKey clientPublicKey = ...// - ​​crypto:PublicKey serverPublicKey = ...// + configurable crypto:PrivateKey clientPrivateKey = ?; + configurable crypto:PublicKey clientPublicKey = ?; + configurable ​crypto:PublicKey serverPublicKey = ?; soap12:Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL", { diff --git a/ballerina/Package.md b/ballerina/Package.md index c4b0467..f5db035 100644 --- a/ballerina/Package.md +++ b/ballerina/Package.md @@ -175,9 +175,9 @@ import ballerina/soap; import ballerina/soap:soap12; public function main() returns error? { - crypto:PrivateKey clientPrivateKey = ...// - crypto:PublicKey clientPublicKey = ...// - ​​crypto:PublicKey serverPublicKey = ...// + configurable crypto:PrivateKey clientPrivateKey = ?; + configurable crypto:PublicKey clientPublicKey = ?; + configurable ​crypto:PublicKey serverPublicKey = ?; soap12:Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL", { From 41b2c841c7fe527cd66302d53c514d4aa576a04c Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Fri, 13 Oct 2023 12:38:34 +0530 Subject: [PATCH 170/189] Replace string with static variable --- native/src/main/java/org/wssec/WsSecurity.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/native/src/main/java/org/wssec/WsSecurity.java b/native/src/main/java/org/wssec/WsSecurity.java index f07bd10..e15cedc 100644 --- a/native/src/main/java/org/wssec/WsSecurity.java +++ b/native/src/main/java/org/wssec/WsSecurity.java @@ -112,7 +112,7 @@ public static Object applyEncryptionOnlyPolicy(BObject wsSecHeader, BObject balE handle = (BHandle) balEncryption.get(StringUtils.fromString(NATIVE_ENCRYPTION)); Encryption encryption = (Encryption) handle.getValue(); try { - byte[] key = UsernameTokenUtil.generateDerivedKey("password", + byte[] key = UsernameTokenUtil.generateDerivedKey(PASSWORD, UsernameTokenUtil.generateSalt(true), ITERATION); Document xmlDocument = encryptEnvelope(wsSecurityHeader, key); WsSecurityUtils.setEncryptedData(xmlDocument, encryption.getEncryptedData(), From d852fd8f20d71ec3a5d3f10389a8f85829725929 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Fri, 13 Oct 2023 12:38:51 +0530 Subject: [PATCH 171/189] Remove redundant test case --- .../soap11/tests/soap11_client_test.bal | 38 ------------------- 1 file changed, 38 deletions(-) diff --git a/ballerina/modules/soap11/tests/soap11_client_test.bal b/ballerina/modules/soap11/tests/soap11_client_test.bal index 6c4a552..e0c67b7 100644 --- a/ballerina/modules/soap11/tests/soap11_client_test.bal +++ b/ballerina/modules/soap11/tests/soap11_client_test.bal @@ -76,44 +76,6 @@ function testSendReceiveWithMime() returns error? { test:assertEquals(response, expected); } -// @test:Config { -// groups: ["soap11", "send_only", "mime"] -// } -// function testSendOnlyWithMime() returns error? { -// xml body = xml ` -// -// -// 2 -// 3 -// -// -// `; - -// mime:Entity[] mtomMessage = []; -// mime:Entity envelope = new; -// check envelope.setContentType("application/xop+xml"); -// envelope.setContentId(""); -// envelope.setBody(body); -// mtomMessage.push(envelope); - -// mime:Entity bytesPart = new; -// string readContent = check io:fileReadString(FILE_PATH); -// bytesPart.setFileAsEntityBody(FILE_PATH); -// string|byte[]|io:ReadableByteChannel|mime:EncodeError bytes = mime:base64Encode(readContent.toBytes()); -// if bytes !is byte[] { -// return error("error"); -// } -// bytesPart.setBody(bytes); -// check bytesPart.setContentType("image/jpeg"); -// bytesPart.setContentId(""); -// mtomMessage.push(bytesPart); - -// Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL"); -// check soapClient->sendOnly(mtomMessage, "http://tempuri.org/Add"); -// } - @test:Config { groups: ["soap11", "send_only"] } From 0739c63e4f9e8df38cc1c78d7089ae21935ab3d1 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Fri, 13 Oct 2023 14:21:41 +0530 Subject: [PATCH 172/189] Remove handle variable from `Document` class --- ballerina/modules/wssec/document.bal | 8 ++------ .../src/main/java/org/wssec/DocumentBuilder.java | 15 ++++++--------- .../src/main/java/org/wssec/WsSecurityHeader.java | 7 +++---- 3 files changed, 11 insertions(+), 19 deletions(-) diff --git a/ballerina/modules/wssec/document.bal b/ballerina/modules/wssec/document.bal index 7c97578..ebb6830 100644 --- a/ballerina/modules/wssec/document.bal +++ b/ballerina/modules/wssec/document.bal @@ -16,15 +16,11 @@ import ballerina/jballerina.java; isolated class Document { - - private handle nativeDocumentBuilder; public isolated function init(xml xmlPayload) returns Error? { - handle|error documentBuilder = newDocument(xmlPayload); + handle|error documentBuilder = newDocument(self, xmlPayload); if documentBuilder is error { return error Error(documentBuilder.message()); - } else { - self.nativeDocumentBuilder = documentBuilder; } } @@ -37,6 +33,6 @@ isolated class Document { } external; } -isolated function newDocument(xml xmlPayload) returns handle|error = @java:Constructor { +isolated function newDocument(Document doc, xml xmlPayload) returns handle|error = @java:Constructor { 'class: "org.wssec.DocumentBuilder" } external; diff --git a/native/src/main/java/org/wssec/DocumentBuilder.java b/native/src/main/java/org/wssec/DocumentBuilder.java index e73bf60..c897058 100644 --- a/native/src/main/java/org/wssec/DocumentBuilder.java +++ b/native/src/main/java/org/wssec/DocumentBuilder.java @@ -17,9 +17,7 @@ package org.wssec; import io.ballerina.runtime.api.creators.ValueCreator; -import io.ballerina.runtime.api.utils.StringUtils; import io.ballerina.runtime.api.values.BArray; -import io.ballerina.runtime.api.values.BHandle; import io.ballerina.runtime.api.values.BObject; import io.ballerina.runtime.api.values.BXml; import org.w3c.dom.Document; @@ -35,10 +33,11 @@ public class DocumentBuilder { private final Document document; - public DocumentBuilder(BXml xmlPayload) throws Exception { + public DocumentBuilder(BObject documentBuilder, BXml xmlPayload) throws Exception { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setNamespaceAware(true); this.document = factory.newDocumentBuilder().parse(new InputSource(new StringReader(xmlPayload.toString()))); + documentBuilder.addNativeData(NATIVE_DOCUMENT, this.document); } protected DocumentBuilder(Document document) { @@ -46,15 +45,13 @@ protected DocumentBuilder(Document document) { } public static BArray getSignatureData(BObject document) { - BHandle handle = (BHandle) document.get(StringUtils.fromString(NATIVE_DOCUMENT)); - DocumentBuilder docBuilder = (DocumentBuilder) handle.getValue(); - return ValueCreator.createArrayValue(WsSecurityUtils.getSignatureValue(docBuilder.getNativeDocument())); + Document nativeDocument = (Document) document.getNativeData().get(NATIVE_DOCUMENT); + return ValueCreator.createArrayValue(WsSecurityUtils.getSignatureValue(nativeDocument)); } public static BArray getEncryptedData(BObject document) { - BHandle handle = (BHandle) document.get(StringUtils.fromString(NATIVE_DOCUMENT)); - DocumentBuilder docBuilder = (DocumentBuilder) handle.getValue(); - return ValueCreator.createArrayValue(WsSecurityUtils.getEncryptedData(docBuilder.getNativeDocument())); + Document nativeDocument = (Document) document.getNativeData().get(NATIVE_DOCUMENT); + return ValueCreator.createArrayValue(WsSecurityUtils.getEncryptedData(nativeDocument)); } protected Document getNativeDocument() { diff --git a/native/src/main/java/org/wssec/WsSecurityHeader.java b/native/src/main/java/org/wssec/WsSecurityHeader.java index cf01fed..8927c53 100644 --- a/native/src/main/java/org/wssec/WsSecurityHeader.java +++ b/native/src/main/java/org/wssec/WsSecurityHeader.java @@ -34,10 +34,9 @@ public class WsSecurityHeader { private final Document document; public WsSecurityHeader(BObject documentBuilder) { - BHandle handle = (BHandle) documentBuilder.get(StringUtils.fromString(NATIVE_DOCUMENT)); - DocumentBuilder docBuilder = (DocumentBuilder) handle.getValue(); - this.wsSecHeader = new WSSecHeader(docBuilder.getNativeDocument()); - this.document = docBuilder.getNativeDocument(); + Document document = (Document) documentBuilder.getNativeData().get(NATIVE_DOCUMENT); + this.wsSecHeader = new WSSecHeader(document); + this.document = document; } protected Document getDocument() { From 7e830b3ccdc12451285968d5b12b6f7bdd4e4c8b Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Fri, 13 Oct 2023 17:09:58 +0530 Subject: [PATCH 173/189] [Automated] Update the native jar versions --- ballerina/Dependencies.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index 9a414c0..7bbbbce 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -5,7 +5,7 @@ [ballerina] dependencies-toml-version = "2" -distribution-version = "2201.8.0" +distribution-version = "2201.8.1" [[package]] org = "ballerina" From 85f7782f65b76a6deafb948a730020e2ee10f840 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Fri, 13 Oct 2023 17:12:40 +0530 Subject: [PATCH 174/189] [Automated] Update the native jar versions --- ballerina/Dependencies.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index 7bbbbce..9a414c0 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -5,7 +5,7 @@ [ballerina] dependencies-toml-version = "2" -distribution-version = "2201.8.1" +distribution-version = "2201.8.0" [[package]] org = "ballerina" From 86c0f058f29e7c4485916e38bab231c8ef4f8278 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Fri, 13 Oct 2023 17:13:27 +0530 Subject: [PATCH 175/189] Change resource path name --- ballerina/modules/soap11/tests/http_soap_service.bal | 2 +- ballerina/modules/soap11/tests/soap11_client_test.bal | 10 +--------- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/ballerina/modules/soap11/tests/http_soap_service.bal b/ballerina/modules/soap11/tests/http_soap_service.bal index 5dfa9f9..4847484 100644 --- a/ballerina/modules/soap11/tests/http_soap_service.bal +++ b/ballerina/modules/soap11/tests/http_soap_service.bal @@ -17,7 +17,7 @@ import ballerina/http; service / on new http:Listener(9090) { - resource function post albums(http:Request request) returns http:Response|error { + resource function post getPayload(http:Request request) returns http:Response|error { http:Response response = new; response.setPayload(check (check request.getBodyParts())[0].getXml()); return response; diff --git a/ballerina/modules/soap11/tests/soap11_client_test.bal b/ballerina/modules/soap11/tests/soap11_client_test.bal index e0c67b7..f401155 100644 --- a/ballerina/modules/soap11/tests/soap11_client_test.bal +++ b/ballerina/modules/soap11/tests/soap11_client_test.bal @@ -66,7 +66,7 @@ function testSendReceiveWithMime() returns error? { bytesPart.setContentId(""); mtomMessage.push(bytesPart); - xml|mime:Entity[] response = check soapClient->sendReceive(mtomMessage, "http://tempuri.org/Add", path = "/albums"); + xml|mime:Entity[] response = check soapClient->sendReceive(mtomMessage, "http://tempuri.org/Add", path = "/getPayload"); xml expected = xml ` 2 @@ -270,14 +270,6 @@ function testSendReceiveWithAsymmetricBindingSecurity() returns error? { }; crypto:PrivateKey clientPrivateKey = check crypto:decodeRsaPrivateKeyFromKeyStore(clientKeyStore, KEY_ALIAS, KEY_PASSWORD); - // wssec:AsymmetricBindingConfig asymmetricConfig = { - // signatureAlgorithm: soap:RSA_SHA256, - // encryptionAlgorithm: soap:RSA_ECB, - // signatureKey: clientPrivateKey, - // encryptionKey: serverPublicKey - // }; - // wssec:AsymmetricBindingConfig & readonly asymmetricConfig2 = asymmetricConfig.clone(); - // readonly & wssec:AsymmetricBindingConfig immutableRecord = asymmetricConfig; Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL", { inboundSecurity: { From 5eed3f5c59d32aa0edc7e59e519bd4b671496ac0 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Fri, 13 Oct 2023 20:14:40 +0530 Subject: [PATCH 176/189] Fix license header issue --- ballerina/modules/wssec/document.bal | 2 +- ballerina/modules/wssec/encryption.bal | 2 +- ballerina/modules/wssec/error.bal | 2 +- ballerina/modules/wssec/init.bal | 2 +- ballerina/modules/wssec/records.bal | 2 +- ballerina/modules/wssec/sec_header.bal | 2 +- ballerina/modules/wssec/signature.bal | 2 +- ballerina/modules/wssec/types.bal | 2 +- ballerina/modules/wssec/ws_security.bal | 2 +- ballerina/modules/wssec/ws_security_methods.bal | 2 +- ballerina/types.bal | 2 +- native/src/main/java/module-info.java | 2 +- native/src/main/java/org/wssec/Constants.java | 2 +- native/src/main/java/org/wssec/DocumentBuilder.java | 2 +- native/src/main/java/org/wssec/Encryption.java | 2 +- native/src/main/java/org/wssec/ModuleUtils.java | 2 +- native/src/main/java/org/wssec/Signature.java | 2 +- native/src/main/java/org/wssec/Utils.java | 2 +- native/src/main/java/org/wssec/WsSecurity.java | 2 +- native/src/main/java/org/wssec/WsSecurityHeader.java | 2 +- native/src/main/java/org/wssec/WsSecurityUtils.java | 2 +- 21 files changed, 21 insertions(+), 21 deletions(-) diff --git a/ballerina/modules/wssec/document.bal b/ballerina/modules/wssec/document.bal index ebb6830..dc4fefb 100644 --- a/ballerina/modules/wssec/document.bal +++ b/ballerina/modules/wssec/document.bal @@ -1,6 +1,6 @@ // Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com) All Rights Reserved. // -// WSO2 Inc. licenses this file to you under the Apache License, +// WSO2 LLC. licenses this file to you under the Apache License, // Version 2.0 (the "License"); you may not use this file except // in compliance with the License. // You may obtain a copy of the License at diff --git a/ballerina/modules/wssec/encryption.bal b/ballerina/modules/wssec/encryption.bal index 03e2fbe..a2cbc82 100644 --- a/ballerina/modules/wssec/encryption.bal +++ b/ballerina/modules/wssec/encryption.bal @@ -1,6 +1,6 @@ // Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com) All Rights Reserved. // -// WSO2 Inc. licenses this file to you under the Apache License, +// WSO2 LLC. licenses this file to you under the Apache License, // Version 2.0 (the "License"); you may not use this file except // in compliance with the License. // You may obtain a copy of the License at diff --git a/ballerina/modules/wssec/error.bal b/ballerina/modules/wssec/error.bal index 2c46083..65baeb3 100644 --- a/ballerina/modules/wssec/error.bal +++ b/ballerina/modules/wssec/error.bal @@ -1,6 +1,6 @@ // Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com) All Rights Reserved. // -// WSO2 Inc. licenses this file to you under the Apache License, +// WSO2 LLC. licenses this file to you under the Apache License, // Version 2.0 (the "License"); you may not use this file except // in compliance with the License. // You may obtain a copy of the License at diff --git a/ballerina/modules/wssec/init.bal b/ballerina/modules/wssec/init.bal index fe99617..a58af80 100644 --- a/ballerina/modules/wssec/init.bal +++ b/ballerina/modules/wssec/init.bal @@ -1,6 +1,6 @@ // Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com) All Rights Reserved. // -// WSO2 Inc. licenses this file to you under the Apache License, +// WSO2 LLC. licenses this file to you under the Apache License, // Version 2.0 (the "License"); you may not use this file except // in compliance with the License. // You may obtain a copy of the License at diff --git a/ballerina/modules/wssec/records.bal b/ballerina/modules/wssec/records.bal index f0f8f7e..ba856f7 100644 --- a/ballerina/modules/wssec/records.bal +++ b/ballerina/modules/wssec/records.bal @@ -1,6 +1,6 @@ // Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com) All Rights Reserved. // -// WSO2 Inc. licenses this file to you under the Apache License, +// WSO2 LLC. licenses this file to you under the Apache License, // Version 2.0 (the "License"); you may not use this file except // in compliance with the License. // You may obtain a copy of the License at diff --git a/ballerina/modules/wssec/sec_header.bal b/ballerina/modules/wssec/sec_header.bal index 0412827..10aa1af 100644 --- a/ballerina/modules/wssec/sec_header.bal +++ b/ballerina/modules/wssec/sec_header.bal @@ -1,6 +1,6 @@ // Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com) All Rights Reserved. // -// WSO2 Inc. licenses this file to you under the Apache License, +// WSO2 LLC. licenses this file to you under the Apache License, // Version 2.0 (the "License"); you may not use this file except // in compliance with the License. // You may obtain a copy of the License at diff --git a/ballerina/modules/wssec/signature.bal b/ballerina/modules/wssec/signature.bal index 5208952..6de5eb8 100644 --- a/ballerina/modules/wssec/signature.bal +++ b/ballerina/modules/wssec/signature.bal @@ -1,6 +1,6 @@ // Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com) All Rights Reserved. // -// WSO2 Inc. licenses this file to you under the Apache License, +// WSO2 LLC. licenses this file to you under the Apache License, // Version 2.0 (the "License"); you may not use this file except // in compliance with the License. // You may obtain a copy of the License at diff --git a/ballerina/modules/wssec/types.bal b/ballerina/modules/wssec/types.bal index 9b194e2..6767a51 100644 --- a/ballerina/modules/wssec/types.bal +++ b/ballerina/modules/wssec/types.bal @@ -1,6 +1,6 @@ // Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com) All Rights Reserved. // -// WSO2 Inc. licenses this file to you under the Apache License, +// WSO2 LLC. licenses this file to you under the Apache License, // Version 2.0 (the "License"); you may not use this file except // in compliance with the License. // You may obtain a copy of the License at diff --git a/ballerina/modules/wssec/ws_security.bal b/ballerina/modules/wssec/ws_security.bal index 881786c..6b2fbec 100644 --- a/ballerina/modules/wssec/ws_security.bal +++ b/ballerina/modules/wssec/ws_security.bal @@ -1,6 +1,6 @@ // Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com) All Rights Reserved. // -// WSO2 Inc. licenses this file to you under the Apache License, +// WSO2 LLC. licenses this file to you under the Apache License, // Version 2.0 (the "License"); you may not use this file except // in compliance with the License. // You may obtain a copy of the License at diff --git a/ballerina/modules/wssec/ws_security_methods.bal b/ballerina/modules/wssec/ws_security_methods.bal index f00edec..9d690e9 100644 --- a/ballerina/modules/wssec/ws_security_methods.bal +++ b/ballerina/modules/wssec/ws_security_methods.bal @@ -1,6 +1,6 @@ // Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com) All Rights Reserved. // -// WSO2 Inc. licenses this file to you under the Apache License, +// WSO2 LLC. licenses this file to you under the Apache License, // Version 2.0 (the "License"); you may not use this file except // in compliance with the License. // You may obtain a copy of the License at diff --git a/ballerina/types.bal b/ballerina/types.bal index 187a507..cae653b 100644 --- a/ballerina/types.bal +++ b/ballerina/types.bal @@ -1,6 +1,6 @@ // Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com) All Rights Reserved. // -// WSO2 Inc. licenses this file to you under the Apache License, +// WSO2 LLC. licenses this file to you under the Apache License, // Version 2.0 (the "License"); you may not use this file except // in compliance with the License. // You may obtain a copy of the License at diff --git a/native/src/main/java/module-info.java b/native/src/main/java/module-info.java index 5ab9e36..4168a3f 100644 --- a/native/src/main/java/module-info.java +++ b/native/src/main/java/module-info.java @@ -1,6 +1,6 @@ // Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com) All Rights Reserved. // -// WSO2 Inc. licenses this file to you under the Apache License, +// WSO2 LLC. licenses this file to you under the Apache License, // Version 2.0 (the "License"); you may not use this file except // in compliance with the License. // You may obtain a copy of the License at diff --git a/native/src/main/java/org/wssec/Constants.java b/native/src/main/java/org/wssec/Constants.java index bd9a0ef..84b60f2 100644 --- a/native/src/main/java/org/wssec/Constants.java +++ b/native/src/main/java/org/wssec/Constants.java @@ -1,6 +1,6 @@ // Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com) All Rights Reserved. // -// WSO2 Inc. licenses this file to you under the Apache License, +// WSO2 LLC. licenses this file to you under the Apache License, // Version 2.0 (the "License"); you may not use this file except // in compliance with the License. // You may obtain a copy of the License at diff --git a/native/src/main/java/org/wssec/DocumentBuilder.java b/native/src/main/java/org/wssec/DocumentBuilder.java index c897058..5e90b47 100644 --- a/native/src/main/java/org/wssec/DocumentBuilder.java +++ b/native/src/main/java/org/wssec/DocumentBuilder.java @@ -1,6 +1,6 @@ // Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com) All Rights Reserved. // -// WSO2 Inc. licenses this file to you under the Apache License, +// WSO2 LLC. licenses this file to you under the Apache License, // Version 2.0 (the "License"); you may not use this file except // in compliance with the License. // You may obtain a copy of the License at diff --git a/native/src/main/java/org/wssec/Encryption.java b/native/src/main/java/org/wssec/Encryption.java index 421096d..c7ced8d 100644 --- a/native/src/main/java/org/wssec/Encryption.java +++ b/native/src/main/java/org/wssec/Encryption.java @@ -1,6 +1,6 @@ // Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com) All Rights Reserved. // -// WSO2 Inc. licenses this file to you under the Apache License, +// WSO2 LLC. licenses this file to you under the Apache License, // Version 2.0 (the "License"); you may not use this file except // in compliance with the License. // You may obtain a copy of the License at diff --git a/native/src/main/java/org/wssec/ModuleUtils.java b/native/src/main/java/org/wssec/ModuleUtils.java index 92a71bf..61b7d62 100644 --- a/native/src/main/java/org/wssec/ModuleUtils.java +++ b/native/src/main/java/org/wssec/ModuleUtils.java @@ -1,6 +1,6 @@ // Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com) All Rights Reserved. // -// WSO2 Inc. licenses this file to you under the Apache License, +// WSO2 LLC. licenses this file to you under the Apache License, // Version 2.0 (the "License"); you may not use this file except // in compliance with the License. // You may obtain a copy of the License at diff --git a/native/src/main/java/org/wssec/Signature.java b/native/src/main/java/org/wssec/Signature.java index e10a566..e9d72b6 100644 --- a/native/src/main/java/org/wssec/Signature.java +++ b/native/src/main/java/org/wssec/Signature.java @@ -1,6 +1,6 @@ // Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com) All Rights Reserved. // -// WSO2 Inc. licenses this file to you under the Apache License, +// WSO2 LLC. licenses this file to you under the Apache License, // Version 2.0 (the "License"); you may not use this file except // in compliance with the License. // You may obtain a copy of the License at diff --git a/native/src/main/java/org/wssec/Utils.java b/native/src/main/java/org/wssec/Utils.java index 1fbf917..29691c0 100644 --- a/native/src/main/java/org/wssec/Utils.java +++ b/native/src/main/java/org/wssec/Utils.java @@ -1,6 +1,6 @@ // Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com) All Rights Reserved. // -// WSO2 Inc. licenses this file to you under the Apache License, +// WSO2 LLC. licenses this file to you under the Apache License, // Version 2.0 (the "License"); you may not use this file except // in compliance with the License. // You may obtain a copy of the License at diff --git a/native/src/main/java/org/wssec/WsSecurity.java b/native/src/main/java/org/wssec/WsSecurity.java index e15cedc..9e0506e 100644 --- a/native/src/main/java/org/wssec/WsSecurity.java +++ b/native/src/main/java/org/wssec/WsSecurity.java @@ -1,6 +1,6 @@ // Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com) All Rights Reserved. // -// WSO2 Inc. licenses this file to you under the Apache License, +// WSO2 LLC. licenses this file to you under the Apache License, // Version 2.0 (the "License"); you may not use this file except // in compliance with the License. // You may obtain a copy of the License at diff --git a/native/src/main/java/org/wssec/WsSecurityHeader.java b/native/src/main/java/org/wssec/WsSecurityHeader.java index 8927c53..be1e09f 100644 --- a/native/src/main/java/org/wssec/WsSecurityHeader.java +++ b/native/src/main/java/org/wssec/WsSecurityHeader.java @@ -1,6 +1,6 @@ // Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com) All Rights Reserved. // -// WSO2 Inc. licenses this file to you under the Apache License, +// WSO2 LLC. licenses this file to you under the Apache License, // Version 2.0 (the "License"); you may not use this file except // in compliance with the License. // You may obtain a copy of the License at diff --git a/native/src/main/java/org/wssec/WsSecurityUtils.java b/native/src/main/java/org/wssec/WsSecurityUtils.java index 286bfd8..ac176fd 100644 --- a/native/src/main/java/org/wssec/WsSecurityUtils.java +++ b/native/src/main/java/org/wssec/WsSecurityUtils.java @@ -1,6 +1,6 @@ // Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com) All Rights Reserved. // -// WSO2 Inc. licenses this file to you under the Apache License, +// WSO2 LLC. licenses this file to you under the Apache License, // Version 2.0 (the "License"); you may not use this file except // in compliance with the License. // You may obtain a copy of the License at From e8e5bc953e172aa48f7edc9bbaf90036b3d454dc Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Fri, 13 Oct 2023 20:15:43 +0530 Subject: [PATCH 177/189] Apply suggestions from the review --- native/src/main/java/org/wssec/WsSecurityUtils.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/native/src/main/java/org/wssec/WsSecurityUtils.java b/native/src/main/java/org/wssec/WsSecurityUtils.java index ac176fd..38c45e4 100644 --- a/native/src/main/java/org/wssec/WsSecurityUtils.java +++ b/native/src/main/java/org/wssec/WsSecurityUtils.java @@ -62,8 +62,7 @@ public class WsSecurityUtils { public static void buildSignature(RequestData reqData, WSSecSignature sign) throws Exception { - List parts; - parts = new ArrayList<>(1); + List parts = new ArrayList<>(1); Document doc = reqData.getSecHeader().getSecurityHeaderElement().getOwnerDocument(); parts.add(WSSecurityUtil.getDefaultEncryptionPart(doc)); List referenceList = sign.addReferencesToSign(parts); From e309edbbc4d7673f4c2ece8673433cf028487275 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Fri, 13 Oct 2023 20:50:12 +0530 Subject: [PATCH 178/189] Apply suggestions from the review --- ballerina/modules/soap11/soap11.bal | 2 +- ballerina/modules/soap12/soap12.bal | 2 +- ballerina/soap_utils.bal | 64 ++++++++----------- .../src/main/java/org/wssec/WsSecurity.java | 2 +- 4 files changed, 28 insertions(+), 42 deletions(-) diff --git a/ballerina/modules/soap11/soap11.bal b/ballerina/modules/soap11/soap11.bal index 84c2dd2..120d5f4 100644 --- a/ballerina/modules/soap11/soap11.bal +++ b/ballerina/modules/soap11/soap11.bal @@ -34,7 +34,7 @@ public isolated client class Client { do { check soap:validateTransportBindingPolicy(config); self.soapClient = check new (url, config.httpConfig); - readonly & soap:ClientConfig readonlyConfig = soap:getReadOnlyRecords(config); + readonly & soap:ClientConfig readonlyConfig = soap:getReadOnlyClientConfig(config); self.inboundSecurity = readonlyConfig.inboundSecurity; self.outboundSecurity = readonlyConfig.outboundSecurity; } on fail var err { diff --git a/ballerina/modules/soap12/soap12.bal b/ballerina/modules/soap12/soap12.bal index c1eaeae..e8ef8c9 100644 --- a/ballerina/modules/soap12/soap12.bal +++ b/ballerina/modules/soap12/soap12.bal @@ -34,7 +34,7 @@ public isolated client class Client { do { check soap:validateTransportBindingPolicy(config); self.soapClient = check new (url, config.httpConfig); - readonly & soap:ClientConfig readonlyConfig = soap:getReadOnlyRecords(config); + readonly & soap:ClientConfig readonlyConfig = soap:getReadOnlyClientConfig(config); self.inboundSecurity = readonlyConfig.inboundSecurity; self.outboundSecurity = readonlyConfig.outboundSecurity; } on fail var err { diff --git a/ballerina/soap_utils.bal b/ballerina/soap_utils.bal index be15240..d94eb16 100644 --- a/ballerina/soap_utils.bal +++ b/ballerina/soap_utils.bal @@ -36,32 +36,29 @@ public isolated function validateTransportBindingPolicy(ClientConfig config) ret } } -public isolated function getReadOnlyRecords(ClientConfig original) returns readonly & ClientConfig = @java:Method { +public isolated function getReadOnlyClientConfig(ClientConfig original) returns readonly & ClientConfig = @java:Method { 'class: "org.wssec.WsSecurity" } external; -public isolated function applySecurityPolicies(wssec:InboundSecurityConfig|wssec:InboundSecurityConfig[] inboundSecurity, - xml envelope) returns xml|wssec:Error { - wssec:InboundSecurityConfig|wssec:InboundSecurityConfig[] securityPolicy = inboundSecurity; - xml securedEnvelope; - if securityPolicy is wssec:InboundSecurityConfig { - if securityPolicy is wssec:TimestampTokenConfig { - securedEnvelope = check wssec:applyTimestampToken(envelope, securityPolicy); - } else if securityPolicy is wssec:UsernameTokenConfig { - securedEnvelope = check wssec:applyUsernameToken(envelope, securityPolicy); - } else if securityPolicy is wssec:SymmetricBindingConfig { - securedEnvelope = check wssec:applySymmetricBinding(envelope, securityPolicy); - } else if securityPolicy is wssec:AsymmetricBindingConfig { - securedEnvelope = check wssec:applyAsymmetricBinding(envelope, securityPolicy); - } else { - securedEnvelope = envelope; - } - } else { - foreach wssec:InboundSecurityConfig policy in securityPolicy { +public isolated function applySecurityPolicies(wssec:InboundSecurityConfig|wssec:InboundSecurityConfig[] security, + xml envelope) returns xml|wssec:Error { + if security is wssec:TimestampTokenConfig { + return wssec:applyTimestampToken(envelope, security); + } else if security is wssec:UsernameTokenConfig { + return wssec:applyUsernameToken(envelope, security); + } else if security is wssec:SymmetricBindingConfig { + return wssec:applySymmetricBinding(envelope, security); + } else if security is wssec:AsymmetricBindingConfig { + return wssec:applyAsymmetricBinding(envelope, security); + } else if security is wssec:InboundSecurityConfig { + return envelope; + } else if security is wssec:InboundSecurityConfig[] { + xml securedEnvelope; + foreach wssec:InboundSecurityConfig policy in security { securedEnvelope = check applySecurityPolicies(policy, envelope); } + return securedEnvelope; } - return securedEnvelope; } public isolated function applyOutboundConfig(wssec:OutboundSecurityConfig outboundSecurity, xml envelope) @@ -92,20 +89,15 @@ public isolated function applyOutboundConfig(wssec:OutboundSecurityConfig outbou } return soapEnvelope; } on fail var e { - return error Error("Outbound security configurations do not match with the SOAP response. ", e.cause()); + return error Error("Outbound security configurations do not match with the SOAP response.", e.cause()); } } -string path = ""; - public isolated function sendReceive(xml|mime:Entity[] body, http:Client httpClient, string? soapAction = (), - map headers = {}, string path = "", boolean soap12 = true) returns xml|Error { - http:Request req; - if soap12 { - req = createSoap12HttpRequest(body, soapAction, headers); - } else { - req = createSoap11HttpRequest(body, soapAction, headers); - } + map headers = {}, string path = "", boolean soap12 = true) + returns xml|Error { + http:Request req = soap12 ? createSoap12HttpRequest(body, soapAction, headers) + : createSoap11HttpRequest(body, soapAction, headers); do { http:Response response = check httpClient->post(path, req); if soap12 { @@ -119,12 +111,8 @@ public isolated function sendReceive(xml|mime:Entity[] body, http:Client httpCli public isolated function sendOnly(xml|mime:Entity[] body, http:Client httpClient, string? soapAction = (), map headers = {}, string path = "", boolean soap12 = true) returns Error? { - http:Request req; - if soap12 { - req = createSoap12HttpRequest(body, soapAction, headers); - } else { - req = createSoap11HttpRequest(body, soapAction, headers); - } + http:Request req = soap12 ? createSoap12HttpRequest(body, soapAction, headers) + : createSoap11HttpRequest(body, soapAction, headers); http:Response|http:ClientError response = httpClient->post(path, req); if response is http:ClientError { return error Error(response.message()); @@ -157,11 +145,9 @@ isolated function createSoap12HttpRequest(xml|mime:Entity[] body, string? soapAc req.setBodyParts(body); } if soapAction is string { - map stringMap = {}; - stringMap[ACTION] = string `${soapAction}`; var mediaType = mime:getMediaType(mime:APPLICATION_SOAP_XML); if mediaType is mime:MediaType { - mediaType.parameters = stringMap; + mediaType.parameters = {[ACTION]: soapAction}; req.setHeader(mime:CONTENT_TYPE, mediaType.toString()); } } else { diff --git a/native/src/main/java/org/wssec/WsSecurity.java b/native/src/main/java/org/wssec/WsSecurity.java index 9e0506e..5e74312 100644 --- a/native/src/main/java/org/wssec/WsSecurity.java +++ b/native/src/main/java/org/wssec/WsSecurity.java @@ -167,7 +167,7 @@ public static WSSecSignature prepareSignature(RequestData reqData, Object x509Fi return sign; } - public static BMap getReadOnlyRecords(BMap securityConfig) { + public static BMap getReadOnlyClientConfig(BMap securityConfig) { securityConfig.freezeDirect(); return securityConfig; } From 4731c3dc3534e1e0959b748f6ecb0bd63ab2413b Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Sat, 14 Oct 2023 20:30:49 +0530 Subject: [PATCH 179/189] Fix unnecessary `else if` statement --- ballerina/soap_utils.bal | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ballerina/soap_utils.bal b/ballerina/soap_utils.bal index d94eb16..cd7aeb5 100644 --- a/ballerina/soap_utils.bal +++ b/ballerina/soap_utils.bal @@ -52,7 +52,7 @@ public isolated function applySecurityPolicies(wssec:InboundSecurityConfig|wssec return wssec:applyAsymmetricBinding(envelope, security); } else if security is wssec:InboundSecurityConfig { return envelope; - } else if security is wssec:InboundSecurityConfig[] { + } else { xml securedEnvelope; foreach wssec:InboundSecurityConfig policy in security { securedEnvelope = check applySecurityPolicies(policy, envelope); @@ -162,11 +162,11 @@ isolated function createSoap12HttpRequest(xml|mime:Entity[] body, string? soapAc isolated function createSoap12Response(http:Response response) returns xml|error { xml payload = check response.getXmlPayload(); xmlns "http://www.w3.org/2003/05/soap-envelope" as soap12; - return payload/; + return payload; } isolated function createSoap11Response(http:Response response) returns xml|error { xml payload = check response.getXmlPayload(); xmlns "http://schemas.xmlsoap.org/soap/envelope/" as soap11; - return payload/; + return payload; } From e7a9ca9470128b1c88a418db6056184f8eb63abf Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Sun, 15 Oct 2023 10:34:34 +0530 Subject: [PATCH 180/189] Fix the code to send `` instead of `` --- .../soap11/tests/soap11_client_test.bal | 28 ++++++++----------- .../soap12/tests/soap12_client_test.bal | 26 ++++++++--------- 2 files changed, 23 insertions(+), 31 deletions(-) diff --git a/ballerina/modules/soap11/tests/soap11_client_test.bal b/ballerina/modules/soap11/tests/soap11_client_test.bal index f401155..63e5116 100644 --- a/ballerina/modules/soap11/tests/soap11_client_test.bal +++ b/ballerina/modules/soap11/tests/soap11_client_test.bal @@ -67,13 +67,7 @@ function testSendReceiveWithMime() returns error? { mtomMessage.push(bytesPart); xml|mime:Entity[] response = check soapClient->sendReceive(mtomMessage, "http://tempuri.org/Add", path = "/getPayload"); - xml expected = xml ` - - 2 - 3 - - `; - test:assertEquals(response, expected); + test:assertEquals(response, body); } @test:Config { @@ -117,7 +111,7 @@ function testSendReceive() returns error? { `; xml|mime:Entity[] response = check soapClient->sendReceive(body, "http://tempuri.org/Add"); - xml expected = xml `5`; + xml expected = xml `5`; test:assertEquals(response, expected); } @@ -140,7 +134,7 @@ function testSendReceiveWithHeaders() returns error? { xml|mime:Entity[] response = check soapClient->sendReceive(body, "http://tempuri.org/Add", {foo: ["bar1", "bar2"]}); - xml expected = xml `5`; + xml expected = xml `5`; test:assertEquals(response, expected); } @@ -212,11 +206,11 @@ function testSendReceiveWithTimestampTokenSecurity() returns error? { `; xml|mime:Entity[] response = check soapClient->sendReceive(body, "http://tempuri.org/Add"); - xml expected = xml `soap:MustUnderstandSystem.Web.Services.Protocols.SoapHeaderException: SOAP header Security was not understood. + xml expected = xml `soap:MustUnderstandSystem.Web.Services.Protocols.SoapHeaderException: SOAP header Security was not understood. at System.Web.Services.Protocols.SoapHeaderHandling.SetHeaderMembers(SoapHeaderCollection headers, Object target, SoapHeaderMapping[] mappings, SoapHeaderDirection direction, Boolean client) at System.Web.Services.Protocols.SoapServerProtocol.CreateServerInstance() at System.Web.Services.Protocols.WebServiceHandler.Invoke() - at System.Web.Services.Protocols.WebServiceHandler.CoreProcessRequest()`; + at System.Web.Services.Protocols.WebServiceHandler.CoreProcessRequest()`; test:assertEquals(response.toString(), expected.toString()); } @@ -245,11 +239,11 @@ function testSendReceiveWithUsernameTokenSecurity() returns error? { `; xml|mime:Entity[] response = check soapClient->sendReceive(body, "http://tempuri.org/Add"); - xml expected = xml `soap:MustUnderstandSystem.Web.Services.Protocols.SoapHeaderException: SOAP header Security was not understood. + xml expected = xml `soap:MustUnderstandSystem.Web.Services.Protocols.SoapHeaderException: SOAP header Security was not understood. at System.Web.Services.Protocols.SoapHeaderHandling.SetHeaderMembers(SoapHeaderCollection headers, Object target, SoapHeaderMapping[] mappings, SoapHeaderDirection direction, Boolean client) at System.Web.Services.Protocols.SoapServerProtocol.CreateServerInstance() at System.Web.Services.Protocols.WebServiceHandler.Invoke() - at System.Web.Services.Protocols.WebServiceHandler.CoreProcessRequest()`; + at System.Web.Services.Protocols.WebServiceHandler.CoreProcessRequest()`; test:assertEquals(response.toString(), expected.toString()); } @@ -292,11 +286,11 @@ function testSendReceiveWithAsymmetricBindingSecurity() returns error? { `; xml|mime:Entity[] response = check soapClient->sendReceive(body, "http://tempuri.org/Add"); - xml expected = xml `soap:MustUnderstandSystem.Web.Services.Protocols.SoapHeaderException: SOAP header Security was not understood. + xml expected = xml `soap:MustUnderstandSystem.Web.Services.Protocols.SoapHeaderException: SOAP header Security was not understood. at System.Web.Services.Protocols.SoapHeaderHandling.SetHeaderMembers(SoapHeaderCollection headers, Object target, SoapHeaderMapping[] mappings, SoapHeaderDirection direction, Boolean client) at System.Web.Services.Protocols.SoapServerProtocol.CreateServerInstance() at System.Web.Services.Protocols.WebServiceHandler.Invoke() - at System.Web.Services.Protocols.WebServiceHandler.CoreProcessRequest()`; + at System.Web.Services.Protocols.WebServiceHandler.CoreProcessRequest()`; test:assertEquals(response.toString(), expected.toString()); } @@ -337,10 +331,10 @@ function testSendReceiveWithSymmetricBindingSecurity() returns error? { `; xml|mime:Entity[] response = check soapClient->sendReceive(body, "http://tempuri.org/Add"); - xml expected = xml `soap:MustUnderstandSystem.Web.Services.Protocols.SoapHeaderException: SOAP header Security was not understood. + xml expected = xml `soap:MustUnderstandSystem.Web.Services.Protocols.SoapHeaderException: SOAP header Security was not understood. at System.Web.Services.Protocols.SoapHeaderHandling.SetHeaderMembers(SoapHeaderCollection headers, Object target, SoapHeaderMapping[] mappings, SoapHeaderDirection direction, Boolean client) at System.Web.Services.Protocols.SoapServerProtocol.CreateServerInstance() at System.Web.Services.Protocols.WebServiceHandler.Invoke() - at System.Web.Services.Protocols.WebServiceHandler.CoreProcessRequest()`; + at System.Web.Services.Protocols.WebServiceHandler.CoreProcessRequest()`; test:assertEquals(response.toString(), expected.toString()); } diff --git a/ballerina/modules/soap12/tests/soap12_client_test.bal b/ballerina/modules/soap12/tests/soap12_client_test.bal index 5833f2d..61b7b3f 100644 --- a/ballerina/modules/soap12/tests/soap12_client_test.bal +++ b/ballerina/modules/soap12/tests/soap12_client_test.bal @@ -53,7 +53,6 @@ function testSendOnly12() returns error? { } function testSendReceive12() returns error? { Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL"); - xml body = xml ` @@ -66,7 +65,7 @@ function testSendReceive12() returns error? { `; xml|mime:Entity[] response = check soapClient->sendReceive(body, "http://tempuri.org/Add"); - xml expected = xml `5`; + xml expected = xml `5`; test:assertEquals(response, expected); } @@ -90,7 +89,7 @@ function testSendReceive12WithHeaders() returns error? { xml|mime:Entity[] response = check soapClient->sendReceive(body, "http://tempuri.org/Add", {foo: ["bar1", "bar2"]}); - xml expected = xml `5`; + xml expected = xml `5`; test:assertEquals(response, expected); } @@ -113,7 +112,7 @@ function testSendReceive12WithoutSoapAction() returns error? { xml|mime:Entity[] response = check soapClient->sendReceive(body); - xml expected = xml `5`; + xml expected = xml `5`; test:assertEquals(response, expected); } @@ -155,7 +154,7 @@ function testSendReceive12IncludingHeadersWithoutSoapAction() returns error? { Client soapClient = check new ("http://www.dneonline.com/calculator.asmx?WSDL"); xml|mime:Entity[] response = check soapClient->sendReceive(body, (), {foo: ["bar1", "bar2"]}); - xml expected = xml `5`; + xml expected = xml `5`; test:assertEquals(response, expected); } @@ -226,11 +225,11 @@ function testSendReceiveWithTimestampTokenSecurity() returns error? { `; xml|mime:Entity[] response = check soapClient->sendReceive(body, "http://tempuri.org/Add"); - xml expected = xml `soap:MustUnderstandSystem.Web.Services.Protocols.SoapHeaderException: SOAP header Security was not understood. + xml expected = xml `soap:MustUnderstandSystem.Web.Services.Protocols.SoapHeaderException: SOAP header Security was not understood. at System.Web.Services.Protocols.SoapHeaderHandling.SetHeaderMembers(SoapHeaderCollection headers, Object target, SoapHeaderMapping[] mappings, SoapHeaderDirection direction, Boolean client) at System.Web.Services.Protocols.SoapServerProtocol.CreateServerInstance() at System.Web.Services.Protocols.WebServiceHandler.Invoke() - at System.Web.Services.Protocols.WebServiceHandler.CoreProcessRequest()`; + at System.Web.Services.Protocols.WebServiceHandler.CoreProcessRequest()`; test:assertEquals(response.toString(), expected.toString()); } @@ -260,11 +259,11 @@ function testSendReceiveWithUsernameTokenSecurity() returns error? { `; xml|mime:Entity[] response = check soapClient->sendReceive(body, "http://tempuri.org/Add"); - xml expected = xml `soap:MustUnderstandSystem.Web.Services.Protocols.SoapHeaderException: SOAP header Security was not understood. + xml expected = xml `soap:MustUnderstandSystem.Web.Services.Protocols.SoapHeaderException: SOAP header Security was not understood. at System.Web.Services.Protocols.SoapHeaderHandling.SetHeaderMembers(SoapHeaderCollection headers, Object target, SoapHeaderMapping[] mappings, SoapHeaderDirection direction, Boolean client) at System.Web.Services.Protocols.SoapServerProtocol.CreateServerInstance() at System.Web.Services.Protocols.WebServiceHandler.Invoke() - at System.Web.Services.Protocols.WebServiceHandler.CoreProcessRequest()`; + at System.Web.Services.Protocols.WebServiceHandler.CoreProcessRequest()`; test:assertEquals(response.toString(), expected.toString()); } @@ -307,11 +306,11 @@ function testSendReceiveWithAsymmetricBindingSecurity() returns error? { `; xml|mime:Entity[] response = check soapClient->sendReceive(body, "http://tempuri.org/Add"); - xml expected = xml `soap:MustUnderstandSystem.Web.Services.Protocols.SoapHeaderException: SOAP header Security was not understood. + xml expected = xml `soap:MustUnderstandSystem.Web.Services.Protocols.SoapHeaderException: SOAP header Security was not understood. at System.Web.Services.Protocols.SoapHeaderHandling.SetHeaderMembers(SoapHeaderCollection headers, Object target, SoapHeaderMapping[] mappings, SoapHeaderDirection direction, Boolean client) at System.Web.Services.Protocols.SoapServerProtocol.CreateServerInstance() at System.Web.Services.Protocols.WebServiceHandler.Invoke() - at System.Web.Services.Protocols.WebServiceHandler.CoreProcessRequest()`; + at System.Web.Services.Protocols.WebServiceHandler.CoreProcessRequest()`; test:assertEquals(response.toString(), expected.toString()); } @@ -353,11 +352,10 @@ function testSendReceiveWithSymmetricBindingSecurity() returns error? { `; xml|mime:Entity[] response = check soapClient->sendReceive(body, "http://tempuri.org/Add"); - xml expected = xml `soap:MustUnderstandSystem.Web.Services.Protocols.SoapHeaderException: SOAP header Security was not understood. + xml expected = xml `soap:MustUnderstandSystem.Web.Services.Protocols.SoapHeaderException: SOAP header Security was not understood. at System.Web.Services.Protocols.SoapHeaderHandling.SetHeaderMembers(SoapHeaderCollection headers, Object target, SoapHeaderMapping[] mappings, SoapHeaderDirection direction, Boolean client) at System.Web.Services.Protocols.SoapServerProtocol.CreateServerInstance() at System.Web.Services.Protocols.WebServiceHandler.Invoke() - at System.Web.Services.Protocols.WebServiceHandler.CoreProcessRequest()`; - + at System.Web.Services.Protocols.WebServiceHandler.CoreProcessRequest()`; test:assertEquals(response.toString(), expected.toString()); } From 2255c4802fd2d2f27cd0e142aba79cf65f51ce79 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Sun, 15 Oct 2023 10:35:33 +0530 Subject: [PATCH 181/189] Add resource functions to receive request from SOAP client --- .../soap11/tests/http_soap_service.bal | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/ballerina/modules/soap11/tests/http_soap_service.bal b/ballerina/modules/soap11/tests/http_soap_service.bal index 4847484..d327c78 100644 --- a/ballerina/modules/soap11/tests/http_soap_service.bal +++ b/ballerina/modules/soap11/tests/http_soap_service.bal @@ -14,6 +14,22 @@ // specific language governing permissions and limitations // under the License. import ballerina/http; +import ballerina/crypto; +import ballerina/soap; + +crypto:KeyStore serverKeyStore = { + path: X509_KEY_STORE_PATH, + password: KEY_PASSWORD +}; +crypto:PublicKey serverPublicKey = check crypto:decodeRsaPublicKeyFromTrustStore(serverKeyStore, KEY_ALIAS); +crypto:PrivateKey serverPrivateKey = check crypto:decodeRsaPrivateKeyFromKeyStore(serverKeyStore, KEY_ALIAS, + KEY_PASSWORD); + +crypto:KeyStore clientKeyStore = { + path: X509_KEY_STORE_PATH_2, + password: KEY_PASSWORD +}; +crypto:PublicKey clientPublicKey = check crypto:decodeRsaPublicKeyFromTrustStore(clientKeyStore, KEY_ALIAS); service / on new http:Listener(9090) { @@ -22,4 +38,32 @@ service / on new http:Listener(9090) { response.setPayload(check (check request.getBodyParts())[0].getXml()); return response; } + + resource function post getSamePayload(http:Request request) returns http:Response|error { + http:Response response = new; + xml payload = check request.getXmlPayload(); + response.setPayload(payload); + return response; + } + + resource function post getSecuredPayload(http:Request request) returns http:Response|error { + http:Response response = new; + xml payload = check request.getXmlPayload(); + xml applyOutboundConfig = check soap:applyOutboundConfig({ + verificationKey: clientPublicKey, + signatureAlgorithm: soap:RSA_SHA256, + decryptionAlgorithm: soap:RSA_ECB, + decryptionKey: serverPrivateKey + }, payload); + + xml securedEnv = check soap:applySecurityPolicies({ + signatureAlgorithm: soap:RSA_SHA256, + encryptionAlgorithm: soap:RSA_ECB, + signatureKey: serverPrivateKey, + encryptionKey: clientPublicKey + }, applyOutboundConfig); + + response.setPayload(securedEnv); + return response; + } } From a04bc4b48ac750e61e388918b630381df3517d52 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Sun, 15 Oct 2023 11:22:51 +0530 Subject: [PATCH 182/189] Remove redundant methods --- ballerina/soap_utils.bal | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/ballerina/soap_utils.bal b/ballerina/soap_utils.bal index cd7aeb5..182ae98 100644 --- a/ballerina/soap_utils.bal +++ b/ballerina/soap_utils.bal @@ -20,6 +20,7 @@ import ballerina/http; import ballerina/mime; import ballerina/lang.regexp; import ballerina/jballerina.java; +import ballerina/test; public isolated function validateTransportBindingPolicy(ClientConfig config) returns Error? { if config.httpConfig.secureSocket is () { @@ -170,3 +171,39 @@ isolated function createSoap11Response(http:Response response) returns xml|error xmlns "http://schemas.xmlsoap.org/soap/envelope/" as soap11; return payload; } + +public function assertUsernameToken(string envelopeString, string username, string password, + wssec:PasswordType passwordType, string body) returns error? { + string:RegExp bodyData = check regexp:fromString(body); + test:assertTrue(envelopeString.includesMatch(bodyData)); + string:RegExp usernameTokenTag = re `.*`; + string:RegExp usernameTag = re `${username}`; + test:assertTrue(envelopeString.includesMatch(usernameTokenTag)); + test:assertTrue(envelopeString.includesMatch(usernameTag)); + string:RegExp passwordTag = re `${password}`; + test:assertTrue(envelopeString.includesMatch(passwordTag)); +} + +public function assertSymmetricBinding(string envelopeString, string body) returns error? { + string:RegExp bodyData = check regexp:fromString(body); + test:assertTrue(envelopeString.includesMatch(bodyData)); + assertSignatureWithoutX509(envelopeString); +} + +public function assertSignatureWithoutX509(string securedEnvelope) { + string:RegExp signature = re `.*`; + string:RegExp signatureInfo = re `.*`; + string:RegExp canonicalizationMethod = re ``; + string:RegExp signatureMethod = re ``; + string:RegExp transformMethod = re ``; + string:RegExp digestMethod = re ``; + string:RegExp signatureValue = re `.*`; + + test:assertTrue(securedEnvelope.includesMatch(signature)); + test:assertTrue(securedEnvelope.includesMatch(signatureInfo)); + test:assertTrue(securedEnvelope.includesMatch(canonicalizationMethod)); + test:assertTrue(securedEnvelope.includesMatch(signatureMethod)); + test:assertTrue(securedEnvelope.includesMatch(transformMethod)); + test:assertTrue(securedEnvelope.includesMatch(digestMethod)); + test:assertTrue(securedEnvelope.includesMatch(signatureValue)); +} From 89ea49bdc9ee6308c2e64ba924a666d96760f583 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Sun, 15 Oct 2023 11:24:34 +0530 Subject: [PATCH 183/189] Add test cases for inbound and outbound configs in SOAP clients --- .../soap11/tests/http_soap_service.bal | 16 +--- .../soap11/tests/soap11_client_test.bal | 93 +++++++++++++++++- .../soap12/tests/http_soap_service.bal | 62 ++++++++++++ .../soap12/tests/soap12_client_test.bal | 94 +++++++++++++++++-- 4 files changed, 243 insertions(+), 22 deletions(-) create mode 100644 ballerina/modules/soap12/tests/http_soap_service.bal diff --git a/ballerina/modules/soap11/tests/http_soap_service.bal b/ballerina/modules/soap11/tests/http_soap_service.bal index d327c78..57827d0 100644 --- a/ballerina/modules/soap11/tests/http_soap_service.bal +++ b/ballerina/modules/soap11/tests/http_soap_service.bal @@ -13,23 +13,17 @@ // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -import ballerina/http; import ballerina/crypto; +import ballerina/http; import ballerina/soap; -crypto:KeyStore serverKeyStore = { +const crypto:KeyStore serverKeyStore = { path: X509_KEY_STORE_PATH, password: KEY_PASSWORD }; -crypto:PublicKey serverPublicKey = check crypto:decodeRsaPublicKeyFromTrustStore(serverKeyStore, KEY_ALIAS); crypto:PrivateKey serverPrivateKey = check crypto:decodeRsaPrivateKeyFromKeyStore(serverKeyStore, KEY_ALIAS, - KEY_PASSWORD); - -crypto:KeyStore clientKeyStore = { - path: X509_KEY_STORE_PATH_2, - password: KEY_PASSWORD -}; -crypto:PublicKey clientPublicKey = check crypto:decodeRsaPublicKeyFromTrustStore(clientKeyStore, KEY_ALIAS); + KEY_PASSWORD); +crypto:PublicKey serverPublicKey = check crypto:decodeRsaPublicKeyFromTrustStore(serverKeyStore, KEY_ALIAS); service / on new http:Listener(9090) { @@ -55,14 +49,12 @@ service / on new http:Listener(9090) { decryptionAlgorithm: soap:RSA_ECB, decryptionKey: serverPrivateKey }, payload); - xml securedEnv = check soap:applySecurityPolicies({ signatureAlgorithm: soap:RSA_SHA256, encryptionAlgorithm: soap:RSA_ECB, signatureKey: serverPrivateKey, encryptionKey: clientPublicKey }, applyOutboundConfig); - response.setPayload(securedEnv); return response; } diff --git a/ballerina/modules/soap11/tests/soap11_client_test.bal b/ballerina/modules/soap11/tests/soap11_client_test.bal index 63e5116..d44fe39 100644 --- a/ballerina/modules/soap11/tests/soap11_client_test.bal +++ b/ballerina/modules/soap11/tests/soap11_client_test.bal @@ -14,23 +14,38 @@ // specific language governing permissions and limitations // under the License. import soap; +import soap.wssec; import ballerina/crypto; +import ballerina/io; import ballerina/mime; import ballerina/test; -import soap.wssec; -import ballerina/io; const string KEY_ALIAS = "wss40"; const string KEY_PASSWORD = "security"; const IMAGE_PATH = "../ballerina/icon.png"; -const FILE_PATH = "../ballerina/Module.md"; +const FILE_PATH = "../ballerina/Module.md"; const string KEY_STORE_PATH = "modules/wssec/tests/resources/wss40.p12"; const string X509_KEY_STORE_PATH = "modules/wssec/tests/resources/x509_certificate.p12"; const string X509_KEY_STORE_PATH_2 = "modules/wssec/tests/resources/x509_certificate_2.p12"; const wssec:TransportBindingConfig TRANSPORT_BINDING = "TransportBinding"; const wssec:NoPolicy NO_POLICY = "NoPolicy"; +const crypto:KeyStore clientKeyStore = { + path: X509_KEY_STORE_PATH_2, + password: KEY_PASSWORD +}; +crypto:PrivateKey clientPrivateKey = check crypto:decodeRsaPrivateKeyFromKeyStore(clientKeyStore, KEY_ALIAS, + KEY_PASSWORD); +crypto:PublicKey clientPublicKey = check crypto:decodeRsaPublicKeyFromTrustStore(clientKeyStore, KEY_ALIAS); + +crypto:KeyStore keyStore = { + path: KEY_STORE_PATH, + password: KEY_PASSWORD +}; +crypto:PrivateKey symmetricKey = check crypto:decodeRsaPrivateKeyFromKeyStore(keyStore, KEY_ALIAS, KEY_PASSWORD); +crypto:PublicKey publicKey = check crypto:decodeRsaPublicKeyFromTrustStore(keyStore, KEY_ALIAS); + @test:Config { groups: ["soap11", "send_receive", "mime", "aa"] } @@ -274,7 +289,7 @@ function testSendReceiveWithAsymmetricBindingSecurity() returns error? { } } ); - + xml body = xml ` @@ -338,3 +353,73 @@ function testSendReceiveWithSymmetricBindingSecurity() returns error? { at System.Web.Services.Protocols.WebServiceHandler.CoreProcessRequest()`; test:assertEquals(response.toString(), expected.toString()); } + +@test:Config { + groups: ["soap11", "send_receive"] +} +function testSoapEndpoint() returns error? { + string username = "user"; + string password = "password"; + Client soapClient = check new ("http://localhost:9090", + { + inboundSecurity: { + username: username, + password: password, + passwordType: wssec:TEXT + } + } + ); + xml body = xml `23`; + xml|mime:Entity[] response = check soapClient->sendReceive(body, "http://tempuri.org/Add", path = "/getSamePayload"); + return soap:assertUsernameToken(response.toString(), username, password, wssec:TEXT, string `23`); +} + +@test:Config { + groups: ["soap11", "send_receive"] +} +function testSoapReceiveWithSymmetricBindingAndOutboundConfig() returns error? { + Client soapClient = check new ("http://localhost:9090", + { + inboundSecurity: { + signatureAlgorithm: wssec:RSA_SHA256, + encryptionAlgorithm: wssec:RSA_ECB, + symmetricKey: symmetricKey, + servicePublicKey: serverPublicKey + }, + outboundSecurity: { + verificationKey: publicKey, + signatureAlgorithm: wssec:RSA_SHA256, + decryptionAlgorithm: wssec:RSA_ECB, + decryptionKey: publicKey + } + } + ); + xml body = xml `23`; + xml|mime:Entity[] response = check soapClient->sendReceive(body, "http://tempuri.org/Add", path = "/getSamePayload"); + return soap:assertSymmetricBinding(response.toString(), string `23`); +} + +@test:Config { + groups: ["soap11", "send_receive", "j"] +} +function testSendReceiveWithAsymmetricBindingAndOutboundConfig() returns error? { + Client soapClient = check new ("http://localhost:9090", + { + inboundSecurity: { + signatureAlgorithm: soap:RSA_SHA256, + encryptionAlgorithm: soap:RSA_ECB, + signatureKey: clientPrivateKey, + encryptionKey: serverPublicKey + }, + outboundSecurity: { + verificationKey: serverPublicKey, + signatureAlgorithm: soap:RSA_SHA256, + decryptionAlgorithm: soap:RSA_ECB, + decryptionKey: clientPrivateKey + } + } + ); + xml body = xml `23`; + xml|mime:Entity[] response = check soapClient->sendReceive(body, "http://tempuri.org/Add", path = "/getSecuredPayload"); + return soap:assertSymmetricBinding(response.toString(), string `23`); +} diff --git a/ballerina/modules/soap12/tests/http_soap_service.bal b/ballerina/modules/soap12/tests/http_soap_service.bal new file mode 100644 index 0000000..94a8782 --- /dev/null +++ b/ballerina/modules/soap12/tests/http_soap_service.bal @@ -0,0 +1,62 @@ +// Copyright (c) 2023, WSO2 LLC. (http://www.wso2.org) All Rights Reserved. +// +// WSO2 LLC. licenses this file to you under the Apache License, +// Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +import ballerina/crypto; +import ballerina/http; +import ballerina/soap; + +const crypto:KeyStore serverKeyStore = { + path: X509_KEY_STORE_PATH, + password: KEY_PASSWORD +}; +crypto:PrivateKey serverPrivateKey = check crypto:decodeRsaPrivateKeyFromKeyStore(serverKeyStore, KEY_ALIAS, + KEY_PASSWORD); +crypto:PublicKey serverPublicKey = check crypto:decodeRsaPublicKeyFromTrustStore(serverKeyStore, KEY_ALIAS); + +service / on new http:Listener(9090) { + + resource function post getPayload(http:Request request) returns http:Response|error { + http:Response response = new; + response.setPayload(check (check request.getBodyParts())[0].getXml()); + return response; + } + + resource function post getSamePayload(http:Request request) returns http:Response|error { + http:Response response = new; + xml payload = check request.getXmlPayload(); + response.setPayload(payload); + return response; + } + + resource function post getSecuredPayload(http:Request request) returns http:Response|error { + http:Response response = new; + xml payload = check request.getXmlPayload(); + xml applyOutboundConfig = check soap:applyOutboundConfig({ + verificationKey: clientPublicKey, + signatureAlgorithm: soap:RSA_SHA256, + decryptionAlgorithm: soap:RSA_ECB, + decryptionKey: serverPrivateKey + }, payload); + + xml securedEnv = check soap:applySecurityPolicies({ + signatureAlgorithm: soap:RSA_SHA256, + encryptionAlgorithm: soap:RSA_ECB, + signatureKey: serverPrivateKey, + encryptionKey: clientPublicKey + }, applyOutboundConfig); + response.setPayload(securedEnv); + return response; + } +} diff --git a/ballerina/modules/soap12/tests/soap12_client_test.bal b/ballerina/modules/soap12/tests/soap12_client_test.bal index 61b7b3f..742a227 100644 --- a/ballerina/modules/soap12/tests/soap12_client_test.bal +++ b/ballerina/modules/soap12/tests/soap12_client_test.bal @@ -14,11 +14,11 @@ // specific language governing permissions and limitations // under the License. import soap; +import soap.wssec; +import ballerina/crypto; import ballerina/mime; import ballerina/test; -import ballerina/crypto; -import soap.wssec; const KEY_ALIAS = "wss40"; const KEY_PASSWORD = "security"; @@ -28,6 +28,21 @@ const X509_KEY_STORE_PATH_2 = "modules/wssec/tests/resources/x509_certificate_2. const wssec:TransportBindingConfig TRANSPORT_BINDING = "TransportBinding"; const wssec:NoPolicy NO_POLICY = "NoPolicy"; +const crypto:KeyStore clientKeyStore = { + path: X509_KEY_STORE_PATH_2, + password: KEY_PASSWORD +}; +crypto:PrivateKey clientPrivateKey = check crypto:decodeRsaPrivateKeyFromKeyStore(clientKeyStore, KEY_ALIAS, + KEY_PASSWORD); +crypto:PublicKey clientPublicKey = check crypto:decodeRsaPublicKeyFromTrustStore(clientKeyStore, KEY_ALIAS); + +crypto:KeyStore keyStore = { + path: KEY_STORE_PATH, + password: KEY_PASSWORD +}; +crypto:PrivateKey symmetricKey = check crypto:decodeRsaPrivateKeyFromKeyStore(keyStore, KEY_ALIAS, KEY_PASSWORD); +crypto:PublicKey publicKey = check crypto:decodeRsaPublicKeyFromTrustStore(keyStore, KEY_ALIAS); + @test:Config { groups: ["soap12", "send_only"] } @@ -172,9 +187,9 @@ function testTransportBindingError() returns error? { } function testTransportBindingError2() returns error? { Client|Error soapClient = new ("http://www.dneonline.com/calculator.asmx?WSDL", - inboundSecurity = [ - TRANSPORT_BINDING - ] + inboundSecurity = [ + TRANSPORT_BINDING + ] ); test:assertTrue(soapClient is Error); test:assertEquals((soapClient).message(), SOAP_CLIENT_ERROR); @@ -200,7 +215,6 @@ function testSendReceiveError() returns error? { test:assertEquals((response).message(), SOAP_RESPONSE_ERROR); } - @test:Config { groups: ["soap12", "send_receive"] } @@ -359,3 +373,71 @@ function testSendReceiveWithSymmetricBindingSecurity() returns error? { at System.Web.Services.Protocols.WebServiceHandler.CoreProcessRequest()`; test:assertEquals(response.toString(), expected.toString()); } + +function testSoapEndpoint() returns error? { + string username = "user"; + string password = "password"; + Client soapClient = check new ("http://localhost:9090", + { + inboundSecurity: { + username: username, + password: password, + passwordType: wssec:TEXT + } + } + ); + xml body = xml `23`; + xml|mime:Entity[] response = check soapClient->sendReceive(body, "http://tempuri.org/Add", path = "/getSamePayload"); + return soap:assertUsernameToken(response.toString(), username, password, wssec:TEXT, string `23`); +} + +@test:Config { + groups: ["soap11", "send_receive"] +} +function testSoapReceiveWithSymmetricBindingAndOutboundConfig() returns error? { + Client soapClient = check new ("http://localhost:9090", + { + inboundSecurity: { + signatureAlgorithm: wssec:RSA_SHA256, + encryptionAlgorithm: wssec:RSA_ECB, + symmetricKey: symmetricKey, + servicePublicKey: serverPublicKey + }, + outboundSecurity: { + verificationKey: publicKey, + signatureAlgorithm: wssec:RSA_SHA256, + decryptionAlgorithm: wssec:RSA_ECB, + decryptionKey: publicKey + } + } + ); + xml body = xml `23`; + xml|mime:Entity[] response = check soapClient->sendReceive(body, "http://tempuri.org/Add", path = "/getSamePayload"); + return soap:assertSymmetricBinding(response.toString(), string `23`); +} + +@test:Config { + groups: ["soap11", "send_receive", "j"] +} +function testSendReceiveWithAsymmetricBindingAndOutboundConfig() returns error? { + Client soapClient = check new ("http://localhost:9090", + { + inboundSecurity: { + signatureAlgorithm: soap:RSA_SHA256, + encryptionAlgorithm: soap:RSA_ECB, + signatureKey: clientPrivateKey, + encryptionKey: serverPublicKey + }, + outboundSecurity: { + verificationKey: serverPublicKey, + signatureAlgorithm: soap:RSA_SHA256, + decryptionAlgorithm: soap:RSA_ECB, + decryptionKey: clientPrivateKey + } + } + ); + + xml body = xml `23`; + xml|mime:Entity[] response = check soapClient->sendReceive(body, "http://tempuri.org/Add", path = "/getSecuredPayload"); + return soap:assertSymmetricBinding(response.toString(), string `23`); +} From 8b3e4729a8b66fb361d4ad2bb30a5a1a137f2781 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Sun, 15 Oct 2023 21:52:13 +0530 Subject: [PATCH 184/189] [Automated] Update the native jar versions --- ballerina/Dependencies.toml | 2 -- 1 file changed, 2 deletions(-) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index 9a414c0..7b1c154 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -157,7 +157,6 @@ dependencies = [ org = "ballerina" name = "lang.error" version = "0.0.0" -scope = "testOnly" dependencies = [ {org = "ballerina", name = "jballerina.java"} ] @@ -301,7 +300,6 @@ dependencies = [ org = "ballerina" name = "test" version = "0.0.0" -scope = "testOnly" dependencies = [ {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "lang.error"} From 90923f5b822cf611d2754ab323a3eee1b9138b31 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Sun, 15 Oct 2023 22:27:30 +0530 Subject: [PATCH 185/189] Fix license header --- native/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/native/build.gradle b/native/build.gradle index 2a861fb..482d386 100644 --- a/native/build.gradle +++ b/native/build.gradle @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com) All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. From 902844feeea46ae121bac4d6f4127613ef2cc750 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Sun, 15 Oct 2023 22:29:53 +0530 Subject: [PATCH 186/189] Apply suggestions from the review --- ballerina/modules/soap11/soap11.bal | 5 +-- .../soap11/tests/http_soap_service.bal | 32 ++++++++++--------- ballerina/modules/soap12/soap12.bal | 5 +-- .../soap12/tests/http_soap_service.bal | 31 +++++++++--------- ballerina/modules/wssec/encryption.bal | 12 +------ .../modules/wssec/ws_security_methods.bal | 12 +++---- ballerina/soap_utils.bal | 2 +- 7 files changed, 47 insertions(+), 52 deletions(-) diff --git a/ballerina/modules/soap11/soap11.bal b/ballerina/modules/soap11/soap11.bal index 120d5f4..5b14194 100644 --- a/ballerina/modules/soap11/soap11.bal +++ b/ballerina/modules/soap11/soap11.bal @@ -53,15 +53,16 @@ public isolated client class Client { # + path - The resource path # + return - If successful, returns the response. Else, returns an error remote isolated function sendReceive(xml|mime:Entity[] body, string action, - map headers = {}, string path = "") returns xml|mime:Entity[]|Error { + map headers = {}, string path = "") + returns xml|mime:Entity[]|Error { do { xml securedBody; - xml response; xml mimeEntity = body is xml ? body : check body[0].getXml(); lock { xml envelope = body is xml ? body.clone() : mimeEntity.clone(); securedBody = check soap:applySecurityPolicies(self.inboundSecurity.clone(), envelope.clone()); } + xml response; if body is mime:Entity[] { body[0].setXml(securedBody); response = check soap:sendReceive(body, self.soapClient, action, headers, path, false); diff --git a/ballerina/modules/soap11/tests/http_soap_service.bal b/ballerina/modules/soap11/tests/http_soap_service.bal index 57827d0..ed4e349 100644 --- a/ballerina/modules/soap11/tests/http_soap_service.bal +++ b/ballerina/modules/soap11/tests/http_soap_service.bal @@ -22,7 +22,7 @@ const crypto:KeyStore serverKeyStore = { password: KEY_PASSWORD }; crypto:PrivateKey serverPrivateKey = check crypto:decodeRsaPrivateKeyFromKeyStore(serverKeyStore, KEY_ALIAS, - KEY_PASSWORD); + KEY_PASSWORD); crypto:PublicKey serverPublicKey = check crypto:decodeRsaPublicKeyFromTrustStore(serverKeyStore, KEY_ALIAS); service / on new http:Listener(9090) { @@ -34,27 +34,29 @@ service / on new http:Listener(9090) { } resource function post getSamePayload(http:Request request) returns http:Response|error { - http:Response response = new; xml payload = check request.getXmlPayload(); + http:Response response = new; response.setPayload(payload); return response; } resource function post getSecuredPayload(http:Request request) returns http:Response|error { - http:Response response = new; xml payload = check request.getXmlPayload(); - xml applyOutboundConfig = check soap:applyOutboundConfig({ - verificationKey: clientPublicKey, - signatureAlgorithm: soap:RSA_SHA256, - decryptionAlgorithm: soap:RSA_ECB, - decryptionKey: serverPrivateKey - }, payload); - xml securedEnv = check soap:applySecurityPolicies({ - signatureAlgorithm: soap:RSA_SHA256, - encryptionAlgorithm: soap:RSA_ECB, - signatureKey: serverPrivateKey, - encryptionKey: clientPublicKey - }, applyOutboundConfig); + xml applyOutboundConfig = check soap:applyOutboundConfig( + { + verificationKey: clientPublicKey, + signatureAlgorithm: soap:RSA_SHA256, + decryptionAlgorithm: soap:RSA_ECB, + decryptionKey: serverPrivateKey + }, payload); + xml securedEnv = check soap:applySecurityPolicies( + { + signatureAlgorithm: soap:RSA_SHA256, + encryptionAlgorithm: soap:RSA_ECB, + signatureKey: serverPrivateKey, + encryptionKey: clientPublicKey + }, applyOutboundConfig); + http:Response response = new; response.setPayload(securedEnv); return response; } diff --git a/ballerina/modules/soap12/soap12.bal b/ballerina/modules/soap12/soap12.bal index e8ef8c9..c7b0369 100644 --- a/ballerina/modules/soap12/soap12.bal +++ b/ballerina/modules/soap12/soap12.bal @@ -53,15 +53,16 @@ public isolated client class Client { # + path - The resource path # + return - If successful, returns the response. Else, returns an error remote isolated function sendReceive(xml|mime:Entity[] body, string? action = (), - map headers = {}, string path = "") returns xml|mime:Entity[]|Error { + map headers = {}, string path = "") + returns xml|mime:Entity[]|Error { do { xml securedBody; - xml response; xml mimeEntity = body is xml ? body : check body[0].getXml(); lock { securedBody = body is xml ? check soap:applySecurityPolicies(self.inboundSecurity.clone(), body.clone()) : check soap:applySecurityPolicies(self.inboundSecurity.clone(), mimeEntity.clone()); } + xml response; if body is mime:Entity[] { body[0].setXml(securedBody); response = check soap:sendReceive(body, self.soapClient, action, headers, path); diff --git a/ballerina/modules/soap12/tests/http_soap_service.bal b/ballerina/modules/soap12/tests/http_soap_service.bal index 94a8782..5c7c6fd 100644 --- a/ballerina/modules/soap12/tests/http_soap_service.bal +++ b/ballerina/modules/soap12/tests/http_soap_service.bal @@ -34,28 +34,29 @@ service / on new http:Listener(9090) { } resource function post getSamePayload(http:Request request) returns http:Response|error { - http:Response response = new; xml payload = check request.getXmlPayload(); + http:Response response = new; response.setPayload(payload); return response; } resource function post getSecuredPayload(http:Request request) returns http:Response|error { - http:Response response = new; xml payload = check request.getXmlPayload(); - xml applyOutboundConfig = check soap:applyOutboundConfig({ - verificationKey: clientPublicKey, - signatureAlgorithm: soap:RSA_SHA256, - decryptionAlgorithm: soap:RSA_ECB, - decryptionKey: serverPrivateKey - }, payload); - - xml securedEnv = check soap:applySecurityPolicies({ - signatureAlgorithm: soap:RSA_SHA256, - encryptionAlgorithm: soap:RSA_ECB, - signatureKey: serverPrivateKey, - encryptionKey: clientPublicKey - }, applyOutboundConfig); + xml applyOutboundConfig = check soap:applyOutboundConfig( + { + verificationKey: clientPublicKey, + signatureAlgorithm: soap:RSA_SHA256, + decryptionAlgorithm: soap:RSA_ECB, + decryptionKey: serverPrivateKey + }, payload); + xml securedEnv = check soap:applySecurityPolicies( + { + signatureAlgorithm: soap:RSA_SHA256, + encryptionAlgorithm: soap:RSA_ECB, + signatureKey: serverPrivateKey, + encryptionKey: clientPublicKey + }, applyOutboundConfig); + http:Response response = new; response.setPayload(securedEnv); return response; } diff --git a/ballerina/modules/wssec/encryption.bal b/ballerina/modules/wssec/encryption.bal index a2cbc82..9a65007 100644 --- a/ballerina/modules/wssec/encryption.bal +++ b/ballerina/modules/wssec/encryption.bal @@ -24,18 +24,8 @@ isolated class Encryption { self.nativeEncryption = newEncryption(); } - isolated function encryptData(string dataString, EncryptionAlgorithm encryptionAlgorithm, - crypto:PublicKey|crypto:PrivateKey key) returns byte[]|Error { - byte[] data = dataString.toBytes(); - do { - return check crypto:encryptRsaEcb(data, key); - } on fail var e { - return error(e.message()); - } - } - public isolated function decryptData(byte[] cipherText, EncryptionAlgorithm encryptionAlgorithm, - crypto:PublicKey|crypto:PrivateKey key) returns byte[]|Error { + crypto:PublicKey|crypto:PrivateKey key) returns byte[]|Error { do { return check crypto:decryptRsaEcb(cipherText, key); } on fail var e { diff --git a/ballerina/modules/wssec/ws_security_methods.bal b/ballerina/modules/wssec/ws_security_methods.bal index 9d690e9..fbb4e47 100644 --- a/ballerina/modules/wssec/ws_security_methods.bal +++ b/ballerina/modules/wssec/ws_security_methods.bal @@ -136,7 +136,8 @@ public isolated function applyUsernameToken(xml envelope, *UsernameTokenConfig u # + envelope - The SOAP envelope # + symmetricBinding - The `SymmetricBindingConfig` record with the required parameters # + return - A `xml` type of SOAP envelope if the security binding is successfully added or else `wssec:Error` -public isolated function applySymmetricBinding(xml envelope, *SymmetricBindingConfig symmetricBinding) returns xml|Error { +public isolated function applySymmetricBinding(xml envelope, *SymmetricBindingConfig symmetricBinding) + returns xml|crypto:Error|Error { Document document = check new (envelope); WSSecurityHeader wsSecurityHeader = check addSecurityHeader(document); string securedEnvelope = envelope.toBalString(); @@ -153,8 +154,8 @@ public isolated function applySymmetricBinding(xml envelope, *SymmetricBindingCo } if encryptionAlgorithm is EncryptionAlgorithm { Encryption encryption = check new (); - byte[] encryptData = check encryption.encryptData((envelope//*).toString(), encryptionAlgorithm - , symmetricBinding.symmetricKey); + byte[] encryptData = check crypto:encryptRsaEcb((envelope//*).toString().toBytes(), + symmetricBinding.symmetricKey); Encryption encryptionResult = check addEncryption(encryption, encryptionAlgorithm, encryptData); WsSecurity wsSecurity = new; securedEnvelope = check wsSecurity.applyEncryptionOnlyPolicy(wsSecurityHeader, encryptionResult); @@ -169,7 +170,7 @@ public isolated function applySymmetricBinding(xml envelope, *SymmetricBindingCo # + envelope - The SOAP envelope # + asymmetricBinding - The `AsymmetricBindingConfig` record with the required parameters # + return - A `xml` type of SOAP envelope if the security binding is successfully added or else `wssec:Error` -public isolated function applyAsymmetricBinding(xml envelope, *AsymmetricBindingConfig asymmetricBinding) returns xml|Error { +public isolated function applyAsymmetricBinding(xml envelope, *AsymmetricBindingConfig asymmetricBinding) returns xml|crypto:Error|Error { Document document = check new (envelope); WSSecurityHeader wsSecurityHeader = check addSecurityHeader(document); string securedEnvelope = envelope.toBalString(); @@ -194,8 +195,7 @@ public isolated function applyAsymmetricBinding(xml envelope, *AsymmetricBinding if encryptionKey !is crypto:PublicKey { return error Error("Encryption key cannot be nil"); } - byte[] encryptData = check encryption.encryptData((envelope//*).toString(), encryptionAlgorithm, - encryptionKey); + byte[] encryptData = check crypto:encryptRsaEcb((envelope//*).toString().toBytes(), encryptionKey); Encryption encryptionResult = check addEncryption(encryption, encryptionAlgorithm, encryptData); WsSecurity wsSecurity = new; securedEnvelope = check wsSecurity.applyEncryptionOnlyPolicy(wsSecurityHeader, encryptionResult); diff --git a/ballerina/soap_utils.bal b/ballerina/soap_utils.bal index 182ae98..c26f089 100644 --- a/ballerina/soap_utils.bal +++ b/ballerina/soap_utils.bal @@ -42,7 +42,7 @@ public isolated function getReadOnlyClientConfig(ClientConfig original) returns } external; public isolated function applySecurityPolicies(wssec:InboundSecurityConfig|wssec:InboundSecurityConfig[] security, - xml envelope) returns xml|wssec:Error { + xml envelope) returns xml|crypto:Error|wssec:Error { if security is wssec:TimestampTokenConfig { return wssec:applyTimestampToken(envelope, security); } else if security is wssec:UsernameTokenConfig { From 14fc658f35b6f00b5b51101fa000b5681f6eecd2 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Mon, 16 Oct 2023 09:52:23 +0530 Subject: [PATCH 187/189] Add an empty line before the imports --- ballerina/configs.bal | 1 + ballerina/constants.bal | 1 + ballerina/modules/soap11/soap11.bal | 1 + ballerina/modules/soap11/tests/http_soap_service.bal | 1 + ballerina/modules/soap11/tests/soap11_client_test.bal | 1 + ballerina/modules/soap12/soap12.bal | 1 + ballerina/modules/soap12/tests/http_soap_service.bal | 1 + ballerina/modules/soap12/tests/soap12_client_test.bal | 1 + ballerina/modules/wssec/document.bal | 1 + ballerina/modules/wssec/encryption.bal | 1 + ballerina/modules/wssec/init.bal | 1 + ballerina/modules/wssec/records.bal | 1 + ballerina/modules/wssec/sec_header.bal | 1 + ballerina/modules/wssec/signature.bal | 1 + ballerina/modules/wssec/tests/test_utils.bal | 1 + ballerina/modules/wssec/tests/ws_security_tests.bal | 1 + ballerina/modules/wssec/ws_security.bal | 1 + ballerina/modules/wssec/ws_security_methods.bal | 1 + ballerina/soap_utils.bal | 1 + 19 files changed, 19 insertions(+) diff --git a/ballerina/configs.bal b/ballerina/configs.bal index fba33bf..22bc461 100644 --- a/ballerina/configs.bal +++ b/ballerina/configs.bal @@ -13,6 +13,7 @@ // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. + import soap.wssec; import ballerina/http; diff --git a/ballerina/constants.bal b/ballerina/constants.bal index 198ce0b..8c846c7 100644 --- a/ballerina/constants.bal +++ b/ballerina/constants.bal @@ -13,6 +13,7 @@ // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. + import soap.wssec; const SOAP_ACTION = "SOAPAction"; diff --git a/ballerina/modules/soap11/soap11.bal b/ballerina/modules/soap11/soap11.bal index 5b14194..366d205 100644 --- a/ballerina/modules/soap11/soap11.bal +++ b/ballerina/modules/soap11/soap11.bal @@ -13,6 +13,7 @@ // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. + import soap; import soap.wssec; diff --git a/ballerina/modules/soap11/tests/http_soap_service.bal b/ballerina/modules/soap11/tests/http_soap_service.bal index ed4e349..75c69d5 100644 --- a/ballerina/modules/soap11/tests/http_soap_service.bal +++ b/ballerina/modules/soap11/tests/http_soap_service.bal @@ -13,6 +13,7 @@ // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. + import ballerina/crypto; import ballerina/http; import ballerina/soap; diff --git a/ballerina/modules/soap11/tests/soap11_client_test.bal b/ballerina/modules/soap11/tests/soap11_client_test.bal index d44fe39..80f229a 100644 --- a/ballerina/modules/soap11/tests/soap11_client_test.bal +++ b/ballerina/modules/soap11/tests/soap11_client_test.bal @@ -13,6 +13,7 @@ // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. + import soap; import soap.wssec; diff --git a/ballerina/modules/soap12/soap12.bal b/ballerina/modules/soap12/soap12.bal index c7b0369..3146961 100644 --- a/ballerina/modules/soap12/soap12.bal +++ b/ballerina/modules/soap12/soap12.bal @@ -13,6 +13,7 @@ // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. + import soap; import soap.wssec; diff --git a/ballerina/modules/soap12/tests/http_soap_service.bal b/ballerina/modules/soap12/tests/http_soap_service.bal index 5c7c6fd..5acebab 100644 --- a/ballerina/modules/soap12/tests/http_soap_service.bal +++ b/ballerina/modules/soap12/tests/http_soap_service.bal @@ -13,6 +13,7 @@ // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. + import ballerina/crypto; import ballerina/http; import ballerina/soap; diff --git a/ballerina/modules/soap12/tests/soap12_client_test.bal b/ballerina/modules/soap12/tests/soap12_client_test.bal index 742a227..bdd81ef 100644 --- a/ballerina/modules/soap12/tests/soap12_client_test.bal +++ b/ballerina/modules/soap12/tests/soap12_client_test.bal @@ -13,6 +13,7 @@ // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. + import soap; import soap.wssec; diff --git a/ballerina/modules/wssec/document.bal b/ballerina/modules/wssec/document.bal index dc4fefb..d70dd38 100644 --- a/ballerina/modules/wssec/document.bal +++ b/ballerina/modules/wssec/document.bal @@ -13,6 +13,7 @@ // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. + import ballerina/jballerina.java; isolated class Document { diff --git a/ballerina/modules/wssec/encryption.bal b/ballerina/modules/wssec/encryption.bal index 9a65007..367647b 100644 --- a/ballerina/modules/wssec/encryption.bal +++ b/ballerina/modules/wssec/encryption.bal @@ -13,6 +13,7 @@ // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. + import ballerina/crypto; import ballerina/jballerina.java; diff --git a/ballerina/modules/wssec/init.bal b/ballerina/modules/wssec/init.bal index a58af80..9780582 100644 --- a/ballerina/modules/wssec/init.bal +++ b/ballerina/modules/wssec/init.bal @@ -13,6 +13,7 @@ // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. + import ballerina/jballerina.java; isolated function init() { diff --git a/ballerina/modules/wssec/records.bal b/ballerina/modules/wssec/records.bal index ba856f7..8d9a3be 100644 --- a/ballerina/modules/wssec/records.bal +++ b/ballerina/modules/wssec/records.bal @@ -13,6 +13,7 @@ // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. + import ballerina/crypto; # Union type of all the inbound web service security configurations. diff --git a/ballerina/modules/wssec/sec_header.bal b/ballerina/modules/wssec/sec_header.bal index 10aa1af..77137ab 100644 --- a/ballerina/modules/wssec/sec_header.bal +++ b/ballerina/modules/wssec/sec_header.bal @@ -13,6 +13,7 @@ // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. + import ballerina/jballerina.java; isolated class WSSecurityHeader { diff --git a/ballerina/modules/wssec/signature.bal b/ballerina/modules/wssec/signature.bal index 6de5eb8..fc7e5f1 100644 --- a/ballerina/modules/wssec/signature.bal +++ b/ballerina/modules/wssec/signature.bal @@ -13,6 +13,7 @@ // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. + import ballerina/crypto; import ballerina/jballerina.java; diff --git a/ballerina/modules/wssec/tests/test_utils.bal b/ballerina/modules/wssec/tests/test_utils.bal index cc39826..93eef26 100644 --- a/ballerina/modules/wssec/tests/test_utils.bal +++ b/ballerina/modules/wssec/tests/test_utils.bal @@ -13,6 +13,7 @@ // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. + import ballerina/test; import ballerina/crypto; diff --git a/ballerina/modules/wssec/tests/ws_security_tests.bal b/ballerina/modules/wssec/tests/ws_security_tests.bal index 2d1559a..76936d4 100644 --- a/ballerina/modules/wssec/tests/ws_security_tests.bal +++ b/ballerina/modules/wssec/tests/ws_security_tests.bal @@ -13,6 +13,7 @@ // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. + import ballerina/crypto; import ballerina/test; import ballerina/lang.regexp; diff --git a/ballerina/modules/wssec/ws_security.bal b/ballerina/modules/wssec/ws_security.bal index 6b2fbec..1b570db 100644 --- a/ballerina/modules/wssec/ws_security.bal +++ b/ballerina/modules/wssec/ws_security.bal @@ -13,6 +13,7 @@ // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. + import ballerina/jballerina.java; isolated class WsSecurity { diff --git a/ballerina/modules/wssec/ws_security_methods.bal b/ballerina/modules/wssec/ws_security_methods.bal index fbb4e47..3018c26 100644 --- a/ballerina/modules/wssec/ws_security_methods.bal +++ b/ballerina/modules/wssec/ws_security_methods.bal @@ -13,6 +13,7 @@ // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. + import ballerina/crypto; import ballerina/lang.regexp; diff --git a/ballerina/soap_utils.bal b/ballerina/soap_utils.bal index c26f089..944bbbc 100644 --- a/ballerina/soap_utils.bal +++ b/ballerina/soap_utils.bal @@ -13,6 +13,7 @@ // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. + import soap.wssec; import ballerina/crypto; From 97e1c39f705c9a366e74fa5acb57545ce08c585d Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Mon, 16 Oct 2023 10:08:25 +0530 Subject: [PATCH 188/189] Fix the errors to return cause --- ballerina/modules/soap11/error.bal | 1 + ballerina/modules/soap11/soap11.bal | 4 ++-- ballerina/modules/soap11/tests/soap11_client_test.bal | 2 +- ballerina/modules/soap12/error.bal | 1 + ballerina/modules/soap12/soap12.bal | 4 ++-- ballerina/modules/soap12/tests/soap12_client_test.bal | 2 +- ballerina/modules/wssec/encryption.bal | 2 +- ballerina/modules/wssec/signature.bal | 4 ++-- ballerina/modules/wssec/ws_security_methods.bal | 2 +- 9 files changed, 12 insertions(+), 10 deletions(-) diff --git a/ballerina/modules/soap11/error.bal b/ballerina/modules/soap11/error.bal index 60fa4ed..50d5fe4 100644 --- a/ballerina/modules/soap11/error.bal +++ b/ballerina/modules/soap11/error.bal @@ -19,4 +19,5 @@ public type Error distinct error; const SOAP_RESPONSE_ERROR = "Failed to create SOAP response."; const SOAP_CLIENT_ERROR = "Failed to initialize SOAP 1.1 client."; +const SOAP_ERROR = "Error occurred while executing the API"; const INVALID_OUTBOUND_SECURITY_ERROR = "Outbound security configurations do not match with the SOAP response."; diff --git a/ballerina/modules/soap11/soap11.bal b/ballerina/modules/soap11/soap11.bal index 366d205..33ea2ee 100644 --- a/ballerina/modules/soap11/soap11.bal +++ b/ballerina/modules/soap11/soap11.bal @@ -82,7 +82,7 @@ public isolated client class Client { return response.clone(); } } on fail var e { - return error Error(e.message()); + return error Error(SOAP_ERROR, e.cause()); } } @@ -108,7 +108,7 @@ public isolated client class Client { } return check soap:sendOnly(securedBody, self.soapClient, action, headers, path, false); } on fail var e { - return error Error(e.message()); + return error Error(SOAP_ERROR, e.cause()); } } } diff --git a/ballerina/modules/soap11/tests/soap11_client_test.bal b/ballerina/modules/soap11/tests/soap11_client_test.bal index 80f229a..37640a7 100644 --- a/ballerina/modules/soap11/tests/soap11_client_test.bal +++ b/ballerina/modules/soap11/tests/soap11_client_test.bal @@ -195,7 +195,7 @@ function testSendReceiveError() returns error? { `; xml|mime:Entity[]|Error response = soapClient->sendReceive(body, "http://tempuri.org/Add"); test:assertTrue(response is Error); - test:assertEquals((response).message(), SOAP_RESPONSE_ERROR); + test:assertEquals((response).message(), SOAP_ERROR); } @test:Config { diff --git a/ballerina/modules/soap12/error.bal b/ballerina/modules/soap12/error.bal index d19c1c1..55ce7c3 100644 --- a/ballerina/modules/soap12/error.bal +++ b/ballerina/modules/soap12/error.bal @@ -19,4 +19,5 @@ public type Error distinct error; const SOAP_RESPONSE_ERROR = "Failed to create SOAP response."; const SOAP_CLIENT_ERROR = "Failed to initialize SOAP 1.2 client."; +const SOAP_ERROR = "Failed to generate a response"; const INVALID_OUTBOUND_SECURITY_ERROR = "Outbound security configurations do not match with the SOAP response."; diff --git a/ballerina/modules/soap12/soap12.bal b/ballerina/modules/soap12/soap12.bal index 3146961..fe8706a 100644 --- a/ballerina/modules/soap12/soap12.bal +++ b/ballerina/modules/soap12/soap12.bal @@ -82,7 +82,7 @@ public isolated client class Client { return response.clone(); } } on fail var e { - return error Error(e.message()); + return error Error(SOAP_ERROR, e.cause()); } } @@ -112,7 +112,7 @@ public isolated client class Client { } return check soap:sendOnly(securedBody, self.soapClient, action, headers, path); } on fail var e { - return error Error(e.message()); + return error Error(SOAP_ERROR, e.cause()); } } } diff --git a/ballerina/modules/soap12/tests/soap12_client_test.bal b/ballerina/modules/soap12/tests/soap12_client_test.bal index bdd81ef..500e006 100644 --- a/ballerina/modules/soap12/tests/soap12_client_test.bal +++ b/ballerina/modules/soap12/tests/soap12_client_test.bal @@ -213,7 +213,7 @@ function testSendReceiveError() returns error? { `; xml|mime:Entity[]|Error response = soapClient->sendReceive(body, "http://tempuri.org/Add"); test:assertTrue(response is Error); - test:assertEquals((response).message(), SOAP_RESPONSE_ERROR); + test:assertEquals((response).message(), SOAP_ERROR); } @test:Config { diff --git a/ballerina/modules/wssec/encryption.bal b/ballerina/modules/wssec/encryption.bal index 367647b..85985b9 100644 --- a/ballerina/modules/wssec/encryption.bal +++ b/ballerina/modules/wssec/encryption.bal @@ -30,7 +30,7 @@ isolated class Encryption { do { return check crypto:decryptRsaEcb(cipherText, key); } on fail var e { - return error Error(e.message()); + return error Error("Error occurred while decrypting the data", e.cause()); } } diff --git a/ballerina/modules/wssec/signature.bal b/ballerina/modules/wssec/signature.bal index fc7e5f1..99d52be 100644 --- a/ballerina/modules/wssec/signature.bal +++ b/ballerina/modules/wssec/signature.bal @@ -44,7 +44,7 @@ isolated class Signature { } } } on fail var e { - return error Error(e.message()); + return error Error("Error occurred while signing the data", e.cause()); } } @@ -66,7 +66,7 @@ isolated class Signature { } } } on fail var e { - return error Error(e.message()); + return error Error("Error occurred while verifying the signature", e.cause()); } } diff --git a/ballerina/modules/wssec/ws_security_methods.bal b/ballerina/modules/wssec/ws_security_methods.bal index 3018c26..c09bdc9 100644 --- a/ballerina/modules/wssec/ws_security_methods.bal +++ b/ballerina/modules/wssec/ws_security_methods.bal @@ -71,7 +71,7 @@ isolated function applyEncryptedKey(string envelopeString, crypto:PrivateKey sym } return securedEnvelope; } on fail var e { - return error Error(e.message()); + return error Error("Error occurred while applying the encrypted key to the envelope", e.cause()); } } From af0ac206c57b60ec11fc743fbf0e3da140abc700 Mon Sep 17 00:00:00 2001 From: Nuvindu Date: Mon, 16 Oct 2023 10:13:20 +0530 Subject: [PATCH 189/189] Fix removing unnecessary methods --- ballerina/modules/wssec/encryption.bal | 10 -------- .../modules/wssec/tests/ws_security_tests.bal | 24 +++++++++---------- .../modules/wssec/ws_security_methods.bal | 6 ----- ballerina/soap_utils.bal | 2 +- 4 files changed, 13 insertions(+), 29 deletions(-) diff --git a/ballerina/modules/wssec/encryption.bal b/ballerina/modules/wssec/encryption.bal index 85985b9..7246866 100644 --- a/ballerina/modules/wssec/encryption.bal +++ b/ballerina/modules/wssec/encryption.bal @@ -14,7 +14,6 @@ // specific language governing permissions and limitations // under the License. -import ballerina/crypto; import ballerina/jballerina.java; isolated class Encryption { @@ -25,15 +24,6 @@ isolated class Encryption { self.nativeEncryption = newEncryption(); } - public isolated function decryptData(byte[] cipherText, EncryptionAlgorithm encryptionAlgorithm, - crypto:PublicKey|crypto:PrivateKey key) returns byte[]|Error { - do { - return check crypto:decryptRsaEcb(cipherText, key); - } on fail var e { - return error Error("Error occurred while decrypting the data", e.cause()); - } - } - public isolated function setEncryptionAlgorithm(string encryptionAlgorithm) = @java:Method { 'class: "org.wssec.Encryption" } external; diff --git a/ballerina/modules/wssec/tests/ws_security_tests.bal b/ballerina/modules/wssec/tests/ws_security_tests.bal index 76936d4..ffd3145 100644 --- a/ballerina/modules/wssec/tests/ws_security_tests.bal +++ b/ballerina/modules/wssec/tests/ws_security_tests.bal @@ -243,7 +243,7 @@ function testSymmetricBindingPolicyEncryptionOnly() returns error? { string envelopeString = securedEnvelope.toString(); byte[] encData = check getEncryptedData(securedEnvelope); - byte[] decryptDataResult = check decryptData(encData, RSA_ECB, publicKey); + byte[] decryptDataResult = check crypto:decryptRsaEcb(encData, publicKey); test:assertEquals((envelope//*).toString(), check string:fromBytes(decryptDataResult)); assertEncryptedSymmetricKey(envelopeString); @@ -276,7 +276,7 @@ function testSymmetricBindingWithSignatureAndEncryption() returns error? { test:assertTrue(validity); byte[] encData = check getEncryptedData(securedEnvelope); - byte[] decryptDataResult = check decryptData(encData, RSA_ECB, publicKey); + byte[] decryptDataResult = check crypto:decryptRsaEcb(encData, publicKey); test:assertEquals((envelope//*).toString(), check string:fromBytes(decryptDataResult)); assertEncryptedSymmetricKey(envelopeString); @@ -312,7 +312,7 @@ function testSymmetricBindingPolicyWithX509SignatureAndEncryption() returns erro test:assertTrue(validity); byte[] encData = check getEncryptedData(securedEnvelope); - byte[] decryptDataResult = check decryptData(encData, RSA_ECB, publicKey); + byte[] decryptDataResult = check crypto:decryptRsaEcb(encData, publicKey); test:assertEquals((envelope//*).toString(), check string:fromBytes(decryptDataResult)); assertEncryptedSymmetricKey(envelopeString); @@ -354,7 +354,7 @@ function testUsernameTokenWithSymmetricBinding() returns error? { test:assertTrue(validity); byte[] encData = check getEncryptedData(securedEnvelope); - byte[] decryptDataResult = check decryptData(encData, RSA_ECB, publicKey); + byte[] decryptDataResult = check crypto:decryptRsaEcb(encData, publicKey); test:assertEquals((envelope//*).toString(), check string:fromBytes(decryptDataResult)); assertEncryptedSymmetricKey(envelopeString); @@ -412,7 +412,7 @@ function testUsernameTokenTimestampWithSymmetricBindingAndX509Token() returns er test:assertTrue(validity); byte[] encData = check getEncryptedData(securedEnvelope); - byte[] decryptDataResult = check decryptData(encData, RSA_ECB, publicKey); + byte[] decryptDataResult = check crypto:decryptRsaEcb(encData, publicKey); test:assertEquals((envelope//*).toString(), check string:fromBytes(decryptDataResult)); assertEncryptedSymmetricKey(envelopeString); @@ -465,7 +465,7 @@ function testSymmetricBindingWithOutboundConfig() returns error? { crypto:PrivateKey|crypto:PublicKey? privateKey = outboundConfig.decryptionKey; if privateKey is crypto:PrivateKey|crypto:PublicKey { byte[] encData = check getEncryptedData(securedEnvelope); - byte[] decryptDataResult = check decryptData(encData, RSA_ECB, privateKey); + byte[] decryptDataResult = check crypto:decryptRsaEcb(encData, privateKey); string decryptedBody = "" + check string:fromBytes(decryptDataResult) + ""; envelopeString = regexp:replace(re `.*`, envelopeString, decryptedBody); securedEnvelope = check xml:fromString(envelopeString); @@ -548,7 +548,7 @@ function testAsymmetricBindingWithEncryption() returns error? { string envelopeString = securedEnvelope.toString(); byte[] encData = check getEncryptedData(securedEnvelope); - byte[] decryptDataResult = check decryptData(encData, RSA_ECB, serverPrivateKey); + byte[] decryptDataResult = check crypto:decryptRsaEcb(encData, serverPrivateKey); test:assertEquals(check string:fromBytes(decryptDataResult), (envelope//*).toString()); assertEncryptedPart(envelopeString); @@ -580,7 +580,7 @@ function testAsymmetricBindingWithSignatureAndEncryption() returns error? { test:assertTrue(validity); byte[] encData = check getEncryptedData(securedEnvelope); - byte[] decryptDataResult = check decryptData(encData, RSA_ECB, serverPrivateKey); + byte[] decryptDataResult = check crypto:decryptRsaEcb(encData, serverPrivateKey); test:assertEquals(check string:fromBytes(decryptDataResult), (envelope//*).toString()); assertSignatureWithoutX509(envelopeString); @@ -613,7 +613,7 @@ function testAsymmetricBindingWithX509SignatureAndEncryption() returns error? { test:assertTrue(validity); byte[] encData = check getEncryptedData(securedEnvelope); - byte[] decryptDataResult = check decryptData(encData, RSA_ECB, serverPrivateKey); + byte[] decryptDataResult = check crypto:decryptRsaEcb(encData, serverPrivateKey); test:assertEquals((envelope//*).toString(), check string:fromBytes(decryptDataResult)); assertSignatureWithX509(envelopeString); @@ -653,7 +653,7 @@ function testUsernameTokenWithAsymmetricBindingAndX509() returns error? { test:assertTrue(validity); byte[] encData = check getEncryptedData(securedEnvelope); - byte[] decryptDataResult = check decryptData(encData, RSA_ECB, serverPrivateKey); + byte[] decryptDataResult = check crypto:decryptRsaEcb(encData, serverPrivateKey); test:assertEquals((envelope//*).toString(), check string:fromBytes(decryptDataResult)); assertUsernameToken(envelopeString, DIGEST); @@ -695,7 +695,7 @@ function testUsernameTokenTimestampWithAsymmetricBindingAndX509() returns error? test:assertTrue(validity); byte[] encData = check getEncryptedData(securedEnvelope); - byte[] decryptDataResult = check decryptData(encData, RSA_ECB, serverPrivateKey); + byte[] decryptDataResult = check crypto:decryptRsaEcb(encData, serverPrivateKey); test:assertEquals((envelope//*).toString(), check string:fromBytes(decryptDataResult)); assertUsernameToken(envelopeString, DIGEST); @@ -734,7 +734,7 @@ function testAsymmetricBindingWithOutboundConfig() returns error? { crypto:PrivateKey|crypto:PublicKey? privateKey = outboundConfig.decryptionKey; if privateKey is crypto:PrivateKey|crypto:PublicKey { byte[] encData = check getEncryptedData(securedEnvelope); - byte[] decryptDataResult = check decryptData(encData, RSA_ECB, privateKey); + byte[] decryptDataResult = check crypto:decryptRsaEcb(encData, privateKey); string decryptedBody = "" + check string:fromBytes(decryptDataResult) + ""; envelopeString = regexp:replace(re `.*`, envelopeString, decryptedBody); securedEnvelope = check xml:fromString(envelopeString); diff --git a/ballerina/modules/wssec/ws_security_methods.bal b/ballerina/modules/wssec/ws_security_methods.bal index c09bdc9..9e328d0 100644 --- a/ballerina/modules/wssec/ws_security_methods.bal +++ b/ballerina/modules/wssec/ws_security_methods.bal @@ -26,12 +26,6 @@ isolated function addSecurityHeader(Document document) returns WSSecurityHeader| return insertHeader ?: wsSecHeader; } -public isolated function decryptData(byte[] cipherText, EncryptionAlgorithm encryptionAlgorithm, - crypto:PublicKey|crypto:PrivateKey key) returns byte[]|Error { - Encryption encrypt = check new (); - return encrypt.decryptData(cipherText, encryptionAlgorithm, key); -} - public isolated function verifyData(byte[] data, byte[] signature, crypto:PublicKey publicKey, SignatureAlgorithm signatureAlgorithm) returns Error? { Signature sign = check new (); diff --git a/ballerina/soap_utils.bal b/ballerina/soap_utils.bal index 944bbbc..ae2bc99 100644 --- a/ballerina/soap_utils.bal +++ b/ballerina/soap_utils.bal @@ -73,7 +73,7 @@ public isolated function applyOutboundConfig(wssec:OutboundSecurityConfig outbou crypto:PrivateKey|crypto:PublicKey? clientPrivateKey = outboundSecurity.decryptionKey; if clientPrivateKey is crypto:PrivateKey|crypto:PublicKey { byte[] encData = check wssec:getEncryptedData(soapEnvelope); - byte[] decryptDataResult = check wssec:decryptData(encData, encryptionAlgorithm, clientPrivateKey); + byte[] decryptDataResult = check crypto:decryptRsaEcb(encData, clientPrivateKey); string decryptedBody = "" + check string:fromBytes(decryptDataResult) + ""; string decryptedEnv = regexp:replace(re `.*`, soapEnvelope.toString(), decryptedBody);