GithubHelp home page GithubHelp logo

istio-ecosystem / authservice Goto Github PK

View Code? Open in Web Editor NEW
209.0 26.0 60.0 1.17 MB

Move OIDC token acquisition out of your app code and into the Istio mesh

License: Apache License 2.0

Makefile 5.93% Shell 1.28% Dockerfile 0.39% Go 92.40%
auth authz istio oidc security

authservice's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

authservice's Issues

approve plugin cannot find owners

{
 insertId: "zsre4bfas8ajr"  
 jsonPayload: {
  author: "cfryanr"   
  component: "hook"   
  event-GUID: "0fef05e0-eecd-11e9-87f6-8b407be6260a"   
  event-type: "pull_request"   
  file: "prow/plugins/approve/approvers/owners.go:164"   
  func: "k8s.io/test-infra/prow/plugins/approve/approvers.Owners.GetSuggestedApprovers"   
  level: "warning"   
  msg: "Couldn't find/suggest approvers for each files. Unapproved: [""]"   
  org: "istio-ecosystem"   
  plugin: "approve"   
  pr: 30   
  repo: "authservice"   
  url: "https://github.com/istio-ecosystem/authservice/pull/30"   
 }
 labels: {…}  
 logName: "projects/istio-testing/logs/hook"  
 receiveTimestamp: "2019-10-14T21:53:37.741292100Z"  
 resource: {…}  
 severity: "ERROR"  
 timestamp: "2019-10-14T21:53:33Z"  
}
  1. You could switch to CODEOWNERS, delete OWNERS and disable the approve and lgtm plugins
  2. Maybe the problem is that

    authservice/OWNERS

    Lines 1 to 5 in db27de6

    approvers:
    -BrenoDeMedeiros
    -liminw
    -sawlanipradeep
    -icygalz # prow
    is not a valid yaml file? I believe there needs to be whitespace after the -

authservice creates invalid `/oauth/authorize` request

Installing the current authservice on k8s/GCP results in the loop during the login in flow, where it got stuck in the authentication request:

https://IDP-DOMAIN/oauth/authorize?client_id=fb142b75-fbc3-454c-983d-6bf12ac08d5b&nonce=%60%97&redirect_uri=https%3A%2F%2F35.222.43.97%2Foauth%2Fcallback&response_type=code&scope=openid&state=

We notice that in the above authentication request, both the nonce and state values are invalid/empty.

Here is the authservice logs:

kubectl logs -f -n istio-system transparent-auth-v1-58d54bcc5f-vlxcl
[2019-09-12 20:32:40.572] [console] [trace] OidcFilter
Server listening on 0.0.0.0:8081
[2019-09-12 20:33:52.160] [console] [trace] Check
[2019-09-12 20:33:52.163] [console] [trace] Process
[2019-09-12 20:33:52.163] [console] [debug] Call from @10.8.1.58 to @10.8.1.72
[2019-09-12 20:33:52.163] [console] [trace] Process: checking handler for ://35.222.43.97-/todos
[2019-09-12 20:34:07.280] [console] [trace] Check
[2019-09-12 20:34:07.280] [console] [trace] Process
[2019-09-12 20:34:07.280] [console] [debug] Call from @10.8.1.58 to @10.8.1.72
[2019-09-12 20:34:07.280] [console] [trace] Process: checking handler for ://35.222.43.97-/oauth/callback?code=22c2imRlWA&state=
[2019-09-12 20:34:07.740] [console] [trace] Check
[2019-09-12 20:34:07.740] [console] [trace] Process
[2019-09-12 20:34:07.740] [console] [debug] Call from @10.8.1.58 to @10.8.1.72
[2019-09-12 20:34:07.740] [console] [trace] Process: checking handler for ://35.222.43.97-/oauth/callback?code=3HZgM779v8&state=
[2019-09-12 20:34:08.065] [console] [trace] Check
[2019-09-12 20:34:08.066] [console] [trace] Process
[2019-09-12 20:34:08.068] [console] [debug] Call from @10.8.1.58 to @10.8.1.72
[2019-09-12 20:34:08.069] [console] [trace] Process: checking handler for ://35.222.43.97-/oauth/callback?code=joXtur3t1d&state=
[2019-09-12 20:34:08.484] [console] [trace] Check
[2019-09-12 20:34:08.484] [console] [trace] Process
[2019-09-12 20:34:08.484] [console] [debug] Call from @10.8.1.58 to @10.8.1.72
[2019-09-12 20:34:08.484] [console] [trace] Process: checking handler for ://35.222.43.97-/oauth/callback?code=DT42Zr79IG&state=

We are suspect the RandomGenerator is not working correctly, in oidc_filter.cc:

common::utilities::RandomGenerator generator;
auto state = generator.Generate(32);

This problem reminds us of a separate problem we encountered where VMs on GCP start with insufficient entropy, causing problem with random generation. Just a thought.

Logout

The user should optionally be able to configure logout.path and logout.redirect_to_uri. If they choose to configure either, then they must configure both.

GIVEN The user has configured the logout.path and logout.redirect_to_uri
WHEN The user makes a GET and/or POST to the logout URI, with and/or without cookies,
THEN all of the authservice cookies should be removed (if any)
AND the user's browser should be redirected to GET the configured logout.redirect_to_uri

authservice should share both the ID token and the access token with the app

Currently the authservice fetches both the id token and the access token from the OIDC provider. It then saves the ID token into a browser cookie, and sets the ID token into the Authorization header for the app.

We believe that some apps would prefer to receive the access token, some apps may want to the ID token, and some apps may want both.

Our suggestion is to make this configurable. One possible way to make this configurable would be to expose two new configuration options:

  1. The name of the http header which the authservice should use to transmit the access token to the app. This could default to Authorization, since the Authorization header is typically used for access tokens for APIs. The content of this header would be Bearer <token> where <token> is the JWT token value, since this is the standard format for oauth tokens passed via the Authorization header.

  2. The name of the http header which the authservice should use to transmit the ID token to the app. This could default to X-AuthService-ID-Token. Perhaps just to be consistent, this should also be passed in the Bearer <token> format. That way, if the user overrides the default and configures this value to instead be Authentication then it would be correctly passed in the bearer token format.

If the user accidentally configures both of these options to be the same header name, then perhaps a reasonable behavior would be for the authservice to log a warning and then send only the ID token using that header name (or maybe log an error and abort).

Choose IDP based on request path (or hostname?)

Today you can only choose between OIDC filters using request header matching. We could also support path-based matching (or hostname matching?), so when the Authservice is applied to the gateway you could support multiple apps in the cluster that want to use different OIDC Providers.

Support basic auth for web proxy servers

In our first draft of supporting web proxies, we decided not to support basic auth usernames and passwords for the proxy_uri configuration option.

If we choose to support basic auth to the proxy server in the future, we should probably also support using https to make the "connect" request to the proxy server, so we are not sending the proxy username/password in the clear on the "connect" request's Proxy-Authorization: Basic base64-encoded-proxy-credentials header.

Also, if we choose to support basic auth to the proxy server in the future, we should consider allowing the @ character in usernames and passwords by introducing the \ character as an escape character. Of course, that would also imply that we would need to support escaping the escape character itself, e.g. \\.

Web proxies can also require other auth types, but we're not sure how common those would be. See Proxy-Authorization and Proxy-Authenticate for more information.

Support using refresh tokens to automatically refresh the access token before/when it expires

The goal of this feature is to avoid giving an expired access token to the app for as long as possible by using the refresh token to fetch a new access token, until the refresh token itself expires, at which point the authservice would start a brand new token request.

One possible implementation could be as follows. If the authservice receives a refresh token along with the ID and access tokens, then it would:

  • Save the refresh token into the encrypted browser cookie along with the other tokens
  • There would be no need to send the refresh token to the app via a header, because the authservice is going to take care of using the refresh token on behalf of the app
  • On each subsequent request, the authservice would decrypt the access token, ID token, and refresh token from the user's cookie and check them all to see which have expired
    • If none have expired, then proceed as usual
    • If either the ID token or the access token has expired, and the refresh token has also expired, then clear the cookie, start a brand new token request flow, and proceed as usual
    • If either the ID token or the access token has expired, but the refresh token is still good, then make a request to use the refresh token to get new ID and access tokens (and potentially a new refresh token too). Save the new tokens into the encrypted cookie, and set the access and ID tokens into the headers to pass them to the app.

Start new flow to new fetch tokens when either the ID token or the access token has expired

Currently, the authservice does not look at the user's tokens inside the cookie on subsequent requests. This choice was perhaps made because Istio already supports adding a Policy (with apiVersion "authentication.istio.io/v1alpha1") to validate JWT tokens on the Authorization header (see https://istio.io/docs/tasks/security/authn-policy/#end-user-authentication). Assuming that you configure your app to use both the authservice for fetching tokens and the authentication policy for checking tokens, then the app is secured.

However, when the tokens inside that cookie expire, the user will not be able to access the app anymore. Presumably they would need to manually clear that cookie from their browser to convince the authservice to help them fetch new tokens.

Instead, the authservice could check the expiration dates of the tokens from the cookie on each request. A first draft of an improvement would be for the authserive to simply throw away the cookie and pretend that it was not there when it sees that one of the tokens inside the cookie has expired. That way, the authservice would help the user start the flow to obtain new tokens during that same request where it first detected that a token has expired.

A future iteration of this type of functionality could go a step further by using the refresh token, as described in issue #16, but the first draft described here would not need to be so sophisticated.

The ID token and the access token could potentially have different expiration dates. It might be worth considering ignoring one of them if the app is not interested in receiving that token type from the authservice, assuming that there were some way for the user to configure that.

It would also be worth considering if/how to handle opaque access tokens in the context of this feature. Presumably the authservice would have to make an http call to the OIDC server to ask if the token is still valid. Of course, this would have a performance implication. This probably needs more conversation.

This line of thought perhaps opens the bigger question of whether or not the authservice should be doing full token validation of the tokens from the cookie on every request before putting them on the http headers for the app. One advantage of doing so would be that the user would not need to configure the Istio authentication policy for checking tokens, and thus avoid repeating the issuer and jwksUri settings between the authservice config and the authentication policy config. Another advantage would be that we could support opaque access tokens, which are not supported by the Istio authentication policy. This probably also needs more conversation.

@nickrmc83 What would you think of adding a feature like this to the beta milestone plan?

When the json config file changes, authservice could apply the new config

At the moment, the authservice only read the json config file upon startup.

Using kubectl apply to update the configmap for authservice causes the json file inside the container to be updated (after a short delay). It would be possible for the authservice to detect that this file has changed and react appropriately, somehow taking the new configuration into account, without needing to restart the whole container/pod.

Instead of configuring a `landing_page`, could the authservice send the user back to the original request path that initiated the oauth authorize flow?

If I visit example.com/some_path and the authservice decides that it needs to redirect me to an IDP to login and get tokens, could the authservice send me back to example.com/some_path after it obtains the tokens?

At first glance it would appear that this would require some kind of state to be stored in the authservice. But is there another way? For example, could this state be put into another browser cookie to avoid storing the state server-side?

Jianfei's feedback for bookinfo example docs and config map key names

From Jianfei Hu (@ jianfeih) on istio.slack.com:

would be nice to align the terminology of the config map with actual what /.well-known/oidc-configuration output. the mapping is obvious but can be better

provide a ready to be used oidc client. iirc, the bookinfo demo tutorials somehow assume you get a oidc client app setup (client id, etc) for a certain identity provider, which require some setup out of the sample instruction.

more config editing automation will be great. sed/kubectl/env var combined shows what's going on same time save some error prone editing.

authservice fails to exchange authorization code for access token with keycloak

We are trying to setup an oidc provider for authZ and authN with istio in our k8s cluster. We followed this example here: Bookinfo with Authservice Example for the integration.
Below are the details on the setup:

OIDC provider: Keycloak
Grant type: authorization_code
Istio version: 1.5

Authentication flow:

  1. On first request, since there is no authentication, authservice successfully redirects to Keycloak, where we're able to login successfully.
  2. Keycloak then redirects the request to the application on the redirect_uri. The authorization code is present in this uri now.
  3. The redirect_uri is intercepted by the authservice again and it detects the url to be the filter url for oidc as defined in the configmap
  4. Now it tries to call keycloak for exchanging the authorization code for the access token.

This is the step where authservice fails and gives the error IdP connection error. The log for the request is as follows:

Check: processing request ://microservice.url.com/appservice/oauth/callback?state=LeCNEqfwA6EUFGNGLt7JALx8jCWkPxjn7qCELbqkKrk&session_state=18f0e3b0-bee2-44a5-b049-6e349dbeda49&code=ddea1ea6-5616-416d-8291-c00bce6f2e9b.18f0e3b0-bee2-44a5-b049-6e349dbeda49.af7e7c31-fd4b-4a66-9856-25d1ac305d3f with filter chain idp_filter_chain
20/03/2020 17:27:48 [2020-03-20 11:57:48.546] [console] [trace] New
20/03/2020 17:27:48 [2020-03-20 11:57:48.547] [console] [trace] OidcFilter
20/03/2020 17:27:48 [2020-03-20 11:57:48.548] [console] [trace] Process
20/03/2020 17:27:48 [2020-03-20 11:57:48.548] [console] [debug] Call from @10.42.5.53 to @10.42.5.58
20/03/2020 17:27:48 [2020-03-20 11:57:48.549] [console] [trace] MatchesCallbackRequest: checking handler for ://microservice.url.com/appservice/oauth/callback?state=LeCNEqfwA6EUFGNGLt7JALx8jCWkPxjn7qCELbqkKrk&session_state=18f0e3b0-bee2-44a5-b049-6e349dbeda49&code=ddea1ea6-5616-416d-8291-c00bce6f2e9b.18f0e3b0-bee2-44a5-b049-6e349dbeda49.af7e7c31-fd4b-4a66-9856-25d1ac305d3f
20/03/2020 17:27:48 [2020-03-20 11:57:48.549] [console] [trace] RetrieveToken
20/03/2020 17:27:48 [2020-03-20 11:57:48.550] [console] [trace] Post
20/03/2020 17:27:48 [2020-03-20 11:57:48.618] [console] [info] Post: HTTP error encountered: stream truncated
20/03/2020 17:27:48 [2020-03-20 11:57:48.618] [console] [info] RetrieveToken: HTTP error encountered: IdP connection error
20/03/2020 17:27:48 [2020-03-20 11:57:48.618] [console] [trace] Request processing complete
20/03/2020 17:27:48 [2020-03-20 11:57:48.619] [console] [trace] Processing completion and deleting state

On further checking the code, I found this error is triggered from here: Authservice oidc filter - Github

To rule out the issues with the configuration, I used OpenID Debugger to manually generate an authorization code and then called the api to exchange it for an api token. I was able to successfully retrieve it, there was no issue with that. But somehow it is failing with authservice.

Could there be something wrong on my end? Has anyone experienced this issue before? Any help appreciated. Let me know if any more details are needed.

Authservice should ignore specified paths and not redirect to the IDP for authentication

Traffic for configured paths and methods (e.g. GET /health) should be allowed to pass the authservice without being redirected to the IDP. For instance an application's marketing landing page or health endpoint may not require a user be logged in to view it.

Both the Istio authn policy and the authz policies (both the deprecated RBAC authz policy and the new authz policy) already allow excluding paths and methods.

Allow specification of TLS root certificates for an IdP

Currently any internal IdP whose TLS certificate is not signed by a well-known authority or some delegation thereof will stop working once we start verifying peers correctly. We should make sure it is possible to specify an optional CA certificate for verifying IdP endpoints.

add more mirrors in WORKSPACE file (Error downloading boost from bintray)

Commit 2e2be29

WARNING: Download from https://dl.bintray.com/boostorg/release/1.70.0/source/boost_1_70_0.tar.gz failed: class java.io.IOException GET returned 403 Forbidden 
docker -v
Docker version 18.09.2, build 6247962                                                                                             

lsb_release -a                                         
LSB Version:    core-9.20170808ubuntu1-noarch:printing-9.20170808ubuntu1-noarch:security-9.20170808ubuntu1-noarch                 
Distributor ID: Ubuntu                                                                                                            
Description:    Ubuntu 18.04 LTS
Release:        18.04 LTS
Codename:       bionic
DEBUG: /root/.cache/bazel/_bazel_root/f8087e59fd95af1ae29e8fcb7ff1a3dc/external/bazel_toolchains/rules/rbe_repo/checked_in.bzl:100:9: rbe_ubuntu_clang_gen not using checked in configs as user set attr to 'False'                                                 
DEBUG: /root/.cache/bazel/_bazel_root/f8087e59fd95af1ae29e8fcb7ff1a3dc/external/bazel_toolchains/rules/rbe_repo/checked_in.bzl:100:9: rbe_ubuntu_clang_libcxx_gen not using checked in configs as user set attr to 'False'                                          
DEBUG: /root/.cache/bazel/_bazel_root/f8087e59fd95af1ae29e8fcb7ff1a3dc/external/bazel_toolchains/rules/rbe_repo/checked_in.bzl:100:9: rbe_ubuntu_gcc_gen not using checked in configs as user set attr to 'False'                                                   
Analyzing: target //src/main:auth_server (1 packages loaded, 0 targets configured)                                                
Analyzing: target //src/main:auth_server (11 packages loaded, 16 targets configured)                                              
Analyzing: target //src/main:auth_server (11 packages loaded, 16 targets configured)                                              
DEBUG: Rule 'com_github_abseil-cpp' indicated that a canonical reproducible form can be obtained by modifying arguments shallow_since = "1562102625 -0400"                                                                                                          
DEBUG: Call stack for the definition of repository 'com_github_abseil-cpp' which is a git_repository (rule definition at /root/.cache/bazel/_bazel_root/f8087e59fd95af1ae29e8fcb7ff1a3dc/external/bazel_tools/tools/build_defs/repo/git.bzl:195:18):                
 - /src/WORKSPACE:88:1                                                                                                            
Analyzing: target //src/main:auth_server (22 packages loaded, 148 targets configured)                                             
Analyzing: target //src/main:auth_server (67 packages loaded, 8323 targets configured)                                            
Analyzing: target //src/main:auth_server (77 packages loaded, 8594 targets configured)                                            
INFO: Call stack for the definition of repository 'boost' which is a http_archive (rule definition at /root/.cache/bazel/_bazel_root/f8087e59fd95af1ae29e8fcb7ff1a3dc/external/bazel_tools/tools/build_defs/repo/http.bzl:262:16):                                  
 - /src/WORKSPACE:107:1                                                                                                           
WARNING: Download from https://dl.bintray.com/boostorg/release/1.70.0/source/boost_1_70_0.tar.gz failed: class java.io.IOException GET returned 403 Forbidden                                                                                                       
ERROR: An error occurred during the fetch of repository 'boost':                                                                  
   java.io.IOException: Error downloading [https://dl.bintray.com/boostorg/release/1.70.0/source/boost_1_70_0.tar.gz] to /root/.cache/bazel/_bazel_root/f8087e59fd95af1ae29e8fcb7ff1a3dc/external/boost/boost_1_70_0.tar.gz: GET returned 403 Forbidden             
INFO: Call stack for the definition of repository 'boringssl' which is a http_archive (rule definition at /root/.cache/bazel/_bazel_root/f8087e59fd95af1ae29e8fcb7ff1a3dc/external/bazel_tools/tools/build_defs/repo/http.bzl:262:16):                              
 - /root/.cache/bazel/_bazel_root/f8087e59fd95af1ae29e8fcb7ff1a3dc/external/envoy_api/bazel/envoy_http_archive.bzl:17:5           
 - /root/.cache/bazel/_bazel_root/f8087e59fd95af1ae29e8fcb7ff1a3dc/external/envoy/bazel/repositories.bzl:23:5                     
 - /root/.cache/bazel/_bazel_root/f8087e59fd95af1ae29e8fcb7ff1a3dc/external/envoy/bazel/repositories.bzl:175:5                    
 - /root/.cache/bazel/_bazel_root/f8087e59fd95af1ae29e8fcb7ff1a3dc/external/envoy/bazel/repositories.bzl:116:5                    
 - /src/WORKSPACE:24:1                                                                                                            
ERROR: /src/src/config/BUILD:5:1: //src/config:config depends on @boost//:all in repository @boost which failed to fetch. no such package '@boost//': java.io.IOException: Error downloading [https://dl.bintray.com/boostorg/release/1.70.0/source/boost_1_70_0.tar.gz] to /root/.cache/bazel/_bazel_root/f8087e59fd95af1ae29e8fcb7ff1a3dc/external/boost/boost_1_70_0.tar.gz: GET returned 403 Forbidden                                                                                                                              
ERROR: Analysis of target '//src/main:auth_server' failed; build aborted: no such package '@boost//': java.io.IOException: Error downloading [https://dl.bintray.com/boostorg/release/1.70.0/source/boost_1_70_0.tar.gz] to /root/.cache/bazel/_bazel_root/f8087e59fd95af1ae29e8fcb7ff1a3dc/external/boost/boost_1_70_0.tar.gz: GET returned 403 Forbidden                                            
INFO: Elapsed time: 91.324s                                                                                                       
INFO: 0 processes.                                                                                                                
FAILED: Build did NOT complete successfully (99 packages loaded, 8858 targets configured)                                         
FAILED: Build did NOT complete successfully (99 packages loaded, 8858 targets configured)                                         
make: *** [Makefile:33: bazel-bin/src/main/auth_server] Error 1 

Support other kind(s) of session storage, e.g. Redis or MySql or something

Authservice server-side sessions store things like your ID token, access token, refresh token, and the url that you originally requested before you were redirected to auth. In the first draft, this is all stored in memory. This has two implications for large-scale production usage:

  1. If the container restarts, those users loses their sessions. This isn't too bad if your IDP has its own sessions with those users, because on their next request the Authservice will redirect to the IDP which will immediately log them in without showing any UI.

  2. If you are scaling the Authservice horizontally, then you need to use session affinity to ensure that each session always lands on the same Authservice instance. Again, if your IDP has its own sessions, then its not too big of a deal for a user to land on the wrong instance of Authservice, as they will transparently be logged in (again) after some redirects. This just puts unnecessary load on the IDP.

Moving session storage to a shared storage layer would fix both of these issues.

That opens the question of which solution(s) would be preferable? e.g. Redis, MySql, others? How do other aspects of Istio do things like this? How is this typically done on k8s?

Minor fixes to bookinfo-example/README.md

Under Deploy Bookinfo Using the Authservice for Token Acquisition + Authorization (Sidecar integration):

  • at step 1, we have: kubectl -f config/authservice-configmap-template-for-authn-and-authz.yaml
    it should be instead: kubectl apply -f config/authservice-configmap-template-for-authn-and-authz.yaml

  • at step 2.iv we say:
    If the callback or logout paths in config/authservice-configmap-template-for-authn.yaml were edited in a previous step, ..."
    here the file should be the same we have applied at step 1 (config/authservice-configmap-template-for-authn-and-authz.yaml instead of config/authservice-configmap-template-for-authn.yaml)

Setup CI/CD

Create CI/CD configuration for running builds and test on all commits and MRs.

Allow configuration of more settings without recompiling

It should be possible for community members to try the upcoming alpha release without compiling the code or rebuilding the container image.

Therefore, let's allow the configuration (without needing to recompile or build a new container image) of the following:

  • jwks
    • Why: The authservice currently does not work correctly unless this is configured, so let's allow people to configure it for the alpha release. This is the most important item in this issue for the alpha release.
  • cryptor_secret
    • Why: When placing the authservice in the same deployment as an app and its envoy sidecar, and then scaling that pod's number of replicas, incoming requests will be load balanced between multiple replicas of the authservice, so all of those authservices need to be configured to use the same cryptor_secret so they can all read and write the same cookies.
  • cookie_name_ and state_cookie_name_
    • Why: When using the authservice in the same deployment as an app, and using it for multiple deployments (i.e. multiple apps) behind the same gateway, the authservice of the first app and the authservice of the second app need to avoid stepping on each other's cookies.
  • log level
    • Why: when community members who want to try to alpha are debugging their deployment, they will need to be able to turn up the log level to trace, and otherwise may wish to turn it down. Since it already defaults to trace, this maybe isn't super important. Allowing the user to turn the log level down would allow them to prevent logging potentially sensitive information, so it would be nice to have.
    • Note: The authservice should probably unconditionally complain in the log if it can't find its json config file, since there's a bit of a chicken and egg consideration in deciding what log level to use to log the fact that it failed to learn about what log level it should be be using.
  • address
    • Why: While 127.0.0.1 is a nice default for the address on which the authservice should listen, it prevents users from deploying the authservice as a separate deployment, in which case they would need it to listen on 0.0.0.0. Since we plan to only recommend using the authservice in the same deployment (i.e. same pod) as your app for the alpha release, this isn't super important. Nice to have.
  • port
    • Why: Just in case it conflicts with the port that their app is using. Pretty unlikely, so not super important for the alpha. Nice to have.

Consider supporting client credential flow

Shubham Shukla:

Hi, We implemented authservice to be used with keycloak. Combined with istio auth policies, our end user authentication and authorization(using authorization_code grant) works great!
We also have the requirement for service to service communication within the mesh(background jobs for example). For this we would need to use either resource owner flow or client credential flow. Does authservice support that? If not, with istio what is the recommended way to go about this?

Test deploying the authservice in the same pod as the envoy which initiates the `check` request

In our previous experiments using the authservice with Istio/k8s we had deployed the authservice as a separate pod.

The goal is to make sure that the approach of deploying it into the same pod works with the current code, and to make sure it is not too hard to configure. The hope is that keeping the communication within the same pod (i.e. on localhost) will make it more efficient/secure.

The Pivotal team offered to test this out.

GRPC Check()'s request object has no scheme for request which includes authcode, causes authservice to go into redirect loop

When the OIDC server redirects the user back to the authservice with the authcode, envoy does not include the scheme in the request object passed to the check() grpc invocation.

You can see in the envoy code in check_request_utils.cc that it intends to read the scheme from the headers and include it in the request object.

However, you can also see in the logs of the sidecar envoy proxy that the header has no scheme, so the scheme ends up setting set to empty string in the request object.

[2019-10-02 17:07:39.415][21][trace][http] [external/envoy/source/common/http/http1/codec_impl.cc:514] [C1012] message complete
[2019-10-02 17:07:39.415][21][debug][http] [external/envoy/source/common/http/conn_manager_impl.cc:620] [C1012][S3038797389355712708] request headers complete (end_stream=true):
':authority', '35.184.251.112'
':path', '/oauth/callback?code=<REDACTED>&state=somestate'
':method', 'GET'
'cache-control', 'max-age=0'
'upgrade-insecure-requests', '1'
'user-agent', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36'
'sec-fetch-mode', 'navigate'
'sec-fetch-user', '?1'
'accept', 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3'
'sec-fetch-site', 'cross-site'
'referer', 'https://demo.login.run.pivotal.io/login'
'accept-encoding', 'gzip, deflate, br'
'accept-language', 'en-US,en;q=0.9'
'cookie', '__Host-acme-state-cookie=U_H1gEHrR2Q6ql4HUpnwg7b0FS-d-rBj4sr9FN8SPLLEWO5KoTsZDJA2encWbrI9nhlWv92RKAwNDS_Wox4dzNSxunds1PVKXTNGejhK1w'
'x-forwarded-for', '10.128.15.194'
'x-forwarded-proto', 'https'
'x-envoy-internal', 'true'
'x-request-id', 'eb56154d-3d36-9296-ae58-ba699589bb07'
'x-envoy-decorator-operation', 'authcode-sample-app.default.svc.cluster.local:8080/oauth*'
'x-istio-attributes', 'CksKGGRlc3RpbmF0aW9uLnNlcnZpY2UuaG9zdBIvEi1hdXRoY29kZS1zYW1wbGUtYXBwLmRlZmF1bHQuc3ZjLmNsdXN0ZXIubG9jYWwKSQoXZGVzdGluYXRpb24uc2VydmljZS51aWQSLhIsaXN0aW86Ly9kZWZhdWx0L3NlcnZpY2VzL2F1dGhjb2RlLXNhbXBsZS1hcHAKMQoYZGVzdGluYXRpb24uc2VydmljZS5uYW1lEhUSE2F1dGhjb2RlLXNhbXBsZS1hcHAKKgodZGVzdGluYXRpb24uc2VydmljZS5uYW1lc3BhY2USCRIHZGVmYXVsdApPCgpzb3VyY2UudWlkEkESP2t1YmVybmV0ZXM6Ly9pc3Rpby1pbmdyZXNzZ2F0ZXdheS03NTc1ZmY2NDc4LXJuc3NqLmlzdGlvLXN5c3RlbQ=='
'x-b3-traceid', 'e227b3e674b2fa1470ba2e837fddd97c'
'x-b3-spanid', '70ba2e837fddd97c'
'x-b3-sampled', '1'
'content-length', '0'

It is unclear why the request has no scheme here. We can see in our Chrome browser's debug tools that the redirect from the OIDC server was in fact an https URL, and that the browser followed that redirect by making a GET request to the https URL.

The authservice code puts out a trace log which shows that the request's scheme is empty:

[2019-10-02 17:07:40.408] [console] [trace] Check
[2019-10-02 17:07:40.409] [console] [trace] Process
[2019-10-02 17:07:40.412] [console] [debug] Call from @10.16.0.10 to @10.16.0.18
[2019-10-02 17:07:40.412] [console] [trace] Process: checking handler for ://35.184.251.112-/oauth/callback?code=<REDACTED>&state=somestate

The result is that the if statement's expression always resolves to false, even in the case where we want it to resolve to true, causing the authservice to never trigger its code which is supposed to exchange the authcode for the token. Instead it starts the token flow from scratch, resulting in a redirect loop which gets halted by the browser.

Async external request support

We need to improve performance for the number in-progress requests. Presently we use blocking grpc and boost network implementations that mean it is conceivable that a trivial DoS could take place and not necessarily by a malicious party.

Session management

Once we have finished implementing server-side sessions, we should consider:

  1. Issue new session IDs as often as possible to help users avoid things like session fixation attacks
  2. Session timeouts
    1. Offer a configuration option for max session idle time
    2. Offer a configuration option for max absolute session lifetime
    3. Also expire session info from the session storage to reduce resource usage

https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Session_Management_Cheat_Sheet.md

Test setting up authservice using filter injection in Istio 1.3.0

We would like to be able to use the alpha version of authservice with the latest release of Istio, v1.3.0.

In our testing with a pre-repease version of Istio 1.3 we were able to inject an envoy.ext_authz filter into the application's sidecar's inbound envoy.http_connection_manager using a EnvoyFilter configuration. We configured that envoy.ext_authz filter to send all incoming requests to the authservice via grpc check requests for evaluation.

Unfortunately, this same approach did not work with the first public release of Istio, v1.3.0. We would like to figure out how to make this work before release, because we had planned to document this as the recommended way to use the alpha version of the authservice with Istio on k8s.

Test using multiple authservices to secure multiple apps at the same time

The goal of testing this is to find if it works to have multiple apps which each have their own sidecar and each have their own authservice at the same time. We would especially expect to discover if the authservice provides enough configuration options to make it possible.

e.g. I would guess that each instance of the authservice would need to have unique cookie names if the apps are deployed within the same domain. (Is this a use case that we want to support?)

e.g. I would also guess that each instance of authservice should also have its own cryptor_secret.

log level flag error

The pod containing the authservice is experiencing CrashLoopBackOff due to the log-level flag:

kubectl logs -n istio-system transparent-auth-v1-55b5f5b849-bhx54
ERROR: Unknown command line flag 'log-level'

Changing the Dockerfile CMD line to "--loglevel" fixes this error. We also noticed that the main function requires "--loglevel" too.

Suggested doc improvements

On Istio Slack:

From Shriram Rajagopalan (Tetrate):

Can you convert the readme into an Istio doc example or something?
This is quite useful. You can document it so that more people have access to it
Take this https://github.com/istio-ecosystem/authservice/tree/master/bookinfo-example#authz-with-review-service-optional and make this change part of official bookinfo so that you wont have to build your own.

As suggested above, we could PR the change to Istio's https://github.com/istio/istio/blob/master/samples/bookinfo/src/productpage/productpage.py#L185 file (fixing incoming_headers to allow the authorization header to be forwarded on backend app requests).

Second, migrate all your stuff to use new authN api
https://github.com/istio-ecosystem/authservice/blob/master/bookinfo-example/config/bookinfo-authn-policy-template-adding-reviews.yaml specificallty

Support http proxy servers when exchanging authcode for token

From a Slack conversation with Enrique Medina Montenegro.

Good morning from the Netherlands 🙂 Here is the info about the proxy issue:

My company uses a corporative proxy --> http://proxy.internal.mycompany.org:8080 <-- to provide access to the Internet

  • If any Pod running in our K8s cluster needs outbound Internet access, then it must configure this proxy as env variables --> HTTP_PROXY, HTTPS_PROXY and NO_PROXY
  • When using the auth-service, the first redirection to our Azure AD IdP is actually performed by the browser, so there is no issue here
  • However, when the auth-service needs to exchange the authorization code for the access token, then it cannot due to not being able to access the Internet

Taking a look at the code, I see that you use the Boost.Beast library for HTTP matters, which claims not to have in its scope the addition of such proxy support:
https://groups.google.com/d/msg/boost-developers-archive/-Zf7f-dfcmA/BUAjLnngBAAJ

However, it seems to be pretty easy:
https://stackoverflow.com/questions/11523829/how-to-add-proxy-support-to-boostasio/11537603#11537603

These are the precise logs:

# kubectl logs productpage-v1-5c6798d7d4-mzhs9 -c authservice
[2019-12-03 08:04:48.487] [console] [info] RunServer: Server listening on 127.0.0.1:10003
[2019-12-03 08:05:01.305] [console] [trace] Check
[2019-12-03 08:05:01.305] [console] [trace] Matches
[2019-12-03 08:05:01.305] [console] [debug] Check: processing request ://bookinfo.dev.epocloud.altia.es/productpage with filter chain idp_filter_chain
[2019-12-03 08:05:01.305] [console] [trace] New
[2019-12-03 08:05:01.306] [console] [trace] OidcFilter
[2019-12-03 08:05:01.306] [console] [trace] Process
[2019-12-03 08:05:01.306] [console] [debug] Call from @172.16.20.105 to @172.16.135.3
[2019-12-03 08:05:01.306] [console] [info] GetTokenFromCookie: __Host-bookinfo-authservice-id-token-cookie token cookie missing
[2019-12-03 08:05:01.306] [console] [info] GetTokenFromCookie: __Host-bookinfo-authservice-access-token-cookie token cookie missing
[2019-12-03 08:05:01.306] [console] [trace] Process: checking handler for ://bookinfo.dev.epocloud.altia.es-/productpage
[2019-12-03 08:05:01.794] [console] [trace] Check
[2019-12-03 08:05:01.794] [console] [trace] Matches
[2019-12-03 08:05:01.794] [console] [debug] Check: processing request ://bookinfo.dev.epocloud.altia.es/productpage/oauth/callback?code=OAQABAAIAAACQN9QBRU3jT6bcBQLZNUj7FraunBPo2Anx9gyAxLsdu-bjmfQnfzP9GJZCGakYWsHRzeV_eP89xj8IlweogBgNVF-IJW88VHMjUF2mb1qBgxYUOcOhN4X0RovpJOv25ad5dUCGWpoHmK0n1Q04dDi5dYtbZDAYqPyc_xJmr-rwtSneZoVu7jL16aJ-cF6M96iJQSoZw5fUXlJDaECEls1FKHr6XOhsqtQYgyu8hEL9yt5r3ONyG7Oo6QDWheJi96axsOrOa4toF62bElJeVm4Rsv5C2FFEvMkTQJXXj1hEhc-zk-owBC4D8m5NVGKzRhwphgpkYtRBMyEZtouiJQReKRcGry4KbbXA87LDfM0S5XGX-Kyad7WHV3-s62gFwjW7QqyG0OUq2D6Obm0xIlnmlk6alUOowSAijHHbgf_zXlI34ACRW4pv7SqZ0b6SHtMEioJe0CNFCDBlUVC7Md3_9lCMoonwNoVpEHNE-9eOLKamC-sJyevrATPt6A-WX9HsWcPk3OBwiqnzwMP9DJxj7MLl6KATfLI0mmeswhluYLINKKuvhr6a6oWncaVK9HlsBjH-MYXoRv5kqoaMCh3tU6lNhFMHhUodCcwvPUG4CBDoPQ9UubmEctTyGway7viwDniuqfzP1hj1pVTH09ZrUcVgeSv4sEHeXgupQ4_j7lYtBqWaohHsoQngxVq5HvmSBA8qd_8_Qlxx3vXyGfXuZSFWaZghaKYKrRP7Dm8Dc9R8PvoliTBvL1fLh2KiyePncMfAalIh96NdN27zCLDtbLoNeJpf0NVvp-HXsBckBMxCxLsxMKm22UNLhB3wdSnBEND-HUFxCiPA1IzXsgCGoZW9cFvMFJtbIjyy3ZXkE7DJSewKjW4I7MIVABBEeccgAA&state=0w05_ITARWBE0BfMcW2oSNwFTMtiPRW3Iq_VBkLbAJY&session_state=c302d6d2-c392-424d-97d3-2579814617c4 with filter chain idp_filter_chain
[2019-12-03 08:05:01.794] [console] [trace] New
[2019-12-03 08:05:01.794] [console] [trace] OidcFilter
[2019-12-03 08:05:01.794] [console] [trace] Process
[2019-12-03 08:05:01.794] [console] [debug] Call from @172.16.20.105 to @172.16.135.3
[2019-12-03 08:05:01.795] [console] [info] GetTokenFromCookie: __Host-bookinfo-authservice-id-token-cookie token cookie missing
[2019-12-03 08:05:01.795] [console] [info] GetTokenFromCookie: __Host-bookinfo-authservice-access-token-cookie token cookie missing
[2019-12-03 08:05:01.795] [console] [trace] Process: checking handler for ://bookinfo.dev.epocloud.altia.es-/productpage/oauth/callback?code=OAQABAAIAAACQN9QBRU3jT6bcBQLZNUj7FraunBPo2Anx9gyAxLsdu-bjmfQnfzP9GJZCGakYWsHRzeV_eP89xj8IlweogBgNVF-IJW88VHMjUF2mb1qBgxYUOcOhN4X0RovpJOv25ad5dUCGWpoHmK0n1Q04dDi5dYtbZDAYqPyc_xJmr-rwtSneZoVu7jL16aJ-cF6M96iJQSoZw5fUXlJDaECEls1FKHr6XOhsqtQYgyu8hEL9yt5r3ONyG7Oo6QDWheJi96axsOrOa4toF62bElJeVm4Rsv5C2FFEvMkTQJXXj1hEhc-zk-owBC4D8m5NVGKzRhwphgpkYtRBMyEZtouiJQReKRcGry4KbbXA87LDfM0S5XGX-Kyad7WHV3-s62gFwjW7QqyG0OUq2D6Obm0xIlnmlk6alUOowSAijHHbgf_zXlI34ACRW4pv7SqZ0b6SHtMEioJe0CNFCDBlUVC7Md3_9lCMoonwNoVpEHNE-9eOLKamC-sJyevrATPt6A-WX9HsWcPk3OBwiqnzwMP9DJxj7MLl6KATfLI0mmeswhluYLINKKuvhr6a6oWncaVK9HlsBjH-MYXoRv5kqoaMCh3tU6lNhFMHhUodCcwvPUG4CBDoPQ9UubmEctTyGway7viwDniuqfzP1hj1pVTH09ZrUcVgeSv4sEHeXgupQ4_j7lYtBqWaohHsoQngxVq5HvmSBA8qd_8_Qlxx3vXyGfXuZSFWaZghaKYKrRP7Dm8Dc9R8PvoliTBvL1fLh2KiyePncMfAalIh96NdN27zCLDtbLoNeJpf0NVvp-HXsBckBMxCxLsxMKm22UNLhB3wdSnBEND-HUFxCiPA1IzXsgCGoZW9cFvMFJtbIjyy3ZXkE7DJSewKjW4I7MIVABBEeccgAA&state=0w05_ITARWBE0BfMcW2oSNwFTMtiPRW3Iq_VBkLbAJY&session_state=c302d6d2-c392-424d-97d3-2579814617c4
[2019-12-03 08:05:01.795] [console] [trace] RetrieveToken
[2019-12-03 08:05:01.795] [console] [trace] Post
[2019-12-03 08:05:01.860] [console] [info] Post: unexpected exception: handshake: WRONG_VERSION_NUMBER
[2019-12-03 08:05:01.860] [console] [info] RetrieveToken: HTTP error encountered: IdP connection error

Authservice not accepting http endpoints: invalid authorization_uri

We are trying to set up the authentication with Istio and keycloak by following the guide here.

We have installed keycloak on our k8s cluster and have exposed it on port 80 as http load balancer.
Keycloak endpoints are http and the 'Require SSL' is set to 'none' at the realm level.
We have configured these endpoints in config/authservice-configmap-template-for-authn.yaml. Istio sidecar injection in enabled in the cluster.

However on applying config/bookinfo-with-authservice-template.yaml, the productpage pod is going to CrashLoopBackOff state with the below error log in the authservice container:

[2020-03-24 08:25:11.162] [console] [error] main: Unexpected error: invalid authorization_uri: uri must be https scheme: http://<ip>/auth/realms/<realm>/protocol/openid-connect/auth

Doesn't authservice support keycloak http endpoints?
In case https endpoints are mandatory for authservice, is there a restriction on how the certificates are generated for keycloak or istio? Should it be a trusted root certificate or can it be a self-signed certificate?

Istio version: 1.4.5
Kubectl version: v1.14.10-gke.17

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.