2525
2626import com .fasterxml .jackson .annotation .JsonProperty ;
2727
28+ import org .springframework .lang .Nullable ;
2829import org .springframework .util .Assert ;
2930import org .springframework .util .Base64Utils ;
3031import org .springframework .vault .VaultException ;
@@ -47,12 +48,19 @@ public class Certificate {
4748
4849 private final String issuingCaCertificate ;
4950
51+ private final List <String > caChain ;
52+
53+ private final Long revocationTime ;
54+
5055 Certificate (@ JsonProperty ("serial_number" ) String serialNumber , @ JsonProperty ("certificate" ) String certificate ,
51- @ JsonProperty ("issuing_ca" ) String issuingCaCertificate ) {
56+ @ JsonProperty ("issuing_ca" ) String issuingCaCertificate , @ JsonProperty ("ca_chain" ) List <String > caChain ,
57+ @ JsonProperty ("revocation_time" ) Long revocationTime ) {
5258
5359 this .serialNumber = serialNumber ;
5460 this .certificate = certificate ;
5561 this .issuingCaCertificate = issuingCaCertificate ;
62+ this .caChain = caChain ;
63+ this .revocationTime = revocationTime ;
5664 }
5765
5866 /**
@@ -69,7 +77,49 @@ public static Certificate of(String serialNumber, String certificate, String iss
6977 Assert .hasText (certificate , "Certificate must not be empty" );
7078 Assert .hasText (issuingCaCertificate , "Issuing CA certificate must not be empty" );
7179
72- return new Certificate (serialNumber , certificate , issuingCaCertificate );
80+ return new Certificate (serialNumber , certificate , issuingCaCertificate , List .of (), null );
81+ }
82+
83+ /**
84+ * Create a {@link Certificate} given a private key with certificates and the serial
85+ * number.
86+ * @param serialNumber must not be empty or {@literal null}.
87+ * @param certificate must not be empty or {@literal null}.
88+ * @param issuingCaCertificate must not be empty or {@literal null}.
89+ * @param caChain empty list allowed
90+ * @return the {@link Certificate}
91+ */
92+ public static Certificate of (String serialNumber , String certificate , String issuingCaCertificate ,
93+ List <String > caChain ) {
94+
95+ Assert .hasText (serialNumber , "Serial number must not be empty" );
96+ Assert .hasText (certificate , "Certificate must not be empty" );
97+ Assert .hasText (issuingCaCertificate , "Issuing CA certificate must not be empty" );
98+ Assert .notNull (caChain , "CA chain must not be null" );
99+
100+ return new Certificate (serialNumber , certificate , issuingCaCertificate , caChain , null );
101+ }
102+
103+ /**
104+ * Create a {@link Certificate} given a private key with certificates and the serial
105+ * number.
106+ * @param serialNumber must not be empty or {@literal null}.
107+ * @param certificate must not be empty or {@literal null}.
108+ * @param issuingCaCertificate must not be empty or {@literal null}.
109+ * @param caChain empty list allowed
110+ * @param revocationTime revocation time, must not be {@literal null}
111+ * @return the {@link Certificate}
112+ */
113+ public static Certificate of (String serialNumber , String certificate , String issuingCaCertificate ,
114+ List <String > caChain , Long revocationTime ) {
115+
116+ Assert .hasText (serialNumber , "Serial number must not be empty" );
117+ Assert .hasText (certificate , "Certificate must not be empty" );
118+ Assert .hasText (issuingCaCertificate , "Issuing CA certificate must not be empty" );
119+ Assert .notNull (caChain , "CA chain must not be null" );
120+ Assert .notNull (revocationTime , "Revocation time" );
121+
122+ return new Certificate (serialNumber , certificate , issuingCaCertificate , caChain , revocationTime );
73123 }
74124
75125 /**
@@ -130,9 +180,27 @@ private X509Certificate doGetCertificate(String cert) {
130180 * @return the {@link KeyStore} containing the private key and certificate chain.
131181 */
132182 public KeyStore createTrustStore () {
183+ return createTrustStore (false );
184+ }
133185
186+ /**
187+ * Create a trust store as {@link KeyStore} from this {@link Certificate} containing *
188+ * the certificate chain.
189+ * @param includeCaChain whether to include the certificate authority chain instead of
190+ * just the issuer certificate.
191+ * @return the {@link KeyStore} containing the certificate and certificate chain.
192+ */
193+ public KeyStore createTrustStore (boolean includeCaChain ) {
134194 try {
135- return KeystoreUtil .createKeyStore (getX509Certificate (), getX509IssuerCertificate ());
195+ List <X509Certificate > certificates = new ArrayList <>();
196+ certificates .add (getX509Certificate ());
197+ if (includeCaChain ) {
198+ certificates .addAll (getX509IssuerCertificates ());
199+ }
200+ else {
201+ certificates .add (getX509IssuerCertificate ());
202+ }
203+ return KeystoreUtil .createKeyStore (certificates .toArray (new X509Certificate [0 ]));
136204 }
137205 catch (GeneralSecurityException | IOException e ) {
138206 throw new VaultException ("Cannot create KeyStore" , e );
@@ -161,4 +229,29 @@ static List<X509Certificate> getCertificates(String certificates) throws Certifi
161229 return result ;
162230 }
163231
232+ /**
233+ * Retrieve the issuing CA certificates as list of {@link X509Certificate}.
234+ * @return the issuing CA {@link X509Certificate}.
235+ * @since 2.3.3
236+ */
237+ public List <X509Certificate > getX509IssuerCertificates () {
238+
239+ List <X509Certificate > certificates = new ArrayList <>();
240+
241+ for (String data : this .caChain ) {
242+ try {
243+ certificates .addAll (getCertificates (data ));
244+ }
245+ catch (CertificateException e ) {
246+ throw new VaultException ("Cannot create Certificate from issuing CA certificate" , e );
247+ }
248+ }
249+
250+ return certificates ;
251+ }
252+
253+ public @ Nullable Long getRevocationTime () {
254+ return this .revocationTime ;
255+ }
256+
164257}
0 commit comments