Tilde Community Ansible Scripts

Posted on: 2017-01-16

If you follow this blog or any of my projects you know that I yearn for the good old days of the internet. That is why I run No Frills Host to give people good old fashioned ~username webhosting like ISPs used to. Every once in a while a get an itch to improve or replace that service. In 2015 I created scripts and setup a local git based PaaS POC that could have taken its place, but I never launched it publically because I'm lazy and because I thought git might be a barrier for some folks. Well, in 2016 I made some ansible scripts to help setup a secure tilde.club inspired server quickly and easily.

Maybe one day I'll gather up the energy to launch a service with it publically. But in the meantime, if you want to create a geek community that features: ~username webhosting, shell services, local e-mail services and local IRC services, feel free to check it out.


Setting Up a Dogtag PKI system

Posted on: 2017-01-16

Dogtag is an opensource PKI product for issuing TLS server and user certs. It also featurs an OCSP server for checking revocation status and a self-service web UI so people in your company can easily issue their own certs. Dogtag stores its cert and config data in LDAP.

We will be configuring it so that the dogtag CA itself is a subordinate signed by an offline and well protected openssl CA and so that only people in specific groups in an external LDAP store can issue certs without further approval. To do this we will be using two CentOS 7 servers. One for running 389 Directory Server acting as our external LDAP user and group store store and the other VM for running the dogtag CA, OCSP and emdedded 389 directory serve for cert and config storage. This guide does assume working DNS or hacked host files on all boxes you touch.

LDAP seerver setup

yum update
yum install epel-release xauth
yum install 389-ds  
hostnamectl set-hostname rhds.lan 
setup-ds-admin.pl
    yes #continue
    yes #ignore tuning recomendations for now
    2
    rhds.lan #hostname
    dirsrv #user
    dirsrv #group
    no #register
    admin
    test1234
    lan #domain
    389
    rhds
    dc=lan #suffix
    cn=Directory Manager #dir manager
    test1234
    9830 #admin port
    yes #install

Lets pull up the gui and add one user and put that user in a group.

ssh -X -Y root@192.168.121.82
389-console
admin
test1234
http://192.168.121.82:9830
open directory server
directory tab
lan > right click People > New > User
fake data, userid = bill password = test1234
right click groups > new > group 
name = pki
members > add > search > bill > search > ok > ok

In real life you'd want to serve LDAP over TLS, serve the admin interface over TLS, choose better domain, users, passwords, etc.

Dogtag server setup

yum update
hostnamectl set-hostname rhcs.lan
echo "192.168.121.82 rhds.lan" >> /etc/hosts
yum install epel-release xauth

cat <<EOF > /etc/yum.repos.d/pki.repo
[group_pki-epel-7.3]
name=Copr repo for epel-7.3 owned by @pki
baseurl=https://copr-be.cloud.fedoraproject.org/results/@pki/epel-7.3/epel-7-$basearch/
type=rpm-md
skip_if_unavailable=True
gpgcheck=1
gpgkey=https://copr-be.cloud.fedoraproject.org/results/@pki/epel-7.3/pubkey.gpg
repo_gpgcheck=0
enabled=1
enabled_metadata=1
EOF

yum install 389-ds dogtag-pki

Now lets configure the 389 data backing store

setup-ds-admin.pl
    yes #continue
    yes #ignore tuning recomendations for now
    2
    rhcs.lan #hostname
    dirsrv #user
    dirsrv #group
    no #register
    admin
    test1234
    lan #domain
    389
    rhcs
    dc=lan #suffix
    cn=Directory Manager #dir manager
    test1234
    9830 #admin port
    yes #install

Now lets configure the offline openssl CA

cd /root/
mkdir offline_ca
cd offline_ca
mkdir certs crl newcerts private
cp /etc/pki/tls/openssl.cnf .
chmod 700 private
touch index.txt
echo 1000 > serial

vim openssl.cnf
dir             = /root/offline_ca
[ v3_ca ]
basicConstraints = CA:true, pathlen:1
keyUsage = cRLSign, keyCertSign

openssl genrsa -out private/cakey.pem 4096
openssl req -config openssl.cnf -key private/cakey.pem -new -x509 -days 7300 -extensions v3_ca -out cacert.pem
Fill in the info and for Common Name make sure you say something Root CA

Now lets configure Dogtag CA

cd /root/
cat <<EOF > ca_step1.txt
[CA]
pki_admin_email=caadmin@localhost
pki_admin_name=caadmin
pki_admin_nickname=caadmin
pki_admin_password=test1234
pki_admin_uid=caadmin

pki_backup_keys=True
pki_backup_password=test1234

pki_client_database_password=test1234
pki_client_database_purge=False
pki_client_pkcs12_password=test1234

pki_ds_base_dn=dc=ca,dc=lan
pki_ds_database=ca
pki_ds_password=test1234
pki_ds_hostname=localhost
pki_ds_bind_dn=cn=Directory Manager

pki_security_domain_name=lan
pki_token_password=test1234

pki_external=True
pki_external_step_two=False
pki_external_csr_path=/tmp/ca_signing.csr
EOF

pkispawn -v -f ca_step1.txt -s CA

cd /root/offline_ca
vi openssl.cnf
[ v3_ca ]
basicConstraints = CA:true, pathlen:0
#keyUsage = cRLSign, keyCertSign

openssl ca -config openssl.cnf -extensions v3_ca -days 7300 -in /tmp/ca_signing.csr -out certs/rhcs.crt -policy policy_anything
y
y

cd /root/   
cat <<EOF > ca_step2.txt
[CA]
pki_admin_email=caadmin@localhost
pki_admin_name=caadmin
pki_admin_nickname=caadmin
pki_admin_password=test1234
pki_admin_uid=caadmin

pki_backup_keys=True
pki_backup_password=test1234

pki_client_database_password=test1234
pki_client_database_purge=False
pki_client_pkcs12_password=test1234

pki_ds_base_dn=dc=ca,dc=lan
pki_ds_database=ca
pki_ds_password=test1234
pki_ds_hostname=localhost
pki_ds_bind_dn=cn=Directory Manager

pki_security_domain_name=lan

pki_token_password=test1234

pki_external=True
pki_external_step_two=True
pki_external_csr_path=/tmp/ca_signing.csr
pki_external_ca_cert_path=/root/offline_ca/certs/rhcs.crt pki_external_ca_cert_chain_path=/root/offline_ca/cacert.pem
EOF

pkispawn -v -f ca_step2.txt -s CA

Now, lets configure Dogtag OCSP

cd /root/
cat <<EOF > ocsp.txt
[OCSP]
pki_admin_cert_file=/root/.dogtag/pki-tomcat/ca_admin.cert
pki_admin_email=ocspadmin@localhost
pki_admin_name=ocspadmin
pki_admin_nickname=ocspadmin
pki_admin_password=test1234
pki_admin_uid=ocspadmin

pki_backup_keys=True
pki_backup_password=test1234

pki_client_database_password=test1234
pki_client_database_purge=False
pki_client_pkcs12_password=test1234

pki_ds_base_dn=dc=ocsp,dc=lan
pki_ds_database=ocsp
pki_ds_password=test1234
pki_ds_hostname=localhost
pki_ds_bind_dn=cn=Directory Manager
pki_ds_remove_data=False

pki_security_domain_name=lan
pki_security_domain_user=caadmin
pki_security_domain_password=test1234

pki_token_password=test1234
EOF

pkispawn -v -f ocsp.txt -s OCSP

Now lets configure a profile to do external LDAP authorization

systemctl stop pki-tomcatd.target
cd /var/lib/pki/pki-tomcat/ca/profiles/ca
cp caDirUserCert.cfg caDirUserCert.bak
cp caServerCert.cfg caDirServerCert.cfg
chown pkiuser.pkiuser caDirServerCert.cfg

vi caDirUserCert.cfg #add like so
authz.acl=group="cn=pki,ou=Groups,dc=lan"

vi caDirServerCert.cfg #change like so, adding where needed
#auth.class_id=
auth.instance_id=UserDirEnrollment
authz.acl=group="cn=pki,ou=Groups,dc=lan"
name=LDAP Auth Server Certificate Enrollment

cd /etc/pki/pki-tomcat/ca
cp CS.cfg CS.bak
vi CS.cfg #change like so, adding where needed
auths.instance.UserDirEnrollment.pluginName=UidPwdDirAuth
auths.instance.UserDirEnrollment.ldap.basedn=dc=lan
auths.instance.UserDirEnrollment.ldap.groupObjectClass=groupofuniquenames
auths.instance.UserDirEnrollment.ldap.groups=ou=Groups
auths.instance.UserDirEnrollment.ldap.groupsBasedn=dc=lan
auths.instance.UserDirEnrollment.ldap.groupsEnable=true
auths.instance.UserDirEnrollment.ldap.ldapconn.host=rhds.lan
auths.instance.UserDirEnrollment.ldap.ldapconn.port=389
auths.instance.UserDirEnrollment.ldap.ldapconn.secureConn=false
profile.caDirServerCert.class_id=caEnrollImpl
profile.caDirServerCert.config=/var/lib/pki/pki-tomcat/ca/profiles/ca/caDirServerCert.cfg
profile.list=caUserCert,caECUserCert,caUserSMIMEcapCert,caDualCert,caDirBasedDualCert,caECDualCert,AdminCert,caSignedLogCert,caTPSCert,caRARouterCert,caRouterCert,caServerCert,caSubsystemCert,caOtherCert,caCACert,caCrossSignedCACert,caInstallCACert,caRACert,caOCSPCert,caStorageCert,caTransportCert,caDirPinUserCert,caDirUserCert,caECDirUserCert,caAgentServerCert,caAgentFileSigning,caCMCUserCert,caFullCMCUserCert,caSimpleCMCUserCert,caTokenDeviceKeyEnrollment,caTokenUserEncryptionKeyEnrollment,caTokenUserSigningKeyEnrollment,caTempTokenDeviceKeyEnrollment,caTempTokenUserEncryptionKeyEnrollment,caTempTokenUserSigningKeyEnrollment,caAdminCert,caInternalAuthServerCert,caInternalAuthTransportCert,caInternalAuthDRMstorageCert,caInternalAuthSubsystemCert,caInternalAuthOCSPCert,caInternalAuthAuditSigningCert,DomainController,caDualRAuserCert,caRAagentCert,caRAserverCert,caUUIDdeviceCert,caSSLClientSelfRenewal,caDirUserRenewal,caManualRenewal,caTokenMSLoginEnrollment,caTokenUserSigningKeyRenewal,caTokenUserEncryptionKeyRenewal,caTokenUserAuthKeyRenewal,caJarSigningCert,caIPAserviceCert,caEncUserCert,caSigningUserCert,caSigningECUserCert,caEncECUserCert,caTokenUserDelegateAuthKeyEnrollment,caTokenUserDelegateSigningKeyEnrollment,caDirServerCert

systemctl restart pki-tomcatd.target

In the real world you would keep the offline_ca directory on some encrypted drive in a safe or something, passwords would be better, you'd talk to the external and embeded LDAP servers over TLS, you'd choose better alias, OU and common names, you'd have an HA setup, you'd import the Root CA throug policy on all users machines and force OCSP checking on their machines as well, etc.

Testing

Start up a firefox browser with a new profile firefox -P on linux. Import the root CA and admin CA.

Edit > Preferences > Advanced > Certificates > View > Authorities > Import > /root/offline_ca/cacert.pem from the other box.  Check all boxes.  
Your certificates > Import > /root/.dogtag/pki-tomcat/ca_admin_cert.p12 from the other box.

https://rhcs.lan:8443 auth with the admin cert

Check cert chain by Green Lock > > More Info > Security > View Certificate Should be green and you should't have had to make any exceptions to view pages Clicking on all OCSP and CA links should work.

A simple cert workflow

  1. End User: https://rhcs.lan:8443 > CA > End User > Manual Server Certificate Enrollment > paste a base64 text of a csr you generate with openssl req -out test.csr -new - newkey rsa:2048 -nodes -keyout test.key.

  2. What security team or help desk would do: https://rhcs.lan:8443 CA > Agent > List Requsts > Find > Click cert from above > Approve request Submit

Now the end user would pick up the cert and serve it and the full CA chain from their web or whatever server.

Now lets pretend it got compromized.
3. What a security team would do: https://rhcs.lan:8443/ CA > Agent > Revoke > Subject Name section check checkbox > Common Name = FQDN of test cert you made > Find > Revoke on the cert you want to revoke > Submit

  1. Validating its revoked: https://rhcs.lan:8443 OCSP > Agent > Number of Revoked Certificates: 1 May take a bit for this to show up. If so, fire up pkiconsole as caadmin Cert Manager > CRL Issuing > Master > and change your settings. The "every time" is a good one. CA > Agent > Display / Updae Revocation are other good things to check.

Self-service workflows

User cert: https://rhcs.lan:8443 > CA > End User > Directory-Authenticated User Dual-Use Certificate Enrollment > bill/test1234 (from rhds.lan earlier) > cert issued

Server cert: https://rhcs.lan:8443 > CA > End User > LDAP Auth Server Certificate Enrollment > bill/test1234 (from rhds.lan earlier) + base64 of test.csr from manual test > Cert issued

References

https://jamielinux.com/docs/openssl-certificate-authority/ http://pki.fedoraproject.org/wiki/External_COPR_Builds_of_CentOS_PKI_EPEL_Packages http://pki.fedoraproject.org/wiki/Quick_Start http://pki.fedoraproject.org/wiki/Installing_CA_with_Externaly-Signed_CA_Certificate https://fedorahosted.org/pki/ticket/1174


Building An RPM

Posted on: 2016-09-11

Every once in a while somebody asks me to build an RPM. This unfortunately doesn't happen often enough that I can remember the process and I have to do a bunch of digging. When I do that digging most of what I find is how to create RPMs from your typical GNU ./configure && make .tar.gz source bundles and not from just a bunch of files, which is what I usually need. This post will show you and future me how to throw some random files into an RPM the same way you would a .tar or a .zip.

Install some software:

yum install rpmdevtools

Create an account to build the rpm with and become that user:

useradd rpmbuild
su - rpmbuild

Create the dirs and spec

rpmdev-setuptree

vim rpmbuild/SPECS/myapp.spec

#jut dumb files. don't compile my python
%global __os_install_post /bin/true
Name: myapp
Version: 2016091100
Release:        1%{?dist}
Summary: my app is some bash scripts needed on our servers

License: GPL
#Source0:
BuildArch: noarch
#BuildRequires: 
#Requires:

%description
collection of scripts to help sysadmins and developers troubleshoot things

#%prep
#%setup -q

#%build
#%configure
#make %{?_smp_mflags}

#%install
#make install DESTDIR=%{buildroot}
rm -Rf $RPM_BUILD_ROOT
mkdir $RPM_BUILD_ROOT
rm -Rf %{_topdir}/RPMS/*
rm -Rf %{_topdir}/SRPMS/*
#just copy files from sources. no reason to tar in between.
cp -Rf %{_topdir}/SOURCES/* $RPM_BUILD_ROOT

%files
%defattr(0644,root,root,-)
%attr(0755,root,root) /usr/sbin/*

#%doc

%clean
rm -Rf $RPM_BUILD_ROOT

%post
#%{_bindir}/systemctl daemon-reload
#%{_bindir}/systemctl enable runlast.timer

%postun
#%{_bindir}/systemctl disable runlast.timer
#%{_bindir}/systemctl daemon-reload

%changelog
*Sun Sep 11 2016 dminnich@localhost
- first release

Some quick notes:

  • Specs or build recipes if you will go into SPECS

  • SOURCES typically holds ./configure && make style .tar.gz. %prep in the spec looks at Source0 and extracts it to BUILD. We won't be using this functionality so its commented out. We will however be placing files in SOURCES, but any folder would work.

  • %build in the spec does the ./configure && make style actions inside of BUILD. We won't be using this so its commented out.

  • %install typically does the make install and copies files from BUILD to BUILDROOT. We are cheating here and just copying files we want over wholesale. We are also removing old build files and previous RPMs and SRPMs. On shared systems you shouldn't really purge RPMs like this, but I do it while I do dev work so I can keep building the same production next version of the RPM.

  • %files sets the permissions the files in the RPMs and files on the end user systems will have. You must have a line or pattern for all the files you add.

  • %doc would contain man pages and similar if you have any.

  • %clean cleans up and prepares for the next build. We simply blow away the directory that had the files in it.

  • %post and %postun are scripts you can run after an install and after an uninstall. We aren't using any here but I left them as examples. This stuff gets tricky fast with upgrades and other things see this if necessary.

  • %changelog should contain changes to the RPM and entries have to be the the specific date email format.

  • Be sure to increment the Version in the spec before each production build.

  • The %global line tells the rpmbuilder not to do anything 'smart' while building the RPM. It for instance won't compile python scripts, strip symbols and do other things. This should be fine if you are building local sysadmin packages and not real world packages that the masses will consume.

  • Fedora Wiki is a great reference for additional information.

Placing your files:

Put the files you want to land on the end systems in their exact location underneath SOURCES. For instance, we will be landing /usr/sbin/troubleshoot.sh so we will be creating SOURCES/usr/bin/troubleshoot.sh

cd rpmbuild/SOURCES
mkdir -p usr/sbin
echo "echo "HI"" >> usr/sbin/troubleshoot.sh

Build and inspect your RPM:

cd ~/rpmbuild/
rpmbuild -ba SPECS/myapp.spec

rpm -qpi RPMS/noarch/myapp-2016091100-1.el7.centos.noarch.rpm 
Name        : myapp
Version     : 2016091100
Release     : 1.el7.centos
Architecture: noarch
Install Date: (not installed)
Group       : Unspecified
Size        : 8
License     : GPL
Signature   : (none)
Source RPM  : myapp-2016091100-1.el7.centos.src.rpm
Build Date  : Sun 11 Sep 2016 02:13:50 PM UTC
Build Host  : a
Relocations : (not relocatable)
Summary     : my app is some bash scripts needed on our servers
Description :
collection of scripts to help sysadmins and developers troubleshoot things

rpm -qpl RPMS/noarch/myapp-2016091100-1.el7.centos.noarch.rpm 
/usr/sbin/troubleshoot.sh

Install the RPM and try it out:

exit #become root
yum localinstall /home/rpmbuild/rpmbuild/RPMS/noarch/myapp-2016091100-1.el7.centos.noarch.rpm
/usr/sbin/troubleshoot.sh 
HI

Bonus...Publish it in a yum repo:

#as root
yum -y install httpd createrepo
mkdir /var/www/html/repo
cp /home/rpmbuild/rpmbuild/RPMS/noarch/myapp-2016091100-1.el7.centos.noarch.rpm /var/www/html/repo/
createrepo /var/www/html/repo/
systemctl enable httpd
systemctl start httpd

Updating your RPM:

su - rpmbuild
vim rpmbuild/SOURCES/usr/sbin/troubleshoot.sh  #make changes
increment the Version in the spec
rpmbuild -ba SPECS/myapp.spec
exit #become root.  only do these next steps if you stood up a repo as well
/bin/cp -f /home/rpmbuild/rpmbuild/RPMS/noarch/*rpm /var/www/html/repo/
createrepo /var/www/html/repo/

Consuming it on clients:

vim /etc/yum.repos.d/myrepo.repo
[myrepo]
name=myrepo
baseurl=http://192.168.4.36/repo/  #your IP
gpgcheck=0

yum install myapp


<<Newer Older>>