# frozen_string_literal: true

require 'litany/mixins'
require 'litany/resource'

module Litany
  class KMSKey < Resource

    cfn_type 'AWS::KMS::Key'

    output

    property :description, nil, [nil, String]
    property :enabled, true, [true, false]
    property :rotate_key, true, [true, false]
    property :default_admin_permissions, true, [true, false]

    child_resource IAMPolicyDocument, :policy
    child_resource KMSAlias, :alias

    def finalize_resource
      # Allow full access to root by default (some ARN *MUST* have these perms)
      if default_admin_permissions
        allow :full
      end
    end

    def allow(permission = :use, account: { Ref: 'AWS::AccountId' }, role: nil, user: nil)
      valid_permissions = [:full, :use, :read]
      raise "Permissions must be one of the following: #{valid_permissions.inspect}. Received `#{permission.inspect}`." unless valid_permissions.include?(permission)

      role_arn = nil
      if role == :instance_profile
        role_arn = ref(parent_resource.instance_profile.role, :Arn)
      elsif role == :task_role
        role_arn = ref(parent_resource.task_role, :Arn)
      elsif [:execution_role, :task_execution_role].include?(role)
        role_arn = ref(parent_resource.task_execution_role, :Arn)
      elsif role.is_a?(IAMRole)
        role_arn = ref(role, :Arn)
      end

      actions = case permission
        when :full
          'kms:*'
        when :use
          ['kms:Encrypt', 'kms:Decrypt', 'kms:ReEncrypt*', 'kms:GenerateDataKey*', 'kms:DescribeKey']
        when :read
          'kms:Decrypt'
      end

      policy.next_statement do
        actions actions
        allow_principal(account: account, role: role, user: user) if role_arn.nil?
        principal({ AWS: role_arn }) unless role_arn.nil?
        on_resource '*'
      end
    end

    def properties
      description self.name.to_s if description.nil?

      props = {
        Description: description,
        Enabled: enabled,
        EnableKeyRotation: rotate_key,
        KeyPolicy: policy
      }

      props
    end

  end
end
