Browse Source

Clean up idempotency issues with session secrets.

Andrew Butcher 9 years ago
parent
commit
9b760b0a89

+ 13 - 6
filter_plugins/oo_filters.py

@@ -8,12 +8,11 @@ Custom filters for use in openshift-ansible
 from ansible import errors
 from operator import itemgetter
 import OpenSSL.crypto
-import os.path
+import os
 import pdb
 import re
 import json
 
-
 class FilterModule(object):
     ''' Custom ansible filters '''
 
@@ -366,9 +365,6 @@ class FilterModule(object):
                            "keyfile": "/etc/origin/master/named_certificates/custom2.key",
                            "names": [ "some-hostname.com" ] }]
         '''
-        if not issubclass(type(certificates), list):
-            raise errors.AnsibleFilterError("|failed expects certificates is a list")
-
         if not issubclass(type(named_certs_dir), unicode):
             raise errors.AnsibleFilterError("|failed expects named_certs_dir is unicode")
 
@@ -468,6 +464,16 @@ class FilterModule(object):
                 pass
         return clusters
 
+    @staticmethod
+    def oo_generate_secret(num_bytes):
+        ''' generate a session secret '''
+
+        if not issubclass(type(num_bytes), int):
+            raise errors.AnsibleFilterError("|failed expects num_bytes is int")
+
+        secret = os.urandom(num_bytes)
+        return secret.encode('base-64').strip()
+
     def filters(self):
         ''' returns a mapping of filters to methods '''
         return {
@@ -486,5 +492,6 @@ class FilterModule(object):
             "oo_parse_heat_stack_outputs": self.oo_parse_heat_stack_outputs,
             "oo_parse_named_certificates": self.oo_parse_named_certificates,
             "oo_haproxy_backend_masters": self.oo_haproxy_backend_masters,
-            "oo_pretty_print_cluster": self.oo_pretty_print_cluster
+            "oo_pretty_print_cluster": self.oo_pretty_print_cluster,
+            "oo_generate_secret": self.oo_generate_secret
         }

+ 28 - 18
playbooks/common/openshift-master/config.yml

@@ -236,29 +236,39 @@
   - role: haproxy
     when: groups.oo_masters_to_config | length > 1
 
-- name: Generate master session keys
+- name: Check for cached session secrets
   hosts: oo_first_master
-  tasks:
+  pre_tasks:
   - fail:
       msg: "Both openshift_master_session_auth_secrets and openshift_master_session_encryption_secrets must be provided if either variable is set"
     when: (openshift_master_session_auth_secrets is defined and openshift_master_session_encryption_secrets is not defined) or (openshift_master_session_encryption_secrets is defined and openshift_master_session_auth_secrets is not defined)
   - fail:
       msg: "openshift_master_session_auth_secrets and openshift_master_encryption_secrets must be equal length"
     when: (openshift_master_session_auth_secrets is defined and openshift_master_session_encryption_secrets is defined) and (openshift_master_session_auth_secrets | length != openshift_master_session_encryption_secrets | length)
-  - name: Install OpenSSL package
-    action: "{{ ansible_pkg_mgr }} name=openssl state=present"
-    when: not openshift.common.is_atomic | bool
-  - name: Generate session authentication key
-    command: /usr/bin/openssl rand -base64 24
-    register: session_auth_output
-    when: openshift_master_session_auth_secrets is undefined
-  - name: Generate session encryption key
-    command: /usr/bin/openssl rand -base64 24
-    register: session_encryption_output
-    when: openshift_master_session_encryption_secrets is undefined
-  - set_fact:
-      session_auth_secret: "{{ openshift_master_session_auth_secrets | default([session_auth_output.stdout]) }}"
-      session_encryption_secret: "{{ openshift_master_session_encryption_secrets | default([session_encryption_output.stdout]) }}"
+  roles:
+  - role: openshift_facts
+  post_tasks:
+  - openshift_facts:
+      role: master
+      local_facts:
+          session_auth_secrets: "{{ openshift_master_session_auth_secrets | default(openshift.master.session_auth_secrets | default(None)) }}"
+          session_encryption_secrets: "{{ openshift_master_session_encryption_secrets | default(openshift.master.session_encryption_secrets | default(None)) }}"
+
+- name: Generate master session secrets
+  hosts: oo_first_master
+  vars:
+    g_session_secrets_present: "{{ (openshift.master.session_auth_secrets | default([]) and openshift.master.session_encryption_secrets | default([])) | length > 0 }}"
+    g_session_auth_secrets: "{{ [ 24 | oo_generate_secret ] }}"
+    g_session_encryption_secrets: "{{ [ 24 | oo_generate_secret ] }}"
+  roles:
+  - role: openshift_facts
+  tasks:
+  - openshift_facts:
+      role: master
+      local_facts:
+        session_auth_secrets: "{{ g_session_auth_secrets }}"
+        session_encryption_secrets: "{{ g_session_encryption_secrets }}"
+    when: not g_session_secrets_present | bool
 
 - name: Parse named certificates
   hosts: localhost
@@ -314,8 +324,8 @@
     sync_tmpdir: "{{ hostvars.localhost.g_master_mktemp.stdout }}"
     openshift_master_ha: "{{ groups.oo_masters_to_config | length > 1 }}"
     openshift_master_count: "{{ groups.oo_masters_to_config | length }}"
-    openshift_master_session_auth_secrets: "{{ hostvars[groups['oo_first_master'][0]]['session_auth_secret'] }}"
-    openshift_master_session_encryption_secrets: "{{ hostvars[groups['oo_first_master'][0]]['session_encryption_secret'] }}"
+    openshift_master_session_auth_secrets: "{{ hostvars[groups.oo_first_master.0].openshift.master.session_auth_secrets }}"
+    openshift_master_session_encryption_secrets: "{{ hostvars[groups.oo_first_master.0].openshift.master.session_encryption_secrets }}"
   pre_tasks:
   - name: Ensure certificate directory exists
     file:

+ 9 - 2
roles/openshift_master/tasks/main.yml

@@ -9,6 +9,13 @@
       Invalid OAuth grant method: {{ openshift_master_oauth_grant_method }}
   when: openshift_master_oauth_grant_method is defined and openshift_master_oauth_grant_method not in openshift_master_valid_grant_methods
 
+# Session Options Validation
+- fail:
+    msg: "Both openshift_master_session_auth_secrets and openshift_master_session_encryption_secrets must be provided if either variable is set"
+  when: (openshift_master_session_auth_secrets is defined and openshift_master_session_encryption_secrets is not defined) or (openshift_master_session_encryption_secrets is defined and openshift_master_session_auth_secrets is not defined)
+- fail:
+    msg: "openshift_master_session_auth_secrets and openshift_master_encryption_secrets must be equal length"
+  when: (openshift_master_session_auth_secrets is defined and openshift_master_session_encryption_secrets is defined) and (openshift_master_session_auth_secrets | length != openshift_master_session_encryption_secrets | length)
 
 # HA Variable Validation
 - fail:
@@ -55,9 +62,9 @@
       portal_net: "{{ openshift_master_portal_net | default(None) }}"
       session_max_seconds: "{{ openshift_master_session_max_seconds | default(None) }}"
       session_name: "{{ openshift_master_session_name | default(None) }}"
+      session_secrets_file: "{{ openshift_master_session_secrets_file | default(None) }}"
       session_auth_secrets: "{{ openshift_master_session_auth_secrets | default(None) }}"
       session_encryption_secrets: "{{ openshift_master_session_encryption_secrets | default(None) }}"
-      session_secrets_file: "{{ openshift_master_session_secrets_file | default(None) }}"
       access_token_max_seconds: "{{ openshift_master_access_token_max_seconds | default(None) }}"
       auth_token_max_seconds: "{{ openshift_master_auth_token_max_seconds | default(None) }}"
       identity_providers: "{{ openshift_master_identity_providers | default(None) }}"
@@ -221,7 +228,7 @@
   template:
     dest: "{{ openshift.master.session_secrets_file }}"
     src: sessionSecretsFile.yaml.v1.j2
-    force: no
+  when: openshift.master.session_auth_secrets is defined and openshift.master.session_encryption_secrets is defined
   notify:
   - restart master
   - restart master api

+ 2 - 0
roles/openshift_master/templates/master.yaml.v1.j2

@@ -127,7 +127,9 @@ oauthConfig:
   sessionConfig:
     sessionMaxAgeSeconds: {{ openshift.master.session_max_seconds }}
     sessionName: {{ openshift.master.session_name }}
+{% if openshift.master.session_auth_secrets is defined and openshift.master.session_encryption_secrets is defined %}
     sessionSecretsFile: {{ openshift.master.session_secrets_file }}
+{% endif %}
   tokenConfig:
     accessTokenMaxAgeSeconds: {{ openshift.master.access_token_max_seconds }}
     authorizeTokenMaxAgeSeconds: {{ openshift.master.auth_token_max_seconds }}

+ 3 - 3
roles/openshift_master/templates/sessionSecretsFile.yaml.v1.j2

@@ -1,7 +1,7 @@
 apiVersion: v1
 kind: SessionSecrets
 secrets:
-{% for secret in openshift_master_session_auth_secrets %}
-- authentication: "{{ openshift_master_session_auth_secrets[loop.index0] }}"
-  encryption: "{{ openshift_master_session_encryption_secrets[loop.index0] }}"
+{% for secret in openshift.master.session_auth_secrets %}
+- authentication: "{{ openshift.master.session_auth_secrets[loop.index0] }}"
+  encryption: "{{ openshift.master.session_encryption_secrets[loop.index0] }}"
 {% endfor %}