From 19a394e3c70ea9a59afc78d0e04cbfbc9e44eabb Mon Sep 17 00:00:00 2001 From: Savindu Dimal Date: Wed, 28 Feb 2024 16:51:10 +0530 Subject: [PATCH 1/2] Add tests for mutual ssl certificate chain validation --- ...SSLCertificateChainValidationTestCase.java | 265 ++++++++++++++++++ .../applicationSharing/deployment.toml | 5 +- .../mutualssl/cert_chain_client.jks | Bin 0 -> 5278 bytes .../mutualssl/cert_chain_root.cer | 23 ++ .../mutualssl/cert_chain_root.jks | Bin 0 -> 2874 bytes .../mutualssl/chain-cert-validation.jks | Bin 0 -> 10067 bytes .../src/test/resources/testng.xml | 1 + 7 files changed, 293 insertions(+), 1 deletion(-) create mode 100644 modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/api/lifecycle/APISecurityMutualSSLCertificateChainValidationTestCase.java create mode 100644 modules/integration/tests-integration/tests-backend/src/test/resources/artifacts/AM/lifecycletest/mutualssl/cert_chain_client.jks create mode 100644 modules/integration/tests-integration/tests-backend/src/test/resources/artifacts/AM/lifecycletest/mutualssl/cert_chain_root.cer create mode 100644 modules/integration/tests-integration/tests-backend/src/test/resources/artifacts/AM/lifecycletest/mutualssl/cert_chain_root.jks create mode 100644 modules/integration/tests-integration/tests-backend/src/test/resources/artifacts/AM/lifecycletest/mutualssl/chain-cert-validation.jks diff --git a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/api/lifecycle/APISecurityMutualSSLCertificateChainValidationTestCase.java b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/api/lifecycle/APISecurityMutualSSLCertificateChainValidationTestCase.java new file mode 100644 index 0000000000..ff50343ff6 --- /dev/null +++ b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/api/lifecycle/APISecurityMutualSSLCertificateChainValidationTestCase.java @@ -0,0 +1,265 @@ +/* + * Copyright (c) 2024, 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 + * 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.wso2.am.integration.tests.api.lifecycle; + +import org.apache.commons.httpclient.HttpStatus; +import org.json.JSONException; +import org.testng.Assert; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Factory; +import org.testng.annotations.Test; +import org.wso2.am.integration.clients.publisher.api.ApiException; +import org.wso2.am.integration.clients.publisher.api.ApiResponse; +import org.wso2.am.integration.clients.publisher.api.v1.dto.APIDTO; +import org.wso2.am.integration.clients.publisher.api.v1.dto.APIOperationsDTO; +import org.wso2.am.integration.clients.store.api.v1.dto.ApplicationDTO; +import org.wso2.am.integration.clients.store.api.v1.dto.ApplicationKeyDTO; +import org.wso2.am.integration.clients.store.api.v1.dto.ApplicationKeyGenerateRequestDTO; +import org.wso2.am.integration.test.utils.APIManagerIntegrationTestException; +import org.wso2.am.integration.test.utils.base.APIMIntegrationConstants; +import org.wso2.am.integration.test.utils.bean.APILifeCycleAction; +import org.wso2.am.integration.test.utils.bean.APIRequest; +import org.wso2.am.integration.test.utils.http.HTTPSClientUtils; +import org.wso2.am.integration.test.utils.http.HttpRequestUtil; +import org.wso2.carbon.automation.engine.annotations.ExecutionEnvironment; +import org.wso2.carbon.automation.engine.annotations.SetEnvironment; +import org.wso2.carbon.automation.engine.context.TestUserMode; +import org.wso2.carbon.automation.test.utils.http.client.HttpResponse; +import org.wso2.carbon.integration.common.utils.exceptions.AutomationUtilException; +import org.wso2.carbon.um.ws.api.stub.ClaimValue; +import org.wso2.carbon.um.ws.api.stub.RemoteUserStoreManagerServiceUserStoreExceptionException; +import org.wso2.carbon.user.core.UserStoreException; + +import javax.xml.xpath.XPathExpressionException; +import java.io.File; +import java.io.IOException; +import java.net.URL; +import java.rmi.RemoteException; +import java.security.KeyManagementException; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.UnrecoverableKeyException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@SetEnvironment(executionEnvironments = { ExecutionEnvironment.STANDALONE }) +public class APISecurityMutualSSLCertificateChainValidationTestCase extends APIManagerLifecycleBaseTest { + + private final String rootCertAPI = "rootCertAPI"; + private final String API_END_POINT_METHOD = "/customers/123"; + private final String API_VERSION_1_0_0 = "1.0.0"; + private final String APPLICATION_NAME = "APISecurityMutualSSLCertificateChainValidationTestCase"; + private String accessToken; + private final String API_END_POINT_POSTFIX_URL = "jaxrs_basic/services/customers/customerservice/"; + private String apiEndPointUrl; + private String applicationId; + private String apiId1; + String users[] = { "apisecUser", "apisecUser2@wso2.com", "apisecUser2@abc.com" }; + String endUserPassword = "password@123"; + + @DataProvider + public static Object[][] userModeDataProvider() { + + return new Object[][] { new Object[] { TestUserMode.SUPER_TENANT_ADMIN }, + new Object[] { TestUserMode.TENANT_ADMIN } }; + } + + private void createUser() + throws RemoteException, RemoteUserStoreManagerServiceUserStoreExceptionException, UserStoreException { + + for (String user : users) { + remoteUserStoreManagerServiceClient.addUser(user, endUserPassword, new String[] {}, new ClaimValue[] {}, + "default", false); + } + } + + @Factory(dataProvider = "userModeDataProvider") + public APISecurityMutualSSLCertificateChainValidationTestCase(TestUserMode userMode) { + + this.userMode = userMode; + } + + @BeforeClass(alwaysRun = true) + public void initialize() throws APIManagerIntegrationTestException, IOException, ApiException, + org.wso2.am.integration.clients.store.api.ApiException, XPathExpressionException, AutomationUtilException, + InterruptedException, JSONException, RemoteUserStoreManagerServiceUserStoreExceptionException, + UserStoreException { + + super.init(userMode); + createUser(); + apiEndPointUrl = backEndServerUrl.getWebAppURLHttp() + API_END_POINT_POSTFIX_URL; + + APIRequest apiRequest1 = new APIRequest(rootCertAPI, rootCertAPI, new URL(apiEndPointUrl)); + apiRequest1.setVersion(API_VERSION_1_0_0); + apiRequest1.setTiersCollection(APIMIntegrationConstants.API_TIER.UNLIMITED); + apiRequest1.setTier(APIMIntegrationConstants.API_TIER.UNLIMITED); + apiRequest1.setTags(API_TAGS); + apiRequest1.setVisibility(APIDTO.VisibilityEnum.PUBLIC.getValue()); + apiRequest1.setProvider(user.getUserName()); + APIOperationsDTO apiOperationsDTO1 = new APIOperationsDTO(); + apiOperationsDTO1.setVerb("GET"); + apiOperationsDTO1.setTarget("/customers/{id}"); + apiOperationsDTO1.setAuthType("Application & Application User"); + apiOperationsDTO1.setThrottlingPolicy("Unlimited"); + + List operationsDTOS = new ArrayList<>(); + operationsDTOS.add(apiOperationsDTO1); + apiRequest1.setOperationsDTOS(operationsDTOS); + + List securitySchemes = new ArrayList<>(); + securitySchemes.add("mutualssl"); + securitySchemes.add("mutualssl_mandatory"); + apiRequest1.setSecurityScheme(securitySchemes); + apiRequest1.setDefault_version("true"); + apiRequest1.setHttps_checked("https"); + apiRequest1.setHttp_checked(null); + apiRequest1.setDefault_version_checked("true"); + HttpResponse response1 = restAPIPublisher.addAPI(apiRequest1); + apiId1 = response1.getData(); + + String certOne = getAMResourceLocation() + File.separator + "lifecycletest" + File.separator + "mutualssl" + + File.separator + "cert_chain_root.cer"; + restAPIPublisher.uploadCertificate(new File(certOne), "example", apiId1, + APIMIntegrationConstants.API_TIER.UNLIMITED); + } + + @Test(description = "This test case tests the behaviour of internal Key token on Created API with authentication " + + "types") + public void testCreateAndDeployRevisionWithInternalKeyTesting() + throws JSONException, ApiException, XPathExpressionException, APIManagerIntegrationTestException, + IOException, org.wso2.am.integration.clients.store.api.ApiException, InterruptedException { + + createAPIRevisionAndDeployUsingRest(apiId1, restAPIPublisher); + APIDTO api1 = restAPIPublisher.getAPIByID(apiId1); + waitForAPIDeploymentSync(api1.getProvider(), api1.getName(), api1.getVersion(), + APIMIntegrationConstants.IS_API_EXISTS); + ApiResponse keyDTOApiResponse1 = restAPIPublisher.generateInternalApiKey( + apiId1); + Assert.assertEquals(keyDTOApiResponse1.getStatusCode(), 200); + HttpResponse httpResponse1 = invokeApiWithInternalKey(rootCertAPI, API_VERSION_1_0_0, API_END_POINT_METHOD, + keyDTOApiResponse1.getData().getApikey()); + Assert.assertEquals(httpResponse1.getResponseCode(), 200); + restAPIPublisher.changeAPILifeCycleStatus(apiId1, APILifeCycleAction.PUBLISH.getAction()); + + HttpResponse applicationResponse = restAPIStore.createApplication(APPLICATION_NAME, "Test Application", + APIMIntegrationConstants.APPLICATION_TIER.UNLIMITED, ApplicationDTO.TokenTypeEnum.JWT); + + applicationId = applicationResponse.getData(); + ArrayList grantTypes = new ArrayList(); + grantTypes.add(APIMIntegrationConstants.GRANT_TYPE.PASSWORD); + grantTypes.add(APIMIntegrationConstants.GRANT_TYPE.CLIENT_CREDENTIAL); + ApplicationKeyDTO applicationKeyDTO = restAPIStore.generateKeys(applicationId, "36000", "", + ApplicationKeyGenerateRequestDTO.KeyTypeEnum.PRODUCTION, null, grantTypes); + //get access token + accessToken = applicationKeyDTO.getToken().getAccessToken(); + + HttpResponse httpResponseAfterPublish = invokeApiWithInternalKey(rootCertAPI, API_VERSION_1_0_0, + API_END_POINT_METHOD, keyDTOApiResponse1.getData().getApikey()); + Assert.assertEquals(httpResponseAfterPublish.getResponseCode(), 200); + + // wait until certificates loaded + Thread.sleep(120000); + } + + private HttpResponse invokeApiWithInternalKey(String context, String version, String resource, String internalKey) + throws XPathExpressionException, IOException { + + Map requestHeaders = new HashMap<>(); + requestHeaders.put("accept", "application/json"); + requestHeaders.put("Internal-Key", internalKey); + return HttpRequestUtil.doGet(getAPIInvocationURLHttps(context, version) + resource, requestHeaders); + } + + @Test(description = "Invoke mutual SSL only API with not supported certificate", dependsOnMethods = "testCreateAndDeployRevisionWithInternalKeyTesting") + public void testAPIInvocationWithMutualSSLOnlyAPINegative() + throws IOException, XPathExpressionException, NoSuchAlgorithmException, KeyStoreException, + KeyManagementException, UnrecoverableKeyException { + + Map requestHeaders = new HashMap<>(); + requestHeaders.put("accept", "text/xml"); + HttpResponse response = HTTPSClientUtils.doMutulSSLGet( + getAMResourceLocation() + File.separator + "lifecycletest" + File.separator + "mutualssl" + + File.separator + "test.jks", + getAPIInvocationURLHttps(rootCertAPI, API_VERSION_1_0_0) + API_END_POINT_METHOD, requestHeaders); + HttpResponse defaultResponse = HTTPSClientUtils.doMutulSSLGet( + getAMResourceLocation() + File.separator + "lifecycletest" + File.separator + "mutualssl" + + File.separator + "test.jks", getAPIInvocationURLHttps(rootCertAPI) + API_END_POINT_METHOD, + requestHeaders); + Assert.assertEquals(response.getResponseCode(), HttpStatus.SC_UNAUTHORIZED); + Assert.assertEquals(defaultResponse.getResponseCode(), HttpStatus.SC_UNAUTHORIZED); + } + + @Test(description = "API invocation with mutual ssl mandatory", dependsOnMethods = "testAPIInvocationWithMutualSSLOnlyAPINegative") + public void testAPIInvocationWithMutualSSLMandatory() + throws IOException, XPathExpressionException, NoSuchAlgorithmException, KeyStoreException, + KeyManagementException, UnrecoverableKeyException { + + Map requestHeaders = new HashMap<>(); + requestHeaders.put("accept", "text/xml"); + requestHeaders.put("Authorization", "Bearer " + accessToken); + + // Using root certificate + HttpResponse rootCertResponse = HTTPSClientUtils.doMutulSSLGet( + getAMResourceLocation() + File.separator + "lifecycletest" + File.separator + "mutualssl" + + File.separator + "cert_chain_root.jks", + getAPIInvocationURLHttps(rootCertAPI, API_VERSION_1_0_0) + API_END_POINT_METHOD, requestHeaders); + Assert.assertEquals(rootCertResponse.getResponseCode(), HttpStatus.SC_OK, "Mutual SSL Authentication has not succeed"); + + // Using client certificate with certificate chain + HttpResponse clientCertResponse = HTTPSClientUtils.doMutulSSLGet( + getAMResourceLocation() + File.separator + "lifecycletest" + File.separator + "mutualssl" + + File.separator + "cert_chain_client.jks", + getAPIInvocationURLHttps(rootCertAPI, API_VERSION_1_0_0) + API_END_POINT_METHOD, requestHeaders); + Assert.assertEquals(clientCertResponse.getResponseCode(), HttpStatus.SC_OK, "Mutual SSL Authentication has not succeed"); + + // For default API version with root certificate + HttpResponse defaultRootCertResponse = HTTPSClientUtils.doMutulSSLGet( + getAMResourceLocation() + File.separator + "lifecycletest" + File.separator + "mutualssl" + + File.separator + "cert_chain_root.jks", + getAPIInvocationURLHttps(rootCertAPI) + API_END_POINT_METHOD, requestHeaders); + Assert.assertEquals(defaultRootCertResponse.getResponseCode(), HttpStatus.SC_OK, + "Mutual SSL Authentication has not succeed"); + + // For default API version with client certificate + HttpResponse defaultClientCertResponse = HTTPSClientUtils.doMutulSSLGet( + getAMResourceLocation() + File.separator + "lifecycletest" + File.separator + "mutualssl" + + File.separator + "cert_chain_client.jks", + getAPIInvocationURLHttps(rootCertAPI) + API_END_POINT_METHOD, requestHeaders); + Assert.assertEquals(defaultClientCertResponse.getResponseCode(), HttpStatus.SC_OK, + "Mutual SSL Authentication has not succeed"); + } + + @AfterClass(alwaysRun = true) + public void cleanUpArtifacts() throws Exception { + + restAPIStore.deleteApplication(applicationId); + restAPIPublisher.deleteAPI(apiId1); + removeUsers(); + } + + private void removeUsers() throws RemoteException, RemoteUserStoreManagerServiceUserStoreExceptionException { + + for (String user : users) { + remoteUserStoreManagerServiceClient.removeUser(user); + } + } +} diff --git a/modules/integration/tests-integration/tests-backend/src/test/resources/artifacts/AM/configFiles/applicationSharing/deployment.toml b/modules/integration/tests-integration/tests-backend/src/test/resources/artifacts/AM/configFiles/applicationSharing/deployment.toml index 064ae0b522..79df12cfdb 100755 --- a/modules/integration/tests-integration/tests-backend/src/test/resources/artifacts/AM/configFiles/applicationSharing/deployment.toml +++ b/modules/integration/tests-integration/tests-backend/src/test/resources/artifacts/AM/configFiles/applicationSharing/deployment.toml @@ -106,4 +106,7 @@ password = "${admin.password}" [apim.sync_runtime_artifacts.gateway.skip_list] apis = ["admin--git2231head_v1.0.0.xml","admin--PizzaShackAPI_v1.0.0.xml","admin--ScriptMediatorAPI_v1.0.xml", -"APIThrottleBackendAPI.xml","BackEndSecurity.xml","DigestAuth_API.xml","git2231.xml","HttpPATCHSupport_API.xml","JWKS-Backend.xml","JWTBackendAPI.xml","multiVSR_v1.0.0.xml","Response_API_1.xml","Response_API_2.xml","Response_Custom_API.xml","Response_Error_API.xml","Response_Loc_API.xml","SpecialCRN_v1.0.0.xml","status_code_204_API.xml","stockquote.xml","XML_API.xml","Version1.xml","Version2.xml","schemaValidationAPI.xml"] \ No newline at end of file +"APIThrottleBackendAPI.xml","BackEndSecurity.xml","DigestAuth_API.xml","git2231.xml","HttpPATCHSupport_API.xml","JWKS-Backend.xml","JWTBackendAPI.xml","multiVSR_v1.0.0.xml","Response_API_1.xml","Response_API_2.xml","Response_Custom_API.xml","Response_Error_API.xml","Response_Loc_API.xml","SpecialCRN_v1.0.0.xml","status_code_204_API.xml","stockquote.xml","XML_API.xml","Version1.xml","Version2.xml","schemaValidationAPI.xml"] + +[apimgt.mutual_ssl] +enable_certificate_chain_validation = true diff --git a/modules/integration/tests-integration/tests-backend/src/test/resources/artifacts/AM/lifecycletest/mutualssl/cert_chain_client.jks b/modules/integration/tests-integration/tests-backend/src/test/resources/artifacts/AM/lifecycletest/mutualssl/cert_chain_client.jks new file mode 100644 index 0000000000000000000000000000000000000000..414c51b392acaec2d2be9597b70ce01c9f968f7b GIT binary patch literal 5278 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 literal 0 HcmV?d00001 diff --git a/modules/integration/tests-integration/tests-backend/src/test/resources/artifacts/AM/lifecycletest/mutualssl/chain-cert-validation.jks b/modules/integration/tests-integration/tests-backend/src/test/resources/artifacts/AM/lifecycletest/mutualssl/chain-cert-validation.jks new file mode 100644 index 0000000000000000000000000000000000000000..2595e07e8a18527a092d06696a7fec357df1b5ea GIT binary patch literal 10067 zcmeI1XH-+$w#SnYdhgW$5*2+VbU-+|@FJZZZC$*sM&s5b$AJI8h%|zIHeG>)LC#R&G)0Vr~*Bu`rH#`XQ$k!6rothyGC6v zszwQDO{?_GBaFzCZ##QIObhfnrR|L-@O&3!1U^hso z1gTkR`sAt8ud+50ETkkoM2*1%VQkuQFy-lY97KMueMz-%4x%~8(Mtjm?Yh7)=d!xg z^Pcp`=W65KV4f#K=+_VB0YHxwoD_^9!;(M8=P7l%%KbHAvpeWCzU;I<-+dpg=fo(k zsg_VEX5OjHcxP%us3fTix}cfS?qezfZoH8mPee67<-7X!rUCPYplfddQY~<5zL0oa z-z^sJKBJpv>v{f5n6$oUbM%kHV`zEe0(b7J58$n~vW;N%7RwDFx5%E50RwIU?na4= zsSR`^);};ltj>=!c}YkUUys zBtn#Q7Zn~55tLpgQ8_S@M0RK_D8b@hHRU~w_G2}|R?8oG$sCFHN{`6u)gVZ*>SN!A zHIF-v1|ELx^At4Pd@ zVolGnu`OT7TB&{UOg*|ql{{A%AnP(qxbxr?&efQ6scV0l+=c(;B&U9Dq+EATg$FM@ zKO59dCuc&pyMr+>RcCuP2>KGjw_$IYS;lL;8#Ig8$9rC(7M49m{p!#}@Jww3@s^O> zO9n;E8tXZ1ZW5ht{ZvV_ow2&*Yws{GPSrCRm%i}O_ZkuuYhk#;k2d}8$a1ouEFcDZ z?GTE)1XZWyI%DShaqDDnVqkf$#7kQTtH_OM`<5>5S zk12O&#+Ed5qkB^kNFOGC7)C!{B+2WhGvArCZ@rV=KH=F0De11`bIyKZg@-Cs^deGJ zL;NXoA0Wna=&HIX+4oP`1kncR?#EQuXd-YBXrY_;{Wrz8-WeCZ7ZWRexv2v>56&Ep zcUB7$0ejNE1z^PoY zB~Gy&IE)wvpDRKo;+Pl+B*X^5T;YT;d>kx&Fb*Y1Lmf^6Bl;!4Bf>^lBW-N|665|| zOz?Lx;a_4F8044tv507Yle!&Uylg%0+uArHyli0*T4Dhqn1Fx?94;gP6F0dE#oz*h zaJZO&xUjeh%<^osY-%c~o(yR(WOc3l@0>1;3o z`DG=?RMX|SJ}T*G@pa~T5qs17%ZH$WW@XaoaWw;4u$g?IV7dxjHzHr6pHI#ibnjTQ zep&*#eFk1V=>B?aE1U*8dNt&tpPaRV+1IEo%3{vZNUyvHU3yN&zJ@oFeM7}AL zI@~>r^^FK_vIm+fk}1R8A~MzN)%NH$3~{ttsP;kvrA48b*@}W2A^>rWc%0;M0ZJ=x-eyBF$EYW zEFRGFjIrX4w$O5Y-qu$6q?^Lb!(-o0C-!kuB|85!fQSY`t^%#$gUcDmSbw_Ek^2I8 zvT65gpF0Hazl*0L6#RnARKOe)cbJ2cH{<-Sp7{U9f1LCSm6s?TA_-ZuR{ z?;VA&*BUwAA`$jR3f*jEMf)7RmKduAjlQ$dMJY0e<+J|g4(auvB1_?3L(&T901gt{ z@x&6V^xg3UKiJQ_eDU!x{`Elw{JE^i9f^BOc+1+F-<+&?3oj5k%()#?SPYL_SgI`* zW>^j15|d)w%nSmC0`zETnYz7WUj?xK%h)?J3NgG=w);^MH97~z(E)B#yPy9C``^zB ze+c^?B_YuU#(FG|E4hIPyto^$1;@F+eXv!^N7pA#osKzK9ZVKP`!k!0KF+}K zSDovul!Eaq9*x(`LcP}C`+QNjR;BcVX&o5szwTW+sP0UGsiM`;a2__Uv$uQ*WfG{8qqTCF)2xWQG_p#-BdA$+narZ1)PoaZ%F zbYJb`w1Z7uv@r)wq)M$u*S3#GvV&*_vSXIVjZIZdW=RP#D~(ZhV}v1Ip^sj$puhhO z`_(J#m#(ny{WJE61MfrlMQ}13oA+df&=vN4M+*NRu)iwqBEMpPRrZD9@L$9KyZrOd zaDQ*%OaG`c>a6-(RKz}pW|B?j9+|)_ITl_RlY{Eyrx5ZG(eEWw99A;NYedo}7kei^rSNcp z!i9)MnaVQ`5~MgFM?u3&F^qCswnRTuu2;~_n?4#WAojv!NAL0yRfekYr7F_j5?-@C zmsf83+?!0?w^fl;)Bd*5?IOZ!o+BtTxQt38q<)vnBRT4{L-&C;dBFycr1AZA#9~*B z1S!)wL2siEds~#FQ)ydt=(!ORn*Tr{#8>@T0WlPhN?8`P_wKACwIIJZeVCQ9t&9Di z!u|KN!5_l?=?@9WTn(Bx1M8e}rKd)lGpKgz=#?6nTOkP^cXKT+*}Lt<-r{EB*3B<6 zn_QSpfJJVC;RKZi^t8M^n^TjLE$p)lsg+a^jnG}LB4Unm!S$z^%%z_m3KH~<%1k~l zq8V<>Ca~|+Q$ADKsF5aH79Xme6{R#E`$)mMQ$?ZcLk6G`m@ffSg%up2u8r+}94F2@ zq%4a`^)v#AmgGSgYQhm>x_xb>)HxssH5 zg6ecp7fwfFw&7M<1{~Q|48!7EgWPJ3hp(VSc_j~_NJ5+V2mNluq{$;NYRAFjjqQh; z&lEIme>FmWubckW4iS5kePxGSwXNXu|G^H~Khl zO0B|b4~_AUJLjkG>h7DqRL#hUsH00ZcUY&)nJ%2r5jjs_HZPgx?@9)`J%c(eMJH$l zC9X`N^bT>}FI(3nhgOuSb?krLKVrB&az~tJrhMXABb*5093BYq;t9cX?ytMK*3cai zC4;%6lexW)tcE?gzGQAno_-@dI2Lp(ZVr zE0LFURmkcni#{0xM%$(@!m^{fQu?0YA2J1TKK;jqAY?=8S;fdCegcufvJY<)aN~&< z{`>@&8z}XemE%Xh(B2%1MXztyBQ|?4Y}$dT zMBPY(Tgj^67p%d*}{!zeNf zeCyK|iE{SzDI3g46!9j|XUIp4{nbl1bBk563hTNsQVEXVH?h(S1zmOP!~!YhZM!LK ziEnKz^yc)^9On?CoWS>#u4y-Z7^Ks|pDb+m;z{eJge34)ncp-wJI~}Zz>!(Nz+Xb7 zhQHxm#JzW$5~9%tX+DjBibi-nTILUWulEt(OJ*>QOOrH0q~618inc(9%aE6Wm-03{ zW|&1zQIUOk8fjm+v!*5Biz}g#q`soqc2YSn`GPH_qVk&&lhgo58#fXcH+yD~2B9X7)R4)YBx;zX>d zTF*OW5>Ip=CfIO4q$%JHFd={l9u>wU0PT1K#2{#iCwSJnBZ^k?P7oWu zC_EO#bJCVvm{8Ru2>ju_(2;Z;r-$PlTgO=#mGu6GU>szrH~vK&^eRz;{?;4)ltkb^ zV9NZn9_gnf`WKy$-*19`bwYkhqMwrJrzH9*iLU*WM1NEg{k_lls}vG6toh$ghGTPD zy(_z$M>^iKiq8{Il^cza&L}$Qa3-S;ApI>&M1B-PhlaD#jM*0Bnq;gaRc?cQ`Rt_8 zQ0o=_3zOJpCtAEyz~is^(8O)^KoHV%;Pt$u#b(}*ttaZ$bp-od?$6U7tUljQU?-GZ z$)uQZef5?hy5wLj%2igJ$YXU$65=^_zr)#_4|%l6FgJSFYd#IH>xgko^6R|=tg{jI zerIh6MAYrd(+S<-4Oya@X@u~_ve1j{ZKyg#O$1z!)C06X>`8a#^0PlL;blgyyP(o_ zr?as<-m>%I4Zkq29VqPpA*OIqWbz6b(M%z(i-R)8^7qDC(U^46@*oy*-s8tz7T!te z#%-Vo)yWG+hn#gS<4Sv_!wS^M3oG&qEvkg<>AQHW?gc^w8S|#NLfvJ}m z^Jns;%c&P+n*0tC0$o$=Uk218g|1myV<^6l63}ra2GsHk0Y+GK-gn=4`tn}8&8lTw z%Zx~K4w`-nKQi2u;W##&*;VU!Q%&;eI|m&xL2tI{laEGr3uC$D4ZBqzdgTZ)IAqP@ z+%Eavj?+BJnW^80IhRS-R^;QId_6x0a-S955;Gj+a^6bo`w?`j8!*n4LvqT&G|+?S ztj+%xDuT3*X*(X6%-qt;Hjia1>QV@-Nqu+h7s5JohN?=`$?!&3OCGj`k~J(SHC?+n z+J7)xeVdOX=URW%(pV(3P1y=g;|1}o=XuiJhzORiPD^0KZi9sjZBxJfcu%t+r83#+ z!$^q(=-B!eyo@iL#=3@0{DdPHR~x17b0G4rF3$KNR2tLgL(fZg!({H@p=QQ#gxz&* zTCV=GQ}&Eh#tR=a=Uc{t4uqR*9zV=a(uq(BIrMI(W_I%yQ$3&7XK%A5aC<~)IAdEf znS^rs7GgJuNh3CxOD?n_sV+e}A@CytGxJ6J{fk6XXc zw1%I5q!&*Ys?f_9$znH7IFZ=PrO0pW#ieBCKUu=Oc0Kk)8VAEOBP-^r+Y|P zfSqq96Roh{6PZep`Pz_i@Mm@)s;x6E>=RsDa@KmLT6Z7}4O%xVl7ADV(8@9UZsvMZ zu5hwAJI~^2n^m1Z@XhyEIn#FcNAH!`J61D87YYw%_|eqjJle{`qJ)7konBOv3d^0terCo=f;h**RNef)#N&C|hdZMzn!4*V7ID*aMT zinWFE0sRp(-Rk8;eEP2yK5zuY=4CyHhKXQL+6`$-b$RiFtQK#S5qX}k8h4Il-vCebgDU1 z*&5xIbVQ>I^Cbjf>Cz|*w_rI;{jtCkhC5)aPc>qsvFLxf(!}1-;y4C75PHV z9eG&>^|x>u7Z9S$Iqq+fORS7(39}hqD(I(E{GU-lzb}%0wncxSEt + From 2bb5a398c8a745816f1390cefaef1b9c87b56a1b Mon Sep 17 00:00:00 2001 From: Savindu Dimal Date: Sun, 17 Mar 2024 19:47:19 +0530 Subject: [PATCH 2/2] Add mutual ssl certificate validation test case Add mutual ssl certificate validation test case for head only exported client certificate Remove unnecessary user and application creation --- ...SSLCertificateChainValidationTestCase.java | 116 ++++++------------ .../mutualssl/cert_chain_client_head_only.jks | Bin 0 -> 2371 bytes .../mutualssl/cert_chain_intermediate.cer | 23 ++++ 3 files changed, 61 insertions(+), 78 deletions(-) create mode 100644 modules/integration/tests-integration/tests-backend/src/test/resources/artifacts/AM/lifecycletest/mutualssl/cert_chain_client_head_only.jks create mode 100644 modules/integration/tests-integration/tests-backend/src/test/resources/artifacts/AM/lifecycletest/mutualssl/cert_chain_intermediate.cer diff --git a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/api/lifecycle/APISecurityMutualSSLCertificateChainValidationTestCase.java b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/api/lifecycle/APISecurityMutualSSLCertificateChainValidationTestCase.java index ff50343ff6..41bc01cd91 100644 --- a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/api/lifecycle/APISecurityMutualSSLCertificateChainValidationTestCase.java +++ b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/api/lifecycle/APISecurityMutualSSLCertificateChainValidationTestCase.java @@ -26,24 +26,17 @@ import org.testng.annotations.Factory; import org.testng.annotations.Test; import org.wso2.am.integration.clients.publisher.api.ApiException; -import org.wso2.am.integration.clients.publisher.api.ApiResponse; import org.wso2.am.integration.clients.publisher.api.v1.dto.APIDTO; import org.wso2.am.integration.clients.publisher.api.v1.dto.APIOperationsDTO; -import org.wso2.am.integration.clients.store.api.v1.dto.ApplicationDTO; -import org.wso2.am.integration.clients.store.api.v1.dto.ApplicationKeyDTO; -import org.wso2.am.integration.clients.store.api.v1.dto.ApplicationKeyGenerateRequestDTO; import org.wso2.am.integration.test.utils.APIManagerIntegrationTestException; import org.wso2.am.integration.test.utils.base.APIMIntegrationConstants; -import org.wso2.am.integration.test.utils.bean.APILifeCycleAction; import org.wso2.am.integration.test.utils.bean.APIRequest; import org.wso2.am.integration.test.utils.http.HTTPSClientUtils; -import org.wso2.am.integration.test.utils.http.HttpRequestUtil; import org.wso2.carbon.automation.engine.annotations.ExecutionEnvironment; import org.wso2.carbon.automation.engine.annotations.SetEnvironment; import org.wso2.carbon.automation.engine.context.TestUserMode; import org.wso2.carbon.automation.test.utils.http.client.HttpResponse; import org.wso2.carbon.integration.common.utils.exceptions.AutomationUtilException; -import org.wso2.carbon.um.ws.api.stub.ClaimValue; import org.wso2.carbon.um.ws.api.stub.RemoteUserStoreManagerServiceUserStoreExceptionException; import org.wso2.carbon.user.core.UserStoreException; @@ -51,7 +44,6 @@ import java.io.File; import java.io.IOException; import java.net.URL; -import java.rmi.RemoteException; import java.security.KeyManagementException; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; @@ -65,16 +57,12 @@ public class APISecurityMutualSSLCertificateChainValidationTestCase extends APIManagerLifecycleBaseTest { private final String rootCertAPI = "rootCertAPI"; + private final String intermediateCertAPI = "intermediateCertAPI"; private final String API_END_POINT_METHOD = "/customers/123"; private final String API_VERSION_1_0_0 = "1.0.0"; - private final String APPLICATION_NAME = "APISecurityMutualSSLCertificateChainValidationTestCase"; - private String accessToken; private final String API_END_POINT_POSTFIX_URL = "jaxrs_basic/services/customers/customerservice/"; private String apiEndPointUrl; - private String applicationId; - private String apiId1; - String users[] = { "apisecUser", "apisecUser2@wso2.com", "apisecUser2@abc.com" }; - String endUserPassword = "password@123"; + private String apiId1, apiId2; @DataProvider public static Object[][] userModeDataProvider() { @@ -83,15 +71,6 @@ public static Object[][] userModeDataProvider() { new Object[] { TestUserMode.TENANT_ADMIN } }; } - private void createUser() - throws RemoteException, RemoteUserStoreManagerServiceUserStoreExceptionException, UserStoreException { - - for (String user : users) { - remoteUserStoreManagerServiceClient.addUser(user, endUserPassword, new String[] {}, new ClaimValue[] {}, - "default", false); - } - } - @Factory(dataProvider = "userModeDataProvider") public APISecurityMutualSSLCertificateChainValidationTestCase(TestUserMode userMode) { @@ -105,7 +84,6 @@ public void initialize() throws APIManagerIntegrationTestException, IOException, UserStoreException { super.init(userMode); - createUser(); apiEndPointUrl = backEndServerUrl.getWebAppURLHttp() + API_END_POINT_POSTFIX_URL; APIRequest apiRequest1 = new APIRequest(rootCertAPI, rootCertAPI, new URL(apiEndPointUrl)); @@ -136,60 +114,44 @@ public void initialize() throws APIManagerIntegrationTestException, IOException, HttpResponse response1 = restAPIPublisher.addAPI(apiRequest1); apiId1 = response1.getData(); - String certOne = getAMResourceLocation() + File.separator + "lifecycletest" + File.separator + "mutualssl" + String rootCertPath = getAMResourceLocation() + File.separator + "lifecycletest" + File.separator + "mutualssl" + File.separator + "cert_chain_root.cer"; - restAPIPublisher.uploadCertificate(new File(certOne), "example", apiId1, + restAPIPublisher.uploadCertificate(new File(rootCertPath), "cert_chain_root", apiId1, APIMIntegrationConstants.API_TIER.UNLIMITED); - } - - @Test(description = "This test case tests the behaviour of internal Key token on Created API with authentication " - + "types") - public void testCreateAndDeployRevisionWithInternalKeyTesting() - throws JSONException, ApiException, XPathExpressionException, APIManagerIntegrationTestException, - IOException, org.wso2.am.integration.clients.store.api.ApiException, InterruptedException { - createAPIRevisionAndDeployUsingRest(apiId1, restAPIPublisher); - APIDTO api1 = restAPIPublisher.getAPIByID(apiId1); - waitForAPIDeploymentSync(api1.getProvider(), api1.getName(), api1.getVersion(), - APIMIntegrationConstants.IS_API_EXISTS); - ApiResponse keyDTOApiResponse1 = restAPIPublisher.generateInternalApiKey( - apiId1); - Assert.assertEquals(keyDTOApiResponse1.getStatusCode(), 200); - HttpResponse httpResponse1 = invokeApiWithInternalKey(rootCertAPI, API_VERSION_1_0_0, API_END_POINT_METHOD, - keyDTOApiResponse1.getData().getApikey()); - Assert.assertEquals(httpResponse1.getResponseCode(), 200); - restAPIPublisher.changeAPILifeCycleStatus(apiId1, APILifeCycleAction.PUBLISH.getAction()); - - HttpResponse applicationResponse = restAPIStore.createApplication(APPLICATION_NAME, "Test Application", - APIMIntegrationConstants.APPLICATION_TIER.UNLIMITED, ApplicationDTO.TokenTypeEnum.JWT); - applicationId = applicationResponse.getData(); - ArrayList grantTypes = new ArrayList(); - grantTypes.add(APIMIntegrationConstants.GRANT_TYPE.PASSWORD); - grantTypes.add(APIMIntegrationConstants.GRANT_TYPE.CLIENT_CREDENTIAL); - ApplicationKeyDTO applicationKeyDTO = restAPIStore.generateKeys(applicationId, "36000", "", - ApplicationKeyGenerateRequestDTO.KeyTypeEnum.PRODUCTION, null, grantTypes); - //get access token - accessToken = applicationKeyDTO.getToken().getAccessToken(); + APIRequest apiRequest2 = new APIRequest(intermediateCertAPI, intermediateCertAPI, new URL(apiEndPointUrl)); + apiRequest2.setVersion(API_VERSION_1_0_0); + apiRequest2.setTiersCollection(APIMIntegrationConstants.API_TIER.UNLIMITED); + apiRequest2.setTier(APIMIntegrationConstants.API_TIER.UNLIMITED); + apiRequest2.setTags(API_TAGS); + apiRequest2.setVisibility(APIDTO.VisibilityEnum.PUBLIC.getValue()); + apiRequest2.setProvider(user.getUserName()); + apiRequest2.setOperationsDTOS(operationsDTOS); + apiRequest2.setSecurityScheme(securitySchemes); + apiRequest2.setDefault_version("true"); + apiRequest2.setHttps_checked("https"); + apiRequest2.setHttp_checked(null); + apiRequest2.setDefault_version_checked("true"); + HttpResponse response2 = restAPIPublisher.addAPI(apiRequest2); + apiId2 = response2.getData(); + + String intermediateCertPath = getAMResourceLocation() + File.separator + "lifecycletest" + File.separator + "mutualssl" + + File.separator + "cert_chain_intermediate.cer"; + restAPIPublisher.uploadCertificate(new File(intermediateCertPath), "cert_chain_intermediate", apiId2, + APIMIntegrationConstants.API_TIER.UNLIMITED); + createAPIRevisionAndDeployUsingRest(apiId2, restAPIPublisher); - HttpResponse httpResponseAfterPublish = invokeApiWithInternalKey(rootCertAPI, API_VERSION_1_0_0, - API_END_POINT_METHOD, keyDTOApiResponse1.getData().getApikey()); - Assert.assertEquals(httpResponseAfterPublish.getResponseCode(), 200); + waitForAPIDeploymentSync(user.getUserName(), rootCertAPI, API_VERSION_1_0_0, + APIMIntegrationConstants.IS_API_EXISTS); + waitForAPIDeploymentSync(user.getUserName(), intermediateCertAPI, API_VERSION_1_0_0, + APIMIntegrationConstants.IS_API_EXISTS); // wait until certificates loaded Thread.sleep(120000); } - private HttpResponse invokeApiWithInternalKey(String context, String version, String resource, String internalKey) - throws XPathExpressionException, IOException { - - Map requestHeaders = new HashMap<>(); - requestHeaders.put("accept", "application/json"); - requestHeaders.put("Internal-Key", internalKey); - return HttpRequestUtil.doGet(getAPIInvocationURLHttps(context, version) + resource, requestHeaders); - } - - @Test(description = "Invoke mutual SSL only API with not supported certificate", dependsOnMethods = "testCreateAndDeployRevisionWithInternalKeyTesting") + @Test(description = "Invoke mutual SSL only API with not supported certificate") public void testAPIInvocationWithMutualSSLOnlyAPINegative() throws IOException, XPathExpressionException, NoSuchAlgorithmException, KeyStoreException, KeyManagementException, UnrecoverableKeyException { @@ -215,7 +177,6 @@ public void testAPIInvocationWithMutualSSLMandatory() Map requestHeaders = new HashMap<>(); requestHeaders.put("accept", "text/xml"); - requestHeaders.put("Authorization", "Bearer " + accessToken); // Using root certificate HttpResponse rootCertResponse = HTTPSClientUtils.doMutulSSLGet( @@ -231,6 +192,13 @@ public void testAPIInvocationWithMutualSSLMandatory() getAPIInvocationURLHttps(rootCertAPI, API_VERSION_1_0_0) + API_END_POINT_METHOD, requestHeaders); Assert.assertEquals(clientCertResponse.getResponseCode(), HttpStatus.SC_OK, "Mutual SSL Authentication has not succeed"); + // Using client certificate with head only exported certificate + HttpResponse headOnlyClientCertResponse = HTTPSClientUtils.doMutulSSLGet( + getAMResourceLocation() + File.separator + "lifecycletest" + File.separator + "mutualssl" + + File.separator + "cert_chain_client_head_only.jks", + getAPIInvocationURLHttps(rootCertAPI, API_VERSION_1_0_0) + API_END_POINT_METHOD, requestHeaders); + Assert.assertEquals(headOnlyClientCertResponse.getResponseCode(), HttpStatus.SC_OK, "Mutual SSL Authentication has not succeed"); + // For default API version with root certificate HttpResponse defaultRootCertResponse = HTTPSClientUtils.doMutulSSLGet( getAMResourceLocation() + File.separator + "lifecycletest" + File.separator + "mutualssl" @@ -251,15 +219,7 @@ public void testAPIInvocationWithMutualSSLMandatory() @AfterClass(alwaysRun = true) public void cleanUpArtifacts() throws Exception { - restAPIStore.deleteApplication(applicationId); restAPIPublisher.deleteAPI(apiId1); - removeUsers(); - } - - private void removeUsers() throws RemoteException, RemoteUserStoreManagerServiceUserStoreExceptionException { - - for (String user : users) { - remoteUserStoreManagerServiceClient.removeUser(user); - } + restAPIPublisher.deleteAPI(apiId2); } } diff --git a/modules/integration/tests-integration/tests-backend/src/test/resources/artifacts/AM/lifecycletest/mutualssl/cert_chain_client_head_only.jks b/modules/integration/tests-integration/tests-backend/src/test/resources/artifacts/AM/lifecycletest/mutualssl/cert_chain_client_head_only.jks new file mode 100644 index 0000000000000000000000000000000000000000..43d34b5a87a40ef2959b5ecfaf0da594f103b054 GIT binary patch literal 2371 zcmb`Ic{J4h7suy2i*;;~J!X)7`Hn4FOUc-`RMuh)jZlMZkzFyCD7zvaM44nSjY+l; z6-uT^i*<}$JQTm_dCv1Yo#*%O?~i*vpVz&g&pG$pd(VCEGIkjd2n5PB;4kCD;RAzJ zaOXV;0V+5@0zM#^8A)41Lt-Hi1PqLW?}6Mb97-$z98iSv0RRF5kAu_A+J3rAI_3Ml z9dAA^?`w%7n=}%oL!57ga~L?Da4&JClS?+Nw>`37iLSaJOmereYE`ShHc(DNkG zN|oC|oe*9+Smu5GoIqw8A_P8KTPiaMP4Jj`#(MpJRrOJ1nn(J~Db;w?bVob%lZgsi z;IyerD0^zUr%{Xg!Li*hJF?4sO5bnD-Y^}jpDg^*(3?sweZrW=uAO#MB+XzrfjDYdK=>^7Dvm6# z=noMs0ehrT_d?|n-TLW^?jG-+Nf)B_G@PT$d$y;V#U3#Ptmx=}Z2k-q{s-JAntB%W;_^Wo7Wj_2s3h=n-YUu&ZLD@S?bTxx;Qlm+R&i>$P`U zxh+msqo)5@=+WzXWNKgY!PWu}OVs}?aFvTE#)wdG*3iJ3y|=q46c%lCjE^pQUG3bR zu~98Cxz@AdKh^x_9R_0{sJaNwA`g<9)}b;EKv#s;zl$fi~70_8QaE+|F2=_+s|6O0ZEo_hf#xWd(JQ zt5a!Chb0J&wq8Lhfi!s36^8EC>TK-OROkMRXNGXbj^_|6RLlwyG%P7Bg%2LAGEQ#R ze>e{PwnW^MS7W2ROq;_qt*D-@m*=UkNC~B7YugW{Wh%!Oec9k4VdnJ&D;-%g z4L#>7i;EKmIk$iVB718>o!nNmwl}CF@(%0Wlo>BsMs@Z}2NgT=)n4x|gX~dsT^=TX zoXgE|Lg=mjWBMspC6WdAd2CyV&`|(_8dMN?^3mdpx>wEW&R6f@mW?gS$?EoSam!|{ zM}c)G6IR<7gtR|B*w7!E9e>2jS|h}r4H~gEfe&`SznL!L&rv-HR!PbeO5})U0sP5f zhJ1vV()^{vCsXau_);U6UTJKX&n(DkW>mCX@UN$L*mV$j+}_cWJIWlsUY3bYh?g(w z$4Y43IGu>l#nSu|v{wqH_8Aei>D)zR{uo9FiP~mRM>VlL)HKqkh$|E^ZIg z@U3`#U&Q4E*!P_Zg{|!mwx-WorwF*#So*A%_&LKejIWx##otOjqANj=YgtfdP5BTp zM-l#OOCrvwYJrC#5ZEFZ2b%}uphG1vC;){D_!-!aZDdV`bV$xH2-`r~lnw&}aYAXsx;6%*sSX}?W}*&8T?2#BQ9rD8*cl}Je-jb~ zh5t_If3*aR1EhX02U9*^aR3j5>F0pP0RW_C@t`&Dd#8_umycO|IaDYb_K|mQdq3Ol zu_aQ7s^!ik3PN!Z9OyajE@I;U<3ZhHM0Y`Xc$d^6?as%}(1?Pplse(t7q3=!P{RC_ z?~~*&(?_HGpPKR{51XG7g1a7z(#XXMcYEB`?Nc@OgZggjwY=BGE$qO*t#+?$;wKl=nhbLLbJ5QtMWK=%|j47aUDk8XYA+=pABev(ai|;6L@TB(~%+y?zd*nRzIZzMz zYG?k$gzJU)jEAjKFrq5Yby{T9$0eOs1{4NBfU?+lFg6C{VOH?~KLG5(5g?3tFol=t z;Q8f%Gp8*Hl>EigaA8m|M&LvxJB7-w+}h&sHE%hpRpD8yOBZzH+MkfkP~7T?Z$v zhpJt69_CDxy4uW_v>sQk+|`!G3YLDXFaN z^ITZx(=0am?sg