diff --git a/cred/README.md b/cred/README.md index ab277d2..d73599f 100644 --- a/cred/README.md +++ b/cred/README.md @@ -18,9 +18,19 @@ org.opencadc.cred.url=jdbc:postgresql://{server}/{database} ``` The `cred` account owns and manages (create, alter, drop) inventory database objects and manages -all the content (insert, update, delete). The database is specified in the JDBC URL and the schema name is specified -in the minoc.properties (below). Failure to connect or initialize the database will show up in logs and in the -VOSI-availability output. +all the content (insert, update, delete). The database is specified in the JDBC URL and the schema +name is specified in the cred.properties (below). Failure to connect or initialize the database +will show up in logs and in the VOSI-availability output. + +See cadc-tomcat +for system properties related to the deployment environment. + +See cadc-util +for common system properties. + +`dap` includes multiple IdentityManager implementations to support authenticated access: + - See cadc-access-control-identity for CADC access-control system support. + - See cadc-gms for OIDC token support. ### cred.properties @@ -48,24 +58,18 @@ org.opencadc.cred.proxy.allowedUser = cn=alt,ou=acme,o=example,c=com org.opencadc.cred.proxy.maxDaysValid = 0.5 ``` -### cred-logControl.properties - +### cadc-log.properties (optional) +See cadc-log for common +dynamic logging control. -## integration testing +### cadc-vosi.properties (optional) +See cadc-vosi for common +service state control. -A client certificates named `cred-test.pem` must exist in the directory $A/test-certificates. -This can be a normal user certificate (or proxy) and is used to delegate (itself) to the cred service (the -normal use of CDP). - -A client certificate named `cred-test-super.pem` must exist in the directory $A/test-certificates and the -distinguished name must be configured as an `org.opencadc.cred.proxy.allowedUser`. This is used to test that -a special operational user can retrieve a proxy cert for another user. - -There is currently no test for `org.opencadc.cred.delegate.allowedUser` as that requires a CA cert in the -test environment and essentially the whole `cadc-cert-gen` functionality. +### cadcproxy.pem (optional) +This client certificate is used to make authenticated server-to-server calls for system-level A&A purposes. ## building - ``` gradle clean build docker build -t cred -f Dockerfile . @@ -81,13 +85,4 @@ docker run -it cred:latest /bin/bash docker run --user tomcat:tomcat --volume=/path/to/external/config:/config:ro --name cred cred:latest ``` -## apply version tags -```bash -. VERSION && echo "tags: $TAGS" -for t in $TAGS; do - docker image tag cred:latest cred:$t -done -unset TAGS -docker image list cred -``` diff --git a/cred/build.gradle b/cred/build.gradle index 58a4f61..e5eb87f 100644 --- a/cred/build.gradle +++ b/cred/build.gradle @@ -22,21 +22,17 @@ war { } dependencies { - providedCompile 'javax.servlet:javax.servlet-api:[3.1.0,)' - compile 'org.jdom:jdom2:[2.0,)' - compile 'org.json:json:20160212' - - compile 'org.opencadc:cadc-util:[1.6,2.0)' - compile 'org.opencadc:cadc-rest:[1.3.10,)' - compile 'org.opencadc:cadc-vosi:[1.3.9,)' - compile 'org.opencadc:cadc-log:[1.1.1,)' - compile 'org.opencadc:cadc-cdp:[1.3,)' - compile 'org.opencadc:cadc-cdp-server:[1.3.0,1.4)' + compile 'org.opencadc:cadc-util:[1.11.2,2.0)' + compile 'org.opencadc:cadc-rest:[1.3.20,)' + compile 'org.opencadc:cadc-vosi:[1.4.6,)' + compile 'org.opencadc:cadc-log:[1.2.1,)' + compile 'org.opencadc:cadc-cdp:[1.4.0,)' - runtime 'org.opencadc:cadc-registry:[1.2.1,)' - runtime 'org.opencadc:cadc-access-control-identity:[1.1.0,)' + runtime 'org.opencadc:cadc-registry:[1.7.6,)' + runtime 'org.opencadc:cadc-gms:[1.0.12,)' + runtime 'org.opencadc:cadc-access-control-identity:[1.2.5,)' testCompile 'junit:junit:[4.0,)' - intTestCompile 'org.opencadc:cadc-test-vosi:[1.0.2,)' + intTestCompile 'org.opencadc:cadc-test-vosi:[1.0.14,)' } diff --git a/cred/src/main/java/org/opencadc/cred/CredConfig.java b/cred/src/main/java/org/opencadc/cred/CredConfig.java new file mode 100644 index 0000000..ce9aac1 --- /dev/null +++ b/cred/src/main/java/org/opencadc/cred/CredConfig.java @@ -0,0 +1,108 @@ +/* +************************************************************************ +******************* CANADIAN ASTRONOMY DATA CENTRE ******************* +************** CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** +* +* (c) 2024. (c) 2024. +* Government of Canada Gouvernement du Canada +* National Research Council Conseil national de recherches +* Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 +* All rights reserved Tous droits réservés +* +* NRC disclaims any warranties, Le CNRC dénie toute garantie +* expressed, implied, or énoncée, implicite ou légale, +* statutory, of any kind with de quelque nature que ce +* respect to the software, soit, concernant le logiciel, +* including without limitation y compris sans restriction +* any warranty of merchantability toute garantie de valeur +* or fitness for a particular marchande ou de pertinence +* purpose. NRC shall not be pour un usage particulier. +* liable in any event for any Le CNRC ne pourra en aucun cas +* damages, whether direct or être tenu responsable de tout +* indirect, special or general, dommage, direct ou indirect, +* consequential or incidental, particulier ou général, +* arising from the use of the accessoire ou fortuit, résultant +* software. Neither the name de l'utilisation du logiciel. Ni +* of the National Research le nom du Conseil National de +* Council of Canada nor the Recherches du Canada ni les noms +* names of its contributors may de ses participants ne peuvent +* be used to endorse or promote être utilisés pour approuver ou +* products derived from this promouvoir les produits dérivés +* software without specific prior de ce logiciel sans autorisation +* written permission. préalable et particulière +* par écrit. +* +* This file is part of the Ce fichier fait partie du projet +* OpenCADC project. OpenCADC. +* +* OpenCADC is free software: OpenCADC est un logiciel libre ; +* you can redistribute it and/or vous pouvez le redistribuer ou le +* modify it under the terms of modifier suivant les termes de +* the GNU Affero General Public la “GNU Affero General Public +* License as published by the License” telle que publiée +* Free Software Foundation, par la Free Software Foundation +* either version 3 of the : soit la version 3 de cette +* License, or (at your option) licence, soit (à votre gré) +* any later version. toute version ultérieure. +* +* OpenCADC is distributed in the OpenCADC est distribué +* hope that it will be useful, dans l’espoir qu’il vous +* but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE +* without even the implied GARANTIE : sans même la garantie +* warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ +* or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF +* PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence +* General Public License for Générale Publique GNU Affero +* more details. pour plus de détails. +* +* You should have received Vous devriez avoir reçu une +* a copy of the GNU Affero copie de la Licence Générale +* General Public License along Publique GNU Affero avec +* with OpenCADC. If not, see OpenCADC ; si ce n’est +* . pas le cas, consultez : +* . +* +************************************************************************ +*/ + +package org.opencadc.cred; + +import java.util.ArrayList; +import java.util.List; +import javax.security.auth.x500.X500Principal; +import org.apache.log4j.Logger; + +/** + * Configuration object that is created at startup and stored in JNDI for use + * by delegation and proxy servlets. + * + * @author pdowler + */ +public class CredConfig { + private static final Logger log = Logger.getLogger(CredConfig.class); + + private final List delegateUsers = new ArrayList<>(); + private final List proxyUsers = new ArrayList<>(); + public float proxyMaxDaysValid = 30.0f; + + public CredConfig() { + } + + public List getDelegateUsers() { + return delegateUsers; + } + + public List getProxyUsers() { + return proxyUsers; + } + + @Override + public String toString() { + return CredConfig.class.getName() + "[" + + "trusted=" + proxyUsers.size() + "," + + "su=" + delegateUsers.size() + "," + + "proxyMaxDaysValid=" + proxyMaxDaysValid + "]"; + } + + +} diff --git a/cred/src/main/java/org/opencadc/cred/CredInitAction.java b/cred/src/main/java/org/opencadc/cred/CredInitAction.java index d465cfe..13ce313 100644 --- a/cred/src/main/java/org/opencadc/cred/CredInitAction.java +++ b/cred/src/main/java/org/opencadc/cred/CredInitAction.java @@ -67,8 +67,6 @@ package org.opencadc.cred; -import ca.nrc.cadc.cred.server.CredConfig; -import ca.nrc.cadc.cred.server.InitDatabaseCDP; import ca.nrc.cadc.db.DBUtil; import ca.nrc.cadc.rest.InitAction; import ca.nrc.cadc.util.MultiValuedProperties; @@ -80,6 +78,7 @@ import javax.security.auth.x500.X500Principal; import javax.sql.DataSource; import org.apache.log4j.Logger; +import org.opencadc.cred.db.InitDatabaseCDP; /** * Validate config and put CredConfig object into JNDI and init the database @@ -95,7 +94,7 @@ public class CredInitAction extends InitAction { private static final String PROXY_PROP = "org.opencadc.cred.proxy.allowedUser"; private static final String MAX_VALID_PROP = "org.opencadc.cred.proxy.maxDaysValid"; - private final String jndiKey = CredConfig.JDNI_KEY; // temporarily hard coded to work with lib + private String jndiKey; private CredConfig credConfig; public CredInitAction() { @@ -103,6 +102,7 @@ public CredInitAction() { @Override public void doInit() { + this.jndiKey = super.appName + "." + CredConfig.class.getSimpleName(); initConfig(); initDatabase(); } diff --git a/cred/src/main/java/org/opencadc/cred/DelegationsImpl.java b/cred/src/main/java/org/opencadc/cred/GetCertAction.java similarity index 83% rename from cred/src/main/java/org/opencadc/cred/DelegationsImpl.java rename to cred/src/main/java/org/opencadc/cred/GetCertAction.java index 8593538..a6f091a 100644 --- a/cred/src/main/java/org/opencadc/cred/DelegationsImpl.java +++ b/cred/src/main/java/org/opencadc/cred/GetCertAction.java @@ -3,12 +3,12 @@ ******************* CANADIAN ASTRONOMY DATA CENTRE ******************* ************** CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** * -* (c) 2022. (c) 2022. +* (c) 2024. (c) 2024. * Government of Canada Gouvernement du Canada * National Research Council Conseil national de recherches * Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 * All rights reserved Tous droits réservés -* +* * NRC disclaims any warranties, Le CNRC dénie toute garantie * expressed, implied, or énoncée, implicite ou légale, * statutory, of any kind with de quelque nature que ce @@ -31,10 +31,10 @@ * software without specific prior de ce logiciel sans autorisation * written permission. préalable et particulière * par écrit. -* +* * This file is part of the Ce fichier fait partie du projet * OpenCADC project. OpenCADC. -* +* * OpenCADC is free software: OpenCADC est un logiciel libre ; * you can redistribute it and/or vous pouvez le redistribuer ou le * modify it under the terms of modifier suivant les termes de @@ -44,7 +44,7 @@ * either version 3 of the : soit la version 3 de cette * License, or (at your option) licence, soit (à votre gré) * any later version. toute version ultérieure. -* +* * OpenCADC is distributed in the OpenCADC est distribué * hope that it will be useful, dans l’espoir qu’il vous * but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE @@ -54,7 +54,7 @@ * PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence * General Public License for Générale Publique GNU Affero * more details. pour plus de détails. -* +* * You should have received Vous devriez avoir reçu une * a copy of the GNU Affero copie de la Licence Générale * General Public License along Publique GNU Affero avec @@ -62,27 +62,35 @@ * . pas le cas, consultez : * . * -* $Revision: 4 $ -* ************************************************************************ */ package org.opencadc.cred; -import ca.nrc.cadc.cred.server.CertificateDAO.CertificateSchema; -import ca.nrc.cadc.cred.server.DatabaseDelegations; +import ca.nrc.cadc.rest.InlineContentHandler; +import ca.nrc.cadc.rest.RestAction; +import org.apache.log4j.Logger; /** - * Implementation of the base Delegations API. + * Skeleton action to generate and return a short-lived certificate. + * + * @author pdowler */ -public class DelegationsImpl extends DatabaseDelegations -{ - public static final String DATASOURCE = "jdbc/cred"; - public static final String CATALOG = null; - public static final String SCHEMA = "cred"; - - public DelegationsImpl() - { - super(DATASOURCE, new CertificateSchema(DATASOURCE, CATALOG, SCHEMA)); +public class GetCertAction extends RestAction { + private static final Logger log = Logger.getLogger(GetCertAction.class); + + public GetCertAction() { + } + + @Override + protected InlineContentHandler getInlineContentHandler() { + return null; } + + @Override + public void doAction() throws Exception { + throw new UnsupportedOperationException(); + } + + } diff --git a/cred/src/main/java/org/opencadc/cred/ServiceAvailability.java b/cred/src/main/java/org/opencadc/cred/ServiceAvailability.java index 6b3487d..6cc4b4e 100644 --- a/cred/src/main/java/org/opencadc/cred/ServiceAvailability.java +++ b/cred/src/main/java/org/opencadc/cred/ServiceAvailability.java @@ -69,9 +69,9 @@ package org.opencadc.cred; -import ca.nrc.cadc.cred.server.CertificateDAO; import ca.nrc.cadc.vosi.Availability; import ca.nrc.cadc.vosi.AvailabilityPlugin; +import org.opencadc.cred.db.CertificateDAO; public class ServiceAvailability implements AvailabilityPlugin { @@ -93,9 +93,7 @@ public Availability getStatus() { boolean isGood = true; String note = "service is accepting requests"; try { - CertificateDAO.CertificateSchema config = new CertificateDAO.CertificateSchema( - DelegationsImpl.DATASOURCE, DelegationsImpl.CATALOG, DelegationsImpl.SCHEMA); - CertificateDAO dao = new CertificateDAO(config); + CertificateDAO dao = new CertificateDAO("cred"); // hard-coded schema dao.exists("no-such-key"); } catch (Throwable t) { // the test itself failed diff --git a/cred/src/main/java/org/opencadc/cred/db/CertificateDAO.java b/cred/src/main/java/org/opencadc/cred/db/CertificateDAO.java new file mode 100644 index 0000000..dfb45c1 --- /dev/null +++ b/cred/src/main/java/org/opencadc/cred/db/CertificateDAO.java @@ -0,0 +1,256 @@ +/* +************************************************************************ +******************* CANADIAN ASTRONOMY DATA CENTRE ******************* +************** CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** +* +* (c) 2024. (c) 2024. +* Government of Canada Gouvernement du Canada +* National Research Council Conseil national de recherches +* Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 +* All rights reserved Tous droits réservés +* +* NRC disclaims any warranties, Le CNRC dénie toute garantie +* expressed, implied, or énoncée, implicite ou légale, +* statutory, of any kind with de quelque nature que ce +* respect to the software, soit, concernant le logiciel, +* including without limitation y compris sans restriction +* any warranty of merchantability toute garantie de valeur +* or fitness for a particular marchande ou de pertinence +* purpose. NRC shall not be pour un usage particulier. +* liable in any event for any Le CNRC ne pourra en aucun cas +* damages, whether direct or être tenu responsable de tout +* indirect, special or general, dommage, direct ou indirect, +* consequential or incidental, particulier ou général, +* arising from the use of the accessoire ou fortuit, résultant +* software. Neither the name de l'utilisation du logiciel. Ni +* of the National Research le nom du Conseil National de +* Council of Canada nor the Recherches du Canada ni les noms +* names of its contributors may de ses participants ne peuvent +* be used to endorse or promote être utilisés pour approuver ou +* products derived from this promouvoir les produits dérivés +* software without specific prior de ce logiciel sans autorisation +* written permission. préalable et particulière +* par écrit. +* +* This file is part of the Ce fichier fait partie du projet +* OpenCADC project. OpenCADC. +* +* OpenCADC is free software: OpenCADC est un logiciel libre ; +* you can redistribute it and/or vous pouvez le redistribuer ou le +* modify it under the terms of modifier suivant les termes de +* the GNU Affero General Public la “GNU Affero General Public +* License as published by the License” telle que publiée +* Free Software Foundation, par la Free Software Foundation +* either version 3 of the : soit la version 3 de cette +* License, or (at your option) licence, soit (à votre gré) +* any later version. toute version ultérieure. +* +* OpenCADC is distributed in the OpenCADC est distribué +* hope that it will be useful, dans l’espoir qu’il vous +* but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE +* without even the implied GARANTIE : sans même la garantie +* warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ +* or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF +* PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence +* General Public License for Générale Publique GNU Affero +* more details. pour plus de détails. +* +* You should have received Vous devriez avoir reçu une +* a copy of the GNU Affero copie de la Licence Générale +* General Public License along Publique GNU Affero avec +* with OpenCADC. If not, see OpenCADC ; si ce n’est +* . pas le cas, consultez : +* . +* +* $Revision: 5 $ +* +************************************************************************ + */ + +package org.opencadc.cred.db; + +import ca.nrc.cadc.auth.AuthenticationUtil; +import ca.nrc.cadc.auth.SSLUtil; +import ca.nrc.cadc.auth.X509CertificateChain; +import ca.nrc.cadc.db.DBUtil; +import ca.nrc.cadc.profiler.Profiler; +import java.io.IOException; +import java.security.NoSuchAlgorithmException; +import java.security.PrivateKey; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.security.spec.InvalidKeySpecException; +import java.sql.Types; +import java.util.Arrays; +import java.util.Date; +import java.util.List; +import java.util.Map; +import javax.naming.NamingException; +import javax.security.auth.x500.X500Principal; +import javax.sql.DataSource; +import org.apache.log4j.Logger; +import org.springframework.dao.EmptyResultDataAccessException; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.jdbc.core.SingleColumnRowMapper; + +/** + * Class to persist certificates in a relational database table. This class has + * been only tested with Sybase ASE 15 so far. + * + * @author pdowler + * + */ +public class CertificateDAO { + private static final Logger log = Logger.getLogger(CertificateDAO.class); + + private static final String JNDI_DATASOURCE = "jdbc/cred"; // context.xml + + private final String tableName; + private final DataSource dataSource; + + public CertificateDAO(String schema) { + this.tableName = schema + "." + X509CertificateChain.class.getSimpleName(); + try { + this.dataSource = DBUtil.findJNDIDataSource(JNDI_DATASOURCE); + } catch (NamingException ex) { + throw new RuntimeException("BUG: failed to find JNDI DataSource: " + JNDI_DATASOURCE, ex); + } + } + + public void put(X509CertificateChain chain) { + Profiler profiler = new Profiler(this.getClass()); + String hashKey = chain.getHashKey(); + String canonDn = AuthenticationUtil.canonizeDistinguishedName(chain.getPrincipal().getName()); + Date expDate = chain.getExpiryDate(); + String certChainStr = chain.certificateString(); + byte[] bytesPrivateKey = chain.getPrivateKey().getEncoded(); + //TODO just for testing - padded with zeros + byte[] testBytesPrivateKey = Arrays.copyOf(bytesPrivateKey, bytesPrivateKey.length + 1); + testBytesPrivateKey[testBytesPrivateKey.length - 1] = 1; + String csr = chain.getCsrString(); + + try { + JdbcTemplate jdbc = new JdbcTemplate(dataSource); + Date now = new Date(); // TODO: should get from the database + if (exists(hashKey)) { + String sql = "update " + tableName + + " set canon_dn = ?, exp_date = ?, cert_chain = ?, private_key = ?, csr = ?, lastModified = ? where hash_dn=?"; + Object[] args = new Object[]{canonDn, expDate, certChainStr, testBytesPrivateKey, csr, now, hashKey}; + int[] argTypes = new int[]{Types.VARCHAR, Types.TIMESTAMP, Types.VARCHAR, Types.VARBINARY, Types.VARCHAR, Types.TIMESTAMP, Types.VARCHAR}; + log.debug("put: " + sql); + jdbc.update(sql, args, argTypes); + } else { + String sql = "insert into " + tableName + + " (canon_dn, exp_date, cert_chain, private_key, csr, hash_dn, lastModified) values (?,?,?,?,?,?,?)"; + Object[] args = new Object[]{canonDn, expDate, certChainStr, testBytesPrivateKey, csr, hashKey, now}; + int[] argTypes + = new int[]{Types.VARCHAR, Types.TIMESTAMP, Types.VARCHAR, Types.VARBINARY, Types.VARCHAR, Types.VARCHAR, Types.TIMESTAMP}; + log.debug("put: " + sql); + jdbc.update(sql, args, argTypes); + } + } catch (Exception ex) { + throw new RuntimeException("FAIL: failed to put certificate", ex); + } + profiler.checkpoint("put"); + } + + public X509CertificateChain get(X500Principal principal) { + if (principal == null) { + return null; + } + String hashKey = X509CertificateChain.genHashKey(principal); + return get(hashKey); + } + + public X509CertificateChain get(String hashKey) { + Profiler profiler = new Profiler(this.getClass()); + X509CertificateChain x509CertificateChain = null; + + String sql = "select canon_dn, exp_date, cert_chain, private_key, csr from " + tableName + " where hash_dn = ? "; + log.debug("get: " + sql); + try { + JdbcTemplate jdbc = new JdbcTemplate(dataSource); + Map map = jdbc.queryForMap(sql, new String[]{hashKey}); + String canonDn = (String) map.get("canon_dn"); + Date expDate = (Date) map.get("exp_date"); + String certChainStr = (String) map.get("cert_chain"); + byte[] bytesPrivateKey = (byte[]) map.get("private_key"); + + String csrStr = (String) map.get("csr"); + + PrivateKey privateKey = SSLUtil.readPrivateKey(bytesPrivateKey); + X500Principal principal = new X500Principal(canonDn); + + if (certChainStr != null) { + byte[] bytesCertChain = certChainStr.getBytes(); + X509Certificate[] certs = SSLUtil.readCertificateChain(bytesCertChain); + + x509CertificateChain = new X509CertificateChain(Arrays.asList(certs)); + } else { + x509CertificateChain = new X509CertificateChain(principal, privateKey, csrStr); + } + x509CertificateChain.setCsrString(csrStr); + x509CertificateChain.setExpiryDate(expDate); + x509CertificateChain.setHashKey(hashKey); + x509CertificateChain.setKey(privateKey); + x509CertificateChain.setPrincipal(principal); + } catch (EmptyResultDataAccessException e) { + // Record not exists. + return null; + } catch (InvalidKeySpecException ex) { + throw new RuntimeException("BUG: failed to read private key", ex); + } catch (NoSuchAlgorithmException ex) { + throw new RuntimeException("BUG: failed to read private key", ex); + } catch (CertificateException ex) { + throw new RuntimeException("BUG: failed to read certficate chain", ex); + } catch (IOException ex) { + throw new RuntimeException("BUG: failed to read certificate chain", ex); + } catch (Exception ex) { + throw new RuntimeException("FAIL: failed to get " + hashKey, ex); + } + profiler.checkpoint("get"); + return x509CertificateChain; + } + + /* (non-Javadoc) + * @see ca.nrc.cadc.accesscontrol.dao.CertificateDAO#delete(java.lang.String) + */ + public void delete(String hashKey) { + Profiler profiler = new Profiler(this.getClass()); + String sql = "delete from " + tableName + " where hash_dn = ? "; + log.debug("delete: " + sql); + try { + JdbcTemplate jdbc = new JdbcTemplate(dataSource); + jdbc.update(sql, new String[]{hashKey}); + profiler.checkpoint("delete"); + } catch (Exception ex) { + throw new RuntimeException("FAIL: failed to delete " + hashKey, ex); + } + } + + // used by intTest and AvailabilityPlugin(s) + public boolean exists(String hashKey) { + RowMapper rowMapper = new SingleColumnRowMapper(String.class); + String sql = "select canon_dn from " + tableName + " where hash_dn = ? "; + log.debug("exists: " + sql); + try { + JdbcTemplate jdbc = new JdbcTemplate(dataSource); + List dnList = jdbc.query(sql, new String[] { hashKey }, rowMapper); + return (dnList != null && dnList.size() == 1); + } catch (Exception ex) { + throw new RuntimeException("FAIL: failed to query for " + hashKey, ex); + } + } + + public List getAllHashKeys() { + Profiler profiler = new Profiler(this.getClass()); + String query = "select hash_dn from " + tableName; + RowMapper rowMapper = new SingleColumnRowMapper(String.class); + JdbcTemplate jdbc = new JdbcTemplate(dataSource); + List hashKeyList = jdbc.query(query, rowMapper); + profiler.checkpoint("getAllHashKeys"); + return hashKeyList; + } + +} diff --git a/cred/src/main/java/org/opencadc/cred/db/InitDatabaseCDP.java b/cred/src/main/java/org/opencadc/cred/db/InitDatabaseCDP.java new file mode 100644 index 0000000..222e7d4 --- /dev/null +++ b/cred/src/main/java/org/opencadc/cred/db/InitDatabaseCDP.java @@ -0,0 +1,113 @@ +/* +************************************************************************ +******************* CANADIAN ASTRONOMY DATA CENTRE ******************* +************** CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** +* +* (c) 2024. (c) 2024. +* Government of Canada Gouvernement du Canada +* National Research Council Conseil national de recherches +* Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 +* All rights reserved Tous droits réservés +* +* NRC disclaims any warranties, Le CNRC dénie toute garantie +* expressed, implied, or énoncée, implicite ou légale, +* statutory, of any kind with de quelque nature que ce +* respect to the software, soit, concernant le logiciel, +* including without limitation y compris sans restriction +* any warranty of merchantability toute garantie de valeur +* or fitness for a particular marchande ou de pertinence +* purpose. NRC shall not be pour un usage particulier. +* liable in any event for any Le CNRC ne pourra en aucun cas +* damages, whether direct or être tenu responsable de tout +* indirect, special or general, dommage, direct ou indirect, +* consequential or incidental, particulier ou général, +* arising from the use of the accessoire ou fortuit, résultant +* software. Neither the name de l'utilisation du logiciel. Ni +* of the National Research le nom du Conseil National de +* Council of Canada nor the Recherches du Canada ni les noms +* names of its contributors may de ses participants ne peuvent +* be used to endorse or promote être utilisés pour approuver ou +* products derived from this promouvoir les produits dérivés +* software without specific prior de ce logiciel sans autorisation +* written permission. préalable et particulière +* par écrit. +* +* This file is part of the Ce fichier fait partie du projet +* OpenCADC project. OpenCADC. +* +* OpenCADC is free software: OpenCADC est un logiciel libre ; +* you can redistribute it and/or vous pouvez le redistribuer ou le +* modify it under the terms of modifier suivant les termes de +* the GNU Affero General Public la “GNU Affero General Public +* License as published by the License” telle que publiée +* Free Software Foundation, par la Free Software Foundation +* either version 3 of the : soit la version 3 de cette +* License, or (at your option) licence, soit (à votre gré) +* any later version. toute version ultérieure. +* +* OpenCADC is distributed in the OpenCADC est distribué +* hope that it will be useful, dans l’espoir qu’il vous +* but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE +* without even the implied GARANTIE : sans même la garantie +* warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ +* or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF +* PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence +* General Public License for Générale Publique GNU Affero +* more details. pour plus de détails. +* +* You should have received Vous devriez avoir reçu une +* a copy of the GNU Affero copie de la Licence Générale +* General Public License along Publique GNU Affero avec +* with OpenCADC. If not, see OpenCADC ; si ce n’est +* . pas le cas, consultez : +* . +* +************************************************************************ +*/ + +package org.opencadc.cred.db; + +import ca.nrc.cadc.db.version.InitDatabase; +import java.net.URL; +import javax.sql.DataSource; +import org.apache.log4j.Logger; + +/** + * + * @author pdowler + */ +public class InitDatabaseCDP extends InitDatabase { + private static final Logger log = Logger.getLogger(InitDatabaseCDP.class); + public static final String MODEL_NAME = "CDP"; + public static final String MODEL_VERSION = "1.2"; + public static final String PREV_MODEL_VERSION = "n/a"; + //public static final String PREV_MODEL_VERSION = "DO-NOT_UPGRADE-BY-ACCIDENT"; + + static String[] CREATE_SQL = new String[] { + "cred.ModelVersion.sql", + "cred.X509CertificateChain.sql", + "cred.permissions.sql" + }; + + static String[] UPGRADE_SQL = new String[] { + "cred.permissions.sql" + }; + + public InitDatabaseCDP(DataSource ds, String database, String schema) { + super(ds, database, schema, MODEL_NAME, MODEL_VERSION, PREV_MODEL_VERSION); + for (String s : CREATE_SQL) { + createSQL.add(s); + } + for (String s : UPGRADE_SQL) { + upgradeSQL.add(s); + } + } + + @Override + protected URL findSQL(String fname) { + // SQL files are stored inside the jar file + return InitDatabase.class.getClassLoader().getResource(fname); + } + + +} diff --git a/cred/src/main/resources/cred.ModelVersion.sql b/cred/src/main/resources/cred.ModelVersion.sql new file mode 100644 index 0000000..ca91266 --- /dev/null +++ b/cred/src/main/resources/cred.ModelVersion.sql @@ -0,0 +1,9 @@ + +create table .ModelVersion +( + model varchar(32) not null primary key, + version varchar(32) not null, + lastModified timestamp not null +) +; + diff --git a/cred/src/main/resources/cred.X509CertificateChain.sql b/cred/src/main/resources/cred.X509CertificateChain.sql new file mode 100644 index 0000000..9c0a251 --- /dev/null +++ b/cred/src/main/resources/cred.X509CertificateChain.sql @@ -0,0 +1,19 @@ + + +create table .X509CertificateChain ( + hash_dn varchar(32) not null primary key, + canon_dn varchar(512) not null, + private_key bytea not null, + + exp_date timestamp, + csr text, + cert_chain text, + + lastModified timestamp not null +); + +create unique index x509_canon_dn on .X509CertificateChain(canon_dn); + +create index x509_expiry on .X509CertificateChain(exp_date); + +create index x509_lastModified on .X509CertificateChain(lastModified); diff --git a/cred/src/main/resources/cred.permissions.sql b/cred/src/main/resources/cred.permissions.sql new file mode 100644 index 0000000..fa8027b --- /dev/null +++ b/cred/src/main/resources/cred.permissions.sql @@ -0,0 +1,4 @@ +-- very open permisions; suitable for dedicated database with minimal accounts +grant usage on schema to public; +grant select on all tables in schema to public; + diff --git a/cred/src/main/webapp/WEB-INF/web.xml b/cred/src/main/webapp/WEB-INF/web.xml index 2586110..562c0bd 100644 --- a/cred/src/main/webapp/WEB-INF/web.xml +++ b/cred/src/main/webapp/WEB-INF/web.xml @@ -101,43 +101,25 @@ ca.nrc.cadc.vosi - - groupAuthorizer - ca.nrc.cadc.ac.client.GroupAuthorizer - - - logControlProperties - cred-logControl.properties - 1 - InitServlet + CertGenServlet ca.nrc.cadc.rest.RestServlet init org.opencadc.cred.CredInitAction + + + get + org.opencadc.cred.GetCertAction + 2 - - - CredentialDelegation - ca.nrc.cadc.cred.server.CadcDelegationServlet - 3 - - - - ProxyServlet - ca.nrc.cadc.cred.server.ProxyServlet - 3 - - CapabilitiesServlet ca.nrc.cadc.rest.RestServlet @@ -157,10 +139,6 @@ input /capabilities.xml - - authHeaders - false - 3 @@ -175,88 +153,23 @@ 3 - - - CredentialDelegation - /delegate/* - - - - ProxyServlet - /priv/* - - - ProxyServlet - /auth/priv/* + CertGenServlet + /generate/* - CapabilitiesServlet /capabilities - AvailabilityServlet /availability - logControl /logControl - - - - - ProxyCertServlet - org.opencadc.cred.ProxyCertServlet - - - ProxyCertServlet - /proxyCert - - - - - authentication for CADC services - public - - - - - auth - - /auth/* - /proxyCert - GET - POST - HEAD - PUT - OPTIONS - TRACE - DELETE - - - force authentication for all requests - public - - - - - BASIC - Canadian Astronomy Data Centre - -