mirror of
https://github.com/openziti/ziti.git
synced 2026-09-10 08:45:41 +00:00
949de99ee4
* fixes #3809 support CSR submission during OIDC authentication - accepts an optional CSR during OIDC login (all auth methods) and signs it into a session-bound certificate with a SPIFFE ID derived from the identity and API session - returns the signed certificate PEM as a top-level "session_cert" field in the token endpoint JSON response (CodeExchange, RefreshToken, TokenExchange) - adds cert-binding verification on RefreshToken and TokenExchange: if z_cfs is present the peer cert fingerprint must match (strict), otherwise falls back to SPIFFE ID verification - supports cert rotation via csr_pem form parameter on refresh and token exchange; replaces the session cert fingerprint while preserving the authenticating cert fingerprint - adds AuthCertFingerprints (z_acfs) claim to track permanent auth cert fingerprints separately from rotatable session cert fingerprints - only the leaf certificate fingerprint is added to z_cfs and z_acfs, intermediates are never included - invalid CSR returns 400 Bad Request in OIDC error format - propagates updated CustomClaims (including CertFingerprints) from access token to renewed refresh token so rotated fingerprints are enforced on subsequent refreshes - adds CertGenerated field to ApiSessionEvent - advertises OIDC_AUTH_WITH_CSR controller capability when OIDC is enabled - adds unit tests for verifyCertBinding (fingerprint, SPIFFE ID, edge cases) and CsrPem field parsing - adds integration tests for initial CSR auth (updb, cert, ext-jwt), cert-binding on refresh/exchange, CSR rotation with cert auth, SPIFFE fallback and z_cfs transition, and CSR property forging resistance * address pr concerns * add z_cfs len tests on junk chain certs * strip csr subject info, replace w/ santized values * fix csr rotation rejection/paths during token exchange/refresh
127 lines
3.3 KiB
Go
127 lines
3.3 KiB
Go
/*
|
|
Copyright NetFoundry Inc.
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
https://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
*/
|
|
|
|
package oidc_auth
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func Test_Map(t *testing.T) {
|
|
|
|
const (
|
|
id = "123"
|
|
envArch = "x64"
|
|
envOs = "linux"
|
|
envOsRelease = "11"
|
|
envOsVersion = "1.1.1"
|
|
sdkAppId = "myAppid"
|
|
sdkAppVersion = "5.1.1"
|
|
sdkBranch = "branch34"
|
|
sdkRevision = "rev1"
|
|
sdkType = "fakeType"
|
|
sdkVersion = "6.4.3"
|
|
username = "admin"
|
|
password = "fake_admin_password"
|
|
configType1 = "one"
|
|
configType2 = "two"
|
|
)
|
|
|
|
t.Run("totp id/code payload", func(t *testing.T) {
|
|
dstTotp := &TotpRequestBody{}
|
|
|
|
srcMap := map[string][]string{
|
|
"id": {"123"},
|
|
"code": {"456"},
|
|
}
|
|
err := MapToStruct(srcMap, dstTotp)
|
|
|
|
req := require.New(t)
|
|
req.NoError(err)
|
|
req.Equal(dstTotp.Code, "456")
|
|
req.Equal(dstTotp.AuthRequestId, "123")
|
|
})
|
|
|
|
t.Run("updb creds with env/sdk info payload", func(t *testing.T) {
|
|
srcMap := map[string][]string{
|
|
"id": {id},
|
|
"envArch": {envArch},
|
|
"envOs": {envOs},
|
|
"envOsRelease": {envOsRelease},
|
|
"envOsVersion": {envOsVersion},
|
|
"sdkAppId": {sdkAppId},
|
|
"sdkAppVersion": {sdkAppVersion},
|
|
"sdkBranch": {sdkBranch},
|
|
"sdkRevision": {sdkRevision},
|
|
"sdkType": {sdkType},
|
|
"sdkVersion": {sdkVersion},
|
|
"username": {username},
|
|
"password": {password},
|
|
"configTypes": {"one", "two"},
|
|
}
|
|
|
|
dst := &OidcUpdbCreds{}
|
|
|
|
err := MapToStruct(srcMap, dst)
|
|
|
|
req := require.New(t)
|
|
req.NoError(err)
|
|
req.Equal(dst.AuthRequestId, id)
|
|
req.NotNil(dst.EnvInfo)
|
|
req.Equal(dst.EnvInfo.Arch, envArch)
|
|
req.Equal(dst.EnvInfo.OsVersion, envOsVersion)
|
|
req.Equal(dst.EnvInfo.OsRelease, envOsRelease)
|
|
req.Equal(dst.EnvInfo.Os, envOs)
|
|
req.NotNil(dst.SdkInfo)
|
|
req.Equal(dst.SdkInfo.AppID, sdkAppId)
|
|
req.Equal(dst.SdkInfo.AppVersion, sdkAppVersion)
|
|
req.Equal(dst.SdkInfo.Type, sdkType)
|
|
req.Equal(dst.SdkInfo.Revision, sdkRevision)
|
|
req.Equal(dst.SdkInfo.Branch, sdkBranch)
|
|
req.Equal(string(dst.Username), username)
|
|
req.Equal(string(dst.Password), password)
|
|
req.NotNil(dst.ConfigTypes)
|
|
req.Equal(dst.ConfigTypes[0], configType1)
|
|
req.Equal(dst.ConfigTypes[1], configType2)
|
|
})
|
|
|
|
t.Run("csrPem field is populated", func(t *testing.T) {
|
|
const csrPem = "-----BEGIN CERTIFICATE REQUEST-----\nfake\n-----END CERTIFICATE REQUEST-----"
|
|
|
|
srcMap := map[string][]string{
|
|
"id": {"req-1"},
|
|
"csrPem": {csrPem},
|
|
"username": {"admin"},
|
|
"password": {"pass"},
|
|
}
|
|
|
|
dst := &OidcUpdbCreds{}
|
|
err := MapToStruct(srcMap, dst)
|
|
|
|
req := require.New(t)
|
|
req.NoError(err)
|
|
req.Equal("req-1", dst.AuthRequestId)
|
|
req.Equal(csrPem, dst.CsrPem)
|
|
req.Equal("admin", string(dst.Username))
|
|
})
|
|
|
|
// test - operator
|
|
// test nil translator
|
|
// test bad field names in translator
|
|
}
|