class Fog::AWS::KMS::Mock

Attributes

account_id[R]

Public Class Methods

data() click to toggle source
# File lib/fog/aws/kms.rb, line 32
def self.data
  @data ||= Hash.new do |hash, region|
    hash[region] = Hash.new do |region_hash, access_key|
      region_hash[access_key] = {
        keys: {},
        pkeys: {}
      }
    end
  end
end
new(options={}) click to toggle source
# File lib/fog/aws/kms.rb, line 49
def initialize(options={})
  @use_iam_profile = options[:use_iam_profile]
  @account_id = Fog::AWS::Mock.owner_id

  @region = options[:region] || 'us-east-1'
  setup_credentials(options)

  Fog::AWS.validate_region!(@region)
end
reset() click to toggle source
# File lib/fog/aws/kms.rb, line 43
def self.reset
  data.clear
end

Public Instance Methods

create_key(*args) click to toggle source
# File lib/fog/aws/requests/kms/create_key.rb, line 30
def create_key(*args)
  options = Fog::AWS::KMS.parse_create_key_args(args)

  response = Excon::Response.new
  key_id   = UUID.uuid
  key_arn  = Fog::AWS::Mock.arn("kms", self.account_id, "key/#{key_id}", @region)

  key = {
    'Arn' => key_arn,
    'AWSAccountId' => self.account_id,
    'CreationDate' => Time.now.utc,
    'DeletionDate' => nil,
    'Description' => nil,
    'Enabled' => true,
    'KeyId' => key_id,
    'KeySpec' => 'SYMMETRIC_DEFAULT',
    'KeyState' => 'Enabled',
    'KeyUsage' => 'ENCRYPT_DECRYPT',
    'Policy' => nil
  }.merge!(options)

  # @todo use default policy

  self.data[:keys][key_id] = key

  klass, arg = {
    'ECC_NIST_P256' => [OpenSSL::PKey::EC, 'prime256v1'],
    'ECC_NIST_P384' => [OpenSSL::PKey::EC, 'secp384r1'],
    'ECC_NIST_P521' => [OpenSSL::PKey::EC, 'secp521r1'],
    'ECC_SECG_P256K1' => [OpenSSL::PKey::EC, 'secp256k1'],
    'RSA_2048' => [OpenSSL::PKey::RSA, 2048],
    'RSA_3072' => [OpenSSL::PKey::RSA, 3072],
    'RSA_4096' => [OpenSSL::PKey::RSA, 4096]
  }[key['KeySpec']]
  raise "Unknown or not-yet-implemented #{key['KeySpec']} KeySpec for kms create_key mocks" unless klass

  self.data[:pkeys][key_id] = klass.generate(arg)

  response.body = { 'KeyMetadata' => key }
  response
end
data() click to toggle source
# File lib/fog/aws/kms.rb, line 66
def data
  self.class.data[@region][@aws_access_key_id]
end
describe_key(identifier) click to toggle source
# File lib/fog/aws/requests/kms/describe_key.rb, line 17
def describe_key(identifier)
  response = Excon::Response.new
  key = self.data[:keys][identifier]

  response.body = { "KeyMetadata" => key }
  response
end
get_public_key(identifier, _grant_tokens = []) click to toggle source
# File lib/fog/aws/requests/kms/get_public_key.rb, line 18
def get_public_key(identifier, _grant_tokens = [])
  response = Excon::Response.new
  key = self.data[:keys][identifier]
  pkey = self.data[:pkeys][identifier]

  response.body = {
    'KeyId' => key['Arn'],
    'KeyUsage' => key['KeyUsage'],
    'KeySpec' => key['KeySpec'],
    'PublicKey' => Base64.strict_encode64(pkey.public_to_der),
    'SigningAlgorithms' => key['SigningAlgorithms']
  }
  response
end
list_keys(options={}) click to toggle source
# File lib/fog/aws/requests/kms/list_keys.rb, line 26
def list_keys(options={})
  limit  = options[:limit]
  marker = options[:marker]

  if limit
    if limit > 1_000
      raise Fog::AWS::KMS::Error.new(
        "ValidationError => 1 validation error detected: Value '#{limit}' at 'limit' failed to satisfy constraint: Member must have value less than or equal to 1000"
      )
    elsif limit <  1
      raise Fog::AWS::KMS::Error.new(
        "ValidationError => 1 validation error detected: Value '#{limit}' at 'limit' failed to satisfy constraint: Member must have value greater than or equal to 1"
      )
    end
  end

  key_set = if marker
              self.data[:markers][marker] || []
            else
              self.data[:keys].inject([]) do |r, (k, v)|
                r << { 'KeyArn' => v['Arn'], 'KeyId' => k }
              end
            end

  keys = if limit
           key_set.slice!(0, limit)
         else
           key_set
         end

  truncated = keys.size < key_set.size

  marker = truncated && "metadata/l/#{account_id}/#{UUID.uuid}"

  response = Excon::Response.new

  body = {
    'Keys'      => keys,
    'Truncated' => truncated,
    'RequestId' => Fog::AWS::Mock.request_id
  }

  if marker
    self.data[:markers][marker] = key_set
    body.merge!('Marker' => marker)
  end

  response.body = body
  response.status = 200

  response
end
reset_data() click to toggle source
# File lib/fog/aws/kms.rb, line 70
def reset_data
  self.class.data[@region].delete(@aws_access_key_id)
end
schedule_key_deletion(identifier, pending_window_in_days) click to toggle source
# File lib/fog/aws/requests/kms/schedule_key_deletion.rb, line 18
def schedule_key_deletion(identifier, pending_window_in_days)
  response = Excon::Response.new
  key = self.data[:keys][identifier]

  key['DeletionDate'] = Time.now + (60 * 60 * 24 * pending_window_in_days)
  key['Enabled'] = false
  key['KeyState'] = 'PendingDeletion'

  response.body = {
    'DeletionDate' => key['DeletionDate'],
    'KeyId' => key['KeyId'],
    'KeyState' => key['KeyState'],
    'PendingWindowInDays' => pending_window_in_days
  }
  response
end
setup_credentials(options) click to toggle source
# File lib/fog/aws/kms.rb, line 59
def setup_credentials(options)
  @aws_access_key_id     = options[:aws_access_key_id]
  @aws_secret_access_key = options[:aws_secret_access_key]

  @signer = Fog::AWS::SignatureV4.new(@aws_access_key_id, @aws_secret_access_key, @region, 'kms')
end
sign(identifier, message, algorithm, options = {}) click to toggle source
# File lib/fog/aws/requests/kms/sign.rb, line 31
def sign(identifier, message, algorithm, options = {})
  response = Excon::Response.new
  pkey = self.data[:pkeys][identifier]
  unless pkey
    response.status = 404
    raise(Excon::Errors.status_error({ expects: 200 }, response))
  end

  data = Base64.decode64(message)

  # FIXME: SM2 support?
  sha = "SHA#{algorithm.split('_SHA_').last}"
  signopts = {}
  signopts[:rsa_padding_mode] = 'pss' if algorithm.start_with?('RSASSA_PSS')

  signature = if options['MessageType'] == 'DIGEST'
                pkey.sign_raw(sha, data, signopts)
              else
                pkey.sign(sha, data, signopts)
              end

  response.body = {
    'KeyId' => identifier,
    'Signature' => Base64.strict_encode64(signature),
    'SigningAlgorithm' => algorithm
  }
  response
end