| |
@@ -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
|
| |
+
|
| |
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 profileThis is what was used to build it in the following COPR repository : https://copr.fedorainfracloud.org/coprs/arrfab/fasjson-client/