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

TLS tag for information flow #814

Closed
tiziano88 opened this issue Apr 6, 2020 · 9 comments · Fixed by #1688
Closed

TLS tag for information flow #814

tiziano88 opened this issue Apr 6, 2020 · 9 comments · Fixed by #1688
Assignees
Labels
Milestone

Comments

@tiziano88
Copy link
Collaborator

Introduce a new type of tag to the information flow control system, which specifies the common name (CN) (and / or other fields) of a certificate that needs to be presented over TLS by a non-Oak destination server.

For instance, data labelled with a secrecy tag of "tls:spanner.google.com" may be sent to that destination via a gRPC client pseudo-node.

The enforcement of this label is managed by the gRPC client pseudo-node implementation. If and when other kinds of pseudo-nodes are implemented (e.g. HTTP client), those will also need to enforce such label. Effectively, the gRPC client pseudo-node must have the ability to declassify this label, based on the details of the entity on the other side of a TLS connection.

message Tag {
oneof tag {
GrpcTag grpc_tag = 1;
WebAssemblyModuleTag web_assembly_module_tag = 2;
}
}

@conradgrobler
Copy link
Collaborator

This should probably use subject alternative names (SAN), as the use of CN is considered deprecated.

@tiziano88
Copy link
Collaborator Author

Related to #819

@tiziano88 tiziano88 self-assigned this Apr 7, 2020
tiziano88 added a commit to tiziano88/oak that referenced this issue Apr 7, 2020
tiziano88 added a commit to tiziano88/oak that referenced this issue Apr 7, 2020
Covers SAN name only.

Not used in code yet.

Ref project-oak#814
tiziano88 added a commit that referenced this issue Apr 7, 2020
Covers SAN name only.

Not used in code yet.

Ref #814
@tiziano88 tiziano88 added the P0 label May 11, 2020
@daviddrysdale daviddrysdale added this to the IFC v0 milestone Jun 27, 2020
@tiziano88
Copy link
Collaborator Author

I am implementing this now, but I cannot find a way of getting the actual server name from an established gRPC channel.

I am considering adding a tls_domain_name to the GrpcClientConfiguration proto message:

// GrpcClientConfiguration describes the configuration of a gRPC client
// pseudo-Node (which is provided by the Oak Runtime), connected to a specific
// external (non-Oak) gRPC service.
message GrpcClientConfiguration {
// The URI component of a gRPC server endpoint. Must contain the "Host"
// element. https://docs.rs/tonic/0.2.1/tonic/transport/struct.Uri.html
string uri = 1;
// The endpoint address of the external gRPC service.
// `address` is represented as an "ip_address:tcp_port" string.
string address = 2;
}

and then pass that to ClientTlsConfig::domain_name in addition to the URI, then use tls_domain_name to determine the privilege of the gRPC node to declassify the TLS tag.

@daviddrysdale @conradgrobler @ipetr0v does this sound reasonable? It would need we would have to pass both from existing application when creating a gRPC client node though.

Alternatively, I don't think there is a way of uniquely determining the TLS domain name from just the URI, right? i.e. account.google.com may in principle be served with a cert for account.google.com, or for *.google.com, right? Or am I misunderstanding how TLS works?

@conradgrobler
Copy link
Collaborator

I think the trusted domain and the SAN entries in the certificates can be separated. If a user trusts a domain (e.g. account.google.com) I don't think it matters whether there is a SAN entry in the certificate that matches account.google.com. If the user trusts the domain, and the domain is verified by a certificate that the Oak runtime trusts (whether wildcard or exact match) it should be ok. Also, if a user trusts all subdomains of google.com it should not matter whether a connection to account.google.com is verified by a certificate with a wildcard SAN entry or an exact entry for account.google.com.

Another (but probably future and separate) feature that might be useful would be to be able to specify a certificate fingerprint to trust, in which case the domain name is not important, only that it was verified using a specific certificate.

@tiziano88
Copy link
Collaborator Author

So if the connection is to account.google.com, but the TLS tag the user specified on the data is google.com, how do we resolve the gap? Do we just do a naive suffix match, on the components separated by dots?

Another (but probably future and separate) feature that might be useful would be to be able to specify a certificate fingerprint to trust, in which case the domain name is not important, only that it was verified using a specific certificate.

This goes back to my original question: how do we get any details about an established TLS connection, for instance in order to check fingerprint or any other details of the cert used for the handshake?

@conradgrobler
Copy link
Collaborator

conradgrobler commented Jul 1, 2020

So if the connection is to account.google.com, but the TLS tag the user specified on the data is google.com, how do we resolve the gap? Do we just do a naive suffix match, on the components separated by dots?

If we allow users to specify wildcards for trust (I am not sure we should), we should be quite strict and require explicit wildcards. E.g. if a user specifies google.com, it should only match google.com and not account.google.com. If a user specifies *.google.com, it should match account.google.com, but not test.account.google.com or google.com. If we allow wildcards we should probably only allow one and only as the left-most component of a domain name.

Another (but probably future and separate) feature that might be useful would be to be able to specify a certificate fingerprint to trust, in which case the domain name is not important, only that it was verified using a specific certificate.

This goes back to my original question: how do we get any details about an established TLS connection, for instance in order to check fingerprint or any other details of the cert used for the handshake?

I suspect this would involve using lower level components from rustls for setting up the initial connection (perhaps by writing a custom TLS connector that stores the certificate information). The Channel is generic, and can represent a plain unencrypted connection or a TLS encrypted channel if TLS is enabled.

tiziano88 added a commit to tiziano88/oak that referenced this issue Jul 1, 2020
@daviddrysdale
Copy link
Contributor

This goes back to my original question: how do we get any details about an established TLS connection, for instance in order to check fingerprint or any other details of the cert used for the handshake?

For simple cases, is this needed? If we've asked tonic to connect to https://some.domain.com/sub/path and have provided the relevant TLS configuration, doesn't a valid returned Channel object give us confirmation that we are indeed connected to some.domain.com over TLS (and so the gRPC client pseudo-Node is allowed to declassify domain:some.domain.com labels)?

To put it another way, could we get away with just extracting config.uri.authority().host() and checking that config.uri.scheme() == Some(Scheme::HTTPS) ?

@tiziano88
Copy link
Collaborator Author

This is what I ended up doing in fact (PR coming soon), but it seems in the future we may want more flexibility, for instance if a.domain.com and b.domain.com use the same certificate, it makes sense that there would be a way of declassifying to either of them.

@daviddrysdale
Copy link
Contributor

if a.domain.com and b.domain.com use the same certificate, it makes sense that there would be a way of declassifying to either of them.

I'm not sure it would be safe to assume any correlation between the SAN domains covered in a UCC cert (example).

tiziano88 added a commit to tiziano88/oak that referenced this issue Jul 1, 2020
tiziano88 added a commit to tiziano88/oak that referenced this issue Jul 1, 2020
tiziano88 added a commit to tiziano88/oak that referenced this issue Jul 1, 2020
Replace the certificate SAN name field in the label, with a field that
represents the authority (host:port) of the remote endpoint instead.

Make `run_event_loop` more type safe by passing in a `Reciever<T>` where
`T` is the same type of the `Node<T>` that actually handles the
messages.

Create an explicit `GrpcServerInit` message to pass to a gRPC server
pseudo-node, instead of manually passing handles to it in an
unstructured way.

Remove unused `address` field from `GrpcClientConfiguration` protobuf
message.

Split aggregator example in two nodes, so that the gRPC worker node may
be assigned a different label in the future, to reflect the fact that it
is handling non-public data.

Add explicit scheme to gRPC client URL in aggregator example (not sure
how / whether it worked previously, Tonic complains).

Make aggregator client submit a meaningful number of samples in order to
reach the aggregation threshold, instead of just one.

Ref project-oak#814
tiziano88 added a commit to tiziano88/oak that referenced this issue Jul 1, 2020
Replace the certificate SAN name field in the label, with a field that
represents the authority (host:port) of the remote endpoint instead.

Make `run_event_loop` more type safe by passing in a `Reciever<T>` where
`T` is the same type of the `Node<T>` that actually handles the
messages.

Create an explicit `GrpcServerInit` message to pass to a gRPC server
pseudo-node, instead of manually passing handles to it in an
unstructured way.

Remove unused `address` field from `GrpcClientConfiguration` protobuf
message.

Split aggregator example in two nodes, so that the gRPC worker node may
be assigned a different label in the future, to reflect the fact that it
is handling non-public data.

Add explicit scheme to gRPC client URL in aggregator example (not sure
how / whether it worked previously, Tonic complains).

Make aggregator client submit a meaningful number of samples in order to
reach the aggregation threshold, instead of just one.

Ref project-oak#814
tiziano88 added a commit to tiziano88/oak that referenced this issue Jul 2, 2020
Replace the certificate SAN name field in the label, with a field that
represents the authority (host:port) of the remote endpoint instead.

Make `run_event_loop` more type safe by passing in a `Reciever<T>` where
`T` is the same type of the `Node<T>` that actually handles the
messages.

Create an explicit `GrpcServerInit` message to pass to a gRPC server
pseudo-node, instead of manually passing handles to it in an
unstructured way.

Remove unused `address` field from `GrpcClientConfiguration` protobuf
message.

Split aggregator example in two nodes, so that the gRPC worker node may
be assigned a different label in the future, to reflect the fact that it
is handling non-public data.

Add explicit scheme to gRPC client URL in aggregator example (not sure
how / whether it worked previously, Tonic complains).

Make aggregator client submit a meaningful number of samples in order to
reach the aggregation threshold, instead of just one.

Ref project-oak#814
tiziano88 added a commit to tiziano88/oak that referenced this issue Jul 2, 2020
Replace the certificate SAN name field in the label, with a field that
represents the authority (host:port) of the remote endpoint instead.

Make `run_event_loop` more type safe by passing in a `Reciever<T>` where
`T` is the same type of the `Node<T>` that actually handles the
messages.

Create an explicit `GrpcServerInit` message to pass to a gRPC server
pseudo-node, instead of manually passing handles to it in an
unstructured way.

Remove unused `address` field from `GrpcClientConfiguration` protobuf
message.

Split aggregator example in two nodes, so that the gRPC worker node may
be assigned a different label in the future, to reflect the fact that it
is handling non-public data.

Add explicit scheme to gRPC client URL in aggregator example (not sure
how / whether it worked previously, Tonic complains).

Make aggregator client submit a meaningful number of samples in order to
reach the aggregation threshold, instead of just one.

Ref project-oak#814
tiziano88 added a commit that referenced this issue Jul 2, 2020
Replace the certificate SAN name field in the label, with a field that
represents the authority (host:port) of the remote endpoint instead.

Make `run_event_loop` more type safe by passing in a `Reciever<T>` where
`T` is the same type of the `Node<T>` that actually handles the
messages.

Create an explicit `GrpcServerInit` message to pass to a gRPC server
pseudo-node, instead of manually passing handles to it in an
unstructured way.

Remove unused `address` field from `GrpcClientConfiguration` protobuf
message.

Split aggregator example in two nodes, so that the gRPC worker node may
be assigned a different label in the future, to reflect the fact that it
is handling non-public data.

Add explicit scheme to gRPC client URL in aggregator example (not sure
how / whether it worked previously, Tonic complains).

Make aggregator client submit a meaningful number of samples in order to
reach the aggregation threshold, instead of just one.

Ref #814
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment