Skip to content
This repository has been archived by the owner on Jun 1, 2022. It is now read-only.

Commit

Permalink
align ilp over http custom settings (#408)
Browse files Browse the repository at this point in the history
* align Ilp-over-http custom settings to match update property style
style should match property definition in issue #383
removed deprecated incomingHttpLinkSettings and outgoingHttpLinkSettings accessors

Signed-off-by: nhartner <[email protected]>

* align Ilp-over-http custom settings to match update property style
style should match property definition in issue #383
removed deprecated incomingHttpLinkSettings and outgoingHttpLinkSettings accessors

Signed-off-by: nhartner <[email protected]>

* guava android compatibility fix

Signed-off-by: nhartner <[email protected]>

* remove unsed SharedSecretTokenSettings

Signed-off-by: nhartner <[email protected]>

* bringing back AuthType on settings.
It was getting difficult to provide meaning error messages for missing fields without knowing the intention of what type of settings were being provided

Signed-off-by: nhartner <[email protected]>

* disable docker container logs

Signed-off-by: nhartner <[email protected]>

* remove fallback logic to deprecated property that no longer exists

Signed-off-by: nhartner <[email protected]>

* make jwt.token_audience a string instead of url because the JWT RFC
does not strictly require it to be a url and in the case of auth0, it's not a url for web flows

Signed-off-by: nhartner <[email protected]>

* fix typo

Signed-off-by: nhartner <[email protected]>

* fix javadoc to include auth_type as a required property

Signed-off-by: nhartner <[email protected]>

* remove deprecated fallback that has been removed

Signed-off-by: nhartner <[email protected]>

* Only require an outgoing url for IlpOverHttpLink instead of link settings

Signed-off-by: nhartner <[email protected]>

* nuke deprecated constructor

Signed-off-by: nhartner <[email protected]>

* fix typo

Signed-off-by: nhartner <[email protected]>

* make toCustomSettingsMap auxiliary so it doesn't get include in toString/hashCode etc

Signed-off-by: nhartner <[email protected]>

* fix testConnection to not use linkSettings and just use outgoingUrl
don't need to log authType either since it's not used

Signed-off-by: nhartner <[email protected]>
  • Loading branch information
nhartner authored Jan 2, 2020
1 parent cbcb47a commit 0e5d699
Show file tree
Hide file tree
Showing 22 changed files with 965 additions and 536 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,6 @@
import org.interledger.core.SharedSecret;
import org.interledger.link.Link;
import org.interledger.link.http.IlpOverHttpLink;
import org.interledger.link.http.IlpOverHttpLinkSettings;
import org.interledger.link.http.IncomingLinkSettings;
import org.interledger.link.http.OutgoingLinkSettings;
import org.interledger.link.http.auth.SimpleBearerTokenSupplier;
import org.interledger.spsp.PaymentPointer;
import org.interledger.spsp.StreamConnectionDetails;
Expand All @@ -19,6 +16,7 @@
import org.interledger.stream.Denominations;
import org.interledger.stream.SendMoneyRequest;
import org.interledger.stream.SendMoneyResult;
import org.interledger.stream.SenderAmountMode;
import org.interledger.stream.sender.FixedSenderAmountPaymentTracker;
import org.interledger.stream.sender.SimpleStreamSender;

Expand Down Expand Up @@ -74,6 +72,7 @@ public static void main(String[] args) throws ExecutionException, InterruptedExc
SendMoneyResult result = simpleStreamSender.sendMoney(
SendMoneyRequest.builder()
.sourceAddress(SENDER_ADDRESS)
.senderAmountMode(SenderAmountMode.SENDER_AMOUNT)
.amount(UnsignedLong.valueOf(100000))
.denomination(Denominations.XRP)
.destinationAddress(connectionDetails.destinationAddress())
Expand All @@ -88,23 +87,9 @@ public static void main(String[] args) throws ExecutionException, InterruptedExc
}

private static Link newIlpOverHttpLink() {
String sharedSecret = "some random secret here";
final IlpOverHttpLinkSettings linkSettings = IlpOverHttpLinkSettings.builder()
.incomingLinkSettings(IncomingLinkSettings.builder()
.authType(IlpOverHttpLinkSettings.AuthType.SIMPLE)
.encryptedTokenSharedSecret(sharedSecret)
.build())
.outgoingLinkSettings(OutgoingLinkSettings.builder()
.authType(IlpOverHttpLinkSettings.AuthType.SIMPLE)
.tokenSubject(SENDER_ACCOUNT_USERNAME)
.url(HttpUrl.parse(TESTNET_URI + "/ilp"))
.encryptedTokenSharedSecret(sharedSecret)
.build())
.build();

return new IlpOverHttpLink(
() -> SENDER_ADDRESS,
linkSettings,
HttpUrl.parse(TESTNET_URI + "/ilp"),
newHttpClient(),
new ObjectMapper(),
InterledgerCodecContextFactory.oer(),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package org.interledger.link.http;

import java.util.Optional;

/**
* Common auth settings for incoming and outgoing links.
*/
public interface AuthenticatedLinkSettings {

/**
* Auth settings if using SIMPLE scheme.
*
* @return settings
*/
Optional<SimpleAuthSettings> simpleAuthSettings();

/**
* Auth settings if using JWT scheme.
*
* @return settings
*/
Optional<JwtAuthSettings> jwtAuthSettings();


/**
* The type of Auth to support for this link.
*
* @return A {@link IlpOverHttpLinkSettings.AuthType} for this link
*/
IlpOverHttpLinkSettings.AuthType authType();

}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import com.google.common.io.CharStreams;
import com.google.common.net.HttpHeaders;
import okhttp3.Headers;
import okhttp3.HttpUrl;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Request.Builder;
Expand Down Expand Up @@ -77,14 +78,16 @@ public class IlpOverHttpLink extends AbstractLink<IlpOverHttpLinkSettings> imple
*/
private final Supplier<String> authTokenSupplier;

private final HttpUrl outgoingUrl;

/**
* Required-args Constructor.
*
* @param operatorAddressSupplier A supplier for the ILP address of this node operating this Link. This value may be
* uninitialized, for example, in cases where the Link obtains its address from a
* parent node using IL-DCP. If an ILP address has not been assigned, or it has not
* been obtained via IL-DCP, then this value will by default be {@link Link#SELF}.
* @param ilpOverHttpLinkSettings A {@link IlpOverHttpLinkSettings} that specified ledger link options.
* @param outgoingUrl A {@link HttpUrl} to the connector.
* @param okHttpClient A {@link OkHttpClient} to use to communicate with the remote ILP-over-HTTP
* endpoint.
* @param objectMapper A {@link ObjectMapper} for reading error responses from the remote ILP-over-HTTP
Expand All @@ -95,13 +98,17 @@ public class IlpOverHttpLink extends AbstractLink<IlpOverHttpLinkSettings> imple
*/
public IlpOverHttpLink(
final Supplier<InterledgerAddress> operatorAddressSupplier,
final IlpOverHttpLinkSettings ilpOverHttpLinkSettings,
final HttpUrl outgoingUrl,
final OkHttpClient okHttpClient,
final ObjectMapper objectMapper,
final CodecContext ilpCodecContext,
final BearerTokenSupplier bearerTokenSupplier
) {
super(operatorAddressSupplier, ilpOverHttpLinkSettings);
// IlpOverHttpLink does not require a full link settings, but the parent class requires one (even though it also
// does not use it for anything). For backwards compatibility pass a bare bones setting but ideally the abstract
// class could be refactored to not require it.
super(operatorAddressSupplier, IlpOverHttpLinkSettings.builder().build());
this.outgoingUrl = outgoingUrl;
this.okHttpClient = Objects.requireNonNull(okHttpClient);
this.objectMapper = Objects.requireNonNull(objectMapper);
this.ilpCodecContext = Objects.requireNonNull(ilpCodecContext);
Expand Down Expand Up @@ -189,15 +196,7 @@ public InterledgerResponsePacket sendPacket(final InterledgerPreparePacket prepa
* the endpoint does not support ILP-over-HTTP requests, then we expect a 415 UNSUPPORTED_MEDIA_TYPE.</p>
*/
public void testConnection() {
final OutgoingLinkSettings outgoingLinkSettings = this.getLinkSettings().outgoingLinkSettings()
.orElseGet(() -> {
logger.warn("Falling back to deprecated means of loading outgoing settings. " +
"Please switch to using outgoingLinkSettings() instead");
return this.getLinkSettings().outgoingHttpLinkSettings();
});
final String tokenSubject = outgoingLinkSettings.tokenSubject();
try {

final Request okHttpRequest = this.constructSendPacketRequest(UNFULFILLABLE_PACKET);

try (Response response = okHttpClient.newCall(okHttpRequest).execute()) {
Expand All @@ -211,26 +210,26 @@ public void testConnection() {
.isPresent();

if (responseHasOctetStreamContentType) {
logger.info("Remote peer-link supports ILP-over-HTTP. tokenSubject={} url={} responseHeaders={}",
outgoingLinkSettings.tokenSubject(), outgoingLinkSettings.url(), response
logger.info("Remote peer-link supports ILP-over-HTTP. url={} responseHeaders={}",
outgoingUrl, response
);
} else {
logger.warn("Remote peer-link supports ILP-over-HTTP but uses wrong ContentType. tokenSubject={} url={} "
logger.warn("Remote peer-link supports ILP-over-HTTP but uses wrong ContentType. url={} "
+ "response={}",
outgoingLinkSettings.tokenSubject(), outgoingLinkSettings.url(), response
outgoingUrl, response
);
}
} else {
if (response.code() == 406 || response.code() == 415) { // NOT_ACCEPTABLE || UNSUPPORTED_MEDIA_TYPE
throw new LinkException(
String.format("Remote peer-link DOES NOT support ILP-over-HTTP. tokenSubject=%s url=%s response=%s",
tokenSubject, outgoingLinkSettings.url(), response
String.format("Remote peer-link DOES NOT support ILP-over-HTTP. url=%s response=%s",
outgoingUrl, response
), getLinkId()
);
} else {
throw new LinkException(
String.format("Unable to connect to ILP-over-HTTP. tokenSubject=%s url=%s response=%s",
tokenSubject, outgoingLinkSettings.url(), response
String.format("Unable to connect to ILP-over-HTTP. url=%s response=%s",
outgoingUrl, response
), getLinkId()
);
}
Expand Down Expand Up @@ -300,20 +299,14 @@ private Optional<ThrowableProblem> parseThrowableProblem(
*/
private Request constructSendPacketRequest(final InterledgerPreparePacket preparePacket) {
Objects.requireNonNull(preparePacket);
final OutgoingLinkSettings outgoingLinkSettings = this.getLinkSettings().outgoingLinkSettings()
.orElseGet(() -> {
logger.warn("Falling back to deprecated means of loading outgoing settings. " +
"Please switch to using outgoingLinkSettings() instead");
return this.getLinkSettings().outgoingHttpLinkSettings();
});

try {
final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ilpCodecContext.write(preparePacket, byteArrayOutputStream);

return new Builder()
.headers(constructHttpRequestHeaders())
.url(outgoingLinkSettings.url())
.url(outgoingUrl)
.post(
RequestBody.create(byteArrayOutputStream.toByteArray(), APPLICATION_OCTET_STREAM)
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,16 +82,12 @@ public Link<?> constructLink(

final BearerTokenSupplier bearerTokenSupplier;
OutgoingLinkSettings outgoingLinkSettings = ilpOverHttpLinkSettings.outgoingLinkSettings()
.orElseGet(() -> {
logger.warn("Falling back to deprecated means of loading outgoing settings. " +
"Please switch to using outgoingLinkSettings() instead");
return ilpOverHttpLinkSettings.outgoingHttpLinkSettings();
});
.orElseThrow(() -> new IllegalArgumentException("No outgoing link settings configured for this link"));
if (outgoingLinkSettings.authType().equals(IlpOverHttpLinkSettings.AuthType.SIMPLE)) {
// Decrypt whatever is inside of the encryptedTokenSharedSecret. For the SIMPLE profile, this will decrypt to the
// actual bearer token.
bearerTokenSupplier = new SimpleBearerTokenSupplier(new String(
decryptor.decrypt(outgoingLinkSettings.encryptedTokenSharedSecret().getBytes())
decryptor.decrypt(outgoingLinkSettings.simpleAuthSettings().get().authToken().getBytes())
));
} else {
// TODO: For now, we assume the bytes are a String that conform to the Crypt CLI. However, this should be made
Expand All @@ -101,7 +97,7 @@ public Link<?> constructLink(
// NOTE: This supplier will always create a copy of the decrypted bytes so that the consumer of each call can
// safely wipe the bytes from memory without affecting other callers.
final SharedSecretBytesSupplier sharedSecretSupplier = () -> decryptor
.decrypt(outgoingLinkSettings.encryptedTokenSharedSecret().getBytes());
.decrypt(outgoingLinkSettings.jwtAuthSettings().get().encryptedTokenSharedSecret().get().getBytes());

bearerTokenSupplier = new JwtHs256BearerTokenSupplier(
sharedSecretSupplier, outgoingLinkSettings
Expand All @@ -110,7 +106,7 @@ public Link<?> constructLink(

final IlpOverHttpLink ilpOverHttpLink = new IlpOverHttpLink(
operatorAddressSupplier,
ModifiableIlpOverHttpLinkSettings.create().from(ilpOverHttpLinkSettings), // Modifiable for testing
outgoingLinkSettings.url(),
okHttpClient,
objectMapper,
ilpCodecContext,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@
import org.interledger.link.LinkSettings;
import org.interledger.link.LinkType;

import com.google.common.collect.ImmutableMap;
import org.immutables.value.Value;
import org.immutables.value.Value.Derived;
import org.immutables.value.Value.Modifiable;

import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import javax.annotation.Nullable;

/**
* An extension of {@link LinkSettings} for ILP-over-HTTP links.
Expand All @@ -24,6 +24,8 @@ public interface IlpOverHttpLinkSettings extends LinkSettings {
String INCOMING = "incoming";

String AUTH_TYPE = "auth_type";
String SIMPLE = "simple";
String JWT = "jwt";

String TOKEN_ISSUER = "token_issuer";
String TOKEN_AUDIENCE = "token_audience";
Expand All @@ -32,6 +34,7 @@ public interface IlpOverHttpLinkSettings extends LinkSettings {

// Used to grab the auth credential from custom settings...
String SHARED_SECRET = "shared_secret";
String AUTH_TOKEN = "auth_token";
String URL = "url";

static ImmutableIlpOverHttpLinkSettings.Builder builder() {
Expand Down Expand Up @@ -64,19 +67,12 @@ static ImmutableIlpOverHttpLinkSettings.Builder applyCustomSettings(
Objects.requireNonNull(builder);
Objects.requireNonNull(customSettings);

final ImmutableIncomingLinkSettings.Builder incomingLinkSettingsBuilder =
IncomingLinkSettings.fromCustomSettings(customSettings);
final ImmutableOutgoingLinkSettings.Builder outgoingLinkSettingsBuilder =
OutgoingLinkSettings.fromCustomSettings(customSettings);

ImmutableIncomingLinkSettings incoming = incomingLinkSettingsBuilder.build();
builder.incomingLinkSettings(incoming);
ImmutableOutgoingLinkSettings outgoing = outgoingLinkSettingsBuilder.build();
builder.outgoingLinkSettings(outgoing);

// FIXME initialize in deprecated as well until removed
builder.incomingHttpLinkSettings(incoming);
builder.outgoingHttpLinkSettings(outgoing);
if (LinkSettingsUtils.getIncomingAuthType(customSettings).isPresent()) {
builder.incomingLinkSettings(IncomingLinkSettings.fromCustomSettings(customSettings).build());
}
if (LinkSettingsUtils.getOutgoingAuthType(customSettings).isPresent()) {
builder.outgoingLinkSettings(OutgoingLinkSettings.fromCustomSettings(customSettings).build());
}

builder.customSettings(customSettings);

Expand All @@ -88,26 +84,6 @@ default LinkType getLinkType() {
return IlpOverHttpLink.LINK_TYPE;
}

/**
* @deprecated use {@link #incomingLinkSettings()}. To be removed in 1.0.4
* Link settings for the incoming HTTP link.
*
* @return A {@link IncomingLinkSettings}.
*/
@Deprecated
@Nullable
IncomingLinkSettings incomingHttpLinkSettings();

/**
* @deprecated use {@link #outgoingLinkSettings()}. To be removed in 1.0.4
* Link settings for the outgoing HTTP link.
*
* @return A {@link OutgoingLinkSettings}.
*/
@Deprecated
@Nullable
OutgoingLinkSettings outgoingHttpLinkSettings();

/**
* Optional link settings for the incoming HTTP link.
*
Expand Down Expand Up @@ -140,9 +116,17 @@ enum AuthType {
JWT_HS_256,

/**
* Use RSA asymmetric keys to create aand verify JWT_RS_256 tokens.
* Use RSA asymmetric keys to create and verify JWT_RS_256 tokens.
*/
//JWT_RS_256
JWT_RS_256
}

@Value.Auxiliary
default Map<String, Object> toCustomSettingsMap() {
ImmutableMap.Builder<String, Object> mapBuilder = ImmutableMap.builder();
incomingLinkSettings().ifPresent(settings -> mapBuilder.putAll(settings.toCustomSettingsMap()));
outgoingLinkSettings().ifPresent(settings -> mapBuilder.putAll(settings.toCustomSettingsMap()));
return mapBuilder.build();
}

@Value.Immutable
Expand Down
Loading

0 comments on commit 0e5d699

Please sign in to comment.