• OpenAM之SAML2配置


    What’s SAML2

    SAML是安全断言标记语言(英语:Security Assertion Markup Language,简称SAML,发音sam-el),一种xml格式的语言。 有两个点: 第一是安全(Security), 第二是断言(assertion)

    先看它的核心概念断言(assertion)。 断言是什么? 就是做出判断的语言。比如一个例子:小红没有权限读取根目录。这就是一个断言。 这种“做出判断的语句”我们在很多场合都需要用到。 比如你在网上尝试登陆一个服务的时候, 这个服务需要知道你是不是合法的用户。 这个时候如果你能提供一个“安全,可靠,可信任”的断言:“***有权登陆XX服务”, 那么这个服务就知道你合法了, 于是就能为你提供服务了。 这个例子比较抽象,但基本上能表达断言在实际用例中的作用了。 实际上SAML2的大部分内容就在于证明你是谁,你拥有什么权限等等了。

    接下来第二个概念就是安全(Security)了。 你能提供一个断言, 别人能不能假冒你提供一个断言从而骗取服务端的信任呢? 另外服务端为什么会信任你给的断言呢? 这就涉及到安全的问题了。为了防止断言被假冒,篡改。SAML中加入了安全措施。 当然现今能抵御假冒,篡改,重放攻击的利器就是公钥-私钥/keystore系统了。 通过给断言加上签名和加密,再结合数字证书系统就确保了SAML不受攻击。

    Config With OpenAM SAML2

    OpenAM配置SAML2分2种方式

    • 默认方式(本文采用默认方式,Sign Assertion)
    • 开发方式(自定义AttributeMapper,TokenProvider)

    默认方式和开发方式都是分3步走,只是配置有所不同而已:

    • 配置SAML2 STS Instance
    • 配置SAML2 Service Provider(Configure OAuth2 authorization server)
    • 验证SAML2

    配置SAML2 STS Instance

    1.进入Top Level Realm,找到STS,这里的STSSecurity Token Service的意思。
    在这里插入图片描述
    2.new一个STSSupported Token Transforms选择OPENAM->SAML2,don't invalidate interim OpenAM session
    在这里插入图片描述
    3.Deployment Url Element就是这个STS的名称,这里要记住,后面会用到,拼接REST请求的时候,URL为rest-sts/stsName,那么我们就是rest-sts/mysts
    在这里插入图片描述
    4.这里定义一下issuer IdEntity Id
    在这里插入图片描述
    5.详细设置SAML2 Sign相关

    • Sign Assertion ,打勾√,启用断言签证,不签的话,报文很少
    • KeyStorePath位于C:Users你的用户openamproopenamprokeystore.jks (如果你的项目叫openam则为C:Users你的用户openamopenamkeystore.jks)
    • Keystore Password,记事本打开.storepass文件,明文copy即可
    • Signature Key Password,记事本打开.keypass文件,明文copy即可
      在这里插入图片描述
      在这里插入图片描述
      6.保存

    配置SAML2 Service Provider

    1.返回Dashboard,扎到Common Tasks下面的Configure SAMLv2 Provider
    在这里插入图片描述
    2.由于是本地Localhost的Provider,所以是选择Create Hosted Service Provider
    在这里插入图片描述
    3.默认配置即可,metadata会自动填写,如果没有就写上项目路径,Circle Of Trust随便写个cot或者mycot即可。
    在这里插入图片描述
    4.保存并返回查看
    在这里插入图片描述
    验证SAML2

    1.POST请求authenticate接口获得以下authenticate报文,无需任何参数

    http://localhost:8099/openampro/json/authenticate

    {
      "authId": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJvdGsiOiJraWM1cmM3aGVjN2dsbWIzYWZzczE4MHQ0cCIsInJlYWxtIjoiZGM9b3BlbmFtLGRjPWZvcmdlcm9jayxkYz1vcmciLCJzZXNzaW9uSWQiOiJBUUlDNXdNMkxZNFNmY3c0OFhTUDNlR2NIZVB1VUN3bW9IdGRyVWpsdHZsX1BIby4qQUFKVFNRQUNNREVBQWxOTEFCTTBOVFEzTURVMU1URTBOVGMwTXpFMU1EZzVBQUpUTVFBQSoifQ.Xq4okO5FjamU62bu0xeZbUSE15pCaG_fKw9XseMJi64",
      "template": "",
      "stage": "DataStore1",
      "header": "Sign in",
      "callbacks": [
        {
          "type": "NameCallback",
          "output": [
            {
              "name": "prompt",
              "value": "User Name:"
            }
          ],
          "input": [
            {
              "name": "IDToken1",
              "value": ""
            }
          ]
        },
        {
          "type": "PasswordCallback",
          "output": [
            {
              "name": "prompt",
              "value": "Password:"
            }
          ],
          "input": [
            {
              "name": "IDToken2",
              "value": ""
            }
          ]
        }
      ]
    }

     

    2.Copy上一部获取到的报文在body/raw里面,然后补全authenticate报文的账号(IDToken1-value)和密码(IDToken2-value),继续请求该接口

    http://localhost:8099/openampro/json/authenticate

    "callbacks": [
        {
          "type": "NameCallback",
          "output": [
            {
              "name": "prompt",
              "value": "User Name:"
            }
          ],
          "input": [
            {
              "name": "IDToken1",
              "value": "这里填写账号"
            }
          ]
        },
        {
          "type": "PasswordCallback",
          "output": [
            {
              "name": "prompt",
              "value": "Password:"
            }
          ],
          "input": [
            {
              "name": "IDToken2",
              "value": "这里填写密码"
            }
          ]
        }
      ]

     

     

    在这里插入图片描述
    3.得到tokenId

    AQIC5wM2LY4SfczBElQ-gyrwsTOLXPZscWBxk776W1IYfS4.AAJTSQACMDEAAlNLABM0ODEyODAzNTQxNzU4MDE3MDA3AAJTMQAA

    4.拼接报文,把tokenId填入session_id后面的值,然后POST请求translate接口,进行OPENAM->SAML2报文转换

    http://localhost:8099/openampro/rest-sts/mysts?_action=translate

    {
        "input_token_state":
            {
                "token_type": "OPENAM",
                "session_id": "AQIC5wM2LY4SfczBElQ-gyrwsTOLXPZscWBxk776W1IYfS4.*AAJTSQACMDEAAlNLABM0ODEyODAzNTQxNzU4MDE3MDA3AAJTMQAA*"
            },
        "output_token_state":
            {
                "token_type": "SAML2",
                "subject_confirmation": "BEARER"
            }
    }

     

     

    在这里插入图片描述
    5.得到Signed后的报文,这就是SAML2报文啦

    {"issued_token":"
    <saml:Assertion xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="s2a8a19d7e7801a6243ad1b34d5066852eca7da372" IssueInstant="2019-05-31T06:25:50Z" Version="2.0">
    
        <saml:Issuer>stsid</saml:Issuer>
        <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
    
            <ds:SignedInfo>
    
                <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
    
                <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
    
                <ds:Reference URI="#s2a8a19d7e7801a6243ad1b34d5066852eca7da372">
    
                    <ds:Transforms>
    
                        <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
    
                        <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
    
                    </ds:Transforms>
    
                    <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
    
                    <ds:DigestValue>AZShA8hm3+BuU8SkTQtbvkjpl9o=</ds:DigestValue>
    
                </ds:Reference>
    
            </ds:SignedInfo>
    
            <ds:SignatureValue>
    RkuIgun5A6sInaD3HWZ7CbQXkiWDxTR2zJ6o/h4IOf7jutSl6lCLEHUs1qSjyILO1xeOMS3VsDpn
    plpYfZF3tHornzdDm++9x538qDnxlzIHVN3WQKu9yLoqrkw0arU1I+KZb8dKnZHIPf9RnK96RLuz
    O4yEsjQrPpB3hRBF0oI=
    </ds:SignatureValue>
    
            <ds:KeyInfo>
    
                <ds:X509Data>
    
                    <ds:X509Certificate>
    MIICQDCCAakCBEeNB0swDQYJKoZIhvcNAQEEBQAwZzELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNh
    bGlmb3JuaWExFDASBgNVBAcTC1NhbnRhIENsYXJhMQwwCgYDVQQKEwNTdW4xEDAOBgNVBAsTB09w
    ZW5TU08xDTALBgNVBAMTBHRlc3QwHhcNMDgwMTE1MTkxOTM5WhcNMTgwMTEyMTkxOTM5WjBnMQsw
    CQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEUMBIGA1UEBxMLU2FudGEgQ2xhcmExDDAK
    BgNVBAoTA1N1bjEQMA4GA1UECxMHT3BlblNTTzENMAsGA1UEAxMEdGVzdDCBnzANBgkqhkiG9w0B
    AQEFAAOBjQAwgYkCgYEArSQc/U75GB2AtKhbGS5piiLkmJzqEsp64rDxbMJ+xDrye0EN/q1U5Of+
    RkDsaN/igkAvV1cuXEgTL6RlafFPcUX7QxDhZBhsYF9pbwtMzi4A4su9hnxIhURebGEmxKW9qJNY
    Js0Vo5+IgjxuEWnjnnVgHTs1+mq5QYTA7E6ZyL8CAwEAATANBgkqhkiG9w0BAQQFAAOBgQB3Pw/U
    QzPKTPTYi9upbFXlrAKMwtFf2OW4yvGWWvlcwcNSZJmTJ8ARvVYOMEVNbsT4OFcfu2/PeYoAdiDA
    cGy/F2Zuj8XJJpuQRSE6PtQqBuDEHjjmOQJ0rV/r8mO1ZCtHRhpZ5zYRjhRC9eCbjx9VrFax0JDC
    /FfwWigmrW0Y0Q==
    </ds:X509Certificate>
    
                </ds:X509Data>
    
            </ds:KeyInfo>
    
        </ds:Signature>
        <saml:Subject>
    
            <saml:NameID Format="urn:oasis:names:tc:SAML:1.0:nameid-format:unspecified">amadmin</saml:NameID>
            <saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
    
                <saml:SubjectConfirmationData NotOnOrAfter="2019-05-31T06:35:50Z"/>
            </saml:SubjectConfirmation>
    
        </saml:Subject>
        <saml:Conditions NotBefore="2019-05-31T06:25:50Z" NotOnOrAfter="2019-05-31T06:35:50Z">
    
            <saml:AudienceRestriction>
    
                <saml:Audience>stsid</saml:Audience>
    
            </saml:AudienceRestriction>
    
        </saml:Conditions>
    
        <saml:AuthnStatement AuthnInstant="2019-05-31T06:25:50Z">
            <saml:AuthnContext>
                <saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:PreviousSession</saml:AuthnContextClassRef>
            </saml:AuthnContext>
        </saml:AuthnStatement>
    </saml:Assertion>"}

    以下部分为shell+json自动化配置,部分核心配置

    使用JSON配置

    {
    	"invocation_context": "invocation_context_client_sdk",
    	"instance_state": {
    		"persist-issued-tokens-in-cts": "false",
    		"supported-token-transforms": [{
    			"inputTokenType": "OPENAM",
    			"outputTokenType": "SAML2",
    			"invalidateInterimOpenAMSession": false
    		}],
    		"custom-token-validators": [],
    		"custom-token-providers": [{
    			"customTokenName":"SAML2_XXX",
    			"customOperationClassName":"com.xxxcompany.sts.tokengeneration.saml2.SamlTokenProvider"
    		}],
    		"custom-token-transforms": [{
    			"inputTokenType": "OPENAM",
    			"outputTokenType": "SAML2_HSM",
    			"invalidateInterimOpenAMSession": false
    		}],
    		"deployment-config": {
    			"deployment-realm": "/sdex_global",
    			"deployment-url-element": "ssotoken_transformer_xxxapp",
    			"deployment-auth-target-mappings": {},
    			"deployment-offloaded-two-way-tls-header-key": null,
    			"deployment-tls-offload-engine-hosts": {}
    		},
    		"saml2-config": {
    			"issuer-name": "xxx",
    			"saml2-sp-entity-id": "xxxapp_url_tbc",
    			"saml2-sp-acs-url": "xxxapp_url_tbc",
    			"saml2-name-id-format": "urn:oasis:names:tc:SAML:1.0:nameid-format:unspecified",
    			"saml2-token-lifetime-seconds": "30",
    			"saml2-custom-conditions-provider-class-name": null,
    			"saml2-custom-subject-provider-class-name": null,
    			"saml2-custom-authentication-statements-provider-class-name": null,
    			"saml2-custom-attribute-statements-provider-class-name": null,
    			"saml2-custom-authz-decision-statements-provider-class-name": null,
    			"saml2-custom-attribute-mapper-class-name": "com.xxxcompany.sts.tokengeneration.saml2.statements.CustomAttributeMapper",
    			"saml2-custom-authn-context-mapper-class-name": null,
    			"saml2-attribute-map": {
    				"customerId": "session|XXXCom-Customer-Id",
    				"guid":"session|guid"				
    			},
    			"saml2-sign-assertion": "true",
    			"saml2-encrypt-assertion": "false",
    			"saml2-encrypt-attributes": "false",
    			"saml2-encrypt-nameid": "false",
    			"saml2-encryption-algorithm": "http://www.w3.org/2001/04/xmlenc#aes128-cbc",
    			"saml2-encryption-algorithm-strength": "128",
    			"saml2-keystore-filename": "/opt/xxxcompany/xxxapp/xxxapp_SAML_xxx_DEV.keystore",
    			"saml2-keystore-password": "changeit",
    			"saml2-encryption-key-alias": "",
    			"saml2-signature-key-alias": "xxxapp_SAML_CMB_DEV",
    			"saml2-signature-key-password": "changeit"
    		}
    	}
    }

     

    sts-setup.sh

    #!/bin/bash
    
    # Constants for text color
    color_off='33[0m'
    color_red='33[0;31m'
    color_green='33[0;32m'
    color_yellow='33[0;33m'
    
    script_path="$( cd "$(dirname "$0")" ; pwd -P )"
    
    # Load bootstrap file
    bootstrap_file=${script_path}/bootstrap.properties
    [ ! -f $bootstrap_file ] && { echo "Error: Missing $bootstrap_file"; exit 1; }
    source $bootstrap_file
    [[ -z "$am_instance_name" ]] && { echo "Error: 'am_instance_name' undefined in $bootstrap_file"; exit 1; }
    [[ -z "$am_server_url" ]] && { echo "Error: 'am_server_url' undefined in $bootstrap_file"; exit 1; }
    [[ -z "$admin_user" ]] && { echo "Error: 'admin_user' undefined in $bootstrap_file"; exit 1; }
    [[ -z "$admin_password_file" ]] && { echo "Error: 'admin_password_file' undefined in $bootstrap_file"; exit 1; }
    [ ! -f $admin_password_file ] && { echo "Error: Missing $admin_password_file"; exit 1; }
    [[ -z "$com_iplanet_am_cookie_name" ]] && { echo "Error: 'com_iplanet_am_cookie_name' undefined in $bootstrap_file"; exit 1; }
    [[ -z "$openam_tools_dir" ]] && { echo "Error: 'openam_tools_dir' undefined in $bootstrap_file"; exit 1; }
    [[ -z "$ssoadm" ]] && { echo "Error: 'ssoadm' undefined in $bootstrap_file"; exit 1; }
    [[ -z "$realms" ]] && { echo "Error: 'realms' undefined in $bootstrap_file"; exit 1; }
    
    create_sts_instance() {
    	realm=$1
    
    	# Validate data file
    	data_file=${script_path}/${realm#/}/rest-sts-instance-config.json
    	[ ! -f $data_file ] && { echo -e "${color_red}Error: Missing data file ${data_file}${color_off}"; return; }
    	deployment_realm=$(cat $data_file 2>/dev/null | python -c 'import sys, json; print json.load(sys.stdin)["instance_state"]["deployment-config"]["deployment-realm"]' 2>/dev/null)
    	[[ -z "$deployment_realm" ]] && { echo -e "${color_red}Error: 'deployment-realm' undefined in ${data_file}${color_off}"; return; }
    	[ "$deployment_realm" != "$realm" ] && { echo -e "${color_red}Error: Deployment realm '${deployment_realm}' is different than the configuration realm '${realm}'${color_off}"; return; }
    	deployment_url_element=$(cat $data_file 2>/dev/null | python -c 'import sys, json; print json.load(sys.stdin)["instance_state"]["deployment-config"]["deployment-url-element"]' 2>/dev/null)
    	[[ -z "$deployment_url_element" ]] && { echo -e "${color_red}Error: 'deployment-url-element' undefined in ${data_file}${color_off}"; return; }
    
    	echo -n "Create STS instance ${deployment_realm}/${deployment_url_element} in realm ${realm}... "
    	admin_password=$(cat $admin_password_file)
    	auth_response=$(curl -k -s -X POST 
    					-H "Content-type: application/json" 
    					-H "X-OpenAM-Username:${admin_user}" 
    					-H "X-OpenAM-Password:${admin_password}" 
    					${am_server_url}/json/authenticate)
    	am_token=$(echo $auth_response | python -c 'import sys, json; print json.load(sys.stdin)["tokenId"]' 2>/dev/null)
    	[[ -z "$am_token" ]] && { echo -e "${color_red}FAILED!
    Authentication failed.
    Authentication response: ${auth_response}${color_off}"; return; }
    	sts_response=$(curl -k -s -X POST 
    					-H "Content-Type: application/json" 
    					-H "${com_iplanet_am_cookie_name}: ${am_token}" 
    					-d @$data_file 
    					${am_server_url}/sts-publish/rest?_action=create)
    	sts_response_result=$(echo $sts_response | python -c 'import sys, json; print json.load(sys.stdin)["result"]' 2>/dev/null)
    	[ "$sts_response_result" = "success" ] && echo -e "${color_green}SUCCESS!" || echo -e "${color_red}FAILED!"
    	echo -e "${sts_response}${color_off}"
    }
    
    for realm in "${realms[@]}"
    do
    	echo "================================================="
    	echo "Configuring realm ${realm}:"
    
    	create_sts_instance $realm
    
    	echo "================================================="
    done

     

    bootstrap.properties

    # AM settings
    am_instance_name=xxx-dsp-openam
    am_server_url=https://yourserver/${am_instance_name}
    admin_user=amadmin
    admin_password_file=/opt/openam/openam-tools/admin/.pwd
    com_iplanet_am_cookie_name=AMToken
    
    # SSO Admin Tools settings
    openam_tools_dir=/opt/openam/openam-tools/admin
    ssoadm=${openam_tools_dir}/${am_instance_name}/bin/ssoadm
    
    # Realms to configure
    realms=("/sdex_global")

     

  • 相关阅读:
    新版SourceTree免帐号登录安装
    常用 Git 命令清单
    Linux添加/删除用户和用户组
    使用sklearn优雅地进行数据挖掘
    matplotlib 散点图scatter
    使用Python进行描述性统计
    pandas将字段中的字符类型转化为时间类型,并设置为索引
    xp系统报错 windows explorer has encountered a problem and needs to close.We are sorry for the inconvenience
    python下几种打开文件的方式
    Python 使用 Matplotlib 做图时,如何画竖直和水平的分割线或者点画线或者直线?
  • 原文地址:https://www.cnblogs.com/taosiyu/p/12098088.html
Copyright © 2020-2023  润新知