From 0c414beabed7a4b05212cf92a0edd6d8c9a26fed Mon Sep 17 00:00:00 2001 From: Fabian Arrotin Date: Feb 01 2021 08:22:00 +0000 Subject: Switched centos-cert to bash wrapper around fasjson-client for IPA/fasjson auth switch Signed-off-by: Fabian Arrotin --- diff --git a/SOURCES/cbs b/SOURCES/cbs new file mode 100644 index 0000000..9c60c9d --- /dev/null +++ b/SOURCES/cbs @@ -0,0 +1,3 @@ +#!/bin/bash +koji --config /etc/koji.conf.d/cbs-koji.conf "$*" + diff --git a/SOURCES/centos-cert b/SOURCES/centos-cert index ec0f8ce..e0fc0df 100644 --- a/SOURCES/centos-cert +++ b/SOURCES/centos-cert @@ -1,136 +1,121 @@ -#!/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.cert ] ; then + 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 + 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} + + +# Now the real work and calling functions +if [ "$#" -eq "0" ] ;then + usage + exit 1 +fi +check_url +get_cert +verify_cert + diff --git a/SPECS/centos-packager.spec b/SPECS/centos-packager.spec index a0d9b03..7313c95 100644 --- a/SPECS/centos-packager.spec +++ b/SPECS/centos-packager.spec @@ -1,16 +1,6 @@ -%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 +Version: 0.7.0 Release: 1%{?dist} Summary: Tools and files necessary for building CentOS packages Group: Applications/Productivity @@ -20,12 +10,15 @@ URL: https://git.centos.org/centos/centos-packager Source0: cbs-koji.conf Source1: COPYING Source2: centos-cert +Source3: cbs Requires: koji 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 @@ -44,10 +37,8 @@ cp %{SOURCE1} . %{__install} -m 0644 %{SOURCE0} %{buildroot}/etc/koji.conf.d/cbs-koji.conf %{__mkdir_p} %{buildroot}/%{_bindir} -ln -sf %{_bindir}/koji %{buildroot}%{_bindir}/cbs +%{__install} -m 0755 %{SOURCE3} %{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 +48,10 @@ sed -i.backup -E '1s|#!/usr/bin/python\>|\0%{python_major_version}|' %{SOURCE2} %{_bindir}/centos-cert %changelog +* Thu Nov 19 2020 Fabian Arrotin - 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 - 0.6.0-1 - Cut a new release