Create a Node Operational Certificate (NOC) - AWS Private Certificate Authority

Create a Node Operational Certificate (NOC)

This Java sample shows how to use the BlankEndEntityCertificate_CriticalBasicConstraints_APIPassthrough/V1 template to create a Matter Node Operational Certificate. You must generate a Base64-encoded KeyUsage value and pass it through a CustomExtension.

The example calls the following AWS Private CA API action:

If you encounter problems, see Troubleshoot AWS Private CA Matter-compliant certificate errors in the Troubleshooting section.

package com.amazonaws.samples.matter; import com.amazonaws.auth.AWSCredentials; import com.amazonaws.auth.profile.ProfileCredentialsProvider; import com.amazonaws.client.builder.AwsClientBuilder; import com.amazonaws.client.builder.AwsClientBuilder.EndpointConfiguration; import com.amazonaws.auth.AWSStaticCredentialsProvider; import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; import java.util.Arrays; import java.util.Base64; import java.util.List; import java.util.Objects; import com.amazonaws.services.acmpca.AWSACMPCA; import com.amazonaws.services.acmpca.AWSACMPCAClientBuilder; import com.amazonaws.services.acmpca.model.ASN1Subject; import com.amazonaws.services.acmpca.model.ApiPassthrough; import com.amazonaws.services.acmpca.model.CustomAttribute; import com.amazonaws.services.acmpca.model.CustomExtension; import com.amazonaws.services.acmpca.model.Extensions; import com.amazonaws.services.acmpca.model.IssueCertificateRequest; import com.amazonaws.services.acmpca.model.IssueCertificateResult; import com.amazonaws.services.acmpca.model.SigningAlgorithm; import com.amazonaws.services.acmpca.model.Validity; import com.amazonaws.AmazonClientException; import com.amazonaws.services.acmpca.model.LimitExceededException; import com.amazonaws.services.acmpca.model.ResourceNotFoundException; import com.amazonaws.services.acmpca.model.InvalidStateException; import com.amazonaws.services.acmpca.model.InvalidArnException; import com.amazonaws.services.acmpca.model.InvalidArgsException; import com.amazonaws.services.acmpca.model.MalformedCSRException; import org.bouncycastle.asn1.x509.ExtendedKeyUsage; import org.bouncycastle.asn1.x509.KeyPurposeId; import org.bouncycastle.asn1.x509.KeyUsage; import org.bouncycastle.jce.X509KeyUsage; import lombok.SneakyThrows; public class IssueNodeOperatingCertificate { public static ByteBuffer stringToByteBuffer(final String string) { if (Objects.isNull(string)) { return null; } byte[] bytes = string.getBytes(StandardCharsets.UTF_8); return ByteBuffer.wrap(bytes); } @SneakyThrows private static String generateExtendedKeyUsageValue() { KeyPurposeId[] keyPurposeIds = new KeyPurposeId[] { KeyPurposeId.id_kp_clientAuth, KeyPurposeId.id_kp_serverAuth }; ExtendedKeyUsage eku = new ExtendedKeyUsage(keyPurposeIds); byte[] ekuBytes = eku.getEncoded(); return Base64.getEncoder().encodeToString(ekuBytes); } @SneakyThrows private static String generateKeyUsageValue() { KeyUsage keyUsage = new KeyUsage(X509KeyUsage.digitalSignature); byte[] kuBytes = keyUsage.getEncoded(); return Base64.getEncoder().encodeToString(kuBytes); } public static void main(String[] args) throws Exception { // Retrieve your credentials from the C:\Users\name\.aws\credentials file // in Windows or the .aws/credentials file in Linux. AWSCredentials credentials = null; try { credentials = new ProfileCredentialsProvider("default").getCredentials(); } catch (Exception e) { throw new AmazonClientException("Cannot load your credentials from disk", e); } // Define the endpoint for your sample. String endpointRegion = "region"; // Substitute your region here, e.g. "ap-southeast-2" String endpointProtocol = "https://acm-pca." + endpointRegion + ".amazonaws.com/"; EndpointConfiguration endpoint = new AwsClientBuilder.EndpointConfiguration(endpointProtocol, endpointRegion); // Create a client that you can use to make requests. AWSACMPCA client = AWSACMPCAClientBuilder.standard() .withEndpointConfiguration(endpoint) .withCredentials(new AWSStaticCredentialsProvider(credentials)) .build(); // Create a certificate request: IssueCertificateRequest req = new IssueCertificateRequest(); // Set the CA ARN. req.withCertificateAuthorityArn("arn:aws:acm-pca:region:123456789012:certificate-authority/12345678-1234-1234-1234-123456789012"); // Specify the certificate signing request (CSR) for the certificate to be signed and issued. String strCSR = "-----BEGIN CERTIFICATE REQUEST-----\n" + "base64-encoded certificate\n" + "-----END CERTIFICATE REQUEST-----\n"; ByteBuffer csrByteBuffer = stringToByteBuffer(strCSR); req.setCsr(csrByteBuffer); // Specify the template for the issued certificate. req.withTemplateArn("arn:aws:acm-pca:::template/BlankEndEntityCertificate_CriticalBasicConstraints_APIPassthrough/V1"); // Set the signing algorithm. req.withSigningAlgorithm(SigningAlgorithm.SHA256WITHECDSA); // Set the validity period for the certificate to be issued. Validity validity = new Validity(); validity.withValue(10L); validity.withType("DAYS"); req.withValidity(validity); // Set the idempotency token. req.setIdempotencyToken("1234"); // Define custom attributes List<CustomAttribute> customAttributes = Arrays.asList( new CustomAttribute() .withObjectIdentifier("1.3.6.1.4.1.37244.1.1") .withValue("DEDEDEDE00010001"), new CustomAttribute() .withObjectIdentifier("1.3.6.1.4.1.37244.1.5") .withValue("FAB000000000001D") ); // Define a cert subject. ASN1Subject subject = new ASN1Subject(); subject.setCustomAttributes(customAttributes); ApiPassthrough apiPassthrough = new ApiPassthrough(); apiPassthrough.setSubject(subject); // Generate Base64 encoded extension value for ExtendedKeyUsage String base64EncodedKUValue = generateKeyUsageValue(); // Generate custom extension CustomExtension customKeyUsageExtension = new CustomExtension(); customKeyUsageExtension.setObjectIdentifier("2.5.29.15"); customKeyUsageExtension.setValue(base64EncodedKUValue); customKeyUsageExtension.setCritical(true); // Generate Base64 encoded extension value for ExtendedKeyUsage String base64EncodedEKUValue = generateExtendedKeyUsageValue(); CustomExtension customExtendedKeyUsageExtension = new CustomExtension(); customExtendedKeyUsageExtension.setObjectIdentifier("2.5.29.37"); // ExtendedKeyUsage Extension OID customExtendedKeyUsageExtension.setValue(base64EncodedEKUValue); customExtendedKeyUsageExtension.setCritical(true); // Set KeyUsage and ExtendedKeyUsage extension to api-passthrough Extensions extensions = new Extensions(); extensions.setCustomExtensions(Arrays.asList(customKeyUsageExtension, customExtendedKeyUsageExtension)); apiPassthrough.setExtensions(extensions); req.setApiPassthrough(apiPassthrough); // Issue the certificate. IssueCertificateResult result = null; try { result = client.issueCertificate(req); } catch (LimitExceededException ex) { throw ex; } catch (ResourceNotFoundException ex) { throw ex; } catch (InvalidStateException ex) { throw ex; } catch (InvalidArnException ex) { throw ex; } catch (InvalidArgsException ex) { throw ex; } catch (MalformedCSRException ex) { throw ex; } // Retrieve and display the certificate ARN. String arn = result.getCertificateArn(); System.out.println(arn); } }