Polishing.

Reorder methods. Reformat code. Add since tags. Convert revocation timestamp into instant.

See: gh-477
Original pull request: gh-820
This commit is contained in:
Mark Paluch
2023-11-01 16:02:13 +01:00
parent 8d7292c049
commit 269a8e128e
6 changed files with 216 additions and 152 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2016-2022 the original author or authors.
* Copyright 2016-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -36,6 +36,7 @@ import org.springframework.vault.support.VaultSignCertificateRequestResponse;
* provide the verification functionality.
*
* @author Mark Paluch
* @author Nanne Baars
* @see <a href=
* "https://www.vaultproject.io/docs/secrets/pki/index.html">https://www.vaultproject.io/docs/secrets/pki/index.html</a>
*/
@@ -66,10 +67,10 @@ public interface VaultPkiOperations {
* @param certificateRequest must not be {@literal null}.
* @return the {@link VaultCertificateResponse} containing a
* {@link org.springframework.vault.support.Certificate} .
* @since 2.0
* @see <a href=
* "https://www.vaultproject.io/docs/secrets/pki/index.html#pki-issue">POST
* /pki/sign/[role name]</a>
* @since 2.0
*/
VaultSignCertificateRequestResponse signCertificateRequest(String roleName, String csr,
VaultCertificateRequest certificateRequest) throws VaultException;
@@ -79,10 +80,10 @@ public interface VaultPkiOperations {
* standard method of revoking using Vault lease IDs. A successful revocation will
* rotate the CRL
* @param serialNumber must not be empty or {@literal null}.
* @since 2.0
* @see <a href=
* "https://www.vaultproject.io/docs/secrets/pki/index.html#revoke-certificate">POST
* /pki/revoke</a>
* @since 2.0
*/
void revoke(String serialNumber) throws VaultException;
@@ -96,43 +97,56 @@ public interface VaultPkiOperations {
* is {@literal null}.
* @return {@link java.io.InputStream} containing the encoded CRL or {@literal null}
* if Vault responds with 204 No Content.
* @since 2.0
* @see <a href="https://www.vaultproject.io/api/secret/pki/index.html#read-crl">GET
* /pki/crl</a>
* @since 2.0
*/
@Nullable
InputStream getCrl(Encoding encoding) throws VaultException;
enum Encoding {
DER, PEM,
}
/**
* Retrieves the specified issuer's certificate. Includes the full ca_chain of the
* issuer.
* Retrieves the specified issuer's certificate. Includes the full {@code ca_chain} of
* the issuer.
* @param issuer reference to an existing issuer, either by Vault-generated
* identifier, or the name assigned to an issuer. Pass the literal string 'default' to
* refer to the currently configured issuer.
* identifier, or the name assigned to an issuer. Pass the literal string
* {@code default} to refer to the currently configured issuer.
* @return the {@link VaultIssuerCertificateRequestResponse} containing a
* {@link org.springframework.vault.support.Certificate}
* @see <a href=
* "https://www.vaultproject.io/api/secret/pki/#read-issuer-certificate">GET *
* /pki/issuer/:issuer_ref/json</a>
*
* @since 3.1
*/
VaultIssuerCertificateRequestResponse getIssuerCertificate(String issuer) throws VaultException;
/**
* Retrieves the specified issuer's certificate. Includes the full ca_chain of the
* issuer.
* @return {@link java.io.InputStream} containing the encoded certificate or
* {@literal null}
* Retrieves the specified issuer's certificate. Includes the full {@code ca_chain} of
* the issuer.
* @param issuer reference to an existing issuer, either by Vault-generated
* identifier, or the name assigned to an issuer. Pass the literal string
* {@code default} to refer to the currently configured issuer.
* @param encoding encoding to use.
* @return {@link java.io.InputStream} containing the encoded certificate.
* @see <a href=
* "https://www.vaultproject.io/api/secret/pki/#read-issuer-certificate">GET
* /pki/issuer/:issuer_ref/{der, pem}</a>
* @since 3.1
*/
InputStream getIssuerCertificate(String issuer, Encoding encoding) throws VaultException;
enum Encoding {
/**
* DER (Distinguished Encoding Rules) format in its binary representation, see
* X.690.
*/
DER,
/**
* Privacy-Enhanced Mail (PEM) format in base64.
*/
PEM;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2016-2022 the original author or authors.
* Copyright 2016-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,9 +17,11 @@ package org.springframework.vault.core;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.Collections;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import org.springframework.http.ResponseEntity;
import org.springframework.util.Assert;
@@ -165,12 +167,14 @@ public class VaultPkiTemplate implements VaultPkiOperations {
@Override
public InputStream getIssuerCertificate(String issuer, Encoding encoding) throws VaultException {
Assert.hasText(issuer, "Issuer must not be empty");
Assert.notNull(encoding, "Encoding must not be null");
return this.vaultOperations.doWithSession(restOperations -> {
String requestPath = encoding == Encoding.DER ? "{path}/issuer/{issuer}/der" : "{path}/issuer/{issuer}/pem";
String requestPath = String.format("{path}/issuer/{issuer}/%s", encoding.name().toLowerCase(Locale.ROOT));
try {
ResponseEntity<byte[]> response = restOperations.getForEntity(requestPath, byte[].class, this.path,
issuer);
@@ -224,7 +228,7 @@ public class VaultPkiTemplate implements VaultPkiOperations {
.to("exclude_cn_from_sans", request);
mapper.from(certificateRequest::getFormat).whenHasText().to("format", request);
mapper.from(certificateRequest::getPrivateKeyFormat).whenHasText().to("private_key_format", request);
mapper.from(certificateRequest::getNotAfter).whenHasText().as(i -> i.toString()).to("not_after", request);
mapper.from(certificateRequest::getNotAfter).whenHasText().as(Instant::toString).to("not_after", request);
mapper.from(certificateRequest::getUserIds).whenHasText().to("user_ids", request);
return request;

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2017-2022 the original author or authors.
* Copyright 2017-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,6 +20,7 @@ import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
@@ -36,9 +37,9 @@ import org.springframework.vault.VaultException;
* encoded. Certificates can be obtained as {@link X509Certificate}.
*
* @author Mark Paluch
* @since 2.0
* @see #getX509Certificate()
* @see #getIssuingCaCertificate()
* @since 2.0
*/
public class Certificate {
@@ -50,17 +51,18 @@ public class Certificate {
private final List<String> caChain;
private final Long revocationTime;
@Nullable
private final Instant revocationTime;
Certificate(@JsonProperty("serial_number") String serialNumber, @JsonProperty("certificate") String certificate,
@JsonProperty("issuing_ca") String issuingCaCertificate, @JsonProperty("ca_chain") List<String> caChain,
@JsonProperty("revocation_time") Long revocationTime) {
@Nullable @JsonProperty("revocation_time") Long revocationTime) {
this.serialNumber = serialNumber;
this.certificate = certificate;
this.issuingCaCertificate = issuingCaCertificate;
this.caChain = caChain;
this.revocationTime = revocationTime;
this.revocationTime = revocationTime != null ? Instant.ofEpochMilli(revocationTime * 1000) : null;
}
/**
@@ -87,7 +89,8 @@ public class Certificate {
* @param certificate must not be empty or {@literal null}.
* @param issuingCaCertificate must not be empty or {@literal null}.
* @param caChain empty list allowed
* @return the {@link Certificate}
* @return the {@link Certificate}.
* @since 3.1
*/
public static Certificate of(String serialNumber, String certificate, String issuingCaCertificate,
List<String> caChain) {
@@ -107,8 +110,9 @@ public class Certificate {
* @param certificate must not be empty or {@literal null}.
* @param issuingCaCertificate must not be empty or {@literal null}.
* @param caChain empty list allowed
* @param revocationTime revocation time, must not be {@literal null}
* @return the {@link Certificate}
* @param revocationTime revocation time, must not be {@literal null}.
* @return the {@link Certificate}.
* @since 3.1
*/
public static Certificate of(String serialNumber, String certificate, String issuingCaCertificate,
List<String> caChain, Long revocationTime) {
@@ -250,8 +254,13 @@ public class Certificate {
return certificates;
}
public @Nullable Long getRevocationTime() {
@Nullable
public Instant getRevocationTime() {
return this.revocationTime;
}
public boolean isRevoked() {
return this.revocationTime != null;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2016-2022 the original author or authors.
* Copyright 2016-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,11 +19,14 @@ import java.time.Duration;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Locale;
import java.util.concurrent.TimeUnit;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
/**
* Request for a Certificate.
@@ -40,6 +43,13 @@ public class VaultCertificateRequest {
*/
private final String commonName;
/**
* If {@literal true}, the given common name will not be included in DNS or Email
* Subject Alternate Names (as appropriate). Useful if the CN is not a hostname or
* email address, but is instead some human-readable identifier.
*/
private final boolean excludeCommonNameFromSubjectAltNames;
/**
* Alternate CN names for additional host names.
*/
@@ -59,6 +69,7 @@ public class VaultCertificateRequest {
* Specifies custom OID/UTF8-string Subject Alternative Names. These must match values
* specified on the role in {@literal allowed_other_sans}. The format is the same as
* OpenSSL: {@literal <oid>;<type>:<value>} where the only current valid type is UTF8.
*
* @since 2.4
*/
private final List<String> otherSans;
@@ -69,6 +80,14 @@ public class VaultCertificateRequest {
@Nullable
private final Duration ttl;
/**
* Set the Not After field of the certificate with specified date value. The value
* format should be given in UTC format YYYY-MM-ddTHH:MM:SSZ. Supports the Y10K end
* date for IEEE 802.1AR-2018 standard devices, 9999-12-31T23:59:59Z.
*/
@Nullable
private final Instant notAfter;
/**
* Specifies the format for returned data. Can be {@literal pem}, {@literal der}, or
* {@literal pem_bundle}; defaults to {@literal der} (in vault api the default is
@@ -76,6 +95,7 @@ public class VaultCertificateRequest {
* the certificate field will contain the private key and certificate, concatenated;
* if the issuing CA is not a Vault-derived self-signed root, this will be included as
* well.
*
* @since 2.4
*/
private final String format;
@@ -85,49 +105,35 @@ public class VaultCertificateRequest {
* which will return either base64-encoded DER or PEM-encoded DER, depending on the
* value of {@literal format}. The other option is {@literal pkcs8} which will return
* the key marshalled as PEM-encoded PKCS8.
*
* @since 2.4
*/
@Nullable
private final String privateKeyFormat;
/**
* Set the Not After field of the certificate with specified date value. The value
* format should be given in UTC format YYYY-MM-ddTHH:MM:SSZ. Supports the Y10K end
* date for IEEE 802.1AR-2018 standard devices, 9999-12-31T23:59:59Z.
*/
@Nullable
private Instant notAfter;
/**
* Specifies the comma-separated list of requested User ID (OID
* 0.9.2342.19200300.100.1.1) Subject values to be placed on the signed certificate.
* This field is validated against allowed_user_ids on the role.
*/
@Nullable
private String userIds;
private final String userIds;
/**
* If {@literal true}, the given common name will not be included in DNS or Email
* Subject Alternate Names (as appropriate). Useful if the CN is not a hostname or
* email address, but is instead some human-readable identifier.
*/
private final boolean excludeCommonNameFromSubjectAltNames;
private VaultCertificateRequest(String commonName, List<String> altNames, List<String> ipSubjectAltNames,
List<String> uriSubjectAltNames, List<String> otherSans, @Nullable Duration ttl, String format,
@Nullable String privateKeyFormat, boolean excludeCommonNameFromSubjectAltNames, @Nullable Instant notAfter,
@Nullable String userIds) {
private VaultCertificateRequest(String commonName, boolean excludeCommonNameFromSubjectAltNames,
List<String> altNames, List<String> ipSubjectAltNames, List<String> uriSubjectAltNames,
List<String> otherSans, @Nullable Duration ttl, @Nullable Instant notAfter, String format,
@Nullable String privateKeyFormat, @Nullable String userIds) {
this.commonName = commonName;
this.excludeCommonNameFromSubjectAltNames = excludeCommonNameFromSubjectAltNames;
this.altNames = altNames;
this.ipSubjectAltNames = ipSubjectAltNames;
this.uriSubjectAltNames = uriSubjectAltNames;
this.otherSans = otherSans;
this.ttl = ttl;
this.excludeCommonNameFromSubjectAltNames = excludeCommonNameFromSubjectAltNames;
this.notAfter = notAfter;
this.format = format;
this.privateKeyFormat = privateKeyFormat;
this.notAfter = notAfter;
this.userIds = userIds;
}
@@ -240,6 +246,18 @@ public class VaultCertificateRequest {
return this;
}
/**
* Exclude the given common name from DNS or Email Subject Alternate Names (as
* appropriate). Useful if the CN is not a hostname or email address, but is
* instead some human-readable identifier.
* @return {@code this} {@link VaultCertificateRequestBuilder}.
*/
public VaultCertificateRequestBuilder excludeCommonNameFromSubjectAltNames() {
this.excludeCommonNameFromSubjectAltNames = true;
return this;
}
/**
* Configure alternative names. Replaces previously configured alt names.
* @param altNames must not be {@literal null}.
@@ -381,6 +399,21 @@ public class VaultCertificateRequest {
return this;
}
/**
* Set the {@code Not After} field of the certificate with specified date value.
* Supports the Y10K end date for IEEE 802.1AR-2018 standard devices,
* 9999-12-31T23:59:59Z.
* @return {@code this} {@link VaultCertificateRequestBuilder}.
* @since 3.1
*/
public VaultCertificateRequestBuilder notAfter(Instant notAfter) {
Assert.notNull(notAfter, "Not after must not be null");
this.notAfter = Instant.from(notAfter).truncatedTo(ChronoUnit.SECONDS);
return this;
}
/**
* Configure the certificate format.
* @param format the certificate format to use. Can be {@code pem}, {@code der},
@@ -412,28 +445,17 @@ public class VaultCertificateRequest {
}
/**
* Exclude the given common name from DNS or Email Subject Alternate Names (as
* appropriate). Useful if the CN is not a hostname or email address, but is
* instead some human-readable identifier.
* Specifies the comma-separated list of requested User ID (OID
* 0.9.2342.19200300.100.1.1) Subject values to be placed on the signed
* certificate. This field is validated against allowed_user_ids on the role.
* @return {@code this} {@link VaultCertificateRequestBuilder}.
* @since 3.1
*/
public VaultCertificateRequestBuilder excludeCommonNameFromSubjectAltNames() {
public VaultCertificateRequestBuilder userId(String userId) {
this.excludeCommonNameFromSubjectAltNames = true;
return this;
}
Assert.hasText(userId, "User ID must not be empty or null");
/**
* Set the Not After field of the certificate with specified date value. The value
* format should be given in UTC format YYYY-MM-ddTHH:MM:SSZ. Supports the Y10K
* end date for IEEE 802.1AR-2018 standard devices, 9999-12-31T23:59:59Z.
* @return {@code this} {@link VaultCertificateRequestBuilder}.
*/
public VaultCertificateRequestBuilder notAfter(Instant notAfter) {
Assert.notNull(notAfter, "Not after must not be null");
this.notAfter = Instant.from(notAfter).truncatedTo(ChronoUnit.SECONDS);
this.userIds = userId;
return this;
}
@@ -442,12 +464,13 @@ public class VaultCertificateRequest {
* 0.9.2342.19200300.100.1.1) Subject values to be placed on the signed
* certificate. This field is validated against allowed_user_ids on the role.
* @return {@code this} {@link VaultCertificateRequestBuilder}.
* @since 3.1
*/
public VaultCertificateRequestBuilder userIds(String userIds) {
public VaultCertificateRequestBuilder userIds(Collection<String> userIds) {
Assert.hasText(userIds, "User IDs must not be empty or null");
Assert.notNull(userIds, "User IDs must not be null");
this.userIds = userIds;
this.userIds = StringUtils.collectionToCommaDelimitedString(userIds);
return this;
}
@@ -510,9 +533,9 @@ public class VaultCertificateRequest {
otherSans = java.util.Collections.unmodifiableList(new ArrayList<>(this.otherSans));
}
return new VaultCertificateRequest(this.commonName, altNames, ipSubjectAltNames, uriSubjectAltNames,
otherSans, this.ttl, this.format, this.privateKeyFormat, this.excludeCommonNameFromSubjectAltNames,
notAfter, userIds);
return new VaultCertificateRequest(this.commonName, this.excludeCommonNameFromSubjectAltNames, altNames,
ipSubjectAltNames, uriSubjectAltNames, otherSans, this.ttl, notAfter, this.format,
this.privateKeyFormat, userIds);
}
private static <E> List<E> toList(Iterable<E> iter) {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2017-2022 the original author or authors.
* Copyright 2017-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,6 +19,7 @@ package org.springframework.vault.support;
* Value object to bind Vault HTTP PKI issue certificate API responses.
*
* @author Nanne Baars
* @since 3.1
*/
public class VaultIssuerCertificateRequestResponse extends VaultResponseSupport<Certificate> {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2016-2022 the original author or authors.
* Copyright 2016-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -59,8 +59,10 @@ import org.springframework.vault.util.RequiresVaultVersion;
import org.springframework.vault.util.Version;
import org.springframework.web.client.HttpClientErrorException;
import static org.assertj.core.api.Assertions.*;
import static org.springframework.vault.util.Settings.*;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.springframework.vault.util.Settings.findWorkDir;
/**
* Integration tests for {@link VaultPkiTemplate} through {@link VaultPkiOperations}.
@@ -268,24 +270,27 @@ class VaultPkiTemplateIntegrationTests extends IntegrationTestSupport {
@Test
void signShouldSignCsrWithNotAfter() {
Instant notAfter = Instant.now().plus(50, ChronoUnit.DAYS);
String csr = "-----BEGIN CERTIFICATE REQUEST-----\n"
+ "MIICzTCCAbUCAQAwgYcxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpTb21lLVN0YXRl\n"
+ "MRUwEwYDVQQHEwxTYW4gVmF1bHRpbm8xFTATBgNVBAoTDFNwcmluZyBWYXVsdDEY\n"
+ "MBYGA1UEAxMPY3NyLmV4YW1wbGUuY29tMRswGQYJKoZIhvcNAQkBFgxzcHJpbmdA\n"
+ "dmF1bHQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDVlDBT1gAONIp4\n"
+ "GQQ7BWDeqNzlscWqu5oQyfvw6oNFZzYWGVTgX/n72biv8d1Wx30MWpVYhbL0mk9m\n"
+ "Uu15elMZHPb4F4bk8VDSiB9527SwAd/QpkNC1RsPp2h6g2LvGPJ2eidHSlLtF2To\n"
+ "A4i6z0K0++nvYKSf9Af0sod2Z51xc9uPj/oN5z/8BQuGoCBpxJqgl7N/csMICixY\n"
+ "2fQcCUbdPPqE9INIInUHe3mPE/yvxko9aYGZ5jnrdZyiQaRRKBdWpvbRLKXQ78Fz\n"
+ "vXR3G33yn9JAN6wl1A916DiXzy2xHT19vyAn1hBUj2M6KFXChQ30oxTyTOqHCMLP\n"
+ "m/BSEOsPAgMBAAGgADANBgkqhkiG9w0BAQsFAAOCAQEAYFssueiUh3YGxnXcQ4dp\n"
+ "ZqVWeVyOuGGaFJ4BA0drwJ9Mt/iNmPUTGE2oBNnh2R7e7HwGcNysFHZZOZBEQ0Hh\n"
+ "Vn93GO7cfaTOetK0VtDqis1VFQD0eVPWf5s6UqT/+XGrFRhwJ9hM+2FQSrUDFecs\n"
+ "+/605n1rD7qOj3vkGrtwvEUrxyRaQaKpPLHmVHENqV6F1NsO3Z27f2FWWAZF2VKN\n"
+ "cCQQJNc//DbIN3J3JSElpIDBDHctoBoQVnMiwpCbSA+CaAtlWYJKnAfhTKeqnNMy\n"
+ "qf3ACZ+1sBIuqSP7dEJ2KfIezaCPQ88+PAloRB52LFa+iq3yI7F5VzkwAvQFnTi+\n" + "cQ==\n"
+ "-----END CERTIFICATE REQUEST-----";
String csr = """
-----BEGIN CERTIFICATE REQUEST-----
MIICzTCCAbUCAQAwgYcxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpTb21lLVN0YXRl
MRUwEwYDVQQHEwxTYW4gVmF1bHRpbm8xFTATBgNVBAoTDFNwcmluZyBWYXVsdDEY
MBYGA1UEAxMPY3NyLmV4YW1wbGUuY29tMRswGQYJKoZIhvcNAQkBFgxzcHJpbmdA
dmF1bHQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDVlDBT1gAONIp4
GQQ7BWDeqNzlscWqu5oQyfvw6oNFZzYWGVTgX/n72biv8d1Wx30MWpVYhbL0mk9m
Uu15elMZHPb4F4bk8VDSiB9527SwAd/QpkNC1RsPp2h6g2LvGPJ2eidHSlLtF2To
A4i6z0K0++nvYKSf9Af0sod2Z51xc9uPj/oN5z/8BQuGoCBpxJqgl7N/csMICixY
2fQcCUbdPPqE9INIInUHe3mPE/yvxko9aYGZ5jnrdZyiQaRRKBdWpvbRLKXQ78Fz
vXR3G33yn9JAN6wl1A916DiXzy2xHT19vyAn1hBUj2M6KFXChQ30oxTyTOqHCMLP
m/BSEOsPAgMBAAGgADANBgkqhkiG9w0BAQsFAAOCAQEAYFssueiUh3YGxnXcQ4dp
ZqVWeVyOuGGaFJ4BA0drwJ9Mt/iNmPUTGE2oBNnh2R7e7HwGcNysFHZZOZBEQ0Hh
Vn93GO7cfaTOetK0VtDqis1VFQD0eVPWf5s6UqT/+XGrFRhwJ9hM+2FQSrUDFecs
+/605n1rD7qOj3vkGrtwvEUrxyRaQaKpPLHmVHENqV6F1NsO3Z27f2FWWAZF2VKN
cCQQJNc//DbIN3J3JSElpIDBDHctoBoQVnMiwpCbSA+CaAtlWYJKnAfhTKeqnNMy
qf3ACZ+1sBIuqSP7dEJ2KfIezaCPQ88+PAloRB52LFa+iq3yI7F5VzkwAvQFnTi+
cQ==
-----END CERTIFICATE REQUEST-----""";
VaultCertificateRequest request = VaultCertificateRequest.builder()
.commonName("hello.example.com")
@@ -302,27 +307,30 @@ class VaultPkiTemplateIntegrationTests extends IntegrationTestSupport {
@Test
@RequiresVaultVersion("1.14.2")
void signShouldFailWithUnknownUserIds() {
String csr = "-----BEGIN CERTIFICATE REQUEST-----\n"
+ "MIICzTCCAbUCAQAwgYcxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpTb21lLVN0YXRl\n"
+ "MRUwEwYDVQQHEwxTYW4gVmF1bHRpbm8xFTATBgNVBAoTDFNwcmluZyBWYXVsdDEY\n"
+ "MBYGA1UEAxMPY3NyLmV4YW1wbGUuY29tMRswGQYJKoZIhvcNAQkBFgxzcHJpbmdA\n"
+ "dmF1bHQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDVlDBT1gAONIp4\n"
+ "GQQ7BWDeqNzlscWqu5oQyfvw6oNFZzYWGVTgX/n72biv8d1Wx30MWpVYhbL0mk9m\n"
+ "Uu15elMZHPb4F4bk8VDSiB9527SwAd/QpkNC1RsPp2h6g2LvGPJ2eidHSlLtF2To\n"
+ "A4i6z0K0++nvYKSf9Af0sod2Z51xc9uPj/oN5z/8BQuGoCBpxJqgl7N/csMICixY\n"
+ "2fQcCUbdPPqE9INIInUHe3mPE/yvxko9aYGZ5jnrdZyiQaRRKBdWpvbRLKXQ78Fz\n"
+ "vXR3G33yn9JAN6wl1A916DiXzy2xHT19vyAn1hBUj2M6KFXChQ30oxTyTOqHCMLP\n"
+ "m/BSEOsPAgMBAAGgADANBgkqhkiG9w0BAQsFAAOCAQEAYFssueiUh3YGxnXcQ4dp\n"
+ "ZqVWeVyOuGGaFJ4BA0drwJ9Mt/iNmPUTGE2oBNnh2R7e7HwGcNysFHZZOZBEQ0Hh\n"
+ "Vn93GO7cfaTOetK0VtDqis1VFQD0eVPWf5s6UqT/+XGrFRhwJ9hM+2FQSrUDFecs\n"
+ "+/605n1rD7qOj3vkGrtwvEUrxyRaQaKpPLHmVHENqV6F1NsO3Z27f2FWWAZF2VKN\n"
+ "cCQQJNc//DbIN3J3JSElpIDBDHctoBoQVnMiwpCbSA+CaAtlWYJKnAfhTKeqnNMy\n"
+ "qf3ACZ+1sBIuqSP7dEJ2KfIezaCPQ88+PAloRB52LFa+iq3yI7F5VzkwAvQFnTi+\n" + "cQ==\n"
+ "-----END CERTIFICATE REQUEST-----";
String csr = """
-----BEGIN CERTIFICATE REQUEST-----
MIICzTCCAbUCAQAwgYcxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpTb21lLVN0YXRl
MRUwEwYDVQQHEwxTYW4gVmF1bHRpbm8xFTATBgNVBAoTDFNwcmluZyBWYXVsdDEY
MBYGA1UEAxMPY3NyLmV4YW1wbGUuY29tMRswGQYJKoZIhvcNAQkBFgxzcHJpbmdA
dmF1bHQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDVlDBT1gAONIp4
GQQ7BWDeqNzlscWqu5oQyfvw6oNFZzYWGVTgX/n72biv8d1Wx30MWpVYhbL0mk9m
Uu15elMZHPb4F4bk8VDSiB9527SwAd/QpkNC1RsPp2h6g2LvGPJ2eidHSlLtF2To
A4i6z0K0++nvYKSf9Af0sod2Z51xc9uPj/oN5z/8BQuGoCBpxJqgl7N/csMICixY
2fQcCUbdPPqE9INIInUHe3mPE/yvxko9aYGZ5jnrdZyiQaRRKBdWpvbRLKXQ78Fz
vXR3G33yn9JAN6wl1A916DiXzy2xHT19vyAn1hBUj2M6KFXChQ30oxTyTOqHCMLP
m/BSEOsPAgMBAAGgADANBgkqhkiG9w0BAQsFAAOCAQEAYFssueiUh3YGxnXcQ4dp
ZqVWeVyOuGGaFJ4BA0drwJ9Mt/iNmPUTGE2oBNnh2R7e7HwGcNysFHZZOZBEQ0Hh
Vn93GO7cfaTOetK0VtDqis1VFQD0eVPWf5s6UqT/+XGrFRhwJ9hM+2FQSrUDFecs
+/605n1rD7qOj3vkGrtwvEUrxyRaQaKpPLHmVHENqV6F1NsO3Z27f2FWWAZF2VKN
cCQQJNc//DbIN3J3JSElpIDBDHctoBoQVnMiwpCbSA+CaAtlWYJKnAfhTKeqnNMy
qf3ACZ+1sBIuqSP7dEJ2KfIezaCPQ88+PAloRB52LFa+iq3yI7F5VzkwAvQFnTi+
cQ==
-----END CERTIFICATE REQUEST-----""";
VaultCertificateRequest request = VaultCertificateRequest.builder()
.commonName("hello.example.com")
.userIds("test1,test2")
.userIds(List.of("test1", "test2"))
.build();
assertThatThrownBy(() -> this.pkiOperations.signCertificateRequest("testrole", csr, request))
@@ -333,27 +341,29 @@ class VaultPkiTemplateIntegrationTests extends IntegrationTestSupport {
@Test
@RequiresVaultVersion("1.14.2")
void signShouldSignWithKnownUserIds() {
String csr = "-----BEGIN CERTIFICATE REQUEST-----\n"
+ "MIICzTCCAbUCAQAwgYcxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpTb21lLVN0YXRl\n"
+ "MRUwEwYDVQQHEwxTYW4gVmF1bHRpbm8xFTATBgNVBAoTDFNwcmluZyBWYXVsdDEY\n"
+ "MBYGA1UEAxMPY3NyLmV4YW1wbGUuY29tMRswGQYJKoZIhvcNAQkBFgxzcHJpbmdA\n"
+ "dmF1bHQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDVlDBT1gAONIp4\n"
+ "GQQ7BWDeqNzlscWqu5oQyfvw6oNFZzYWGVTgX/n72biv8d1Wx30MWpVYhbL0mk9m\n"
+ "Uu15elMZHPb4F4bk8VDSiB9527SwAd/QpkNC1RsPp2h6g2LvGPJ2eidHSlLtF2To\n"
+ "A4i6z0K0++nvYKSf9Af0sod2Z51xc9uPj/oN5z/8BQuGoCBpxJqgl7N/csMICixY\n"
+ "2fQcCUbdPPqE9INIInUHe3mPE/yvxko9aYGZ5jnrdZyiQaRRKBdWpvbRLKXQ78Fz\n"
+ "vXR3G33yn9JAN6wl1A916DiXzy2xHT19vyAn1hBUj2M6KFXChQ30oxTyTOqHCMLP\n"
+ "m/BSEOsPAgMBAAGgADANBgkqhkiG9w0BAQsFAAOCAQEAYFssueiUh3YGxnXcQ4dp\n"
+ "ZqVWeVyOuGGaFJ4BA0drwJ9Mt/iNmPUTGE2oBNnh2R7e7HwGcNysFHZZOZBEQ0Hh\n"
+ "Vn93GO7cfaTOetK0VtDqis1VFQD0eVPWf5s6UqT/+XGrFRhwJ9hM+2FQSrUDFecs\n"
+ "+/605n1rD7qOj3vkGrtwvEUrxyRaQaKpPLHmVHENqV6F1NsO3Z27f2FWWAZF2VKN\n"
+ "cCQQJNc//DbIN3J3JSElpIDBDHctoBoQVnMiwpCbSA+CaAtlWYJKnAfhTKeqnNMy\n"
+ "qf3ACZ+1sBIuqSP7dEJ2KfIezaCPQ88+PAloRB52LFa+iq3yI7F5VzkwAvQFnTi+\n" + "cQ==\n"
+ "-----END CERTIFICATE REQUEST-----";
String csr = """
-----BEGIN CERTIFICATE REQUEST-----
MIICzTCCAbUCAQAwgYcxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpTb21lLVN0YXRl
MRUwEwYDVQQHEwxTYW4gVmF1bHRpbm8xFTATBgNVBAoTDFNwcmluZyBWYXVsdDEY
MBYGA1UEAxMPY3NyLmV4YW1wbGUuY29tMRswGQYJKoZIhvcNAQkBFgxzcHJpbmdA
dmF1bHQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDVlDBT1gAONIp4
GQQ7BWDeqNzlscWqu5oQyfvw6oNFZzYWGVTgX/n72biv8d1Wx30MWpVYhbL0mk9m
Uu15elMZHPb4F4bk8VDSiB9527SwAd/QpkNC1RsPp2h6g2LvGPJ2eidHSlLtF2To
A4i6z0K0++nvYKSf9Af0sod2Z51xc9uPj/oN5z/8BQuGoCBpxJqgl7N/csMICixY
2fQcCUbdPPqE9INIInUHe3mPE/yvxko9aYGZ5jnrdZyiQaRRKBdWpvbRLKXQ78Fz
vXR3G33yn9JAN6wl1A916DiXzy2xHT19vyAn1hBUj2M6KFXChQ30oxTyTOqHCMLP
m/BSEOsPAgMBAAGgADANBgkqhkiG9w0BAQsFAAOCAQEAYFssueiUh3YGxnXcQ4dp
ZqVWeVyOuGGaFJ4BA0drwJ9Mt/iNmPUTGE2oBNnh2R7e7HwGcNysFHZZOZBEQ0Hh
Vn93GO7cfaTOetK0VtDqis1VFQD0eVPWf5s6UqT/+XGrFRhwJ9hM+2FQSrUDFecs
+/605n1rD7qOj3vkGrtwvEUrxyRaQaKpPLHmVHENqV6F1NsO3Z27f2FWWAZF2VKN
cCQQJNc//DbIN3J3JSElpIDBDHctoBoQVnMiwpCbSA+CaAtlWYJKnAfhTKeqnNMy
qf3ACZ+1sBIuqSP7dEJ2KfIezaCPQ88+PAloRB52LFa+iq3yI7F5VzkwAvQFnTi+
cQ==
-----END CERTIFICATE REQUEST-----""";
VaultCertificateRequest request = VaultCertificateRequest.builder()
.commonName("hello.example.com")
.userIds("robot,humanoid")
.userIds(Arrays.asList("robot", "humanoid"))
.build();
VaultSignCertificateRequestResponse certificateResponse = this.pkiOperations.signCertificateRequest("testrole",
@@ -369,23 +379,25 @@ class VaultPkiTemplateIntegrationTests extends IntegrationTestSupport {
@Test
void signShouldSignCsr() {
String csr = "-----BEGIN CERTIFICATE REQUEST-----\n"
+ "MIICzTCCAbUCAQAwgYcxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpTb21lLVN0YXRl\n"
+ "MRUwEwYDVQQHEwxTYW4gVmF1bHRpbm8xFTATBgNVBAoTDFNwcmluZyBWYXVsdDEY\n"
+ "MBYGA1UEAxMPY3NyLmV4YW1wbGUuY29tMRswGQYJKoZIhvcNAQkBFgxzcHJpbmdA\n"
+ "dmF1bHQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDVlDBT1gAONIp4\n"
+ "GQQ7BWDeqNzlscWqu5oQyfvw6oNFZzYWGVTgX/n72biv8d1Wx30MWpVYhbL0mk9m\n"
+ "Uu15elMZHPb4F4bk8VDSiB9527SwAd/QpkNC1RsPp2h6g2LvGPJ2eidHSlLtF2To\n"
+ "A4i6z0K0++nvYKSf9Af0sod2Z51xc9uPj/oN5z/8BQuGoCBpxJqgl7N/csMICixY\n"
+ "2fQcCUbdPPqE9INIInUHe3mPE/yvxko9aYGZ5jnrdZyiQaRRKBdWpvbRLKXQ78Fz\n"
+ "vXR3G33yn9JAN6wl1A916DiXzy2xHT19vyAn1hBUj2M6KFXChQ30oxTyTOqHCMLP\n"
+ "m/BSEOsPAgMBAAGgADANBgkqhkiG9w0BAQsFAAOCAQEAYFssueiUh3YGxnXcQ4dp\n"
+ "ZqVWeVyOuGGaFJ4BA0drwJ9Mt/iNmPUTGE2oBNnh2R7e7HwGcNysFHZZOZBEQ0Hh\n"
+ "Vn93GO7cfaTOetK0VtDqis1VFQD0eVPWf5s6UqT/+XGrFRhwJ9hM+2FQSrUDFecs\n"
+ "+/605n1rD7qOj3vkGrtwvEUrxyRaQaKpPLHmVHENqV6F1NsO3Z27f2FWWAZF2VKN\n"
+ "cCQQJNc//DbIN3J3JSElpIDBDHctoBoQVnMiwpCbSA+CaAtlWYJKnAfhTKeqnNMy\n"
+ "qf3ACZ+1sBIuqSP7dEJ2KfIezaCPQ88+PAloRB52LFa+iq3yI7F5VzkwAvQFnTi+\n" + "cQ==\n"
+ "-----END CERTIFICATE REQUEST-----";
String csr = """
-----BEGIN CERTIFICATE REQUEST-----
MIICzTCCAbUCAQAwgYcxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpTb21lLVN0YXRl
MRUwEwYDVQQHEwxTYW4gVmF1bHRpbm8xFTATBgNVBAoTDFNwcmluZyBWYXVsdDEY
MBYGA1UEAxMPY3NyLmV4YW1wbGUuY29tMRswGQYJKoZIhvcNAQkBFgxzcHJpbmdA
dmF1bHQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDVlDBT1gAONIp4
GQQ7BWDeqNzlscWqu5oQyfvw6oNFZzYWGVTgX/n72biv8d1Wx30MWpVYhbL0mk9m
Uu15elMZHPb4F4bk8VDSiB9527SwAd/QpkNC1RsPp2h6g2LvGPJ2eidHSlLtF2To
A4i6z0K0++nvYKSf9Af0sod2Z51xc9uPj/oN5z/8BQuGoCBpxJqgl7N/csMICixY
2fQcCUbdPPqE9INIInUHe3mPE/yvxko9aYGZ5jnrdZyiQaRRKBdWpvbRLKXQ78Fz
vXR3G33yn9JAN6wl1A916DiXzy2xHT19vyAn1hBUj2M6KFXChQ30oxTyTOqHCMLP
m/BSEOsPAgMBAAGgADANBgkqhkiG9w0BAQsFAAOCAQEAYFssueiUh3YGxnXcQ4dp
ZqVWeVyOuGGaFJ4BA0drwJ9Mt/iNmPUTGE2oBNnh2R7e7HwGcNysFHZZOZBEQ0Hh
Vn93GO7cfaTOetK0VtDqis1VFQD0eVPWf5s6UqT/+XGrFRhwJ9hM+2FQSrUDFecs
+/605n1rD7qOj3vkGrtwvEUrxyRaQaKpPLHmVHENqV6F1NsO3Z27f2FWWAZF2VKN
cCQQJNc//DbIN3J3JSElpIDBDHctoBoQVnMiwpCbSA+CaAtlWYJKnAfhTKeqnNMy
qf3ACZ+1sBIuqSP7dEJ2KfIezaCPQ88+PAloRB52LFa+iq3yI7F5VzkwAvQFnTi+
cQ==
-----END CERTIFICATE REQUEST-----""";
VaultCertificateRequest request = VaultCertificateRequest.create("hello.example.com");
@@ -450,6 +462,7 @@ class VaultPkiTemplateIntegrationTests extends IntegrationTestSupport {
@Test
void shouldReturnCA() throws Exception {
VaultIssuerCertificateRequestResponse certificateResponse = this.pkiOperations.getIssuerCertificate("default");
Certificate data = certificateResponse.getRequiredData();