Duo Workflow composite identity onboarding

What does this MR do and why?

Summary by Duo

This merge request creates database columns to store service account and OAuth application information for Duo Workflow, adds controllers to manage these settings, and implements the core functionality to connect and disconnect from the service. The code includes a migration to update the database schema, new models and services to handle the onboarding process, and a library to check if Duo Workflow is enabled, connected, and available. The implementation follows a similar pattern to the existing Amazon Q integration, creating a service account with composite identity enforcement and an OAuth application with specific scopes. The feature is protected by license checks and can be toggled on/off by administrators.

References

Please include cross links to any resources that are relevant to this MR. This will give reviewers and future readers helpful context to give an efficient review of the changes introduced.

MR acceptance checklist

Please evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.

Screenshots or screen recordings

Screenshots are required for UI changes, and strongly recommended for all other merge requests.

Before After

How to set up and validate locally

Numbered steps to set up and validate the change are strongly suggested.

  1. To onboard Duo Workflow with composite identity, execute in rails console

    # get instance admin user -> admin_user
    # select organization or default
    organization_id = Organizations::Organization::DEFAULT_ORGANIZATION_ID
    organization = Organizations::Organization.find_by_id(organization_id)
    service = Ai::DuoWorkflows::OnboardingService.new(current_user: admin_user, organization: organization)
    service.execute
  2. OR execute the below request as an admin user

    POST /admin/ai/duo_workflow_settings HTTP/1.1
    Host: gdk.test:3000
    Authorization: 
  3. Check ai settings table for updated service account and oauth app

    -> ::Ai::Setting.instance.duo_workflow_oauth_application_id
    -> ::Ai::Setting.instance.duo_workflow_service_account_user_id

Related to #515309 (closed)

Database Query

Create oauth app
   TRANSACTION (0.1ms)  BEGIN /*application:console,db_config_database:gitlabhq_development,db_config_name:main,console_username:surabhi,line:/ee/app/services/ai/duo_workflows/onboarding_service.rb:85:in `find_or_create_oauth_app!'*/
  Doorkeeper::Application Exists? (0.8ms)  SELECT 1 AS one FROM "oauth_applications" WHERE "oauth_applications"."uid" = '$REDACTED' LIMIT 1 /*application:console,db_config_database:gitlabhq_development,db_config_name:main,console_username:surabhi,line:/ee/app/services/ai/duo_workflows/onboarding_service.rb:85:in `find_or_create_oauth_app!'*/
  Doorkeeper::Application Create (0.8ms)  INSERT INTO "oauth_applications" ("name", "uid", "secret", "redirect_uri", "scopes", "created_at", "updated_at", "confidential") VALUES ('GitLab Duo Workflow Composite OAuth Application', '$REDACTED', '$REDACTED', 'http://gdk.test:3000/', 'ai_workflows user:*', '2025-03-17 11:21:03.425657', '2025-03-17 11:21:03.425657', FALSE) RETURNING "id" /*application:console,db_config_database:gitlabhq_development,db_config_name:main,console_username:surabhi,line:/ee/app/services/ai/duo_workflows/onboarding_service.rb:85:in `find_or_create_oauth_app!'*/
  TRANSACTION (0.1ms)  COMMIT /*application:console,db_config_database:gitlabhq_development,db_config_name:main,console_username:surabhi,line:/lib/gitlab/database.rb:433:in `commit'*/
Create service account
 TRANSACTION (0.1ms)  BEGIN /*application:console,db_config_database:gitlabhq_development,db_config_name:main,console_username:surabhi,line:/app/services/users/create_service.rb:36:in `create_user'*/
  User Exists? (0.8ms)  SELECT 1 AS one FROM "users" WHERE "users"."email" = 'service_account_03cec3b8b4fa6c10d7d9f350b931b3e7@noreply.gdk.test' LIMIT 1 /*application:console,db_config_database:gitlabhq_development,db_config_name:main,console_username:surabhi,line:/app/services/users/create_service.rb:36:in `create_user'*/
  Route Exists? (1.9ms)  SELECT 1 AS one FROM "routes" WHERE LOWER("routes"."path") = LOWER('service_account_03cec3b8b4fa6c10d7d9f350b931b3e7') LIMIT 1 /*application:console,db_config_database:gitlabhq_development,db_config_name:main,console_username:surabhi,line:/app/services/users/create_service.rb:36:in `create_user'*/
  Feature::FlipperGate Pluck (0.1ms)  SELECT "feature_gates"."key", "feature_gates"."value" FROM "feature_gates" WHERE "feature_gates"."feature_key" = 'change_namespace_default_role_for_pipeline_variables' /*application:console,db_config_database:gitlabhq_development,db_config_name:main,console_username:surabhi,line:/lib/feature.rb:324:in `block in current_feature_value'*/
  Organizations::Organization Load (0.1ms)  SELECT "organizations".* FROM "organizations" WHERE "organizations"."id" = 1 LIMIT 1 /*application:console,db_config_database:gitlabhq_development,db_config_name:main,console_username:surabhi,line:/app/services/users/create_service.rb:36:in `create_user'*/
  Organizations::OrganizationUser Exists? (1.0ms)  SELECT 1 AS one FROM "organization_users" WHERE "organization_users"."user_id" IS NULL AND "organization_users"."organization_id" = 1 LIMIT 1 /*application:console,db_config_database:gitlabhq_development,db_config_name:main,console_username:surabhi,line:/app/services/users/create_service.rb:36:in `create_user'*/
  ProjectSetting Exists? (1.3ms)  SELECT 1 AS one FROM "project_settings" WHERE "project_settings"."pages_unique_domain" = 'service_account_03cec3b8b4fa6c10d7d9f350b931b3e7' LIMIT 1 /*application:console,db_config_database:gitlabhq_development,db_config_name:main,console_username:surabhi,line:/app/models/project_setting.rb:55:in `unique_domain_exists?'*/
  Feature::FlipperGate Pluck (0.1ms)  SELECT "feature_gates"."key", "feature_gates"."value" FROM "feature_gates" WHERE "feature_gates"."feature_key" = 'optional_personal_namespace' /*application:console,db_config_database:gitlabhq_development,db_config_name:main,console_username:surabhi,line:/lib/feature.rb:324:in `block in current_feature_value'*/
  Email Exists? (0.1ms)  SELECT 1 AS one FROM "emails" WHERE "emails"."user_id" IS NOT NULL AND "emails"."email" = 'service_account_03cec3b8b4fa6c10d7d9f350b931b3e7@noreply.gdk.test' LIMIT 1 /*application:console,db_config_database:gitlabhq_development,db_config_name:main,console_username:surabhi,line:/app/models/user.rb:1315:in `unique_email'*/
  User Load (1.4ms)  SELECT "users"."id", "users"."email", "users"."encrypted_password", "users"."reset_password_token", "users"."reset_password_sent_at", "users"."remember_created_at", "users"."sign_in_count", "users"."current_sign_in_at", "users"."last_sign_in_at", "users"."current_sign_in_ip", "users"."last_sign_in_ip", "users"."created_at", "users"."updated_at", "users"."name", "users"."admin", "users"."projects_limit", "users"."failed_attempts", "users"."locked_at", "users"."username", "users"."can_create_group", "users"."can_create_team", "users"."state", "users"."color_scheme_id", "users"."password_expires_at", "users"."created_by_id", "users"."last_credential_check_at", "users"."avatar", "users"."confirmation_token", "users"."confirmed_at", "users"."confirmation_sent_at", "users"."unconfirmed_email", "users"."hide_no_ssh_key", "users"."admin_email_unsubscribed_at", "users"."notification_email", "users"."hide_no_password", "users"."password_automatically_set", "users"."encrypted_otp_secret", "users"."encrypted_otp_secret_iv", "users"."encrypted_otp_secret_salt", "users"."otp_required_for_login", "users"."otp_backup_codes", "users"."public_email", "users"."dashboard", "users"."project_view", "users"."consumed_timestep", "users"."layout", "users"."hide_project_limit", "users"."note", "users"."unlock_token", "users"."otp_grace_period_started_at", "users"."external", "users"."incoming_email_token", "users"."auditor", "users"."require_two_factor_authentication_from_group", "users"."two_factor_grace_period", "users"."last_activity_on", "users"."notified_of_own_activity", "users"."preferred_language", "users"."theme_id", "users"."accepted_term_id", "users"."feed_token", "users"."private_profile", "users"."roadmap_layout", "users"."include_private_contributions", "users"."commit_email", "users"."group_view", "users"."managing_group_id", "users"."first_name", "users"."last_name", "users"."static_object_token", "users"."role", "users"."user_type", "users"."static_object_token_encrypted", "users"."otp_secret_expires_at", "users"."onboarding_in_progress", "users"."color_mode_id", "users"."composite_identity_enforced" FROM "users" WHERE "users"."incoming_email_token" = '$REDACTED' LIMIT 1 /*application:console,db_config_database:gitlabhq_development,db_config_name:main,console_username:surabhi,line:/lib/authn/token_field/insecure.rb:7:in `find_token_authenticatable'*/
  User Create (5.4ms)  INSERT INTO "users" ("email", "created_at", "updated_at", "name", "projects_limit", "username", "can_create_group", "can_create_team", "state", "created_by_id", "confirmed_at", "project_view", "external", "incoming_email_token", "preferred_language", "theme_id", "private_profile", "user_type", "composite_identity_enforced") VALUES ('service_account_03cec3b8b4fa6c10d7d9f350b931b3e7@noreply.gdk.test', '2025-03-17 11:21:03.024282', '2025-03-17 11:21:03.024282', 'Duo Workflow Service', 0, 'service_account_03cec3b8b4fa6c10d7d9f350b931b3e7', FALSE, FALSE, 'active', 1, '2025-03-17 11:21:02.770145', 2, TRUE, '$REDACTED', 'en', 3, TRUE, 13, TRUE) RETURNING "id" /*application:console,db_config_database:gitlabhq_development,db_config_name:main,console_username:surabhi,line:/lib/gitlab/database/query_analyzers/prevent_cross_database_modification.rb:29:in `temporary_ignore_tables_in_transaction'*/
  Feature::FlipperGate Pluck (0.2ms)  SELECT "feature_gates"."key", "feature_gates"."value" FROM "feature_gates" WHERE "feature_gates"."feature_key" = 'personal_snippet_reference_filters' /*application:console,db_config_database:gitlabhq_development,db_config_name:main,console_username:surabhi,line:/lib/feature.rb:324:in `block in current_feature_value'*/
  Namespaces::UserNamespace Create (9.9ms)  INSERT INTO "namespaces" ("name", "path", "owner_id", "created_at", "updated_at", "description_html", "cached_markdown_version", "organization_id") VALUES ('Duo Workflow Service', 'service_account_03cec3b8b4fa6c10d7d9f350b931b3e7', 93, '2025-03-17 11:21:03.065129', '2025-03-17 11:21:03.065129', '', 2162688, 1) RETURNING "id" /*application:console,db_config_database:gitlabhq_development,db_config_name:main,console_username:surabhi,line:/lib/gitlab/database/query_analyzers/prevent_cross_database_modification.rb:29:in `temporary_ignore_tables_in_transaction'*/
  Route Create (2.3ms)  INSERT INTO "routes" ("source_id", "source_type", "path", "created_at", "updated_at", "name", "namespace_id") VALUES (151, 'Namespace', 'service_account_03cec3b8b4fa6c10d7d9f350b931b3e7', '2025-03-17 11:21:03.147849', '2025-03-17 11:21:03.147849', 'Duo Workflow Service', 151) RETURNING "id" /*application:console,db_config_database:gitlabhq_development,db_config_name:main,console_username:surabhi,line:/lib/gitlab/database/query_analyzers/prevent_cross_database_modification.rb:29:in `temporary_ignore_tables_in_transaction'*/
  RedirectRoute Delete All (1.4ms)  DELETE FROM "redirect_routes" WHERE (LOWER(redirect_routes.path) = LOWER('service_account_03cec3b8b4fa6c10d7d9f350b931b3e7') OR LOWER(redirect_routes.path) LIKE LOWER('service\_account\_03cec3b8b4fa6c10d7d9f350b931b3e7/%')) /*application:console,db_config_database:gitlabhq_development,db_config_name:main,console_username:surabhi,line:/app/models/route.rb:40:in `delete_conflicting_redirects'*/
   (0.1ms)  SHOW LOCK_TIMEOUT /*application:console,db_config_database:gitlabhq_development,db_config_name:main,console_username:surabhi,line:/lib/gitlab/database/transaction/settings.rb:36:in `get'*/
  SQL (0.2ms)  SET LOCAL LOCK_TIMEOUT = '1000ms' /*application:console,db_config_database:gitlabhq_development,db_config_name:main,console_username:surabhi,line:/lib/gitlab/database/transaction/settings.rb:30:in `set'*/
  Namespace Load (0.2ms)  SELECT "namespaces"."id", "namespaces"."name", "namespaces"."path", "namespaces"."owner_id", "namespaces"."created_at", "namespaces"."updated_at", "namespaces"."type", "namespaces"."description", "namespaces"."avatar", "namespaces"."membership_lock", "namespaces"."share_with_group_lock", "namespaces"."visibility_level", "namespaces"."request_access_enabled", "namespaces"."ldap_sync_status", "namespaces"."ldap_sync_error", "namespaces"."ldap_sync_last_update_at", "namespaces"."ldap_sync_last_successful_update_at", "namespaces"."ldap_sync_last_sync_at", "namespaces"."description_html", "namespaces"."lfs_enabled", "namespaces"."parent_id", "namespaces"."shared_runners_minutes_limit", "namespaces"."repository_size_limit", "namespaces"."require_two_factor_authentication", "namespaces"."two_factor_grace_period", "namespaces"."cached_markdown_version", "namespaces"."project_creation_level", "namespaces"."runners_token", "namespaces"."file_template_project_id", "namespaces"."saml_discovery_token", "namespaces"."runners_token_encrypted", "namespaces"."custom_project_templates_group_id", "namespaces"."auto_devops_enabled", "namespaces"."extra_shared_runners_minutes_limit", "namespaces"."last_ci_minutes_notification_at", "namespaces"."last_ci_minutes_usage_notification_level", "namespaces"."subgroup_creation_level", "namespaces"."max_pages_size", "namespaces"."max_artifacts_size", "namespaces"."mentions_disabled", "namespaces"."default_branch_protection", "namespaces"."max_personal_access_token_lifetime", "namespaces"."push_rule_id", "namespaces"."shared_runners_enabled", "namespaces"."allow_descendants_override_disabled_shared_runners", "namespaces"."traversal_ids", "namespaces"."organization_id" FROM "namespaces" WHERE "namespaces"."id" = 151 LIMIT 1 FOR NO KEY UPDATE /*application:console,db_config_database:gitlabhq_development,db_config_name:main,console_username:surabhi,line:/app/models/namespace/traversal_hierarchy.rb:130:in `block in acquire_locks'*/
  SQL (0.0ms)  SET LOCAL LOCK_TIMEOUT = '0' /*application:console,db_config_database:gitlabhq_development,db_config_name:main,console_username:surabhi,line:/lib/gitlab/database/transaction/settings.rb:30:in `set'*/
  SQL (3.5ms)            UPDATE namespaces
          SET traversal_ids = cte.traversal_ids
          FROM (WITH RECURSIVE cte(id, traversal_ids, cycle) AS (
  VALUES(151::bigint, ARRAY[151]::bigint[], false)
UNION ALL
  SELECT n.id, cte.traversal_ids || n.id::bigint, n.id = ANY(cte.traversal_ids)
  FROM namespaces n, cte
  WHERE n.parent_id = cte.id AND NOT cycle
)
SELECT id, traversal_ids FROM cte
) as cte
          WHERE namespaces.id = cte.id
            AND namespaces.traversal_ids::bigint[] <> cte.traversal_ids
 /*application:console,db_config_database:gitlabhq_development,db_config_name:main,console_username:surabhi,line:/app/models/namespace/traversal_hierarchy.rb:107:in `block in sync_traversal_ids_tree!'*/
  NamespaceSetting Create (2.0ms)  INSERT INTO "namespace_settings" ("created_at", "updated_at", "namespace_id") VALUES ('2025-03-17 11:21:03.166965', '2025-03-17 11:21:03.166965', 151) RETURNING "namespace_id" /*application:console,db_config_database:gitlabhq_development,db_config_name:main,console_username:surabhi,line:/lib/gitlab/database/query_analyzers/prevent_cross_database_modification.rb:29:in `temporary_ignore_tables_in_transaction'*/
  Namespace::Detail Load (0.1ms)  SELECT "namespace_details".* FROM "namespace_details" WHERE "namespace_details"."namespace_id" = 151 LIMIT 1 /*application:console,db_config_database:gitlabhq_development,db_config_name:main,console_username:surabhi,line:/app/models/namespace.rb:885:in `reload_namespace_details'*/
  Namespace::Detail Load (0.1ms)  SELECT "namespace_details".* FROM "namespace_details" WHERE "namespace_details"."namespace_id" = 151 LIMIT 1 /*application:console,db_config_database:gitlabhq_development,db_config_name:main,console_username:surabhi,line:/app/models/namespace.rb:887:in `reload_namespace_details'*/
  Organizations::OrganizationUser Create (1.1ms)  INSERT INTO "organization_users" ("organization_id", "user_id", "created_at", "updated_at") VALUES (1, 93, '2025-03-17 11:21:03.175884', '2025-03-17 11:21:03.175884') RETURNING "id" /*application:console,db_config_database:gitlabhq_development,db_config_name:main,console_username:surabhi,line:/lib/gitlab/database/query_analyzers/prevent_cross_database_modification.rb:29:in `temporary_ignore_tables_in_transaction'*/
  UserDetail Create (2.0ms)  INSERT INTO "user_details" ("user_id") VALUES (93) RETURNING "user_id" /*application:console,db_config_database:gitlabhq_development,db_config_name:main,console_username:surabhi,line:/lib/gitlab/database/query_analyzers/prevent_cross_database_modification.rb:29:in `temporary_ignore_tables_in_transaction'*/
  Email Load (0.1ms)  SELECT "emails".* FROM "emails" WHERE "emails"."user_id" = 93 AND "emails"."email" = 'service_account_03cec3b8b4fa6c10d7d9f350b931b3e7@noreply.gdk.test' LIMIT 1 /*application:console,db_config_database:gitlabhq_development,db_config_name:main,console_username:surabhi,line:/app/models/user.rb:390:in `block in <class:User>'*/
  Email Exists? (0.1ms)  SELECT 1 AS one FROM "emails" WHERE "emails"."email" = 'service_account_03cec3b8b4fa6c10d7d9f350b931b3e7@noreply.gdk.test' LIMIT 1 /*application:console,db_config_database:gitlabhq_development,db_config_name:main,console_username:surabhi,line:/app/models/concerns/cross_database_modification.rb:91:in `block in transaction'*/
  User Exists? (0.1ms)  SELECT 1 AS one FROM "users" WHERE "users"."email" = 'service_account_03cec3b8b4fa6c10d7d9f350b931b3e7@noreply.gdk.test' AND "users"."id" != 93 LIMIT 1 /*application:console,db_config_database:gitlabhq_development,db_config_name:main,console_username:surabhi,line:/app/models/email.rb:58:in `primary_email_of_another_user?'*/
  Email Create (1.8ms)  INSERT INTO "emails" ("user_id", "email", "created_at", "updated_at", "confirmed_at", "detumbled_email") VALUES (93, 'service_account_03cec3b8b4fa6c10d7d9f350b931b3e7@noreply.gdk.test', '2025-03-17 11:21:03.190502', '2025-03-17 11:21:03.190502', '2025-03-17 11:21:02.770145', 'service_account_03cec3b8b4fa6c10d7d9f350b931b3e7@noreply.gdk.test') RETURNING "id" /*application:console,db_config_database:gitlabhq_development,db_config_name:main,console_username:surabhi,line:/app/models/concerns/cross_database_modification.rb:91:in `block in transaction'*/
  AuditEvent Create (3.7ms)  INSERT INTO "audit_events" ("author_id", "entity_id", "entity_type", "details", "author_name", "entity_path", "target_details", "created_at", "target_type", "target_id") VALUES (93, 93, 'User', '---
:add: email
:author_name: Duo Workflow Service
:target_type: Email
:event_name: email_created
:author_class: User
:target_id: 101
:target_details: unknown
:custom_message: Email created
:ip_address:
:entity_path: service_account_03cec3b8b4fa6c10d7d9f350b931b3e7
', 'Duo Workflow Service', 'service_account_03cec3b8b4fa6c10d7d9f350b931b3e7', 'unknown', '2025-03-17 11:21:03.284650', 'Email', 101) RETURNING "id" /*application:console,db_config_database:gitlabhq_development,db_config_name:main,console_username:surabhi,line:/lib/gitlab/audit/auditor.rb:191:in `log_to_database'*/
  User Load (0.2ms)  SELECT "users"."id", "users"."name", "users"."username", "users"."email" FROM "users" WHERE "users"."id" = 93 ORDER BY "users"."id" ASC LIMIT 1000 /*application:console,db_config_database:gitlabhq_development,db_config_name:main,console_username:surabhi,line:<internal:kernel>:187:in `loop'*/
  AuditEvents::UserAuditEvent Create (2.0ms)  INSERT INTO "user_audit_events" ("id", "created_at", "user_id", "author_id", "target_id", "event_name", "details", "author_name", "entity_path", "target_details", "target_type") VALUES (5925, '2025-03-17 11:21:03.284650', 93, 93, 101, 'email_created', '---
:add: email
:author_name: Duo Workflow Service
:target_type: Email
:event_name: email_created
:author_class: User
:target_id: 101
:target_details: unknown
:custom_message: Email created
:ip_address:
:entity_path: service_account_03cec3b8b4fa6c10d7d9f350b931b3e7
', 'Duo Workflow Service', 'service_account_03cec3b8b4fa6c10d7d9f350b931b3e7', 'unknown', 'Email') RETURNING "id" /*application:console,db_config_database:gitlabhq_development,db_config_name:main,console_username:surabhi,line:/lib/gitlab/audit/logging.rb:30:in `log_events'*/
  TRANSACTION (0.3ms)  COMMIT /*application:console,db_config_database:gitlabhq_development,db_config_name:main,console_username:surabhi,line:/lib/gitlab/database.rb:433:in `commit'*/
  Namespaces::UserNamespace Pluck (0.2ms)  SELECT "namespaces"."traversal_ids" FROM "namespaces" WHERE "namespaces"."type" = 'User' AND "namespaces"."id" = 151 LIMIT 1 /*application:console,db_config_database:gitlabhq_development,db_config_name:main,console_username:surabhi,line:/app/models/namespaces/traversal/linear.rb:234:in `set_traversal_ids'*/
  GpgKey Load (1.3ms)  SELECT "gpg_keys".* FROM "gpg_keys" WHERE "gpg_keys"."user_id" = 93 /*application:console,db_config_database:gitlabhq_development,db_config_name:main,console_username:surabhi,line:/app/models/user.rb:1357:in `update_invalid_gpg_signatures'*/
  User Load (0.3ms)  SELECT "users"."id", "users"."email", "users"."encrypted_password", "users"."reset_password_token", "users"."reset_password_sent_at", "users"."remember_created_at", "users"."sign_in_count", "users"."current_sign_in_at", "users"."last_sign_in_at", "users"."current_sign_in_ip", "users"."last_sign_in_ip", "users"."created_at", "users"."updated_at", "users"."name", "users"."admin", "users"."projects_limit", "users"."failed_attempts", "users"."locked_at", "users"."username", "users"."can_create_group", "users"."can_create_team", "users"."state", "users"."color_scheme_id", "users"."password_expires_at", "users"."created_by_id", "users"."last_credential_check_at", "users"."avatar", "users"."confirmation_token", "users"."confirmed_at", "users"."confirmation_sent_at", "users"."unconfirmed_email", "users"."hide_no_ssh_key", "users"."admin_email_unsubscribed_at", "users"."notification_email", "users"."hide_no_password", "users"."password_automatically_set", "users"."encrypted_otp_secret", "users"."encrypted_otp_secret_iv", "users"."encrypted_otp_secret_salt", "users"."otp_required_for_login", "users"."otp_backup_codes", "users"."public_email", "users"."dashboard", "users"."project_view", "users"."consumed_timestep", "users"."layout", "users"."hide_project_limit", "users"."note", "users"."unlock_token", "users"."otp_grace_period_started_at", "users"."external", "users"."incoming_email_token", "users"."auditor", "users"."require_two_factor_authentication_from_group", "users"."two_factor_grace_period", "users"."last_activity_on", "users"."notified_of_own_activity", "users"."preferred_language", "users"."theme_id", "users"."accepted_term_id", "users"."feed_token", "users"."private_profile", "users"."roadmap_layout", "users"."include_private_contributions", "users"."commit_email", "users"."group_view", "users"."managing_group_id", "users"."first_name", "users"."last_name", "users"."static_object_token", "users"."role", "users"."user_type", "users"."static_object_token_encrypted", "users"."otp_secret_expires_at", "users"."onboarding_in_progress", "users"."color_mode_id", "users"."composite_identity_enforced" FROM "users" WHERE "users"."id" = 93 ORDER BY "users"."id" ASC LIMIT 1000 /*application:console,db_config_database:gitlabhq_development,db_config_name:main,console_username:surabhi,line:<internal:kernel>:187:in `loop'*/
  Feature::FlipperGate Pluck (0.1ms)  SELECT "feature_gates"."key", "feature_gates"."value" FROM "feature_gates" WHERE "feature_gates"."feature_key" = 'audit_events_external_destination_streamer_consolidation_refactor' /*application:console,db_config_database:gitlabhq_development,db_config_name:main,console_username:surabhi,line:/lib/feature.rb:324:in `block in current_feature_value'*/
  AuditEvents::InstanceExternalAuditEventDestination Exists? (1.4ms)  SELECT 1 AS one FROM "audit_events_instance_external_audit_event_destinations" LIMIT 1 /*application:console,db_config_database:gitlabhq_development,db_config_name:main,console_username:surabhi,line:/ee/lib/audit_events/strategies/instance_external_destination_strategy.rb:8:in `streamable?'*/
  AuditEvents::Instance::GoogleCloudLoggingConfiguration Exists? (0.4ms)  SELECT 1 AS one FROM "audit_events_instance_google_cloud_logging_configurations" LIMIT 1 /*application:console,db_config_database:gitlabhq_development,db_config_name:main,console_username:surabhi,line:/ee/lib/audit_events/strategies/instance/google_cloud_logging_destination_strategy.rb:9:in `streamable?'*/
  AuditEvents::Instance::AmazonS3Configuration Exists? (0.4ms)  SELECT 1 AS one FROM "audit_events_instance_amazon_s3_configurations" LIMIT 1 /*application:console,db_config_database:gitlabhq_development,db_config_name:main,console_username:surabhi,line:/ee/lib/audit_events/strategies/instance/amazon_s3_destination_strategy.rb:9:in `streamable?'*/
  SystemHook Load (1.2ms)  SELECT "web_hooks".* FROM "web_hooks" WHERE "web_hooks"."type" = 'SystemHook' ORDER BY "web_hooks"."id" ASC LIMIT 1000 /*application:console,db_config_database:gitlabhq_development,db_config_name:main,console_username:surabhi,line:<internal:kernel>:187:in `loop'*/
  TRANSACTION (0.1ms)  BEGIN /*application:console,db_config_database:gitlabhq_development,db_config_name:main,console_username:surabhi,line:/lib/gitlab/audit/auditor.rb:191:in `log_to_database'*/
  AuditEvent Create (0.4ms)  INSERT INTO "audit_events" ("author_id", "entity_id", "entity_type", "details", "ip_address", "author_name", "entity_path", "target_details", "created_at", "target_type", "target_id") VALUES (1, 93, 'User', '---
:add: user
:registration_details:
  :id: 93
  :username: service_account_03cec3b8b4fa6c10d7d9f350b931b3e7
  :name: Duo Workflow Service
  :email: service_account_03cec3b8b4fa6c10d7d9f350b931b3e7@noreply.gdk.test
  :access_level: :regular
:event_name: user_created
:author_name: Administrator
:author_class: User
:target_id: 93
:target_type: User
:target_details: service_account_03cec3b8b4fa6c10d7d9f350b931b3e7
:custom_message: User service_account_03cec3b8b4fa6c10d7d9f350b931b3e7 created
:ip_address: $REDACTED
:entity_path: service_account_03cec3b8b4fa6c10d7d9f350b931b3e7
', '$REDACTED', 'Administrator', 'service_account_03cec3b8b4fa6c10d7d9f350b931b3e7', 'service_account_03cec3b8b4fa6c10d7d9f350b931b3e7', '2025-03-17 11:21:03.393157', 'User', 93) RETURNING "id" /*application:console,db_config_database:gitlabhq_development,db_config_name:main,console_username:surabhi,line:/lib/gitlab/audit/auditor.rb:191:in `log_to_database'*/
  TRANSACTION (0.1ms)  COMMIT /*application:console,db_config_database:gitlabhq_development,db_config_name:main,console_username:surabhi,line:/lib/gitlab/database.rb:433:in `commit'*/
  User Load (0.3ms)  SELECT "users"."id", "users"."name", "users"."username", "users"."email" FROM "users" WHERE "users"."id" IN (93, 1) ORDER BY "users"."id" ASC LIMIT 1000 /*application:console,db_config_database:gitlabhq_development,db_config_name:main,console_username:surabhi,line:<internal:kernel>:187:in `loop'*/
  TRANSACTION (0.0ms)  BEGIN /*application:console,db_config_database:gitlabhq_development,db_config_name:main,console_username:surabhi,line:/lib/gitlab/audit/logging.rb:30:in `log_events'*/
  AuditEvents::UserAuditEvent Create (0.7ms)  INSERT INTO "user_audit_events" ("id", "created_at", "user_id", "author_id", "target_id", "event_name", "details", "ip_address", "author_name", "entity_path", "target_details", "target_type") VALUES (5926, '2025-03-17 11:21:03.393157', 93, 1, 93, 'user_created', '---
:add: user
:registration_details:
  :id: 93
  :username: service_account_03cec3b8b4fa6c10d7d9f350b931b3e7
  :name: Duo Workflow Service
  :email: service_account_03cec3b8b4fa6c10d7d9f350b931b3e7@noreply.gdk.test
  :access_level: :regular
:event_name: user_created
:author_name: Administrator
:author_class: User
:target_id: 93
:target_type: User
:target_details: service_account_03cec3b8b4fa6c10d7d9f350b931b3e7
:custom_message: User service_account_03cec3b8b4fa6c10d7d9f350b931b3e7 created
:ip_address: $REDACTED
:entity_path: service_account_03cec3b8b4fa6c10d7d9f350b931b3e7
', '$REDACTED', 'Administrator', 'service_account_03cec3b8b4fa6c10d7d9f350b931b3e7', 'service_account_03cec3b8b4fa6c10d7d9f350b931b3e7', 'User') RETURNING "id" /*application:console,db_config_database:gitlabhq_development,db_config_name:main,console_username:surabhi,line:/lib/gitlab/audit/logging.rb:30:in `log_events'*/
TRANSACTION (0.1ms)  COMMIT /*application:console,db_config_database:gitlabhq_development,db_config_name:main,console_username:surabhi,line:/lib/gitlab/database.rb:433:in `commit'*/
Add ouath app and service account to ai settings
  TRANSACTION (0.0ms)  BEGIN /*application:console,db_config_database:gitlabhq_development,db_config_name:main,console_username:surabhi,line:/ee/app/models/ai/setting.rb:40:in `validates_singleton'*/
  Ai::Setting Count (0.2ms)  SELECT COUNT(*) FROM "ai_settings" /*application:console,db_config_database:gitlabhq_development,db_config_name:main,console_username:surabhi,line:/ee/app/models/ai/setting.rb:40:in `validates_singleton'*/
  Ai::Setting Load (0.1ms)  SELECT "ai_settings".* FROM "ai_settings" ORDER BY "ai_settings"."id" ASC LIMIT 1 /*application:console,db_config_database:gitlabhq_development,db_config_name:main,console_username:surabhi,line:/ee/app/models/ai/setting.rb:40:in `validates_singleton'*/
  Ai::Setting Update (0.6ms)  UPDATE "ai_settings" SET "updated_at" = '2025-03-17 11:21:03.428838', "duo_workflow_service_account_user_id" = 93, "duo_workflow_oauth_application_id" = 8 WHERE "ai_settings"."id" = 1 /*application:console,db_config_database:gitlabhq_development,db_config_name:main,console_username:surabhi,line:/ee/app/services/ai/duo_workflows/onboarding_service.rb:38:in `update_settings'*/
  TRANSACTION (0.1ms)  COMMIT /*application:console,db_config_database:gitlabhq_development,db_config_name:main,console_username:surabhi,line:/lib/gitlab/database.rb:433:in `commit'*/
Edited by Surabhi Suman

Merge request reports

Loading