package com.intel.mtwilson.as.rest; //import javax.ejb.Stateless; import javax.ws.rs.Consumes; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.MediaType; import com.intel.mtwilson.as.ca.TrustAgentCertificateAuthority; import com.intel.dcsg.cpg.crypto.CryptographyException; import com.intel.dcsg.cpg.x509.X509Util; //import javax.annotation.security.RolesAllowed; import com.intel.mtwilson.security.annotations.*; import com.intel.dcsg.cpg.validation.ValidationUtil; import com.intel.mtwilson.launcher.ws.ext.V1; import java.io.FileNotFoundException; import java.io.IOException; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import javax.ws.rs.GET; import org.apache.commons.codec.binary.Base64; //import org.codehaus.enunciate.jaxrs.TypeHint; /** * REST Web Service * * */ @V1 //@Stateless @Path("/AttestationService/resources/ca2") public class CA { private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(CA.class); private TrustAgentCertificateAuthority ca = null; public CA() { /* try { ca = new TrustAgentCertificateAuthority(); } catch(IOException e) { log.error("Cannot initialize CA", e); ca = null; } */ } @GET @Produces({MediaType.TEXT_PLAIN}) public String defaultCaGetAction() { return ""; // note: we are not doing anything here, this function exists only to work around this error: SEVERE: Conflicting URI templates. The URI template /ca for root resource class com.intel.mtwilson.ms.rest.CA and the URI template /ca transform to the same regular expression /ca(/.*)? } /** * Sign a Trust Agent's SSL Certificate. * * Sample request: * POST http://localhost:8080/AttestationService/resources/ca/signTrustAgentSsl * Authorization: HMAC ... hash of self-signed certificate, nonce, and current time using CA password, so server can verify... * (post data is base64-encoded self-signed certificate that is used as a certificate signing request) * * Sample output: * (output is base64-encoded ca-signed ssl certificate) * * See also http://tools.ietf.org/html/rfc2986 (PKCS#10) * * @return the CA-signed X509 Certificate with HTTP Status 200 OK on success, or other HTTP Status codes on error (403 if CA signing password is wrong, 400 if request does not include a self-signed cert) */ //@PermitAll // or should we require the "Security" role? Or a new "CA" role?? and do we need an annotation to indicate that authentication should be done with HMAC ??? so we could maintain an hmac users table too, and define a "ca" user that way admin can easily set the password for this via website @POST @Consumes({MediaType.TEXT_PLAIN}) @Produces({MediaType.TEXT_PLAIN}) @Path("/signTrustAgentSsl") public String signTrustAgentSsl(String csrBase64, @QueryParam("password") String caPassword) { if( ca == null ) { log.error("signTrustAgentSsl request cannot be completed because CA is not initialized"); return null; } ValidationUtil.validate(csrBase64); ValidationUtil.validate(caPassword); try { X509Certificate csr = X509Util.decodePemCertificate(csrBase64); X509Certificate caSignedCertificate = ca.signSslCertificate(csr, caPassword); return Base64.encodeBase64String(caSignedCertificate.getEncoded()); } catch(FileNotFoundException e) { return null; } catch(CertificateException e) { return null; } catch(CryptographyException e) { return null; } } }