/* * Copyright (C) 2014 Intel Corporation * All rights reserved. */ package com.intel.mtwilson.v2.client; import com.intel.dcsg.cpg.crypto.CryptographyException; import com.intel.dcsg.cpg.crypto.RsaCredentialX509; import com.intel.dcsg.cpg.crypto.RsaUtil; import com.intel.dcsg.cpg.crypto.SimpleKeystore; import com.intel.dcsg.cpg.io.FileResource; import com.intel.dcsg.cpg.io.Resource; import com.intel.dcsg.cpg.tls.policy.TlsPolicy; import com.intel.dcsg.cpg.tls.policy.TlsUtil; import com.intel.dcsg.cpg.tls.policy.impl.InsecureTlsPolicy; import com.intel.mtwilson.My; import com.intel.mtwilson.api.ApiException; import com.intel.mtwilson.api.ClientException; import com.intel.mtwilson.attestation.client.jaxrs.CaCertificates; import com.intel.mtwilson.user.management.client.jaxrs.RegisterUsers; import com.intel.mtwilson.user.management.rest.v2.model.RegisterUserWithCertificate; import com.intel.mtwilson.user.management.rest.v2.model.User; import com.intel.mtwilson.user.management.rest.v2.model.UserLoginCertificate; import java.io.File; import java.io.IOException; import java.net.URL; import java.security.KeyManagementException; import java.security.KeyPair; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.UnrecoverableEntryException; import java.security.cert.CertificateEncodingException; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.util.Locale; import java.util.Properties; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * * @author jbuhacoff */ public class MwClientUtil { private static final Logger log = LoggerFactory.getLogger(MwClientUtil.class); private static SimpleKeystore createUserKeystoreInResource(Resource resource, String username, String password) throws CryptographyException, IOException { try { // create the keystore and a new credential SimpleKeystore keystore = new SimpleKeystore(resource, password); // KeyManagementException KeyPair keypair = RsaUtil.generateRsaKeyPair(RsaUtil.MINIMUM_RSA_KEY_SIZE); // NoSuchAlgorithmException X509Certificate certificate = RsaUtil.generateX509Certificate(/*"CN="+*/username, keypair, RsaUtil.DEFAULT_RSA_KEY_EXPIRES_DAYS); // GeneralSecurityException keystore.addKeyPairX509(keypair.getPrivate(), certificate, username, password); // KeyManagementException keystore.save(); // KeyStoreException, IOException, CertificateException return keystore; } catch(KeyManagementException | NoSuchAlgorithmException | KeyStoreException | CertificateException e) { throw new CryptographyException("Cannot create keystore", e); } } /** * Helper function to create a request of user's access along with the keystore with user's RSA keypair and MTW server's TLS, SAML, Privacy CA and Root certificates. * @param directory Directory where the keystore need to be created * @param username Name of the user. The keystore would be created with the same name as well. * @param password Password for the account. This password would be used to encrypt the keystore as well. * @param server IP address of the MTW server * @param comments Any additional comments such as the roles needed by the user. * @param properties For this keystore creation and user registration the TLS policy has to be specified in the properties. User can choose any of the * supported TLS policies including certificate,certificate-digest,public-key,public-key-digest,TRUST_FIRST_CERTIFICATE,INSECURE. * @return Created user keystore object. * @since Mt.Wilson 2.0 * @mtwRequiresPermissions None * @mtwSampleApiCall * <pre> * // Need to register the extension of the TlsPolicy being used to authenticate to the MTW server. In the example we are using the Insecure policy. * Extensions.register(TlsPolicyCreator.class, com.intel.mtwilson.tls.policy.creator.impl.InsecureTlsPolicyCreator.class); * * Properties properties = new Properties(); * properties.setProperty("mtwilson.api.tls.policy.certificate.sha1", "a1 81 3f 6e 67 3d 29 16 f6 e9 0b 5b e3 f2 1e 72 f9 3d 29 70"); * String userName = "apiclient1"; * String password = "password"; * URL server = new URL("https://10.1.71.234:8181/mtwilson/v2/"); * * SimpleKeystore keystore = MwClientUtil.createUserInDirectoryV2(new java.io.File("c:\\intel\\mtwilson"), userName, password, server, "Admin role needed", properties); * </pre> */ public static SimpleKeystore createUserInDirectoryV2(File directory, String username, String password, URL server, String comments, Properties properties) throws IOException, ApiException, CryptographyException, ClientException { if( username.contains("..") || username.contains(File.separator) || username.contains(" ") ) { throw new IllegalArgumentException("Username must not include path-forming characters"); } File keystoreFile = new File(directory.getAbsoluteFile() + File.separator + username + ".jks"); FileResource resource = new FileResource(keystoreFile); return createUserInResourceV2(resource, username, password, server, properties, comments, null, "TLS"); } /*public static SimpleKeystore createUserInResourceV2(Resource resource, String username, String password, URL server, String comments) throws IOException, ApiException, CryptographyException, ClientException { return createUserInResourceV2(resource, username, password, server, new InsecureTlsPolicy(), comments, null); } public static SimpleKeystore createUserInResourceV2(Resource resource, String username, String password, URL server, TlsPolicy tlsPolicy, String comments, Locale locale) throws IOException, ApiException, CryptographyException, ClientException { return createUserInResourceV2(resource, username, password, server, tlsPolicy, comments, locale, "TLS"); }*/ /** * Helper function to create a request of user's access along with the keystore with user's RSA keypair and MTW server's TLS, SAML, Privacy CA and Root certificates. * @param resource Resource object which would have the user's keystore * @param username Name of the user. The keystore would be created with the same name as well. * @param password Password for the account. This password would be used to encrypt the keystore as well. * @param server IP address of the MTW server * @param comments Any additional comments such as the roles needed by the user. * @param properties For this keystore creation and user registration the TLS policy has to be specified in the properties. User can choose any of the * supported TLS policies including certificate,certificate-digest,public-key,public-key-digest,TRUST_FIRST_CERTIFICATE,INSECURE. * @param locale Locale of the user (Currently not being used) * @param tlsProtocol TLS protocol to be used. By default we use "TLS" * @return Created user keystore object. * @since Mt.Wilson 2.0 * @mtwRequiresPermissions None * @mtwSampleApiCall * <pre> * // Need to register the extension of the TlsPolicy being used to authenticate to the MTW server. In the example we are using the Insecure policy. * Extensions.register(TlsPolicyCreator.class, com.intel.mtwilson.tls.policy.creator.impl.InsecureTlsPolicyCreator.class); * * Properties properties = new Properties(); * properties.setProperty("mtwilson.api.tls.policy.certificate.sha1", "a1 81 3f 6e 67 3d 29 16 f6 e9 0b 5b e3 f2 1e 72 f9 3d 29 70"); * String userName = "apiclient1"; * String password = "password"; * URL server = new URL("https://10.1.71.234:8181/mtwilson/v2/"); * FileResource resource = new FileResource(new java.io.File("c:\\intel\\mtwilson\\"+userName+".jks")); * * SimpleKeystore keystore = MwClientUtil.createUserInResourceV2(resource, userName, password, server, "Admin role needed", properties, null, "TLS"); * </pre> */ public static SimpleKeystore createUserInResourceV2(Resource resource, String username, String password, URL server, Properties properties, String comments, Locale locale, String tlsProtocol) throws IOException, ApiException, CryptographyException, ClientException { URL baseUrl = new URL(server.getProtocol() + "://" + server.getAuthority()); SimpleKeystore keystore = createUserKeystoreInResource(resource, username, password); log.debug("URL Protocol: {}", baseUrl.getProtocol()); if( "https".equals(baseUrl.getProtocol()) ) { TlsUtil.addSslCertificatesToKeystore(keystore, baseUrl, tlsProtocol); //CryptographyException, IOException } try { String[] aliases = keystore.aliases(); for(String alias : aliases) { log.debug("Certificate: "+keystore.getX509Certificate(alias).getSubjectX500Principal().getName()); } } catch(KeyStoreException | NoSuchAlgorithmException | UnrecoverableEntryException | CertificateEncodingException e) { log.debug("cannot display keystore: "+e.toString()); } try { RegisterUsers client = new RegisterUsers(properties);//My.configuration().getClientProperties()); RegisterUserWithCertificate rpcUserWithCert = new RegisterUserWithCertificate(); User newUser = new User(); newUser.setUsername(username); newUser.setLocale(locale); newUser.setComment(comments); RsaCredentialX509 rsaCredential = keystore.getRsaCredentialX509(username, password); UserLoginCertificate userLoginCertificate = new UserLoginCertificate(); userLoginCertificate.setCertificate(rsaCredential.getCertificate().getEncoded()); userLoginCertificate.setComment(comments); rpcUserWithCert.setUser(newUser); rpcUserWithCert.setUserLoginCertificate(userLoginCertificate); boolean result = client.registerUserWithCertificate(rpcUserWithCert); if( !result ) { throw new IllegalStateException("Failed to register user with certificate"); } } catch (Exception ex) { log.error("Error during creation of user.", ex); } try { CaCertificates certClient = new CaCertificates(properties); X509Certificate rootCertificate = certClient.retrieveCaCertificate("root"); X509Certificate samlCertificate = certClient.retrieveCaCertificate("saml"); X509Certificate privacyCertificate = certClient.retrieveCaCertificate("privacy"); log.debug("Adding CA Certificate with alias {} from server {}", rootCertificate.getSubjectX500Principal().getName(), server.getHost()); keystore.addTrustedCaCertificate(rootCertificate, rootCertificate.getSubjectX500Principal().getName()); log.debug("Adding Privacy CA Certificate with alias {} from server {}", privacyCertificate.getSubjectX500Principal().getName(), server.getHost()); keystore.addTrustedCaCertificate(privacyCertificate, privacyCertificate.getSubjectX500Principal().getName()); if (samlCertificate.getBasicConstraints() == -1) { // -1 indicates the cert is not a CA cert log.debug("Adding SAML Certificate with alias {} from server {}", samlCertificate.getSubjectX500Principal().getName(), server.getHost()); keystore.addTrustedSamlCertificate(samlCertificate, samlCertificate.getSubjectX500Principal().getName()); } else { log.debug("Adding SAML Certificate as CA cert with alias {} from server {}", samlCertificate.getSubjectX500Principal().getName(), server.getHost()); keystore.addTrustedCaCertificate(samlCertificate, samlCertificate.getSubjectX500Principal().getName()); } } catch (Exception ex) { log.error("Error during retrieval of certificates for writing to the key store.", ex); } try { keystore.save(); return keystore; } catch(KeyStoreException | IOException | NoSuchAlgorithmException | CertificateException e) { throw new CryptographyException("Cannot save keystore to resource: "+e.toString(), e); } } }