Skip to content

Commit

Permalink
433: HAPI FHIR REST Audit Sender for BALP Audits
Browse files Browse the repository at this point in the history
  • Loading branch information
Boris Stanojevic committed Jan 25, 2024
1 parent 4766c2a commit 7df3541
Show file tree
Hide file tree
Showing 62 changed files with 1,937 additions and 105 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,4 @@ work
/commons/ihe/xds/generated-stubs
generated-stubs
/commons/audit/.vertx
/local_history.patch
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ public AuditContext auditContext(IpfAtnaConfigurationProperties config,
auditContext.setAuditSource(config.getAuditSourceType());
auditContext.setIncludeParticipantsFromResponse(config.isIncludeParticipantsFromResponse());
auditContext.setAuditValueIfMissing(config.getAuditValueIfMissing());
auditContext.setAuditRepositoryContextPath(config.getAuditRepositoryContextPath());

// Strategies and complex parameters; overrideable
auditContext.setTlsParameters(tlsParameters);
Expand Down Expand Up @@ -95,10 +96,10 @@ public AuditTransmissionProtocol auditTransmissionProtocol(IpfAtnaConfigurationP
TlsParameters tlsParameters) throws Exception {
if (config.getAuditSenderClass() != null) {
return config.getAuditSenderClass().getConstructor(TlsParameters.class)
.newInstance(tlsParameters);
.newInstance(tlsParameters);
}
return AuditTransmissionChannel.fromProtocolName(config.getAuditRepositoryTransport())
.makeInstance(tlsParameters);
.makeInstance(tlsParameters);
}

@Bean
Expand All @@ -107,8 +108,8 @@ public AuditMetadataProvider auditMetadataProvider(IpfAtnaConfigurationPropertie
@Value("${spring.application.name}") String appName) {
var auditMetadataProvider = new DefaultAuditMetadataProvider();
auditMetadataProvider.setSendingApplication(config.getAuditSendingApplication() != null ?
config.getAuditSendingApplication() :
appName);
config.getAuditSendingApplication() :
appName);
return auditMetadataProvider;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,12 @@ public class IpfAtnaConfigurationProperties {
@Getter @Setter
private int auditRepositoryPort = 514;

/**
* Sets the context-path of the BALP audit record repository.
*/
@Getter @Setter
private String auditRepositoryContextPath = "";

/**
* Enterprise Site Id
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ public void testAtnaSettings() throws Exception {
assertEquals("mysite", auditContext.getAuditEnterpriseSiteId());
assertEquals("localhost", auditContext.getAuditRepositoryHostName());
assertEquals(1342, auditContext.getAuditRepositoryPort());
assertEquals("fhir", auditContext.getAuditRepositoryContextPath());
assertEquals("TLS", auditContext.getAuditTransmissionProtocol().getTransportName());
assertTrue(auditContext.getAuditMessageQueue() instanceof AsynchronousAuditMessageQueue);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ ipf:
audit-enabled: false
audit-repository-host: localhost
audit-repository-port: 1342
audit-repository-context-path: fhir
audit-repository-transport: TLS
audit-enterprise-site-id: mysite
audit-queue-class: org.openehealth.ipf.commons.audit.queue.AsynchronousAuditMessageQueue
security-domain-name: mydomain

4 changes: 4 additions & 0 deletions commons/audit/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@
<artifactId>jakarta.jms-api</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-base</artifactId>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,8 @@ default SerializationStrategy getSerializationStrategy() {
default void audit(AuditMessage... messages) {
if (isAuditEnabled() && messages != null) {
getAuditMessageQueue().audit(this, Stream.of(messages)
.map(getAuditMessagePostProcessor())
.toArray(AuditMessage[]::new));
.map(getAuditMessagePostProcessor())
.toArray(AuditMessage[]::new));
}
}

Expand Down Expand Up @@ -165,6 +165,8 @@ default String getAuditValueIfMissing() {
*/
boolean isIncludeParticipantsFromResponse();

String getAuditRepositoryContextPath();

static AuditContext noAudit() {
return DefaultAuditContext.NO_AUDIT;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,10 @@ public class DefaultAuditContext implements AuditContext {
@Setter
private String auditValueIfMissing = "UNKNOWN";

@Getter
@Setter
private String auditRepositoryContextPath = "";

public String getAuditRepositoryTransport() {
return auditTransmissionProtocol.getTransportName();
}
Expand All @@ -111,7 +115,7 @@ public void setAuditRepositoryHost(String host) {

public void setAuditRepositoryTransport(String transport) {
setAuditTransmissionProtocol(
AuditTransmissionChannel.fromProtocolName(transport).makeInstance(tlsParameters)
AuditTransmissionChannel.fromProtocolName(transport).makeInstance(tlsParameters)
);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Copyright 2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.openehealth.ipf.commons.audit;

import ca.uhn.fhir.context.FhirContext;

public class FhirContextHolder {

private static final ThreadLocal<FhirContext> currentFhirContext = new ThreadLocal<>();

public static void setCurrentContext(FhirContext fhirContext) {
currentFhirContext.set(fhirContext);
}

public static FhirContext get() {
return currentFhirContext.get();
}

public static void remove() {
currentFhirContext.remove();
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -18,45 +18,57 @@

import org.openehealth.ipf.commons.audit.AuditException;
import org.openehealth.ipf.commons.audit.TlsParameters;
import org.openehealth.ipf.commons.audit.protocol.providers.NettyTLSSyslogSenderProvider;
import org.openehealth.ipf.commons.audit.protocol.providers.ReactorNettyTLSSyslogSenderProvider;
import org.openehealth.ipf.commons.audit.protocol.providers.RecordingAuditMessageTransmissionProvider;
import org.openehealth.ipf.commons.audit.protocol.providers.TLSSyslogSenderProvider;
import org.openehealth.ipf.commons.audit.protocol.providers.UDPSyslogSenderProvider;
import org.openehealth.ipf.commons.audit.protocol.providers.VertxTLSSyslogSenderProvider;

import java.util.Arrays;
import java.util.ServiceLoader;
import java.util.stream.Collectors;

/**
* Maps AuditTransmissionProtocol names to instances
* Maps AuditTransmissionProtocol names to service providers which should provide a concrete instance of an
* {@link AuditTransmissionProtocol} over a {@link ServiceLoader} mechanism.
*
* @author Christian Ohr
*/
public enum AuditTransmissionChannel {

UDP("UDP", UDPSyslogSenderImpl.class),
NIO_UDP("NIO-UDP", UDPSyslogSenderImpl.class),
VERTX_UDP("VERTX-UDP", UDPSyslogSenderImpl.class),
TLS("TLS", TLSSyslogSenderImpl.class),
NIO_TLS("NIO-TLS", NettyTLSSyslogSenderImpl.class),
VERTX_TLS("VERTX-TLS", VertxTLSSyslogSenderImpl.class),
NETTY_TLS("NETTY-TLS", NettyTLSSyslogSenderImpl.class),
REACTOR_NETTY_TLS("REACTOR-NETTY-TLS", ReactorNettyTLSSyslogSenderImpl.class),
RECORDING("RECORDING", RecordingAuditMessageTransmission.class);
UDP("UDP", UDPSyslogSenderProvider.class.getName()),
NIO_UDP("NIO-UDP", UDPSyslogSenderProvider.class.getName()),
VERTX_UDP("VERTX-UDP", UDPSyslogSenderProvider.class.getName()),
TLS("TLS", TLSSyslogSenderProvider.class.getName()),
NIO_TLS("NIO-TLS", NettyTLSSyslogSenderProvider.class.getName()),
VERTX_TLS("VERTX-TLS", VertxTLSSyslogSenderProvider.class.getName()),
NETTY_TLS("NETTY-TLS", NettyTLSSyslogSenderProvider.class.getName()),
REACTOR_NETTY_TLS("REACTOR-NETTY-TLS", ReactorNettyTLSSyslogSenderProvider.class.getName()),
FHIR_REST_TLS("FHIR-REST-TLS", "org.openehealth.ipf.commons.ihe.fhir.audit.protocol.FhirRestTLSAuditRecordApacheSenderProvider"),
FHIR_REST_METHANOL_TLS("FHIR-REST-METHANOL-TLS", "org.openehealth.ipf.commons.ihe.fhir.audit.protocol.FhirRestTLSAuditRecordMethanolSenderProvider"),
RECORDING("RECORDING", RecordingAuditMessageTransmissionProvider.class.getName());

private final String protocolName;
private final Class<? extends AuditTransmissionProtocol> protocol;
private final String protocolClass;

AuditTransmissionChannel(String protocolName, Class<? extends AuditTransmissionProtocol> protocol) {
AuditTransmissionChannel(String protocolName, String protocolClass) {
this.protocolName = protocolName;
this.protocol = protocol;
this.protocolClass = protocolClass;
}

public String getProtocolName() {
return protocolName;
}

public AuditTransmissionProtocol makeInstance(TlsParameters tlsParameters) {
try {
return protocol.getConstructor(TlsParameters.class).newInstance(tlsParameters);
} catch (Exception e) {
throw new AuditException(e);
ServiceLoader<AuditTransmissionProtocolProvider> loader = ServiceLoader.load(AuditTransmissionProtocolProvider.class);
for (AuditTransmissionProtocolProvider provider : loader) {
if (protocolClass.equals(provider.getClass().getName())) {
return provider.createAuditTransmissionProtocol(tlsParameters);
}
}
throw new AuditException("Could not instantiate AuditTransmissionProtocolProvider for name " + protocolName);
}

public static AuditTransmissionChannel fromProtocolName(String protocolName) {
Expand All @@ -66,9 +78,10 @@ public static AuditTransmissionChannel fromProtocolName(String protocolName) {
}
}
throw new IllegalArgumentException("Unknown audit protocol name: " + protocolName +
". Choose one of: " +
Arrays.stream(AuditTransmissionChannel.values())
.map(AuditTransmissionChannel::getProtocolName)
.collect(Collectors.joining(",")));
". Choose one of: " +
Arrays.stream(AuditTransmissionChannel.values())
.map(AuditTransmissionChannel::getProtocolName)
.collect(Collectors.joining(",")));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* Copyright 2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.openehealth.ipf.commons.audit.protocol;

import org.openehealth.ipf.commons.audit.TlsParameters;

/**
* A Service Provider interface located and loaded by {@link java.util.ServiceLoader}.
* Implementations should provide an instance of {@link AuditTransmissionProtocol}
*
* @see AuditTransmissionProtocol
* @see AuditTransmissionChannel
*
* @author Boris Stanojevic
*/
public interface AuditTransmissionProtocolProvider {
AuditTransmissionProtocol createAuditTransmissionProtocol(TlsParameters tlsParameters);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Copyright 2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.openehealth.ipf.commons.audit.protocol.providers;

import org.openehealth.ipf.commons.audit.TlsParameters;
import org.openehealth.ipf.commons.audit.protocol.AuditTransmissionProtocol;
import org.openehealth.ipf.commons.audit.protocol.AuditTransmissionProtocolProvider;
import org.openehealth.ipf.commons.audit.protocol.NettyTLSSyslogSenderImpl;

public class NettyTLSSyslogSenderProvider implements AuditTransmissionProtocolProvider {

@Override
public AuditTransmissionProtocol createAuditTransmissionProtocol(TlsParameters tlsParameters) {
return new NettyTLSSyslogSenderImpl(tlsParameters);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Copyright 2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.openehealth.ipf.commons.audit.protocol.providers;

import org.openehealth.ipf.commons.audit.TlsParameters;
import org.openehealth.ipf.commons.audit.protocol.AuditTransmissionProtocol;
import org.openehealth.ipf.commons.audit.protocol.AuditTransmissionProtocolProvider;
import org.openehealth.ipf.commons.audit.protocol.ReactorNettyTLSSyslogSenderImpl;

public class ReactorNettyTLSSyslogSenderProvider implements AuditTransmissionProtocolProvider {

@Override
public AuditTransmissionProtocol createAuditTransmissionProtocol(TlsParameters tlsParameters) {
return new ReactorNettyTLSSyslogSenderImpl(tlsParameters);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Copyright 2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.openehealth.ipf.commons.audit.protocol.providers;

import org.openehealth.ipf.commons.audit.TlsParameters;
import org.openehealth.ipf.commons.audit.protocol.AuditTransmissionProtocol;
import org.openehealth.ipf.commons.audit.protocol.AuditTransmissionProtocolProvider;
import org.openehealth.ipf.commons.audit.protocol.RecordingAuditMessageTransmission;

public class RecordingAuditMessageTransmissionProvider implements AuditTransmissionProtocolProvider {

@Override
public AuditTransmissionProtocol createAuditTransmissionProtocol(TlsParameters tlsParameters) {
return new RecordingAuditMessageTransmission(tlsParameters);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Copyright 2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.openehealth.ipf.commons.audit.protocol.providers;

import org.openehealth.ipf.commons.audit.TlsParameters;
import org.openehealth.ipf.commons.audit.protocol.AuditTransmissionProtocol;
import org.openehealth.ipf.commons.audit.protocol.AuditTransmissionProtocolProvider;
import org.openehealth.ipf.commons.audit.protocol.TLSSyslogSenderImpl;

public class TLSSyslogSenderProvider implements AuditTransmissionProtocolProvider {

@Override
public AuditTransmissionProtocol createAuditTransmissionProtocol(TlsParameters tlsParameters) {
return new TLSSyslogSenderImpl(tlsParameters);
}
}
Loading

0 comments on commit 7df3541

Please sign in to comment.