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

Default Policy examples #201

Closed
edwarnicke opened this issue Apr 14, 2020 · 4 comments
Closed

Default Policy examples #201

edwarnicke opened this issue Apr 14, 2020 · 4 comments
Assignees
Labels
enhancement New feature or request

Comments

@edwarnicke
Copy link
Member

We need default OPA Policies based upon the update in input found in #200

Among the examples we'd want:

  1. Tokens valid - checks the validity of some or all of the tokens in the path.
  2. No Tokens in path expired - none of the tokens in the chain are expired.
  3. Last Token matches TLSInfo - checks to make sure that the Last Token (JWT) is signed by the same cert as found in TLSInfo.
  4. Token.Aud for token n in path matches Token.Sub for n+1 token in chain
@edwarnicke edwarnicke added this to To do in Issue/PR tracking via automation Apr 14, 2020
@lazyniv
Copy link
Member

lazyniv commented Apr 17, 2020

I think, we can consider the following use case example of tokens validation(1)

So, for example of tokens validation we can consider the case of matching clients and endpoints by their SPIFFE IDs. The map of matching(endpoint’s spiffe id -> list of allowed clients by spiffe id) can be stored on NSMgrs. The policy of matching also can be stored on NSMgrs. So let’s consider the case more detailed:

  1. Client generates jwt token with the following claims:

    1. src spiffe id -- client’s spiffe id
    2. dst spiffe id -- spiffe id of the endpoint the client wants
  2. Then this token should be sign by provided x.509 certificate

  3. Then this token should be validated on NSMgr(which placed on the same node as a client) by provided policy using OPA(in our case it’s just a matching by spiffe ids)

  4. Then we get the policy decision from the OPA and do something with this request (e.g. reject)

Am I in the right direction?

We have the following problems:

  1. Where should we handle the policies?
  2. How are we going to deploy policies? We need to API for that

@edwarnicke
Copy link
Member Author

So, for example of tokens validation we can consider the case of matching clients and endpoints by their SPIFFE IDs. The map of matching(endpoint’s spiffe id -> list of allowed clients by spiffe id) can be stored on NSMgrs. The policy of matching also can be stored on NSMgrs. So let’s consider the case more detailed:

No... an Endpoint itself applies its own policy. The NSMgr is not responsible for that policy. The NSMgr may have certain kinds of policy applicable to its own role... but client/endpoint permissiblity isn't among them.

  1. Client generates jwt token with the following claims:

src spiffe id -- client’s spiffe id
dst spiffe id -- spiffe id of the endpoint the client wants

The client generally speaking isn't asking for an endpoint, it's asking for a Network Service. The NSMgr is selecting an Endpoint that can provide it, and forwarding on the (possibly modified) request to the endpoint (likely via other intermediaries). The updatepath chain element creates the token... based on the token.GeneratorFunc it is provided by the implementor of the Client or Endpoint.

We are recommending (but not requiring) SpiffeJWTTokenGeneratorFunc
which generates SpiffeJWTSVID based upon a SpiffeX509 cert.

It populates

  1. 'sub' with the spiffe ID of the Client
  2. 'aud' with the entity that the Client is immediately talking to (in most cases, its NSMgr).

This means that as the Path is extended, you can rule out man in the middle attacks by comparing the identity of the 'aud' from token n with the identity of the 'sub' from token n+1.

  1. Then this token should be sign by provided x.509 certificate
    Yes! See SpiffeJWTTokenGeneratorFunc
  1. Then this token should be validated on NSMgr(which placed on the same node as a client) by provided policy using OPA(in our case it’s just a matching by spiffe ids)
    Yes! A good choice of default policy for a NSMgr would include 'validate the token of Path.PathSegment[Path.Index].Token. That validation would commonly involve:
  1. Authenticate the Path.PathSegment[Path.Index].Token
  2. Ensure the SpiffeId for the Path.PathSegment[Path.Index].Token matches the SpiffeID for the TLS cert received from the client (this is why the TLS cert needs to be part of the 'input')

Then we get the policy decision from the OPA and do something with this request (e.g. reject)
Please note... allof the validating etc should be done by the OPA policy :)

We have the following problems:

Where should we handle the policies?

authorize chain element

How are we going to deploy policies? We need to API for that

Don't worry yet about the policy deploying pieces... OPA has some standard APIs for that, for the moment we are just passing them into the authorize chain element

@lazyniv lazyniv moved this from To do to In progress in Issue/PR tracking Apr 29, 2020
@lazyniv lazyniv moved this from In progress to To do in Issue/PR tracking Apr 29, 2020
@lazyniv lazyniv moved this from To do to In progress in Issue/PR tracking May 8, 2020
@lazyniv
Copy link
Member

lazyniv commented May 19, 2020

@edwarnicke I have some questions about first and third policies

  1. Tokens valid - checks the validity of some or all of the tokens in the path.

You wrote

Authenticate the Path.PathSegment[Path.Index].Token
Ensure the SpiffeId for the Path.PathSegment[Path.Index].Token matches the SpiffeID for the TLS cert received from the client

I think, that the first policy should be like that:

package defaultpolicies

default tokens_valid = false

tokens_valid {
    token := input.connection.path.path_segments[input.connection.path.index].token
    cert := input.auth_info.certificate
    spiffe_id := input.auth_info.spiffe_id # spiffe_id from tlsInfo(SVIDx509Cert)
    io.jwt.verify_es256(token, cert) # signature verification 
    [_, payload, _] := io.jwt.decode(token) 
    payload.sub == spiffe_id
  1. Last Token matches TLSInfo - checks to make sure that the Last Token (JWT) is signed by the same cert as found in TLSInfo.

So, I think third policy should be like that:

package defaultpolicies

default last_token_matches_tls = false

last_token_matches_tls {
    token := input.connection.path.path_segments[input.connection.path.index].token
    cert := input.auth_info.certificate
    io.jwt.verify_es256(token, cert)
}

Where should we get the certificate(tlsInfo)?

Is it a right direction?

Other policies(2,4) and use cases you can take a look in spec

Also have implemented use case about validity chain(path_segments[n-1].token.aud == path_segments[n].token.sub). You can take a look it in draft pr on this

@edwarnicke
Copy link
Member Author

This looks like a great start! :)

@denis-tingaikin denis-tingaikin self-assigned this May 26, 2020
@denis-tingaikin denis-tingaikin added the enhancement New feature or request label May 26, 2020
Issue/PR tracking automation moved this from In progress to Done Jun 9, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
Development

No branches or pull requests

3 participants