W podstawowej konfiguracji komunikacja pomiędzy serwerem RHQ oraz agentami monitorującymi poszczególne systemy nie jest ani szyfrowana ani nie ma zaimplementowanych mechanizmów uwierzytelnienia. Może to prowadzić do wielu problemów związanych z bezpieczeństwem systemów:

  • jest możliwe dodanie do infrastruktury monitorującego nowego agenta i jego rejestracja w serwerze RHQ
  • jest możliwe podsłuchanie ruchu pomiędzy serwerem a agentami (i tym samym poznanie konfiguracji maszyn, być może różnych dodatkowych wrażliwych informacji)
  • istnieje możliwość przechwycenie komunikacji pomiędzy serwerem RHQ a agentem monitorującym oraz takie jej zmodyfikowanie, aby uzyskać wpływ na działanie agenta (a trzeba pamiętać, że agent często pracuje na uprawnieniach użytkownika root)

Oczywiście, takie potencjalne problemy mogą prowadzić tylko do jednego wniosku: taką konfigurację można używać tylko w ramach takiej infrastruktury, która jest kontrolowana w 100% i nikt nie powołany nie może z niej korzystać (czyli jak dla mnie to nigdy :D).

W przypadku serwera RHQ problem zabezpieczenia komunikacji oraz uwierzytelniania pomiędzy nim a agentami jest rozwiązana przy użyciu szyfrowania SSL oraz konfiguracji odpowiednich certyfikatów.

W sytuacji, gdy chcemy skonfigurować tylko szyfrowane połączenie (bez uwierzytelniania agentów) wystarczy tylko włączyć używanie protokołu SSL. Odpowiedni certyfikat powinien być już wygenerowany i domyślnie będzie znajdował się w pliku rhq-server/jbossas/server/default/conf/rhq.keystore.

Ja postaram się przedstawić bardziej zaawansowaną konfigurację, gdzie każdy agent także uwierzytelnia się na podstawie odpowiedniego certyfikatu.

Krok 1: Utworzenie certyfikatów SSL

Aby zarówno serwer RHQ jak agent monitorujący potrafiły zidentyfikować się wzajemnie należy zdefiniować odpowiednie certyfikaty SSL, które pozwolą na ich identyfikację. Zarówno serwer RHQ jak i każdy agent musi posiadać swój własny certyfikat. Można tutaj wykorzystać zarówno istniejące certyfikaty (podpisane np. przez jakieś CA), lub też wygenerować własne korzystając z narzędzia keytool.

Poniższe kroki należy wykonać osobno dla serwera RHQ jak i dla każdego agenta monitorującego, modyfikując odpowiednio parametry:

  1. Utworzenie pliku z certyfikatem oraz kluczami publicznym i prywatnym (należy pamiętać, że operację tę należy wykonać zarówno dla serwera jak i dla każdego agenta monitorującego):
    keytool -genkey -dname "CN=nazwa_hosta.example.com" -keystore nazwa_hosta-keystore.dat\
            -validity 3650 -alias nazwa_hosta -keyalg DSA -storetype JKS\
            -keypass haslo_do_klucza_prywatnego -storepass haslo_do_pliku_z_certyfikatem

    Polecenie to utworzy plik o nazwie nazwa_hosta-keystore.dat, w którym zostanie zapisany certyfikat z podaną nazwą maszyny (ważne, należy użyć odpowiedniej nazwy, przypisanej do danej maszyny na której działa agent lub serwer). Certyfikat będzie dostępu przy użyciu nazwy zdefiniowanej przy użyciu parametru alias, czyli w tym przypadku będzie to nazwa_hosta. Klucz prywatny zostanie zabezpieczony hasłem podanym przy użyciu parametru keypass a cały plik hasłem podanym przy użyciu parametru storepass. Certyfikat będzie miał ważność 10 lat (wartość validity). Podane wartości należy zapamiętać, będą one potrzebne dalej.

  2. Zapisanie utworzonego certyfikatu w osobnym pliku (co umożliwi potem jego import to pliku ze wszystkimi certyfikatami):
    keytool -export -keystore nazwa_host-keystore.dat -alias nazwa_hosta\
            -storetype JKS -storepass haslo_do_pliku_z_certyfikatem -file nazwa_hosta-cert
  3. Dodanie certyfikatu do wspólnego pliku z certyfikatami truststore.dat:
    keytool -import -keystore truststore.dat -alias nazwa_hosta\
            -storetype JKS -filenazwa_hosta-cert -noprompt\
            -keypass haslo_do_klucza_prywatnego -storepass haslo_do_pliku_z_certyfikatem

    Dzięki tej operacji dodamy każdy certyfikat do jednego pliku, dzięki czemu będziemy mogli ich używać w celu uwierzytelnienia agentów.

  4. Można w każdej chwili sprawdzić, czy i jakie certyfikaty znajdują się w pliku truststore.dat:
    keytool -list -keystore truststore.dat -storepass haslo_do_pliku_z_certyfikatem\
            -storetype JKS

Po wykonaniu powyższych operacji dla każdego agenta monitorującego i serwera RHQ będziemy dysponowali zarówno zdefiniowanymi dla każdego z nich kluczami prywatnymi jak i plikiem z certyfikatami, dzięki czemu będzie możliwe sprawdzenie ich tożsamości.

Aby ułatwić sobie kolejne kroki, stworzyłem prosty skrypt, które dokładnie wykona wszystkie powyższe kroki dla każdej maszyny. Skrypt należy zapisać w pliku o nazwie create_cert.sh a następnie wywoływać z dwoma parametrami: aliasem klucza oraz pełną nazwą maszyny, czyli np. tak:

./create_cert.sh nazwa_hosta nazwa_hosta.example.com

Skrypt tworzący klucze create_cert.sh:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#!/bin/bash

ALIAS=$1
HOSTNAME=$2

KEYPASS="haslo"
STOREPASS="haslo"
KEYSTORE="${ALIAS}-keystore.dat"
CERTSTORE="${ALIAS}-cert"
TRUSTSTORE="truststore.dat"

echo -n "Create SSL Cert for $ALIAS...   "
keytool -genkey -dname "CN=$HOSTNAME" -keystore ${KEYSTORE}\
        -validity 3650 -alias $ALIAS -keyalg DSA -storetype JKS\
        -keypass ${KEYPASS} -storepass ${STOREPASS}
echo "done"

echo "Export certficate"
keytool -export -keystore ${KEYSTORE} -alias ${ALIAS}\
        -storetype JKS -storepass super_haslo -file ${CERTSTORE}

echo -n "Import certificate to ${TRUSTSTORE}...  "
keytool -import -keystore ${TRUSTSTORE} -alias ${ALIAS}\
        -storetype JKS -file ${CERTSTORE} -noprompt\
        -keypass ${KEYPASS} -storepass ${STOREPASS}
echo "done"

echo "Certificate list"
keytool -list -keystore ${TRUSTSTORE} -storepass ${STOREPASS}\
        -storetype JKS

Oczywiście, należy zdefiniować w skrypcie odpowiednie hasło.

Krok 2: Dystrybucja kluczy

Odpowiednie pliki z kluczami są już utworzone, należy je teraz skopiować na odpowiednie maszyny. Należy skopiować zarówno plik ze wszystkimi certyfikatami oraz specyficzny dla każdego agenta plik z kluczem prywatnym. Należy zwrócić szczególną uwagę na to, aby odpowiednie pliku umieścić na odpowiednich maszynach.

  • Instalacja certyfikatu na serwerze RHQ
    Najprościej będzie umieścić plik z certyfikatem serwera (o nazwie nazwa_hosta-keystore.dat) oraz truststore.dat w katalogu konfiguracyjnym serwera JBoss, w ramach którego pracuje RHQ. Czyli kopiujemy te pliki do katalogu rhq-server/jbossas/server/default/conf. Oczywiście można je umieścić w dowolnym innym miejscu, należy tylko pamiętać aby serwer RHQ miał możliwość ich odczytania.

    Należy jeszcze tak zmienić parametry dostępu do tych plików, aby tylko właściciel procesu RHQ miał możliwość ich odczytu.

  • Instalacje certyfikatu w agencie monitorującym
    Plik z kluczem prywatnym (nazwa_hosta-keystore.dat) oraz truststore.dat należy także umieścić w katalogu conf danego agenta, czyli w katalogu rhq-agent/conf. Dzięki temu, plik ten nie zostanie usunięty podczas procesu automatycznej aktualizacji agenta. Jeszcze raz powtórzę: należy skopiować odpowiedni plik nazwa_hosta-keystore.dat do odpowiedniego agenta.

Krok 3: Konfiguracja serwera RHQ

Teraz czas na odpowiednią konfigurację serwera RHQ, czyli włączenie szyfrowania i uwierzytelnienia. Najlepiej jest wyłączeń serwer przed przystąpieniem do realizacji kolejnych kroków.

Zaczynamy od edycji pliku konfiguracyjnego serwera rhq-server/bin/rhq-server.properties:

  • włączenie korzystania z SSL poprzez zdefiniowania transportu jako sslservlet:
    64
    65
    66
    67
    rhq.communications.connector.transport=sslservlet
    rhq.communications.connector.bind-address=
    rhq.communications.connector.bind-port=
    rhq.communications.connector.transport-params=/jboss-remoting-servlet-invoker/ServerInvokerServlet
  • konfiguracja magazynów z kluczami dla połączeń przychodzących:
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    # Server-side SSL Security Configuration for HTTPS thru Tomcat
    # These are used for browser https: access and for incoming messages from agents over sslservlet transport
    # [you cannot use ${x} variables - see https://jira.jboss.org/jira/browse/JBWEB-74]
    rhq.server.tomcat.security.client-auth-mode=true
    rhq.server.tomcat.security.secure-socket-protocol=TLS
    rhq.server.tomcat.security.algorithm=SunX509
    rhq.server.tomcat.security.keystore.alias=alias_klucza_dla_serwera
    rhq.server.tomcat.security.keystore.file=conf/nazwa_hosta_keystore.dat
    rhq.server.tomcat.security.keystore.password=haslo
    rhq.server.tomcat.security.keystore.type=JKS
    rhq.server.tomcat.security.truststore.file=conf/truststore.dat
    rhq.server.tomcat.security.truststore.password=haslo
    rhq.server.tomcat.security.truststore.type=JKS

    Powyższa konfiguracja umożliwia odszyfrowanie wiadomości przychodzących od agentów. Jednocześnie pozwoli także na uwierzytelnienie tych agentów, ponieważ będzie można odczytać tylko te wiadomości od tych agentów, których klucze publiczne znajdują się w pliku truststore.dat. Jednocześnie będzie można określić, jaki agent dana informację wysłał.

  • konfiguracja magazynów z kluczami dla połączeń wychodzących:
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    # Client-side SSL Security Configuration (for outgoing messages to agents)
    rhq.server.client.security.secure-socket-protocol=TLS
    rhq.server.client.security.keystore.file=${jboss.server.home.dir}/conf/nazwa_hosta-keystore.dat
    rhq.server.client.security.keystore.algorithm=SunX509
    rhq.server.client.security.keystore.type=JKS
    rhq.server.client.security.keystore.password=haslo
    rhq.server.client.security.keystore.key-password=haslo
    rhq.server.client.security.keystore.alias=nazwa_hosta
    rhq.server.client.security.truststore.file=${jboss.server.home.dir}/conf/truststore.dat
    rhq.server.client.security.truststore.algorithm=SunX509
    rhq.server.client.security.truststore.type=JKS
    rhq.server.client.security.truststore.password=haslo
    rhq.server.client.security.server-auth-mode-enabled=true

    Dzięki tej konfiguracji będzie można komunikować się z agentami tak, aby byli oni pewni że nadawcą jest serwer RHQ.

Krok 4: Konfiguracja agenta monitorującego

Ostatnim elementem będzie konfiguracja agenta monitorującego. Istnieją trzy sposoby na jakie można skonfigurować agenta:

  1. Uruchomić konfigurowanie agenta w trybie zaawansowanym, można to zrobić uruchamiając go z następującymi parametrami --cleanconfig --setup --advanced.
  2. Uruchomić agenta w trybie console a następnie wydać polecenie setup advanced.
  3. Bezpośrednio zmodyfikować plik konfiguracyjny conf/agent-configuration.xml i następnie uruchomić agenta z przełącznikiem cleanconfig.

Sposoby pierwszy i drugi wymagają odpowiedzi na szereg pytań, ja przedstawię co należy zmodyfikować w pliku konfiguracyjnym.

  • konfiguracja połączenia z serwerem:
    120
    121
    122
    123
    <entry key="rhq.agent.server.transport"        value="sslservlet" />
    <entry key="rhq.agent.server.bind-port"        value="7443" />
    <entry key="rhq.agent.server.bind-address"     value="rhq-server.example.com" />
    <entry key="rhq.agent.server.transport-params" value="/jboss-remoting-servlet-invoker/ServerInvokerServlet" />
  • konfiguracja łączności agenta monitorującego
    885
    886
    887
    <entry key="rhq.communications.connector.rhqtype"          value="agent" />
    <entry key="rhq.communications.connector.transport"        value="sslsocket" />
    <entry key="rhq.communications.connector.bind-port"        value="16163" />
  • konfiguracja łączności z serwerem – włączenie korzystania z uwierzytelnienia (parametr client-auth-mode) oraz definicja dostępu do certyfikatów:
    931
    932
    933
    934
    935
    936
    937
    938
    939
    940
    941
    942
    <entry key="rhq.communications.connector.security.secure-socket-protocol" value="TLS" />
    <entry key="rhq.communications.connector.security.keystore.file"          value="conf/nazwa_hosta-keystore.dat" />
    <entry key="rhq.communications.connector.security.keystore.algorithm"     value="SunX509" />
    <entry key="rhq.communications.connector.security.keystore.type"          value="JKS" />
    <entry key="rhq.communications.connector.security.keystore.password"      value="haslo" />
    <entry key="rhq.communications.connector.security.keystore.key-password"  value="haslo" />
    <entry key="rhq.communications.connector.security.keystore.alias"         value="nazwa_hasla" />
    <entry key="rhq.communications.connector.security.truststore.file"        value="conf/truststore.dat" />
    <entry key="rhq.communications.connector.security.truststore.algorithm"   value="SunX509" />
    <entry key="rhq.communications.connector.security.truststore.type"        value="JKS" />
    <entry key="rhq.communications.connector.security.truststore.password"    value="haslo" />
    <entry key="rhq.communications.connector.security.client-auth-mode"       value="need" />
  • konfiguracja łączności z klientem – włączenie korzystania z uwierzytelnienia (parametr server-auth-mode-enabled) oraz konfiguracja dostępu do plików z certyfikatami:
    944
    945
    946
    947
    948
    949
    950
    951
    952
    953
    954
    955
    <entry key="rhq.agent.client.security.secure-socket-protocol"   value="TLS" />
    <entry key="rhq.agent.client.security.keystore.file"            value="conf/nazwa_hosta-keystore.dat" />
    <entry key="rhq.agent.client.security.keystore.algorithm"       value="SunX509" />
    <entry key="rhq.agent.client.security.keystore.type"            value="JKS" />
    <entry key="rhq.agent.client.security.keystore.password"        value="haslo" />
    <entry key="rhq.agent.client.security.keystore.key-password"    value="haslo" />
    <entry key="rhq.agent.client.security.keystore.alias"           value="nazwa_hosta" />
    <entry key="rhq.agent.client.security.truststore.file"          value="conf/truststore.dat" />
    <entry key="rhq.agent.client.security.truststore.algorithm"     value="SunX509" />
    <entry key="rhq.agent.client.security.truststore.type"          value="JKS" />
    <entry key="rhq.agent.client.security.truststore.password"      value="haslo" />
    <entry key="rhq.agent.client.security.server-auth-mode-enabled" value="true" />

Oczywiście, należy te wpisy dostosować do własnych potrzeb (w szczególności dotyczy to zdefiniowania odpowiednich haseł). Po wprowadzeniu modyfikacji, należy zatrzymać agenta i uruchomić go przy użyciu następującej komendy:

rhq-agent/bin/rhq-agent.sh --cleanconfig

Spowoduje ona uruchomienie agenta oraz uruchomienie jego procesu konfiguracji. Należy odpowiedzieć na pierwsze pytania, poczekać aż agent połączy się z serwerem i jeżeli nie wystąpiły żadne błędy to wszystko powinno działać OK.

Jeżeli wystąpiły błędy, to trzeba je zanalizować i próbować zmienić wpisy w pliku konfiguracyjnym. Jeżeli pierwsze uruchomienie powiodło się, można już uruchomić agenta przy użyciu skryptu uruchomieniowego.

Pozostaje teraz skonfigurowanie pozostałych agentów i możemy się cieszyć szyfrowaną transmisją między serwerem RHQ a agentami.

Źródła