diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md
index a168df4fd63ef48a9114591ce2f5c3babc734c8f..ec212ca3d61b2e50e23bd8f2b135668a1e816e92 100644
--- a/doc/api/graphql/reference/index.md
+++ b/doc/api/graphql/reference/index.md
@@ -73,7 +73,7 @@ Returns [`CiConfig`](#ciconfig).
 
 ### `Query.ciMinutesUsage`
 
-Monthly CI minutes usage data for the current user.
+CI/CD minutes usage data for a namespace.
 
 Returns [`CiMinutesNamespaceMonthlyUsageConnection`](#ciminutesnamespacemonthlyusageconnection).
 
@@ -81,6 +81,12 @@ This field returns a [connection](#connections). It accepts the
 four standard [pagination arguments](#connection-pagination-arguments):
 `before: String`, `after: String`, `first: Int`, `last: Int`.
 
+#### Arguments
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="queryciminutesusagenamespaceid"></a>`namespaceId` | [`NamespaceID`](#namespaceid) | Global ID of the Namespace for the monthly CI/CD minutes usage. |
+
 ### `Query.containerRepository`
 
 Find a container repository.
diff --git a/ee/app/graphql/ee/types/query_type.rb b/ee/app/graphql/ee/types/query_type.rb
index 03b521c017ab678db309906976430825447fc9ef..1658bd517e41d8385c2da01452b8c0f4d37904b4 100644
--- a/ee/app/graphql/ee/types/query_type.rb
+++ b/ee/app/graphql/ee/types/query_type.rb
@@ -4,7 +4,6 @@ module EE
   module Types
     module QueryType
       extend ActiveSupport::Concern
-
       prepended do
         field :iteration, ::Types::IterationType,
               null: true,
@@ -70,7 +69,12 @@ module QueryType
 
         field :ci_minutes_usage, ::Types::Ci::Minutes::NamespaceMonthlyUsageType.connection_type,
               null: true,
-              description: 'Monthly CI minutes usage data for the current user.'
+              description: 'CI/CD minutes usage data for a namespace.' do
+          argument :namespace_id,
+                   ::Types::GlobalIDType[::Namespace],
+                   required: false,
+                   description: 'Global ID of the Namespace for the monthly CI/CD minutes usage.'
+        end
       end
 
       def vulnerability(id:)
@@ -87,8 +91,20 @@ def iteration(id:)
         ::GitlabSchema.find_by_gid(id)
       end
 
-      def ci_minutes_usage
-        ::Ci::Minutes::NamespaceMonthlyUsage.for_namespace(current_user.namespace)
+      def ci_minutes_usage(namespace_id: nil)
+        root_namespace = find_root_namespace(namespace_id)
+        ::Ci::Minutes::NamespaceMonthlyUsage.for_namespace(root_namespace)
+      end
+
+      private
+
+      def find_root_namespace(namespace_id)
+        return current_user&.namespace unless namespace_id
+
+        namespace = ::Gitlab::Graphql::Lazy.force(::GitlabSchema.find_by_gid(namespace_id))
+        return unless namespace&.root?
+
+        namespace
       end
     end
   end
diff --git a/ee/app/graphql/types/ci/minutes/namespace_monthly_usage_type.rb b/ee/app/graphql/types/ci/minutes/namespace_monthly_usage_type.rb
index 8047a70f9988575984ed532d5691046ed8a4c800..994a792aef91f4d4add351c8108729be3cf889af 100644
--- a/ee/app/graphql/types/ci/minutes/namespace_monthly_usage_type.rb
+++ b/ee/app/graphql/types/ci/minutes/namespace_monthly_usage_type.rb
@@ -7,6 +7,7 @@ module Minutes
       # this type only exposes data related to the current user
       class NamespaceMonthlyUsageType < BaseObject
         graphql_name 'CiMinutesNamespaceMonthlyUsage'
+        authorize :read_usage
 
         field :month, ::GraphQL::Types::String, null: true,
               description: 'Month related to the usage data.'
diff --git a/ee/app/policies/ci/minutes/namespace_monthly_usage_policy.rb b/ee/app/policies/ci/minutes/namespace_monthly_usage_policy.rb
new file mode 100644
index 0000000000000000000000000000000000000000..8f5667909982fee947ece0e2b88bc5fec2540b20
--- /dev/null
+++ b/ee/app/policies/ci/minutes/namespace_monthly_usage_policy.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+module Ci
+  module Minutes
+    class NamespaceMonthlyUsagePolicy < BasePolicy
+      delegate { @subject.namespace }
+
+      rule { can?(:owner_access) }.enable :read_usage
+    end
+  end
+end
diff --git a/ee/spec/policies/ci/minutes/namespace_monthly_usage_policy_spec.rb b/ee/spec/policies/ci/minutes/namespace_monthly_usage_policy_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..8f58643daf93e0379c488e59952084c5b26a577f
--- /dev/null
+++ b/ee/spec/policies/ci/minutes/namespace_monthly_usage_policy_spec.rb
@@ -0,0 +1,48 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Ci::Minutes::NamespaceMonthlyUsagePolicy do
+  let(:group) { create(:group, :private, name: 'test') }
+  let(:current_user) { create(:user) }
+
+  let(:namespace_monthly_usage) do
+    create(:ci_namespace_monthly_usage, namespace: group)
+  end
+
+  subject(:policy) do
+    described_class.new(current_user, namespace_monthly_usage)
+  end
+
+  context 'with an owner' do
+    before do
+      group.add_owner(current_user)
+    end
+
+    it { is_expected.to be_allowed(:read_usage) }
+  end
+
+  context 'with a developer' do
+    before do
+      group.add_developer(current_user)
+    end
+
+    it { is_expected.not_to be_allowed(:read_usage) }
+  end
+
+  context "with a user's namespace" do
+    let(:namespace_monthly_usage) do
+      create(:ci_namespace_monthly_usage, namespace: current_user.namespace)
+    end
+
+    it { is_expected.to be_allowed(:read_usage) }
+  end
+
+  context 'with a different namespace' do
+    let(:namespace_monthly_usage) do
+      create(:ci_namespace_monthly_usage, namespace: create(:user).namespace)
+    end
+
+    it { is_expected.not_to be_allowed(:read_usage) }
+  end
+end
diff --git a/ee/spec/requests/api/graphql/ci/minutes/usage_spec.rb b/ee/spec/requests/api/graphql/ci/minutes/usage_spec.rb
index 1d174898a11b19b38cfce4aeb363fbb8e2b26f5a..b0f5df3880106f1d8b20f6d6639e8cd45d04f60a 100644
--- a/ee/spec/requests/api/graphql/ci/minutes/usage_spec.rb
+++ b/ee/spec/requests/api/graphql/ci/minutes/usage_spec.rb
@@ -6,70 +6,130 @@
   include GraphqlHelpers
 
   let_it_be(:user) { create(:user) }
-  let_it_be(:project) { create(:project, name: 'Project 1', namespace: user.namespace) }
+  let_it_be(:user_project) { create(:project, name: 'Project 1', namespace: user.namespace) }
+  let_it_be_with_refind(:group) { create(:group, :public, name: 'test') }
 
   before(:all) do
     create(:ci_namespace_monthly_usage, namespace: user.namespace, amount_used: 50, date: Date.new(2021, 5, 1))
-    create(:ci_project_monthly_usage, project: project, amount_used: 50, date: Date.new(2021, 5, 1))
+    create(:ci_project_monthly_usage, project: user_project, amount_used: 40, date: Date.new(2021, 5, 1))
+
+    create(:ci_namespace_monthly_usage, namespace: group, amount_used: 100, date: Date.new(2021, 6, 1))
   end
 
-  it 'returns usage data by month for the current user' do
-    query = <<-QUERY
-      {
-        ciMinutesUsage {
-          nodes {
-            minutes
-            month
-            projects {
-              nodes {
-                name
-                minutes
+  subject(:result) { post_graphql(query, current_user: user) }
+
+  context 'when no namespace_id is provided' do
+    let(:query) do
+      <<-QUERY
+        {
+          ciMinutesUsage {
+            nodes {
+              minutes
+              month
+              projects {
+                nodes {
+                  name
+                  minutes
+                }
               }
             }
           }
         }
-      }
-    QUERY
-
-    post_graphql(query, current_user: user)
-
-    monthly_usage = graphql_data_at(:ci_minutes_usage, :nodes)
-    expect(monthly_usage).to contain_exactly({
-      'month' => 'May',
-      'minutes' => 50,
-      'projects' => { 'nodes' => [{
-        'name' => 'Project 1',
-        'minutes' => 50
-      }] }
-    })
+      QUERY
+    end
+
+    it 'returns usage data by month for the current user' do
+      subject
+
+      monthly_usage = graphql_data_at(:ci_minutes_usage, :nodes)
+      expect(monthly_usage).to contain_exactly({
+        'month' => 'May',
+        'minutes' => 50,
+        'projects' => { 'nodes' => [{
+          'name' => 'Project 1',
+          'minutes' => 40
+        }] }
+      })
+    end
+
+    it 'does not create N+1 queries' do
+      control_count = ActiveRecord::QueryRecorder.new do
+        post_graphql(query, current_user: user)
+      end
+      expect(graphql_errors).to be_nil
+
+      project_2 = create(:project, name: 'Project 2', namespace: user.namespace)
+      create(:ci_project_monthly_usage, project: project_2, amount_used: 50, date: Date.new(2021, 5, 1))
+
+      expect do
+        post_graphql(query, current_user: user)
+      end.not_to exceed_query_limit(control_count)
+      expect(graphql_errors).to be_nil
+    end
   end
 
-  it 'does not create N+1 queries' do
-    query = <<-QUERY
-      {
-        ciMinutesUsage {
-          nodes {
-            projects {
-              nodes {
-                name
-              }
+  context 'when namespace_id is provided' do
+    let(:namespace) { group }
+
+    let(:query) do
+      <<-QUERY
+        {
+          ciMinutesUsage(namespaceId: "#{namespace.to_global_id}") {
+            nodes {
+              minutes
+              month
             }
           }
         }
-      }
-    QUERY
+      QUERY
+    end
+
+    context 'when group is root' do
+      context 'when user is an owner' do
+        before do
+          group.add_owner(user)
+        end
+
+        it 'returns the usage data' do
+          subject
+
+          monthly_usage = graphql_data_at(:ci_minutes_usage, :nodes)
+          expect(monthly_usage).to contain_exactly({
+            'month' => 'June',
+            'minutes' => 100
+          })
+        end
+      end
 
-    control_count = ActiveRecord::QueryRecorder.new do
-      post_graphql(query, current_user: user)
+      context 'when user is not an owner' do
+        before do
+          group.add_developer(user)
+        end
+
+        it 'does not return usage data' do
+          subject
+
+          monthly_usage = graphql_data_at(:ci_minutes_usage, :nodes)
+          expect(monthly_usage).to be_empty
+        end
+      end
     end
-    expect(graphql_errors).to be_nil
 
-    project_2 = create(:project, name: 'Project 2', namespace: user.namespace)
-    create(:ci_project_monthly_usage, project: project_2, amount_used: 50, date: Date.new(2021, 5, 1))
+    context 'when group is a subgroup' do
+      let(:subgroup) { create(:group, :public, parent: group) }
+      let(:namespace) { subgroup }
+
+      before do
+        create(:ci_namespace_monthly_usage, namespace: subgroup)
+        subgroup.add_owner(user)
+      end
 
-    expect do
-      post_graphql(query, current_user: user)
-    end.not_to exceed_query_limit(control_count)
-    expect(graphql_errors).to be_nil
+      it 'does not return usage data' do
+        subject
+
+        monthly_usage = graphql_data_at(:ci_minutes_usage, :nodes)
+        expect(monthly_usage).to be_empty
+      end
+    end
   end
 end