diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md
index aba5ea4de71f4b333ebc9e00198478dd44b64748..a517f4bf6a13bc9173d9b74d361040ce25d18a50 100644
--- a/doc/api/graphql/reference/index.md
+++ b/doc/api/graphql/reference/index.md
@@ -3521,6 +3521,29 @@ Input type: `GitlabSubscriptionActivateInput`
 | <a id="mutationgitlabsubscriptionactivatefuturesubscriptions"></a>`futureSubscriptions` | [`[SubscriptionFutureEntry!]`](#subscriptionfutureentry) | Array of future subscriptions. |
 | <a id="mutationgitlabsubscriptionactivatelicense"></a>`license` | [`CurrentLicense`](#currentlicense) | Current license. |
 
+### `Mutation.googleCloudLoggingConfigurationCreate`
+
+Input type: `GoogleCloudLoggingConfigurationCreateInput`
+
+#### Arguments
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="mutationgooglecloudloggingconfigurationcreateclientemail"></a>`clientEmail` | [`String!`](#string) | Client email. |
+| <a id="mutationgooglecloudloggingconfigurationcreateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| <a id="mutationgooglecloudloggingconfigurationcreategoogleprojectidname"></a>`googleProjectIdName` | [`String!`](#string) | Google project ID. |
+| <a id="mutationgooglecloudloggingconfigurationcreategrouppath"></a>`groupPath` | [`ID!`](#id) | Group path. |
+| <a id="mutationgooglecloudloggingconfigurationcreatelogidname"></a>`logIdName` | [`String`](#string) | Log ID. (defaults to `audit_events`). |
+| <a id="mutationgooglecloudloggingconfigurationcreateprivatekey"></a>`privateKey` | [`String!`](#string) | Private key. |
+
+#### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="mutationgooglecloudloggingconfigurationcreateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| <a id="mutationgooglecloudloggingconfigurationcreateerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
+| <a id="mutationgooglecloudloggingconfigurationcreategooglecloudloggingconfiguration"></a>`googleCloudLoggingConfiguration` | [`GoogleCloudLoggingConfigurationType`](#googlecloudloggingconfigurationtype) | configuration created. |
+
 ### `Mutation.groupMemberBulkUpdate`
 
 Input type: `GroupMemberBulkUpdateInput`
@@ -15154,6 +15177,21 @@ four standard [pagination arguments](#connection-pagination-arguments):
 | <a id="geonodeuploadregistriesreplicationstate"></a>`replicationState` | [`ReplicationStateEnum`](#replicationstateenum) | Filters registries by their replication state. |
 | <a id="geonodeuploadregistriesverificationstate"></a>`verificationState` | [`VerificationStateEnum`](#verificationstateenum) | Filters registries by their verification state. |
 
+### `GoogleCloudLoggingConfigurationType`
+
+Stores Google Cloud Logging configurations associated with IAM service accounts,used for generating access tokens.
+
+#### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="googlecloudloggingconfigurationtypeclientemail"></a>`clientEmail` | [`String!`](#string) | Client email. |
+| <a id="googlecloudloggingconfigurationtypegoogleprojectidname"></a>`googleProjectIdName` | [`String!`](#string) | Google project ID. |
+| <a id="googlecloudloggingconfigurationtypegroup"></a>`group` | [`Group!`](#group) | Group the configuration belongs to. |
+| <a id="googlecloudloggingconfigurationtypeid"></a>`id` | [`ID!`](#id) | ID of the configuration. |
+| <a id="googlecloudloggingconfigurationtypelogidname"></a>`logIdName` | [`String!`](#string) | Log ID. |
+| <a id="googlecloudloggingconfigurationtypeprivatekey"></a>`privateKey` | [`String!`](#string) | Private key. |
+
 ### `GpgSignature`
 
 GPG signature for a signed commit.
diff --git a/ee/app/graphql/ee/types/mutation_type.rb b/ee/app/graphql/ee/types/mutation_type.rb
index 10c0f7fcf5267050700d289fdd884ef53b020f51..d88d1447fe66493667955520ea080c45a445aa8a 100644
--- a/ee/app/graphql/ee/types/mutation_type.rb
+++ b/ee/app/graphql/ee/types/mutation_type.rb
@@ -115,6 +115,7 @@ module MutationType
         mount_mutation ::Mutations::AuditEvents::InstanceExternalAuditEventDestinations::Create
         mount_mutation ::Mutations::AuditEvents::InstanceExternalAuditEventDestinations::Destroy
         mount_mutation ::Mutations::AuditEvents::InstanceExternalAuditEventDestinations::Update
+        mount_mutation ::Mutations::AuditEvents::GoogleCloudLoggingConfigurations::Create
         mount_mutation ::Mutations::Forecasting::BuildForecast, alpha: { milestone: '16.0' }
 
         prepend(Types::DeprecatedMutations)
diff --git a/ee/app/graphql/mutations/audit_events/google_cloud_logging_configurations/create.rb b/ee/app/graphql/mutations/audit_events/google_cloud_logging_configurations/create.rb
new file mode 100644
index 0000000000000000000000000000000000000000..1bed033a0dfcb6d06856ff5ef3bbae3b45c5e7e2
--- /dev/null
+++ b/ee/app/graphql/mutations/audit_events/google_cloud_logging_configurations/create.rb
@@ -0,0 +1,64 @@
+# frozen_string_literal: true
+
+module Mutations
+  module AuditEvents
+    module GoogleCloudLoggingConfigurations
+      class Create < BaseMutation
+        graphql_name 'GoogleCloudLoggingConfigurationCreate'
+
+        authorize :admin_external_audit_events
+
+        argument :group_path, GraphQL::Types::ID,
+          required: true,
+          description: 'Group path.'
+
+        argument :google_project_id_name, GraphQL::Types::String,
+          required: true,
+          description: 'Google project ID.'
+
+        argument :client_email, GraphQL::Types::String,
+          required: true,
+          description: 'Client email.'
+
+        argument :log_id_name, GraphQL::Types::String,
+          required: false,
+          description: 'Log ID. (defaults to `audit_events`).',
+          default_value: 'audit_events'
+
+        argument :private_key, GraphQL::Types::String,
+          required: true,
+          description: 'Private key.'
+
+        field :google_cloud_logging_configuration, ::Types::AuditEvents::GoogleCloudLoggingConfigurationType,
+          null: true,
+          description: 'configuration created.'
+
+        def resolve(group_path:, google_project_id_name:, client_email:, private_key:, log_id_name: nil)
+          group = authorized_find!(group_path)
+          config_attributes = {
+            group: group,
+            google_project_id_name: google_project_id_name,
+            client_email: client_email,
+            private_key: private_key
+          }
+
+          config_attributes[:log_id_name] = log_id_name if log_id_name.present?
+
+          config = ::AuditEvents::GoogleCloudLoggingConfiguration.new(config_attributes)
+
+          if config.save
+            { google_cloud_logging_configuration: config, errors: [] }
+          else
+            { google_cloud_logging_configuration: nil, errors: Array(config.errors) }
+          end
+        end
+
+        private
+
+        def find_object(group_path)
+          ::Group.find_by_full_path(group_path)
+        end
+      end
+    end
+  end
+end
diff --git a/ee/app/graphql/types/audit_events/google_cloud_logging_configuration_type.rb b/ee/app/graphql/types/audit_events/google_cloud_logging_configuration_type.rb
new file mode 100644
index 0000000000000000000000000000000000000000..5d5eacea8a87f8bf9c29dd32896881036d73925d
--- /dev/null
+++ b/ee/app/graphql/types/audit_events/google_cloud_logging_configuration_type.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+module Types
+  module AuditEvents
+    class GoogleCloudLoggingConfigurationType < ::Types::BaseObject
+      graphql_name 'GoogleCloudLoggingConfigurationType'
+      description 'Stores Google Cloud Logging configurations associated with IAM service accounts,' \
+                  'used for generating access tokens.'
+      authorize :admin_external_audit_events
+
+      field :group, ::Types::GroupType,
+        null: false,
+        description: 'Group the configuration belongs to.'
+
+      field :id, GraphQL::Types::ID,
+        null: false,
+        description: 'ID of the configuration.'
+
+      field :google_project_id_name, GraphQL::Types::String,
+        null: false,
+        description: 'Google project ID.'
+
+      field :client_email, GraphQL::Types::String,
+        null: false,
+        description: 'Client email.'
+
+      field :log_id_name, GraphQL::Types::String,
+        null: false,
+        description: 'Log ID.'
+
+      field :private_key, GraphQL::Types::String,
+        null: false,
+        description: 'Private key.'
+    end
+  end
+end
diff --git a/ee/app/models/audit_events/google_cloud_logging_configuration.rb b/ee/app/models/audit_events/google_cloud_logging_configuration.rb
index b5cd49df8ab37a0dd68f9eb21d5a0f54b8b4d08e..583e0bbd570e0e1f2da01a85c4127f487c0c6500 100644
--- a/ee/app/models/audit_events/google_cloud_logging_configuration.rb
+++ b/ee/app/models/audit_events/google_cloud_logging_configuration.rb
@@ -11,6 +11,10 @@ class GoogleCloudLoggingConfiguration < ApplicationRecord
     GOOGLE_PROJECT_ID_NAME_REGEX = %r{\A[a-z][a-z0-9-]*[a-z0-9]\z}
     LOG_ID_NAME_REGEX = %r{\A[\w/.-]+\z}
 
+    DEFAULT_LOG_ID_NAME = "audit_events"
+
+    attribute :log_id_name, :string, default: DEFAULT_LOG_ID_NAME
+
     belongs_to :group, class_name: '::Group', foreign_key: 'namespace_id',
       inverse_of: :google_cloud_logging_configurations
 
@@ -18,7 +22,8 @@ class GoogleCloudLoggingConfiguration < ApplicationRecord
       format: { with: GOOGLE_PROJECT_ID_NAME_REGEX,
                 message: 'must only contain lowercase letters, digits, or hyphens, ' \
                          'and must start and end with a letter or digit' },
-      length: { in: 6..30 }
+      length: { in: 6..30 },
+      uniqueness: { scope: [:namespace_id, :log_id_name] }
 
     validates :log_id_name, presence: true,
       format: { with: LOG_ID_NAME_REGEX,
diff --git a/ee/app/policies/audit_events/google_cloud_logging_configuration_policy.rb b/ee/app/policies/audit_events/google_cloud_logging_configuration_policy.rb
new file mode 100644
index 0000000000000000000000000000000000000000..7edd961ccbca8be23c59dd0383341ffee8e71f7c
--- /dev/null
+++ b/ee/app/policies/audit_events/google_cloud_logging_configuration_policy.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+module AuditEvents
+  class GoogleCloudLoggingConfigurationPolicy < ::BasePolicy
+    delegate { @subject.group }
+  end
+end
diff --git a/ee/spec/models/audit_events/google_cloud_logging_configuration_spec.rb b/ee/spec/models/audit_events/google_cloud_logging_configuration_spec.rb
index f803228742885ffc40b2e2d0b96892b3ad5f5bd1..7bb9c9622c4f9bb4578c2549741e99df59e2f4b3 100644
--- a/ee/spec/models/audit_events/google_cloud_logging_configuration_spec.rb
+++ b/ee/spec/models/audit_events/google_cloud_logging_configuration_spec.rb
@@ -45,6 +45,24 @@
     it { is_expected.not_to allow_value('#AUDIT_EVENT').for(:log_id_name) }
     it { is_expected.not_to allow_value('%audit_events/123').for(:log_id_name) }
 
+    context 'when the same google_project_id_name for the same namespace and log_id_name exists' do
+      let(:group) { create(:group) }
+      let(:google_project_id_name) { 'valid-project-id' }
+      let(:log_id_name) { 'audit_events' }
+
+      before do
+        create(:google_cloud_logging_configuration, group: group, google_project_id_name: google_project_id_name,
+          log_id_name: log_id_name)
+      end
+
+      it 'is not valid and adds an error message' do
+        config = build(:google_cloud_logging_configuration, group: group,
+          google_project_id_name: google_project_id_name, log_id_name: log_id_name)
+        expect(config).not_to be_valid
+        expect(config.errors[:google_project_id_name]).to include('has already been taken')
+      end
+    end
+
     context 'when the group is a subgroup' do
       let_it_be(:group) { create(:group) }
       let_it_be(:subgroup) { create(:group, parent: group) }
@@ -60,6 +78,12 @@
     end
   end
 
+  describe 'default values' do
+    it "uses 'audit_events' as default value for log_id_name" do
+      expect(described_class.new.log_id_name).to eq('audit_events')
+    end
+  end
+
   it_behaves_like 'includes Limitable concern' do
     subject { build(:google_cloud_logging_configuration, group: create(:group)) }
   end
diff --git a/ee/spec/requests/api/graphql/mutations/audit_events/google_cloud_logging_configurations/create_spec.rb b/ee/spec/requests/api/graphql/mutations/audit_events/google_cloud_logging_configurations/create_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..99a38f4af44f7482fd7e441d11325625a745cea0
--- /dev/null
+++ b/ee/spec/requests/api/graphql/mutations/audit_events/google_cloud_logging_configurations/create_spec.rb
@@ -0,0 +1,150 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Create google cloud logging configuration', feature_category: :audit_events do
+  include GraphqlHelpers
+
+  let_it_be(:group) { create(:group) }
+  let_it_be(:owner) { create(:user) }
+  let_it_be(:google_project_id_name) { 'test-project' }
+  let_it_be(:client_email) { 'test-email@example.com' }
+  let_it_be(:private_key) { OpenSSL::PKey::RSA.new(4096).to_pem }
+  let_it_be(:default_log_id_name) { 'audit_events' }
+
+  let(:current_user) { owner }
+  let(:mutation) { graphql_mutation(:google_cloud_logging_configuration_create, input) }
+  let(:mutation_response) { graphql_mutation_response(:google_cloud_logging_configuration_create) }
+
+  let(:input) do
+    {
+      groupPath: group.full_path,
+      googleProjectIdName: google_project_id_name,
+      clientEmail: client_email,
+      privateKey: private_key
+    }
+  end
+
+  subject(:mutate) { post_graphql_mutation(mutation, current_user: owner) }
+
+  shared_examples 'a mutation that does not create a configuration' do
+    it 'does not destroy the configuration' do
+      expect { mutate }
+        .not_to change { AuditEvents::GoogleCloudLoggingConfiguration.count }
+    end
+  end
+
+  shared_examples 'an unauthorized mutation that does not create a configuration' do
+    it_behaves_like 'a mutation on an unauthorized resource'
+    it_behaves_like 'a mutation that does not create a configuration'
+  end
+
+  context 'when feature is licensed' do
+    before do
+      stub_licensed_features(external_audit_events: true)
+    end
+
+    context 'when current user is a group owner' do
+      before do
+        group.add_owner(owner)
+      end
+
+      it 'resolves group by full path' do
+        expect(::Group).to receive(:find_by_full_path).with(group.full_path)
+
+        mutate
+      end
+
+      it 'creates the configuration' do
+        expect { mutate }
+          .to change { AuditEvents::GoogleCloudLoggingConfiguration.count }.by(1)
+
+        config = AuditEvents::GoogleCloudLoggingConfiguration.last
+        expect(config.group).to eq(group)
+        expect(config.google_project_id_name).to eq(google_project_id_name)
+        expect(config.client_email).to eq(client_email)
+        expect(config.log_id_name).to eq(default_log_id_name)
+        expect(config.private_key).to eq(private_key)
+      end
+
+      context 'when overriding log id name' do
+        let_it_be(:log_id_name) { 'test-log-id' }
+
+        let(:input) do
+          {
+            groupPath: group.full_path,
+            googleProjectIdName: google_project_id_name,
+            clientEmail: client_email,
+            privateKey: private_key,
+            logIdName: log_id_name
+          }
+        end
+
+        it 'creates the configuration' do
+          expect { mutate }
+            .to change { AuditEvents::GoogleCloudLoggingConfiguration.count }.by(1)
+
+          config = AuditEvents::GoogleCloudLoggingConfiguration.last
+          expect(config.group).to eq(group)
+          expect(config.google_project_id_name).to eq(google_project_id_name)
+          expect(config.client_email).to eq(client_email)
+          expect(config.log_id_name).to eq(log_id_name)
+          expect(config.private_key).to eq(private_key)
+        end
+      end
+
+      context 'when there is error while saving' do
+        before do
+          allow_next_instance_of(AuditEvents::GoogleCloudLoggingConfiguration) do |instance|
+            allow(instance).to receive(:save).and_return(false)
+
+            errors = ActiveModel::Errors.new(instance).tap { |e| e.add(:log_id_name, 'error message') }
+            allow(instance).to receive(:errors).and_return(errors)
+          end
+        end
+
+        it 'does not create the configuration and returns the error' do
+          expect { mutate }
+            .not_to change { AuditEvents::GoogleCloudLoggingConfiguration.count }
+
+          expect(mutation_response).to include(
+            'googleCloudLoggingConfiguration' => nil,
+            'errors' => ["Log id name error message"]
+          )
+        end
+      end
+    end
+
+    context 'when current user is a group maintainer' do
+      before do
+        group.add_maintainer(owner)
+      end
+
+      it_behaves_like 'an unauthorized mutation that does not create a configuration'
+    end
+
+    context 'when current user is a group developer' do
+      before do
+        group.add_developer(owner)
+      end
+
+      it_behaves_like 'an unauthorized mutation that does not create a configuration'
+    end
+
+    context 'when current user is a group guest' do
+      before do
+        group.add_guest(owner)
+      end
+
+      it_behaves_like 'an unauthorized mutation that does not create a configuration'
+    end
+  end
+
+  context 'when feature is unlicensed' do
+    before do
+      stub_licensed_features(external_audit_events: false)
+    end
+
+    it_behaves_like 'an unauthorized mutation that does not create a configuration'
+  end
+end