diff --git a/.github/workflows/apitest-push-trigger.yml b/.github/workflows/apitest-push-trigger.yml index c3f27d1a17..d705909de1 100644 --- a/.github/workflows/apitest-push-trigger.yml +++ b/.github/workflows/apitest-push-trigger.yml @@ -56,6 +56,33 @@ jobs: uses: mosip/kattu/.github/workflows/maven-sonar-analysis.yml@master-java21 with: SERVICE_LOCATION: ./apitest-commons + secrets: + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + ORG_KEY: ${{ secrets.ORG_KEY }} + OSSRH_USER: ${{ secrets.OSSRH_USER }} + OSSRH_SECRET: ${{ secrets.OSSRH_SECRET }} + OSSRH_TOKEN: ${{ secrets.OSSRH_TOKEN }} + GPG_SECRET: ${{ secrets.GPG_SECRET }} + SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }} + + build-maven-authentication-demo-service: + uses: mosip/kattu/.github/workflows/maven-build.yml@master-java21 + with: + SERVICE_LOCATION: ./authentication-demo-service + BUILD_ARTIFACT: authentication-demo-service + secrets: + OSSRH_USER: ${{ secrets.OSSRH_USER }} + OSSRH_SECRET: ${{ secrets.OSSRH_SECRET }} + OSSRH_TOKEN: ${{ secrets.OSSRH_TOKEN }} + GPG_SECRET: ${{ secrets.GPG_SECRET }} + SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }} + + sonar_analysis-authentication-demo-service: + needs: build-maven-authentication-demo-service + if: "${{ github.event_name != 'pull_request' }}" + uses: mosip/kattu/.github/workflows/maven-sonar-analysis.yml@master-java21 + with: + SERVICE_LOCATION: ./authentication-demo-service secrets: SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} ORG_KEY: ${{ secrets.ORG_KEY }} diff --git a/.github/workflows/chart-lint-publish.yml b/.github/workflows/chart-lint-publish.yml new file mode 100644 index 0000000000..1b51dddc74 --- /dev/null +++ b/.github/workflows/chart-lint-publish.yml @@ -0,0 +1,62 @@ +name: Validate / Publish helm charts + +on: + release: + types: [published] + pull_request: + types: [opened, reopened, synchronize] + paths: + - 'helm/**' + workflow_dispatch: + inputs: + IGNORE_CHARTS: + description: 'Provide list of charts to be ignored separated by pipe(|)' + required: false + default: '""' + type: string + CHART_PUBLISH: + description: 'Chart publishing to gh-pages branch' + required: false + default: 'NO' + type: string + options: + - YES + - NO + INCLUDE_ALL_CHARTS: + description: 'Include all charts for Linting/Publishing (YES/NO)' + required: false + default: 'NO' + type: string + options: + - YES + - NO + push: + branches: + - '!release-branch' + - '!master' + - 1.* + - 0.* + - develop + - release* + paths: + - 'helm/**' + +jobs: + chart-lint-publish: + uses: mosip/kattu/.github/workflows/chart-lint-publish.yml@master + with: + CHARTS_DIR: ./helm + CHARTS_URL: https://mosip.github.io/mosip-helm + REPOSITORY: mosip-helm + BRANCH: gh-pages + INCLUDE_ALL_CHARTS: "${{ inputs.INCLUDE_ALL_CHARTS || 'NO' }}" + IGNORE_CHARTS: "${{ inputs.IGNORE_CHARTS || '\"\"' }}" + CHART_PUBLISH: "${{ inputs.CHART_PUBLISH || 'YES' }}" + LINTING_CHART_SCHEMA_YAML_URL: "https://raw.githubusercontent.com/mosip/kattu/master/.github/helm-lint-configs/chart-schema.yaml" + LINTING_LINTCONF_YAML_URL: "https://raw.githubusercontent.com/mosip/kattu/master/.github/helm-lint-configs/lintconf.yaml" + LINTING_CHART_TESTING_CONFIG_YAML_URL: "https://raw.githubusercontent.com/mosip/kattu/master/.github/helm-lint-configs/chart-testing-config.yaml" + LINTING_HEALTH_CHECK_SCHEMA_YAML_URL: "https://raw.githubusercontent.com/mosip/kattu/master/.github/helm-lint-configs/health-check-schema.yaml" + DEPENDENCIES: "mosip,https://mosip.github.io/mosip-helm;" + secrets: + TOKEN: ${{ secrets.ACTION_PAT }} + SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }} \ No newline at end of file diff --git a/apitest-commons/pom.xml b/apitest-commons/pom.xml index 8cd782cb2e..5766323b56 100644 --- a/apitest-commons/pom.xml +++ b/apitest-commons/pom.xml @@ -36,7 +36,7 @@ UTF-8 - 1.2.1-java21-SNAPSHOT + 1.2.1-SNAPSHOT 21 @@ -55,11 +55,11 @@ 1.11.368 - 6.5.2.Final + 5.2.17.Final 1.1.2-incubating - 1.2.1-java21-SNAPSHOT + 1.2.1-SNAPSHOT 0.4.7 3.0.0 2.41.2 @@ -67,6 +67,7 @@ 6.11 1.13 apitest-commons-1.2.1-java21-SNAPSHOT-jar-with-dependencies + @@ -334,29 +335,6 @@ javax.mail-api 1.6.2 - - - - - io.mosip.kernel - kernel-registration-packet-manager - 1.1.5.3 - - - org.springframework - spring-expression - - - org.bouncycastle - bcprov-jdk15on - - - - - io.mosip.kernel - kernel-crypto-jce - 1.1.5.3 - org.apache.wink wink-json4j-provider @@ -399,7 +377,7 @@ io.mosip.mock.mds mock-mds - 1.2.1-java21-SNAPSHOT + 1.2.1-SNAPSHOT javax.xml.bind @@ -449,13 +427,13 @@ io.mosip.kernel kernel-templatemanager-velocity - 1.2.1-java21-SNAPSHOT + 1.2.1-SNAPSHOT io.mosip.kernel kernel-keymanager-service - 1.2.1-java21-SNAPSHOT + 1.2.1-SNAPSHOT lib @@ -470,6 +448,10 @@ org.bouncycastle bcpkix-jdk15on + + org.hibernate.orm + hibernate-core + @@ -490,7 +472,7 @@ io.mosip.kernel kernel-bom - 1.2.1-java21-SNAPSHOT + 1.2.1-SNAPSHOT pom import diff --git a/apitest-commons/src/main/java/io/mosip/testrig/apirig/admin/fw/config/BeanConfig.java b/apitest-commons/src/main/java/io/mosip/testrig/apirig/admin/fw/config/BeanConfig.java index a162a2198b..59e1ded5e8 100644 --- a/apitest-commons/src/main/java/io/mosip/testrig/apirig/admin/fw/config/BeanConfig.java +++ b/apitest-commons/src/main/java/io/mosip/testrig/apirig/admin/fw/config/BeanConfig.java @@ -1,14 +1,29 @@ package io.mosip.testrig.apirig.admin.fw.config; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; -import io.mosip.kernel.crypto.jce.core.CryptoCore; +import io.mosip.testrig.apirig.utils.BioDataUtility; +import io.mosip.testrig.apirig.utils.CryptoCore; +import io.mosip.testrig.apirig.utils.EncryptionDecrptionUtil; + @Configuration -@Import({ CryptoCore.class }) +@Import({CryptoCore.class}) @ComponentScan(basePackages = { "io.mosip.testrig.apirig", "io.mosip.testrig.dslrig"}) public class BeanConfig { int i = 0; + + @Bean + public BioDataUtility bioDataUtility() { + return new BioDataUtility(); + } + + @Bean + public EncryptionDecrptionUtil encryptionDecrptionUtil() { + return new EncryptionDecrptionUtil(); + } + } diff --git a/apitest-commons/src/main/java/io/mosip/testrig/apirig/dataprovider/BiometricDataProvider.java b/apitest-commons/src/main/java/io/mosip/testrig/apirig/dataprovider/BiometricDataProvider.java index adaca9effb..871201572c 100644 --- a/apitest-commons/src/main/java/io/mosip/testrig/apirig/dataprovider/BiometricDataProvider.java +++ b/apitest-commons/src/main/java/io/mosip/testrig/apirig/dataprovider/BiometricDataProvider.java @@ -64,7 +64,6 @@ public class BiometricDataProvider { public static HashMap portmap = new HashMap(); - //private static final Logger logger = LoggerFactory.getLogger(BiometricDataProvider.class); private static final Logger logger = Logger.getLogger(BiometricDataProvider.class); // String constants diff --git a/apitest-commons/src/main/java/io/mosip/testrig/apirig/dbaccess/AuditDBManager.java b/apitest-commons/src/main/java/io/mosip/testrig/apirig/dbaccess/AuditDBManager.java index 67fe0de32a..e859826ea6 100644 --- a/apitest-commons/src/main/java/io/mosip/testrig/apirig/dbaccess/AuditDBManager.java +++ b/apitest-commons/src/main/java/io/mosip/testrig/apirig/dbaccess/AuditDBManager.java @@ -146,7 +146,6 @@ private static SessionFactory getDataBaseConnectionSessionFactory(String dbName) config.setProperty("hibernate.show_sql", propsKernel.getProperty("show_sql")); config.setProperty("hibernate.current_session_context_class", propsKernel.getProperty("current_session_context_class")); - config.addFile(new File(MosipTestRunner.getGlobalResourcePath() + "/dbFiles/dbConfig.xml")); factory = config.buildSessionFactory(); } catch (HibernateException e) { DBCONNECTION_LOGGER.error("Exception in Database Connection with following message: " + e.getMessage()); diff --git a/apitest-commons/src/main/java/io/mosip/testrig/apirig/dto/TestCaseDTO.java b/apitest-commons/src/main/java/io/mosip/testrig/apirig/dto/TestCaseDTO.java index 328ff63e69..830c2ca816 100644 --- a/apitest-commons/src/main/java/io/mosip/testrig/apirig/dto/TestCaseDTO.java +++ b/apitest-commons/src/main/java/io/mosip/testrig/apirig/dto/TestCaseDTO.java @@ -20,4 +20,5 @@ public class TestCaseDTO { private String allowedErrorCodes; private String[] kycFields; private String description; + private String uniqueIdentifier; } diff --git a/apitest-commons/src/main/java/io/mosip/testrig/apirig/report/EmailableReport.java b/apitest-commons/src/main/java/io/mosip/testrig/apirig/report/EmailableReport.java index c000ea1ee5..4ae90c3a07 100644 --- a/apitest-commons/src/main/java/io/mosip/testrig/apirig/report/EmailableReport.java +++ b/apitest-commons/src/main/java/io/mosip/testrig/apirig/report/EmailableReport.java @@ -47,6 +47,9 @@ public class EmailableReport implements IReporter { protected PrintWriter writer; protected final List suiteResults = Lists.newArrayList(); + + protected final boolean reportIgnoredTestCases = ConfigManager.reportIgnoredTestCases(); + protected final boolean reportKnownIssueTestCases = ConfigManager.reportKnownIssueTestCases(); // Reusable buffer private final StringBuilder buffer = new StringBuilder(); @@ -58,6 +61,7 @@ public class EmailableReport implements IReporter { private int totalPassedTests = 0; private int totalSkippedTests = 0; private int totalIgnoredTests = 0; + private int totalKnownIssueTests = 0; private int totalFailedTests = 0; private long totalDuration = 0; @@ -89,20 +93,31 @@ public void generateReport(List xmlSuites, List suites, String writer.close(); int totalTestCases = 0; - if (ConfigManager.reportIgnoredTestCases()) { - totalTestCases = totalPassedTests + totalSkippedTests + totalFailedTests + totalIgnoredTests; - }else { - totalTestCases = totalPassedTests + totalSkippedTests + totalFailedTests; + + totalTestCases = totalPassedTests + totalSkippedTests + totalFailedTests; + + if (reportIgnoredTestCases) { + totalTestCases = totalTestCases + totalIgnoredTests; + } + if (reportKnownIssueTestCases) { + totalTestCases = totalTestCases + totalKnownIssueTests; } String oldString = System.getProperty(GlobalConstants.EMAILABLEREPORT2NAME); String temp = ""; - if (ConfigManager.reportIgnoredTestCases()) { + + temp = "-report_T-" + totalTestCases + "_P-" + totalPassedTests + "_S-" + totalSkippedTests + "_F-" + + totalFailedTests; + + if (reportIgnoredTestCases && reportKnownIssueTestCases) { + temp = "-report_T-" + totalTestCases + "_P-" + totalPassedTests + "_S-" + totalSkippedTests + "_F-" + + totalFailedTests + "_I-" + totalIgnoredTests + "_KI-" + totalKnownIssueTests; + } else if (reportIgnoredTestCases && !(reportKnownIssueTestCases)) { temp = "-report_T-" + totalTestCases + "_P-" + totalPassedTests + "_S-" + totalSkippedTests + "_F-" + totalFailedTests + "_I-" + totalIgnoredTests; - }else { + } else if (reportKnownIssueTestCases && !(reportIgnoredTestCases)) { temp = "-report_T-" + totalTestCases + "_P-" + totalPassedTests + "_S-" + totalSkippedTests + "_F-" - + totalFailedTests; + + totalFailedTests + "_KI-" + totalKnownIssueTests; } String newString = oldString.replace("-report", temp); @@ -194,6 +209,7 @@ protected void writeStylesheet() { writer.print(".num {text-align:center}"); writer.print(".orange-bg {background-color: #FFA500}"); writer.print(".grey-bg {background-color: #808080}"); + writer.print(".thich-orange-bg {background-color: #CC5500}"); writer.print(".green-bg {background-color: #0A0}"); writer.print(".attn {background-color: #D00}"); writer.print(".passedodd td {background-color: #3F3}"); @@ -204,6 +220,8 @@ protected void writeStylesheet() { writer.print(".failedeven td,.stripe {background-color: #D00}"); writer.print(".ignoredodd td {background-color: #808080}"); writer.print(".ignoredeven td {background-color: #808080}"); + writer.print(".known_issuesodd td {background-color: #CC5500}"); + writer.print(".known_issueseven td {background-color: #CC5500}"); writer.print(".stacktrace {white-space:pre;font-family:monospace}"); writer.print(".totop {font-size:85%;text-align:center;border-bottom:2px solid #000}"); writer.print(""); @@ -244,6 +262,7 @@ protected void writeSuiteSummary() { totalPassedTests = 0; totalSkippedTests = 0; totalIgnoredTests = 0; + totalKnownIssueTests = 0; totalFailedTests = 0; totalDuration = 0; @@ -251,7 +270,7 @@ protected void writeSuiteSummary() { int testIndex = 0; for (SuiteResult suiteResult : suiteResults) { - writer.print(""); + writer.print(""); writer.print(Utils.escapeHtml(suiteResult.getSuiteName() + " ---- " + "Report Date: " + formattedDate + " ---- " + "Tested Environment: " + System.getProperty("env.endpoint").replaceAll(".*?\\.([^\\.]+)\\..*", "$1") + " ---- " @@ -259,32 +278,32 @@ protected void writeSuiteSummary() { writer.print(GlobalConstants.TRTR); // Left column: "Tested Component Details" with central alignment - writer.print("
");
+			writer.print("
");
 			writer.print(Utils.escapeHtml("Server Component Details"));
 			writer.print("");
 
 			// Right column: Details from AdminTestUtil.getServerComponentsDetails() without bold formatting
-			writer.print("
");
+			writer.print("
");
 			writer.print(Utils.escapeHtml(AdminTestUtil.getServerComponentsDetails()));
 			writer.print("
"); writer.print(GlobalConstants.TRTR); // Left column: "Tested Component Details" with central alignment - writer.print("
");
+			writer.print("
");
 			writer.print(Utils.escapeHtml("End Points used"));
 			writer.print("");
 
 			// Right column: Details from AdminTestUtil.getServerComponentsDetails() without bold formatting
-			writer.print("
");
+			writer.print("
");
 			writer.print(Utils.escapeHtml(GlobalMethods.getComponentDetails()));
 			writer.print("
"); writer.print(GlobalConstants.TRTR); if (GlobalMethods.getServerErrors().equals("No server errors")) { - writer.print("
");
+				writer.print("
");
 			} else {
 				writer.print(
-						"
");
+						"
");
 			}
 			writer.print(Utils.escapeHtml("Server Errors " + "\n" + GlobalMethods.getServerErrors()));
 			writer.print("
"); @@ -297,9 +316,13 @@ protected void writeSuiteSummary() { writer.print("# Passed"); writer.print("# Skipped"); writer.print("# Failed"); - if (ConfigManager.reportIgnoredTestCases()) { + if (reportIgnoredTestCases) { writer.print("# Ignored"); } + + if (reportKnownIssueTestCases) { + writer.print("# Known_Issues"); + } writer.print("Execution Time (ms)"); // writer.print("Included Groups"); // writer.print("Excluded Groups"); @@ -308,13 +331,20 @@ protected void writeSuiteSummary() { for (TestResult testResult : suiteResult.getTestResults()) { int passedTests = testResult.getPassedTestCount(); int ignoredTests = testResult.getIgnoredTestCount(); + int knownIssueTests = testResult.getKnownIssueTestCount(); int skippedTests = testResult.getSkippedTestCount(); int failedTests = testResult.getFailedTestCount(); long duration = testResult.getDuration(); int totalTests = 0; - totalTests = ConfigManager.reportIgnoredTestCases() - ? (passedTests + skippedTests + failedTests + ignoredTests) - : (passedTests + skippedTests + failedTests); + + totalTests = passedTests + skippedTests + failedTests; + + if (reportIgnoredTestCases) { + totalTests = totalTests + ignoredTests; + } + if (reportKnownIssueTestCases) { + totalTests = totalTests + knownIssueTests; + } // All test cases are ignored. Hence don't print anything in the report. if (totalTests < 1) continue; @@ -339,9 +369,13 @@ protected void writeSuiteSummary() { writeTableData(integerFormat.format(skippedTests), (skippedTests > 0 ? "num orange-bg" : "num")); writeTableData(integerFormat.format(failedTests), (failedTests > 0 ? GlobalConstants.NUMATTN : "num")); // print the ignored column based on the flag - if (ConfigManager.reportIgnoredTestCases()) { + if (reportIgnoredTestCases) { writeTableData(integerFormat.format(ignoredTests), (ignoredTests > 0 ? "num grey-bg" : "num")); } + + if (reportKnownIssueTestCases) { + writeTableData(integerFormat.format(knownIssueTests), (knownIssueTests > 0 ? "num thich-orange-bg" : "num")); + } writeTableData(decimalFormat.format(duration), "num"); // writeTableData(testResult.getIncludedGroups()); // writeTableData(testResult.getExcludedGroups()); @@ -352,6 +386,7 @@ protected void writeSuiteSummary() { totalSkippedTests += skippedTests; totalFailedTests += failedTests; totalIgnoredTests += ignoredTests; + totalKnownIssueTests += knownIssueTests; totalDuration += duration; testIndex++; @@ -362,9 +397,16 @@ protected void writeSuiteSummary() { writer.print(""); writer.print("Total"); writeTableHeader("", "num"); - if (ConfigManager.reportIgnoredTestCases()) { - writeTableHeader(integerFormat - .format(totalPassedTests + totalSkippedTests + totalFailedTests + totalIgnoredTests), "num"); + + if (reportIgnoredTestCases && reportKnownIssueTestCases) { + writeTableHeader(integerFormat.format(totalPassedTests + totalSkippedTests + totalFailedTests + + totalIgnoredTests + totalKnownIssueTests), "num"); + } else if (reportIgnoredTestCases && !(reportKnownIssueTestCases)) { + writeTableHeader(integerFormat.format(totalPassedTests + totalSkippedTests + totalFailedTests + + totalIgnoredTests), "num"); + } else if (reportKnownIssueTestCases && !(reportIgnoredTestCases)) { + writeTableHeader(integerFormat.format(totalPassedTests + totalSkippedTests + totalFailedTests + +totalKnownIssueTests), "num"); } else { writeTableHeader(integerFormat.format(totalPassedTests + totalSkippedTests + totalFailedTests), "num"); } @@ -373,10 +415,14 @@ protected void writeSuiteSummary() { (totalSkippedTests > 0 ? "num orange-bg" : "num")); writeTableHeader(integerFormat.format(totalFailedTests), (totalFailedTests > 0 ? GlobalConstants.NUMATTN : "num")); - if (ConfigManager.reportIgnoredTestCases()) { + if (reportIgnoredTestCases) { writeTableHeader(integerFormat.format(totalIgnoredTests), (totalIgnoredTests > 0 ? "num grey-bg" : "num")); } + if (reportKnownIssueTestCases) { + writeTableHeader(integerFormat.format(totalKnownIssueTests), + (totalKnownIssueTests > 0 ? "num thich-orange-bg" : "num")); + } writeTableHeader(decimalFormat.format(totalDuration), "num"); writer.print(GlobalConstants.TR); } @@ -401,9 +447,17 @@ protected static Set getResultsSubSet(Set resultsSet, } else { // Skip the test result } + } else if (subSetString.contains(GlobalConstants.KNOWN_ISSUES_STRING)) { + if (containsAny(throwable.getMessage(), subSetString)) { + // Add only results which are skipped due to feature not supported + testResultsSubList.add(result); + } else { + // Skip the test result + } } else { // Service not deployed. Hence skipping the testcase // skipped if (!throwable.getMessage().contains(GlobalConstants.FEATURE_NOT_SUPPORTED) - && !throwable.getMessage().contains(GlobalConstants.SERVICE_NOT_DEPLOYED)) { + && !throwable.getMessage().contains(GlobalConstants.SERVICE_NOT_DEPLOYED) + && !throwable.getMessage().contains(GlobalConstants.KNOWN_ISSUES)) { // Add only results which are not skipped due to feature not supported testResultsSubList.add(result); } else { @@ -451,12 +505,19 @@ protected void writeScenarioSummary() { for (TestResult testResult : suiteResult.getTestResults()) { int passedTests = testResult.getPassedTestCount(); int ignoredTests = testResult.getIgnoredTestCount(); + int knownIssueTests = testResult.getKnownIssueTestCount(); int skippedTests = testResult.getSkippedTestCount(); int failedTests = testResult.getFailedTestCount(); int totalTests = 0; - totalTests = ConfigManager.reportIgnoredTestCases() - ? (passedTests + skippedTests + failedTests + ignoredTests) - : (passedTests + skippedTests + failedTests); + + totalTests = passedTests + skippedTests + failedTests; + + if (reportIgnoredTestCases) { + totalTests = totalTests + ignoredTests; + } + if (reportKnownIssueTestCases) { + totalTests = totalTests + knownIssueTests; + } // All test cases are ignored. Hence don't print anything in the report. if (totalTests < 1) continue; @@ -466,10 +527,16 @@ protected void writeScenarioSummary() { String testName = Utils.escapeHtml(testResult.getTestName()); - if (ConfigManager.reportIgnoredTestCases()) { + if (reportIgnoredTestCases) { scenarioIndex += writeScenarioSummary(testName + " — Ignored", testResult.getIgnoredTestResults(), "ignored", scenarioIndex); } + + if (reportKnownIssueTestCases) { + scenarioIndex += writeScenarioSummary(testName + " — known_issues", + testResult.getKnownIssueTestResults(), "known_issues", scenarioIndex); + } + scenarioIndex += writeScenarioSummary(testName + " — Failed", testResult.getFailedTestResults(), "failed", scenarioIndex); scenarioIndex += writeScenarioSummary(testName + " — Skipped", testResult.getSkippedTestResults(), @@ -582,9 +649,13 @@ protected void writeScenarioDetails() { writer.print(Utils.escapeHtml(testResult.getTestName())); writer.print(""); - if (ConfigManager.reportIgnoredTestCases()) { + if (reportIgnoredTestCases) { scenarioIndex += writeScenarioDetails(testResult.getIgnoredTestResults(), scenarioIndex); } + + if (reportKnownIssueTestCases) { + scenarioIndex += writeScenarioDetails(testResult.getKnownIssueTestResults(), scenarioIndex); + } scenarioIndex += writeScenarioDetails(testResult.getFailedConfigurationResults(), scenarioIndex); scenarioIndex += writeScenarioDetails(testResult.getFailedTestResults(), scenarioIndex); scenarioIndex += writeScenarioDetails(testResult.getSkippedConfigurationResults(), scenarioIndex); @@ -836,7 +907,9 @@ public int compare(ITestResult o1, ITestResult o2) { private final List skippedTestResults; private final List passedTestResults; private final List ignoredTestResults; + private final List knownIssueTestResults; private final int ignoredTestCount; + private final int knownIssueTestCount; private final int failedTestCount; private final int skippedTestCount; private final int passedTestCount; @@ -855,6 +928,7 @@ public TestResult(ITestContext context) { // Set skippedTests = context.getSkippedTests().getAllResults(); Set skippedTests = getResultsSubSet(context.getSkippedTests().getAllResults(), GlobalConstants.SKIPPED); Set ignoredTests = getResultsSubSet(context.getSkippedTests().getAllResults(), GlobalConstants.IGNORED_SUBSET_STRING); + Set knownIssueTests = getResultsSubSet(context.getSkippedTests().getAllResults(), GlobalConstants.KNOWN_ISSUE_SUBSET_STRING); Set passedTests = context.getPassedTests().getAllResults(); failedConfigurationResults = groupResults(failedConfigurations); @@ -862,12 +936,14 @@ public TestResult(ITestContext context) { skippedConfigurationResults = groupResults(skippedConfigurations); skippedTestResults = groupResults(skippedTests); ignoredTestResults = groupResults(ignoredTests); + knownIssueTestResults = groupResults(knownIssueTests); passedTestResults = groupResults(passedTests); failedTestCount = failedTests.size(); skippedTestCount = skippedTests.size(); passedTestCount = passedTests.size(); ignoredTestCount = ignoredTests.size(); + knownIssueTestCount = knownIssueTests.size(); duration = context.getEndDate().getTime() - context.getStartDate().getTime(); @@ -954,6 +1030,10 @@ public List getFailedTestResults() { public List getIgnoredTestResults() { return ignoredTestResults; } + + public List getKnownIssueTestResults() { + return knownIssueTestResults; + } /** * @return the results for skipped configurations (possibly empty) @@ -991,6 +1071,10 @@ public int getPassedTestCount() { public int getIgnoredTestCount() { return ignoredTestCount; } + + public int getKnownIssueTestCount() { + return knownIssueTestCount; + } public long getDuration() { return duration; diff --git a/apitest-commons/src/main/java/io/mosip/testrig/apirig/testrunner/BaseTestCase.java b/apitest-commons/src/main/java/io/mosip/testrig/apirig/testrunner/BaseTestCase.java index bd0a877622..a8c334482e 100644 --- a/apitest-commons/src/main/java/io/mosip/testrig/apirig/testrunner/BaseTestCase.java +++ b/apitest-commons/src/main/java/io/mosip/testrig/apirig/testrunner/BaseTestCase.java @@ -328,15 +328,15 @@ public static void suiteSetup() { setReportName(GlobalConstants.PREREG); AdminTestUtil.copyPreregTestResource(); } -// if (listOfModules.contains(GlobalConstants.INJICERTIFY)) { -// BaseTestCase.currentModule = GlobalConstants.INJICERTIFY; -// BaseTestCase.certsForModule = GlobalConstants.INJICERTIFY; -// DBManager.clearKeyManagerDbCertData(); -// DBManager.clearIDADbCertData(); -// DBManager.clearMasterDbCertData(); -// setReportName(GlobalConstants.INJICERTIFY); -// AdminTestUtil.copymoduleSpecificAndConfigFile(GlobalConstants.INJICERTIFY); -// } + if (listOfModules.contains(GlobalConstants.INJICERTIFY)) { + BaseTestCase.currentModule = GlobalConstants.INJICERTIFY; + BaseTestCase.certsForModule = GlobalConstants.INJICERTIFY; + DBManager.clearKeyManagerDbCertData(); + DBManager.clearIDADbCertData(); + DBManager.clearMasterDbCertData(); + setReportName(GlobalConstants.INJICERTIFY); + AdminTestUtil.copymoduleSpecificAndConfigFile(GlobalConstants.INJICERTIFY); + } mockSMTPListener = new MockSMTPListener(); mockSMTPListener.run(); } @@ -740,4 +740,10 @@ public static String generateRandomNumberString(int length) { } return numericString.toString(); } + + public static int getRecommendedHierarchyLevel() { + String recommendedHierarchLevel = getValueFromActuators(propsKernel.getProperty("actuatorMasterDataEndpoint"), + "/mosip-config/application-default.properties", "mosip.recommended.centers.locCode"); + return Integer.parseInt(recommendedHierarchLevel); + } } diff --git a/apitest-commons/src/main/java/io/mosip/testrig/apirig/testrunner/ExtractResource.java b/apitest-commons/src/main/java/io/mosip/testrig/apirig/testrunner/ExtractResource.java index cbdee0a36e..92379bfe50 100644 --- a/apitest-commons/src/main/java/io/mosip/testrig/apirig/testrunner/ExtractResource.java +++ b/apitest-commons/src/main/java/io/mosip/testrig/apirig/testrunner/ExtractResource.java @@ -21,6 +21,7 @@ public static void extractCommonResourceFromJar() { getListOfFilesFromJarAndCopyToExternalResource("spring.properties"); getListOfFilesFromJarAndCopyToExternalResource("validations.properties"); getListOfFilesFromJarAndCopyToExternalResource("dbFiles/"); + getListOfFilesFromJarAndCopyToExternalResource("testCaseSkippedList.txt"); } public static void copyCommonResources(){ @@ -31,6 +32,7 @@ public static void copyCommonResources(){ copyCommonResources("spring.properties"); copyCommonResources("validations.properties"); copyCommonResources("dbFiles/"); + copyCommonResources("testCaseSkippedList.txt"); } public static void copyCommonResources(String moduleName){ diff --git a/apitest-commons/src/main/java/io/mosip/testrig/apirig/utils/AdminTestUtil.java b/apitest-commons/src/main/java/io/mosip/testrig/apirig/utils/AdminTestUtil.java index bafba170be..47e113adca 100644 --- a/apitest-commons/src/main/java/io/mosip/testrig/apirig/utils/AdminTestUtil.java +++ b/apitest-commons/src/main/java/io/mosip/testrig/apirig/utils/AdminTestUtil.java @@ -1,8 +1,7 @@ package io.mosip.testrig.apirig.utils; import static io.restassured.RestAssured.given; -import de.mkammerer.argon2.Argon2; -import de.mkammerer.argon2.Argon2Factory; + import java.io.BufferedInputStream; import java.io.BufferedReader; import java.io.BufferedWriter; @@ -17,6 +16,7 @@ import java.io.OutputStreamWriter; import java.io.StringReader; import java.lang.reflect.Type; +import java.math.BigDecimal; import java.math.BigInteger; import java.net.URI; import java.net.URISyntaxException; @@ -33,8 +33,6 @@ import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; -import java.security.interfaces.RSAPrivateKey; -import java.security.interfaces.RSAPublicKey; import java.text.SimpleDateFormat; import java.time.Instant; import java.time.LocalDate; @@ -56,6 +54,8 @@ import java.util.Set; import java.util.TimeZone; import java.util.UUID; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import java.util.stream.Collectors; import javax.ws.rs.core.MediaType; @@ -79,9 +79,7 @@ import org.testng.SkipException; import org.yaml.snakeyaml.Yaml; -import java.lang.Double; import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.github.jknack.handlebars.Context; import com.github.jknack.handlebars.Handlebars; @@ -119,8 +117,6 @@ import io.restassured.RestAssured; import io.restassured.http.ContentType; import io.restassured.response.Response; -import java.util.regex.Matcher; -import java.util.regex.Pattern; /** * @author Ravi Kant @@ -141,6 +137,7 @@ public class AdminTestUtil extends BaseTestCase { public static String propsHealthCheckURL = MosipTestRunner.getGlobalResourcePath() + "/" + "config/healthCheckEndpoint.properties"; private static String serverComponentsCommitDetails; + private static boolean foundHandlesInIdSchema= false; protected static String token = null; String idToken = null; @@ -170,9 +167,9 @@ public class AdminTestUtil extends BaseTestCase { protected static String policygroupId = null; protected static String regDeviceResponse = null; protected static String generatedVID = null; - public static final String RANDOM_ID = "mosip" + generateRandomNumberString(2) + public String RANDOM_ID = "mosip" + generateRandomNumberString(2) + Calendar.getInstance().getTimeInMillis(); - public static final String RANDOM_ID_2 = "mosip" + generateRandomNumberString(2) + public final String RANDOM_ID_2 = "mosip" + generateRandomNumberString(2) + Calendar.getInstance().getTimeInMillis(); public static final String RANDOM_ID_V2 = "mosip" + generateRandomNumberString(2) + Calendar.getInstance().getTimeInMillis(); @@ -185,6 +182,7 @@ public class AdminTestUtil extends BaseTestCase { public static final String AUTH_HEADER_VALUE = "Some String"; public static final String SIGNATURE_HEADERNAME = GlobalConstants.SIGNATURE; public static String updatedPolicyId = ""; + public static String currentLanguage; // public static BioDataUtility bioDataUtil = new BioDataUtility(); // // public static BioDataUtility getBioDataUtil() { @@ -194,6 +192,7 @@ public class AdminTestUtil extends BaseTestCase { // public static EncryptionDecrptionUtil encryptDecryptUtil = null; protected static String idField = null; protected static String identityHbs = null; + protected static String updateIdentityHbs = null; protected static String draftHbs = null; protected static String preregHbsForCreate = null; protected static String preregHbsForUpdate = null; @@ -253,6 +252,7 @@ public class AdminTestUtil extends BaseTestCase { public static final String BINDINGCERTCONSENTEMPTYCLAIMFILE = "BINDINGCERTCONSENTEMPTYCLAIMFile"; public static final String BINDINGCERTCONSENTUSER2FILE = "BINDINGCERTCONSENTUSER2File"; public static final String BINDINGCERTVIDCONSENTUSER2FILE = "BINDINGCERTCONSENTVIDUSER2File"; + private static String selectedHandlesValue=null; private static final String UIN_CODE_VERIFIER_POS_1 = generateRandomAlphaNumericString(GlobalConstants.INTEGER_36); @@ -2734,9 +2734,8 @@ public String getAutogenIdKeyName(String testCaseName, String fieldName) { return null; int indexof = testCaseName.indexOf("_"); String autogenIdKeyName = testCaseName.substring(indexof + 1); - if ((!BaseTestCase.isTargetEnvLTS() || isOTPEnabled().equals("false")) && fieldName.equals("VID") - && (BaseTestCase.currentModule.equals("auth") || BaseTestCase.currentModule.equals("esignet") - || BaseTestCase.currentModule.equals(GlobalConstants.MIMOTO))) + if ((!BaseTestCase.isTargetEnvLTS()) && fieldName.equals("VID") + && (BaseTestCase.currentModule.equals("auth") || BaseTestCase.currentModule.equals("esignet"))) autogenIdKeyName = autogenIdKeyName + "_" + fieldName.toLowerCase(); else autogenIdKeyName = autogenIdKeyName + "_" + fieldName; @@ -2963,9 +2962,10 @@ public String uriKeyWordHandelerUri(String uri, String testCaseName) { } public static String getAuthTransactionId(String oidcTransactionId) { - final String transactionId = oidcTransactionId.replaceAll("_|-", ""); - String lengthOfTransactionId = AdminTestUtil.getValueFromEsignetActuator("/mosip/mosip-config/esignet-default.properties", "mosip.esignet.auth-txn-id-length"); - int authTransactionIdLength = lengthOfTransactionId != null ? Integer.parseInt(lengthOfTransactionId): 0; + final String transactionId = oidcTransactionId.replaceAll("_|-", ""); + String lengthOfTransactionId = AdminTestUtil.getValueFromEsignetActuator( + ConfigManager.getEsignetActuatorPropertySection(), "mosip.esignet.auth-txn-id-length"); + int authTransactionIdLength = lengthOfTransactionId != null ? Integer.parseInt(lengthOfTransactionId): 0; final byte[] oidcTransactionIdBytes = transactionId.getBytes(); final byte[] authTransactionIdBytes = new byte[authTransactionIdLength]; int i = oidcTransactionIdBytes.length - 1; @@ -3005,6 +3005,9 @@ public String inputJsonKeyWordHandeler(String jsonString, String testCaseName) { jsonString = replaceKeywordWithValue(jsonString, "$POLICYNUMBERFORSUNBIRDRC$", properties.getProperty("policyNumberForSunBirdRC")); } + + + if (jsonString.contains("$FULLNAMEFORSUNBIRDRC$")) { jsonString = replaceKeywordWithValue(jsonString, "$FULLNAMEFORSUNBIRDRC$", fullNameForSunBirdRC); @@ -3114,6 +3117,8 @@ public String inputJsonKeyWordHandeler(String jsonString, String testCaseName) { } if (jsonString.contains("$1STLANG$")) jsonString = replaceKeywordWithValue(jsonString, "$1STLANG$", BaseTestCase.languageList.get(0)); + if (jsonString.contains("$2NDLANG$")) + jsonString = replaceKeywordWithValue(jsonString, "$2NDLANG$", BaseTestCase.languageList.get(1)); if (jsonString.contains(GlobalConstants.KEYCLOAK_USER_1)) @@ -3390,10 +3395,6 @@ public String inputJsonKeyWordHandeler(String jsonString, String testCaseName) { jsonString = replaceKeywordWithValue(jsonString, "$DOB$", getValueFromActuator(GlobalConstants.RESIDENT_DEFAULT_PROPERTIES, "mosip.date-of-birth.pattern")); } - if (jsonString.contains("$GETCLIENTIDFROMMIMOTOACTUATOR$")) { - jsonString = replaceKeywordWithValue(jsonString, "$GETCLIENTIDFROMMIMOTOACTUATOR$", - getValueFromMimotoActuator("configService:overrides", "mimoto.oidc.partner.clientid")); - } if (jsonString.contains("$IDPREDIRECTURI$")) { jsonString = replaceKeywordWithValue(jsonString, "$IDPREDIRECTURI$", ApplnURI.replace(GlobalConstants.API_INTERNAL, "healthservices") + "/userprofile"); @@ -3572,8 +3573,11 @@ public String inputJsonKeyWordHandeler(String jsonString, String testCaseName) { if (request.has("client_id")) { clientId = request.get("client_id").toString(); } + + String tempUrl = getValueFromEsignetWellKnownEndPoint("token_endpoint", ConfigManager.getEsignetBaseUrl()); + jsonString = replaceKeywordWithValue(jsonString, "$CLIENT_ASSERTION_JWK$", - signJWKKey(clientId, oidcJWKKey1)); + signJWKKey(clientId, oidcJWKKey1, tempUrl)); } if (jsonString.contains("$CLIENT_ASSERTION_USER3_JWK$")) { @@ -3590,8 +3594,10 @@ public String inputJsonKeyWordHandeler(String jsonString, String testCaseName) { if (request.has("client_id")) { clientId = request.get("client_id").toString(); } + + String tempUrl = getValueFromEsignetWellKnownEndPoint("token_endpoint", ConfigManager.getEsignetBaseUrl()); jsonString = replaceKeywordWithValue(jsonString, "$CLIENT_ASSERTION_USER3_JWK$", - signJWKKey(clientId, oidcJWKKey3)); + signJWKKey(clientId, oidcJWKKey3, tempUrl)); } if (jsonString.contains("$CLIENT_ASSERTION_USER4_JWK$")) { @@ -3617,8 +3623,9 @@ public String inputJsonKeyWordHandeler(String jsonString, String testCaseName) { "mosip.iam.module.clientID"); String esignetBaseURI = getValueFromActuator(GlobalConstants.RESIDENT_DEFAULT_PROPERTIES, "mosip.iam.token_endpoint"); - int idTokenExpirySecs = Integer.parseInt(getValueFromEsignetActuator( - GlobalConstants.ESIGNET_DEFAULT_PROPERTIES, GlobalConstants.MOSIP_ESIGNET_ID_TOKEN_EXPIRE_SECONDS)); + int idTokenExpirySecs = Integer + .parseInt(getValueFromEsignetActuator(ConfigManager.getEsignetActuatorPropertySection(), + GlobalConstants.MOSIP_ESIGNET_ID_TOKEN_EXPIRE_SECONDS)); Instant instant = Instant.now(); @@ -3737,10 +3744,14 @@ public String inputJsonKeyWordHandeler(String jsonString, String testCaseName) { } if (jsonString.contains("$NAMEFORUPDATEUIN$")) { - String name = getValueFromAuthActuator("json-property", "name"); - String nameResult = name.replaceAll("\\[\"|\"\\]", ""); - + String nameResult = ""; + + if (new JSONArray(name).length() > 1) { + nameResult = new JSONArray(name).getString(0); + }else { + nameResult = name.replaceAll("\\[\"|\"\\]", ""); + } jsonString = replaceKeywordWithValue(jsonString, "$NAMEFORUPDATEUIN$", nameResult); } @@ -3792,6 +3803,7 @@ public String inputJsonKeyWordHandeler(String jsonString, String testCaseName) { JSONObject request = new JSONObject(jsonString); String clientId = ""; String accessToken = ""; + String tempUrl = ""; if (request.has("client_id")) { clientId = request.getString("client_id"); request.remove("client_id"); @@ -3800,8 +3812,21 @@ public String inputJsonKeyWordHandeler(String jsonString, String testCaseName) { accessToken = request.getString("idpAccessToken"); } jsonString = request.toString(); + + if (BaseTestCase.currentModule.equals(GlobalConstants.INJICERTIFY)) { + String baseURL = ConfigManager.getInjiCertifyBaseUrl(); + if (testCaseName.contains("_GetCredentialSunBirdC")) { + tempUrl = getValueFromInjiCertifyWellKnownEndPoint("credential_issuer", + baseURL.replace("injicertify.", "injicertify-insurance.")); + } + } else { + tempUrl = getValueFromEsignetWellKnownEndPoint("issuer", ConfigManager.getEsignetBaseUrl()); + if (tempUrl.contains("esignet.")) { + tempUrl = tempUrl.replace("esignet.", propsKernel.getProperty("esignetMockBaseURL")); + } + } jsonString = replaceKeywordWithValue(jsonString, "$PROOF_JWT_2$", - signJWKForMock(clientId, accessToken, oidcJWKKey4, testCaseName)); + signJWKForMock(clientId, accessToken, oidcJWKKey4, testCaseName, tempUrl)); } if (jsonString.contains(GlobalConstants.REMOVE)) @@ -3810,14 +3835,11 @@ public String inputJsonKeyWordHandeler(String jsonString, String testCaseName) { return jsonString; } - public static String signJWKForMock(String clientId, String accessToken, RSAKey jwkKey, String testCaseName) { -// String tempUrl = getValueFromActuator(GlobalConstants.RESIDENT_DEFAULT_PROPERTIES, "mosip.iam.base.url"); - String tempUrl = getValueFromEsignetWellKnownEndPoint("issuer"); - if (tempUrl.contains("esignet.")) { - tempUrl = tempUrl.replace("esignet.", propsKernel.getProperty("esignetMockBaseURL")); - } - int idTokenExpirySecs = Integer.parseInt(getValueFromEsignetActuator(GlobalConstants.ESIGNET_DEFAULT_PROPERTIES, - GlobalConstants.MOSIP_ESIGNET_ID_TOKEN_EXPIRE_SECONDS)); + public static String signJWKForMock(String clientId, String accessToken, RSAKey jwkKey, String testCaseName, + String tempUrl) { + int idTokenExpirySecs = Integer + .parseInt(getValueFromEsignetActuator(ConfigManager.getEsignetActuatorPropertySection(), + GlobalConstants.MOSIP_ESIGNET_ID_TOKEN_EXPIRE_SECONDS)); JWSSigner signer; String proofJWT = ""; String typ = "openid4vci-proof+jwt"; @@ -3860,10 +3882,10 @@ public static String signJWKForMock(String clientId, String accessToken, RSAKey } public static String signJWK(String clientId, String accessToken, RSAKey jwkKey, String testCaseName) { -// String tempUrl = getValueFromActuator(GlobalConstants.RESIDENT_DEFAULT_PROPERTIES, "mosip.iam.base.url"); - String tempUrl = getValueFromEsignetWellKnownEndPoint("issuer"); - int idTokenExpirySecs = Integer.parseInt(getValueFromEsignetActuator(GlobalConstants.ESIGNET_DEFAULT_PROPERTIES, - GlobalConstants.MOSIP_ESIGNET_ID_TOKEN_EXPIRE_SECONDS)); + String tempUrl = getValueFromEsignetWellKnownEndPoint("issuer", ConfigManager.getEsignetBaseUrl()); + int idTokenExpirySecs = Integer + .parseInt(getValueFromEsignetActuator(ConfigManager.getEsignetActuatorPropertySection(), + GlobalConstants.MOSIP_ESIGNET_ID_TOKEN_EXPIRE_SECONDS)); JWSSigner signer; String proofJWT = ""; String typ = "openid4vci-proof+jwt"; @@ -4212,7 +4234,47 @@ private String replaceIdWithAutogeneratedId(String jsonString, String idKey, Str if (!jsonString.contains(idKey)) return jsonString; String keyForIdProperty = StringUtils.substringBetween(jsonString, idKey, "$"); - String keyToReplace = idKey + keyForIdProperty + "$"; + String keyToReplace = ""; + + // mock = email,phone; default + // mock = phone; + // mock = email; + + // $ID:AddIdentity_withValidParameters_smoke_Pos_EMAIL$ + + // $ID:AddIdentity_withValidParameters_smoke_Pos_PHONE$@phone + + + + if (keyForIdProperty.endsWith("_EMAIL") && ConfigManager.getMockNotificationChannel().equalsIgnoreCase("phone")) { + String temp = idKey + keyForIdProperty + "$" ; //$ID:AddIdentity_withValidParameters_smoke_Pos_EMAIL$ + keyForIdProperty = keyForIdProperty.replace("_EMAIL", "_PHONE"); // AddIdentity_withValidParameters_smoke_Pos_PHONE + keyToReplace = temp; // $ID:AddIdentity_withValidParameters_smoke_Pos_PHONE$@phone + + jsonString = jsonString.replace(temp, temp + "@phone"); + + + } else if (keyForIdProperty.endsWith("_PHONE") && ConfigManager.getMockNotificationChannel().equalsIgnoreCase("email")) { + String temp = idKey + keyForIdProperty + "$" ; //$ID:AddIdentity_withValidParameters_smoke_Pos_PHONE$ + keyForIdProperty = keyForIdProperty.replace("_PHONE", "_EMAIL"); // AddIdentity_withValidParameters_smoke_Pos_EMAIL + keyToReplace = temp + "@phone"; + } else { + keyToReplace = idKey + keyForIdProperty + "$"; //AddIdentity_withValidParameters_smoke_Pos_EMAIL + } + + + + + + + + + + + + + + Properties props = new Properties(); try (FileInputStream inputStream = new FileInputStream(getResourcePath() + autoGenIdFileName);) { @@ -4532,6 +4594,14 @@ private static ArrayList convertJson(String[] templateFields, String translatedValue = valueToConvert; isFilterRequired = true; } + } else if (jsonObject.has(GlobalConstants.KEYWORD_DATA)) { + String filterValueToConvert = jsonObject.getJSONArray(GlobalConstants.KEYWORD_DATA).get(0).toString(); + JSONObject filtervalue = new JSONObject(filterValueToConvert); + if (filtervalue.has(fieldToConvert)) { + valueToConvert = filtervalue.getString(fieldToConvert); + translatedValue = valueToConvert; + isFilterRequired = false; + } } if (!language.equalsIgnoreCase("eng") && valueToConvert != null) { @@ -4926,8 +4996,8 @@ public static String modifySchemaGenerateHbs(boolean regenerateHbs) { org.json.JSONObject responseJson = new org.json.JSONObject(response.asString()); org.json.JSONObject schemaData = (org.json.JSONObject) responseJson.get(GlobalConstants.RESPONSE); - Double schemaVersion = (Double) schemaData.get(GlobalConstants.ID_VERSION); - idSchemaVersion = (Double) schemaData.get(GlobalConstants.ID_VERSION); + Double schemaVersion = ((BigDecimal) schemaData.get(GlobalConstants.ID_VERSION)).doubleValue(); + idSchemaVersion = ((BigDecimal) schemaData.get(GlobalConstants.ID_VERSION)).doubleValue(); String schemaJsonData = schemaData.getString(GlobalConstants.SCHEMA_JSON); String schemaFile = schemaJsonData; @@ -4968,7 +5038,10 @@ public static String modifySchemaGenerateHbs(boolean regenerateHbs) { requestJson.getJSONObject("request").put("registrationId", "{{registrationId}}"); JSONObject identityJson = new JSONObject(); identityJson.put("UIN", "{{UIN}}"); + JSONArray handleArray = new JSONArray(); + handleArray.put("handles"); + List selectedHandles = new ArrayList<>(); //requiredPropsArray.put("functionalId"); for (int i = 0, size = requiredPropsArray.length(); i < size; i++) { String eachRequiredProp = requiredPropsArray.getString(i); @@ -4993,17 +5066,30 @@ public static String modifySchemaGenerateHbs(boolean regenerateHbs) { JSONObject eachValueJsonForHandles = new JSONObject(); if (eachRequiredProp.equals(emailResult)) { eachValueJsonForHandles.put("value", "$EMAILVALUE$"); + eachValueJsonForHandles.put("tags", handleArray); + selectedHandles.add(emailResult); + } else if (eachRequiredProp.equals(result)) { eachValueJsonForHandles.put("value", "$PHONENUMBERFORIDENTITY$"); + //"tags": ":["handle"] + eachValueJsonForHandles.put("tags", handleArray); + selectedHandles.add(result); } else { - eachValueJsonForHandles.put("value", "1726266"); + eachValueJsonForHandles.put("value", "$FUNCTIONALID$"); + eachValueJsonForHandles.put("tags", handleArray); + selectedHandles.add(eachRequiredProp); } eachPropDataArrayForHandles.put(eachValueJsonForHandles); - identityJson.put(eachRequiredProp, eachPropDataArrayForHandles); + identityJson.put(eachRequiredProp, eachPropDataArrayForHandles); + } - + + else if (eachPropDataJson.has("$ref") && eachPropDataJson.get("$ref").toString().contains("simpleType")) { + if(eachPropDataJson.has("handle")){ + selectedHandles.add(eachRequiredProp); + } JSONArray eachPropDataArray = new JSONArray(); for (int j = 0; j < BaseTestCase.getLanguageList().size(); j++) { @@ -5026,8 +5112,10 @@ else if (eachPropDataJson.has("$ref") && eachPropDataJson.get("$ref").toString() } } identityJson.put(eachRequiredProp, eachPropDataArray); + } else { if (eachRequiredProp.equals("proofOfIdentity")) { + identityJson.put(eachRequiredProp, new HashMap<>()); identityJson.getJSONObject(eachRequiredProp).put("format", "txt"); identityJson.getJSONObject(eachRequiredProp).put("type", "DOC001"); @@ -5043,8 +5131,18 @@ else if (eachPropDataJson.has("$ref") && eachPropDataJson.get("$ref").toString() identityJson.put(eachRequiredProp, genStringAsperRegex( eachPropDataJson.getJSONArray("validators").getJSONObject(0).getString("validator"))); } else if (eachRequiredProp.equals(result)) { + if(eachPropDataJson.has("handle")){ + selectedHandles.add(eachRequiredProp); + } identityJson.put(eachRequiredProp, "$PHONENUMBERFORIDENTITY$"); - } else if (eachRequiredProp.equals("password")) { + } else if (eachRequiredProp.equals(emailResult)) { + if(eachPropDataJson.has("handle")){ + selectedHandles.add(eachRequiredProp); + } + identityJson.put(eachRequiredProp, "$EMAILVALUE$"); + } + + else if (eachRequiredProp.equals("password")) { identityJson.put(eachRequiredProp, new HashMap<>()); if (addIdentityPassword.isBlank() && addIdentitySalt.isBlank()) getPasswordSaltFromKeyManager(PASSWORD_FOR_ADDIDENTITY_AND_REGISTRATION); @@ -5058,10 +5156,18 @@ else if (eachPropDataJson.has("$ref") && eachPropDataJson.get("$ref").toString() } else if (eachRequiredProp.equals("IDSchemaVersion")) { identityJson.put(eachRequiredProp, schemaVersion); } else { + if(eachPropDataJson.has("handle")){ + selectedHandles.add(eachRequiredProp); + } identityJson.put(eachRequiredProp, "{{" + eachRequiredProp + "}}"); } } } + if (selectedHandles != null && selectedHandles.size()>=1) { + setfoundHandlesInIdSchema(true); + identityJson.put("selectedHandles", selectedHandles); + } + // Constructing and adding functionalIds JSONArray functionalIdsArray = new JSONArray(); @@ -5097,6 +5203,199 @@ else if (eachPropDataJson.has("$ref") && eachPropDataJson.get("$ref").toString() return identityHbs; } + + public static String updateIdentityHbs(boolean regenerateHbs) { + if (updateIdentityHbs != null && !regenerateHbs) { + + return updateIdentityHbs; + } + JSONObject requestJson = new JSONObject(); + kernelAuthLib = new KernelAuthentication(); + String token = kernelAuthLib.getTokenByRole(GlobalConstants.ADMIN); + String url = ApplnURI + properties.getProperty(GlobalConstants.MASTER_SCHEMA_URL); + + Response response = RestClient.getRequestWithCookie(url, MediaType.APPLICATION_JSON, MediaType.APPLICATION_JSON, + GlobalConstants.AUTHORIZATION, token); + + org.json.JSONObject responseJson = new org.json.JSONObject(response.asString()); + org.json.JSONObject schemaData = (org.json.JSONObject) responseJson.get(GlobalConstants.RESPONSE); + + Double schemaVersion = ((BigDecimal) schemaData.get(GlobalConstants.ID_VERSION)).doubleValue(); + idSchemaVersion = ((BigDecimal) schemaData.get(GlobalConstants.ID_VERSION)).doubleValue(); + String schemaJsonData = schemaData.getString(GlobalConstants.SCHEMA_JSON); + + String schemaFile = schemaJsonData; + + boolean emailFieldAdditionallyAdded = false; + boolean phoneFieldAdditionallyAdded = false; + try { + JSONObject schemaFileJson = new JSONObject(schemaFile); + JSONObject schemaPropsJson = schemaFileJson.getJSONObject("properties"); + JSONObject schemaIdentityJson = schemaPropsJson.getJSONObject("identity"); + JSONObject identityPropsJson = schemaIdentityJson.getJSONObject("properties"); + JSONArray requiredPropsArray = schemaIdentityJson.getJSONArray("required"); + + schemaRequiredField = requiredPropsArray.toString(); + + String phone = getValueFromAuthActuator("json-property", "phone_number"); + String result = phone.replaceAll("\\[\"|\"\\]", ""); + + if (!isElementPresent(requiredPropsArray, result)) { + requiredPropsArray.put(result); + phoneFieldAdditionallyAdded = true; + } + if (identityPropsJson.has(result)) { + phoneSchemaRegex = identityPropsJson.getJSONObject(result).getJSONArray("validators") + .getJSONObject(0).getString("validator"); + } + + String email = getValueFromAuthActuator("json-property", "emailId"); + String emailResult = email.replaceAll("\\[\"|\"\\]", ""); + + if (!isElementPresent(requiredPropsArray, emailResult)) { + requiredPropsArray.put(emailResult); + emailFieldAdditionallyAdded = true; + } + + requestJson.put("id", "{{id}}"); + requestJson.put("status", "ACTIVATED"); + requestJson.put("request", new HashMap<>()); + requestJson.getJSONObject("request").put("registrationId", "{{registrationId}}"); + JSONObject identityJson = new JSONObject(); + identityJson.put("UIN", "{{UIN}}"); + JSONArray handleArray = new JSONArray(); + handleArray.put("handles"); + + List selectedHandles = new ArrayList<>(); + //requiredPropsArray.put("functionalId"); + for (int i = 0, size = requiredPropsArray.length(); i < size; i++) { + String eachRequiredProp = requiredPropsArray.getString(i); + + if (!identityPropsJson.has(eachRequiredProp)) { + continue; + } + + JSONObject eachPropDataJson = (JSONObject) identityPropsJson.get(eachRequiredProp); + String randomValue = ""; + if(eachRequiredProp == emailResult) { + randomValue ="shshssh"; + } + if(eachRequiredProp == result) { + randomValue =phoneSchemaRegex ; + } + + + // Processing for TaggedListType + if (eachPropDataJson.has("$ref") && eachPropDataJson.get("$ref").toString().contains("TaggedListType")) { + JSONArray eachPropDataArrayForHandles = new JSONArray(); + JSONObject eachValueJsonForHandles = new JSONObject(); + if (eachRequiredProp.equals(emailResult)) { + eachValueJsonForHandles.put("value", "$EMAILVALUE$"); + eachValueJsonForHandles.put("tags", handleArray); + selectedHandles.add(emailResult); + + } else if (eachRequiredProp.equals(result)) { + eachValueJsonForHandles.put("value", "$PHONENUMBERFORIDENTITY$"); + //"tags": ":["handle"] + eachValueJsonForHandles.put("tags", handleArray); + selectedHandles.add(result); + } else { + eachValueJsonForHandles.put("value", "$FUNCTIONALID$"); + eachValueJsonForHandles.put("tags", handleArray); + selectedHandles.add(eachRequiredProp); + } + eachPropDataArrayForHandles.put(eachValueJsonForHandles); + identityJson.put(eachRequiredProp, eachPropDataArrayForHandles); + + } + + + + else if (eachPropDataJson.has("$ref") && eachPropDataJson.get("$ref").toString().contains("simpleType")) { + if(eachPropDataJson.has("handle")){ + selectedHandles.add(eachRequiredProp); + } + JSONArray eachPropDataArray = new JSONArray(); + + for (int j = 0; j < BaseTestCase.getLanguageList().size(); j++) { + if (BaseTestCase.getLanguageList().get(j) != null + && !BaseTestCase.getLanguageList().get(j).isEmpty()) { + JSONObject eachValueJson = new JSONObject(); + eachValueJson.put("language", BaseTestCase.getLanguageList().get(j)); + if (eachRequiredProp.contains(GlobalConstants.FULLNAME) && regenerateHbs == true) { + eachValueJson.put(GlobalConstants.VALUE, propsMap.getProperty(eachRequiredProp + "1")); + } else if (eachRequiredProp.contains(GlobalConstants.FIRST_NAME) && regenerateHbs == true) { + eachValueJson.put(GlobalConstants.VALUE, propsMap.getProperty(eachRequiredProp + 1)); + } else if (eachRequiredProp.contains(GlobalConstants.GENDER)) { + eachValueJson.put(GlobalConstants.VALUE, propsMap.getProperty(eachRequiredProp)); + } else { + eachValueJson.put(GlobalConstants.VALUE, + (propsMap.getProperty(eachRequiredProp) == null) ? "TEST_" + eachRequiredProp + : propsMap.getProperty(eachRequiredProp) + BaseTestCase.getLanguageList().get(j)); + } + eachPropDataArray.put(eachValueJson); + } + } + identityJson.put(eachRequiredProp, eachPropDataArray); + + } else { + if (eachRequiredProp.equals("IDSchemaVersion")) { + identityJson.put(eachRequiredProp, schemaVersion); + } + else if (eachRequiredProp.equals("individualBiometrics")) { + identityJson.remove("individualBiometrics"); + } + else if (eachRequiredProp.equals(emailResult)) { + if(eachPropDataJson.has("handle")){ + selectedHandles.add(eachRequiredProp); + } + identityJson.put(eachRequiredProp, "$EMAILVALUE$"); + } + else if (eachRequiredProp.equals(result)) { + if(eachPropDataJson.has("handle")){ + selectedHandles.add(eachRequiredProp); + } + identityJson.put(eachRequiredProp, "$PHONENUMBERFORIDENTITY$"); + } + else if (eachRequiredProp.equals("proofOfIdentity")) { + identityJson.remove("proofOfIdentity"); + } + else { + if(eachPropDataJson.has("handle")){ + selectedHandles.add(eachRequiredProp); + } + identityJson.put(eachRequiredProp, "{{" + eachRequiredProp + "}}"); + } + } + } + if (selectedHandles != null) { + setfoundHandlesInIdSchema(true); + identityJson.put("selectedHandles", selectedHandles); + } + + + // Constructing and adding functionalIds + JSONArray functionalIdsArray = new JSONArray(); + for (String language : BaseTestCase.getLanguageList()) { + if (language != null && !language.isEmpty()) { + JSONObject functionalId = new JSONObject(); + functionalId.put("value", "TEST_CITY" + language); + functionalIdsArray.put(functionalId); + } + } + requestJson.getJSONObject("request").put("identity", identityJson); + requestJson.put("requesttime", "{{requesttime}}"); + requestJson.put("version", "{{version}}"); + + System.out.println(requestJson); + + } catch (Exception e) { + logger.error(e.getMessage()); + } + + updateIdentityHbs = requestJson.toString(); + return updateIdentityHbs; + } public static int generateLatestSchemaVersion() { @@ -5111,7 +5410,7 @@ public static int generateLatestSchemaVersion() { org.json.JSONObject responseJson = new org.json.JSONObject(response.asString()); org.json.JSONObject schemaData = (org.json.JSONObject) responseJson.get(GlobalConstants.RESPONSE); - Double schemaVersion = (Double) schemaData.get(GlobalConstants.ID_VERSION); + Double schemaVersion = ((BigDecimal) schemaData.get(GlobalConstants.ID_VERSION)).doubleValue(); int latestSchemaVersion = Double.valueOf(schemaVersion).intValue(); logger.info(latestSchemaVersion); return latestSchemaVersion; @@ -5134,7 +5433,7 @@ public static String generateHbsForUpdateDraft() { org.json.JSONObject responseJson = new org.json.JSONObject(response.asString()); org.json.JSONObject schemaData = (org.json.JSONObject) responseJson.get(GlobalConstants.RESPONSE); - Double schemaVersion = (Double) schemaData.get(GlobalConstants.ID_VERSION); + Double schemaVersion = ((BigDecimal) schemaData.get(GlobalConstants.ID_VERSION)).doubleValue(); logger.info(schemaVersion); String schemaJsonData = schemaData.getString(GlobalConstants.SCHEMA_JSON); @@ -5423,7 +5722,7 @@ public static String generateHbsForPrereg(boolean isItUpdate) { org.json.JSONObject responseJson = new org.json.JSONObject(response.asString()); org.json.JSONObject schemaData = (org.json.JSONObject) responseJson.get(GlobalConstants.RESPONSE); - Double schemaVersion = (Double) schemaData.get(GlobalConstants.ID_VERSION); + Double schemaVersion = ((BigDecimal) schemaData.get(GlobalConstants.ID_VERSION)).doubleValue(); logger.info(schemaVersion); String schemaJsonData = schemaData.getString(GlobalConstants.SCHEMA_JSON); @@ -5951,13 +6250,13 @@ public static void createAndPublishPolicyForKyc() { // } public static String signJWKKeyForMock(String clientId, RSAKey jwkKey) { -// String tempUrl = getValueFromActuator(GlobalConstants.RESIDENT_DEFAULT_PROPERTIES, "mosip.iam.token_endpoint"); - String tempUrl = getValueFromEsignetWellKnownEndPoint("token_endpoint"); + String tempUrl = getValueFromEsignetWellKnownEndPoint("token_endpoint", ConfigManager.getEsignetBaseUrl()); if (tempUrl.contains("esignet.")) { tempUrl = tempUrl.replace("esignet.", propsKernel.getProperty("esignetMockBaseURL")); } - int idTokenExpirySecs = Integer.parseInt(getValueFromEsignetActuator(GlobalConstants.ESIGNET_DEFAULT_PROPERTIES, - GlobalConstants.MOSIP_ESIGNET_ID_TOKEN_EXPIRE_SECONDS)); + int idTokenExpirySecs = Integer + .parseInt(getValueFromEsignetActuator(ConfigManager.getEsignetActuatorPropertySection(), + GlobalConstants.MOSIP_ESIGNET_ID_TOKEN_EXPIRE_SECONDS)); JWSSigner signer; try { @@ -5991,11 +6290,10 @@ public static String signJWKKeyForMock(String clientId, RSAKey jwkKey) { return clientAssertionToken; } - public static String signJWKKey(String clientId, RSAKey jwkKey) { -// String tempUrl = getValueFromActuator(GlobalConstants.RESIDENT_DEFAULT_PROPERTIES, "mosip.iam.token_endpoint"); - String tempUrl = getValueFromEsignetWellKnownEndPoint("token_endpoint"); - int idTokenExpirySecs = Integer.parseInt(getValueFromEsignetActuator(GlobalConstants.ESIGNET_DEFAULT_PROPERTIES, - GlobalConstants.MOSIP_ESIGNET_ID_TOKEN_EXPIRE_SECONDS)); + public static String signJWKKey(String clientId, RSAKey jwkKey, String tempUrl) { + int idTokenExpirySecs = Integer + .parseInt(getValueFromEsignetActuator(ConfigManager.getEsignetActuatorPropertySection(), + GlobalConstants.MOSIP_ESIGNET_ID_TOKEN_EXPIRE_SECONDS)); JWSSigner signer; try { @@ -6032,8 +6330,9 @@ public static String signJWKKey(String clientId, RSAKey jwkKey) { public static String getWlaToken(String individualId, RSAKey jwkKey, String certData) throws JoseException, JOSEException { String tempUrl = propsKernel.getProperty("validateBindingEndpoint"); - int idTokenExpirySecs = Integer.parseInt(getValueFromEsignetActuator(GlobalConstants.ESIGNET_DEFAULT_PROPERTIES, - GlobalConstants.MOSIP_ESIGNET_ID_TOKEN_EXPIRE_SECONDS)); + int idTokenExpirySecs = Integer + .parseInt(getValueFromEsignetActuator(ConfigManager.getEsignetActuatorPropertySection(), + GlobalConstants.MOSIP_ESIGNET_ID_TOKEN_EXPIRE_SECONDS)); Instant instant = Instant.now(); long epochValue = instant.getEpochSecond(); @@ -6125,8 +6424,8 @@ public static int getOtpExpTimeFromActuator() { return Integer.parseInt(otpExpTime); } - public static String getValueFromEsignetWellKnownEndPoint(String key) { - String url = ConfigManager.getEsignetBaseUrl() + propsKernel.getProperty("esignetWellKnownEndPoint"); + public static String getValueFromEsignetWellKnownEndPoint(String key, String baseURL) { + String url = baseURL + propsKernel.getProperty("esignetWellKnownEndPoint"); Response response = null; JSONObject responseJson = null; if (responseJson == null) { @@ -6140,6 +6439,29 @@ public static String getValueFromEsignetWellKnownEndPoint(String key) { } return responseJson.getString(key); } + + public static String getValueFromInjiCertifyWellKnownEndPoint(String key, String baseURL) { + String url = baseURL + propsKernel.getProperty("injiCertifyWellKnownEndPoint"); + + String actuatorCacheKey = url + key; + String value = actuatorValueCache.get(actuatorCacheKey); + if (value != null && !value.isEmpty()) + return value; + + Response response = null; + JSONObject responseJson = null; + try { + response = RestClient.getRequest(url, MediaType.APPLICATION_JSON, MediaType.APPLICATION_JSON); + responseJson = new org.json.JSONObject(response.getBody().asString()); + if (responseJson.has(key)) { + actuatorValueCache.put(actuatorCacheKey, responseJson.getString(key)); + return responseJson.getString(key); + } + } catch (Exception e) { + logger.error(GlobalConstants.EXCEPTION_STRING_2 + e); + } + return responseJson.getString(key); + } public static JSONObject signUpSettingsResponseJson = null; @@ -6214,17 +6536,16 @@ public static String getValueFromActuator(String section, String key) { } public static JSONArray mimotoActuatorResponseArray = null; - private static String otpEnabled = "true"; - - public static String isOTPEnabled() { - String value = getValueFromMimotoActuator("/mimoto-default.properties", "mosip.otp.download.enable"); - if (value != null && !(value.isBlank())) - otpEnabled = value; - return otpEnabled; - } public static String getValueFromMimotoActuator(String section, String key) { String url = ApplnURI + propsKernel.getProperty("actuatorMimotoEndpoint"); + if (!(System.getenv("useOldContextURL") == null) + && !(System.getenv("useOldContextURL").isBlank()) + && System.getenv("useOldContextURL").equalsIgnoreCase("true")) { + if (url.contains("/v1/mimoto/")) { + url = url.replace("/v1/mimoto/", "/residentmobileapp/"); + } + } String actuatorCacheKey = url + section + key; String value = actuatorValueCache.get(actuatorCacheKey); if (value != null && !value.isEmpty()) @@ -6475,6 +6796,12 @@ public static String isTestCaseValidForExecution(TestCaseDTO testCaseDTO) { && (!isElementPresent(new JSONArray(schemaRequiredField), dob))) { throw new SkipException(GlobalConstants.FEATURE_NOT_SUPPORTED_MESSAGE); } + + if (testCaseName.startsWith("IdRepository_") && testCaseName.contains("_handle") && foundHandlesInIdSchema == false) { + throw new SkipException(GlobalConstants.HANDLE_SCHEMA_NOT_DEPLOYED_MESSAGE); + } + + else if (testCaseName.startsWith("IdRepository_") && testCaseName.contains("Email") && (!isElementPresent(new JSONArray(schemaRequiredField), email))) { @@ -6516,22 +6843,14 @@ else if (testCaseName.startsWith("IdRepository_") && testCaseName.contains("Inva && (!isElementPresent(new JSONArray(schemaRequiredField), individualBiometrics))) { throw new SkipException(GlobalConstants.FEATURE_NOT_SUPPORTED_MESSAGE); } - } else if (BaseTestCase.currentModule.equalsIgnoreCase(GlobalConstants.MIMOTO)) { - if (isOTPEnabled().equals("false") && (testCaseDTO.getEndPoint().contains(GlobalConstants.SEND_OTP_ENDPOINT) - || testCaseDTO.getInput().contains(GlobalConstants.SEND_OTP_ENDPOINT) - || testCaseName.startsWith(GlobalConstants.MIMOTO_CREDENTIAL_STATUS))) { - throw new SkipException(GlobalConstants.OTP_FEATURE_NOT_SUPPORTED); - } else if (isOTPEnabled().equals("true") - && testCaseDTO.getEndPoint().contains(GlobalConstants.CREATE_VID_ENDPOINT)) { - throw new SkipException( - GlobalConstants.VID_GENERATED_USING_RESIDENT_API_SO_FEATURE_NOT_SUPPORTED_OR_NEEDED_MESSAGE); - } } if ((ConfigManager.isInServiceNotDeployedList(GlobalConstants.ESIGNET)) && BaseTestCase.currentModule.equalsIgnoreCase("resident") && testCaseName.contains("_SignJWT_")) { throw new SkipException("esignet module is not deployed"); } + + if ((ConfigManager.isInServiceNotDeployedList(GlobalConstants.ESIGNET)) && BaseTestCase.currentModule.equalsIgnoreCase("resident") @@ -6763,7 +7082,8 @@ public static String smtpOtpHandler(String inputJson, String testCaseName) { } } if (BaseTestCase.currentModule.equals(GlobalConstants.ESIGNET) - || testCaseName.startsWith("Mimoto_WalletBinding")) { + || testCaseName.startsWith("Mimoto_WalletBinding") + || testCaseName.startsWith("Mimoto_ESignet_AuthenticateUser")) { if (request.has(GlobalConstants.REQUEST)) { if (request.getJSONObject(GlobalConstants.REQUEST).has("otp")) { if (request.getJSONObject(GlobalConstants.REQUEST).getString("otp") @@ -6961,6 +7281,7 @@ public static void getLocationData() { JSONObject responseJson = null; String url = ApplnURI + props.getProperty("fetchLocationData"); String token = kernelAuthLib.getTokenByRole(GlobalConstants.ADMIN); + int recommendedHierarchyLevel = getRecommendedHierarchyLevel(); try { response = RestClient.getRequestWithCookie(url, MediaType.APPLICATION_JSON, MediaType.APPLICATION_JSON, GlobalConstants.AUTHORIZATION, token); @@ -6971,15 +7292,21 @@ public static void getLocationData() { JSONObject responseObject = responseJson.getJSONObject("response"); JSONArray data = responseObject.getJSONArray("data"); + if (!(languageList.size() > 1)) { + currentLanguage = BaseTestCase.languageList.get(0); + } + for (int i = 0; i < data.length(); i++) { JSONObject entry = data.getJSONObject(i); String langCode = entry.getString("langCode"); - - if (BaseTestCase.languageList.get(0).equals(langCode)) { - hierarchyName = entry.getString("hierarchyName"); - hierarchyLevel = entry.getInt("hierarchyLevel"); - parentLocCode = entry.optString("parentLocCode", ""); - break; + hierarchyLevel = entry.getInt("hierarchyLevel"); + + if (hierarchyLevel == recommendedHierarchyLevel) { + if (currentLanguage.equals(langCode)) { + hierarchyName = entry.getString("hierarchyName"); + parentLocCode = entry.optString("parentLocCode", ""); + break; + } } } @@ -7312,6 +7639,654 @@ public static boolean IsCertSyncd(String certSubjectSubString) { return false; } + public String replaceArrayHandleValues(String inputJson, String testCaseName) { + JSONObject jsonObj = new JSONObject(inputJson); + JSONObject request = jsonObj.getJSONObject("request"); + JSONObject identity = request.getJSONObject("identity"); + JSONArray selectedHandles = identity.getJSONArray("selectedHandles"); + String email = getValueFromAuthActuator("json-property", "emailId"); + String emailResult = email.replaceAll("\\[\"|\"\\]", ""); + + for (int i = 0; i < selectedHandles.length(); i++) { + String handle = selectedHandles.getString(i); + + if (identity.has(handle)) { + Object handleObj = identity.get(handle); // Dynamically get the handle object + + // Check if the handle is an array + if (handleObj instanceof JSONArray) { + JSONArray handleArray = (JSONArray) handleObj; + + if (testCaseName.contains("_onlywithtags")) { + for (int j = 0; j < handleArray.length(); j++) { + JSONObject obj = handleArray.getJSONObject(j); + obj.remove("value"); + } + } else if (testCaseName.contains("_withouttags")) { + for (int j = 0; j < handleArray.length(); j++) { + JSONObject obj = handleArray.getJSONObject(j); + obj.remove("tags"); + } + } else if (testCaseName.contains("_withtagwithoutselectedhandles")) { + for (int j = 0; j < handleArray.length(); j++) { + JSONObject obj = handleArray.getJSONObject(j); + obj.remove("selectedHandles"); + } + } else if (testCaseName.contains("_withinvalidtag")) { + for (int j = 0; j < handleArray.length(); j++) { + JSONObject obj = handleArray.getJSONObject(j); + JSONArray tags = obj.optJSONArray("tags"); + if (tags != null) { + for (int k = 0; k < tags.length(); k++) { + String tag = tags.getString(k); + tags.put(k, tag + "_invalid" + "RANDOM_ID"); + } + obj.put("tags", tags); + } + } + } else if (testCaseName.contains("_withmultiplevalues")) { + for (int j = 0; j < handleArray.length(); j++) { + JSONObject obj = handleArray.getJSONObject(j); + JSONArray valuesArray = new JSONArray(); + valuesArray.put("mosip501724826584965_modified_1"); + valuesArray.put("mosip501724826584965_modified_2"); + valuesArray.put("mosip501724826584965_modified_3"); + obj.put("values", valuesArray); + } + } else if (testCaseName.contains("_withmultiplevaluesandwithouttags")) { + for (int j = 0; j < handleArray.length(); j++) { + JSONObject obj = handleArray.getJSONObject(j); + JSONArray valuesArray = new JSONArray(); + valuesArray.put("mosip501724826584965_modified_1"); + valuesArray.put("mosip501724826584965_modified_2"); + valuesArray.put("mosip501724826584965_modified_3"); + obj.put("values", valuesArray); + obj.remove("tags"); + } + } else if (testCaseName.contains("_withemptyselecthandles")) { + identity.put("selectedHandles", new JSONArray()); + } else if (testCaseName.contains("_withoutselectedhandles")) { + identity.remove("selectedHandles"); + break; + } else if (testCaseName.contains("_withmultiplehandleswithoutvalue")) { + String phone = getValueFromAuthActuator("json-property", "phone_number"); + String result = phone.replaceAll("\\[\"|\"\\]", ""); + boolean containsPhone = false; + for (int j = 0; j < selectedHandles.length(); j++) { + if (result.equalsIgnoreCase(selectedHandles.getString(j))) { + containsPhone = true; + break; + } + } + if (!containsPhone) { + selectedHandles.put(result); + JSONObject phoneEntry = new JSONObject(); + phoneEntry.put("value", "$PHONENUMBERFORIDENTITY$"); + JSONArray phoneArray = new JSONArray(); + phoneArray.put(phoneEntry); + identity.put(result, phoneArray); + } + for (int j = 0; j < handleArray.length(); j++) { + JSONObject obj = handleArray.getJSONObject(j); + obj.remove("value"); + } + } else if (testCaseName.contains("_withfunctionalIds") && handle.equals("functionalId")) { + for (int j = 0; j < handleArray.length(); j++) { + JSONObject obj = handleArray.getJSONObject(j); + obj.remove("tags"); + } + } else if (testCaseName.contains("_withfunctionalIdsUsedFirstTwoValue") && handle.equals("functionalId")) { + if (handleArray.length() < 3) { + JSONObject secondValue = new JSONObject(); + secondValue.put("value", "RANDOM_ID_2" + 12); + secondValue.put("tags", new JSONArray().put("handle")); + JSONObject thirdValue = new JSONObject(); + thirdValue.put("value", "RANDOM_ID_2" + 34); + handleArray.put(secondValue); + handleArray.put(thirdValue); + } + } else if (testCaseName.contains("_withfunctionalIdsandPhoneWithoutTags")) { + String phone = getValueFromAuthActuator("json-property", "phone_number"); + String result = phone.replaceAll("\\[\"|\"\\]", ""); + boolean containsPhone = false; + for (int j = 0; j < selectedHandles.length(); j++) { + if (result.equalsIgnoreCase(selectedHandles.getString(j))) { + containsPhone = true; + break; + } + } + if (!containsPhone) { + selectedHandles.put(result); + JSONObject phoneEntry = new JSONObject(); + phoneEntry.put("value", "$PHONENUMBERFORIDENTITY$"); + JSONArray phoneArray = new JSONArray(); + phoneArray.put(phoneEntry); + identity.put(result, phoneArray); + } + for (int j = 0; j < handleArray.length(); j++) { + JSONObject obj = handleArray.getJSONObject(j); + obj.remove("tags"); + } + } else if (testCaseName.contains("_withfunctionalIdsUsedFirstTwoValueOutOfFive")) { + String baseValue = ""; + if (handleArray.length() > 0) { + baseValue = handleArray.getJSONObject(0).getString("value"); + } + for (int j = 0; j < 4; j++) { + JSONObject obj = new JSONObject(); + if (j < 1) { + obj.put("value", baseValue + j); + obj.put("tags", new JSONArray().put("handle")); + } else { + obj.put("value", baseValue + j); + } + handleArray.put(obj); + } + } + //43 in update identity + else if (testCaseName.contains("_removeexceptfirsthandle")) { + if (identity.has("selectedHandles")) { + + if (selectedHandles.length() > 0) { + String firstHandleToKeep = selectedHandles.getString(0); + + for (int j = 1; j < selectedHandles.length(); j++) { + if (identity.has(handle)) { + identity.remove(handle); + } + } + while (selectedHandles.length() > 1) { + selectedHandles.remove(1); + } + } + } + } + //44 in update identity + else if (testCaseName.contains("_withinvaliddemofield_inupdate")) { + if (identity.has("selectedHandles")) { + + if (selectedHandles.length() > 0) { + String firstHandleToKeep = selectedHandles.getString(0); + + for (int j = 1; j < selectedHandles.length(); j++) { + if (identity.has(handle)) { + identity.remove(handle); + } + } + while (selectedHandles.length() > 1) { + selectedHandles.remove(1); + } + } + } + } + //50 + else if (testCaseName.contains("_withonedemofield")) { + if (identity.has("selectedHandles")) { + String firstHandle = selectedHandles.getString(0); + for (int j = 1; j < selectedHandles.length(); j++) { + if (identity.has(handle)) { + Object handleValue = identity.get(handle); + if (handleValue instanceof JSONArray) { + identity.remove(handle); + } + } + } + JSONArray newSelectedHandles = new JSONArray(); + newSelectedHandles.put(firstHandle); + identity.put("selectedHandles", newSelectedHandles); + } + } + + //82 + + else if (testCaseName.contains("_withcasesensitivehandles")) { + for (int j = 0; j < handleArray.length(); j++) { + JSONObject obj = handleArray.getJSONObject(j); + obj.put("value", "HANDLES"); + } + } + //77 + else if (testCaseName.contains("_replaceselectedhandles")) { + identity.put("selectedHandles", new JSONArray().put(emailResult)); + } + //76 + else if (testCaseName.contains("_onlywithemail")) { + identity.put("selectedHandles", new JSONArray().put(emailResult)); + } + + //73 + else if (testCaseName.contains("_withoutselectedhandlesinidentity")) { + identity.remove("selectedHandles"); + } + + else if (testCaseName.contains("_withdublicatevalue")) { + for (int j = 0; j < handleArray.length(); j++) { + JSONObject obj = handleArray.getJSONObject(j); + if (testCaseName.contains("_save_withdublicatevalue")) + selectedHandlesValue=obj.getString("value"); + obj.put("value", selectedHandlesValue); + } + } + else if (testCaseName.contains("_withmultipledublicatevalue")) { + JSONObject secondValue = new JSONObject(); + secondValue.put("value", selectedHandlesValue); + secondValue.put("tags", new JSONArray().put("handle")); + handleArray.put(secondValue); + } + else if (testCaseName.contains("_removevalueaddexistingvalue")) { + for (int j = 0; j < handleArray.length(); j++) { + JSONObject obj = handleArray.getJSONObject(j); + obj.remove("value"); + obj.put("value", selectedHandlesValue); + } + } + else if (testCaseName.contains("_withselectedhandlephone")) { + if (identity.has("selectedHandles")) { + // Remove "email" and "functionalId", keep only "phone" + JSONArray updatedHandles = new JSONArray(); + boolean containsPhone = false; + + for (int j = 0; j < selectedHandles.length(); j++) { + handle = selectedHandles.getString(j); + if (handle.equalsIgnoreCase("phone")) { + containsPhone = true; + updatedHandles.put("phone"); // Ensure "phone" is kept + } + } + + // Add "phone" if not present + if (!containsPhone) { + updatedHandles.put("phone"); + } + + // Update the identity with the modified selectedHandles array + identity.put("selectedHandles", updatedHandles); + }else if (testCaseName.contains("_removealltagshandles")) { + removeTagsHandles(jsonObj); + + + } else { + // If "selectedHandles" doesn't exist, create it with "phone" + JSONArray newSelectedHandles = new JSONArray(); + newSelectedHandles.put("phone"); + identity.put("selectedHandles", newSelectedHandles); + } + } + + + else { + for (int j = 0; j < handleArray.length(); j++) { + JSONObject obj = handleArray.getJSONObject(j); + obj.put("value", obj.getString("value")); + } + } + + identity.put(handle, handleArray); + } + } + } + + return jsonObj.toString(); + } + private void removeTagsHandles(JSONObject jsonObj) { + for (String key : jsonObj.keySet()) { + Object value = jsonObj.get(key); + if (value instanceof JSONObject) { + JSONObject nestedObject = (JSONObject) value; + if (nestedObject.has("tags")) { + JSONArray tagsArray = nestedObject.getJSONArray("tags"); + if (tagsArray.length() == 1 && "handles".equals(tagsArray.getString(0))) { + nestedObject.remove("tags"); + } + } + removeTagsHandles(nestedObject); // Recursively call for deeper levels + } else if (value instanceof JSONArray) { + JSONArray jsonArray = (JSONArray) value; + for (int i = 0; i < jsonArray.length(); i++) { + Object arrayElement = jsonArray.get(i); + if (arrayElement instanceof JSONObject) { + removeTagsHandles((JSONObject) arrayElement); // Recursively handle each element + } + } + } + } + } + + public String replaceArrayHandleValuesForUpdateIdentity(String inputJson, String testCaseName) { + JSONObject jsonObj = new JSONObject(inputJson); + JSONObject request = jsonObj.getJSONObject("request"); + JSONObject identity = request.getJSONObject("identity"); + JSONArray selectedHandles = identity.getJSONArray("selectedHandles"); + String phone = getValueFromAuthActuator("json-property", "phone_number"); + String result = phone.replaceAll("\\[\"|\"\\]", ""); + String email = getValueFromAuthActuator("json-property", "emailId"); + String emailResult = email.replaceAll("\\[\"|\"\\]", ""); + + + + // Iterate over each handle in the selectedHandles array + for (int i = 0; i < selectedHandles.length(); i++) { + String handle = selectedHandles.getString(i); + + // Check if the handle exists in identity and if its value is a JSONArray + if (identity.has(handle) && identity.get(handle) instanceof JSONArray) { + JSONArray handleArray = identity.getJSONArray(handle); + + if (testCaseName.contains("_withupdatevalues")) { + for (int j = 0; j < handleArray.length(); j++) { + JSONObject handleObj = handleArray.getJSONObject(j); + handleObj.put("value", "mosip" + RANDOM_ID + "_" + j); + } + } else if (testCaseName.contains("_withmultiplevalues")) { + for (int j = 0; j < handleArray.length(); j++) { + JSONObject handleObj = handleArray.getJSONObject(j); + JSONArray valuesArray = new JSONArray(); + valuesArray.put("mosip501724826584965_modified_1"); + valuesArray.put("mosip501724826584965_modified_2"); + valuesArray.put("mosip501724826584965_modified_3"); + handleObj.put("values", valuesArray); + } + } else if (testCaseName.contains("_withupdatetags")) { + for (int j = 0; j < handleArray.length(); j++) { + JSONObject handleObj = handleArray.getJSONObject(j); + JSONArray tags = handleObj.optJSONArray("tags"); + if (tags != null) { + for (int k = 0; k < tags.length(); k++) { + tags.put(k, tags.getString(k) + "_invalid" + RANDOM_ID); + } + } + } + } else if (testCaseName.contains("_withupdatetagsandhandles")) { + for (int j = 0; j < handleArray.length(); j++) { + JSONObject handleObj = handleArray.getJSONObject(j); + JSONArray tags = handleObj.optJSONArray("tags"); + if (tags != null) { + for (int k = 0; k < tags.length(); k++) { + tags.put(k, tags.getString(k) + "_invalid" + RANDOM_ID); + } + } + JSONArray values = handleObj.optJSONArray("value"); + if (values != null) { + for (int k = 0; k < values.length(); k++) { + values.put(k, values.getString(k) + "_invalid" + RANDOM_ID); + } + } + } + } else if (testCaseName.contains("_withmultipledemohandles")) { + // Handle specific demo handles by checking and adding them to the selectedHandles + + boolean containsPhone = false; + for (int j = 0; j < selectedHandles.length(); j++) { + if (result.equalsIgnoreCase(selectedHandles.getString(j))) { + containsPhone = true; + break; + } + } + if (!containsPhone) { + selectedHandles.put(result); + JSONObject phoneEntry = new JSONObject(); + phoneEntry.put("value", "$PHONENUMBERFORIDENTITY$"); + JSONArray phoneArray = new JSONArray(); + phoneArray.put(phoneEntry); + identity.put(result, phoneArray); + } + } else if (testCaseName.contains("_withdeletehandlefromrecord")) { + for (int j = 0; j < selectedHandles.length(); j++) { + String handleToDelete = selectedHandles.getString(j); + if (identity.has(handleToDelete)) { + identity.remove(handleToDelete); + } + } + identity.remove("selectedHandles"); + } else if (testCaseName.contains("_withupdatedselectedhandle")) { + String firstHandle = selectedHandles.getString(0); + String updatedHandle = firstHandle + RANDOM_ID; + selectedHandles.put(0, updatedHandle); + } else if (testCaseName.contains("_withupdatedselectedhandleanddemo")) { + if (selectedHandles.length() > 0) { + String originalHandle = selectedHandles.getString(0); + String updatedHandle = originalHandle + RANDOM_ID; + selectedHandles.put(0, updatedHandle); + if (identity.has(originalHandle)) { + JSONArray originalHandleArray = identity.getJSONArray(originalHandle); + for (int J = 0; J < originalHandleArray.length(); J++) { + JSONObject handleObject = originalHandleArray.getJSONObject(i); + String originalValue = handleObject.optString("value", ""); + handleObject.put("value", originalValue + RANDOM_ID); + originalHandleArray.put(J, handleObject); + } + identity.remove(originalHandle); + identity.put(updatedHandle, originalHandleArray); + } + } + } else if (testCaseName.contains("_withupdatedselectedhandleandfirstattribute")) { + Iterator keys = identity.keys(); + if (keys.hasNext()) { + String firstKey = keys.next(); + if (!firstKey.equals("selectedHandles")) { + selectedHandles.put(0, firstKey); + if (identity.has(firstKey)) { + JSONArray originalArray = identity.getJSONArray(firstKey); + for (int j = 0; j < originalArray.length(); j++) { + JSONObject handleObject = originalArray.getJSONObject(j); + if (handleObject.has("value")) { + String originalValue = handleObject.getString("value"); + handleObject.put("value", originalValue + "123"); + } + if (handleObject.has("tags")) { + JSONArray tagsArray = handleObject.getJSONArray("tags"); + for (int k = 0; k < tagsArray.length(); k++) { + String tag = tagsArray.getString(k); + tagsArray.put(k, tag + "123"); + } + handleObject.put("tags", tagsArray); + } + originalArray.put(j, handleObject); + } + identity.remove(firstKey); + identity.put(firstKey, originalArray); + } + } + } + } + else if (testCaseName.contains("_withremovedtaggedattribute")) { + for (int j = 0; j < selectedHandles.length(); j++) { + String handle1 = selectedHandles.getString(j); + + if (identity.has(handle1) && identity.get(handle1) instanceof JSONArray) { + JSONArray handleArray1 = identity.getJSONArray(handle1); + + for (int k = 0; k < handleArray1.length(); k++) { + JSONObject handleObject = handleArray1.getJSONObject(k); + if (handleObject.has("tags")) { + handleObject.remove("tags"); + } + } + identity.put(handle, handleArray); + } + } + } + else if (testCaseName.contains("_withemptyhandles")) { + identity.remove("selectedHandles"); + + } + + else if (testCaseName.contains("_withouthandlesattr")) { + if (identity.has("selectedHandles")) { + selectedHandles = identity.getJSONArray("selectedHandles"); + for (int j = 0; j < selectedHandles.length(); j++) { + handle = selectedHandles.getString(j); + if (identity.has(handle)) { + identity.remove(handle); + } + } + identity.remove("selectedHandles"); + } + } + + //44 + else if (testCaseName.contains("_withinvaliddemofield")) { + if (identity.has("selectedHandles")) { + for (int j = 0; j < selectedHandles.length(); j++) { + if (identity.has(handle)) { + Object currentValue = identity.get(handle); + if (currentValue instanceof String) { + identity.put(handle, "invalid_" + currentValue); + } else if (currentValue instanceof JSONArray) { + JSONArray jsonArray = (JSONArray) currentValue; + for (int k = 0; k < jsonArray.length(); k++) { + JSONObject obj = jsonArray.getJSONObject(k); + if (obj.has("value")) { + obj.put("value", "invalid_" + obj.getString("value")); + } + } + identity.put(handle, jsonArray); + } + } + selectedHandles.put(i, "invalid_" + handle); + } + identity.put("selectedHandles", selectedHandles); + } + } + //49 + else if (testCaseName.contains("_withoutselectedhandlesandattri")) { + + for (int j = 0; j < selectedHandles.length(); j++) { + + if (identity.has(handle)) { + identity.remove(handle); + } + } + + identity.remove("selectedHandles"); + } + + else if (testCaseName.contains("_withalldemofieldsremoved")) { + + for (int j = 0; j < selectedHandles.length(); j++) { + if (identity.has(handle)) { + identity.remove(handle); + } + } + } + + else if (testCaseName.contains("_withemptyselectedhandle")) { + if (identity.has("selectedHandles")) { + identity.put("selectedHandles", new JSONArray()); + } + } + + + else if (testCaseName.contains("_witharandomnonhandleattr")) { + if (identity.has("selectedHandles")) { + List existingHandles = new ArrayList<>(); + for (int j = 0; j < selectedHandles.length(); j++) { + existingHandles.add(selectedHandles.getString(j)); + } + Iterator keys = identity.keys(); + while (keys.hasNext()) { + String key = keys.next(); + if (key.equals("selectedHandles")) { + continue; + } + if (!existingHandles.contains(key)) { + selectedHandles.put(key); + break; + } + } + } + } + + else if (testCaseName.contains("_updateselectedhandleswithinvalid")) { + JSONArray updatedHandlesArray = new JSONArray(); + updatedHandlesArray.put("invalidscehema123"); + identity.put("selectedHandles", updatedHandlesArray); + } + + else if (testCaseName.contains("_withinvaliddhandle")) { + selectedHandles.put("newFieldHandle"); + } + + else if (testCaseName.contains("_updateselectedhandleswithscehmaattrwhichisnothandle")) { + Iterator keys = identity.keys(); + while (keys.hasNext()) { + String key = keys.next(); + if (!selectedHandles.toList().contains(key) && identity.optString(key) != null && identity.get(key) instanceof String) { + selectedHandles.put(key); + break; + } + } + } + + else if (testCaseName.contains("_removeselectedhandle_updatephone")) { + if (identity.has("selectedHandles")) { + identity.remove("selectedHandles"); + } + + if (identity.has(result)) { + identity.put(result, generateRandomNumberString(10)); + } + } + + else if (testCaseName.contains("_withupdatedhandlewhichisnotinschema")) { + JSONArray newSelectedHandles = new JSONArray(); + newSelectedHandles.put("invalid12@@"); + identity.put("selectedHandles", newSelectedHandles); + } + + else if (testCaseName.contains("_replaceselectedhandles")) { + identity.put("selectedHandles", new JSONArray().put(result)); + } + + else if (testCaseName.contains("_updatewithphoneemail")) { + JSONArray updatedHandles = new JSONArray(); + updatedHandles.put(emailResult); + updatedHandles.put(result); + + identity.put("selectedHandles", updatedHandles); + } + else if (testCaseName.contains("_withusedphone")) { + if (identity.has(result)) { + identity.put(result, "$ID:AddIdentity_array_handle_value_smoke_Pos_withphonenumber_PHONE$" ); + } + } + else if (testCaseName.contains("_withphonevalue")) { + if (identity.has(result)) { + identity.put(result, "$ID:AddIdentity_array_handle_value_smoke_Pos_withselectedhandlephone_PHONE$" ); + } + } + else if (testCaseName.contains("_removeselectedhandlesandupdateemail")) { + if (identity.has("selectedHandles")) { + identity.remove("selectedHandles"); + } + if (identity.has(emailResult)) { + identity.put(emailResult, "$ID:AddIdentity_array_handle_value_update_smoke_Pos_withselectedhandlephone_EMAIL$" ); + } + } + + identity.put(handle, handleArray); + } + } + + // Return the modified JSON as a string + return jsonObj.toString(); + } + + + + + + public static void setfoundHandlesInIdSchema(boolean foundHandles) { + + foundHandlesInIdSchema=foundHandles; + } + + public static boolean isHandlesAvailableInIdSchema(boolean foundHandles) { + + return foundHandlesInIdSchema; + } + + // public static boolean checkIsCertTrusted(String certIssuer, JSONArray ArrayOfJsonObjects, int recursiveCount) { // for (int i = 0; i < ArrayOfJsonObjects.length(); i++) { // if (ArrayOfJsonObjects.getJSONObject(i).has("certSubject") @@ -7352,4 +8327,6 @@ public static boolean IsCertSyncd(String certSubjectSubString) { // } // return false; // } -} \ No newline at end of file +} + + diff --git a/apitest-commons/src/main/java/io/mosip/testrig/apirig/utils/BioDataUtility.java b/apitest-commons/src/main/java/io/mosip/testrig/apirig/utils/BioDataUtility.java index 5b46688a8b..72ede924f4 100644 --- a/apitest-commons/src/main/java/io/mosip/testrig/apirig/utils/BioDataUtility.java +++ b/apitest-commons/src/main/java/io/mosip/testrig/apirig/utils/BioDataUtility.java @@ -33,10 +33,9 @@ public class BioDataUtility extends AdminTestUtil { private static final Logger logger = Logger.getLogger(BioDataUtility.class); - @Autowired - private EncryptionDecrptionUtil encryptDecryptUtil; - @Autowired - private Encrypt encrypt; + + //@Autowired + private Encrypt encrypt = new Encrypt(); private String encryptIsoBioValue(String isoBiovalue, String timestamp, String bioValueEncryptionTemplateJson, diff --git a/apitest-commons/src/main/java/io/mosip/testrig/apirig/utils/BiometricDataUtility.java b/apitest-commons/src/main/java/io/mosip/testrig/apirig/utils/BiometricDataUtility.java index 3c5ccffbb4..a4b04bab4a 100644 --- a/apitest-commons/src/main/java/io/mosip/testrig/apirig/utils/BiometricDataUtility.java +++ b/apitest-commons/src/main/java/io/mosip/testrig/apirig/utils/BiometricDataUtility.java @@ -16,10 +16,10 @@ import javax.ws.rs.core.MediaType; import org.apache.log4j.Logger; +import org.springframework.beans.factory.annotation.Autowired; import io.mosip.kernel.core.util.CryptoUtil; import io.mosip.kernel.core.util.HMACUtils; -import io.mosip.kernel.crypto.jce.util.JWSValidation; import io.mosip.testrig.apirig.testrunner.JsonPrecondtion; /** @@ -32,6 +32,9 @@ public class BiometricDataUtility extends AuthTestsUtil { + @Autowired + private static CryptoCore cryptoCore; + private static final Logger logger = Logger.getLogger(BiometricDataUtility.class); private static String cryptoEncryptUrl = RunConfigUtil.objRunConfig.getEndPointUrl() @@ -123,8 +126,7 @@ private static String getSignedData(String identityDataBlock) { .generateCertificate(bIS); KeyFactory kf = KeyFactory.getInstance("RSA"); PrivateKey privateKey = kf.generatePrivate(new PKCS8EncodedKeySpec(Base64.getDecoder().decode(pKey))); - JWSValidation jws = new JWSValidation(); - return jws.jwsSign(identityDataBlock, privateKey, certificate); + return cryptoCore.sign(identityDataBlock.getBytes(), privateKey, certificate); } catch (Exception e) { logger.error("Exception Occured in signing the bio data:" + e.getMessage()); return "Automation error occured: "+e.getMessage(); diff --git a/apitest-commons/src/main/java/io/mosip/testrig/apirig/utils/ConfigManager.java b/apitest-commons/src/main/java/io/mosip/testrig/apirig/utils/ConfigManager.java index ce3d0266bc..b12b363c4a 100644 --- a/apitest-commons/src/main/java/io/mosip/testrig/apirig/utils/ConfigManager.java +++ b/apitest-commons/src/main/java/io/mosip/testrig/apirig/utils/ConfigManager.java @@ -70,11 +70,14 @@ public class ConfigManager { private static String PUSH_TO_S3 = "push-reports-to-s3"; private static String ENABLE_DEBUG = "enableDebug"; private static String REPORT_IGNORED_TEST_CASES = "reportIgnoredTestCases"; + private static String REPORT_KNOWN_ISSUE_TEST_CASES = "reportKnownIssueTestCases"; private static String THREAD_COUNT = "threadCount"; private static String LANG_SELECT = "langselect"; private static String USEPRECONFIGOTP = "usePreConfiguredOtp"; private static String ESIGNET_BASE_URL = "eSignetbaseurl"; + private static String ESIGNET_ACTUATOR_PROPERTY_SECTION = "esignetActuatorPropertySection"; + private static String INJI_CERTIFY_BASE_URL = "injiCertifyBaseURL"; private static String ESIGNET_MOCK_BASE_URL = "esignetMockBaseURL"; private static String SUNBIRD_BASE_URL = "sunBirdBaseURL"; @@ -121,6 +124,7 @@ public class ConfigManager { private static String MOUNT_PATH = "mountPath"; private static String AUTHCERTS_PATH = "authCertsPath"; private static String MOUNT_PATH_FOR_SCENARIO = "mountPathForScenario"; + private static String MOCK_NOTIFICATION_CHANNEL = "mockNotificationChannel"; private static String SERVER_ERRORS_TO_MONITOR = "serverErrorsToMonitor"; @@ -198,6 +202,7 @@ public class ConfigManager { private static String push_reports_to_s3; private static String enableDebug; private static String reportIgnoredTestCases; + private static String reportKnownIssueTestCases; private static String threadCount; private static String langselect; private static String usePreConfiguredOtp; @@ -205,6 +210,8 @@ public class ConfigManager { private static String eSignetbaseurl; private static String esignetMockBaseURL; private static String sunBirdBaseURL; + private static String esignetActuatorPropertySection; + private static String injiCertifyBaseURL; private static String dbPort; private static String dbDomain; @@ -245,6 +252,7 @@ public class ConfigManager { private static String mountPath; private static String authCertsPath; + private static String mockNotificationChannel; private static String mountPathForScenario; private static String packetUtilityBaseUrl; public static Properties propsKernel; @@ -359,6 +367,11 @@ public static void init() { mountPath = System.getenv(MOUNT_PATH) == null ? propsKernel.getProperty(MOUNT_PATH) : System.getenv(MOUNT_PATH); propsKernel.setProperty(MOUNT_PATH, mountPath); + mockNotificationChannel = System.getenv(MOCK_NOTIFICATION_CHANNEL) == null + ? propsKernel.getProperty(MOCK_NOTIFICATION_CHANNEL) + : System.getenv(MOCK_NOTIFICATION_CHANNEL); + propsKernel.setProperty(MOCK_NOTIFICATION_CHANNEL, mockNotificationChannel); + authCertsPath = System.getenv(AUTHCERTS_PATH) == null ? propsKernel.getProperty(AUTHCERTS_PATH) : System.getenv(AUTHCERTS_PATH); propsKernel.setProperty(AUTHCERTS_PATH, authCertsPath); @@ -385,6 +398,11 @@ public static void init() { ? propsKernel.getProperty(REPORT_IGNORED_TEST_CASES) : System.getenv(REPORT_IGNORED_TEST_CASES); propsKernel.setProperty(REPORT_IGNORED_TEST_CASES, reportIgnoredTestCases); + + reportKnownIssueTestCases = System.getenv(REPORT_KNOWN_ISSUE_TEST_CASES) == null + ? propsKernel.getProperty(REPORT_KNOWN_ISSUE_TEST_CASES) + : System.getenv(REPORT_KNOWN_ISSUE_TEST_CASES); + propsKernel.setProperty(REPORT_KNOWN_ISSUE_TEST_CASES, reportKnownIssueTestCases); threadCount = System.getenv(THREAD_COUNT) == null ? propsKernel.getProperty(THREAD_COUNT) : System.getenv(THREAD_COUNT); @@ -406,13 +424,25 @@ public static void init() { ? propsKernel.getProperty(USE_EXTERNAL_SCENARIO_SHEET) : System.getenv(USE_EXTERNAL_SCENARIO_SHEET); propsKernel.setProperty(USE_EXTERNAL_SCENARIO_SHEET, useExternalScenario_sheet); + + esignetActuatorPropertySection = System.getenv(ESIGNET_ACTUATOR_PROPERTY_SECTION) == null + ? propsKernel.getProperty(ESIGNET_ACTUATOR_PROPERTY_SECTION) + : System.getenv(ESIGNET_ACTUATOR_PROPERTY_SECTION); + propsKernel.setProperty(ESIGNET_ACTUATOR_PROPERTY_SECTION, esignetActuatorPropertySection); if (System.getenv(ESIGNET_BASE_URL) != null) { eSignetbaseurl = System.getenv(ESIGNET_BASE_URL); } else { - eSignetbaseurl = System.getProperty("env.endpoint").replace("-internal", ""); + eSignetbaseurl = System.getProperty("env.endpoint").replace("api-internal", "esignet"); } propsKernel.setProperty(ESIGNET_BASE_URL, eSignetbaseurl); + + if (System.getenv(INJI_CERTIFY_BASE_URL) != null) { + injiCertifyBaseURL = System.getenv(INJI_CERTIFY_BASE_URL); + } else { + injiCertifyBaseURL = System.getProperty("env.endpoint").replace("api-internal", "injicertify"); + } + propsKernel.setProperty(INJI_CERTIFY_BASE_URL, injiCertifyBaseURL); esignetMockBaseURL = System.getenv(ESIGNET_MOCK_BASE_URL) == null ? propsKernel.getProperty(ESIGNET_MOCK_BASE_URL) @@ -519,6 +549,11 @@ public static boolean isInTobeExecuteList(String stringToFind) { return false; } + public static String getEsignetActuatorPropertySection() { + return esignetActuatorPropertySection; + + } + public static String getComponentBaseURL(String component) { return mosip_components_base_urls.get(component); } @@ -547,6 +582,10 @@ public static Boolean IsDebugEnabled() { public static Boolean reportIgnoredTestCases() { return reportIgnoredTestCases.equalsIgnoreCase("yes"); } + + public static Boolean reportKnownIssueTestCases() { + return reportKnownIssueTestCases.equalsIgnoreCase("yes"); + } public static String getReportExpirationInDays() { return reportExpirationInDays; @@ -561,6 +600,11 @@ public static String getEsignetBaseUrl() { return eSignetbaseurl; } + + public static String getInjiCertifyBaseUrl() { + return injiCertifyBaseURL; + + } public static String getEsignetMockBaseURL() { return esignetMockBaseURL; @@ -603,6 +647,10 @@ public static String getmountPathForScenario() { public static String getpacketUtilityBaseUrl() { return packetUtilityBaseUrl; } + + public static String getMockNotificationChannel() { + return mockNotificationChannel; + } public static String getauthCertsPath() { return authCertsPath; diff --git a/apitest-commons/src/main/java/io/mosip/testrig/apirig/utils/CryptoCore.java b/apitest-commons/src/main/java/io/mosip/testrig/apirig/utils/CryptoCore.java new file mode 100644 index 0000000000..855e8a1afe --- /dev/null +++ b/apitest-commons/src/main/java/io/mosip/testrig/apirig/utils/CryptoCore.java @@ -0,0 +1,549 @@ +package io.mosip.testrig.apirig.utils; + +import java.math.BigInteger; +import java.security.InvalidAlgorithmParameterException; +import java.security.NoSuchProviderException; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.SecureRandom; +import java.security.cert.CertificateExpiredException; +import java.security.cert.CertificateNotYetValidException; +import java.security.cert.X509Certificate; +import java.security.interfaces.RSAPrivateKey; +import java.security.interfaces.RSAPublicKey; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.MGF1ParameterSpec; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; + +import jakarta.annotation.PostConstruct; +import javax.crypto.BadPaddingException; +import javax.crypto.Cipher; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.NoSuchPaddingException; +import javax.crypto.SecretKey; +import javax.crypto.SecretKeyFactory; +import javax.crypto.spec.GCMParameterSpec; +import javax.crypto.spec.OAEPParameterSpec; +import javax.crypto.spec.PBEKeySpec; +import javax.crypto.spec.PSource.PSpecified; +import javax.crypto.spec.SecretKeySpec; +import javax.xml.bind.DatatypeConverter; +import org.bouncycastle.crypto.InvalidCipherTextException; +import org.bouncycastle.crypto.digests.SHA256Digest; +import org.bouncycastle.crypto.encodings.OAEPEncoding; +import org.bouncycastle.crypto.engines.RSAEngine; +import org.bouncycastle.crypto.params.RSAKeyParameters; +import org.jose4j.jws.JsonWebSignature; +import org.jose4j.jwx.CompactSerializer; +import org.jose4j.lang.JoseException; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import io.mosip.kernel.core.crypto.exception.InvalidDataException; +import io.mosip.kernel.core.crypto.exception.InvalidKeyException; +import io.mosip.kernel.core.crypto.exception.InvalidParamSpecException; +import io.mosip.kernel.core.crypto.exception.SignatureException; +import io.mosip.kernel.core.crypto.spi.CryptoCoreSpec; +import io.mosip.kernel.core.exception.NoSuchAlgorithmException; +import io.mosip.kernel.core.util.CryptoUtil; +import io.mosip.kernel.core.util.EmptyCheckUtils; +import io.mosip.kernel.crypto.jce.constant.SecurityExceptionCodeConstant; +import io.mosip.kernel.crypto.jce.util.CryptoUtils; + +/** + * This class provided Basic and Core Cryptographic functionalities . + * + * This class follows {@link CryptoCoreSpec} and implement all basic + * Cryptographic functions. + * + * @author Urvil Joshi + * @author Rajath + * @since 1.0.0 + * + * @see CryptoCoreSpec + * @see PrivateKey + * @see PublicKey + * @see SecretKey + * @see Cipher + * @see GCMParameterSpec + * @see SecureRandom + */ +//Code optimization remaining (Code Dupe) +@Component +public class CryptoCore implements CryptoCoreSpec { + + private static final String PERIOD_SEPARATOR_REGEX = "\\."; + + // Used as a hack for softhsm oeap padding decryption usecase will be when we + // will use in HSM + @SuppressWarnings("java:S106") + private static final String RSA_ECB_NO_PADDING = "RSA/ECB/NoPadding"; // NOSONAR using the padding for allowing OAEP padding in PKCS11 library + + private static final String PKCS11_STORE_TYPE = "PKCS11"; + + @Value("${mosip.kernel.keygenerator.asymmetric-key-length:2048}") + private int asymmetricKeyLength; + + private static final String MGF1 = "MGF1"; + + private static final String HASH_ALGO = "SHA-256"; + + private static final String AES = "AES"; + + //@Value("${mosip.kernel.crypto.gcm-tag-length:128}") + private int tagLength = 128; + + //@Value("${mosip.automation.crypto.symmetric-algorithm-name:AES/GCM/NoPadding}") + private String symmetricAlgorithm = "AES/GCM/NoPadding"; + + //@Value("${mosip.kernel.crypto.asymmetric-algorithm-name:RSA/ECB/OAEPWITHSHA-256ANDMGF1PADDING}") + private String asymmetricAlgorithm = "RSA/ECB/OAEPWITHSHA-256ANDMGF1PADDING"; + + @Value("${mosip.kernel.crypto.hash-algorithm-name:PBKDF2WithHmacSHA512}") + private String passwordAlgorithm; + + @Value("${mosip.kernel.crypto.sign-algorithm-name:RS256}") + private String signAlgorithm; + + @Value("${mosip.kernel.crypto.hash-symmetric-key-length:256}") + private int symmetricKeyLength; + + @Value("${mosip.kernel.crypto.hash-iteration:100000}") + private int iterations; + + @Value("${mosip.kernel.keymanager.hsm.keystore-type:PKCS11}") + private String keystoreType; + + private SecureRandom secureRandom = new SecureRandom(); + +// @PostConstruct +// public void init() { +// secureRandom = new SecureRandom(); +// } + + @Override + public byte[] symmetricEncrypt(SecretKey key, byte[] data, byte[] aad) { + Objects.requireNonNull(key, SecurityExceptionCodeConstant.MOSIP_INVALID_KEY_EXCEPTION.getErrorMessage()); + CryptoUtils.verifyData(data); + Cipher cipher; + try { + cipher = Cipher.getInstance(symmetricAlgorithm); + } catch (java.security.NoSuchAlgorithmException | NoSuchPaddingException e) { + throw new NoSuchAlgorithmException( + SecurityExceptionCodeConstant.MOSIP_NO_SUCH_ALGORITHM_EXCEPTION.getErrorCode(), + SecurityExceptionCodeConstant.MOSIP_NO_SUCH_ALGORITHM_EXCEPTION.getErrorMessage(), e); + } + byte[] output = null; + byte[] randomIV = generateIV(cipher.getBlockSize()); + try { + SecretKeySpec keySpec = new SecretKeySpec(key.getEncoded(), AES); + GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(tagLength, randomIV); + cipher.init(Cipher.ENCRYPT_MODE, keySpec, gcmParameterSpec); + output = new byte[cipher.getOutputSize(data.length) + cipher.getBlockSize()]; + if (aad != null && aad.length != 0) { + cipher.updateAAD(aad); + } + byte[] processData = doFinal(data, cipher); + System.arraycopy(processData, 0, output, 0, processData.length); + System.arraycopy(randomIV, 0, output, processData.length, randomIV.length); + } catch (java.security.InvalidKeyException e) { + throw new InvalidKeyException(SecurityExceptionCodeConstant.MOSIP_INVALID_KEY_EXCEPTION.getErrorCode(), + SecurityExceptionCodeConstant.MOSIP_INVALID_KEY_EXCEPTION.getErrorMessage(), e); + } catch (InvalidAlgorithmParameterException e) { + throw new InvalidKeyException( + SecurityExceptionCodeConstant.MOSIP_INVALID_PARAM_SPEC_EXCEPTION.getErrorCode(), + SecurityExceptionCodeConstant.MOSIP_INVALID_PARAM_SPEC_EXCEPTION.getErrorMessage(), e); + } + return output; + } + + @Override + public byte[] symmetricEncrypt(SecretKey key, byte[] data, byte[] iv, byte[] aad) { + Objects.requireNonNull(key, SecurityExceptionCodeConstant.MOSIP_INVALID_KEY_EXCEPTION.getErrorMessage()); + CryptoUtils.verifyData(data); + if (iv == null) { + return symmetricEncrypt(key, data, aad); + } + Cipher cipher; + try { + cipher = Cipher.getInstance(symmetricAlgorithm); + } catch (java.security.NoSuchAlgorithmException | NoSuchPaddingException e) { + throw new NoSuchAlgorithmException( + SecurityExceptionCodeConstant.MOSIP_NO_SUCH_ALGORITHM_EXCEPTION.getErrorCode(), + SecurityExceptionCodeConstant.MOSIP_NO_SUCH_ALGORITHM_EXCEPTION.getErrorMessage(), e); + } + try { + SecretKeySpec keySpec = new SecretKeySpec(key.getEncoded(), AES); + GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(tagLength, iv); + cipher.init(Cipher.ENCRYPT_MODE, keySpec, gcmParameterSpec); + if (aad != null && aad.length != 0) { + cipher.updateAAD(aad); + } + return doFinal(data, cipher); + } catch (java.security.InvalidKeyException e) { + throw new InvalidKeyException(SecurityExceptionCodeConstant.MOSIP_INVALID_KEY_EXCEPTION.getErrorCode(), + SecurityExceptionCodeConstant.MOSIP_INVALID_KEY_EXCEPTION.getErrorMessage(), e); + } catch (InvalidAlgorithmParameterException e) { + throw new InvalidParamSpecException( + SecurityExceptionCodeConstant.MOSIP_INVALID_PARAM_SPEC_EXCEPTION.getErrorCode(), + SecurityExceptionCodeConstant.MOSIP_INVALID_PARAM_SPEC_EXCEPTION.getErrorMessage(), e); + } + } + + @Override + public byte[] symmetricDecrypt(SecretKey key, byte[] data, byte[] aad) { + Objects.requireNonNull(key, SecurityExceptionCodeConstant.MOSIP_INVALID_KEY_EXCEPTION.getErrorMessage()); + CryptoUtils.verifyData(data); + Cipher cipher; + try { + cipher = Cipher.getInstance(symmetricAlgorithm); + } catch (java.security.NoSuchAlgorithmException | NoSuchPaddingException e) { + throw new NoSuchAlgorithmException( + SecurityExceptionCodeConstant.MOSIP_NO_SUCH_ALGORITHM_EXCEPTION.getErrorCode(), + SecurityExceptionCodeConstant.MOSIP_NO_SUCH_ALGORITHM_EXCEPTION.getErrorMessage(), e); + } + byte[] output = null; + try { + byte[] randomIV = Arrays.copyOfRange(data, data.length - cipher.getBlockSize(), data.length); + SecretKeySpec keySpec = new SecretKeySpec(key.getEncoded(), AES); + GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(tagLength, randomIV); + cipher.init(Cipher.DECRYPT_MODE, keySpec, gcmParameterSpec); + if (aad != null && aad.length != 0) { + cipher.updateAAD(aad); + } + output = doFinal(Arrays.copyOf(data, data.length - cipher.getBlockSize()), cipher); + } catch (java.security.InvalidKeyException e) { + throw new InvalidKeyException(SecurityExceptionCodeConstant.MOSIP_INVALID_KEY_EXCEPTION.getErrorCode(), + SecurityExceptionCodeConstant.MOSIP_INVALID_KEY_EXCEPTION.getErrorMessage(), e); + } catch (InvalidAlgorithmParameterException e) { + throw new InvalidKeyException( + SecurityExceptionCodeConstant.MOSIP_INVALID_PARAM_SPEC_EXCEPTION.getErrorCode(), + SecurityExceptionCodeConstant.MOSIP_INVALID_PARAM_SPEC_EXCEPTION.getErrorMessage(), e); + } catch (ArrayIndexOutOfBoundsException e) { + throw new InvalidDataException( + SecurityExceptionCodeConstant.MOSIP_INVALID_DATA_LENGTH_EXCEPTION.getErrorCode(), + SecurityExceptionCodeConstant.MOSIP_INVALID_DATA_LENGTH_EXCEPTION.getErrorMessage(), e); + } + return output; + } + + @Override + public byte[] symmetricDecrypt(SecretKey key, byte[] data, byte[] iv, byte[] aad) { + Objects.requireNonNull(key, SecurityExceptionCodeConstant.MOSIP_INVALID_KEY_EXCEPTION.getErrorMessage()); + CryptoUtils.verifyData(data); + if (iv == null) { + return symmetricDecrypt(key, data, aad); + } + Cipher cipher; + try { + cipher = Cipher.getInstance(symmetricAlgorithm); + } catch (java.security.NoSuchAlgorithmException | NoSuchPaddingException e) { + throw new NoSuchAlgorithmException( + SecurityExceptionCodeConstant.MOSIP_NO_SUCH_ALGORITHM_EXCEPTION.getErrorCode(), + SecurityExceptionCodeConstant.MOSIP_NO_SUCH_ALGORITHM_EXCEPTION.getErrorMessage(), e); + } + try { + SecretKeySpec keySpec = new SecretKeySpec(key.getEncoded(), AES); + GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(tagLength, iv); + cipher.init(Cipher.DECRYPT_MODE, keySpec, gcmParameterSpec); + if (aad != null) { + cipher.updateAAD(aad); + } + return doFinal(data, cipher); + } catch (java.security.InvalidKeyException e) { + throw new InvalidKeyException(SecurityExceptionCodeConstant.MOSIP_INVALID_KEY_EXCEPTION.getErrorCode(), + SecurityExceptionCodeConstant.MOSIP_INVALID_KEY_EXCEPTION.getErrorMessage(), e); + } catch (InvalidAlgorithmParameterException e) { + throw new InvalidParamSpecException( + SecurityExceptionCodeConstant.MOSIP_INVALID_PARAM_SPEC_EXCEPTION.getErrorCode(), + SecurityExceptionCodeConstant.MOSIP_INVALID_PARAM_SPEC_EXCEPTION.getErrorMessage(), e); + } + } + + @Override + public byte[] asymmetricEncrypt(PublicKey key, byte[] data) { + Objects.requireNonNull(key, SecurityExceptionCodeConstant.MOSIP_INVALID_KEY_EXCEPTION.getErrorMessage()); + CryptoUtils.verifyData(data); + Cipher cipher; + try { + cipher = Cipher.getInstance(asymmetricAlgorithm); + } catch (java.security.NoSuchAlgorithmException | NoSuchPaddingException e) { + throw new NoSuchAlgorithmException( + SecurityExceptionCodeConstant.MOSIP_NO_SUCH_ALGORITHM_EXCEPTION.getErrorCode(), + SecurityExceptionCodeConstant.MOSIP_NO_SUCH_ALGORITHM_EXCEPTION.getErrorMessage(), e); + } + final OAEPParameterSpec oaepParams = new OAEPParameterSpec(HASH_ALGO, MGF1, MGF1ParameterSpec.SHA256, + PSpecified.DEFAULT); + try { + cipher.init(Cipher.ENCRYPT_MODE, key, oaepParams); + } catch (java.security.InvalidKeyException e) { + throw new InvalidKeyException(SecurityExceptionCodeConstant.MOSIP_INVALID_KEY_EXCEPTION.getErrorCode(), + e.getMessage(), e); + } catch (InvalidAlgorithmParameterException e) { + throw new InvalidParamSpecException( + SecurityExceptionCodeConstant.MOSIP_INVALID_PARAM_SPEC_EXCEPTION.getErrorCode(), + SecurityExceptionCodeConstant.MOSIP_INVALID_PARAM_SPEC_EXCEPTION.getErrorMessage(), e); + } + return doFinal(data, cipher); + } + + @Override + public byte[] asymmetricDecrypt(PrivateKey privateKey, byte[] data) { + if (PKCS11_STORE_TYPE.equalsIgnoreCase(keystoreType)) { + BigInteger keyModulus = ((RSAPrivateKey) privateKey).getModulus(); + return asymmetricDecrypt(privateKey, keyModulus, data, null); + } + return jceAsymmetricDecrypt(privateKey, data, null); + } + + @Override + public byte[] asymmetricDecrypt(PrivateKey privateKey, PublicKey publicKey, byte[] data) { + if (PKCS11_STORE_TYPE.equalsIgnoreCase(keystoreType)) { + BigInteger keyModulus = Objects.nonNull(publicKey) ? ((RSAPublicKey) publicKey).getModulus() : + ((RSAPrivateKey) privateKey).getModulus(); + return asymmetricDecrypt(privateKey, keyModulus, data, null); + } + return jceAsymmetricDecrypt(privateKey, data, null); + } + + @Override + public byte[] asymmetricDecrypt(PrivateKey privateKey, PublicKey publicKey, byte[] data, String storeType) { + if (PKCS11_STORE_TYPE.equalsIgnoreCase(keystoreType)) { + BigInteger keyModulus = Objects.nonNull(publicKey) ? ((RSAPublicKey) publicKey).getModulus() : + ((RSAPrivateKey) privateKey).getModulus(); + return asymmetricDecrypt(privateKey, keyModulus, data, storeType); + } + return jceAsymmetricDecrypt(privateKey, data, storeType); + } + + private byte[] asymmetricDecrypt(PrivateKey privateKey, BigInteger keyModulus, byte[] data, String storeType) { + Objects.requireNonNull(privateKey, SecurityExceptionCodeConstant.MOSIP_INVALID_KEY_EXCEPTION.getErrorMessage()); + CryptoUtils.verifyData(data); + Cipher cipher; + try { + cipher = Objects.isNull(storeType) ? Cipher.getInstance(RSA_ECB_NO_PADDING) : // NOSONAR using the padding for allowing OAEP padding in PKCS11 library + Cipher.getInstance(RSA_ECB_NO_PADDING, storeType); // NOSONAR using the padding for allowing OAEP padding in PKCS11 library + } catch (java.security.NoSuchAlgorithmException | NoSuchPaddingException | NoSuchProviderException e) { + throw new NoSuchAlgorithmException( + SecurityExceptionCodeConstant.MOSIP_NO_SUCH_ALGORITHM_EXCEPTION.getErrorCode(), + SecurityExceptionCodeConstant.MOSIP_NO_SUCH_ALGORITHM_EXCEPTION.getErrorMessage(), e); + } + + try { + cipher.init(Cipher.DECRYPT_MODE, privateKey); + } catch (java.security.InvalidKeyException e) { + throw new InvalidKeyException(SecurityExceptionCodeConstant.MOSIP_INVALID_KEY_EXCEPTION.getErrorCode(), + e.getMessage(), e); + } + /* + * This is a hack of removing OEAP padding after decryption with NO Padding as + * SoftHSM does not support it.Will be removed after HSM implementation + */ + byte[] paddedPlainText = doFinal(data, cipher); + if (paddedPlainText.length < asymmetricKeyLength / 8) { + byte[] tempPipe = new byte[asymmetricKeyLength / 8]; + System.arraycopy(paddedPlainText, 0, tempPipe, tempPipe.length - paddedPlainText.length, + paddedPlainText.length); + paddedPlainText = tempPipe; + } + + return unpadOAEPPadding(paddedPlainText, keyModulus); + } + + // This is a hack of removing OEAP padding after decryption with NO Padding as + // SoftHSM does not support it.Will be removed after HSM implementation + /** + * + * @param paddedPlainText + * @param privateKey + * @return + */ + private byte[] unpadOAEPPadding(byte[] paddedPlainText, BigInteger keyModulus) { + + try { + OAEPEncoding encode = new OAEPEncoding(new RSAEngine(), new SHA256Digest()); + BigInteger exponent = new BigInteger("1"); + RSAKeyParameters keyParams = new RSAKeyParameters(false, keyModulus, exponent); + encode.init(false, keyParams); + return encode.processBlock(paddedPlainText, 0, paddedPlainText.length); + } catch (InvalidCipherTextException e) { + throw new InvalidKeyException(SecurityExceptionCodeConstant.MOSIP_INVALID_KEY_EXCEPTION + .getErrorCode(), e.getMessage(), e); + } + } + + private byte[] jceAsymmetricDecrypt(PrivateKey privateKey, byte[] data, String storeType){ + Objects.requireNonNull(privateKey, SecurityExceptionCodeConstant.MOSIP_INVALID_KEY_EXCEPTION.getErrorMessage()); + CryptoUtils.verifyData(data); + Cipher cipher; + try { + cipher = Objects.isNull(storeType) ? Cipher.getInstance(asymmetricAlgorithm) : + Cipher.getInstance(asymmetricAlgorithm, storeType); + OAEPParameterSpec oaepParams = new OAEPParameterSpec(HASH_ALGO, MGF1, MGF1ParameterSpec.SHA256, + PSpecified.DEFAULT); + cipher.init(Cipher.DECRYPT_MODE, privateKey, oaepParams); + return doFinal(data, cipher); + } catch (java.security.NoSuchAlgorithmException | NoSuchPaddingException | NoSuchProviderException e) { + throw new NoSuchAlgorithmException( + SecurityExceptionCodeConstant.MOSIP_NO_SUCH_ALGORITHM_EXCEPTION.getErrorCode(), + SecurityExceptionCodeConstant.MOSIP_NO_SUCH_ALGORITHM_EXCEPTION.getErrorMessage(), e); + } catch (java.security.InvalidKeyException e) { + throw new InvalidKeyException(SecurityExceptionCodeConstant.MOSIP_INVALID_KEY_EXCEPTION.getErrorCode(), + e.getMessage(), e); + } catch (InvalidAlgorithmParameterException e) { + throw new InvalidParamSpecException( + SecurityExceptionCodeConstant.MOSIP_INVALID_PARAM_SPEC_EXCEPTION.getErrorCode(), + SecurityExceptionCodeConstant.MOSIP_INVALID_PARAM_SPEC_EXCEPTION.getErrorMessage(), e); + } + } + + + @Override + public String hash(byte[] data, byte[] salt) { + CryptoUtils.verifyData(data); + CryptoUtils.verifyData(salt, SecurityExceptionCodeConstant.SALT_PROVIDED_IS_NULL_OR_EMPTY.getErrorCode(), + SecurityExceptionCodeConstant.SALT_PROVIDED_IS_NULL_OR_EMPTY.getErrorMessage()); + SecretKeyFactory secretKeyFactory; + char[] convertedData = new String(data).toCharArray(); + PBEKeySpec pbeKeySpec = new PBEKeySpec(convertedData, salt, iterations, symmetricKeyLength); + SecretKey key; + try { + secretKeyFactory = SecretKeyFactory.getInstance(passwordAlgorithm); + key = secretKeyFactory.generateSecret(pbeKeySpec); + } catch (InvalidKeySpecException e) { + throw new InvalidParamSpecException( + SecurityExceptionCodeConstant.MOSIP_INVALID_PARAM_SPEC_EXCEPTION.getErrorCode(), e.getMessage(), e); + } catch (java.security.NoSuchAlgorithmException e) { + throw new NoSuchAlgorithmException( + SecurityExceptionCodeConstant.MOSIP_NO_SUCH_ALGORITHM_EXCEPTION.getErrorCode(), + SecurityExceptionCodeConstant.MOSIP_NO_SUCH_ALGORITHM_EXCEPTION.getErrorMessage(), e); + } + return DatatypeConverter.printHexBinary(key.getEncoded()); + } + + @Override + public String sign(byte[] data, PrivateKey privateKey) { + Objects.requireNonNull(privateKey, SecurityExceptionCodeConstant.MOSIP_INVALID_KEY_EXCEPTION.getErrorMessage()); + CryptoUtils.verifyData(data); + JsonWebSignature jws = new JsonWebSignature(); + jws.setPayloadBytes(data); + jws.setAlgorithmHeaderValue(signAlgorithm); + jws.setKey(privateKey); + jws.setDoKeyValidation(false); + try { + return jws.getDetachedContentCompactSerialization(); + } catch (JoseException e) { + throw new SignatureException(SecurityExceptionCodeConstant.MOSIP_SIGNATURE_EXCEPTION.getErrorCode(), + e.getMessage(), e); + } + } + + @Override + public boolean verifySignature(byte[] data, String sign, PublicKey publicKey) { + if (EmptyCheckUtils.isNullEmpty(sign)) { + throw new SignatureException(SecurityExceptionCodeConstant.MOSIP_SIGNATURE_EXCEPTION.getErrorCode(), + SecurityExceptionCodeConstant.MOSIP_SIGNATURE_EXCEPTION.getErrorMessage()); + } + Objects.requireNonNull(publicKey, SecurityExceptionCodeConstant.MOSIP_INVALID_KEY_EXCEPTION.getErrorMessage()); + CryptoUtils.verifyData(data); + JsonWebSignature jws = new JsonWebSignature(); + try { + String[] parts = sign.split(PERIOD_SEPARATOR_REGEX); + parts[1] = CryptoUtil.encodeBase64(data); + jws.setCompactSerialization(CompactSerializer.serialize(parts)); + jws.setKey(publicKey); + return jws.verifySignature(); + } catch (ArrayIndexOutOfBoundsException | JoseException e) { + throw new SignatureException(SecurityExceptionCodeConstant.MOSIP_SIGNATURE_EXCEPTION.getErrorCode(), + e.getMessage(), e); + } + + } + + @SuppressWarnings("unchecked") + @Override + public SecureRandom random() { + return secureRandom; + } + + /** + * Generator for IV(Initialisation Vector) + * + * @param blockSize blocksize of current cipher + * @return generated IV + */ + private byte[] generateIV(int blockSize) { + byte[] byteIV = new byte[blockSize]; + secureRandom.nextBytes(byteIV); + return byteIV; + } + + private byte[] doFinal(byte[] data, Cipher cipher) { + try { + return cipher.doFinal(data); + } catch (IllegalBlockSizeException e) { + throw new InvalidDataException( + SecurityExceptionCodeConstant.MOSIP_INVALID_DATA_SIZE_EXCEPTION.getErrorCode(), e.getMessage(), e); + } catch (BadPaddingException e) { + throw new InvalidDataException( + SecurityExceptionCodeConstant.MOSIP_INVALID_ENCRYPTED_DATA_CORRUPT_EXCEPTION.getErrorCode(), + e.getMessage(), e); + } + } + + /* + * This two methods here are for temporary, Unit test for this will be written + * in next versions + */ + @Override + public String sign(byte[] data, PrivateKey privateKey, X509Certificate x509Certificate) { + Objects.requireNonNull(privateKey, SecurityExceptionCodeConstant.MOSIP_INVALID_KEY_EXCEPTION.getErrorMessage()); + CryptoUtils.verifyData(data); + JsonWebSignature jws = new JsonWebSignature(); + List certList = new ArrayList<>(); + certList.add(x509Certificate); + X509Certificate[] certArray = certList.toArray(new X509Certificate[] {}); + jws.setCertificateChainHeaderValue(certArray); + jws.setPayloadBytes(data); + jws.setAlgorithmHeaderValue(signAlgorithm); + jws.setKey(privateKey); + jws.setDoKeyValidation(false); + try { + return jws.getCompactSerialization(); + } catch (JoseException e) { + throw new SignatureException(SecurityExceptionCodeConstant.MOSIP_SIGNATURE_EXCEPTION.getErrorCode(), + e.getMessage(), e); + } + } + + /* + * This two methods here are for temporary, Unit test for this will be written + * in next versions + */ + @Override + public boolean verifySignature(String sign) { + if (EmptyCheckUtils.isNullEmpty(sign)) { + throw new SignatureException(SecurityExceptionCodeConstant.MOSIP_SIGNATURE_EXCEPTION.getErrorCode(), + SecurityExceptionCodeConstant.MOSIP_SIGNATURE_EXCEPTION.getErrorMessage()); + } + JsonWebSignature jws = new JsonWebSignature(); + try { + jws.setCompactSerialization(sign); + List certificateChainHeaderValue = jws.getCertificateChainHeaderValue(); + X509Certificate certificate = certificateChainHeaderValue.get(0); + certificate.checkValidity(); + PublicKey publicKey = certificate.getPublicKey(); + jws.setKey(publicKey); + return jws.verifySignature(); + } catch (JoseException | CertificateExpiredException | CertificateNotYetValidException e) { + throw new SignatureException(SecurityExceptionCodeConstant.MOSIP_SIGNATURE_EXCEPTION.getErrorCode(), + e.getMessage(), e); + } + + } + + +} diff --git a/apitest-commons/src/main/java/io/mosip/testrig/apirig/utils/CryptoUtil.java b/apitest-commons/src/main/java/io/mosip/testrig/apirig/utils/CryptoUtil.java index 1b01bd8de0..7973cc2590 100644 --- a/apitest-commons/src/main/java/io/mosip/testrig/apirig/utils/CryptoUtil.java +++ b/apitest-commons/src/main/java/io/mosip/testrig/apirig/utils/CryptoUtil.java @@ -1,6 +1,7 @@ package io.mosip.testrig.apirig.utils; import io.mosip.kernel.core.crypto.spi.CryptoCoreSpec; + import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -34,8 +35,8 @@ public class CryptoUtil { /** * {@link CryptoCoreSpec} instance for cryptographic functionalities. */ - @Autowired - private CryptoCoreSpec cryptoCore; + //@Autowired + private CryptoCore cryptoCore = new CryptoCore(); diff --git a/apitest-commons/src/main/java/io/mosip/testrig/apirig/utils/EncryptionDecrptionUtil.java b/apitest-commons/src/main/java/io/mosip/testrig/apirig/utils/EncryptionDecrptionUtil.java index a235d5fd0f..3492ae2395 100644 --- a/apitest-commons/src/main/java/io/mosip/testrig/apirig/utils/EncryptionDecrptionUtil.java +++ b/apitest-commons/src/main/java/io/mosip/testrig/apirig/utils/EncryptionDecrptionUtil.java @@ -52,12 +52,12 @@ public class EncryptionDecrptionUtil extends AdminTestUtil{ public static String internalThumbPrint =null; public static String idaFirThumbPrint =null; private static ObjectMapper objMapper = new ObjectMapper(); - @Autowired - private CryptoUtil cryptoUtil; - @Autowired - private KeyMgrUtil keymgrUtil; - @Autowired - private Encrypt encrypt; + //@Autowired + private static CryptoUtil cryptoUtil = new CryptoUtil(); + //@Autowired + private static KeyMgrUtil keymgrUtil = new KeyMgrUtil(); +// @Autowired +// private Encrypt encrypt; static { getThumbprints(); @@ -130,7 +130,7 @@ public Map getInternalEncryptSessionKeyValue(String jsonString) */ - public EncryptionResponseDto encrypt(String jsonString) throws Exception { + public static EncryptionResponseDto encrypt(String jsonString) throws Exception { String refId= null; boolean isInternal = false; @@ -160,11 +160,12 @@ private static String getRefId(boolean isInternal, boolean isBiometrics) { return refId; } - private EncryptionResponseDto kernelEncrypt(String identityBlock, String refId) throws Exception { + private static EncryptionResponseDto kernelEncrypt(String identityBlock, String refId) throws Exception { // String identityBlock = objMapper.writeValueAsString(jsonString); SecretKey secretKey = cryptoUtil.genSecKey(); EncryptionResponseDto encryptionResponseDto = new EncryptionResponseDto(); + lOGGER.info("Strated encrypting the Identity block"); byte[] encryptedIdentityBlock = cryptoUtil.symmetricEncrypt(identityBlock.getBytes(StandardCharsets.UTF_8), secretKey); encryptionResponseDto.setEncryptedIdentity(Base64.getUrlEncoder().encodeToString(encryptedIdentityBlock)); diff --git a/apitest-commons/src/main/java/io/mosip/testrig/apirig/utils/GlobalConstants.java b/apitest-commons/src/main/java/io/mosip/testrig/apirig/utils/GlobalConstants.java index 13241304d0..ea7f726ca6 100644 --- a/apitest-commons/src/main/java/io/mosip/testrig/apirig/utils/GlobalConstants.java +++ b/apitest-commons/src/main/java/io/mosip/testrig/apirig/utils/GlobalConstants.java @@ -115,6 +115,7 @@ public class GlobalConstants { public static final String CERTIFICATEDATA = "certificateData"; public static final String PARTNERDOMAIN = "partnerDomain"; public static final String DATA = ".data"; + public static final String KEYWORD_DATA = "data"; public static final String AUTOMATION = "automation"; public static final String AUTOMATIONLABS = "@automationlabs.com"; public static final String REPSONSE = "Repsonse: %s %s%n"; @@ -211,11 +212,15 @@ public class GlobalConstants { public static final String VID_FEATURE_NOT_SUPPORTED = "VID feature not supported. Hence skipping the testcase"; public static final String UIN_FEATURE_NOT_SUPPORTED = "UIN feature not supported. Hence skipping the testcase"; public static final String FEATURE_NOT_SUPPORTED_MESSAGE = "feature not supported. Hence skipping the testcase"; + public static final String HANDLE_SCHEMA_NOT_DEPLOYED_MESSAGE = "ARRAY HANDLE Related Schema is not there Hence skipping the testcase"; public static final String VID_GENERATED_USING_RESIDENT_API_SO_FEATURE_NOT_SUPPORTED_OR_NEEDED_MESSAGE = "Generating VID using Resident API. So, this feature not supported/needed. Hence skipping the testcase"; public static final String SERVICE_NOT_DEPLOYED_MESSAGE = "Service not deployed. Hence skipping the testcase"; public static final String FEATURE_NOT_SUPPORTED = "feature not supported"; public static final String SERVICE_NOT_DEPLOYED = "Service not deployed"; + public static final String KNOWN_ISSUES_STRING = "known issue"; + public static final String KNOWN_ISSUES = "known issue. Hence skipping the testcase"; public static final String IGNORED_SUBSET_STRING = "feature not supported;Service not deployed"; + public static final String KNOWN_ISSUE_SUBSET_STRING = "known issue;"; public static final String SKIPPED = "Skipped"; public static final String TARGET_ENV_HEALTH_CHECK_FAILED = "Target env health check failed "; public static final String HOTLIST = "hotlist"; @@ -227,4 +232,4 @@ public class GlobalConstants { public static final String SEND_OTP_ENDPOINT = "mimoto/req/"; public static final String CREATE_VID_ENDPOINT = "/idrepository/v1/vid"; public static final String MIMOTO_CREDENTIAL_STATUS = "Mimoto_CredentialsStatus_"; -} \ No newline at end of file +} diff --git a/apitest-commons/src/main/java/io/mosip/testrig/apirig/utils/KernelAuthentication.java b/apitest-commons/src/main/java/io/mosip/testrig/apirig/utils/KernelAuthentication.java index bf40ce6a12..f32f6b75a8 100644 --- a/apitest-commons/src/main/java/io/mosip/testrig/apirig/utils/KernelAuthentication.java +++ b/apitest-commons/src/main/java/io/mosip/testrig/apirig/utils/KernelAuthentication.java @@ -158,8 +158,8 @@ public String getTokenByRole(String role, String tokenType) { batchJobToken = kernelAuthLib.getPreRegToken(); return batchJobToken; - case "invalidBatch": - if (!kernelCmnLib.isValidToken(batchJobToken)) + case "invalidbatch": + if (!kernelCmnLib.isValidToken(invalidBatchJobToken)) invalidBatchJobToken = kernelAuthLib.getPreRegInvalidToken(); return invalidBatchJobToken; @@ -556,22 +556,7 @@ public String getPreRegToken() { @SuppressWarnings("unchecked") public String getPreRegInvalidToken() { - JSONObject actualRequest_generation = getRequestJson("config/prereg_SendOtp.json"); - actualRequest_generation.put(GlobalConstants.REQUESTTIME, clib.getCurrentUTCTime()); - ((JSONObject) actualRequest_generation.get(GlobalConstants.REQUEST)).put("langCode", - BaseTestCase.getLanguageList().get(0)); - ((JSONObject) actualRequest_generation.get(GlobalConstants.REQUEST)).get("userId").toString(); - JSONObject actualRequest_validation = getRequestJson("config/prereg_ValidateOtp.json"); - appl.postWithJson(preregSendOtp, actualRequest_generation); - String otp = null; - if (proxy) - otp = "111222"; - else { - } - ((JSONObject) actualRequest_validation.get(GlobalConstants.REQUEST)).put("otp", otp); - actualRequest_validation.put(GlobalConstants.REQUESTTIME, clib.getCurrentUTCTime()); - Response otpValidate = appl.postWithJson(preregValidateOtp, actualRequest_validation); - cookie = otpValidate.getCookie(GlobalConstants.AUTHORIZATION); + cookie = "ddhdh76478383hdgdgdgg@#$%$%%^^^^^$###$fgdhdhdjj"; return cookie; } diff --git a/apitest-commons/src/main/java/io/mosip/testrig/apirig/utils/OutputValidationUtil.java b/apitest-commons/src/main/java/io/mosip/testrig/apirig/utils/OutputValidationUtil.java index e8537588a6..82d3f6b839 100644 --- a/apitest-commons/src/main/java/io/mosip/testrig/apirig/utils/OutputValidationUtil.java +++ b/apitest-commons/src/main/java/io/mosip/testrig/apirig/utils/OutputValidationUtil.java @@ -580,7 +580,9 @@ public static boolean doesResponseHasErrorCode(String responseString, String all } public static void reportServerIssues(String responseString, TestCaseDTO testCaseDTO) throws AdminTestException { - if (responseString.startsWith("")) + if (responseString.startsWith("") || responseString.startsWith(" testcaseToBeSkippedList = new ArrayList<>(); + + public static void main(String[] args) { + String filePath = "C:\\Users\\sivan\\Downloads\\SynData\\testCaseSkippedList.txt"; // Replace with your file + // path + + loadTestcaseToBeSkippedList(filePath); + + // Example usage of the checkStringInList method + String searchString = "IdRepository_UpdateIdentity_handle_value_value_withupdatevalues"; + boolean exists = isTestCaseInSkippedList(searchString); + logger.info("Does the string exist? " + exists); + + searchString = "IdRepository_UpdateIdentity_handle_value_value_withupdatevalues"; + exists = isTestCaseInSkippedList(searchString); + logger.info("Does the string exist? " + exists); + + } + + // load test cases to be skipped in the execution in the list + public static void loadTestcaseToBeSkippedList(String fileName) { + try (BufferedReader br = new BufferedReader( + new FileReader(MosipTestRunner.getGlobalResourcePath() + "/" + fileName))) { + String line; + while ((line = br.readLine()) != null) { + // Ignore lines starting with # as it is commented line + if (line.startsWith("#")) { + continue; + } + + // Split the line by "------" and store the second part + if (line.contains("------")) { + String[] parts = line.split("------"); + if (parts.length > 1) { + testcaseToBeSkippedList.add(parts[1].trim()); + } + } + } + } catch (IOException e) { + e.printStackTrace(); + } + } + + // Method to check if a given test case exists in the list + public static boolean isTestCaseInSkippedList(String strTestCase) { + return testcaseToBeSkippedList.contains(strTestCase); + } +} \ No newline at end of file diff --git a/authentication-demo-service/pom.xml b/authentication-demo-service/pom.xml index cc1db3e5d5..1f9fa8d852 100644 --- a/authentication-demo-service/pom.xml +++ b/authentication-demo-service/pom.xml @@ -1,388 +1,391 @@ - 4.0.0 - - - io.mosip.testrig.authentication.demo - 1.2.1-java21-SNAPSHOT - authentication-demo-service - authentication-demo-service - Parent project of MOSIP functional tests - https://github.com/mosip/mosip-functional-tests - jar - - - - MPL 2.0 - https://www.mozilla.org/en-US/MPL/2.0/ - - - - - scm:git:git://github.com/mosip/mosip-functional-tests.git - scm:git:ssh://github.com:mosip/mosip-functional-tests.git - https://github.com/mosip/mosip-functional-tests - HEAD - - - - - Mosip - mosip.emailnotifier@gmail.com - io.mosip - https://github.com/mosip/mosip-functional-tests - - - - - - local-maven-repo - file:///${basedir}/lib - - - - snapshots-repo - https://oss.sonatype.org/content/repositories/snapshots - false - true - - - - releases-repo - https://oss.sonatype.org/service/local/staging/deploy/maven2 - false - false - - - - danubetech-maven-public - https://repo.danubetech.com/repository/maven-public/ - - - - - - 3.2.3 - 2.0.0.RELEASE - - 21 - 21 - 3.8.0 - 3.0.1 - 2.9.2 - 0.8.2 - false - - 1.2.1-java21-SNAPSHOT - - - - - - - org.springframework.boot - spring-boot-starter-web - - - org.springframework.boot - spring-boot-starter-test - - - commons-io - commons-io - - - javax.ws.rs - javax.ws.rs-api - 2.0 - - - org.glassfish.jersey.core - jersey-common - test - - - io.mosip.authentication - authentication-core - 1.2.1-java21-SNAPSHOT - - - commons-codec - commons-codec - - - - - commons-fileupload - commons-fileupload - - - - org.mockito - mockito-core - - - - io.mosip.kernel - kernel-core - 1.2.1-java21-SNAPSHOT - - - org.springframework.boot - - spring-boot-starter-security - - - - commons-codec - commons-codec - - - - - io.mosip.kernel - kernel-websubclient-api - ${kernel-websubclient-api.version} - - - - org.springframework.boot - spring-boot-starter-actuator - - - - org.apache.httpcomponents - httpclient - - - commons-codec - commons-codec - - - - - - - org.apache.httpcomponents - httpmime - 4.5.7 - - - org.json - json - 20180813 - - - org.apache.commons - commons-lang3 - - - org.tensorflow - tensorflow - 1.12.0 - - - - org.apache.commons - commons-io - 1.3.2 - - - - - commons-lang - commons-lang - 2.4 - - - org.apache.commons - commons-text - 1.6 - - - commons-codec - commons-codec - - - io.mosip.kernel - kernel-templatemanager-velocity - 1.2.1-java21-SNAPSHOT - - - org.springframework.cloud - spring-cloud-starter-config - - - org.postgresql - postgresql - - - com.github.jai-imageio - jai-imageio-jpeg2000 - 1.3.0 - - - org.json - json - 20180813 - - - io.mosip.kernel - kernel-keymanager-service - 1.2.1-java21-SNAPSHOT - lib - - - org.springframework.boot - - spring-boot-starter-security - - - - - - dom4j - dom4j - 1.6.1 - - - org.junit.vintage - junit-vintage-engine - - - org.springdoc - springdoc-openapi-starter-webmvc-ui - 2.5.0 - - - - - - io.mosip.kernel - kernel-bom - 1.2.1-java21-SNAPSHOT - pom - import - - - - - - - org.apache.maven.plugins - maven-javadoc-plugin - - - attach-javadocs - - jar - - - - - none - - - - org.springframework.boot - spring-boot-maven-plugin - ${spring.boot.version} - - true - ZIP - - - - - build-info - repackage - - - - - - - org.apache.maven.plugins - maven-gpg-plugin - 1.5 - - - sign-artifacts - verify - - sign - - - - --pinentry-mode - loopback - - - - - - - pl.project13.maven - git-commit-id-plugin - 3.0.1 - - - get-the-git-infos - - revision - - validate - - - - true - ${project.build.outputDirectory}/service-git.properties - - ^git.build.(time|version)$ - ^git.commit.id.(abbrev|full)$ - - full - ${project.basedir}/.git - - - - - org.apache.maven.plugins - maven-compiler-plugin - ${maven.compiler.version} - - ${maven.compiler.source} - ${maven.compiler.target} - - - - org.jacoco - jacoco-maven-plugin - - - **/constant/** - **/config/** - **/dto/** - io/mosip/authentication/service/*.class - io/mosip/authentication/service/filter/** - io/mosip/demo/authentication/service/IdAuthenticationDemoApplication.class - - - - - - prepare-agent - - - - report - prepare-package - - report - - - - - - + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + 4.0.0 + + + io.mosip.testrig.authentication.demo + 1.2.1-SNAPSHOT + authentication-demo-service + authentication-demo-service + Parent project of MOSIP functional tests + https://github.com/mosip/mosip-functional-tests + jar + + + + MPL 2.0 + https://www.mozilla.org/en-US/MPL/2.0/ + + + + + scm:git:git://github.com/mosip/mosip-functional-tests.git + scm:git:ssh://github.com:mosip/mosip-functional-tests.git + https://github.com/mosip/mosip-functional-tests + HEAD + + + + + Mosip + mosip.emailnotifier@gmail.com + io.mosip + https://github.com/mosip/mosip-functional-tests + + + + + + local-maven-repo + file:///${basedir}/lib + + + + snapshots-repo + https://oss.sonatype.org/content/repositories/snapshots + false + true + + + + releases-repo + https://oss.sonatype.org/service/local/staging/deploy/maven2 + false + false + + + + danubetech-maven-public + https://repo.danubetech.com/repository/maven-public/ + + + + + + 3.2.3 + 2.0.0.RELEASE + + 21 + 21 + 3.8.0 + 3.0.1 + 2.9.2 + 0.8.2 + + 1.2.1-SNAPSHOT + + + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-test + + + commons-io + commons-io + + + javax.ws.rs + javax.ws.rs-api + 2.0 + + + org.glassfish.jersey.core + jersey-common + test + + + io.mosip.authentication + authentication-core + 1.2.1-SNAPSHOT + + + commons-codec + commons-codec + + + org.springdoc + springdoc-openapi-ui + + + + + commons-fileupload + commons-fileupload + + + + org.mockito + mockito-core + + + + io.mosip.kernel + kernel-core + 1.2.1-SNAPSHOT + + + org.springframework.boot + + spring-boot-starter-security + + + + commons-codec + commons-codec + + + + + io.mosip.kernel + kernel-websubclient-api + ${kernel-websubclient-api.version} + + + + org.springframework.boot + spring-boot-starter-actuator + + + + org.apache.httpcomponents + httpclient + + + commons-codec + commons-codec + + + + + + + org.apache.httpcomponents + httpmime + 4.5.7 + + + org.json + json + 20231013 + + + org.apache.commons + commons-lang3 + + + org.tensorflow + tensorflow + 1.12.0 + + + + org.apache.commons + commons-io + 1.3.2 + + + + + commons-lang + commons-lang + 2.4 + + + org.apache.commons + commons-text + 1.10.0 + + + commons-codec + commons-codec + + + io.mosip.kernel + kernel-templatemanager-velocity + 1.2.1-SNAPSHOT + + + org.springframework.cloud + spring-cloud-starter-config + + + org.postgresql + postgresql + + + com.github.jai-imageio + jai-imageio-jpeg2000 + 1.3.0 + + + org.json + json + 20231013 + + + io.mosip.kernel + kernel-keymanager-service + 1.2.1-SNAPSHOT + lib + + + org.springframework.boot + + spring-boot-starter-security + + + + + + dom4j + dom4j + 1.6.1 + + + org.junit.vintage + junit-vintage-engine + + + org.springdoc + springdoc-openapi-starter-webmvc-ui + 2.6.0 + + + + + + io.mosip.kernel + kernel-bom + 1.2.1-SNAPSHOT + pom + import + + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + + + attach-javadocs + + jar + + + + + none + + + + org.springframework.boot + spring-boot-maven-plugin + ${spring.boot.version} + + true + ZIP + + + + + build-info + repackage + + + + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.5 + + + sign-artifacts + verify + + sign + + + + --pinentry-mode + loopback + + + + + + + pl.project13.maven + git-commit-id-plugin + 3.0.1 + + + get-the-git-infos + + revision + + validate + + + + true + ${project.build.outputDirectory}/service-git.properties + + ^git.build.(time|version)$ + ^git.commit.id.(abbrev|full)$ + + full + ${project.basedir}/.git + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven.compiler.version} + + ${maven.compiler.source} + ${maven.compiler.target} + + + + org.jacoco + jacoco-maven-plugin + + + **/constant/** + **/config/** + **/dto/** + io/mosip/authentication/service/*.class + io/mosip/authentication/service/filter/** + io/mosip/demo/authentication/service/IdAuthenticationDemoApplication.class + + + + + + prepare-agent + + + + report + prepare-package + + report + + + + + + \ No newline at end of file diff --git a/deploy/apitestrig/README.md b/deploy/apitestrig/README.md new file mode 100644 index 0000000000..ef7619b8ae --- /dev/null +++ b/deploy/apitestrig/README.md @@ -0,0 +1,44 @@ +# APITESTRIG + +## Introduction +ApiTestRig will test the working of APIs of the MOSIP modules. + +## Install +* Review `values.yaml` and, Make sure to enable required modules for apitestrig operation. +* Install +```sh +./install.sh +``` +* During the execution of the `install.sh` script, a prompt appears requesting information regarding the presence of a public domain and a valid SSL certificate on the server. +* If the server lacks a public domain and a valid SSL certificate, it is advisable to select the `n` option. Opting it will enable the `init-container` with an `emptyDir` volume and include it in the deployment process. +* The init-container will proceed to download the server's self-signed SSL certificate and mount it to the specified location within the container's Java keystore (i.e., `cacerts`) file. +* This particular functionality caters to scenarios where the script needs to be employed on a server utilizing self-signed SSL certificates. + +## Uninstall +* To uninstall ApiTestRig, run `delete.sh` script. +```sh +./delete.sh +``` + +## Run apitestrig manually + +#### Rancher UI +* Run apitestrig manually via Rancher UI. + ![apitestrig-2.png](../../docs/_images/apitestrig-2.png) +* There are two modes of apitestrig `smoke` & `smokeAndRegression`. +* By default, apitestrig will execute with `smokeAndRegression`.
+ If you want to run apitestrig with only `smoke`.
+ You have to update the `apitestrig` configmap and rerun the specific apitestrig job. + +#### CLI +* Download Kubernetes cluster `kubeconfig` file from `rancher dashboard` to your local. + ![apitestrig-1.png](../../docs/_images/apitestrig-1.png) +* Install `kubectl` package to your local machine. +* Run apitestrig manually via CLI by creating a new job from an existing k8s cronjob. + ``` + kubectl --kubeconfig= -n apitestrig create job --from=cronjob/ + ``` + example: + ``` + kubectl --kubeconfig=/home/xxx/Downloads/qa4.config -n apitestrig create job --from=cronjob/cronjob-apitestrig-masterdata cronjob-apitestrig-masterdata + ``` diff --git a/deploy/apitestrig/copy_cm.sh b/deploy/apitestrig/copy_cm.sh new file mode 100644 index 0000000000..450e385ca0 --- /dev/null +++ b/deploy/apitestrig/copy_cm.sh @@ -0,0 +1,25 @@ +#!/bin/bash +# Copy configmaps from other namespaces +# DST_NS: Destination namespace + +function copying_cm() { + UTIL_URL=https://raw.githubusercontent.com/mosip/mosip-infra/master/deployment/v3/utils/copy_cm_func.sh + COPY_UTIL=./copy_cm_func.sh + DST_NS=apitestrig + + wget -q $UTIL_URL -O copy_cm_func.sh && chmod +x copy_cm_func.sh + + $COPY_UTIL configmap global default $DST_NS + $COPY_UTIL configmap keycloak-host keycloak $DST_NS + $COPY_UTIL configmap artifactory-share artifactory $DST_NS + $COPY_UTIL configmap config-server-share config-server $DST_NS + return 0 +} + +# set commands for error handling. +set -e +set -o errexit ## set -e : exit the script if any statement returns a non-true return value +set -o nounset ## set -u : exit the script if you try to use an uninitialised variable +set -o errtrace # trace ERR through 'time command' and other functions +set -o pipefail # trace ERR through pipes +copying_cm # calling function \ No newline at end of file diff --git a/deploy/apitestrig/copy_secrets.sh b/deploy/apitestrig/copy_secrets.sh new file mode 100644 index 0000000000..f0948b5f6d --- /dev/null +++ b/deploy/apitestrig/copy_secrets.sh @@ -0,0 +1,24 @@ +#!/bin/bash +# Copy secrets from other namespaces +# DST_NS: Destination namespace + +function copying_secrets() { + UTIL_URL=https://raw.githubusercontent.com/mosip/mosip-infra/master/deployment/v3/utils/copy_cm_func.sh + COPY_UTIL=./copy_cm_func.sh + DST_NS=apitestrig + + wget -q $UTIL_URL -O copy_cm_func.sh && chmod +x copy_cm_func.sh + + $COPY_UTIL secret keycloak-client-secrets keycloak $DST_NS + $COPY_UTIL secret s3 s3 $DST_NS + $COPY_UTIL secret postgres-postgresql postgres $DST_NS + return 0 +} + +# set commands for error handling. +set -e +set -o errexit ## set -e : exit the script if any statement returns a non-true return value +set -o nounset ## set -u : exit the script if you try to use an uninitialised variable +set -o errtrace # trace ERR through 'time command' and other functions +set -o pipefail # trace ERR through pipes +copying_secrets # calling function \ No newline at end of file diff --git a/deploy/apitestrig/delete.sh b/deploy/apitestrig/delete.sh new file mode 100644 index 0000000000..6a28aa852f --- /dev/null +++ b/deploy/apitestrig/delete.sh @@ -0,0 +1,30 @@ +#!/bin/bash +# Uninstalls apitestrig +## Usage: ./delete.sh [kubeconfig] + +if [ $# -ge 1 ] ; then + export KUBECONFIG=$1 +fi + +function deleting_apitestrig() { + NS=apitestrig + while true; do + read -p "Are you sure you want to delete apitestrig helm charts?(Y/n) " yn + if [ $yn = "Y" ] + then + helm -n $NS delete apitestrig + break + else + break + fi + done + return 0 +} + +# set commands for error handling. +set -e +set -o errexit ## set -e : exit the script if any statement returns a non-true return value +set -o nounset ## set -u : exit the script if you try to use an uninitialised variable +set -o errtrace # trace ERR through 'time command' and other functions +set -o pipefail # trace ERR through pipes +deleting_apitestrig # calling function \ No newline at end of file diff --git a/deploy/apitestrig/install.sh b/deploy/apitestrig/install.sh new file mode 100644 index 0000000000..cd6d4783af --- /dev/null +++ b/deploy/apitestrig/install.sh @@ -0,0 +1,124 @@ +#!/bin/bash +# Installs apitestrig +## Usage: ./install.sh [kubeconfig] + +if [ $# -ge 1 ] ; then + export KUBECONFIG=$1 +fi + +NS=apitestrig +CHART_VERSION=0.0.1-develop + +echo Create $NS namespace +kubectl create ns $NS + +function installing_apitestrig() { + echo Istio label + kubectl label ns $NS istio-injection=disabled --overwrite + helm repo update + + echo Copy configmaps + ./copy_cm.sh + + echo Copy secrets + ./copy_secrets.sh + + echo "Delete s3, db, & apitestrig configmap if exists" + kubectl -n $NS delete --ignore-not-found=true configmap s3 + kubectl -n $NS delete --ignore-not-found=true configmap db + kubectl -n $NS delete --ignore-not-found=true configmap apitestrig + + DB_HOST=$( kubectl -n default get cm global -o json |jq -r '.data."mosip-api-internal-host"' ) + API_INTERNAL_HOST=$( kubectl -n default get cm global -o json |jq -r '.data."mosip-api-internal-host"' ) + ENV_USER=$( kubectl -n default get cm global -o json |jq -r '.data."mosip-api-internal-host"' | awk -F '.' '/api-internal/{print $1"."$2}') + + read -p "Please enter the time(hr) to run the cronjob every day (time: 0-23) : " time + if [ -z "$time" ]; then + echo "ERROT: Time cannot be empty; EXITING;"; + exit 1; + fi + if ! [ $time -eq $time ] 2>/dev/null; then + echo "ERROR: Time $time is not a number; EXITING;"; + exit 1; + fi + if [ $time -gt 23 ] || [ $time -lt 0 ] ; then + echo "ERROR: Time should be in range ( 0-23 ); EXITING;"; + exit 1; + fi + + echo "Do you have public domain & valid SSL? (Y/n) " + echo "Y: if you have public domain & valid ssl certificate" + echo "n: If you don't have a public domain and a valid SSL certificate. Note: It is recommended to use this option only in development environments." + read -p "" flag + + if [ -z "$flag" ]; then + echo "'flag' was provided; EXITING;" + exit 1; + fi + ENABLE_INSECURE='' + if [ "$flag" = "n" ]; then + ENABLE_INSECURE='--set enable_insecure=true'; + fi + + read -p "Please provide the retention days to remove old reports ( Default: 3 )" reportExpirationInDays + + if [[ -z $reportExpirationInDays ]]; then + reportExpirationInDays=3 + fi + if ! [[ $reportExpirationInDays =~ ^[0-9]+$ ]]; then + echo "The variable \"reportExpirationInDays\" should contain only number; EXITING"; + exit 1; + fi + + read -p "Please provide slack webhook URL to notify server end issues on your slack channel : " slackWebhookUrl + + if [ -z $slackWebhookUrl ]; then + echo "slack webhook URL not provided; EXITING;" + exit 1; + fi + + valid_inputs=("yes" "no") + eSignetDeployed="" + + while [[ ! " ${valid_inputs[@]} " =~ " ${eSignetDeployed} " ]]; do + read -p "Is the eSignet service deployed? (yes/no): " eSignetDeployed + eSignetDeployed=${eSignetDeployed,,} # Convert input to lowercase + done + + if [[ $eSignetDeployed == "yes" ]]; then + echo "eSignet service is deployed. Proceeding with installation..." + else + echo "eSignet service is not deployed. hence will be skipping esignet related test-cases..." + fi + + echo Installing apitestrig + helm -n $NS install apitestrig mosip/apitestrig \ + --set crontime="0 $time * * *" \ + -f values.yaml \ + --version $CHART_VERSION \ + --set apitestrig.configmaps.s3.s3-host='http://minio.minio:9000' \ + --set apitestrig.configmaps.s3.s3-user-key='admin' \ + --set apitestrig.configmaps.s3.s3-region='' \ + --set apitestrig.configmaps.db.db-server="$DB_HOST" \ + --set apitestrig.configmaps.db.db-su-user="postgres" \ + --set apitestrig.configmaps.db.db-port="5432" \ + --set apitestrig.configmaps.apitestrig.ENV_USER="$ENV_USER" \ + --set apitestrig.configmaps.apitestrig.ENV_ENDPOINT="https://$API_INTERNAL_HOST" \ + --set apitestrig.configmaps.apitestrig.ENV_TESTLEVEL="smokeAndRegression" \ + --set apitestrig.configmaps.apitestrig.reportExpirationInDays="$reportExpirationInDays" \ + --set apitestrig.configmaps.apitestrig.slack-webhook-url="$slackWebhookUrl" \ + --set apitestrig.configmaps.apitestrig.eSignetDeployed="$eSignetDeployed" \ + --set apitestrig.configmaps.apitestrig.NS="$NS" \ + $ENABLE_INSECURE + + echo Installed apitestrig. + return 0 +} + +# set commands for error handling. +set -e +set -o errexit ## set -e : exit the script if any statement returns a non-true return value +set -o nounset ## set -u : exit the script if you try to use an uninitialised variable +set -o errtrace # trace ERR through 'time command' and other functions +set -o pipefail # trace ERR through pipes +installing_apitestrig # calling function \ No newline at end of file diff --git a/deploy/apitestrig/values.yaml b/deploy/apitestrig/values.yaml new file mode 100644 index 0000000000..fd2bca2911 --- /dev/null +++ b/deploy/apitestrig/values.yaml @@ -0,0 +1,55 @@ +modules: + prereg: + enabled: false + image: + repository: mosipqa/apitest-prereg + tag: develop + pullPolicy: Always + masterdata: + enabled: false + image: + repository: mosipqa/apitest-masterdata + tag: develop + pullPolicy: Always + idrepo: + enabled: false + image: + repository: mosipqa/apitest-idrepo + tag: develop + pullPolicy: Always + partner: + enabled: false + image: + repository: mosipqa/apitest-pms + tag: develop + pullPolicy: Always + pms: + enabled: false + image: + repository: mosipdev/apitest-pms + tag: develop + pullPolicy: Always + resident: + enabled: false + image: + repository: mosipqa/apitest-resident + tag: develop + pullPolicy: Always + auth: + enabled: false + image: + repository: mosipqa/apitest-auth + tag: develop + pullPolicy: Always + esignet: + enabled: false + image: + repository: mosipqa/apitest-esignet + tag: develop + pullPolicy: Always + mimoto: + enabled: false + image: + repository: mosipqa/apitest-mimoto + tag: develop + pullPolicy: Always diff --git a/deploy/uitestrig/README.md b/deploy/uitestrig/README.md new file mode 100644 index 0000000000..c1dc01550b --- /dev/null +++ b/deploy/uitestrig/README.md @@ -0,0 +1,42 @@ +# UITESTRIG + +## Introduction +UITESTRIG will test end-to-end functional flows involving multiple UI modules. + +## Install +* Install +```sh +./install.sh +``` + +## Uninstall +* To uninstall UITESTRIG, run `delete.sh` script. +```sh +./delete.sh +``` + +## Run UITESTRIG manually + +#### CLI +* Download Kubernetes cluster `kubeconfig` file from `rancher dashboard` to your local. +* Install `kubectl` package to your local machine. +* Run UITESTRIG manually via CLI by creating a new job from an existing k8s cronjob. + ``` + kubectl --kubeconfig= -n UITESTRIG create job --from=cronjob/ + ``` + example: + ``` + kubectl --kubeconfig=/home/xxx/Downloads/qa4.config -n UITESTRIG create job --from=cronjob/cronjob-uitestrig cronjob-uitestrig + ``` + +## Run ui-testrig using rancher-ui + +#### Rancher UI +* Run ui-testrig manually via Rancher UI. + ![ui-testrig.png](../../docs/_images/ui-testrig.png) +* There are 3 cronjobs for ui-testrig: + - adminui + - pmp-ui + - residentui +* select the cronjob which you want to initiate and select the `Run Now` button as shown in the above picture. +* Once the job is completed the reports will be avaiable in `S3/minio`. diff --git a/deploy/uitestrig/copy_cm.sh b/deploy/uitestrig/copy_cm.sh new file mode 100644 index 0000000000..828bb6d6de --- /dev/null +++ b/deploy/uitestrig/copy_cm.sh @@ -0,0 +1,25 @@ +#!/bin/bash +# Copy configmaps from other namespaces +# DST_NS: Destination namespace + +function copying_cm() { + UTIL_URL=https://raw.githubusercontent.com/mosip/mosip-infra/master/deployment/v3/utils/copy_cm_func.sh + COPY_UTIL=./copy_cm_func.sh + DST_NS=uitestrig + + wget -q $UTIL_URL -O copy_cm_func.sh && chmod +x copy_cm_func.sh + + $COPY_UTIL configmap global default $DST_NS + $COPY_UTIL configmap keycloak-host keycloak $DST_NS + $COPY_UTIL configmap artifactory-share artifactory $DST_NS + $COPY_UTIL configmap config-server-share config-server $DST_NS + return 0 +} + +# set commands for error handling. +set -e +set -o errexit ## set -e : exit the script if any statement returns a non-true return value +set -o nounset ## set -u : exit the script if you try to use an uninitialised variable +set -o errtrace # trace ERR through 'time command' and other functions +set -o pipefail # trace ERR through pipes +copying_cm # calling function \ No newline at end of file diff --git a/deploy/uitestrig/copy_secrets.sh b/deploy/uitestrig/copy_secrets.sh new file mode 100644 index 0000000000..47561e6ade --- /dev/null +++ b/deploy/uitestrig/copy_secrets.sh @@ -0,0 +1,24 @@ +#!/bin/bash +# Copy secrets from other namespaces +# DST_NS: Destination namespace + +function copying_secrets() { + UTIL_URL=https://raw.githubusercontent.com/mosip/mosip-infra/master/deployment/v3/utils/copy_cm_func.sh + COPY_UTIL=./copy_cm_func.sh + DST_NS=uitestrig + + wget -q $UTIL_URL -O copy_cm_func.sh && chmod +x copy_cm_func.sh + + $COPY_UTIL secret keycloak-client-secrets keycloak $DST_NS + $COPY_UTIL secret s3 s3 $DST_NS + $COPY_UTIL secret postgres-postgresql postgres $DST_NS + return 0 +} + +# set commands for error handling. +set -e +set -o errexit ## set -e : exit the script if any statement returns a non-true return value +set -o nounset ## set -u : exit the script if you try to use an uninitialised variable +set -o errtrace # trace ERR through 'time command' and other functions +set -o pipefail # trace ERR through pipes +copying_secrets # calling function \ No newline at end of file diff --git a/deploy/uitestrig/delete.sh b/deploy/uitestrig/delete.sh new file mode 100644 index 0000000000..fac7ba3b56 --- /dev/null +++ b/deploy/uitestrig/delete.sh @@ -0,0 +1,30 @@ +#!/bin/bash +# Uninstalls uitestrig +## Usage: ./delete.sh [kubeconfig] + +if [ $# -ge 1 ] ; then + export KUBECONFIG=$1 +fi + +function deleting_uitestrig() { + NS=uitestrig + while true; do + read -p "Are you sure you want to delete uitestrig helm charts?(Y/n) " yn + if [ $yn = "Y" ] + then + helm -n $NS delete uitestrig + break + else + break + fi + done + return 0 +} + +# set commands for error handling. +set -e +set -o errexit ## set -e : exit the script if any statement returns a non-true return value +set -o nounset ## set -u : exit the script if you try to use an uninitialised variable +set -o errtrace # trace ERR through 'time command' and other functions +set -o pipefail # trace ERR through pipes +deleting_uitestrig # calling function \ No newline at end of file diff --git a/deploy/uitestrig/install.sh b/deploy/uitestrig/install.sh new file mode 100644 index 0000000000..98c0577ff1 --- /dev/null +++ b/deploy/uitestrig/install.sh @@ -0,0 +1,91 @@ +#!/bin/bash +# Installs uitestrig automation +## Usage: ./install.sh [kubeconfig] + +if [ $# -ge 1 ] ; then + export KUBECONFIG=$1 +fi + +NS=uitestrig +CHART_VERSION=0.0.1-develop + +echo Create $NS namespace +kubectl create ns $NS + + +function installing_uitestrig() { + ENV_NAME=$( kubectl -n default get cm global -o json |jq -r '.data."installation-domain"') + + read -p "Please enter the time(hr) to run the cronjob every day (time: 0-23) : " time + if [ -z "$time" ]; then + echo "ERROR: Time cannot be empty; EXITING;"; + exit 1; + fi + if ! [ $time -eq $time ] 2>/dev/null; then + echo "ERROR: Time $time is not a number; EXITING;"; + exit 1; + fi + if [ $time -gt 23 ] || [ $time -lt 0 ] ; then + echo "ERROR: Time should be in range ( 0-23 ); EXITING;"; + exit 1; + fi + + echo "Do you have public domain & valid SSL? (Y/n) " + echo "Y: if you have public domain & valid ssl certificate" + echo "n: if you don't have public domain & valid ssl certificate" + read -p "" flag + + if [ -z "$flag" ]; then + echo "'flag' was provided; EXITING;" + exit 1; + fi + ENABLE_INSECURE='' + if [ "$flag" = "n" ]; then + ENABLE_INSECURE='--set uitestrig.configmaps.uitestrig.ENABLE_INSECURE=true'; + fi + + echo Istio label + kubectl label ns $NS istio-injection=disabled --overwrite + helm repo update + + echo Copy configmaps + ./copy_cm.sh + + echo Copy secrets + ./copy_secrets.sh + + DB_HOST=$( kubectl -n default get cm global -o json |jq -r '.data."mosip-api-internal-host"' ) + PMP_HOST=$(kubectl -n default get cm global -o json |jq -r '.data."mosip-pmp-host"') + ADMIN_HOST=$(kubectl -n default get cm global -o json |jq -r '.data."mosip-admin-host"') + RESIDENT_HOST=$(kubectl -n default get cm global -o json |jq -r '.data."mosip-resident-host"') + API_INTERNAL_HOST=$( kubectl -n default get cm global -o json |jq -r '.data."mosip-api-internal-host"' ) + + echo Installing uitestrig + helm -n $NS install uitestrig mosip/uitestrig \ + --set crontime="0 $time * * *" \ + -f values.yaml \ + --version $CHART_VERSION \ + --set uitestrig.configmaps.s3.s3-host='http://minio.minio:9000' \ + --set uitestrig.configmaps.s3.s3-user-key='admin' \ + --set uitestrig.configmaps.s3.s3-region='' \ + --set uitestrig.configmaps.db.db-server="$DB_HOST" \ + --set uitestrig.configmaps.db.db-su-user="postgres" \ + --set uitestrig.configmaps.db.db-port="5432" \ + --set uitestrig.configmaps.uitestrig.apiInternalEndPoint="https://$API_INTERNAL_HOST" \ + --set uitestrig.configmaps.uitestrig.apiEnvUser="$API_INTERNAL_HOST" \ + --set uitestrig.configmaps.uitestrig.PmpPortalPath="https://$PMP_HOST" \ + --set uitestrig.configmaps.uitestrig.adminPortalPath="https://$ADMIN_HOST" \ + --set uitestrig.configmaps.uitestrig.residentPortalPath="https://$RESIDENT_HOST" \ + --set uitestrig.configmaps.uitestrig.NS="$NS" \ + $ENABLE_INSECURE + + return 0 +} + +# set commands for error handling. +set -e +set -o errexit ## set -e : exit the script if any statement returns a non-true return value +set -o nounset ## set -u : exit the script if you try to use an uninitialised variable +set -o errtrace # trace ERR through 'time command' and other functions +set -o pipefail # trace ERR through pipes +installing_uitestrig # calling function \ No newline at end of file diff --git a/deploy/uitestrig/values.yaml b/deploy/uitestrig/values.yaml new file mode 100644 index 0000000000..014727441d --- /dev/null +++ b/deploy/uitestrig/values.yaml @@ -0,0 +1,22 @@ +modules: + - name: admin-ui + enabled: false + image: + registry: docker.io + repository: mosipqa/uitest-admin + tag: develop + pullPolicy: Always + - name: pmp-ui + enabled: false + image: + registry: docker.io + repository: mosipqa/uitest-pmp + tag: develop + pullPolicy: Always + - name: resident-ui + enabled: false + image: + registry: docker.io + repository: mosipqa/uitest-resident + tag: develop + pullPolicy: Always diff --git a/docs/_images/apitestrig-1.png b/docs/_images/apitestrig-1.png new file mode 100644 index 0000000000..a7f36f6f05 Binary files /dev/null and b/docs/_images/apitestrig-1.png differ diff --git a/docs/_images/apitestrig-2.png b/docs/_images/apitestrig-2.png new file mode 100644 index 0000000000..c6e48e63d3 Binary files /dev/null and b/docs/_images/apitestrig-2.png differ diff --git a/docs/_images/ui-testrig.png b/docs/_images/ui-testrig.png new file mode 100644 index 0000000000..d2010016f7 Binary files /dev/null and b/docs/_images/ui-testrig.png differ diff --git a/helm/apitestrig/.gitignore b/helm/apitestrig/.gitignore new file mode 100644 index 0000000000..ee3892e879 --- /dev/null +++ b/helm/apitestrig/.gitignore @@ -0,0 +1 @@ +charts/ diff --git a/helm/apitestrig/.helmignore b/helm/apitestrig/.helmignore new file mode 100644 index 0000000000..f0c1319444 --- /dev/null +++ b/helm/apitestrig/.helmignore @@ -0,0 +1,21 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*~ +# Various IDEs +.project +.idea/ +*.tmproj diff --git a/helm/apitestrig/Chart.yaml b/helm/apitestrig/Chart.yaml new file mode 100644 index 0000000000..ffa48e31d3 --- /dev/null +++ b/helm/apitestrig/Chart.yaml @@ -0,0 +1,19 @@ +apiVersion: v2 +name: apitestrig +description: A Helm chart to deploy APITESTRIG for MOSIP modules +type: application +version: 0.0.1-develop +appVersion: "" +dependencies: + - name: common + repository: https://charts.bitnami.com/bitnami + tags: + - bitnami-common + version: 1.x.x +home: https://mosip.io +keywords: + - mosip + - apitestrig +maintainers: + - email: info@mosip.io + name: MOSIP diff --git a/helm/apitestrig/README.md b/helm/apitestrig/README.md new file mode 100644 index 0000000000..25c35e3591 --- /dev/null +++ b/helm/apitestrig/README.md @@ -0,0 +1,10 @@ +# APITESTRIG + +Helm chart to deploy APITESTRIG for `MOSIP` modules + +## TL;DR + +```console +$ helm repo add mosip https://mosip.github.io +$ helm install my-release mosip/apitestrig +``` diff --git a/helm/apitestrig/templates/NOTES.txt b/helm/apitestrig/templates/NOTES.txt new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/helm/apitestrig/templates/NOTES.txt @@ -0,0 +1 @@ + diff --git a/helm/apitestrig/templates/_helpers.tpl b/helm/apitestrig/templates/_helpers.tpl new file mode 100644 index 0000000000..d99caf0c43 --- /dev/null +++ b/helm/apitestrig/templates/_helpers.tpl @@ -0,0 +1,63 @@ +{{/* +Return the proper image name +*/}} +{{- define "apitestrig.image" -}} +{{ include "common.images.image" (dict "imageRoot" .Values.image "global" .Values.global) }} +{{- end -}} + +{{/* +Return the proper image name (for the init container volume-permissions image) +*/}} +{{- define "apitestrig.volumePermissions.image" -}} +{{- include "common.images.image" ( dict "imageRoot" .Values.volumePermissions.image "global" .Values.global ) -}} +{{- end -}} + +{{/* +Return the proper Docker Image Registry Secret Names +*/}} +{{- define "apitestrig.imagePullSecrets" -}} +{{- include "common.images.pullSecrets" (dict "images" (list .Values.image .Values.volumePermissions.image) "global" .Values.global) -}} +{{- end -}} + +{{/* +Create the name of the service account to use +*/}} +{{- define "apitestrig.serviceAccountName" -}} +{{- if .Values.serviceAccount.create -}} + {{ default (printf "%s" (include "common.names.fullname" .)) .Values.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.serviceAccount.name }} +{{- end -}} +{{- end -}} + +{{/* +Compile all warnings into a single message. +*/}} +{{- define "apitestrig.validateValues" -}} +{{- $messages := list -}} +{{- $messages := append $messages (include "apitestrig.validateValues.foo" .) -}} +{{- $messages := append $messages (include "apitestrig.validateValues.bar" .) -}} +{{- $messages := without $messages "" -}} +{{- $message := join "\n" $messages -}} + +{{- if $message -}} +{{- printf "\nVALUES VALIDATION:\n%s" $message -}} +{{- end -}} +{{- end -}} + +{{/* +Return podAnnotations +*/}} +{{- define "apitestrig.podAnnotations" -}} +{{- if .Values.podAnnotations }} +{{ include "common.tplvalues.render" (dict "value" .Values.podAnnotations "context" $) }} +{{- end }} +{{- if and .Values.metrics.enabled .Values.metrics.podAnnotations }} +{{ include "common.tplvalues.render" (dict "value" .Values.metrics.podAnnotations "context" $) }} +{{- end }} +{{- end -}} + +{{/* Create the name for restart cronjob */}} +{{- define "apitestrig.cronjob" -}} +{{ default (printf "cronjob-%s" (include "common.names.fullname" .)) .Values.serviceAccount.name }} +{{- end -}} \ No newline at end of file diff --git a/helm/apitestrig/templates/clusterrole.yaml b/helm/apitestrig/templates/clusterrole.yaml new file mode 100644 index 0000000000..da268fdf58 --- /dev/null +++ b/helm/apitestrig/templates/clusterrole.yaml @@ -0,0 +1,10 @@ +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ template "apitestrig.serviceAccountName" . }}-{{ .Release.Namespace }} + namespace: {{ .Release.Namespace }} +rules: + - apiGroups: [""] + resources: ["pods"] + verbs: ["get","patch","list","watch"] diff --git a/helm/apitestrig/templates/clusterrolebinding.yaml b/helm/apitestrig/templates/clusterrolebinding.yaml new file mode 100644 index 0000000000..12594c8d18 --- /dev/null +++ b/helm/apitestrig/templates/clusterrolebinding.yaml @@ -0,0 +1,19 @@ +kind: ClusterRoleBinding +apiVersion: {{ include "common.capabilities.rbac.apiVersion" . }} +metadata: + labels: {{- include "common.labels.standard" . | nindent 4 }} + {{- if .Values.commonLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- end }} + name: {{ template "common.names.fullname" . }}-{{ .Release.Namespace }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ template "apitestrig.serviceAccountName" . }}-{{ .Release.Namespace }} +subjects: + - kind: ServiceAccount + name: {{ template "apitestrig.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} diff --git a/helm/apitestrig/templates/configmaps.yaml b/helm/apitestrig/templates/configmaps.yaml new file mode 100644 index 0000000000..4925083776 --- /dev/null +++ b/helm/apitestrig/templates/configmaps.yaml @@ -0,0 +1,21 @@ +{{- if .Values.apitestrig.configmaps }} +{{- range $cm_name, $cm_value := .Values.apitestrig.configmaps }} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ $cm_name }} + namespace: {{ $.Release.Namespace }} + labels: {{- include "common.labels.standard" $ | nindent 8 }} + {{- if $.Values.commonLabels }} + {{- include "common.tplvalues.render" ( dict "value" $.Values.commonLabels "context" $ ) | nindent 8 }} + {{- end }} + {{- if $.Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $.Values.commonAnnotations "context" $ ) | nindent 8 }} + {{- end }} +data: + {{- range $key, $value := $cm_value }} + {{ $key }}: {{ $value | quote }} + {{- end }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/helm/apitestrig/templates/cronjob.yaml b/helm/apitestrig/templates/cronjob.yaml new file mode 100644 index 0000000000..cb3ce9a2cc --- /dev/null +++ b/helm/apitestrig/templates/cronjob.yaml @@ -0,0 +1,108 @@ +{{- range $modulename, $module := $.Values.modules }} +{{- if $module.enabled }} +--- +apiVersion: {{ include "common.capabilities.cronjob.apiVersion" $ }} +kind: CronJob +metadata: + name: {{ template "apitestrig.cronjob" $ }}-{{ $modulename }} + namespace: {{ $.Release.Namespace }} + annotations: + {{- if $.Values.commonAnnotations }} + {{- include "common.tplvalues.render" ( dict "value" $.Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} + labels: {{- include "common.labels.standard" $ | nindent 4 }} + {{- if $.Values.commonLabels }} + {{- include "common.tplvalues.render" ( dict "value" $.Values.commonLabels "context" $ ) | nindent 4 }} + {{- end }} + +spec: + concurrencyPolicy: Forbid + successfulJobsHistoryLimit: 1 # remove jobs which are successfully executed + failedJobsHistoryLimit: 1 # except 1 recent failed job, remove jobs which are not successfully executed + #schedule: '*/3 * * * *' # cron spec of time, here, 8 o'clock + schedule: {{ $.Values.crontime }} + jobTemplate: + spec: + backoffLimit: 0 # this has very low chance of failing, as all this does + # is prompt kubernetes to schedule new replica set for + # the deployment + # activeDeadlineSeconds: 600 # timeout, makes most sense with + # "waiting for rollout" variant specified below + template: + spec: + # account configured above + restartPolicy: Never + serviceAccountName: {{ template "apitestrig.serviceAccountName" $ }} + initContainers: + {{- if $.Values.enable_insecure }} + {{- include "common.tplvalues.render" (dict "value" $.Values.initContainers "context" $) | nindent 12 }} + {{- end }} + containers: + - name: {{ template "apitestrig.serviceAccountName" $ }}-{{ $modulename }} + image: {{ $module.image.repository }}:{{ $module.image.tag }} + imagePullPolicy: {{ $module.image.pullPolicy }} + {{- if $.Values.lifecycleHooks }} + lifecycle: {{- include "common.tpvalues.render" (dict "value" $.Values.lifecycleHooks "context" $) | nindent 12 }} + {{- end }} + {{- if $.Values.containerSecurityContext.enabled }} + securityContext: {{- omit $.Values.containerSecurityContext "enabled" | toYaml | nindent 12 }} + {{- end }} + {{- if $.Values.command }} + command: {{- include "common.tplvalues.render" (dict "value" $.Values.command "context" $) | nindent 12 }} + {{- end }} + {{- if $.Values.args }} + args: {{- include "common.tplvalues.render" (dict "value" $.Values.args "context" $) | nindent 12 }} + {{- end }} + env: + - name: container_user + value: {{ $.Values.containerSecurityContext.runAsUser }} + - name: JDK_JAVA_OPTIONS + value: {{ $.Values.additionalResources.javaOpts }} + - name: MODULES + value: {{ $modulename }} + {{- if $.Values.extraEnvVars }} + {{- include "common.tpvalues.render" (dict "value" $.Values.extraEnvVars "context" $) | nindent 12 }} + {{- end }} + envFrom: + {{- if $.Values.extraEnvVarsCM }} + {{- range $.Values.extraEnvVarsCM }} + - configMapRef: + name: {{ . }} + {{- end }} + {{- end }} + {{- if $.Values.extraEnvVarsSecret }} + {{- range $.Values.extraEnvVarsSecret }} + - secretRef: + name: {{ . }} + {{- end }} + {{- end }} + ports: + - name: spring-service + containerPort: {{ $.Values.springServicePort }} + volumeMounts: + {{- if $.Values.enable_insecure }} + - mountPath: /usr/local/openjdk-11/lib/security/cacerts + name: cacerts + subPath: cacerts + {{- end }} + {{- if $.Values.apitestrig.volumes }} + {{- range $volume_name, $volume_value := $.Values.apitestrig.volumes.configmaps }} + - name: {{ $volume_name }} + mountPath: {{ $volume_value.volumeMounts.mountPath }} + {{- end }} + {{- end }} + volumes: + {{- if $.Values.enable_insecure }} + - name: cacerts + emptyDir: {} + {{- end }} + {{- if $.Values.apitestrig.volumes }} + {{- range $volume_name, $volume_value := $.Values.apitestrig.volumes.configmaps }} + - name: {{ $volume_name }} + configMap: + defaultMode: {{ $volume_value.defaultMode }} + name: {{ $volume_name }} + {{- end }} + {{- end }} +{{- end }} +{{- end }} diff --git a/helm/apitestrig/templates/extra-list.yaml b/helm/apitestrig/templates/extra-list.yaml new file mode 100644 index 0000000000..9ac65f9e16 --- /dev/null +++ b/helm/apitestrig/templates/extra-list.yaml @@ -0,0 +1,4 @@ +{{- range .Values.extraDeploy }} +--- +{{ include "common.tplvalues.render" (dict "value" . "context" $) }} +{{- end }} diff --git a/helm/apitestrig/templates/secrets.yaml b/helm/apitestrig/templates/secrets.yaml new file mode 100644 index 0000000000..1ef8dc9893 --- /dev/null +++ b/helm/apitestrig/templates/secrets.yaml @@ -0,0 +1,22 @@ +{{- if .Values.apitestrig.secrets }} +{{- range $secret_name, $secret_value := .Values.apitestrig.secrets }} +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ $secret_name }} + namespace: {{ $.Release.Namespace }} + labels: {{- include "common.labels.standard" $ | nindent 8 }} + {{- if $.Values.commonLabels }} + {{- include "common.tplvalues.render" ( dict "value" $.Values.commonLabels "context" $ ) | nindent 8 }} + {{- end }} + {{- if $.Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $.Values.commonAnnotations "context" $ ) | nindent 8 }} + {{- end }} +type: Opaque +data: + {{- range $key, $value := $secret_value }} + {{ $key }}: {{ $value | b64enc | quote }} + {{- end }} +{{- end }} +{{- end }} diff --git a/helm/apitestrig/templates/service-account.yaml b/helm/apitestrig/templates/service-account.yaml new file mode 100644 index 0000000000..466590df49 --- /dev/null +++ b/helm/apitestrig/templates/service-account.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: {{- include "common.labels.standard" . | nindent 4 }} + {{- if .Values.commonLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- end }} + name: {{ template "apitestrig.serviceAccountName" . }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} + namespace: {{ .Release.Namespace }} diff --git a/helm/apitestrig/values.yaml b/helm/apitestrig/values.yaml new file mode 100644 index 0000000000..8b5beb6f8f --- /dev/null +++ b/helm/apitestrig/values.yaml @@ -0,0 +1,545 @@ +## Global Docker image parameters +## Please, note that this will override the image parameters, including dependencies, configured to use the global value +## Current available global Docker image parameters: imageRegistry and imagePullSecrets +## +# global: +# imageRegistry: myRegistryName +# imagePullSecrets: +# - myRegistryKeySecretName +# storageClass: myStorageClass + +## Add labels to all the deployed resources +## +commonLabels: + app.kubernetes.io/component: mosip + +## Add annotations to all the deployed resources +## +commonAnnotations: {} + +## Kubernetes Cluster Domain +## +clusterDomain: cluster.local + +## Extra objects to deploy (value evaluated as a template) +## +extraDeploy: [] + +## Number of nodes +## +replicaCount: 1 + +service: + type: ClusterIP + port: 80 + ## loadBalancerIP for the SuiteCRM Service (optional, cloud specific) + ## ref: http://kubernetes.io/docs/user-guide/services/#type-loadbalancer + ## + ## loadBalancerIP: + ## + ## nodePorts: + ## http: + ## https: + ## + nodePorts: + http: "" + https: "" + ## Enable client source IP preservation + ## ref http://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip + ## + externalTrafficPolicy: Cluster + +## Port on which this particular spring service module is running. +springServicePort: 8083 + +## Configure extra options for liveness and readiness probes +## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes +## + +## +# existingConfigmap: + +## Command and args for running the container (set to default if not set). Use array form +## +command: ['/bin/bash'] +args: ['-c', "/home/${container_user}/scripts/fetch_docker_image_hash_ids.sh"] + +## Deployment pod host aliases +## https://kubernetes.io/docs/concepts/services-networking/add-entries-to-pod-etc-hosts-with-host-aliases/ +## +hostAliases: [] + +## ref: http://kubernetes.io/docs/user-guide/compute-resources/ +## +resources: + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + limits: + cpu: 1500m + memory: 3500Mi + requests: + cpu: 1000m + memory: 3500Mi + +additionalResources: + ## Specify any JAVA_OPTS string here. These typically will be specified in conjunction with above resources + ## Example: java_opts: "-Xms500M -Xmx500M" + javaOpts: "-Xms2600M -Xmx2600M" + +## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container +## Clamav container already runs as 'mosip' user, so we may not need to enable this +containerSecurityContext: + enabled: false + runAsUser: mosip + runAsNonRoot: true + +## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod +## +podSecurityContext: + enabled: false + fsGroup: 1001 + +## Pod affinity preset +## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity +## Allowed values: soft, hard +## +podAffinityPreset: "" + +## Pod anti-affinity preset +## Ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity +## Allowed values: soft, hard +## +podAntiAffinityPreset: soft + +## Node affinity preset +## Ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity +## Allowed values: soft, hard +## +nodeAffinityPreset: + ## Node affinity type + ## Allowed values: soft, hard + ## + type: "" + ## Node label key to match + ## E.g. + ## key: "kubernetes.io/e2e-az-name" + ## + key: "" + ## Node label values to match + ## E.g. + ## values: + ## - e2e-az1 + ## - e2e-az2 + ## + values: [] + +## Affinity for pod assignment. Evaluated as a template. +## Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity +## +affinity: {} + +## Node labels for pod assignment. Evaluated as a template. +## ref: https://kubernetes.io/docs/user-guide/node-selection/ +## +nodeSelector: {} + +## Tolerations for pod assignment. Evaluated as a template. +## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ +## +tolerations: [] + +## Pod extra labels +## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ +## +podLabels: {} + +## Annotations for server pods. +## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ +## +podAnnotations: {} + +## pods' priority. +## ref: https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/ +## +# priorityClassName: "" + +## lifecycleHooks for the container to automate configuration before or after startup. +## +lifecycleHooks: {} + +## Custom Liveness probes for +## +customLivenessProbe: {} + +## Custom Rediness probes +## +customReadinessProbe: {} + +## Update strategy - only really applicable for deployments with RWO PVs attached +## If replicas = 1, an update can get "stuck", as the previous pod remains attached to the +## PV, and the "incoming" pod can never start. Changing the strategy to "Recreate" will +## terminate the single previous pod, so that the new, incoming pod can attach to the PV +## +updateStrategy: + type: RollingUpdate + +## Additional environment variables to set +## Example: +## extraEnvVars: +## - name: FOO +## value: "bar" +## +extraEnvVars: [] + +## ConfigMap with extra environment variables +## +extraEnvVarsCM: + - global + - s3 + - keycloak-host + - db + - apitestrig + - config-server-share + - artifactory-share +## Secret with extra environment variables +## +extraEnvVarsSecret: + - apitestrig + - s3 + - keycloak-client-secrets + - postgres-postgresql + +## Extra volumes to add to the deployment +## +extraVolumes: [] + +## Extra volume mounts to add to the container +## +extraVolumeMounts: [] + +## Add init containers to the pods. +## Example: +## initContainers: +## - name: your-image-name +## image: your-image +## imagePullPolicy: Always +## ports: +## - name: portname +## containerPort: 1234 +## +initContainers: + - command: + - /bin/bash + - -c + - if [ "$ENABLE_INSECURE" = "true" ]; then HOST=$( env | grep "mosip-api-internal-host" + |sed "s/mosip-api-internal-host=//g"); if [ -z "$HOST" ]; then echo "HOST + $HOST is empty; EXITING"; exit 1; fi; openssl s_client -servername "$HOST" + -connect "$HOST":443 > "$HOST.cer" 2>/dev/null & sleep 2 ; sed -i -ne '/-BEGIN + CERTIFICATE-/,/-END CERTIFICATE-/p' "$HOST.cer"; cat "$HOST.cer"; /usr/local/openjdk-11/bin/keytool + -delete -alias "$HOST" -keystore $JAVA_HOME/lib/security/cacerts -storepass + changeit; /usr/local/openjdk-11/bin/keytool -trustcacerts -keystore "$JAVA_HOME/lib/security/cacerts" + -storepass changeit -noprompt -importcert -alias "$HOST" -file "$HOST.cer" + ; if [ $? -gt 0 ]; then echo "Failed to add SSL certificate for host $host; + EXITING"; exit 1; fi; cp /usr/local/openjdk-11/lib/security/cacerts /cacerts; + fi + env: + - name: ENABLE_INSECURE + value: "true" + envFrom: + - configMapRef: + name: global + image: docker.io/openjdk:11-jre + imagePullPolicy: Always + name: cacerts + resources: {} + securityContext: + runAsUser: 0 + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File + volumeMounts: + - mountPath: /cacerts + name: cacerts + +## Add sidecars to the pods. +## Example: +## sidecars: +## - name: your-image-name +## image: your-image +## imagePullPolicy: Always +## ports: +## - name: portname +## containerPort: 1234 +## +sidecars: {} + +persistence: + enabled: false + ## If defined, storageClassName: + ## If set to "-", storageClassName: "", which disables dynamic provisioning + ## If undefined (the default) or set to null, no storageClassName spec is + ## set, choosing the default provisioner. (gp2 on AWS, standard on + ## GKE, AWS & OpenStack). + ## + # storageClass: "-" + ## + ## If you want to reuse an existing claim, you can pass the name of the PVC using + ## the existingClaim variable + # existingClaim: your-claim + ## ReadWriteMany not supported by AWS gp2 + storageClass: + accessModes: + - ReadWriteOnce + size: 10M + existingClaim: + # Dir where config and keys are written inside container + mountDir: + +## Init containers parameters: +## volumePermissions: Change the owner and group of the persistent volume mountpoint to runAsUser:fsGroup values from the securityContext section. +## +volumePermissions: + enabled: false + image: + registry: docker.io + repository: bitnami/bitnami-shell + tag: "10" + pullPolicy: Always + ## Optionally specify an array of imagePullSecrets. + ## Secrets must be manually created in the namespace. + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ + ## + pullSecrets: [] + ## - myRegistryKeySecretName + ## Init containers' resource requests and limits + ## ref: http://kubernetes.io/docs/user-guide/compute-resources/ + ## + resources: + ## We usually recommend not to specify default resources and to leave this as a conscious + ## choice for the user. This also increases chances charts run on environments with little + ## resources, such as Minikube. If you do want to specify resources, uncomment the following + ## lines, adjust them as necessary, and remove the curly braces after 'resources:'. + ## + limits: {} + ## cpu: 100m + ## memory: 128Mi + ## + requests: {} + ## cpu: 100m + ## memory: 128Mi + ## + +## Specifies whether RBAC resources should be created +## +rbac: + create: true + +## Specifies whether a ServiceAccount should be created +## +serviceAccount: + create: true + ## The name of the ServiceAccount to use. + ## If not set and create is true, a name is generated using the fullname template + ## + name: + +## Prometheus Metrics +## +metrics: + enabled: false + ## Prometheus pod annotations + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ + ## + podAnnotations: + prometheus.io/scrape: "true" + + endpointPath: + + ## Prometheus Service Monitor + ## ref: https://github.com/coreos/prometheus-operator + ## + serviceMonitor: + ## If the operator is installed in your cluster, set to true to create a Service Monitor Entry + ## + enabled: true + ## Specify the namespace in which the serviceMonitor resource will be created + ## + # namespace: "" + ## Specify the interval at which metrics should be scraped + ## + interval: 10s + ## Specify the timeout after which the scrape is ended + ## + # scrapeTimeout: 30s + ## Specify Metric Relabellings to add to the scrape endpoint + ## + # relabellings: + ## Specify honorLabels parameter to add the scrape endpoint + ## + honorLabels: false + ## Used to pass Labels that are used by the Prometheus installed in your cluster to select Service Monitors to work with + ## ref: https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#prometheusspec + ## + additionalLabels: {} + + ## Custom PrometheusRule to be defined + ## The value is evaluated as a template, so, for example, the value can depend on .Release or .Chart + ## ref: https://github.com/coreos/prometheus-operator#customresourcedefinitions + ## + prometheusRule: + enabled: false + additionalLabels: {} + namespace: '' + ## List of rules, used as template by Helm. + ## These are just examples rules inspired from https://awesome-prometheus-alerts.grep.to/rules.html + # rules: + # - alert: RabbitmqDown + # expr: rabbitmq_up{service="{{ template "rabbitmq.fullname" . }}"} == 0 + # for: 5m + # labels: + # severity: error + rules: [] + +## Admin swagger should have only internal access. Hence linked to internal gateway +istio: + enabled: false + gateways: + - istio-system/internal + prefix: + corsPolicy: + allowOrigins: + - prefix: https://api-internal.sandbox.xyz.net + allowCredentials: true + allowHeaders: + - Accept + - Accept-Encoding + - Accept-Language + - Connection + - Content-Type + - Cookie + - Host + - Referer + - Sec-Fetch-Dest + - Sec-Fetch-Mode + - Sec-Fetch-Site + - Sec-Fetch-User + - Origin + - Upgrade-Insecure-Requests + - User-Agent + - sec-ch-ua + - sec-ch-ua-mobile + - sec-ch-ua-platform + - x-xsrf-token + - xsrf-token + allowMethods: + - GET + - POST + - PATCH + - PUT + - DELETE + +modules: + prereg: + enabled: true + image: + repository: mosipqa/apitest-prereg + tag: develop + pullPolicy: Always + masterdata: + enabled: true + image: + repository: mosipqa/apitest-masterdata + tag: develop + pullPolicy: Always + idrepo: + enabled: true + image: + repository: mosipqa/apitest-idrepo + tag: develop + pullPolicy: Always + partner: + enabled: true + image: + repository: mosipqa/apitest-pms + tag: develop + pullPolicy: Always + pms: + enabled: true + image: + repository: mosipdev/apitest-pms + tag: develop + pullPolicy: Always + resident: + enabled: true + image: + repository: mosipqa/apitest-resident + tag: develop + pullPolicy: Always + auth: + enabled: true + image: + repository: mosipqa/apitest-auth + tag: develop + pullPolicy: Always + esignet: + enabled: true + image: + repository: mosipqa/apitest-esignet + tag: develop + pullPolicy: Always + mimoto: + enabled: true + image: + repository: mosipqa/apitest-mimoto + tag: develop + pullPolicy: Always + +crontime: "0 3 * * *" ## run cronjob every day at 3 AM (time hr: 0-23 ) + +apitestrig: + configmaps: + s3: + s3-host: 'http://minio.minio:9000' + s3-user-key: 'admin' + s3-region: '' + db: + db-port: '5432' + db-su-user: 'postgres' + db-server: 'api-internal.sandbox.xyz.net' + apitestrig: + ENV_USER: 'api-internal.sandbox' + ENV_ENDPOINT: 'https://api-internal.sandbox.xyz.net' + ENV_TESTLEVEL: 'smokeAndRegression' + authDemoServiceBaseURL: http://authdemo.authdemo + authDemoServicePort: 80 + eSignetDeployed: yes or no + push-reports-to-s3: 'yes' + authCertsPath: '/home/mosip/authcerts' + scripts: + fetch_docker_image_hash_ids.sh: | + #!/bin/bash + sleep 5 + export DOCKER_HASH_ID=$( kubectl get pod "$HOSTNAME" -n "$NS" -o jsonpath='{.status.containerStatuses[*].imageID}' | sed 's/ /\n/g' | grep -v 'istio' | sed 's/docker\-pullable\:\/\///g' ) + export DOCKER_IMAGE=$( kubectl get pod "$HOSTNAME" -n "$NS" -o jsonpath='{.status.containerStatuses[*].image}' | sed 's/ /\n/g' | grep -v 'istio' | sed 's/docker\-pullable\:\/\///g' ) + if [[ -z $DOCKER_HASH_ID ]]; then + echo "DOCKER_HASH_ID IS EMPTY;EXITING"; + exit 1; + fi + echo "DOCKER_HASH_ID ; $DOCKER_HASH_ID" + echo "DOCKER_IMAGE : $DOCKER_IMAGE" + kubectl get pods -A -o=jsonpath='{range .items[*]}{.metadata.namespace}{","}{.metadata.labels.app\.kubernetes\.io\/name}{","}{.status.containerStatuses[?(@.name!="istio-proxy")].image}{","}{.status.containerStatuses[?(@.name!="istio-proxy")].imageID}{","}{.metadata.creationTimestamp}{"\n"}' | sed 's/ /\n/g' | grep -vE 'istio*|longhorn*|cattle*|rancher|kube' | sed 's/docker\-pullable\:\/\///g' | sort -u | sed '/,,,/d' | awk -F ',' 'BEGIN {print "{ \"POD_NAME\": \"'$(echo $HOSTNAME)'\", \"DOCKER_IMAGE\": \"'$(echo $DOCKER_IMAGE)'\", \"DOCKER_HASH_ID\": \"'$(echo $DOCKER_HASH_ID)'\", \"k8s-cluster-image-list\": ["} {print "{"} {print "\"namespace\": \"" $1 "\","} {print "\"app_name\": \"" $2 "\","} {print "\"docker_image_name\": \"" $3 "\","} {print "\"docker_image_id\": \"" $4 "\","} {print "\"creation_timestamp\": \"" $5 "\"" } {print "},"} END {print "]}"}' | sed -z 's/},\n]/}\n]/g' | jq -r . | tee -a images-list.json + ## run entrypoint script + sleep 5 + cd /home/${container_user}/ + bash ./entrypoint.sh + secrets: + apitestrig: + volumes: + configmaps: + scripts: + defaultMode: 0777 + volumeMounts: + mountPath: '/home/mosip/scripts/' + +enable_insecure: false diff --git a/helm/uitestrig/.helmignore b/helm/uitestrig/.helmignore new file mode 100644 index 0000000000..f0c1319444 --- /dev/null +++ b/helm/uitestrig/.helmignore @@ -0,0 +1,21 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*~ +# Various IDEs +.project +.idea/ +*.tmproj diff --git a/helm/uitestrig/Chart.yaml b/helm/uitestrig/Chart.yaml new file mode 100644 index 0000000000..8763cc302a --- /dev/null +++ b/helm/uitestrig/Chart.yaml @@ -0,0 +1,20 @@ +apiVersion: v2 +name: uitestrig +description: A Helm chart to deploy uitestrig to test working of MOSIP modules +type: application +version: 0.0.1-develop +appVersion: "" +dependencies: + - name: common + repository: https://charts.bitnami.com/bitnami + tags: + - bitnami-common + version: 1.x.x +home: https://mosip.io +keywords: + - mosip + - uitestrig + - testrig +maintainers: + - email: info@mosip.io + name: MOSIP diff --git a/helm/uitestrig/README.md b/helm/uitestrig/README.md new file mode 100644 index 0000000000..c313265108 --- /dev/null +++ b/helm/uitestrig/README.md @@ -0,0 +1,10 @@ +# UITESTRIG + +Helm chart to deploy UITESTRIG for `MOSIP` modules + +## TL;DR + +```console +$ helm repo add mosip https://mosip.github.io +$ helm install my-release mosip/uitestrig +``` diff --git a/helm/uitestrig/templates/NOTES.txt b/helm/uitestrig/templates/NOTES.txt new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/helm/uitestrig/templates/NOTES.txt @@ -0,0 +1 @@ + diff --git a/helm/uitestrig/templates/_helpers.tpl b/helm/uitestrig/templates/_helpers.tpl new file mode 100644 index 0000000000..4a344cd5ff --- /dev/null +++ b/helm/uitestrig/templates/_helpers.tpl @@ -0,0 +1,63 @@ +{{/* +Return the proper image name +*/}} +{{- define "uitestrig.image" -}} +{{ include "common.images.image" (dict "imageRoot" .Values.image "global" .Values.global) }} +{{- end -}} + +{{/* +Return the proper image name (for the init container volume-permissions image) +*/}} +{{- define "uitestrig.volumePermissions.image" -}} +{{- include "common.images.image" ( dict "imageRoot" .Values.volumePermissions.image "global" .Values.global ) -}} +{{- end -}} + +{{/* +Return the proper Docker Image Registry Secret Names +*/}} +{{- define "uitestrig.imagePullSecrets" -}} +{{- include "common.images.pullSecrets" (dict "images" (list .Values.image .Values.volumePermissions.image) "global" .Values.global) -}} +{{- end -}} + +{{/* +Create the name of the service account to use +*/}} +{{- define "uitestrig.serviceAccountName" -}} +{{- if .Values.serviceAccount.create -}} + {{ default (printf "%s" (include "common.names.fullname" .)) .Values.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.serviceAccount.name }} +{{- end -}} +{{- end -}} + +{{/* +Compile all warnings into a single message. +*/}} +{{- define "uitestrig.validateValues" -}} +{{- $messages := list -}} +{{- $messages := append $messages (include "uitestrig.validateValues.foo" .) -}} +{{- $messages := append $messages (include "uitestrig.validateValues.bar" .) -}} +{{- $messages := without $messages "" -}} +{{- $message := join "\n" $messages -}} + +{{- if $message -}} +{{- printf "\nVALUES VALIDATION:\n%s" $message -}} +{{- end -}} +{{- end -}} + +{{/* +Return podAnnotations +*/}} +{{- define "uitestrig.podAnnotations" -}} +{{- if .Values.podAnnotations }} +{{ include "common.tplvalues.render" (dict "value" .Values.podAnnotations "context" $) }} +{{- end }} +{{- if and .Values.metrics.enabled .Values.metrics.podAnnotations }} +{{ include "common.tplvalues.render" (dict "value" .Values.metrics.podAnnotations "context" $) }} +{{- end }} +{{- end -}} + +{{/* Create the name for restart cronjob */}} +{{- define "uitestrig.cronjob" -}} +{{ default (printf "cronjob-%s" (include "common.names.fullname" .)) .Values.serviceAccount.name }} +{{- end -}} diff --git a/helm/uitestrig/templates/clusterrole.yaml b/helm/uitestrig/templates/clusterrole.yaml new file mode 100644 index 0000000000..9ba5e13433 --- /dev/null +++ b/helm/uitestrig/templates/clusterrole.yaml @@ -0,0 +1,10 @@ +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ template "uitestrig.serviceAccountName" . }}-{{ .Release.Namespace }} + namespace: {{ .Release.Namespace }} +rules: + - apiGroups: [""] + resources: ["pods"] + verbs: ["get","patch","list","watch"] diff --git a/helm/uitestrig/templates/clusterrolebinding.yaml b/helm/uitestrig/templates/clusterrolebinding.yaml new file mode 100644 index 0000000000..13f43a28ab --- /dev/null +++ b/helm/uitestrig/templates/clusterrolebinding.yaml @@ -0,0 +1,19 @@ +kind: ClusterRoleBinding +apiVersion: {{ include "common.capabilities.rbac.apiVersion" . }} +metadata: + labels: {{- include "common.labels.standard" . | nindent 4 }} + {{- if .Values.commonLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- end }} + name: {{ template "common.names.fullname" . }}-{{ .Release.Namespace }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ template "uitestrig.serviceAccountName" . }}-{{ .Release.Namespace }} +subjects: + - kind: ServiceAccount + name: {{ template "uitestrig.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} diff --git a/helm/uitestrig/templates/configmaps.yaml b/helm/uitestrig/templates/configmaps.yaml new file mode 100644 index 0000000000..30d26167fe --- /dev/null +++ b/helm/uitestrig/templates/configmaps.yaml @@ -0,0 +1,21 @@ +{{- if .Values.uitestrig.configmaps }} +{{- range $cm_name, $cm_value := .Values.uitestrig.configmaps }} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ $cm_name }} + namespace: {{ $.Release.Namespace }} + labels: {{- include "common.labels.standard" $ | nindent 8 }} + {{- if $.Values.commonLabels }} + {{- include "common.tplvalues.render" ( dict "value" $.Values.commonLabels "context" $ ) | nindent 8 }} + {{- end }} + {{- if $.Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $.Values.commonAnnotations "context" $ ) | nindent 8 }} + {{- end }} +data: + {{- range $key, $value := $cm_value }} + {{ $key }}: {{ $value | quote }} + {{- end }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/helm/uitestrig/templates/cronjob.yaml b/helm/uitestrig/templates/cronjob.yaml new file mode 100644 index 0000000000..02bdf3a7e0 --- /dev/null +++ b/helm/uitestrig/templates/cronjob.yaml @@ -0,0 +1,106 @@ +{{- range $module := $.Values.modules }} +{{- if $module.enabled }} +--- +apiVersion: {{ include "common.capabilities.cronjob.apiVersion" $ }} +kind: CronJob +metadata: + name: {{ template "uitestrig.cronjob" $ }}-{{ $module.name }} + namespace: {{ $.Release.Namespace }} + annotations: + {{- if $.Values.commonAnnotations }} + {{- include "common.tplvalues.render" ( dict "value" $.Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} + labels: {{- include "common.labels.standard" $ | nindent 4 }} + {{- if $.Values.commonLabels }} + {{- include "common.tplvalues.render" ( dict "value" $.Values.commonLabels "context" $ ) | nindent 4 }} + {{- end }} +spec: + concurrencyPolicy: Forbid + successfulJobsHistoryLimit: 1 # remove jobs which are successfully executed + failedJobsHistoryLimit: 1 # except 1 recent failed job, remove jobs which are not successfully executed + #schedule: '*/3 * * * *' # cron spec of time + schedule: {{ $.Values.crontime }} + jobTemplate: + spec: + backoffLimit: 0 # this has very low chance of failing, as all this does + # is prompt kubernetes to schedule new replica set for + # the deployment + # activeDeadlineSeconds: 600 # timeout, makes most sense with + # "waiting for rollout" variant specified below + template: + spec: + # account configured above + serviceAccountName: {{ template "uitestrig.serviceAccountName" $ }} + restartPolicy: Never + containers: + - name: {{ $module.name }} + image: {{ $module.image.registry }}/{{ $module.image.repository }}:{{ $module.image.tag }} + imagePullPolicy: {{ $module.image.pullPolicy }} + {{- if $.Values.lifecycleHooks }} + lifecycle: {{- include "common.tpvalues.render" (dict "value" $.Values.lifecycleHooks "context" $) | nindent 12 }} + {{- end }} + {{- if $.Values.containerSecurityContext.enabled }} + securityContext: {{- omit $.Values.containerSecurityContext "enabled" | toYaml | nindent 12 }} + {{- end }} + {{- if $.Values.command }} + command: {{- include "common.tplvalues.render" (dict "value" $.Values.command "context" $) | nindent 12 }} + {{- end }} + {{- if $.Values.args }} + args: {{- include "common.tplvalues.render" (dict "value" $.Values.args "context" $) | nindent 12 }} + {{- end }} + env: + - name: container_user + value: "{{ $.Values.containerSecurityContext.runAsUser }}" + - name: JDK_JAVA_OPTIONS + value: "{{ $.Values.additionalResources.javaOpts }}" + - name: modules + value: "{{ $module.name }}" + {{- if $.Values.extraEnvVars }} + {{- include "common.tpvalues.render" (dict "value" $.Values.extraEnvVars "context" $) | nindent 12 }} + {{- end }} + + envFrom: + {{- if $.Values.extraEnvVarsCM }} + {{- range $.Values.extraEnvVarsCM }} + - configMapRef: + name: {{ . }} + {{- end }} + {{- end }} + {{- if $.Values.extraEnvVarsSecret }} + {{- range $.Values.extraEnvVarsSecret }} + - secretRef: + name: {{ . }} + {{- end }} + {{- end }} + ports: + - name: spring-service + containerPort: {{ $.Values.springServicePort }} + volumeMounts: + {{- if $.Values.enable_insecure }} + - mountPath: /usr/local/openjdk-11/lib/security/cacerts + name: cacerts + subPath: cacerts + {{- end }} + {{- if $.Values.uitestrig.volumes }} + {{- range $volume_name, $volume_value := $.Values.uitestrig.volumes.configmaps }} + - name: {{ $volume_name }} + mountPath: {{ $volume_value.volumeMounts.mountPath }} + {{- end }} + {{- end }} + volumes: + {{- if $.Values.enable_insecure }} + - name: cacerts + emptyDir: {} + {{- end }} + {{- if $.Values.uitestrig.volumes }} + {{- range $volume_name, $volume_value := $.Values.uitestrig.volumes.configmaps }} + - name: {{ $volume_name }} + configMap: + defaultMode: {{ $volume_value.defaultMode }} + name: {{ $volume_name }} + {{- end }} + {{- end }} +{{- end }} +{{- end }} + + diff --git a/helm/uitestrig/templates/extra-list.yaml b/helm/uitestrig/templates/extra-list.yaml new file mode 100644 index 0000000000..9ac65f9e16 --- /dev/null +++ b/helm/uitestrig/templates/extra-list.yaml @@ -0,0 +1,4 @@ +{{- range .Values.extraDeploy }} +--- +{{ include "common.tplvalues.render" (dict "value" . "context" $) }} +{{- end }} diff --git a/helm/uitestrig/templates/secrets.yaml b/helm/uitestrig/templates/secrets.yaml new file mode 100644 index 0000000000..8200c6701d --- /dev/null +++ b/helm/uitestrig/templates/secrets.yaml @@ -0,0 +1,21 @@ +{{- if .Values.uitestrig.secrets }} +{{- range $secret_name, $secret_value := .Values.uitestrig.secrets }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ $secret_name }} + namespace: {{ $.Release.Namespace }} + labels: {{- include "common.labels.standard" $ | nindent 8 }} + {{- if $.Values.commonLabels }} + {{- include "common.tplvalues.render" ( dict "value" $.Values.commonLabels "context" $ ) | nindent 8 }} + {{- end }} + {{- if $.Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $.Values.commonAnnotations "context" $ ) | nindent 8 }} + {{- end }} +type: Opaque +data: + {{- range $key, $value := $secret_value }} + {{ $key }}: {{ $value | b64enc | quote }} + {{- end }} +{{- end }} +{{- end }} diff --git a/helm/uitestrig/templates/service-account.yaml b/helm/uitestrig/templates/service-account.yaml new file mode 100644 index 0000000000..28bff8af43 --- /dev/null +++ b/helm/uitestrig/templates/service-account.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: {{- include "common.labels.standard" . | nindent 4 }} + {{- if .Values.commonLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- end }} + name: {{ template "uitestrig.serviceAccountName" . }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} + namespace: {{ .Release.Namespace }} diff --git a/helm/uitestrig/values.yaml b/helm/uitestrig/values.yaml new file mode 100644 index 0000000000..75e39c80a1 --- /dev/null +++ b/helm/uitestrig/values.yaml @@ -0,0 +1,511 @@ +## Global Docker image parameters +## Please, note that this will override the image parameters, including dependencies, configured to use the global value +## Current available global Docker image parameters: imageRegistry and imagePullSecrets +## +# global: +# imageRegistry: myRegistryName +# imagePullSecrets: +# - myRegistryKeySecretName +# storageClass: myStorageClass + +## Add labels to all the deployed resources +## +commonLabels: + app.kubernetes.io/component: mosip + +## Add annotations to all the deployed resources +## +commonAnnotations: {} + +## Kubernetes Cluster Domain +## +clusterDomain: cluster.local + +## Extra objects to deploy (value evaluated as a template) +## +extraDeploy: [] + +## Number of nodes +## +replicaCount: 1 + +service: + type: ClusterIP + port: 80 + ## loadBalancerIP for the SuiteCRM Service (optional, cloud specific) + ## ref: http://kubernetes.io/docs/user-guide/services/#type-loadbalancer + ## + ## loadBalancerIP: + ## + ## nodePorts: + ## http: + ## https: + ## + nodePorts: + http: "" + https: "" + ## Enable client source IP preservation + ## ref http://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip + ## + externalTrafficPolicy: Cluster + +## Port on which this particular spring service module is running. +springServicePort: 8083 + +## Configure extra options for liveness and readiness probes +## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes +## + +## +# existingConfigmap: + +## Command and args for running the container (set to default if not set). Use array form +## +command: ['/bin/bash'] +args: ['-c', "/home/${container_user}/scripts/fetch_docker_image_hash_ids.sh"] + +## Deployment pod host aliases +## https://kubernetes.io/docs/concepts/services-networking/add-entries-to-pod-etc-hosts-with-host-aliases/ +## +hostAliases: [] + +## ref: http://kubernetes.io/docs/user-guide/compute-resources/ +## +resources: + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + limits: + cpu: 1000m + memory: 3500Mi + requests: + cpu: 1000m + memory: 3500Mi + +additionalResources: + ## Specify any JAVA_OPTS string here. These typically will be specified in conjunction with above resources + ## Example: java_opts: "-Xms500M -Xmx500M" + javaOpts: "-Xms3500M -Xmx3500M" + +## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container +## Clamav container already runs as 'mosip' user, so we may not need to enable this +containerSecurityContext: + enabled: false + runAsUser: mosip + runAsNonRoot: true + +## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod +## +podSecurityContext: + enabled: false + fsGroup: 1001 + +## Pod affinity preset +## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity +## Allowed values: soft, hard +## +podAffinityPreset: "" + +## Pod anti-affinity preset +## Ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity +## Allowed values: soft, hard +## +podAntiAffinityPreset: soft + +## Node affinity preset +## Ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity +## Allowed values: soft, hard +## +nodeAffinityPreset: + ## Node affinity type + ## Allowed values: soft, hard + ## + type: "" + ## Node label key to match + ## E.g. + ## key: "kubernetes.io/e2e-az-name" + ## + key: "" + ## Node label values to match + ## E.g. + ## values: + ## - e2e-az1 + ## - e2e-az2 + ## + values: [] + +## Affinity for pod assignment. Evaluated as a template. +## Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity +## +affinity: {} + +## Node labels for pod assignment. Evaluated as a template. +## ref: https://kubernetes.io/docs/user-guide/node-selection/ +## +nodeSelector: {} + +## Tolerations for pod assignment. Evaluated as a template. +## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ +## +tolerations: [] + +## Pod extra labels +## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ +## +podLabels: {} + +## Annotations for server pods. +## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ +## +podAnnotations: {} + +## pods' priority. +## ref: https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/ +## +# priorityClassName: "" + +## lifecycleHooks for the container to automate configuration before or after startup. +## +lifecycleHooks: {} + +## Custom Liveness probes for +## +customLivenessProbe: {} + +## Custom Rediness probes +## +customReadinessProbe: {} + +## Update strategy - only really applicable for deployments with RWO PVs attached +## If replicas = 1, an update can get "stuck", as the previous pod remains attached to the +## PV, and the "incoming" pod can never start. Changing the strategy to "Recreate" will +## terminate the single previous pod, so that the new, incoming pod can attach to the PV +## +updateStrategy: + type: RollingUpdate + +## Additional environment variables to set +## Example: +## extraEnvVars: +## - name: FOO +## value: "bar" +## +extraEnvVars: [] + +## ConfigMap with extra environment variables +## +extraEnvVarsCM: + - global + - s3 + - keycloak-host + - db + - uitestrig + - config-server-share + - artifactory-share +## Secret with extra environment variables +## +extraEnvVarsSecret: + - s3 + - keycloak-client-secrets + - postgres-postgresql + +## Extra volumes to add to the deployment +## +extraVolumes: [] + +## Extra volume mounts to add to the container +## +extraVolumeMounts: [] + +## Add init containers to the pods. +## Example: +## initContainers: +## - name: your-image-name +## image: your-image +## imagePullPolicy: Always +## ports: +## - name: portname +## containerPort: 1234 +## +initContainers: + - command: + - /bin/bash + - -c + - if [ "$ENABLE_INSECURE" = "true" ]; then HOST=$( env | grep "mosip-api-internal-host" + |sed "s/mosip-api-internal-host=//g"); if [ -z "$HOST" ]; then echo "HOST + $HOST is empty; EXITING"; exit 1; fi; openssl s_client -servername "$HOST" + -connect "$HOST":443 > "$HOST.cer" 2>/dev/null & sleep 2 ; sed -i -ne '/-BEGIN + CERTIFICATE-/,/-END CERTIFICATE-/p' "$HOST.cer"; cat "$HOST.cer"; /usr/local/openjdk-11/bin/keytool + -delete -alias "$HOST" -keystore $JAVA_HOME/lib/security/cacerts -storepass + changeit; /usr/local/openjdk-11/bin/keytool -trustcacerts -keystore "$JAVA_HOME/lib/security/cacerts" + -storepass changeit -noprompt -importcert -alias "$HOST" -file "$HOST.cer" + ; if [ $? -gt 0 ]; then echo "Failed to add SSL certificate for host $host; + EXITING"; exit 1; fi; cp /usr/local/openjdk-11/lib/security/cacerts /cacerts; + fi + env: + - name: ENABLE_INSECURE + value: "true" + envFrom: + - configMapRef: + name: global + - configMapRef: + name: uitestrig + image: docker.io/openjdk:11-jre + imagePullPolicy: Always + name: cacerts + resources: {} + securityContext: + runAsUser: 0 + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File + volumeMounts: + - mountPath: /cacerts + name: cacerts + +## Add sidecars to the pods. +## Example: +## sidecars: +## - name: your-image-name +## image: your-image +## imagePullPolicy: Always +## ports: +## - name: portname +## containerPort: 1234 +## +sidecars: {} + +persistence: + enabled: true + ## If defined, storageClassName: + ## If set to "-", storageClassName: "", which disables dynamic provisioning + ## If undefined (the default) or set to null, no storageClassName spec is + ## set, choosing the default provisioner. (gp2 on AWS, standard on + ## GKE, AWS & OpenStack). + ## + # storageClass: "-" + ## + ## If you want to reuse an existing claim, you can pass the name of the PVC using + ## the existingClaim variable + # existingClaim: your-claim + ## ReadWriteMany not supported by AWS gp2 + storageClass: + accessModes: + - ReadWriteOnce + size: 100m + +## Init containers parameters: +## volumePermissions: Change the owner and group of the persistent volume mountpoint to runAsUser:fsGroup values from the securityContext section. +## +volumePermissions: + enabled: false + image: + registry: docker.io + repository: bitnami/bitnami-shell + tag: "10" + pullPolicy: Always + ## Optionally specify an array of imagePullSecrets. + ## Secrets must be manually created in the namespace. + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ + ## + pullSecrets: [] + ## - myRegistryKeySecretName + ## Init containers' resource requests and limits + ## ref: http://kubernetes.io/docs/user-guide/compute-resources/ + ## + resources: + ## We usually recommend not to specify default resources and to leave this as a conscious + ## choice for the user. This also increases chances charts run on environments with little + ## resources, such as Minikube. If you do want to specify resources, uncomment the following + ## lines, adjust them as necessary, and remove the curly braces after 'resources:'. + ## + limits: {} + ## cpu: 100m + ## memory: 128Mi + ## + requests: {} + ## cpu: 100m + ## memory: 128Mi + ## + +## Specifies whether RBAC resources should be created +## +rbac: + create: true + +## Specifies whether a ServiceAccount should be created +## +serviceAccount: + create: true + ## The name of the ServiceAccount to use. + ## If not set and create is true, a name is generated using the fullname template + ## + name: + +## Prometheus Metrics +## +metrics: + enabled: false + ## Prometheus pod annotations + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ + ## + podAnnotations: + prometheus.io/scrape: "true" + + endpointPath: + + ## Prometheus Service Monitor + ## ref: https://github.com/coreos/prometheus-operator + ## + serviceMonitor: + ## If the operator is installed in your cluster, set to true to create a Service Monitor Entry + ## + enabled: true + ## Specify the namespace in which the serviceMonitor resource will be created + ## + # namespace: "" + ## Specify the interval at which metrics should be scraped + ## + interval: 10s + ## Specify the timeout after which the scrape is ended + ## + # scrapeTimeout: 30s + ## Specify Metric Relabellings to add to the scrape endpoint + ## + # relabellings: + ## Specify honorLabels parameter to add the scrape endpoint + ## + honorLabels: false + ## Used to pass Labels that are used by the Prometheus installed in your cluster to select Service Monitors to work with + ## ref: https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#prometheusspec + ## + additionalLabels: {} + + ## Custom PrometheusRule to be defined + ## The value is evaluated as a template, so, for example, the value can depend on .Release or .Chart + ## ref: https://github.com/coreos/prometheus-operator#customresourcedefinitions + ## + prometheusRule: + enabled: false + additionalLabels: {} + namespace: '' + ## List of rules, used as template by Helm. + ## These are just examples rules inspired from https://awesome-prometheus-alerts.grep.to/rules.html + # rules: + # - alert: RabbitmqDown + # expr: rabbitmq_up{service="{{ template "rabbitmq.fullname" . }}"} == 0 + # for: 5m + # labels: + # severity: error + rules: [] + +## Admin swagger should have only internal access. Hence linked to internal gateway +istio: + enabled: false + gateways: + - istio-system/internal + prefix: + corsPolicy: + allowOrigins: + - prefix: https://api-internal.sandbox.xyz.net + allowCredentials: true + allowHeaders: + - Accept + - Accept-Encoding + - Accept-Language + - Connection + - Content-Type + - Cookie + - Host + - Referer + - Sec-Fetch-Dest + - Sec-Fetch-Mode + - Sec-Fetch-Site + - Sec-Fetch-User + - Origin + - Upgrade-Insecure-Requests + - User-Agent + - sec-ch-ua + - sec-ch-ua-mobile + - sec-ch-ua-platform + - x-xsrf-token + - xsrf-token + allowMethods: + - GET + - POST + - PATCH + - PUT + - DELETE + +modules: + - name: admin-ui + enabled: true + image: + registry: docker.io + repository: mosipqa/uitest-admin + tag: develop + pullPolicy: Always + - name: pmp-ui + enabled: true + image: + registry: docker.io + repository: mosipqa/uitest-pmp + tag: develop + pullPolicy: Always + - name: resident-ui + enabled: true + image: + registry: docker.io + repository: mosipqa/uitest-resident + tag: develop + pullPolicy: Always + +crontime: "0 3 * * *" ## run cronjob every day at 3 AM (time hr: 0-23 ) + +uitestrig: + configmaps: + s3: + s3-host: 'http://minio.minio:9000' + s3-user-key: 'admin' + s3-region: '' + db: + db-port: '5432' + db-su-user: 'postgres' + db-server: 'api-internal.sandbox.xyz.net' + uitestrig: + apiInternalEndPoint: 'https://api-internal.sandbox.xyz.net' + apiEnvUser: 'api-internal.sandbox.xyz.net' + PmpPortalPath: 'https://pmp.sandbox.xyz.net' + adminPortalPath: 'https://admin.sandbox.xyz.net' + residentPortalPath: 'https://resident.sandbox.xyz.net' + CHROME_DRIVER_CPU_LIMIT: "2" + CHROME_DRIVER_MEMORY: 3g + loginlang: sin + push-reports-to-s3: 'yes' + s3-account: uitestrig + scripts: + fetch_docker_image_hash_ids.sh: | + #!/bin/bash + sleep 5 + export DOCKER_HASH_ID=$( kubectl get pod "$HOSTNAME" -n "$NS" -o jsonpath='{.status.containerStatuses[*].imageID}' | sed 's/ /\n/g' | grep -v 'istio' | sed 's/docker\-pullable\:\/\///g' ) + export DOCKER_IMAGE=$( kubectl get pod "$HOSTNAME" -n "$NS" -o jsonpath='{.status.containerStatuses[*].image}' | sed 's/ /\n/g' | grep -v 'istio' | sed 's/docker\-pullable\:\/\///g' ) + if [[ -z $DOCKER_HASH_ID ]]; then + echo "DOCKER_HASH_ID IS EMPTY;EXITING"; + exit 1; + fi + echo "DOCKER_HASH_ID ; $DOCKER_HASH_ID" + echo "DOCKER_IMAGE : $DOCKER_IMAGE" + kubectl get pods -A -o=jsonpath='{range .items[*]}{.metadata.namespace}{","}{.metadata.labels.app\.kubernetes\.io\/name}{","}{.status.containerStatuses[?(@.name!="istio-proxy")].image}{","}{.status.containerStatuses[?(@.name!="istio-proxy")].imageID}{","}{.metadata.creationTimestamp}{"\n"}' | sed 's/ /\n/g' | grep -vE 'istio*|longhorn*|cattle*|rancher|kube' | sed 's/docker\-pullable\:\/\///g' | sort -u | sed '/,,,/d' | awk -F ',' 'BEGIN {print "{ \"POD_NAME\": \"'$(echo $HOSTNAME)'\", \"DOCKER_IMAGE\": \"'$(echo $DOCKER_IMAGE)'\", \"DOCKER_HASH_ID\": \"'$(echo $DOCKER_HASH_ID)'\", \"k8s-cluster-image-list\": ["} {print "{"} {print "\"namespace\": \"" $1 "\","} {print "\"app_name\": \"" $2 "\","} {print "\"docker_image_name\": \"" $3 "\","} {print "\"docker_image_id\": \"" $4 "\","} {print "\"creation_timestamp\": \"" $5 "\"" } {print "},"} END {print "]}"}' | sed -z 's/},\n]/}\n]/g' | jq -r . | tee -a images-list.json + ## run entrypoint script + sleep 5 + cd /home/${container_user}/ + bash ./entrypoint.sh + secrets: + volumes: + configmaps: + scripts: + defaultMode: 0777 + volumeMounts: + mountPath: '/home/mosip/scripts/' + +enable_insecure: false diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000000..306e1ddc56 --- /dev/null +++ b/pom.xml @@ -0,0 +1,286 @@ + + + 4.0.0 + + io.mosip.testrig + mosip-functional-test + 1.2.1-SNAPSHOT + pom + mosip-function-test + Parent project of MOSIP Functional test + mosip-functional-tests + + + + MPL 2.0 + https://www.mozilla.org/en-US/MPL/2.0/ + + + + + scm:git:git://github.com/mosip/mosip-functional-tests.git + scm:git:ssh://github.com:mosip/mosip-functional-tests.git + https://github.com/mosip/mosip-functional-tests + HEAD + + + + + Mosip + mosip.emailnotifier@gmail.com + io.mosip + https://github.com/mosip/mosip-functional-tests + + + + + + ossrh + CentralRepository + https://oss.sonatype.org/content/repositories/snapshots + default + + true + + + + central + MavenCentral + default + https://repo1.maven.org/maven2 + + false + + + + + + + ossrh + https://oss.sonatype.org/content/repositories/snapshots + + + ossrh + https://oss.sonatype.org/service/local/staging/deploy/maven2/ + + + + + UTF-8 + + + 21 + 21 + 3.7.0.1746 + 0.8.11 + 0.8.11 + + + io.mosip.testrig.apirig.apitest.commons/** + + io.mosip.testrig.apirig.apitest.commons/** + + + + authentication-demo-service + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + ${skipTests} + false + + --add-opens=java.base/java.lang=ALL-UNNAMED + --add-opens=java.base/java.util=ALL-UNNAMED + --add-opens=java.base/java.net=ALL-UNNAMED + --add-opens=java.base/java.time=ALL-UNNAMED + --add-opens=java.base/java.io=ALL-UNNAMED + --add-opens=java.base/java.time.format=ALL-UNNAMED + + + + + org.apache.maven.plugins + maven-javadoc-plugin + + + attach-javadocs + + jar + + + + + none + -Xdoclint:none + + + + org.sonatype.plugins + nexus-staging-maven-plugin + true + + ossrh + https://oss.sonatype.org/ + false + + + + org.apache.maven.plugins + maven-jar-plugin + + + + true + true + + + ${project.name} + ${project.version} + + + + + + org.apache.maven.plugins + maven-war-plugin + + + + true + true + + + ${project.name} + ${project.version} + + + + + + org.apache.maven.plugins + maven-source-plugin + + + attach-sources + + jar-no-fork + + + + + + org.apache.maven.plugins + maven-gpg-plugin + + + sign-artifacts + verify + + sign + + + + --pinentry-mode + loopback + + + + + + + pl.project13.maven + git-commit-id-plugin + + + get-the-git-infos + + revision + + validate + + + + true + git.properties + + ^git.build.(time|version)$ + ^git.commit.id.(abbrev|full)$ + + full + ${project.basedir}/.git + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + -parameters + + ${maven.compiler.source} + ${maven.compiler.target} + + + + org.jacoco + jacoco-maven-plugin + ${jacoco.maven.plugin.version} + + + jacoco-initialize + + prepare-agent + + + + jacoco-site + package + + report + + + + + + + + + sonar + + . + src/main/java/**,src/main/resources/** + ${sonar.coverage.exclusions} + https://sonarcloud.io + true + + + false + + + + + org.sonarsource.scanner.maven + sonar-maven-plugin + ${maven.sonar.plugin.version} + + + verify + + sonar + + + + + + + + +