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

(7.0) App access client cert auth #5918

Merged
merged 1 commit into from
Mar 22, 2021
Merged

(7.0) App access client cert auth #5918

merged 1 commit into from
Mar 22, 2021

Conversation

r0mant
Copy link
Collaborator

@r0mant r0mant commented Mar 9, 2021

Introduce ability to use application access with client certificates for authentication. Refs #5213.

Here's what the UX looks like.

View registered applications:

➜ build/tsh app ls
Application Description Public Address                Labels
----------- ----------- ----------------------------- --------
debug-root              debug-root.gravitational.io   app=test
grafana                 grafana-root.gravitational.io app=test

Retrieve certificate / init a session for the app:

➜ build/tsh app login debug-root
Logged into app "debug-root". Example curl command:

curl \
  --cacert /Users/r0mant/.tsh/keys/root.gravitational.io/certs.pem \
  --cert /Users/r0mant/.tsh/keys/root.gravitational.io/r0mant-app/root/debug-root-x509.pem \
  --key /Users/r0mant/.tsh/keys/root.gravitational.io/r0mant \
  https://debug-root.gravitational.io:3080

View app information:

➜ build/tsh app config
Name:      debug-root
URI:       https://debug-root.gravitational.io:3080
CA:        /Users/r0mant/.tsh/keys/root.gravitational.io/certs.pem
Cert:      /Users/r0mant/.tsh/keys/root.gravitational.io/r0mant-app/root/debug-root-x509.pem
Key:       /Users/r0mant/.tsh/keys/root.gravitational.io/r0mant

For automation friendliness, use --format to print specific parts of the app config:

# Print only app URI
➜ build/tsh app config --format=uri
https://debug-root.gravitational.io:3080

# Print only CA path
➜ build/tsh app config --format=ca
/Users/r0mant/.tsh/keys/root.gravitational.io/certs.pem

# Print only cert path
➜ build/tsh app config --format=cert
/Users/r0mant/.tsh/keys/root.gravitational.io/r0mant-app/root/debug-root-x509.pem

# Print only key path
➜ build/tsh app config --format=key
/Users/r0mant/.tsh/keys/root.gravitational.io/r0mant

# Print example curl command
➜ build/tsh app config --format=curl
curl \
  --cacert /Users/r0mant/.tsh/keys/root.gravitational.io/certs.pem \
  --cert /Users/r0mant/.tsh/keys/root.gravitational.io/r0mant-app/root/debug-root-x509.pem \
  --key /Users/r0mant/.tsh/keys/root.gravitational.io/r0mant \
  https://debug-root.gravitational.io:3080

With this you could do something like:

➜ curl -H "Authorization: Bearer xyz" \
  --cacert $(tsh app config --format=ca) \
  --cert $(tsh app config --format=cert) \
  --key $(tsh app config --format=key) \
  $(tsh app config --format=uri)/xxx/yyy

api/types/session.go Show resolved Hide resolved
integration/app_integration_test.go Show resolved Hide resolved
integration/app_integration_test.go Outdated Show resolved Hide resolved
lib/client/api.go Outdated Show resolved Hide resolved
lib/client/keystore.go Outdated Show resolved Hide resolved
tool/tsh/app.go Show resolved Hide resolved
tool/tsh/app.go Outdated Show resolved Hide resolved
tool/tsh/app.go Outdated Show resolved Hide resolved
tool/tsh/app.go Outdated Show resolved Hide resolved
tool/tsh/app.go Outdated Show resolved Hide resolved
Copy link
Contributor

@russjones russjones left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First pass, will continue tomorrow.


// WaitForAppSession will block until the requested application session shows up in the
// cache or a timeout occurs.
func WaitForAppSession(ctx context.Context, sessionID, user string, ap AccessPoint) error {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@fspmarshall has been putting functions like these into services.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function needs an AccessPoint which resides here in auth package so I can't really move it to services without introducing cyclic deps.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can create an interface with just GetAppSession and NewWatcher in it.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I tried that and it doesn't work either unfortunately since this method also depends on services/local so it'd be a loop anyway :-/

lib/auth/sessions.go Outdated Show resolved Hide resolved
lib/auth/sessions.go Outdated Show resolved Hide resolved
lib/auth/sessions.go Outdated Show resolved Hide resolved
lib/auth/auth.go Outdated Show resolved Hide resolved

// WaitForAppSession will block until the requested application session shows up in the
// cache or a timeout occurs.
func WaitForAppSession(ctx context.Context, sessionID, user string, ap AccessPoint) error {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can create an interface with just GetAppSession and NewWatcher in it.

Comment on lines 46 to 56
// Check that a matching parent web session exists in the backend.
parentSession, err := s.GetWebSession(ctx, types.GetWebSessionRequest{
User: req.Username,
SessionID: req.ParentSession,
})
if err != nil {
return nil, trace.Wrap(err)
}

// Don't let the TTL of the child certificate go longer than the parent.
ttl := checker.AdjustSessionTTL(parentSession.GetExpiryTime().Sub(s.clock.Now()))
// Don't let the app session go longer than the identity expiration,
// which matches the parent web session TTL as well.
ttl := checker.AdjustSessionTTL(identity.Expires.Sub(s.clock.Now()))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@r0mant I think this is fine.

Can you update the comment with some more details about why this works for browser based Application Access: browser will send a cookie with sessionID which will be used to fetch services.WebSession which contains a certificate whose life matches the life of the session that will be used to establish the connection.

@awly You might want to review these changes as well.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated the comment.

lib/web/app/handler.go Outdated Show resolved Hide resolved
tool/tsh/app.go Outdated Show resolved Hide resolved
api/types/session.go Outdated Show resolved Hide resolved
@r0mant
Copy link
Collaborator Author

r0mant commented Mar 18, 2021

@russjones I've addressed your comments.

@r0mant r0mant force-pushed the roman/curl branch 2 times, most recently from 2ea7a89 to 6aaa029 Compare March 20, 2021 00:25
@r0mant r0mant changed the title App access client cert auth (7.0) App access client cert auth Mar 22, 2021
@r0mant r0mant enabled auto-merge (squash) March 22, 2021 16:09
@r0mant r0mant merged commit a3837f6 into master Mar 22, 2021
@r0mant r0mant deleted the roman/curl branch March 22, 2021 16:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants