Skip to content

Commit

Permalink
Merge pull request #299 from bbockelm/ce_registry
Browse files Browse the repository at this point in the history
Implement CE registration app (SOFTWARE-4089)
  • Loading branch information
brianhlin authored May 8, 2020
2 parents c8f3cae + 87364ac commit 1fb23a7
Show file tree
Hide file tree
Showing 15 changed files with 968 additions and 1 deletion.
22 changes: 22 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ install(PROGRAMS
src/condor_ce_reconfig
src/condor_ce_router_q
src/condor_ce_status
src/condor_ce_register
src/condor_ce_reschedule
src/condor_ce_run
src/condor_ce_trace
Expand All @@ -89,8 +90,13 @@ install(FILES
src/htcondorce/rrd.py
src/htcondorce/tools.py
src/htcondorce/info_query.py
src/htcondorce/registry.py
src/audit_payloads.py
DESTINATION ${PYTHON_SITELIB}/htcondorce)
install(FILES
src/htcondorce/static/bootstrap-pincode-input.css
src/htcondorce/static/bootstrap-pincode-input.js
DESTINATION ${PYTHON_SITELIB}/htcondorce/static)

install(FILES
config/condor_config
Expand All @@ -99,6 +105,13 @@ install(FILES
config/condor_mapfile.osg
DESTINATION ${SYSCONF_INSTALL_DIR}/condor-ce)

install(FILES config/htcondorce_registry.conf DESTINATION ${SYSCONF_INSTALL_DIR}/httpd/conf.d)
# This file should contain various OIDC secrets; should not be world-readable.
install(CODE "execute_process(COMMAND chmod 0700 ${SYSCONF_INSTALL_DIR}/httpd/conf.d/htcondorce_registry.conf)")
install(CODE "execute_process(COMMAND chown root:root ${SYSCONF_INSTALL_DIR}/httpd/conf.d/htcondorce_registry.conf)")

install(FILES src/htcondor-ce-registry.wsgi DESTINATION ${STATE_INSTALL_DIR}/www/wsgi-scripts/htcondor-ce)

install(FILES
contrib/apelscripts/README.md
DESTINATION ${SHARE_INSTALL_PREFIX}/condor-ce/apel)
Expand Down Expand Up @@ -172,6 +185,14 @@ foreach(root_dir IN ITEMS ${HTCONDORCE_ROOT_DIRS})
install(CODE "execute_process(COMMAND chown root:root ${root_dir})")
endforeach(root_dir)

# These are the tokens for use by the CE registry webapp
set(HTCONDORCE_WEBAPP_DIRS ${SYSCONF_INSTALL_DIR}/condor-ce/webapp.tokens.d
${STATE_INSTALL_DIR}/lib/condor-ce/webapp)
foreach(webapp_dir IN ITEMS ${HTCONDORCE_WEBAPP_DIRS})
install(DIRECTORY DESTINATION ${webapp_dir})
install(CODE "execute_process(COMMAND chown condorce_webapp:condorce_webapp ${webapp_dir})")
endforeach(webapp_dir)

set(STICKY_HTCONDORCE_DIRS ${STATE_INSTALL_DIR}/log/condor-ce/user ${STATE_INSTALL_DIR}/lock/condor-ce/user
${SYSCONF_INSTALL_DIR}/logrotate.d)

Expand All @@ -188,6 +209,7 @@ endforeach(private_dir)

install(FILES config/ce-status.cpf config/pilot-status.cpf DESTINATION ${SHARE_INSTALL_PREFIX}/condor-ce)
install(FILES templates/index.html templates/vos.html templates/metrics.html
templates/code.html templates/code_submit.html templates/code_submit_failure.html
templates/health.html templates/header.html templates/pilots.html DESTINATION ${SHARE_INSTALL_PREFIX}/condor-ce/templates)
install(FILES config/condor-ce config/condor-ce-collector DESTINATION ${SYSCONF_INSTALL_DIR}/sysconfig)

Expand Down
1 change: 1 addition & 0 deletions config/01-ce-collector-defaults.conf
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,4 @@ EXPIRE_INVALIDATED_ADS = true

COLLECTOR_PERSISTENT_AD_LOG = $(SPOOL)/collector_ads.log
VALID_SPOOL_FILES=collector_ads.log $(VALID_SPOOL_FILES)

3 changes: 3 additions & 0 deletions config/01-common-auth-defaults.conf
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,6 @@ AUTH_SSL_SERVER_CAFILE = /etc/pki/tls/certs/ca-bundle.crt
# N.B. authN negotation here is ultimately decided by the client so this
# configuration only applies to usage of 'condor_ce_q'
TOOL.CONDOR_Q_ONLY_MY_JOBS = false

# Override the token directory
SEC_TOKEN_SYSTEM_DIRECTORY = /etc/condor-ce/tokens.d
7 changes: 7 additions & 0 deletions config/05-ce-collector-auth.conf
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,10 @@ COLLECTOR.SEC_ADVERTISE_MASTER_AUTHENTICATION_METHODS = SSL, GSI
COLLECTOR.ALLOW_ADVERTISE_SCHEDD = $(COLLECTOR.ALLOW_ADVERTISE_SCHEDD), $(UNMAPPED_USERS), $(USERS)
COLLECTOR.ALLOW_ADVERTISE_STARTD = $(COLLECTOR.ALLOW_ADVERTISE_STARTD), $(UNMAPPED_USERS), $(USERS)
COLLECTOR.ALLOW_ADVERTISE_MASTER = $(COLLECTOR.ALLOW_ADVERTISE_MASTER), $(USERS)

# Allow the CE registry webapp to approve CE token requests.
COLLECTOR.SEC_DAEMON_AUTHENTICATION_METHODS = FS,TOKEN
[email protected]/localhost [email protected]/$(FULL_HOSTNAME)

# When requesting a token to register a new CE, only allow it to advertise a schedd.
SEC_TOKEN_REQUEST_LIMITS = ADVERTISE_SCHEDD
49 changes: 49 additions & 0 deletions config/htcondorce_registry.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@

#####################################################
## OIDC and WSGI configuration for the CE Registry ##
#####################################################

## Review, uncomment, end update the various configuration lines in this
## file in order to configure the CE Registry application.
##
## Note you MUST change the following lines:
## - OIDCClientID
## - OIDCClientSecret
## - OIDCCryptoPassphrase
## - OIDCRedirectURI
##
## This file will NOT be overwritten on upgrade.
##

#OIDCProviderMetadataURL https://cilogon.org/.well-known/openid-configuration

## Navigate to https://registry.cilogon.org/registry/ to create a new OIDC client.
# OIDCClientID cilogon:/client_id/EXAMPLE_ID
## CILogon doesn't store the client secret -- if you lose it, you will need to register a
## new client
# OIDCClientSecret EXAMPLE_CLIENT_SECRET
## Generate a random passphrase for encrypting the on-disk secrets.
## This can be done with the following:
## openssl rand 32 -base64
#OIDCCryptoPassphrase CLIENT_PASSPHRASE_HERE

## OIDCRedirectURI is a vanity URL that must point to somewhere inside /registry but
## but not contain content; installs should simply change the hostname
# OIDCRedirectURI https://collector.example.com/registry/callback

## This puts /registry
#<Location /registry/>
# AuthType openid-connect
# Require valid-user
#</Location>
#WSGIDaemonProcess CERegistry user=condorce_webapp group=condorce_webapp processes=2 threads=25 display-name=CERegistry
#WSGIProcessGroup CERegistry
#WSGIScriptAlias /registry /var/www/wsgi-scripts/htcondor-ce/htcondor-ce-registry.wsgi

## Recommendation from upstream mod_wsgi developers.
#LogLevel info

## Required for wsgi-scripts directory to allow executing WSGI.
#<Directory /var/www/wsgi-scripts>
# Require all granted
#</Directory>
40 changes: 40 additions & 0 deletions rpm/htcondor-ce.spec
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ Requires: python-cherrypy
Requires: python-genshi
Requires: ganglia-gmond
Requires: rrdtool-python
Requires: python-flask

%description view
%{summary}
Expand Down Expand Up @@ -176,6 +177,15 @@ Summary: Central HTCondor-CE information services collector
Provides: %{name}-master = %{version}-%{release}
Requires: %{name}-client = %{version}-%{release}
Requires: libxml2-python
Requires: python-six

# Various requirements for the CE registry application
# for registering the CE with this collector.
Requires: mod_auth_openidc
Requires: mod_wsgi
Requires: python-flask
Requires: python-genshi

Conflicts: %{name}

%description collector
Expand Down Expand Up @@ -226,6 +236,13 @@ mv ${RPM_BUILD_ROOT}%{_sysconfdir}/condor-ce/condor_mapfile{.osg,}
install -m 0755 -d -p $RPM_BUILD_ROOT/%{_sysconfdir}/logrotate.d
install -m 0755 -d -p $RPM_BUILD_ROOT/%{_sysconfdir}/condor-ce/bosco_override

%pre collector

getent group condorce_webapp >/dev/null || groupadd -r condorce_webapp
getent passwd condorce_webapp >/dev/null || \
useradd -r -g condorce_webapp -d %_var/lib/condor-ce/webapp -s /sbin/nologin \
-c "Webapp user for HTCondor-CE collector" condorce_webapp

%post
/bin/systemctl daemon-reload >/dev/null 2>&1 || :

Expand All @@ -239,6 +256,16 @@ fi
/bin/systemctl daemon-reload >/dev/null 2>&1 || :
%systemd_post condor-ce-collector.service condor-ce-collector-config.service

if [ ! -e /etc/condor-ce/passwords.d/POOL ]; then
%{_datadir}/condor-ce/condor_ce_create_password >/dev/null 2>&1 || :
fi

autogenerated_token=/etc/condor-ce/webapp.tokens.d/50-webapp
if [ ! -e $autogenerated_token ]; then
CONDOR_CONFIG=/etc/condor-ce/condor_config condor_token_create \
-authz ADMINISTRATOR -identity [email protected] > $autogenerated_token 2>&1 || :
fi

%preun
%systemd_preun condor-ce.service

Expand Down Expand Up @@ -286,6 +313,7 @@ fi
%{python_sitelib}/htcondorce/audit_payloads.py*

%{_bindir}/condor_ce_host_network_check
%{_bindir}/condor_ce_register

%attr(-,condor,condor) %dir %{_localstatedir}/run/condor-ce
%attr(-,condor,condor) %dir %{_localstatedir}/log/condor-ce
Expand Down Expand Up @@ -321,13 +349,19 @@ fi
%{python_sitelib}/htcondorce/web.py*
%{python_sitelib}/htcondorce/web_utils.py*
%{python_sitelib}/htcondorce/rrd.py*
%{python_sitelib}/htcondorce/registry.py*
%{python_sitelib}/htcondorce/static/bootstrap-pincode-input.js
%{python_sitelib}/htcondorce/static/bootstrap-pincode-input.css

%{_datadir}/condor-ce/templates/index.html
%{_datadir}/condor-ce/templates/vos.html
%{_datadir}/condor-ce/templates/metrics.html
%{_datadir}/condor-ce/templates/health.html
%{_datadir}/condor-ce/templates/header.html
%{_datadir}/condor-ce/templates/pilots.html
%{_datadir}/condor-ce/templates/code.html
%{_datadir}/condor-ce/templates/code_submit.html
%{_datadir}/condor-ce/templates/code_submit_failure.html

%{_datadir}/condor-ce/config.d/05-ce-view-defaults.conf
%config(noreplace) %{_sysconfdir}/condor-ce/config.d/05-ce-view.conf
Expand Down Expand Up @@ -433,6 +467,7 @@ fi

%{_datadir}/condor-ce/config.d/01-ce-collector-defaults.conf
%{_datadir}/condor-ce/config.d/01-ce-auth-defaults.conf
%{_datadir}/condor-ce/condor_ce_create_password

%{_unitdir}/condor-ce-collector.service
%{_tmpfilesdir}/condor-ce-collector.conf
Expand All @@ -442,6 +477,10 @@ fi
%config %{_sysconfdir}/condor-ce/condor_mapfile.central_collector
%config(noreplace) %{_sysconfdir}/sysconfig/condor-ce-collector
%config(noreplace) %{_sysconfdir}/condor-ce/config.d/01-ce-collector.conf
%attr(0700,condorce_webapp,condorce_webapp) %dir %{_sysconfdir}/condor-ce/webapp.tokens.d
%attr(0700,root,root) %dir %{_sysconfdir}/condor-ce/passwords.d

%attr(0700,root,root) %{_sysconfdir}/httpd/conf.d/htcondorce_registry.conf

%attr(-,condor,condor) %dir %{_localstatedir}/run/condor-ce
%attr(-,condor,condor) %dir %{_localstatedir}/log/condor-ce
Expand All @@ -452,6 +491,7 @@ fi
%attr(-,condor,condor) %dir %{_localstatedir}/lock/condor-ce
%attr(1777,condor,condor) %dir %{_localstatedir}/lock/condor-ce/user
%attr(1777,root,root) %dir %{_localstatedir}/lib/gratia/condorce_data
%{_localstatedir}/www/wsgi-scripts/htcondor-ce/htcondor-ce-registry.wsgi

%changelog
* Wed Mar 18 2020 Brian Lin <[email protected]> - 4.2.1-1
Expand Down
81 changes: 81 additions & 0 deletions src/condor_ce_register
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
#!/usr/bin/python3

import argparse
import os
import socket
import subprocess
import sys

import htcondor

DEFAULT_COLLECTOR_PORT="9619"

def parse_args():
default_hostname = socket.getfqdn()

parser = argparse.ArgumentParser(description="Register a HTCondor-CE with a collector")
parser.add_argument("-pool", help="Remote collector to query", metavar="coll",
default="collector.opensciencegrid.org")
parser.add_argument("-name", help="CE name to register as", metavar="name",
default=default_hostname)
parser.add_argument("-debug", action="store_true", help="Enable debug mode")
return parser.parse_args()


def request_token(pool, name, debug=False):
coll = htcondor.Collector(pool)
coll_ad = coll.locate(htcondor.DaemonTypes.Collector)

identity = '%[email protected]' % name

htcondor.param['SEC_TOKEN_DIRECTORY'] = '/etc/condor-ce/tokens.d'

req = htcondor.TokenRequest(identity, bounding_set=['ADVERTISE_SCHEDD'])
req.submit(coll_ad)
reqid = req.request_id

pool_without_port = pool.split(":")[0]
print("Request is queued with collector %s; please approve it by visiting"
" https://%s/registry/code" % (pool, pool_without_port))
token = None
for idx in range(10):
print("Request ID is %s" % reqid)
try:
token = req.result(600)
except RuntimeError:
print("Failure occurred: %s; will retry with a new request")
req = htcondor.TokenRequest(identity, bounding_set=['ADVERTISE_SCHEDD'])
req.submit(coll_ad)
reqid = req.request_id
break

if token is None:
print("Token request failed after 10 retries.")
return False

token.write("50-%s-registration" % pool_without_port)
print("CE registration is complete!")
return True


def reconfig():
subprocess.call(["condor_ce_reconfig"])


def main():
args = parse_args()

if os.geteuid() != 0:
print("This command must be run as root")
sys.exit(1)

pool = args.pool
if not pool.startswith("<") and pool.find(":") < 0:
pool += ":" + DEFAULT_COLLECTOR_PORT

if request_token(pool, args.name, debug=args.debug):
print("Successfully acquired token; sending a reconfig to the CE.")
reconfig()

if __name__ == '__main__':
main()
15 changes: 15 additions & 0 deletions src/htcondor-ce-registry.wsgi
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@

from htcondorce.registry import create_app

# Uncomment one-or-more options to customize the webapp
# Most of these options are useful for running the HTCondor-CE Registry webapp
# out of a custom HTCondor (or HTCondor-CE) install.
test_config={
#'CONDOR_TOKEN_REQUEST_LIST': '/home/example/condor-build/release_dir/bin/condor_token_request_list',
#'HTCONDORCE_TEMPLATES': '/home/cse496/example/htcondor-ce/templates',
#'DEBUG': True
}
if not test_config:
test_config = None

application = create_app(test_config=test_config)
Loading

0 comments on commit 1fb23a7

Please sign in to comment.