Class: Azure::Certificate
- Inherits:
-
Object
- Object
- Azure::Certificate
- Defined in:
- lib/azure/service_management/certificate.rb
Instance Attribute Summary collapse
-
#cert_data ⇒ Object
Returns the value of attribute cert_data.
-
#certificate_version ⇒ Object
Returns the value of attribute certificate_version.
-
#connection ⇒ Object
Returns the value of attribute connection.
-
#fingerprint ⇒ Object
Returns the value of attribute fingerprint.
Instance Method Summary collapse
- #add_certificate(certificate_data, certificate_password, certificate_format, dns_name) ⇒ Object
- #create(params) ⇒ Object
-
#create_ssl_certificate(cert_params) ⇒ Object
SSL certificate generation for knife-azure ssl bootstrap ######.
- #generate_certificate(rsa_key, cert_params) ⇒ Object
- #generate_keypair(key_length) ⇒ Object
- #generate_public_key_certificate_data(params) ⇒ Object
- #get_certificate(dns_name, fingerprint) ⇒ Object
-
#initialize(connection) ⇒ Certificate
constructor
A new instance of Certificate.
- #prompt_for_domain ⇒ Object
- #prompt_for_file_path ⇒ Object
- #prompt_for_passphrase ⇒ Object
- #write_certificate_to_file(cert, file_path, rsa_key, cert_params) ⇒ Object
Constructor Details
#initialize(connection) ⇒ Certificate
Returns a new instance of Certificate.
53 54 55 56 |
# File 'lib/azure/service_management/certificate.rb', line 53 def initialize(connection) @connection = connection @certificate_version = 2 # cf. RFC 5280 - to make it a "v3" certificate end |
Instance Attribute Details
#cert_data ⇒ Object
Returns the value of attribute cert_data.
52 53 54 |
# File 'lib/azure/service_management/certificate.rb', line 52 def cert_data @cert_data end |
#certificate_version ⇒ Object
Returns the value of attribute certificate_version.
52 53 54 |
# File 'lib/azure/service_management/certificate.rb', line 52 def certificate_version @certificate_version end |
#connection ⇒ Object
Returns the value of attribute connection.
51 52 53 |
# File 'lib/azure/service_management/certificate.rb', line 51 def connection @connection end |
#fingerprint ⇒ Object
Returns the value of attribute fingerprint.
52 53 54 |
# File 'lib/azure/service_management/certificate.rb', line 52 def fingerprint @fingerprint end |
Instance Method Details
#add_certificate(certificate_data, certificate_password, certificate_format, dns_name) ⇒ Object
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 |
# File 'lib/azure/service_management/certificate.rb', line 97 def add_certificate(certificate_data, certificate_password, certificate_format, dns_name) # Generate XML to call the API # Add certificate to the hosted service builder = Nokogiri::XML::Builder.new do |xml| xml.CertificateFile("xmlns" => "http://schemas.microsoft.com/windowsazure") do xml.Data certificate_data xml.CertificateFormat certificate_format xml.Password certificate_password end end # Windows Azure API call @connection.query_azure("hostedservices/#{dns_name}/certificates", "post", builder.to_xml) # Check if certificate is available else raise error for attempt in 0..4 Chef::Log.info "Waiting to get certificate ..." res = get_certificate(dns_name, @fingerprint) break unless res.empty? if attempt == 4 raise "The certificate with thumbprint #{fingerprint} was not found." else sleep 5 end end end |
#create(params) ⇒ Object
58 59 60 61 62 63 64 65 66 67 |
# File 'lib/azure/service_management/certificate.rb', line 58 def create(params) # If RSA private key has been specified, then generate an x 509 certificate from the # public part of the key @cert_data = generate_public_key_certificate_data({ ssh_key: params[:ssh_identity_file], ssh_key_passphrase: params[:identity_file_passphrase] }) add_certificate @cert_data, "knifeazure", "pfx", params[:azure_dns_name] # Return the fingerprint to be used while adding role @fingerprint end |
#create_ssl_certificate(cert_params) ⇒ Object
SSL certificate generation for knife-azure ssl bootstrap ######
128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 |
# File 'lib/azure/service_management/certificate.rb', line 128 def create_ssl_certificate(cert_params) file_path = cert_params[:output_file].sub(/\.(\w+)$/, "") path = prompt_for_file_path file_path = File.join(path, file_path) unless path.empty? cert_params[:domain] = prompt_for_domain rsa_key = generate_keypair cert_params[:key_length] cert = generate_certificate(rsa_key, cert_params) write_certificate_to_file cert, file_path, rsa_key, cert_params puts "*" * 70 puts "Generated Certificates:" puts "- #{file_path}.pfx - PKCS12 format keypair. Contains both the public and private keys, usually used on the server." puts "- #{file_path}.b64 - Base64 encoded PKCS12 keypair. Contains both the public and private keys, for upload to the Azure REST API." puts "- #{file_path}.pem - Base64 encoded public certificate only. Required by the client to connect to the server." puts "Certificate Thumbprint: #{@thumbprint.to_s.upcase}" puts "*" * 70 Chef::Config[:knife][:ca_trust_file] = file_path + ".pem" if Chef::Config[:knife][:ca_trust_file].nil? cert_data = File.read (file_path + ".b64") add_certificate cert_data, @winrm_cert_passphrase, "pfx", cert_params[:azure_dns_name] @thumbprint end |
#generate_certificate(rsa_key, cert_params) ⇒ Object
197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 |
# File 'lib/azure/service_management/certificate.rb', line 197 def generate_certificate(rsa_key, cert_params) @hostname = "*" if cert_params[:domain] @hostname = "*." + cert_params[:domain] end # Create a self-signed X509 certificate from the rsa_key (unencrypted) cert = OpenSSL::X509::Certificate.new cert.version = 2 cert.serial = Random.rand(65534) + 1 # 2 digit byte range random number for better security aspect cert.subject = OpenSSL::X509::Name.parse "/CN=#{@hostname}" cert.issuer = cert.subject cert.public_key = rsa_key.public_key cert.not_before = Time.now cert.not_after = cert.not_before + 2 * 365 * cert_params[:cert_validity].to_i * 60 * 60 # 2 years validity ef = OpenSSL::X509::ExtensionFactory.new ef.subject_certificate = cert ef.issuer_certificate = cert cert.add_extension(ef.create_extension("subjectKeyIdentifier", "hash", false)) cert.add_extension(ef.create_extension("authorityKeyIdentifier", "keyid:always", false)) cert.add_extension(ef.create_extension("extendedKeyUsage", "1.3.6.1.5.5.7.3.1", false)) cert.sign(rsa_key, OpenSSL::Digest::SHA1.new) @thumbprint = OpenSSL::Digest::SHA1.new(cert.to_der) cert end |
#generate_keypair(key_length) ⇒ Object
151 152 153 |
# File 'lib/azure/service_management/certificate.rb', line 151 def generate_keypair(key_length) OpenSSL::PKey::RSA.new(key_length.to_i) end |
#generate_public_key_certificate_data(params) ⇒ Object
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 |
# File 'lib/azure/service_management/certificate.rb', line 69 def generate_public_key_certificate_data(params) # Generate OpenSSL RSA key from the mentioned ssh key path (and passphrase) key = OpenSSL::PKey::RSA.new(File.read(params[:ssh_key]), params[:ssh_key_passphrase]) # Generate X 509 certificate ca = OpenSSL::X509::Certificate.new ca.version = @certificate_version ca.serial = Random.rand(65534) + 1 # 2 digit byte range random number for better security aspect ca.subject = OpenSSL::X509::Name.parse "/DC=org/DC=knife-plugin/CN=Opscode CA" ca.issuer = ca.subject # root CA's are "self-signed" ca.public_key = key.public_key # Assign the ssh-key's public part to the certificate ca.not_before = Time.now ca.not_after = ca.not_before + 2 * 365 * 24 * 60 * 60 # 2 years validity ef = OpenSSL::X509::ExtensionFactory.new ef.subject_certificate = ca ef.issuer_certificate = ca ca.add_extension(ef.create_extension("basicConstraints", "CA:TRUE", true)) ca.add_extension(ef.create_extension("keyUsage", "keyCertSign, cRLSign", true)) ca.add_extension(ef.create_extension("subjectKeyIdentifier", "hash", false)) ca.add_extension(ef.create_extension("authorityKeyIdentifier", "keyid:always", false)) ca.sign(key, OpenSSL::Digest::SHA256.new) # Generate the SHA1 fingerprint of the der format of the X 509 certificate @fingerprint = OpenSSL::Digest::SHA1.new(ca.to_der) # Create the pfx format of the certificate pfx = OpenSSL::PKCS12.create("knifeazure", "knife-azure-pfx", key, ca) # Encode the pfx format - upload this certificate Base64.strict_encode64(pfx.to_der) end |
#get_certificate(dns_name, fingerprint) ⇒ Object
123 124 125 |
# File 'lib/azure/service_management/certificate.rb', line 123 def get_certificate(dns_name, fingerprint) @connection.query_azure("hostedservices/#{dns_name}/certificates/sha1-#{fingerprint}", "get").search("Certificate") end |
#prompt_for_domain ⇒ Object
185 186 187 188 189 190 191 192 193 194 195 |
# File 'lib/azure/service_management/certificate.rb', line 185 def prompt_for_domain counter = 0 begin print "Enter the domain (mandatory):" domain = STDIN.gets domain = domain.strip counter += 1 exit(1) if counter == 3 end until !domain.empty? domain end |
#prompt_for_file_path ⇒ Object
169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 |
# File 'lib/azure/service_management/certificate.rb', line 169 def prompt_for_file_path file_path = "" counter = 0 begin print "Invalid location! \n" unless file_path.empty? print 'Enter the file path for certificates e.g. C:\Windows (empty for current location):' file_path = STDIN.gets stripped_file_path = file_path.strip return stripped_file_path if file_path == "\n" counter += 1 exit(1) if counter == 3 end until File.directory?(stripped_file_path) stripped_file_path end |
#prompt_for_passphrase ⇒ Object
155 156 157 158 159 160 161 162 163 164 165 166 167 |
# File 'lib/azure/service_management/certificate.rb', line 155 def prompt_for_passphrase passphrase = "" begin print "Passphrases do not match. Try again.\n" unless passphrase.empty? print "Enter certificate passphrase (empty for no passphrase):" passphrase = STDIN.gets return passphrase.strip if passphrase == "\n" print "Enter same passphrase again:" confirm_passphrase = STDIN.gets end until passphrase == confirm_passphrase passphrase.strip end |
#write_certificate_to_file(cert, file_path, rsa_key, cert_params) ⇒ Object
224 225 226 227 228 229 230 |
# File 'lib/azure/service_management/certificate.rb', line 224 def write_certificate_to_file(cert, file_path, rsa_key, cert_params) File.open(file_path + ".pem", "wb") { |f| f.print cert.to_pem } @winrm_cert_passphrase = prompt_for_passphrase unless @winrm_cert_passphrase pfx = OpenSSL::PKCS12.create("#{cert_params[:winrm_cert_passphrase]}", "winrmcert", rsa_key, cert) File.open(file_path + ".pfx", "wb") { |f| f.print pfx.to_der } File.open(file_path + ".b64", "wb") { |f| f.print Base64.strict_encode64(pfx.to_der) } end |