11/29/2017

Direct Rules for Firewalld

Direct Rules for Firewalld

Why Firewalld Direct Rules?

  1. You need more power than what's available with simply adding or removing services
  2. You want to make exceptions for certain hosts.
  3. You want to make exceptions for certain networks.
  4. You have experience with iptables, ip6tables, or ebtables commands needed for direct rules.
The documentation for Direct Rules can be found with:

man firewalld.direct

The basic structure of a rule is:

ipv - "ipv4|ipv6|eb" # If rule is iptables, ip6tables or ebtables based
table -"table" # Location of rule in filter, mangle, nat, etc. table
chain - "chain" # Location of rule in INPUT, OUTPUT, FORWARD, etc. chain
priority - "priority" # Lower priority value rules take precedence over higher priority values
rule

If you have with the iptables command, then you should feel comfortable with basic Direct Rules.  Instead of starting with "iptables", the command will start with "firewall-cmd --permanent --direct --add-rule" followed by the rule that follows the basic structure above.

One simple firewall scenario

The web server service should only be available to one host and reject all others. Both actions should be logged.

Whitelist one host for one service

In this scenario, the host 10.0.0.107 would be allowed access to the http service, but any other host (the 0.0.0.0/0 network) would be rejected. Beware, any reject or drop rules are evaluated before accept rules.

firewall-cmd --permanent --direct --add-rule \
ipv4 \
filter \
INPUT 0 \
-p tcp --dport 80 -s 10.0.0.107 \
-j LOG --log-prefix "DIRECT HTTP ACCEPT"  


firewall-cmd --permanent --direct --add-rule \
ipv4 \
filter \
INPUT 1 \
-p tcp --dport 80 -s 10.0.0.107 \
-j ACCEPT


firewall-cmd --permanent --direct --add-rule \
ipv4 \
filter \
INPUT 2 \
-p tcp --dport 80 \
-j LOG --log-prefix "DIRECT HTTP REJECT"    

firewall-cmd --permanent --direct --add-rule \
ipv4 \
filter \
INPUT 3 \
-p tcp --dport 80 -s 10.0.0.107 \
-j REJECT --reject-with icmp-host-unreachable

Since these rules were added with the --permanent option, they are not active in the runtime rules, yet. So, to make the permanent rules active, use the --reload option.

firewall-cmd --reload
I discovered that you have to "get" the rules instead of querying for a "list" of them:

firewall-cmd --direct --get-all-rules

ipv4 filter INPUT 0 -p tcp --dport 80 -s 10.0.0.107 -j LOG --log-prefix 'DIRECT HTTP ACCEPT'
ipv4 filter INPUT 1 -p tcp --dport 80 -s 10.0.0.107 -j ACCEPT
ipv4 filter INPUT 2 -p tcp --dport 80 -j LOG --log-prefix 'DIRECT HTTP REJECT'
ipv4 filter INPUT 3 -p tcp --dport 80 -s 10.0.0.107 -j REJECT --reject-with icmp-host-unreachable


Rich rules for Firewalld

Rich rules for Firewalld

Why Firewalld Rich Rules?


  1. You need more power than what's available with simply adding or removing services
  2. You want to make exceptions for certain hosts.
  3. You want to make exceptions for certain networks.
  4. You don't experience with iptables command needed for direct rules.

Basic Documentation

The man page for firewall-cmd does not cover rich rules. To get the man page about them use:

   man firewalld.richlanguage to view the details like... 

       A rule is part of a zone. One zone can contain several rules. If some rules
       interact/contradict, the first rule that matches "wins".

       General rule structure

           rule
             [source]
             [destination]
             service|port|protocol|icmp-block|icmp-type|masquerade|forward-port|source-port
             [log]
             [audit]
             [accept|reject|drop|mark]


Summary Firewalld Rich Rules common options:

rule [family="ipv4|ipv6"] 
source [not] address="address[/mask]"|mac="mac-address"|ipset="ipset"
destination [not] address="address[/mask]"
port port="port value" protocol="tcp|udp"
log [prefix="prefix text"] [level="log level"] [limit value="rate/duration"]
accept [limit value="rate/duration"]
reject [type="reject type"] [limit value="rate/duration"]
drop [limit value="rate/duration"]
mark set="mark[/mask]" [limit value="rate/duration"]

Working with reject action

Actually, I think for the reject action above, the type argument is mandatory. For the reject action, the type must use one of: 

icmp-host-prohibited, host-prohib, icmp-net-unreachable, net-unreach, icmp-host-unreachable, host-unreach, icmp-port-unreachable, port-unreach, icmp-proto-unreachable, proto-unreach, icmp-net-prohibited, net-prohib, tcp-reset, tcp-rst, icmp-admin-prohibited, admin-prohib 

Two simple firewall scenarios

Let's take two services running on a host, a web server and a dns server. The web server service should only be available to one host and reject all others. The dns server service should be available to all hosts except one, and drop all others.

Whitelist one host for one service

In this scenario, the host 10.0.0.107 would be allowed access to the http service, but any other host (the 0.0.0.0/0 network) would be rejected. Beware, any reject or drop rules are evaluated before accept rules.

firewall-cmd --add-rich-rule='
rule family=ipv4 
source address="10.0.0.107" 
service name="http" 
log prefix="RICH HTTP ACCEPTED" 
accept' 

firewall-cmd --add-rich-rule='
rule family=ipv4 
source NOT address="10.0.0.107" 
service name="http" 
log prefix="RICH HTTP REJECTED " 
reject type="icmp-host-prohibited"

Monitoring the RICH HTTP firewall log

To see attempts to connect either be accepted or rejected, try to access the web server from the host 10.0.0.107 and 10.0.0.108, respectively after executing the following on a host like 10.0.0.5 with the httpd service running:

tail -f /var/log/messages | grep 'RICH HTTP '

Blacklist one host for one service

In this scenario, the host 10.0.0.107 would be blacklisted from accessing the DNS service, and its attempts to connect will be dropped. All other hosts will be accepted for access:

firewall-cmd --add-rich-rule='
rule family=ipv4 
source address="10.0.0.107" 
service name="dns" 
log prefix="RICH DNS DROPPED " 
drop'

firewall-cmd --add-rich-rule='
rule family=ipv4 
source address="0.0.0.0/0" 
service name="dns" 
log prefix="RICH DNS ACCEPTED " 
accept' 

Monitoring the RICH DNS firewall log

To see attempts to connect to the DNS server either be accepted or rejected, try to access the dns server from the host 10.0.0.107 and 10.0.0.108, respectively after executing the following on a host like 10.0.0.5 with the httpd service running:

tail -f /var/log/messages | grep 'RICH DNS '

Rich Rule Persistence

For the rules entered above to be maintained across restarting firewalld or the system, they need to be either added again with the --permanent option, or you can use the --runtime-to-permanent option to preserve the rules in the default zone (You can also create rich rules in other zones using the --zone option).


firewall-cmd --runtime-to-permanent

After the above command is executed the rules are saved to a file like /etc/firewalld/zones/public.xml based upon the default active zone. Although you can use the firewall-cmd --remove-rich-rules option to delete rich rules that you no longer want, you can also edit the zone xml file directly, and then use:

firewall-cmd --reload

Other Useful firewall-cmd commands:

firewall-cmd --get-active-zones
firewall-cmd --list-all
firewall-cmd --list-all-zones
firewall-cmd --list-rich-rules
firewall-cmd --help


11/26/2017

Installing Kubernetes on CentOS 7 with kubeadm

Kubernetes on CentOS 7

Prepare CentOS 7 for Kubernetes for Master and Worker

Disable SELinux Enforcement

Update the file /etc/selinux/config:

SELINUX=permissive

To avoid rebooting to have that become effective, execute:

setenforce 0


Disable swap

Swap must be disabled for the kubeadm init process to complete. Edit the /etc/fstab file and comment out the swap entry. For example:

In the file /etc/fstab comment out the line(s) containing swap:
#/dev/sda5 swap                    swap    defaults        0 0

To avoid rebooting to have that become effective, execute:

swapoff -a


Configure the firewall services



Create the k8s-master.xml and k8s-worker.xml files


cd /etc/firewalld/services

wget \
https://raw.githubusercontent.com/wrightrocket/k8s-firewalld/master/k8s-master.xml

wget \
https://raw.githubusercontent.com/wrightrocket/k8s-firewalld/master/k8s-worker.xml



Reload the firewall 


To make the new services available for use, the firewall must be reloaded. Execute the following to avoid rebooting:

firewall-cmd --reload

Apply the firewall rules


On the master execute:

firewall-cmd --add-service k8s-master 
firewall-cmd --add-service k8s-master --permanent

On worker nodes execute:
firewall-cmd --add-service k8s-worker
firewall-cmd --add-service k8s-worker --permanent


Create Kubernetes Yum Repository

cat << EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg
        https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
EOF


Install the packages


yum install -y docker kubelet kubeadm kubectl 

Configure the Kubelet service

Add to the /etc/systemd/system/kubelet.service.d/10-kubeadm.conf file $KUBELET_KUBECONFIG_ARGS:

--runtime-cgroups=/systemd/system.slice --kubelet-cgroups=/systemd/system.slice

Reload systemd
For the updated kubelet configuration to be recognized, systemd must be reloaded.

systemctl daemon-reload
systemctl enable kubelet
systemctl restart kubelet

Enable the Docker service

systemctl enable docker --now

Create the needed sysctl rules

cat  > /etc/sysctl.d/k8s.conf <
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
HERE

Apply the sysctl rules

sysctl --system

Installing Kubernetes on CentOS 7 on Master

Initialize the Master Node

Since the flannel network will be used with the kubernetes cluster, the --pod-network-cidr option is used to specify the network that will be used, which will match the network in the kube-flannel.yml file applied later.

kubeadm init --pod-network-cidr 10.244.0.0/16

Configure kubectl for user

mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

Verify node is Ready

kubectl get nodes

NAME           STATUS    ROLES     AGE       VERSION
kate.lf.test   Ready     master    2m        v1.8.3


Verfify kube-system Pods are Ready

kubectl get pods --all-namespaces

NAMESPACE     NAME                                   READY     STATUS    RESTARTS   AGE
default       website-7cd5577444-xfp6s               1/1       Running   0          8m
kube-system   etcd-kate.lf.test                      1/1       Running   4          2d
kube-system   kube-apiserver-kate.lf.test            1/1       Running   5          2d
kube-system   kube-controller-manager-kate.lf.test   1/1       Running   7          2d
kube-system   kube-dns-545bc4bfd4-9tgcv              3/3       Running   14         2d
kube-system   kube-flannel-ds-gbzhp                  1/1       Running   2          1d
kube-system   kube-proxy-l9fts                       1/1       Running   3          2d
kube-system   kube-scheduler-kate.lf.test            1/1       Running   6          2d

Retrieve the Configuration for Flannel

wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml

Apply the Flannel Network 

kubectl apply -f kube-flannel

Installing Kubernetes on CentOS 7 on a Worker

Retrieve the Token

On the Master node, retrieve the token that was generated during the installation.

kubeadm token list

TOKEN     TTL       EXPIRES   USAGES    DESCRIPTION   EXTRA GROUPS


If no token is shown , then a new token can be generated. The original installation token expires after one day, but the option --ttl 0 can be used with kubeadm token create to create a token that never expires.

kubeadm token create --ttl 0
33d628.3d1c0bf58ab1a68a


Join the Cluster

On the Worker node, join the cluster. Use the token from the previous step and the IP address of your master node.

kubeadm join --token 33d628.3d1c0bf58ab1a68a 10.0.0.108:6443

Install the flannel package

yum -y install flannel

This package is installed after the flannel network so that the flanneld and docker services will start correctly.

Configure flannel

The etcd prefix value in the file /etc/sysconfig/flanneld is not correct, so the flanneld will fail to start as it is not able to retrieve the prefix given. The value of FLANNEL_ETCD_PREFIX must changed to the following:

#FLANNEL_ETCD_PREFIX="/atomic.io/network"
FLANNEL_ETCD_PREFIX="/coreos.com/network"

Enable and start flanneld

systemctl enable flanneld --now

This enables and starts flanneld. Since docker has a dependency on flanneld, it will also be restarted, so it may take a while.

Configure kubectl for user

mkdir -p $HOME/.kube


sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config


Verify Nodes are Ready

It may take several minutes for all the nodes to get to "Ready" status.

kubectl get nodes

NAME           STATUS    ROLES     AGE       VERSION
kate.lf.test   Ready     master    10d       v1.8.3
kave.lf.test   Ready         4d        v1.8.3



11/13/2017

Docker Basics

Docker Basics


This post isn't going to be about everything Docker, it is just about the basics of using Docker in a Linux operating system.  In Fedora 25, I used the following commands.


Getting Started with Docker

First, you need to get Docker software installed on your Linux system using your package manager.
In Fedora, I executed the following command to install docker:
dnf install docker
or in SUSE:
zypper install docker
or in Debian/Ubuntu:
apt-get install docker

Next, you need to start and enable the docker service.

systemctl start docker
systemctl enable docker

To verify that your installation is successful execute:

docker run hello-world

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://cloud.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/engine/userguide/

Exploring Docker


If all went well, then you can begin to search for images that you might want to use like "minimal", "centos", "suse", "ubuntu" or "mariadb".

docker search minimal

If you execute the docker command without any sub-commands, then it will display a summary of the usage of the docker command:


docker
Usage: docker [OPTIONS] COMMAND [arg...]
       docker [ --help | -v | --version ]

A self-sufficient runtime for containers.

Options:

  --config=~/.docker              Location of client config files
  -D, --debug                     Enable debug mode
  -H, --host=[]                   Daemon socket(s) to connect to
  -h, --help                      Print usage
  -l, --log-level=info            Set the logging level
  --tls                           Use TLS; implied by --tlsverify
  --tlscacert=~/.docker/ca.pem    Trust certs signed only by this CA
  --tlscert=~/.docker/cert.pem    Path to TLS certificate file
  --tlskey=~/.docker/key.pem      Path to TLS key file
  --tlsverify                     Use TLS and verify the remote
  -v, --version                   Print version information and quit

Commands:
    attach    Attach to a running container
    build     Build an image from a Dockerfile
    commit    Create a new image from a container's changes
    cp        Copy files/folders between a container and the local filesystem
    create    Create a new container
    diff      Inspect changes on a container's filesystem
    events    Get real time events from the server
    exec      Run a command in a running container
    export    Export a container's filesystem as a tar archive
    history   Show the history of an image
    images    List images
    import    Import the contents from a tarball to create a filesystem image
    info      Display system-wide information
    inspect   Return low-level information on a container, image or task
    kill      Kill one or more running containers
    load      Load an image from a tar archive or STDIN
    login     Log in to a Docker registry.
    logout    Log out from a Docker registry.
    logs      Fetch the logs of a container
    network   Manage Docker networks
    node      Manage Docker Swarm nodes
    pause     Pause all processes within one or more containers
    port      List port mappings or a specific mapping for the container
    ps        List containers
    pull      Pull an image or a repository from a registry
    push      Push an image or a repository to a registry
    rename    Rename a container
    restart   Restart a container
    rm        Remove one or more containers
    rmi       Remove one or more images
    run       Run a command in a new container
    save      Save one or more images to a tar archive (streamed to STDOUT by default)
    search    Search the Docker Hub for images
    service   Manage Docker services
    start     Start one or more stopped containers
    stats     Display a live stream of container(s) resource usage statistics
    stop      Stop one or more running containers
    swarm     Manage Docker Swarm
    tag       Tag an image into a repository
    top       Display the running processes of a container
    unpause   Unpause all processes within one or more containers
    update    Update configuration of one or more containers
    version   Show the Docker version information
    volume    Manage Docker volumes
    wait      Block until a container stops, then print its exit code

Run 'docker COMMAND --help' for more information on a command.

For the next recommended test, try out the ubuntu image.  To start the bash shell inside the ubuntu container, execute:

docker run -it ubuntu bash

root@bb21045eda79:/#

To see the this container running from another terminal execute:

docker ps

CONTAINER ID    IMAGE            COMMAND   CREATED            STATUS              PORTS        NAMES
bb21045eda79        ubuntu              "bash"              8 seconds ago       Up 5 seconds                            hopeful_fermi

The name shown "hopeful_fermi" was automatically generated. Replace this name with the name automatically generated by your system in the command below.

To stop this container  from another terminal execute:

docker stop hopeful_fermi
hopeful_fermi

To start a container based upon the ubuntu image with a specific name like "zesty" execute:

docker run -it --name "zesty" ubuntu bash
root@2658f64e637a:/#

To see the this container running from another terminal execute:

docker ps

CONTAINER ID    IMAGE            COMMAND   CREATED            STATUS              PORTS        NAMES

2658f64e637a        ubuntu              "bash"              37 seconds ago      Up 35 seconds                          zesty


Saving Docker Container Changes

What if you've customized your docker container, and you want to launch the customized changes the next time you use it?One technique that can be used with the docker is the commit sub-command to save the changes to a new container. 

Start running a docker container for the mariadb database mapping with -p local:remote and -e ENVIRONMENT_VARIABLE=value:

docker run  -p 3306:3306 -e MYSQL_ROOT_PASSWORD='secret' mariadb

The name that you see for your container may not be what you want it to be when you use the command to view running processes. You can use the name sub-command or pass a --name option when beginning to run the container.

docker ps

CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                              NAMES
0675838efe90             mariadb              "docker-entrypoint.sh"   46 minutes ago      Up 46 minutes       0.0.0.0:3306->3306/tcp   wright-mariadb


You may want to rename the container based upon the image like:

docker rename 0675838efe90 colorsdb

Then, you can save the changes to your container with a docker commit command:

docker commit colorsdb

For more details, you can look at the help available for the commit command.

docker commit --help

Usage:  docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
Create a new image from a container's changes
Options:  -a, --author string    Author (e.g., "John Hannibal Smith ")  -c, --change value     Apply Dockerfile instruction to the created image (default [])      --help             Print usage  -m, --message string   Commit message  -p, --pause            Pause container during commit (default true)


To stop running the container, you can now use:

docker stop colorsdb

To start the container with the changes that have been committed to it after it has been stopped, you can use:

docker start colorsdb


Using Docker Containers


So now what? You can download and run an image and create a container or execute commands inside of it. You might be wondering like me, how do you use this container? 

In order to access to use some containers, you can access these containers through ports they expose to the host system or to other containers.



To connect to the container that has exposed port 3306 on the localhost to map to 3306 on the remote the machine, you could execute:


mysql -h localhost -P 3306 --protocol=tcp -p







4/24/2017

Solving CA Certificate Errors

Solving CA Certificate Errors


Do you get an CA Certificate error of "unable to get local issuer certificate" or
"certificate verify failed?"

Copy the certificate to /usr/local/share/ca-certificates 
or
/usr/share/ca-trust

Then execute:
update-ca-certificates
or
update-ca-trust

Read the man page on update-ca-certificates for more details.

10/07/2016

Android Studio 2.2 Ready for Prime Time!

Android Studio 2.2 Ready for Prime Time!

I've tried Android Studio several times over the last year or so, but each time, it was not ready for prime time. By this statement, I mean that by default, it was so broken so that it was unable to build a new unmodified project. To be honest, Eclipse for Android Developers has been similarly broken, and was broken at the time I wrote this.

Recently, Google released Android Studio 2.2,0.12 and it is ready to build apps for API 24 right out of the box. I'm excited about being able to start developing without having to fight to get my build environment working!

8/23/2016

JOOSAN NVR Admin Password Reset

JOOSAN NVR Admin Password Reset

I purchased a 4 Camera Wireless Surveillance NVR kit from CCTV Systems on Amazon in 2016. Somehow the password for the admin account stopped working, and I don't remember changing it. It had better not happen again, or I might return the unit! Without the admin password, I was unable to change any settings on the device.

When I got stuck without being able to login as admin, thankfully the vendor, CCTV Systems was able to tell me how to reset the admin password. Apparently, if they know the date on your unit, then they can generate a password for admin account that will allow a login, which is a bit scary. Maybe my unit won't be running with the actual date...

When I told them that the date had been reset to 1970/01/01 because I had unplugged the battery from the unit in trying to reset the system, they gave me a different solution. Here is what I was told via email:

This date is not normal.
So now you can on the screen of login,and input the wrong password,when it pop-up a message with invalid password,you can right-click,left-click  with the mouse,cycle times.Then it will let you reset the user and password.

This led to me developing the following procedure to reset the admin password for the JOOSAN NVR:

  1. Unplug the unit.
  2. Open the top cover by unscrewing the necessary screws.
  3. Remove the battery from the unit by pulling it up.
  4. Replace the battery and cover after a minute or two.
  5. Power the unit back on and wait until system is initialized.
  6. Right-click to try System Setup.
  7. Attempt to login as admin with the wrong password.
  8. Alternately, right-click and left-click several times. 
  9. A dialog should pop up and let you reset the admin password back to nothing or being blank.

Here are some steps you will want to perform after resetting the system.


Reset the time:

  1. Right-click to go to System setup.
  2. Click General setup on the top, Time setup on the left, and set up the time in the middle.
  3. Be sure to click Apply before you click OK.

Reset the admin user password:

  1. Right-click to go to System setup.
  2. Click System Admin on the top, User management on the left.
  3. Select the row of the admin user.
  4. Click the Set password button.
  5. Type the old admin password or leave it blank after resetting the system.
  6. Type and repeat the new password.
  7. Click the Ok button.
Since resetting the admin password, I have also created an extra super user account to avoid being locked out in the future by using System Admin, User management, Add user. In addition, I created an account for family members that can be used for just viewing the cameras.

I hope this helps you! Best wishes!

8/21/2016

LDAP: On-Line Configuration (OLC) and Static slapd.conf

LDAP: On-Line Configuration (OLC) and Static slapd.conf


Installing OpenLDAP 

To install both the client and server packages on RHEL/CentOS 7:

yum -y install openldap-servers openldap-clients

Enable and start the service:

systemctl enable slapd
systemctl start slapd


OLC

Until OpenLDAP 2.3, an OpenLDAP server was configured by editing a /etc/openldap/slapd.conf. This required that the server had to be restarted to make changes to the server configuration.

With OpenLDAP 2.3+ On-Line Configuration of the server was made possible by adding a Directory Information Tree (DIT) called cn=config.

To view the OLC, you can execute as root:

ldapsearch -H ldapi:/// -Y EXTERNAL -b cn=config


olcSuffix, olcRootDN and olcRootPW
The first step in configuring your domain will be to set the suffix for the DIT for your domain, the information about the administrative user's Distinguished Name (DN) and password. The olcRootDN must end with the same suffix specified by the olcSuffix.

Create an LDIF file with the follow contents updated for your own domain, and the olcRootPW generated by executing slappasswd. This information can then be modified on the LDAP server with the following command:

ldapmodify -H ldapi:/// -Y EXTERNAL -f olc-root.ldif

olc-root.ldif:


dn:  olcDatabase={2}hdb,cn=config
changetype: modify
replace: olcSuffix
olcSuffix: dc=samba,dc=org
-
replace: olcRootDN
olcRootDN: cn=admin,dc=samba,dc=org
-
replace: olcRootPW
olcRootPW: {SSHA}GTeZbB7rpAMtPHVNxBZFN6ZFhwe+kINv

Configuring Logging with OLC

ldapmodify -H ldapi:/// -Y EXTERNAL -f olc-logging.ldif

olc-logging.ldif:

dn: cn=config
changetype: modify
add: olcLogFile
olcLogFile: /var/log/slapd.log
-
add: olcLogLevel
olcLogLevel: filter config acl



Configuring Organizational Units(OUs)

If want to configure the LDAP Directory to contain information for authenticating users of your domain, then you will need to create the following dcObject, organization, and organization unit entries. The simpleSecurityObject and organizationalRole entry can be used as a administrator account for the suffix. Entries for this suffix will need to be modified using the DN of this LDAP Administrator entry.

Create an LDIF file with the follow contents updated for your own domain, and then update the LDAP server by executing:

ldapadd -D cn=admin,dc=samba,dc=org -w secret -f olc-domain.ldif

olc-domain.ldif:

dn: dc=samba,dc=org
objectClass: top
objectClass: dcObject
objectClass: organization
o: samba.org
dc: samba

dn: cn=admin,dc=samba,dc=org
objectClass: simpleSecurityObject
objectClass: organizationalRole
cn: admin
description: LDAP administrator
userPassword: secret

dn: ou=users,dc=samba,dc=org
objectClass: top
objectClass: organizationalUnit
ou: users

dn: ou=groups,dc=samba,dc=org
objectClass: top
objectClass: organizationalUnit
ou: groups

dn: ou=idmap,dc=samba,dc=org
objectClass: top
objectClass: organizationalUnit
ou: idmap

dn: ou=computers,dc=samba,dc=org
objectClass: top
objectClass: organizationalUnit
ou: computers


Configuring OLC Schema

To discover which schema have been added to your server, you can execute the following query:

ldapsearch -H ldapi:/// -Y EXTERNAL -b cn=schema,cn=config cn

Most installations will only have the "core" schema installed. The others that are often added for use in authentication by executing the following commands in order, otherwise an attribute that may be defined in one schema that cannot be referenced will prevent adding another schema. 

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

ldapadd -H ldapi:/// -Y EXTERNAL -f /etc/openldap/schema/corba.ldif

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

ldapadd -H ldapi:/// -Y EXTERNAL -f \
/usr/share/doc/samba-4.2.3/LDAP/samba.ldif





7/27/2016

Help for Vi or Vim in Python

Help for Vi or Vim in Python

Using vi or vim can be tricky to be sure! It has syntax color coding for Python, but the way it handles tabs and spaces can be problematic. It's also nice to be able to control the indentation of the text in the editor. The following settings can help with these issues.

Hidden Tabs and Spaces

Using :set list can display the hidden tabs and spaces that might cause you problems.

Custom Vim Configuration

If you want to make vi or vim your primary editor, then you can use a custom resource ~/.vimrc file to store preferences that will make using it easier with Python.


~/.vimrc Comments

One thing to note is that comments in a vi or vim resource file are different from most configuration files. To add a comment to the custom file you use the quote (") as shown below.

Python ~/.vimrc Example

As someone who writes Python frequently, I like my tab key to indent four spaces, and convert the tabs into a spaces. I like to also be able to select text to indent or un-indent it for Python levels of scope. Here are the settings I add to my ~/.vimrc file:

set expandtab " expand tabs to spaces
set tabstop=4 " use four spaces for each tab
set shiftwidth=4 " select with V and use  < or > to shift for spaces

In order to take advantage of the shiftwidth, you can press V and then select the lines to indent, or un-indent. Pressing < or > will un-indent or indent the selected lines.

1/31/2016

How to change the UUID of a VirtualBox Image in Windows

Set your path to include the installation directory for VirtualBox, typically C:\Program Files\Oracle\VirtualBox, or else you will need to prefix the following command with that path.

VBoxManage internalcommands sethduuid CentOS.vdi

12/28/2015

Windows Command Line

Windows Command Line

FINDSTR

The FINDSTR command works almost like grep, so it can be useful with other commands:

ASSOC | FINDSTR Python

A couple of Windows command line tools that are helpful for dealing with Windows programs from the command line are: ASSOC and FTYPE.

ASSOC

ASSOC will list all the file associations if given no arguments.
If provided a file extension like ".py", then it will give you the file type for that association:

C:\>ASSOC .py
.py=Python.File


FTYPE

FTYPE will get or set the command to execute for a specific file type. For example:

C:\>ftype Python.File
Python.File="C:\WINDOWS\py.exe" "%1" %*

For me, this was associating with a Python 2.7 interpreter, instead of the Python 3.4 one I wanted. To fix my problem, I executed:

C:\Python34\myscripts>ftype Python.File

Python.File="C:\Python34\python.exe" "%1" %*


Restoring F8 key at Boot

If you want to be able to use the F8 key at boot time in Windows 8+, you need to execute the following before it's too late!

bcdedit /set {default} bootmenupolicy legacy

11/10/2015

Creating an Encrypted Partition in CentOS 7

Creating an Encrypted Partition in CentOS 7

First, prepare a partition with fdisk. In this example, it is assumed that /dev/sdb1 has been created.

Then, use cryptsetup to luksFormat the partition with a passphrase.

cryptsetup -y luksFormat /dev/sdb1

You will need to type: YES
if you are sure you want to continue.

You will be prompted to Enter and Verify your passphrase.  Be sure to select one that is not too simple or less than 8 characters, as now it does verify the complexity. If you complete this successfully, then you will need the passphrase that you used to open the device.  You can open the device under any name that you want to appear underneath /dev/mapper/.

Next, use cryptsetup to luksOpen the partition to a name like "confidential" that will become part of the path to the new /dev/mapper/confidential device.

crypstsetup luksOpen /dev/sdb1 confidential

You will then be prompted with the passphrase that you used when you executed cryptsetup with luksFormat subcommand.

The device will now appear as /dev/mapper/confidential, but it will actually be a symbolic link to a /dev/dm* device.

Format the open (unencrypted) device by making a filesystem.

mkfs.ext4 /dev/mapper/confidential

Create a mount point and mount the new filesystem.

mkdir /var/lib/confidential
mount /dev/mapper/confidential /var/lib/confidential

Put the data that you want to be encrypted onto the filesystem. For example, to copy confidential data from a user's home directory to the encrypted device, you could execute something like:

cp /home/user/confidential.data /var/lib/confidential

Unmount the filesystem and use cryptsetup to luksClose the filesystem.

umount /var/lib/confidential
cryptsetup luksClose confidential

Create /etc/crypttab
confidential /dev/sdb1

11/07/2015

Creating an iSCSI target and and initiator with CentOS 7

Creating an iSCSI target and and initiator with CentOS 7

First, you will probably need to install the necessary packages, as they are not installed by default. For the iSCSI server, target portal, you will need to install scsi-target-utils and targetcli packages, and on the client, the iscsi-initiator-utils package.  For testing purposes, it may be useful to have all three installed on the server, or if you are just trying out iSCSI using just a single system for practice.  The following command will install all three packages:

yum -y install scsi-target-utils targetcli iscsi-initiator-utils


iSCSI Qualified Name (IQN) 

You will need to assign a unique iSCSI Qualified Name (IQN) for your server, client, and each target.  The IQN starts with "iqn." followed by the year-month that the target will be available after, like "2015-11".  After that, the domain name in reverse, like "com.example", and finally a colon followed by the name of the specific entity like ":lun0", or ":centos7".  Put all together the IQN looks like this: "iqn.2015-11.com.example:lun0" or "iqn.2015-11.com.example:centos7".

If you want to have a IQN generated for your system that should be universally unique that you can place into /etc/iscsi/initiatorname.iscsi, instead of setting your own, you can execute:

iscsi-iname

which should output something like:

iqn.1994-05.com.redhat:34d4db0d675

iSCSI Target Portal (Server) Configuration

Your system is already identified with an IQN in the file /etc/iscsi/initiatorname.iscsi.  You can modify this to something unique for your network (or the world), such as: iqn.2015-11.com.example:centos7.  You will need all the IQNs for the clients that will connect to your iSCSI portal. After updating the previous file, the iscsid service should be restarted with:

systemctl restart iscsid

Rather than having to edit configuration files by hand, the targetcli command provides an interface for managing the targets of your portal which uses a directory metaphor for organization and navigation.  Start the interface by executing:

targetcli

First navigate, and then create an appropriate backing store.  If you have a block device, like /dev/sdd, then you could a backing store named back1 by executing:

cd /backstores/block
create back1 /dev/sdd

To use a file image backing store with a size of 100Mb, you could execute:

cd /backstores/fileio
create back1 /var/lib/iscsi-lun0.img 100M

Next, to create target IQNs, you can create entries under /iscsi.  For example, to create a  target of iqn.2015-11.com.example:lun0, you would execute:

cd /iscsi
create iqn.2015-11.com.example:lun0

The backing store created earlier must be associated with the target IQN. You do this by navigating under the IQN, the target portal group, and the luns directory like /iscsi/iqn.2015-11.com.example:lun0/tpg1/luns.

Pay attention to which /backstore file you used previously. If you created the block device /backstores/block/back1 earlier then you would execute:

cd /iscsi/iqn.2015-11.com.example:lun0/tpg1/luns
create /backstores/block/back1 

If you created the fileio backstore earlier, then you would execute:

cd /iscsi/iqn.2015-11.com.example:lun0/tpg1/luns
create /backstores/fileio/back1

Then, for each client, an acl must be added. Begin by changing to the acls under your IQN/tpg1:

cd /iscsi/iqn.2015-11.com.example:lun0/tpg1/acls

For each client, add the acl by creating an IQN entry:

create iqn.2015-11.com.example.com:centos7

Optionally, add authentication information (this matches the initiator configuration below):

cd iqn.2015-11.com.example.com:centos7
set auth userid=student
set auth password=password

If you return to the targetcli interface interface later, you can navigate to this "directory" and use the following command to view the authentication information for this client (this command is useful in user "directories" within targetcli, too):

cd /iscsi/iqn.2015-11.com.example.com:lun0/tpg1/acls/iqn.2015-11.com.example.com:centos7
info

which output:

chap_password: password
chap_userid: student
wwns:

iqn.2015-11.com.example:centos7

When you are done, you can leave the program.

exit

Hot Tip! Each time you exit targetcli, it informs you that it has updated the /etc/target/saveconfig.json file, which could be edited.  Also, targetcli keeps a copy of the last ten configurations you have used in /etc/target/backup. So it is easy to edit the current configuration or restore one of these configuration files by copying the /etc/target/backup/saveconfig-[TIMESTAMP].json file over the /etc/target/saveconfig.json, and then restart the iscsid service.

After you have finished providing each client acl, you can should review the configuration by using the following suggestions.  You can navigate the configuration like a normal filesystem with cd and ls, and use info and help to get information specific to each directory of the configuration:

cd /
ls 
cd /backstores/fileio
ls
help
cd /iscsi
ls

If you are satisfied, then exit the interface by executing:

exit

Finally, enable and start the iscsid service:

systemctl enable iscsid
systemctl start iscsid

If this is working correctly, then the port 3260/tcp should be listening and shown by the following command:

ss -tln | grep 3260

which should show:

LISTEN     0      5                         *:3260                     *:*  

You may need to enable the port through the firewalld configuration, which is used for the firewall by default.  You have several ways that you could achieve this with greater security, but this example assumes that you want to make the port open for all addresses:

firewall-cmd --zone public --add-port 3260/tcp --permanent
firewall-cmd --reload
firewall-cmd --list-all



iSCSI Initiator (Client) Configuration

Just as was done on the server, the client should be identified by a IQN in the /etc/iscsi/initiatorname.iscsi file. Make sure that the you use the same IQN for each client that you used to create the acl entries on the server.  Don't forget to update the /etc/iscsi/initiatorname.iscsi file and restart the iscsid service:

systemctl restart iscsid

If you set a userid and password in the acl you created on the server, then in /etc/iscsi/iscsid.conf on the client, uncomment and modify the userid and password to match the one that you used:

node.session.auth.authmethod = CHAP
node.session.auth.username = student
node.session.auth.password = password

First, you need to discover the target at the portal by executing:

iscsiadm -m discovery -t sendtargets -p 10.0.2.5 # where the IP is the target portal server above

The above command should show the IQNs available at the target portal server.  You can attempt to login to see if you have any errors, especially if using authentication by using:

iscsiadm -m node --login

For information about the session which is hopefully created, you can use iscsiadm in the session mode.  In the session mode, you can print session information in increasing verbosity by setting the -P option from 0 for the lowest verbosity to 3 the highest verbosity.  For example, here's the inetadm command run in session mode to print out medium high verbosity:

inetadm -P 2 -m session

which had the output of:

Target: iqn.2015-11.com.example:lun0 (non-flash)
Current Portal: 10.0.2.5:3260,1
Persistent Portal: 10.0.2.5:3260,1
**********
Interface:
**********
Iface Name: default
Iface Transport: tcp
Iface Initiatorname: iqn.2015-11.com.example:centos7
Iface IPaddress: 10.0.2.5
Iface HWaddress:
Iface Netdev:
SID: 1
iSCSI Connection State: LOGGED IN
iSCSI Session State: LOGGED_IN
Internal iscsid Session State: NO CHANGE
*********
Timeouts:
*********
Recovery Timeout: 120
Target Reset Timeout: 30
LUN Reset Timeout: 30
Abort Timeout: 15
*****
CHAP:
*****
username: student
password: ********
username_in:
password_in: ********
************************
Negotiated iSCSI params:
************************
HeaderDigest: None
DataDigest: None
MaxRecvDataSegmentLength: 262144
MaxXmitDataSegmentLength: 262144
FirstBurstLength: 65536
MaxBurstLength: 262144
ImmediateData: Yes
InitialR2T: Yes
MaxOutstandingR2T: 1

Once you have resolved any issues with making a connection, you should enable and start the iscsi service:

systemctl enable iscsi
systemctl start iscsi

If everything has gone successfully, then a new SCSI disk device should appear with a name found by listing /dev/sd*.  In this example, the new disk appears as /dev/sdb.

ls /dev/sd*

Shows the output:

/dev/sda  /dev/sda1  /dev/sda2  /dev/sdb 

Most likely, the new device will be the last one shown like /dev/sdb above.  To get it ready for a filesystem, you can use fdisk and the new device name to create a partition.  In the following example, one new partition is created that uses all the space on the device:

fdisk /dev/sdb
Welcome to fdisk (util-linux 2.23.2).

Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.

Command (m for help): n
Partition type:
   p   primary (0 primary, 0 extended, 4 free)
   e   extended
Select (default p): 
Using default response p
Partition number (1-4, default 1): 
First sector (8192-204799, default 8192): 
Using default value 8192
Last sector, +sectors or +size{K,M,G} (8192-204799, default 204799): 
Using default value 204799
Partition 1 of type Linux and of size 96 MiB is set

Command (m for help): w
The partition table has been altered!

Calling ioctl() to re-read partition table.
Syncing disks.

Now executing the following command should show the new partition, /dev/sdb1:

ls /dev/sd*

Shows the output:

/dev/sda  /dev/sda1  /dev/sda2  /dev/sdb /dev/sdb1

To prepare the partition for mounting, create a filesystem on it it, in this case an ext4 filesystem will be created:

mkfs -t ext4 /dev/sdb1

Create the directory where you want to mount the new filesystem such as /mnt/lun0

mkdir /mnt/lun0

Verify that the filesystem can be successfully mounted:

mount /dev/sdb1 /mnt/lun0
mount | grep lun0

If successful, this should output something like:

/dev/sdb1 on /mnt/lun0 type ext4 (rw,relatime,seclabel,stripe=4096,data=ordered)

When you want to make this mount permanent, you have to be careful to add the "_netdev" mount option in your /etc/fstab entry.  It is also a good idea to use UUID identifiers instead of device names as device names may change depending on the order in which devices are detected.  To discover the UUID for the new device execute:

blkid 

or for this specific example

blkid /dev/sdb1

which had the output of:

/dev/sdb1: UUID="3735827d-b4f4-48ed-aca1-a264a3ec956e" TYPE="ext4"

The entry in this example would look similar to the following, but your UUID will be different.
CHECK THE OUTPUT OF blkid FOR YOUR CORRECT UUID:

UUID=3735827d-b4f4-48ed-aca1-a264a3ec956e /mnt/lun0  ext4 _netdev 0 0

After adding the entry, unmount your new device, and the mount all /etc/fstab entries to verify that your new entry is correct.  

umount /dev/sdb1
mount -a
mount | grep lun0

should output:

/dev/sdb1 on /mnt/lun0 type ext4 (rw,relatime,seclabel,stripe=4096,data=ordered,_netdev)

If that works, and you won't disturb anyone else on the system, you might reboot the system(s) starting with the server first, and then the client, to verify that everything has been enabled correctly for automatic mounting of the iSCSI device. After the systems have rebooted, check that the client is still mounting the lun0 target with:

mount | grep lun0

If you made it this far, then congratulations! You have a persistent iSCSI target portal server and an iSCSI initiator client able to perform CHAP authentication.

Wrap-up and Troubleshooting

If you are still having issues, then review the files that were updated, and the firewall settings.  For example, the wrong IQN for a client will mean failure to authorize, the wrong userid or password, a failure to authenticate.  Also, revisit the targetcli interface and review the configuration information.  Here's a quick tour of some troubleshooting with commands in bold, the output of the command in italics. and the relevant information highlighted.

cat /etc/iscsi/initiatorname.iscsi
InitiatorName=iqn.2015-11.com.example:centos7

fdisk -l
Disk /dev/sda: 42.9 GB, 42949672960 bytes, 83886080 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk label type: dos
Disk identifier: 0x000d9dbb

   Device Boot      Start         End      Blocks   Id  System
/dev/sda1   *        2048    39938047    19968000   83  Linux
/dev/sda2        39938048    41943039     1002496   82  Linux swap / Solaris

Disk /dev/sdb: 104 MB, 104857600 bytes, 204800 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 4194304 bytes
Disk label type: dos
Disk identifier: 0x761d8fba

   Device Boot      Start         End      Blocks   Id  System
/dev/sdb1            8192      204799       98304   83  Linux

blkid 
/dev/sda1: UUID="cfc6be43-cf4b-4cb5-9bf3-67f24d1d5205" TYPE="ext4" 

/dev/sda2: UUID="d5c08700-0ff1-4062-a13b-f3782b80c66b" TYPE="swap" 
/dev/sdb1: UUID="3735827d-b4f4-48ed-aca1-a264a3ec956e" TYPE="ext4"

cat /etc/fstab
# /etc/fstab
# Created by anaconda on Fri Nov 6 16:02:18 2015
#
# Accessible filesystems, by reference, are maintained under '/dev/disk'
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
#
UUID=cfc6be43-cf4b-4cb5-9bf3-67f24d1d5205 /                       ext4    defaults        1 1
UUID=d5c08700-0ff1-4062-a13b-f3782b80c66b swap                    swap    defaults        0 0

UUID=3735827d-b4f4-48ed-aca1-a264a3ec956e /mnt/lun0  ext4 _netdev 0 0 

grep -Ev '^#|^$' /etc/iscsi/iscsid.conf  # exclude comments and blank lines
iscsid.startup = /bin/systemctl start iscsid.socket iscsiuio.socket
node.startup = automatic
node.leading_login = No
node.session.auth.authmethod = CHAP
node.session.auth.username = student
node.session.auth.password = password
node.session.timeo.replacement_timeout = 120
node.conn[0].timeo.login_timeout = 15
# remaining output omitted

firewall-cmd --list-all
public (default, active)
  interfaces: enp0s3
  sources: 
  services: dhcpv6-client ssh
  ports: 23/tcp 3260/tcp 23/udp
  masquerade: no
  forward-ports: 
  icmp-blocks: 
  rich rules:

targetcli
/iscsi> cd /
/> ls
o- / ..................................................................... [...]
  o- backstores .......................................................... [...]
  | o- block .............................................. [Storage Objects: 0]
  | o- fileio ............................................. [Storage Objects: 1]
  | | o- back1 ....... [/var/lib/iscsi-lun0.img (100.0MiB) write-back activated]
  | o- pscsi .............................................. [Storage Objects: 0]
  | o- ramdisk ............................................ [Storage Objects: 0]
  o- iscsi ........................................................ [Targets: 1]
  | o- iqn.2015-11.com.example:lun0 .................................. [TPGs: 1]
  |   o- tpg1 ........................................... [no-gen-acls, no-auth]
  |     o- acls ...................................................... [ACLs: 1]
  |     | o- iqn.2015-11.com.example:centos7 .................. [Mapped LUNs: 1]
  |     |   o- mapped_lun0 ............................ [lun0 fileio/back1 (rw)]
  |     o- luns ...................................................... [LUNs: 1]
  |     | o- lun0 ..................... [fileio/back1 (/var/lib/iscsi-lun0.img)]
  |     o- portals ................................................ [Portals: 1]
  |       o- 0.0.0.0:3260 ................................................. [OK]
  o- loopback ..................................................... [Targets: 0]

/> cd /iscsi/iqn.2015-11.com.example:lun0/tpg1/acls/iqn.2015-11.com.example:centos7/
/iscsi/iqn.20...ample:centos7> info
chap_password: password
chap_userid: student
wwns:
iqn.2015-11.com.example:centos7
exit

iscsiadm -m discovery -t sendtargets -p 10.0.2.5 # the -p must be the correct IP for the portal

10.0.2.5:3260,1 iqn.2015-11.com.example:lun0

iscsiadm -m node -v --login

10.0.2.5:3260,1 iqn.2015-11.com.example:lun0

iscsiadm -P3 -m session 
iSCSI Transport Class version 2.0-870
version 6.2.0.873-28
Target: iqn.2015-11.com.example:lun0 (non-flash)
Current Portal: 10.0.2.5:3260,1
Persistent Portal: 10.0.2.5:3260,1
**********
Interface:
**********
Iface Name: default
Iface Transport: tcp
Iface Initiatorname: iqn.2015-11.com.example:centos7
Iface IPaddress: 10.0.2.5
Iface HWaddress:
Iface Netdev:
SID: 1
iSCSI Connection State: LOGGED IN
iSCSI Session State: LOGGED_IN
Internal iscsid Session State: NO CHANGE
*********
Timeouts:
*********
Recovery Timeout: 120
Target Reset Timeout: 30
LUN Reset Timeout: 30
Abort Timeout: 15
*****
CHAP:
*****
username: student
password: ********
username_in:
password_in: ********
************************
Negotiated iSCSI params:
************************
HeaderDigest: None
DataDigest: None
MaxRecvDataSegmentLength: 262144
MaxXmitDataSegmentLength: 262144
FirstBurstLength: 65536
MaxBurstLength: 262144
ImmediateData: Yes
InitialR2T: Yes
MaxOutstandingR2T: 1
************************
Attached SCSI devices:
************************
Host Number: 3 State: running
scsi3 Channel 00 Id 0 Lun: 0
Attached scsi disk sdb State: running

Good Luck!

About Me - WrightRocket

My photo

I've worked with computers for over 30 years, programming, administering, using and building them from scratch.

I'm an instructor for technical computer courses, an editor and developer of training manuals, and an Android developer.