Repository: openshift/openshift-ansible

Issue:
Check for file paths outside of /etc/origin/master in master's config fails on auditConfig.policyConfiguratio
#### Description

The openshift_control_plane "Check for file paths outside of /etc/origin/master in master's config" fails on auditConfig policyConfiguration that includes nonResourceURLs specifications by interpreting these as file paths.

##### Version



```
ansible 2.7.5
  config file = /home/ansible/openshift-provision-demo/ansible.cfg
  configured module search path = [u'/home/ansible/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python2.7/site-packages/ansible
  executable location = /usr/bin/ansible
  python version = 2.7.5 (default, Oct 30 2018, 23:45:53) [GCC 4.8.5 20150623 (Red Hat 4.8.5-36)]
$ git describe 
openshift-ansible-3.11.69-1-4-g0964a5f
```

##### Steps To Reproduce

1. Start with a master with /etc/origin/master/master-config.yaml containing:

```
auditConfig:
  auditFilePath: /var/log/origin/audit.log
  enabled: true
  logFormat: json
  policyConfiguration:
    apiVersion: audit.k8s.io/v1beta1
    omitStages:
    - RequestReceived
    rules:
    - level: Metadata
      nonResourceURLs:
      - /login*
      - /oauth*
```

2. Run openshift-ansible deploy

##### Expected Results

This check should not choke on the auditConfig policyConfiguration.

##### Observed Results

```
TASK [openshift_control_plane : Check for file paths outside of /etc/origin/master in master's config] ************************************************************************************************************
fatal: [demo-sbx-okd-v3-11-master-0.c.openshift-provision.internal]: FAILED! => {"msg": "A string value that appears to be a file path located outside of\n/dev/null, /etc/origin/master/, /var/lib/origin, /etc/origin/cloudprovider, /etc/origin/kubelet-plugins, /usr/libexec/kubernetes/kubelet-plugins, /var/log/origin has been found in /etc/origin/master/master-config.yaml.\nIn 3.10 and newer, all files needed by the master must reside inside of\nthose directories or a subdirectory or it will not be readable by the\nmaster process. Please migrate all files needed by the master into\none of /dev/null, /etc/origin/master/, /var/lib/origin, /etc/origin/cloudprovider, /etc/origin/kubelet-plugins, /usr/libexec/kubernetes/kubelet-plugins, /var/log/origin or a subdirectory and update your master configs before\nproceeding. The string found was: /login*\n***********************\nNOTE: the following items do not need to be migrated, they will be migrated\nfor you: oauthConfig.identityProviders"}

NO MORE HOSTS LEFT ************************************************************************************************************************************************************************************************
	to retry, use: --limit @/home/ansible/openshift-provision-demo/provision-cluster/bootstrap.retry

PLAY RECAP ********************************************************************************************************************************************************************************************************
demo-sbx-okd-v3-11-image.c.openshift-provision.internal : ok=25   changed=0    unreachable=0    failed=0   
demo-sbx-okd-v3-11-master-0.c.openshift-provision.internal : ok=28   changed=0    unreachable=0    failed=1   
localhost                  : ok=59   changed=0    unreachable=0    failed=0   


INSTALLER STATUS **************************************************************************************************************************************************************************************************
Initialization  : In Progress (0:00:07)


Failure summary:


  1. Hosts:    demo-sbx-okd-v3-11-master-0.c.openshift-provision.internal
     Play:     Retrieve existing master configs and validate
     Task:     Check for file paths outside of /etc/origin/master in master's config
     Message:  A string value that appears to be a file path located outside of
               /dev/null, /etc/origin/master/, /var/lib/origin, /etc/origin/cloudprovider, /etc/origin/kubelet-plugins, /usr/libexec/kubernetes/kubelet-plugins, /var/log/origin has been found in /etc/origin/master/master-config.yaml.
               In 3.10 and newer, all files needed by the master must reside inside of
               those directories or a subdirectory or it will not be readable by the
               master process. Please migrate all files needed by the master into
               one of /dev/null, /etc/origin/master/, /var/lib/origin, /etc/origin/cloudprovider, /etc/origin/kubelet-plugins, /usr/libexec/kubernetes/kubelet-plugins, /var/log/origin or a subdirectory and update your master configs before
               proceeding. The string found was: /login*
               ***********************
               NOTE: the following items do not need to be migrated, they will be migrated
               for you: oauthConfig.identityProviders
```

##### Additional Information

This has behavior has been observed with OKD 3.11 and OCP 3.11 deployments.


Discussion:

Resolving patch:
diff --git a/roles/lib_utils/action_plugins/master_check_paths_in_config.py b/roles/lib_utils/action_plugins/master_check_paths_in_config.py
--- a/roles/lib_utils/action_plugins/master_check_paths_in_config.py
+++ b/roles/lib_utils/action_plugins/master_check_paths_in_config.py
@@ -22,6 +22,7 @@
 
 
 ITEMS_TO_POP = (
+    ('auditConfig', 'policyConfiguration'),
     ('oauthConfig', 'identityProviders'),
 )
 # Create csv string of dot-separated dictionary keys:
@@ -45,12 +46,19 @@ def pop_migrated_fields(mastercfg):
     """Some fields do not need to be searched because they will be migrated
     for users automatically"""
     # Walk down the tree and pop the specific item we migrate / don't care about
-    for item in ITEMS_TO_POP:
-        field = mastercfg
-        for sub_field in item:
-            parent_field = field
-            field = field[sub_field]
-        parent_field.pop(item[len(item) - 1])
+    for field_path in ITEMS_TO_POP:
+        pop_migrated_field(mastercfg, field_path)
+
+
+def pop_migrated_field(mastercfg, field_path):
+    """Remove field at given path from config"""
+    field = mastercfg
+    for sub_field in field_path:
+        parent_field = field
+        if sub_field not in field:
+            return
+        field = field[sub_field]
+    parent_field.pop(field_path[-1])
 
 
 def do_item_check(val, strings_to_check):


Test patch: