More updates to gatekeeper protocol
This commit is contained in:
parent
45406c75ac
commit
4dca1b1615
|
@ -1,3 +1,3 @@
|
|||
let ?root_ds = dataspace
|
||||
<require-service <relay-listener <tcp "0.0.0.0" 9001> $gatekeeper>>
|
||||
<bind <ref "syndicate" #x""> $root_ds #f>
|
||||
<bind <ref { oid: "syndicate" key: #x"" }> $root_ds #f>
|
||||
|
|
|
@ -15,7 +15,7 @@ use core::time::Duration;
|
|||
|
||||
#[derive(Clone, Debug, StructOpt)]
|
||||
pub struct Config {
|
||||
#[structopt(short = "d", default_value = "b4b303726566b10973796e646963617465b584b21069ca300c1dbfa08fba692102dd82311a84")]
|
||||
#[structopt(short = "d", default_value = "b4b303726566b7b3036f6964b10973796e646963617465b303736967b21069ca300c1dbfa08fba692102dd82311a8484")]
|
||||
dataspace: String,
|
||||
}
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ mod dirty;
|
|||
|
||||
#[derive(Clone, Debug, StructOpt)]
|
||||
pub struct Config {
|
||||
#[structopt(short = "d", default_value = "b4b303726566b10973796e646963617465b584b21069ca300c1dbfa08fba692102dd82311a84")]
|
||||
#[structopt(short = "d", default_value = "b4b303726566b7b3036f6964b10973796e646963617465b303736967b21069ca300c1dbfa08fba692102dd82311a8484")]
|
||||
dataspace: String,
|
||||
}
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ pub struct Config {
|
|||
#[structopt(short = "b", default_value = "0")]
|
||||
bytes_padding: usize,
|
||||
|
||||
#[structopt(short = "d", default_value = "b4b303726566b10973796e646963617465b584b21069ca300c1dbfa08fba692102dd82311a84")]
|
||||
#[structopt(short = "d", default_value = "b4b303726566b7b3036f6964b10973796e646963617465b303736967b21069ca300c1dbfa08fba692102dd82311a8484")]
|
||||
dataspace: String,
|
||||
}
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ pub struct Config {
|
|||
#[structopt(subcommand)]
|
||||
mode: PingPongMode,
|
||||
|
||||
#[structopt(short = "d", default_value = "b4b303726566b10973796e646963617465b584b21069ca300c1dbfa08fba692102dd82311a84")]
|
||||
#[structopt(short = "d", default_value = "b4b303726566b7b3036f6964b10973796e646963617465b303736967b21069ca300c1dbfa08fba692102dd82311a8484")]
|
||||
dataspace: String,
|
||||
}
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ pub struct Config {
|
|||
#[structopt(short = "b", default_value = "0")]
|
||||
bytes_padding: usize,
|
||||
|
||||
#[structopt(short = "d", default_value = "b4b303726566b10973796e646963617465b584b21069ca300c1dbfa08fba692102dd82311a84")]
|
||||
#[structopt(short = "d", default_value = "b4b303726566b7b3036f6964b10973796e646963617465b303736967b21069ca300c1dbfa08fba692102dd82311a8484")]
|
||||
dataspace: String,
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ use core::time::Duration;
|
|||
|
||||
#[derive(Clone, Debug, StructOpt)]
|
||||
pub struct Config {
|
||||
#[structopt(short = "d", default_value = "b4b303726566b10973796e646963617465b584b21069ca300c1dbfa08fba692102dd82311a84")]
|
||||
#[structopt(short = "d", default_value = "b4b303726566b7b3036f6964b10973796e646963617465b303736967b21069ca300c1dbfa08fba692102dd82311a8484")]
|
||||
dataspace: String,
|
||||
}
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ use tokio::net::TcpStream;
|
|||
|
||||
#[derive(Clone, Debug, StructOpt)]
|
||||
pub struct Config {
|
||||
#[structopt(short = "d", default_value = "b4b303726566b10973796e646963617465b584b21069ca300c1dbfa08fba692102dd82311a84")]
|
||||
#[structopt(short = "d", default_value = "b4b303726566b7b3036f6964b10973796e646963617465b303736967b21069ca300c1dbfa08fba692102dd82311a8484")]
|
||||
dataspace: String,
|
||||
}
|
||||
|
||||
|
|
|
@ -27,38 +27,44 @@ use crate::language::language;
|
|||
use syndicate_macros::during;
|
||||
use syndicate_macros::pattern;
|
||||
|
||||
pub fn handle_binds(t: &mut Activation, ds: &Arc<Cap>) -> ActorResult {
|
||||
Ok(during!(t, ds, language(), <bind $description $target $observer>, |t: &mut Activation| {
|
||||
t.spawn_link(None, move |t| { handle_bind(t, description, target, observer) });
|
||||
Ok(())
|
||||
}))
|
||||
fn sturdy_step_type() -> String {
|
||||
language().unparse(&sturdy::SturdyStepType).value().to_symbol().unwrap().clone()
|
||||
}
|
||||
|
||||
fn handle_bind(
|
||||
t: &mut Activation,
|
||||
description: AnyValue,
|
||||
target: AnyValue,
|
||||
observer: AnyValue,
|
||||
) -> ActorResult {
|
||||
let _target = target.value().to_embedded()?;
|
||||
let observer = language().parse::<gatekeeper::BindObserver>(&observer)?;
|
||||
fn noise_step_type() -> String {
|
||||
language().unparse(&noise::NoiseStepType).value().to_symbol().unwrap().clone()
|
||||
}
|
||||
|
||||
if let Ok(s) = language().parse::<sturdy::SturdyService>(&description) {
|
||||
let sr = sturdy::SturdyRef::mint(s.oid, &s.key);
|
||||
pub fn handle_binds(t: &mut Activation, ds: &Arc<Cap>) -> ActorResult {
|
||||
during!(t, ds, language(), <bind <ref $desc> $target $observer>, |t: &mut Activation| {
|
||||
t.spawn_link(None, move |t| {
|
||||
target.value().to_embedded()?;
|
||||
let observer = language().parse::<gatekeeper::BindObserver>(&observer)?;
|
||||
let desc = language().parse::<sturdy::SturdyDescriptionDetail>(&desc)?;
|
||||
let sr = sturdy::SturdyRef::mint(desc.oid, &desc.key);
|
||||
if let gatekeeper::BindObserver::Present(o) = observer {
|
||||
o.assert(t, language(), &gatekeeper::Bound::Bound {
|
||||
step: language().unparse(&sr),
|
||||
path_step: Box::new(gatekeeper::PathStep {
|
||||
step_type: sturdy_step_type(),
|
||||
detail: language().unparse(&sr.parameters),
|
||||
}),
|
||||
});
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if let Ok(s) = language().parse::<noise::NoiseService<AnyValue>>(&description) {
|
||||
match validate_noise_spec(s.spec) {
|
||||
Ok(())
|
||||
});
|
||||
Ok(())
|
||||
});
|
||||
during!(t, ds, language(), <bind <noise $desc> $target $observer>, |t: &mut Activation| {
|
||||
t.spawn_link(None, move |t| {
|
||||
target.value().to_embedded()?;
|
||||
let observer = language().parse::<gatekeeper::BindObserver>(&observer)?;
|
||||
let spec = language().parse::<noise::NoiseDescriptionDetail<AnyValue>>(&desc)?.0;
|
||||
match validate_noise_spec(spec) {
|
||||
Ok(spec) => if let gatekeeper::BindObserver::Present(o) = observer {
|
||||
o.assert(t, language(), &gatekeeper::Bound::Bound {
|
||||
step: language().unparse(&noise::NoiseRouteStep {
|
||||
spec: noise::NoiseSpec {
|
||||
path_step: Box::new(gatekeeper::PathStep {
|
||||
step_type: noise_step_type(),
|
||||
detail: language().unparse(&noise::NoisePathStepDetail(noise::NoiseSpec {
|
||||
key: spec.public_key,
|
||||
service: noise::ServiceSelector(spec.service),
|
||||
protocol: if spec.protocol == default_noise_protocol() {
|
||||
|
@ -75,7 +81,7 @@ fn handle_bind(
|
|||
pre_shared_keys: spec.psks,
|
||||
}
|
||||
},
|
||||
},
|
||||
})),
|
||||
}),
|
||||
});
|
||||
},
|
||||
|
@ -89,15 +95,10 @@ fn handle_bind(
|
|||
tracing::error!("Invalid noise bind description: {}", e);
|
||||
}
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if let gatekeeper::BindObserver::Present(o) = observer {
|
||||
o.assert(t, language(), &gatekeeper::Bound::Rejected(
|
||||
Box::new(gatekeeper::Rejected {
|
||||
detail: AnyValue::symbol("unsupported"),
|
||||
})));
|
||||
}
|
||||
Ok(())
|
||||
});
|
||||
Ok(())
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -114,15 +115,24 @@ pub fn handle_resolves(
|
|||
t: &mut Activation,
|
||||
a: gatekeeper::Resolve,
|
||||
) -> DuringResult<Arc<Cap>> {
|
||||
let step = language().unparse(&a.step);
|
||||
if let Ok(s) = language().parse::<sturdy::SturdyStep>(&step) {
|
||||
return handle_resolve_sturdyref(ds, t, s.0, a.observer);
|
||||
let mut detail: &'static str = "unsupported";
|
||||
|
||||
if a.step.step_type == sturdy_step_type() {
|
||||
detail = "invalid";
|
||||
if let Ok(s) = language().parse::<sturdy::SturdyStepDetail>(&a.step.detail) {
|
||||
return handle_resolve_sturdyref(ds, t, sturdy::SturdyRef { parameters: s.0 }, a.observer);
|
||||
}
|
||||
if let Ok(s) = language().parse::<noise::NoiseStep<AnyValue>>(&step) {
|
||||
return handle_resolve_noise(ds, t, s.service.0, a.observer);
|
||||
}
|
||||
|
||||
if a.step.step_type == noise_step_type() {
|
||||
detail = "invalid";
|
||||
if let Ok(s) = language().parse::<noise::NoiseStepDetail<AnyValue>>(&a.step.detail) {
|
||||
return handle_resolve_noise(ds, t, s.0.0, a.observer);
|
||||
}
|
||||
}
|
||||
|
||||
eventually_retract(ds.assert(t, language(), &gatekeeper::Rejected {
|
||||
detail: AnyValue::symbol("unsupported"),
|
||||
detail: AnyValue::symbol(detail),
|
||||
}))
|
||||
}
|
||||
|
||||
|
@ -132,7 +142,7 @@ fn handle_resolve_sturdyref(
|
|||
sturdyref: sturdy::SturdyRef,
|
||||
observer: Arc<Cap>,
|
||||
) -> DuringResult<Arc<Cap>> {
|
||||
let queried_oid = sturdyref.oid.clone();
|
||||
let queried_oid = sturdyref.parameters.oid.clone();
|
||||
let handler = syndicate::entity(observer)
|
||||
.on_asserted(move |observer, t, a: AnyValue| {
|
||||
let bindings = a.value().to_sequence()?;
|
||||
|
@ -160,7 +170,7 @@ fn handle_resolve_sturdyref(
|
|||
.create_cap(t);
|
||||
eventually_retract(ds.assert(t, language(), &dataspace::Observe {
|
||||
// TODO: codegen plugin to generate pattern constructors
|
||||
pattern: pattern!{<bind <ref #(&queried_oid) $> $ _>},
|
||||
pattern: pattern!{<bind <ref { oid: #(&queried_oid), key: $ }> $ _>},
|
||||
observer: handler,
|
||||
}))
|
||||
}
|
||||
|
|
|
@ -195,14 +195,16 @@ pub fn connect_stream<I, O, Step, E, F>(
|
|||
let i = Input::Bytes(Box::pin(i));
|
||||
let o = Output::Bytes(Box::pin(o));
|
||||
let gatekeeper = TunnelRelay::run(t, i, o, None, Some(sturdy::Oid(0.into())), output_text).unwrap();
|
||||
let main_entity = t.create(during::entity(initial_state).on_asserted(move |state, t, a: AnyValue| {
|
||||
let denotation = a.value().to_embedded()?;
|
||||
f(state, t, Arc::clone(denotation))
|
||||
let main_entity = t.create(during::entity(initial_state).on_asserted(move |state, t, a: gatekeeper::Resolved| {
|
||||
match a {
|
||||
gatekeeper::Resolved::Accepted { responder_session } => f(state, t, responder_session),
|
||||
gatekeeper::Resolved::Rejected(r) => Err(error("Resolve rejected", r.detail))?,
|
||||
}
|
||||
}));
|
||||
let step = language().parse::<gatekeeper::Step>(&language().unparse(&step))?;
|
||||
gatekeeper.assert(t, language(), &gatekeeper::Resolve::<AnyValue> {
|
||||
step,
|
||||
observer: Cap::new(&main_entity),
|
||||
observer: Cap::guard(Language::arc(), main_entity),
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ pub use super::schemas::sturdy::*;
|
|||
pub enum ValidationError {
|
||||
SignatureError,
|
||||
AttenuationError(CaveatError),
|
||||
BadCaveatsField,
|
||||
}
|
||||
|
||||
impl std::fmt::Display for ValidationError {
|
||||
|
@ -30,6 +31,8 @@ impl std::fmt::Display for ValidationError {
|
|||
write!(f, "Invalid SturdyRef signature"),
|
||||
ValidationError::AttenuationError(e) =>
|
||||
write!(f, "Invalid SturdyRef attenuation: {:?}", e),
|
||||
ValidationError::BadCaveatsField =>
|
||||
write!(f, "Invalid caveats field in SturdyRef parameters"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -71,7 +74,21 @@ pub fn decode<N: NestedValue>(bs: &[u8]) -> io::Result<N> {
|
|||
impl SturdyRef {
|
||||
pub fn mint(oid: _Any, key: &[u8]) -> Self {
|
||||
let sig = signature(key, &encode(&oid));
|
||||
SturdyRef { oid, caveat_chain: Vec::new(), sig }
|
||||
SturdyRef::from_parts(oid, vec![], sig)
|
||||
}
|
||||
|
||||
pub fn from_parts(oid: _Any, caveats: Vec<Caveat>, sig: Vec<u8>) -> Self {
|
||||
SturdyRef {
|
||||
parameters: Parameters {
|
||||
oid,
|
||||
sig,
|
||||
caveats: if caveats.is_empty() {
|
||||
CaveatsField::Absent
|
||||
} else {
|
||||
CaveatsField::Present { caveats }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_hex(s: &str) -> Result<Self, Error> {
|
||||
|
@ -83,6 +100,14 @@ impl SturdyRef {
|
|||
HexFormatter::Packed.encode(&encode(&language().unparse(self)))
|
||||
}
|
||||
|
||||
pub fn caveat_chain(&self) -> Result<&[Caveat], ValidationError> {
|
||||
match &self.parameters.caveats {
|
||||
CaveatsField::Absent => Ok(&[]),
|
||||
CaveatsField::Invalid { .. } => Err(ValidationError::BadCaveatsField),
|
||||
CaveatsField::Present { caveats } => Ok(caveats),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn validate_and_attenuate(
|
||||
&self,
|
||||
key: &[u8],
|
||||
|
@ -90,14 +115,15 @@ impl SturdyRef {
|
|||
) -> Result<_Ptr, ValidationError> {
|
||||
self.validate(key).map_err(|_| ValidationError::SignatureError)?;
|
||||
let target = unattenuated_target
|
||||
.attenuate(&self.caveat_chain)
|
||||
.attenuate(self.caveat_chain()?)
|
||||
.map_err(ValidationError::AttenuationError)?;
|
||||
Ok(target)
|
||||
}
|
||||
|
||||
pub fn validate(&self, key: &[u8]) -> Result<(), ()> {
|
||||
let SturdyRef { oid, caveat_chain, sig } = self;
|
||||
let key = chain_signature(&signature(&key, &encode(oid)), caveat_chain);
|
||||
let SturdyRef { parameters: Parameters { oid, sig, .. } } = self;
|
||||
let key = chain_signature(&signature(&key, &encode(oid)),
|
||||
self.caveat_chain().map_err(|_| ())?);
|
||||
if &key == sig {
|
||||
Ok(())
|
||||
} else {
|
||||
|
@ -105,13 +131,13 @@ impl SturdyRef {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn attenuate(&self, attenuation: &[Caveat]) -> Result<Self, CaveatError> {
|
||||
Caveat::validate_many(attenuation)?;
|
||||
let SturdyRef { oid, caveat_chain, sig } = self;
|
||||
pub fn attenuate(&self, attenuation: &[Caveat]) -> Result<Self, ValidationError> {
|
||||
Caveat::validate_many(attenuation).map_err(ValidationError::AttenuationError)?;
|
||||
let SturdyRef { parameters: Parameters { oid, sig, .. } } = self;
|
||||
let oid = oid.clone();
|
||||
let mut caveat_chain = caveat_chain.clone();
|
||||
let mut caveat_chain = self.caveat_chain()?.to_vec();
|
||||
caveat_chain.extend(attenuation.iter().cloned());
|
||||
let sig = chain_signature(&sig, attenuation);
|
||||
Ok(SturdyRef { oid, caveat_chain, sig })
|
||||
Ok(SturdyRef::from_parts(oid, caveat_chain, sig))
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue