parallaxsecond / parsec-client-rust Goto Github PK
View Code? Open in Web Editor NEWParsec Rust Client
License: Apache License 2.0
Parsec Rust Client
License: Apache License 2.0
Implement support for the ListAuthenticators
operation and support for handling a new authenticator type (UDS peer credentials), on the back of changes done in parallaxsecond/parsec-interface-rs#70 .
Determine if the BasicClient
should identify a mismatch between the selected app identity type and the existing authenticator.
A developper should not have to depend on the interface and the client. The client should expose the interface structures it needs so there are no clashes in version.
Methods for the CoreClient
should be renamed to contain the psa_
prefix, as the users that would interact with the service at this level should be aware of the different operations natively supported by the service and are trusted to understand how to use them.
Add a new variant to the Rust client's AuthenticationData
for JwtSvid
and a constructor that uses rust-spiffe
to automatically fetch the JWT-SVID it will use to authenticate.
The path to the Workload API can be configured but by default can be assumed to be SPIRE-like and /tmp/agent.sock
.
No proper work has been done to identify solid trends within the Rust development community as to how cryptography APIs should be defined. Time invested in this would be worthwhile, especially with a plan to update our core client (and any future abstract clients).
If possible, the outcome of the investigation should be to improve our APIs. Additionally, the findings should be summarised as a markdown page presenting the ideas behind/"philosophy of" our APIs.
In all methods of the BasicClient
that need a key. See here for reference.
Some of the methods of the BasicClient
do not have proper examples or not examples at all.
The examples should follow this guideline.
The rust-sec team has recommended moving away from the users crate. The last release of the "users" crate was on 2020-10-08. This is also the last day on which code changes happened in the project's git repo on GitHub.
The "sysinfo" crate is listed as a possible alternative.
RUSTSEC-2023-0040 https://rustsec.org/advisories/RUSTSEC-2023-0040.html
The dependencies for this crate currently include a specific git reference for rust-spiffe
, which means that cargo publish
refuses to publish the crate. There is a desire to publish this crate at version 0.12.0
in order to consume parsec-interface-rs
at 0.22.0
and (indirectly) psa-crypto
at 0.6.1
. This publication is needed to unblock the PR incoming to add the first pieces of CryptoAuthLib support.
This crate was incremented to version 0.12.0
with this PR: #63
A tag 0.12.0
was created at this commit level: 2fd8770
An attempt was made to cargo publish
the crate, which failed due to the unversioned rust-spiffe
dependency.
Because the publication failed, the 0.12.0
was later removed to avoid confusion later.
There remains the need to publish and tag the 0.12.0
release, but the SPIFFE dependency needs to be fixed first.
Currently all client structures are constructed with default parameters. In the future, some of these might need changing to allow for a flexible deployment of Parsec.
As part of this task we should also consider whether configuration can/should be done automatically, when the service will allow for such a thing. e.g. we could implement a init
method on CoreClient
that creates a client, uses it to retrieve configuration data from the service, updates the client with said data and returns the already-configured client value.
As a proof to the following mitigation on the Client threat model:
The Parsec client is coded with safety in mind and is tested extensively.
There should be a list of tests, somewhere, describing in high-level terms the kind of tests that we do on the client.
This could either be in the book or somewhere in this repo. It would also probably be good to have a link from this repo to the threat model. Clients using Parsec through this Rust crate directly might not even look at the global Parsec documentation but just want to use it.
The service now offers operations that can be used to bootstrap the client library into using the recommended provider and the supported authentication method.
Currently the users of BasicClient
need to make those calls themselves and then configure the client object, but there's no reason that functionality cannot be implemented on top of or into BasicClient
to limit code duplication.
A design proposal should be made before this can be started.
The initial client returns raw ResponseStatus
es as error values for all its methods. A better solution would be to return a client-specific error type which would make a distinction between errors originating in the service and errors raised by the client itself.
This should be done before #4
Testing could be done with a "mock service" that creates the socket and replies to requests in a predefined way. A test script could then spin up the mock and run a batch of tests using the client.
The RequestHandler
is currently tied into using UnixSockets
for IPC communication. To make it more flexible, the IPC-specific functionality should be extracted and placed in a separate module.
Documentation for the client should be greatly enhanced to allow developers to easily use the service. Docs should include examples.
This issues should be resolved only after all the development tasks are done, before publishing a first version upstream.
Introduce a mechanism in the Rust client (which would also apply uniformly to all clients) whereby a well-known and documented environment variable can be used for discovery of the correct Parsec service endpoint.
Currently, the rust client is defaulting two things in the code:
These things can be overridden if the caller passes in alternatives. However:
An environment variable would be an idiomatic way to allow configuration to be decided in the external environment, rather than in the client code. It would also allow different client processes to be directed at different service endpoints if Parsec evolves to support multiple endpoints, which it may do. This could be done with identical code on the client side.
PARSEC_SERVICE_ENDPOINT
.unix:///tmp/parsec/parsec.sock
.unix:///tmp/parsec/parsec.sock
where it is undefined.unix:
would be the only supported scheme initially.In addition to endpoint discovery, it might also make sense for the authentication scheme to be set by an environment variable as well. But if we want to do that, then that's probably a separate request.
We'd need to think about how this impacts the threat model and its mitigations within the code, such as the permission check on the socket path. Presumably this permission check could still occur, because the check is performed on whatever socket path is configured. It's only the preferred source of the data that is changing.
To support parallaxsecond/parsec-tool#49 it is necessary to create a new BasicClient without authentication being automatically configured as it is with BasicClient::new().
It would be possible to use latest version of new_naked(), but this would not automatically configure other aspects of the client (e.g. providers).
New method should do all the auto configuration as BasicClient::new() except for authenticator, which should be set to Authentication::None
Some of the data handles by the client could be seen as sensitive and in need of memory scrubbing once they are dropped (or just enhanced protection for reading/revealing).
One example would be the authentication values passed within requests.
Some other bits of data coming from a user might be equally sensitive, but it's debateable:
Client-side socket path security checks can (and most likely will) fail if client is running in a Docker container.
On any Linux system, create a secure deployment of Parsec according to these documented steps.
Use the following numeric UIDs and GIDs (or else change the examples used in this repro recipe for different values)
2000
for the parsec
user
3000
for the parsec-clients
group
2001
for the parsec-client-1
example client user
Start the Parsec service as the parsec
user.
Clone and build the parsec-tool. Use cargo build
to build the default set of features. This will include the rust client with the socket folder permission checks.
Install Docker.
Change directory to where parsec-tool
is checked out.
Create a Dockerfile
with the following contents:
FROM debian
ADD target/debug/* /
CMD ["/parsec-tool", "ping"]
From the same directory run docker build --tag parsec-ping .
A docker image should be created. Run the image as follows:
docker run -v /run/parsec:/run/parsec -u 2001:3000 parsec-ping
EXPECTED: The docker container should execute the parsec-tool ping
command running as user 2001
in group 3000
(which is parsec-client-1
in group parsec-clients
). The output should be a successful ping of the service, reporting the supported wire protocol version.
OBSERVED: The container image runs, but the ping fails with an error saying Socket permission checks failed.
The issue is caused by the rust client checking the folder permissions by name and group name rather than by uid and gid respectively. The parsec
and parsec-clients
names are known to the host, but not known within the container, hence the permission checks fail.
We either need to relax the restrictions on the socket folder, or do the checks based on numeric ids rather than names. For the latter, we would need to document well-known numeric IDs for the parsec
user and parsec-clients
group.
This is just an issue to think about it. I am sorry to not have mentionned it earlier in a PR.
I think the CoreClient
should not contain any abstraction, that is any structure that is not created in the interface or any logic more than executing the operation.
I propose then the following changes:
provider_id
field inside the CoreClient
(ProviderID
type), which is the exact number used to send the operation on the wire protocol. Add setters and getters for that field. Use that field when sending operation and not the Provider
parameter of the methods.CoreClient
that are not supported. It should be possible to do anything with the CoreClient
Provider
structure out of the CoreClient
. I think this structure is our first abstraction over the core client and should be in its own module, like providers.rs
. I think that the logic needed to retrieve the provider ID of a known provider should not be part of the CoreClient
CC @ionut-arm what do you think?
Uses of expect
and unwrawp
were not pruned out of the client. This needs to be done before publishing a working version.
For use-cases where you just want to sign data easily and securely without having to care about the signing algorithm chosen and the name of the key (because maybe you will only use one), it might be useful to create a new abstract client which:
BasicClient
: automatic authenticator and provider selectionsign-client-key
)Signer
trait from RustCrypto returning an enumeration of all possible signature types (wrapper around other types implementing Signature
like ecdsa::Signature
)verify_key
(similar to this) returning the public part of the key generated as a wrapper enum of possible public key (like ecdsa::verify::VerifyingKey
)The methods leverage the RustCrypto traits and types so that the client is idiomatic and can easily be used in contexts where other implementations of those traits are used, but with Parsec. Fix #6
A possible simplification of this, is not to abstract over all possible signature/public key types but only focus on one, let's say ecdsa
using the ecdsa
crate. SignClient
could be EcdsaSignClient
or we hide this to the developper. Maybe in the future we will want RsaSignClient
though (but the RustCrypto rsa
crate does not yet support integration with the signature
traits).
A good way to test this would be to find dependent crates of the signature
traits and ecdsa
(here) and replace their signature::Signer
implementation with the Parsec Client's one and see if it works.
Most parameters get owned by the client once a method call is performed - this could/should be changed so that most parameters are instead passed by reference. The client can clone whatever it needs inside the methods.
The question is whether data buffers that we would normally own and zeroize on drop should be passed as references too.
Following parallaxsecond/parsec-interface-rs#127 we should add support in the BasicClient
to generate and verify MACs.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.