#5 Preparing the switch to IPA/FASJSON auth switch
Merged 3 years ago by bstinson. Opened 3 years ago by arrfab.
centos/ arrfab/centos-packager ipa_fasjson_switch  into  master

file modified
+141 -136
@@ -1,136 +1,141 @@ 

- #!/usr/bin/python

- # -*- coding: utf-8 -*-

- from __future__ import print_function

- 

- import os

- import pwd

- import sys

- import optparse

- import requests

- 

- from getpass import getpass

- 

- from centos import CentOSUserCert

- from centos import defaults

- 

- try:

-     import urlparse

- except ImportError:

-     import urllib.parse as urlparse

- 

- 

- def download_cert(username, password, topurl=None):

-     if not topurl:

-         topurl = defaults.FAS_TOPURL

- 

-     splittopurl = urlparse.urlsplit(topurl)

- 

-     usercertpath = os.path.join(splittopurl.path, 'user/dogencert')

-     params = {'user_name': username, 'password': password, 'login': 'Login'}

- 

-     userspliturl = urlparse.SplitResult(splittopurl.scheme,

-                                         splittopurl.netloc,

-                                         usercertpath,

-                                         None,

-                                         None)

- 

-     servercapath = os.path.join(splittopurl.path, 'ca/ca-cert.pem')

-     servercaspliturl = urlparse.SplitResult(splittopurl.scheme,

-                                             splittopurl.netloc,

-                                             servercapath,

-                                             None,

-                                             None)

- 

-     userurl = urlparse.urlunsplit(userspliturl)

-     servercaurl = urlparse.urlunsplit(servercaspliturl)

- 

-     certfile = os.path.expanduser(defaults.USER_CERT_FILE)

-     if os.path.exists(certfile):

-         # Delete file in case we are changing its mode

-         os.unlink(certfile)

-     flags = os.O_WRONLY | os.O_CREAT

-     mode = 0o600

-     with os.fdopen(os.open(certfile, flags, mode), 'w') as usercertfile:

-         r = requests.post(userurl, params=params)

-         try:

-             r.raise_for_status()

-         except requests.exceptions.HTTPError as e:

-             print("""Could not generate certificate!

- Response Code: {0}

- Message: {1}""".format(e.response.status_code, e.response.reason).strip())

-             sys.exit(1)

- 

-         response = r.text

-         usercertfile.write(response)

- 

-     with open(os.path.expanduser(defaults.SERVER_CA_CERT_FILE), 'w') as servercacertfile:

-         r = requests.get(servercaurl)

-         try:

-             r.raise_for_status()

-         except requests.exceptions.HTTPError as e:

-             print("""Could not download CA Certificate!

- Response Code: {0}

- Message: {1}""".format(e.response.status_code, e.response.reason).strip())

-             sys.exit(1)

- 

-         response = r.text

-         servercacertfile.write(response)

- 

-     # for now upload-ca.cert is the same as the server-ca cert. let's link them here

-     if os.path.exists(os.path.expanduser(defaults.UPLOAD_CA_CERT_FILE)):

-         os.unlink(os.path.expanduser(defaults.UPLOAD_CA_CERT_FILE))

- 

-     os.symlink(os.path.expanduser(defaults.SERVER_CA_CERT_FILE),

-                os.path.expanduser(defaults.UPLOAD_CA_CERT_FILE))

- 

- 

- def main(opts):

- 

-     if not opts.certfile:

-         certfile = defaults.USER_CERT_FILE

-     else:

-         certfile = opts.certfile

- 

-     if opts.username and not opts.verifycert:

-         username = opts.username

-     else:

-         try:

-             cert = CentOSUserCert(certfile)

-             username = cert.CN

-         except IOError as e:

-             if opts.verifycert:

-                 print("{0}: {1}".format(os.path.expanduser(certfile), e.strerror))

-                 exit(1)

-             username = pwd.getpwuid(os.geteuid())[0]

- 

-     if opts.verifycert:

-         if not cert.valid:

-             print("Your certificate is not valid")

-             sys.exit(1)

-         else:

-             print("Your certificate is valid")

-             sys.exit(0)

- 

-     if opts.newcert:

-         password = getpass('ACO Password: ')

-         download_cert(username, password)

- 

- 

- if __name__ == '__main__':

-     parser = optparse.OptionParser(usage="%prog [OPTIONS] ")

-     parser.add_option('-u', '--username', action='store', dest='username',

-                       default=False, help="ACO Username.")

-     parser.add_option('-n', '--new-cert', action='store_true', dest='newcert',

-                       default=False, help="Generate a new User Certificate.")

-     parser.add_option('-f', '--file', action='store', dest='certfile',

-                       default=None, help="User Certificate.")

-     parser.add_option('-v', '--verify-cert', action='store_true', dest='verifycert',

-                       default=False, help="Verify Certificate.")

-     opts, args = parser.parse_args()

- 

-     if not opts.newcert and not opts.verifycert:

-         print("Must specify one of arguments: -v or -n")

-         parser.print_help()

-         sys.exit(1)

- 

-     main(opts)

+ #!/bin/bash

+ 

+ # This is a simple bash wrapper for CentOS SIG and using fasjson-client with some values

+ # Goal is to retrieve signed TLS cert for user accounts, using kerberos ticket and then using the fasjson endpoint

+ 

+ function usage() {

+ cat << EOF

+ 

+ You need to call the script like this : $0 -arguments

+  -u : username ([REQUIRED] : your existing ACO/FAS username)

+  -v : just validates the existing TLS certificate ([OPTIONAL])

+  -r : REALM to use for kerberos ([OPTIONAL] : defaults to FEDORAPROJECT.ORG)

+  -f : fasjson url ([OPTIONAL]: defaults to https://fasjson.fedoraproject.org)

+  -h : display this help

+ 

+ EOF

+ 

+ }

+ 

+ function varcheck() {

+ if [ -z "$1" ] ; then

+         usage

+         exit 1

+ fi

+ }

+ 

+ function f_log() {

+    echo "[+] $(date +%Y%m%d-%H:%M) centos-cert -> $*" 

+ }

+ 

+ function verify_cert() {

+   echo ""

+   f_log "Verifying if TLS cert is still valid ..."

+   if [ ! -e ~/.centos-server-ca.cert ] ; then

+     f_log "[ERROR] No CA cert found to validate your TLS cert"

+     f_log "Please retrieve it first with [$0 -u]"

+     exit 1

+   fi

+   if [ -e ~/.centos.cert ] ; then

+     f_log "Validating TLS cert against ~/.centos-server-ca.cert ..."

+     openssl verify -CAfile ~/.centos-server-ca.cert ~/.centos.cert

+     if [ "$?" -ne "0" ] ; then

+       f_log "[ERROR] your TLS cert is not signed by correct CA"

+       exit 1

+     else

+       f_log "[SUCCESS] ~/.centos.cert TLS cert verified by ~/.centos-server-ca.cert CA crt"   

+     fi

+     end_date=$(openssl x509 -in ~/.centos.cert -noout -text|sed -n 's/ *Not After : *//p')

+     end_date_seconds=$(date '+%s' --date "$end_date")

+     now_seconds=$(date '+%s')

+     remaining_days=$(echo "($end_date_seconds-$now_seconds)/24/3600" | bc)

+     if [ "${remaining_days}" -gt "0" ] ; then

+       f_log "[SUCCESS] Your TLS cert is still valid for [${remaining_days}] days"

+       echo ""

+       exit 0

+     else

+       f_log "[ERROR] Your TLS cert has expired : [${remaining_days}] days"

+       echo ""

+       exit 1

+     fi

+   else

+     f_log "[WARNING] : no TLS cert found so running this script to first get one"

+     echo ""

+   fi

+ }

+ 

+ function check_url() {

+   echo ""

+   f_log Validating user [${fasjson_user}] with realm [${fasjson_realm}] against ${fasjson_url}

+   curl --fail --negotiate -u : ${fasjson_url}/v1/me/ --silent >/dev/null 

+   if [ "$?" -ne "0" ] ; then

+     f_log "Not able to negotiate kerberos with ${fasjson_url} ..."

+     f_log "Forcing kinit to obtain valid kerberos ticket :"

+     kinit ${fasjson_user}@${fasjson_realm} || (f_log "Not able to get kerberos ticket .." ; exit 1)

+   else

+     f_log "We can reach [${fasjson_url}] with realm [${fasjson_user}@${fasjson_realm}], so now asking for TLS cert ..." 

+   fi

+ }

+ 

+ function get_cert(){

+   fasjson-client --verbose --url ${fasjson_url} get-cert -u ${fasjson_user} -p ~/.centos-${fasjson_user}.key -s ~/.centos-${fasjson_user}.crt --overwrite

+   if [ "$?" -ne "0" ] ; then

+     f_log "[ISSUE] : Unable to retrieve TLS cert"

+     exit 1

+   else

+     f_log "Concatenating cert to ~/.centos.cert"

+     cat ~/.centos-${fasjson_user}.key ~/.centos-${fasjson_user}.crt > ~/.centos.cert

+   fi

+   f_log "Downloading correct CA cert .."

+   curl --fail --silent ${ca_url} > ~/.centos-server-ca.cert CA crt

+   echo ""

+ }

+ 

+ 

+ while getopts "hu:r:vf:" option

+ do

+   case ${option} in

+     h)

+       usage

+       exit 1

+       ;;

+     u)

+       opt_user=${OPTARG}

+       ;;

+     r)

+       opt_realm=${OPTARG}

+       ;;

+     v)

+       verify_cert

+       exit

+       ;;

+     f)

+       opt_fasjson_url=${OPTARG}

+       ;;

+     ?)

+       usage

+       exit

+       ;;

+   esac

+ done

+ 

+ # Parsing and assigning default values if needed

+ fasjson_user=${opt_user:-$USER}

+ fasjson_realm=${opt_realm:-FEDORAPROJECT.ORG}

+ fasjson_url=${opt_fasjson_url:-https://fasjson.fedoraproject.org}

+ if [[ "$fasjson_url" =~ "fasjson.stg*" ]] ; then

+   ca_url="https://id.stg.fedoraproject.org/ipa/config/ca.crt"

+ else

+   ca_url="https://id.fedoraproject.org/ipa/config/ca.crt"

+ fi

+ 

+ 

+ # Now the real work and calling functions

+ if [ "$#" -eq "0" ] ;then

+   usage

+   exit 1

+ fi

+ check_url

+ get_cert

+ verify_cert

+ 

file modified
+15 -15
@@ -1,17 +1,7 @@ 

- %if 0%{?fedora} >= 28 || 0%{?rhel} >= 8

- # Use Python 3

- %global     python_major_version 3

- %global     python_dist()   python3dist(%1)

- %else

- # Use Python 2

- %global     python_major_version 2

- %global     python_dist()   python2-%1

- %endif

- 

  

  Name:           centos-packager

- Version:        0.6.0

- Release:        1%{?dist}

+ Version:        0.7.0

+ Release:        3%{?dist}

  Summary:        Tools and files necessary for building CentOS packages

  Group:          Applications/Productivity

  
@@ -25,7 +15,9 @@ 

  Requires:       rpm-build rpmdevtools rpmlint

  Requires:       mock curl openssh-clients

  Requires:       redhat-rpm-config

- Requires:       %{python_dist centos}

+ Requires:				bc

+ Requires:				krb5-workstation

+ Requires:       fasjson-client python3-fasjson-client

  

  BuildArch:      noarch

  
@@ -46,8 +38,6 @@ 

  %{__mkdir_p} %{buildroot}/%{_bindir}

  ln -sf %{_bindir}/koji %{buildroot}%{_bindir}/cbs

  

- # Fix shebang to require explicit python version

- sed -i.backup -E '1s|#!/usr/bin/python\>|\0%{python_major_version}|' %{SOURCE2}

  %{__install} -m 0755 %{SOURCE2} %{buildroot}%{_bindir}/centos-cert

  

  %files
@@ -57,6 +47,16 @@ 

  %{_bindir}/centos-cert

  

  %changelog

+ * Sat Mar 27 2021	Fabian Arrotin <fabian.arrotin@arrfab.net> - 0.7.0-2

+ - Bumped centos-cert for additional verification with CA 

+ 

+ * Mon Feb 1	2021 Fabian Arrotin <fabian.arrotin@arrfab.net> - 0.7.0-2

+ - Fixed the cbs call for correct profile

+ 

+ * Thu Nov 19 2020 Fabian Arrotin <fabian.arrotin@arrfab.net> - 0.7.0-1

+ - added Requires: on fasjson-client (talking to IPA and not FAS anymore)

+ - replaced centos-cert script with just a wrapper around fasjson-client for TLS cert 

+ 

  * Tue Aug 11 2020 Brian Stinson <bstinson@centosproject.org> - 0.6.0-1

  - Cut a new release

  

Technically we don't need to use centos-cert but still good to have something that looks like what we had. Basically just a simple bash wrapper around the new needed fasjson-client pkg, that uses kerberos authentication to talk to fasjson API (itself forwarding kerberos ticket to talk to IPA api endpoint for cert signing)
Simple koji profile and cbs script using that profile

This is what was used to build it in the following COPR repository : https://copr.fedorainfracloud.org/coprs/arrfab/fasjson-client/

@bstinson when you have time, can you just review and merge ? as we're now one week away from migration and that package will be the one that people will be pointed to for centos-cert

Thanks

1 new commit added

  • Bumped to centos-cert with CA verify step
3 years ago

1 new commit added

  • Removed unneeded bash wrapper as we have symlink for koji/cbs
3 years ago

1 new commit added

  • Removed unused Source in spec
3 years ago

Pull-Request has been merged by bstinson

3 years ago