GithubHelp home page GithubHelp logo

parallaxsecond / parsec-client-rust Goto Github PK

View Code? Open in Web Editor NEW
10.0 7.0 19.0 212 KB

Parsec Rust Client

License: Apache License 2.0

Rust 98.41% Shell 1.59%
cryptography-library hardware-abstraction rust-library

parsec-client-rust's People

Contributors

akazimierskigl avatar anta5010 avatar gowthamsk-arm avatar hug-dev avatar ionut-arm avatar kakemone avatar marcsvll avatar mattdavis00 avatar mohamedasaker-arm avatar paulhowardarm avatar robertdrazkowskigl avatar sbailey-arm avatar tgonzalezorlandoarm avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

parsec-client-rust's Issues

Implement new authenticator support

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.

Rename methods to contain `psa_` prefix

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 JWT-SVID authentication data

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.

Investigate Rustacean crypto APIs

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.

Un-versioned SPIFFE dependency prevents publishing crate at version 0.12.0

Summary

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.

Details

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.

Implement configuration

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.

List existing tests

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.

Implement component bootstrapping

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.

Implement client-specific error structures

The initial client returns raw ResponseStatuses 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

Create test framework

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.

Improve documentation

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.

Resolve service endpoint from a URI environment variable

Summary

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.

Rationale

Currently, the rust client is defaulting two things in the code:

  • The nature of the IPC handler (currently defaulting to Unix socket, chiefly because that's the only form of IPC that Parsec supports today).
  • The address of the endpoint (namely the socket path for Unix socket).

These things can be overridden if the caller passes in alternatives. However:

  • If the caller is the SE driver (C client), then there is no means of passing through this information. This means the C client would break if the socket endpoint were configured to be anything other than the hard-coded default.
  • Even when the caller has the ability to pass in the information, where should they get it from? Who has enough intelligence about the overall deployment to know what the service endpoint should be? Application developers won't typically have this intelligence - they will simply want to "use Parsec".

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.

Requirements

  • Define and document an environment variable such as PARSEC_SERVICE_ENDPOINT.
  • The variable should be defined as a URI (RFC 3986) so that it can specify a scheme as well as an endpoint address, such as unix:///tmp/parsec/parsec.sock.
  • The rust client should obtain the value of this environment variable, but fall back on unix:///tmp/parsec/parsec.sock where it is undefined.
  • The rust client should use both the scheme and the address segments of the URI to create a correct IPC handler pointed at the correct service endpoint. It remains the case that unix: would be the only supported scheme initially.
  • Use of the environment variable should be default behaviour, although it should still be possible for callers to pass in explicit values to override this.
  • Update the Parsec book to describe this behaviour of clients. It will need to become a general rule for client library development, since the same discovery logic will need to be replicated in the Go client and all other clients.

Discussion

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.

Add BasicClient::new_non_authenticated()

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

Manage data safely within the client

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:

  • hashes given for signing
  • signatures returned

Socket path security checks can fail when the client is in a container

Summary

Client-side socket path security checks can (and most likely will) fail if client is running in a Docker container.

Repro

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.

Root Cause

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.

Required Fix

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.

Make the CoreClient really dumb

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:

  1. put a 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.
  2. do not restrict the core operations to be executed only on the core providers: I think that the "intelligence" needed to know which operation is executable on which provider should not be part of the core client but at a higher level. It should be possible to send operations with the CoreClient that are not supported. It should be possible to do anything with the CoreClient
  3. move the 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?

Improve use of unsafe methods

Uses of expect and unwrawp were not pruned out of the client. This needs to be done before publishing a working version.

Investigate a SignClient for just-in-time key creation

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:

  • is based on the BasicClient: automatic authenticator and provider selection
  • automatically choose the asymmetric signing algorithm which is going to be used and the key properties: RSA or ECC? Which curve (if ECC)? Which key length? PKCS#1 v1.5 or PSS (if RSA)?
  • generate a key pair (if it does not exist) with those properties with a fixed named (sign-client-key)
  • provides the following methods:

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).

Testing

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.

Modify interface to take parameters as reference

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.

Add support for ListClients and DeleteClient

Based on this. We also need to make sure that a good error is returned to the user when the operation failed because they do not have admin privilege. This should be handled with the AdminOperation response status added here.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.