require 'time'

module Serverspec::Type
  class X509PrivateKey < Base
    def valid?
      runner_res = @runner.run_command("openssl rsa -in #{name} -check -noout")
      ( runner_res.exit_status == 0 && runner_res.stdout.chomp == 'RSA key ok' )
    end

    def encrypted?
      @runner.run_command("grep -Ewq \"^(Proc-Type.*ENCRYPTED|-----BEGIN ENCRYPTED PRIVATE KEY-----)$\" #{name}").exit_status == 0
    end

    def has_matching_certificate?(cert_file)
      h1 = @runner.run_command("openssl x509 -noout -modulus -in #{cert_file}")
      h2 = @runner.run_command("openssl rsa -noout -modulus -in #{name}")
      (h1.stdout == h2.stdout) && (h1.exit_status == 0) && (h2.exit_status == 0)
    end
  end
end

require 'time'

module Serverspec::Type
  class X509PrivateKey < Base
    def valid?
      runner_res = @runner.run_command("echo | openssl rsa -in #{name} -check -noout -passin #{@options[:passin] || "stdin"}")
      ( runner_res.exit_status == 0 && runner_res.stdout.chomp == 'RSA key ok' ) && (!@options.has_key?(:passin) || encrypted?)
    end

    def encrypted?
      @runner.run_command("grep -Ewq \"^(Proc-Type.*ENCRYPTED|-----BEGIN ENCRYPTED PRIVATE KEY-----)$\" #{name}").exit_status == 0
    end

    def has_matching_certificate?(cert_file)
      h1 = @runner.run_command("openssl x509 -noout -modulus -in #{cert_file}")
      h2 = @runner.run_command("echo | openssl rsa -noout -modulus -in #{name} -passin #{@options[:passin] || "stdin"}")
      (h1.stdout == h2.stdout) && (h1.exit_status == 0) && (h2.exit_status == 0)
    end
  end
end

Add support for X.509 encrypted private key
Add support for X.509 encrypted private key

X509PrivateKey#valid?
- uses the @options[:passin] as the argument for "openssl rsa -passin" option
- if the @options[:passin] is set, it requires that the private key be encrypted
- if the @options[:passin] is not set, "echo | openssl rsa -passin stdin" is used so the check will not stop responding if the private key is encrypted and the password is not provided

X509PrivateKey#has_matching_certificate?
- uses the @options[:passin] as the argument for "openssl rsa -passin" option
- if the @options[:passin] is not set, "echo | openssl rsa -passin stdin" is used so the check will not stop responding if the private key is encrypted and the password is not provided

Usage:

description x509_private_key(KEY_FILE, {:passin => "pass:PASSPHRASE"}) do
  it { is_expected.to be_encrypted }
  it { is_expected.to be_valid }
  it { is_expected.to have_matching_certificate(crt) }
end
