Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

kms additions #731

Merged
merged 23 commits into from
Dec 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
3f89d37
add kms test lint fixes
geemus Dec 9, 2024
db1faeb
remove unused default key policy constant from KMS create key request
geemus Dec 9, 2024
010b621
minor cleanup and add first pass at schedule_key_deletion method and …
geemus Dec 9, 2024
c6c4a25
fix for schedule_key_deletion test
geemus Dec 9, 2024
13094ba
[kms] convert create_key to options hash instead of positional arguments
geemus Dec 10, 2024
48e1d83
fix mock data after options hash change
geemus Dec 10, 2024
4b91783
add KeySpec to create_key mock and expected format in tests
geemus Dec 10, 2024
351512f
first pass at get_public_key requests and mocks
geemus Dec 10, 2024
6e78c02
fix params for create_key in tests so that public_key/signing mocks w…
geemus Dec 10, 2024
d8cf0a2
size for rsa key should be cast to integer
geemus Dec 10, 2024
feeb15b
add mocks for ECC pkeys
geemus Dec 10, 2024
68e717e
first pass at kms sign request and mocks
geemus Dec 10, 2024
a6e2dab
simplify by using sign instead of sign_raw
geemus Dec 10, 2024
2812138
switch to sign_pss, hopefully compatible with 3.0
geemus Dec 10, 2024
37f60b6
fix ec curve mapping
geemus Dec 11, 2024
3e67ab0
kms: mocks - cleanup signopts, support both raw and digest signing
geemus Dec 11, 2024
13ab68e
starting to flesh out mock tests around signing/verification
geemus Dec 12, 2024
61d340a
further fleshing out/refining tests
geemus Dec 12, 2024
fe614bc
add mock table tests for signing
geemus Dec 12, 2024
828d761
get_public_key KeyId is actually ARN, also delete after sign table te…
geemus Dec 13, 2024
1dfc9e6
add missing keyspec to describe_key parser
geemus Dec 13, 2024
f21b07a
add overlooked base64 encode to sign request calls
geemus Dec 16, 2024
3040bcd
add a digest test to live+mock key tests as well
geemus Dec 16, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion lib/fog/aws/kms.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ class KMS < Fog::Service
request :list_keys
request :create_key
request :describe_key
request :get_public_key
request :schedule_key_deletion
request :sign

model_path 'fog/aws/models/kms'
model :key
Expand All @@ -30,7 +33,8 @@ def self.data
@data ||= Hash.new do |hash, region|
hash[region] = Hash.new do |region_hash, access_key|
region_hash[access_key] = {
:keys => {},
keys: {},
pkeys: {}
}
end
end
Expand Down
4 changes: 2 additions & 2 deletions lib/fog/aws/parsers/kms/describe_key.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ def start_element(name, attrs = [])

def end_element(name)
case name
when 'KeyUsage', 'AWSAccountId', 'Description', 'KeyId', 'Arn'
when 'Arn', 'AWSAccountId', 'Description', 'KeyId', 'KeySpec', 'KeyState', 'KeyUsage'
@key[name] = value
when 'CreationDate'
when 'CreationDate', 'DeletionDate'
@key[name] = Time.parse(value)
when 'Enabled'
@key[name] = (value == 'true')
Expand Down
30 changes: 30 additions & 0 deletions lib/fog/aws/parsers/kms/get_public_key.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
module Fog
module Parsers
module AWS
module KMS
class GetPublicKey < Fog::Parsers::Base
def reset
@response = {}
end

def start_element(name, attrs = [])
super
case name
when 'EncryptionAlgorithms', 'KeyAgreementAlgorithms', 'SigningAlgorithms'
@response[name] = []
end
end

def end_element(name)
case name
when 'KeyId', 'KeySpec', 'KeyUsage', 'PublicKey'
@response[name] = value
when 'EncryptionAlgorithms', 'KeyAgreementAlgorithms', 'SigningAlgorithms'
@response[name] << value
end
end
end
end
end
end
end
28 changes: 28 additions & 0 deletions lib/fog/aws/parsers/kms/schedule_key_deletion.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
module Fog
module Parsers
module AWS
module KMS
class ScheduleKeyDeletion < Fog::Parsers::Base
def reset
@response = {}
end

def start_element(name, attrs = [])
super
end

def end_element(name)
case name
when 'DeletionDate'
@response[name] = Time.parse(value)
when 'KeyId', 'KeyState'
@response[name] = value
when 'PendingWindowInDays'
@response[name] = value.to_i
end
end
end
end
end
end
end
24 changes: 24 additions & 0 deletions lib/fog/aws/parsers/kms/sign.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
module Fog
module Parsers
module AWS
module KMS
class Sign < Fog::Parsers::Base
def reset
@response = {}
end

def start_element(name, attrs = [])
super
end

def end_element(name)
case name
when 'KeyId', 'Signature', 'SigningAlgorithm'
@response[name] = value
end
end
end
end
end
end
end
110 changes: 74 additions & 36 deletions lib/fog/aws/requests/kms/create_key.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,61 +2,99 @@ module Fog
module AWS
class KMS
class Real
DEFAULT_KEY_POLICY = <<-JSON
{
"Version": "2012-10-17",
"Id": "key-default-1",
"Statement": [
{
"Sid": "Enable IAM User Permissions",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::915445820265:root"
},
"Action": "kms:*",
"Resource": "*"
}
]
}
JSON

require 'fog/aws/parsers/kms/describe_key'

def create_key(policy = nil, description = nil, usage = "ENCRYPT_DECRYPT")
request(
'Action' => 'CreateKey',
'Description' => description,
'KeyUsage' => usage,
'Policy' => policy,
:parser => Fog::Parsers::AWS::KMS::DescribeKey.new
)
# Create Key
#
# ==== Parameters
# * options<~Hash>:
# * 'Description'<~String>:
# * 'KeyUsage'<~String>:
# * 'Policy'<~String>:
# * ... (see docs from see also)
#
# === Returns
#
# ==== See Also
# https://docs.aws.amazon.com/kms/latest/APIReference/API_CreateKey.html
def create_key(*args)
options = Fog::AWS::KMS.parse_create_key_args(args)
request({
'Action' => 'CreateKey',
:parser => Fog::Parsers::AWS::KMS::DescribeKey.new
}.merge!(options))
end
end

class Mock
def create_key(policy = nil, description = nil, usage = "ENCRYPT_DECRYPT")
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 = {
"KeyUsage" => usage,
"AWSAccountId" => self.account_id,
"KeyId" => key_id,
"Description" => description,
"CreationDate" => Time.now,
"Arn" => key_arn,
"Enabled" => true,
}
'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

response.body = { "KeyMetadata" => 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
end

# previous args (policy, description, usage) was deprecated in favor of a hash of options
def self.parse_create_key_args(args)
case args.size
when 0
{}
when 1
if args[0].is_a?(Hash)
args[0]
else
Fog::Logger.deprecation("create_key with distinct arguments is deprecated, use options hash instead [light_black](#{caller.first})[/]")
{
'Policy' => args[0]
}
end
when 2, 3
Fog::Logger.deprecation("create_key with distinct arguments is deprecated, use options hash instead [light_black](#{caller.first})[/]")
{
'Policy' => args[0],
'Description' => args[1],
'KeyUsage' => args[2] || 'ENCRYPT_DECRYPT'
}
else
raise "Unknown argument style: #{args.inspect}, use options hash instead."
end
end
end
end
end
35 changes: 35 additions & 0 deletions lib/fog/aws/requests/kms/get_public_key.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
module Fog
module AWS
class KMS
class Real
require 'fog/aws/parsers/kms/get_public_key'

def get_public_key(identifier, grant_tokens = nil)
request(
'Action' => 'GetPublicKey',
'GrantTokens' => grant_tokens,
'KeyId' => identifier,
:parser => Fog::Parsers::AWS::KMS::GetPublicKey.new
)
end
end

class Mock
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
end
end
end
end
7 changes: 3 additions & 4 deletions lib/fog/aws/requests/kms/list_keys.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ module Fog
module AWS
class KMS
class Real

require 'fog/aws/parsers/kms/list_keys'

def list_keys(options={})
Expand Down Expand Up @@ -43,9 +42,9 @@ def list_keys(options={})
key_set = if marker
self.data[:markers][marker] || []
else
self.data[:keys].inject([]) { |r,(k,v)|
r << { "KeyId" => k, "KeyArn" => v["Arn"] }
}
self.data[:keys].inject([]) do |r, (k, v)|
r << { 'KeyArn' => v['Arn'], 'KeyId' => k }
end
end

keys = if limit
Expand Down
37 changes: 37 additions & 0 deletions lib/fog/aws/requests/kms/schedule_key_deletion.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
module Fog
module AWS
class KMS
class Real
require 'fog/aws/parsers/kms/schedule_key_deletion'

def schedule_key_deletion(identifier, pending_window_in_days)
request(
'Action' => 'ScheduleKeyDeletion',
'KeyId' => identifier,
'PendingWindowInDays' => pending_window_in_days,
:parser => Fog::Parsers::AWS::KMS::ScheduleKeyDeletion.new
)
end
end

class Mock
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
end
end
end
end
Loading
Loading