Monday, August 19, 2019

ELK / Elastic stack deployment




Summary:

"ELK" is the acronym for three open source projects: Elasticsearch, Logstash, and Kibana.
Elasticsearch is a search and analytics engine.
Logstash is a server-side data processing pipeline that ingests data from multiple sources simultaneously, transforms it, and then sends it to a "stash" like Elasticsearch.
Kibana lets users visualize data with charts and graphs in Elasticsearch.



Environment:

Virtual machine 1
hostname: elk-master
ip address: 10.152.0.33
installed with : Elasticsearch, filebeat, logstash, kibana



Virtual machine 2 & 3
hostname: elk-data1 and elk-data2
ip address: 10.152.0.34 & 35
installed with : Elasticsearch


 
 
Install Elasticsearch on three nodes:
 

yum install java-1.8.0-openjdk -y
rpm --import  https://artifacts.elastic.co/GPG-KEY-elasticsearch
wget http://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-6.2.3.rpm




rpm --install  elasticsearch-6.2.3.rpm
systemctl daemon-reload
systemctl enable elasticsearch.service 



Edit “elasticsearch.yml” configuration on master node:

node.name: master1
node.data: false
network.host: ["localhost", "10.152.0.33"]

 

Start elasticsearch service:

systemctl start elasticsearch.service
systemctl status elasticsearch.service



Edit “elasticsearch.yml” configuration on data node1:

node.name: data1
node.master: false
network.host: ["localhost", "10.152.0.34"]
discovery.zen.ping.unicast.hosts: ["10.152.0.33"]

Edit “elasticsearch.yml” configuration on data node2:


node.name: data2
node.master: false
network.host: ["localhost", "10.152.0.35"]
discovery.zen.ping.unicast.hosts: ["10.152.0.33"] 


Start elasticsearch service on both data nodes

Verify from less /var/log/elasticsearch/elasticsearch.log :

2019-08-12T08:22:54,971][INFO ][o.e.t.TransportService   ] [data2] publish_address {10.152.0.35:9300}, bound_addresses {127.0.0.1:9300}, {[::1]:9300}, {10.152.0.35:9300}
[2019-08-12T08:22:54,983][INFO ][o.e.b.BootstrapChecks    ] [data2] bound or publishing to a non-loopback address, enforcing bootstrap checks
[2019-08-12T08:22:58,348][INFO ][o.e.c.s.ClusterApplierService] [data2] detected_master {master1}{WRj0WpZfQVW5jiCg5nzvnQ}{-zQAViRrSASrA-94_LeUjg}{10.152.0.33}{10.152.0.33:9300}, added {{master1}{WRj0WpZfQVW5jiCg5nzvnQ}{-zQAViRrSASrA-94_LeUjg}{10.152.0.33}{10.152.0.33:9300},{data1}{ZuBdW3zPSpq0xhQgR8WGnA}{L7P8_nXcRMSGmsaZ7ySouw}{10.152.0.34}{10.152.0.34:9300},}, reason: apply cluster state (from master [master {master1}{WRj0WpZfQVW5jiCg5nzvnQ}{-zQAViRrSASrA-94_LeUjg}{10.152.0.33}{10.152.0.33:9300} committed version [6]])
[2019-08-12T08:22:58,412][INFO ][o.e.h.n.Netty4HttpServerTransport] [data2] publish_address {10.152.0.35:9200}, bound_addresses {127.0.0.1:9200}, {[::1]:9200}, {10.152.0.35:9200}
[2019-08-12T08:22:58,412][INFO ][o.e.n.Node               ] [data2] started 


Verify on all nodes:

curl localhost:9200


curl localhost:9200/_cluster/health?pretty=true


Install Logstash on master node :
 

wget https://artifacts.elastic.co/downloads/logstash/logstash-6.2.3.rpm


rpm --install logstash-6.2.3.rpm
systemctl enable logstash



pipelines.yml configuration:

- pipeline.id: main
  path.config: "/etc/logstash/conf.d/*.conf"


Download and copy sample apache conf file to /etc/logstash/conf.d/ 

wget https://github.com/linuxacademy/content-elastic-log-samples/raw/master/apache.conf

 



systemctl start logstash
systemctl status logstash



Verify logstash installation:

less /var/log/logstash/logstash-plain.log 


Filebeat install and Ship Log Events on master node:
mkdir /var/log/apache2
cd /var/log/apache2
wget https://github.com/linuxacademy/content-elastic-log-samples/raw/master/access.log 

wget https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-6.2.3-x86_64.rpm

rpm --install filebeat-6.2.3-x86_64.rpm
systemctl enable filebeat


 
filebeat  setup
 


vim  /etc/filebeat/ filebeat.yml ( change as mentioned below )

#-------------------------- Elasticsearch output ------------------------------
#output.elasticsearch:
#hosts: ["localhost:9200"]

 

#----------------------------- Logstash output --------------------------------
output.logstash:
hosts: ["localhost:5044"] 





Enable filebeat module:

filebeat modules enable apache2 



Before starting filebeat make sure logstash, elasticsearch, and all nodes are up:

systemctl status logstash
systemctl status elasticsearch
curl localhost:9200/_cluster/health?pretty=true

If all ok than start filebeat:

systemctl start filebeat
systemctl status filebeat




Verify filebeat:

less /var/log/filebeat/filebeat



tail /var/lib/filebeat/registry
curl localhost:9200/_cluster/health?pretty=true



Kibana Install and Visualize on master node :

wget https://artifacts.elastic.co/downloads/kibana/kibana-6.2.3-x86_64.rpm 



rpm --install kibana-6.2.3-x86_64.rpm
systemctl enable kibana



systemctl start kibana
systemctl status kibana


 
Check kibana status from log :

tail /var/log/messages 



Kibana UI access (remote tunnal using ssh) from your laptop running with linux:

ssh root@<public ip>  -L 5601:localhost:5601


Using browser open page: http://localhost:5601 

 

Wednesday, August 7, 2019

Deploy Apache web server using openLDAP and Keycloak token based authentication





Summary :

This post will show about how to integrate Apache web server, openldap with keycloak.


Keycloak is an open source software product to allow single sign-on with Identity Management and Access Management aimed at modern applications and services.

OpenLDAP is a free, open-source implementation of the Lightweight Directory Access Protocol developed by the OpenLDAP Project.

Test environment :

virtual machine1:


  • Installed: Centos 7 , Apache 2.4, openldap
  • Host name: ldap-apache
  • Internal IP: 10.152.0.31
  • Temp Public IP: 35.197.180.204

virtual machine2:

  • Installed: Centos 7 , keycloak
  • Host name: keycloak
  • Internal IP: 10.152.0.29
  • Temp Public IP: 35.244.79.144


Follow below steps on virtual machine1:
 
Install Apache 2.4 web server

yum install httpd -y
systemctl enable httpd.service
systemctl start httpd

To set up the self-signed certificate, we have to install mod_ssl.

yum install mod_ssl -y

Create directory to keep certificate and this directory must be kept strictly private:

mkdir /etc/ssl/private
chmod 700 /etc/ssl/private

Create the SSL key and certificate files using openssl:

openssl req -x509 -nodes -days 365 \
-newkey rsa:2048 -keyout /etc/ssl/private/apache-selfsigned.key \
-out /etc/ssl/certs/apache-selfsigned.crt

 
Create a strong Diffie-Hellman group for to negotiate Perfect Forward Secrecy with clients:

openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048
cat /etc/ssl/certs/dhparam.pem | sudo tee -a /etc/ssl/certs/apache-selfsigned.crt
 
 
Install the OpenLDAP packages:

yum install openldap compat-openldap \
openldap-clients openldap-servers \
openldap-servers-sql openldap-devel -y
 

Enable and initialize the openLDAP service:

systemctl enable slapd
systemctl start slapd

Allow ldap on firewall:
firewall-cmd --add-service=ldap
firewall-cmd --reload

Configuring openLDAP server
Generate the OpenLDAP root password:

slappasswd -h {SSHA} –s your_password
 
Make entry in /etc/hosts file:

vim /etc/hosts
<ip address> ldap-apache.local

Create the openLDAP configuration file:

vim /etc/openldap/slapd.d/conf.ldif

dn: olcDatabase={2}hdb,cn=config
changetype: modify
replace: olcSuffix
olcSuffix: dc=ldap-apache,dc=local

dn: olcDatabase={2}hdb,cn=config
changetype: modify
replace: olcRootDN
olcRootDN: cn=root,dc= ldap-apache,dc=local

dn: olcDatabase={2}hdb,cn=config
changetype: modify
replace: olcRootPW
olcRootPW: {SSHA}8ipIU8QRc24R18BYG2A5kpVP9yaV+EqB

Upload the configuration created to openLDAP with ldapmodify:

ldapmodify -Y EXTERNAL -H ldapi:/// -f /etc/openldap/slapd.d/conf.ldif 
 
 
Configuring the openLDAP Database:
Copy the example database and grant it permissions:


cp /usr/share/openldap-servers/DB_CONFIG.example /var/lib/ldap/DB_CONFIG
chown ldap:ldap /var/lib/ldap/*

Add the rest of the schemas:

ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/cosine.ldif
ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/nis.ldif
ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/inetorgperson.ldif

Create our file named base.ldif

vim /etc/openldap/slapd.d/base.ldif

dn: dc=ldap-apache,dc=local
dc: ldap-apache
objectClass: top
objectClass: domain

dn: cn=root ,dc=ldap-apache,dc=local
objectClass: organizationalRole
cn: root
description: LDAP Manager

dn: ou=users,dc=ldap-apache,dc=local
objectClass: organizationalUnit
ou: Users

dn: ou=Group,dc=ldap-apache,dc=local
objectClass: organizationalUnit
ou: Group

ldapadd -x -W -D "cn=root,dc=ldap-apache,dc=local" -f base.ldif

 
 

Create a user for openLDAP using newuser.ldif

vim /etc/openldap/slapd.d/newuser.ldif

dn: uid=devops,ou=users,dc=ldap-apache,dc=local
objectClass: top
objectClass: account
objectClass: posixAccount
objectClass: shadowAccount
cn: devops
uid: devops
uidNumber: 9999
gidNumber: 100
homeDirectory: /home/devops
loginShell: /bin/bash
gecos: user
userPassword: {crypt}x
shadowLastChange: 17058
shadowMin: 0
shadowMax: 99999
shadowWarning: 7


ldapadd -x -W -D "cn=root,dc=ldap-apache,dc=local" -f newuser.ldif
 
 
 
Give the new user a password:

ldappasswd -s ansible123 -W -D "cn=root,dc=ldap-apache,dc=local" -x "uid=devops,ou=users,dc=ldap-apache,dc=local"
 
 
Test ldap server in order:

ldapsearch -x cn=devops -b dc=ldap-apache,dc=local
 
 
Check client authentication from client machine:
 
Install necessary packages for client authentication:

yum install openldap openldap-clients nss-pam-ldapd

Enable the client system to authenticate using LDAP:

authconfig --enableldap --enableldapauth --ldapserver=ldap-apache.local \
--ldapbasedn="dc=ldap-apache,dc=local" --enablemkhomedir --update

Restart ldap client daemon:

systemctl restart nslcd

Check user ldap entry:

getent passwd devops
 
 


Install Keycloak

Download and unpack Keycloak 4.8.3
 
cd /opt
wget https://downloads.jboss.org/keycloak/4.8.3.Final/keycloak-4.8.3.Final.tar.gz
tar xzf keycloak-4.8.3.Final.tar.gz
 
 
Add keycloak user and change ownership of files

groupadd -r keycloak
useradd -m -d /var/lib/keycloak -s /sbin/nologin -r -g keycloak keycloak
chown keycloak: -R keycloak-4.8.3.Final
 
Restrict access to keycloak-4.8.3.Final/standalone, which will contain sensitive data for the Keycloak server

cd keycloak-4.8.3.Final
sudo -u keycloak chmod 700 standalone
 
 
Install JDK 1.8.0

yum install java-1.8.0-openjdk-devel
 
Added ‘admin’ to ‘/opt/keycloak-4.8.3.Final/standalone/configuration/keycloak-add-user.json’, Restart server to load user.

sudo -u keycloak ./bin/add-user-keycloak.sh --user admin --password KEYCLOAKPASS --realm master
 
 
Modify standalone/configuration/standalone.xml to enable proxying to Keycloak:

sudo -u keycloak ./bin/jboss-cli.sh \
'embed-server,/subsystem=undertow/server\
=default-server/http-listener=default:write-attribute(name=proxy-address-forwarding,value=true)'

sudo -u keycloak ./bin/jboss-cli.sh \
'embed-server,/socket-binding-group=\
standard-sockets/socket-binding=proxy-https:add(port=8443)'

sudo -u keycloak ./bin/jboss-cli.sh \
'embed-server,/subsystem=undertow/server\
=default-server/http-listener=default:write-attribute(name=redirect-socket,value=proxy-https)'
 
 
Start Keycloak Server

Create keycloak.service to start and stop the server:

sudo cat > /etc/systemd/system/keycloak.service <<EOF

[Unit]
Description=KeyCloak Jboss Application Server
After=network.target

[Service]
Type=idle
User=keycloak
Group=keycloak
ExecStart=/opt/keycloak-4.8.3.Final/bin/standalone.sh -b 0.0.0.0
TimeoutStartSec=600
TimeoutStopSec=600

[Install]
WantedBy=multi-user.target
EOF
 
 
start keycloak:

systemctl daemon-reload
systemctl start keycloak
 
 

Install apache to use Keycloak GUI.

Open Keycloak GUI using external IP:

Integrating openLDAP with Keycloak

Console Display Name: ldap
Import Users: ON
Edit Mode: Writeable
Sync Registration: ON
Vendor: Other
Username LDAP attribute: uid
RDN LDAP attribute: uid
UUID LDAP attribute: uid
User Object Classes: inetOrgPerson, organizationalPerson
Connection URL: ldap://35.197.180.204:389      (openLDAP server IP)
Users DN: ou=users,dc=ldap-apache,dc=local
Authentication Type: Simple
Bind DN: cn=root,dc=ldap-apache,dc=local
Bind Credential: XXXXXXX                      (OpenLDAP admin user password)
Search Scope: one level
Use Truststore SPI : Only for ldaps



Configure clients

Client ID: apache
Client Protocol: openid-connect
Access Type: confidential
Valid Redirect URIs: https://35.197.180.204/protected/redirect_uri


Configure ssl.conf on Apache server

Listen 443 https
SSLPassPhraseDialog exec:/usr/libexec/httpd-ssl-pass-dialog
SSLSessionCache         shmcb:/run/httpd/sslcache(512000)
SSLSessionCacheTimeout  300
SSLRandomSeed startup file:/dev/urandom  256
SSLRandomSeed connect builtin
SSLCryptoDevice builtin

#LoadModule auth_openidc_module modules/mod_auth_openidc.so

<VirtualHost _default_:443>

DocumentRoot "/var/www/html"
ServerName ldap-apache

ErrorLog /var/log/httpd/ssl_error_log
TransferLog logs/ssl_access_log
LogLevel warn

SSLEngine on

SSLCertificateFile /etc/ssl/certs/apache-selfsigned.crt
SSLCertificateKeyFile /etc/ssl/private/apache-selfsigned.key

BrowserMatch "MSIE [2-5]" \
         nokeepalive ssl-unclean-shutdown \
         downgrade-1.0 force-response-1.0

CustomLog logs/ssl_request_log \
          "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"

#this is required by mod_auth_openidc
OIDCCryptoPassphrase a-random-secret-used-by-apache-oidc-and-balancer

OIDCProviderMetadataURL https://35.197.180.204:8443/auth/realms/master/.well-known/openid-configuration
OIDCClientID apache
OIDCClientSecret 494ae6ea-f7e3-4888-9928-03b0e3bee328
OIDCRedirectURI https://35.197.180.204/protected/redirect_uri

# maps the prefered_username claim to the REMOTE_USER environment variable
OIDCRemoteUserClaim preferred_username
OIDCSSLValidateServer Off


<Location /protected>
    AuthType openid-connect
    Require valid-user
</Location>

<Directory /var/www/html/protected>
    Options +Includes
    AddOutputFilter INCLUDES .html
</Directory>

</VirtualHost>                                  

SSLCipherSuite EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH
SSLProtocol All -SSLv2 -SSLv3
SSLHonorCipherOrder On

Header always set Strict-Transport-Security "max-age=63072000; includeSubdomains"
Header always set X-Frame-Options DENY
Header always set X-Content-Type-Options nosniff
SSLCompression off 
SSLUseStapling on 
SSLStaplingCache "shmcb:logs/stapling-cache(150000)" 

LDAPLibraryDebug 7
 
 
Verify authentication
 
curl -k -d 'client_id=apache' \
-d 'username=keyuser1' \
-d 'password=test123' \
-d 'grant_type=password' \
-d 'client_secret=494ae6ea-f7e3-4888-9928-03b0e3bee328'\
 'https://35.244.79.144:8443/auth/realms/master/protocol/openid-connect/token' | python -m json.tool  

 
curl -k -u keyuser1 https://35.197.180.204   (prompt you to type the password)