Skip to content

fetch ohttp keys through CONNECT tunnel#194

Merged
DanGould merged 9 commits into
payjoin:masterfrom
DanGould:fetch-ohttp-keys
Mar 17, 2024
Merged

fetch ohttp keys through CONNECT tunnel#194
DanGould merged 9 commits into
payjoin:masterfrom
DanGould:fetch-ohttp-keys

Conversation

@DanGould

@DanGould DanGould commented Feb 12, 2024

Copy link
Copy Markdown
Member

Previously we were supplying the OHTTP Gateway's Key Configuration OhttpKeys manually with configuration.

Now that the Rust ohttp-relay supports fetching it via https-in-https CONNECT tunnel, we can fetch it from the server while revealing our IP address only to an ohttp relay.

While ureq and reqwest advertise https-in-https CONNECT functionality, in practice neither properly tunnels TLS in TLS, though I'm trying to change this. For this reason this version uses https-in-http CONNECT which still gets an authenticated response from the gateway (payjoin directory)

Now we only e2e test v1 payjoin cli, and this is complex behavior we probably want to test for which means standing up an ohttp-relay, payjoin directory, and provisioning https certs for them in testing.

refactored and built on #198

  • handle errors
  • test
  • suppress warnings

Regarding Configuration

This PR makes it possible to provide an optional default ohttp-keys config to override fetching one.

In the future, ohttp-keys may be cached per-directory and only refreshed when they fail.

@DanGould
DanGould force-pushed the fetch-ohttp-keys branch 4 times, most recently from fa83e06 to 1ba02c0 Compare February 21, 2024 21:11
@DanGould
DanGould force-pushed the fetch-ohttp-keys branch 3 times, most recently from 4a82716 to d22bee4 Compare March 4, 2024 17:00
@DanGould
DanGould marked this pull request as ready for review March 4, 2024 17:27
@DanGould
DanGould requested a review from jbesraa March 4, 2024 17:28
@DanGould
DanGould marked this pull request as draft March 4, 2024 21:48
@DanGould
DanGould marked this pull request as ready for review March 4, 2024 22:12
@DanGould
DanGould force-pushed the fetch-ohttp-keys branch 2 times, most recently from 26029ec to b245008 Compare March 7, 2024 19:59

@DanGould DanGould left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While the feature seems to be able to work in production as-is, fetching keys via relay is not yet included in integration tests. The Proxy agent does not support the danger_local_https feature either.

Comment thread payjoin-cli/src/app/v2.rs Outdated

impl App {
fn construct_payjoin_uri(
async fn construct_payjoin_uri(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why this need to be async?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whoops nice catch. It doesn't.

I actually think the Enrolled struct has all of the information necessary to construct a Uri and should become available from one of its methods.

Comment thread payjoin-cli/src/app/v2.rs Outdated
}
}

async fn get_ohttp_keys(config: &AppConfig) -> Result<payjoin::OhttpKeys> {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel that get_ohttp_keys, fetch_ohttp_keys and normalize_proxy_url should be part of the payjoin crate.
the fetch.. could require the http client the user is using as input.

@DanGould DanGould Mar 8, 2024

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that there should be library code for fetching ohttp keys, however, the strong typing is already part of payjoin::OhttpKeys::decode(bytes). That leaves the i/o. Since payjoin is a no-IO crate, this makes the functionality, including normalize_proxy_url as candidates for a payjoin-io crate. normalize_proxy_url is a hack for a strange ureq bug I'm hoping can be fixed. I'm happy to begin work on the new crate but would prefer to leave that to a new PR. It would be simple to create a dependency on a local payjoin-io crate as a follow up.

get_ohttp_keys is an app method that takes config as input, so I'm not sure that can be included in a common library.

Comment thread payjoin-cli/src/app/v2.rs
let relay_port = find_free_port();
let relay_url = Url::parse(&format!("http://0.0.0.0:{}", relay_port)).unwrap();
let pj_endpoint = Url::parse("https://payjo.in:443").unwrap();
tokio::select! {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I saw this tokio::select! few times already and always get confused about it. can please explain whats the motivation of using it in this kind of scenarios?

@DanGould DanGould Mar 8, 2024

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Select is a way to call concurrent async methods without starting new tasks. It's less boilerplate than tasks when multiple async calls, like multiple servers, need to run in e.g. tests. It also cancels all of the functions as soon as one of them returns.

https://tokio.rs/tokio/tutorial/select

Comment thread payjoin-cli/src/app/v2.rs Outdated
let response = spawn_blocking(move || {
http.post(req.url.as_ref())
.set("Content-Type", "text/plain")
.set("content-type", "message/ohttp-req")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the content-type is quite important in payjoin world, maybe we should consider add RequestContentType enum to the main crate with the available options. I believe these are text/plain and message/ohttp-req.

@DanGould DanGould Mar 8, 2024

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see two ergonomic TODOs in this comment

  1. define header key/value constants so these can't be misinterpreted during implementation
  2. include headers in req from which to set them rather than set them manually

Beyond these TODOs, these are exactly the confusing implementation details that a payjoin-io crate could abstract.

edit: since these are ergonomic in nature and don't affect the logic of the fetch I'd rather leave them to another PR

Comment thread payjoin-cli/src/main.rs Outdated
@DanGould
DanGould force-pushed the fetch-ohttp-keys branch 2 times, most recently from c9f69a9 to 4a3dd68 Compare March 8, 2024 17:08
@DanGould

DanGould commented Mar 8, 2024

Copy link
Copy Markdown
Member Author

@jbesraa wonderful review. You raised some great points which I've addressed. It's looking like the time for the IO crate to be developed is upon us.

@DanGould
DanGould requested review from jbesraa and removed request for jbesraa March 8, 2024 17:15
Comment thread payjoin/src/receive/v2.rs
@@ -28,7 +29,7 @@ pub struct Request {
#[derive(Debug, Clone)]
pub struct V2Context {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should document the properties here, probably for a different PR

Comment thread payjoin/src/receive/v2.rs
@@ -37,20 +38,14 @@ pub struct V2Context {
#[derive(Debug, Clone)]
pub struct Enroller {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should document the properties here, probably for a different PR

Comment thread payjoin/src/receive/v2.rs

#[derive(Debug, Clone)]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Enrolled {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should document the properties here, probably for a different PR

@DanGould

Copy link
Copy Markdown
Member Author

@jbesraa I'm leaving a note as to why that hasn't been merged yet. Thanks for all the reviews.

I'd like to merge, but not without that danger-local-https feature support and basic tests. In order to do that testing I've been working on #207 to refactor tests to run payjoin-directory as a library but that ran into MSRV issues. I may have been able to make a hack to get MSRV to 1.63.0 with sqlx but it seemed better to use the same time to kill two birds with one stone by switching to redis in #210. Our tests are getting seriously robust now.

@DanGould
DanGould requested a review from jbesraa March 14, 2024 03:14
@DanGould
DanGould removed the request for review from jbesraa March 14, 2024 05:37
@DanGould

Copy link
Copy Markdown
Member Author

This PR now tests the CONNECT bootstrap mechanism by introducing an ohttp_relay dependency integration and duplicating the fetch mechanism found in payjoin-cli. @jbesraa Assuming you agree with the implementation, the duplicate code should make a great starting point for #211. The tests appear not to pass in CI because of a DNS issue I will try to fix in the morning. They seem to pass in my local environment.

@DanGould
DanGould force-pushed the fetch-ohttp-keys branch 2 times, most recently from 8ff3497 to ba69abc Compare March 14, 2024 21:11
@DanGould
DanGould force-pushed the fetch-ohttp-keys branch 10 times, most recently from 72a0fc8 to 8c6b360 Compare March 16, 2024 19:45
@DanGould

DanGould commented Mar 16, 2024

Copy link
Copy Markdown
Member Author

Testing the networking between local environment and CI has been frustrating. This branch seems to pass v2 tests: https://github.com/DanGould/rust-payjoin/tree/fetch-ohttp-keys-ci

but making requests to 0.0.0.0 seems to work exclusively in ci but to localhost exclusively in local v2 tests. There are even some discrepancies between rust versions: the first time v2 tests ran on that commit, test_bad_ohttp_keys failed, but the second run passed. Confusing. Perhaps there is some sort of race in addition to what appears to be a discrepancy in DNS resolution.

@DanGould

Copy link
Copy Markdown
Member Author

The most recent test suggests that ohttp-relay is resolving localhost to ipv6 [::1]:$PORT which the directory server is not listening for. Aha!

@DanGould
DanGould force-pushed the fetch-ohttp-keys branch 4 times, most recently from fbb4e7e to 1ab0f8e Compare March 17, 2024 17:02
@DanGould

Copy link
Copy Markdown
Member Author

@jbesraa I took your feedback into account and e2e tested the results. Our test framework is way better after this as a side effect.

@DanGould
DanGould merged commit 2913646 into payjoin:master Mar 17, 2024
@DanGould
DanGould deleted the fetch-ohttp-keys branch March 17, 2024 17:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants