Search in sources :

Example 1 with CryptoException

use of com.yahoo.athenz.auth.util.CryptoException in project athenz by yahoo.

the class ZTSClient method getAWSLambdaServiceCertificate.

/**
 * For AWS Lambda functions generate a new private key, request a
 * x.509 certificate based on the requested CSR and return both to
 * the client in order to establish tls connections with other
 * Athenz enabled services.
 * @param domainName name of the domain
 * @param serviceName name of the service
 * @param account AWS account name that the function runs in
 * @param provider name of the provider service for AWS Lambda
 * @return AWSLambdaIdentity with private key and certificate
 */
public AWSLambdaIdentity getAWSLambdaServiceCertificate(String domainName, String serviceName, String account, String provider) {
    if (domainName == null || serviceName == null) {
        throw new IllegalArgumentException("Domain and Service must be specified");
    }
    if (account == null || provider == null) {
        throw new IllegalArgumentException("AWS Account and Provider must be specified");
    }
    if (x509CsrDomain == null) {
        throw new IllegalArgumentException("X509 CSR Domain must be specified");
    }
    // first we're going to generate a private key for the request
    AWSLambdaIdentity lambdaIdentity = new AWSLambdaIdentity();
    try {
        lambdaIdentity.setPrivateKey(Crypto.generateRSAPrivateKey(2048));
    } catch (CryptoException ex) {
        throw new ZTSClientException(ZTSClientException.BAD_REQUEST, ex.getMessage());
    }
    // we need to generate an csr with an instance register object
    InstanceRegisterInformation info = new InstanceRegisterInformation();
    info.setDomain(domainName.toLowerCase());
    info.setService(serviceName.toLowerCase());
    info.setProvider(provider.toLowerCase());
    final String athenzService = info.getDomain() + "." + info.getService();
    // generate our dn which will be based on our service name
    StringBuilder dnBuilder = new StringBuilder(128);
    dnBuilder.append("cn=");
    dnBuilder.append(athenzService);
    if (x509CsrDn != null) {
        dnBuilder.append(',');
        dnBuilder.append(x509CsrDn);
    }
    // now let's generate our dsnName field based on our principal's details
    StringBuilder hostBuilder = new StringBuilder(128);
    hostBuilder.append(info.getService());
    hostBuilder.append('.');
    hostBuilder.append(info.getDomain().replace('.', '-'));
    hostBuilder.append('.');
    hostBuilder.append(x509CsrDomain);
    StringBuilder instanceHostBuilder = new StringBuilder(128);
    instanceHostBuilder.append("lambda-");
    instanceHostBuilder.append(account);
    instanceHostBuilder.append('-');
    instanceHostBuilder.append(info.getService());
    instanceHostBuilder.append(".instanceid.athenz.");
    instanceHostBuilder.append(x509CsrDomain);
    GeneralName[] sanArray = new GeneralName[2];
    sanArray[0] = new GeneralName(GeneralName.dNSName, new DERIA5String(hostBuilder.toString()));
    sanArray[1] = new GeneralName(GeneralName.dNSName, new DERIA5String(instanceHostBuilder.toString()));
    try {
        info.setCsr(Crypto.generateX509CSR(lambdaIdentity.getPrivateKey(), dnBuilder.toString(), sanArray));
    } catch (OperatorCreationException | IOException ex) {
        throw new ZTSClientException(ZTSClientException.BAD_REQUEST, ex.getMessage());
    }
    // finally obtain attestation data for lambda
    info.setAttestationData(getAWSLambdaAttestationData(athenzService, account));
    // request the x.509 certificate from zts server
    Map<String, List<String>> responseHeaders = new HashMap<>();
    InstanceIdentity identity = postInstanceRegisterInformation(info, responseHeaders);
    try {
        lambdaIdentity.setX509Certificate(Crypto.loadX509Certificate(identity.getX509Certificate()));
    } catch (CryptoException ex) {
        throw new ZTSClientException(ZTSClientException.BAD_REQUEST, ex.getMessage());
    }
    return lambdaIdentity;
}
Also used : ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) HashMap(java.util.HashMap) DERIA5String(org.bouncycastle.asn1.DERIA5String) IOException(java.io.IOException) DERIA5String(org.bouncycastle.asn1.DERIA5String) List(java.util.List) ArrayList(java.util.ArrayList) GeneralName(org.bouncycastle.asn1.x509.GeneralName) CryptoException(com.yahoo.athenz.auth.util.CryptoException) OperatorCreationException(org.bouncycastle.operator.OperatorCreationException)

Example 2 with CryptoException

use of com.yahoo.athenz.auth.util.CryptoException in project athenz by yahoo.

the class CryptoTest method testGetPKCS10CertRequestInvalid.

@Test
public void testGetPKCS10CertRequestInvalid() throws IOException {
    try {
        Crypto.getPKCS10CertRequest(null);
        fail();
    } catch (CryptoException ex) {
        assertTrue(ex.getMessage().contains("CSR is null"));
    }
    try {
        Crypto.getPKCS10CertRequest("");
        fail();
    } catch (CryptoException ex) {
        assertTrue(ex.getMessage().contains("CSR is null"));
    }
    // now let's try with invalid csr
    Path path = Paths.get("src/test/resources/invalid.csr");
    String certStr = new String(Files.readAllBytes(path));
    try {
        Crypto.getPKCS10CertRequest(certStr);
        fail();
    } catch (CryptoException ex) {
        assertTrue(true, "Caught expected crypto exception");
    }
}
Also used : Path(java.nio.file.Path) DERIA5String(org.bouncycastle.asn1.DERIA5String) CryptoException(com.yahoo.athenz.auth.util.CryptoException) Test(org.testng.annotations.Test)

Example 3 with CryptoException

use of com.yahoo.athenz.auth.util.CryptoException in project athenz by yahoo.

the class CryptoTest method testLoadX509CertificateInvalid.

@Test
public void testLoadX509CertificateInvalid() throws IOException {
    Path path = Paths.get("src/test/resources/invalid_x509.cert");
    String certStr = new String(Files.readAllBytes(path));
    try {
        Crypto.loadX509Certificate(certStr);
        fail();
    } catch (CryptoException ex) {
        assertTrue(true, "Caught expected CryptoException");
    }
}
Also used : Path(java.nio.file.Path) DERIA5String(org.bouncycastle.asn1.DERIA5String) CryptoException(com.yahoo.athenz.auth.util.CryptoException) Test(org.testng.annotations.Test)

Example 4 with CryptoException

use of com.yahoo.athenz.auth.util.CryptoException in project athenz by yahoo.

the class ZTSImpl method processProviderX509RefreshRequest.

InstanceIdentity processProviderX509RefreshRequest(ResourceContext ctx, final Principal principal, final String domain, final String service, final String provider, final Principal providerService, final String instanceId, InstanceRefreshInformation info, X509CertRecord x509CertRecord, final String caller) {
    // parse and validate our CSR
    X509CertRequest certReq = null;
    try {
        certReq = new X509CertRequest(info.getCsr());
    } catch (CryptoException ex) {
        throw requestError("unable to parse PKCS10 CSR", caller, domain);
    }
    StringBuilder errorMsg = new StringBuilder(256);
    if (!certReq.validate(providerService, domain, service, instanceId, authorizer, errorMsg)) {
        throw requestError("CSR validation failed - " + errorMsg.toString(), caller, domain);
    }
    // retrieve the certificate that was used for authentication
    // and verify that the dns names in the certificate match to
    // the values specified in the CSR
    X509Certificate cert = principal.getX509Certificate();
    if (!certReq.compareDnsNames(cert)) {
        throw requestError("dnsName attribute mismatch in CSR", caller, domain);
    }
    // validate attestation data is included in the request
    InstanceProvider instanceProvider = instanceProviderManager.getProvider(provider);
    if (instanceProvider == null) {
        throw requestError("unable to get instance for provider: " + provider, caller, domain);
    }
    InstanceConfirmation instance = generateInstanceConfirmObject(ctx, provider, domain, service, info.getAttestationData(), certReq);
    try {
        instance = instanceProvider.refreshInstance(instance);
    } catch (com.yahoo.athenz.instance.provider.ResourceException ex) {
        if (ex.getCode() == com.yahoo.athenz.instance.provider.ResourceException.FORBIDDEN) {
            throw forbiddenError("unable to verify attestation data: " + ex.getMessage(), caller, domain);
        }
    } finally {
        instanceProvider.close();
    }
    // determine what type of certificate the provider is authorizing
    // this instance to refresh - possible values are: server, client or
    // null (indicating both client and server). Additionally, we're
    // going to see if the provider wants to impose an expiry time
    // though the certificate signer might decide to ignore that
    // request and override it with its own value.
    String certUsage = null;
    int certExpiryTime = 0;
    Map<String, String> instanceAttrs = instance.getAttributes();
    if (instanceAttrs != null) {
        certUsage = instanceAttrs.remove(ZTSConsts.ZTS_CERT_USAGE);
        final String expiryTime = instanceAttrs.remove(ZTSConsts.ZTS_CERT_EXPIRY_TIME);
        if (expiryTime != null && !expiryTime.isEmpty()) {
            certExpiryTime = Integer.parseInt(expiryTime);
        }
    }
    // validate that the tenant domain/service matches to the values
    // in the cert record when it was initially issued
    final String principalName = principal.getFullName();
    // now we need to make sure the serial number for the certificate
    // matches to what we had issued previously. If we have a mismatch
    // then we're going to revoke this instance as it has been possibly
    // compromised
    String serialNumber = cert.getSerialNumber().toString();
    if (x509CertRecord.getCurrentSerial().equals(serialNumber)) {
        // update the record to mark current as previous
        // and we'll update the current set with our existing
        // details
        x509CertRecord.setPrevIP(x509CertRecord.getCurrentIP());
        x509CertRecord.setPrevTime(x509CertRecord.getCurrentTime());
        x509CertRecord.setPrevSerial(x509CertRecord.getCurrentSerial());
    } else if (!x509CertRecord.getPrevSerial().equals(serialNumber)) {
        // we have a mismatch for both current and previous serial
        // numbers so we're going to revoke it
        LOGGER.error("Revoking certificate refresh for cn: {} instance id: {}," + " current serial: {}, previous serial: {}, cert serial: {}", principalName, x509CertRecord.getInstanceId(), x509CertRecord.getCurrentSerial(), x509CertRecord.getPrevSerial(), serialNumber);
        x509CertRecord.setPrevSerial("-1");
        x509CertRecord.setCurrentSerial("-1");
        instanceCertManager.updateX509CertRecord(x509CertRecord);
        throw forbiddenError("Certificate revoked", caller, domain);
    }
    // generate identity with the certificate
    InstanceIdentity identity = instanceCertManager.generateIdentity(info.getCsr(), principalName, x509CertRecord.getClientCert() ? ZTSConsts.ZTS_CERT_USAGE_CLIENT : certUsage, certExpiryTime);
    if (identity == null) {
        throw serverError("unable to generate identity", caller, domain);
    }
    // if we're asked then we should also generate a ssh
    // certificate for the instance as well
    instanceCertManager.generateSshIdentity(identity, info.getSsh(), null);
    // set the other required attributes in the identity object
    identity.setProvider(provider);
    identity.setInstanceId(instanceId);
    // need to update our cert record with new certificate details
    X509Certificate newCert = Crypto.loadX509Certificate(identity.getX509Certificate());
    x509CertRecord.setCurrentSerial(newCert.getSerialNumber().toString());
    x509CertRecord.setCurrentIP(ServletRequestUtil.getRemoteAddress(ctx.request()));
    x509CertRecord.setCurrentTime(new Date());
    if (!instanceCertManager.updateX509CertRecord(x509CertRecord)) {
        throw serverError("unable to update cert db", caller, domain);
    }
    if (info.getToken() == Boolean.TRUE) {
        PrincipalToken svcToken = new PrincipalToken.Builder("S1", domain, service).expirationWindow(svcTokenTimeout).keyId(privateKeyId).host(serverHostName).ip(ServletRequestUtil.getRemoteAddress(ctx.request())).keyService(ZTSConsts.ZTS_SERVICE).build();
        svcToken.sign(privateKey);
        identity.setServiceToken(svcToken.getSignedToken());
    }
    // create our audit log entry
    AuditLogMsgBuilder msgBldr = getAuditLogMsgBuilder(ctx, domain, caller, HTTP_POST);
    msgBldr.whatEntity(instanceId);
    StringBuilder auditLogDetails = new StringBuilder(512);
    auditLogDetails.append("Provider: ").append(provider).append(" Domain: ").append(domain).append(" Service: ").append(service).append(" InstanceId: ").append(instanceId).append(" Serial: ").append(x509CertRecord.getCurrentSerial()).append(" Type: x509");
    msgBldr.whatDetails(auditLogDetails.toString());
    auditLogger.log(msgBldr);
    return identity;
}
Also used : InstanceConfirmation(com.yahoo.athenz.instance.provider.InstanceConfirmation) AuditLogMsgBuilder(com.yahoo.athenz.common.server.log.AuditLogMsgBuilder) AuditLogMsgBuilder(com.yahoo.athenz.common.server.log.AuditLogMsgBuilder) PrincipalToken(com.yahoo.athenz.auth.token.PrincipalToken) X509Certificate(java.security.cert.X509Certificate) Date(java.util.Date) X509CertRequest(com.yahoo.athenz.zts.cert.X509CertRequest) CryptoException(com.yahoo.athenz.auth.util.CryptoException) InstanceProvider(com.yahoo.athenz.instance.provider.InstanceProvider)

Example 5 with CryptoException

use of com.yahoo.athenz.auth.util.CryptoException in project athenz by yahoo.

the class ZTSImpl method postInstanceRegisterInformation.

@Override
public void postInstanceRegisterInformation(ResourceContext ctx, InstanceRegisterInformation info, PostInstanceRegisterInformationResult instanceResult) {
    final String caller = "postinstanceregisterinformation";
    final String callerTiming = "postinstanceregisterinformation_timing";
    metric.increment(HTTP_POST);
    validateRequest(ctx.request(), caller);
    validate(info, TYPE_INSTANCE_REGISTER_INFO, caller);
    // for consistent handling of all requests, we're going to convert
    // all incoming object values into lower case (e.g. domain, role,
    // policy, service, etc name)
    AthenzObject.INSTANCE_REGISTER_INFO.convertToLowerCase(info);
    final String domain = info.getDomain();
    final String service = info.getService();
    final String cn = domain + "." + service;
    ((RsrcCtxWrapper) ctx).logPrincipal(cn);
    Object timerMetric = metric.startTiming(callerTiming, domain);
    metric.increment(HTTP_REQUEST, domain);
    metric.increment(caller, domain);
    // before running any checks make sure it's coming from
    // an authorized ip address
    final String ipAddress = ServletRequestUtil.getRemoteAddress(ctx.request());
    if (!instanceCertManager.verifyInstanceCertIPAddress(ipAddress)) {
        throw forbiddenError("Unknown IP: " + ipAddress, caller, domain);
    }
    // run the authorization checks to make sure the provider has been
    // authorized to launch instances in Athenz and the service has
    // authorized this provider to launch its instances
    final String provider = info.getProvider();
    Principal providerService = createPrincipalForName(provider);
    StringBuilder errorMsg = new StringBuilder(256);
    if (!instanceCertManager.authorizeLaunch(providerService, domain, service, authorizer, errorMsg)) {
        throw forbiddenError(errorMsg.toString(), caller, domain);
    }
    // validate request/csr details
    X509CertRequest certReq = null;
    try {
        certReq = new X509CertRequest(info.getCsr());
    } catch (CryptoException ex) {
        throw requestError("unable to parse PKCS10 CSR: " + ex.getMessage(), caller, domain);
    }
    if (!certReq.validate(providerService, domain, service, null, authorizer, errorMsg)) {
        throw requestError("CSR validation failed - " + errorMsg.toString(), caller, domain);
    }
    final String certReqInstanceId = certReq.getInstanceId();
    // validate attestation data is included in the request
    InstanceProvider instanceProvider = instanceProviderManager.getProvider(provider);
    if (instanceProvider == null) {
        throw requestError("unable to get instance for provider: " + provider, caller, domain);
    }
    InstanceConfirmation instance = generateInstanceConfirmObject(ctx, provider, domain, service, info.getAttestationData(), certReq);
    try {
        instance = instanceProvider.confirmInstance(instance);
    } catch (Exception ex) {
        throw forbiddenError("unable to verify attestation data: " + ex.getMessage(), caller, domain);
    } finally {
        instanceProvider.close();
    }
    // determine what type of certificate the provider is authorizing
    // this instance to get - possible values are: server, client or
    // null (indicating both client and server). Additionally, we're
    // going to see if the provider wants to impose an expiry time
    // though the certificate signer might decide to ignore that
    // request and override it with its own value.
    String certUsage = null;
    int certExpiryTime = 0;
    boolean certRefreshAllowed = true;
    Map<String, String> instanceAttrs = instance.getAttributes();
    if (instanceAttrs != null) {
        certUsage = instanceAttrs.remove(ZTSConsts.ZTS_CERT_USAGE);
        final String expiryTime = instanceAttrs.remove(ZTSConsts.ZTS_CERT_EXPIRY_TIME);
        if (expiryTime != null && !expiryTime.isEmpty()) {
            certExpiryTime = Integer.parseInt(expiryTime);
        }
        final String certRefreshState = instanceAttrs.remove(ZTSConsts.ZTS_CERT_REFRESH);
        if (certRefreshState != null && !certRefreshState.isEmpty()) {
            certRefreshAllowed = Boolean.parseBoolean(certRefreshState);
        }
    }
    // generate certificate for the instance
    InstanceIdentity identity = instanceCertManager.generateIdentity(info.getCsr(), cn, certUsage, certExpiryTime);
    if (identity == null) {
        throw serverError("unable to generate identity", caller, domain);
    }
    // if we're asked then we should also generate a ssh
    // certificate for the instance as well
    instanceCertManager.generateSshIdentity(identity, info.getSsh(), ZTSConsts.ZTS_SSH_HOST);
    // set the other required attributes in the identity object
    identity.setAttributes(instanceAttrs);
    identity.setProvider(provider);
    identity.setInstanceId(certReqInstanceId);
    X509Certificate newCert = Crypto.loadX509Certificate(identity.getX509Certificate());
    final String certSerial = newCert.getSerialNumber().toString();
    if (certRefreshAllowed) {
        X509CertRecord x509CertRecord = new X509CertRecord();
        x509CertRecord.setService(cn);
        x509CertRecord.setProvider(provider);
        x509CertRecord.setInstanceId(certReqInstanceId);
        x509CertRecord.setCurrentSerial(certSerial);
        x509CertRecord.setCurrentIP(ServletRequestUtil.getRemoteAddress(ctx.request()));
        x509CertRecord.setCurrentTime(new Date());
        x509CertRecord.setPrevSerial(x509CertRecord.getCurrentSerial());
        x509CertRecord.setPrevIP(x509CertRecord.getCurrentIP());
        x509CertRecord.setPrevTime(x509CertRecord.getCurrentTime());
        x509CertRecord.setClientCert(ZTSConsts.ZTS_CERT_USAGE_CLIENT.equalsIgnoreCase(certUsage));
        if (!instanceCertManager.insertX509CertRecord(x509CertRecord)) {
            throw serverError("unable to update cert db", caller, domain);
        }
    }
    if (info.getToken() == Boolean.TRUE) {
        PrincipalToken svcToken = new PrincipalToken.Builder("S1", domain, service).expirationWindow(svcTokenTimeout).keyId(privateKeyId).host(serverHostName).ip(ServletRequestUtil.getRemoteAddress(ctx.request())).keyService(ZTSConsts.ZTS_SERVICE).build();
        svcToken.sign(privateKey);
        identity.setServiceToken(svcToken.getSignedToken());
    }
    // create our audit log entry
    AuditLogMsgBuilder msgBldr = getAuditLogMsgBuilder(ctx, domain, caller, HTTP_POST);
    msgBldr.whatEntity(certReqInstanceId);
    StringBuilder auditLogDetails = new StringBuilder(512);
    auditLogDetails.append("Provider: ").append(provider).append(" Domain: ").append(domain).append(" Service: ").append(service).append(" InstanceId: ").append(certReqInstanceId).append(" Serial: ").append(certSerial);
    msgBldr.whatDetails(auditLogDetails.toString());
    auditLogger.log(msgBldr);
    final String location = "/zts/v1/instance/" + provider + "/" + domain + "/" + service + "/" + certReqInstanceId;
    metric.stopTiming(timerMetric);
    instanceResult.done(ResourceException.CREATED, identity, location);
}
Also used : InstanceConfirmation(com.yahoo.athenz.instance.provider.InstanceConfirmation) AuditLogMsgBuilder(com.yahoo.athenz.common.server.log.AuditLogMsgBuilder) AuditLogMsgBuilder(com.yahoo.athenz.common.server.log.AuditLogMsgBuilder) PrincipalToken(com.yahoo.athenz.auth.token.PrincipalToken) UnsupportedEncodingException(java.io.UnsupportedEncodingException) CryptoException(com.yahoo.athenz.auth.util.CryptoException) X509Certificate(java.security.cert.X509Certificate) X509CertRecord(com.yahoo.athenz.zts.cert.X509CertRecord) Date(java.util.Date) X509CertRequest(com.yahoo.athenz.zts.cert.X509CertRequest) CryptoException(com.yahoo.athenz.auth.util.CryptoException) SimplePrincipal(com.yahoo.athenz.auth.impl.SimplePrincipal) Principal(com.yahoo.athenz.auth.Principal) InstanceProvider(com.yahoo.athenz.instance.provider.InstanceProvider)

Aggregations

CryptoException (com.yahoo.athenz.auth.util.CryptoException)8 DERIA5String (org.bouncycastle.asn1.DERIA5String)4 Test (org.testng.annotations.Test)4 AuditLogMsgBuilder (com.yahoo.athenz.common.server.log.AuditLogMsgBuilder)3 X509CertRequest (com.yahoo.athenz.zts.cert.X509CertRequest)3 Path (java.nio.file.Path)3 X509Certificate (java.security.cert.X509Certificate)3 PKCS10CertificationRequest (org.bouncycastle.pkcs.PKCS10CertificationRequest)3 Principal (com.yahoo.athenz.auth.Principal)2 SimplePrincipal (com.yahoo.athenz.auth.impl.SimplePrincipal)2 PrincipalToken (com.yahoo.athenz.auth.token.PrincipalToken)2 InstanceConfirmation (com.yahoo.athenz.instance.provider.InstanceConfirmation)2 InstanceProvider (com.yahoo.athenz.instance.provider.InstanceProvider)2 Date (java.util.Date)2 Authority (com.yahoo.athenz.auth.Authority)1 CertificateAuthority (com.yahoo.athenz.auth.impl.CertificateAuthority)1 X509CertRecord (com.yahoo.athenz.zts.cert.X509CertRecord)1 IOException (java.io.IOException)1 UnsupportedEncodingException (java.io.UnsupportedEncodingException)1 PrivateKey (java.security.PrivateKey)1