Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release v2.1.6 branch #15

Merged
merged 47 commits into from
Nov 20, 2024
Merged
Changes from 4 commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
6ac8f6f
Initial commit of base code.
keithboone May 25, 2024
d205a5f
Added Workflow file
keithboone May 25, 2024
2a68865
Fix workflow error.
keithboone May 25, 2024
220afa3
Merge branch 'Release_v2.1.0-branch' into IGDD-1505_Refactor_Hub_and_…
keithboone May 25, 2024
324135f
Fix environment variable error.
keithboone May 25, 2024
63d4d6f
Merge branch 'IGDD-1505_Refactor_Hub_and_Core' of https://github.com/…
keithboone May 25, 2024
bd148f3
Working on settings.xml values for GITHUB_ACTOR and GITHUB_TOKEN
keithboone May 25, 2024
5597edc
Adjusting spring-boot dependency.
keithboone May 25, 2024
0d6d23d
Added base dependencies from izgateway pom.xml file.
keithboone May 25, 2024
f2e2a68
Working on settings.xml some more.
keithboone May 25, 2024
505003a
Continuing work on settings.xml
keithboone May 25, 2024
168e922
Merge pull request #1 from IZGateway/IGDD-1505_Refactor_Hub_and_Core
keithboone Jun 10, 2024
977ec6d
Igdd 1546 add demo data to mock (#2)
keithboone Jun 10, 2024
584c061
Migrate 2.0.5 patch (#3)
keithboone Jun 17, 2024
6762c79
Merge 2.0.5 changes
keithboone Jun 29, 2024
3bc90e9
Merging in 2.0.6 Changes
keithboone Jun 29, 2024
fb1f17a
Notes on code change for IGDD-1620
keithboone Jul 16, 2024
e1784c3
Refactor LoggingValve for use in both Hub and Transformation Service.…
pcahillai Jul 25, 2024
935b3b2
Adding code to take in config value for wsdl location element. (#5)
pcahillai Jul 25, 2024
924f550
Upgraded Spring Boot to 3.3.2
keithboone Jul 26, 2024
a7eb6ae
IGDD-1643 Status History is reporting exceptions
keithboone Jul 31, 2024
3e2ef4e
Added some javadoc to SystemUtils.
keithboone Jul 31, 2024
aee02a4
Added back ErrorText support.
keithboone Aug 2, 2024
99e403e
Merge pull request #6 from IZGateway/IGDD-1643_Status_History_is_repo…
pcahillai Aug 2, 2024
df4afb4
Updating for save to blacklist. (#7)
keithboone Aug 6, 2024
78ecd1c
Igdd 1642 rework access controls (#8)
keithboone Aug 6, 2024
82be650
Restrict logging for non-test messages.
keithboone Aug 14, 2024
cb09e99
Fix .classpath
keithboone Aug 18, 2024
5901bca
Upgrade spring-framework to 6.1.12 for CVE-2024-38809
keithboone Aug 19, 2024
3170c5e
Updating version for Release
keithboone Aug 19, 2024
f6dd9b6
Adjusting test patterns to Lori's list since rebuilding anyway.
keithboone Aug 21, 2024
aef437f
Local commit
keithboone Aug 26, 2024
392c31d
Fix classpath.
keithboone Aug 26, 2024
436e7a2
Adjusting Test Message Criteria
keithboone Aug 26, 2024
1530a40
Update for credential masking.
keithboone Aug 26, 2024
45b7f35
Remove OPEN Role IGDD-1713, clean up logging and add support for DEX 2.0
keithboone Sep 23, 2024
1dc02bc
Merge branch 'main' into Release_v2.1.3-branch
keithboone Sep 24, 2024
a812706
Upgraded to spring-boot-starter-parent 3.3.4
keithboone Sep 24, 2024
93b0cff
Upgrade to spring 3.3.4
keithboone Sep 24, 2024
56c786a
Merge branch 'Release_v2.1.3-branch' of https://github.com/IZGateway/…
keithboone Sep 24, 2024
8856836
Local push for migration.
keithboone Oct 10, 2024
bcde615
Fixes for IZHD-4563 and updating Health reporting to report Database
keithboone Oct 12, 2024
7e04634
Upgrade Bouncy Castle to 2.0
keithboone Oct 17, 2024
584af43
Merge branch 'main' into Release_v2.1.4-branch
keithboone Oct 23, 2024
9b24ac9
Fixing merge error.
keithboone Oct 23, 2024
db6d80a
Fixes for 2.1.6
keithboone Nov 18, 2024
771d6d1
NPE fix
keithboone Nov 20, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 90 additions & 2 deletions src/main/java/gov/cdc/izgateway/soap/net/MessageSender.java
Original file line number Diff line number Diff line change
@@ -46,6 +46,7 @@
import gov.cdc.izgateway.soap.fault.DestinationConnectionFault;
import gov.cdc.izgateway.soap.fault.Fault;
import gov.cdc.izgateway.soap.fault.HubClientFault;
import gov.cdc.izgateway.soap.fault.SecurityFault;
import gov.cdc.izgateway.soap.message.ConnectivityTestRequest;
import gov.cdc.izgateway.soap.message.ConnectivityTestResponse;
import gov.cdc.izgateway.soap.message.FaultMessage;
@@ -54,10 +55,22 @@
import gov.cdc.izgateway.soap.message.SubmitSingleMessageResponse;
import gov.cdc.izgateway.utils.FixedByteArrayOutputStream;
import gov.cdc.izgateway.utils.PreservingOutputStream;
import gov.cdc.izgateway.utils.SystemUtils;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLPeerUnverifiedException;

/**
* MessageSender is responsible for sending messages to a given destination,
* and then returning the response back into a message object. It uses
* the SoapMessageConverter to handle marshalling and unmarshalling into and from
* the wire formats.
*
* @see SoapMessageConverter
*
* @author Audacious Inquiry
*
*/
@Component
public class MessageSender {
private static final List<Integer> ACCEPTABLE_RESPONSE_CODES = Arrays.asList(HttpURLConnection.HTTP_OK, HttpURLConnection.HTTP_BAD_REQUEST, HttpURLConnection.HTTP_INTERNAL_ERROR);
@@ -70,6 +83,16 @@ public class MessageSender {
private IStatusCheckerService statusChecker;
private boolean preserveOutput = true; // set to true to preserve output for debugging.
private final boolean isProduction;

/**
* Construct a message sender
* @param serverConfig The server
* @param senderConfig The sender configuration
* @param clientConfig The client configuration parameters
* @param tlsSupport Tls configuration
* @param statusService The service that records the status of communications
* @param app The web application configuration
*/
@Autowired
public MessageSender(
final ServerConfiguration serverConfig,
@@ -104,13 +127,30 @@ public boolean isExempt(String destId) {
}
};
}
/**
* Set the service used to check status. This is late bound to avoid
* circular class dependencies.
*
* @param statusChecker The status checker service
*/
public void setStatusChecker(IStatusCheckerService statusChecker) {
this.statusChecker = statusChecker;
}
/**
* Get the status checker service
* @return the status checker service
*/
public IStatusCheckerService getStatusChecker() {
return statusChecker;
}

/**
* Send a submitSingleMessage request
* @param dest The destination to send it to
* @param submitSingleMessage The message to send
* @return The response
* @throws Fault If an error occurred while sending or unmarshalling the response
*/
public SubmitSingleMessageResponse sendSubmitSingleMessage(
IDestination dest,
SubmitSingleMessageRequest submitSingleMessage
@@ -231,6 +271,21 @@ private String getSchemaToUse(IDestination dest) {
return SoapMessage.IIS2014_NS;
}

/**
* Sends a connectivity test request to the destination.
*
* Connectivity tests are used to verify connectivity between IZ Gateway and the destination endpoint. They originated
* in the CDC WSDL but IZ Gateway can also route a connectivity test from a sender to a specific destination to verify
* that it is alive. Not all jurisdictions are able to support the connectivity test, either due to security requirements
* or technical limitations. If you get back a response, the jurisdiction endpoint is at least alive and listening. If
* you do not, it MAY be due to jurisdiction limitations on supporting this capability. All new onboarded jurisdictions
* MUST support this capability.
*
* @param dest The destination
* @param connectivityTest The connectivity test message
* @return The response (which should contain the same message body back)
* @throws Fault If an error occurred.
*/
public ConnectivityTestResponse sendConnectivityTest(IDestination dest, ConnectivityTestRequest connectivityTest)
throws Fault {
String schemaToUse = dest.is2011() ? SoapMessage.IIS2011_NS : SoapMessage.IIS2014_NS;
@@ -242,6 +297,15 @@ public ConnectivityTestResponse sendConnectivityTest(IDestination dest, Connecti
return toBeReturned;
}

/**
* Send a message and obtain a response of the specified type to the given destination
* @param <T> represents the type of the response
* @param clazz The class of the expected response message
* @param dest The destination to send the message to
* @param toBeSent The message to send
* @return The response
* @throws Fault If a fault occurs during sending.
*/
public <T extends SoapMessage> T sendMessage(Class<T> clazz, IDestination dest, SoapMessage toBeSent)
throws Fault {
long started = 0;
@@ -377,12 +441,26 @@ private HubClientFault processHttpError(IDestination dest, int statusCode, Input
return HubClientFault.httpError(dest, statusCode, error);
}

URL getUrl(IDestination dest) throws DestinationConnectionFault {
/**
* Get the URL from the destination
* @param dest The destination to get the URL for
* @return A url properly configured for sending, and verified against security rules.
* @throws DestinationConnectionFault If the URL is misconfigured.
* @throws SecurityFault If the system and destination do not agree on the operating environment (e.g., prod, onboarding, dev)
*/
URL getUrl(IDestination dest) throws DestinationConnectionFault, SecurityFault {

String destUri = StringUtils.substringBefore(dest.getDestUri(), "?"); // Remove any query parameter from the path.
String errorMsg = "Destination " + dest.getDestId();

if (dest.getDestTypeId() != SystemUtils.getDestType()) {
throw SecurityFault.generalSecurity(errorMsg + " environment mismatch",
"Expected " + SystemUtils.getDestTypeAsString() + " != " + dest.getDestType(), null);
}


if (StringUtils.startsWith(destUri, "http:")) {
throw new SecurityException(errorMsg + " is not using https: " + destUri);
throw SecurityFault.generalSecurity(errorMsg + " is not using https", destUri, null);
}

try {
@@ -413,6 +491,16 @@ URL getReportedUrl(IDestination dest, URL destUrl) throws DestinationConnectionF
return destUrl;
}

/**
* Capture information about the destination certificates for subsequent logging.
*
* This method captures information about
* - whether or not a connection was made successfully
* - the jurisdiction certificate used in the connection
* - the cipher suite selected for the connection.
*
* @param con The connection used to connect to the jurisdiction.
*/
public static void logDestinationCertificates(HttpURLConnection con) {
DestinationInfo destination = RequestContext.getDestinationInfo();
if (destination.isConnected() && con instanceof HttpsURLConnection conx) {
53 changes: 48 additions & 5 deletions src/main/java/gov/cdc/izgateway/utils/SystemUtils.java
Original file line number Diff line number Diff line change
@@ -4,6 +4,12 @@
import java.util.List;
import org.apache.commons.lang3.StringUtils;

/**
* SystemUtils answers questions about the system and server environment.
*
* @author Audacious Inquiry
*
*/
public class SystemUtils {

private static final String HOSTNAME = hostName();
@@ -18,14 +24,29 @@ public class SystemUtils {
protected static final String[] ENVIRONMENT_TAGS = { "unknown", "prod", "test", "onboard", "staging", "dev" };

private SystemUtils() { }

/**
* Get the hostname.
* @return The hostname.
*/
public static String getHostname() {
return HOSTNAME;
}

/**
* Get the value that identifies the environment.
* @return The destination type.
*/
public static int getDestType() {
return DESTTYPE;
}

/**
* Dynamically get the value that identifies the hostname.
* Used during class initiation ONCE.
*
* @return The hostname.
*/
private static String hostName() {
String host = System.getenv("HOSTNAME");
if ( StringUtils.isEmpty( host)) {
@@ -43,6 +64,11 @@ private static String hostName() {
return host;
}

/**
* Dynamically get the value that identifies the environment.
* Used during class initiation ONCE.
* @return The environment id.
*/
private static int destType() {
String tag = System.getenv("ELASTIC_ENV_TAG");
if (tag == null) {
@@ -63,27 +89,44 @@ private static int destType() {
}
}

/**
* Convert environment to a human readable string
* @return a human readable string representation of the environment id
*/
public static String getDestTypeAsString() {
return ENVIRONMENTS[DESTTYPE];
}

/**
* Convert environment to the tag used to identify it in logs.
* @return the elastic log tag for the environment.
*/
public static String getDestTag() {
return ENVIRONMENT_TAGS[DESTTYPE];
}

public static String getDestTag(int destType) {
return ENVIRONMENT_TAGS[destType];
}

/**
* Get All tags used to identify an environment in elastic.
* @return the elastic log tags for all known environments.
*/
public static String[] getDestTags() {
return ENVIRONMENT_TAGS;
}

/**
* Convert the string back to an integer
* @param destType2 The string
* @return The environment value it corresponds to
*/
public static int getDestTypeId(String destType2) {
return Arrays.asList(SystemUtils.ENVIRONMENTS).indexOf(destType2);
}

/**
* Get the list of legitimate environment names
* @return the list of legitimate environment names
*/
public static List<String> getDestTypes() {
return Arrays.asList(SystemUtils.ENVIRONMENTS).subList(1, SystemUtils.ENVIRONMENTS.length);
}
}
}
22 changes: 19 additions & 3 deletions src/main/java/gov/cdc/izgateway/utils/XmlUtils.java
Original file line number Diff line number Diff line change
@@ -49,23 +49,39 @@ static DocumentBuilder getDocumentBuilder() {
}
}

/**
* Parse a String as an XML Document using an safe XML Builder.
* @param s The string to parse
* @return The parsed document, or null if the string was empty, or there was any sort of error
*/
public static Document parseDocument(String s) {
if (documentBuilder == null) {
if (documentBuilder == null || StringUtils.isBlank(s)) {
return null;
}
try {
if (!StringUtils.isEmpty(s)) {
return documentBuilder.parse(new InputSource(new StringReader(s)));
}
} catch (SAXException | IOException e) {
// Swallow the exception

Document d = documentBuilder.newDocument();
d.appendChild(d.createElement("ErrorText"));
d.getDocumentElement().appendChild(d.createTextNode(s));
return d;

} catch (Exception e) {
// Swallow any exception
}
Document d = documentBuilder.newDocument();
d.appendChild(d.createElement("ErrorText"));
d.getDocumentElement().appendChild(d.createTextNode(s));
return d;
}

/**
* Convert an input stream to a string
* @param is The stream
* @return The string, or null if any sort of error occurred.
*/
public static String toString(InputStream is) {
try {
if (is != null) {
25 changes: 24 additions & 1 deletion src/main/resources/statusquery.json
Original file line number Diff line number Diff line change
@@ -177,7 +177,30 @@
}
}
}
}
},
"tags-bucket": {
"filter": {
"bool": {
"must": [],
"filter": [],
"should": [],
"must_not": []
}
},
"aggs": {
"tags-metric": {
"top_metrics": {
"metrics": {
"field": "tags.keyword"
},
"size": 1,
"sort": {
"@timestamp": "desc"
}
}
}
}
}
}
}
}