2023-02-15 09:14:59 +01:00
|
|
|
package command
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2023-03-13 17:34:29 +01:00
|
|
|
"errors"
|
2023-02-15 09:14:59 +01:00
|
|
|
"testing"
|
2023-03-24 16:18:56 +01:00
|
|
|
"time"
|
2023-02-15 09:14:59 +01:00
|
|
|
|
2024-05-23 07:04:07 +02:00
|
|
|
"github.com/muhlemmer/gu"
|
2023-02-15 09:14:59 +01:00
|
|
|
"github.com/stretchr/testify/assert"
|
2023-10-19 12:34:00 +02:00
|
|
|
openid "github.com/zitadel/oidc/v3/pkg/oidc"
|
2023-11-22 12:56:43 +02:00
|
|
|
"go.uber.org/mock/gomock"
|
2023-02-15 09:14:59 +01:00
|
|
|
|
|
|
|
"github.com/zitadel/zitadel/internal/api/authz"
|
|
|
|
"github.com/zitadel/zitadel/internal/crypto"
|
|
|
|
"github.com/zitadel/zitadel/internal/domain"
|
|
|
|
"github.com/zitadel/zitadel/internal/eventstore"
|
|
|
|
"github.com/zitadel/zitadel/internal/id"
|
|
|
|
id_mock "github.com/zitadel/zitadel/internal/id/mock"
|
|
|
|
"github.com/zitadel/zitadel/internal/repository/idp"
|
|
|
|
"github.com/zitadel/zitadel/internal/repository/instance"
|
2023-12-08 16:30:55 +02:00
|
|
|
"github.com/zitadel/zitadel/internal/zerrors"
|
2023-02-15 09:14:59 +01:00
|
|
|
)
|
|
|
|
|
2024-12-03 11:38:28 +01:00
|
|
|
var (
|
|
|
|
validSAMLMetadata = []byte(`<?xml version="1.0" encoding="UTF-8"?>
|
|
|
|
<EntityDescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata" entityID="http://localhost:8080/saml/v2/metadata" ID="_8b02ecf6-aea4-4eda-96c6-190551f05b07">
|
|
|
|
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
|
|
|
|
<SignedInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
|
|
|
|
<CanonicalizationMethod xmlns="http://www.w3.org/2000/09/xmldsig#" Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></CanonicalizationMethod>
|
|
|
|
<SignatureMethod xmlns="http://www.w3.org/2000/09/xmldsig#" Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"></SignatureMethod>
|
|
|
|
<Reference xmlns="http://www.w3.org/2000/09/xmldsig#" URI="#_8b02ecf6-aea4-4eda-96c6-190551f05b07">
|
|
|
|
<Transforms xmlns="http://www.w3.org/2000/09/xmldsig#">
|
|
|
|
<Transform xmlns="http://www.w3.org/2000/09/xmldsig#" Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"></Transform>
|
|
|
|
<Transform xmlns="http://www.w3.org/2000/09/xmldsig#" Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></Transform>
|
|
|
|
</Transforms>
|
|
|
|
<DigestMethod xmlns="http://www.w3.org/2000/09/xmldsig#" Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
|
|
|
|
<DigestValue xmlns="http://www.w3.org/2000/09/xmldsig#">Tyw4csdpNNq0E7wi5FXWdVNkdPNg+cM6kK21VB2+iF0=</DigestValue>
|
|
|
|
</Reference>
|
|
|
|
</SignedInfo>
|
|
|
|
<SignatureValue xmlns="http://www.w3.org/2000/09/xmldsig#">hWQSYmnBJENy/okk2qRDuHaZiyqpDsdV6BF9/T/LNjUh/8z4dV2NEZvkNhFEyQ+bqdj+NmRWvKqpg1dtgNJxQc32+IsLQvXNYyhMCtyG570/jaTOtm8daV4NKJyTV7SdwM6yfXgubz5YCRTyV13W2gBIFYppIRImIv5NDcjz+lEmWhnrkw8G2wRSFUY7VvkDn9rgsTzw/Pnsw6hlzpjGDYPMPx3ux3kjFVevdhFGNo+VC7t9ozruuGyH3yue9Re6FZoqa4oyWaPSOwei0ZH6UNqkX93Eo5Y49QKwaO8Rm+kWsOhdTqebVmCc+SpWbbrZbQj4nSLgWGlvCkZSivmH7ezr4Ol1ZkRetQ92UQ7xJS7E0y6uXAGvdgpDnyqHCOFfhTS6yqltHtc3m7JZex327xkv6e69uAEOSiv++sifVUIE0h/5u3hZLvwmTPrkoRVY4wgZ4ieb86QPvhw4UPeYapOhCBk5RfjoEFIeYwPUw5rtOlpTyeBJiKMpH1+mDAoa+8HQytZoMrnnY1s612vINtY7jU5igMwIk6MitQpRGibnBVBHRc2A6aE+XS333ganFK9hX6TzNkpHUb66NINDZ8Rgb1thn3MABArGlomtM5/enrAixWExZp70TSElor7SBdBW57H7OZCYUCobZuPRDLsCO6LLKeVrbdygWeRqr/o=</SignatureValue>
|
|
|
|
<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
|
|
|
|
<X509Data xmlns="http://www.w3.org/2000/09/xmldsig#">
|
|
|
|
<X509Certificate xmlns="http://www.w3.org/2000/09/xmldsig#">MIIFIjCCAwqgAwIBAgICA7YwDQYJKoZIhvcNAQELBQAwLDEQMA4GA1UEChMHWklUQURFTDEYMBYGA1UEAxMPWklUQURFTCBTQU1MIENBMB4XDTI0MTEyNzEwMjc0NFoXDTI1MTEyNzE2Mjc0NFowMjEQMA4GA1UEChMHWklUQURFTDEeMBwGA1UEAxMVWklUQURFTCBTQU1MIG1ldGFkYXRhMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEApEpYT7EjbRBp0Hw7PGCiSgUoJtwd2nwZOhGy5WZVWvraAtHzW5ih2B6UwEShjwCmRJZeKYEN9JKJbpAy2EdL/l2rm/pArVNvSQu6sN4izz5p2rd9NfHAO3/EcvYdrelWLQj8WQx6LVM282Z4wbclp8Jz1y8Ow43352hGfFVc1x8gauoNl5MAy4kdbvs8UqihqcRmEyIOWl6UwTApb+XIRSRz0Yop99Fv9ALJwfUppsx+d4j9rlRDvrQJMJz7GC/19L9INTbY0HsVEiTltdAWHwREwrpwxNJQt42p3W/zpf1mjwXd3qNNDZAr1t2POPP4SXd598kabBZ3EMWGGxFw+NYYajyjG5EFOZw09FFJn2jIcovejvigfdqem5DGPECvHefqcqHkBPGukI3RaotXpAYyAGfnV7slVytSW484IX3KloAJLICbETbFGGsGQzIDw8rUqWyaOCOttw2fVNDyRFUMHrGe1PhJ9qA1If+KCWYD0iJqF03rIEhdrvNSdQNYkRa0DdtpacQLpzQtqsUioODqX0W3uzLceJEXLBbU0ZEk8mWZM/auwMo3ycPNXDVwrb6AkUKar+sqSumUuixw7da3KF1/mynh6M2Eo4NRB16oUiyN0EYrit/RRJjsTdH+71cj0V+8KqO88cBpmm+lO6x4RM5xpOf/EwwQHivxgRkCAwEAAaNIMEYwDgYDVR0PAQH/BAQDAgWgMBMGA1UdJQQMMAoGCCsGAQUFBwMCMB8GA1UdIwQYMBaAFIzl7uckcPWldirXeOFL3rH6K8FLMA0GCSqGSIb3DQEBCwUAA4ICAQBz+7R99uX1Us9T4BB2RK3RD9K8Q5foNmxJ8GbxpOQFL8IG1DE3FqBssciJkOsKY+1+Y6eow2TgmD9MxfCY444C8k8YDDjxIcs+4dEaWMUxA6NoEy378ciy0U1E6rpYLxWYTxXmsELyODWwTrRNIiWfbBD2m0w9HYbK6QvX6IYQqYoTOJJ3WJKsMCeQ8XhQsJYNINZEq8RsERY/aikOlTWN7ax4Mkr3bfnz1euXGClExCOM6ej4m2I33i4nyYBvvRkRRZRQCfkAQ+5WFVZoVXrQHNe/Oifit7tfLaDuybcjgkzzY3o0YbczzbdV69fVoj53VpR3QQOB+PCF/VJPUMtUFPEC05yH76g24KVBiM/Ws8GaERW1AxgupHSmvTY3GSiwDXQ2NzgDxUHfRHo8rxenJdEcPlGM0DstbUONDSFGLwvGDiidUVtqj1UB4yGL26bgtmwf61G4qsTn9PJMWdRmCeeOf7fmloRxTA0EEey3bulBBHim466tWHUhgOP+g1X0iE7CnwL8aJ//CCiQOAv1O6x5RLyxrmVTehPLr1T8qvnBmxpmuYU0kfbYpO3tMVe7VLabBx0cYh7izClZKHhgEj1w4aE9tIk7nqVAwvVocT3io8RrcKixlnBrFd7RYIuF3+RsYC/kYEgnZYKAig5u2TySgGmJ7nIS24FYW68WDg==</X509Certificate>
|
|
|
|
</X509Data>
|
|
|
|
</KeyInfo>
|
|
|
|
</Signature>
|
|
|
|
<IDPSSODescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata" WantAuthnRequestsSigned="1" ID="_fd70402c-8a31-4a9a-a4a7-da526524c609" validUntil="2024-12-02T16:54:55.656Z" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
|
|
|
|
<SingleSignOnService xmlns="urn:oasis:names:tc:SAML:2.0:metadata" Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="http://localhost:8080/saml/v2/SSO"></SingleSignOnService>
|
|
|
|
<SingleSignOnService xmlns="urn:oasis:names:tc:SAML:2.0:metadata" Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="http://localhost:8080/saml/v2/SSO"></SingleSignOnService>
|
|
|
|
<AttributeProfile>urn:oasis:names:tc:SAML:2.0:profiles:attribute:basic</AttributeProfile>
|
|
|
|
<Attribute xmlns="urn:oasis:names:tc:SAML:2.0:assertion" Name="Email" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"><AttributeValue></AttributeValue></Attribute>
|
|
|
|
<Attribute xmlns="urn:oasis:names:tc:SAML:2.0:assertion" Name="SurName" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"><AttributeValue></AttributeValue></Attribute>
|
|
|
|
<Attribute xmlns="urn:oasis:names:tc:SAML:2.0:assertion" Name="FirstName" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"><AttributeValue></AttributeValue></Attribute>
|
|
|
|
<Attribute xmlns="urn:oasis:names:tc:SAML:2.0:assertion" Name="FullName" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"><AttributeValue></AttributeValue></Attribute>
|
|
|
|
<Attribute xmlns="urn:oasis:names:tc:SAML:2.0:assertion" Name="UserName" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"><AttributeValue></AttributeValue></Attribute>
|
|
|
|
<Attribute xmlns="urn:oasis:names:tc:SAML:2.0:assertion" Name="UserID" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"><AttributeValue></AttributeValue></Attribute>
|
|
|
|
<SingleLogoutService xmlns="urn:oasis:names:tc:SAML:2.0:metadata" Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="http://localhost:8080/saml/v2/SLO"></SingleLogoutService>
|
|
|
|
<SingleLogoutService xmlns="urn:oasis:names:tc:SAML:2.0:metadata" Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="http://localhost:8080/saml/v2/SLO"></SingleLogoutService>
|
|
|
|
<NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:persistent</NameIDFormat>
|
|
|
|
<KeyDescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata" use="signing">
|
|
|
|
<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
|
|
|
|
<KeyName>http://localhost:8080/saml/v2/metadata IDP signing</KeyName>
|
|
|
|
<X509Data xmlns="http://www.w3.org/2000/09/xmldsig#">
|
|
|
|
<X509Certificate xmlns="http://www.w3.org/2000/09/xmldsig#">MIIFIjCCAwqgAwIBAgICA7QwDQYJKoZIhvcNAQELBQAwLDEQMA4GA1UEChMHWklUQURFTDEYMBYGA1UEAxMPWklUQURFTCBTQU1MIENBMB4XDTI0MTEyNzEwMjUwMloXDTI1MTEyNzE2MjUwMlowMjEQMA4GA1UEChMHWklUQURFTDEeMBwGA1UEAxMVWklUQURFTCBTQU1MIHJlc3BvbnNlMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA2lUgaI6AS/9xvM9DNSWK6Ho64LpK8UIioM26QfvAfeQ/I2pgX6SwWxEbd7qv+PkJzaFTjrXSlwOmWsJYma+UsdyFClaGFRyCgY8SWxPceandC8a+hQIDS/irLd9XF33RWp0b/09HjQl+n0HZ4teUFDUd2U1mUf3XCpn0+Ho316bmi6xSW6zaMy5RsbUl01hgWj2fgapAsGAHSBphwCE3Dz/9I/UfHWQw1k2/UTgjc9uIujcza6WgOxfsKluXYIOxwNKTfmzzOJMUwXz6GRgB2jhQI29MuKOZOITA7pXq5kZKf0lSRU8zKFTMJaK4zAHQ6f877Drr8XdAHemuXGZ2JdH/Dbdwarzy3YBMCWsAYlpeEvaVAdiSpyR7fAZktNuHd39Zg00Vlj2wdc44Vk5yVssW7pv5qnVZ7JTrXX2uBYFecLAXmplQ2ph1VdSXZLEDGgjiNA2T/fBj7G4/VjsuCBZFm1I0KCJp3HWEJx5dwwhSVc5wOJEzl7fMuPYMKWH/RM6P/7LnO1ulpdmiKPa4gHzdg3hDZn42NKcVt3UYf0phtxpWMrZp/DUEeizhckrC4ed6cfGtS3CUtJEqoycrCROJ5Hy+ONHl5Aqxt+JoPU+t/XATuctfPxQVcDr0itHzo2cjh/AVTU+IC7C0oQHSS9CC8Fp58UqbtYwFtSAd7ecCAwEAAaNIMEYwDgYDVR0PAQH/BAQDAgWgMBMGA1UdJQQMMAoGCCsGAQUFBwMCMB8GA1UdIwQYMBaAFIzl7uckcPWldirXeOFL3rH6K8FLMA0GCSqGSIb3DQEBCwUAA4ICAQAp+IGZScVIbRdCq5HPjlYBPOY7UbL8ZXnlMW/HLELV9GndnULuFhnuQTIdA5dquCsk8RI1fKsScEV1rqWvHZeSo5nVbvUaPJctoD/4GACqE6F8axs1AgSOvpJMyuycjSzSh6gDM1z37Fdqc/2IRqgi7SKdDsfJpi8XW8LtErpp4kyE1rEXopsXG2fe1UH25bZpXraUqYvp61rwVUCazAtV/U7ARG5AnT0mPqzUriIPrfL+v/+2ntV/BSc8/uCqYnHbwpIwjPURCaxo1Pmm6EEkm+V/Ss4ieNwwkD2bLLLST1LoVMim7Ebfy53PEKpsznKsGlVSu0YYKUsStWQVpwhKQw0bQLCJHdpvZtZSDgS9RbSMZz+aY/fpoNx6wDvmMgtdrb3pVXZ8vPKdq9YDrGfFqP60QdZ3CuSHXCM/zX4742GgImJ4KYAcTuF1+BkGf5JLAJOUZBkfCQ/kBT5wr8+EotLxASOC6717whLBYMEG6N8osEk+LDqoJRTLqkzirJsyOHWChKK47yGkdS3HBIZfo91QrJwKpfATYziBjEnqipkTu+6jFylBIkxKTPye4b3vgcodZP8LSNVXAsMGTPNPJxzPWQ37ba4zMnYZ5iUerlaox/SNsn68DT6RajIb1A1JDq+HNFc3hQP2bzk2y5pCax8zo5swjdklnm4clfB2Lw==</X509Certificate>
|
|
|
|
</X509Data>
|
|
|
|
</KeyInfo>
|
|
|
|
</KeyDescriptor>
|
|
|
|
</IDPSSODescriptor>
|
|
|
|
<AttributeAuthorityDescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata" ID="_b3fed381-af56-4160-abf5-5ffd1e21cf61" validUntil="2024-12-02T16:54:55.656Z" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
|
|
|
|
<AttributeService xmlns="urn:oasis:names:tc:SAML:2.0:metadata" Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP" Location="http://localhost:8080/saml/v2/attribute"></AttributeService>
|
|
|
|
<NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:persistent</NameIDFormat>
|
|
|
|
<AttributeProfile>urn:oasis:names:tc:SAML:2.0:profiles:attribute:basic</AttributeProfile>
|
|
|
|
<Attribute xmlns="urn:oasis:names:tc:SAML:2.0:assertion" Name="Email" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"><AttributeValue></AttributeValue></Attribute>
|
|
|
|
<Attribute xmlns="urn:oasis:names:tc:SAML:2.0:assertion" Name="SurName" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"><AttributeValue></AttributeValue></Attribute>
|
|
|
|
<Attribute xmlns="urn:oasis:names:tc:SAML:2.0:assertion" Name="FirstName" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"><AttributeValue></AttributeValue></Attribute>
|
|
|
|
<Attribute xmlns="urn:oasis:names:tc:SAML:2.0:assertion" Name="FullName" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"><AttributeValue></AttributeValue></Attribute>
|
|
|
|
<Attribute xmlns="urn:oasis:names:tc:SAML:2.0:assertion" Name="UserName" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"><AttributeValue></AttributeValue></Attribute>
|
|
|
|
<Attribute xmlns="urn:oasis:names:tc:SAML:2.0:assertion" Name="UserID" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"><AttributeValue></AttributeValue></Attribute>
|
|
|
|
<KeyDescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata" use="signing">
|
|
|
|
<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
|
|
|
|
<KeyName>http://localhost:8080/saml/v2/metadata IDP signing</KeyName>
|
|
|
|
<X509Data xmlns="http://www.w3.org/2000/09/xmldsig#">
|
|
|
|
<X509Certificate xmlns="http://www.w3.org/2000/09/xmldsig#">MIIFIjCCAwqgAwIBAgICA7QwDQYJKoZIhvcNAQELBQAwLDEQMA4GA1UEChMHWklUQURFTDEYMBYGA1UEAxMPWklUQURFTCBTQU1MIENBMB4XDTI0MTEyNzEwMjUwMloXDTI1MTEyNzE2MjUwMlowMjEQMA4GA1UEChMHWklUQURFTDEeMBwGA1UEAxMVWklUQURFTCBTQU1MIHJlc3BvbnNlMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA2lUgaI6AS/9xvM9DNSWK6Ho64LpK8UIioM26QfvAfeQ/I2pgX6SwWxEbd7qv+PkJzaFTjrXSlwOmWsJYma+UsdyFClaGFRyCgY8SWxPceandC8a+hQIDS/irLd9XF33RWp0b/09HjQl+n0HZ4teUFDUd2U1mUf3XCpn0+Ho316bmi6xSW6zaMy5RsbUl01hgWj2fgapAsGAHSBphwCE3Dz/9I/UfHWQw1k2/UTgjc9uIujcza6WgOxfsKluXYIOxwNKTfmzzOJMUwXz6GRgB2jhQI29MuKOZOITA7pXq5kZKf0lSRU8zKFTMJaK4zAHQ6f877Drr8XdAHemuXGZ2JdH/Dbdwarzy3YBMCWsAYlpeEvaVAdiSpyR7fAZktNuHd39Zg00Vlj2wdc44Vk5yVssW7pv5qnVZ7JTrXX2uBYFecLAXmplQ2ph1VdSXZLEDGgjiNA2T/fBj7G4/VjsuCBZFm1I0KCJp3HWEJx5dwwhSVc5wOJEzl7fMuPYMKWH/RM6P/7LnO1ulpdmiKPa4gHzdg3hDZn42NKcVt3UYf0phtxpWMrZp/DUEeizhckrC4ed6cfGtS3CUtJEqoycrCROJ5Hy+ONHl5Aqxt+JoPU+t/XATuctfPxQVcDr0itHzo2cjh/AVTU+IC7C0oQHSS9CC8Fp58UqbtYwFtSAd7ecCAwEAAaNIMEYwDgYDVR0PAQH/BAQDAgWgMBMGA1UdJQQMMAoGCCsGAQUFBwMCMB8GA1UdIwQYMBaAFIzl7uckcPWldirXeOFL3rH6K8FLMA0GCSqGSIb3DQEBCwUAA4ICAQAp+IGZScVIbRdCq5HPjlYBPOY7UbL8ZXnlMW/HLELV9GndnULuFhnuQTIdA5dquCsk8RI1fKsScEV1rqWvHZeSo5nVbvUaPJctoD/4GACqE6F8axs1AgSOvpJMyuycjSzSh6gDM1z37Fdqc/2IRqgi7SKdDsfJpi8XW8LtErpp4kyE1rEXopsXG2fe1UH25bZpXraUqYvp61rwVUCazAtV/U7ARG5AnT0mPqzUriIPrfL+v/+2ntV/BSc8/uCqYnHbwpIwjPURCaxo1Pmm6EEkm+V/Ss4ieNwwkD2bLLLST1LoVMim7Ebfy53PEKpsznKsGlVSu0YYKUsStWQVpwhKQw0bQLCJHdpvZtZSDgS9RbSMZz+aY/fpoNx6wDvmMgtdrb3pVXZ8vPKdq9YDrGfFqP60QdZ3CuSHXCM/zX4742GgImJ4KYAcTuF1+BkGf5JLAJOUZBkfCQ/kBT5wr8+EotLxASOC6717whLBYMEG6N8osEk+LDqoJRTLqkzirJsyOHWChKK47yGkdS3HBIZfo91QrJwKpfATYziBjEnqipkTu+6jFylBIkxKTPye4b3vgcodZP8LSNVXAsMGTPNPJxzPWQ37ba4zMnYZ5iUerlaox/SNsn68DT6RajIb1A1JDq+HNFc3hQP2bzk2y5pCax8zo5swjdklnm4clfB2Lw==</X509Certificate>
|
|
|
|
</X509Data>
|
|
|
|
</KeyInfo>
|
|
|
|
</KeyDescriptor>
|
|
|
|
</AttributeAuthorityDescriptor>
|
|
|
|
</EntityDescriptor>`)
|
2025-03-18 15:23:12 +00:00
|
|
|
validLDAPRootCA = []byte(`-----BEGIN CERTIFICATE-----
|
|
|
|
MIIDITCCAgmgAwIBAgIUKjAUmxsHO44X+/TKBNciPgNl1GEwDQYJKoZIhvcNAQEL
|
|
|
|
BQAwIDEeMBwGA1UEAwwVbXlzZXJ2aWNlLmV4YW1wbGUuY29tMB4XDTI0MTIxOTEz
|
|
|
|
Mzc1MVoXDTI1MTIxOTEzMzc1MVowIDEeMBwGA1UEAwwVbXlzZXJ2aWNlLmV4YW1w
|
|
|
|
bGUuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0QYuJsayILRI
|
|
|
|
hVT7G1DlitVSXnt1iw3gEXJZfe81Egz06fUbvXF6Yo1LJmwYpqe/rm+hf4FNUb8e
|
|
|
|
2O+LH2FieA9FkVe4P2gKOzw87A/KxvpV8stgNgl4LlqRCokbc1AzeE/NiLr5TcTD
|
|
|
|
RXm3DUcYxXxinprtDu2jftFysaOZmNAukvE/iL6qS3X6ggVEDDM7tY9n5FV2eJ4E
|
|
|
|
p0ImKfypi2aZYROxOK+v5x9ryFRMl4y07lMDvmtcV45uXYmfGNCgG9PNf91Kk/mh
|
|
|
|
JxEQbxycJwFoSi9XWljR8ahPdO11LXG7Dsj/RVbY8k2LdKNstl6Ae3aCpbe9u2Pj
|
|
|
|
vxYs1bVJuQIDAQABo1MwUTAdBgNVHQ4EFgQU+mRVN5HYJWgnpopReaLhf2cMcoYw
|
|
|
|
HwYDVR0jBBgwFoAU+mRVN5HYJWgnpopReaLhf2cMcoYwDwYDVR0TAQH/BAUwAwEB
|
|
|
|
/zANBgkqhkiG9w0BAQsFAAOCAQEABJpHVuc9tGhD04infRVlofvqXIUizTlOrjZX
|
|
|
|
vozW9pIhSWEHX8o+sJP8AMZLnrsdq+bm0HE0HvgYrw7Lb8pd4FpR46TkFHjeukoj
|
|
|
|
izqfgckjIBl2nwPGlynbKA0/U/rTCSxVt7XiAn+lgYUGIpOzNdk06/hRMitrMNB7
|
|
|
|
t2C97NseVC4b1ZgyFrozsefCfUmD8IJF0+XJ4Wzmsh0jRrI8koCtVmPYnKn6vw1b
|
|
|
|
cZprg/97CWHYrsavd406wOB60CMtYl83Q16ucOF1dretDFqJC5kY+aFLvuqfag2+
|
|
|
|
kIaoPV1MnGsxveQyyHdOsEatS5XOv/1OWcmnvePDPxcvb9jCcw==
|
|
|
|
-----END CERTIFICATE-----
|
|
|
|
`)
|
2024-12-03 11:38:28 +01:00
|
|
|
)
|
|
|
|
|
2023-02-24 15:16:06 +01:00
|
|
|
func TestCommandSide_AddInstanceGenericOAuthIDP(t *testing.T) {
|
|
|
|
type fields struct {
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore func(*testing.T) *eventstore.Eventstore
|
2023-02-24 15:16:06 +01:00
|
|
|
idGenerator id.Generator
|
|
|
|
secretCrypto crypto.EncryptionAlgorithm
|
|
|
|
}
|
|
|
|
type args struct {
|
|
|
|
ctx context.Context
|
|
|
|
provider GenericOAuthProvider
|
|
|
|
}
|
|
|
|
type res struct {
|
|
|
|
id string
|
|
|
|
want *domain.ObjectDetails
|
|
|
|
err func(error) bool
|
|
|
|
}
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
fields fields
|
|
|
|
args args
|
|
|
|
res res
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
"invalid name",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-02-24 15:16:06 +01:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
provider: GenericOAuthProvider{},
|
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-D32ef", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
2023-02-24 15:16:06 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid clientID",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-02-24 15:16:06 +01:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
provider: GenericOAuthProvider{
|
|
|
|
Name: "name",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-Dbgzf", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
2023-02-24 15:16:06 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid clientSecret",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-02-24 15:16:06 +01:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
provider: GenericOAuthProvider{
|
|
|
|
Name: "name",
|
|
|
|
ClientID: "clientID",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-DF4ga", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
2023-02-24 15:16:06 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid auth endpoint",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-02-24 15:16:06 +01:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
provider: GenericOAuthProvider{
|
|
|
|
Name: "name",
|
|
|
|
ClientID: "clientID",
|
|
|
|
ClientSecret: "clientSecret",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-B23bs", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
2023-02-24 15:16:06 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid token endpoint",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-02-24 15:16:06 +01:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
provider: GenericOAuthProvider{
|
|
|
|
Name: "name",
|
|
|
|
ClientID: "clientID",
|
|
|
|
ClientSecret: "clientSecret",
|
|
|
|
AuthorizationEndpoint: "auth",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-D2gj8", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
2023-02-24 15:16:06 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid user endpoint",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-02-24 15:16:06 +01:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
provider: GenericOAuthProvider{
|
|
|
|
Name: "name",
|
|
|
|
ClientID: "clientID",
|
|
|
|
ClientSecret: "clientSecret",
|
|
|
|
AuthorizationEndpoint: "auth",
|
|
|
|
TokenEndpoint: "token",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-Fb8jk", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
2023-02-24 15:16:06 +01:00
|
|
|
},
|
|
|
|
},
|
2023-03-03 11:38:49 +01:00
|
|
|
{
|
|
|
|
"invalid id attribute",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-03 11:38:49 +01:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
provider: GenericOAuthProvider{
|
|
|
|
Name: "name",
|
|
|
|
ClientID: "clientID",
|
|
|
|
ClientSecret: "clientSecret",
|
|
|
|
AuthorizationEndpoint: "auth",
|
|
|
|
TokenEndpoint: "token",
|
|
|
|
UserEndpoint: "user",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-sdf3f", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
2023-03-03 11:38:49 +01:00
|
|
|
},
|
|
|
|
},
|
2023-02-24 15:16:06 +01:00
|
|
|
{
|
|
|
|
name: "ok",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-02-24 15:16:06 +01:00
|
|
|
expectFilter(),
|
|
|
|
expectPush(
|
2023-10-19 12:19:10 +02:00
|
|
|
instance.NewOAuthIDPAddedEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"name",
|
|
|
|
"clientID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("clientSecret"),
|
|
|
|
},
|
|
|
|
"auth",
|
|
|
|
"token",
|
|
|
|
"user",
|
|
|
|
"idAttribute",
|
|
|
|
nil,
|
2025-02-26 13:20:47 +01:00
|
|
|
true,
|
2023-10-19 12:19:10 +02:00
|
|
|
idp.Options{},
|
|
|
|
),
|
2023-02-24 15:16:06 +01:00
|
|
|
),
|
|
|
|
),
|
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
provider: GenericOAuthProvider{
|
|
|
|
Name: "name",
|
|
|
|
ClientID: "clientID",
|
|
|
|
ClientSecret: "clientSecret",
|
|
|
|
AuthorizationEndpoint: "auth",
|
|
|
|
TokenEndpoint: "token",
|
|
|
|
UserEndpoint: "user",
|
2023-03-03 11:38:49 +01:00
|
|
|
IDAttribute: "idAttribute",
|
2025-02-26 13:20:47 +01:00
|
|
|
UsePKCE: true,
|
2023-02-24 15:16:06 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
id: "id1",
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "instance1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "ok all set",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-02-24 15:16:06 +01:00
|
|
|
expectFilter(),
|
|
|
|
expectPush(
|
2023-10-19 12:19:10 +02:00
|
|
|
instance.NewOAuthIDPAddedEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"name",
|
|
|
|
"clientID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("clientSecret"),
|
|
|
|
},
|
|
|
|
"auth",
|
|
|
|
"token",
|
|
|
|
"user",
|
|
|
|
"idAttribute",
|
|
|
|
[]string{"user"},
|
2025-02-26 13:20:47 +01:00
|
|
|
true,
|
2023-10-19 12:19:10 +02:00
|
|
|
idp.Options{
|
|
|
|
IsCreationAllowed: true,
|
|
|
|
IsLinkingAllowed: true,
|
|
|
|
IsAutoCreation: true,
|
|
|
|
IsAutoUpdate: true,
|
|
|
|
},
|
|
|
|
),
|
2023-02-24 15:16:06 +01:00
|
|
|
),
|
|
|
|
),
|
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
provider: GenericOAuthProvider{
|
|
|
|
Name: "name",
|
|
|
|
ClientID: "clientID",
|
|
|
|
ClientSecret: "clientSecret",
|
|
|
|
AuthorizationEndpoint: "auth",
|
|
|
|
TokenEndpoint: "token",
|
|
|
|
UserEndpoint: "user",
|
|
|
|
Scopes: []string{"user"},
|
2023-03-03 11:38:49 +01:00
|
|
|
IDAttribute: "idAttribute",
|
2025-02-26 13:20:47 +01:00
|
|
|
UsePKCE: true,
|
2023-02-24 15:16:06 +01:00
|
|
|
IDPOptions: idp.Options{
|
|
|
|
IsCreationAllowed: true,
|
|
|
|
IsLinkingAllowed: true,
|
|
|
|
IsAutoCreation: true,
|
|
|
|
IsAutoUpdate: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
id: "id1",
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "instance1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
c := &Commands{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: tt.fields.eventstore(t),
|
2023-02-24 15:16:06 +01:00
|
|
|
idGenerator: tt.fields.idGenerator,
|
|
|
|
idpConfigEncryption: tt.fields.secretCrypto,
|
|
|
|
}
|
|
|
|
id, got, err := c.AddInstanceGenericOAuthProvider(tt.args.ctx, tt.args.provider)
|
|
|
|
if tt.res.err == nil {
|
|
|
|
assert.NoError(t, err)
|
|
|
|
}
|
|
|
|
if tt.res.err != nil && !tt.res.err(err) {
|
|
|
|
t.Errorf("got wrong err: %v ", err)
|
|
|
|
}
|
|
|
|
if tt.res.err == nil {
|
|
|
|
assert.Equal(t, tt.res.id, id)
|
2024-08-12 22:32:01 +02:00
|
|
|
assertObjectDetails(t, tt.res.want, got)
|
2023-02-24 15:16:06 +01:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCommandSide_UpdateInstanceGenericOAuthIDP(t *testing.T) {
|
|
|
|
type fields struct {
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore func(*testing.T) *eventstore.Eventstore
|
2023-02-24 15:16:06 +01:00
|
|
|
secretCrypto crypto.EncryptionAlgorithm
|
|
|
|
}
|
|
|
|
type args struct {
|
|
|
|
ctx context.Context
|
|
|
|
id string
|
|
|
|
provider GenericOAuthProvider
|
|
|
|
}
|
|
|
|
type res struct {
|
|
|
|
want *domain.ObjectDetails
|
|
|
|
err func(error) bool
|
|
|
|
}
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
fields fields
|
|
|
|
args args
|
|
|
|
res res
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
"invalid id",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-02-24 15:16:06 +01:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
provider: GenericOAuthProvider{},
|
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-SAffg", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
2023-02-24 15:16:06 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid name",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-02-24 15:16:06 +01:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
id: "id1",
|
|
|
|
provider: GenericOAuthProvider{},
|
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-Sf3gh", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
2023-02-24 15:16:06 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid clientID",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-02-24 15:16:06 +01:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
id: "id1",
|
|
|
|
provider: GenericOAuthProvider{
|
|
|
|
Name: "name",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-SHJ3ui", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
2023-02-24 15:16:06 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid auth endpoint",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-02-24 15:16:06 +01:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
id: "id1",
|
|
|
|
provider: GenericOAuthProvider{
|
2023-03-13 17:34:29 +01:00
|
|
|
Name: "name",
|
|
|
|
ClientID: "clientID",
|
2023-02-24 15:16:06 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-SVrgh", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
2023-02-24 15:16:06 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid token endpoint",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-02-24 15:16:06 +01:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
id: "id1",
|
|
|
|
provider: GenericOAuthProvider{
|
|
|
|
Name: "name",
|
|
|
|
ClientID: "clientID",
|
|
|
|
AuthorizationEndpoint: "auth",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-DJKeio", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
2023-02-24 15:16:06 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid user endpoint",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-02-24 15:16:06 +01:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
id: "id1",
|
|
|
|
provider: GenericOAuthProvider{
|
|
|
|
Name: "name",
|
|
|
|
ClientID: "clientID",
|
|
|
|
AuthorizationEndpoint: "auth",
|
|
|
|
TokenEndpoint: "token",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-ILSJi", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
2023-02-24 15:16:06 +01:00
|
|
|
},
|
|
|
|
},
|
2023-03-03 11:38:49 +01:00
|
|
|
{
|
|
|
|
"invalid id attribute",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-03 11:38:49 +01:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
id: "id1",
|
|
|
|
provider: GenericOAuthProvider{
|
|
|
|
Name: "name",
|
|
|
|
ClientID: "clientID",
|
|
|
|
AuthorizationEndpoint: "auth",
|
|
|
|
TokenEndpoint: "token",
|
|
|
|
UserEndpoint: "user",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-JKD3h", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
2023-03-03 11:38:49 +01:00
|
|
|
},
|
|
|
|
},
|
2023-02-24 15:16:06 +01:00
|
|
|
{
|
|
|
|
name: "not found",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-02-24 15:16:06 +01:00
|
|
|
expectFilter(),
|
|
|
|
),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
id: "id1",
|
|
|
|
provider: GenericOAuthProvider{
|
|
|
|
Name: "name",
|
|
|
|
ClientID: "clientID",
|
|
|
|
AuthorizationEndpoint: "auth",
|
|
|
|
TokenEndpoint: "token",
|
|
|
|
UserEndpoint: "user",
|
2023-03-03 11:38:49 +01:00
|
|
|
IDAttribute: "idAttribute",
|
2023-02-24 15:16:06 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
2023-12-08 16:30:55 +02:00
|
|
|
err: zerrors.IsNotFound,
|
2023-02-24 15:16:06 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "no changes",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-02-24 15:16:06 +01:00
|
|
|
expectFilter(
|
|
|
|
eventFromEventPusher(
|
|
|
|
instance.NewOAuthIDPAddedEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"name",
|
|
|
|
"clientID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("clientSecret"),
|
|
|
|
},
|
|
|
|
"auth",
|
|
|
|
"token",
|
|
|
|
"user",
|
2023-03-03 11:38:49 +01:00
|
|
|
"idAttribute",
|
2023-02-24 15:16:06 +01:00
|
|
|
nil,
|
2025-02-26 13:20:47 +01:00
|
|
|
true,
|
2023-02-24 15:16:06 +01:00
|
|
|
idp.Options{},
|
|
|
|
)),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
id: "id1",
|
|
|
|
provider: GenericOAuthProvider{
|
|
|
|
Name: "name",
|
|
|
|
ClientID: "clientID",
|
|
|
|
AuthorizationEndpoint: "auth",
|
|
|
|
TokenEndpoint: "token",
|
|
|
|
UserEndpoint: "user",
|
2023-03-03 11:38:49 +01:00
|
|
|
IDAttribute: "idAttribute",
|
2025-02-26 13:20:47 +01:00
|
|
|
UsePKCE: true,
|
2023-02-24 15:16:06 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "instance1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "change ok",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-02-24 15:16:06 +01:00
|
|
|
expectFilter(
|
|
|
|
eventFromEventPusher(
|
|
|
|
instance.NewOAuthIDPAddedEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"name",
|
|
|
|
"clientID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("clientSecret"),
|
|
|
|
},
|
|
|
|
"auth",
|
|
|
|
"token",
|
|
|
|
"user",
|
2023-03-03 11:38:49 +01:00
|
|
|
"idAttribute",
|
2023-02-24 15:16:06 +01:00
|
|
|
nil,
|
2025-02-26 13:20:47 +01:00
|
|
|
false,
|
2023-02-24 15:16:06 +01:00
|
|
|
idp.Options{},
|
|
|
|
)),
|
|
|
|
),
|
|
|
|
expectPush(
|
2023-10-19 12:19:10 +02:00
|
|
|
func() eventstore.Command {
|
|
|
|
t := true
|
|
|
|
event, _ := instance.NewOAuthIDPChangedEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
[]idp.OAuthIDPChanges{
|
|
|
|
idp.ChangeOAuthName("new name"),
|
|
|
|
idp.ChangeOAuthClientID("clientID2"),
|
|
|
|
idp.ChangeOAuthClientSecret(&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("newSecret"),
|
|
|
|
}),
|
|
|
|
idp.ChangeOAuthAuthorizationEndpoint("new auth"),
|
|
|
|
idp.ChangeOAuthTokenEndpoint("new token"),
|
|
|
|
idp.ChangeOAuthUserEndpoint("new user"),
|
|
|
|
idp.ChangeOAuthScopes([]string{"openid", "profile"}),
|
|
|
|
idp.ChangeOAuthIDAttribute("newAttribute"),
|
2025-02-26 13:20:47 +01:00
|
|
|
idp.ChangeOAuthUsePKCE(true),
|
2023-10-19 12:19:10 +02:00
|
|
|
idp.ChangeOAuthOptions(idp.OptionChanges{
|
|
|
|
IsCreationAllowed: &t,
|
|
|
|
IsLinkingAllowed: &t,
|
|
|
|
IsAutoCreation: &t,
|
|
|
|
IsAutoUpdate: &t,
|
|
|
|
}),
|
|
|
|
},
|
|
|
|
)
|
|
|
|
return event
|
|
|
|
}(),
|
2023-02-24 15:16:06 +01:00
|
|
|
),
|
|
|
|
),
|
|
|
|
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
id: "id1",
|
|
|
|
provider: GenericOAuthProvider{
|
|
|
|
Name: "new name",
|
|
|
|
ClientID: "clientID2",
|
|
|
|
ClientSecret: "newSecret",
|
|
|
|
AuthorizationEndpoint: "new auth",
|
|
|
|
TokenEndpoint: "new token",
|
|
|
|
UserEndpoint: "new user",
|
|
|
|
Scopes: []string{"openid", "profile"},
|
2023-03-03 11:38:49 +01:00
|
|
|
IDAttribute: "newAttribute",
|
2025-02-26 13:20:47 +01:00
|
|
|
UsePKCE: true,
|
2023-02-24 15:16:06 +01:00
|
|
|
IDPOptions: idp.Options{
|
|
|
|
IsCreationAllowed: true,
|
|
|
|
IsLinkingAllowed: true,
|
|
|
|
IsAutoCreation: true,
|
|
|
|
IsAutoUpdate: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "instance1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
c := &Commands{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: tt.fields.eventstore(t),
|
2023-02-24 15:16:06 +01:00
|
|
|
idpConfigEncryption: tt.fields.secretCrypto,
|
|
|
|
}
|
|
|
|
got, err := c.UpdateInstanceGenericOAuthProvider(tt.args.ctx, tt.args.id, tt.args.provider)
|
2023-03-08 11:17:28 +01:00
|
|
|
if tt.res.err == nil {
|
|
|
|
assert.NoError(t, err)
|
|
|
|
}
|
|
|
|
if tt.res.err != nil && !tt.res.err(err) {
|
|
|
|
t.Errorf("got wrong err: %v ", err)
|
2023-03-15 07:48:37 +01:00
|
|
|
}
|
|
|
|
if tt.res.err == nil {
|
2024-08-12 22:32:01 +02:00
|
|
|
assertObjectDetails(t, tt.res.want, got)
|
2023-03-15 07:48:37 +01:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-03-16 16:47:22 +01:00
|
|
|
func TestCommandSide_AddInstanceGenericOIDCIDP(t *testing.T) {
|
|
|
|
type fields struct {
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore func(*testing.T) *eventstore.Eventstore
|
2023-03-16 16:47:22 +01:00
|
|
|
idGenerator id.Generator
|
|
|
|
secretCrypto crypto.EncryptionAlgorithm
|
|
|
|
}
|
|
|
|
type args struct {
|
|
|
|
ctx context.Context
|
|
|
|
provider GenericOIDCProvider
|
|
|
|
}
|
|
|
|
type res struct {
|
|
|
|
id string
|
|
|
|
want *domain.ObjectDetails
|
|
|
|
err func(error) bool
|
|
|
|
}
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
fields fields
|
|
|
|
args args
|
|
|
|
res res
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
"invalid name",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-16 16:47:22 +01:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
provider: GenericOIDCProvider{},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-Sgtj5", ""))
|
2023-03-16 16:47:22 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid issuer",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-16 16:47:22 +01:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
provider: GenericOIDCProvider{
|
|
|
|
Name: "name",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-Hz6zj", ""))
|
2023-03-16 16:47:22 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid clientID",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-16 16:47:22 +01:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
provider: GenericOIDCProvider{
|
|
|
|
Name: "name",
|
|
|
|
Issuer: "issuer",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-fb5jm", ""))
|
2023-03-16 16:47:22 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid clientSecret",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-16 16:47:22 +01:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
provider: GenericOIDCProvider{
|
|
|
|
Name: "name",
|
|
|
|
Issuer: "issuer",
|
|
|
|
ClientID: "clientID",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-Sfdf4", ""))
|
2023-03-16 16:47:22 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "ok",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-03-16 16:47:22 +01:00
|
|
|
expectFilter(),
|
|
|
|
expectPush(
|
2023-10-19 12:19:10 +02:00
|
|
|
instance.NewOIDCIDPAddedEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"name",
|
|
|
|
"issuer",
|
|
|
|
"clientID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("clientSecret"),
|
|
|
|
},
|
|
|
|
nil,
|
|
|
|
false,
|
2025-02-26 13:20:47 +01:00
|
|
|
true,
|
2023-10-19 12:19:10 +02:00
|
|
|
idp.Options{},
|
|
|
|
),
|
2023-03-16 16:47:22 +01:00
|
|
|
),
|
|
|
|
),
|
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
provider: GenericOIDCProvider{
|
|
|
|
Name: "name",
|
|
|
|
Issuer: "issuer",
|
|
|
|
ClientID: "clientID",
|
|
|
|
ClientSecret: "clientSecret",
|
2025-02-26 13:20:47 +01:00
|
|
|
UsePKCE: true,
|
2023-03-16 16:47:22 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
id: "id1",
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "instance1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "ok all set",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-03-16 16:47:22 +01:00
|
|
|
expectFilter(),
|
|
|
|
expectPush(
|
2023-10-19 12:19:10 +02:00
|
|
|
instance.NewOIDCIDPAddedEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"name",
|
|
|
|
"issuer",
|
|
|
|
"clientID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("clientSecret"),
|
|
|
|
},
|
|
|
|
[]string{openid.ScopeOpenID},
|
|
|
|
true,
|
2025-02-26 13:20:47 +01:00
|
|
|
true,
|
2023-10-19 12:19:10 +02:00
|
|
|
idp.Options{
|
|
|
|
IsCreationAllowed: true,
|
|
|
|
IsLinkingAllowed: true,
|
|
|
|
IsAutoCreation: true,
|
|
|
|
IsAutoUpdate: true,
|
|
|
|
},
|
|
|
|
),
|
2023-03-16 16:47:22 +01:00
|
|
|
),
|
|
|
|
),
|
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
provider: GenericOIDCProvider{
|
|
|
|
Name: "name",
|
|
|
|
Issuer: "issuer",
|
|
|
|
ClientID: "clientID",
|
|
|
|
ClientSecret: "clientSecret",
|
|
|
|
Scopes: []string{openid.ScopeOpenID},
|
|
|
|
IsIDTokenMapping: true,
|
2025-02-26 13:20:47 +01:00
|
|
|
UsePKCE: true,
|
2023-03-16 16:47:22 +01:00
|
|
|
IDPOptions: idp.Options{
|
|
|
|
IsCreationAllowed: true,
|
|
|
|
IsLinkingAllowed: true,
|
|
|
|
IsAutoCreation: true,
|
|
|
|
IsAutoUpdate: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
id: "id1",
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "instance1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
c := &Commands{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: tt.fields.eventstore(t),
|
2023-03-16 16:47:22 +01:00
|
|
|
idGenerator: tt.fields.idGenerator,
|
|
|
|
idpConfigEncryption: tt.fields.secretCrypto,
|
|
|
|
}
|
|
|
|
id, got, err := c.AddInstanceGenericOIDCProvider(tt.args.ctx, tt.args.provider)
|
|
|
|
if tt.res.err == nil {
|
|
|
|
assert.NoError(t, err)
|
|
|
|
}
|
|
|
|
if tt.res.err != nil && !tt.res.err(err) {
|
|
|
|
t.Errorf("got wrong err: %v ", err)
|
|
|
|
}
|
|
|
|
if tt.res.err == nil {
|
|
|
|
assert.Equal(t, tt.res.id, id)
|
2024-08-12 22:32:01 +02:00
|
|
|
assertObjectDetails(t, tt.res.want, got)
|
2023-03-16 16:47:22 +01:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCommandSide_UpdateInstanceGenericOIDCIDP(t *testing.T) {
|
|
|
|
type fields struct {
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore func(*testing.T) *eventstore.Eventstore
|
2023-03-16 16:47:22 +01:00
|
|
|
secretCrypto crypto.EncryptionAlgorithm
|
|
|
|
}
|
|
|
|
type args struct {
|
|
|
|
ctx context.Context
|
|
|
|
id string
|
|
|
|
provider GenericOIDCProvider
|
|
|
|
}
|
|
|
|
type res struct {
|
|
|
|
want *domain.ObjectDetails
|
|
|
|
err func(error) bool
|
|
|
|
}
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
fields fields
|
|
|
|
args args
|
|
|
|
res res
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
"invalid id",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-16 16:47:22 +01:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
provider: GenericOIDCProvider{},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-SAfd3", ""))
|
2023-03-16 16:47:22 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid name",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-16 16:47:22 +01:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
id: "id1",
|
|
|
|
provider: GenericOIDCProvider{},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-Dvf4f", ""))
|
2023-03-16 16:47:22 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid issuer",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-16 16:47:22 +01:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
id: "id1",
|
|
|
|
provider: GenericOIDCProvider{
|
|
|
|
Name: "name",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-BDfr3", ""))
|
2023-03-16 16:47:22 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid clientID",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-16 16:47:22 +01:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
id: "id1",
|
|
|
|
provider: GenericOIDCProvider{
|
|
|
|
Name: "name",
|
|
|
|
Issuer: "issuer",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-Db3bs", ""))
|
2023-03-16 16:47:22 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "not found",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-03-16 16:47:22 +01:00
|
|
|
expectFilter(),
|
|
|
|
),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
id: "id1",
|
|
|
|
provider: GenericOIDCProvider{
|
|
|
|
Name: "name",
|
|
|
|
Issuer: "issuer",
|
|
|
|
ClientID: "clientID",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
2023-12-08 16:30:55 +02:00
|
|
|
err: zerrors.IsNotFound,
|
2023-03-16 16:47:22 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "no changes",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-03-16 16:47:22 +01:00
|
|
|
expectFilter(
|
|
|
|
eventFromEventPusher(
|
|
|
|
instance.NewOIDCIDPAddedEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"name",
|
|
|
|
"issuer",
|
|
|
|
"clientID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("clientSecret"),
|
|
|
|
},
|
|
|
|
nil,
|
|
|
|
false,
|
2025-02-26 13:20:47 +01:00
|
|
|
false,
|
2023-03-16 16:47:22 +01:00
|
|
|
idp.Options{},
|
|
|
|
)),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
id: "id1",
|
|
|
|
provider: GenericOIDCProvider{
|
|
|
|
Name: "name",
|
|
|
|
Issuer: "issuer",
|
|
|
|
ClientID: "clientID",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "instance1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "change ok",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-03-16 16:47:22 +01:00
|
|
|
expectFilter(
|
|
|
|
eventFromEventPusher(
|
|
|
|
instance.NewOIDCIDPAddedEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"name",
|
|
|
|
"issuer",
|
|
|
|
"clientID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("clientSecret"),
|
|
|
|
},
|
|
|
|
nil,
|
|
|
|
false,
|
2025-02-26 13:20:47 +01:00
|
|
|
false,
|
2023-03-16 16:47:22 +01:00
|
|
|
idp.Options{},
|
|
|
|
)),
|
|
|
|
),
|
|
|
|
expectPush(
|
2023-10-19 12:19:10 +02:00
|
|
|
func() eventstore.Command {
|
|
|
|
t := true
|
|
|
|
event, _ := instance.NewOIDCIDPChangedEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
[]idp.OIDCIDPChanges{
|
|
|
|
idp.ChangeOIDCName("new name"),
|
|
|
|
idp.ChangeOIDCIssuer("new issuer"),
|
|
|
|
idp.ChangeOIDCClientID("clientID2"),
|
|
|
|
idp.ChangeOIDCClientSecret(&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("newSecret"),
|
|
|
|
}),
|
|
|
|
idp.ChangeOIDCScopes([]string{"openid", "profile"}),
|
|
|
|
idp.ChangeOIDCIsIDTokenMapping(true),
|
2025-02-26 13:20:47 +01:00
|
|
|
idp.ChangeOIDCUsePKCE(true),
|
2023-10-19 12:19:10 +02:00
|
|
|
idp.ChangeOIDCOptions(idp.OptionChanges{
|
|
|
|
IsCreationAllowed: &t,
|
|
|
|
IsLinkingAllowed: &t,
|
|
|
|
IsAutoCreation: &t,
|
|
|
|
IsAutoUpdate: &t,
|
|
|
|
}),
|
|
|
|
},
|
|
|
|
)
|
|
|
|
return event
|
|
|
|
}(),
|
2023-03-16 16:47:22 +01:00
|
|
|
),
|
|
|
|
),
|
|
|
|
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
id: "id1",
|
|
|
|
provider: GenericOIDCProvider{
|
|
|
|
Name: "new name",
|
|
|
|
Issuer: "new issuer",
|
|
|
|
ClientID: "clientID2",
|
|
|
|
ClientSecret: "newSecret",
|
|
|
|
Scopes: []string{"openid", "profile"},
|
|
|
|
IsIDTokenMapping: true,
|
2025-02-26 13:20:47 +01:00
|
|
|
UsePKCE: true,
|
2023-03-16 16:47:22 +01:00
|
|
|
IDPOptions: idp.Options{
|
|
|
|
IsCreationAllowed: true,
|
|
|
|
IsLinkingAllowed: true,
|
|
|
|
IsAutoCreation: true,
|
|
|
|
IsAutoUpdate: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "instance1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
c := &Commands{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: tt.fields.eventstore(t),
|
2023-03-16 16:47:22 +01:00
|
|
|
idpConfigEncryption: tt.fields.secretCrypto,
|
|
|
|
}
|
|
|
|
got, err := c.UpdateInstanceGenericOIDCProvider(tt.args.ctx, tt.args.id, tt.args.provider)
|
|
|
|
if tt.res.err == nil {
|
|
|
|
assert.NoError(t, err)
|
|
|
|
}
|
|
|
|
if tt.res.err != nil && !tt.res.err(err) {
|
|
|
|
t.Errorf("got wrong err: %v ", err)
|
|
|
|
}
|
|
|
|
if tt.res.err == nil {
|
2024-08-12 22:32:01 +02:00
|
|
|
assertObjectDetails(t, tt.res.want, got)
|
2023-03-16 16:47:22 +01:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-06-08 00:50:53 +02:00
|
|
|
func TestCommandSide_MigrateInstanceGenericOIDCToAzureADProvider(t *testing.T) {
|
|
|
|
type fields struct {
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore func(*testing.T) *eventstore.Eventstore
|
2023-06-08 00:50:53 +02:00
|
|
|
secretCrypto crypto.EncryptionAlgorithm
|
|
|
|
}
|
|
|
|
type args struct {
|
|
|
|
ctx context.Context
|
|
|
|
id string
|
|
|
|
provider AzureADProvider
|
|
|
|
}
|
|
|
|
type res struct {
|
|
|
|
want *domain.ObjectDetails
|
|
|
|
err func(error) bool
|
|
|
|
}
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
fields fields
|
|
|
|
args args
|
|
|
|
res res
|
|
|
|
}{
|
|
|
|
|
|
|
|
{
|
|
|
|
"invalid name",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-06-08 00:50:53 +02:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
provider: AzureADProvider{},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-sdf3g", ""))
|
2023-06-08 00:50:53 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid client id",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-06-08 00:50:53 +02:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
provider: AzureADProvider{
|
|
|
|
Name: "name",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-Fhbr2", ""))
|
2023-06-08 00:50:53 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid client secret",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-06-08 00:50:53 +02:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
provider: AzureADProvider{
|
|
|
|
Name: "name",
|
|
|
|
ClientID: "clientID",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-Dzh3g", ""))
|
2023-06-08 00:50:53 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "not found",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-06-08 00:50:53 +02:00
|
|
|
expectFilter(),
|
|
|
|
),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
id: "id1",
|
|
|
|
provider: AzureADProvider{
|
|
|
|
Name: "name",
|
|
|
|
ClientID: "clientID",
|
|
|
|
ClientSecret: "clientSecret",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
2023-12-08 16:30:55 +02:00
|
|
|
err: zerrors.IsNotFound,
|
2023-06-08 00:50:53 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "migrate ok",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-06-08 00:50:53 +02:00
|
|
|
expectFilter(
|
|
|
|
eventFromEventPusher(
|
|
|
|
instance.NewOIDCIDPAddedEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"name",
|
|
|
|
"issuer",
|
|
|
|
"clientID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("clientSecret"),
|
|
|
|
},
|
|
|
|
nil,
|
|
|
|
false,
|
2025-02-26 13:20:47 +01:00
|
|
|
false,
|
2023-06-08 00:50:53 +02:00
|
|
|
idp.Options{},
|
|
|
|
)),
|
|
|
|
),
|
|
|
|
expectPush(
|
2023-10-19 12:19:10 +02:00
|
|
|
func() eventstore.Command {
|
|
|
|
event := instance.NewOIDCIDPMigratedAzureADEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"name",
|
|
|
|
"clientID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("clientSecret"),
|
|
|
|
},
|
|
|
|
nil,
|
|
|
|
"",
|
|
|
|
false,
|
|
|
|
idp.Options{},
|
|
|
|
)
|
|
|
|
return event
|
|
|
|
}(),
|
2023-06-08 00:50:53 +02:00
|
|
|
),
|
|
|
|
),
|
|
|
|
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
id: "id1",
|
|
|
|
provider: AzureADProvider{
|
|
|
|
Name: "name",
|
|
|
|
ClientID: "clientID",
|
|
|
|
ClientSecret: "clientSecret",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "instance1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "migrate ok full",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-06-08 00:50:53 +02:00
|
|
|
expectFilter(
|
|
|
|
eventFromEventPusher(
|
|
|
|
instance.NewOIDCIDPAddedEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"name",
|
|
|
|
"issuer",
|
|
|
|
"clientID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("clientSecret"),
|
|
|
|
},
|
|
|
|
nil,
|
|
|
|
false,
|
2025-02-26 13:20:47 +01:00
|
|
|
false,
|
2023-06-08 00:50:53 +02:00
|
|
|
idp.Options{},
|
|
|
|
)),
|
|
|
|
),
|
|
|
|
expectPush(
|
2023-10-19 12:19:10 +02:00
|
|
|
func() eventstore.Command {
|
|
|
|
event := instance.NewOIDCIDPMigratedAzureADEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"name",
|
|
|
|
"clientID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("clientSecret"),
|
|
|
|
},
|
|
|
|
[]string{"openid"},
|
|
|
|
"tenant",
|
|
|
|
true,
|
|
|
|
idp.Options{
|
|
|
|
IsCreationAllowed: true,
|
|
|
|
IsLinkingAllowed: true,
|
|
|
|
IsAutoCreation: true,
|
|
|
|
IsAutoUpdate: true,
|
|
|
|
},
|
|
|
|
)
|
|
|
|
return event
|
|
|
|
}(),
|
2023-06-08 00:50:53 +02:00
|
|
|
),
|
|
|
|
),
|
|
|
|
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
id: "id1",
|
|
|
|
provider: AzureADProvider{
|
|
|
|
Name: "name",
|
|
|
|
ClientID: "clientID",
|
|
|
|
ClientSecret: "clientSecret",
|
|
|
|
Scopes: []string{"openid"},
|
|
|
|
Tenant: "tenant",
|
|
|
|
EmailVerified: true,
|
|
|
|
IDPOptions: idp.Options{
|
|
|
|
IsCreationAllowed: true,
|
|
|
|
IsLinkingAllowed: true,
|
|
|
|
IsAutoCreation: true,
|
|
|
|
IsAutoUpdate: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "instance1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
c := &Commands{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: tt.fields.eventstore(t),
|
2023-06-08 00:50:53 +02:00
|
|
|
idpConfigEncryption: tt.fields.secretCrypto,
|
|
|
|
}
|
|
|
|
got, err := c.MigrateInstanceGenericOIDCToAzureADProvider(tt.args.ctx, tt.args.id, tt.args.provider)
|
|
|
|
if tt.res.err == nil {
|
|
|
|
assert.NoError(t, err)
|
|
|
|
}
|
|
|
|
if tt.res.err != nil && !tt.res.err(err) {
|
|
|
|
t.Errorf("got wrong err: %v ", err)
|
|
|
|
}
|
|
|
|
if tt.res.err == nil {
|
2024-08-12 22:32:01 +02:00
|
|
|
assertObjectDetails(t, tt.res.want, got)
|
2023-06-08 00:50:53 +02:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCommandSide_MigrateInstanceOIDCToGoogleIDP(t *testing.T) {
|
|
|
|
type fields struct {
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore func(*testing.T) *eventstore.Eventstore
|
2023-06-08 00:50:53 +02:00
|
|
|
secretCrypto crypto.EncryptionAlgorithm
|
|
|
|
}
|
|
|
|
type args struct {
|
|
|
|
ctx context.Context
|
|
|
|
id string
|
|
|
|
provider GoogleProvider
|
|
|
|
}
|
|
|
|
type res struct {
|
|
|
|
want *domain.ObjectDetails
|
|
|
|
err func(error) bool
|
|
|
|
}
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
fields fields
|
|
|
|
args args
|
|
|
|
res res
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
"invalid clientID",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-06-08 00:50:53 +02:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
provider: GoogleProvider{},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-D3fvs", ""))
|
2023-06-08 00:50:53 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid clientSecret",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-06-08 00:50:53 +02:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
provider: GoogleProvider{
|
|
|
|
ClientID: "clientID",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-W2vqs", ""))
|
2023-06-08 00:50:53 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "not found",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-06-08 00:50:53 +02:00
|
|
|
expectFilter(),
|
|
|
|
),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
id: "id1",
|
|
|
|
provider: GoogleProvider{
|
|
|
|
ClientID: "clientID",
|
|
|
|
ClientSecret: "clientSecret",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
2023-12-08 16:30:55 +02:00
|
|
|
err: zerrors.IsNotFound,
|
2023-06-08 00:50:53 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "migrate ok",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-06-08 00:50:53 +02:00
|
|
|
expectFilter(
|
|
|
|
eventFromEventPusher(
|
|
|
|
instance.NewOIDCIDPAddedEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"name",
|
|
|
|
"issuer",
|
|
|
|
"clientID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("clientSecret"),
|
|
|
|
},
|
|
|
|
nil,
|
|
|
|
false,
|
2025-02-26 13:20:47 +01:00
|
|
|
false,
|
2023-06-08 00:50:53 +02:00
|
|
|
idp.Options{},
|
|
|
|
)),
|
|
|
|
),
|
|
|
|
expectPush(
|
2023-10-19 12:19:10 +02:00
|
|
|
instance.NewOIDCIDPMigratedGoogleEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"",
|
|
|
|
"clientID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("clientSecret"),
|
|
|
|
},
|
|
|
|
nil,
|
|
|
|
idp.Options{},
|
|
|
|
),
|
2023-06-08 00:50:53 +02:00
|
|
|
),
|
|
|
|
),
|
|
|
|
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
id: "id1",
|
|
|
|
provider: GoogleProvider{
|
|
|
|
ClientID: "clientID",
|
|
|
|
ClientSecret: "clientSecret",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "instance1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "migrate ok full",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-06-08 00:50:53 +02:00
|
|
|
expectFilter(
|
|
|
|
eventFromEventPusher(
|
|
|
|
instance.NewOIDCIDPAddedEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"name",
|
|
|
|
"issuer",
|
|
|
|
"clientID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("clientSecret"),
|
|
|
|
},
|
|
|
|
nil,
|
|
|
|
false,
|
2025-02-26 13:20:47 +01:00
|
|
|
false,
|
2023-06-08 00:50:53 +02:00
|
|
|
idp.Options{},
|
|
|
|
)),
|
|
|
|
),
|
|
|
|
expectPush(
|
2023-10-19 12:19:10 +02:00
|
|
|
instance.NewOIDCIDPMigratedGoogleEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"",
|
|
|
|
"clientID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("clientSecret"),
|
|
|
|
},
|
|
|
|
[]string{"openid"},
|
|
|
|
idp.Options{
|
|
|
|
IsCreationAllowed: true,
|
|
|
|
IsLinkingAllowed: true,
|
|
|
|
IsAutoCreation: true,
|
|
|
|
IsAutoUpdate: true,
|
|
|
|
},
|
|
|
|
),
|
2023-06-08 00:50:53 +02:00
|
|
|
),
|
|
|
|
),
|
|
|
|
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
id: "id1",
|
|
|
|
provider: GoogleProvider{
|
|
|
|
ClientID: "clientID",
|
|
|
|
ClientSecret: "clientSecret",
|
|
|
|
Scopes: []string{"openid"},
|
|
|
|
IDPOptions: idp.Options{
|
|
|
|
IsCreationAllowed: true,
|
|
|
|
IsLinkingAllowed: true,
|
|
|
|
IsAutoCreation: true,
|
|
|
|
IsAutoUpdate: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "instance1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
c := &Commands{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: tt.fields.eventstore(t),
|
2023-06-08 00:50:53 +02:00
|
|
|
idpConfigEncryption: tt.fields.secretCrypto,
|
|
|
|
}
|
|
|
|
got, err := c.MigrateInstanceGenericOIDCToGoogleProvider(tt.args.ctx, tt.args.id, tt.args.provider)
|
|
|
|
if tt.res.err == nil {
|
|
|
|
assert.NoError(t, err)
|
|
|
|
}
|
|
|
|
if tt.res.err != nil && !tt.res.err(err) {
|
|
|
|
t.Errorf("got wrong err: %v ", err)
|
|
|
|
}
|
|
|
|
if tt.res.err == nil {
|
2024-08-12 22:32:01 +02:00
|
|
|
assertObjectDetails(t, tt.res.want, got)
|
2023-06-08 00:50:53 +02:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-03-15 07:48:37 +01:00
|
|
|
func TestCommandSide_AddInstanceAzureADIDP(t *testing.T) {
|
|
|
|
type fields struct {
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore func(*testing.T) *eventstore.Eventstore
|
2023-03-15 07:48:37 +01:00
|
|
|
idGenerator id.Generator
|
|
|
|
secretCrypto crypto.EncryptionAlgorithm
|
|
|
|
}
|
|
|
|
type args struct {
|
|
|
|
ctx context.Context
|
|
|
|
provider AzureADProvider
|
|
|
|
}
|
|
|
|
type res struct {
|
|
|
|
id string
|
|
|
|
want *domain.ObjectDetails
|
|
|
|
err func(error) bool
|
|
|
|
}
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
fields fields
|
|
|
|
args args
|
|
|
|
res res
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
"invalid name",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-15 07:48:37 +01:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
provider: AzureADProvider{},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-sdf3g", ""))
|
2023-03-15 07:48:37 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid client id",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-15 07:48:37 +01:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
provider: AzureADProvider{
|
|
|
|
Name: "name",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-Fhbr2", ""))
|
2023-03-15 07:48:37 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid client secret",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-15 07:48:37 +01:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
provider: AzureADProvider{
|
|
|
|
Name: "name",
|
|
|
|
ClientID: "clientID",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-Dzh3g", ""))
|
2023-03-15 07:48:37 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "ok",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-03-15 07:48:37 +01:00
|
|
|
expectFilter(),
|
|
|
|
expectPush(
|
2023-10-19 12:19:10 +02:00
|
|
|
instance.NewAzureADIDPAddedEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"name",
|
|
|
|
"clientID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("clientSecret"),
|
|
|
|
},
|
|
|
|
nil,
|
|
|
|
"",
|
|
|
|
false,
|
|
|
|
idp.Options{},
|
|
|
|
),
|
2023-03-15 07:48:37 +01:00
|
|
|
),
|
|
|
|
),
|
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
provider: AzureADProvider{
|
|
|
|
Name: "name",
|
|
|
|
ClientID: "clientID",
|
|
|
|
ClientSecret: "clientSecret",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
id: "id1",
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "instance1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "ok all set",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-03-15 07:48:37 +01:00
|
|
|
expectFilter(),
|
|
|
|
expectPush(
|
2023-10-19 12:19:10 +02:00
|
|
|
instance.NewAzureADIDPAddedEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"name",
|
|
|
|
"clientID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("clientSecret"),
|
|
|
|
},
|
|
|
|
[]string{"openid"},
|
|
|
|
"tenant",
|
|
|
|
true,
|
|
|
|
idp.Options{
|
|
|
|
IsCreationAllowed: true,
|
|
|
|
IsLinkingAllowed: true,
|
|
|
|
IsAutoCreation: true,
|
|
|
|
IsAutoUpdate: true,
|
|
|
|
},
|
|
|
|
),
|
2023-03-15 07:48:37 +01:00
|
|
|
),
|
|
|
|
),
|
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
provider: AzureADProvider{
|
|
|
|
Name: "name",
|
|
|
|
ClientID: "clientID",
|
|
|
|
ClientSecret: "clientSecret",
|
|
|
|
Scopes: []string{"openid"},
|
|
|
|
Tenant: "tenant",
|
|
|
|
EmailVerified: true,
|
|
|
|
IDPOptions: idp.Options{
|
|
|
|
IsCreationAllowed: true,
|
|
|
|
IsLinkingAllowed: true,
|
|
|
|
IsAutoCreation: true,
|
|
|
|
IsAutoUpdate: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
id: "id1",
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "instance1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
c := &Commands{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: tt.fields.eventstore(t),
|
2023-03-15 07:48:37 +01:00
|
|
|
idGenerator: tt.fields.idGenerator,
|
|
|
|
idpConfigEncryption: tt.fields.secretCrypto,
|
|
|
|
}
|
|
|
|
id, got, err := c.AddInstanceAzureADProvider(tt.args.ctx, tt.args.provider)
|
|
|
|
if tt.res.err == nil {
|
|
|
|
assert.NoError(t, err)
|
|
|
|
}
|
|
|
|
if tt.res.err != nil && !tt.res.err(err) {
|
|
|
|
t.Errorf("got wrong err: %v ", err)
|
|
|
|
}
|
|
|
|
if tt.res.err == nil {
|
|
|
|
assert.Equal(t, tt.res.id, id)
|
2024-08-12 22:32:01 +02:00
|
|
|
assertObjectDetails(t, tt.res.want, got)
|
2023-03-15 07:48:37 +01:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCommandSide_UpdateInstanceAzureADIDP(t *testing.T) {
|
|
|
|
type fields struct {
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore func(*testing.T) *eventstore.Eventstore
|
2023-03-15 07:48:37 +01:00
|
|
|
secretCrypto crypto.EncryptionAlgorithm
|
|
|
|
}
|
|
|
|
type args struct {
|
|
|
|
ctx context.Context
|
|
|
|
id string
|
|
|
|
provider AzureADProvider
|
|
|
|
}
|
|
|
|
type res struct {
|
|
|
|
want *domain.ObjectDetails
|
|
|
|
err func(error) bool
|
|
|
|
}
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
fields fields
|
|
|
|
args args
|
|
|
|
res res
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
"invalid id",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-15 07:48:37 +01:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
provider: AzureADProvider{},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-SAgh2", ""))
|
2023-03-15 07:48:37 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid name",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-15 07:48:37 +01:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
id: "id1",
|
|
|
|
provider: AzureADProvider{},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-fh3h1", ""))
|
2023-03-15 07:48:37 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid client id",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-15 07:48:37 +01:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
id: "id1",
|
|
|
|
provider: AzureADProvider{
|
|
|
|
Name: "name",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-dmitg", ""))
|
2023-03-15 07:48:37 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "not found",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-03-15 07:48:37 +01:00
|
|
|
expectFilter(),
|
|
|
|
),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
id: "id1",
|
|
|
|
provider: AzureADProvider{
|
|
|
|
Name: "name",
|
|
|
|
ClientID: "clientID",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
2023-12-08 16:30:55 +02:00
|
|
|
err: zerrors.IsNotFound,
|
2023-03-15 07:48:37 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "no changes",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-03-15 07:48:37 +01:00
|
|
|
expectFilter(
|
|
|
|
eventFromEventPusher(
|
|
|
|
instance.NewAzureADIDPAddedEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"name",
|
|
|
|
"clientID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("clientSecret"),
|
|
|
|
},
|
|
|
|
nil,
|
|
|
|
"",
|
|
|
|
false,
|
|
|
|
idp.Options{},
|
|
|
|
)),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
id: "id1",
|
|
|
|
provider: AzureADProvider{
|
|
|
|
Name: "name",
|
|
|
|
ClientID: "clientID",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "instance1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "change ok",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-03-15 07:48:37 +01:00
|
|
|
expectFilter(
|
|
|
|
eventFromEventPusher(
|
|
|
|
instance.NewAzureADIDPAddedEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"name",
|
|
|
|
"clientID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("clientSecret"),
|
|
|
|
},
|
|
|
|
nil,
|
|
|
|
"",
|
|
|
|
false,
|
|
|
|
idp.Options{},
|
|
|
|
)),
|
|
|
|
),
|
|
|
|
expectPush(
|
2023-10-19 12:19:10 +02:00
|
|
|
func() eventstore.Command {
|
|
|
|
t := true
|
|
|
|
event, _ := instance.NewAzureADIDPChangedEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
[]idp.AzureADIDPChanges{
|
|
|
|
idp.ChangeAzureADName("new name"),
|
|
|
|
idp.ChangeAzureADClientID("new clientID"),
|
|
|
|
idp.ChangeAzureADClientSecret(&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("new clientSecret"),
|
|
|
|
}),
|
|
|
|
idp.ChangeAzureADScopes([]string{"openid", "profile"}),
|
|
|
|
idp.ChangeAzureADTenant("new tenant"),
|
|
|
|
idp.ChangeAzureADIsEmailVerified(true),
|
|
|
|
idp.ChangeAzureADOptions(idp.OptionChanges{
|
|
|
|
IsCreationAllowed: &t,
|
|
|
|
IsLinkingAllowed: &t,
|
|
|
|
IsAutoCreation: &t,
|
|
|
|
IsAutoUpdate: &t,
|
|
|
|
}),
|
|
|
|
},
|
|
|
|
)
|
|
|
|
return event
|
|
|
|
}(),
|
2023-03-15 07:48:37 +01:00
|
|
|
),
|
|
|
|
),
|
|
|
|
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
id: "id1",
|
|
|
|
provider: AzureADProvider{
|
|
|
|
Name: "new name",
|
|
|
|
ClientID: "new clientID",
|
|
|
|
ClientSecret: "new clientSecret",
|
|
|
|
Scopes: []string{"openid", "profile"},
|
|
|
|
Tenant: "new tenant",
|
|
|
|
EmailVerified: true,
|
|
|
|
IDPOptions: idp.Options{
|
|
|
|
IsCreationAllowed: true,
|
|
|
|
IsLinkingAllowed: true,
|
|
|
|
IsAutoCreation: true,
|
|
|
|
IsAutoUpdate: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "instance1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
c := &Commands{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: tt.fields.eventstore(t),
|
2023-03-15 07:48:37 +01:00
|
|
|
idpConfigEncryption: tt.fields.secretCrypto,
|
|
|
|
}
|
|
|
|
got, err := c.UpdateInstanceAzureADProvider(tt.args.ctx, tt.args.id, tt.args.provider)
|
|
|
|
if tt.res.err == nil {
|
|
|
|
assert.NoError(t, err)
|
|
|
|
}
|
|
|
|
if tt.res.err != nil && !tt.res.err(err) {
|
|
|
|
t.Errorf("got wrong err: %v ", err)
|
2023-03-08 11:17:28 +01:00
|
|
|
}
|
|
|
|
if tt.res.err == nil {
|
2024-08-12 22:32:01 +02:00
|
|
|
assertObjectDetails(t, tt.res.want, got)
|
2023-03-08 11:17:28 +01:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCommandSide_AddInstanceGitHubIDP(t *testing.T) {
|
|
|
|
type fields struct {
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore func(*testing.T) *eventstore.Eventstore
|
2023-03-08 11:17:28 +01:00
|
|
|
idGenerator id.Generator
|
|
|
|
secretCrypto crypto.EncryptionAlgorithm
|
|
|
|
}
|
|
|
|
type args struct {
|
|
|
|
ctx context.Context
|
|
|
|
provider GitHubProvider
|
|
|
|
}
|
|
|
|
type res struct {
|
|
|
|
id string
|
|
|
|
want *domain.ObjectDetails
|
|
|
|
err func(error) bool
|
|
|
|
}
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
fields fields
|
|
|
|
args args
|
|
|
|
res res
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
"invalid client id",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-08 11:17:28 +01:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
provider: GitHubProvider{},
|
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-Jdsgf", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
2023-03-08 11:17:28 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid client secret",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-08 11:17:28 +01:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
provider: GitHubProvider{
|
|
|
|
ClientID: "clientID",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-dsgz3", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
2023-03-08 11:17:28 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "ok",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-03-08 11:17:28 +01:00
|
|
|
expectFilter(),
|
|
|
|
expectPush(
|
2023-10-19 12:19:10 +02:00
|
|
|
instance.NewGitHubIDPAddedEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"",
|
|
|
|
"clientID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("clientSecret"),
|
|
|
|
},
|
|
|
|
nil,
|
|
|
|
idp.Options{},
|
|
|
|
),
|
2023-03-08 11:17:28 +01:00
|
|
|
),
|
|
|
|
),
|
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
provider: GitHubProvider{
|
|
|
|
ClientID: "clientID",
|
|
|
|
ClientSecret: "clientSecret",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
id: "id1",
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "instance1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "ok all set",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-03-08 11:17:28 +01:00
|
|
|
expectFilter(),
|
|
|
|
expectPush(
|
2023-10-19 12:19:10 +02:00
|
|
|
instance.NewGitHubIDPAddedEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"name",
|
|
|
|
"clientID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("clientSecret"),
|
|
|
|
},
|
|
|
|
[]string{"openid"},
|
|
|
|
idp.Options{
|
|
|
|
IsCreationAllowed: true,
|
|
|
|
IsLinkingAllowed: true,
|
|
|
|
IsAutoCreation: true,
|
|
|
|
IsAutoUpdate: true,
|
|
|
|
},
|
|
|
|
),
|
2023-03-08 11:17:28 +01:00
|
|
|
),
|
|
|
|
),
|
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
provider: GitHubProvider{
|
|
|
|
Name: "name",
|
|
|
|
ClientID: "clientID",
|
|
|
|
ClientSecret: "clientSecret",
|
|
|
|
Scopes: []string{"openid"},
|
|
|
|
IDPOptions: idp.Options{
|
|
|
|
IsCreationAllowed: true,
|
|
|
|
IsLinkingAllowed: true,
|
|
|
|
IsAutoCreation: true,
|
|
|
|
IsAutoUpdate: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
id: "id1",
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "instance1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
c := &Commands{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: tt.fields.eventstore(t),
|
2023-03-08 11:17:28 +01:00
|
|
|
idGenerator: tt.fields.idGenerator,
|
|
|
|
idpConfigEncryption: tt.fields.secretCrypto,
|
|
|
|
}
|
|
|
|
id, got, err := c.AddInstanceGitHubProvider(tt.args.ctx, tt.args.provider)
|
|
|
|
if tt.res.err == nil {
|
|
|
|
assert.NoError(t, err)
|
|
|
|
}
|
|
|
|
if tt.res.err != nil && !tt.res.err(err) {
|
|
|
|
t.Errorf("got wrong err: %v ", err)
|
|
|
|
}
|
|
|
|
if tt.res.err == nil {
|
|
|
|
assert.Equal(t, tt.res.id, id)
|
2024-08-12 22:32:01 +02:00
|
|
|
assertObjectDetails(t, tt.res.want, got)
|
2023-03-08 11:17:28 +01:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCommandSide_UpdateInstanceGitHubIDP(t *testing.T) {
|
|
|
|
type fields struct {
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore func(*testing.T) *eventstore.Eventstore
|
2023-03-08 11:17:28 +01:00
|
|
|
secretCrypto crypto.EncryptionAlgorithm
|
|
|
|
}
|
|
|
|
type args struct {
|
|
|
|
ctx context.Context
|
|
|
|
id string
|
|
|
|
provider GitHubProvider
|
|
|
|
}
|
|
|
|
type res struct {
|
|
|
|
want *domain.ObjectDetails
|
|
|
|
err func(error) bool
|
|
|
|
}
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
fields fields
|
|
|
|
args args
|
|
|
|
res res
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
"invalid id",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-08 11:17:28 +01:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
provider: GitHubProvider{},
|
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-sdf4h", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
2023-03-08 11:17:28 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid client id",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-08 11:17:28 +01:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
id: "id1",
|
|
|
|
provider: GitHubProvider{},
|
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-fdh5z", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
2023-03-08 11:17:28 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "not found",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-03-08 11:17:28 +01:00
|
|
|
expectFilter(),
|
|
|
|
),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
id: "id1",
|
|
|
|
provider: GitHubProvider{
|
|
|
|
ClientID: "clientID",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
2023-12-08 16:30:55 +02:00
|
|
|
err: zerrors.IsNotFound,
|
2023-03-08 11:17:28 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "no changes",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-03-08 11:17:28 +01:00
|
|
|
expectFilter(
|
|
|
|
eventFromEventPusher(
|
|
|
|
instance.NewGitHubIDPAddedEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"",
|
|
|
|
"clientID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("clientSecret"),
|
|
|
|
},
|
|
|
|
nil,
|
|
|
|
idp.Options{},
|
|
|
|
)),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
id: "id1",
|
|
|
|
provider: GitHubProvider{
|
|
|
|
ClientID: "clientID",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "instance1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "change ok",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-03-08 11:17:28 +01:00
|
|
|
expectFilter(
|
|
|
|
eventFromEventPusher(
|
|
|
|
instance.NewGitHubIDPAddedEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"name",
|
|
|
|
"clientID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("clientSecret"),
|
|
|
|
},
|
|
|
|
nil,
|
|
|
|
idp.Options{},
|
|
|
|
)),
|
|
|
|
),
|
|
|
|
expectPush(
|
2023-10-19 12:19:10 +02:00
|
|
|
func() eventstore.Command {
|
|
|
|
t := true
|
|
|
|
event, _ := instance.NewGitHubIDPChangedEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
[]idp.GitHubIDPChanges{
|
|
|
|
idp.ChangeGitHubName("new name"),
|
|
|
|
idp.ChangeGitHubClientID("new clientID"),
|
|
|
|
idp.ChangeGitHubClientSecret(&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("new clientSecret"),
|
|
|
|
}),
|
|
|
|
idp.ChangeGitHubScopes([]string{"openid", "profile"}),
|
|
|
|
idp.ChangeGitHubOptions(idp.OptionChanges{
|
|
|
|
IsCreationAllowed: &t,
|
|
|
|
IsLinkingAllowed: &t,
|
|
|
|
IsAutoCreation: &t,
|
|
|
|
IsAutoUpdate: &t,
|
|
|
|
}),
|
|
|
|
},
|
|
|
|
)
|
|
|
|
return event
|
|
|
|
}(),
|
2023-03-08 11:17:28 +01:00
|
|
|
),
|
|
|
|
),
|
|
|
|
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
id: "id1",
|
|
|
|
provider: GitHubProvider{
|
|
|
|
Name: "new name",
|
|
|
|
ClientID: "new clientID",
|
|
|
|
ClientSecret: "new clientSecret",
|
|
|
|
Scopes: []string{"openid", "profile"},
|
|
|
|
IDPOptions: idp.Options{
|
|
|
|
IsCreationAllowed: true,
|
|
|
|
IsLinkingAllowed: true,
|
|
|
|
IsAutoCreation: true,
|
|
|
|
IsAutoUpdate: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "instance1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
c := &Commands{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: tt.fields.eventstore(t),
|
2023-03-08 11:17:28 +01:00
|
|
|
idpConfigEncryption: tt.fields.secretCrypto,
|
|
|
|
}
|
|
|
|
got, err := c.UpdateInstanceGitHubProvider(tt.args.ctx, tt.args.id, tt.args.provider)
|
|
|
|
if tt.res.err == nil {
|
|
|
|
assert.NoError(t, err)
|
|
|
|
}
|
|
|
|
if tt.res.err != nil && !tt.res.err(err) {
|
|
|
|
t.Errorf("got wrong err: %v ", err)
|
|
|
|
}
|
|
|
|
if tt.res.err == nil {
|
2024-08-12 22:32:01 +02:00
|
|
|
assertObjectDetails(t, tt.res.want, got)
|
2023-03-08 11:17:28 +01:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCommandSide_AddInstanceGitHubEnterpriseIDP(t *testing.T) {
|
|
|
|
type fields struct {
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore func(*testing.T) *eventstore.Eventstore
|
2023-03-08 11:17:28 +01:00
|
|
|
idGenerator id.Generator
|
|
|
|
secretCrypto crypto.EncryptionAlgorithm
|
|
|
|
}
|
|
|
|
type args struct {
|
|
|
|
ctx context.Context
|
|
|
|
provider GitHubEnterpriseProvider
|
|
|
|
}
|
|
|
|
type res struct {
|
|
|
|
id string
|
|
|
|
want *domain.ObjectDetails
|
|
|
|
err func(error) bool
|
|
|
|
}
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
fields fields
|
|
|
|
args args
|
|
|
|
res res
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
"invalid name",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-08 11:17:28 +01:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
provider: GitHubEnterpriseProvider{},
|
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-Dg4td", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
2023-03-08 11:17:28 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid clientID",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-08 11:17:28 +01:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
provider: GitHubEnterpriseProvider{
|
|
|
|
Name: "name",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-dgj53", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
2023-03-08 11:17:28 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid clientSecret",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-08 11:17:28 +01:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
provider: GitHubEnterpriseProvider{
|
|
|
|
Name: "name",
|
|
|
|
ClientID: "clientID",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-Ghjjs", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
2023-03-08 11:17:28 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid auth endpoint",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-08 11:17:28 +01:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
provider: GitHubEnterpriseProvider{
|
|
|
|
Name: "name",
|
|
|
|
ClientID: "clientID",
|
|
|
|
ClientSecret: "clientSecret",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-sani2", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
2023-03-08 11:17:28 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid token endpoint",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-08 11:17:28 +01:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
provider: GitHubEnterpriseProvider{
|
|
|
|
Name: "name",
|
|
|
|
ClientID: "clientID",
|
|
|
|
ClientSecret: "clientSecret",
|
|
|
|
AuthorizationEndpoint: "auth",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-agj42", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
2023-03-08 11:17:28 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid user endpoint",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-08 11:17:28 +01:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
provider: GitHubEnterpriseProvider{
|
|
|
|
Name: "name",
|
|
|
|
ClientID: "clientID",
|
|
|
|
ClientSecret: "clientSecret",
|
|
|
|
AuthorizationEndpoint: "auth",
|
|
|
|
TokenEndpoint: "token",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-sd5hn", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
2023-03-08 11:17:28 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "ok",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-03-08 11:17:28 +01:00
|
|
|
expectFilter(),
|
|
|
|
expectPush(
|
2023-10-19 12:19:10 +02:00
|
|
|
instance.NewGitHubEnterpriseIDPAddedEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"name",
|
|
|
|
"clientID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("clientSecret"),
|
|
|
|
},
|
|
|
|
"auth",
|
|
|
|
"token",
|
|
|
|
"user",
|
|
|
|
nil,
|
|
|
|
idp.Options{},
|
|
|
|
),
|
2023-03-08 11:17:28 +01:00
|
|
|
),
|
|
|
|
),
|
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
provider: GitHubEnterpriseProvider{
|
|
|
|
Name: "name",
|
|
|
|
ClientID: "clientID",
|
|
|
|
ClientSecret: "clientSecret",
|
|
|
|
AuthorizationEndpoint: "auth",
|
|
|
|
TokenEndpoint: "token",
|
|
|
|
UserEndpoint: "user",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
id: "id1",
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "instance1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "ok all set",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-03-08 11:17:28 +01:00
|
|
|
expectFilter(),
|
|
|
|
expectPush(
|
2023-10-19 12:19:10 +02:00
|
|
|
instance.NewGitHubEnterpriseIDPAddedEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"name",
|
|
|
|
"clientID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("clientSecret"),
|
|
|
|
},
|
|
|
|
"auth",
|
|
|
|
"token",
|
|
|
|
"user",
|
|
|
|
[]string{"user"},
|
|
|
|
idp.Options{
|
|
|
|
IsCreationAllowed: true,
|
|
|
|
IsLinkingAllowed: true,
|
|
|
|
IsAutoCreation: true,
|
|
|
|
IsAutoUpdate: true,
|
|
|
|
},
|
|
|
|
),
|
2023-03-08 11:17:28 +01:00
|
|
|
),
|
|
|
|
),
|
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
provider: GitHubEnterpriseProvider{
|
|
|
|
Name: "name",
|
|
|
|
ClientID: "clientID",
|
|
|
|
ClientSecret: "clientSecret",
|
|
|
|
AuthorizationEndpoint: "auth",
|
|
|
|
TokenEndpoint: "token",
|
|
|
|
UserEndpoint: "user",
|
|
|
|
Scopes: []string{"user"},
|
|
|
|
IDPOptions: idp.Options{
|
|
|
|
IsCreationAllowed: true,
|
|
|
|
IsLinkingAllowed: true,
|
|
|
|
IsAutoCreation: true,
|
|
|
|
IsAutoUpdate: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
id: "id1",
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "instance1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
c := &Commands{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: tt.fields.eventstore(t),
|
2023-03-08 11:17:28 +01:00
|
|
|
idGenerator: tt.fields.idGenerator,
|
|
|
|
idpConfigEncryption: tt.fields.secretCrypto,
|
|
|
|
}
|
|
|
|
id, got, err := c.AddInstanceGitHubEnterpriseProvider(tt.args.ctx, tt.args.provider)
|
|
|
|
if tt.res.err == nil {
|
|
|
|
assert.NoError(t, err)
|
|
|
|
}
|
|
|
|
if tt.res.err != nil && !tt.res.err(err) {
|
|
|
|
t.Errorf("got wrong err: %v ", err)
|
|
|
|
}
|
|
|
|
if tt.res.err == nil {
|
|
|
|
assert.Equal(t, tt.res.id, id)
|
2024-08-12 22:32:01 +02:00
|
|
|
assertObjectDetails(t, tt.res.want, got)
|
2023-03-08 11:17:28 +01:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCommandSide_UpdateInstanceGitHubEnterpriseIDP(t *testing.T) {
|
|
|
|
type fields struct {
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore func(*testing.T) *eventstore.Eventstore
|
2023-03-08 11:17:28 +01:00
|
|
|
secretCrypto crypto.EncryptionAlgorithm
|
|
|
|
}
|
|
|
|
type args struct {
|
|
|
|
ctx context.Context
|
|
|
|
id string
|
|
|
|
provider GitHubEnterpriseProvider
|
|
|
|
}
|
|
|
|
type res struct {
|
|
|
|
want *domain.ObjectDetails
|
|
|
|
err func(error) bool
|
|
|
|
}
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
fields fields
|
|
|
|
args args
|
|
|
|
res res
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
"invalid id",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-08 11:17:28 +01:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
provider: GitHubEnterpriseProvider{},
|
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-sdfh3", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
2023-03-08 11:17:28 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid name",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-08 11:17:28 +01:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
id: "id1",
|
|
|
|
provider: GitHubEnterpriseProvider{},
|
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-shj42", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
2023-03-08 11:17:28 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid clientID",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-08 11:17:28 +01:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
id: "id1",
|
|
|
|
provider: GitHubEnterpriseProvider{
|
|
|
|
Name: "name",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-sdh73", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
2023-03-08 11:17:28 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid auth endpoint",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-08 11:17:28 +01:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
id: "id1",
|
|
|
|
provider: GitHubEnterpriseProvider{
|
2023-03-13 17:34:29 +01:00
|
|
|
Name: "name",
|
|
|
|
ClientID: "clientID",
|
2023-03-08 11:17:28 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-acx2w", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
2023-03-08 11:17:28 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid token endpoint",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-08 11:17:28 +01:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
id: "id1",
|
|
|
|
provider: GitHubEnterpriseProvider{
|
|
|
|
Name: "name",
|
|
|
|
ClientID: "clientID",
|
|
|
|
AuthorizationEndpoint: "auth",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-dgj6q", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
2023-03-08 11:17:28 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid user endpoint",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-08 11:17:28 +01:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
id: "id1",
|
|
|
|
provider: GitHubEnterpriseProvider{
|
|
|
|
Name: "name",
|
|
|
|
ClientID: "clientID",
|
|
|
|
AuthorizationEndpoint: "auth",
|
|
|
|
TokenEndpoint: "token",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-ybj62", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
2023-03-08 11:17:28 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "not found",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-03-08 11:17:28 +01:00
|
|
|
expectFilter(),
|
|
|
|
),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
id: "id1",
|
|
|
|
provider: GitHubEnterpriseProvider{
|
|
|
|
Name: "name",
|
|
|
|
ClientID: "clientID",
|
|
|
|
AuthorizationEndpoint: "auth",
|
|
|
|
TokenEndpoint: "token",
|
|
|
|
UserEndpoint: "user",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
2023-12-08 16:30:55 +02:00
|
|
|
err: zerrors.IsNotFound,
|
2023-03-08 11:17:28 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "no changes",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-03-08 11:17:28 +01:00
|
|
|
expectFilter(
|
|
|
|
eventFromEventPusher(
|
|
|
|
instance.NewGitHubEnterpriseIDPAddedEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"name",
|
|
|
|
"clientID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("clientSecret"),
|
|
|
|
},
|
|
|
|
"auth",
|
|
|
|
"token",
|
|
|
|
"user",
|
|
|
|
nil,
|
|
|
|
idp.Options{},
|
|
|
|
)),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
id: "id1",
|
|
|
|
provider: GitHubEnterpriseProvider{
|
|
|
|
Name: "name",
|
|
|
|
ClientID: "clientID",
|
|
|
|
AuthorizationEndpoint: "auth",
|
|
|
|
TokenEndpoint: "token",
|
|
|
|
UserEndpoint: "user",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "instance1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "change ok",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-03-08 11:17:28 +01:00
|
|
|
expectFilter(
|
|
|
|
eventFromEventPusher(
|
|
|
|
instance.NewGitHubEnterpriseIDPAddedEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"name",
|
|
|
|
"clientID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("clientSecret"),
|
|
|
|
},
|
|
|
|
"auth",
|
|
|
|
"token",
|
|
|
|
"user",
|
|
|
|
nil,
|
|
|
|
idp.Options{},
|
|
|
|
)),
|
|
|
|
),
|
|
|
|
expectPush(
|
2023-10-19 12:19:10 +02:00
|
|
|
func() eventstore.Command {
|
|
|
|
t := true
|
|
|
|
event, _ := instance.NewGitHubEnterpriseIDPChangedEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
[]idp.GitHubEnterpriseIDPChanges{
|
|
|
|
idp.ChangeGitHubEnterpriseName("new name"),
|
|
|
|
idp.ChangeGitHubEnterpriseClientID("clientID2"),
|
|
|
|
idp.ChangeGitHubEnterpriseClientSecret(&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("newSecret"),
|
|
|
|
}),
|
|
|
|
idp.ChangeGitHubEnterpriseAuthorizationEndpoint("new auth"),
|
|
|
|
idp.ChangeGitHubEnterpriseTokenEndpoint("new token"),
|
|
|
|
idp.ChangeGitHubEnterpriseUserEndpoint("new user"),
|
|
|
|
idp.ChangeGitHubEnterpriseScopes([]string{"openid", "profile"}),
|
|
|
|
idp.ChangeGitHubEnterpriseOptions(idp.OptionChanges{
|
|
|
|
IsCreationAllowed: &t,
|
|
|
|
IsLinkingAllowed: &t,
|
|
|
|
IsAutoCreation: &t,
|
|
|
|
IsAutoUpdate: &t,
|
|
|
|
}),
|
|
|
|
},
|
|
|
|
)
|
|
|
|
return event
|
|
|
|
}(),
|
2023-03-08 11:17:28 +01:00
|
|
|
),
|
|
|
|
),
|
|
|
|
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
id: "id1",
|
|
|
|
provider: GitHubEnterpriseProvider{
|
|
|
|
Name: "new name",
|
|
|
|
ClientID: "clientID2",
|
|
|
|
ClientSecret: "newSecret",
|
|
|
|
AuthorizationEndpoint: "new auth",
|
|
|
|
TokenEndpoint: "new token",
|
|
|
|
UserEndpoint: "new user",
|
|
|
|
Scopes: []string{"openid", "profile"},
|
|
|
|
IDPOptions: idp.Options{
|
|
|
|
IsCreationAllowed: true,
|
|
|
|
IsLinkingAllowed: true,
|
|
|
|
IsAutoCreation: true,
|
|
|
|
IsAutoUpdate: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "instance1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
c := &Commands{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: tt.fields.eventstore(t),
|
2023-03-08 11:17:28 +01:00
|
|
|
idpConfigEncryption: tt.fields.secretCrypto,
|
|
|
|
}
|
|
|
|
got, err := c.UpdateInstanceGitHubEnterpriseProvider(tt.args.ctx, tt.args.id, tt.args.provider)
|
2023-02-24 15:16:06 +01:00
|
|
|
if tt.res.err == nil {
|
|
|
|
assert.NoError(t, err)
|
|
|
|
}
|
|
|
|
if tt.res.err != nil && !tt.res.err(err) {
|
|
|
|
t.Errorf("got wrong err: %v ", err)
|
|
|
|
}
|
|
|
|
if tt.res.err == nil {
|
2024-08-12 22:32:01 +02:00
|
|
|
assertObjectDetails(t, tt.res.want, got)
|
2023-02-24 15:16:06 +01:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-03-13 17:34:29 +01:00
|
|
|
func TestCommandSide_AddInstanceGitLabIDP(t *testing.T) {
|
2023-02-21 18:18:28 +01:00
|
|
|
type fields struct {
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore func(*testing.T) *eventstore.Eventstore
|
2023-02-21 18:18:28 +01:00
|
|
|
idGenerator id.Generator
|
|
|
|
secretCrypto crypto.EncryptionAlgorithm
|
|
|
|
}
|
|
|
|
type args struct {
|
|
|
|
ctx context.Context
|
2023-03-13 17:34:29 +01:00
|
|
|
provider GitLabProvider
|
2023-02-21 18:18:28 +01:00
|
|
|
}
|
|
|
|
type res struct {
|
|
|
|
id string
|
|
|
|
want *domain.ObjectDetails
|
|
|
|
err func(error) bool
|
|
|
|
}
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
fields fields
|
|
|
|
args args
|
|
|
|
res res
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
"invalid clientID",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-02-21 18:18:28 +01:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
2023-03-13 17:34:29 +01:00
|
|
|
provider: GitLabProvider{},
|
2023-02-21 18:18:28 +01:00
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-adsg2", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
2023-02-21 18:18:28 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid clientSecret",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-02-21 18:18:28 +01:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
2023-03-13 17:34:29 +01:00
|
|
|
provider: GitLabProvider{
|
2023-02-21 18:18:28 +01:00
|
|
|
ClientID: "clientID",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-GD1j2", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
2023-02-21 18:18:28 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "ok",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-02-21 18:18:28 +01:00
|
|
|
expectFilter(),
|
|
|
|
expectPush(
|
2023-10-19 12:19:10 +02:00
|
|
|
instance.NewGitLabIDPAddedEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"",
|
|
|
|
"clientID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("clientSecret"),
|
|
|
|
},
|
|
|
|
nil,
|
|
|
|
idp.Options{},
|
|
|
|
),
|
2023-02-21 18:18:28 +01:00
|
|
|
),
|
|
|
|
),
|
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
2023-03-13 17:34:29 +01:00
|
|
|
provider: GitLabProvider{
|
2023-02-21 18:18:28 +01:00
|
|
|
ClientID: "clientID",
|
|
|
|
ClientSecret: "clientSecret",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
id: "id1",
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "instance1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "ok all set",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-02-21 18:18:28 +01:00
|
|
|
expectFilter(),
|
|
|
|
expectPush(
|
2023-10-19 12:19:10 +02:00
|
|
|
instance.NewGitLabIDPAddedEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"",
|
|
|
|
"clientID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("clientSecret"),
|
|
|
|
},
|
|
|
|
[]string{"openid"},
|
|
|
|
idp.Options{
|
|
|
|
IsCreationAllowed: true,
|
|
|
|
IsLinkingAllowed: true,
|
|
|
|
IsAutoCreation: true,
|
|
|
|
IsAutoUpdate: true,
|
|
|
|
},
|
|
|
|
),
|
2023-02-21 18:18:28 +01:00
|
|
|
),
|
|
|
|
),
|
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
2023-03-13 17:34:29 +01:00
|
|
|
provider: GitLabProvider{
|
2023-02-21 18:18:28 +01:00
|
|
|
ClientID: "clientID",
|
|
|
|
ClientSecret: "clientSecret",
|
|
|
|
Scopes: []string{"openid"},
|
|
|
|
IDPOptions: idp.Options{
|
|
|
|
IsCreationAllowed: true,
|
|
|
|
IsLinkingAllowed: true,
|
|
|
|
IsAutoCreation: true,
|
|
|
|
IsAutoUpdate: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
id: "id1",
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "instance1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
c := &Commands{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: tt.fields.eventstore(t),
|
2023-02-21 18:18:28 +01:00
|
|
|
idGenerator: tt.fields.idGenerator,
|
|
|
|
idpConfigEncryption: tt.fields.secretCrypto,
|
|
|
|
}
|
2023-03-13 17:34:29 +01:00
|
|
|
id, got, err := c.AddInstanceGitLabProvider(tt.args.ctx, tt.args.provider)
|
2023-02-21 18:18:28 +01:00
|
|
|
if tt.res.err == nil {
|
|
|
|
assert.NoError(t, err)
|
|
|
|
}
|
|
|
|
if tt.res.err != nil && !tt.res.err(err) {
|
|
|
|
t.Errorf("got wrong err: %v ", err)
|
|
|
|
}
|
|
|
|
if tt.res.err == nil {
|
|
|
|
assert.Equal(t, tt.res.id, id)
|
2024-08-12 22:32:01 +02:00
|
|
|
assertObjectDetails(t, tt.res.want, got)
|
2023-02-21 18:18:28 +01:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-03-13 17:34:29 +01:00
|
|
|
func TestCommandSide_UpdateInstanceGitLabIDP(t *testing.T) {
|
2023-02-21 18:18:28 +01:00
|
|
|
type fields struct {
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore func(*testing.T) *eventstore.Eventstore
|
2023-02-21 18:18:28 +01:00
|
|
|
secretCrypto crypto.EncryptionAlgorithm
|
|
|
|
}
|
|
|
|
type args struct {
|
|
|
|
ctx context.Context
|
|
|
|
id string
|
2023-03-13 17:34:29 +01:00
|
|
|
provider GitLabProvider
|
2023-02-21 18:18:28 +01:00
|
|
|
}
|
|
|
|
type res struct {
|
|
|
|
want *domain.ObjectDetails
|
|
|
|
err func(error) bool
|
|
|
|
}
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
fields fields
|
|
|
|
args args
|
|
|
|
res res
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
"invalid id",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-02-21 18:18:28 +01:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
2023-03-13 17:34:29 +01:00
|
|
|
provider: GitLabProvider{},
|
2023-02-21 18:18:28 +01:00
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-HJK91", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
2023-02-21 18:18:28 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid clientID",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-02-21 18:18:28 +01:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
id: "id1",
|
2023-03-13 17:34:29 +01:00
|
|
|
provider: GitLabProvider{},
|
2023-02-21 18:18:28 +01:00
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-D12t6", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
2023-02-21 18:18:28 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "not found",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-02-21 18:18:28 +01:00
|
|
|
expectFilter(),
|
|
|
|
),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
id: "id1",
|
2023-03-13 17:34:29 +01:00
|
|
|
provider: GitLabProvider{
|
2023-02-21 18:18:28 +01:00
|
|
|
ClientID: "clientID",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
2023-12-08 16:30:55 +02:00
|
|
|
err: zerrors.IsNotFound,
|
2023-02-21 18:18:28 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "no changes",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-02-21 18:18:28 +01:00
|
|
|
expectFilter(
|
|
|
|
eventFromEventPusher(
|
2023-03-13 17:34:29 +01:00
|
|
|
instance.NewGitLabIDPAddedEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
|
2023-02-21 18:18:28 +01:00
|
|
|
"id1",
|
|
|
|
"",
|
|
|
|
"clientID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("clientSecret"),
|
|
|
|
},
|
|
|
|
nil,
|
|
|
|
idp.Options{},
|
|
|
|
)),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
id: "id1",
|
2023-03-13 17:34:29 +01:00
|
|
|
provider: GitLabProvider{
|
2023-02-21 18:18:28 +01:00
|
|
|
ClientID: "clientID",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
2023-02-24 15:16:06 +01:00
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "instance1"},
|
2023-02-21 18:18:28 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "change ok",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-02-21 18:18:28 +01:00
|
|
|
expectFilter(
|
|
|
|
eventFromEventPusher(
|
2023-03-13 17:34:29 +01:00
|
|
|
instance.NewGitLabIDPAddedEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
|
2023-02-21 18:18:28 +01:00
|
|
|
"id1",
|
|
|
|
"",
|
|
|
|
"clientID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("clientSecret"),
|
|
|
|
},
|
|
|
|
nil,
|
|
|
|
idp.Options{},
|
|
|
|
)),
|
|
|
|
),
|
|
|
|
expectPush(
|
2023-10-19 12:19:10 +02:00
|
|
|
func() eventstore.Command {
|
|
|
|
t := true
|
|
|
|
event, _ := instance.NewGitLabIDPChangedEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
[]idp.GitLabIDPChanges{
|
|
|
|
idp.ChangeGitLabClientID("clientID2"),
|
|
|
|
idp.ChangeGitLabClientSecret(&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("newSecret"),
|
|
|
|
}),
|
|
|
|
idp.ChangeGitLabScopes([]string{"openid", "profile"}),
|
|
|
|
idp.ChangeGitLabOptions(idp.OptionChanges{
|
|
|
|
IsCreationAllowed: &t,
|
|
|
|
IsLinkingAllowed: &t,
|
|
|
|
IsAutoCreation: &t,
|
|
|
|
IsAutoUpdate: &t,
|
|
|
|
}),
|
|
|
|
},
|
|
|
|
)
|
|
|
|
return event
|
|
|
|
}(),
|
2023-02-21 18:18:28 +01:00
|
|
|
),
|
|
|
|
),
|
|
|
|
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
id: "id1",
|
2023-03-13 17:34:29 +01:00
|
|
|
provider: GitLabProvider{
|
2023-02-21 18:18:28 +01:00
|
|
|
ClientID: "clientID2",
|
|
|
|
ClientSecret: "newSecret",
|
|
|
|
Scopes: []string{"openid", "profile"},
|
|
|
|
IDPOptions: idp.Options{
|
|
|
|
IsCreationAllowed: true,
|
|
|
|
IsLinkingAllowed: true,
|
|
|
|
IsAutoCreation: true,
|
|
|
|
IsAutoUpdate: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "instance1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
c := &Commands{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: tt.fields.eventstore(t),
|
2023-02-21 18:18:28 +01:00
|
|
|
idpConfigEncryption: tt.fields.secretCrypto,
|
|
|
|
}
|
2023-03-13 17:34:29 +01:00
|
|
|
got, err := c.UpdateInstanceGitLabProvider(tt.args.ctx, tt.args.id, tt.args.provider)
|
2023-02-21 18:18:28 +01:00
|
|
|
if tt.res.err == nil {
|
|
|
|
assert.NoError(t, err)
|
|
|
|
}
|
|
|
|
if tt.res.err != nil && !tt.res.err(err) {
|
|
|
|
t.Errorf("got wrong err: %v ", err)
|
|
|
|
}
|
|
|
|
if tt.res.err == nil {
|
2024-08-12 22:32:01 +02:00
|
|
|
assertObjectDetails(t, tt.res.want, got)
|
2023-02-21 18:18:28 +01:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-03-13 17:34:29 +01:00
|
|
|
func TestCommandSide_AddInstanceGitLabSelfHostedIDP(t *testing.T) {
|
2023-02-15 09:14:59 +01:00
|
|
|
type fields struct {
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore func(*testing.T) *eventstore.Eventstore
|
2023-02-15 09:14:59 +01:00
|
|
|
idGenerator id.Generator
|
|
|
|
secretCrypto crypto.EncryptionAlgorithm
|
|
|
|
}
|
|
|
|
type args struct {
|
|
|
|
ctx context.Context
|
2023-03-13 17:34:29 +01:00
|
|
|
provider GitLabSelfHostedProvider
|
2023-02-15 09:14:59 +01:00
|
|
|
}
|
|
|
|
type res struct {
|
|
|
|
id string
|
|
|
|
want *domain.ObjectDetails
|
|
|
|
err func(error) bool
|
|
|
|
}
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
fields fields
|
|
|
|
args args
|
|
|
|
res res
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
"invalid name",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-02-15 09:14:59 +01:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
2023-03-13 17:34:29 +01:00
|
|
|
provider: GitLabSelfHostedProvider{},
|
2023-02-15 09:14:59 +01:00
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-jw4ZT", ""))
|
2023-02-15 09:14:59 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
2023-03-13 17:34:29 +01:00
|
|
|
"invalid issuer",
|
2023-02-15 09:14:59 +01:00
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-02-15 09:14:59 +01:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
2023-03-13 17:34:29 +01:00
|
|
|
provider: GitLabSelfHostedProvider{
|
2023-02-15 09:14:59 +01:00
|
|
|
Name: "name",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-AST4S", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
2023-02-15 09:14:59 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
2023-03-13 17:34:29 +01:00
|
|
|
"invalid clientID",
|
2023-02-15 09:14:59 +01:00
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-02-15 09:14:59 +01:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
2023-03-13 17:34:29 +01:00
|
|
|
provider: GitLabSelfHostedProvider{
|
2023-02-15 09:14:59 +01:00
|
|
|
Name: "name",
|
2023-03-13 17:34:29 +01:00
|
|
|
Issuer: "issuer",
|
2023-02-15 09:14:59 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-DBZHJ", ""))
|
2023-02-15 09:14:59 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
2023-03-13 17:34:29 +01:00
|
|
|
"invalid clientSecret",
|
2023-02-15 09:14:59 +01:00
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-02-15 09:14:59 +01:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
2023-03-13 17:34:29 +01:00
|
|
|
provider: GitLabSelfHostedProvider{
|
|
|
|
Name: "name",
|
|
|
|
Issuer: "issuer",
|
|
|
|
ClientID: "clientID",
|
2023-02-15 09:14:59 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-SDGJ4", ""))
|
2023-02-15 09:14:59 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "ok",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-02-15 09:14:59 +01:00
|
|
|
expectFilter(),
|
|
|
|
expectPush(
|
2023-10-19 12:19:10 +02:00
|
|
|
instance.NewGitLabSelfHostedIDPAddedEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"name",
|
|
|
|
"issuer",
|
|
|
|
"clientID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("clientSecret"),
|
|
|
|
},
|
|
|
|
nil,
|
|
|
|
idp.Options{},
|
|
|
|
),
|
2023-02-15 09:14:59 +01:00
|
|
|
),
|
|
|
|
),
|
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
2023-03-13 17:34:29 +01:00
|
|
|
provider: GitLabSelfHostedProvider{
|
|
|
|
Name: "name",
|
|
|
|
Issuer: "issuer",
|
|
|
|
ClientID: "clientID",
|
|
|
|
ClientSecret: "clientSecret",
|
2023-02-15 09:14:59 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
id: "id1",
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "instance1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "ok all set",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-02-15 09:14:59 +01:00
|
|
|
expectFilter(),
|
|
|
|
expectPush(
|
2023-10-19 12:19:10 +02:00
|
|
|
instance.NewGitLabSelfHostedIDPAddedEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"name",
|
|
|
|
"issuer",
|
|
|
|
"clientID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("clientSecret"),
|
|
|
|
},
|
|
|
|
[]string{"openid"},
|
|
|
|
idp.Options{
|
|
|
|
IsCreationAllowed: true,
|
|
|
|
IsLinkingAllowed: true,
|
|
|
|
IsAutoCreation: true,
|
|
|
|
IsAutoUpdate: true,
|
|
|
|
},
|
|
|
|
),
|
2023-02-15 09:14:59 +01:00
|
|
|
),
|
|
|
|
),
|
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
2023-03-13 17:34:29 +01:00
|
|
|
provider: GitLabSelfHostedProvider{
|
|
|
|
Name: "name",
|
|
|
|
Issuer: "issuer",
|
|
|
|
ClientID: "clientID",
|
|
|
|
ClientSecret: "clientSecret",
|
|
|
|
Scopes: []string{"openid"},
|
2023-02-15 09:14:59 +01:00
|
|
|
IDPOptions: idp.Options{
|
|
|
|
IsCreationAllowed: true,
|
|
|
|
IsLinkingAllowed: true,
|
|
|
|
IsAutoCreation: true,
|
|
|
|
IsAutoUpdate: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
id: "id1",
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "instance1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
c := &Commands{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: tt.fields.eventstore(t),
|
2023-02-15 09:14:59 +01:00
|
|
|
idGenerator: tt.fields.idGenerator,
|
|
|
|
idpConfigEncryption: tt.fields.secretCrypto,
|
|
|
|
}
|
2023-03-13 17:34:29 +01:00
|
|
|
id, got, err := c.AddInstanceGitLabSelfHostedProvider(tt.args.ctx, tt.args.provider)
|
2023-02-15 09:14:59 +01:00
|
|
|
if tt.res.err == nil {
|
|
|
|
assert.NoError(t, err)
|
|
|
|
}
|
|
|
|
if tt.res.err != nil && !tt.res.err(err) {
|
|
|
|
t.Errorf("got wrong err: %v ", err)
|
|
|
|
}
|
|
|
|
if tt.res.err == nil {
|
|
|
|
assert.Equal(t, tt.res.id, id)
|
2024-08-12 22:32:01 +02:00
|
|
|
assertObjectDetails(t, tt.res.want, got)
|
2023-02-15 09:14:59 +01:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-03-13 17:34:29 +01:00
|
|
|
func TestCommandSide_UpdateInstanceGitLabSelfHostedIDP(t *testing.T) {
|
2023-02-15 09:14:59 +01:00
|
|
|
type fields struct {
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore func(*testing.T) *eventstore.Eventstore
|
2023-02-15 09:14:59 +01:00
|
|
|
secretCrypto crypto.EncryptionAlgorithm
|
|
|
|
}
|
|
|
|
type args struct {
|
|
|
|
ctx context.Context
|
|
|
|
id string
|
2023-03-13 17:34:29 +01:00
|
|
|
provider GitLabSelfHostedProvider
|
2023-02-15 09:14:59 +01:00
|
|
|
}
|
|
|
|
type res struct {
|
|
|
|
want *domain.ObjectDetails
|
|
|
|
err func(error) bool
|
|
|
|
}
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
fields fields
|
|
|
|
args args
|
|
|
|
res res
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
"invalid id",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-02-15 09:14:59 +01:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
2023-03-13 17:34:29 +01:00
|
|
|
provider: GitLabSelfHostedProvider{},
|
2023-02-15 09:14:59 +01:00
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-SAFG4", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
2023-02-15 09:14:59 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid name",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-02-15 09:14:59 +01:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
id: "id1",
|
2023-03-13 17:34:29 +01:00
|
|
|
provider: GitLabSelfHostedProvider{},
|
2023-02-15 09:14:59 +01:00
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-DG4H", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
2023-02-15 09:14:59 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
2023-03-13 17:34:29 +01:00
|
|
|
"invalid issuer",
|
2023-02-15 09:14:59 +01:00
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-02-15 09:14:59 +01:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
id: "id1",
|
2023-03-13 17:34:29 +01:00
|
|
|
provider: GitLabSelfHostedProvider{
|
2023-02-15 09:14:59 +01:00
|
|
|
Name: "name",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-SD4eb", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
2023-02-15 09:14:59 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
2023-03-13 17:34:29 +01:00
|
|
|
"invalid clientID",
|
2023-02-15 09:14:59 +01:00
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-02-15 09:14:59 +01:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
id: "id1",
|
2023-03-13 17:34:29 +01:00
|
|
|
provider: GitLabSelfHostedProvider{
|
|
|
|
Name: "name",
|
|
|
|
Issuer: "issuer",
|
2023-02-15 09:14:59 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-GHWE3", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
2023-02-15 09:14:59 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
2023-03-13 17:34:29 +01:00
|
|
|
name: "not found",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-03-13 17:34:29 +01:00
|
|
|
expectFilter(),
|
|
|
|
),
|
2023-02-15 09:14:59 +01:00
|
|
|
},
|
2023-03-13 17:34:29 +01:00
|
|
|
args: args{
|
2023-02-15 09:14:59 +01:00
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
id: "id1",
|
2023-03-13 17:34:29 +01:00
|
|
|
provider: GitLabSelfHostedProvider{
|
|
|
|
Name: "name",
|
|
|
|
Issuer: "issuer",
|
|
|
|
ClientID: "clientID",
|
2023-02-15 09:14:59 +01:00
|
|
|
},
|
|
|
|
},
|
2023-03-13 17:34:29 +01:00
|
|
|
res: res{
|
2023-12-08 16:30:55 +02:00
|
|
|
err: zerrors.IsNotFound,
|
2023-02-15 09:14:59 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
2023-03-13 17:34:29 +01:00
|
|
|
name: "no changes",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-03-13 17:34:29 +01:00
|
|
|
expectFilter(
|
|
|
|
eventFromEventPusher(
|
|
|
|
instance.NewGitLabSelfHostedIDPAddedEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"name",
|
|
|
|
"issuer",
|
|
|
|
"clientID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("clientSecret"),
|
|
|
|
},
|
|
|
|
nil,
|
|
|
|
idp.Options{},
|
|
|
|
)),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
id: "id1",
|
|
|
|
provider: GitLabSelfHostedProvider{
|
|
|
|
Name: "name",
|
|
|
|
Issuer: "issuer",
|
|
|
|
ClientID: "clientID",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "instance1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "change ok",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-03-13 17:34:29 +01:00
|
|
|
expectFilter(
|
|
|
|
eventFromEventPusher(
|
|
|
|
instance.NewGitLabSelfHostedIDPAddedEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"name",
|
|
|
|
"issuer",
|
|
|
|
"clientID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("clientSecret"),
|
|
|
|
},
|
|
|
|
nil,
|
|
|
|
idp.Options{},
|
|
|
|
)),
|
|
|
|
),
|
|
|
|
expectPush(
|
2023-10-19 12:19:10 +02:00
|
|
|
func() eventstore.Command {
|
|
|
|
t := true
|
|
|
|
event, _ := instance.NewGitLabSelfHostedIDPChangedEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
[]idp.GitLabSelfHostedIDPChanges{
|
|
|
|
idp.ChangeGitLabSelfHostedClientID("clientID2"),
|
|
|
|
idp.ChangeGitLabSelfHostedIssuer("newIssuer"),
|
|
|
|
idp.ChangeGitLabSelfHostedName("newName"),
|
|
|
|
idp.ChangeGitLabSelfHostedClientSecret(&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("newSecret"),
|
|
|
|
}),
|
|
|
|
idp.ChangeGitLabSelfHostedScopes([]string{"openid", "profile"}),
|
|
|
|
idp.ChangeGitLabSelfHostedOptions(idp.OptionChanges{
|
|
|
|
IsCreationAllowed: &t,
|
|
|
|
IsLinkingAllowed: &t,
|
|
|
|
IsAutoCreation: &t,
|
|
|
|
IsAutoUpdate: &t,
|
|
|
|
}),
|
|
|
|
},
|
|
|
|
)
|
|
|
|
return event
|
|
|
|
}(),
|
2023-03-13 17:34:29 +01:00
|
|
|
),
|
|
|
|
),
|
|
|
|
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
id: "id1",
|
|
|
|
provider: GitLabSelfHostedProvider{
|
|
|
|
Issuer: "newIssuer",
|
|
|
|
Name: "newName",
|
|
|
|
ClientID: "clientID2",
|
|
|
|
ClientSecret: "newSecret",
|
|
|
|
Scopes: []string{"openid", "profile"},
|
|
|
|
IDPOptions: idp.Options{
|
|
|
|
IsCreationAllowed: true,
|
|
|
|
IsLinkingAllowed: true,
|
|
|
|
IsAutoCreation: true,
|
|
|
|
IsAutoUpdate: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "instance1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
c := &Commands{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: tt.fields.eventstore(t),
|
2023-03-13 17:34:29 +01:00
|
|
|
idpConfigEncryption: tt.fields.secretCrypto,
|
|
|
|
}
|
|
|
|
got, err := c.UpdateInstanceGitLabSelfHostedProvider(tt.args.ctx, tt.args.id, tt.args.provider)
|
|
|
|
if tt.res.err == nil {
|
|
|
|
assert.NoError(t, err)
|
|
|
|
}
|
|
|
|
if tt.res.err != nil && !tt.res.err(err) {
|
|
|
|
t.Errorf("got wrong err: %v ", err)
|
|
|
|
}
|
|
|
|
if tt.res.err == nil {
|
2024-08-12 22:32:01 +02:00
|
|
|
assertObjectDetails(t, tt.res.want, got)
|
2023-03-13 17:34:29 +01:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCommandSide_AddInstanceGoogleIDP(t *testing.T) {
|
|
|
|
type fields struct {
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore func(*testing.T) *eventstore.Eventstore
|
2023-03-13 17:34:29 +01:00
|
|
|
idGenerator id.Generator
|
|
|
|
secretCrypto crypto.EncryptionAlgorithm
|
|
|
|
}
|
|
|
|
type args struct {
|
|
|
|
ctx context.Context
|
|
|
|
provider GoogleProvider
|
|
|
|
}
|
|
|
|
type res struct {
|
|
|
|
id string
|
|
|
|
want *domain.ObjectDetails
|
|
|
|
err func(error) bool
|
|
|
|
}
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
fields fields
|
|
|
|
args args
|
|
|
|
res res
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
"invalid clientID",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-13 17:34:29 +01:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
provider: GoogleProvider{},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-D3fvs", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid clientSecret",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-13 17:34:29 +01:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
provider: GoogleProvider{
|
|
|
|
ClientID: "clientID",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-W2vqs", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "ok",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-03-13 17:34:29 +01:00
|
|
|
expectFilter(),
|
|
|
|
expectPush(
|
2023-10-19 12:19:10 +02:00
|
|
|
instance.NewGoogleIDPAddedEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"",
|
|
|
|
"clientID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("clientSecret"),
|
|
|
|
},
|
|
|
|
nil,
|
|
|
|
idp.Options{},
|
|
|
|
),
|
2023-03-13 17:34:29 +01:00
|
|
|
),
|
|
|
|
),
|
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
provider: GoogleProvider{
|
|
|
|
ClientID: "clientID",
|
|
|
|
ClientSecret: "clientSecret",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
id: "id1",
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "instance1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "ok all set",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-03-13 17:34:29 +01:00
|
|
|
expectFilter(),
|
|
|
|
expectPush(
|
2023-10-19 12:19:10 +02:00
|
|
|
instance.NewGoogleIDPAddedEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"",
|
|
|
|
"clientID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("clientSecret"),
|
|
|
|
},
|
|
|
|
[]string{"openid"},
|
|
|
|
idp.Options{
|
|
|
|
IsCreationAllowed: true,
|
|
|
|
IsLinkingAllowed: true,
|
|
|
|
IsAutoCreation: true,
|
|
|
|
IsAutoUpdate: true,
|
|
|
|
},
|
|
|
|
),
|
2023-03-13 17:34:29 +01:00
|
|
|
),
|
|
|
|
),
|
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
provider: GoogleProvider{
|
|
|
|
ClientID: "clientID",
|
|
|
|
ClientSecret: "clientSecret",
|
|
|
|
Scopes: []string{"openid"},
|
|
|
|
IDPOptions: idp.Options{
|
|
|
|
IsCreationAllowed: true,
|
|
|
|
IsLinkingAllowed: true,
|
|
|
|
IsAutoCreation: true,
|
|
|
|
IsAutoUpdate: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
id: "id1",
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "instance1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
c := &Commands{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: tt.fields.eventstore(t),
|
2023-03-13 17:34:29 +01:00
|
|
|
idGenerator: tt.fields.idGenerator,
|
|
|
|
idpConfigEncryption: tt.fields.secretCrypto,
|
|
|
|
}
|
|
|
|
id, got, err := c.AddInstanceGoogleProvider(tt.args.ctx, tt.args.provider)
|
|
|
|
if tt.res.err == nil {
|
|
|
|
assert.NoError(t, err)
|
|
|
|
}
|
|
|
|
if tt.res.err != nil && !tt.res.err(err) {
|
|
|
|
t.Errorf("got wrong err: %v ", err)
|
|
|
|
}
|
|
|
|
if tt.res.err == nil {
|
|
|
|
assert.Equal(t, tt.res.id, id)
|
2024-08-12 22:32:01 +02:00
|
|
|
assertObjectDetails(t, tt.res.want, got)
|
2023-03-13 17:34:29 +01:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCommandSide_UpdateInstanceGoogleIDP(t *testing.T) {
|
|
|
|
type fields struct {
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore func(*testing.T) *eventstore.Eventstore
|
2023-03-13 17:34:29 +01:00
|
|
|
secretCrypto crypto.EncryptionAlgorithm
|
|
|
|
}
|
|
|
|
type args struct {
|
|
|
|
ctx context.Context
|
|
|
|
id string
|
|
|
|
provider GoogleProvider
|
|
|
|
}
|
|
|
|
type res struct {
|
|
|
|
want *domain.ObjectDetails
|
|
|
|
err func(error) bool
|
|
|
|
}
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
fields fields
|
|
|
|
args args
|
|
|
|
res res
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
"invalid id",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
provider: GoogleProvider{},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-S32t1", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid clientID",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
id: "id1",
|
|
|
|
provider: GoogleProvider{},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-ds432", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "not found",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-03-13 17:34:29 +01:00
|
|
|
expectFilter(),
|
|
|
|
),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
id: "id1",
|
|
|
|
provider: GoogleProvider{
|
|
|
|
ClientID: "clientID",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
2023-12-08 16:30:55 +02:00
|
|
|
err: zerrors.IsNotFound,
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "no changes",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-03-13 17:34:29 +01:00
|
|
|
expectFilter(
|
|
|
|
eventFromEventPusher(
|
|
|
|
instance.NewGoogleIDPAddedEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"",
|
|
|
|
"clientID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("clientSecret"),
|
|
|
|
},
|
|
|
|
nil,
|
|
|
|
idp.Options{},
|
|
|
|
)),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
id: "id1",
|
|
|
|
provider: GoogleProvider{
|
|
|
|
ClientID: "clientID",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "instance1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "change ok",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-03-13 17:34:29 +01:00
|
|
|
expectFilter(
|
|
|
|
eventFromEventPusher(
|
|
|
|
instance.NewGoogleIDPAddedEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"",
|
|
|
|
"clientID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("clientSecret"),
|
|
|
|
},
|
|
|
|
nil,
|
|
|
|
idp.Options{},
|
|
|
|
)),
|
|
|
|
),
|
|
|
|
expectPush(
|
2023-10-19 12:19:10 +02:00
|
|
|
func() eventstore.Command {
|
|
|
|
t := true
|
|
|
|
event, _ := instance.NewGoogleIDPChangedEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
[]idp.GoogleIDPChanges{
|
|
|
|
idp.ChangeGoogleClientID("clientID2"),
|
|
|
|
idp.ChangeGoogleClientSecret(&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("newSecret"),
|
|
|
|
}),
|
|
|
|
idp.ChangeGoogleScopes([]string{"openid", "profile"}),
|
|
|
|
idp.ChangeGoogleOptions(idp.OptionChanges{
|
|
|
|
IsCreationAllowed: &t,
|
|
|
|
IsLinkingAllowed: &t,
|
|
|
|
IsAutoCreation: &t,
|
|
|
|
IsAutoUpdate: &t,
|
|
|
|
}),
|
|
|
|
},
|
|
|
|
)
|
|
|
|
return event
|
|
|
|
}(),
|
2023-03-13 17:34:29 +01:00
|
|
|
),
|
|
|
|
),
|
|
|
|
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
id: "id1",
|
|
|
|
provider: GoogleProvider{
|
|
|
|
ClientID: "clientID2",
|
|
|
|
ClientSecret: "newSecret",
|
|
|
|
Scopes: []string{"openid", "profile"},
|
|
|
|
IDPOptions: idp.Options{
|
|
|
|
IsCreationAllowed: true,
|
|
|
|
IsLinkingAllowed: true,
|
|
|
|
IsAutoCreation: true,
|
|
|
|
IsAutoUpdate: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "instance1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
c := &Commands{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: tt.fields.eventstore(t),
|
2023-03-13 17:34:29 +01:00
|
|
|
idpConfigEncryption: tt.fields.secretCrypto,
|
|
|
|
}
|
|
|
|
got, err := c.UpdateInstanceGoogleProvider(tt.args.ctx, tt.args.id, tt.args.provider)
|
|
|
|
if tt.res.err == nil {
|
|
|
|
assert.NoError(t, err)
|
|
|
|
}
|
|
|
|
if tt.res.err != nil && !tt.res.err(err) {
|
|
|
|
t.Errorf("got wrong err: %v ", err)
|
|
|
|
}
|
|
|
|
if tt.res.err == nil {
|
2024-08-12 22:32:01 +02:00
|
|
|
assertObjectDetails(t, tt.res.want, got)
|
2023-03-13 17:34:29 +01:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCommandSide_AddInstanceLDAPIDP(t *testing.T) {
|
|
|
|
type fields struct {
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore func(*testing.T) *eventstore.Eventstore
|
2023-03-13 17:34:29 +01:00
|
|
|
idGenerator id.Generator
|
|
|
|
secretCrypto crypto.EncryptionAlgorithm
|
|
|
|
}
|
|
|
|
type args struct {
|
|
|
|
ctx context.Context
|
|
|
|
provider LDAPProvider
|
|
|
|
}
|
|
|
|
type res struct {
|
|
|
|
id string
|
|
|
|
want *domain.ObjectDetails
|
|
|
|
err func(error) bool
|
|
|
|
}
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
fields fields
|
|
|
|
args args
|
|
|
|
res res
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
"invalid name",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-13 17:34:29 +01:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
provider: LDAPProvider{},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-SAfdd", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
2023-03-24 16:18:56 +01:00
|
|
|
"invalid baseDN",
|
2023-03-13 17:34:29 +01:00
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-13 17:34:29 +01:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
provider: LDAPProvider{
|
|
|
|
Name: "name",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-sv31s", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
2023-03-24 16:18:56 +01:00
|
|
|
"invalid bindDN",
|
2023-03-13 17:34:29 +01:00
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-13 17:34:29 +01:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
provider: LDAPProvider{
|
2023-03-24 16:18:56 +01:00
|
|
|
Name: "name",
|
|
|
|
BaseDN: "baseDN",
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-sdgf4", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
2023-03-24 16:18:56 +01:00
|
|
|
"invalid bindPassword",
|
2023-03-13 17:34:29 +01:00
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-13 17:34:29 +01:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
provider: LDAPProvider{
|
|
|
|
Name: "name",
|
2023-03-24 16:18:56 +01:00
|
|
|
BindDN: "binddn",
|
2023-03-13 17:34:29 +01:00
|
|
|
BaseDN: "baseDN",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-AEG2w", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
2023-03-24 16:18:56 +01:00
|
|
|
"invalid userBase",
|
2023-03-13 17:34:29 +01:00
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-13 17:34:29 +01:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
provider: LDAPProvider{
|
2023-03-24 16:18:56 +01:00
|
|
|
Name: "name",
|
|
|
|
BindDN: "binddn",
|
|
|
|
BaseDN: "baseDN",
|
|
|
|
BindPassword: "password",
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-SAD5n", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
2023-03-24 16:18:56 +01:00
|
|
|
"invalid servers",
|
2023-03-13 17:34:29 +01:00
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-13 17:34:29 +01:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
provider: LDAPProvider{
|
2023-03-24 16:18:56 +01:00
|
|
|
Name: "name",
|
|
|
|
BindDN: "binddn",
|
|
|
|
BaseDN: "baseDN",
|
|
|
|
BindPassword: "password",
|
|
|
|
UserBase: "user",
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-SAx905n", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
2023-03-24 16:18:56 +01:00
|
|
|
"invalid userObjectClasses",
|
2023-03-13 17:34:29 +01:00
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-13 17:34:29 +01:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
provider: LDAPProvider{
|
2023-03-24 16:18:56 +01:00
|
|
|
Name: "name",
|
|
|
|
Servers: []string{"server"},
|
|
|
|
BindDN: "binddn",
|
|
|
|
BaseDN: "baseDN",
|
|
|
|
BindPassword: "password",
|
|
|
|
UserBase: "user",
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-S1x905n", ""))
|
2023-03-24 16:18:56 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid userFilters",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-24 16:18:56 +01:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
provider: LDAPProvider{
|
|
|
|
Name: "name",
|
|
|
|
Servers: []string{"server"},
|
|
|
|
BindDN: "binddn",
|
|
|
|
BaseDN: "baseDN",
|
|
|
|
BindPassword: "password",
|
|
|
|
UserBase: "user",
|
|
|
|
UserObjectClasses: []string{"object"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-aAx905n", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2025-03-18 15:23:12 +00:00
|
|
|
{
|
|
|
|
"invalid rootCA",
|
|
|
|
fields{
|
|
|
|
eventstore: expectEventstore(),
|
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
provider: LDAPProvider{
|
|
|
|
Name: "name",
|
|
|
|
Servers: []string{"server"},
|
|
|
|
StartTLS: false,
|
|
|
|
BaseDN: "baseDN",
|
|
|
|
BindDN: "dn",
|
|
|
|
BindPassword: "password",
|
|
|
|
UserBase: "user",
|
|
|
|
UserObjectClasses: []string{"object"},
|
|
|
|
UserFilters: []string{"filter"},
|
|
|
|
Timeout: time.Second * 30,
|
|
|
|
RootCA: []byte("certificate"),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-cwqVVdBwKt", "Errors.Invalid.Argument"))
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2023-03-13 17:34:29 +01:00
|
|
|
{
|
|
|
|
name: "ok",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-03-13 17:34:29 +01:00
|
|
|
expectFilter(),
|
|
|
|
expectPush(
|
2023-10-19 12:19:10 +02:00
|
|
|
instance.NewLDAPIDPAddedEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"name",
|
|
|
|
[]string{"server"},
|
|
|
|
false,
|
|
|
|
"baseDN",
|
|
|
|
"dn",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("password"),
|
|
|
|
},
|
|
|
|
"user",
|
|
|
|
[]string{"object"},
|
|
|
|
[]string{"filter"},
|
|
|
|
time.Second*30,
|
2025-03-18 15:23:12 +00:00
|
|
|
nil,
|
2023-10-19 12:19:10 +02:00
|
|
|
idp.LDAPAttributes{},
|
|
|
|
idp.Options{},
|
|
|
|
),
|
2023-03-13 17:34:29 +01:00
|
|
|
),
|
|
|
|
),
|
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
provider: LDAPProvider{
|
2023-03-24 16:18:56 +01:00
|
|
|
Name: "name",
|
|
|
|
Servers: []string{"server"},
|
|
|
|
StartTLS: false,
|
|
|
|
BaseDN: "baseDN",
|
|
|
|
BindDN: "dn",
|
|
|
|
BindPassword: "password",
|
|
|
|
UserBase: "user",
|
|
|
|
UserObjectClasses: []string{"object"},
|
|
|
|
UserFilters: []string{"filter"},
|
|
|
|
Timeout: time.Second * 30,
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
id: "id1",
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "instance1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "ok all set",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-03-13 17:34:29 +01:00
|
|
|
expectFilter(),
|
|
|
|
expectPush(
|
2023-10-19 12:19:10 +02:00
|
|
|
instance.NewLDAPIDPAddedEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"name",
|
|
|
|
[]string{"server"},
|
|
|
|
false,
|
|
|
|
"baseDN",
|
|
|
|
"dn",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("password"),
|
|
|
|
},
|
|
|
|
"user",
|
|
|
|
[]string{"object"},
|
|
|
|
[]string{"filter"},
|
|
|
|
time.Second*30,
|
2025-03-18 15:23:12 +00:00
|
|
|
validLDAPRootCA,
|
2023-10-19 12:19:10 +02:00
|
|
|
idp.LDAPAttributes{
|
|
|
|
IDAttribute: "id",
|
|
|
|
FirstNameAttribute: "firstName",
|
|
|
|
LastNameAttribute: "lastName",
|
|
|
|
DisplayNameAttribute: "displayName",
|
|
|
|
NickNameAttribute: "nickName",
|
|
|
|
PreferredUsernameAttribute: "preferredUsername",
|
|
|
|
EmailAttribute: "email",
|
|
|
|
EmailVerifiedAttribute: "emailVerified",
|
|
|
|
PhoneAttribute: "phone",
|
|
|
|
PhoneVerifiedAttribute: "phoneVerified",
|
|
|
|
PreferredLanguageAttribute: "preferredLanguage",
|
|
|
|
AvatarURLAttribute: "avatarURL",
|
|
|
|
ProfileAttribute: "profile",
|
|
|
|
},
|
|
|
|
idp.Options{
|
|
|
|
IsCreationAllowed: true,
|
|
|
|
IsLinkingAllowed: true,
|
|
|
|
IsAutoCreation: true,
|
|
|
|
IsAutoUpdate: true,
|
|
|
|
},
|
|
|
|
),
|
2023-03-13 17:34:29 +01:00
|
|
|
),
|
|
|
|
),
|
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
provider: LDAPProvider{
|
2023-03-24 16:18:56 +01:00
|
|
|
Name: "name",
|
|
|
|
Servers: []string{"server"},
|
|
|
|
StartTLS: false,
|
|
|
|
BaseDN: "baseDN",
|
|
|
|
BindDN: "dn",
|
|
|
|
BindPassword: "password",
|
|
|
|
UserBase: "user",
|
|
|
|
UserObjectClasses: []string{"object"},
|
|
|
|
UserFilters: []string{"filter"},
|
|
|
|
Timeout: time.Second * 30,
|
2025-03-18 15:23:12 +00:00
|
|
|
RootCA: validLDAPRootCA,
|
2023-03-13 17:34:29 +01:00
|
|
|
LDAPAttributes: idp.LDAPAttributes{
|
|
|
|
IDAttribute: "id",
|
|
|
|
FirstNameAttribute: "firstName",
|
|
|
|
LastNameAttribute: "lastName",
|
|
|
|
DisplayNameAttribute: "displayName",
|
|
|
|
NickNameAttribute: "nickName",
|
|
|
|
PreferredUsernameAttribute: "preferredUsername",
|
|
|
|
EmailAttribute: "email",
|
|
|
|
EmailVerifiedAttribute: "emailVerified",
|
|
|
|
PhoneAttribute: "phone",
|
|
|
|
PhoneVerifiedAttribute: "phoneVerified",
|
|
|
|
PreferredLanguageAttribute: "preferredLanguage",
|
|
|
|
AvatarURLAttribute: "avatarURL",
|
|
|
|
ProfileAttribute: "profile",
|
|
|
|
},
|
|
|
|
IDPOptions: idp.Options{
|
|
|
|
IsCreationAllowed: true,
|
|
|
|
IsLinkingAllowed: true,
|
|
|
|
IsAutoCreation: true,
|
|
|
|
IsAutoUpdate: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
id: "id1",
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "instance1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
c := &Commands{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: tt.fields.eventstore(t),
|
2023-03-13 17:34:29 +01:00
|
|
|
idGenerator: tt.fields.idGenerator,
|
|
|
|
idpConfigEncryption: tt.fields.secretCrypto,
|
|
|
|
}
|
|
|
|
id, got, err := c.AddInstanceLDAPProvider(tt.args.ctx, tt.args.provider)
|
|
|
|
if tt.res.err == nil {
|
|
|
|
assert.NoError(t, err)
|
|
|
|
}
|
|
|
|
if tt.res.err != nil && !tt.res.err(err) {
|
|
|
|
t.Errorf("got wrong err: %v ", err)
|
|
|
|
}
|
|
|
|
if tt.res.err == nil {
|
|
|
|
assert.Equal(t, tt.res.id, id)
|
2024-08-12 22:32:01 +02:00
|
|
|
assertObjectDetails(t, tt.res.want, got)
|
2023-03-13 17:34:29 +01:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCommandSide_UpdateInstanceLDAPIDP(t *testing.T) {
|
|
|
|
type fields struct {
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore func(*testing.T) *eventstore.Eventstore
|
2023-03-13 17:34:29 +01:00
|
|
|
secretCrypto crypto.EncryptionAlgorithm
|
|
|
|
}
|
|
|
|
type args struct {
|
|
|
|
ctx context.Context
|
|
|
|
id string
|
|
|
|
provider LDAPProvider
|
|
|
|
}
|
|
|
|
type res struct {
|
|
|
|
want *domain.ObjectDetails
|
|
|
|
err func(error) bool
|
|
|
|
}
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
fields fields
|
|
|
|
args args
|
|
|
|
res res
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
"invalid id",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
provider: LDAPProvider{},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-Dgdbs", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid name",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
id: "id1",
|
|
|
|
provider: LDAPProvider{},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-Sffgd", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
2023-03-24 16:18:56 +01:00
|
|
|
"invalid baseDN",
|
2023-03-13 17:34:29 +01:00
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
id: "id1",
|
|
|
|
provider: LDAPProvider{
|
|
|
|
Name: "name",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-vb3ss", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
2023-03-24 16:18:56 +01:00
|
|
|
"invalid bindDN",
|
2023-03-13 17:34:29 +01:00
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
id: "id1",
|
|
|
|
provider: LDAPProvider{
|
2023-03-24 16:18:56 +01:00
|
|
|
Name: "name",
|
|
|
|
BaseDN: "baseDN",
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-hbere", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
2023-03-24 16:18:56 +01:00
|
|
|
"invalid userbase",
|
2023-03-13 17:34:29 +01:00
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
id: "id1",
|
|
|
|
provider: LDAPProvider{
|
|
|
|
Name: "name",
|
|
|
|
BaseDN: "baseDN",
|
2023-03-24 16:18:56 +01:00
|
|
|
BindDN: "bindDN",
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-DG45z", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
2023-03-24 16:18:56 +01:00
|
|
|
"invalid servers",
|
2023-02-15 09:14:59 +01:00
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-02-15 09:14:59 +01:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
id: "id1",
|
|
|
|
provider: LDAPProvider{
|
2023-03-24 16:18:56 +01:00
|
|
|
Name: "name",
|
|
|
|
BaseDN: "baseDN",
|
|
|
|
BindDN: "bindDN",
|
|
|
|
UserBase: "user",
|
2023-02-15 09:14:59 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-SAx945n", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
2023-02-15 09:14:59 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
2023-03-24 16:18:56 +01:00
|
|
|
"invalid userObjectClasses",
|
2023-02-15 09:14:59 +01:00
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-02-15 09:14:59 +01:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
id: "id1",
|
|
|
|
provider: LDAPProvider{
|
2023-03-24 16:18:56 +01:00
|
|
|
Name: "name",
|
|
|
|
Servers: []string{"server"},
|
|
|
|
BaseDN: "baseDN",
|
|
|
|
BindDN: "bindDN",
|
|
|
|
UserBase: "user",
|
2023-02-15 09:14:59 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-S1x605n", ""))
|
2023-03-24 16:18:56 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid userFilters",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-24 16:18:56 +01:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
id: "id1",
|
|
|
|
provider: LDAPProvider{
|
|
|
|
Name: "name",
|
|
|
|
Servers: []string{"server"},
|
|
|
|
BaseDN: "baseDN",
|
|
|
|
BindDN: "bindDN",
|
|
|
|
UserBase: "user",
|
|
|
|
UserObjectClasses: []string{"object"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-aAx901n", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
2023-02-15 09:14:59 +01:00
|
|
|
},
|
|
|
|
},
|
2025-03-18 15:23:12 +00:00
|
|
|
{
|
|
|
|
"invalid rootCA",
|
|
|
|
fields{
|
|
|
|
eventstore: expectEventstore(),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
id: "id1",
|
|
|
|
provider: LDAPProvider{
|
|
|
|
Name: "name",
|
|
|
|
Servers: []string{"server"},
|
|
|
|
BaseDN: "baseDN",
|
|
|
|
BindDN: "binddn",
|
|
|
|
BindPassword: "password",
|
|
|
|
UserBase: "user",
|
|
|
|
UserObjectClasses: []string{"object"},
|
|
|
|
UserFilters: []string{"filter"},
|
|
|
|
RootCA: []byte("certificate"),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-cwqVVdBwKt", "Errors.Invalid.Argument"))
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2023-02-15 09:14:59 +01:00
|
|
|
{
|
|
|
|
name: "not found",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-02-15 09:14:59 +01:00
|
|
|
expectFilter(),
|
|
|
|
),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
id: "id1",
|
|
|
|
provider: LDAPProvider{
|
2023-03-24 16:18:56 +01:00
|
|
|
Name: "name",
|
|
|
|
Servers: []string{"server"},
|
|
|
|
BaseDN: "baseDN",
|
|
|
|
BindDN: "binddn",
|
|
|
|
BindPassword: "password",
|
|
|
|
UserBase: "user",
|
|
|
|
UserObjectClasses: []string{"object"},
|
|
|
|
UserFilters: []string{"filter"},
|
2023-02-15 09:14:59 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
2023-03-24 16:18:56 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowNotFound(nil, "INST-ASF3F", ""))
|
2023-03-24 16:18:56 +01:00
|
|
|
},
|
2023-02-15 09:14:59 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "no changes",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-02-15 09:14:59 +01:00
|
|
|
expectFilter(
|
|
|
|
eventFromEventPusher(
|
|
|
|
instance.NewLDAPIDPAddedEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"name",
|
2023-03-24 16:18:56 +01:00
|
|
|
[]string{"server"},
|
2023-02-15 09:14:59 +01:00
|
|
|
false,
|
2023-03-24 16:18:56 +01:00
|
|
|
"basedn",
|
|
|
|
"binddn",
|
2023-02-15 09:14:59 +01:00
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("password"),
|
|
|
|
},
|
2023-03-24 16:18:56 +01:00
|
|
|
"user",
|
|
|
|
[]string{"object"},
|
|
|
|
[]string{"filter"},
|
|
|
|
time.Second*30,
|
2025-03-18 15:23:12 +00:00
|
|
|
validLDAPRootCA,
|
2023-02-15 09:14:59 +01:00
|
|
|
idp.LDAPAttributes{},
|
|
|
|
idp.Options{},
|
|
|
|
)),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
id: "id1",
|
|
|
|
provider: LDAPProvider{
|
2023-03-24 16:18:56 +01:00
|
|
|
Name: "name",
|
|
|
|
Servers: []string{"server"},
|
|
|
|
StartTLS: false,
|
|
|
|
BaseDN: "basedn",
|
|
|
|
BindDN: "binddn",
|
|
|
|
UserBase: "user",
|
|
|
|
UserObjectClasses: []string{"object"},
|
|
|
|
UserFilters: []string{"filter"},
|
|
|
|
Timeout: time.Second * 30,
|
2025-03-18 15:23:12 +00:00
|
|
|
RootCA: validLDAPRootCA,
|
2023-02-15 09:14:59 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
2023-02-24 15:16:06 +01:00
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "instance1"},
|
2023-02-15 09:14:59 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "change ok",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-02-15 09:14:59 +01:00
|
|
|
expectFilter(
|
|
|
|
eventFromEventPusher(
|
|
|
|
instance.NewLDAPIDPAddedEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"name",
|
2023-03-24 16:18:56 +01:00
|
|
|
[]string{"server"},
|
2023-02-15 09:14:59 +01:00
|
|
|
false,
|
2023-03-24 16:18:56 +01:00
|
|
|
"basedn",
|
|
|
|
"binddn",
|
2023-02-15 09:14:59 +01:00
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("password"),
|
|
|
|
},
|
2023-03-24 16:18:56 +01:00
|
|
|
"user",
|
|
|
|
[]string{"object"},
|
|
|
|
[]string{"filter"},
|
|
|
|
time.Second*30,
|
2025-03-18 15:23:12 +00:00
|
|
|
nil,
|
2023-02-15 09:14:59 +01:00
|
|
|
idp.LDAPAttributes{},
|
|
|
|
idp.Options{},
|
|
|
|
)),
|
|
|
|
),
|
|
|
|
expectPush(
|
2023-10-19 12:19:10 +02:00
|
|
|
func() eventstore.Command {
|
|
|
|
t := true
|
|
|
|
event, _ := instance.NewLDAPIDPChangedEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
[]idp.LDAPIDPChanges{
|
|
|
|
idp.ChangeLDAPName("new name"),
|
|
|
|
idp.ChangeLDAPServers([]string{"new server"}),
|
|
|
|
idp.ChangeLDAPStartTLS(true),
|
|
|
|
idp.ChangeLDAPBaseDN("new basedn"),
|
|
|
|
idp.ChangeLDAPBindDN("new binddn"),
|
|
|
|
idp.ChangeLDAPBindPassword(&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("new password"),
|
|
|
|
}),
|
|
|
|
idp.ChangeLDAPUserBase("new user"),
|
|
|
|
idp.ChangeLDAPUserObjectClasses([]string{"new object"}),
|
|
|
|
idp.ChangeLDAPUserFilters([]string{"new filter"}),
|
|
|
|
idp.ChangeLDAPTimeout(time.Second * 20),
|
|
|
|
idp.ChangeLDAPAttributes(idp.LDAPAttributeChanges{
|
|
|
|
IDAttribute: stringPointer("new id"),
|
|
|
|
FirstNameAttribute: stringPointer("new firstName"),
|
|
|
|
LastNameAttribute: stringPointer("new lastName"),
|
|
|
|
DisplayNameAttribute: stringPointer("new displayName"),
|
|
|
|
NickNameAttribute: stringPointer("new nickName"),
|
|
|
|
PreferredUsernameAttribute: stringPointer("new preferredUsername"),
|
|
|
|
EmailAttribute: stringPointer("new email"),
|
|
|
|
EmailVerifiedAttribute: stringPointer("new emailVerified"),
|
|
|
|
PhoneAttribute: stringPointer("new phone"),
|
|
|
|
PhoneVerifiedAttribute: stringPointer("new phoneVerified"),
|
|
|
|
PreferredLanguageAttribute: stringPointer("new preferredLanguage"),
|
|
|
|
AvatarURLAttribute: stringPointer("new avatarURL"),
|
|
|
|
ProfileAttribute: stringPointer("new profile"),
|
|
|
|
}),
|
|
|
|
idp.ChangeLDAPOptions(idp.OptionChanges{
|
|
|
|
IsCreationAllowed: &t,
|
|
|
|
IsLinkingAllowed: &t,
|
|
|
|
IsAutoCreation: &t,
|
|
|
|
IsAutoUpdate: &t,
|
|
|
|
}),
|
2025-03-18 15:23:12 +00:00
|
|
|
idp.ChangeLDAPRootCA(validLDAPRootCA),
|
2023-10-19 12:19:10 +02:00
|
|
|
},
|
|
|
|
)
|
|
|
|
return event
|
|
|
|
}(),
|
2023-02-15 09:14:59 +01:00
|
|
|
),
|
|
|
|
),
|
|
|
|
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
id: "id1",
|
|
|
|
provider: LDAPProvider{
|
2023-03-24 16:18:56 +01:00
|
|
|
Name: "new name",
|
|
|
|
Servers: []string{"new server"},
|
|
|
|
StartTLS: true,
|
|
|
|
BaseDN: "new basedn",
|
|
|
|
BindDN: "new binddn",
|
|
|
|
BindPassword: "new password",
|
|
|
|
UserBase: "new user",
|
|
|
|
UserObjectClasses: []string{"new object"},
|
|
|
|
UserFilters: []string{"new filter"},
|
|
|
|
Timeout: time.Second * 20,
|
2025-03-18 15:23:12 +00:00
|
|
|
RootCA: validLDAPRootCA,
|
2023-02-15 09:14:59 +01:00
|
|
|
LDAPAttributes: idp.LDAPAttributes{
|
|
|
|
IDAttribute: "new id",
|
|
|
|
FirstNameAttribute: "new firstName",
|
|
|
|
LastNameAttribute: "new lastName",
|
|
|
|
DisplayNameAttribute: "new displayName",
|
|
|
|
NickNameAttribute: "new nickName",
|
|
|
|
PreferredUsernameAttribute: "new preferredUsername",
|
|
|
|
EmailAttribute: "new email",
|
|
|
|
EmailVerifiedAttribute: "new emailVerified",
|
|
|
|
PhoneAttribute: "new phone",
|
|
|
|
PhoneVerifiedAttribute: "new phoneVerified",
|
|
|
|
PreferredLanguageAttribute: "new preferredLanguage",
|
|
|
|
AvatarURLAttribute: "new avatarURL",
|
|
|
|
ProfileAttribute: "new profile",
|
|
|
|
},
|
|
|
|
IDPOptions: idp.Options{
|
|
|
|
IsCreationAllowed: true,
|
|
|
|
IsLinkingAllowed: true,
|
|
|
|
IsAutoCreation: true,
|
|
|
|
IsAutoUpdate: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "instance1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
c := &Commands{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: tt.fields.eventstore(t),
|
2023-02-15 09:14:59 +01:00
|
|
|
idpConfigEncryption: tt.fields.secretCrypto,
|
|
|
|
}
|
|
|
|
got, err := c.UpdateInstanceLDAPProvider(tt.args.ctx, tt.args.id, tt.args.provider)
|
|
|
|
if tt.res.err == nil {
|
|
|
|
assert.NoError(t, err)
|
|
|
|
}
|
|
|
|
if tt.res.err != nil && !tt.res.err(err) {
|
|
|
|
t.Errorf("got wrong err: %v ", err)
|
|
|
|
}
|
|
|
|
if tt.res.err == nil {
|
2024-08-12 22:32:01 +02:00
|
|
|
assertObjectDetails(t, tt.res.want, got)
|
2023-02-15 09:14:59 +01:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
2023-08-31 08:39:16 +02:00
|
|
|
|
|
|
|
func TestCommandSide_AddInstanceAppleIDP(t *testing.T) {
|
|
|
|
type fields struct {
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore func(*testing.T) *eventstore.Eventstore
|
2023-08-31 08:39:16 +02:00
|
|
|
idGenerator id.Generator
|
|
|
|
secretCrypto crypto.EncryptionAlgorithm
|
|
|
|
}
|
|
|
|
type args struct {
|
|
|
|
ctx context.Context
|
|
|
|
provider AppleProvider
|
|
|
|
}
|
|
|
|
type res struct {
|
|
|
|
id string
|
|
|
|
want *domain.ObjectDetails
|
|
|
|
err func(error) bool
|
|
|
|
}
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
fields fields
|
|
|
|
args args
|
|
|
|
res res
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
"invalid clientID",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-08-31 08:39:16 +02:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
provider: AppleProvider{},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-jkn3w", "Errors.IDP.ClientIDMissing"))
|
2023-08-31 08:39:16 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid teamID",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-08-31 08:39:16 +02:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
provider: AppleProvider{
|
|
|
|
ClientID: "clientID",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-Ffg32", "Errors.IDP.TeamIDMissing"))
|
2023-08-31 08:39:16 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid keyID",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-08-31 08:39:16 +02:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
provider: AppleProvider{
|
|
|
|
ClientID: "clientID",
|
|
|
|
TeamID: "teamID",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-GDjm5", "Errors.IDP.KeyIDMissing"))
|
2023-08-31 08:39:16 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid privateKey",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-08-31 08:39:16 +02:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
provider: AppleProvider{
|
|
|
|
ClientID: "clientID",
|
|
|
|
TeamID: "teamID",
|
|
|
|
KeyID: "keyID",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-GVD4n", "Errors.IDP.PrivateKeyMissing"))
|
2023-08-31 08:39:16 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "ok",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-08-31 08:39:16 +02:00
|
|
|
expectFilter(),
|
|
|
|
expectPush(
|
2023-10-19 12:19:10 +02:00
|
|
|
instance.NewAppleIDPAddedEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"",
|
|
|
|
"clientID",
|
|
|
|
"teamID",
|
|
|
|
"keyID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("privateKey"),
|
|
|
|
},
|
|
|
|
nil,
|
|
|
|
idp.Options{},
|
|
|
|
),
|
2023-08-31 08:39:16 +02:00
|
|
|
),
|
|
|
|
),
|
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
provider: AppleProvider{
|
|
|
|
ClientID: "clientID",
|
|
|
|
TeamID: "teamID",
|
|
|
|
KeyID: "keyID",
|
|
|
|
PrivateKey: []byte("privateKey"),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
id: "id1",
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "instance1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "ok all set",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-08-31 08:39:16 +02:00
|
|
|
expectFilter(),
|
|
|
|
expectPush(
|
2023-10-19 12:19:10 +02:00
|
|
|
instance.NewAppleIDPAddedEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"",
|
|
|
|
"clientID",
|
|
|
|
"teamID",
|
|
|
|
"keyID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("privateKey"),
|
|
|
|
},
|
|
|
|
[]string{"name", "email"},
|
|
|
|
idp.Options{
|
|
|
|
IsCreationAllowed: true,
|
|
|
|
IsLinkingAllowed: true,
|
|
|
|
IsAutoCreation: true,
|
|
|
|
IsAutoUpdate: true,
|
|
|
|
},
|
|
|
|
),
|
2023-08-31 08:39:16 +02:00
|
|
|
),
|
|
|
|
),
|
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
provider: AppleProvider{
|
|
|
|
ClientID: "clientID",
|
|
|
|
TeamID: "teamID",
|
|
|
|
KeyID: "keyID",
|
|
|
|
PrivateKey: []byte("privateKey"),
|
|
|
|
Scopes: []string{"name", "email"},
|
|
|
|
IDPOptions: idp.Options{
|
|
|
|
IsCreationAllowed: true,
|
|
|
|
IsLinkingAllowed: true,
|
|
|
|
IsAutoCreation: true,
|
|
|
|
IsAutoUpdate: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
id: "id1",
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "instance1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
c := &Commands{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: tt.fields.eventstore(t),
|
2023-08-31 08:39:16 +02:00
|
|
|
idGenerator: tt.fields.idGenerator,
|
|
|
|
idpConfigEncryption: tt.fields.secretCrypto,
|
|
|
|
}
|
|
|
|
id, got, err := c.AddInstanceAppleProvider(tt.args.ctx, tt.args.provider)
|
|
|
|
if tt.res.err == nil {
|
|
|
|
assert.NoError(t, err)
|
|
|
|
}
|
|
|
|
if tt.res.err != nil && !tt.res.err(err) {
|
|
|
|
t.Errorf("got wrong err: %v ", err)
|
|
|
|
}
|
|
|
|
if tt.res.err == nil {
|
|
|
|
assert.Equal(t, tt.res.id, id)
|
2024-08-12 22:32:01 +02:00
|
|
|
assertObjectDetails(t, tt.res.want, got)
|
2023-08-31 08:39:16 +02:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCommandSide_UpdateInstanceAppleIDP(t *testing.T) {
|
|
|
|
type fields struct {
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore func(*testing.T) *eventstore.Eventstore
|
2023-08-31 08:39:16 +02:00
|
|
|
secretCrypto crypto.EncryptionAlgorithm
|
|
|
|
}
|
|
|
|
type args struct {
|
|
|
|
ctx context.Context
|
|
|
|
id string
|
|
|
|
provider AppleProvider
|
|
|
|
}
|
|
|
|
type res struct {
|
|
|
|
want *domain.ObjectDetails
|
|
|
|
err func(error) bool
|
|
|
|
}
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
fields fields
|
|
|
|
args args
|
|
|
|
res res
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
"invalid id",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-08-31 08:39:16 +02:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
provider: AppleProvider{},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-FRHBH", "Errors.IDMissing"))
|
2023-08-31 08:39:16 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid clientID",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-08-31 08:39:16 +02:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
id: "id1",
|
|
|
|
provider: AppleProvider{},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-SFm4l", "Errors.IDP.ClientIDMissing"))
|
2023-08-31 08:39:16 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid teamID",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-08-31 08:39:16 +02:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
id: "id1",
|
|
|
|
provider: AppleProvider{
|
|
|
|
ClientID: "clientID",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-SG34t", "Errors.IDP.TeamIDMissing"))
|
2023-08-31 08:39:16 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid keyID",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-08-31 08:39:16 +02:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
id: "id1",
|
|
|
|
provider: AppleProvider{
|
|
|
|
ClientID: "clientID",
|
|
|
|
TeamID: "teamID",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-Gh4z2", "Errors.IDP.KeyIDMissing"))
|
2023-08-31 08:39:16 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "not found",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-08-31 08:39:16 +02:00
|
|
|
expectFilter(),
|
|
|
|
),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
id: "id1",
|
|
|
|
provider: AppleProvider{
|
|
|
|
ClientID: "clientID",
|
|
|
|
TeamID: "teamID",
|
|
|
|
KeyID: "keyID",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
2023-12-08 16:30:55 +02:00
|
|
|
err: zerrors.IsNotFound,
|
2023-08-31 08:39:16 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "no changes",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-08-31 08:39:16 +02:00
|
|
|
expectFilter(
|
|
|
|
eventFromEventPusher(
|
|
|
|
instance.NewAppleIDPAddedEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"",
|
|
|
|
"clientID",
|
|
|
|
"teamID",
|
|
|
|
"keyID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("privateKey"),
|
|
|
|
},
|
|
|
|
nil,
|
|
|
|
idp.Options{},
|
|
|
|
)),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
id: "id1",
|
|
|
|
provider: AppleProvider{
|
|
|
|
ClientID: "clientID",
|
|
|
|
TeamID: "teamID",
|
|
|
|
KeyID: "keyID",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "instance1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "change ok",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-08-31 08:39:16 +02:00
|
|
|
expectFilter(
|
|
|
|
eventFromEventPusher(
|
|
|
|
instance.NewAppleIDPAddedEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"",
|
|
|
|
"clientID",
|
|
|
|
"teamID",
|
|
|
|
"keyID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("privateKey"),
|
|
|
|
},
|
|
|
|
nil,
|
|
|
|
idp.Options{},
|
|
|
|
)),
|
|
|
|
),
|
|
|
|
expectPush(
|
2023-10-19 12:19:10 +02:00
|
|
|
func() eventstore.Command {
|
|
|
|
t := true
|
|
|
|
event, _ := instance.NewAppleIDPChangedEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
[]idp.AppleIDPChanges{
|
|
|
|
idp.ChangeAppleClientID("clientID2"),
|
|
|
|
idp.ChangeAppleTeamID("teamID2"),
|
|
|
|
idp.ChangeAppleKeyID("keyID2"),
|
|
|
|
idp.ChangeApplePrivateKey(&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("newPrivateKey"),
|
|
|
|
}),
|
|
|
|
idp.ChangeAppleScopes([]string{"name", "email"}),
|
|
|
|
idp.ChangeAppleOptions(idp.OptionChanges{
|
|
|
|
IsCreationAllowed: &t,
|
|
|
|
IsLinkingAllowed: &t,
|
|
|
|
IsAutoCreation: &t,
|
|
|
|
IsAutoUpdate: &t,
|
|
|
|
}),
|
|
|
|
},
|
|
|
|
)
|
|
|
|
return event
|
|
|
|
}(),
|
2023-08-31 08:39:16 +02:00
|
|
|
),
|
|
|
|
),
|
|
|
|
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
id: "id1",
|
|
|
|
provider: AppleProvider{
|
|
|
|
ClientID: "clientID2",
|
|
|
|
TeamID: "teamID2",
|
|
|
|
KeyID: "keyID2",
|
|
|
|
PrivateKey: []byte("newPrivateKey"),
|
|
|
|
Scopes: []string{"name", "email"},
|
|
|
|
IDPOptions: idp.Options{
|
|
|
|
IsCreationAllowed: true,
|
|
|
|
IsLinkingAllowed: true,
|
|
|
|
IsAutoCreation: true,
|
|
|
|
IsAutoUpdate: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "instance1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
c := &Commands{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: tt.fields.eventstore(t),
|
2023-08-31 08:39:16 +02:00
|
|
|
idpConfigEncryption: tt.fields.secretCrypto,
|
|
|
|
}
|
|
|
|
got, err := c.UpdateInstanceAppleProvider(tt.args.ctx, tt.args.id, tt.args.provider)
|
|
|
|
if tt.res.err == nil {
|
|
|
|
assert.NoError(t, err)
|
|
|
|
}
|
|
|
|
if tt.res.err != nil && !tt.res.err(err) {
|
|
|
|
t.Errorf("got wrong err: %v ", err)
|
|
|
|
}
|
|
|
|
if tt.res.err == nil {
|
2024-08-12 22:32:01 +02:00
|
|
|
assertObjectDetails(t, tt.res.want, got)
|
2023-08-31 08:39:16 +02:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
2023-09-29 11:26:14 +02:00
|
|
|
|
|
|
|
func TestCommandSide_AddInstanceSAMLIDP(t *testing.T) {
|
|
|
|
type fields struct {
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore func(*testing.T) *eventstore.Eventstore
|
2023-09-29 11:26:14 +02:00
|
|
|
idGenerator id.Generator
|
|
|
|
secretCrypto crypto.EncryptionAlgorithm
|
|
|
|
certificateAndKeyGenerator func(id string) ([]byte, []byte, error)
|
|
|
|
}
|
|
|
|
type args struct {
|
|
|
|
ctx context.Context
|
2024-12-03 11:38:28 +01:00
|
|
|
provider *SAMLProvider
|
2023-09-29 11:26:14 +02:00
|
|
|
}
|
|
|
|
type res struct {
|
|
|
|
id string
|
|
|
|
want *domain.ObjectDetails
|
|
|
|
err func(error) bool
|
|
|
|
}
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
fields fields
|
|
|
|
args args
|
|
|
|
res res
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
"invalid name",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-09-29 11:26:14 +02:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
2024-12-03 11:38:28 +01:00
|
|
|
provider: &SAMLProvider{},
|
2023-09-29 11:26:14 +02:00
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-o07zjotgnd", ""))
|
2023-09-29 11:26:14 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
2024-12-03 11:38:28 +01:00
|
|
|
"no metadata",
|
2023-09-29 11:26:14 +02:00
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-09-29 11:26:14 +02:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
2024-12-03 11:38:28 +01:00
|
|
|
provider: &SAMLProvider{
|
2023-09-29 11:26:14 +02:00
|
|
|
Name: "name",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-3bi3esi16t", "Errors.Invalid.Argument"))
|
2023-09-29 11:26:14 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2024-12-03 11:38:28 +01:00
|
|
|
{
|
|
|
|
"invalid metadata, error",
|
|
|
|
fields{
|
|
|
|
eventstore: expectEventstore(),
|
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
provider: &SAMLProvider{
|
|
|
|
Name: "name",
|
|
|
|
Metadata: []byte("metadata"),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-SF3rwhgh", "Errors.Project.App.SAMLMetadataFormat"))
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2023-09-29 11:26:14 +02:00
|
|
|
{
|
|
|
|
name: "ok",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-09-29 11:26:14 +02:00
|
|
|
expectFilter(),
|
|
|
|
expectPush(
|
2023-10-19 12:19:10 +02:00
|
|
|
instance.NewSAMLIDPAddedEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"name",
|
2024-12-03 11:38:28 +01:00
|
|
|
validSAMLMetadata,
|
2023-10-19 12:19:10 +02:00
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("key"),
|
|
|
|
},
|
|
|
|
[]byte("certificate"),
|
|
|
|
"",
|
|
|
|
false,
|
2024-05-23 07:04:07 +02:00
|
|
|
nil,
|
|
|
|
"",
|
feat: federated logout for SAML IdPs (#9931)
# Which Problems Are Solved
Currently if a user signs in using an IdP, once they sign out of
Zitadel, the corresponding IdP session is not terminated. This can be
the desired behavior. In some cases, e.g. when using a shared computer
it results in a potential security risk, since a follower user might be
able to sign in as the previous using the still open IdP session.
# How the Problems Are Solved
- Admins can enabled a federated logout option on SAML IdPs through the
Admin and Management APIs.
- During the termination of a login V1 session using OIDC end_session
endpoint, Zitadel will check if an IdP was used to authenticate that
session.
- In case there was a SAML IdP used with Federated Logout enabled, it
will intercept the logout process, store the information into the shared
cache and redirect to the federated logout endpoint in the V1 login.
- The V1 login federated logout endpoint checks every request on an
existing cache entry. On success it will create a SAML logout request
for the used IdP and either redirect or POST to the configured SLO
endpoint. The cache entry is updated with a `redirected` state.
- A SLO endpoint is added to the `/idp` handlers, which will handle the
SAML logout responses. At the moment it will check again for an existing
federated logout entry (with state `redirected`) in the cache. On
success, the user is redirected to the initially provided
`post_logout_redirect_uri` from the end_session request.
# Additional Changes
None
# Additional Context
- This PR merges the https://github.com/zitadel/zitadel/pull/9841 and
https://github.com/zitadel/zitadel/pull/9854 to main, additionally
updating the docs on Entra ID SAML.
- closes #9228
- backport to 3.x
---------
Co-authored-by: Silvan <27845747+adlerhurst@users.noreply.github.com>
Co-authored-by: Zach Hirschtritt <zachary.hirschtritt@klaviyo.com>
(cherry picked from commit 2cf3ef4de4ef993367daec6ff3974bdbdf70d2f3)
2025-05-23 13:52:25 +02:00
|
|
|
false,
|
2023-10-19 12:19:10 +02:00
|
|
|
idp.Options{},
|
|
|
|
),
|
2023-09-29 11:26:14 +02:00
|
|
|
),
|
|
|
|
),
|
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
|
|
|
certificateAndKeyGenerator: func(id string) ([]byte, []byte, error) { return []byte("key"), []byte("certificate"), nil },
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
2024-12-03 11:38:28 +01:00
|
|
|
provider: &SAMLProvider{
|
2023-09-29 11:26:14 +02:00
|
|
|
Name: "name",
|
2024-12-03 11:38:28 +01:00
|
|
|
Metadata: validSAMLMetadata,
|
2023-09-29 11:26:14 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
id: "id1",
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "instance1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "ok all set",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-09-29 11:26:14 +02:00
|
|
|
expectFilter(),
|
|
|
|
expectPush(
|
2023-10-19 12:19:10 +02:00
|
|
|
instance.NewSAMLIDPAddedEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"name",
|
2024-12-03 11:38:28 +01:00
|
|
|
validSAMLMetadata,
|
2023-10-19 12:19:10 +02:00
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("key"),
|
|
|
|
},
|
|
|
|
[]byte("certificate"),
|
|
|
|
"binding",
|
|
|
|
true,
|
2024-05-23 07:04:07 +02:00
|
|
|
gu.Ptr(domain.SAMLNameIDFormatTransient),
|
|
|
|
"customAttribute",
|
feat: federated logout for SAML IdPs (#9931)
# Which Problems Are Solved
Currently if a user signs in using an IdP, once they sign out of
Zitadel, the corresponding IdP session is not terminated. This can be
the desired behavior. In some cases, e.g. when using a shared computer
it results in a potential security risk, since a follower user might be
able to sign in as the previous using the still open IdP session.
# How the Problems Are Solved
- Admins can enabled a federated logout option on SAML IdPs through the
Admin and Management APIs.
- During the termination of a login V1 session using OIDC end_session
endpoint, Zitadel will check if an IdP was used to authenticate that
session.
- In case there was a SAML IdP used with Federated Logout enabled, it
will intercept the logout process, store the information into the shared
cache and redirect to the federated logout endpoint in the V1 login.
- The V1 login federated logout endpoint checks every request on an
existing cache entry. On success it will create a SAML logout request
for the used IdP and either redirect or POST to the configured SLO
endpoint. The cache entry is updated with a `redirected` state.
- A SLO endpoint is added to the `/idp` handlers, which will handle the
SAML logout responses. At the moment it will check again for an existing
federated logout entry (with state `redirected`) in the cache. On
success, the user is redirected to the initially provided
`post_logout_redirect_uri` from the end_session request.
# Additional Changes
None
# Additional Context
- This PR merges the https://github.com/zitadel/zitadel/pull/9841 and
https://github.com/zitadel/zitadel/pull/9854 to main, additionally
updating the docs on Entra ID SAML.
- closes #9228
- backport to 3.x
---------
Co-authored-by: Silvan <27845747+adlerhurst@users.noreply.github.com>
Co-authored-by: Zach Hirschtritt <zachary.hirschtritt@klaviyo.com>
(cherry picked from commit 2cf3ef4de4ef993367daec6ff3974bdbdf70d2f3)
2025-05-23 13:52:25 +02:00
|
|
|
true,
|
2023-10-19 12:19:10 +02:00
|
|
|
idp.Options{
|
|
|
|
IsCreationAllowed: true,
|
|
|
|
IsLinkingAllowed: true,
|
|
|
|
IsAutoCreation: true,
|
|
|
|
IsAutoUpdate: true,
|
|
|
|
},
|
|
|
|
),
|
2023-09-29 11:26:14 +02:00
|
|
|
),
|
|
|
|
),
|
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
|
|
|
certificateAndKeyGenerator: func(id string) ([]byte, []byte, error) { return []byte("key"), []byte("certificate"), nil },
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
2024-12-03 11:38:28 +01:00
|
|
|
provider: &SAMLProvider{
|
2024-05-23 07:04:07 +02:00
|
|
|
Name: "name",
|
2024-12-03 11:38:28 +01:00
|
|
|
Metadata: validSAMLMetadata,
|
2024-05-23 07:04:07 +02:00
|
|
|
Binding: "binding",
|
|
|
|
WithSignedRequest: true,
|
|
|
|
NameIDFormat: gu.Ptr(domain.SAMLNameIDFormatTransient),
|
|
|
|
TransientMappingAttributeName: "customAttribute",
|
feat: federated logout for SAML IdPs (#9931)
# Which Problems Are Solved
Currently if a user signs in using an IdP, once they sign out of
Zitadel, the corresponding IdP session is not terminated. This can be
the desired behavior. In some cases, e.g. when using a shared computer
it results in a potential security risk, since a follower user might be
able to sign in as the previous using the still open IdP session.
# How the Problems Are Solved
- Admins can enabled a federated logout option on SAML IdPs through the
Admin and Management APIs.
- During the termination of a login V1 session using OIDC end_session
endpoint, Zitadel will check if an IdP was used to authenticate that
session.
- In case there was a SAML IdP used with Federated Logout enabled, it
will intercept the logout process, store the information into the shared
cache and redirect to the federated logout endpoint in the V1 login.
- The V1 login federated logout endpoint checks every request on an
existing cache entry. On success it will create a SAML logout request
for the used IdP and either redirect or POST to the configured SLO
endpoint. The cache entry is updated with a `redirected` state.
- A SLO endpoint is added to the `/idp` handlers, which will handle the
SAML logout responses. At the moment it will check again for an existing
federated logout entry (with state `redirected`) in the cache. On
success, the user is redirected to the initially provided
`post_logout_redirect_uri` from the end_session request.
# Additional Changes
None
# Additional Context
- This PR merges the https://github.com/zitadel/zitadel/pull/9841 and
https://github.com/zitadel/zitadel/pull/9854 to main, additionally
updating the docs on Entra ID SAML.
- closes #9228
- backport to 3.x
---------
Co-authored-by: Silvan <27845747+adlerhurst@users.noreply.github.com>
Co-authored-by: Zach Hirschtritt <zachary.hirschtritt@klaviyo.com>
(cherry picked from commit 2cf3ef4de4ef993367daec6ff3974bdbdf70d2f3)
2025-05-23 13:52:25 +02:00
|
|
|
FederatedLogoutEnabled: true,
|
2023-09-29 11:26:14 +02:00
|
|
|
IDPOptions: idp.Options{
|
|
|
|
IsCreationAllowed: true,
|
|
|
|
IsLinkingAllowed: true,
|
|
|
|
IsAutoCreation: true,
|
|
|
|
IsAutoUpdate: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
id: "id1",
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "instance1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
c := &Commands{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: tt.fields.eventstore(t),
|
2023-09-29 11:26:14 +02:00
|
|
|
idGenerator: tt.fields.idGenerator,
|
|
|
|
idpConfigEncryption: tt.fields.secretCrypto,
|
|
|
|
samlCertificateAndKeyGenerator: tt.fields.certificateAndKeyGenerator,
|
|
|
|
}
|
|
|
|
id, got, err := c.AddInstanceSAMLProvider(tt.args.ctx, tt.args.provider)
|
|
|
|
if tt.res.err == nil {
|
|
|
|
assert.NoError(t, err)
|
|
|
|
}
|
|
|
|
if tt.res.err != nil && !tt.res.err(err) {
|
|
|
|
t.Errorf("got wrong err: %v ", err)
|
|
|
|
}
|
|
|
|
if tt.res.err == nil {
|
|
|
|
assert.Equal(t, tt.res.id, id)
|
2024-08-12 22:32:01 +02:00
|
|
|
assertObjectDetails(t, tt.res.want, got)
|
2023-09-29 11:26:14 +02:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCommandSide_UpdateInstanceGenericSAMLIDP(t *testing.T) {
|
|
|
|
type fields struct {
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore func(*testing.T) *eventstore.Eventstore
|
2023-09-29 11:26:14 +02:00
|
|
|
secretCrypto crypto.EncryptionAlgorithm
|
|
|
|
}
|
|
|
|
type args struct {
|
|
|
|
ctx context.Context
|
|
|
|
id string
|
2024-12-03 11:38:28 +01:00
|
|
|
provider *SAMLProvider
|
2023-09-29 11:26:14 +02:00
|
|
|
}
|
|
|
|
type res struct {
|
|
|
|
want *domain.ObjectDetails
|
|
|
|
err func(error) bool
|
|
|
|
}
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
fields fields
|
|
|
|
args args
|
|
|
|
res res
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
"invalid id",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-09-29 11:26:14 +02:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
2024-12-03 11:38:28 +01:00
|
|
|
provider: &SAMLProvider{},
|
2023-09-29 11:26:14 +02:00
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-7o3rq1owpm", ""))
|
2023-09-29 11:26:14 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid name",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-09-29 11:26:14 +02:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
id: "id1",
|
2024-12-03 11:38:28 +01:00
|
|
|
provider: &SAMLProvider{},
|
2023-09-29 11:26:14 +02:00
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-q2s9rak7o9", ""))
|
2023-09-29 11:26:14 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
2024-12-03 11:38:28 +01:00
|
|
|
"no metadata",
|
2023-09-29 11:26:14 +02:00
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-09-29 11:26:14 +02:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
id: "id1",
|
2024-12-03 11:38:28 +01:00
|
|
|
provider: &SAMLProvider{
|
2023-09-29 11:26:14 +02:00
|
|
|
Name: "name",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-iw1rxnf4sf", ""))
|
2023-09-29 11:26:14 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2024-12-03 11:38:28 +01:00
|
|
|
{
|
|
|
|
"invalid metadata, error",
|
|
|
|
fields{
|
|
|
|
eventstore: expectEventstore(),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
id: "id1",
|
|
|
|
provider: &SAMLProvider{
|
|
|
|
Name: "name",
|
|
|
|
Metadata: []byte("metadata"),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-dsfj3kl2", "Errors.Project.App.SAMLMetadataFormat"))
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2023-09-29 11:26:14 +02:00
|
|
|
{
|
|
|
|
name: "not found",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-09-29 11:26:14 +02:00
|
|
|
expectFilter(),
|
|
|
|
),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
id: "id1",
|
2024-12-03 11:38:28 +01:00
|
|
|
provider: &SAMLProvider{
|
2023-09-29 11:26:14 +02:00
|
|
|
Name: "name",
|
2024-12-03 11:38:28 +01:00
|
|
|
Metadata: validSAMLMetadata,
|
2023-09-29 11:26:14 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
2023-12-08 16:30:55 +02:00
|
|
|
err: zerrors.IsNotFound,
|
2023-09-29 11:26:14 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "no changes",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-09-29 11:26:14 +02:00
|
|
|
expectFilter(
|
|
|
|
eventFromEventPusher(
|
|
|
|
instance.NewSAMLIDPAddedEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"name",
|
2024-12-03 11:38:28 +01:00
|
|
|
validSAMLMetadata,
|
2023-09-29 11:26:14 +02:00
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("key"),
|
|
|
|
},
|
|
|
|
[]byte("certificate"),
|
|
|
|
"",
|
|
|
|
false,
|
2024-05-23 07:04:07 +02:00
|
|
|
nil,
|
|
|
|
"",
|
feat: federated logout for SAML IdPs (#9931)
# Which Problems Are Solved
Currently if a user signs in using an IdP, once they sign out of
Zitadel, the corresponding IdP session is not terminated. This can be
the desired behavior. In some cases, e.g. when using a shared computer
it results in a potential security risk, since a follower user might be
able to sign in as the previous using the still open IdP session.
# How the Problems Are Solved
- Admins can enabled a federated logout option on SAML IdPs through the
Admin and Management APIs.
- During the termination of a login V1 session using OIDC end_session
endpoint, Zitadel will check if an IdP was used to authenticate that
session.
- In case there was a SAML IdP used with Federated Logout enabled, it
will intercept the logout process, store the information into the shared
cache and redirect to the federated logout endpoint in the V1 login.
- The V1 login federated logout endpoint checks every request on an
existing cache entry. On success it will create a SAML logout request
for the used IdP and either redirect or POST to the configured SLO
endpoint. The cache entry is updated with a `redirected` state.
- A SLO endpoint is added to the `/idp` handlers, which will handle the
SAML logout responses. At the moment it will check again for an existing
federated logout entry (with state `redirected`) in the cache. On
success, the user is redirected to the initially provided
`post_logout_redirect_uri` from the end_session request.
# Additional Changes
None
# Additional Context
- This PR merges the https://github.com/zitadel/zitadel/pull/9841 and
https://github.com/zitadel/zitadel/pull/9854 to main, additionally
updating the docs on Entra ID SAML.
- closes #9228
- backport to 3.x
---------
Co-authored-by: Silvan <27845747+adlerhurst@users.noreply.github.com>
Co-authored-by: Zach Hirschtritt <zachary.hirschtritt@klaviyo.com>
(cherry picked from commit 2cf3ef4de4ef993367daec6ff3974bdbdf70d2f3)
2025-05-23 13:52:25 +02:00
|
|
|
false,
|
2023-09-29 11:26:14 +02:00
|
|
|
idp.Options{},
|
|
|
|
)),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
id: "id1",
|
2024-12-03 11:38:28 +01:00
|
|
|
provider: &SAMLProvider{
|
2023-09-29 11:26:14 +02:00
|
|
|
Name: "name",
|
2024-12-03 11:38:28 +01:00
|
|
|
Metadata: validSAMLMetadata,
|
2023-09-29 11:26:14 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "instance1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "change ok",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-09-29 11:26:14 +02:00
|
|
|
expectFilter(
|
|
|
|
eventFromEventPusher(
|
|
|
|
instance.NewSAMLIDPAddedEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"name",
|
|
|
|
[]byte("metadata"),
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("key"),
|
|
|
|
},
|
|
|
|
[]byte("certificate"),
|
|
|
|
"binding",
|
|
|
|
false,
|
2024-05-23 07:04:07 +02:00
|
|
|
gu.Ptr(domain.SAMLNameIDFormatUnspecified),
|
|
|
|
"",
|
feat: federated logout for SAML IdPs (#9931)
# Which Problems Are Solved
Currently if a user signs in using an IdP, once they sign out of
Zitadel, the corresponding IdP session is not terminated. This can be
the desired behavior. In some cases, e.g. when using a shared computer
it results in a potential security risk, since a follower user might be
able to sign in as the previous using the still open IdP session.
# How the Problems Are Solved
- Admins can enabled a federated logout option on SAML IdPs through the
Admin and Management APIs.
- During the termination of a login V1 session using OIDC end_session
endpoint, Zitadel will check if an IdP was used to authenticate that
session.
- In case there was a SAML IdP used with Federated Logout enabled, it
will intercept the logout process, store the information into the shared
cache and redirect to the federated logout endpoint in the V1 login.
- The V1 login federated logout endpoint checks every request on an
existing cache entry. On success it will create a SAML logout request
for the used IdP and either redirect or POST to the configured SLO
endpoint. The cache entry is updated with a `redirected` state.
- A SLO endpoint is added to the `/idp` handlers, which will handle the
SAML logout responses. At the moment it will check again for an existing
federated logout entry (with state `redirected`) in the cache. On
success, the user is redirected to the initially provided
`post_logout_redirect_uri` from the end_session request.
# Additional Changes
None
# Additional Context
- This PR merges the https://github.com/zitadel/zitadel/pull/9841 and
https://github.com/zitadel/zitadel/pull/9854 to main, additionally
updating the docs on Entra ID SAML.
- closes #9228
- backport to 3.x
---------
Co-authored-by: Silvan <27845747+adlerhurst@users.noreply.github.com>
Co-authored-by: Zach Hirschtritt <zachary.hirschtritt@klaviyo.com>
(cherry picked from commit 2cf3ef4de4ef993367daec6ff3974bdbdf70d2f3)
2025-05-23 13:52:25 +02:00
|
|
|
false,
|
2023-09-29 11:26:14 +02:00
|
|
|
idp.Options{},
|
|
|
|
)),
|
|
|
|
),
|
|
|
|
expectPush(
|
2023-10-19 12:19:10 +02:00
|
|
|
func() eventstore.Command {
|
|
|
|
t := true
|
|
|
|
event, _ := instance.NewSAMLIDPChangedEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
[]idp.SAMLIDPChanges{
|
|
|
|
idp.ChangeSAMLName("new name"),
|
2024-12-03 11:38:28 +01:00
|
|
|
idp.ChangeSAMLMetadata(validSAMLMetadata),
|
2023-10-19 12:19:10 +02:00
|
|
|
idp.ChangeSAMLBinding("new binding"),
|
|
|
|
idp.ChangeSAMLWithSignedRequest(true),
|
2024-05-23 07:04:07 +02:00
|
|
|
idp.ChangeSAMLNameIDFormat(gu.Ptr(domain.SAMLNameIDFormatTransient)),
|
|
|
|
idp.ChangeSAMLTransientMappingAttributeName("customAttribute"),
|
feat: federated logout for SAML IdPs (#9931)
# Which Problems Are Solved
Currently if a user signs in using an IdP, once they sign out of
Zitadel, the corresponding IdP session is not terminated. This can be
the desired behavior. In some cases, e.g. when using a shared computer
it results in a potential security risk, since a follower user might be
able to sign in as the previous using the still open IdP session.
# How the Problems Are Solved
- Admins can enabled a federated logout option on SAML IdPs through the
Admin and Management APIs.
- During the termination of a login V1 session using OIDC end_session
endpoint, Zitadel will check if an IdP was used to authenticate that
session.
- In case there was a SAML IdP used with Federated Logout enabled, it
will intercept the logout process, store the information into the shared
cache and redirect to the federated logout endpoint in the V1 login.
- The V1 login federated logout endpoint checks every request on an
existing cache entry. On success it will create a SAML logout request
for the used IdP and either redirect or POST to the configured SLO
endpoint. The cache entry is updated with a `redirected` state.
- A SLO endpoint is added to the `/idp` handlers, which will handle the
SAML logout responses. At the moment it will check again for an existing
federated logout entry (with state `redirected`) in the cache. On
success, the user is redirected to the initially provided
`post_logout_redirect_uri` from the end_session request.
# Additional Changes
None
# Additional Context
- This PR merges the https://github.com/zitadel/zitadel/pull/9841 and
https://github.com/zitadel/zitadel/pull/9854 to main, additionally
updating the docs on Entra ID SAML.
- closes #9228
- backport to 3.x
---------
Co-authored-by: Silvan <27845747+adlerhurst@users.noreply.github.com>
Co-authored-by: Zach Hirschtritt <zachary.hirschtritt@klaviyo.com>
(cherry picked from commit 2cf3ef4de4ef993367daec6ff3974bdbdf70d2f3)
2025-05-23 13:52:25 +02:00
|
|
|
idp.ChangeSAMLFederatedLogoutEnabled(true),
|
2023-10-19 12:19:10 +02:00
|
|
|
idp.ChangeSAMLOptions(idp.OptionChanges{
|
|
|
|
IsCreationAllowed: &t,
|
|
|
|
IsLinkingAllowed: &t,
|
|
|
|
IsAutoCreation: &t,
|
|
|
|
IsAutoUpdate: &t,
|
|
|
|
}),
|
|
|
|
},
|
|
|
|
)
|
|
|
|
return event
|
|
|
|
}(),
|
2023-09-29 11:26:14 +02:00
|
|
|
),
|
|
|
|
),
|
|
|
|
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
id: "id1",
|
2024-12-03 11:38:28 +01:00
|
|
|
provider: &SAMLProvider{
|
2024-05-23 07:04:07 +02:00
|
|
|
Name: "new name",
|
2024-12-03 11:38:28 +01:00
|
|
|
Metadata: validSAMLMetadata,
|
2024-05-23 07:04:07 +02:00
|
|
|
Binding: "new binding",
|
|
|
|
WithSignedRequest: true,
|
|
|
|
NameIDFormat: gu.Ptr(domain.SAMLNameIDFormatTransient),
|
|
|
|
TransientMappingAttributeName: "customAttribute",
|
feat: federated logout for SAML IdPs (#9931)
# Which Problems Are Solved
Currently if a user signs in using an IdP, once they sign out of
Zitadel, the corresponding IdP session is not terminated. This can be
the desired behavior. In some cases, e.g. when using a shared computer
it results in a potential security risk, since a follower user might be
able to sign in as the previous using the still open IdP session.
# How the Problems Are Solved
- Admins can enabled a federated logout option on SAML IdPs through the
Admin and Management APIs.
- During the termination of a login V1 session using OIDC end_session
endpoint, Zitadel will check if an IdP was used to authenticate that
session.
- In case there was a SAML IdP used with Federated Logout enabled, it
will intercept the logout process, store the information into the shared
cache and redirect to the federated logout endpoint in the V1 login.
- The V1 login federated logout endpoint checks every request on an
existing cache entry. On success it will create a SAML logout request
for the used IdP and either redirect or POST to the configured SLO
endpoint. The cache entry is updated with a `redirected` state.
- A SLO endpoint is added to the `/idp` handlers, which will handle the
SAML logout responses. At the moment it will check again for an existing
federated logout entry (with state `redirected`) in the cache. On
success, the user is redirected to the initially provided
`post_logout_redirect_uri` from the end_session request.
# Additional Changes
None
# Additional Context
- This PR merges the https://github.com/zitadel/zitadel/pull/9841 and
https://github.com/zitadel/zitadel/pull/9854 to main, additionally
updating the docs on Entra ID SAML.
- closes #9228
- backport to 3.x
---------
Co-authored-by: Silvan <27845747+adlerhurst@users.noreply.github.com>
Co-authored-by: Zach Hirschtritt <zachary.hirschtritt@klaviyo.com>
(cherry picked from commit 2cf3ef4de4ef993367daec6ff3974bdbdf70d2f3)
2025-05-23 13:52:25 +02:00
|
|
|
FederatedLogoutEnabled: true,
|
2023-09-29 11:26:14 +02:00
|
|
|
IDPOptions: idp.Options{
|
|
|
|
IsCreationAllowed: true,
|
|
|
|
IsLinkingAllowed: true,
|
|
|
|
IsAutoCreation: true,
|
|
|
|
IsAutoUpdate: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "instance1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
c := &Commands{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: tt.fields.eventstore(t),
|
2023-09-29 11:26:14 +02:00
|
|
|
idpConfigEncryption: tt.fields.secretCrypto,
|
|
|
|
}
|
|
|
|
got, err := c.UpdateInstanceSAMLProvider(tt.args.ctx, tt.args.id, tt.args.provider)
|
|
|
|
if tt.res.err == nil {
|
|
|
|
assert.NoError(t, err)
|
|
|
|
}
|
|
|
|
if tt.res.err != nil && !tt.res.err(err) {
|
|
|
|
t.Errorf("got wrong err: %v ", err)
|
|
|
|
}
|
|
|
|
if tt.res.err == nil {
|
2024-08-12 22:32:01 +02:00
|
|
|
assertObjectDetails(t, tt.res.want, got)
|
2023-09-29 11:26:14 +02:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCommandSide_RegenerateInstanceSAMLProviderCertificate(t *testing.T) {
|
|
|
|
type fields struct {
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore func(*testing.T) *eventstore.Eventstore
|
2023-09-29 11:26:14 +02:00
|
|
|
secretCrypto crypto.EncryptionAlgorithm
|
|
|
|
certificateAndKeyGenerator func(id string) ([]byte, []byte, error)
|
|
|
|
}
|
|
|
|
type args struct {
|
|
|
|
ctx context.Context
|
|
|
|
id string
|
|
|
|
}
|
|
|
|
type res struct {
|
|
|
|
want *domain.ObjectDetails
|
|
|
|
err func(error) bool
|
|
|
|
}
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
fields fields
|
|
|
|
args args
|
|
|
|
res res
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
"invalid id",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-09-29 11:26:14 +02:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-7de108gqya", ""))
|
2023-09-29 11:26:14 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "not found",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-09-29 11:26:14 +02:00
|
|
|
expectFilter(),
|
|
|
|
),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
id: "id1",
|
|
|
|
},
|
|
|
|
res: res{
|
2023-12-08 16:30:55 +02:00
|
|
|
err: zerrors.IsNotFound,
|
2023-09-29 11:26:14 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "change ok",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-09-29 11:26:14 +02:00
|
|
|
expectFilter(
|
|
|
|
eventFromEventPusher(
|
|
|
|
instance.NewSAMLIDPAddedEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"name",
|
|
|
|
[]byte("metadata"),
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("key"),
|
|
|
|
},
|
|
|
|
[]byte("certificate"),
|
|
|
|
"binding",
|
|
|
|
false,
|
2024-05-23 07:04:07 +02:00
|
|
|
gu.Ptr(domain.SAMLNameIDFormatUnspecified),
|
|
|
|
"",
|
feat: federated logout for SAML IdPs (#9931)
# Which Problems Are Solved
Currently if a user signs in using an IdP, once they sign out of
Zitadel, the corresponding IdP session is not terminated. This can be
the desired behavior. In some cases, e.g. when using a shared computer
it results in a potential security risk, since a follower user might be
able to sign in as the previous using the still open IdP session.
# How the Problems Are Solved
- Admins can enabled a federated logout option on SAML IdPs through the
Admin and Management APIs.
- During the termination of a login V1 session using OIDC end_session
endpoint, Zitadel will check if an IdP was used to authenticate that
session.
- In case there was a SAML IdP used with Federated Logout enabled, it
will intercept the logout process, store the information into the shared
cache and redirect to the federated logout endpoint in the V1 login.
- The V1 login federated logout endpoint checks every request on an
existing cache entry. On success it will create a SAML logout request
for the used IdP and either redirect or POST to the configured SLO
endpoint. The cache entry is updated with a `redirected` state.
- A SLO endpoint is added to the `/idp` handlers, which will handle the
SAML logout responses. At the moment it will check again for an existing
federated logout entry (with state `redirected`) in the cache. On
success, the user is redirected to the initially provided
`post_logout_redirect_uri` from the end_session request.
# Additional Changes
None
# Additional Context
- This PR merges the https://github.com/zitadel/zitadel/pull/9841 and
https://github.com/zitadel/zitadel/pull/9854 to main, additionally
updating the docs on Entra ID SAML.
- closes #9228
- backport to 3.x
---------
Co-authored-by: Silvan <27845747+adlerhurst@users.noreply.github.com>
Co-authored-by: Zach Hirschtritt <zachary.hirschtritt@klaviyo.com>
(cherry picked from commit 2cf3ef4de4ef993367daec6ff3974bdbdf70d2f3)
2025-05-23 13:52:25 +02:00
|
|
|
false,
|
2023-09-29 11:26:14 +02:00
|
|
|
idp.Options{},
|
|
|
|
)),
|
|
|
|
),
|
|
|
|
expectPush(
|
2023-10-19 12:19:10 +02:00
|
|
|
func() eventstore.Command {
|
|
|
|
event, _ := instance.NewSAMLIDPChangedEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
[]idp.SAMLIDPChanges{
|
|
|
|
idp.ChangeSAMLKey(&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("new key"),
|
|
|
|
}),
|
|
|
|
idp.ChangeSAMLCertificate([]byte("new certificate")),
|
|
|
|
},
|
|
|
|
)
|
|
|
|
return event
|
|
|
|
}(),
|
2023-09-29 11:26:14 +02:00
|
|
|
),
|
|
|
|
),
|
|
|
|
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
|
|
|
certificateAndKeyGenerator: func(id string) ([]byte, []byte, error) {
|
|
|
|
return []byte("new key"), []byte("new certificate"), nil
|
|
|
|
},
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
id: "id1",
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "instance1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
c := &Commands{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: tt.fields.eventstore(t),
|
2023-09-29 11:26:14 +02:00
|
|
|
idpConfigEncryption: tt.fields.secretCrypto,
|
|
|
|
samlCertificateAndKeyGenerator: tt.fields.certificateAndKeyGenerator,
|
|
|
|
}
|
|
|
|
got, err := c.RegenerateInstanceSAMLProviderCertificate(tt.args.ctx, tt.args.id)
|
|
|
|
if tt.res.err == nil {
|
|
|
|
assert.NoError(t, err)
|
|
|
|
}
|
|
|
|
if tt.res.err != nil && !tt.res.err(err) {
|
|
|
|
t.Errorf("got wrong err: %v ", err)
|
|
|
|
}
|
|
|
|
if tt.res.err == nil {
|
2024-08-12 22:32:01 +02:00
|
|
|
assertObjectDetails(t, tt.res.want, got)
|
2023-09-29 11:26:14 +02:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|