-
Notifications
You must be signed in to change notification settings - Fork 8.1k
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
[SECURITY] add telemetry on authentication type #119371
Conversation
x-pack/plugins/security/public/nav_control/nav_control_service.tsx
Outdated
Show resolved
Hide resolved
x-pack/plugins/security/server/routes/telemetry/authentication_type.ts
Outdated
Show resolved
Hide resolved
x-pack/plugins/security/public/nav_control/nav_control_service.tsx
Outdated
Show resolved
Hide resolved
Pinging @elastic/kibana-security (Team:Security) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice job on this, a weird problem with a not-so-straightforward solution. A few nits below, main thing is I am concerned we are not recording all of the data that we need.
x-pack/plugins/security/public/authentication/logout/logout_app.ts
Outdated
Show resolved
Hide resolved
x-pack/plugins/security/server/routes/telemetry/authentication_type.ts
Outdated
Show resolved
Hide resolved
x-pack/plugins/security/server/routes/telemetry/authentication_type.ts
Outdated
Show resolved
Hide resolved
x-pack/plugins/security/server/routes/telemetry/authentication_type.ts
Outdated
Show resolved
Hide resolved
oldAuthType !== authUser?.authentication_type) | ||
) { | ||
usageCounter.incrementCounter({ | ||
counterName: authUser?.authentication_type, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The source issue (#117517) suggests recording more data points:
If an interactive session is detected, then we want to record the following from the
AuthenticatedUser
model:
authentication_realm.type
lookup_realm.type
authentication_provider.type
authentication_type
I might not be in the loop though. Did you intentionally leave the the other ones out, or was that an oversight?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not even sure, let's talk to @legrego about it when he is back. I will put back the PR in progress to avoid slack/notification.
💛 Build succeeded, but was flaky
Metrics [docs]Module Count
Page load bundle
History
To update your PR or re-run it, just comment with: cc @XavierM |
this.securityFeaturesSubscription = this.securityLicense.features$.subscribe( | ||
({ allowRbac }) => { | ||
if (allowRbac) { | ||
getCurrentUser().then(() => this.recordAuthTypeUsageCollection(http)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do we do in the event of a promise rejection? I think it's fine to ignore it, but we probably want to explicitly ignore it with a .catch
block.
oldAuthType !== authUser?.authentication_type) | ||
) { | ||
usageCounter.incrementCounter({ | ||
counterName: authUser?.authentication_type, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
authentication_type
won't tell us whether or not the user was authenticated via proxy. For that, I think we need the authentication_provider
from the user (users who authenticate via the http
provider are proxy-based)
Additionally, in order to satisfy this example, we need to extract the authentication scheme used (basic
, bearer
, ApiKey
, etc.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
authentication_type
won't tell us whether or not the user was authenticated via proxy. For that, I think we need theauthentication_provider
from the user (users who authenticate via thehttp
provider are proxy-based)
Ah, Xavier and I were discussing this offline --
I think where we were getting tripped up is that we were looking at the docs for Kibana's configurable authentication providers, and "http" is not an authentication provider according to the config.
However, in the implementation, "http" is an authentication provider: https://github.com/elastic/kibana/blob/6ecffcc57c9a5b0328257cd25b737140a8471dda/x-pack/plugins/security/server/authentication/providers/http.ts
Additionally, in order to satisfy this example, we need to extract the authentication scheme used (
basic
,bearer
,ApiKey
, etc.)
Ah, so it looks like the scheme is not stored in the AuthenticatedUser
, so we'll have to grab it from the request
object by parsing the authorization header:
const authorizationHeader = HTTPAuthorizationHeader.parseFromRequest(request); | |
if (authorizationHeader == null) { | |
this.logger.debug('Authorization header is not presented.'); | |
return AuthenticationResult.notHandled(); | |
} | |
if (!this.supportedSchemes.has(authorizationHeader.scheme.toLowerCase())) { | |
this.logger.debug(`Unsupported authentication scheme: ${authorizationHeader.scheme}`); | |
return AuthenticationResult.notHandled(); | |
} |
I was wondering if we could combine all the info we need into a single string value so we can still use the Core usage collector for this, but it sounds like we might want to be able to analyze these things separately. So maybe that's not a good idea, WDYT?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was wondering if we could combine all the info we need into a single string value so we can still use the Core usage collector for this, but it sounds like we might want to be able to analyze these things separately. So maybe that's not a good idea, WDYT?
I think it depends™️. If we constrain the schemes to Basic
, Bearer
, ApiKey
, and Custom
, and only report for the http
provider, then we could accomplish this using the Core usage collector if we were comfortable using 4 distinct objects (one for each scheme). If that's asking too much of the usage collector, or if we feel that's too limiting for potential future use-cases, then we might want to move forward with a bespoke implementation.
My gut feeling is that the Core usage collector may be too limiting. We wouldn't be able to add any more information to this in the future, and we'd likely need to do something custom for the next authentication data point we want to collect. I'm also cognizant that we may never need this flexibility, but I suspect we will.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also recently heard a question about how to measure Daily Active Users (DAU), which we don't have a good way to do right now.
We currently have 7 auth providers in Kibana (not including the "http" provider). Are we interested in comparing usage of these?
We could define our own saved object type with separate counters like this:
{
authLoginUsage: {
providerTypes: {
basic: number;
token: number;
saml: number;
oidc: number;
kerberos: number;
pki: number;
anonymous: number;
total: number;
},
realmTypes: {
reserved: number;
native: number;
ldap: number;
activeDirectory: number;
pki: number;
file: number;
saml: number;
oidc: number;
kerberos: number;
total: number;
},
httpAuthSchemes: {
basic: number;
bearer: number;
apiKey: number;
custom: number;
total: number;
}
}
However, we would lose some fidelity here because we don't know which providers were used with which realms.
Also, I like how the Core usage collector bins these into separate days so we can measure how these things change over time.
If we don't really need to know what realms are being used, I'm leaning towards suggesting that we define two different Core usage counters:
- Auth providers types used (including HTTP):
(Note: I edited
{ "counterName": "basic" | "token" | "saml" | "oidc" | "kerberos" | "pki" | "anonymous" | "http", "counterType": "SecurityAuthProviderType", }
counterName
above according to [SECURITY] add telemetry on authentication type #119371 (comment)) - HTTP auth schemes used:
{ "counterName": "basic" | "bearer" | "apiKey" | "custom", "counterType": "SecurityAuthHttpScheme", }
If the user is authenticating using an HTTP header (e.g., sessionless), we'd record both metrics. Otherwise, we'd record only the auth provider type.
This has a few advantages, namely:
- The implementation is almost done, just need a few tweaks
- We get metrics binned on a daily basis for free
- Easy to visualize comparisons like the example above without adding runtime fields
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we don't really need to know what realms are being used, I'm leaning towards suggesting that we define two different Core usage counters
This approach looks reasonable to me!
If the user is authenticating using an HTTP header (e.g., sessionless), we'd record both metrics. Otherwise, we'd record only the auth provider type
This is true only if we expand SecurityAuthProviderType
to include the http
pseudo-provider as a distinct counterName
. If you authenticate to Kibana using an Authorization
header, then you will always go through the http
provider, regardless of what type of credentials you end up providing.
This statement might become less true with the introduction of header-based PKI auth (to support PKI on ESS), but we can cross that bridge when we get there.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried to analyze what combinations of providers, realms and HTTP headers would give us more insight into how Kibana's authentication subsystem is used and ended up with two different lists: minimal and verbose.
It seems we haven't discussed setup when Kibana is used in conjunction with the custom Elasticsearch realms, especially via HTTP authentication. I included counters for these setups too.
I know it's a lot of counters and I still need to check if it's easy to consume this type of data, but I wanted to check with you first if there was reason to not pursue this option initially @jportner @legrego ?
Minimal (19 counters, excluded least probable and combined least useful):
Provider (Kibana) | Realm (Elasticsearch) | Usage Counter |
---|---|---|
Basic | Native/File/AD/LDAP/Reserved | Basic |
Basic | Custom | Custom |
Token | Native/File/AD/LDAP/Reserved | Token |
Token | Custom | Token_Custom |
SAML | SAML | SAML |
OIDC | OIDC | OIDC |
Kerberos | Kerberos | Kerberos |
PKI | PKI | PKI |
Anonymous | Native/File/AD/LDAP/Reserved | Anonymous |
Anonymous | Anonymous | Anonymous_PLEASE_NO |
Anonymous | Custom | Anonymous_Custom |
Anonymous | ApiKey | Anonymous_ApiKey |
HTTP Basic | Native/File/AD/LDAP/Reserved | HTTP_Basic |
HTTP Basic | Custom | HTTP_Basic_Custom |
HTTP Bearer | SAML/OIDC/Kerberos/PKI | HTTP_Bearer |
HTTP Bearer | Custom | HTTP_Bearer_Custom |
HTTP ApiKey | ApiKey | HTTP_ApiKey |
HTTP Custom | JWT | HTTP_Custom_JWT |
HTTP Custom | * | HTTP_Custom |
Verbose (42 counters, almost all possible combinations):
Provider (Kibana) | Realm (Elasticsearch) | Usage Counter |
---|---|---|
Basic | Native | Native |
Basic | File | File |
Basic | LDAP | LDAP |
Basic | AD | AD |
Basic | Reserved | Reserved |
Basic | Custom | Custom |
Token | Native | Token_Native |
Token | File | Token_File |
Token | LDAP | Token_LDAP |
Token | AD | Token_AD |
Token | Reserved | Token_Reserved |
Token | Custom | Token_Custom |
SAML | SAML | SAML |
SAML | Custom | SAML_Custom |
OIDC | OIDC | OIDC |
OIDC | Custom | OIDC_Custom |
Kerberos | Kerberos | Kerberos |
Kerberos | Custom | Kerberos_Custom |
PKI | PKI | PKI |
PKI | Custom | PKI_Custom |
Anonymous | Native | Anonymous_Native |
Anonymous | File | Anonymous_File |
Anonymous | LDAP | Anonymous_LDAP |
Anonymous | AD | Anonymous_AD |
Anonymous | Reserved | Anonymous_Reserved |
Anonymous | Anonymous | Anonymous_PLEASE_NO |
Anonymous | Custom | Anonymous_Custom |
Anonymous | ApiKey | Anonymous_ApiKey |
HTTP Basic | Native | HTTP_Basic_Native |
HTTP Basic | File | HTTP_Basic_File |
HTTP Basic | LDAP | HTTP_Basic_LDAP |
HTTP Basic | AD | HTTP_Basic_AD |
HTTP Basic | Reserved | HTTP_Basic_Reserved |
HTTP Basic | Custom | HTTP_Basic_Custom |
HTTP Bearer | SAML | HTTP_Bearer_SAML |
HTTP Bearer | OIDC | HTTP_Bearer_OIDC |
HTTP Bearer | Kerberos | HTTP_Bearer_Kerberos |
HTTP Bearer | PKI | HTTP_Bearer_PKI |
HTTP Bearer | Custom | HTTP_Bearer_Custom |
HTTP ApiKey | ApiKey | HTTP_ApiKey |
HTTP Custom | JWT | HTTP_Custom_JWT |
HTTP Custom | * | HTTP_Custom |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@azasypkin thanks for putting these tables together.
It seems we haven't discussed setup when Kibana is used in conjunction with the custom Elasticsearch realms, especially via HTTP authentication. I included counters for these setups too.
Great idea!
I know it's a lot of counters and I still need to check if it's easy to consume this type of data, but I wanted to check with you first if there was reason to not pursue this option initially
If the telemetry team is OK with the number of proposed counters, then I don't have any concerns with the expanded set.
Do you think we would get a lot of benefit from reporting basic
and token
auth providers under different counters? Could we report those under the same set of counters, since each cluster can only run either basic
or token
? From a metrics perspective, we can still detect how many clusters are choosing token
/`basic
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you think we would get a lot of benefit from reporting basic and token auth providers under different counters? Could we report those under the same set of counters, since each cluster can only run either basic or token?
Yeah, it's a good point, I always forget that they cannot be used together (and we consider merging them in the future too). I agree, we can combine these counters.
If the telemetry team is OK with the number of proposed counters, then I don't have any concerns with the expanded set.
I'll check with the telemetry team!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMO, I don't think the verbose approach is problematic at all... Especially bearing in mind that one instance of Kibana will use just a few of those.
I just wish I had completed #121992 by 8.2 so you could leverage it instead for this use case. Unfortunately, it'll slip to 8.3.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Summary
Resolves: #117517
To Verify
Checklist