aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--Makefile52
-rw-r--r--README.md84
-rw-r--r--certService/src/main/java/org/onap/oom/certservice/cmpv2client/impl/CmpClientImpl.java37
-rw-r--r--certService/src/main/resources/application.properties3
-rw-r--r--certService/src/test/java/org/onap/oom/certservice/cmpv2client/Cmpv2ClientTest.java89
-rw-r--r--compose-resources/cmpServers.json4
-rwxr-xr-xcompose-resources/ejbca-configuration.sh10
-rw-r--r--docker-compose.yml1
-rwxr-xr-xparseCertServiceResponse.sh4
10 files changed, 263 insertions, 22 deletions
diff --git a/.gitignore b/.gitignore
index 8a3ca168..452eeebe 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,6 +3,7 @@ target/
!**/src/test/**
**/var
compose-resources/client-volume
+compose-resources/certs-from-curl
### STS ###
.apt_generated
diff --git a/Makefile b/Makefile
index d48fd994..5827199b 100644
--- a/Makefile
+++ b/Makefile
@@ -32,3 +32,55 @@ stop-backend:
@echo "##### Stop Cert Service #####"
docker-compose down
@echo "##### DONE #####"
+
+send-initialization-request:
+ @echo "##### Create folder for certificates from curl: `pwd`/compose-resources/certs-from-curl/ #####"
+ mkdir -p `pwd`/compose-resources/certs-from-curl/
+ @echo "##### Generate CSR and Key #####"
+ openssl req -new -newkey rsa:2048 -nodes -keyout `pwd`/compose-resources/certs-from-curl/ir.key \
+ -out `pwd`/compose-resources/certs-from-curl/ir.csr \
+ -subj "/C=US/ST=California/L=San-Francisco/O=ONAP/OU=Linux-Foundation/CN=onap.org" \
+ -addext "subjectAltName = DNS:test.onap.org"
+ @echo "##### Send Initialization Request #####"
+ curl -sN https://localhost:8443/v1/certificate/RA -H "PK: $$(cat ./compose-resources/certs-from-curl/ir.key | base64 | tr -d \\n)" \
+ -H "CSR: $$(cat ./compose-resources/certs-from-curl/ir.csr | base64 | tr -d \\n)" \
+ --cert `pwd`/certs/cmpv2Issuer-cert.pem \
+ --key `pwd`/certs/cmpv2Issuer-key.pem \
+ --cacert `pwd`/certs/cacert.pem | `pwd`/parseCertServiceResponse.sh "ir"
+
+send-key-update-request: verify-initialization-request-files-exist
+ @echo "##### Generate CSR and Key #####"
+ openssl req -new -newkey rsa:2048 -nodes -keyout `pwd`/compose-resources/certs-from-curl/kur.key \
+ -out `pwd`/compose-resources/certs-from-curl/kur.csr \
+ -subj "/C=US/ST=California/L=San-Francisco/O=ONAP/OU=Linux-Foundation/CN=onap.org" \
+ -addext "subjectAltName = DNS:test.onap.org"
+ @echo "##### Send Key Update Request #####"
+ curl -sN https://localhost:8443/v1/certificate-update/RA -H "PK: $$(cat ./compose-resources/certs-from-curl/kur.key | base64 | tr -d \\n)" \
+ -H "CSR: $$(cat ./compose-resources/certs-from-curl/kur.csr | base64 | tr -d \\n)" \
+ -H "OLD_PK: $$(cat ./compose-resources/certs-from-curl/ir.key | base64 | tr -d \\n)" \
+ -H "OLD_CERT: $$(cat ./compose-resources/certs-from-curl/ir-cert.pem | base64 | tr -d \\n)" \
+ --cert `pwd`/certs/cmpv2Issuer-cert.pem \
+ --key `pwd`/certs/cmpv2Issuer-key.pem \
+ --cacert `pwd`/certs/cacert.pem | `pwd`/parseCertServiceResponse.sh "kur"
+
+send-certification-request: verify-initialization-request-files-exist
+ @echo "##### Generate CSR and Key #####"
+ openssl req -new -newkey rsa:2048 -nodes -keyout `pwd`/compose-resources/certs-from-curl/cr.key \
+ -out `pwd`/compose-resources/certs-from-curl/cr.csr \
+ -subj "/C=US/ST=California/L=San-Francisco/O=ONAP/OU=Linux-Foundation/CN=new-onap.org" \
+ -addext "subjectAltName = DNS:test.onap.org"
+ @echo "##### Send Key Update Request #####"
+ curl -sN https://localhost:8443/v1/certificate-update/RA -H "PK: $$(cat ./compose-resources/certs-from-curl/cr.key | base64 | tr -d \\n)" \
+ -H "CSR: $$(cat ./compose-resources/certs-from-curl/cr.csr | base64 | tr -d \\n)" \
+ -H "OLD_PK: $$(cat ./compose-resources/certs-from-curl/ir.key | base64 | tr -d \\n)" \
+ -H "OLD_CERT: $$(cat ./compose-resources/certs-from-curl/ir-cert.pem | base64 | tr -d \\n)" \
+ --cert `pwd`/certs/cmpv2Issuer-cert.pem \
+ --key `pwd`/certs/cmpv2Issuer-key.pem \
+ --cacert `pwd`/certs/cacert.pem | `pwd`/parseCertServiceResponse.sh "cr"
+
+verify-initialization-request-files-exist:
+ ifeq (,$(wildcard compose-resources/certs-from-curl/ir.key))
+ ifeq (,$(wildcard compose-resources/certs-from-curl/ir-cert.pem))
+ $(error Execute send-initialization-request first)
+ endif
+ endif
diff --git a/README.md b/README.md
index 2d91ee8f..ddbdfff7 100644
--- a/README.md
+++ b/README.md
@@ -54,6 +54,90 @@ make run-client
make stop-backend
```
+### Generating certificates via REST Api
+#### Requirements
+* OpenSSL
+* cURL
+* jq (for parseCertServiceResponse.sh script)
+#### Initialization Request
+1. Create Certificate Signing Request and Private Key
+```
+openssl req -new -newkey rsa:2048 -nodes -keyout ./compose-resources/certs-from-curl/ir.key \
+ -out ./compose-resources/certs-from-curl/ir.csr \
+ -subj "/C=US/ST=California/L=San-Francisco/O=ONAP/OU=Linux-Foundation/CN=onap.org" \
+ -addext "subjectAltName = DNS:test.onap.org"
+```
+2. Send Initialization Request
+```
+curl -s https://localhost:8443/v1/certificate/RA -H "PK: $(cat ./compose-resources/certs-from-curl/ir.key | base64 | tr -d \\n)" \
+ -H "CSR: $(cat ./compose-resources/certs-from-curl/ir.csr | base64 | tr -d \\n)" \
+ --cert ./certs/cmpv2Issuer-cert.pem \
+ --key ./certs/cmpv2Issuer-key.pem \
+ --cacert ./certs/cacert.pem
+```
+to parse the response pipe the output to `parseCertserviceResponse.sh` script, providing prefix as argument
+```
+curl -sN https://localhost:8443/v1/certificate/RA -H "PK: $(cat ./compose-resources/certs-from-curl/ir.key | base64 | tr -d \\n)" \
+ -H "CSR: $(cat ./compose-resources/certs-from-curl/ir.csr | base64 | tr -d \\n)" \
+ --cert ./certs/cmpv2Issuer-cert.pem \
+ --key ./certs/cmpv2Issuer-key.pem \
+ --cacert ./certs/cacert.pem | `pwd`/parseCertServiceResponse.sh "ir"
+```
+
+#### Update Request
+1. Create Certificate Signing Request and Private Key - same as for Initialization Request.
+When CSR data (like Subject and SANS) is unchanged, Key Update Request will be performed.
+Otherwise Certification Request will be performed.
+Example for KUR:
+```
+openssl req -new -newkey rsa:2048 -nodes -keyout ./compose-resources/certs-from-curl/kur.key \
+-out ./compose-resources/certs-from-curl/kur.csr \
+-subj "/C=US/ST=California/L=San-Francisco/O=ONAP/OU=Linux-Foundation/CN=onap.org" \
+-addext "subjectAltName = DNS:test.onap.org"
+```
+Example for CR:
+```
+openssl req -new -newkey rsa:2048 -nodes -keyout ./compose-resources/certs-from-curl/cr.key \
+-out ./compose-resources/certs-from-curl/cr.csr \
+-subj "/C=US/ST=California/L=San-Francisco/O=ONAP/OU=Linux-Foundation/CN=new-onap.org" \
+-addext "subjectAltName = DNS:test.onap.org"
+```
+2. Send Update Request.
+Example for KUR:
+```
+curl -sN https://localhost:8443/v1/certificate-update/RA -H "PK: $(cat ./compose-resources/certs-from-curl/kur.key | base64 | tr -d \\n)" \
+ -H "CSR: $(cat ./compose-resources/certs-from-curl/kur.csr | base64 | tr -d \\n)" \
+ -H "OLDPK: $(cat ./compose-resources/certs-from-curl/ir.key | base64 | tr -d \\n)" \
+ -H "OLDCERT: $(cat ./compose-resources/certs-from-curl/ir-cert.pem | base64 | tr -d \\n)" \
+ --cert ./certs/cmpv2Issuer-cert.pem \
+ --key ./certs/cmpv2Issuer-key.pem \
+ --cacert ./certs/cacert.pem | `pwd`/parseCertServiceResponse.sh "kur"
+```
+Example CR:
+```
+curl -sN https://localhost:8443/v1/certificate-update/RA -H "PK: $$(cat ./compose-resources/certs-from-curl/cr.key | base64 | tr -d \\n)" \
+ -H "CSR: $$(cat ./compose-resources/certs-from-curl/cr.csr | base64 | tr -d \\n)" \
+ -H "OLD_PK: $$(cat ./compose-resources/certs-from-curl/ir.key | base64 | tr -d \\n)" \
+ -H "OLD_CERT: $$(cat ./compose-resources/certs-from-curl/ir-cert.pem | base64 | tr -d \\n)" \
+ --cert ./certs/cmpv2Issuer-cert.pem \
+ --key ./certs/cmpv2Issuer-key.pem \
+ --cacert ./certs/cacert.pem | `pwd`/parseCertServiceResponse.sh "cr"
+```
+
+#### Using makefile
+1. Perform Initialization Request:
+```
+make send-initialization-request
+```
+2. Perform Update Request:
+```
+make send-key-update-request
+```
+or:
+```
+make send-certification-request
+```
+
### OOM CertService CSITs
#### CSIT repository
```
diff --git a/certService/src/main/java/org/onap/oom/certservice/cmpv2client/impl/CmpClientImpl.java b/certService/src/main/java/org/onap/oom/certservice/cmpv2client/impl/CmpClientImpl.java
index 68b78f23..06e785ac 100644
--- a/certService/src/main/java/org/onap/oom/certservice/cmpv2client/impl/CmpClientImpl.java
+++ b/certService/src/main/java/org/onap/oom/certservice/cmpv2client/impl/CmpClientImpl.java
@@ -39,6 +39,7 @@ import java.util.Date;
import java.util.Objects;
import java.util.Optional;
import org.apache.http.impl.client.CloseableHttpClient;
+import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.cmp.CMPCertificate;
import org.bouncycastle.asn1.cmp.CertRepMessage;
import org.bouncycastle.asn1.cmp.CertResponse;
@@ -67,6 +68,7 @@ public class CmpClientImpl implements CmpClient {
private static final String DEFAULT_CA_NAME = "Certification Authority";
private static final String DEFAULT_PROFILE = CaMode.RA.getProfile();
+ private static final ASN1ObjectIdentifier PASSWORD_BASED_MAC = new ASN1ObjectIdentifier("1.2.840.113533.7.66.13");
public CmpClientImpl(CloseableHttpClient httpClient) {
this.httpClient = httpClient;
@@ -114,7 +116,18 @@ public class CmpClientImpl implements CmpClient {
final PKIHeader header = respPkiMessage.getHeader();
final AlgorithmIdentifier protectionAlgo = header.getProtectionAlg();
verifySignatureWithPublicKey(respPkiMessage, publicKey);
- verifyProtectionWithProtectionAlgo(respPkiMessage, initAuthPassword, header, protectionAlgo);
+ if (isPasswordBasedMacAlgorithm(protectionAlgo)) {
+ LOG.info("CMP response is protected by Password Base Mac Algorithm. Attempt to verify protection");
+ verifyPasswordBasedMacProtection(respPkiMessage, initAuthPassword, header, protectionAlgo);
+ }
+ }
+
+ private boolean isPasswordBasedMacAlgorithm(AlgorithmIdentifier protectionAlgo) throws CmpClientException {
+ if (Objects.isNull(protectionAlgo)) {
+ LOG.error("CMP response does not contain Protection Algorithm field");
+ throw new CmpClientException("CMP response does not contain Protection Algorithm field");
+ }
+ return PASSWORD_BASED_MAC.equals(protectionAlgo.getAlgorithm());
}
private void verifySignatureWithPublicKey(PKIMessage respPkiMessage, PublicKey publicKey)
@@ -129,22 +142,12 @@ public class CmpClientImpl implements CmpClient {
}
}
- private void verifyProtectionWithProtectionAlgo(
- PKIMessage respPkiMessage,
- String initAuthPassword,
- PKIHeader header,
- AlgorithmIdentifier protectionAlgo)
- throws CmpClientException {
- if (Objects.nonNull(protectionAlgo)) {
- LOG.debug("Verifying PasswordBased Protection of the Response.");
- verifyPasswordBasedProtection(respPkiMessage, initAuthPassword, protectionAlgo);
- checkImplicitConfirm(header);
- } else {
- LOG.error(
- "Protection Algorithm is not available when expecting PBE protected response containing protection algorithm");
- throw new CmpClientException(
- "Protection Algorithm is not available when expecting PBE protected response containing protection algorithm");
- }
+ private void verifyPasswordBasedMacProtection(PKIMessage respPkiMessage, String initAuthPassword,
+ PKIHeader header, AlgorithmIdentifier protectionAlgo)
+ throws CmpClientException {
+ LOG.debug("Verifying PasswordBased Protection of the Response.");
+ verifyPasswordBasedProtection(respPkiMessage, initAuthPassword, protectionAlgo);
+ checkImplicitConfirm(header);
}
private Cmpv2CertificationModel checkCmpCertRepMessage(final PKIMessage respPkiMessage)
diff --git a/certService/src/main/resources/application.properties b/certService/src/main/resources/application.properties
index a7f5eea8..8698a314 100644
--- a/certService/src/main/resources/application.properties
+++ b/certService/src/main/resources/application.properties
@@ -10,6 +10,9 @@ springdoc.swagger-ui.path=/docs
# OOM CertService app specific configuration
app.config.path=/etc/onap/oom/certservice
+# HTTP Configuration
+server.max-http-header-size=16384
+
# Mutual TLS configuration
server.ssl.enabled=true
server.ssl.client-auth=need
diff --git a/certService/src/test/java/org/onap/oom/certservice/cmpv2client/Cmpv2ClientTest.java b/certService/src/test/java/org/onap/oom/certservice/cmpv2client/Cmpv2ClientTest.java
index 6a5a37f6..337ed8c1 100644
--- a/certService/src/test/java/org/onap/oom/certservice/cmpv2client/Cmpv2ClientTest.java
+++ b/certService/src/test/java/org/onap/oom/certservice/cmpv2client/Cmpv2ClientTest.java
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2019 Ericsson Software Technology AB. All rights reserved.
+ * Copyright (C) 2021 Nokia. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,6 +17,7 @@
package org.onap.oom.certservice.cmpv2client;
+import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doAnswer;
@@ -24,6 +26,7 @@ import static org.mockito.Mockito.when;
import static org.mockito.MockitoAnnotations.initMocks;
import java.io.BufferedInputStream;
+import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
@@ -35,7 +38,7 @@ import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Security;
-import java.security.cert.X509Certificate;
+
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
@@ -47,6 +50,18 @@ import org.apache.commons.io.IOUtils;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.impl.client.CloseableHttpClient;
+import org.bouncycastle.asn1.ASN1GeneralizedTime;
+import org.bouncycastle.asn1.ASN1Integer;
+import org.bouncycastle.asn1.DERBitString;
+import org.bouncycastle.asn1.cmp.PKIBody;
+import org.bouncycastle.asn1.cmp.PKIHeader;
+import org.bouncycastle.asn1.cmp.PKIHeaderBuilder;
+import org.bouncycastle.asn1.cmp.PKIMessage;
+import org.bouncycastle.asn1.crmf.CertReqMessages;
+import org.bouncycastle.asn1.crmf.CertReqMsg;
+import org.bouncycastle.asn1.crmf.CertRequest;
+import org.bouncycastle.asn1.crmf.CertTemplateBuilder;
+import org.bouncycastle.asn1.crmf.ProofOfPossession;
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.asn1.x500.X500NameBuilder;
import org.bouncycastle.asn1.x500.style.BCStyle;
@@ -76,8 +91,6 @@ class Cmpv2ClientTest {
private Date notAfter;
private X500Name dn;
- @Mock
- X509Certificate cert;
@Mock
CloseableHttpClient httpClient;
@@ -233,6 +246,47 @@ class Cmpv2ClientTest {
() -> cmpClient.createCertificate(csrModel, server, notBefore, notAfter));
}
+
+ @Test
+ void shouldThrowExceptionWhenResponseNotContainProtectionAlgorithmField()
+ throws IOException, ParseException {
+
+ Date beforeDate = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse("2019/11/11 12:00:00");
+ Date afterDate = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse("2020/11/11 12:00:00");
+ setCsrModelAndServerValues(
+ "password",
+ "senderKID",
+ "http://127.0.0.1/ejbca/publicweb/cmp/cmp",
+ beforeDate,
+ afterDate);
+
+ when(httpClient.execute(any())).thenReturn(httpResponse);
+ when(httpResponse.getEntity()).thenReturn(httpEntity);
+
+ try (
+ BufferedInputStream bis = new BufferedInputStream(new ByteArrayInputStream(
+ preparePKIMessageWithoutProtectionAlgorithm().getEncoded()
+ ))) {
+
+ byte[] ba = IOUtils.toByteArray(bis);
+ doAnswer(
+ invocation -> {
+ OutputStream os = invocation.getArgument(0);
+ os.write(ba);
+ return null;
+ })
+ .when(httpEntity)
+ .writeTo(any(OutputStream.class));
+ }
+
+ CmpClientImpl cmpClient = new CmpClientImpl(httpClient);
+
+ assertThatExceptionOfType(CmpClientException.class)
+ .isThrownBy(() -> cmpClient.createCertificate(csrModel, server, notBefore, notAfter))
+ .withMessageContaining("CMP response does not contain Protection Algorithm field");
+
+ }
+
@Test
void shouldThrowIllegalArgumentExceptionWhencreateCertificateCalledWithInvalidCsr()
throws ParseException {
@@ -285,4 +339,33 @@ class Cmpv2ClientTest {
this.notBefore = notBefore;
this.notAfter = notAfter;
}
+
+ private PKIMessage preparePKIMessageWithoutProtectionAlgorithm() {
+
+ CertTemplateBuilder certTemplateBuilder = new CertTemplateBuilder();
+ X500Name issuerDN = getTestIssuerDN();
+
+ certTemplateBuilder.setIssuer(issuerDN);
+ certTemplateBuilder.setSerialNumber(new ASN1Integer(0L));
+
+ CertRequest certRequest = new CertRequest(4, certTemplateBuilder.build(), null);
+ CertReqMsg certReqMsg = new CertReqMsg(certRequest, new ProofOfPossession(), null);
+ CertReqMessages certReqMessages = new CertReqMessages(certReqMsg);
+
+ PKIHeaderBuilder pkiHeaderBuilder = new PKIHeaderBuilder(PKIHeader.CMP_2000, new GeneralName(issuerDN), new GeneralName(issuerDN));
+ pkiHeaderBuilder.setMessageTime(new ASN1GeneralizedTime(new Date()));
+ pkiHeaderBuilder.setProtectionAlg(null);
+
+ PKIBody pkiBody = new PKIBody(PKIBody.TYPE_INIT_REQ, certReqMessages);
+ return new PKIMessage(pkiHeaderBuilder.build(), pkiBody, new DERBitString("test".getBytes()));
+ }
+
+ private X500Name getTestIssuerDN() {
+ return new X500NameBuilder()
+ .addRDN(BCStyle.O, "Test_Organization")
+ .addRDN(BCStyle.UID, "Test_UID")
+ .addRDN(BCStyle.CN, "Test_CA")
+ .build();
+ }
+
}
diff --git a/compose-resources/cmpServers.json b/compose-resources/cmpServers.json
index 72564949..8972fd4d 100644
--- a/compose-resources/cmpServers.json
+++ b/compose-resources/cmpServers.json
@@ -3,7 +3,7 @@
{
"caName": "Client",
"url": "http://oomcert-ejbca:8080/ejbca/publicweb/cmp/cmp",
- "issuerDN": "CN=ManagementCA",
+ "issuerDN": "O=EJBCA Container Quickstart,CN=ManagementCA,UID=12345",
"caMode": "CLIENT",
"authentication": {
"iak": "mypassword",
@@ -13,7 +13,7 @@
{
"caName": "RA",
"url": "http://oomcert-ejbca:8080/ejbca/publicweb/cmp/cmpRA",
- "issuerDN": "CN=ManagementCA",
+ "issuerDN": "O=EJBCA Container Quickstart,CN=ManagementCA,UID=12345",
"caMode": "RA",
"authentication": {
"iak": "mypassword",
diff --git a/compose-resources/ejbca-configuration.sh b/compose-resources/ejbca-configuration.sh
index 8e6bd038..42e3f6bd 100755
--- a/compose-resources/ejbca-configuration.sh
+++ b/compose-resources/ejbca-configuration.sh
@@ -1,6 +1,16 @@
#!/bin/bash
configureEjbca() {
+ ejbca.sh ca init \
+ --caname ManagementCA \
+ --dn "O=EJBCA Container Quickstart,CN=ManagementCA,UID=12345" \
+ --tokenType soft \
+ --keyspec 3072 \
+ --keytype RSA \
+ -v 3652 \
+ --policy null \
+ -s SHA256WithRSA \
+ -type "x509"
ejbca.sh config cmp addalias --alias cmpRA
ejbca.sh config cmp updatealias --alias cmpRA --key operationmode --value ra
ejbca.sh ca editca --caname ManagementCA --field cmpRaAuthSecret --value mypassword
diff --git a/docker-compose.yml b/docker-compose.yml
index 3e55c29b..1b154f4d 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -10,6 +10,7 @@ services:
- "443:8443"
environment:
- INITIAL_ADMIN=;PublicAccessAuthenticationToken:TRANSPORT_ANY;
+ - NO_CREATE_CA=true
volumes:
- ./compose-resources/ejbca-configuration.sh:/opt/primekey/scripts/ejbca-configuration.sh
- ./compose-resources/certprofile_CUSTOM_ENDUSER-1834889499.xml:/opt/primekey/custom_profiles/certprofile_CUSTOM_ENDUSER-1834889499.xml
diff --git a/parseCertServiceResponse.sh b/parseCertServiceResponse.sh
new file mode 100755
index 00000000..dff867fa
--- /dev/null
+++ b/parseCertServiceResponse.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+read -r RESPONSE
+echo "$RESPONSE" | jq -r '.certificateChain[]' > ./compose-resources/certs-from-curl/$1-cert.pem
+echo "$RESPONSE" | jq -r '.trustedCertificates[]' > ./compose-resources/certs-from-curl/$1-cacert.pem