diff --git a/doc/administration/audit_event_streaming/audit_event_types.md b/doc/administration/audit_event_streaming/audit_event_types.md
index 3b2ae09846930001c2e36cebf2c3a8487fbcee8b..2d1249e2b6c5e74e6a076ebbaf6c6d826fb3dec2 100644
--- a/doc/administration/audit_event_streaming/audit_event_types.md
+++ b/doc/administration/audit_event_streaming/audit_event_types.md
@@ -37,6 +37,7 @@ Audit event types belong to the following product categories.
| Name | Description | Saved to database | Streamed | Introduced in |
|:-----|:------------|:------------------|:---------|:--------------|
| [`amazon_s3_configuration_created`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/132443) | Triggered when Amazon S3 configuration for audit events streaming is created| **{check-circle}** Yes | **{check-circle}** Yes | GitLab [16.5](https://gitlab.com/gitlab-org/gitlab/-/issues/423229) |
+| [`amazon_s3_configuration_deleted`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/133695) | Triggered when Amazon S3 configuration for audit events streaming is deleted.| **{check-circle}** Yes | **{check-circle}** Yes | GitLab [16.5](https://gitlab.com/gitlab-org/gitlab/-/issues/423229) |
| [`amazon_s3_configuration_updated`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/133691) | Triggered when Amazon S3 configuration for audit events streaming is updated.| **{check-circle}** Yes | **{check-circle}** Yes | GitLab [16.5](https://gitlab.com/gitlab-org/gitlab/-/issues/423229) |
| [`audit_events_streaming_headers_create`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/92068) | Triggered when a streaming header for audit events is created| **{check-circle}** Yes | **{check-circle}** Yes | GitLab [15.3](https://gitlab.com/gitlab-org/gitlab/-/issues/366350) |
| [`audit_events_streaming_headers_destroy`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/92068) | Triggered when a streaming header for audit events is deleted| **{check-circle}** Yes | **{check-circle}** Yes | GitLab [15.3](https://gitlab.com/gitlab-org/gitlab/-/issues/366350) |
diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md
index 89957613b6337abb854e620210f9b5088e8294c1..5e6d47f70718e89b0f36c873b748ce29959a2d21 100644
--- a/doc/api/graphql/reference/index.md
+++ b/doc/api/graphql/reference/index.md
@@ -1274,94 +1274,112 @@ Input type: `AlertTodoCreateInput`
| `issue` | [`Issue`](#issue) | Issue created after mutation. |
| `todo` | [`Todo`](#todo) | To-do item after mutation. |
-### `Mutation.amazonS3ConfigurationCreate`
+### `Mutation.approveDeployment`
-Input type: `AmazonS3ConfigurationCreateInput`
+Input type: `ApproveDeploymentInput`
#### Arguments
| Name | Type | Description |
| ---- | ---- | ----------- |
-| `accessKeyXid` | [`String!`](#string) | Access key ID of the Amazon S3 account. |
-| `awsRegion` | [`String!`](#string) | AWS region where the bucket is created. |
-| `bucketName` | [`String!`](#string) | Name of the bucket where the audit events would be logged. |
-| `clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
-| `groupPath` | [`ID!`](#id) | Group path. |
-| `name` | [`String`](#string) | Destination name. |
-| `secretAccessKey` | [`String!`](#string) | Secret access key of the Amazon S3 account. |
+| `clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| `comment` | [`String`](#string) | Comment to go with the approval. |
+| `id` | [`DeploymentID!`](#deploymentid) | ID of the deployment. |
+| `representedAs` | [`String`](#string) | Name of the User/Group/Role to use for the approval, when the user belongs to multiple approval rules. |
+| `status` | [`DeploymentsApprovalStatus!`](#deploymentsapprovalstatus) | Status of the approval (either `APPROVED` or `REJECTED`). |
#### Fields
| Name | Type | Description |
| ---- | ---- | ----------- |
-| `amazonS3Configuration` | [`AmazonS3ConfigurationType`](#amazons3configurationtype) | configuration created. |
-| `clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
-| `errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
+| `clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| `deploymentApproval` | [`DeploymentApproval!`](#deploymentapproval) | DeploymentApproval after mutation. |
+| `errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
-### `Mutation.amazonS3ConfigurationUpdate`
+### `Mutation.artifactDestroy`
-Input type: `AmazonS3ConfigurationUpdateInput`
+Input type: `ArtifactDestroyInput`
#### Arguments
| Name | Type | Description |
| ---- | ---- | ----------- |
-| `accessKeyXid` | [`String`](#string) | Access key ID of the Amazon S3 account. |
-| `awsRegion` | [`String`](#string) | AWS region where the bucket is created. |
-| `bucketName` | [`String`](#string) | Name of the bucket where the audit events would be logged. |
-| `clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
-| `id` | [`AuditEventsAmazonS3ConfigurationID!`](#auditeventsamazons3configurationid) | ID of the Amazon S3 configuration to update. |
-| `name` | [`String`](#string) | Destination name. |
-| `secretAccessKey` | [`String`](#string) | Secret access key of the Amazon S3 account. |
+| `clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| `id` | [`CiJobArtifactID!`](#cijobartifactid) | ID of the artifact to delete. |
#### Fields
| Name | Type | Description |
| ---- | ---- | ----------- |
-| `amazonS3Configuration` | [`AmazonS3ConfigurationType`](#amazons3configurationtype) | Updated Amazon S3 configuration. |
-| `clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
-| `errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
+| `artifact` | [`CiJobArtifact`](#cijobartifact) | Deleted artifact. |
+| `clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| `errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
-### `Mutation.approveDeployment`
+### `Mutation.auditEventsAmazonS3ConfigurationCreate`
-Input type: `ApproveDeploymentInput`
+Input type: `AuditEventsAmazonS3ConfigurationCreateInput`
#### Arguments
| Name | Type | Description |
| ---- | ---- | ----------- |
-| `clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
-| `comment` | [`String`](#string) | Comment to go with the approval. |
-| `id` | [`DeploymentID!`](#deploymentid) | ID of the deployment. |
-| `representedAs` | [`String`](#string) | Name of the User/Group/Role to use for the approval, when the user belongs to multiple approval rules. |
-| `status` | [`DeploymentsApprovalStatus!`](#deploymentsapprovalstatus) | Status of the approval (either `APPROVED` or `REJECTED`). |
+| `accessKeyXid` | [`String!`](#string) | Access key ID of the Amazon S3 account. |
+| `awsRegion` | [`String!`](#string) | AWS region where the bucket is created. |
+| `bucketName` | [`String!`](#string) | Name of the bucket where the audit events would be logged. |
+| `clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| `groupPath` | [`ID!`](#id) | Group path. |
+| `name` | [`String`](#string) | Destination name. |
+| `secretAccessKey` | [`String!`](#string) | Secret access key of the Amazon S3 account. |
#### Fields
| Name | Type | Description |
| ---- | ---- | ----------- |
-| `clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
-| `deploymentApproval` | [`DeploymentApproval!`](#deploymentapproval) | DeploymentApproval after mutation. |
-| `errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
+| `amazonS3Configuration` | [`AmazonS3ConfigurationType`](#amazons3configurationtype) | configuration created. |
+| `clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| `errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
-### `Mutation.artifactDestroy`
+### `Mutation.auditEventsAmazonS3ConfigurationDelete`
-Input type: `ArtifactDestroyInput`
+Input type: `AuditEventsAmazonS3ConfigurationDeleteInput`
#### Arguments
| Name | Type | Description |
| ---- | ---- | ----------- |
-| `clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
-| `id` | [`CiJobArtifactID!`](#cijobartifactid) | ID of the artifact to delete. |
+| `clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| `id` | [`AuditEventsAmazonS3ConfigurationID!`](#auditeventsamazons3configurationid) | ID of the Amazon S3 configuration to destroy. |
#### Fields
| Name | Type | Description |
| ---- | ---- | ----------- |
-| `artifact` | [`CiJobArtifact`](#cijobartifact) | Deleted artifact. |
-| `clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
-| `errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
+| `clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| `errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
+
+### `Mutation.auditEventsAmazonS3ConfigurationUpdate`
+
+Input type: `AuditEventsAmazonS3ConfigurationUpdateInput`
+
+#### Arguments
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| `accessKeyXid` | [`String`](#string) | Access key ID of the Amazon S3 account. |
+| `awsRegion` | [`String`](#string) | AWS region where the bucket is created. |
+| `bucketName` | [`String`](#string) | Name of the bucket where the audit events would be logged. |
+| `clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| `id` | [`AuditEventsAmazonS3ConfigurationID!`](#auditeventsamazons3configurationid) | ID of the Amazon S3 configuration to update. |
+| `name` | [`String`](#string) | Destination name. |
+| `secretAccessKey` | [`String`](#string) | Secret access key of the Amazon S3 account. |
+
+#### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| `amazonS3Configuration` | [`AmazonS3ConfigurationType`](#amazons3configurationtype) | Updated Amazon S3 configuration. |
+| `clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| `errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
### `Mutation.auditEventsStreamingDestinationEventsAdd`
diff --git a/ee/app/graphql/ee/types/mutation_type.rb b/ee/app/graphql/ee/types/mutation_type.rb
index f086bc24430ef1ae6782c4506a5c7b2a5ab41c2c..6ccbc695caff7ca8016f017838cc48bd6edbd6ec 100644
--- a/ee/app/graphql/ee/types/mutation_type.rb
+++ b/ee/app/graphql/ee/types/mutation_type.rb
@@ -124,6 +124,7 @@ module MutationType
mount_mutation ::Mutations::AuditEvents::GoogleCloudLoggingConfigurations::Destroy
mount_mutation ::Mutations::AuditEvents::GoogleCloudLoggingConfigurations::Update
mount_mutation ::Mutations::AuditEvents::AmazonS3Configurations::Create
+ mount_mutation ::Mutations::AuditEvents::AmazonS3Configurations::Delete
mount_mutation ::Mutations::AuditEvents::AmazonS3Configurations::Update
mount_mutation ::Mutations::AuditEvents::Instance::GoogleCloudLoggingConfigurations::Create
mount_mutation ::Mutations::Forecasting::BuildForecast, alpha: { milestone: '16.0' }
diff --git a/ee/app/graphql/mutations/audit_events/amazon_s3_configurations/base.rb b/ee/app/graphql/mutations/audit_events/amazon_s3_configurations/base.rb
index f6c70d16704a3135254b619f462363a420de545d..df6595428ecd0fce3221ba2ae20dc3248236f38c 100644
--- a/ee/app/graphql/mutations/audit_events/amazon_s3_configurations/base.rb
+++ b/ee/app/graphql/mutations/audit_events/amazon_s3_configurations/base.rb
@@ -4,6 +4,8 @@ module Mutations
module AuditEvents
module AmazonS3Configurations
class Base < BaseMutation
+ authorize :admin_external_audit_events
+
private
def audit(config, action:)
@@ -18,6 +20,10 @@ def audit(config, action:)
::Gitlab::Audit::Auditor.audit(audit_context)
end
+
+ def find_object(config_gid)
+ GitlabSchema.object_from_id(config_gid, expected_type: ::AuditEvents::AmazonS3Configuration)
+ end
end
end
end
diff --git a/ee/app/graphql/mutations/audit_events/amazon_s3_configurations/create.rb b/ee/app/graphql/mutations/audit_events/amazon_s3_configurations/create.rb
index 51fd0baa827aa43931cf52094fc432cd753c91c1..37617bc3fb573298b9f59b539197ff9b1710d6d2 100644
--- a/ee/app/graphql/mutations/audit_events/amazon_s3_configurations/create.rb
+++ b/ee/app/graphql/mutations/audit_events/amazon_s3_configurations/create.rb
@@ -4,9 +4,7 @@ module Mutations
module AuditEvents
module AmazonS3Configurations
class Create < Base
- graphql_name 'AmazonS3ConfigurationCreate'
-
- authorize :admin_external_audit_events
+ graphql_name 'AuditEventsAmazonS3ConfigurationCreate'
argument :name, GraphQL::Types::String,
required: false,
diff --git a/ee/app/graphql/mutations/audit_events/amazon_s3_configurations/delete.rb b/ee/app/graphql/mutations/audit_events/amazon_s3_configurations/delete.rb
new file mode 100644
index 0000000000000000000000000000000000000000..395bb0abc0fdaa94342b3020a6638b1a634992c3
--- /dev/null
+++ b/ee/app/graphql/mutations/audit_events/amazon_s3_configurations/delete.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+module Mutations
+ module AuditEvents
+ module AmazonS3Configurations
+ class Delete < Base
+ graphql_name 'AuditEventsAmazonS3ConfigurationDelete'
+
+ argument :id, ::Types::GlobalIDType[::AuditEvents::AmazonS3Configuration],
+ required: true,
+ description: 'ID of the Amazon S3 configuration to destroy.'
+
+ def resolve(id:)
+ config = authorized_find!(id)
+
+ audit(config, action: :deleted) if config.destroy
+ { errors: Array(config.errors) }
+ end
+ end
+ end
+ end
+end
diff --git a/ee/app/graphql/mutations/audit_events/amazon_s3_configurations/update.rb b/ee/app/graphql/mutations/audit_events/amazon_s3_configurations/update.rb
index 8a19466e71a0d3aed1ccbffd48a1f0aba0e4f15e..2002d5d5b4bfa414cf52e878b453bfc45ab8c4ae 100644
--- a/ee/app/graphql/mutations/audit_events/amazon_s3_configurations/update.rb
+++ b/ee/app/graphql/mutations/audit_events/amazon_s3_configurations/update.rb
@@ -4,15 +4,13 @@ module Mutations
module AuditEvents
module AmazonS3Configurations
class Update < Base
- graphql_name 'AmazonS3ConfigurationUpdate'
+ graphql_name 'AuditEventsAmazonS3ConfigurationUpdate'
include ::Audit::Changes
UPDATE_EVENT_NAME = 'amazon_s3_configuration_updated'
AUDIT_EVENT_COLUMNS = [:access_key_xid, :secret_access_key, :bucket_name, :aws_region, :name].freeze
- authorize :admin_external_audit_events
-
argument :id, ::Types::GlobalIDType[::AuditEvents::AmazonS3Configuration],
required: true,
description: 'ID of the Amazon S3 configuration to update.'
@@ -72,10 +70,6 @@ def audit_update(config)
)
end
end
-
- def find_object(config_gid)
- GitlabSchema.object_from_id(config_gid, expected_type: ::AuditEvents::AmazonS3Configuration).sync
- end
end
end
end
diff --git a/ee/config/audit_events/types/amazon_s3_configuration_deleted.yml b/ee/config/audit_events/types/amazon_s3_configuration_deleted.yml
new file mode 100644
index 0000000000000000000000000000000000000000..400633bdac71a3386e7b04543147d49bf66dc9cb
--- /dev/null
+++ b/ee/config/audit_events/types/amazon_s3_configuration_deleted.yml
@@ -0,0 +1,9 @@
+---
+name: amazon_s3_configuration_deleted
+description: Triggered when Amazon S3 configuration for audit events streaming is deleted.
+introduced_by_issue: https://gitlab.com/gitlab-org/gitlab/-/issues/423229
+introduced_by_mr: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/133695
+feature_category: audit_events
+milestone: '16.5'
+saved_to_database: true
+streamed: true
diff --git a/ee/spec/requests/api/graphql/mutations/audit_events/amazon_s3_configurations/create_spec.rb b/ee/spec/requests/api/graphql/mutations/audit_events/amazon_s3_configurations/create_spec.rb
index dc4508451787e08c1140ea360d70ae0d5bf7e75d..a5c1278b34f445a465e80050b54e04315a0621a8 100644
--- a/ee/spec/requests/api/graphql/mutations/audit_events/amazon_s3_configurations/create_spec.rb
+++ b/ee/spec/requests/api/graphql/mutations/audit_events/amazon_s3_configurations/create_spec.rb
@@ -13,8 +13,8 @@
let_it_be(:bucket_name) { 'test-bucket' }
let_it_be(:aws_region) { 'us-east-1' }
- let(:mutation) { graphql_mutation(:amazon_s3_configuration_create, input) }
- let(:mutation_response) { graphql_mutation_response(:amazon_s3_configuration_create) }
+ let(:mutation) { graphql_mutation(:audit_events_amazon_s3_configuration_create, input) }
+ let(:mutation_response) { graphql_mutation_response(:audit_events_amazon_s3_configuration_create) }
let(:input) do
{
diff --git a/ee/spec/requests/api/graphql/mutations/audit_events/amazon_s3_configurations/delete_spec.rb b/ee/spec/requests/api/graphql/mutations/audit_events/amazon_s3_configurations/delete_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..a893924f76d89199a610afee494ff420e80caaea
--- /dev/null
+++ b/ee/spec/requests/api/graphql/mutations/audit_events/amazon_s3_configurations/delete_spec.rb
@@ -0,0 +1,79 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Delete Amazon S3 configuration', feature_category: :audit_events do
+ include GraphqlHelpers
+
+ let_it_be(:config) { create(:amazon_s3_configuration) }
+ let_it_be(:group) { config.group }
+ let_it_be(:current_user) { create(:user) }
+
+ let(:mutation) { graphql_mutation(:audit_events_amazon_s3_configuration_delete, id: global_id_of(config)) }
+ let(:mutation_response) { graphql_mutation_response(:audit_events_amazon_s3_configuration_delete) }
+
+ subject(:mutate) { post_graphql_mutation(mutation, current_user: current_user) }
+
+ 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_all do
+ group.add_owner(current_user)
+ end
+
+ it 'destroys the configuration' do
+ expect { mutate }.to change { AuditEvents::AmazonS3Configuration.count }.by(-1)
+ end
+
+ it 'audits the deletion' do
+ expected_hash = {
+ name: 'amazon_s3_configuration_deleted',
+ author: current_user,
+ scope: group,
+ target: group,
+ message: "Deleted Amazon S3 configuration with name: #{config.name} bucket: " \
+ "#{config.bucket_name} and AWS region: #{config.aws_region}"
+ }
+
+ expect(Gitlab::Audit::Auditor).to receive(:audit).with(hash_including(expected_hash))
+
+ mutate
+ end
+
+ context 'when there is an error during destroy' do
+ before do
+ expect_next_found_instance_of(AuditEvents::AmazonS3Configuration) do |config|
+ allow(config).to receive(:destroy).and_return(false)
+ errors = ActiveModel::Errors.new(config).tap { |e| e.add(:base, 'error message') }
+ allow(config).to receive(:errors).and_return(errors)
+ end
+ end
+
+ it 'does not destroy the configuration and returns the error' do
+ expect { mutate }.not_to change { AuditEvents::AmazonS3Configuration.count }
+
+ expect(mutation_response).to include('errors' => ['error message'])
+ end
+ end
+ end
+
+ context 'when current user is a group maintainer' do
+ before_all do
+ group.add_maintainer(current_user)
+ end
+
+ it_behaves_like 'a mutation on an unauthorized resource'
+ end
+ end
+
+ context 'when feature is unlicensed' do
+ before do
+ stub_licensed_features(external_audit_events: false)
+ end
+
+ it_behaves_like 'a mutation on an unauthorized resource'
+ end
+end
diff --git a/ee/spec/requests/api/graphql/mutations/audit_events/amazon_s3_configurations/update_spec.rb b/ee/spec/requests/api/graphql/mutations/audit_events/amazon_s3_configurations/update_spec.rb
index 7e29514846c0d5c3cab8a2602addce3e0aa35ba4..d6785b29cc048606ea65b9fdcfbe65a23dc17f90 100644
--- a/ee/spec/requests/api/graphql/mutations/audit_events/amazon_s3_configurations/update_spec.rb
+++ b/ee/spec/requests/api/graphql/mutations/audit_events/amazon_s3_configurations/update_spec.rb
@@ -16,8 +16,8 @@
let_it_be(:updated_destination_name) { 'updated_destination_name' }
let_it_be(:config_gid) { global_id_of(config) }
- let(:mutation) { graphql_mutation(:amazon_s3_configuration_update, input) }
- let(:mutation_response) { graphql_mutation_response(:amazon_s3_configuration_update) }
+ let(:mutation) { graphql_mutation(:audit_events_amazon_s3_configuration_update, input) }
+ let(:mutation_response) { graphql_mutation_response(:audit_events_amazon_s3_configuration_update) }
let(:input) do
{