Instructions for testing smartcards with pkinit on rhel 7 These instructions illustrate how to test our smartcard configuration using virt-manager and a virtual smartcard. It's possible to also use a physical smartcard, but that requires access to a TPS (Red Hat Certificate System). Asha has one I think, if you want to go that route. The below way is more self-contained, and convenient since you don't have to deal with physcially inserting and removing smartcards while you test. The first thing you'll need is a directory server. I set up IPA for this task. To do that, - start up virt-manager and create a new virtual network for the domain. 1) Click Edit -> Connection Details 2) Click "Virtual Networks" 3) Click the '+' sign to create a new one. 4) Type a network name, for instance, redhat 5) Give it a subnet, for instance, 172.17.0.0/24 6) Do not enable DHCP, that will be provided by the server 7) Forward to physical network using NAT - create a new guest and install rhel7 into it 1) Click File -> New Virtual Machine 2) Choose Local Install media 3) ISO image: http://filerhosthere/os/images/boot.iso 4) I gave it 2gbs of ram and 2 cpus 5) 20gb disk (don't "Allocate entire disk now") 6) I called it directory-server-redhat 7) Click Advanced Options and change network to "Virtual network 'red hat': NAT" 8) Boot the image and start the installation 9) click on network & host name 10) click on Ethernet (ens3) and click Configure... 11) click IPv4 Settings 12) Method: Manual Address: 172.17.0.2 Netmask 255.255.255.0 Gateway 172.17.0.1 13) DNS servers: 10.11.5.19 10.5.30.160 14) click General 15) "Automatically connect to this network when it is available" 16) Click Done 17) Click Installation Source, URL http://filerhosthere/os 18) Click Done 19) Software Selection 20) Infrastructure Server: DNS Name Server, File and Storage Server, Guest Agents, Identity management server, Security Tools 21) defaults for partitioning 22) begin installation 23) set root password to "otherpassword" . Hit "Done" twice 24) create local admin user "shadowman". Make this user an administrator. Set password to "otherpassword" 25) wait for installation to finish 26) reboot - log in as shadowman - complete gnome-initial-setup - register for rhn 1) open a terminal 2) run subscription-manager --register 3) enter username and password (say qa@redhat.com or whatever) 4) run subscription-manager-gui 5) click auto-attach 6) close subscription-manager-gui - maybe add extra yum repo 1) open up /etc/yum.conf 2) add this to it. [rhel-7-server-nightly] name = RHEL 7 nightly metadata_expire = 86400 baseurl = http://filerhosthere/os/ enabled = 1 gpgcheck = 0 - disable firewall 1) systemctl stop firewalld 2) systemctl disable firewalld - set hostname to ipa.redhat.test 1) open /etc/hosts and add: 172.17.0.2 ipa.redhat.test 2) sudo hostnamectl set-hostname ipa.redhat.test - Install dhcp server 1) sudo yum -y install dhcp 2) use this /etc/dhcp/dhcp.conf option domain-name "redhat.test"; option domain-name-servers ipa.redhat.test; option routers 172.17.0.1; authoritative; log-facility local7; subnet 172.17.0.0 netmask 255.255.255.0 { range 172.17.0.127 172.17.0.253; } 3) systemctl enable dhcpd 4) reboot - configure IPA 1) yum install bind-dyndb-ldap 2) run ipa-server-install 3) configure integrated dns 4) set server hostname to ipa.redhat.test 5) set domain name to redhat.test 6) set kerberos realm to REDHAT.TEST 7) set directory manager password to PASSWORD 8) set IPA admin password to PASSWORD 9) configure DNS forwarders to 10.11.5.19 10.5.30.160 10) configure reverse zone 0.17.172.in-addr.arpa. 11) reboot - enable IPA admin UI 1) log in as shadowman to system 2) click on the shadowman in control-center and go to Settings 3) go to online accounts 4) click the + icon 5) choose Other 6) choose Enterprise Login (Kerberos) 7) use redhat.test for domain 8) admin for username 9) PASSWORD for password 10) open firefox and go to http://ipa.redhat.test 11) click on the link "configured" in the text To login with Kerberos, please make sure you have valid tickets (obtainable via kinit) and configured the browser correctly, then click Login. 12) click on the Firefox configuration page link 13) go through all 4 steps in sequence. 14) at this point you should be in the web ui as Administrator. - reboot Next step is to create another guest to serve as the client machine getting tested. - create a new guest and install rhel7 into it 1) Click File -> New Virtual Machine 2) Choose Local Install media 3) ISO image: http://filerhosthere/os/images/boot.iso 4) I gave it 1gb of ram and 1 cpus 5) 20gb disk (don't "Allocate entire disk now") 6) I called it smartcard-client-redhat 7) Click Advanced Options and change network to "Virtual network 'red hat': NAT" 8) Boot the image and start the installation 9) click on network & host name 10) click on Ethernet (ens3) and click Configure... 11) click IPv4 Settings 12) Method: Automatic (DHCP), require IPv4 addressing, 14) click General 15) "Automatically connect to this network when it is available" 16) Click Close 17) toggle the switch on 18) Click Done 19) Click Installation Source, URL http://filerhosthere/os 20) Click Done 21) Software Selection 22) Development and Creative Workstation: Network File System Client, Security Tools, Smart Card Support 23) defaults for partitioning 24) begin installation 25) set root password to "otherpassword" . Hit "Done" twice 26) create local admin user "shadowman". Make this user an administrator. Set password to "otherpassword" 27) wait for installation to finish 28) reboot 29) complete initial-setup, including rhn registration. 30) log in as shadowman 31) complete gnome-initial-setup - define client in IPA 1) click on shadowman in upper right corner of client machine 2) click Settings 3) go to network panel 4) note hardware address. In my case it's 52:54:00:3E:44:09 5) start firefox in the IPA machine 6) go to http://ipa.redhat.test 7) Click Network Services > DNS > DNS Zones > redhat.test. 8) Click "+ Add" 9) Record name smartcard-client, record type a, ip 172.17.0.10, Create reverse 10) Click "Add" 11) Bring up a terminal and su to root 12) edit /etc/dhcp/dhcpd.conf and add this to the bottom: host smartcard-client { hardware ethernet 52:54:00:3E:44:09; fixed-address 172.17.0.10; server-name "smartcard-client.redhat.test"; } 13) systemctl restart dhcpd 14) on client machine run: sudo hostnamectl set-hostname smartcard-client.redhat.test - create network user 1) return to IPA admin console 2) go to Identity > Users 3) click "+ Add" 4) create a user Denis Smith, "dsmith", password PASSWORD 6) log into client machine as shadowman 7) click on "Shadowman" in the upper right corner of the screen 8) go to Settings 9) go to the Users panel 10) Click unlock and type password 10) Click on the "+" icon 11) Click Enterprise Login 12) Use domain redhat.test 13) login name dsmith, password PASSWORD 14) click Add 15) Type admin password PASSWORD 16) open up /etc/sssd/sssd.conf and change use_fully_qualified_names to False and add enumerate = True in the same section 17) reboot 18) Log in as user dsmith 19) complete gnome-initial-setup - configure KDC for pkinit. We need to generate a private key and certificate for the KDC itself using the IPA CA certificate. In theory the dogtag instance that comes with IPA should be able to do this, but it lacks a template for producing a cert with the right extensions. I spent a few hours trying to make one but gave up and switched to openssl which is more straightforward. 1) Put IPA CA certificate into kdc data directory on IPA machine: # openssl pkcs12 -in /root/cacert.p12 -nodes -chain -cacerts -out /var/kerberos/krb5kdc/cacert.pem (use PASSWORD for password) 2) create a file called create-kdc-pkinit-cert.sh with these contents: #!/bin/sh set -e if [ $# -lt 1 -o -z "$1" ]; then echo "please pass kerberos realm" exit 1 fi REALM="$1" export REALM rm -rf "${REALM}" mkdir -p "${REALM}" cd "${REALM}" ca_pkcs12_bundle="cacert.p12" ca_cert="cacert.pem" ca_serial="cacert.srl" request="${REALM}.req" private_key="$REALM}-private.pem" cert="${REALM}.pem" template="${REALM}.certificate-template" function generate_certificate_template() { cat << EOF > ${template} [kdc_extensions] basicConstraints=CA:FALSE keyUsage=nonRepudiation,digitalSignature,keyEncipherment,keyAgreement extendedKeyUsage=1.3.6.1.5.2.3.5 subjectKeyIdentifier=hash authorityKeyIdentifier=keyid,issuer subjectAltName=otherName:1.3.6.1.5.2.2;SEQUENCE:kdc_principal [kdc_principal] realm=EXP:0,GeneralString:${REALM} principal=EXP:1,SEQUENCE:principal_sequence [principal_sequence] name_type=EXP:0,INTEGER:1 name_string=EXP:1,SEQUENCE:principal_parts [principal_parts] primary=GeneralString:krbtgt realm=GeneralString:${REALM} EOF } function unpack_ca_bundle() { [ -e ../${ca_cert} ] && return; openssl pkcs12 -in ../cacert.p12 -nodes -chain -out ../${ca_cert} } function generate_serial_file() { [ -e ../${ca_serial} ] && return; echo 00 > ../${ca_serial} } function link_ca_files() { ln ../${ca_cert} ${ca_cert} ln ../${ca_serial} ${ca_serial} } function generate_private_key() { openssl genrsa -out "$1" 2048 } function generate_certificate_request() { openssl req -new -subj "/CN=KDC pkinit Certificate,O=$REALM/" -out "$2" -key "$1" } function generate_certificate() { extensions_arg="" if [ $# -eq 3 ]; then extensions_arg="-extensions $3" fi openssl x509 -req -in "$1" -CA "${ca_cert}" -out "$2" -days 3650 -extfile "${template}" $extensions_arg } unpack_ca_bundle generate_serial_file link_ca_files generate_private_key "$private_key" generate_certificate_template generate_certificate_request $private_key $request generate_certificate $request $cert "kdc_extensions" cat "$cert" "$private_key" > kdc.pem echo -e "\nCertificate PEM bundle for KDC $REALM in $PWD:" ls kdc.pem 3) run ./create-kdc-pkinit-cert.sh REDHAT.TEST 4) copy REDHAT.TEST/kdc.pem to /var/kerberos/krb5kdc 5) ensure /var/kerberos/krb5kdc/kdc.conf has pkinit_identity set to the kdc.pem file and pkinit_anchors to the cacert.pem in /var/kerberos/krb5kdc - configure KDC to allow dsmith to use pkinit 1) kadmin.local -q 'modprinc +requires_preauth dsmith@REDHAT.TEST' - Generate certificates for dsmith's smartcard. We need three certificates (signing, encryption, and id). Only the signing certificate is used for login. The encryption certificate would be needed if testing the smartcard crypto features. The id certificate is unused, but needed to make the smartcard look like a physical CAC card (a qemu/libcacard requirement) 1) create a file called create-user-cac-certs.sh with these contents: #!/bin/sh set -e if [ $# -lt 1 -o -z "$1" ]; then echo "please pass kerberos principle" exit 1 fi PRIMARY="$(echo $1 | awk -F@ '{ print $1 }')" REALM="$(echo $1 | awk -F@ '{ print $2 }')" export PRIMARY REALM rm -rf "${REALM}/${PRIMARY}" mkdir -p "${REALM}/${PRIMARY}" cd "${REALM}/${PRIMARY}" ca_pkcs12_bundle="cacert.p12" ca_cert="cacert.pem" ca_serial="cacert.srl" encryption_request="${PRIMARY}-encryption.req" signing_request="${PRIMARY}-signing.req" id_request="${PRIMARY}-id.req" encryption_private_key="${PRIMARY}-encryption-private.pem" signing_private_key="${PRIMARY}-signing-private.pem" id_private_key="${PRIMARY}-id-private.pem" template="${PRIMARY}.certificate-template" encryption_cert="${PRIMARY}-encryption.pem" signing_cert="${PRIMARY}-signing.pem" id_cert="${PRIMARY}-id.pem" encryption_pkcs12_bundle="${PRIMARY}-encryption.p12" signing_pkcs12_bundle="${PRIMARY}-signing.p12" id_pkcs12_bundle="${PRIMARY}-id.p12" function generate_certificate_template() { cat << EOF > ${template} [encryption_extensions] basicConstraints=CA:FALSE keyUsage=nonRepudiation,keyEncipherment,keyAgreement extendedKeyUsage=emailProtection subjectKeyIdentifier=hash authorityKeyIdentifier=keyid,issuer [signing_extensions] basicConstraints=CA:FALSE keyUsage=digitalSignature,keyAgreement extendedKeyUsage=1.3.6.1.5.2.3.4,clientAuth subjectKeyIdentifier=hash authorityKeyIdentifier=keyid,issuer subjectAltName=otherName:1.3.6.1.5.2.2;SEQUENCE:kerberos_principal [id_extensions] basicConstraints=CA:FALSE keyUsage=nonRepudiation subjectKeyIdentifier=hash authorityKeyIdentifier=keyid,issuer [kerberos_principal] realm=EXP:0,GeneralString:${REALM} primary=EXP:1,SEQUENCE:primary_sequence [primary_sequence] name_type=EXP:0,INTEGER:1 name_string=EXP:1,SEQUENCE:primaries [primaries] primary1=GeneralString:${PRIMARY} EOF } function unpack_ca_bundle() { [ -e ../../${ca_cert} ] && return; openssl pkcs12 -in ../../cacert.p12 -nodes -chain -out ../../${ca_cert} } function generate_serial_file() { [ -e ../../${ca_serial} ] && return; echo 00 > ../../${ca_serial} } function link_ca_files() { ln ../../${ca_cert} ${ca_cert} ln ../../${ca_serial} ${ca_serial} } function generate_private_key() { openssl genrsa -out "$1" 2048 } function generate_certificate_request() { openssl req -new -out "$3" -subj "/CN=$1/" -key "$2" } function generate_certificate() { openssl x509 -req -in "$1" -CA ${ca_cert} -out "$3" -days 3650 -extfile "${template}" -extensions $2 } function pack_certificate_bundle() { openssl pkcs12 -export -inkey "$2" -CAfile ${ca_cert} -in "$1" -nodes -out "$4" -name "$3" -caname "$3" -passout "pass:" } unpack_ca_bundle generate_serial_file link_ca_files generate_private_key "$encryption_private_key" generate_private_key "$signing_private_key" generate_private_key "$id_private_key" generate_certificate_template generate_certificate_request "${PRIMARY}@${REALM} Encryption Certificate" $encryption_private_key $encryption_request generate_certificate $encryption_request "encryption_extensions" $encryption_cert pack_certificate_bundle $encryption_cert $encryption_private_key "${PRIMARY}-encryption" $encryption_pkcs12_bundle generate_certificate_request "${PRIMARY}" $signing_private_key $signing_request generate_certificate $signing_request "signing_extensions" $signing_cert pack_certificate_bundle $signing_cert $signing_private_key "${PRIMARY}-signing" $signing_pkcs12_bundle generate_certificate_request "${PRIMARY}@${REALM}" $id_private_key $id_request generate_certificate $id_request "id_extensions" $id_cert pack_certificate_bundle $id_cert $id_private_key "${PRIMARY}" $id_pkcs12_bundle echo -e "\nCertificate PKCS12 bundles for user $PRIMARY@$REALM in $PWD:" ls *.p12 3) run ./create-user-cac-certs.sh dsmith@REDHAT.TEST 4) copy dsmith-encryption.p12 dsmith-id.p12 and dsmith-signing.p12 to the host hosting the 2 VMs - create nssdb to serve as the backing store for smartcard on host machine 1) mkdir -p domains/redhat.test/cac-card 2) cd domains/redhat.test/cac-card 3) certutil -d . -N 4) The password will be your pin code for the smartcard. Use "0000" 5) copy the ca cert to domains/redhat.test (say from /var/kerberos/krb5kdc/cacert.pem on the ipa vm or /etc/ipa/ca.crt on the client vm) 6) import the ca certificate into the nssdb certutil -d . -A -i ../ca.crt -n "ipa-ca" -t CT,C,C 7) move dsmith-encryption.p12 dsmith-id.p12 and dsmith-signing.p12 to domains/redhat.test 8) import the 3 certificates into the nssdb (from within domains/redhat.test/cac-card): pk12util -d . -i ../dsmith-encryption.p12 pk12util -d . -i ../dsmith-id.p12 pk12util -d . -i ../dsmith-signing.p12 (use 0000 for pin and just hit enter for pkcs12 password) - configure client machine to allow smartcard login 1) yum install authconfig-gtk krb5-pkinit 2) run authconfig-gtk 3) go to Advanced Options tab 4) Check "Enable smart card support" 5) Click Apply 6) configure pam_pkcs11 mapping between unix user and smartcard. do this by opening up /etc/pam_pkcs11/pam_pkcs11.conf and edit the use_mappers line to only have use_mappers = pwent; 7) open up /etc/krb5.conf and add pkinit_cert_match = digitalSignature to a new line below the line that says pkinit_anchors = FILE:/etc/ipa/ca.crt pkinit is often used with a lone certificate instead of a smartcard full of certificates. This flag gives it a way of picking which certificate on the smartcard to use. 7) run authconfig-tui and tick the "Use kerberos" box and click next 8) Use Realm REDHAT.TEST 9) open up /etc/pam.d/smartcard-auth and /etc/pam.d/system-auth They should now have auth lines mentioning pam_krb5.so add to the ends of those lines: preauth_options=X509_user_identity=PKCS11:/usr/lib64/pkcs11/libcoolkeypk11.so (one addition in each file) 7) power off VM 8) go to the details screen of the VM (lightbulb) 9) Click Add Hardware > Smartcard > Mode: Passthrough 10) Click Finish 11) Power back on VM - pass virtual smartcard through to client machine 1) on host machine go into domains/redhat.test/cac-card directory 2) run as root virt-viewer smartcard-client-redhat --spice-smartcard --spice-smartcard-certificates=dsmith,dsmith-signing,dsmith-encryption --spice-smartcard-db=$PWD 3) at this point the client machine should notice the smartcard inserted. To simulate a removal hit shift-f9, to simulate an insertion hit shift-f8 - Log in using the smartcard 1) ensure the virtual smartcard is inserted (if not, focus the outside of the virt-viewer window and hit shift-f8) 2) type in 0000 - verify there's a kerberos ticket 1) open a terminal and type klist -A There should be a line marked krbtgt/REDHAT.TEST@REDHAT.TEST 2) click dsmith in the upper right corner of the screen 3) go to settings 4) go to online accounts 5) there should be an Enterprise Login entry there - verify the ticket can be destroyed using online accounts 1) Click the off switch beside Network Resources 2) open a terminal and rerun klist -A and verify the krbtgt line is gone - verify the ticket can be recreated using online accounts 1) Click the on switch beisde Network Resources 2) Verify it asks for a PIN password 3) type 0000 4) rerun klist -A and verify the krbtgt line came back