mirror of
				https://github.com/ansible-collections/community.general.git
				synced 2025-10-24 21:14:00 -07:00 
			
		
		
		
	openssl_*: Allow user to specify privatekey passphrase
Allow a user to specify the privatekey passphrase when dealing with openssl modules.
This commit is contained in:
		
					parent
					
						
							
								a260063ffd
							
						
					
				
			
			
				commit
				
					
						f40db199aa
					
				
			
		
					 4 changed files with 66 additions and 12 deletions
				
			
		|  | @ -26,12 +26,14 @@ except ImportError: | |||
| import hashlib | ||||
| 
 | ||||
| 
 | ||||
| def get_fingerprint(path): | ||||
| def get_fingerprint(path, passphrase): | ||||
|     """Generate the fingerprint of the public key. """ | ||||
| 
 | ||||
|     fingerprint = {} | ||||
| 
 | ||||
|     privatekey = crypto.load_privatekey(crypto.FILETYPE_PEM, open(path, 'r').read()) | ||||
|     privatekey = crypto.load_privatekey(crypto.FILETYPE_PEM, | ||||
|                                         open(path, 'rb').read(), | ||||
|                                         passphrase) | ||||
| 
 | ||||
|     try: | ||||
|         publickey = crypto.dump_publickey(crypto.FILETYPE_ASN1, privatekey) | ||||
|  |  | |||
|  | @ -50,6 +50,11 @@ options: | |||
|         required: true | ||||
|         description: | ||||
|             - Path to the privatekey to use when signing the certificate signing request | ||||
|     privatekey_passphrase: | ||||
|         required: false | ||||
|         description: | ||||
|             - The passphrase for the privatekey. | ||||
|         version_added: "2.4" | ||||
|     version: | ||||
|         required: false | ||||
|         default: 3 | ||||
|  | @ -114,6 +119,14 @@ EXAMPLES = ''' | |||
|     privatekey_path: /etc/ssl/private/ansible.com.pem | ||||
|     commonName: www.ansible.com | ||||
| 
 | ||||
| # Generate an OpenSSL Certificate Signing Request with a | ||||
| # passphrase protected private key | ||||
| - openssl_csr: | ||||
|     path: /etc/ssl/csr/www.ansible.com.csr | ||||
|     privatekey_path: /etc/ssl/private/ansible.com.pem | ||||
|     privatekey_passphrase: ansible | ||||
|     commonName: www.ansible.com | ||||
| 
 | ||||
| # Generate an OpenSSL Certificate Signing Request with Subject information | ||||
| - openssl_csr: | ||||
|     path: /etc/ssl/csr/www.ansible.com.csr | ||||
|  | @ -183,6 +196,7 @@ class CertificateSigningRequest(object): | |||
|         self.subjectAltName = module.params['subjectAltName'] | ||||
|         self.path = module.params['path'] | ||||
|         self.privatekey_path = module.params['privatekey_path'] | ||||
|         self.privatekey_passphrase = module.params['privatekey_passphrase'] | ||||
|         self.version = module.params['version'] | ||||
|         self.changed = True | ||||
|         self.request = None | ||||
|  | @ -218,8 +232,9 @@ class CertificateSigningRequest(object): | |||
|                 req.add_extensions([crypto.X509Extension(b"subjectAltName", False, self.subjectAltName.encode('ascii'))]) | ||||
| 
 | ||||
|             privatekey_content = open(self.privatekey_path).read() | ||||
|             self.privatekey = crypto.load_privatekey(crypto.FILETYPE_PEM, privatekey_content) | ||||
| 
 | ||||
|             self.privatekey = crypto.load_privatekey(crypto.FILETYPE_PEM, | ||||
|                                                      privatekey_content, | ||||
|                                                      self.privatekey_passphrase) | ||||
|             req.set_pubkey(self.privatekey) | ||||
|             req.sign(self.privatekey, self.digest) | ||||
|             self.request = req | ||||
|  | @ -267,6 +282,7 @@ def main(): | |||
|             state=dict(default='present', choices=['present', 'absent'], type='str'), | ||||
|             digest=dict(default='sha256', type='str'), | ||||
|             privatekey_path=dict(require=True, type='path'), | ||||
|             privatekey_passphrase=dict(type='str', no_log=True), | ||||
|             version=dict(default='3', type='int'), | ||||
|             force=dict(default=False, type='bool'), | ||||
|             subjectAltName=dict(aliases=['subjectAltName'], type='str'), | ||||
|  |  | |||
|  | @ -62,14 +62,30 @@ options: | |||
|         required: true | ||||
|         description: | ||||
|             - Name of the file in which the generated TLS/SSL private key will be written. It will have 0600 mode. | ||||
|     passphrase: | ||||
|         required: false | ||||
|         description: | ||||
|             - The passphrase for the private key. | ||||
|         version_added: "2.4" | ||||
|     cipher: | ||||
|         required: false | ||||
|         description: | ||||
|             - The cipher to encrypt the private key. (cipher can be found by running `openssl list-cipher-algorithms`) | ||||
|         version_added: "2.4" | ||||
| ''' | ||||
| 
 | ||||
| EXAMPLES = ''' | ||||
| # Generate an OpenSSL private key with the default values (4096 bits, RSA) | ||||
| # and no public key | ||||
| - openssl_privatekey: | ||||
|     path: /etc/ssl/private/ansible.com.pem | ||||
| 
 | ||||
| # Generate an OpenSSL private key with the default values (4096 bits, RSA) | ||||
| # and a passphrase | ||||
| - openssl_privatekey: | ||||
|     path: /etc/ssl/private/ansible.com.pem | ||||
|     passphrase: ansible | ||||
|     cipher: aes256 | ||||
| 
 | ||||
| # Generate an OpenSSL private key with a different size (2048 bits) | ||||
| - openssl_privatekey: | ||||
|     path: /etc/ssl/private/ansible.com.pem | ||||
|  | @ -145,13 +161,14 @@ class PrivateKey(object): | |||
|         self.type = module.params['type'] | ||||
|         self.force = module.params['force'] | ||||
|         self.path = module.params['path'] | ||||
|         self.passphrase = module.params['passphrase'] | ||||
|         self.cipher = module.params['cipher'] | ||||
|         self.mode = module.params['mode'] | ||||
|         self.changed = True | ||||
|         self.privatekey = None | ||||
|         self.fingerprint = {} | ||||
|         self.check_mode = module.check_mode | ||||
| 
 | ||||
| 
 | ||||
|     def generate(self, module): | ||||
|         """Generate a keypair.""" | ||||
| 
 | ||||
|  | @ -173,7 +190,11 @@ class PrivateKey(object): | |||
|                                           os.O_WRONLY | os.O_CREAT | os.O_TRUNC, | ||||
|                                           self.mode) | ||||
| 
 | ||||
|                 os.write(privatekey_file, crypto.dump_privatekey(crypto.FILETYPE_PEM, self.privatekey)) | ||||
|                 extras = {} | ||||
|                 if self.cipher and self.passphrase: | ||||
|                     extras = {'cipher': self.cipher, 'passphrase': self.passphrase} | ||||
| 
 | ||||
|                 os.write(privatekey_file, crypto.dump_privatekey(crypto.FILETYPE_PEM, self.privatekey, **extras)) | ||||
|                 os.close(privatekey_file) | ||||
|             except IOError as exc: | ||||
|                 self.remove() | ||||
|  | @ -181,12 +202,11 @@ class PrivateKey(object): | |||
|         else: | ||||
|             self.changed = False | ||||
| 
 | ||||
|         self.fingerprint = get_fingerprint(self.path) | ||||
|         self.fingerprint = get_fingerprint(self.path, self.passphrase) | ||||
|         file_args = module.load_file_common_arguments(module.params) | ||||
|         if module.set_fs_attributes_if_different(file_args, False): | ||||
|             self.changed = True | ||||
| 
 | ||||
| 
 | ||||
|     def remove(self): | ||||
|         """Remove the private key from the filesystem.""" | ||||
| 
 | ||||
|  | @ -198,7 +218,6 @@ class PrivateKey(object): | |||
|             else: | ||||
|                 self.changed = False | ||||
| 
 | ||||
| 
 | ||||
|     def dump(self): | ||||
|         """Serialize the object into a dictionary.""" | ||||
| 
 | ||||
|  | @ -222,9 +241,12 @@ def main(): | |||
|             type=dict(default='RSA', choices=['RSA', 'DSA'], type='str'), | ||||
|             force=dict(default=False, type='bool'), | ||||
|             path=dict(required=True, type='path'), | ||||
|             passphrase=dict(type='str', no_log=True), | ||||
|             cipher=dict(type='str'), | ||||
|         ), | ||||
|         supports_check_mode = True, | ||||
|         add_file_common_args = True, | ||||
|         required_together=[['cipher', 'passphrase']], | ||||
|     ) | ||||
| 
 | ||||
|     if not pyopenssl_found: | ||||
|  |  | |||
|  | @ -62,6 +62,11 @@ options: | |||
|         required: true | ||||
|         description: | ||||
|             - Path to the TLS/SSL private key from which to generate the public key. | ||||
|     privatekey_passphrase: | ||||
|         required: false | ||||
|         description: | ||||
|             - The passphrase for the privatekey. | ||||
|         version_added: "2.4" | ||||
| ''' | ||||
| 
 | ||||
| EXAMPLES = ''' | ||||
|  | @ -76,6 +81,13 @@ EXAMPLES = ''' | |||
|     privatekey_path: /etc/ssl/private/ansible.com.pem | ||||
|     format: OpenSSH | ||||
| 
 | ||||
| # Generate an OpenSSL public key with a passphrase protected | ||||
| # private key | ||||
| - openssl_publickey: | ||||
|     path: /etc/ssl/public/ansible.com.pem | ||||
|     privatekey_path: /etc/ssl/private/ansible.com.pem | ||||
|     privatekey_passphrase: ansible | ||||
| 
 | ||||
| # Force regenerate an OpenSSL public key if it already exists | ||||
| - openssl_publickey: | ||||
|     path: /etc/ssl/public/ansible.com.pem | ||||
|  | @ -150,6 +162,7 @@ class PublicKey(object): | |||
|         self.name = os.path.basename(module.params['path']) | ||||
|         self.path = module.params['path'] | ||||
|         self.privatekey_path = module.params['privatekey_path'] | ||||
|         self.privatekey_passphrase = module.params['privatekey_passphrase'] | ||||
|         self.privatekey = None | ||||
|         self.changed = True | ||||
|         self.fingerprint = {} | ||||
|  | @ -164,7 +177,7 @@ class PublicKey(object): | |||
| 
 | ||||
|                 if self.format == 'OpenSSH': | ||||
|                     key = crypto_serialization.load_pem_private_key(privatekey_content, | ||||
|                                                                     password=None, | ||||
|                                                                     password=self.privatekey_passphrase, | ||||
|                                                                     backend=default_backend()) | ||||
|                     publickey_content = key.public_key().public_bytes( | ||||
|                         crypto_serialization.Encoding.OpenSSH, | ||||
|  | @ -190,7 +203,7 @@ class PublicKey(object): | |||
|             self.changed = False | ||||
| 
 | ||||
|         file_args = module.load_file_common_arguments(module.params) | ||||
|         self.fingerprint = get_fingerprint(self.privatekey_path) | ||||
|         self.fingerprint = get_fingerprint(self.privatekey_path, self.privatekey_passphrase) | ||||
|         if module.set_fs_attributes_if_different(file_args, False): | ||||
|             self.changed = True | ||||
| 
 | ||||
|  | @ -228,6 +241,7 @@ def main(): | |||
|             path=dict(required=True, type='path'), | ||||
|             privatekey_path=dict(type='path'), | ||||
|             format=dict(type='str', choices=['PEM', 'OpenSSH'], default='PEM'), | ||||
|             privatekey_passphrase=dict(type='path', no_log=True), | ||||
|         ), | ||||
|         supports_check_mode = True, | ||||
|         add_file_common_args = True, | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue