{"action":"created","issue":{"url":"https://api.github.com/repos/eclipse/smarthome/issues/4088","repository_url":"https://api.github.com/repos/eclipse/smarthome","labels_url":"https://api.github.com/repos/eclipse/smarthome/issues/4088/labels{/name}","comments_url":"https://api.github.com/repos/eclipse/smarthome/issues/4088/comments","events_url":"https://api.github.com/repos/eclipse/smarthome/issues/4088/events","html_url":"https://github.com/eclipse/smarthome/issues/4088","id":251159243,"number":4088,"title":"New service for providing SSL/DTLS configuration","user":{"login":"davidgraeff","id":66436,"avatar_url":"https://avatars2.githubusercontent.com/u/66436?v=4","gravatar_id":"","url":"https://api.github.com/users/davidgraeff","html_url":"https://github.com/davidgraeff","followers_url":"https://api.github.com/users/davidgraeff/followers","following_url":"https://api.github.com/users/davidgraeff/following{/other_user}","gists_url":"https://api.github.com/users/davidgraeff/gists{/gist_id}","starred_url":"https://api.github.com/users/davidgraeff/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/davidgraeff/subscriptions","organizations_url":"https://api.github.com/users/davidgraeff/orgs","repos_url":"https://api.github.com/users/davidgraeff/repos","events_url":"https://api.github.com/users/davidgraeff/events{/privacy}","received_events_url":"https://api.github.com/users/davidgraeff/received_events","type":"User","site_admin":false},"labels":[{"id":294421275,"url":"https://api.github.com/repos/eclipse/smarthome/labels/Core","name":"Core","color":"207de5","default":false}],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":12,"created_at":"2017-08-18T07:12:49Z","updated_at":"2017-09-01T10:24:11Z","closed_at":null,"author_association":"CONTRIBUTOR","body":"At the moment there are only web services (REST, PaperUI, etc), that needs configuration for secure connection support. But this may change with further enhancements and added features, like\r\n* the embedded Mqtt Broker ( #3910 ) and\r\n* LwM2M support, which is based on CoAP and therefore ESH would be in the role of a CoAP server ( #4063 ).\r\n\r\nI suggest to provide a central OSGi service to provide SSL/DTLS configuration.\r\n\r\n## Features\r\n* Easy for a consumer of ESH to configure private key and certificate key files in a central place (would allow to integrate this configuration into PaperUI)\r\n* It should support means to create a secure server socket for TCP (TLS) as well as UDP (DTLS).\r\n* Generate a single private/public key and self-signed certificate on first start for out-of-the-box HTTPS and SSL support for all running network server services. \r\n* If the user provides (or changes) the domain configuration, ACME would be used to sign a certificate with Let's Encrypt.\r\n* Although the purpose of this service is to provide a single point for creating TLS sockets, to share the same certificate and keys, it might be required in some environments to create sockets in different contexts with different certificates. For instance management interfaces like PaperUI on one hand (for an internal domain) and extensions with server functionality like an embedded Mqtt broker (for an external domain) on the other hand.\r\n\r\n## API\r\n\r\n```\r\n  interface NetworkServerTlsApi {\r\n     SSLContext createSSLContext(@Nullable String context) throws SecureSocketException;\r\n\r\n     Connector createConnector(@Nullable String context, InetSocketAddress bindToAddress) throws SecureSocketException;\r\n  };\r\n\r\n  @Component(service = NetworkServerTlsApi.class, configurationPolicy = \r\n           ConfigurationPolicy.OPTIONAL, name = \"tls\")\r\n  class NetworkServerTls implements NetworkServerTlsApi {\r\n\r\n     SSLContext createSSLContext(String context) throws SecureSocketException;\r\n\r\n     Connector createConnector(String context, InetSocketAddress bindToAddress) throws SecureSocketException;\r\n  };\r\n```\r\n\r\n* TCP/TLS: The service would provide a `getSSLContext()` method which returns a `SSLContext`. The context can be used to create a `SSLServerSocketFactory` or `SSLEngine` if necessary.\r\n* UDP/DTLS: The use of *Element-Connector* of https://github.com/eclipse/californium/tree/master/scandium-core provides an easy interface. A method `getConnector(InetAddress)` which returns a `Connector` would be provided. (The alternative is to make the user implement his own UDP connection management with a `SSLEngine`, that would require implementing packet reordering, retransmitting, DTLS handshake.)\r\n\r\nThe methods would throw a `SecureSocketException` which wraps the original `Exception` if anything goes wrong.\r\n\r\n## Configuration of the service\r\n\r\nBecause configuration cannot be hierarchically, we use the \"|\" character to map a config value to different contexts. If a requested context is not found, the \"default\" context is used.\r\nThe following configuration parameters are available:\r\n\r\n* javaKeystore=/to/file|default, /another/file|keyStorePassword|otherContext\r\n* privateKeyPassword=password|default\r\n* domain: www.example.com|default\r\n* presharedkey: BASE64KEY|default, ANOTHERBASE64KEY|other\r\n\r\nIf domain is set and valid, ACME will be used to request a certificate signing from Let's Encrypt.\r\nDTLS allows PSK and some IoT devices might only support PSK. \r\n\r\nAdvanced configuration options could be provided for algorithm selection and certificate details like:\r\n* algorithm (\"SHA1WithRSA\")\r\n* keysize  (1024)\r\n* commonName = (\"www.thedomainname.com\")\r\n* organizationalUnit = (\"Eclipse Smarthome\")\r\n* organization = (\"Eclipse\")\r\n* city = \"somecity\"\r\n* state = \"somestate\"\r\n* country = \"DE\"\r\n* validity = 1096; // 3 years\r\n* alias = \"esh\";\r\n\r\n## Implementation\r\n\r\n* `java.security.KeyPairGenerator` (public / private key)\r\n* `sun.security.tools.keytool.CertAndKeyGen` (self signed certificate)\r\n* [ACME library](https://github.com/shred/acme4j)\r\n\r\nExample implementations:\r\n* KeyPairGenerator: https://stackoverflow.com/a/6164414\r\n* CertAndKeyGen: https://stackoverflow.com/a/7304633\r\n* ACME: openhab/openhab-core#92\r\n\r\n## Always valid certificates\r\n\r\nWhen one of the get methods is used, the validity of the certificate is checked, if it is invalid or will be invalid within the next 7 days, a new certificate is generated (and ACME signed).\r\n\r\nA scheduled tasks checks every 14 days (for long running ESH instances) if a certificate needs replacement.\r\n\r\n## Discussion\r\n1. The naming of the Service class and interface\r\n2. The method names and signatures\r\n3. Do we want to allow multiple context and a default context?\r\n4. If a self-signed certificate is generated, what should be used for \"Organisation\", \"City\", \"State\" etc.\r\n5. Should there be a listener interface to notify consumers of replaced/refreshed certificates?\r\n6. Should the user be limited in what formats he can provide to us? A the moment he needs to provide a public key and private key / certificate file (with any supported format). Should we allow the user to provide a single java keystore file, too?"},"comment":{"url":"https://api.github.com/repos/eclipse/smarthome/issues/comments/326546515","html_url":"https://github.com/eclipse/smarthome/issues/4088#issuecomment-326546515","issue_url":"https://api.github.com/repos/eclipse/smarthome/issues/4088","id":326546515,"user":{"login":"kaikreuzer","id":3244965,"avatar_url":"https://avatars3.githubusercontent.com/u/3244965?v=4","gravatar_id":"","url":"https://api.github.com/users/kaikreuzer","html_url":"https://github.com/kaikreuzer","followers_url":"https://api.github.com/users/kaikreuzer/followers","following_url":"https://api.github.com/users/kaikreuzer/following{/other_user}","gists_url":"https://api.github.com/users/kaikreuzer/gists{/gist_id}","starred_url":"https://api.github.com/users/kaikreuzer/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kaikreuzer/subscriptions","organizations_url":"https://api.github.com/users/kaikreuzer/orgs","repos_url":"https://api.github.com/users/kaikreuzer/repos","events_url":"https://api.github.com/users/kaikreuzer/events{/privacy}","received_events_url":"https://api.github.com/users/kaikreuzer/received_events","type":"User","site_admin":false},"created_at":"2017-09-01T10:24:11Z","updated_at":"2017-09-01T10:24:11Z","author_association":"MEMBER","body":"No, groups are only used for a logical grouping within the UI based on the parameters. Every parameter can refer to a groupId it belongs to. But you cannot create new group \"instances\" within a configuration."}}
{"actor":{"display_login":"kaikreuzer"}}