#
# Copyright:: Chef Software, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

require_relative 'preflight_checks'

class SslPreflightValidator < PreflightValidator
  def initialize(node)
    super
    @user_config = PrivateChef['nginx']
  end

  def run!
    validate_fips
    verify_cert_pair
  end

  def validate_fips
    if PrivateChef['fips'] && !fips_supported_ssl?
      fail_with <<~EOF
        You have enabled FIPS-mode in #{ChefUtils::Dist::Server::SERVER}.rb but FIPS does not appear
        to be supported on this platform.

        #{openssl_exe} reported its version as:

            #{openssl_version}

        which does not contain the expected -fips identifier.
      EOF
    end
  end

  def openssl_exe
    "/opt/#{ChefUtils::Dist::Org::LEGACY_CONF_DIR}/embedded/bin/openssl"
  end

  def openssl_version
    @openssl_version ||= begin
                           `#{openssl_exe} list -providers`
                         rescue
                           'unknown'
                         end
  end

  def fips_supported_ssl?
    output = openssl_version
    return true if output =~ /^unknown/ # Handle unknown case

    # Check for FIPS provider in multi-line output
    return true if output =~ /OpenSSL FIPS Provider.*\n.*version: 3.2.4.*\n.*status: active/m

    # Keep existing -fips check
    return true if output =~ /OpenSSL .*-fips/

    false
  end

  def verify_cert_pair
    cert = @user_config['ssl_certificate']
    key  = @user_config['ssl_certificate_key']
    if !cert.nil? && key.nil?
      fail_with <<~EOF
        Your configuration has specified

        nginx['ssl_certificate'] = "#{cert}"

        but has not specified nginx['ssl_certificate_key'].  You must specify
        both configuration options or neither.
      EOF
    elsif cert.nil? && !key.nil?
      fail_with <<~EOF
        Your configuration has specified

        nginx['ssl_certificate_key'] = "#{key}"

        but has not specified nginx['ssl_certificate'].  You must specify
        both configuration options or neither.
      EOF
    end
  end
end
