diff --git a/lib/gitlab/ci/config/node/before_script.rb b/lib/gitlab/ci/config/node/before_script.rb
index 586eab12a0873ab02b1cd89663d34e25b655b777..a8c350f3c7d704e05dda9c56eccd6cbe7e8f9e96 100644
--- a/lib/gitlab/ci/config/node/before_script.rb
+++ b/lib/gitlab/ci/config/node/before_script.rb
@@ -5,10 +5,6 @@ module Gitlab
         class BeforeScript < Entry
           include ValidationHelpers
 
-          def keys
-            {}
-          end
-
           def validate!
             unless validate_array_of_strings(@value)
               @errors << 'before_script should be an array of strings'
diff --git a/lib/gitlab/ci/config/node/entry.rb b/lib/gitlab/ci/config/node/entry.rb
index e95bc7bad4bd086544a3b0ad0440b7af7d6b4e3e..3043dc4c61f85dc6f74aa4796aa827fd46092329 100644
--- a/lib/gitlab/ci/config/node/entry.rb
+++ b/lib/gitlab/ci/config/node/entry.rb
@@ -48,12 +48,22 @@ module Gitlab
           end
 
           def keys
-            raise NotImplementedError
+            self.class.nodes || {}
           end
 
           def validate!
             raise NotImplementedError
           end
+
+          class << self
+            attr_reader :nodes
+
+            private
+
+            def add_node(symbol, entry_class)
+              (@nodes ||= {}).merge!(symbol.to_sym => entry_class)
+            end
+          end
         end
       end
     end
diff --git a/lib/gitlab/ci/config/node/global.rb b/lib/gitlab/ci/config/node/global.rb
index 81a9d0667be347c681768b9f237d3b602c0f562e..cfa506c28b7fa83ec45ee5b6997e19992ee19ac9 100644
--- a/lib/gitlab/ci/config/node/global.rb
+++ b/lib/gitlab/ci/config/node/global.rb
@@ -3,9 +3,7 @@ module Gitlab
     class Config
       module Node
         class Global < Entry
-          def keys
-            { before_script: BeforeScript }
-          end
+          add_node :before_script, BeforeScript
         end
       end
     end
diff --git a/lib/gitlab/ci/config/node/null.rb b/lib/gitlab/ci/config/node/null.rb
index 6147b0d882faa4bb195b459f2e3504baefcc4ae8..fc240e16f556304867dfdf974b4f3b7822d93e3b 100644
--- a/lib/gitlab/ci/config/node/null.rb
+++ b/lib/gitlab/ci/config/node/null.rb
@@ -3,10 +3,6 @@ module Gitlab
     class Config
       module Node
         class Null < Entry
-          def keys
-            {}
-          end
-
           def method_missing(*)
             nil
           end
diff --git a/spec/lib/gitlab/ci/config/node/global_spec.rb b/spec/lib/gitlab/ci/config/node/global_spec.rb
index f277c457a3be33d06b2a2bd31c0fa2b51d9d3ffb..05e035ada3909a30eab2333f233be3ec131cd074 100644
--- a/spec/lib/gitlab/ci/config/node/global_spec.rb
+++ b/spec/lib/gitlab/ci/config/node/global_spec.rb
@@ -7,6 +7,10 @@ describe Gitlab::Ci::Config::Node::Global do
     it 'can contain global config keys' do
       expect(global.keys).to include :before_script
     end
+
+    it 'returns a hash' do
+      expect(global.keys).to be_a Hash
+    end
   end
 
   context 'when hash is valid' do