Skip to content

Define and Implement AWS Secrets Manager Schema

Description

Implement the AWS Secrets Manager schema in the GitLab CI/CD configuration system, adding support for a new secrets provider alongside the existing ones (HashiCorp Vault, GCP Secret Manager, and Azure Key Vault).

Goals

  • Add AWS Secrets Manager as a supported secrets provider in the CI/CD configuration
  • Implement validation for required and optional fields
  • Ensure proper error messages for validation failures

Implementation Plan

Step 1: Locate Existing Secret Provider Implementations

First, you'll need to understand how existing secret providers are implemented. Look at:

# File: lib/gitlab/ci/config/entry/secret.rb (or similar)

module Gitlab
  module Ci
    module Config
      module Entry
        class Secret < Node
          # Existing provider implementations will be here
        end
      end
    end
  end
end

Step 2: Add AWS Secret Manager Schema Definition

Add the AWS Secret Manager schema, following the pattern of existing providers:

# Add this alongside other provider validations

class AwsSecretManager < ::Gitlab::Config::Entry::Node
  include ::Gitlab::Config::Entry::Validatable

  validations do
    # Required fields
    validates :name, type: String, presence: true
    validates :region, type: String, presence: true
    
    # Optional fields
    validates :version_id, type: String, allow_nil: true
    validates :version_stage, type: String, allow_nil: true
  end

  # Define entry points for nested configuration
  entry :name, Entry::String,
    description: 'Name of the secret in AWS Secrets Manager.'
  
  entry :region, Entry::String,
    description: 'AWS region where the secret is stored.'
  
  entry :version_id, Entry::String,
    description: 'Specific version ID of the secret to retrieve.',
    inherit: false
  
  entry :version_stage, Entry::String,
    description: 'Stage of the secret version to retrieve (e.g., AWSCURRENT).',
    inherit: false
end

Step 3: Register AWS Secret Manager in Secrets Configuration

Update the secret entry class to include AWS Secrets Manager:

# In the Secret class definition

entry :aws_secret_manager, AwsSecretManager,
  description: 'AWS Secrets Manager configuration.',
  inherit: false

Step 4: Update Validation Logic

If necessary, update the validation logic to recognize AWS Secret Manager:

def validate_provider_used_once!
  used_providers = %i[vault azure_key_vault gcp_secret_manager aws_secret_manager].count do |provider|
    self[provider].present?
  end

  if used_providers != 1
    errors.add(:config, 'should use exactly one secret provider')
  end
end

Testing Plan

Step 1: Write Unit Tests for Schema Validation

# spec/lib/gitlab/ci/config/entry/secret_spec.rb

RSpec.describe Gitlab::Ci::Config::Entry::Secret do
  describe 'aws_secret_manager' do
    let(:secret) do
      described_class.new(
        name: 'DB_PASSWORD',
        config: { aws_secret_manager: aws_secret_manager_config }
      )
    end

    context 'with valid configuration' do
      let(:aws_secret_manager_config) do
        { name: 'db-password', region: 'us-east-1' }
      end

      it 'is valid' do
        expect(secret).to be_valid
      end

      context 'with optional fields' do
        let(:aws_secret_manager_config) do
          { 
            name: 'db-password', 
            region: 'us-east-1',
            version_id: 'abcdef1234567890',
            version_stage: 'AWSCURRENT' 
          }
        end

        it 'is valid' do
          expect(secret).to be_valid
        end
      end
    end

    context 'with invalid configuration' do
      context 'when name is missing' do
        let(:aws_secret_manager_config) do
          { region: 'us-east-1' }
        end

        it 'is not valid' do
          expect(secret).not_to be_valid
          expect(secret.errors[:aws_secret_manager]).to include(/name is missing/)
        end
      end

      context 'when region is missing' do
        let(:aws_secret_manager_config) do
          { name: 'db-password' }
        end

        it 'is not valid' do
          expect(secret).not_to be_valid
          expect(secret.errors[:aws_secret_manager]).to include(/region is missing/)
        end
      end
    end
  end
end

Step 2: Test Integration with CI Configuration

# spec/lib/gitlab/ci/config_spec.rb

RSpec.describe Gitlab::Ci::Config do
  context 'with aws_secret_manager' do
    let(:config_hash) do
      {
        job: {
          script: 'echo hello',
          secrets: {
            DB_PASSWORD: {
              aws_secret_manager: {
                name: 'db-password',
                region: 'us-east-1'
              }
            }
          }
        }
      }
    end

    it 'creates a valid config' do
      config = described_class.new(config_hash)
      expect(config).to be_valid
    end
  end
end

Acceptance Criteria

  • AWS Secrets Manager schema is successfully added to the CI/CD configuration system
  • Validation correctly identifies missing required fields
  • Validation allows optional fields to be omitted
  • Clear error messages are provided for validation failures
  • All tests pass
Edited by Aditya Tiwari