瀏覽代碼

Merge pull request #3378 from kwoodson/oadm_ca

Adding oc_adm_ca_server_cert to lib_openshift
Kenny Woodson 8 年之前
父節點
當前提交
5226b6583d

File diff suppressed because it is too large
+ 1492 - 0
roles/lib_openshift/library/oc_adm_ca_server_cert.py


+ 35 - 0
roles/lib_openshift/src/ansible/oc_adm_ca_server_cert.py

@@ -0,0 +1,35 @@
+# pylint: skip-file
+# flake8: noqa
+
+def main():
+    '''
+    ansible oc adm module for ca create-server-cert
+    '''
+
+    module = AnsibleModule(
+        argument_spec=dict(
+            state=dict(default='present', type='str', choices=['present']),
+            debug=dict(default=False, type='bool'),
+            kubeconfig=dict(default='/etc/origin/master/admin.kubeconfig', type='str'),
+            backup=dict(default=True, type='bool'),
+            force=dict(default=False, type='bool'),
+            # oc adm ca create-server-cert [options]
+            cert=dict(default=None, type='str'),
+            key=dict(default=None, type='str'),
+            signer_cert=dict(default='/etc/origin/master/ca.crt', type='str'),
+            signer_key=dict(default='/etc/origin/master/ca.key', type='str'),
+            signer_serial=dict(default='/etc/origin/master/ca.serial.txt', type='str'),
+            hostnames=dict(default=[], type='list'),
+        ),
+        supports_check_mode=True,
+    )
+
+    results = CAServerCert.run_ansible(module.params, module.check_mode)
+    if 'failed' in results:
+        return module.fail_json(**results)
+
+    return module.exit_json(**results)
+
+
+if __name__ == '__main__':
+    main()

+ 135 - 0
roles/lib_openshift/src/class/oc_adm_ca_server_cert.py

@@ -0,0 +1,135 @@
+# pylint: skip-file
+# flake8: noqa
+
+class CAServerCertConfig(OpenShiftCLIConfig):
+    ''' CAServerCertConfig is a DTO for the oc adm ca command '''
+    def __init__(self, kubeconfig, verbose, ca_options):
+        super(CAServerCertConfig, self).__init__('ca', None, kubeconfig, ca_options)
+        self.kubeconfig = kubeconfig
+        self.verbose = verbose
+        self._ca = ca_options
+
+
+class CAServerCert(OpenShiftCLI):
+    ''' Class to wrap the oc adm ca create-server-cert command line'''
+    def __init__(self,
+                 config,
+                 verbose=False):
+        ''' Constructor for oadm ca '''
+        super(CAServerCert, self).__init__(None, config.kubeconfig, verbose)
+        self.config = config
+        self.verbose = verbose
+
+    def get(self):
+        '''get the current cert file
+
+           If a file exists by the same name in the specified location then the cert exists
+        '''
+        cert = self.config.config_options['cert']['value']
+        if cert and os.path.exists(cert):
+            return open(cert).read()
+
+        return None
+
+    def create(self):
+        '''run openshift oc adm ca create-server-cert cmd'''
+
+        # Added this here as a safegaurd for stomping on the
+        # cert and key files if they exist
+        if self.config.config_options['backup']['value']:
+            import time
+            ext = time.strftime("%Y-%m-%d@%H:%M:%S", time.localtime(time.time()))
+            date_str = "%s_" + "%s" % ext
+
+            if os.path.exists(self.config.config_options['key']['value']):
+                shutil.copy(self.config.config_options['key']['value'],
+                            date_str % self.config.config_options['key']['value'])
+            if os.path.exists(self.config.config_options['cert']['value']):
+                shutil.copy(self.config.config_options['cert']['value'],
+                            date_str % self.config.config_options['cert']['value'])
+
+        options = self.config.to_option_list()
+
+        cmd = ['ca', 'create-server-cert']
+        cmd.extend(options)
+
+        return self.openshift_cmd(cmd, oadm=True)
+
+    def exists(self):
+        ''' check whether the certificate exists and has the clusterIP '''
+
+        cert_path = self.config.config_options['cert']['value']
+        if not os.path.exists(cert_path):
+            return False
+
+        # Would prefer pyopenssl but is not installed.
+        # When we verify it is, switch this code
+        # Here is the code to get the subject and the SAN
+        # openssl x509 -text -noout -certopt \
+        #  no_header,no_version,no_serial,no_signame,no_validity,no_issuer,no_pubkey,no_sigdump,no_aux \
+        #  -in /etc/origin/master/registry.crt
+        # Instead of this solution we will use a regex.
+        cert_names = []
+        hostnames = self.config.config_options['hostnames']['value'].split(',')
+        proc = subprocess.Popen(['openssl', 'x509', '-noout', '-text', '-in', cert_path],
+                                stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+
+        x509output, _ = proc.communicate()
+        if proc.returncode == 0:
+            regex = re.compile(r"^\s*X509v3 Subject Alternative Name:\s*?\n\s*(.*)\s*\n", re.MULTILINE)
+            match = regex.search(x509output)  # E501
+            for entry in re.split(r", *", match.group(1)):
+                if entry.startswith('DNS') or entry.startswith('IP Address'):
+                    cert_names.append(entry.split(':')[1])
+            # now that we have cert names let's compare
+            cert_set = set(cert_names)
+            hname_set = set(hostnames)
+            if cert_set.issubset(hname_set) and hname_set.issubset(cert_set):
+                return True
+
+        return False
+
+    @staticmethod
+    def run_ansible(params, check_mode):
+        '''run the idempotent ansible code'''
+
+        config = CAServerCertConfig(params['kubeconfig'],
+                                    params['debug'],
+                                    {'cert':          {'value': params['cert'], 'include': True},
+                                     'hostnames':     {'value': ','.join(params['hostnames']), 'include': True},
+                                     'overwrite':     {'value': True, 'include': True},
+                                     'key':           {'value': params['key'], 'include': True},
+                                     'signer_cert':   {'value': params['signer_cert'], 'include': True},
+                                     'signer_key':    {'value': params['signer_key'], 'include': True},
+                                     'signer_serial': {'value': params['signer_serial'], 'include': True},
+                                     'backup':        {'value': params['backup'], 'include': False},
+                                    })
+
+        server_cert = CAServerCert(config)
+
+        state = params['state']
+
+        if state == 'present':
+            ########
+            # Create
+            ########
+            if not server_cert.exists() or params['force']:
+
+                if check_mode:
+                    return {'changed': True,
+                            'msg': "CHECK_MODE: Would have created the certificate.",
+                            'state': state}
+
+                api_rval = server_cert.create()
+
+                return {'changed': True, 'results': api_rval, 'state': state}
+
+            ########
+            # Exists
+            ########
+            api_rval = server_cert.get()
+            return {'changed': False, 'results': api_rval, 'state': state}
+
+        return {'failed': True,
+                'msg': 'Unknown state passed. %s' % state}
+

+ 96 - 0
roles/lib_openshift/src/doc/ca_server_cert

@@ -0,0 +1,96 @@
+# flake8: noqa
+# pylint: skip-file
+
+DOCUMENTATION = '''
+---
+module: oc_adm_ca_server_cert
+short_description: Module to run openshift oc adm ca create-server-cert
+description:
+  - Wrapper around the openshift `oc adm ca create-server-cert` command.
+options:
+  state:
+    description:
+    - Present is the only supported state.  The state present means that `oc adm ca` will generate a certificate
+    - and verify if the hostnames and the ClusterIP exists in the certificate.
+    - When create-server-cert is desired then the following parameters are passed.
+    - ['cert', 'key', 'signer_cert', 'signer_key', 'signer_serial']
+    required: false
+    default: present
+    choices: 
+    - present
+    aliases: []
+  kubeconfig:
+    description:
+    - The path for the kubeconfig file to use for authentication
+    required: false
+    default: /etc/origin/master/admin.kubeconfig
+    aliases: []
+  debug:
+    description:
+    - Turn on debug output.
+    required: false
+    default: False
+    aliases: []
+  cert:
+    description:
+    - The certificate file. Choose a name that indicates what the service is.
+    required: false
+    default: None
+    aliases: []
+  key:
+    description:
+    - The key file. Choose a name that indicates what the service is.
+    required: false
+    default: None
+    aliases: []
+  force:
+    description:
+    - Force updating of the existing cert and key files
+    required: false
+    default: False
+    aliases: []
+  signer_cert:
+    description:
+    - The signer certificate file.
+    required: false
+    default: /etc/origin/master/ca.crt
+    aliases: []
+  signer_key:
+    description:
+    - The signer key file.
+    required: false
+    default: /etc/origin/master/ca.key
+    aliases: []
+  signer_serial:
+    description:
+    - The signer serial file.
+    required: false
+    default: /etc/origin/master/ca.serial.txt
+    aliases: []
+  hostnames:
+    description:
+    - Every hostname or IP that server certs should be valid for (comma-delimited list)
+    required: false
+    default: None
+    aliases: []
+  backup:
+    description:
+    - Whether to backup the cert and key files before writing them.
+    required: false
+    default: True
+    aliases: []
+author:
+- "Kenny Woodson <kwoodson@redhat.com>"
+extends_documentation_fragment: []
+'''
+
+EXAMPLES = '''
+- name: Create a self-signed cert
+  oc_adm_ca_server_cert:
+    signer_cert: /etc/origin/master/ca.crt
+    signer_key: /etc/origin/master/ca.key
+    signer_serial: /etc/origin/master/ca.serial.txt
+    hostnames: "registry.test.openshift.com,127.0.0.1,docker-registry.default.svc.cluster.local"
+    cert: /etc/origin/master/registry.crt
+    key: /etc/origin/master/registry.key
+'''

+ 10 - 0
roles/lib_openshift/src/sources.yml

@@ -1,4 +1,14 @@
 ---
+oc_adm_ca_server_cert.py:
+- doc/generated
+- doc/license
+- lib/import.py
+- doc/ca_server_cert
+- ../../lib_utils/src/class/yedit.py
+- lib/base.py
+- class/oc_adm_ca_server_cert.py
+- ansible/oc_adm_ca_server_cert.py
+
 oadm_manage_node.py:
 - doc/generated
 - doc/license