summaryrefslogtreecommitdiff
path: root/lib/chef/resource/openssl_x509_crl.rb
blob: a04ef2e5e21c343bda6de35a8195ce9f63a69a36 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#
# License:: Apache License, Version 2.0
# Author:: Julien Huon
# Copyright:: Copyright 2018, 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 "../resource"

class Chef
  class Resource
    class OpensslX509Crl < Chef::Resource
      require_relative "../mixin/openssl_helper"
      include Chef::Mixin::OpenSSLHelper

      resource_name :openssl_x509_crl

      description "Use the openssl_x509_crl resource to generate PEM-formatted x509 certificate revocation list (CRL) files."
      introduced "14.4"

      property :path, String,
               description: "An optional property for specifying the path to write the file to if it differs from the resource block's name.",
               name_property: true

      property :serial_to_revoke, [Integer, String],
               description: "Serial of the X509 Certificate to revoke."

      property :revocation_reason, Integer,
               description: "Reason for the revocation.",
               default: 0

      property :expire, Integer,
               description: "Value representing the number of days from now through which the issued CRL will remain valid. The CRL will expire after this period.",
               default: 8

      property :renewal_threshold, Integer,
               description: "Number of days before the expiration. It this threshold is reached, the CRL will be renewed.",
               default: 1

      property :ca_cert_file, String,
               description: "The path to the CA X509 Certificate on the filesystem. If the ca_cert_file property is specified, the ca_key_file property must also be specified, the CRL will be signed with them.",
               required: true

      property :ca_key_file, String,
               description: "The path to the CA private key on the filesystem. If the ca_key_file property is specified, the ca_cert_file property must also be specified, the CRL will be signed with them.",
               required: true

      property :ca_key_pass, String,
               description: "The passphrase for CA private key's passphrase."

      property :owner, [String, Integer],
               description: "The owner permission for the CRL file."

      property :group, [String, Integer],
               description: "The group permission for the CRL file."

      property :mode, [Integer, String],
               description: "The permission mode of the CRL file."

      action :create do
        description "Create the CRL file."

        file new_resource.path do
          owner new_resource.owner unless new_resource.owner.nil?
          group new_resource.group unless new_resource.group.nil?
          mode new_resource.mode unless new_resource.mode.nil?
          content crl.to_pem
          action :create
        end
      end

      action_class do
        def crl_info
          # Will contain issuer & expiration
          crl_info = {}

          crl_info["issuer"] = ::OpenSSL::X509::Certificate.new ::File.read(new_resource.ca_cert_file)
          crl_info["validity"] = new_resource.expire

          crl_info
        end

        def revoke_info
          # Will contain Serial to revoke & reason
          revoke_info = {}

          revoke_info["serial"] = new_resource.serial_to_revoke
          revoke_info["reason"] = new_resource.revocation_reason

          revoke_info
        end

        def ca_private_key
          ca_private_key = ::OpenSSL::PKey.read ::File.read(new_resource.ca_key_file), new_resource.ca_key_pass
          ca_private_key
        end

        def crl
          if crl_file_valid?(new_resource.path)
            crl = ::OpenSSL::X509::CRL.new ::File.read(new_resource.path)
          else
            log "Creating a CRL #{new_resource.path} for CA #{new_resource.ca_cert_file}"
            crl = gen_x509_crl(ca_private_key, crl_info)
          end

          if !new_resource.serial_to_revoke.nil? && serial_revoked?(crl, new_resource.serial_to_revoke) == false
            log "Revoking serial #{new_resource.serial_to_revoke} in CRL #{new_resource.path}"
            crl = revoke_x509_crl(revoke_info, crl, ca_private_key, crl_info)
          elsif crl.next_update <= Time.now + 3600 * 24 * new_resource.renewal_threshold
            log "Renewing CRL for CA #{new_resource.ca_cert_file}"
            crl = renew_x509_crl(crl, ca_private_key, crl_info)
          end

          crl
        end
      end

    end
  end
end