mirror of
https://github.com/gravitational/teleport.git
synced 2026-10-25 10:40:02 +08:00
* support saml http-post binding request: - add PreferredRequestBinding to SAMLConnectorSpecV2 - add PreferredRequestBinding and PostFormData to SAMLAuthRequest * add lib/saml package with saml auth request writer * support tsh sso login * make -C integrations/operator crd * cover both redirect and post form response in saml ceremony test * indicate clients that support http-post * proto changes to support client version * comments * more make -C integrations/operator crd * remove ClientVersion validation that wont be sent by older clients * move preferred request binding value validation to ValidateSAMLConnector * review comments: - add comments to test, improve test case - add comment to SSOLoginConsoleResponse struct - return http error instead of redirection for error * add sso url validation * udpate test files
85 lines
2.6 KiB
Go
85 lines
2.6 KiB
Go
/*
|
|
* Teleport
|
|
* Copyright (C) 2025 Gravitational, Inc.
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Affero General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Affero General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Affero General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
package saml
|
|
|
|
import (
|
|
"io"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestWriteSAMLPostRequestWithHeaders(t *testing.T) {
|
|
handler := func(w http.ResponseWriter, r *http.Request) {
|
|
WriteSAMLPostRequestWithHeaders(w, []byte(postform))
|
|
}
|
|
|
|
req := httptest.NewRequest("GET", "http://example.com/foo", nil)
|
|
w := httptest.NewRecorder()
|
|
handler(w, req)
|
|
|
|
body, err := io.ReadAll(w.Result().Body)
|
|
require.NoError(t, err)
|
|
require.Contains(t, string(body), "Teleport SAML Service Provider")
|
|
|
|
cspStr := w.Header().Get("Content-Security-Policy")
|
|
csp, err := parseCSP(cspStr)
|
|
require.NoError(t, err)
|
|
valdiateBaseCSPValues(t, csp)
|
|
require.Equal(t, sha256sum, csp["script-src"][0])
|
|
}
|
|
|
|
const postform = `
|
|
<form method="POST" action="https://example.com"
|
|
id="SAMLRequestForm"><input type="hidden" name="SAMLRequest"
|
|
value="PHNhbY1ZXN0Pg==" />
|
|
<input id="SAMLSubmitButton" type="submit" value="Submit" />
|
|
</form>
|
|
<script>document.getElementById('SAMLSubmitButton').style.visibility="hidden";
|
|
document.getElementById('SAMLRequestForm').submit();</script>
|
|
`
|
|
|
|
func valdiateBaseCSPValues(t *testing.T, csp map[string][]string) {
|
|
require.Equal(t, []string{"'none'"}, csp["object-src"])
|
|
require.Equal(t, []string{"'none'"}, csp["base-uri"])
|
|
require.Equal(t, []string{"'none'"}, csp["frame-ancestors"])
|
|
require.Equal(t, []string{"'none'"}, csp["img-src"])
|
|
require.Equal(t, []string{"'none'"}, csp["style-src"])
|
|
}
|
|
|
|
// TODO(sshah): share csp parser between service provider and identity provider.
|
|
func parseCSP(policyStr string) (map[string][]string, error) {
|
|
policies := strings.Split(policyStr, ";")
|
|
var policyMap = make(map[string][]string)
|
|
for _, policy := range policies {
|
|
parts := strings.Split(strings.TrimSpace(policy), " ")
|
|
if len(parts) == 1 {
|
|
policyMap[parts[0]] = []string{}
|
|
break
|
|
}
|
|
|
|
policyMap[parts[0]] = parts[1:]
|
|
|
|
}
|
|
return policyMap, nil
|
|
}
|