Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: bind to [::1] per default instead of 127.0.0.1 in PocketIC #3280

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 0 additions & 9 deletions packages/pocket-ic/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,6 @@ rust_test_suite(
proc_macro_deps = MACRO_DEPENDENCIES,
tags = [
"cpu:16",
# TODO: remove 'requires-network' tag when the root cause for sporadic error below on Apple Silicon is identified and fixed.
# Failed to crate http gateway: Failed to bind to address 127.0.0.1:0: Operation not permitted (os error 1)
"requires-network",
"test_macos",
],
deps = [":pocket-ic"] + DEPENDENCIES + TEST_DEPENDENCIES,
Expand All @@ -110,9 +107,6 @@ rust_test_suite(
flaky = False,
proc_macro_deps = MACRO_DEPENDENCIES,
tags = [
# TODO: remove 'requires-network' tag when the root cause for sporadic error below on Apple Silicon is identified and fixed.
# Failed to crate http gateway: Failed to bind to address 127.0.0.1:0: Operation not permitted (os error 1)
"requires-network",
"test_macos",
],
deps = [":pocket-ic"] + DEPENDENCIES + TEST_DEPENDENCIES,
Expand All @@ -136,9 +130,6 @@ rust_test_suite(
proc_macro_deps = MACRO_DEPENDENCIES,
tags = [
"cpu:16",
# TODO: remove 'requires-network' tag when the root cause for sporadic error below on Apple Silicon is identified and fixed.
# Failed to crate http gateway: Failed to bind to address 127.0.0.1:0: Operation not permitted (os error 1)
"requires-network",
"test_macos",
],
deps = [":pocket-ic"] + DEPENDENCIES + TEST_DEPENDENCIES,
Expand Down
4 changes: 2 additions & 2 deletions packages/pocket-ic/HOWTO.md
Original file line number Diff line number Diff line change
Expand Up @@ -538,7 +538,7 @@ Now we create a PocketIC instance configured with the Bitcoin subnet and the `bi
.with_ii_subnet() // to have tECDSA keys available
.with_application_subnet() // to deploy the test dapp
.with_bitcoind_addr(SocketAddr::new(
IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)),
IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)),
18444,
))
.build();
Expand Down Expand Up @@ -589,7 +589,7 @@ To mine blocks with rewards credited to a given `bitcoin_address: String`, you c
```rust
use bitcoincore_rpc::{bitcoin::Address, Auth, Client, RpcApi};
let btc_rpc = Client::new(
"http://127.0.0.1:18443",
"http://[::1]:18443",
Auth::UserPass(
"ic-btc-integration".to_string(),
"QPQiNaph19FqUsCrBRN0FII7lyM26B51fAMeBQzCb-E=".to_string(),
Expand Down
2 changes: 1 addition & 1 deletion packages/pocket-ic/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ const EXPECTED_SERVER_VERSION: &str = "pocket-ic-server 7.0.0";
// the default timeout of a PocketIC operation
const DEFAULT_MAX_REQUEST_TIME_MS: u64 = 300_000;

const LOCALHOST: &str = "127.0.0.1";
const LOCALHOST: &str = "[::1]";

pub struct PocketIcBuilder {
config: Option<ExtendedSubnetConfigSet>,
Expand Down
14 changes: 0 additions & 14 deletions rs/pocket_ic_server/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -189,17 +189,6 @@ rust_test(
},
tags = [
"cpu:8",
# TODO: remove 'requires-network' tag when the root cause for sporadic error below on Apple Silicon is identified and fixed.
# ---- test_http_gateway stdout ----
# thread 'test_http_gateway' panicked at rs/pocket_ic_server/tests/test.rs:383:48:
# called `Result::unwrap()` on an `Err` value: reqwest::Error {
# kind: Request, url: "http://7tjcv-pp777-77776-qaaaa-cai.raw.localhost:49380/",
# source: hyper_util::client::legacy::Error(
# Connect,
# ConnectError("tcp connect error", Os { code: 1, kind: PermissionDenied, message: "Operation not permitted" })
# )
# }
"requires-network",
"test_macos",
],
deps = TEST_DEPENDENCIES,
Expand Down Expand Up @@ -252,9 +241,6 @@ rust_test(
"SSL_CERT_FILE": "$(rootpath @mozilla_root_ca_store//file)",
},
tags = [
# TODO: remove 'requires-network' tag when the root cause for sporadic error below on Apple Silicon is identified and fixed.
# Failed to crate http gateway: Failed to bind to address 127.0.0.1:0: Operation not permitted (os error 1)
"requires-network",
"test_macos",
],
deps = TEST_DEPENDENCIES,
Expand Down
3 changes: 3 additions & 0 deletions rs/pocket_ic_server/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
- New endpoint `/instances/<instance_id>/read/ingress_status` to fetch the status of an update call submitted through an ingress message.

### Changed
- The default IP address to which the PocketIC server and HTTP gateway bind is [::1] instead of 127.0.0.1.

### Fixed
- Canisters created via `provisional_create_canister_with_cycles` with the management canister ID as the effective canister ID
are created on an arbitrary subnet.
Expand Down
4 changes: 2 additions & 2 deletions rs/pocket_ic_server/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ const LOG_DIR_LEVELS_ENV_NAME: &str = "POCKET_IC_LOG_DIR_LEVELS";
#[derive(Parser)]
#[clap(version = "7.0.0")]
struct Args {
/// The IP address to which the PocketIC server should bind (defaults to 127.0.0.1)
/// The IP address to which the PocketIC server should bind (defaults to [::1])
#[clap(long, short)]
ip_addr: Option<String>,
/// Log levels for PocketIC server logs (defaults to `pocket_ic_server=info,tower_http=info,axum::rejection=trace`).
Expand Down Expand Up @@ -122,7 +122,7 @@ async fn start(runtime: Arc<Runtime>) {
None
};

let ip_addr = args.ip_addr.unwrap_or("127.0.0.1".to_string());
let ip_addr = args.ip_addr.unwrap_or("[::1]".to_string());
let addr = format!("{}:{}", ip_addr, args.port);
let listener = std::net::TcpListener::bind(addr.clone())
.unwrap_or_else(|_| panic!("Failed to bind PocketIC server to address {}", addr));
Expand Down
11 changes: 8 additions & 3 deletions rs/pocket_ic_server/src/state_api/canister_id.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@ use crate::state_api::state::HandlerState;
use async_trait::async_trait;
use axum::extract::FromRequestParts;
use candid::Principal;
use fqdn::{fqdn, Fqdn, FQDN};
use fqdn::{Fqdn, FQDN};
use hyper::{
header::{HOST, REFERER},
http::request::Parts,
Uri,
};
use std::collections::BTreeMap;
use std::str::FromStr;
use std::sync::Arc;

// ADAPTED from ic-gateway
Expand Down Expand Up @@ -189,8 +190,10 @@ impl FromRequestParts<DomainResolver> for HostHeader {
.rsplit_once(':')
.map(|(host, _port)| host)
.unwrap_or(host);
let fqdn =
FQDN::from_str(host).map_err(|_| "Could not parse domain name from Host header")?;
resolver
.resolve_domain(&fqdn!(host))
.resolve_domain(&fqdn)
.map(|d| d.canister_id)
.ok_or(BAD_HOST)?
.ok_or(BAD_HOST)
Expand Down Expand Up @@ -228,8 +231,10 @@ impl FromRequestParts<DomainResolver> for RefererHeaderHost {
let referer = referer.to_str().map_err(|_| BAD_REFERER)?;
let referer: Uri = referer.parse().map_err(|_| BAD_REFERER)?;
let referer = referer.authority().ok_or(BAD_REFERER)?;
let fqdn = FQDN::from_str(referer.host())
.map_err(|_| "Could not parse domain name from Referer header")?;
resolver
.resolve_domain(&fqdn!(referer.host()))
.resolve_domain(&fqdn)
.map(|d| d.canister_id)
.ok_or(BAD_REFERER)?
.ok_or(BAD_REFERER)
Expand Down
9 changes: 5 additions & 4 deletions rs/pocket_ic_server/src/state_api/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use axum::{
use axum_server::tls_rustls::RustlsConfig;
use axum_server::Handle;
use base64;
use fqdn::{fqdn, FQDN};
use fqdn::FQDN;
use futures::future::Shared;
use http::{
header::{
Expand Down Expand Up @@ -810,7 +810,7 @@ impl ApiState {
let ip_addr = http_gateway_config
.ip_addr
.clone()
.unwrap_or("127.0.0.1".to_string());
.unwrap_or("[::1]".to_string());
let port = http_gateway_config.port.unwrap_or_default();
let addr = format!("{}:{}", ip_addr, port);
let listener = std::net::TcpListener::bind(&addr)
Expand Down Expand Up @@ -844,8 +844,9 @@ impl ApiState {
.clone()
.unwrap_or(vec!["localhost".to_string()])
.iter()
.map(|d| fqdn!(d))
.collect();
.map(|d| FQDN::from_str(d))
.collect::<Result<Vec<_>, _>>()
.map_err(|e| e.to_string())?;
spawn(async move {
let http_gateway_client = ic_http_gateway::HttpGatewayClientBuilder::new()
.with_agent(agent)
Expand Down
6 changes: 3 additions & 3 deletions rs/pocket_ic_server/tests/bitcoin_integration_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use ic_nns_constants::ROOT_CANISTER_ID;
use pocket_ic::{update_candid, PocketIc, PocketIcBuilder};
use std::fs::{create_dir, File};
use std::io::Write;
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
use std::net::{IpAddr, Ipv6Addr, SocketAddr};
use std::process::Command;
use std::str::FromStr;
use std::time::SystemTime;
Expand Down Expand Up @@ -105,7 +105,7 @@ rpcauth=ic-btc-integration:cdf2741387f3a12438f69092f0fdad8e$62081498c98bee09a0dc
.with_ii_subnet()
.with_application_subnet()
.with_bitcoind_addr(SocketAddr::new(
IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)),
IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)),
18444,
))
.build();
Expand All @@ -130,7 +130,7 @@ rpcauth=ic-btc-integration:cdf2741387f3a12438f69092f0fdad8e$62081498c98bee09a0dc
.0;

let btc_rpc = Client::new(
"http://127.0.0.1:18443",
"http://[::1]:18443",
Auth::UserPass(
"ic-btc-integration".to_string(),
"QPQiNaph19FqUsCrBRN0FII7lyM26B51fAMeBQzCb-E=".to_string(),
Expand Down
16 changes: 8 additions & 8 deletions rs/pocket_ic_server/tests/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,13 @@ use reqwest::{StatusCode, Url};
use slog::Level;
use std::io::Read;
use std::io::Write;
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
use std::net::{IpAddr, Ipv6Addr, SocketAddr};
use std::path::PathBuf;
use std::process::{Child, Command};
use std::time::Duration;
use tempfile::{NamedTempFile, TempDir};

pub const LOCALHOST: &str = "127.0.0.1";
pub const LOCALHOST: &str = "[::1]";

fn start_server_helper(
test_driver_pid: Option<u32>,
Expand Down Expand Up @@ -290,7 +290,7 @@ async fn test_gateway(server_url: Url, https: bool) {
assert_eq!(http_gateway_details.domains, domains);
assert_eq!(http_gateway_details.https_config, https_config);

// create a non-blocking reqwest client resolving localhost/example.com and <canister-id>.(raw.)localhost/example.com to 127.0.0.1
// create a non-blocking reqwest client resolving localhost/example.com and <canister-id>.(raw.)localhost/example.com to [::1]
let mut builder = NonblockingClient::builder();
for domain in [
localhost,
Expand All @@ -302,7 +302,7 @@ async fn test_gateway(server_url: Url, https: bool) {
] {
builder = builder.resolve(
domain,
SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), port),
SocketAddr::new(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)), port),
);
}
// add a custom root certificate
Expand Down Expand Up @@ -345,13 +345,13 @@ async fn test_gateway(server_url: Url, https: bool) {
.await
.unwrap();

// perform frontend asset request for the title page at http://127.0.0.1:<port>/?canisterId=<canister-id>
// perform frontend asset request for the title page at http://[::1]:<port>/?canisterId=<canister-id>
let mut test_urls = vec![];
if !https {
assert_eq!(proto, "http");
let canister_url = format!(
"{}://{}:{}/?canisterId={}",
"http", "127.0.0.1", port, canister_id
"http", LOCALHOST, port, canister_id
);
test_urls.push(canister_url);
}
Expand Down Expand Up @@ -1124,7 +1124,7 @@ fn test_gateway_ip_addr_host() {

let mut endpoint = pic.make_live(None);
endpoint
.set_ip_host(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)))
.set_ip_host(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)))
.unwrap();

let rt = tokio::runtime::Builder::new_current_thread()
Expand Down Expand Up @@ -1486,7 +1486,7 @@ fn test_gateway_address_in_use() {
)
.unwrap_err();
assert!(err.contains(&format!(
"Failed to bind to address 127.0.0.1:{}: Address already in use",
"Failed to bind to address [::1]:{}: Address already in use",
port
)));
}
Loading