def __init__(self, **kwargs):
        super().__init__(**kwargs)

        if self.auto_IdP_metadata:
            idp_data = OneLogin_Saml2_IdPMetadataParser.parse_remote(
                self.auto_IdP_metadata)
            self.saml_settings = OneLogin_Saml2_IdPMetadataParser.merge_settings(
                self.saml_settings, idp_data)
    def testMergeSettings(self):
        """
        Tests the merge_settings method of the OneLogin_Saml2_IdPMetadataParser
        """
        with self.assertRaises(AttributeError):
            settings_result = OneLogin_Saml2_IdPMetadataParser.merge_settings(None, {})

        with self.assertRaises(TypeError):
            settings_result = OneLogin_Saml2_IdPMetadataParser.merge_settings({}, None)

        xml_idp_metadata = self.file_contents(join(self.data_path, 'metadata', 'idp_metadata.xml'))
        data = OneLogin_Saml2_IdPMetadataParser.parse(xml_idp_metadata)
        settings = self.loadSettingsJSON()
        settings_result = OneLogin_Saml2_IdPMetadataParser.merge_settings(settings, data)
        expected_data = {u'sp': {'NameIDFormat': 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress'}, u'idp': {'singleLogoutService': {'url': 'https://app.onelogin.com/trust/saml2/http-post/sso/383123'}, 'entityId': 'https://app.onelogin.com/saml/metadata/383123', 'x509cert': 'MIIEHjCCAwagAwIBAgIBATANBgkqhkiG9w0BAQUFADBnMQswCQYDVQQGEwJVUzET\nMBEGA1UECAwKQ2FsaWZvcm5pYTEVMBMGA1UEBwwMU2FudGEgTW9uaWNhMREwDwYD\nVQQKDAhPbmVMb2dpbjEZMBcGA1UEAwwQYXBwLm9uZWxvZ2luLmNvbTAeFw0xMzA2\nMDUxNzE2MjBaFw0xODA2MDUxNzE2MjBaMGcxCzAJBgNVBAYTAlVTMRMwEQYDVQQI\nDApDYWxpZm9ybmlhMRUwEwYDVQQHDAxTYW50YSBNb25pY2ExETAPBgNVBAoMCE9u\nZUxvZ2luMRkwFwYDVQQDDBBhcHAub25lbG9naW4uY29tMIIBIjANBgkqhkiG9w0B\nAQEFAAOCAQ8AMIIBCgKCAQEAse8rnep4qL2GmhH10pMQyJ2Jae+AQHyfgVjaQZ7Z\n0QQog5jX91vcJRSMi0XWJnUtOr6lF0dq1+yckjZ92wyLrH+7fvngNO1aV4Mjk9sT\ngf+iqMrae6y6fRxDt9PXrEFVjvd3vv7QTJf2FuIPy4vVP06Dt8EMkQIr8rmLmU0m\nTr1k2DkrdtdlCuNFTXuAu3QqfvNCRrRwfNObn9MP6JeOUdcGLJsBjGF8exfcN1SF\nzRF0JFr3dmOlx761zK5liD0T1sYWnDquatj/JD9fZMbKecBKni1NglH/LVd+b6aJ\nUAr5LulERULUjLqYJRKW31u91/4Qazdo9tbvwqyFxaoUrwIDAQABo4HUMIHRMAwG\nA1UdEwEB/wQCMAAwHQYDVR0OBBYEFPWcXvQSlTXnzZD2xziuoUvrrDedMIGRBgNV\nHSMEgYkwgYaAFPWcXvQSlTXnzZD2xziuoUvrrDedoWukaTBnMQswCQYDVQQGEwJV\nUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEVMBMGA1UEBwwMU2FudGEgTW9uaWNhMREw\nDwYDVQQKDAhPbmVMb2dpbjEZMBcGA1UEAwwQYXBwLm9uZWxvZ2luLmNvbYIBATAO\nBgNVHQ8BAf8EBAMCBPAwDQYJKoZIhvcNAQEFBQADggEBAB/8xe3rzqXQVxzHyAHu\nAuPa73ClDoL1cko0Fp8CGcqEIyj6Te9gx5z6wyfv+Lo8RFvBLlnB1lXqbC+fTGcV\ngG/4oKLJ5UwRFxInqpZPnOAudVNnd0PYOODn9FWs6u+OTIQIaIcPUv3MhB9lwHIJ\nsTk/bs9xcru5TPyLIxLLd6ib/pRceKH2mTkzUd0DYk9CQNXXeoGx/du5B9nh3ClP\nTbVakRzl3oswgI5MQIphYxkW70SopEh4kOFSRE1ND31NNIq1YrXlgtkguQBFsZWu\nQOPR6cEwFZzP0tHTYbI839WgxX6hfhIUTUz6mLqq4+3P4BG3+1OXeVDg63y8Uh78\n1sE='}, u'strict': False, u'contactPerson': {u'technical': {u'givenName': u'technical_name', u'emailAddress': u'*****@*****.**'}, u'support': {u'givenName': u'support_name', u'emailAddress': u'*****@*****.**'}}, u'debug': False, u'organization': {u'en-US': {u'url': u'http://sp.example.com', u'displayname': u'SP test', u'name': u'sp_test'}}, u'security': {u'signMetadata': False, u'wantAssertionsSigned': False, u'authnRequestsSigned': False}, u'custom_base_path': u'../../../tests/data/customPath/'}
        self.assertEqual(expected_data, settings_result)

        expected_data2 = {'sp': {u'singleLogoutService': {u'url': u'http://stuff.com/endpoints/endpoints/sls.php'}, u'assertionConsumerService': {u'url': u'http://stuff.com/endpoints/endpoints/acs.php'}, u'entityId': u'http://stuff.com/endpoints/metadata.php', u'NameIDFormat': u'urn:oasis:names:tc:SAML:2.0:nameid-format:unspecified'}, 'idp': {u'singleLogoutService': {u'url': u'http://idp.example.com/SingleLogoutService.php'}, u'entityId': u'http://idp.example.com/', u'x509cert': u'MIICgTCCAeoCCQCbOlrWDdX7FTANBgkqhkiG9w0BAQUFADCBhDELMAkGA1UEBhMCTk8xGDAWBgNVBAgTD0FuZHJlYXMgU29sYmVyZzEMMAoGA1UEBxMDRm9vMRAwDgYDVQQKEwdVTklORVRUMRgwFgYDVQQDEw9mZWlkZS5lcmxhbmcubm8xITAfBgkqhkiG9w0BCQEWEmFuZHJlYXNAdW5pbmV0dC5ubzAeFw0wNzA2MTUxMjAxMzVaFw0wNzA4MTQxMjAxMzVaMIGEMQswCQYDVQQGEwJOTzEYMBYGA1UECBMPQW5kcmVhcyBTb2xiZXJnMQwwCgYDVQQHEwNGb28xEDAOBgNVBAoTB1VOSU5FVFQxGDAWBgNVBAMTD2ZlaWRlLmVybGFuZy5ubzEhMB8GCSqGSIb3DQEJARYSYW5kcmVhc0B1bmluZXR0Lm5vMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDivbhR7P516x/S3BqKxupQe0LONoliupiBOesCO3SHbDrl3+q9IbfnfmE04rNuMcPsIxB161TdDpIesLCn7c8aPHISKOtPlAeTZSnb8QAu7aRjZq3+PbrP5uW3TcfCGPtKTytHOge/OlJbo078dVhXQ14d1EDwXJW1rRXuUt4C8QIDAQABMA0GCSqGSIb3DQEBBQUAA4GBACDVfp86HObqY+e8BUoWQ9+VMQx1ASDohBjwOsg2WykUqRXF+dLfcUH9dWR63CtZIKFDbStNomPnQz7nbK+onygwBspVEbnHuUihZq3ZUdmumQqCw4Uvs/1Uvq3orOo/WJVhTyvLgFVK2QarQ4/67OZfHd7R+POBXhophSMv1ZOo', u'singleSignOnService': {u'url': u'http://idp.example.com/SSOService.php'}}, u'strict': False, u'contactPerson': {u'technical': {u'givenName': u'technical_name', u'emailAddress': u'*****@*****.**'}, u'support': {u'givenName': u'support_name', u'emailAddress': u'*****@*****.**'}}, u'debug': False, u'organization': {u'en-US': {u'url': u'http://sp.example.com', u'displayname': u'SP test', u'name': u'sp_test'}}, u'security': {u'signMetadata': False, u'wantAssertionsSigned': False, u'authnRequestsSigned': False}, u'custom_base_path': u'../../../tests/data/customPath/'}
        settings_result2 = OneLogin_Saml2_IdPMetadataParser.merge_settings(data, settings)
        self.assertEqual(expected_data2, settings_result2)
Exemple #3
0
def _set_saml_settings(cmd, sp_x_509_cert, sp_private_key, has_sp_cert):
    ceph_dashboard_base_url = cmd['ceph_dashboard_base_url']
    idp_metadata = cmd['idp_metadata']
    idp_username_attribute = _get_optional_attr(
        cmd, 'idp_username_attribute', 'uid')
    idp_entity_id = _get_optional_attr(cmd, 'idp_entity_id', None)
    idp_settings = _parse_saml_settings(idp_metadata, idp_entity_id)

    url_prefix = prepare_url_prefix(
        mgr.get_module_option('url_prefix', default=''))
    settings = {
        'sp': {
            'entityId': '{}{}/auth/saml2/metadata'.format(ceph_dashboard_base_url, url_prefix),
            'assertionConsumerService': {
                'url': '{}{}/auth/saml2'.format(ceph_dashboard_base_url, url_prefix),
                'binding': "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
            },
            'attributeConsumingService': {
                'serviceName': "Ceph Dashboard",
                "serviceDescription": "Ceph Dashboard Service",
                "requestedAttributes": [
                    {
                        "name": idp_username_attribute,
                        "isRequired": True
                    }
                ]
            },
            'singleLogoutService': {
                'url': '{}{}/auth/saml2/logout'.format(ceph_dashboard_base_url, url_prefix),
                'binding': 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect'
            },
            "x509cert": sp_x_509_cert,
            "privateKey": sp_private_key
        },
        'security': {
            "nameIdEncrypted": has_sp_cert,
            "authnRequestsSigned": has_sp_cert,
            "logoutRequestSigned": has_sp_cert,
            "logoutResponseSigned": has_sp_cert,
            "signMetadata": has_sp_cert,
            "wantMessagesSigned": has_sp_cert,
            "wantAssertionsSigned": has_sp_cert,
            "wantAssertionsEncrypted": has_sp_cert,
            # Not all Identity Providers support this.
            "wantNameIdEncrypted": False,
            "metadataValidUntil": '',
            "wantAttributeStatement": False
        }
    }
    settings = Saml2Parser.merge_settings(settings, idp_settings)
    mgr.SSO_DB.saml2.onelogin_settings = settings
    mgr.SSO_DB.protocol = 'saml2'
    mgr.SSO_DB.save()
def fetch_settings(app):
    json_filename = app['SSO_CONFIG_FOLDER'] + '/settings.json'
    json_data_file = open(json_filename, 'r')
    settings_base = json.load(json_data_file)
    json_data_file.close()
    idp_filename = app['SSO_CONFIG_FOLDER'] + '/idp.xml'
    idp_data_file = open(idp_filename, 'r')
    idp_data = OneLogin_Saml2_IdPMetadataParser.parse(idp_data_file.read())
    idp_data_file.close()
    settings = OneLogin_Saml2_IdPMetadataParser.merge_settings(
        settings_base, idp_data)
    app['saml_settings'] = settings
    def initialize(self, *args, **kwargs):
        super().initialize(*args, **kwargs)
        self.log.info("Initializing AuthHub")
        self.parse_command_line(*args, **kwargs)
        if self.generate_config:
            return

        self.log.info("Loading config")
        self.load_config_file(self.config_file)
        if self.auto_IdP_metadata:
            self.log.info("Getting the IdP metadata.")
            idp_data = OneLogin_Saml2_IdPMetadataParser.parse_remote(
                self.auto_IdP_metadata)
            self.saml_settings = OneLogin_Saml2_IdPMetadataParser.merge_settings(
                self.saml_settings, idp_data)

        self.init_logging()
        self.init_db()
        self.init_secrets()
        self.init_handlers()
        self.init_tornado_settings()
        self.init_tornado()
Exemple #6
0
def _get_saml_settings():
    # load settings from environment
    settings = current_app.config.get('SAML_SETTINGS')

    # if settings doesn't exist and a file is provided, load the file
    settings_file = current_app.config.get('SAML_SETTINGS_FILE')
    if not settings and settings_file:
        with open(settings_file, 'r') as json_data_file:
            settings = json.load(json_data_file)

    # if saml metadata url is provided, load idp settings via metadata
    idp_metadata_url = current_app.config.get('SAML_METADATA_URL')
    idp_metadata_entity_id = current_app.config.get('SAML_METADATA_ENTITY_ID',
                                                    None)
    if idp_metadata_url:
        idp_settings = OneLogin_Saml2_IdPMetadataParser.parse_remote(
            idp_metadata_url, entity_id=idp_metadata_entity_id)

        settings = OneLogin_Saml2_IdPMetadataParser.merge_settings(
            settings, idp_settings)

    return settings
Exemple #7
0
def _get_saml_settings():
    # load settings from environment
    settings = current_app.config.get('SAML_SETTINGS')

    # if settings doesn't exist and a file is provided, load the file
    settings_file = current_app.config.get('SAML_SETTINGS_FILE')
    if not settings and settings_file:
        with open(settings_file, 'r') as json_data_file:
            settings = json.load(json_data_file)

    # if saml metadata url is provided, load idp settings via metadata
    idp_metadata_url = current_app.config.get('SAML_METADATA_URL')
    idp_metadata_entity_id = current_app.config.get('SAML_METADATA_ENTITY_ID', None)
    if idp_metadata_url:
        idp_settings = OneLogin_Saml2_IdPMetadataParser.parse_remote(
            idp_metadata_url,
            entity_id=idp_metadata_entity_id
        )

        settings = OneLogin_Saml2_IdPMetadataParser.merge_settings(settings, idp_settings)

    return settings
Exemple #8
0
    def test_merge_settings(self):
        """
        Tests the merge_settings method of the OneLogin_Saml2_IdPMetadataParser
        """
        with self.assertRaises(TypeError):
            settings_result = OneLogin_Saml2_IdPMetadataParser.merge_settings(
                None, {})

        with self.assertRaises(TypeError):
            settings_result = OneLogin_Saml2_IdPMetadataParser.merge_settings(
                {}, None)

        xml_idp_metadata = self.file_contents(
            join(self.data_path, 'metadata', 'idp_metadata.xml'))

        # Parse XML metadata.
        data = OneLogin_Saml2_IdPMetadataParser.parse(xml_idp_metadata)

        # Read base settings.
        settings = self.loadSettingsJSON()

        # Merge settings from XML metadata into base settings,
        # let XML metadata have priority if there are conflicting
        # attributes.
        settings_result = OneLogin_Saml2_IdPMetadataParser.merge_settings(
            settings, data)

        # Generate readable JSON representation:
        # print("%s" % json.dumps(settings_result, indent=2)

        expected_settings_json = """
        {
          "custom_base_path": "../../../tests/data/customPath/",
          "contactPerson": {
            "support": {
              "emailAddress": "*****@*****.**",
              "givenName": "support_name"
            },
            "technical": {
              "emailAddress": "*****@*****.**",
              "givenName": "technical_name"
            }
          },
          "idp": {
            "singleSignOnService": {
              "url": "https://app.onelogin.com/trust/saml2/http-post/sso/383123",
              "binding": "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
            },
            "entityId": "https://app.onelogin.com/saml/metadata/383123",
            "singleLogoutService": {
              "url": "http://idp.example.com/SingleLogoutService.php"
            },
            "x509cert": "MIIEHjCCAwagAwIBAgIBATANBgkqhkiG9w0BAQUFADBnMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEVMBMGA1UEBwwMU2FudGEgTW9uaWNhMREwDwYDVQQKDAhPbmVMb2dpbjEZMBcGA1UEAwwQYXBwLm9uZWxvZ2luLmNvbTAeFw0xMzA2MDUxNzE2MjBaFw0xODA2MDUxNzE2MjBaMGcxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRUwEwYDVQQHDAxTYW50YSBNb25pY2ExETAPBgNVBAoMCE9uZUxvZ2luMRkwFwYDVQQDDBBhcHAub25lbG9naW4uY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAse8rnep4qL2GmhH10pMQyJ2Jae+AQHyfgVjaQZ7Z0QQog5jX91vcJRSMi0XWJnUtOr6lF0dq1+yckjZ92wyLrH+7fvngNO1aV4Mjk9sTgf+iqMrae6y6fRxDt9PXrEFVjvd3vv7QTJf2FuIPy4vVP06Dt8EMkQIr8rmLmU0mTr1k2DkrdtdlCuNFTXuAu3QqfvNCRrRwfNObn9MP6JeOUdcGLJsBjGF8exfcN1SFzRF0JFr3dmOlx761zK5liD0T1sYWnDquatj/JD9fZMbKecBKni1NglH/LVd+b6aJUAr5LulERULUjLqYJRKW31u91/4Qazdo9tbvwqyFxaoUrwIDAQABo4HUMIHRMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFPWcXvQSlTXnzZD2xziuoUvrrDedMIGRBgNVHSMEgYkwgYaAFPWcXvQSlTXnzZD2xziuoUvrrDedoWukaTBnMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEVMBMGA1UEBwwMU2FudGEgTW9uaWNhMREwDwYDVQQKDAhPbmVMb2dpbjEZMBcGA1UEAwwQYXBwLm9uZWxvZ2luLmNvbYIBATAOBgNVHQ8BAf8EBAMCBPAwDQYJKoZIhvcNAQEFBQADggEBAB/8xe3rzqXQVxzHyAHuAuPa73ClDoL1cko0Fp8CGcqEIyj6Te9gx5z6wyfv+Lo8RFvBLlnB1lXqbC+fTGcVgG/4oKLJ5UwRFxInqpZPnOAudVNnd0PYOODn9FWs6u+OTIQIaIcPUv3MhB9lwHIJsTk/bs9xcru5TPyLIxLLd6ib/pRceKH2mTkzUd0DYk9CQNXXeoGx/du5B9nh3ClPTbVakRzl3oswgI5MQIphYxkW70SopEh4kOFSRE1ND31NNIq1YrXlgtkguQBFsZWuQOPR6cEwFZzP0tHTYbI839WgxX6hfhIUTUz6mLqq4+3P4BG3+1OXeVDg63y8Uh781sE="
          },
          "sp": {
            "NameIDFormat": "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress",
            "entityId": "http://stuff.com/endpoints/metadata.php",
            "assertionConsumerService": {
              "url": "http://stuff.com/endpoints/endpoints/acs.php"
            },
            "singleLogoutService": {
              "url": "http://stuff.com/endpoints/endpoints/sls.php"
            }
          },
          "security": {
            "wantAssertionsSigned": false,
            "authnRequestsSigned": false,
            "signMetadata": false
          },
          "debug": false,
          "organization": {
            "en-US": {
              "displayname": "SP test",
              "url": "http://sp.example.com",
              "name": "sp_test"
            }
          },
          "strict": false
        }
        """
        expected_settings = json.loads(expected_settings_json)
        self.assertEqual(expected_settings, settings_result)

        # Commute merge operation. As the order determines which settings
        # dictionary has priority, here we expect a different result.
        settings_result2 = OneLogin_Saml2_IdPMetadataParser.merge_settings(
            data, settings)
        expected_settings2_json = """
        {
          "debug": false,
          "idp": {
            "singleLogoutService": {
              "url": "http://idp.example.com/SingleLogoutService.php"
            },
            "singleSignOnService": {
              "url": "http://idp.example.com/SSOService.php",
              "binding": "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
            },
            "entityId": "http://idp.example.com/",
            "x509cert": "MIICgTCCAeoCCQCbOlrWDdX7FTANBgkqhkiG9w0BAQUFADCBhDELMAkGA1UEBhMCTk8xGDAWBgNVBAgTD0FuZHJlYXMgU29sYmVyZzEMMAoGA1UEBxMDRm9vMRAwDgYDVQQKEwdVTklORVRUMRgwFgYDVQQDEw9mZWlkZS5lcmxhbmcubm8xITAfBgkqhkiG9w0BCQEWEmFuZHJlYXNAdW5pbmV0dC5ubzAeFw0wNzA2MTUxMjAxMzVaFw0wNzA4MTQxMjAxMzVaMIGEMQswCQYDVQQGEwJOTzEYMBYGA1UECBMPQW5kcmVhcyBTb2xiZXJnMQwwCgYDVQQHEwNGb28xEDAOBgNVBAoTB1VOSU5FVFQxGDAWBgNVBAMTD2ZlaWRlLmVybGFuZy5ubzEhMB8GCSqGSIb3DQEJARYSYW5kcmVhc0B1bmluZXR0Lm5vMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDivbhR7P516x/S3BqKxupQe0LONoliupiBOesCO3SHbDrl3+q9IbfnfmE04rNuMcPsIxB161TdDpIesLCn7c8aPHISKOtPlAeTZSnb8QAu7aRjZq3+PbrP5uW3TcfCGPtKTytHOge/OlJbo078dVhXQ14d1EDwXJW1rRXuUt4C8QIDAQABMA0GCSqGSIb3DQEBBQUAA4GBACDVfp86HObqY+e8BUoWQ9+VMQx1ASDohBjwOsg2WykUqRXF+dLfcUH9dWR63CtZIKFDbStNomPnQz7nbK+onygwBspVEbnHuUihZq3ZUdmumQqCw4Uvs/1Uvq3orOo/WJVhTyvLgFVK2QarQ4/67OZfHd7R+POBXhophSMv1ZOo"
          },
          "security": {
            "authnRequestsSigned": false,
            "wantAssertionsSigned": false,
            "signMetadata": false
          },
          "contactPerson": {
            "technical": {
              "emailAddress": "*****@*****.**",
              "givenName": "technical_name"
            },
            "support": {
              "emailAddress": "*****@*****.**",
              "givenName": "support_name"
            }
          },
          "strict": false,
          "sp": {
            "singleLogoutService": {
              "url": "http://stuff.com/endpoints/endpoints/sls.php"
            },
            "assertionConsumerService": {
              "url": "http://stuff.com/endpoints/endpoints/acs.php"
            },
            "entityId": "http://stuff.com/endpoints/metadata.php",
            "NameIDFormat": "urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"
          },
          "custom_base_path": "../../../tests/data/customPath/",
          "organization": {
            "en-US": {
              "displayname": "SP test",
              "url": "http://sp.example.com",
              "name": "sp_test"
            }
          }
        }
        """
        expected_settings2 = json.loads(expected_settings2_json)
        self.assertEqual(expected_settings2, settings_result2)

        # Test merging multiple certs
        xml_idp_metadata = self.file_contents(
            join(self.data_path, 'metadata', 'idp_metadata_multi_certs.xml'))
        data3 = OneLogin_Saml2_IdPMetadataParser.parse(xml_idp_metadata)
        settings_result3 = OneLogin_Saml2_IdPMetadataParser.merge_settings(
            settings, data3)
        expected_settings3_json = """
        {
          "debug": false,
          "strict": false,
          "custom_base_path": "../../../tests/data/customPath/",
          "sp": {
            "singleLogoutService": {
              "url": "http://stuff.com/endpoints/endpoints/sls.php"
            },
            "assertionConsumerService": {
              "url": "http://stuff.com/endpoints/endpoints/acs.php"
            },
            "entityId": "http://stuff.com/endpoints/metadata.php",
            "NameIDFormat": "urn:oasis:names:tc:SAML:2.0:nameid-format:transient"
          },
          "idp": {
            "singleLogoutService": {
              "url": "https://idp.examle.com/saml/slo",
              "binding": "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
            },
            "x509certMulti": {
              "encryption": [
                "MIIEZTCCA02gAwIBAgIUPyy/A3bZAZ4m28PzEUUoT7RJhxIwDQYJKoZIhvcNAQEFBQAwcjELMAkGA1UEBhMCVVMxKzApBgNVBAoMIk9uZUxvZ2luIFRlc3QgKHNnYXJjaWEtdXMtcHJlcHJvZCkxFTATBgNVBAsMDE9uZUxvZ2luIElkUDEfMB0GA1UEAwwWT25lTG9naW4gQWNjb3VudCA4OTE0NjAeFw0xNjA4MDQyMjI5MzdaFw0yMTA4MDUyMjI5MzdaMHIxCzAJBgNVBAYTAlVTMSswKQYDVQQKDCJPbmVMb2dpbiBUZXN0IChzZ2FyY2lhLXVzLXByZXByb2QpMRUwEwYDVQQLDAxPbmVMb2dpbiBJZFAxHzAdBgNVBAMMFk9uZUxvZ2luIEFjY291bnQgODkxNDYwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDN6iqQGcLOCglNO42I2rkzE05UXSiMXT6c8ALThMMiaDw6qqzo3sd/tKK+NcNKWLIIC8TozWVyh5ykUiVZps+08xil7VsTU7E+wKu3kvmOsvw2wlRwtnoKZJwYhnr+RkBa+h1r3ZYUgXm1ZPeHMKj1g18KaWz9+MxYL6BhKqrOzfW/P2xxVRcFH7/pq+ZsDdgNzD2GD+apzY4MZyZj/N6BpBWJ0GlFsmtBegpbX3LBitJuFkk5L4/U/jjF1AJa3boBdCUVfATqO5G03H4XS1GySjBIRQXmlUF52rLjg6xCgWJ30/+t1X+IHLJeixiQ0vxyh6C4/usCEt94cgD1r8ADAgMBAAGjgfIwge8wDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQUPW0DcH0G3IwynWgi74co4wZ6n7gwga8GA1UdIwSBpzCBpIAUPW0DcH0G3IwynWgi74co4wZ6n7ihdqR0MHIxCzAJBgNVBAYTAlVTMSswKQYDVQQKDCJPbmVMb2dpbiBUZXN0IChzZ2FyY2lhLXVzLXByZXByb2QpMRUwEwYDVQQLDAxPbmVMb2dpbiBJZFAxHzAdBgNVBAMMFk9uZUxvZ2luIEFjY291bnQgODkxNDaCFD8svwN22QGeJtvD8xFFKE+0SYcSMA4GA1UdDwEB/wQEAwIHgDANBgkqhkiG9w0BAQUFAAOCAQEAQhB4q9jrycwbHrDSoYR1X4LFFzvJ9Us75wQquRHXpdyS9D6HUBXMGI6ahPicXCQrfLgN8vzMIiqZqfySXXv/8/dxe/X4UsWLYKYJHDJmxXD5EmWTa65chjkeP1oJAc8f3CKCpcP2lOBTthbnk2fEVAeLHR4xNdQO0VvGXWO9BliYPpkYqUIBvlm+Fg9mF7AM/Uagq2503XXIE1Lq//HON68P10vNMwLSKOtYLsoTiCnuIKGJqG37MsZVjQ1ZPRcO+LSLkq0i91gFxrOrVCrgztX4JQi5XkvEsYZGIXXjwHqxTVyt3adZWQO0LPxPqRiUqUzyhDhLo/xXNrHCu4VbMw=="
              ],
              "signing": [
                "MIIEZTCCA02gAwIBAgIUPyy/A3bZAZ4m28PzEUUoT7RJhxIwDQYJKoZIhvcNAQEFBQAwcjELMAkGA1UEBhMCVVMxKzApBgNVBAoMIk9uZUxvZ2luIFRlc3QgKHNnYXJjaWEtdXMtcHJlcHJvZCkxFTATBgNVBAsMDE9uZUxvZ2luIElkUDEfMB0GA1UEAwwWT25lTG9naW4gQWNjb3VudCA4OTE0NjAeFw0xNjA4MDQyMjI5MzdaFw0yMTA4MDUyMjI5MzdaMHIxCzAJBgNVBAYTAlVTMSswKQYDVQQKDCJPbmVMb2dpbiBUZXN0IChzZ2FyY2lhLXVzLXByZXByb2QpMRUwEwYDVQQLDAxPbmVMb2dpbiBJZFAxHzAdBgNVBAMMFk9uZUxvZ2luIEFjY291bnQgODkxNDYwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDN6iqQGcLOCglNO42I2rkzE05UXSiMXT6c8ALThMMiaDw6qqzo3sd/tKK+NcNKWLIIC8TozWVyh5ykUiVZps+08xil7VsTU7E+wKu3kvmOsvw2wlRwtnoKZJwYhnr+RkBa+h1r3ZYUgXm1ZPeHMKj1g18KaWz9+MxYL6BhKqrOzfW/P2xxVRcFH7/pq+ZsDdgNzD2GD+apzY4MZyZj/N6BpBWJ0GlFsmtBegpbX3LBitJuFkk5L4/U/jjF1AJa3boBdCUVfATqO5G03H4XS1GySjBIRQXmlUF52rLjg6xCgWJ30/+t1X+IHLJeixiQ0vxyh6C4/usCEt94cgD1r8ADAgMBAAGjgfIwge8wDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQUPW0DcH0G3IwynWgi74co4wZ6n7gwga8GA1UdIwSBpzCBpIAUPW0DcH0G3IwynWgi74co4wZ6n7ihdqR0MHIxCzAJBgNVBAYTAlVTMSswKQYDVQQKDCJPbmVMb2dpbiBUZXN0IChzZ2FyY2lhLXVzLXByZXByb2QpMRUwEwYDVQQLDAxPbmVMb2dpbiBJZFAxHzAdBgNVBAMMFk9uZUxvZ2luIEFjY291bnQgODkxNDaCFD8svwN22QGeJtvD8xFFKE+0SYcSMA4GA1UdDwEB/wQEAwIHgDANBgkqhkiG9w0BAQUFAAOCAQEAQhB4q9jrycwbHrDSoYR1X4LFFzvJ9Us75wQquRHXpdyS9D6HUBXMGI6ahPicXCQrfLgN8vzMIiqZqfySXXv/8/dxe/X4UsWLYKYJHDJmxXD5EmWTa65chjkeP1oJAc8f3CKCpcP2lOBTthbnk2fEVAeLHR4xNdQO0VvGXWO9BliYPpkYqUIBvlm+Fg9mF7AM/Uagq2503XXIE1Lq//HON68P10vNMwLSKOtYLsoTiCnuIKGJqG37MsZVjQ1ZPRcO+LSLkq0i91gFxrOrVCrgztX4JQi5XkvEsYZGIXXjwHqxTVyt3adZWQO0LPxPqRiUqUzyhDhLo/xXNrHCu4VbMw==",
                "MIICZDCCAc2gAwIBAgIBADANBgkqhkiG9w0BAQ0FADBPMQswCQYDVQQGEwJ1czEUMBIGA1UECAwLZXhhbXBsZS5jb20xFDASBgNVBAoMC2V4YW1wbGUuY29tMRQwEgYDVQQDDAtleGFtcGxlLmNvbTAeFw0xNzA0MTUxNjMzMThaFw0xODA0MTUxNjMzMThaME8xCzAJBgNVBAYTAnVzMRQwEgYDVQQIDAtleGFtcGxlLmNvbTEUMBIGA1UECgwLZXhhbXBsZS5jb20xFDASBgNVBAMMC2V4YW1wbGUuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC6GLkl5lDUZdHNDAojp5i24OoPlqrt5TGXJIPqAZYT1hQvJW5nv17MFDHrjmtEnmW4ACKEy0fAX80QWIcHunZSkbEGHb+NG/6oTi5RipXMvmHnfFnPJJ0AdtiLiPE478CV856gXekV4Xx5u3KrylcOgkpYsp0GMIQBDzleMUXlYQIDAQABo1AwTjAdBgNVHQ4EFgQUnP8vlYPGPL2n6ZzDYij2kMDC8wMwHwYDVR0jBBgwFoAUnP8vlYPGPL2n6ZzDYij2kMDC8wMwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQ0FAAOBgQAlQGAl+b8Cpot1g+65lLLjVoY7APJPWLW0klKQNlMU0s4MU+71Y3ExUEOXDAZgKcFoavb1fEOGMwEf38NaJAy1e/l6VNuixXShffq20ymqHQxOG0q8ujeNkgZF9k6XDfn/QZ3AD0o/IrCT7UMc/0QsfgIjWYxwCvp2syApc5CYfQ=="
              ]
            },
            "entityId": "https://idp.examle.com/saml/metadata",
            "singleSignOnService": {
              "url": "https://idp.examle.com/saml/sso",
              "binding": "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
            }
          },
          "security": {
            "authnRequestsSigned": false,
            "wantAssertionsSigned": false,
            "signMetadata": false
          },
          "contactPerson": {
            "technical": {
              "emailAddress": "*****@*****.**",
              "givenName": "technical_name"
            },
            "support": {
              "emailAddress": "*****@*****.**",
              "givenName": "support_name"
            }
          },
          "organization": {
            "en-US": {
              "displayname": "SP test",
              "url": "http://sp.example.com",
              "name": "sp_test"
            }
          }
        }
        """
        expected_settings3 = json.loads(expected_settings3_json)
        self.assertEqual(expected_settings3, settings_result3)
    def testMergeSettings(self):
        """
        Tests the merge_settings method of the OneLogin_Saml2_IdPMetadataParser
        """
        with self.assertRaises(AttributeError):
            settings_result = OneLogin_Saml2_IdPMetadataParser.merge_settings(
                None, {})

        with self.assertRaises(TypeError):
            settings_result = OneLogin_Saml2_IdPMetadataParser.merge_settings(
                {}, None)

        xml_idp_metadata = self.file_contents(
            join(self.data_path, 'metadata', 'idp_metadata.xml'))
        data = OneLogin_Saml2_IdPMetadataParser.parse(xml_idp_metadata)
        settings = self.loadSettingsJSON()
        settings_result = OneLogin_Saml2_IdPMetadataParser.merge_settings(
            settings, data)
        expected_data = {
            u'sp': {
                'NameIDFormat':
                'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress'
            },
            u'idp': {
                'singleLogoutService': {
                    'url':
                    'https://app.onelogin.com/trust/saml2/http-post/sso/383123'
                },
                'entityId':
                'https://app.onelogin.com/saml/metadata/383123',
                'x509cert':
                'MIIEHjCCAwagAwIBAgIBATANBgkqhkiG9w0BAQUFADBnMQswCQYDVQQGEwJVUzET\nMBEGA1UECAwKQ2FsaWZvcm5pYTEVMBMGA1UEBwwMU2FudGEgTW9uaWNhMREwDwYD\nVQQKDAhPbmVMb2dpbjEZMBcGA1UEAwwQYXBwLm9uZWxvZ2luLmNvbTAeFw0xMzA2\nMDUxNzE2MjBaFw0xODA2MDUxNzE2MjBaMGcxCzAJBgNVBAYTAlVTMRMwEQYDVQQI\nDApDYWxpZm9ybmlhMRUwEwYDVQQHDAxTYW50YSBNb25pY2ExETAPBgNVBAoMCE9u\nZUxvZ2luMRkwFwYDVQQDDBBhcHAub25lbG9naW4uY29tMIIBIjANBgkqhkiG9w0B\nAQEFAAOCAQ8AMIIBCgKCAQEAse8rnep4qL2GmhH10pMQyJ2Jae+AQHyfgVjaQZ7Z\n0QQog5jX91vcJRSMi0XWJnUtOr6lF0dq1+yckjZ92wyLrH+7fvngNO1aV4Mjk9sT\ngf+iqMrae6y6fRxDt9PXrEFVjvd3vv7QTJf2FuIPy4vVP06Dt8EMkQIr8rmLmU0m\nTr1k2DkrdtdlCuNFTXuAu3QqfvNCRrRwfNObn9MP6JeOUdcGLJsBjGF8exfcN1SF\nzRF0JFr3dmOlx761zK5liD0T1sYWnDquatj/JD9fZMbKecBKni1NglH/LVd+b6aJ\nUAr5LulERULUjLqYJRKW31u91/4Qazdo9tbvwqyFxaoUrwIDAQABo4HUMIHRMAwG\nA1UdEwEB/wQCMAAwHQYDVR0OBBYEFPWcXvQSlTXnzZD2xziuoUvrrDedMIGRBgNV\nHSMEgYkwgYaAFPWcXvQSlTXnzZD2xziuoUvrrDedoWukaTBnMQswCQYDVQQGEwJV\nUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEVMBMGA1UEBwwMU2FudGEgTW9uaWNhMREw\nDwYDVQQKDAhPbmVMb2dpbjEZMBcGA1UEAwwQYXBwLm9uZWxvZ2luLmNvbYIBATAO\nBgNVHQ8BAf8EBAMCBPAwDQYJKoZIhvcNAQEFBQADggEBAB/8xe3rzqXQVxzHyAHu\nAuPa73ClDoL1cko0Fp8CGcqEIyj6Te9gx5z6wyfv+Lo8RFvBLlnB1lXqbC+fTGcV\ngG/4oKLJ5UwRFxInqpZPnOAudVNnd0PYOODn9FWs6u+OTIQIaIcPUv3MhB9lwHIJ\nsTk/bs9xcru5TPyLIxLLd6ib/pRceKH2mTkzUd0DYk9CQNXXeoGx/du5B9nh3ClP\nTbVakRzl3oswgI5MQIphYxkW70SopEh4kOFSRE1ND31NNIq1YrXlgtkguQBFsZWu\nQOPR6cEwFZzP0tHTYbI839WgxX6hfhIUTUz6mLqq4+3P4BG3+1OXeVDg63y8Uh78\n1sE='
            },
            u'strict': False,
            u'contactPerson': {
                u'technical': {
                    u'givenName': u'technical_name',
                    u'emailAddress': u'*****@*****.**'
                },
                u'support': {
                    u'givenName': u'support_name',
                    u'emailAddress': u'*****@*****.**'
                }
            },
            u'debug': False,
            u'organization': {
                u'en-US': {
                    u'url': u'http://sp.example.com',
                    u'displayname': u'SP test',
                    u'name': u'sp_test'
                }
            },
            u'security': {
                u'signMetadata': False,
                u'wantAssertionsSigned': False,
                u'authnRequestsSigned': False
            },
            u'custom_base_path': u'../../../tests/data/customPath/'
        }
        self.assertEqual(expected_data, settings_result)

        expected_data2 = {
            'sp': {
                u'singleLogoutService': {
                    u'url': u'http://stuff.com/endpoints/endpoints/sls.php'
                },
                u'assertionConsumerService': {
                    u'url': u'http://stuff.com/endpoints/endpoints/acs.php'
                },
                u'entityId':
                u'http://stuff.com/endpoints/metadata.php',
                u'NameIDFormat':
                u'urn:oasis:names:tc:SAML:2.0:nameid-format:unspecified'
            },
            'idp': {
                u'singleLogoutService': {
                    u'url': u'http://idp.example.com/SingleLogoutService.php'
                },
                u'entityId': u'http://idp.example.com/',
                u'x509cert':
                u'MIICgTCCAeoCCQCbOlrWDdX7FTANBgkqhkiG9w0BAQUFADCBhDELMAkGA1UEBhMCTk8xGDAWBgNVBAgTD0FuZHJlYXMgU29sYmVyZzEMMAoGA1UEBxMDRm9vMRAwDgYDVQQKEwdVTklORVRUMRgwFgYDVQQDEw9mZWlkZS5lcmxhbmcubm8xITAfBgkqhkiG9w0BCQEWEmFuZHJlYXNAdW5pbmV0dC5ubzAeFw0wNzA2MTUxMjAxMzVaFw0wNzA4MTQxMjAxMzVaMIGEMQswCQYDVQQGEwJOTzEYMBYGA1UECBMPQW5kcmVhcyBTb2xiZXJnMQwwCgYDVQQHEwNGb28xEDAOBgNVBAoTB1VOSU5FVFQxGDAWBgNVBAMTD2ZlaWRlLmVybGFuZy5ubzEhMB8GCSqGSIb3DQEJARYSYW5kcmVhc0B1bmluZXR0Lm5vMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDivbhR7P516x/S3BqKxupQe0LONoliupiBOesCO3SHbDrl3+q9IbfnfmE04rNuMcPsIxB161TdDpIesLCn7c8aPHISKOtPlAeTZSnb8QAu7aRjZq3+PbrP5uW3TcfCGPtKTytHOge/OlJbo078dVhXQ14d1EDwXJW1rRXuUt4C8QIDAQABMA0GCSqGSIb3DQEBBQUAA4GBACDVfp86HObqY+e8BUoWQ9+VMQx1ASDohBjwOsg2WykUqRXF+dLfcUH9dWR63CtZIKFDbStNomPnQz7nbK+onygwBspVEbnHuUihZq3ZUdmumQqCw4Uvs/1Uvq3orOo/WJVhTyvLgFVK2QarQ4/67OZfHd7R+POBXhophSMv1ZOo',
                u'singleSignOnService': {
                    u'url': u'http://idp.example.com/SSOService.php'
                }
            },
            u'strict': False,
            u'contactPerson': {
                u'technical': {
                    u'givenName': u'technical_name',
                    u'emailAddress': u'*****@*****.**'
                },
                u'support': {
                    u'givenName': u'support_name',
                    u'emailAddress': u'*****@*****.**'
                }
            },
            u'debug': False,
            u'organization': {
                u'en-US': {
                    u'url': u'http://sp.example.com',
                    u'displayname': u'SP test',
                    u'name': u'sp_test'
                }
            },
            u'security': {
                u'signMetadata': False,
                u'wantAssertionsSigned': False,
                u'authnRequestsSigned': False
            },
            u'custom_base_path': u'../../../tests/data/customPath/'
        }
        settings_result2 = OneLogin_Saml2_IdPMetadataParser.merge_settings(
            data, settings)
        self.assertEqual(expected_data2, settings_result2)
Exemple #10
0
def handle_sso_command(cmd):
    if cmd['prefix'] not in ['dashboard sso enable saml2',
                             'dashboard sso disable',
                             'dashboard sso status',
                             'dashboard sso show saml2',
                             'dashboard sso setup saml2']:
        return -errno.ENOSYS, '', ''

    if not python_saml_imported:
        python_saml_name = 'python3-saml' if sys.version_info >= (3, 0) else 'python-saml'
        return -errno.EPERM, '', 'Required library not found: `{}`'.format(python_saml_name)

    if cmd['prefix'] == 'dashboard sso enable saml2':
        try:
            OneLogin_Saml2_Settings(SSO_DB.saml2.onelogin_settings)
        except OneLogin_Saml2_Error:
            return -errno.EPERM, '', 'Single Sign-On is not configured: ' \
                          'use `ceph dashboard sso setup saml2`'
        SSO_DB.protocol = 'saml2'
        SSO_DB.save()
        return 0, 'SSO is "enabled" with "SAML2" protocol.', ''

    if cmd['prefix'] == 'dashboard sso disable':
        SSO_DB.protocol = ''
        SSO_DB.save()
        return 0, 'SSO is "disabled".', ''

    if cmd['prefix'] == 'dashboard sso status':
        if SSO_DB.protocol == 'saml2':
            return 0, 'SSO is "enabled" with "SAML2" protocol.', ''

        return 0, 'SSO is "disabled".', ''

    if cmd['prefix'] == 'dashboard sso show saml2':
        return 0, json.dumps(SSO_DB.saml2.to_dict()), ''

    if cmd['prefix'] == 'dashboard sso setup saml2':
        ceph_dashboard_base_url = cmd['ceph_dashboard_base_url']
        idp_metadata = cmd['idp_metadata']
        idp_username_attribute = _get_optional_attr(cmd, 'idp_username_attribute', 'uid')
        idp_entity_id = _get_optional_attr(cmd, 'idp_entity_id', None)
        sp_x_509_cert = _get_optional_attr(cmd, 'sp_x_509_cert', '')
        sp_private_key = _get_optional_attr(cmd, 'sp_private_key', '')
        if sp_x_509_cert and not sp_private_key:
            return -errno.EINVAL, '', 'Missing parameter `sp_private_key`.'
        if not sp_x_509_cert and sp_private_key:
            return -errno.EINVAL, '', 'Missing parameter `sp_x_509_cert`.'
        has_sp_cert = sp_x_509_cert != "" and sp_private_key != ""
        try:
            # pylint: disable=undefined-variable
            FileNotFoundError
        except NameError:
            # pylint: disable=redefined-builtin
            FileNotFoundError = IOError
        try:
            f = open(sp_x_509_cert, 'r')
            sp_x_509_cert = f.read()
            f.close()
        except FileNotFoundError:
            pass
        try:
            f = open(sp_private_key, 'r')
            sp_private_key = f.read()
            f.close()
        except FileNotFoundError:
            pass
        try:
            idp_settings = OneLogin_Saml2_IdPMetadataParser.parse_remote(idp_metadata,
                                                                         validate_cert=False,
                                                                         entity_id=idp_entity_id)
        # pylint: disable=broad-except
        except Exception:
            try:
                f = open(idp_metadata, 'r')
                idp_metadata = f.read()
                f.close()
            except FileNotFoundError:
                pass
            try:
                idp_settings = OneLogin_Saml2_IdPMetadataParser.parse(idp_metadata,
                                                                      entity_id=idp_entity_id)
            # pylint: disable=broad-except
            except Exception:
                return -errno.EINVAL, '', 'Invalid parameter `idp_metadata`.'

        url_prefix = prepare_url_prefix(mgr.get_config('url_prefix', default=''))
        settings = {
            'sp': {
                'entityId': '{}{}/auth/saml2/metadata'.format(ceph_dashboard_base_url, url_prefix),
                'assertionConsumerService': {
                    'url': '{}{}/auth/saml2'.format(ceph_dashboard_base_url, url_prefix),
                    'binding': "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
                },
                'attributeConsumingService': {
                    'serviceName': "Ceph Dashboard",
                    "serviceDescription": "Ceph Dashboard Service",
                    "requestedAttributes": [
                        {
                            "name": idp_username_attribute,
                            "isRequired": True
                        }
                    ]
                },
                'singleLogoutService': {
                    'url': '{}{}/auth/saml2/logout'.format(ceph_dashboard_base_url, url_prefix),
                    'binding': 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect'
                },
                "x509cert": sp_x_509_cert,
                "privateKey": sp_private_key
            },
            'security': {
                "nameIdEncrypted": has_sp_cert,
                "authnRequestsSigned": has_sp_cert,
                "logoutRequestSigned": has_sp_cert,
                "logoutResponseSigned": has_sp_cert,
                "signMetadata": has_sp_cert,
                "wantMessagesSigned": has_sp_cert,
                "wantAssertionsSigned": has_sp_cert,
                "wantAssertionsEncrypted": has_sp_cert,
                "wantNameIdEncrypted": has_sp_cert,
                "metadataValidUntil": '',
                "wantAttributeStatement": False
            }
        }
        settings = OneLogin_Saml2_IdPMetadataParser.merge_settings(settings, idp_settings)
        SSO_DB.saml2.onelogin_settings = settings
        SSO_DB.protocol = 'saml2'
        SSO_DB.save()
        return 0, json.dumps(SSO_DB.saml2.onelogin_settings), ''

    return -errno.ENOSYS, '', ''
    def test_merge_settings(self):
        """
        Tests the merge_settings method of the OneLogin_Saml2_IdPMetadataParser
        """
        with self.assertRaises(TypeError):
            settings_result = OneLogin_Saml2_IdPMetadataParser.merge_settings(None, {})

        with self.assertRaises(TypeError):
            settings_result = OneLogin_Saml2_IdPMetadataParser.merge_settings({}, None)

        xml_idp_metadata = self.file_contents(join(self.data_path, 'metadata', 'idp_metadata.xml'))

        # Parse XML metadata.
        data = OneLogin_Saml2_IdPMetadataParser.parse(xml_idp_metadata)

        # Read base settings.
        settings = self.loadSettingsJSON()

        # Merge settings from XML metadata into base settings,
        # let XML metadata have priority if there are conflicting
        # attributes.
        settings_result = OneLogin_Saml2_IdPMetadataParser.merge_settings(settings, data)

        # Generate readable JSON representation:
        # print("%s" % json.dumps(settings_result, indent=2).replace(r'\n', r'\\n'))

        expected_settings_json = """
        {
          "custom_base_path": "../../../tests/data/customPath/",
          "contactPerson": {
            "support": {
              "emailAddress": "*****@*****.**",
              "givenName": "support_name"
            },
            "technical": {
              "emailAddress": "*****@*****.**",
              "givenName": "technical_name"
            }
          },
          "idp": {
            "singleSignOnService": {
              "url": "https://app.onelogin.com/trust/saml2/http-post/sso/383123",
              "binding": "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
            },
            "entityId": "https://app.onelogin.com/saml/metadata/383123",
            "singleLogoutService": {
              "url": "http://idp.example.com/SingleLogoutService.php"
            },
            "x509cert": "MIIEHjCCAwagAwIBAgIBATANBgkqhkiG9w0BAQUFADBnMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEVMBMGA1UEBwwMU2FudGEgTW9uaWNhMREwDwYDVQQKDAhPbmVMb2dpbjEZMBcGA1UEAwwQYXBwLm9uZWxvZ2luLmNvbTAeFw0xMzA2MDUxNzE2MjBaFw0xODA2MDUxNzE2MjBaMGcxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRUwEwYDVQQHDAxTYW50YSBNb25pY2ExETAPBgNVBAoMCE9uZUxvZ2luMRkwFwYDVQQDDBBhcHAub25lbG9naW4uY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAse8rnep4qL2GmhH10pMQyJ2Jae+AQHyfgVjaQZ7Z0QQog5jX91vcJRSMi0XWJnUtOr6lF0dq1+yckjZ92wyLrH+7fvngNO1aV4Mjk9sTgf+iqMrae6y6fRxDt9PXrEFVjvd3vv7QTJf2FuIPy4vVP06Dt8EMkQIr8rmLmU0mTr1k2DkrdtdlCuNFTXuAu3QqfvNCRrRwfNObn9MP6JeOUdcGLJsBjGF8exfcN1SFzRF0JFr3dmOlx761zK5liD0T1sYWnDquatj/JD9fZMbKecBKni1NglH/LVd+b6aJUAr5LulERULUjLqYJRKW31u91/4Qazdo9tbvwqyFxaoUrwIDAQABo4HUMIHRMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFPWcXvQSlTXnzZD2xziuoUvrrDedMIGRBgNVHSMEgYkwgYaAFPWcXvQSlTXnzZD2xziuoUvrrDedoWukaTBnMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEVMBMGA1UEBwwMU2FudGEgTW9uaWNhMREwDwYDVQQKDAhPbmVMb2dpbjEZMBcGA1UEAwwQYXBwLm9uZWxvZ2luLmNvbYIBATAOBgNVHQ8BAf8EBAMCBPAwDQYJKoZIhvcNAQEFBQADggEBAB/8xe3rzqXQVxzHyAHuAuPa73ClDoL1cko0Fp8CGcqEIyj6Te9gx5z6wyfv+Lo8RFvBLlnB1lXqbC+fTGcVgG/4oKLJ5UwRFxInqpZPnOAudVNnd0PYOODn9FWs6u+OTIQIaIcPUv3MhB9lwHIJsTk/bs9xcru5TPyLIxLLd6ib/pRceKH2mTkzUd0DYk9CQNXXeoGx/du5B9nh3ClPTbVakRzl3oswgI5MQIphYxkW70SopEh4kOFSRE1ND31NNIq1YrXlgtkguQBFsZWuQOPR6cEwFZzP0tHTYbI839WgxX6hfhIUTUz6mLqq4+3P4BG3+1OXeVDg63y8Uh781sE="
          },
          "sp": {
            "NameIDFormat": "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress",
            "entityId": "http://stuff.com/endpoints/metadata.php",
            "assertionConsumerService": {
              "url": "http://stuff.com/endpoints/endpoints/acs.php"
            },
            "singleLogoutService": {
              "url": "http://stuff.com/endpoints/endpoints/sls.php"
            }
          },
          "security": {
            "wantAssertionsSigned": false,
            "authnRequestsSigned": false,
            "signMetadata": false
          },
          "debug": false,
          "organization": {
            "en-US": {
              "displayname": "SP test",
              "url": "http://sp.example.com",
              "name": "sp_test"
            }
          },
          "strict": false
        }
        """
        expected_settings = json.loads(expected_settings_json)
        self.assertEqual(expected_settings, settings_result)

        # Commute merge operation. As the order determines which settings
        # dictionary has priority, here we expect a different result.
        settings_result2 = OneLogin_Saml2_IdPMetadataParser.merge_settings(data, settings)
        expected_settings2_json = """
        {
          "debug": false,
          "idp": {
            "singleLogoutService": {
              "url": "http://idp.example.com/SingleLogoutService.php"
            },
            "singleSignOnService": {
              "url": "http://idp.example.com/SSOService.php",
              "binding": "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
            },
            "entityId": "http://idp.example.com/",
            "x509cert": "MIICgTCCAeoCCQCbOlrWDdX7FTANBgkqhkiG9w0BAQUFADCBhDELMAkGA1UEBhMCTk8xGDAWBgNVBAgTD0FuZHJlYXMgU29sYmVyZzEMMAoGA1UEBxMDRm9vMRAwDgYDVQQKEwdVTklORVRUMRgwFgYDVQQDEw9mZWlkZS5lcmxhbmcubm8xITAfBgkqhkiG9w0BCQEWEmFuZHJlYXNAdW5pbmV0dC5ubzAeFw0wNzA2MTUxMjAxMzVaFw0wNzA4MTQxMjAxMzVaMIGEMQswCQYDVQQGEwJOTzEYMBYGA1UECBMPQW5kcmVhcyBTb2xiZXJnMQwwCgYDVQQHEwNGb28xEDAOBgNVBAoTB1VOSU5FVFQxGDAWBgNVBAMTD2ZlaWRlLmVybGFuZy5ubzEhMB8GCSqGSIb3DQEJARYSYW5kcmVhc0B1bmluZXR0Lm5vMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDivbhR7P516x/S3BqKxupQe0LONoliupiBOesCO3SHbDrl3+q9IbfnfmE04rNuMcPsIxB161TdDpIesLCn7c8aPHISKOtPlAeTZSnb8QAu7aRjZq3+PbrP5uW3TcfCGPtKTytHOge/OlJbo078dVhXQ14d1EDwXJW1rRXuUt4C8QIDAQABMA0GCSqGSIb3DQEBBQUAA4GBACDVfp86HObqY+e8BUoWQ9+VMQx1ASDohBjwOsg2WykUqRXF+dLfcUH9dWR63CtZIKFDbStNomPnQz7nbK+onygwBspVEbnHuUihZq3ZUdmumQqCw4Uvs/1Uvq3orOo/WJVhTyvLgFVK2QarQ4/67OZfHd7R+POBXhophSMv1ZOo"
          },
          "security": {
            "authnRequestsSigned": false,
            "wantAssertionsSigned": false,
            "signMetadata": false
          },
          "contactPerson": {
            "technical": {
              "emailAddress": "*****@*****.**",
              "givenName": "technical_name"
            },
            "support": {
              "emailAddress": "*****@*****.**",
              "givenName": "support_name"
            }
          },
          "strict": false,
          "sp": {
            "singleLogoutService": {
              "url": "http://stuff.com/endpoints/endpoints/sls.php"
            },
            "assertionConsumerService": {
              "url": "http://stuff.com/endpoints/endpoints/acs.php"
            },
            "entityId": "http://stuff.com/endpoints/metadata.php",
            "NameIDFormat": "urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"
          },
          "custom_base_path": "../../../tests/data/customPath/",
          "organization": {
            "en-US": {
              "displayname": "SP test",
              "url": "http://sp.example.com",
              "name": "sp_test"
            }
          }
        }
        """
        expected_settings2 = json.loads(expected_settings2_json)
        self.assertEqual(expected_settings2, settings_result2)

        # Test merging multiple certs
        xml_idp_metadata = self.file_contents(join(self.data_path, 'metadata', 'idp_metadata_multi_certs.xml'))
        data3 = OneLogin_Saml2_IdPMetadataParser.parse(xml_idp_metadata)
        settings_result3 = OneLogin_Saml2_IdPMetadataParser.merge_settings(settings, data3)
        expected_settings3_json = """
        {
          "debug": false,
          "strict": false,
          "custom_base_path": "../../../tests/data/customPath/",
          "sp": {
            "singleLogoutService": {
              "url": "http://stuff.com/endpoints/endpoints/sls.php"
            },
            "assertionConsumerService": {
              "url": "http://stuff.com/endpoints/endpoints/acs.php"
            },
            "entityId": "http://stuff.com/endpoints/metadata.php",
            "NameIDFormat": "urn:oasis:names:tc:SAML:2.0:nameid-format:transient"
          },
          "idp": {
            "singleLogoutService": {
              "url": "https://idp.examle.com/saml/slo",
              "binding": "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
            },
            "x509certMulti": {
              "encryption": [
                "MIIEZTCCA02gAwIBAgIUPyy/A3bZAZ4m28PzEUUoT7RJhxIwDQYJKoZIhvcNAQEFBQAwcjELMAkGA1UEBhMCVVMxKzApBgNVBAoMIk9uZUxvZ2luIFRlc3QgKHNnYXJjaWEtdXMtcHJlcHJvZCkxFTATBgNVBAsMDE9uZUxvZ2luIElkUDEfMB0GA1UEAwwWT25lTG9naW4gQWNjb3VudCA4OTE0NjAeFw0xNjA4MDQyMjI5MzdaFw0yMTA4MDUyMjI5MzdaMHIxCzAJBgNVBAYTAlVTMSswKQYDVQQKDCJPbmVMb2dpbiBUZXN0IChzZ2FyY2lhLXVzLXByZXByb2QpMRUwEwYDVQQLDAxPbmVMb2dpbiBJZFAxHzAdBgNVBAMMFk9uZUxvZ2luIEFjY291bnQgODkxNDYwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDN6iqQGcLOCglNO42I2rkzE05UXSiMXT6c8ALThMMiaDw6qqzo3sd/tKK+NcNKWLIIC8TozWVyh5ykUiVZps+08xil7VsTU7E+wKu3kvmOsvw2wlRwtnoKZJwYhnr+RkBa+h1r3ZYUgXm1ZPeHMKj1g18KaWz9+MxYL6BhKqrOzfW/P2xxVRcFH7/pq+ZsDdgNzD2GD+apzY4MZyZj/N6BpBWJ0GlFsmtBegpbX3LBitJuFkk5L4/U/jjF1AJa3boBdCUVfATqO5G03H4XS1GySjBIRQXmlUF52rLjg6xCgWJ30/+t1X+IHLJeixiQ0vxyh6C4/usCEt94cgD1r8ADAgMBAAGjgfIwge8wDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQUPW0DcH0G3IwynWgi74co4wZ6n7gwga8GA1UdIwSBpzCBpIAUPW0DcH0G3IwynWgi74co4wZ6n7ihdqR0MHIxCzAJBgNVBAYTAlVTMSswKQYDVQQKDCJPbmVMb2dpbiBUZXN0IChzZ2FyY2lhLXVzLXByZXByb2QpMRUwEwYDVQQLDAxPbmVMb2dpbiBJZFAxHzAdBgNVBAMMFk9uZUxvZ2luIEFjY291bnQgODkxNDaCFD8svwN22QGeJtvD8xFFKE+0SYcSMA4GA1UdDwEB/wQEAwIHgDANBgkqhkiG9w0BAQUFAAOCAQEAQhB4q9jrycwbHrDSoYR1X4LFFzvJ9Us75wQquRHXpdyS9D6HUBXMGI6ahPicXCQrfLgN8vzMIiqZqfySXXv/8/dxe/X4UsWLYKYJHDJmxXD5EmWTa65chjkeP1oJAc8f3CKCpcP2lOBTthbnk2fEVAeLHR4xNdQO0VvGXWO9BliYPpkYqUIBvlm+Fg9mF7AM/Uagq2503XXIE1Lq//HON68P10vNMwLSKOtYLsoTiCnuIKGJqG37MsZVjQ1ZPRcO+LSLkq0i91gFxrOrVCrgztX4JQi5XkvEsYZGIXXjwHqxTVyt3adZWQO0LPxPqRiUqUzyhDhLo/xXNrHCu4VbMw=="
              ],
              "signing": [
                "MIIEZTCCA02gAwIBAgIUPyy/A3bZAZ4m28PzEUUoT7RJhxIwDQYJKoZIhvcNAQEFBQAwcjELMAkGA1UEBhMCVVMxKzApBgNVBAoMIk9uZUxvZ2luIFRlc3QgKHNnYXJjaWEtdXMtcHJlcHJvZCkxFTATBgNVBAsMDE9uZUxvZ2luIElkUDEfMB0GA1UEAwwWT25lTG9naW4gQWNjb3VudCA4OTE0NjAeFw0xNjA4MDQyMjI5MzdaFw0yMTA4MDUyMjI5MzdaMHIxCzAJBgNVBAYTAlVTMSswKQYDVQQKDCJPbmVMb2dpbiBUZXN0IChzZ2FyY2lhLXVzLXByZXByb2QpMRUwEwYDVQQLDAxPbmVMb2dpbiBJZFAxHzAdBgNVBAMMFk9uZUxvZ2luIEFjY291bnQgODkxNDYwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDN6iqQGcLOCglNO42I2rkzE05UXSiMXT6c8ALThMMiaDw6qqzo3sd/tKK+NcNKWLIIC8TozWVyh5ykUiVZps+08xil7VsTU7E+wKu3kvmOsvw2wlRwtnoKZJwYhnr+RkBa+h1r3ZYUgXm1ZPeHMKj1g18KaWz9+MxYL6BhKqrOzfW/P2xxVRcFH7/pq+ZsDdgNzD2GD+apzY4MZyZj/N6BpBWJ0GlFsmtBegpbX3LBitJuFkk5L4/U/jjF1AJa3boBdCUVfATqO5G03H4XS1GySjBIRQXmlUF52rLjg6xCgWJ30/+t1X+IHLJeixiQ0vxyh6C4/usCEt94cgD1r8ADAgMBAAGjgfIwge8wDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQUPW0DcH0G3IwynWgi74co4wZ6n7gwga8GA1UdIwSBpzCBpIAUPW0DcH0G3IwynWgi74co4wZ6n7ihdqR0MHIxCzAJBgNVBAYTAlVTMSswKQYDVQQKDCJPbmVMb2dpbiBUZXN0IChzZ2FyY2lhLXVzLXByZXByb2QpMRUwEwYDVQQLDAxPbmVMb2dpbiBJZFAxHzAdBgNVBAMMFk9uZUxvZ2luIEFjY291bnQgODkxNDaCFD8svwN22QGeJtvD8xFFKE+0SYcSMA4GA1UdDwEB/wQEAwIHgDANBgkqhkiG9w0BAQUFAAOCAQEAQhB4q9jrycwbHrDSoYR1X4LFFzvJ9Us75wQquRHXpdyS9D6HUBXMGI6ahPicXCQrfLgN8vzMIiqZqfySXXv/8/dxe/X4UsWLYKYJHDJmxXD5EmWTa65chjkeP1oJAc8f3CKCpcP2lOBTthbnk2fEVAeLHR4xNdQO0VvGXWO9BliYPpkYqUIBvlm+Fg9mF7AM/Uagq2503XXIE1Lq//HON68P10vNMwLSKOtYLsoTiCnuIKGJqG37MsZVjQ1ZPRcO+LSLkq0i91gFxrOrVCrgztX4JQi5XkvEsYZGIXXjwHqxTVyt3adZWQO0LPxPqRiUqUzyhDhLo/xXNrHCu4VbMw==",
                "MIICZDCCAc2gAwIBAgIBADANBgkqhkiG9w0BAQ0FADBPMQswCQYDVQQGEwJ1czEUMBIGA1UECAwLZXhhbXBsZS5jb20xFDASBgNVBAoMC2V4YW1wbGUuY29tMRQwEgYDVQQDDAtleGFtcGxlLmNvbTAeFw0xNzA0MTUxNjMzMThaFw0xODA0MTUxNjMzMThaME8xCzAJBgNVBAYTAnVzMRQwEgYDVQQIDAtleGFtcGxlLmNvbTEUMBIGA1UECgwLZXhhbXBsZS5jb20xFDASBgNVBAMMC2V4YW1wbGUuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC6GLkl5lDUZdHNDAojp5i24OoPlqrt5TGXJIPqAZYT1hQvJW5nv17MFDHrjmtEnmW4ACKEy0fAX80QWIcHunZSkbEGHb+NG/6oTi5RipXMvmHnfFnPJJ0AdtiLiPE478CV856gXekV4Xx5u3KrylcOgkpYsp0GMIQBDzleMUXlYQIDAQABo1AwTjAdBgNVHQ4EFgQUnP8vlYPGPL2n6ZzDYij2kMDC8wMwHwYDVR0jBBgwFoAUnP8vlYPGPL2n6ZzDYij2kMDC8wMwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQ0FAAOBgQAlQGAl+b8Cpot1g+65lLLjVoY7APJPWLW0klKQNlMU0s4MU+71Y3ExUEOXDAZgKcFoavb1fEOGMwEf38NaJAy1e/l6VNuixXShffq20ymqHQxOG0q8ujeNkgZF9k6XDfn/QZ3AD0o/IrCT7UMc/0QsfgIjWYxwCvp2syApc5CYfQ=="
              ]
            },
            "entityId": "https://idp.examle.com/saml/metadata",
            "singleSignOnService": {
              "url": "https://idp.examle.com/saml/sso",
              "binding": "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
            }
          },
          "security": {
            "authnRequestsSigned": false,
            "wantAssertionsSigned": false,
            "signMetadata": false
          },
          "contactPerson": {
            "technical": {
              "emailAddress": "*****@*****.**",
              "givenName": "technical_name"
            },
            "support": {
              "emailAddress": "*****@*****.**",
              "givenName": "support_name"
            }
          },
          "organization": {
            "en-US": {
              "displayname": "SP test",
              "url": "http://sp.example.com",
              "name": "sp_test"
            }
          }
        }
        """
        expected_settings3 = json.loads(expected_settings3_json)
        self.assertEqual(expected_settings3, settings_result3)
Exemple #12
0
def handle_sso_command(cmd):
    if cmd['prefix'] not in ['dashboard sso enable saml2',
                             'dashboard sso disable',
                             'dashboard sso status',
                             'dashboard sso show saml2',
                             'dashboard sso setup saml2']:
        return -errno.ENOSYS, '', ''

    if not python_saml_imported:
        return -errno.EPERM, '', 'Required library not found: `python3-saml`'

    if cmd['prefix'] == 'dashboard sso enable saml2':
        try:
            Saml2Settings(mgr.SSO_DB.saml2.onelogin_settings)
        except Saml2Error:
            return -errno.EPERM, '', 'Single Sign-On is not configured: ' \
                          'use `ceph dashboard sso setup saml2`'
        mgr.SSO_DB.protocol = 'saml2'
        mgr.SSO_DB.save()
        return 0, 'SSO is "enabled" with "SAML2" protocol.', ''

    if cmd['prefix'] == 'dashboard sso disable':
        mgr.SSO_DB.protocol = ''
        mgr.SSO_DB.save()
        return 0, 'SSO is "disabled".', ''

    if cmd['prefix'] == 'dashboard sso status':
        if mgr.SSO_DB.protocol == 'saml2':
            return 0, 'SSO is "enabled" with "SAML2" protocol.', ''

        return 0, 'SSO is "disabled".', ''

    if cmd['prefix'] == 'dashboard sso show saml2':
        return 0, json.dumps(mgr.SSO_DB.saml2.to_dict()), ''

    if cmd['prefix'] == 'dashboard sso setup saml2':
        ceph_dashboard_base_url = cmd['ceph_dashboard_base_url']
        idp_metadata = cmd['idp_metadata']
        idp_username_attribute = _get_optional_attr(cmd, 'idp_username_attribute', 'uid')
        idp_entity_id = _get_optional_attr(cmd, 'idp_entity_id', None)
        sp_x_509_cert_path = _get_optional_attr(cmd, 'sp_x_509_cert', '')
        sp_private_key_path = _get_optional_attr(cmd, 'sp_private_key', '')
        if sp_x_509_cert_path and not sp_private_key_path:
            return -errno.EINVAL, '', 'Missing parameter `sp_private_key`.'
        if not sp_x_509_cert_path and sp_private_key_path:
            return -errno.EINVAL, '', 'Missing parameter `sp_x_509_cert`.'
        has_sp_cert = sp_x_509_cert_path != "" and sp_private_key_path != ""
        try:
            with open(sp_x_509_cert_path, 'r') as f:
                sp_x_509_cert = f.read()
        except FileNotFoundError:
            sp_x_509_cert = ''
        try:
            with open(sp_private_key_path, 'r') as f:
                sp_private_key = f.read()
        except FileNotFoundError:
            sp_private_key = ''

        if os.path.isfile(idp_metadata):
            warnings.warn(
                "Please prepend 'file://' to indicate a local SAML2 IdP file", DeprecationWarning)
            with open(idp_metadata, 'r') as f:
                idp_settings = Saml2Parser.parse(f.read(), entity_id=idp_entity_id)
        elif parse.urlparse(idp_metadata)[0] in ('http', 'https', 'file'):
            idp_settings = Saml2Parser.parse_remote(
                url=idp_metadata, validate_cert=False, entity_id=idp_entity_id)
        else:
            idp_settings = Saml2Parser.parse(idp_metadata, entity_id=idp_entity_id)

        url_prefix = prepare_url_prefix(mgr.get_module_option('url_prefix', default=''))
        settings = {
            'sp': {
                'entityId': '{}{}/auth/saml2/metadata'.format(ceph_dashboard_base_url, url_prefix),
                'assertionConsumerService': {
                    'url': '{}{}/auth/saml2'.format(ceph_dashboard_base_url, url_prefix),
                    'binding': "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
                },
                'attributeConsumingService': {
                    'serviceName': "Ceph Dashboard",
                    "serviceDescription": "Ceph Dashboard Service",
                    "requestedAttributes": [
                        {
                            "name": idp_username_attribute,
                            "isRequired": True
                        }
                    ]
                },
                'singleLogoutService': {
                    'url': '{}{}/auth/saml2/logout'.format(ceph_dashboard_base_url, url_prefix),
                    'binding': 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect'
                },
                "x509cert": sp_x_509_cert,
                "privateKey": sp_private_key
            },
            'security': {
                "nameIdEncrypted": has_sp_cert,
                "authnRequestsSigned": has_sp_cert,
                "logoutRequestSigned": has_sp_cert,
                "logoutResponseSigned": has_sp_cert,
                "signMetadata": has_sp_cert,
                "wantMessagesSigned": has_sp_cert,
                "wantAssertionsSigned": has_sp_cert,
                "wantAssertionsEncrypted": has_sp_cert,
                "wantNameIdEncrypted": has_sp_cert,
                "metadataValidUntil": '',
                "wantAttributeStatement": False
            }
        }
        settings = Saml2Parser.merge_settings(settings, idp_settings)
        mgr.SSO_DB.saml2.onelogin_settings = settings
        mgr.SSO_DB.protocol = 'saml2'
        mgr.SSO_DB.save()
        return 0, json.dumps(mgr.SSO_DB.saml2.onelogin_settings), ''

    return -errno.ENOSYS, '', ''
Exemple #13
0
def handle_sso_command(cmd):
    if cmd['prefix'] not in [
            'dashboard sso enable saml2', 'dashboard sso disable',
            'dashboard sso status', 'dashboard sso show saml2',
            'dashboard sso setup saml2'
    ]:
        return -errno.ENOSYS, '', ''

    if not python_saml_imported:
        python_saml_name = 'python3-saml' if sys.version_info >= (
            3, 0) else 'python-saml'
        return -errno.EPERM, '', 'Required library not found: `{}`'.format(
            python_saml_name)

    if cmd['prefix'] == 'dashboard sso enable saml2':
        try:
            OneLogin_Saml2_Settings(mgr.SSO_DB.saml2.onelogin_settings)
        except OneLogin_Saml2_Error:
            return -errno.EPERM, '', 'Single Sign-On is not configured: ' \
                          'use `ceph dashboard sso setup saml2`'
        mgr.SSO_DB.protocol = 'saml2'
        mgr.SSO_DB.save()
        return 0, 'SSO is "enabled" with "SAML2" protocol.', ''

    if cmd['prefix'] == 'dashboard sso disable':
        mgr.SSO_DB.protocol = ''
        mgr.SSO_DB.save()
        return 0, 'SSO is "disabled".', ''

    if cmd['prefix'] == 'dashboard sso status':
        if mgr.SSO_DB.protocol == 'saml2':
            return 0, 'SSO is "enabled" with "SAML2" protocol.', ''

        return 0, 'SSO is "disabled".', ''

    if cmd['prefix'] == 'dashboard sso show saml2':
        return 0, json.dumps(mgr.SSO_DB.saml2.to_dict()), ''

    if cmd['prefix'] == 'dashboard sso setup saml2':
        ceph_dashboard_base_url = cmd['ceph_dashboard_base_url']
        idp_metadata = cmd['idp_metadata']
        idp_username_attribute = _get_optional_attr(cmd,
                                                    'idp_username_attribute',
                                                    'uid')
        idp_entity_id = _get_optional_attr(cmd, 'idp_entity_id', None)
        sp_x_509_cert = _get_optional_attr(cmd, 'sp_x_509_cert', '')
        sp_private_key = _get_optional_attr(cmd, 'sp_private_key', '')
        if sp_x_509_cert and not sp_private_key:
            return -errno.EINVAL, '', 'Missing parameter `sp_private_key`.'
        if not sp_x_509_cert and sp_private_key:
            return -errno.EINVAL, '', 'Missing parameter `sp_x_509_cert`.'
        has_sp_cert = sp_x_509_cert != "" and sp_private_key != ""
        try:
            # pylint: disable=undefined-variable
            FileNotFoundError
        except NameError:
            # pylint: disable=redefined-builtin
            FileNotFoundError = IOError
        try:
            f = open(sp_x_509_cert, 'r', encoding='utf-8') if six.PY3 else \
                open(sp_x_509_cert, 'rb')
            sp_x_509_cert = f.read()
            f.close()
        except FileNotFoundError:
            pass
        try:
            f = open(sp_private_key, 'r', encoding='utf-8') if six.PY3 else \
                open(sp_private_key, 'rb')
            sp_private_key = f.read()
            f.close()
        except FileNotFoundError:
            pass
        try:
            idp_settings = OneLogin_Saml2_IdPMetadataParser.parse_remote(
                idp_metadata, validate_cert=False, entity_id=idp_entity_id)
        # pylint: disable=broad-except
        except Exception:
            try:
                f = open(idp_metadata, 'r', encoding='utf-8') if six.PY3 else \
                    open(idp_metadata, 'rb')
                idp_metadata = f.read()
                f.close()
            except FileNotFoundError:
                pass
            try:
                idp_settings = OneLogin_Saml2_IdPMetadataParser.parse(
                    idp_metadata, entity_id=idp_entity_id)
            # pylint: disable=broad-except
            except Exception:
                return -errno.EINVAL, '', 'Invalid parameter `idp_metadata`.'

        url_prefix = prepare_url_prefix(
            mgr.get_module_option('url_prefix', default=''))
        settings = {
            'sp': {
                'entityId':
                '{}{}/auth/saml2/metadata'.format(ceph_dashboard_base_url,
                                                  url_prefix),
                'assertionConsumerService': {
                    'url':
                    '{}{}/auth/saml2'.format(ceph_dashboard_base_url,
                                             url_prefix),
                    'binding':
                    "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
                },
                'attributeConsumingService': {
                    'serviceName':
                    "Ceph Dashboard",
                    "serviceDescription":
                    "Ceph Dashboard Service",
                    "requestedAttributes": [{
                        "name": idp_username_attribute,
                        "isRequired": True
                    }]
                },
                'singleLogoutService': {
                    'url':
                    '{}{}/auth/saml2/logout'.format(ceph_dashboard_base_url,
                                                    url_prefix),
                    'binding':
                    'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect'
                },
                "x509cert":
                sp_x_509_cert,
                "privateKey":
                sp_private_key
            },
            'security': {
                "nameIdEncrypted": has_sp_cert,
                "authnRequestsSigned": has_sp_cert,
                "logoutRequestSigned": has_sp_cert,
                "logoutResponseSigned": has_sp_cert,
                "signMetadata": has_sp_cert,
                "wantMessagesSigned": has_sp_cert,
                "wantAssertionsSigned": has_sp_cert,
                "wantAssertionsEncrypted": has_sp_cert,
                "wantNameIdEncrypted":
                False,  # Not all Identity Providers support this.
                "metadataValidUntil": '',
                "wantAttributeStatement": False
            }
        }
        settings = OneLogin_Saml2_IdPMetadataParser.merge_settings(
            settings, idp_settings)
        mgr.SSO_DB.saml2.onelogin_settings = settings
        mgr.SSO_DB.protocol = 'saml2'
        mgr.SSO_DB.save()
        return 0, json.dumps(mgr.SSO_DB.saml2.onelogin_settings), ''

    return -errno.ENOSYS, '', ''