Repository: ansible/awx

Issue:
Configuring SAML via extra_settings fails with "May not set both `read_only` and `required`."
### Please confirm the following

- [X] I agree to follow this project's [code of conduct](https://docs.ansible.com/ansible/latest/community/code_of_conduct.html).
- [X] I have checked the [current issues](https://github.com/ansible/awx/issues) for duplicates.
- [X] I understand that AWX is open source software provided for free and that I might not receive a timely response.

### Bug Summary

Attempts to configure SAML via `extra_settings` fails with:

```
...
2022-07-18 15:43:13,203 ERROR    [402bca9ac1674040a668c9cc8821c75a] django.request Internal Server Error: /api/v2/auth/
Traceback (most recent call last):
  File "/var/lib/awx/venv/awx/lib64/python3.9/site-packages/django/core/handlers/exception.py", line 47, in inner
    response = get_response(request)
  File "/var/lib/awx/venv/awx/lib64/python3.9/site-packages/django/core/handlers/base.py", line 181, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/usr/lib64/python3.9/contextlib.py", line 79, in inner
    return func(*args, **kwds)
  File "/var/lib/awx/venv/awx/lib64/python3.9/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
    return view_func(*args, **kwargs)
  File "/var/lib/awx/venv/awx/lib64/python3.9/site-packages/django/views/generic/base.py", line 70, in view
    return self.dispatch(request, *args, **kwargs)
  File "/var/lib/awx/venv/awx/lib64/python3.9/site-packages/awx/api/generics.py", line 340, in dispatch
    return super(APIView, self).dispatch(request, *args, **kwargs)
  File "/var/lib/awx/venv/awx/lib64/python3.9/site-packages/rest_framework/views.py", line 509, in dispatch
    response = self.handle_exception(exc)
  File "/var/lib/awx/venv/awx/lib64/python3.9/site-packages/rest_framework/views.py", line 469, in handle_exception
    self.raise_uncaught_exception(exc)
  File "/var/lib/awx/venv/awx/lib64/python3.9/site-packages/rest_framework/views.py", line 480, in raise_uncaught_exception
    raise exc
  File "/var/lib/awx/venv/awx/lib64/python3.9/site-packages/rest_framework/views.py", line 506, in dispatch
    response = handler(request, *args, **kwargs)
  File "/var/lib/awx/venv/awx/lib64/python3.9/site-packages/awx/api/views/__init__.py", line 642, in get
    auth_backends = list(load_backends(settings.AUTHENTICATION_BACKENDS, force_load=True).items())
  File "/var/lib/awx/venv/awx/lib64/python3.9/site-packages/awx/conf/settings.py", line 515, in __getattr_without_cache__
    return getattr(self._wrapped, name)
  File "/var/lib/awx/venv/awx/lib64/python3.9/site-packages/awx/conf/settings.py", line 413, in __getattr__
    value = self._get_local_with_cache(name)
  File "/var/lib/awx/venv/awx/lib64/python3.9/site-packages/cachetools/decorators.py", line 80, in wrapper
    v = method(self, *args, **kwargs)
  File "/var/lib/awx/venv/awx/lib64/python3.9/site-packages/awx/conf/settings.py", line 408, in _get_local_with_cache
    return self._get_local(name)
  File "/var/lib/awx/venv/awx/lib64/python3.9/site-packages/awx/conf/settings.py", line 360, in _get_local
    value = field.get_default()
  File "/var/lib/awx/venv/awx/lib64/python3.9/site-packages/rest_framework/fields.py", line 518, in get_default
    return self.default()
  File "/var/lib/awx/venv/awx/lib64/python3.9/site-packages/awx/sso/fields.py", line 227, in _default_from_required_settings
    if all([getattr(settings, rs, None) for rs in required_settings]):
  File "/var/lib/awx/venv/awx/lib64/python3.9/site-packages/awx/sso/fields.py", line 227, in <listcomp>
    if all([getattr(settings, rs, None) for rs in required_settings]):
  File "/var/lib/awx/venv/awx/lib64/python3.9/site-packages/awx/conf/settings.py", line 515, in __getattr_without_cache__
    return getattr(self._wrapped, name)
  File "/var/lib/awx/venv/awx/lib64/python3.9/site-packages/awx/conf/settings.py", line 413, in __getattr__
    value = self._get_local_with_cache(name)
  File "/var/lib/awx/venv/awx/lib64/python3.9/site-packages/cachetools/decorators.py", line 80, in wrapper
    v = method(self, *args, **kwargs)
  File "/var/lib/awx/venv/awx/lib64/python3.9/site-packages/awx/conf/settings.py", line 408, in _get_local_with_cache
    return self._get_local(name)
  File "/var/lib/awx/venv/awx/lib64/python3.9/site-packages/awx/conf/settings.py", line 343, in _get_local
    field = self.registry.get_setting_field(name)
  File "/var/lib/awx/venv/awx/lib64/python3.9/site-packages/awx/conf/registry.py", line 132, in get_setting_field
    field_instance = field_class(**field_kwargs)
  File "/var/lib/awx/venv/awx/lib64/python3.9/site-packages/rest_framework/fields.py", line 778, in __init__
    super().__init__(**kwargs)
  File "/var/lib/awx/venv/awx/lib64/python3.9/site-packages/rest_framework/fields.py", line 336, in __init__
    assert not (read_only and required), NOT_READ_ONLY_REQUIRED
AssertionError: May not set both `read_only` and `required`
```

Installed with `awx-operator`: 0.23.0

### AWX version

0.23.0

### Select the relevant components

- [ ] UI
- [ ] API
- [ ] Docs
- [ ] Collection
- [ ] CLI
- [X] Other

### Installation method

kubernetes

### Modifications

no

### Ansible version

_No response_

### Operating system

_No response_

### Web browser

_No response_

### Steps to reproduce

The config I am using looks like below (some values have been redacted):

```
---
apiVersion: awx.ansible.com/v1beta1
kind: AWX
metadata:
  name: awx-test
spec:
  admin_password_secret: awx-test-admin-password
  bundle_cacert_secret: awx-pgo-cacert
  no_log: 'no'
  extra_settings:
    - setting: TOWER_URL_BASE
      value: "'https://tower.thing.here'"
    - setting: SOCIAL_AUTH_SAML_SP_ENTITY_ID
      value: "'https://tower.thing.here/'"
    - setting: SOCIAL_AUTH_SAML_SP_PUBLIC_CERT
      value: '''pubcert -- this is newline separated and includes both begin and end statements'''
    - setting: SOCIAL_AUTH_SAML_SP_PRIVATE_KEY
      value: '''privatekey -- this is newline separated and includes both begin and end statements'''
    - setting: SOCIAL_AUTH_SAML_ORG_INFO
      value: '''{"en-US": {"url": "https://tower.thing.here/","displayname": "My Display Name","name": "NameHere"}}'''
    - setting: SOCIAL_AUTH_SAML_TECHNICAL_CONTACT
      value: '''{"givenName": "SomethingHere","emailAddress": "myemail@email.com"}'''
    - setting: SOCIAL_AUTH_SAML_SUPPORT_CONTACT
      value: '''{"givenName": "SomethingHere","emailAddress": "myemail@email.com"}'''
    - setting: SOCIAL_AUTH_SAML_ENABLED_IDPS
      value: '''{"myidp": {"entity_id": "https://myidp.idp.com/sso/SAML2","url": "https://myidp.idp.com/sso/SAML2?RedirectUrl=https://tower.thing.here/sso/complete/saml/","x509cert": "certinfohere","attr_first_name": "firstname","attr_last_name": "lastname","attr_email": "email","attr_user_permanent_id": "email","attr_username": "email"}}'''
  ingress_type: ingress
  ingress_tls_secret: power-tower-tls
  ingress_annotations: |
    ingress.kubernetes.io/ssl-redirect: "true"
    ingress.kubernetes.io/proxy-body-size: "0"
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
    nginx.ingress.kubernetes.io/proxy-body-size: "0"
  postgres_configuration_secret: awx-test-postgres-configuration
  service_type: ClusterIP
```

### Expected results

Able to login with admin or via SAML.

### Actual results

Logins fail and there is no SAML button

### Additional information

_No response_


Discussion:
Having the exact same issue :(

Resolving patch:
diff --git a/awx/sso/conf.py b/awx/sso/conf.py
--- a/awx/sso/conf.py
+++ b/awx/sso/conf.py
@@ -1341,7 +1341,6 @@ def get_saml_entity_id():
     'SOCIAL_AUTH_SAML_SP_PUBLIC_CERT',
     field_class=fields.CharField,
     allow_blank=True,
-    required=True,
     validators=[validate_certificate],
     label=_('SAML Service Provider Public Certificate'),
     help_text=_('Create a keypair to use as a service provider (SP) and include the certificate content here.'),
@@ -1353,7 +1352,6 @@ def get_saml_entity_id():
     'SOCIAL_AUTH_SAML_SP_PRIVATE_KEY',
     field_class=fields.CharField,
     allow_blank=True,
-    required=True,
     validators=[validate_private_key],
     label=_('SAML Service Provider Private Key'),
     help_text=_('Create a keypair to use as a service provider (SP) and include the private key content here.'),
@@ -1365,7 +1363,6 @@ def get_saml_entity_id():
 register(
     'SOCIAL_AUTH_SAML_ORG_INFO',
     field_class=SAMLOrgInfoField,
-    required=True,
     label=_('SAML Service Provider Organization Info'),
     help_text=_('Provide the URL, display name, and the name of your app. Refer to the documentation for example syntax.'),
     category=_('SAML'),
@@ -1379,7 +1376,6 @@ def get_saml_entity_id():
     'SOCIAL_AUTH_SAML_TECHNICAL_CONTACT',
     field_class=SAMLContactField,
     allow_blank=True,
-    required=True,
     label=_('SAML Service Provider Technical Contact'),
     help_text=_('Provide the name and email address of the technical contact for your service provider. Refer to the documentation for example syntax.'),
     category=_('SAML'),
@@ -1391,7 +1387,6 @@ def get_saml_entity_id():
     'SOCIAL_AUTH_SAML_SUPPORT_CONTACT',
     field_class=SAMLContactField,
     allow_blank=True,
-    required=True,
     label=_('SAML Service Provider Support Contact'),
     help_text=_('Provide the name and email address of the support contact for your service provider. Refer to the documentation for example syntax.'),
     category=_('SAML'),


Test patch: