Adding fetchJwtSvid method not requiring subject as parameter.

Signed-off-by: Max Lambrecht <maxlambrecht@gmail.com>
This commit is contained in:
Max Lambrecht 2020-07-06 16:21:06 -03:00
parent db4e78616e
commit d310d7bbee
7 changed files with 73 additions and 1 deletions

View File

@ -8,6 +8,16 @@ import io.spiffe.spiffeid.SpiffeId;
*/ */
public interface JwtSvidSource { public interface JwtSvidSource {
/**
* Fetches a JWT-SVID from the source with the given audiences.
*
* @param audience the audience
* @param extraAudiences a list of extra audiences as an array of String
* @return a {@link JwtSvid}
* @throws JwtSvidException when there is an error fetching the JWT SVID
*/
JwtSvid fetchJwtSvid(String audience, String... extraAudiences) throws JwtSvidException;
/** /**
* Fetches a JWT-SVID from the source with the given subject and audiences. * Fetches a JWT-SVID from the source with the given subject and audiences.
* *

View File

@ -181,6 +181,19 @@ public final class DefaultWorkloadApiClient implements WorkloadApiClient {
this.cancellableContexts.add(cancellableContext); this.cancellableContexts.add(cancellableContext);
} }
/**
* {@inheritDoc}
*/
@Override
public JwtSvid fetchJwtSvid(@NonNull String audience, String... extraAudience) throws JwtSvidException {
final Set<String> audParam = createAudienceSet(audience, extraAudience);
try (val cancellableContext = Context.current().withCancellation()) {
return cancellableContext.call(() -> callFetchJwtSvid(audParam));
} catch (Exception e) {
throw new JwtSvidException("Error fetching JWT SVID", e);
}
}
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@ -289,6 +302,14 @@ public final class DefaultWorkloadApiClient implements WorkloadApiClient {
return JwtSvid.parseInsecure(response.getSvids(0).getSvid(), audience); return JwtSvid.parseInsecure(response.getSvids(0).getSvid(), audience);
} }
private JwtSvid callFetchJwtSvid(final Set<String> audience) throws JwtSvidException {
val jwtSvidRequest = Workload.JWTSVIDRequest.newBuilder()
.addAllAudience(audience)
.build();
val response = workloadApiBlockingStub.fetchJWTSVID(jwtSvidRequest);
return JwtSvid.parseInsecure(response.getSvids(0).getSvid(), audience);
}
private JwtBundleSet callFetchBundles() throws JwtBundleException { private JwtBundleSet callFetchBundles() throws JwtBundleException {
val request = Workload.JWTBundlesRequest.newBuilder().build(); val request = Workload.JWTBundlesRequest.newBuilder().build();
val bundlesResponse = workloadApiBlockingStub.fetchJWTBundles(request); val bundlesResponse = workloadApiBlockingStub.fetchJWTBundles(request);

View File

@ -107,6 +107,14 @@ public class JwtSource implements JwtSvidSource, BundleSource<JwtBundle>, Closea
return jwtSource; return jwtSource;
} }
@Override
public JwtSvid fetchJwtSvid(String audience, String... extraAudiences) throws JwtSvidException {
if (isClosed()) {
throw new IllegalStateException("JWT SVID source is closed");
}
return workloadApiClient.fetchJwtSvid(audience, extraAudiences);
}
/** /**
* Fetches a new JWT SVID from the Workload API for the given subject SPIFFE ID and audiences. * Fetches a new JWT SVID from the Workload API for the given subject SPIFFE ID and audiences.
* *

View File

@ -36,6 +36,16 @@ public interface WorkloadApiClient extends Closeable {
*/ */
void watchX509Context(@NonNull Watcher<X509Context> watcher); void watchX509Context(@NonNull Watcher<X509Context> watcher);
/**
* Fetches a SPIFFE JWT-SVID on one-shot blocking call.
*
* @param audience the audience of the JWT-SVID
* @param extraAudience the extra audience for the JWT_SVID
* @return an instance of a {@link JwtSvid}
* @throws JwtSvidException if there is an error fetching or processing the JWT from the Workload API
*/
JwtSvid fetchJwtSvid(@NonNull String audience, String... extraAudience) throws JwtSvidException;
/** /**
* Fetches a SPIFFE JWT-SVID on one-shot blocking call. * Fetches a SPIFFE JWT-SVID on one-shot blocking call.
* *

View File

@ -61,7 +61,7 @@ class JwtSourceTest {
} }
@Test @Test
void testFetchJwtSvid() { void testFetchJwtSvidWithSubject() {
try { try {
JwtSvid svid = jwtSource.fetchJwtSvid(SpiffeId.parse("spiffe://example.org/workload-server"), "aud1", "aud2", "aud3"); JwtSvid svid = jwtSource.fetchJwtSvid(SpiffeId.parse("spiffe://example.org/workload-server"), "aud1", "aud2", "aud3");
assertNotNull(svid); assertNotNull(svid);
@ -72,6 +72,18 @@ class JwtSourceTest {
} }
} }
@Test
void testFetchJwtSvidWithoutSubject() {
try {
JwtSvid svid = jwtSource.fetchJwtSvid("aud1", "aud2", "aud3");
assertNotNull(svid);
assertEquals(SpiffeId.parse("spiffe://example.org/workload-server"), svid.getSpiffeId());
assertEquals(Sets.newHashSet("aud1", "aud2", "aud3"), svid.getAudience());
} catch (JwtSvidException e) {
fail(e);
}
}
@Test @Test
void testFetchJwtSvid_SourceIsClosed_ThrowsIllegalStateException() { void testFetchJwtSvid_SourceIsClosed_ThrowsIllegalStateException() {
jwtSource.close(); jwtSource.close();

View File

@ -39,6 +39,7 @@ public class WorkloadApiClientStub implements WorkloadApiClient {
final String svid = "testdata/workloadapi/svid.der"; final String svid = "testdata/workloadapi/svid.der";
final String x509Bundle = "testdata/workloadapi/bundle.der"; final String x509Bundle = "testdata/workloadapi/bundle.der";
final String jwtBundle = "testdata/workloadapi/bundle.json"; final String jwtBundle = "testdata/workloadapi/bundle.json";
final SpiffeId subject = SpiffeId.parse("spiffe://example.org/workload-server");
boolean closed; boolean closed;
@ -53,6 +54,11 @@ public class WorkloadApiClientStub implements WorkloadApiClient {
watcher.onUpdate(update); watcher.onUpdate(update);
} }
@Override
public JwtSvid fetchJwtSvid(@NonNull final String audience, final String... extraAudience) throws JwtSvidException {
return generateJwtSvid(subject, audience, extraAudience);
}
@Override @Override
public JwtSvid fetchJwtSvid(@NonNull final SpiffeId subject, @NonNull final String audience, final String... extraAudience) throws JwtSvidException { public JwtSvid fetchJwtSvid(@NonNull final SpiffeId subject, @NonNull final String audience, final String... extraAudience) throws JwtSvidException {
return generateJwtSvid(subject, audience, extraAudience); return generateJwtSvid(subject, audience, extraAudience);

View File

@ -42,6 +42,11 @@ public class WorkloadApiClientStub implements WorkloadApiClient {
watcher.onUpdate(update); watcher.onUpdate(update);
} }
@Override
public JwtSvid fetchJwtSvid(@NonNull String audience, String... extraAudience) throws JwtSvidException {
return null;
}
@Override @Override
public JwtSvid fetchJwtSvid(@NonNull final SpiffeId subject, @NonNull final String audience, final String... extraAudience) throws JwtSvidException { public JwtSvid fetchJwtSvid(@NonNull final SpiffeId subject, @NonNull final String audience, final String... extraAudience) throws JwtSvidException {
return null; return null;