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

Add Transport Layer abstraction at Bootstrap server side. #1336

Merged
merged 2 commits into from
Jan 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -21,27 +21,37 @@
import java.io.File;
import java.io.PrintWriter;
import java.net.InetSocketAddress;
import java.net.URI;
import java.security.cert.Certificate;
import java.util.List;

import org.eclipse.californium.core.config.CoapConfig;
import org.eclipse.californium.elements.config.Configuration;
import org.eclipse.californium.scandium.config.DtlsConfig;
import org.eclipse.californium.scandium.config.DtlsConnectorConfig;
import org.eclipse.californium.scandium.config.DtlsConnectorConfig.Builder;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.webapp.WebAppContext;
import org.eclipse.leshan.core.californium.PrincipalMdcConnectionListener;
import org.eclipse.leshan.core.demo.cli.ShortErrorMessageHandler;
import org.eclipse.leshan.core.endpoint.EndpointUriUtil;
import org.eclipse.leshan.core.endpoint.Protocol;
import org.eclipse.leshan.core.model.ObjectLoader;
import org.eclipse.leshan.core.model.ObjectModel;
import org.eclipse.leshan.server.bootstrap.EditableBootstrapConfigStore;
import org.eclipse.leshan.server.bootstrap.LeshanBootstrapServer;
import org.eclipse.leshan.server.bootstrap.LeshanBootstrapServerBuilder;
import org.eclipse.leshan.server.bootstrap.demo.cli.LeshanBsServerDemoCLI;
import org.eclipse.leshan.server.bootstrap.demo.servlet.BootstrapServlet;
import org.eclipse.leshan.server.bootstrap.demo.servlet.EventServlet;
import org.eclipse.leshan.server.bootstrap.demo.servlet.ServerServlet;
import org.eclipse.leshan.server.californium.bootstrap.LeshanBootstrapServer;
import org.eclipse.leshan.server.californium.bootstrap.LeshanBootstrapServerBuilder;
import org.eclipse.leshan.server.californium.bootstrap.endpoint.BootstrapServerProtocolProvider;
import org.eclipse.leshan.server.californium.bootstrap.endpoint.CaliforniumBootstrapServerEndpointFactory;
import org.eclipse.leshan.server.californium.bootstrap.endpoint.CaliforniumBootstrapServerEndpointsProvider;
import org.eclipse.leshan.server.californium.bootstrap.endpoint.coap.CoapBootstrapServerProtocolProvider;
import org.eclipse.leshan.server.californium.bootstrap.endpoint.coap.CoapOscoreBootstrapServerEndpointFactory;
import org.eclipse.leshan.server.californium.bootstrap.endpoint.coaps.CoapsBootstrapServerEndpointFactory;
import org.eclipse.leshan.server.californium.bootstrap.endpoint.coaps.CoapsBootstrapServerProtocolProvider;
import org.eclipse.leshan.server.core.demo.json.servlet.SecurityServlet;
import org.eclipse.leshan.server.model.VersionedBootstrapModelProvider;
import org.eclipse.leshan.server.security.BootstrapSecurityStoreAdapter;
Expand Down Expand Up @@ -113,37 +123,15 @@ public static LeshanBootstrapServer createBsLeshanServer(LeshanBsServerDemoCLI c
// Prepare LWM2M server
LeshanBootstrapServerBuilder builder = new LeshanBootstrapServerBuilder();

// Create CoAP Config
File configFile = new File(CF_CONFIGURATION_FILENAME);
Configuration coapConfig = LeshanBootstrapServerBuilder.createDefaultCoapConfiguration();
// these configuration values are always overwritten by CLI
// therefore set them to transient.
coapConfig.setTransient(DtlsConfig.DTLS_RECOMMENDED_CIPHER_SUITES_ONLY);
coapConfig.setTransient(DtlsConfig.DTLS_CONNECTION_ID_LENGTH);
if (configFile.isFile()) {
coapConfig.load(configFile);
} else {
coapConfig.store(configFile, CF_CONFIGURATION_HEADER);
}
builder.setCoapConfig(coapConfig);

// ports from CoAP Config if needed
builder.setLocalAddress(cli.main.localAddress,
cli.main.localPort == null ? coapConfig.get(CoapConfig.COAP_PORT) : cli.main.localPort);
builder.setLocalSecureAddress(cli.main.secureLocalAddress,
cli.main.secureLocalPort == null ? coapConfig.get(CoapConfig.COAP_SECURE_PORT)
: cli.main.secureLocalPort);

// Create DTLS Config
DtlsConnectorConfig.Builder dtlsConfig = DtlsConnectorConfig.builder(coapConfig);
dtlsConfig.set(DtlsConfig.DTLS_RECOMMENDED_CIPHER_SUITES_ONLY, !cli.dtls.supportDeprecatedCiphers);
if (cli.dtls.cid != null) {
dtlsConfig.set(DtlsConfig.DTLS_CONNECTION_ID_LENGTH, cli.dtls.cid);
}
// Add MDC for connection logs
if (cli.helpsOptions.getVerboseLevel() > 0) {
dtlsConfig.setConnectionListener(new PrincipalMdcConnectionListener());
// Create Models
List<ObjectModel> models = ObjectLoader.loadDefault();
if (cli.main.modelsFolder != null) {
models.addAll(ObjectLoader.loadObjectsFromDir(cli.main.modelsFolder, true));
}
builder.setObjectModelProvider(new VersionedBootstrapModelProvider(models));

builder.setConfigStore(bsConfigStore);
builder.setSecurityStore(new BootstrapSecurityStoreAdapter(securityStore));

if (cli.identity.isx509()) {
// use X.509 mode (+ RPK)
Expand All @@ -159,24 +147,75 @@ public static LeshanBootstrapServer createBsLeshanServer(LeshanBsServerDemoCLI c
builder.setPrivateKey(cli.identity.getPrivateKey());
}

// Set DTLS Config
builder.setDtlsConfig(dtlsConfig);
// Create Californium Endpoints Provider:
// ------------------
// Create Custom CoAPS protocol provider to add MDC logger :
BootstrapServerProtocolProvider coapsProtocolProvider = new CoapsBootstrapServerProtocolProvider() {
@Override
public CaliforniumBootstrapServerEndpointFactory createDefaultEndpointFactory(URI uri) {
return new CoapsBootstrapServerEndpointFactory(uri) {

@Override
protected Builder createDtlsConnectorConfigBuilder(Configuration configuration) {
Builder dtlsConfigBuilder = super.createDtlsConnectorConfigBuilder(configuration);

// Add MDC for connection logs
if (cli.helpsOptions.getVerboseLevel() > 0)
dtlsConfigBuilder.setConnectionListener(new PrincipalMdcConnectionListener());

return dtlsConfigBuilder;
}
};
}
};

// Create Bootstrap Server Endpoints Provider
CaliforniumBootstrapServerEndpointsProvider.Builder endpointsBuilder = new CaliforniumBootstrapServerEndpointsProvider.Builder(
new CoapBootstrapServerProtocolProvider(), coapsProtocolProvider);

// Create Californium Configuration
Configuration serverCoapConfig = endpointsBuilder.createDefaultConfiguration();

// Set some DTLS stuff
// These configuration values are always overwritten by CLI therefore set them to transient.
serverCoapConfig.setTransient(DtlsConfig.DTLS_RECOMMENDED_CIPHER_SUITES_ONLY);
serverCoapConfig.setTransient(DtlsConfig.DTLS_CONNECTION_ID_LENGTH);
serverCoapConfig.set(DtlsConfig.DTLS_RECOMMENDED_CIPHER_SUITES_ONLY, !cli.dtls.supportDeprecatedCiphers);
if (cli.dtls.cid != null) {
serverCoapConfig.set(DtlsConfig.DTLS_CONNECTION_ID_LENGTH, cli.dtls.cid);
}

// Create Models
List<ObjectModel> models = ObjectLoader.loadDefault();
if (cli.main.modelsFolder != null) {
models.addAll(ObjectLoader.loadObjectsFromDir(cli.main.modelsFolder, true));
// Persist configuration
File configFile = new File(CF_CONFIGURATION_FILENAME);
if (configFile.isFile()) {
serverCoapConfig.load(configFile);
} else {
serverCoapConfig.store(configFile, CF_CONFIGURATION_HEADER);
}
builder.setObjectModelProvider(new VersionedBootstrapModelProvider(models));

builder.setConfigStore(bsConfigStore);
builder.setSecurityStore(new BootstrapSecurityStoreAdapter(securityStore));
// Set Californium Configuration
endpointsBuilder.setConfiguration(serverCoapConfig);

// TODO OSCORE Temporary cli option to deactivate OSCORE
if (!cli.main.disableOscore) {
builder.setEnableOscore(true);
// Create CoAP endpoint
int coapPort = cli.main.localPort == null ? serverCoapConfig.get(CoapConfig.COAP_PORT) : cli.main.localPort;
InetSocketAddress coapAddr = cli.main.localAddress == null ? new InetSocketAddress(coapPort)
: new InetSocketAddress(cli.main.localAddress, coapPort);
if (cli.main.disableOscore) {
endpointsBuilder.addEndpoint(coapAddr, Protocol.COAP);
} else {
endpointsBuilder.addEndpoint(new CoapOscoreBootstrapServerEndpointFactory(
EndpointUriUtil.createUri(Protocol.COAP.getUriScheme(), coapAddr)));
}

// Create CoAP over DTLS endpoint
int coapsPort = cli.main.secureLocalPort == null ? serverCoapConfig.get(CoapConfig.COAP_SECURE_PORT)
: cli.main.secureLocalPort;
InetSocketAddress coapsAddr = cli.main.secureLocalAddress == null ? new InetSocketAddress(coapsPort)
: new InetSocketAddress(cli.main.secureLocalAddress, coapsPort);
endpointsBuilder.addEndpoint(coapsAddr, Protocol.COAPS);

// Create LWM2M server
builder.setEndpointsProvider(endpointsBuilder.build());
return builder.build();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
import org.eclipse.leshan.server.bootstrap.BootstrapFailureCause;
import org.eclipse.leshan.server.bootstrap.BootstrapSession;
import org.eclipse.leshan.server.bootstrap.BootstrapSessionListener;
import org.eclipse.leshan.server.californium.bootstrap.LeshanBootstrapServer;
import org.eclipse.leshan.server.bootstrap.LeshanBootstrapServer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.eclipse.leshan.server.californium.bootstrap.LeshanBootstrapServer;
import org.eclipse.leshan.core.endpoint.Protocol;
import org.eclipse.leshan.server.bootstrap.LeshanBootstrapServer;
import org.eclipse.leshan.server.bootstrap.endpoint.LwM2mBootstrapServerEndpoint;
import org.eclipse.leshan.server.core.demo.json.PublicKeySerDes;
import org.eclipse.leshan.server.core.demo.json.X509CertificateSerDes;

Expand Down Expand Up @@ -83,14 +85,23 @@ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws Se
return;
}

// search coap and coaps port
Integer coapPort = null;
Integer coapsPort = null;
for (LwM2mBootstrapServerEndpoint endpoint : server.getEndpoints()) {
if (endpoint.getProtocol().equals(Protocol.COAP)) {
coapPort = endpoint.getURI().getPort();
} else if (endpoint.getProtocol().equals(Protocol.COAPS)) {
coapsPort = endpoint.getURI().getPort();
}
}

if ("endpoint".equals(path[0])) {
resp.setStatus(HttpServletResponse.SC_OK);
resp.setContentType("application/json");
resp.getOutputStream()
.write(String
.format("{ \"securedEndpointPort\":\"%s\", \"unsecuredEndpointPort\":\"%s\"}",
server.getSecuredAddress().getPort(), server.getUnsecuredAddress().getPort())
.getBytes(StandardCharsets.UTF_8));
resp.getOutputStream().write(String
.format("{ \"securedEndpointPort\":\"%s\", \"unsecuredEndpointPort\":\"%s\"}", coapsPort, coapPort)
.getBytes(StandardCharsets.UTF_8));
return;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@
import org.eclipse.leshan.core.CertificateUsage;
import org.eclipse.leshan.core.SecurityMode;
import org.eclipse.leshan.core.californium.DefaultExceptionTranslator;
import org.eclipse.leshan.core.californium.EndpointContextUtil;
import org.eclipse.leshan.core.californium.ExceptionTranslator;
import org.eclipse.leshan.core.californium.Lwm2mEndpointContextMatcher;
import org.eclipse.leshan.core.californium.identity.IdentityHandler;
Expand All @@ -76,6 +75,7 @@
import org.eclipse.leshan.core.request.Identity;
import org.eclipse.leshan.core.request.exception.TimeoutException;
import org.eclipse.leshan.core.request.exception.TimeoutException.Type;
import org.eclipse.leshan.core.util.X509CertUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -358,7 +358,7 @@ public Identity getIdentity(Message receivedMessage) {
return Identity.rpk(peerAddress, publicKey);
} else if (senderIdentity instanceof X500Principal || senderIdentity instanceof X509CertPath) {
// Extract common name
String x509CommonName = EndpointContextUtil.extractCN(senderIdentity.getName());
String x509CommonName = X509CertUtil.extractCN(senderIdentity.getName());
return Identity.x509(peerAddress, x509CommonName);
}
throw new IllegalStateException(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,6 @@
*/
public abstract class AsyncRequestObserver<T extends LwM2mResponse> extends CoapAsyncRequestObserver {

public AsyncRequestObserver(Request coapRequest, final ResponseCallback<T> responseCallback,
final ErrorCallback errorCallback, long timeoutInMs, ScheduledExecutorService executor) {
this(coapRequest, responseCallback, errorCallback, timeoutInMs, executor, new TemporaryExceptionTranslator());
}

/**
* A Californium message observer for a CoAP request helping to get results asynchronously dedicated for LWM2M
* requests.
Expand Down
Loading