Using Puppet to host a private RPM repository

A repository is a place where files are stored, indexed, and available through a package manager to anyone who has the repository information. With rpm based systems, a repository is created with a tool called createrepo. Most of the time, publicly available repositories already offer the packages your server needs. When you have a custom application you want to deploy (or even rebuild an existing application with your patches), it is best to distribute that package with a repository rather than a file share or some other means. Often a folder structure is created so that differing client OS versions can connect to the same repository and access versions compiled to that specific release. In my example below, I am not creating this folder structure as I am only serving one major release – Centos 7 – and the packages I am generating are website directories which are just a collection of portable code.

A private repository is not a tricky feat – all you have to do is serve the repository via https and require http basic authentication. You then configure the clients to connect to the repository with the basic authentication in the URL string (i.e. baseurl=https://user:pass@repo.example.com/). The HTTPS protocol is not required to serve a repository, but it does prevent network snoopers from seeing your repository credentials.

Now that we know what is needed for a private repository, we can then define it in our puppet code.

node 'repo.example.com' {

  file { '/var/yumrepos':
    ensure => directory,
  }

  createrepo { 'yumrepo':
    repository_dir => '/var/yumrepos/yumrepo',
    repo_cache_dir => '/var/cache/yumrepos/yumrepo',
    enable_cron    => false, #optional cron job to generate new rpms every 10 minutes
  }

  package { 'httpd':
    ensure => installed,
  }

  httpauth { 'repouser':
    ensure    => present,
    file      => '/usr/local/nagios/etc/htpasswd.users',
    password  => 'some-long-password',
    mechanism => basic,
    require   => Package['httpd'],
  }

  file { '/usr/local/nagios/etc/htpasswd.users':
    ensure => file,
    owner  => 'nginx',
    mode   => '0644',
  }

  class{'nginx':
    manage_repo    => true,
    package_source => 'nginx-mainline',
  }

  nginx::resource::vhost{"$::fqdn":
    www_root             => '/var/yumrepos/yumrepo',
    index_files          => [],
    autoindex            => 'on',
    rewrite_to_https     => true,
    ssl                  => true,
    auth_basic           => 'true',
    auth_basic_user_file => '/usr/local/nagios/etc/htpasswd.users',
    ssl_cert             => "/etc/puppetlabs/puppet/ssl/public_keys/$::fqdn.pem",
    ssl_key              => "/etc/puppetlabs/puppet/ssl/private_keys/$::fqdn.pem",
    vhost_cfg_prepend    => {
      'default_type'     => 'text/html',
    }
  }

}

For the above code to work, we need the required modules:

mod 'palli/createrepo', '1.1.0'
mod "puppet/nginx", "0.4.0"
mod "jamtur01/httpauth", "0.0.3"

We can then use the following declaration on our nodes to use this repository.

yumrepo {'private-repo':
  descr           => 'My Private Repo - x86_64',
  baseurl         => 'https://repouser:some-long-password@repo.example.com/',
  enabled         => 'true',
  gpgcheck        => 'false',
  metadata_expire => '1',
}

You now have a fully functional private repository – deploy your awesome software.

Website protection

There are several factors that go into securing a web application. Most are second nature to seasoned system administrators, but it is still too common to talk to someone who does not know how to properly secure a web application. Here is the common checklist I go through when I determine if a website is secured.

  • Is it using a firewall?
  • Am I using unique passwords that are over 20 characters?
  • Are passwords required to alter data?
  • Is my codebase up to date?
  • Are the only public facing ports HTTP and HTTPS?
  • Do I protect data in transit from the user to my site by enforcing HTTPS?
  • Do I protect data from my website to the database with SSL?
  • Is my database only accessible to my application?
  • Do I have my database and application on different servers?
  • Can a malicious user drop/delete/alter data from my database from a form/switch/button that is publicly accessible on my website or do they need to login to perform that operation?
  • Do I have separate connections and users to the database for writing and reading data?
  • Do I rate limit connections via web application firewall or utility like fail2ban?
  • Am I reading and blocking malicious inputs via web application firewall or mod_security?
  • Can anyone brute force a login or am I blocking it after 5 tries?

So the Cubs won the world series

I am still in shock that the Chicago Cubs won the World Series in Baseball which ended their 108 year drought. Last time the Cubs won the world series, they won it back-to-back. I can expect nothing less this time around. 😀

GlusterFS overview

GlusterFS is a distributed file system. Think of it as a replacement of traditional file storage (a single NFS/samba server), an alternative to Microsoft’s DFS, or a modern implementation of SAN. It really shines when you have multiple locations and need a file server which must have the same data and be continually in sync. It is also superb for virtual machine disks as they will then become highly available.

You can use GlusterFS in a replica, distributed, and distributed-replica models. Replica is where a copy of file a is located on all GlusterFS hosts. Distributed is where file a is on some hosts and file b is on the other hosts. Distributed-replica is a combination of both – in other words a subset of two distributed hosts in a parent of replicas.

To get started with GlusterFS, all you need is commodity hardware. Nothing has to match – not even the harddrive space. GlusterFS will configure the storage allocation pool automatically. I do recommend at least a 1GB NIC connection and a large internet pipe between locations. Partitioning your system appropriately must also be considered – have a separate mount for /var/log and /data. Keeping /data as the location of your shares makes adding and removing nodes consistent with the documentation.

You need at least a multiple of 2 GlusterFS hosts to experience replica, distributed (minimum of 2 hosts), and (minimum of 4) distributed-replica. If you plan on serving Virtual machines off of the GlusterFS volume, multiples of 3 are recommended. Clusters can also be geographically bound so that if one node fails, your clients will connect to another gluster server in that region rather than just any gluster node.

The quick start documentation goes over setting up two nodes, pairing them together, connecting via the GlusterFS protocol on your client, and creating 100 files. In total, this is about 6 commands.

For managing a large cluster of GlusterFS servers, one may want to take a look at heketi which manages the lifecycle of GlusterFS. Facebook also developed a tool called AntFarm, but it is currently closed source.

A journey to LFCE

I began my Linux hobby in 1999. I was given a CD of RedHat Linux which I installed on an old computer. At first use, it was slow and buggy and uninstalled in favor of Windows 98. I installed Debian a few months later and discovered I could install a different desktop environment – KDE which looked like Windows, but was different. After playing with it for a few weeks, I discovered Knoppix – a live CD that didn’t overwrite my hard drive and let me play around without grave consequences. A friend then introduced me to Gentoo which allowed for complete customization for my 1ghz single core processor. After a few failed misconfigurations and a desire to get back to binary installs, I switched to Fedora Core 1 and used it on my desktop. Another friend showed me a new distribution called Ubuntu – similar to Debian, but more up to date. This was then installed on my laptop that I used for college. I switched completely to Ubuntu after the release of Fedora core 4 as I got frustrated with yum.

After college, I started working in a help desk position. It was mainly servicing Windows desktops and a few OSX machines. I then received a task from my boss to create a simple lookup website. I got to choose the server OS, create the VM on a Hyper-V host, and use any tools I could muster to perform this simple task. The project was a success and I received another – parse a text file and output it to a standard CSV. At the time, I only knew PHP and none of the cool features of sed and awk. PHP turned out to be a good choice for this project as I was later informed a user would use my creation every day to convert a text file to this new format. I simply had to create a web front end, parse the uploaded file, and give the user an option to download this file.

I began to develop more skills in Linux as my various work tasks involved more and more Enterprise level responsibility – such as LDAP authentication for websites, Active Directory maintenance, converting databases from Access to MySQL with a front end, Migration of Exchange 2003 to 2007, and introducing Google Apps for Education to about 700 students. 

When my boss left the organization, I assumed his role and provided oversight for network connectivity (switch/router config), overseeing two, 6 figure technology budgets, and also my regular responsibilities. I was able to attend training events as well as attend online courses regarding Linux. At that time, I began reading more books on tech practices, management, and Linux. I felt I learned enough to prove my skills with certification – even though I was doing the work successfully without being certified. The Linux Foundation released their equivalent to Red Hat’s RHCSA – the Linux Foundation Certified SysAdmin (LFCS). The domains and competencies covered described all the tasks I have done since setting up my first Linux box – create users, partitions, edit text files, etc. I took the introduction to Linux course offered by the Linux Foundation on edx, and scheduled an exam for my LFCS. On my first try, I misconfigured RAID, and rebooted the server. (Whoops!) The Linux Foundation was gracious to allow a free retake which I passed. I kept going around to my co-workers (after being certified) and quoting my favorite Dilbert comic: “Step away from that network server… I AM CERTIFIED!”

At this time, my skilled co-workers left (not all at once) and my team turned out to be just me for a period of eight months to cover 1,100 network attached devices and 1,300 users. It was about this time I researched CMEs (Chef, CFEngine, and Puppet) to help do tasks. I eventually picked puppet and successfully deployed RPi-wayfinding with it. A year and a half later, I passed the Puppet Certified Professional exam. With that out of the way, I turned my attention to the LFCE – especially since the Linux Foundation had a sale on the course and test for less than the test amount. 

The LFCE was the easiest certification test of all the ones I took. I scored an 88 out of 100, and I think the things I missed were saving the iptables rules :/

My next step is to take an AWS certificate test as I have been using AWS for nearly 2 years, but I will probably take an OpenStack cert first as I was given a discounted rate for the cert + course from the Linux Foundation.

Deploying Puppet Open Source

Update: (5/28/17) yes, there is the puppet/r10k which supercedes the zack/r10k. While you are free to deviate from the article in your own environment, the below steps still work as intended. I will have to update this article as well as explain why having r10k and dynamic environments is a good idea.

In this guide we will go over best practices to deploy Puppet Open Source using the recommended workflow (r10k), PuppetDB, and the foreman. You can deploy Puppet server on any of their supported *nix distributions. In this tutorial we will assume it to be on CentOS 7 as this seems to have the best support.

Continue reading Deploying Puppet Open Source

Hobby vs responsibility

One of my hobbies is video gaming. In my teen years, I would spend on average of 60-80 hours a week playing either Counter Strike, Team Fortress 2, or any other Valve software title. It was not until I went to college and got a job when my average went to 30-40 hours a week. After being married and having children, my average is now down to 8-12 hours a week. As my responsibilities increased, my hobby time decreased. I would consider myself addicted to video games (i.e. I cannot stop playing them); however, I do not feel like I am missing out from partaking in my hobby. Here is what I have done to lower my addiction to video games:

  1. I stopped playing multiplayer FPS
  2. I only buy video games that run on Linux
  3. I play during specific time frames only

My current favorite game is Factorio – you crash landed on a distant planet and have to build a rocket to escape.

Repercussions from a 1.1 Tbsp DDoS

In case you missed it, the largest recorded Direct Denial of Service (DDoS) occurred. While under DDoS, a victim’s server (or servers) is under high load and cannot complete all requests that are requested by it. Basically, a DDoS victim is someone the attacker wants silenced on the internet. In order to send a DDoS of that magnitude, the attacker has to have control over many computers – a botnet. It is believed that this attack originated from over 150,000 computers in the IoT category (smart TVs, refrigerators, thermostats, etc.). Due to their poor default security, the IoT devices are easy targets for hackers who intend on adding them to their botnets. A recent article on Ars Technica points out the current issues with IoT and Linux kernel security, but with most articles of this nature, provides no clear cut solution to the problem we are experiencing. Below are my thoughts to this current situation and how it may be resolved.

We need a governing body to issue a seal of approval for IoT and anything that is compiled with the Linux kernel. Then we, as consumers, must use, buy, and encourage others to buy from the companies that have this seal. The governing body should ensure each company seeking the seal comply with the following criteria:

  1. Every new device created and sent to market has a minimum of 5 years worth of bi-monthly security patches and updates since the day of release to the public.
  2. In the event the company goes bankrupt, dissolves, or cannot support any older product they have released in the past 5 years, the company must provide schematics, instructions, or software that open source enthusiasts can recreate, patch, or upgrade the legacy product.
  3. No known vulnerability must be willingly left unpatched.
  4. When a CVE is identified on a company’s product, a test case must be created and run on that code base for every future release.
  5. A notification service must be in place when new updates are released and must be available in RSS or email form.
  6. Automatic updates should occur over HTTPS
  7. Backdoors, admin terminals, etc. should require a physical connector be applied on the device in order to grant access.

    For a potential company to get this approval, it may seem like an arduous task to get all the controls in place; however, by applying DevOps methodologies, these tasks can be a simple feat. This would require the governing body to not only enforce the list, but also have the training available to comply to this list. For this reason, I suggest the Linux Foundation to become this governing body and issue out seals of approval.

    First puppet module published

    I completed my first public module for puppet and submitted it to the puppet forge. It seems too simple to compile into a build and submit it to the forge; however, I made it public for these reasons:

    1. I needed experience with puppet code testing. This helped me at the most basic level.
    2. I felt like someone else could benefit from the code – even if it is one person.
    3. I wanted to do it.

    Still, the code seems too juvenile to be submitted to the forge. All it does is take the hostname of a Digital Ocean droplet and submit its IP address as a new DNS record inside of Digital Ocean DNS. The code is located here.

    I almost want to follow up with this and develop my duplicity module into reusable code for the community.

    Signs you are doing IT wrong

    1. You still use FTP
    2. You use SFTP
    3. You have a single server hosting 1 website, MySQL, and PHP. It has 4+ GB of RAM and you only have ~2,000 visitors a day.
    4. You login via root
    5. You don’t use version control
    6. You use a control panel for servers which you have SSH access.
    7. It takes you over an hour to migrate 1 website
    8. Your DNS TTL records are over 10 minutes
    9. Your SQL server is not accessible over SSL/TLS
    10. You use mod_php instead of reverse proxying to php-fpm
    11. You develop for the web on Windows
    12. You chmod 777
    13. You use modules/plugins that require chmod 777
    14. You have no backups
    15. You host multiple websites on one server (internal-only websites excluded)
    16. You SSH with passwords
    17. You reuse passwords
    18. You don’t read books
    19. You don’t attend conferences
    20. You attend more than 6 conferences a year
    21. You use skype for communication
    22. You make a separate mobile site
    23. You add more RAM to fix your memory leaks

    Iced coffee is the best

    I am not a very big fan of hot drinks, but I enjoy drinking a cup/glass/thermos/pot/gallon of coffee. I especially drink it more when my taste buds dance around and say, “Wow! That was some good, quality coffee!” A few weeks ago I set out to find a better way to make my favorite drink – iced coffee. In my opinion, the best method of procuring coffee is in whole bean form. I tend to buy a brand that is roasted in my region – supporting the local economy – that also tastes good. I store the whole bean bag in my freezer and the grounded bean in a small coffee can in my refrigerator.

    At first, I tried pouring hot coffee over Frozen coffee cubes, then added my refrigerated creamer. This lasted for a few weeks, but I couldn’t notice a huge difference in taste between water iced cubes and coffee iced cubes.

    Secondly, I tried cold brewing coffee – placing ground coffee beans in cold water into the refrigerator overnight. This only resulted in weak, flavorless coffee.

    Next, I tried hot brewing coffee, pouring it into a container, and letting it sit in the refrigerator overnight. This seems to be the best option so far. I still get to keep my 1.5 tbsp ratio for coffee beans and resulting liquid. The iced cubes do not melt when the coffee is poured over them. I think I will stick to this option for now.

    My IoT device history

    The internet of things (IoT) is getting pretty saturated with devices most of which are either smart watches or activity trackers. Smart watches do not appeal to me as I have a very nasty habit of destroying the clock face of my watches. Last November, I was able to get a Vivosmart from Garmin for $60 plus tax and shipping. It was great – did step tracking, allowed for notifications, allowed me to dismiss calls and see texts. My brother-in-law also received one as a gift a few months later (he preferred it over the Fitbit which did less and cost more).

    A month ago we both noticed the pixels disappearing on the Garmin Vivosmart display. I was able to submit a warranty request through their website quite painlessly, and the offered to upgrade me to a Garmin Vivosmart HR! Of course I took the upgrade offer and paid the shipping for the old device to be sent back. My brother-in-law had a complete different experience. The website at first said his Garmin Vivosmart was out of warranty (even though it was newer than mine) then it eventually – a day later – said it was in warranty. He was given the option to replace the Garmin Vivosmart with a non-HR model, but they gave him a shipping label. It is quite odd that we both had different experiences within a few days of submitting our warranty requests.

    I recently received the newer model after waiting the RMA process and I am quite impressed. At first, the font was too skinny and hard to read, but all I had to do was upgrade to the latest firmware and it was fixed. One neat feature that was added (besides the obvious HR function) was the ability to see the weather – up to a 4 day forecast. Two new goal trackers were also added – a stair counter and strenuous activity counter. The plain Garmin Vivosmart’s battery lasted over a week. I haven’t depleted the new model all the way, but I am assuming it will last 4-5 days depending on my use.

    Provisioning VMs with cloud init

    One of the easiest ways to deploy a virtual machine in oVirt is first to install the OS then turn it into a template. This will allow you to copy that template to deploy new instances. One mundane task after a new template is copied to a new instance is logging in, changing the IP, setting the hostname, setting up Puppet, running puppet, etc. cloud-init is the tool designed to fix that mundane task process by allowing those steps to be automated. oVirt/RHEV (as well as OpenStack, AWS, and others) allow you to pass in user data which is then supplied to cloud-init after the template is copied over and turned on. This allows for scripting on the new VM – easing deployment.

    For my environment, I wanted a CentOS 7 template. To have that, I must first install CentOS on a new VM and seal it (Windows calls this Sysprep). Before I seal it, I must install cloud-init and any other tools I might use for deployment – such as puppet. Here are the steps to obtain just that:

    Continue reading Provisioning VMs with cloud init

    Securing PWM

    In last week’s post we set up PWM insecurely. In this post, we are going to secure it down and install mysql to store the reset questions. This guide assumes you have this CentOS 7 server publicly accessible with ports 80 and 443 available to the entire world. First, we will need to install mysql, set up a database, and add a user to that database. To do that, we need to edit our manifest.pp and append the following:

     class { '::mysql::server':
         root_password           => 'My4cc0unt$$password!',
         remove_default_accounts => true,
         package_name            => 'mariadb-server',
         package_ensure          => 'installed',
         service_name            => 'mariadb',
     }
    
     mysql::db { 'pwm':
         user     => 'pwm',
         password => 'pwm_passworD2!', # Can't do a password hash here :(
     }
    
     class { 'mysql::bindings':
         java_enable => true,
     }
    
    file { '/opt/tomcat8/pwm/lib/mysql-connector-java.jar':
         ensure  => link,
         target  => '/usr/share/java/mysql-connector-java.jar',
         require => Class['mysql::bindings']
    }

    We will also need to install additional modules: Continue reading Securing PWM

    Password management portal for end users

    We in IT have heard it often, the #1 request coming into help desk ticket systems is password resets, account lockouts, and the like. PWM is a password reset web application written in Java for use with LDAP directories. You can configure it to work with Active Directory, OpenLDAP, FreeIPA, and others. There are already a handful of good tutorials on how to set up PWM (I think of this one in particular); however, I want to demonstrate the puppet apply command in this tutorial.

    Prerequisites

    This guide assumes you have an Active Directory server with TLS set up (to change passwords) which is beyond the scope of this post. It also assumes you have a CentOS 7 instance which can communicate to the Active Directory server. It also assumes this is in an environment without a puppet master/server. The end manifest can be uploaded to a master and used that way.

    Continue reading Password management portal for end users