Beispiel #1
0
    def test_authn_response(self, context, idp_conf, sp_conf):
        response_binding = BINDING_HTTP_REDIRECT
        fakesp = FakeSP(SPConfig().load(sp_conf, metadata_construction=False))
        fakeidp = FakeIdP(USERS,
                          config=IdPConfig().load(idp_conf,
                                                  metadata_construction=False))
        destination, request_params = fakesp.make_auth_req(
            idp_conf["entityid"])
        url, auth_resp = fakeidp.handle_auth_req(
            request_params["SAMLRequest"],
            request_params["RelayState"],
            BINDING_HTTP_REDIRECT,
            "testuser1",
            response_binding=response_binding)

        context.request = auth_resp
        context.state[self.samlbackend.name] = {
            "relay_state": request_params["RelayState"]
        }
        self.samlbackend.authn_response(context, response_binding)

        context, internal_resp = self.samlbackend.auth_callback_func.call_args[
            0]
        self.assert_authn_response(internal_resp)
        assert self.samlbackend.name not in context.state
Beispiel #2
0
    def test_authn_response_no_name_id(self, context, idp_conf, sp_conf):
        response_binding = BINDING_HTTP_REDIRECT

        fakesp_conf = SPConfig().load(sp_conf, metadata_construction=False)
        fakesp = FakeSP(fakesp_conf)

        fakeidp_conf = IdPConfig().load(idp_conf, metadata_construction=False)
        fakeidp = FakeIdP(USERS, config=fakeidp_conf)

        destination, request_params = fakesp.make_auth_req(
            idp_conf["entityid"])

        # Use the fake IdP to mock up an authentication request that has no
        # <NameID> element.
        url, auth_resp = fakeidp.handle_auth_req_no_name_id(
            request_params["SAMLRequest"],
            request_params["RelayState"],
            BINDING_HTTP_REDIRECT,
            "testuser1",
            response_binding=response_binding)

        backend = self.samlbackend

        context.request = auth_resp
        context.state[backend.name] = {
            "relay_state": request_params["RelayState"],
        }
        backend.authn_response(context, response_binding)

        context, internal_resp = backend.auth_callback_func.call_args[0]
        assert_authn_response(internal_resp)
        assert backend.name not in context.state
Beispiel #3
0
 def dispatch(self, request, *args, **kwargs):
     """ Construct IDP server with config from settings dict
     """
     conf = IdPConfig()
     conf.load(copy.deepcopy(settings.SAML_IDP_CONFIG))
     self.IDP = Server(config=conf)
     return super(IdPHandlerViewMixin, self).dispatch(request, *args, **kwargs)
def test_crypto_backend():
    idpc = IdPConfig()
    idpc.load(IDP_XMLSECURITY)

    assert idpc.crypto_backend == 'XMLSecurity'
    sec = security_context(idpc)
    assert isinstance(sec.crypto, CryptoBackendXMLSecurity)
Beispiel #5
0
    def idp_configure(self, metadata_construction=False):
        sys.path.insert(0, self.args.configpath)
        mod = import_module(self.args.config)
        self.idp_config = IdPConfig().load(mod.CONFIG, metadata_construction)

        if not self.args.insecure:
            self.idp_config.verify_ssl_cert = False
        else:
            if self.args.ca_certs:
                self.idp_config.ca_certs = self.args.ca_certs
            else:
                self.idp_config.ca_certs = "../keys/cacert.pem"
        # hack to change idp cert without config change. TODO: find interface to
        # change IDP cert after __init__
        if self.args.oper == 'sp-04':
            self.idp_config.cert_file = os.path.join(self.args.keysdir,
                                                     "non_md_cert.pem")
            self.idp_config.key_file = os.path.join(self.args.keysdir,
                                                    "non_md_key.pem")
            for f in [self.idp_config.cert_file, self.idp_config.key_file]:
                if not os.path.isfile(f):
                    print "File not found: %s" % os.path.abspath(f)
                    raise

        self.idp = Server(config=self.idp_config)
Beispiel #6
0
def metadata(request):
    """ Returns an XML with the SAML 2.0 metadata for this Idp.
        The metadata is constructed on-the-fly based on the config dict in the django settings.
    """
    conf = IdPConfig()
    conf.load(copy.deepcopy(settings.SAML_IDP_CONFIG))
    metadata = entity_descriptor(conf)
    return HttpResponse(content=text_type(metadata).encode('utf-8'), content_type="text/xml; charset=utf8")
 def metadata(cls) -> str:
     conf = IdPConfig()
     try:
         conf.load(cls.construct_metadata())
         metadata = entity_descriptor(conf)
     except:
         pass
     return str(metadata)
             
Beispiel #8
0
    def test_full_flow(self, satosa_config_dict, oidc_frontend_config, saml_backend_config, idp_conf):
        subject_id = "testuser1"

        # proxy config
        satosa_config_dict["FRONTEND_MODULES"] = [oidc_frontend_config]
        satosa_config_dict["BACKEND_MODULES"] = [saml_backend_config]
        satosa_config_dict["INTERNAL_ATTRIBUTES"]["attributes"] = {attr_name: {"openid": [attr_name],
                                                                               "saml": [attr_name]}
                                                                   for attr_name in USERS[subject_id]}
        _, backend_metadata = create_entity_descriptors(SATOSAConfig(satosa_config_dict))

        # application
        test_client = Client(make_app(SATOSAConfig(satosa_config_dict)), Response)

        # get frontend OP config info
        provider_config = json.loads(test_client.get("/.well-known/openid-configuration").data.decode("utf-8"))

        # create auth req
        claims_request = ClaimsRequest(id_token=Claims(**{k: None for k in USERS[subject_id]}))
        req_args = {"scope": "openid", "response_type": "id_token", "client_id": CLIENT_ID,
                    "redirect_uri": REDIRECT_URI, "nonce": "nonce",
                    "claims": claims_request.to_json()}
        auth_req = urlparse(provider_config["authorization_endpoint"]).path + "?" + urlencode(req_args)

        # make auth req to proxy
        proxied_auth_req = test_client.get(auth_req)
        assert proxied_auth_req.status == "303 See Other"

        # config test IdP
        backend_metadata_str = str(backend_metadata[saml_backend_config["name"]][0])
        idp_conf["metadata"]["inline"].append(backend_metadata_str)
        fakeidp = FakeIdP(USERS, config=IdPConfig().load(idp_conf))

        # create auth resp
        req_params = dict(parse_qsl(urlparse(proxied_auth_req.data.decode("utf-8")).query))
        url, authn_resp = fakeidp.handle_auth_req(
            req_params["SAMLRequest"],
            req_params["RelayState"],
            BINDING_HTTP_REDIRECT,
            subject_id,
            response_binding=BINDING_HTTP_REDIRECT)

        # make auth resp to proxy
        authn_resp_req = urlparse(url).path + "?" + urlencode(authn_resp)
        authn_resp = test_client.get(authn_resp_req)
        assert authn_resp.status == "303 See Other"

        # verify auth resp from proxy
        resp_dict = dict(parse_qsl(urlparse(authn_resp.data.decode("utf-8")).fragment))
        signing_key = RSAKey(key=rsa_load(oidc_frontend_config["config"]["signing_key_path"]),
                             use="sig", alg="RS256")
        id_token_claims = JWS().verify_compact(resp_dict["id_token"], keys=[signing_key])

        assert all(
            (name, values) in id_token_claims.items()
            for name, values in OIDC_USERS[subject_id].items()
        )
Beispiel #9
0
def test_idp_1():
    c = IdPConfig().load(IDP1)
    c.context = "idp"

    print c
    assert c.endpoint("single_sign_on_service")[0] == 'http://localhost:8088/'

    attribute_restrictions = c.policy.get_attribute_restriction("")
    assert attribute_restrictions["eduPersonAffiliation"][0].match("staff")
Beispiel #10
0
 def metadata(cls) -> str:
     """ Get the IDP metadata as a string. """
     conf = IdPConfig()
     try:
         conf.load(cls.construct_metadata())
         metadata = entity_descriptor(conf)
     except Exception as e:
         raise ImproperlyConfigured(_('Could not instantiate IDP metadata based on the SAML_IDP_CONFIG settings and configured ServiceProviders: {}').format(str(e)))
     return str(metadata)
 def load(cls, force_refresh:bool = False) -> Server:
     if cls._server_instance is None or force_refresh:
         conf = IdPConfig() #
         md = cls.construct_metadata() #
         try:
             conf.load(md)
             cls._server_instance = Server(config=conf)
         except:
             pass
     return cls._server_instance
Beispiel #12
0
 def dispatch(self, request, *args, **kwargs):
     """ Construct IDP server with config from settings dict
     """
     conf = IdPConfig()
     try:
         conf.load(copy.deepcopy(settings.SAML_IDP_CONFIG))
         self.IDP = Server(config=conf)
     except Exception as e:
         return self.handle_error(request, exception=e)
     return super().dispatch(request, *args, **kwargs)
Beispiel #13
0
 def dispatch(self, request, *args, **kwargs):
     """ Construct IDP server with config from settings dict
     """
     conf = IdPConfig()
     try:
         conf.load(copy.deepcopy(get_idp_config()))
         self.IDP = Server(config=conf)
     except Exception as e:
         return self.handle_error(request, exception=e)
     return super(IdPHandlerViewMixin,
                  self).dispatch(request, *args, **kwargs)
Beispiel #14
0
 def register_endpoints(self, providers):
     """
     See super class satosa.frontends.base.FrontendModule
     :type providers: list[str]
     :rtype: list[(str, ((satosa.context.Context, Any) -> satosa.response.Response, Any))]
     """
     self._validate_providers(providers)
     self.config = self._build_idp_config_endpoints(self.config, providers)
     # Create the idp
     idp_config = IdPConfig().load(copy.deepcopy(self.config), metadata_construction=False)
     self.idp = Server(config=idp_config)
     return self._register_endpoints(providers)
Beispiel #15
0
def test_assertion_consumer_service():
    c = IdPConfig()
    c.load_file(dotname("idp_conf"))
    c.context = "idp"

    c.metadata.load("local", full_path("InCommon-metadata.xml"))

    entity_id = "https://www.zimride.com/shibboleth"
    acs = c.metadata.assertion_consumer_service(entity_id)
    assert len(acs) == 1
    assert acs[0][
        "location"] == 'https://www.zimride.com/Shibboleth.sso/SAML2/POST'
Beispiel #16
0
 def register_endpoints(self, backend_names):
     """
     See super class satosa.frontends.base.FrontendModule
     :type backend_names: list[str]
     :rtype: list[(str, ((satosa.context.Context, Any) -> satosa.response.Response, Any))]
     """
     self.idp_config = self._build_idp_config_endpoints(
         self.config[self.KEY_IDP_CONFIG], backend_names)
     # Create the idp
     idp_config = IdPConfig().load(copy.deepcopy(self.idp_config))
     self.idp = Server(config=idp_config)
     return self._register_endpoints(backend_names)
Beispiel #17
0
def test_idp_2():
    c = IdPConfig().load(IDP2)
    c.context = "idp"

    print(c)
    assert c.endpoint("single_logout_service", BINDING_SOAP) == []
    assert c.endpoint("single_logout_service",
                      BINDING_HTTP_REDIRECT) == ["http://localhost:8088/"]

    attribute_restrictions = c.getattr("policy",
                                       "idp").get_attribute_restrictions("")
    assert attribute_restrictions["edupersonaffiliation"][0].match("staff")
Beispiel #18
0
def test_do_idp_sso_descriptor():
    conf = IdPConfig().load(IDP)
    idpsso = metadata.do_idpsso_descriptor(conf)

    assert isinstance(idpsso, md.IDPSSODescriptor)
    assert _eq(idpsso.keyswv(), [
        'protocol_support_enumeration', 'single_sign_on_service',
        'want_authn_requests_signed', "extensions"
    ])
    exts = idpsso.extensions.extension_elements
    assert len(exts) == 2
    print(exts)
    inst = saml2.extension_element_to_element(exts[0],
                                              shibmd.ELEMENT_FROM_STRING,
                                              namespace=shibmd.NAMESPACE)
    assert isinstance(inst, shibmd.Scope)
    assert inst.text == "example.org"
    assert inst.regexp == "false"

    uiinfo = saml2.extension_element_to_element(exts[1],
                                                mdui.ELEMENT_FROM_STRING,
                                                namespace=mdui.NAMESPACE)

    assert uiinfo
    assert _eq(uiinfo.keyswv(), [
        'display_name', 'description', 'information_url',
        'privacy_statement_url', 'keywords', 'logo'
    ])

    assert len(uiinfo.privacy_statement_url) == 1
    assert uiinfo.privacy_statement_url[
        0].text == "http://example.com/saml2/privacyStatement.html"
    assert len(uiinfo.description) == 1
    assert uiinfo.description[0].text == "Exempel bolag"
    assert uiinfo.description[0].lang == "se"

    res = extension_elements_to_elements(exts, [shibmd, mdui])

    assert len(res) == 2
    # one is a shibmd.Scope instance and the other a mdui.UIInfo instance
    if isinstance(res[0], shibmd.Scope):
        assert isinstance(res[1], mdui.UIInfo)
    elif isinstance(res[1], shibmd.Scope):
        assert isinstance(res[0], mdui.UIInfo)

    found = idpsso.extensions.find_extensions(mdui.UIInfo.c_tag,
                                              mdui.NAMESPACE)
    assert len(found) == 1

    elem = idpsso.extensions.extensions_as_elements(mdui.UIInfo.c_tag, mdui)
    assert len(elem) == 1
    assert isinstance(elem[0], mdui.UIInfo)
Beispiel #19
0
def run():
    '''配置IdP,生成证书、元数据文件'''
    if not os.path.exists(BASEDIR+'/djangosaml2idp/certificates/mycert.pem') or not \
        os.path.exists(BASEDIR+'/djangosaml2idp/certificates/mykey.pem'):
        create_self_signed_cert()

    conf = IdPConfig()  # pylint: disable=invalid-name
    conf.load(copy.deepcopy(idpsettings.SAML_IDP_CONFIG))
    meta_data = entity_descriptor(conf)  # pylint: disable=invalid-name
    content = text_type(meta_data).encode('utf-8')
    with open(BASEDIR + '/djangosaml2idp/saml2_config/idp_metadata.xml',
              'wb') as f:
        f.write(content)
    def __init__(self, config, attribute_map=None):
        """Initialize SAML Identity Provider.

        Args:
            config (dict): Identity Provider config info in dict form
            attribute_map (dict): Mapping of attribute keys to user data
        """
        self._config = IdPConfig()
        self._config.load(config)
        self._server = Server(config=self._config)
        self.attribute_map = {}
        if attribute_map is not None:
            self.attribute_map = attribute_map
Beispiel #21
0
 def load(cls, force_refresh: bool = False) -> Server:
     """ Instantiate a IDP Server instance based on the config defined in the SAML_IDP_CONFIG settings.
         Throws an ImproperlyConfigured exception if it could not do so for any reason.
     """
     if cls._server_instance is None or force_refresh:
         conf = IdPConfig()
         md = cls.construct_metadata()
         try:
             conf.load(md)
             cls._server_instance = Server(config=conf)
         except Exception as e:
             raise ImproperlyConfigured(_('Could not instantiate an IDP based on the SAML_IDP_CONFIG settings and configured ServiceProviders: {}').format(str(e)))
     return cls._server_instance
Beispiel #22
0
 def setup(self):
     """
     Initiates the test.
     :return: None
     """
     self.sp = FakeSP(None,
                      config=SPConfig().load(
                          TestConfiguration.get_instance().fake_sp_config,
                          metadata_construction=False))
     self.idp = FakeIdP(
         USERS,
         IdPConfig().load(TestConfiguration.get_instance().fake_idp_config,
                          metadata_construction=False))
Beispiel #23
0
    def idp_configure(self, metadata_construction=False):
        sys.path.insert(0, self.args.configpath)
        mod = import_module(self.args.config)
        self.idp_config = IdPConfig().load(mod.CONFIG, metadata_construction)

        if not self.args.insecure:
            self.idp_config.verify_ssl_cert = False
        else:
            if self.args.ca_certs:
                self.idp_config.ca_certs = self.args.ca_certs
            else:
                self.idp_config.ca_certs = "../keys/cacert.pem"

        self.idp = Server(config=self.idp_config)
Beispiel #24
0
    def dispatch(self, request, *args, **kwargs):
        """
        Construct IDP server with config from settings dict
        """
        conf = IdPConfig()
        try:
            SAML_IDP_CONFIG = {  # pylint: disable=invalid-name
                'debug': settings.DEBUG,
                'xmlsec_binary': get_xmlsec_binary(['/opt/local/bin', '/usr/bin/xmlsec1']),
                'entityid': '%s/saml/metadata/' % settings.BASE_URL,
                'description': 'longguikeji IdP setup',

                'service': {
                    'idp': {
                        'name': 'Django localhost IdP',
                        'endpoints': {
                            'single_sign_on_service': [
                                ('%s/saml/sso/post/' % settings.BASE_URL, BINDING_HTTP_POST),
                                ('%s/saml/sso/redirect/' % settings.BASE_URL, BINDING_HTTP_REDIRECT),
                            ],
                        },
                        'name_id_format': [NAMEID_FORMAT_EMAILADDRESS, NAMEID_FORMAT_UNSPECIFIED],
                        'sign_response': True,
                        'sign_assertion': True,
                    },
                },

                'metadata': {
                    'local': [os.path.join(os.path.join(os.path.join(BASEDIR, 'djangosaml2idp'), \
                                                        'saml2_config'), f) for f in
                              os.listdir(BASEDIR + '/djangosaml2idp/saml2_config/') \
                              if f.split('.')[-1] == 'xml'],
                },
                # Signing
                'key_file': BASEDIR + '/djangosaml2idp/certificates/mykey.pem',
                'cert_file': BASEDIR + '/djangosaml2idp/certificates/mycert.pem',
                # Encryption
                'encryption_keypairs': [{
                    'key_file': BASEDIR + '/djangosaml2idp/certificates/mykey.pem',
                    'cert_file': BASEDIR + '/djangosaml2idp/certificates/mycert.pem',
                }],
                'valid_for': 365 * 24,
            }

            conf.load(copy.copy(SAML_IDP_CONFIG))
            self.IDP = Server(config=conf)  # pylint: disable=invalid-name
        except Exception as e:  # pylint: disable=invalid-name, broad-except
            return self.handle_error(request, exception=e)
        return super(IdPHandlerViewMixin,
                     self).dispatch(request, *args, **kwargs)
Beispiel #25
0
def test_assertion_consumer_service():
    c = IdPConfig()
    c.load_file("idp_conf")
    c.context = "idp"

    xml_src = open("inCommon-metadata.xml").read()
    # A trick so outdated data is allowed
    c.metadata.import_metadata(xml_src, "-")

    print c.metadata.entity.keys()
    entity_id = "https://www.zimride.com/shibboleth"
    acs = c.assertion_consumer_services(entity_id)
    assert len(acs) == 1
    assert acs[0].location == 'https://www.zimride.com/Shibboleth.sso/SAML2/POST'
Beispiel #26
0
    def _load_idp_dynamic_entity_id(self, state):
        """
        Loads an idp server with the entity id saved in state

        :type state: satosa.state.State
        :rtype: saml.server.Server

        :param state: The current state
        :return: An idp server
        """
        # Change the idp entity id dynamically
        idp_config_file = copy.deepcopy(self.idp_config)
        idp_config_file["entityid"] = "{}/{}".format(self.idp_config["entityid"], state[self.name]["target_entity_id"])
        idp_config = IdPConfig().load(idp_config_file)
        return Server(config=idp_config)
Beispiel #27
0
    def _load_idp_dynamic_endpoints(self, context):
        """
        Loads an idp server that accepts the target backend name in the endpoint url
         ex: /<backend_name>/sso/redirect

        :type context: The current context
        :rtype: saml.server.Server

        :param context:
        :return: An idp server
        """
        target_entity_id = context.target_entity_id_from_path()
        idp_conf_file = self._load_endpoints_to_config(context.target_backend, target_entity_id)
        idp_config = IdPConfig().load(idp_conf_file)
        return Server(config=idp_config)
Beispiel #28
0
    def _load_idp_dynamic_endpoints(self, context):
        """
        Loads an idp server that accepts the target backend name in the endpoint url
         ex: /<backend_name>/sso/redirect

        :type context: The current context
        :rtype: saml.server.Server

        :param context:
        :return: An idp server
        """
        target_entity_id = context.path.split("/")[1]
        context.decorate(Context.KEY_MIRROR_TARGET_ENTITYID, target_entity_id)
        idp_conf_file = self._load_endpoints_to_config(context.target_backend, target_entity_id)
        idp_config = IdPConfig().load(idp_conf_file, metadata_construction=False)
        return Server(config=idp_config)
Beispiel #29
0
def send_assertion():
    logger.debug("Sending SAML assertion")

    idp_config = current_app.config['IDP_CONFIG']
    idp_config_object = IdPConfig().load(copy.deepcopy(idp_config),
                                         metadata_construction=False)
    idp = Server(config=idp_config_object)

    name_id_format = 'urn:oasis:names:tc:SAML:2.0:nameid-format:transient'
    name_id_policy = NameIDPolicy(format=name_id_format)

    args = {
        'identity': {},
        'name_id': None,
        'authn': {
            'class_ref': 'https://refeds.org/profile/mfa',
            'authn_auth': idp_config['entityid']
        },
        'sign_response': True,
        'sign_assertion': False,
        'encrypted_advice_attributes': False,
        'in_response_to': session['saml_authn_request_id'],
        'sp_entity_id': session['saml_sp_entity_id'],
        'name_id_policy': name_id_policy,
        'binding': 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST',
        'destination': session['saml_sp_acs'],
        'sign_alg': 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256',
        'digest_alg': 'http://www.w3.org/2001/04/xmlenc#sha256',
    }

    saml_response_string = idp.create_authn_response(**args)
    saml_response_string_encoded = saml_response_string.encode('utf-8')
    saml_response = b64encode(saml_response_string_encoded)
    saml_response_encoded = saml_response.decode('ascii')

    action = session['saml_sp_acs']
    saml_relay_state = session['saml_relay_state']
    rendered_template = render_template(
        'saml_http_post_binding.html',
        action=action,
        saml_response_encoded=saml_response_encoded,
        saml_relay_state=saml_relay_state)

    # Kill the session
    session.clear()

    return rendered_template
Beispiel #30
0
def create_authn_response(session_id, identity=dict(), sign=True):
    config = IdPConfig()
    config.load(idp_config)
    idp_server = Server(config=config)
    idp_server.ident = Identifier(auth.AuthDictCache(dict(), '_ident'))
    authn_response = str(
        idp_server.authn_response(
            identity=identity,
            in_response_to=session_id,
            destination='https://foo.example.com/sp/acs',
            sp_entity_id='https://foo.example.com/sp/metadata',
            name_id_policy=None,
            userid='Irrelevent',
            sign=sign,
            instance=True))
    response = samlp.response_from_string(authn_response)
    return response.assertion[0].subject.name_id.text, authn_response