This commit is contained in:
Bill Burke 2016-04-28 16:34:44 -04:00
parent 54981bcd9f
commit 394592068d
8 changed files with 448 additions and 5 deletions

View file

@ -25,10 +25,16 @@
{% if book.community %}
. link:topics/mongo.adoc[Mongo DB Setup]
{% endif %}
. link:topics/cache.adoc[Server Cache]
. link:topics/network.adoc[Network Setup]
.. link:topics/network/bind-address.adoc[Bind Addresses]
.. link:topics/network/ports.adoc[Socket Port Bindings]
.. link:topics/network/https.adoc[HTTPS/SSL Setup]
.. link:topics/network/outgoing.adoc[Outgoing HTTP Requests]
. link:topics/clustering.adoc[Clustering]
. link:topics/cache.adoc[Server Cache Configuration]
{% if book.community %}
. link:topics/proxy.adoc[Keycloak Security Proxy]
. link:topics/proxy.adoc[Keycloak Security Proxy]
{% endif %}
. link:topics/migration.adoc[Upgrading and Migrating]

View file

@ -22,6 +22,14 @@
"datasource": {
"name": "JBoss EAP Administration and Configuration Guide",
"link": "https://access.redhat.com/documentation/en-US/JBoss_Enterprise_Application_Platform/6.4/html/Administration_and_Configuration_Guide/chap-Datasource_Management.html"
},
"network": {
"name": "JBoss EAP Administration and Configuration Guide",
"link": "https://access.redhat.com/documentation/en-US/JBoss_Enterprise_Application_Platform/6.4/html/Administration_and_Configuration_Guide/chap-Network_and_Port_Configuration.html#Configure_interfaces"
},
"socket": {
"name": "JBoss EAP Administration and Configuration Guide",
"link": "https://access.redhat.com/documentation/en-US/JBoss_Enterprise_Application_Platform/6.4/html/Administration_and_Configuration_Guide/sect-Socket_Binding_Groups.html"
}
},
"caching": {

View file

@ -1,3 +0,0 @@
:attributes: yes
Include worked!

20
topics/network.adoc Executable file
View file

@ -0,0 +1,20 @@
[[_network]]
== Network Setup
{{book.project.name}} can run out of the box, with some limitations. For one, all network endpoints bind to +localhost+
so the auth server is really only usable on one local machine. For HTTP based connections, it does not use default ports
like 80 and 443. The SSO protocols that {{book.project.name}} uses all require
SSL/HTTPS or otherwise these protocols have some serious vulnerabilities. HTTPS/SSL is not configured out of the box.
Finally, {{book.project.name}}
may often need to make secure SSL connections to external servers and thus need a trust store set up so that endpoints can
be validated correctly. This chapter discusses all of these things.

View file

@ -0,0 +1,51 @@
=== Bind Addresses
By default {{book.project.name}} binds to the localhost loopback address 127.0.0.1. That's not a very useful default if
you want the authentication server available on your network. Generally, what we recommend is that you deploy a reverse proxy
or load balancer on a public network and route traffic to individual {{book.project.name}} server instances on a private network.
In either case though, you still need to set up your network interfaces to bind to something other than +localhost+.
Setting the bind address is actually quite easy and can be done on the command line with either the _standalone.sh_ or
_domain.sh_ boot scripts discussed in the <<fake/../../operating-mode.adoc#_operating-mode, Choosing an Operating Mode>> chapter.
[source]
----
$ standalone.sh -b 192.168.0.5
----
The +-b+ switch tells the boot script the IP bind address for any public interfaces.
Alternatively, you can edit the profile configuration of your deployment if you do not want to specify this IP address
every time you boot the server. Open up the profile configuration file (_standalone.xml or _domain.xml_ depending on your
<<fake/../../operating-mode.adoc#_operating-mode, operating mode>> and look for the interfaces XML block.
[source,xml]
----
<interfaces>
<interface name="management">
<inet-address value="${jboss.bind.address.management:127.0.0.1}"/>
</interface>
<interface name="public">
<inet-address value="${jboss.bind.address:127.0.0.1}"/>
</interface>
</interfaces>
----
The +public+ interface corresponds to subsystems creating sockets that are available publically. An example of one
of these subsystems is the web layer which serves up the authentication endpoints of {{book.project.name}}. The +management+
interface corresponds to sockets opened up by the management layer of the {{book.appserver.name}}. Specifically the sockets
which allow you to use the +jboss-cli.sh+ command line interface and the {{book.appserver.name}} web console.
In looking at the +public+ interface you see that it has a special string +${jboss.bind.address:127.0.0.1}+. This string
denotes a value +127.0.0.1+ that can be overriden on the command line by setting a Java system property, i.e.:
[source]
----
$ domain.sh -Djboss.bind.address=192.168.0.5
----
+-b+ is actually just a convenience function for this. So, you can either change the bind address value directly in the profile config, or change it on the command line when
you boot up.
NOTE: There's a lot more nifty options when setting up +interface+ definitions. See the link:{{book.appserver.network.link}}[the network interface]
chapter of the {{book.appserver.network.name}}.

189
topics/network/https.adoc Executable file
View file

@ -0,0 +1,189 @@
=== Setting up HTTPS/SSL
WARNING: {{book.project.name}} is not set up by default to handle SSL/HTTPS.
It is highly recommended that you either enable SSL on the {{book.project.name}} server itself or on a reverse proxy in front of the {{book.project.name}} server.
{{book.project.name}} can run out of the box without SSL/HTTPS so long as you stick to private IP addresses like localhost, 127.0.0.1, 10.0.x.x, 192.168.x.x, and 172..16.x.x.
If you try to access {{book.project.name}} out of the box via a non-private IP address you will get an error.
This default behavior is defined by the SSL/HTTPS mode of each {{book.project.name}} realm. This is discussed in more detail in the
link:{{book.adminguide.link}}[{{book.adminguide.name}}], but let's give some context and a brief overview of these modes.
external::
{{book.project.name}} can run out of the box without SSL so long as you stick to private IP addresses like localhost, 127.0.0.1, 10.0.x.x, 192.168.x.x, and 172..16.x.x.
If you try to access {{book.project.name}} from a non-private IP adress you will get an error.
none::
{{book.project.name}} does not require SSL. This should really only be used in development when you are playing around with things.
all::
{{book.project.name}} requires SSL for all IP addresses.
==== Enable HTTPS/SSL with a Reverse Proxy
It is believed that most deployments of {{book.project.name}} will be clustered and will use a reverse proxy or load balancer
in front of {{book.project.name}} server instances.
To enable SSL/HTTPS in this deployment scenario, follow the documentation for your reverse proxy first, before doing any {{book.project.name}} setup.
It is important that you make sure the proxy sets the `X-Forwarded-For` and `X-Forwarded-Proto` headers on the requests made to {{book.project.name}}.
Next you need to enable `proxy-address-forwarding` on the {{book.project.name}} http connector in {{book.project.name}} configuration
Assuming that your reverse proxy doesn't use port 8443 for SSL you also need to configure what port http traffic is redirected to.
. Open _standalone.xml_, _standalone-ha.xml_, or _domain.xml_ file (depends on your <<fake/../../operating-mode.adoc#_operating-mode, operating mode>>).
. First add `proxy-address-forwarding` and `redirect-socket` to the `http-listener` element:
[source]
----
<subsystem xmlns="urn:jboss:domain:undertow:1.1">
...
<http-listener name="default" socket-binding="http"
proxy-address-forwarding="true" redirect-socket="proxy-https"/>
...
</subsystem>
----
Then add a new `socket-binding` element to the `socket-binding-group` element:
[source]
----
<socket-binding-group name="standard-sockets" default-interface="public"
port-offset="${jboss.socket.binding.port-offset:0}">
...
<socket-binding name="proxy-https" port="443"/>
...
</socket-binding-group>
----
Also remember that when running in <<fake/../../operating-mode/domain.adoc#_domain-mode,domain mode>> what +socket-binding-group+
you modify depends on how you have your server groups configured.
==== Enabling SSL/HTTPS for the {{book.project.name}} Server
If you are not using a reverse proxy or load blancer to handle HTTPS traffic for you, you'll need to enable HTTPS
for the {{book.project.name}} server. This involves
. Obtaining or generating a keystore that contains the private key and certificate for SSL/HTTP traffic
. Configuring the {{book.project.name}} server to use this keypair and certificate.
===== Creating the Certificate and Java Keystore
In order to allow HTTPS connections, you need to obtain a self signed or third-party signed certificate and import it into a Java keystore before you can enable HTTPS in the web container you are deploying the Keycloak Server to.
====== Self Signed Certificate
In development, you will probably not have a third party signed certificate available to test a {{book.project.name}} deployment so you'll need to generate a self-signed on.
Generate one is very easy to do with the `keytool` utility that comes with the Java jdk.
[source]
----
$ keytool -genkey -alias localhost -keyalg RSA -keystore keycloak.jks -validity 10950
Enter keystore password: secret
Re-enter new password: secret
What is your first and last name?
[Unknown]: localhost
What is the name of your organizational unit?
[Unknown]: Keycloak
What is the name of your organization?
[Unknown]: Red Hat
What is the name of your City or Locality?
[Unknown]: Westford
What is the name of your State or Province?
[Unknown]: MA
What is the two-letter country code for this unit?
[Unknown]: US
Is CN=localhost, OU=Keycloak, O=Test, L=Westford, ST=MA, C=US correct?
[no]: yes
----
You should answer `What is your first and last name ?` question with the DNS name of the machine you're installing the server on.
For testing purposes, `localhost` should be used.
After executing this command, the `keycloak.jks` file will be generated in the same directory as you executed the `keytool` command in.
If you want a third-party signed certificate, but don't have one, you can obtain one for free at http://cacert.org[cacert.org].
You'll have to do a little set up first before doing this though.
The first thing to do is generate a Certificate Request:
[source]
----
$ keytool -certreq -alias yourdomain -keystore keycloak.jks > keycloak.careq
----
Where `yourdomain` is a DNS name for which this certificate is generated for.
Keytool generates the request:
[source]
----
-----BEGIN NEW CERTIFICATE REQUEST-----
MIIC2jCCAcICAQAwZTELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAk1BMREwDwYDVQQHEwhXZXN0Zm9y
ZDEQMA4GA1UEChMHUmVkIEhhdDEQMA4GA1UECxMHUmVkIEhhdDESMBAGA1UEAxMJbG9jYWxob3N0
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAr7kck2TaavlEOGbcpi9c0rncY4HhdzmY
Ax2nZfq1eZEaIPqI5aTxwQZzzLDK9qbeAd8Ji79HzSqnRDxNYaZu7mAYhFKHgixsolE3o5Yfzbw1
29Rvy+eUVe+WZxv5oo9wolVVpdSINIMEL2LaFhtX/c1dqiqYVpfnvFshZQaIg2nL8juzZcBjj4as
H98gIS7khql/dkZKsw9NLvyxgJvp7PaXurX29fNf3ihG+oFrL22oFyV54BWWxXCKU/GPn61EGZGw
Ft2qSIGLdctpMD1aJR2bcnlhEjZKDksjQZoQ5YMXaAGkcYkG6QkgrocDE2YXDbi7GIdf9MegVJ35
2DQMpwIDAQABoDAwLgYJKoZIhvcNAQkOMSEwHzAdBgNVHQ4EFgQUQwlZJBA+fjiDdiVzaO9vrE/i
n2swDQYJKoZIhvcNAQELBQADggEBAC5FRvMkhal3q86tHPBYWBuTtmcSjs4qUm6V6f63frhveWHf
PzRrI1xH272XUIeBk0gtzWo0nNZnf0mMCtUBbHhhDcG82xolikfqibZijoQZCiGiedVjHJFtniDQ
9bMDUOXEMQ7gHZg5q6mJfNG9MbMpQaUVEEFvfGEQQxbiFK7hRWU8S23/d80e8nExgQxdJWJ6vd0X
MzzFK6j4Dj55bJVuM7GFmfdNC52pNOD5vYe47Aqh8oajHX9XTycVtPXl45rrWAH33ftbrS8SrZ2S
vqIFQeuLL3BaHwpl3t7j2lMWcK1p80laAxEASib/fAwrRHpLHBXRcq6uALUOZl4Alt8=
-----END NEW CERTIFICATE REQUEST-----
----
Send this ca request to your CA.
The CA will issue you a signed certificate and send it to you.
Before you import your new cert, you must obtain and import the root certificate of the CA.
You can download the cert from CA (ie.: root.crt) and import as follows:
[source]
----
$ keytool -import -keystore keycloak.jks -file root.crt -alias root
----
Last step is import your new CA generated certificate to your keystore:
[source]
----
$ keytool -import -alias yourdomain -keystore keycloak.jks -file your-certificate.cer
----
===== Configure {{book.project.name}} to Use the Keystore
Now that you have a Java keystore with the appropriate certificates, you need to configure your {{book.project.name}} installation to use it.
First step is to move the keystore file to the _configuration_ directory of your deployment and to edit the _standalone.xml_, _standalone-ha.xml_ or _domain.xml_ file to use
the keystore and enable HTTPS. (See <<fake/../../operating-mode.adoc#_operating-mode, operating mode>>).
In the standalone or domain configuration file, search for the `security-realms` element and add:
[source]
----
<security-realm name="UndertowRealm">
<server-identities>
<ssl>
<keystore path="keycloak.jks" relative-to="jboss.server.config.dir" keystore-password="secret" />
</ssl>
</server-identities>
</security-realm>
----
Find the element `server name="default-server"` (it's a child element of `subsystem xmlns="urn:jboss:domain:undertow:`) and add:
[source]
----
<subsystem xmlns="urn:jboss:domain:undertow:3.0">
<buffer-cache name="default"/>
<server name="default-server">
<https-listener name="https" socket-binding="https" security-realm="UndertowRealm"/>
...
</subsystem>
----

115
topics/network/outgoing.adoc Executable file
View file

@ -0,0 +1,115 @@
=== Outgoing HTTP Requests
The {{book.project.name}} server often needs to invoke non-browser HTTP requests on the applications and services it secures.
The auth server manages these outgoing connections by maintaining an HTTP client connection pool. There are a few settings
of which you should be aware of. These settings live in the file _keycloak-server.json_ _keycloak-server.json_ file that corresponds to your <<fake/../../operating-mode.adoc#_operating-mode, operating mode>>
By default the setting is like this:
[source,json]
----
"connectionsHttpClient": {
"default": {}
},
----
Possible configuration options are:
establish-connection-timeout-millis::
Timeout for establishing a socket connection.
socket-timeout-millis::
If an outgoing request does not receive data for this amount of time, timeout the connection.
connection-pool-size::
How many connections can be in the pool (128 by default).
max-pooled-per-route::
How many connections can be pooled per host (64 by default).
connection-ttl-millis::
Maximum connection time to live in milliseconds.
Not set by default.
max-connection-idle-time-millis::
Maximum time the connection might stay idle in the connection pool (900 seconds by default). Will start background cleaner thread of Apache HTTP client.
Set to -1 to disable this checking and the background thread.
disable-cookies::
`true` by default.
When set to true, this will disable any cookie caching.
client-keystore::
This is the file path to a Java keystore file.
This keystore contains client certificate for two-way SSL.
client-keystore-password::
Password for the client keystore.
This is _REQUIRED_ if `client-keystore` is set.
client-key-password::
_Not supported yet, but we will support in future versions. Password for the client's key.
This is _REQUIRED_ if `client-keystore` is set.
[[_truststore]]
==== Outgoing HTTPS Request Truststore
When {{book.project.name}} connects out to remote HTTP endpoints over secure https connection, it has to validate the other server's certificate in order to ensure it is connecting to a trusted server.
This is necessary in order to prevent man-in-the-middle attacks.
How certificates are validated is also configured in the _keycloak-server.json_ file that corresponds to your <<fake/../../operating-mode.adoc#_operating-mode, operating mode>>.
`standalone/configuration/keycloak-server.json`.
By default truststore provider is not configured, and any https connections fall back to standard java truststore configuration as described in https://docs.oracle.com/javase/8/docs/technotes/guides/security/jsse/JSSERefGuide.html[
Java's JSSE Reference Guide] - using `javax.net.ssl.trustStore system property`, otherwise `cacerts` file that comes with java is used.
Truststore is used when connecting securely to identity brokers, LDAP identity providers, when sending emails, and for backchannel communication with client applications.
Some of these facilities may - in case when no trusted certificate is found in your configured truststore - fallback to using the JSSE provided truststore.
The default JavaMail API implementation used to send out emails behaves in this way, for example.
You can add your truststore configuration by using the following template:
[source]
----
"truststore": {
"file": {
"file": "path to your .jks file containing public certificates",
"password": "password",
"hostname-verification-policy": "WILDCARD",
"disabled": false
}
}
----
Possible configuration options are:
file::
The value is the file path to a Java keystore file.
HTTPS requests need a way to verify the host of the server they are talking to.
This is what the trustore does.
The keystore contains one or more trusted host certificates or certificate authorities.
Truststore file should only contain public certificates of your secured hosts.
This is _REQUIRED_ if `disabled` is not true.
password::
Password for the truststore.
This is _REQUIRED_ if `disabled` is not true.
hostname-verification-policy::
`WILDCARD` by default.
For HTTPS requests, this verifies the hostname of the server's certificate.
`ANY` means that the hostname is not verified. `WILDCARD` Allows wildcards in subdomain names i.e.
*.foo.com. `STRICT` CN must match hostname exactly.
disabled::
If true (default value), truststore configuration will be ignored, and certificate checking will fall back to JSSE configuration as described.
If set to false, you must configure `file`, and `password` for the truststore.
You can use _keytool_ to create a new truststore file and add trusted host certificates to it:
[source]
----
$ keytool -import -alias HOSTDOMAIN -keystore truststore.jks -file host-certificate.cer
----

57
topics/network/ports.adoc Executable file
View file

@ -0,0 +1,57 @@
=== Socket Port Bindings
The ports for each socket also have a pre-defined default that can be overriden at the command line or within configuration.
To illustrate this configuration, let's pretend you are running in <<fake/../../operating-mode/standalone.adoc#_standalone-mode,standalone mode>> and
open up the _.../standalone/configuration/standalone.xml_. Search for +socket-binding-group+.
[source,xml]
----
<socket-binding-group name="standard-sockets" default-interface="public" port-offset="${jboss.socket.binding.port-offset:0}">
<socket-binding name="management-http" interface="management" port="${jboss.management.http.port:9990}"/>
<socket-binding name="management-https" interface="management" port="${jboss.management.https.port:9993}"/>
<socket-binding name="ajp" port="${jboss.ajp.port:8009}"/>
<socket-binding name="http" port="${jboss.http.port:8080}"/>
<socket-binding name="https" port="${jboss.https.port:8443}"/>
<socket-binding name="txn-recovery-environment" port="4712"/>
<socket-binding name="txn-status-manager" port="4713"/>
<outbound-socket-binding name="mail-smtp">
<remote-destination host="localhost" port="25"/>
</outbound-socket-binding>
</socket-binding-group>
----
+socket-bindings+ define actual socket connections that will be open by the server that covers both the +interface+ (bind address)
that will be used as wel as the port. The ones you will be most interested in are
http::
Defines the port used by {{book.project.name}} HTTP connections
https::
Defines the port used by {{book.project.name}} HTTPS connections
ajp::
The Apache HTTPD server is often used with _mod-cluster_ as a load balancer. AJP is the protocol that is used.
This socket binding defines the port used for the AJP protocol.
management-http::
Defines the HTTP connection used by {{book.appserer.name}} CLI and web console.
When running in <<fake/../../operating-mode/domain.adoc#_domain-mode,domain mode>> locking the socket configurations
is a bit trickier as the example _domain.xml_ file has multiple +socket-binding-groups+ defined. If you scroll down
to the +server-group+ definitions you can see what +socket-binding-group+ is used for each +server-group+.
.domain socket bindings
[source,xml]
----
<server-groups>
<server-group name="load-balancer-group" profile="load-balancer">
...
<socket-binding-group ref="load-balancer-sockets"/>
</server-group>
<server-group name="auth-server-group" profile="auth-server-clustered">
...
<socket-binding-group ref="ha-sockets"/>
</server-group>
</server-groups>
----
NOTE: There's a lot more nifty options when setting up +socket-binding-group+ definitions. See the link:{{book.appserver.socket.link}}[the socket binding group]
chapter of the {{book.appserver.socket.name}}.