New gatekeeper internal-service, for partitioning access
This commit is contained in:
parent
545e247c21
commit
56f04786ab
|
@ -0,0 +1,97 @@
|
||||||
|
# We will create a TCP listener on port 9222, which speaks unencrypted
|
||||||
|
# protocol and allows interaction with the default/system gatekeeper, which
|
||||||
|
# has a single noise binding for introducing encrypted interaction with a
|
||||||
|
# *second* gatekeeper, which finally allows resolution of references to
|
||||||
|
# other objects.
|
||||||
|
|
||||||
|
# First, build a space where we place bindings for the inner gatekeeper to
|
||||||
|
# expose.
|
||||||
|
let ?inner-bindings = dataspace
|
||||||
|
|
||||||
|
# Next, start the inner gatekeeper.
|
||||||
|
<require-service <gatekeeper $inner-bindings>>
|
||||||
|
? <service-object <gatekeeper $inner-bindings> ?inner-gatekeeper> [
|
||||||
|
# Expose it via a noise binding at the outer/system gatekeeper.
|
||||||
|
<bind <noise { key: #[z1w/OLy0wi3Veyk8/D+2182YxcrKpgc8y0ZJEBDrmWs],
|
||||||
|
secretKey: #[qLkyuJw/K4yobr4XVKExbinDwEx9QTt9PfDWyx14/kg],
|
||||||
|
service: world }>
|
||||||
|
$inner-gatekeeper #f>
|
||||||
|
]
|
||||||
|
|
||||||
|
# Now, expose the outer gatekeeper to the world, via TCP. The system
|
||||||
|
# gatekeeper is a primordial syndicate-server object bound to $gatekeeper.
|
||||||
|
<require-service <relay-listener <tcp "0.0.0.0" 9222> $gatekeeper>>
|
||||||
|
|
||||||
|
# Finally, let's expose some behaviour accessible via the inner gatekeeper.
|
||||||
|
#
|
||||||
|
# We will create a service dataspace called $world.
|
||||||
|
let ?world = dataspace
|
||||||
|
|
||||||
|
# Running `syndicate-macaroon mint --oid a-service --phrase hello` yields:
|
||||||
|
#
|
||||||
|
# <ref {oid: a-service, sig: #[JTTGQeYCgohMXW/2S2XH8g]}>
|
||||||
|
#
|
||||||
|
# That's a root capability for the service. We use the corresponding
|
||||||
|
# sturdy.SturdyDescriptionDetail to bind it to $world.
|
||||||
|
#
|
||||||
|
$inner-bindings += <bind <ref {oid: a-service, key: #"hello"}>
|
||||||
|
$world #f>
|
||||||
|
|
||||||
|
# Now, we can hand out paths to our services involving an initial noise
|
||||||
|
# step and a subsequent sturdyref/macaroon step.
|
||||||
|
#
|
||||||
|
# For example, running `syndicate-macaroon` like this:
|
||||||
|
#
|
||||||
|
# syndicate-macaroon mint --oid a-service --phrase hello \
|
||||||
|
# --caveat '<rewrite <bind <_>> <rec labelled [<lit "alice"> <ref 0>]>>'
|
||||||
|
#
|
||||||
|
# generates
|
||||||
|
#
|
||||||
|
# <ref {caveats: [<rewrite <bind <_>> <rec labelled [<lit "alice">, <ref 0>]>>],
|
||||||
|
# oid: a-service,
|
||||||
|
# sig: #[CXn7+rAoO3Xr6Y6Laap3OA]}>
|
||||||
|
#
|
||||||
|
# which is an attenuation of the root capability we bound that wraps all
|
||||||
|
# assertions and messages in a `<labelled "alice" _>` wrapper.
|
||||||
|
#
|
||||||
|
# All together, the `gatekeeper.Route` that Alice would use would be
|
||||||
|
# something like:
|
||||||
|
#
|
||||||
|
# <route [<ws "wss://generic-dataspace.demo.leastfixedpoint.com/">]
|
||||||
|
# <noise { key: #[z1w/OLy0wi3Veyk8/D+2182YxcrKpgc8y0ZJEBDrmWs],
|
||||||
|
# service: world }>
|
||||||
|
# <ref { caveats: [<rewrite <bind <_>> <rec labelled [<lit "alice">, <ref 0>]>>],
|
||||||
|
# oid: a-service,
|
||||||
|
# sig: #[CXn7+rAoO3Xr6Y6Laap3OA] }>>
|
||||||
|
#
|
||||||
|
# Here's one for "bob":
|
||||||
|
#
|
||||||
|
# syndicate-macaroon mint --oid a-service --phrase hello \
|
||||||
|
# --caveat '<rewrite <bind <_>> <rec labelled [<lit "bob"> <ref 0>]>>'
|
||||||
|
#
|
||||||
|
# <ref {caveats: [<rewrite <bind <_>> <rec labelled [<lit "bob">, <ref 0>]>>],
|
||||||
|
# oid: a-service,
|
||||||
|
# sig: #[/75BbF77LOiqNcvpzNHf0g]}>
|
||||||
|
#
|
||||||
|
# <route [<ws "wss://generic-dataspace.demo.leastfixedpoint.com/">]
|
||||||
|
# <noise { key: #[z1w/OLy0wi3Veyk8/D+2182YxcrKpgc8y0ZJEBDrmWs],
|
||||||
|
# service: world }>
|
||||||
|
# <ref { caveats: [<rewrite <bind <_>> <rec labelled [<lit "bob">, <ref 0>]>>],
|
||||||
|
# oid: a-service,
|
||||||
|
# sig: #[/75BbF77LOiqNcvpzNHf0g] }>>
|
||||||
|
#
|
||||||
|
# We relay labelled to unlabelled information, enacting a chat protocol
|
||||||
|
# that enforces usernames.
|
||||||
|
$world [
|
||||||
|
|
||||||
|
# Assertions of presence have the username wiped out and replaced with the label.
|
||||||
|
? <labelled ?who <Present _>> <Present $who>
|
||||||
|
|
||||||
|
# Likewise utterance messages.
|
||||||
|
?? <labelled ?who <Says _ ?what>> ! <Says $who $what>
|
||||||
|
|
||||||
|
# We allow anyone to subscribe to presence and utterances.
|
||||||
|
? <labelled _ <Observe <rec Present ?p> ?o>> <Observe <rec Present $p> $o>
|
||||||
|
? <labelled _ <Observe <rec Says ?p> ?o>> <Observe <rec Says $p> $o>
|
||||||
|
|
||||||
|
]
|
|
@ -4,6 +4,9 @@ ProcessDir
|
||||||
ProcessEnv´³orµµ±present´³dict·³env´³named³env´³dictof´³refµ„³EnvVariable„´³refµ„³EnvValue„„„„„„µ±invalid´³dict·³env´³named³env³any„„„„µ±absent´³dict·„„„„„³CommandLine´³orµµ±shell´³atom³String„„µ±full´³refµ„³FullCommandLine„„„„³EnvVariable´³orµµ±string´³atom³String„„µ±symbol´³atom³Symbol„„µ±invalid³any„„„³FullProcess´³andµ´³dict·³argv´³named³argv´³refµ„³CommandLine„„„„´³named³env´³refµ„³
|
ProcessEnv´³orµµ±present´³dict·³env´³named³env´³dictof´³refµ„³EnvVariable„´³refµ„³EnvValue„„„„„„µ±invalid´³dict·³env´³named³env³any„„„„µ±absent´³dict·„„„„„³CommandLine´³orµµ±shell´³atom³String„„µ±full´³refµ„³FullCommandLine„„„„³EnvVariable´³orµµ±string´³atom³String„„µ±symbol´³atom³Symbol„„µ±invalid³any„„„³FullProcess´³andµ´³dict·³argv´³named³argv´³refµ„³CommandLine„„„„´³named³env´³refµ„³
|
||||||
ProcessEnv„„´³named³dir´³refµ„³
|
ProcessEnv„„´³named³dir´³refµ„³
|
||||||
ProcessDir„„´³named³clearEnv´³refµ„³ClearEnv„„„„³ReadyOnStart´³orµµ±present´³dict·³readyOnStart´³named³readyOnStart´³atom³Boolean„„„„„µ±invalid´³dict·³readyOnStart´³named³readyOnStart³any„„„„µ±absent´³dict·„„„„„³RestartField´³orµµ±present´³dict·³restart´³named³restart´³refµ„³
RestartPolicy„„„„„µ±invalid´³dict·³restart´³named³restart³any„„„„µ±absent´³dict·„„„„„³
DaemonProcess´³rec´³lit³daemon„´³tupleµ´³named³id³any„´³named³config´³refµ„³DaemonProcessSpec„„„„„³
DaemonService´³rec´³lit³daemon„´³tupleµ´³named³id³any„„„„³
ProtocolField´³orµµ±present´³dict·³protocol´³named³protocol´³refµ„³Protocol„„„„„µ±invalid´³dict·³protocol´³named³protocol³any„„„„µ±absent´³dict·„„„„„³
RestartPolicy´³orµµ±always´³lit³always„„µ±onError´³lit³on-error„„µ±all´³lit³all„„µ±never´³lit³never„„„„³FullCommandLine´³tuplePrefixµ´³named³program´³atom³String„„„´³named³args´³seqof´³atom³String„„„„³DaemonProcessSpec´³orµµ±simple´³refµ„³CommandLine„„µ±oneShot´³rec´³lit³one-shot„´³tupleµ´³named³setup´³refµ„³CommandLine„„„„„„µ±full´³refµ„³FullDaemonProcess„„„„³FullDaemonProcess´³andµ´³named³process´³refµ„³FullProcess„„´³named³readyOnStart´³refµ„³ReadyOnStart„„´³named³restart´³refµ„³RestartField„„´³named³protocol´³refµ„³
ProtocolField„„„„„³embeddedType´³refµ³ EntityRef„³Cap„„„µ³internalServices„´³schema·³version°³definitions·³ ConfigEnv´³dictof´³atom³Symbol„³any„³
|
ProcessDir„„´³named³clearEnv´³refµ„³ClearEnv„„„„³ReadyOnStart´³orµµ±present´³dict·³readyOnStart´³named³readyOnStart´³atom³Boolean„„„„„µ±invalid´³dict·³readyOnStart´³named³readyOnStart³any„„„„µ±absent´³dict·„„„„„³RestartField´³orµµ±present´³dict·³restart´³named³restart´³refµ„³
RestartPolicy„„„„„µ±invalid´³dict·³restart´³named³restart³any„„„„µ±absent´³dict·„„„„„³
DaemonProcess´³rec´³lit³daemon„´³tupleµ´³named³id³any„´³named³config´³refµ„³DaemonProcessSpec„„„„„³
DaemonService´³rec´³lit³daemon„´³tupleµ´³named³id³any„„„„³
ProtocolField´³orµµ±present´³dict·³protocol´³named³protocol´³refµ„³Protocol„„„„„µ±invalid´³dict·³protocol´³named³protocol³any„„„„µ±absent´³dict·„„„„„³
RestartPolicy´³orµµ±always´³lit³always„„µ±onError´³lit³on-error„„µ±all´³lit³all„„µ±never´³lit³never„„„„³FullCommandLine´³tuplePrefixµ´³named³program´³atom³String„„„´³named³args´³seqof´³atom³String„„„„³DaemonProcessSpec´³orµµ±simple´³refµ„³CommandLine„„µ±oneShot´³rec´³lit³one-shot„´³tupleµ´³named³setup´³refµ„³CommandLine„„„„„„µ±full´³refµ„³FullDaemonProcess„„„„³FullDaemonProcess´³andµ´³named³process´³refµ„³FullProcess„„´³named³readyOnStart´³refµ„³ReadyOnStart„„´³named³restart´³refµ„³RestartField„„´³named³protocol´³refµ„³
ProtocolField„„„„„³embeddedType´³refµ³ EntityRef„³Cap„„„µ³internalServices„´³schema·³version°³definitions·³ ConfigEnv´³dictof´³atom³Symbol„³any„³
|
||||||
|
Gatekeeper´³rec´³lit³
|
||||||
|
gatekeeper„´³tupleµ´³named³ bindspace´³embedded´³refµ³
|
||||||
|
gatekeeper„³Bind„„„„„„³
|
||||||
HttpRouter´³rec´³lit³http-router„´³tupleµ´³named³httpd´³embedded³any„„„„„³TcpWithHttp´³rec´³lit³relay-listener„´³tupleµ´³named³addr´³refµ³TransportAddress„³Tcp„„´³named³
|
HttpRouter´³rec´³lit³http-router„´³tupleµ´³named³httpd´³embedded³any„„„„„³TcpWithHttp´³rec´³lit³relay-listener„´³tupleµ´³named³addr´³refµ³TransportAddress„³Tcp„„´³named³
|
||||||
gatekeeper´³embedded´³refµ³
|
gatekeeper´³embedded´³refµ³
|
||||||
gatekeeper„³Resolve„„„´³named³httpd´³embedded´³refµ³http„³HttpContext„„„„„„³DebtReporter´³rec´³lit³
debt-reporter„´³tupleµ´³named³intervalSeconds´³atom³Double„„„„„³
ConfigWatcher´³rec´³lit³config-watcher„´³tupleµ´³named³path´³atom³String„„´³named³env´³refµ„³ ConfigEnv„„„„„³TcpWithoutHttp´³rec´³lit³relay-listener„´³tupleµ´³named³addr´³refµ³TransportAddress„³Tcp„„´³named³
|
gatekeeper„³Resolve„„„´³named³httpd´³embedded´³refµ³http„³HttpContext„„„„„„³DebtReporter´³rec´³lit³
debt-reporter„´³tupleµ´³named³intervalSeconds´³atom³Double„„„„„³
ConfigWatcher´³rec´³lit³config-watcher„´³tupleµ´³named³path´³atom³String„„´³named³env´³refµ„³ ConfigEnv„„„„„³TcpWithoutHttp´³rec´³lit³relay-listener„´³tupleµ´³named³addr´³refµ³TransportAddress„³Tcp„„´³named³
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
version 1 .
|
version 1 .
|
||||||
embeddedType EntityRef.Cap .
|
embeddedType EntityRef.Cap .
|
||||||
|
|
||||||
|
Gatekeeper = <gatekeeper @bindspace #!gatekeeper.Bind> .
|
||||||
|
|
||||||
DebtReporter = <debt-reporter @intervalSeconds double>.
|
DebtReporter = <debt-reporter @intervalSeconds double>.
|
||||||
|
|
||||||
TcpRelayListener = TcpWithoutHttp / TcpWithHttp .
|
TcpRelayListener = TcpWithoutHttp / TcpWithHttp .
|
||||||
|
|
|
@ -127,6 +127,7 @@ async fn main() -> ActorResult {
|
||||||
services::config_watcher::on_demand(t, Arc::clone(&server_config_ds));
|
services::config_watcher::on_demand(t, Arc::clone(&server_config_ds));
|
||||||
services::daemon::on_demand(t, Arc::clone(&server_config_ds), Arc::clone(&log_ds));
|
services::daemon::on_demand(t, Arc::clone(&server_config_ds), Arc::clone(&log_ds));
|
||||||
services::debt_reporter::on_demand(t, Arc::clone(&server_config_ds));
|
services::debt_reporter::on_demand(t, Arc::clone(&server_config_ds));
|
||||||
|
services::gatekeeper::on_demand(t, Arc::clone(&server_config_ds));
|
||||||
services::http_router::on_demand(t, Arc::clone(&server_config_ds));
|
services::http_router::on_demand(t, Arc::clone(&server_config_ds));
|
||||||
services::tcp_relay_listener::on_demand(t, Arc::clone(&server_config_ds));
|
services::tcp_relay_listener::on_demand(t, Arc::clone(&server_config_ds));
|
||||||
services::unix_relay_listener::on_demand(t, Arc::clone(&server_config_ds));
|
services::unix_relay_listener::on_demand(t, Arc::clone(&server_config_ds));
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
use preserves_schema::Codec;
|
||||||
|
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use syndicate::actor::*;
|
||||||
|
use syndicate::enclose;
|
||||||
|
use syndicate::preserves::rec;
|
||||||
|
use syndicate::preserves::value::NestedValue;
|
||||||
|
|
||||||
|
use crate::gatekeeper;
|
||||||
|
use crate::language::Language;
|
||||||
|
use crate::language::language;
|
||||||
|
use crate::lifecycle;
|
||||||
|
use crate::schemas::internal_services::Gatekeeper;
|
||||||
|
|
||||||
|
use syndicate_macros::during;
|
||||||
|
|
||||||
|
pub fn on_demand(t: &mut Activation, ds: Arc<Cap>) {
|
||||||
|
t.spawn(Some(AnyValue::symbol("gatekeeper_listener")), move |t| {
|
||||||
|
Ok(during!(t, ds, language(), <run-service $spec: Gatekeeper::<AnyValue>>, |t: &mut Activation| {
|
||||||
|
t.spawn_link(Some(rec![AnyValue::symbol("gatekeeper"), language().unparse(&spec)]),
|
||||||
|
enclose!((ds) |t| run(t, ds, spec)));
|
||||||
|
Ok(())
|
||||||
|
}))
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run(t: &mut Activation, ds: Arc<Cap>, spec: Gatekeeper<AnyValue>) -> ActorResult {
|
||||||
|
let resolver = t.create(syndicate::entity(Arc::clone(&spec.bindspace))
|
||||||
|
.on_asserted(gatekeeper::handle_resolves));
|
||||||
|
ds.assert(t, language(), &syndicate::schemas::service::ServiceObject {
|
||||||
|
service_name: language().unparse(&spec),
|
||||||
|
object: AnyValue::domain(Cap::guard(Language::arc(), resolver)),
|
||||||
|
});
|
||||||
|
gatekeeper::handle_binds(t, &spec.bindspace)?;
|
||||||
|
ds.assert(t, language(), &lifecycle::started(&spec));
|
||||||
|
ds.assert(t, language(), &lifecycle::ready(&spec));
|
||||||
|
Ok(())
|
||||||
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
pub mod config_watcher;
|
pub mod config_watcher;
|
||||||
pub mod daemon;
|
pub mod daemon;
|
||||||
pub mod debt_reporter;
|
pub mod debt_reporter;
|
||||||
|
pub mod gatekeeper;
|
||||||
pub mod http_router;
|
pub mod http_router;
|
||||||
pub mod tcp_relay_listener;
|
pub mod tcp_relay_listener;
|
||||||
pub mod unix_relay_listener;
|
pub mod unix_relay_listener;
|
||||||
|
|
Loading…
Reference in New Issue