diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md index a125f03679351024b066676825d9c867af52edd3..4ca8e72bf0ac5c8a13e94c4bfc17c683672ee337 100644 --- a/doc/api/graphql/reference/index.md +++ b/doc/api/graphql/reference/index.md @@ -120,6 +120,16 @@ This field returns a [connection](#connections). It accepts the four standard [pagination arguments](#connection-pagination-arguments): `before: String`, `after: String`, `first: Int`, `last: Int`. +### `Query.auditEventsInstanceAmazonS3Configurations` + +Instance-level Amazon S3 configurations for audit events. + +Returns [`InstanceAmazonS3ConfigurationTypeConnection`](#instanceamazons3configurationtypeconnection). + +This field returns a [connection](#connections). It accepts the +four standard [pagination arguments](#connection-pagination-arguments): +`before: String`, `after: String`, `first: Int`, `last: Int`. + ### `Query.boardList` Find an issue board list. @@ -10997,6 +11007,29 @@ The edge type for [`InheritedCiVariable`](#inheritedcivariable). | <a id="inheritedcivariableedgecursor"></a>`cursor` | [`String!`](#string) | A cursor for use in pagination. | | <a id="inheritedcivariableedgenode"></a>`node` | [`InheritedCiVariable`](#inheritedcivariable) | The item at the end of the edge. | +#### `InstanceAmazonS3ConfigurationTypeConnection` + +The connection type for [`InstanceAmazonS3ConfigurationType`](#instanceamazons3configurationtype). + +##### Fields + +| Name | Type | Description | +| ---- | ---- | ----------- | +| <a id="instanceamazons3configurationtypeconnectionedges"></a>`edges` | [`[InstanceAmazonS3ConfigurationTypeEdge]`](#instanceamazons3configurationtypeedge) | A list of edges. | +| <a id="instanceamazons3configurationtypeconnectionnodes"></a>`nodes` | [`[InstanceAmazonS3ConfigurationType]`](#instanceamazons3configurationtype) | A list of nodes. | +| <a id="instanceamazons3configurationtypeconnectionpageinfo"></a>`pageInfo` | [`PageInfo!`](#pageinfo) | Information to aid in pagination. | + +#### `InstanceAmazonS3ConfigurationTypeEdge` + +The edge type for [`InstanceAmazonS3ConfigurationType`](#instanceamazons3configurationtype). + +##### Fields + +| Name | Type | Description | +| ---- | ---- | ----------- | +| <a id="instanceamazons3configurationtypeedgecursor"></a>`cursor` | [`String!`](#string) | A cursor for use in pagination. | +| <a id="instanceamazons3configurationtypeedgenode"></a>`node` | [`InstanceAmazonS3ConfigurationType`](#instanceamazons3configurationtype) | The item at the end of the edge. | + #### `InstanceExternalAuditEventDestinationConnection` The connection type for [`InstanceExternalAuditEventDestination`](#instanceexternalauditeventdestination). diff --git a/ee/app/graphql/ee/types/query_type.rb b/ee/app/graphql/ee/types/query_type.rb index f64345957a49ade32fcce857d57b0122362e2c43..29a8216434b67c93bb802b21d2eeda34340a85bb 100644 --- a/ee/app/graphql/ee/types/query_type.rb +++ b/ee/app/graphql/ee/types/query_type.rb @@ -137,6 +137,11 @@ module QueryType description: 'Users within the self-managed instance who are eligible for add-ons.', resolver: ::Resolvers::GitlabSubscriptions::SelfManaged::AddOnEligibleUsersResolver, alpha: { milestone: '16.7' } + field :audit_events_instance_amazon_s3_configurations, + ::Types::AuditEvents::Instance::AmazonS3ConfigurationType.connection_type, + null: true, + description: 'Instance-level Amazon S3 configurations for audit events.', + resolver: ::Resolvers::AuditEvents::Instance::AmazonS3ConfigurationsResolver end def vulnerability(id:) diff --git a/ee/app/graphql/resolvers/audit_events/instance/amazon_s3_configurations_resolver.rb b/ee/app/graphql/resolvers/audit_events/instance/amazon_s3_configurations_resolver.rb new file mode 100644 index 0000000000000000000000000000000000000000..d5adfe10f1093279dee1c175295d2bce1b44a8c5 --- /dev/null +++ b/ee/app/graphql/resolvers/audit_events/instance/amazon_s3_configurations_resolver.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +module Resolvers + module AuditEvents + module Instance + class AmazonS3ConfigurationsResolver < BaseResolver + type [::Types::AuditEvents::Instance::AmazonS3ConfigurationType], null: true + + def resolve + ::AuditEvents::Instance::AmazonS3Configuration.all + end + end + end + end +end diff --git a/ee/spec/graphql/types/query_type_spec.rb b/ee/spec/graphql/types/query_type_spec.rb index 69e75528d5feffc72cda991a1bc90e8c7d155681..8d301afc23413382661e0a13ac80f879491973ab 100644 --- a/ee/spec/graphql/types/query_type_spec.rb +++ b/ee/spec/graphql/types/query_type_spec.rb @@ -32,6 +32,7 @@ :workspaces, :instance_external_audit_event_destinations, :instance_google_cloud_logging_configurations, + :audit_events_instance_amazon_s3_configurations, :member_role, :self_managed_add_on_eligible_users ] diff --git a/ee/spec/requests/api/graphql/audit_events/instance/amazon_s3_configuration_spec.rb b/ee/spec/requests/api/graphql/audit_events/instance/amazon_s3_configuration_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..3de839028d2d7520bce5b0d82199d0f3b737b5d8 --- /dev/null +++ b/ee/spec/requests/api/graphql/audit_events/instance/amazon_s3_configuration_spec.rb @@ -0,0 +1,103 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe 'List audit event Amazon S3 destinations for the instance', feature_category: :audit_events do + include GraphqlHelpers + + let_it_be(:admin) { create(:admin) } + let_it_be(:user) { create(:user) } + let_it_be(:destination_1) { create(:instance_amazon_s3_configuration) } + let_it_be(:destination_2) { create(:instance_amazon_s3_configuration) } + + let(:path) { %i[audit_events_instance_amazon_s3_configurations nodes] } + + let(:query) do + graphql_query_for( + :audit_events_instance_amazon_s3_configurations + ) + end + + shared_examples 'a request that returns no destinations' do + it 'returns no destinations' do + post_graphql(query, current_user: current_user) + + expect(graphql_data_at(:audit_events_instance_amazon_s3_configurations, :nodes)).to be_empty + end + end + + context 'when user is authenticated' do + context 'when feature is licensed' do + before do + stub_licensed_features(external_audit_events: true) + end + + context 'when user is instance admin' do + it 'returns the instance audit event Amazon S3 configurations', :aggregate_failures do + post_graphql(query, current_user: admin) + + expect(graphql_data_at(*path)).to contain_exactly( + a_hash_including( + 'bucketName' => destination_1.bucket_name, + 'awsRegion' => destination_1.aws_region, + 'accessKeyXid' => destination_1.access_key_xid, + 'name' => destination_1.name + ), + a_hash_including( + 'bucketName' => destination_2.bucket_name, + 'awsRegion' => destination_2.aws_region, + 'accessKeyXid' => destination_2.access_key_xid, + 'name' => destination_2.name + ) + ) + + expect(graphql_data_at(*path)) + .to contain_exactly( + hash_not_including('secretAccessKey'), + hash_not_including('secretAccessKey') + ) + end + end + + context 'when user is not instance admin' do + it_behaves_like 'a request that returns no destinations' do + let(:current_user) { user } + end + end + end + + context 'when feature is not licensed' do + context 'when user is instance admin' do + it_behaves_like 'a request that returns no destinations' do + let(:current_user) { admin } + end + end + + context 'when user is not instance admin' do + it_behaves_like 'a request that returns no destinations' do + let(:current_user) { user } + end + end + end + end + + context 'when user is not authenticated' do + let(:user) { nil } + + context 'when feature is licensed' do + before do + stub_licensed_features(external_audit_events: true) + end + + it_behaves_like 'a request that returns no destinations' do + let(:current_user) { user } + end + end + + context 'when feature is not licensed' do + it_behaves_like 'a request that returns no destinations' do + let(:current_user) { user } + end + end + end +end