Permalink
Browse files

Added SSL HealthStatusProvider and dev-manager.yml compose profile

  • Loading branch information...
richturner committed Oct 3, 2018
1 parent e0d60f7 commit d6dd797aa7bfbcbb1633468d646b38e4e2054c62
@@ -0,0 +1,123 @@
/*
* Copyright 2018, OpenRemote Inc.
*
* See the CONTRIBUTORS.txt file in the distribution for a
* full listing of individual contributors.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.openremote.manager.system;
import org.openremote.container.Container;
import org.openremote.container.ContainerService;
import org.openremote.model.system.HealthStatusProvider;
import org.openremote.model.value.ObjectValue;
import org.openremote.model.value.Value;
import org.openremote.model.value.Values;
import javax.net.ssl.*;
import java.io.IOException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Date;
import java.util.logging.Level;
import java.util.logging.Logger;
import static java.time.temporal.ChronoUnit.DAYS;
import static org.openremote.container.security.IdentityService.*;
import static org.openremote.container.util.MapAccess.getBoolean;
import static org.openremote.container.util.MapAccess.getInteger;
public class SslHealthStatusProvider implements HealthStatusProvider, ContainerService, X509TrustManager {
public static final String NAME = "ssl";
public static final String VERSION = "1.0";
protected static final Logger LOG = Logger.getLogger(SslHealthStatusProvider.class.getName());
protected boolean sslEnabled;
protected String hostname;
protected int port;
protected SSLContext sslContext;
@Override
public void init(Container container) throws Exception {
sslEnabled = getBoolean(container.getConfig(), IDENTITY_NETWORK_SECURE, IDENTITY_NETWORK_SECURE_DEFAULT);
hostname = container.getConfig().getOrDefault(IDENTITY_NETWORK_HOST, IDENTITY_NETWORK_HOST_DEFAULT);
port = getInteger(container.getConfig(), IDENTITY_NETWORK_WEBSERVER_PORT, IDENTITY_NETWORK_WEBSERVER_PORT_DEFAULT);
}
@Override
public void start(Container container) throws Exception {
if (sslEnabled) {
sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, new TrustManager[]{this}, null);
}
}
@Override
public void stop(Container container) throws Exception {
}
@Override
public String getHealthStatusName() {
return NAME;
}
@Override
public String getHealthStatusVersion() {
return VERSION;
}
@Override
public Value getHealthStatus() {
if (!sslEnabled) {
return null;
}
SSLSocketFactory ssf = sslContext.getSocketFactory();
try {
SSLSocket socket = (SSLSocket) ssf.createSocket(hostname, 443);
socket.startHandshake();
X509Certificate[] peerCertificates = (X509Certificate[]) socket.getSession().getPeerCertificates();
X509Certificate serverCert = peerCertificates[0];
Date date = serverCert.getNotAfter();
long validDays = DAYS.between(Instant.now(), date.toInstant());
ObjectValue objectValue = Values.createObject();
objectValue.put("validDays", Values.create(validDays));
return objectValue;
} catch (IOException e) {
LOG.log(Level.WARNING, "Failed to connect to SSL port 443 on host: " + hostname);
return null;
}
}
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return null;
}
}
@@ -1,4 +1,5 @@
org.openremote.manager.system.JvmHealthStatusProvider
org.openremote.manager.system.SslHealthStatusProvider
org.openremote.manager.system.SystemHealthStatusProvider
org.openremote.manager.rules.RulesHealthStatusProvider
org.openremote.manager.agent.AgentHealthStatusProvider
View
@@ -11,4 +11,6 @@ The profiles extend each other, your project should also extend them:
* [dev.yml](/profile/dev.yml) - A transient development stack with all services, uses local bind mounts
* [dev-testing.yml](/profile/dev-testing.yml) - A transient development minimal services stack used to run build tests and work in IDE
* [dev-manager.yml](/profile/dev-manager.yml) - A transient development minimal services stack used to work on the manager in IDE behind the reverse proxy (replicates production setup)
View
@@ -0,0 +1,70 @@
#
# Profile for doing development work on the manager in an IDE; uses proxy container to redirect to host machine.
#
# https://localhost/master
#
# Your changes will be visible live on browser reload or after restart:
#
# - Run the manager in an IDE with the following required environment variables:
# WEBSERVER_LISTEN_HOST=0.0.0.0
# IDENTITY_NETWORK_WEBSERVER_PORT=443
# IDENTITY_NETWORK_SECURE=true
# - Edit files in deployment/manager/
# - Edit files in keycloak/theme/
# - Mount the proxy-data volume in a new container and edit proxy configuration files
# - Change the proxy configuration to a directory mount and edit configuration files
#
version: '2.2'
#networks:
# default:
# driver: bridge
# ipam:
# driver: default
# config:
# - subnet: 172.18.18.0/24
# gateway: 172.18.18.1
volumes:
proxy-data:
postgresql-data:
services:
proxy:
extends:
file: deploy.yml
service: proxy
volumes:
# Store data either in host-mapped directory or a named Docker volume
# - ${DEPLOYMENT_DIRECTORY:-../deployment}/proxy:/deployment
- proxy-data:/deployment
environment:
PROXY_BACKEND_HOST: 'host.docker.internal'
keycloak:
extends:
file: deploy.yml
service: keycloak
build:
context: ../keycloak
dockerfile: dev.Dockerfile
image: openremote/keycloak_dev:latest
# Access directly if needed on localhost
ports:
- "127.0.0.1:8081:8080"
volumes:
- ../keycloak/theme:/opt/jboss/keycloak/themes/openremote
depends_on:
postgresql:
condition: service_healthy
postgresql:
extends:
file: deploy.yml
service: postgresql
# Access directly if needed on localhost
ports:
- "127.0.0.1:5432:5432"
volumes:
- postgresql-data:/data
View
@@ -22,8 +22,8 @@ ARG DOMAINNAME
ENV DOMAINNAME=${DOMAINNAME:-localhost}
ENV TERM xterm
ENV PROXY_LOGLEVEL notice
ENV PROXY_BACKEND_HOST manager
ENV PROXY_BACKEND_PORT 8080
ENV PROXY_BACKEND_HOST=${PROXY_BACKEND_HOST:-manager}
ENV PROXY_BACKEND_PORT=${PROXY_BACKEND_POST:-8080}
RUN mkdir /tmp/lua && cd /tmp/lua \
&& curl -sSL https://www.lua.org/ftp/lua-${LUA_VERSION}.tar.gz -o lua.tar.gz \

0 comments on commit d6dd797

Please sign in to comment.