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

emit user_origin for local login event #52124

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

flyinghermit
Copy link
Contributor

@flyinghermit flyinghermit commented Feb 13, 2025

As part of Extend user activity report events with Identity events we want to emit user origin in user login event to distinguish user originated from Identity Governance related integration. This PR updates local user login event to include user_origin value and have them emitted in the UserActivityRecord and the UserLogin event.

To pass the user origin value to the audit and usage event, new user_login field has been added to UserMetadata type.
The UserMetadata is included in many user related audit event, including UserLogin type that is emitted during local login. We set the user_login value only for the UserLogin event.

The origin label of the user resource metadata teleport.dev/origin is used to retrieve the origin value. If the label is not set, then we fall back to user type, which can be local or sso.

changelog: Updates local user login audit event to include user_origin field.

Part of https://github.com/gravitational/teleport.e/issues/5946

@flyinghermit flyinghermit marked this pull request as ready for review February 13, 2025 17:02
@@ -271,6 +271,11 @@ func (r *Reporter) run(ctx context.Context) {

return record
}
userRecordWithOrigin := func(userName string, v1AlphaUserKind prehogv1alpha.UserKind, v1AlphaUserOrigin prehogv1alpha.UserOrigin) *prehogv1.UserActivityRecord {
record := userRecord(userName, v1AlphaUserKind)
record.UserOrigin = prehogv1.UserOrigin(v1AlphaUserOrigin)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Casting enum types here and below. I've put a note on the proto definition to keep the enum values in sync. Open for suggestion to implement explicit conversion.

@@ -161,7 +168,8 @@ func (a *Server) emitAuthAuditEvent(ctx context.Context, props authAuditProps) e
Success: true,
},
UserMetadata: apievents.UserMetadata{
User: props.username,
User: props.username,
UserOrigin: props.userOrigin,
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The integer value will be reflected in the UI audit event. Not sold out on the alternative to use string field for audit event and the use int for the usage event. Open for suggestions.

I noticed we emit integer value for user_kind field.

@@ -136,6 +141,7 @@ func (a *Server) authenticateUserLogin(ctx context.Context, req authclient.Authe
clientMetadata: req.ClientMetadata,
mfaDevice: mfaDev,
checker: checker,
userOrigin: userOrigin,
Copy link
Contributor

@smallinsky smallinsky Feb 14, 2025

Choose a reason for hiding this comment

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

Is it possible to emit userOrigin on failure?

a.emitAuthAuditEven reused is invoked in multiple places, but right now the userOrigin is only set here in the successful flow.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not possible, only successful attempts are passed to the usage reporter. See https://github.com/gravitational/teleport/blob/master/lib/usagereporter/teleport/audit.go#L62C2-L67C1.

Comment on lines +116 to +119
userOrigin := apievents.UserOriginFromOriginLabel(user.Origin())
if userOrigin == apievents.UserOrigin_USER_ORIGIN_UNSPECIFIED {
userOrigin = apievents.UserOriginFromUserType(user.GetUserType())
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
userOrigin := apievents.UserOriginFromOriginLabel(user.Origin())
if userOrigin == apievents.UserOrigin_USER_ORIGIN_UNSPECIFIED {
userOrigin = apievents.UserOriginFromUserType(user.GetUserType())
}
userOrigin := getUserOrgin(user)

or even

  emitAuthAuditEvent(ctx, authAuditProps{
  ... 
   userOrigin: getUserOrgin(user),
  ... 
 }

@@ -271,6 +271,17 @@ func (r *Reporter) run(ctx context.Context) {

return record
}
userRecordWithOrigin := func(userName string, v1AlphaUserKind prehogv1alpha.UserKind, v1AlphaUserOrigin prehogv1alpha.UserOrigin) *prehogv1.UserActivityRecord {
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
userRecordWithOrigin := func(userName string, v1AlphaUserKind prehogv1alpha.UserKind, v1AlphaUserOrigin prehogv1alpha.UserOrigin) *prehogv1.UserActivityRecord {
userRecordWithOrigin := func(userName string, kind prehogv1alpha.UserKind, origin prehogv1alpha.UserOrigin) *prehogv1.UserActivityRecord {

Copy link
Contributor Author

@flyinghermit flyinghermit Feb 15, 2025

Choose a reason for hiding this comment

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

Agree the naming could be better but if you see line above, the userRecordWithOrigin just wraps the userRecord function with origin label. And the userRecord uses the same function param names v1AlphaUserKind. So imo its rather ideal to reuse the same param names rather than having two different terminology within a same method.

Comment on lines +275 to +283
record := userRecord(userName, v1AlphaUserKind)
if v1AlphaUserOrigin == prehogv1alpha.UserOrigin_USER_ORIGIN_UNSPECIFIED {
// Ignore unspecified value cause the request may be coming from an
// older auth that does not process user_origin.
return record
}
// Allow overriding origin value with a new value.
record.UserOrigin = prehogv1.UserOrigin(v1AlphaUserOrigin)
return record
Copy link
Contributor

Choose a reason for hiding this comment

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

Why not just:

Suggested change
record := userRecord(userName, v1AlphaUserKind)
if v1AlphaUserOrigin == prehogv1alpha.UserOrigin_USER_ORIGIN_UNSPECIFIED {
// Ignore unspecified value cause the request may be coming from an
// older auth that does not process user_origin.
return record
}
// Allow overriding origin value with a new value.
record.UserOrigin = prehogv1.UserOrigin(v1AlphaUserOrigin)
return record
record := userRecord(userName, v1AlphaUserKind)
record.UserOrigin = prehogv1.UserOrigin(v1AlphaUserOrigin)
return record

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Because an older auth might override correct origin value set by the latest auth so the skipping USER_ORIGIN_UNSPECIFIED saves us from that.

}
}

// UserOriginFromUserType converts API origin label value to UserOrigin.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
// UserOriginFromUserType converts API origin label value to UserOrigin.
// UserOriginFromOriginLabel converts API origin label value to UserOrigin.

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.

2 participants