mirror of
https://github.com/gravitational/teleport.git
synced 2026-09-01 16:03:55 +08:00
add option to allow client redirects from IPs in specified CIDR ranges in SSO client logins (#44556)
Co-authored-by: Andrew LeFevre <Andrew LeFevre>
This commit is contained in:
@@ -14,7 +14,7 @@
|
||||
|
||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||
// versions:
|
||||
// - protoc-gen-go-grpc v1.4.0
|
||||
// - protoc-gen-go-grpc v1.5.0
|
||||
// - protoc (unknown)
|
||||
// source: teleport/userprovisioning/v1/statichostuser_service.proto
|
||||
|
||||
@@ -30,8 +30,8 @@ import (
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the grpc package it is being compiled against.
|
||||
// Requires gRPC-Go v1.62.0 or later.
|
||||
const _ = grpc.SupportPackageIsVersion8
|
||||
// Requires gRPC-Go v1.64.0 or later.
|
||||
const _ = grpc.SupportPackageIsVersion9
|
||||
|
||||
const (
|
||||
StaticHostUsersService_GetStaticHostUser_FullMethodName = "/teleport.userprovisioning.v1.StaticHostUsersService/GetStaticHostUser"
|
||||
@@ -132,7 +132,7 @@ func (c *staticHostUsersServiceClient) DeleteStaticHostUser(ctx context.Context,
|
||||
|
||||
// StaticHostUsersServiceServer is the server API for StaticHostUsersService service.
|
||||
// All implementations must embed UnimplementedStaticHostUsersServiceServer
|
||||
// for forward compatibility
|
||||
// for forward compatibility.
|
||||
//
|
||||
// StaticHostUsersService provides methods to manage static host users.
|
||||
type StaticHostUsersServiceServer interface {
|
||||
@@ -151,9 +151,12 @@ type StaticHostUsersServiceServer interface {
|
||||
mustEmbedUnimplementedStaticHostUsersServiceServer()
|
||||
}
|
||||
|
||||
// UnimplementedStaticHostUsersServiceServer must be embedded to have forward compatible implementations.
|
||||
type UnimplementedStaticHostUsersServiceServer struct {
|
||||
}
|
||||
// UnimplementedStaticHostUsersServiceServer must be embedded to have
|
||||
// forward compatible implementations.
|
||||
//
|
||||
// NOTE: this should be embedded by value instead of pointer to avoid a nil
|
||||
// pointer dereference when methods are called.
|
||||
type UnimplementedStaticHostUsersServiceServer struct{}
|
||||
|
||||
func (UnimplementedStaticHostUsersServiceServer) GetStaticHostUser(context.Context, *GetStaticHostUserRequest) (*StaticHostUser, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetStaticHostUser not implemented")
|
||||
@@ -175,6 +178,7 @@ func (UnimplementedStaticHostUsersServiceServer) DeleteStaticHostUser(context.Co
|
||||
}
|
||||
func (UnimplementedStaticHostUsersServiceServer) mustEmbedUnimplementedStaticHostUsersServiceServer() {
|
||||
}
|
||||
func (UnimplementedStaticHostUsersServiceServer) testEmbeddedByValue() {}
|
||||
|
||||
// UnsafeStaticHostUsersServiceServer may be embedded to opt out of forward compatibility for this service.
|
||||
// Use of this interface is not recommended, as added methods to StaticHostUsersServiceServer will
|
||||
@@ -184,6 +188,13 @@ type UnsafeStaticHostUsersServiceServer interface {
|
||||
}
|
||||
|
||||
func RegisterStaticHostUsersServiceServer(s grpc.ServiceRegistrar, srv StaticHostUsersServiceServer) {
|
||||
// If the following call pancis, it indicates UnimplementedStaticHostUsersServiceServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
|
||||
t.testEmbeddedByValue()
|
||||
}
|
||||
s.RegisterService(&StaticHostUsersService_ServiceDesc, srv)
|
||||
}
|
||||
|
||||
|
||||
@@ -4436,6 +4436,8 @@ message MaxAge {
|
||||
message SSOClientRedirectSettings {
|
||||
// a list of hostnames allowed for https client redirect URLs
|
||||
repeated string allowed_https_hostnames = 1;
|
||||
// a list of CIDRs allowed for HTTP or HTTPS client redirect URLs
|
||||
repeated string insecure_allowed_cidr_ranges = 2;
|
||||
}
|
||||
|
||||
// OIDCAuthRequest is a request to authenticate with OIDC
|
||||
|
||||
@@ -17,6 +17,7 @@ limitations under the License.
|
||||
package types
|
||||
|
||||
import (
|
||||
"net/netip"
|
||||
"net/url"
|
||||
"slices"
|
||||
"time"
|
||||
@@ -35,6 +36,11 @@ type OIDCConnector interface {
|
||||
// ResourceWithSecrets provides common methods for objects
|
||||
ResourceWithSecrets
|
||||
ResourceWithOrigin
|
||||
// Validate will preform checks not found in CheckAndSetDefaults
|
||||
// that should only be preformed when the OIDC connector resource
|
||||
// itself is being created or updated, not when a OIDCConnector
|
||||
// object is being created or updated.
|
||||
Validate() error
|
||||
// Issuer URL is the endpoint of the provider, e.g. https://accounts.google.com
|
||||
GetIssuerURL() string
|
||||
// ClientID is id for authentication client (in our case it's our Auth server)
|
||||
@@ -449,6 +455,23 @@ func (o *OIDCConnectorV3) CheckAndSetDefaults() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Validate will preform checks not found in CheckAndSetDefaults
|
||||
// that should only be preformed when the OIDC connector resource
|
||||
// itself is being created or updated, not when a OIDCConnector
|
||||
// object is being created or updated.
|
||||
func (o *OIDCConnectorV3) Validate() error {
|
||||
if o.Spec.ClientRedirectSettings != nil {
|
||||
for _, cidrStr := range o.Spec.ClientRedirectSettings.InsecureAllowedCidrRanges {
|
||||
_, err := netip.ParsePrefix(cidrStr)
|
||||
if err != nil {
|
||||
return trace.BadParameter("bad CIDR range in insecure_allowed_cidr_ranges '%s': %v", cidrStr, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetAllowUnverifiedEmail returns true if unverified emails should be allowed in received users.
|
||||
func (o *OIDCConnectorV3) GetAllowUnverifiedEmail() bool {
|
||||
return o.Spec.AllowUnverifiedEmail
|
||||
|
||||
+743
-692
File diff suppressed because it is too large
Load Diff
@@ -197,6 +197,35 @@ authentication succeeds, Teleport will retrieve SSH and X.509 certificates and
|
||||
store them in the `~/.tsh/keys/<clustername>` directory. The tool will also will
|
||||
add SSH cert to an SSH agent if there's one running.
|
||||
|
||||
### Changing Callback Address
|
||||
|
||||
The callback address can be changed if calling back to a remote machine
|
||||
instead of the local machine is required:
|
||||
|
||||
```code
|
||||
# --bind-addr sets the host and port tsh will listen on, and --callback changes
|
||||
# what link is displayed to the user
|
||||
$ tsh login --proxy=proxy.example.com --auth=github --bind-addr=localhost:1234 --callback https://remote.machine:1234
|
||||
```
|
||||
|
||||
For this to work the hostname or CIDR of the remote machine that will be used for
|
||||
the callback will need to be allowed via`spec.client_redirect_settings`:
|
||||
|
||||
```code
|
||||
spec:
|
||||
client_redirect_settings:
|
||||
# a list of hostnames allowed for HTTPS client redirect URLs
|
||||
# can be a regex pattern
|
||||
allowed_https_hostnames:
|
||||
- remote.machine
|
||||
- '*.app.github.dev'
|
||||
- '^\d+-[a-zA-Z0-9]+\.foo.internal$'
|
||||
# a list of CIDRs allowed for HTTP or HTTPS client redirect URLs
|
||||
insecure_allowed_cidr_ranges:
|
||||
- '192.168.1.0/24'
|
||||
- '2001:db8::/96'
|
||||
```
|
||||
|
||||
## Configuring SSO
|
||||
|
||||
Teleport works with SSO providers by relying on the concept of an
|
||||
|
||||
@@ -316,6 +316,7 @@ $ tsh login [<flags>] [<cluster>]
|
||||
| Name | Default Value(s) | Allowed Value(s) | Description |
|
||||
| - | - | - | - |
|
||||
| `--bind-addr` | none | host:port | Address in the form of host:port to bind to for login command webhook |
|
||||
| `--callback` | none | host:port | Override the base URL (host:port) of the link shown when opening a browser for cluster logins. Must be used with --bind-addr.
|
||||
| `-o, --out` | none | filepath | Identity output filepath |
|
||||
| `--format` | `file` | `file`, `openssh` or `kubernetes` | Identity format: file, openssh (for OpenSSH compatibility) or kubernetes (for kubeconfig) |
|
||||
| `--browser` | none | `none` | Set to 'none' to suppress opening system default browser for `tsh login` commands |
|
||||
|
||||
@@ -45,6 +45,7 @@ Optional:
|
||||
Optional:
|
||||
|
||||
- `allowed_https_hostnames` (List of String) a list of hostnames allowed for https client redirect URLs
|
||||
- `insecure_allowed_cidr_ranges` (List of String) a list of CIDRs allowed for HTTP or HTTPS client redirect URLs
|
||||
|
||||
|
||||
### Nested Schema for `spec.teams_to_logins`
|
||||
|
||||
@@ -59,6 +59,7 @@ Optional:
|
||||
Optional:
|
||||
|
||||
- `allowed_https_hostnames` (List of String) a list of hostnames allowed for https client redirect URLs
|
||||
- `insecure_allowed_cidr_ranges` (List of String) a list of CIDRs allowed for HTTP or HTTPS client redirect URLs
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -69,6 +69,7 @@ Optional:
|
||||
Optional:
|
||||
|
||||
- `allowed_https_hostnames` (List of String) a list of hostnames allowed for https client redirect URLs
|
||||
- `insecure_allowed_cidr_ranges` (List of String) a list of CIDRs allowed for HTTP or HTTPS client redirect URLs
|
||||
|
||||
|
||||
### Nested Schema for `spec.signing_key_pair`
|
||||
|
||||
@@ -76,6 +76,7 @@ Optional:
|
||||
Optional:
|
||||
|
||||
- `allowed_https_hostnames` (List of String) a list of hostnames allowed for https client redirect URLs
|
||||
- `insecure_allowed_cidr_ranges` (List of String) a list of CIDRs allowed for HTTP or HTTPS client redirect URLs
|
||||
|
||||
|
||||
### Nested Schema for `spec.teams_to_logins`
|
||||
|
||||
@@ -89,6 +89,7 @@ Optional:
|
||||
Optional:
|
||||
|
||||
- `allowed_https_hostnames` (List of String) a list of hostnames allowed for https client redirect URLs
|
||||
- `insecure_allowed_cidr_ranges` (List of String) a list of CIDRs allowed for HTTP or HTTPS client redirect URLs
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -115,6 +115,7 @@ Optional:
|
||||
Optional:
|
||||
|
||||
- `allowed_https_hostnames` (List of String) a list of hostnames allowed for https client redirect URLs
|
||||
- `insecure_allowed_cidr_ranges` (List of String) a list of CIDRs allowed for HTTP or HTTPS client redirect URLs
|
||||
|
||||
|
||||
### Nested Schema for `spec.signing_key_pair`
|
||||
|
||||
+7
@@ -55,6 +55,13 @@ spec:
|
||||
type: string
|
||||
nullable: true
|
||||
type: array
|
||||
insecure_allowed_cidr_ranges:
|
||||
description: a list of CIDRs allowed for HTTP or HTTPS client
|
||||
redirect URLs
|
||||
items:
|
||||
type: string
|
||||
nullable: true
|
||||
type: array
|
||||
type: object
|
||||
client_secret:
|
||||
description: ClientSecret is the Github OAuth app client secret.
|
||||
|
||||
+7
@@ -80,6 +80,13 @@ spec:
|
||||
type: string
|
||||
nullable: true
|
||||
type: array
|
||||
insecure_allowed_cidr_ranges:
|
||||
description: a list of CIDRs allowed for HTTP or HTTPS client
|
||||
redirect URLs
|
||||
items:
|
||||
type: string
|
||||
nullable: true
|
||||
type: array
|
||||
type: object
|
||||
client_secret:
|
||||
description: ClientSecret is used to authenticate the client.
|
||||
|
||||
+7
@@ -95,6 +95,13 @@ spec:
|
||||
type: string
|
||||
nullable: true
|
||||
type: array
|
||||
insecure_allowed_cidr_ranges:
|
||||
description: a list of CIDRs allowed for HTTP or HTTPS client
|
||||
redirect URLs
|
||||
items:
|
||||
type: string
|
||||
nullable: true
|
||||
type: array
|
||||
type: object
|
||||
display:
|
||||
description: Display controls how this connector is displayed.
|
||||
|
||||
@@ -62,3 +62,15 @@ spec:
|
||||
- name: "http://schemas.xmlsoap.org/claims/Group"
|
||||
value: "Users"
|
||||
roles: ["access"]
|
||||
|
||||
client_redirect_settings:
|
||||
# a list of hostnames allowed for HTTPS client redirect URLs
|
||||
# can be a regex pattern
|
||||
allowed_https_hostnames:
|
||||
- remote.machine
|
||||
- '*.app.github.dev'
|
||||
- '^\d+-[a-zA-Z0-9]+\.foo.internal$'
|
||||
# a list of CIDRs allowed for HTTP or HTTPS client redirect URLs
|
||||
insecure_allowed_cidr_ranges:
|
||||
- '192.168.1.0/24'
|
||||
- '2001:db8::/96'
|
||||
|
||||
@@ -20,3 +20,14 @@ spec:
|
||||
- editor
|
||||
organization: <github-org>
|
||||
team: <github-team>
|
||||
client_redirect_settings:
|
||||
# a list of hostnames allowed for HTTPS client redirect URLs
|
||||
# can be a regex pattern
|
||||
allowed_https_hostnames:
|
||||
- remote.machine
|
||||
- '*.app.github.dev'
|
||||
- '^\d+-[a-zA-Z0-9]+\.foo.internal$'
|
||||
# a list of CIDRs allowed for HTTP or HTTPS client redirect URLs
|
||||
insecure_allowed_cidr_ranges:
|
||||
- '192.168.1.0/24'
|
||||
- '2001:db8::/96'
|
||||
|
||||
@@ -33,4 +33,15 @@ spec:
|
||||
scope:
|
||||
- openid
|
||||
- email
|
||||
client_redirect_settings:
|
||||
# a list of hostnames allowed for HTTPS client redirect URLs
|
||||
# can be a regex pattern
|
||||
allowed_https_hostnames:
|
||||
- remote.machine
|
||||
- '*.app.github.dev'
|
||||
- '^\d+-[a-zA-Z0-9]+\.foo.internal$'
|
||||
# a list of CIDRs allowed for HTTP or HTTPS client redirect URLs
|
||||
insecure_allowed_cidr_ranges:
|
||||
- '192.168.1.0/24'
|
||||
- '2001:db8::/96'
|
||||
version: v3
|
||||
|
||||
@@ -21,4 +21,15 @@ spec:
|
||||
scope:
|
||||
- openid
|
||||
- email
|
||||
client_redirect_settings:
|
||||
# a list of hostnames allowed for HTTPS client redirect URLs
|
||||
# can be a regex pattern
|
||||
allowed_https_hostnames:
|
||||
- remote.machine
|
||||
- '*.app.github.dev'
|
||||
- '^\d+-[a-zA-Z0-9]+\.foo.internal$'
|
||||
# a list of CIDRs allowed for HTTP or HTTPS client redirect URLs
|
||||
insecure_allowed_cidr_ranges:
|
||||
- '192.168.1.0/24'
|
||||
- '2001:db8::/96'
|
||||
version: v3
|
||||
|
||||
@@ -16,4 +16,15 @@ spec:
|
||||
issuer_url: https://idp.example.com/
|
||||
redirect_url: https://mytenant.teleport.sh:443/v1/webapi/oidc/callback
|
||||
max_age: 24h
|
||||
client_redirect_settings:
|
||||
# a list of hostnames allowed for HTTPS client redirect URLs
|
||||
# can be a regex pattern
|
||||
allowed_https_hostnames:
|
||||
- remote.machine
|
||||
- '*.app.github.dev'
|
||||
- '^\d+-[a-zA-Z0-9]+\.foo.internal$'
|
||||
# a list of CIDRs allowed for HTTP or HTTPS client redirect URLs
|
||||
insecure_allowed_cidr_ranges:
|
||||
- '192.168.1.0/24'
|
||||
- '2001:db8::/96'
|
||||
version: v3
|
||||
|
||||
@@ -23,4 +23,15 @@ spec:
|
||||
issuer: ""
|
||||
service_provider_issuer: https://teleport.example.com:443/v1/webapi/saml/acs/onelogin
|
||||
sso: ""
|
||||
client_redirect_settings:
|
||||
# a list of hostnames allowed for HTTPS client redirect URLs
|
||||
# can be a regex pattern
|
||||
allowed_https_hostnames:
|
||||
- remote.machine
|
||||
- '*.app.github.dev'
|
||||
- '^\d+-[a-zA-Z0-9]+\.foo.internal$'
|
||||
# a list of CIDRs allowed for HTTP or HTTPS client redirect URLs
|
||||
insecure_allowed_cidr_ranges:
|
||||
- '192.168.1.0/24'
|
||||
- '2001:db8::/96'
|
||||
version: v2
|
||||
@@ -31,4 +31,15 @@ spec:
|
||||
# Optional SAML Single Logout endpoint. If set, logging out of Teleport
|
||||
# will also log the user out of the SAML provider session.
|
||||
single_logout_url: https://example.okta.com/app/your-app-id/slo/saml
|
||||
client_redirect_settings:
|
||||
# a list of hostnames allowed for HTTPS client redirect URLs
|
||||
# can be a regex pattern
|
||||
allowed_https_hostnames:
|
||||
- remote.machine
|
||||
- '*.app.github.dev'
|
||||
- '^\d+-[a-zA-Z0-9]+\.foo.internal$'
|
||||
# a list of CIDRs allowed for HTTP or HTTPS client redirect URLs
|
||||
insecure_allowed_cidr_ranges:
|
||||
- '192.168.1.0/24'
|
||||
- '2001:db8::/96'
|
||||
|
||||
@@ -55,6 +55,13 @@ spec:
|
||||
type: string
|
||||
nullable: true
|
||||
type: array
|
||||
insecure_allowed_cidr_ranges:
|
||||
description: a list of CIDRs allowed for HTTP or HTTPS client
|
||||
redirect URLs
|
||||
items:
|
||||
type: string
|
||||
nullable: true
|
||||
type: array
|
||||
type: object
|
||||
client_secret:
|
||||
description: ClientSecret is the Github OAuth app client secret.
|
||||
|
||||
@@ -80,6 +80,13 @@ spec:
|
||||
type: string
|
||||
nullable: true
|
||||
type: array
|
||||
insecure_allowed_cidr_ranges:
|
||||
description: a list of CIDRs allowed for HTTP or HTTPS client
|
||||
redirect URLs
|
||||
items:
|
||||
type: string
|
||||
nullable: true
|
||||
type: array
|
||||
type: object
|
||||
client_secret:
|
||||
description: ClientSecret is used to authenticate the client.
|
||||
|
||||
@@ -95,6 +95,13 @@ spec:
|
||||
type: string
|
||||
nullable: true
|
||||
type: array
|
||||
insecure_allowed_cidr_ranges:
|
||||
description: a list of CIDRs allowed for HTTP or HTTPS client
|
||||
redirect URLs
|
||||
items:
|
||||
type: string
|
||||
nullable: true
|
||||
type: array
|
||||
type: object
|
||||
display:
|
||||
description: Display controls how this connector is displayed.
|
||||
|
||||
@@ -2709,11 +2709,18 @@ func GenSchemaOIDCConnectorV3(ctx context.Context) (github_com_hashicorp_terrafo
|
||||
Type: github_com_hashicorp_terraform_plugin_framework_types.StringType,
|
||||
},
|
||||
"client_redirect_settings": {
|
||||
Attributes: github_com_hashicorp_terraform_plugin_framework_tfsdk.SingleNestedAttributes(map[string]github_com_hashicorp_terraform_plugin_framework_tfsdk.Attribute{"allowed_https_hostnames": {
|
||||
Description: "a list of hostnames allowed for https client redirect URLs",
|
||||
Optional: true,
|
||||
Type: github_com_hashicorp_terraform_plugin_framework_types.ListType{ElemType: github_com_hashicorp_terraform_plugin_framework_types.StringType},
|
||||
}}),
|
||||
Attributes: github_com_hashicorp_terraform_plugin_framework_tfsdk.SingleNestedAttributes(map[string]github_com_hashicorp_terraform_plugin_framework_tfsdk.Attribute{
|
||||
"allowed_https_hostnames": {
|
||||
Description: "a list of hostnames allowed for https client redirect URLs",
|
||||
Optional: true,
|
||||
Type: github_com_hashicorp_terraform_plugin_framework_types.ListType{ElemType: github_com_hashicorp_terraform_plugin_framework_types.StringType},
|
||||
},
|
||||
"insecure_allowed_cidr_ranges": {
|
||||
Description: "a list of CIDRs allowed for HTTP or HTTPS client redirect URLs",
|
||||
Optional: true,
|
||||
Type: github_com_hashicorp_terraform_plugin_framework_types.ListType{ElemType: github_com_hashicorp_terraform_plugin_framework_types.StringType},
|
||||
},
|
||||
}),
|
||||
Description: "ClientRedirectSettings defines which client redirect URLs are allowed for non-browser SSO logins other than the standard localhost ones.",
|
||||
Optional: true,
|
||||
},
|
||||
@@ -2918,11 +2925,18 @@ func GenSchemaSAMLConnectorV2(ctx context.Context) (github_com_hashicorp_terrafo
|
||||
Type: github_com_hashicorp_terraform_plugin_framework_types.StringType,
|
||||
},
|
||||
"client_redirect_settings": {
|
||||
Attributes: github_com_hashicorp_terraform_plugin_framework_tfsdk.SingleNestedAttributes(map[string]github_com_hashicorp_terraform_plugin_framework_tfsdk.Attribute{"allowed_https_hostnames": {
|
||||
Description: "a list of hostnames allowed for https client redirect URLs",
|
||||
Optional: true,
|
||||
Type: github_com_hashicorp_terraform_plugin_framework_types.ListType{ElemType: github_com_hashicorp_terraform_plugin_framework_types.StringType},
|
||||
}}),
|
||||
Attributes: github_com_hashicorp_terraform_plugin_framework_tfsdk.SingleNestedAttributes(map[string]github_com_hashicorp_terraform_plugin_framework_tfsdk.Attribute{
|
||||
"allowed_https_hostnames": {
|
||||
Description: "a list of hostnames allowed for https client redirect URLs",
|
||||
Optional: true,
|
||||
Type: github_com_hashicorp_terraform_plugin_framework_types.ListType{ElemType: github_com_hashicorp_terraform_plugin_framework_types.StringType},
|
||||
},
|
||||
"insecure_allowed_cidr_ranges": {
|
||||
Description: "a list of CIDRs allowed for HTTP or HTTPS client redirect URLs",
|
||||
Optional: true,
|
||||
Type: github_com_hashicorp_terraform_plugin_framework_types.ListType{ElemType: github_com_hashicorp_terraform_plugin_framework_types.StringType},
|
||||
},
|
||||
}),
|
||||
Description: "ClientRedirectSettings defines which client redirect URLs are allowed for non-browser SSO logins other than the standard localhost ones.",
|
||||
Optional: true,
|
||||
},
|
||||
@@ -3085,11 +3099,18 @@ func GenSchemaGithubConnectorV3(ctx context.Context) (github_com_hashicorp_terra
|
||||
Type: github_com_hashicorp_terraform_plugin_framework_types.StringType,
|
||||
},
|
||||
"client_redirect_settings": {
|
||||
Attributes: github_com_hashicorp_terraform_plugin_framework_tfsdk.SingleNestedAttributes(map[string]github_com_hashicorp_terraform_plugin_framework_tfsdk.Attribute{"allowed_https_hostnames": {
|
||||
Description: "a list of hostnames allowed for https client redirect URLs",
|
||||
Optional: true,
|
||||
Type: github_com_hashicorp_terraform_plugin_framework_types.ListType{ElemType: github_com_hashicorp_terraform_plugin_framework_types.StringType},
|
||||
}}),
|
||||
Attributes: github_com_hashicorp_terraform_plugin_framework_tfsdk.SingleNestedAttributes(map[string]github_com_hashicorp_terraform_plugin_framework_tfsdk.Attribute{
|
||||
"allowed_https_hostnames": {
|
||||
Description: "a list of hostnames allowed for https client redirect URLs",
|
||||
Optional: true,
|
||||
Type: github_com_hashicorp_terraform_plugin_framework_types.ListType{ElemType: github_com_hashicorp_terraform_plugin_framework_types.StringType},
|
||||
},
|
||||
"insecure_allowed_cidr_ranges": {
|
||||
Description: "a list of CIDRs allowed for HTTP or HTTPS client redirect URLs",
|
||||
Optional: true,
|
||||
Type: github_com_hashicorp_terraform_plugin_framework_types.ListType{ElemType: github_com_hashicorp_terraform_plugin_framework_types.StringType},
|
||||
},
|
||||
}),
|
||||
Description: "ClientRedirectSettings defines which client redirect URLs are allowed for non-browser SSO logins other than the standard localhost ones.",
|
||||
Optional: true,
|
||||
},
|
||||
@@ -28154,6 +28175,33 @@ func CopyOIDCConnectorV3FromTerraform(_ context.Context, tf github_com_hashicorp
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
a, ok := tf.Attrs["insecure_allowed_cidr_ranges"]
|
||||
if !ok {
|
||||
diags.Append(attrReadMissingDiag{"OIDCConnectorV3.Spec.ClientRedirectSettings.insecure_allowed_cidr_ranges"})
|
||||
} else {
|
||||
v, ok := a.(github_com_hashicorp_terraform_plugin_framework_types.List)
|
||||
if !ok {
|
||||
diags.Append(attrReadConversionFailureDiag{"OIDCConnectorV3.Spec.ClientRedirectSettings.insecure_allowed_cidr_ranges", "github.com/hashicorp/terraform-plugin-framework/types.List"})
|
||||
} else {
|
||||
obj.InsecureAllowedCidrRanges = make([]string, len(v.Elems))
|
||||
if !v.Null && !v.Unknown {
|
||||
for k, a := range v.Elems {
|
||||
v, ok := a.(github_com_hashicorp_terraform_plugin_framework_types.String)
|
||||
if !ok {
|
||||
diags.Append(attrReadConversionFailureDiag{"OIDCConnectorV3.Spec.ClientRedirectSettings.insecure_allowed_cidr_ranges", "github_com_hashicorp_terraform_plugin_framework_types.String"})
|
||||
} else {
|
||||
var t string
|
||||
if !v.Null && !v.Unknown {
|
||||
t = string(v.Value)
|
||||
}
|
||||
obj.InsecureAllowedCidrRanges[k] = t
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -29042,6 +29090,59 @@ func CopyOIDCConnectorV3ToTerraform(ctx context.Context, obj *github_com_gravita
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
a, ok := tf.AttrTypes["insecure_allowed_cidr_ranges"]
|
||||
if !ok {
|
||||
diags.Append(attrWriteMissingDiag{"OIDCConnectorV3.Spec.ClientRedirectSettings.insecure_allowed_cidr_ranges"})
|
||||
} else {
|
||||
o, ok := a.(github_com_hashicorp_terraform_plugin_framework_types.ListType)
|
||||
if !ok {
|
||||
diags.Append(attrWriteConversionFailureDiag{"OIDCConnectorV3.Spec.ClientRedirectSettings.insecure_allowed_cidr_ranges", "github.com/hashicorp/terraform-plugin-framework/types.ListType"})
|
||||
} else {
|
||||
c, ok := tf.Attrs["insecure_allowed_cidr_ranges"].(github_com_hashicorp_terraform_plugin_framework_types.List)
|
||||
if !ok {
|
||||
c = github_com_hashicorp_terraform_plugin_framework_types.List{
|
||||
|
||||
ElemType: o.ElemType,
|
||||
Elems: make([]github_com_hashicorp_terraform_plugin_framework_attr.Value, len(obj.InsecureAllowedCidrRanges)),
|
||||
Null: true,
|
||||
}
|
||||
} else {
|
||||
if c.Elems == nil {
|
||||
c.Elems = make([]github_com_hashicorp_terraform_plugin_framework_attr.Value, len(obj.InsecureAllowedCidrRanges))
|
||||
}
|
||||
}
|
||||
if obj.InsecureAllowedCidrRanges != nil {
|
||||
t := o.ElemType
|
||||
if len(obj.InsecureAllowedCidrRanges) != len(c.Elems) {
|
||||
c.Elems = make([]github_com_hashicorp_terraform_plugin_framework_attr.Value, len(obj.InsecureAllowedCidrRanges))
|
||||
}
|
||||
for k, a := range obj.InsecureAllowedCidrRanges {
|
||||
v, ok := tf.Attrs["insecure_allowed_cidr_ranges"].(github_com_hashicorp_terraform_plugin_framework_types.String)
|
||||
if !ok {
|
||||
i, err := t.ValueFromTerraform(ctx, github_com_hashicorp_terraform_plugin_go_tftypes.NewValue(t.TerraformType(ctx), nil))
|
||||
if err != nil {
|
||||
diags.Append(attrWriteGeneralError{"OIDCConnectorV3.Spec.ClientRedirectSettings.insecure_allowed_cidr_ranges", err})
|
||||
}
|
||||
v, ok = i.(github_com_hashicorp_terraform_plugin_framework_types.String)
|
||||
if !ok {
|
||||
diags.Append(attrWriteConversionFailureDiag{"OIDCConnectorV3.Spec.ClientRedirectSettings.insecure_allowed_cidr_ranges", "github.com/hashicorp/terraform-plugin-framework/types.String"})
|
||||
}
|
||||
v.Null = string(a) == ""
|
||||
}
|
||||
v.Value = string(a)
|
||||
v.Unknown = false
|
||||
c.Elems[k] = v
|
||||
}
|
||||
if len(obj.InsecureAllowedCidrRanges) > 0 {
|
||||
c.Null = false
|
||||
}
|
||||
}
|
||||
c.Unknown = false
|
||||
tf.Attrs["insecure_allowed_cidr_ranges"] = c
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
v.Unknown = false
|
||||
tf.Attrs["client_redirect_settings"] = v
|
||||
@@ -29675,6 +29776,33 @@ func CopySAMLConnectorV2FromTerraform(_ context.Context, tf github_com_hashicorp
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
a, ok := tf.Attrs["insecure_allowed_cidr_ranges"]
|
||||
if !ok {
|
||||
diags.Append(attrReadMissingDiag{"SAMLConnectorV2.Spec.ClientRedirectSettings.insecure_allowed_cidr_ranges"})
|
||||
} else {
|
||||
v, ok := a.(github_com_hashicorp_terraform_plugin_framework_types.List)
|
||||
if !ok {
|
||||
diags.Append(attrReadConversionFailureDiag{"SAMLConnectorV2.Spec.ClientRedirectSettings.insecure_allowed_cidr_ranges", "github.com/hashicorp/terraform-plugin-framework/types.List"})
|
||||
} else {
|
||||
obj.InsecureAllowedCidrRanges = make([]string, len(v.Elems))
|
||||
if !v.Null && !v.Unknown {
|
||||
for k, a := range v.Elems {
|
||||
v, ok := a.(github_com_hashicorp_terraform_plugin_framework_types.String)
|
||||
if !ok {
|
||||
diags.Append(attrReadConversionFailureDiag{"SAMLConnectorV2.Spec.ClientRedirectSettings.insecure_allowed_cidr_ranges", "github_com_hashicorp_terraform_plugin_framework_types.String"})
|
||||
} else {
|
||||
var t string
|
||||
if !v.Null && !v.Unknown {
|
||||
t = string(v.Value)
|
||||
}
|
||||
obj.InsecureAllowedCidrRanges[k] = t
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -30622,6 +30750,59 @@ func CopySAMLConnectorV2ToTerraform(ctx context.Context, obj *github_com_gravita
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
a, ok := tf.AttrTypes["insecure_allowed_cidr_ranges"]
|
||||
if !ok {
|
||||
diags.Append(attrWriteMissingDiag{"SAMLConnectorV2.Spec.ClientRedirectSettings.insecure_allowed_cidr_ranges"})
|
||||
} else {
|
||||
o, ok := a.(github_com_hashicorp_terraform_plugin_framework_types.ListType)
|
||||
if !ok {
|
||||
diags.Append(attrWriteConversionFailureDiag{"SAMLConnectorV2.Spec.ClientRedirectSettings.insecure_allowed_cidr_ranges", "github.com/hashicorp/terraform-plugin-framework/types.ListType"})
|
||||
} else {
|
||||
c, ok := tf.Attrs["insecure_allowed_cidr_ranges"].(github_com_hashicorp_terraform_plugin_framework_types.List)
|
||||
if !ok {
|
||||
c = github_com_hashicorp_terraform_plugin_framework_types.List{
|
||||
|
||||
ElemType: o.ElemType,
|
||||
Elems: make([]github_com_hashicorp_terraform_plugin_framework_attr.Value, len(obj.InsecureAllowedCidrRanges)),
|
||||
Null: true,
|
||||
}
|
||||
} else {
|
||||
if c.Elems == nil {
|
||||
c.Elems = make([]github_com_hashicorp_terraform_plugin_framework_attr.Value, len(obj.InsecureAllowedCidrRanges))
|
||||
}
|
||||
}
|
||||
if obj.InsecureAllowedCidrRanges != nil {
|
||||
t := o.ElemType
|
||||
if len(obj.InsecureAllowedCidrRanges) != len(c.Elems) {
|
||||
c.Elems = make([]github_com_hashicorp_terraform_plugin_framework_attr.Value, len(obj.InsecureAllowedCidrRanges))
|
||||
}
|
||||
for k, a := range obj.InsecureAllowedCidrRanges {
|
||||
v, ok := tf.Attrs["insecure_allowed_cidr_ranges"].(github_com_hashicorp_terraform_plugin_framework_types.String)
|
||||
if !ok {
|
||||
i, err := t.ValueFromTerraform(ctx, github_com_hashicorp_terraform_plugin_go_tftypes.NewValue(t.TerraformType(ctx), nil))
|
||||
if err != nil {
|
||||
diags.Append(attrWriteGeneralError{"SAMLConnectorV2.Spec.ClientRedirectSettings.insecure_allowed_cidr_ranges", err})
|
||||
}
|
||||
v, ok = i.(github_com_hashicorp_terraform_plugin_framework_types.String)
|
||||
if !ok {
|
||||
diags.Append(attrWriteConversionFailureDiag{"SAMLConnectorV2.Spec.ClientRedirectSettings.insecure_allowed_cidr_ranges", "github.com/hashicorp/terraform-plugin-framework/types.String"})
|
||||
}
|
||||
v.Null = string(a) == ""
|
||||
}
|
||||
v.Value = string(a)
|
||||
v.Unknown = false
|
||||
c.Elems[k] = v
|
||||
}
|
||||
if len(obj.InsecureAllowedCidrRanges) > 0 {
|
||||
c.Null = false
|
||||
}
|
||||
}
|
||||
c.Unknown = false
|
||||
tf.Attrs["insecure_allowed_cidr_ranges"] = c
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
v.Unknown = false
|
||||
tf.Attrs["client_redirect_settings"] = v
|
||||
@@ -31231,6 +31412,33 @@ func CopyGithubConnectorV3FromTerraform(_ context.Context, tf github_com_hashico
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
a, ok := tf.Attrs["insecure_allowed_cidr_ranges"]
|
||||
if !ok {
|
||||
diags.Append(attrReadMissingDiag{"GithubConnectorV3.Spec.ClientRedirectSettings.insecure_allowed_cidr_ranges"})
|
||||
} else {
|
||||
v, ok := a.(github_com_hashicorp_terraform_plugin_framework_types.List)
|
||||
if !ok {
|
||||
diags.Append(attrReadConversionFailureDiag{"GithubConnectorV3.Spec.ClientRedirectSettings.insecure_allowed_cidr_ranges", "github.com/hashicorp/terraform-plugin-framework/types.List"})
|
||||
} else {
|
||||
obj.InsecureAllowedCidrRanges = make([]string, len(v.Elems))
|
||||
if !v.Null && !v.Unknown {
|
||||
for k, a := range v.Elems {
|
||||
v, ok := a.(github_com_hashicorp_terraform_plugin_framework_types.String)
|
||||
if !ok {
|
||||
diags.Append(attrReadConversionFailureDiag{"GithubConnectorV3.Spec.ClientRedirectSettings.insecure_allowed_cidr_ranges", "github_com_hashicorp_terraform_plugin_framework_types.String"})
|
||||
} else {
|
||||
var t string
|
||||
if !v.Null && !v.Unknown {
|
||||
t = string(v.Value)
|
||||
}
|
||||
obj.InsecureAllowedCidrRanges[k] = t
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -32158,6 +32366,59 @@ func CopyGithubConnectorV3ToTerraform(ctx context.Context, obj *github_com_gravi
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
a, ok := tf.AttrTypes["insecure_allowed_cidr_ranges"]
|
||||
if !ok {
|
||||
diags.Append(attrWriteMissingDiag{"GithubConnectorV3.Spec.ClientRedirectSettings.insecure_allowed_cidr_ranges"})
|
||||
} else {
|
||||
o, ok := a.(github_com_hashicorp_terraform_plugin_framework_types.ListType)
|
||||
if !ok {
|
||||
diags.Append(attrWriteConversionFailureDiag{"GithubConnectorV3.Spec.ClientRedirectSettings.insecure_allowed_cidr_ranges", "github.com/hashicorp/terraform-plugin-framework/types.ListType"})
|
||||
} else {
|
||||
c, ok := tf.Attrs["insecure_allowed_cidr_ranges"].(github_com_hashicorp_terraform_plugin_framework_types.List)
|
||||
if !ok {
|
||||
c = github_com_hashicorp_terraform_plugin_framework_types.List{
|
||||
|
||||
ElemType: o.ElemType,
|
||||
Elems: make([]github_com_hashicorp_terraform_plugin_framework_attr.Value, len(obj.InsecureAllowedCidrRanges)),
|
||||
Null: true,
|
||||
}
|
||||
} else {
|
||||
if c.Elems == nil {
|
||||
c.Elems = make([]github_com_hashicorp_terraform_plugin_framework_attr.Value, len(obj.InsecureAllowedCidrRanges))
|
||||
}
|
||||
}
|
||||
if obj.InsecureAllowedCidrRanges != nil {
|
||||
t := o.ElemType
|
||||
if len(obj.InsecureAllowedCidrRanges) != len(c.Elems) {
|
||||
c.Elems = make([]github_com_hashicorp_terraform_plugin_framework_attr.Value, len(obj.InsecureAllowedCidrRanges))
|
||||
}
|
||||
for k, a := range obj.InsecureAllowedCidrRanges {
|
||||
v, ok := tf.Attrs["insecure_allowed_cidr_ranges"].(github_com_hashicorp_terraform_plugin_framework_types.String)
|
||||
if !ok {
|
||||
i, err := t.ValueFromTerraform(ctx, github_com_hashicorp_terraform_plugin_go_tftypes.NewValue(t.TerraformType(ctx), nil))
|
||||
if err != nil {
|
||||
diags.Append(attrWriteGeneralError{"GithubConnectorV3.Spec.ClientRedirectSettings.insecure_allowed_cidr_ranges", err})
|
||||
}
|
||||
v, ok = i.(github_com_hashicorp_terraform_plugin_framework_types.String)
|
||||
if !ok {
|
||||
diags.Append(attrWriteConversionFailureDiag{"GithubConnectorV3.Spec.ClientRedirectSettings.insecure_allowed_cidr_ranges", "github.com/hashicorp/terraform-plugin-framework/types.String"})
|
||||
}
|
||||
v.Null = string(a) == ""
|
||||
}
|
||||
v.Value = string(a)
|
||||
v.Unknown = false
|
||||
c.Elems[k] = v
|
||||
}
|
||||
if len(obj.InsecureAllowedCidrRanges) > 0 {
|
||||
c.Null = false
|
||||
}
|
||||
}
|
||||
c.Unknown = false
|
||||
tf.Attrs["insecure_allowed_cidr_ranges"] = c
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
v.Unknown = false
|
||||
tf.Attrs["client_redirect_settings"] = v
|
||||
|
||||
+52
-28
@@ -24,8 +24,11 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"net/netip"
|
||||
"net/url"
|
||||
"slices"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -909,6 +912,8 @@ func (a *Server) createGithubUser(ctx context.Context, p *CreateUserParams, dryR
|
||||
return user, nil
|
||||
}
|
||||
|
||||
const unknownRedirectHostnameErrMsg = "unknown custom client redirect URL hostname"
|
||||
|
||||
// ValidateClientRedirect checks a desktop client redirect URL for SSO logins
|
||||
// against some (potentially nil) settings from an auth connector; in the
|
||||
// current implementation, that means either "http" schema with a hostname of
|
||||
@@ -916,7 +921,10 @@ func (a *Server) createGithubUser(ctx context.Context, p *CreateUserParams, dryR
|
||||
// or "https" schema with a hostname that matches one in the https_hostname
|
||||
// list, a path of "/callback" and either an empty port or explicitly 443. The
|
||||
// settings are ignored and only localhost URLs are allowed if we're using an
|
||||
// ephemeral connector (in the SSO testing flow).
|
||||
// ephemeral connector (in the SSO testing flow). If the insecure_allowed_cidr_ranges
|
||||
// list is non-empty URLs in both the "http" and "https" schema are allowed
|
||||
// if the hostname is an IP address that is contained in a specified CIDR
|
||||
// range on any port.
|
||||
func ValidateClientRedirect(clientRedirect string, ssoTestFlow bool, settings *types.SSOClientRedirectSettings) error {
|
||||
if clientRedirect == "" {
|
||||
// empty redirects are non-functional and harmless, so we allow them as
|
||||
@@ -946,45 +954,61 @@ func ValidateClientRedirect(clientRedirect string, ssoTestFlow bool, settings *t
|
||||
}
|
||||
|
||||
// we checked everything but u.Scheme and u.Host now
|
||||
|
||||
switch u.Scheme {
|
||||
default:
|
||||
if u.Scheme != "http" && u.Scheme != "https" {
|
||||
return trace.BadParameter("invalid scheme in client redirect URL")
|
||||
}
|
||||
|
||||
case "http":
|
||||
switch u.Hostname() {
|
||||
default:
|
||||
return trace.BadParameter("invalid hostname in client redirect URL")
|
||||
case "localhost", "127.0.0.1", "::1":
|
||||
return nil
|
||||
}
|
||||
|
||||
case "https":
|
||||
if ssoTestFlow {
|
||||
return trace.AccessDenied("custom client redirect URLs are not allowed in SSO test")
|
||||
// allow HTTP redirects to local addresses
|
||||
allowedHTTPLocalAddrs := []string{"localhost", "127.0.0.1", "::1"}
|
||||
if u.Scheme == "http" && slices.Contains(allowedHTTPLocalAddrs, u.Hostname()) {
|
||||
return nil
|
||||
}
|
||||
|
||||
if ssoTestFlow {
|
||||
return trace.AccessDenied("custom client redirect URLs are not allowed in SSO test")
|
||||
}
|
||||
|
||||
if settings == nil {
|
||||
return trace.AccessDenied(unknownRedirectHostnameErrMsg)
|
||||
}
|
||||
|
||||
// allow HTTP or HTTPS redirects from IPs in specified CIDR ranges
|
||||
hostIP, err := netip.ParseAddr(u.Hostname())
|
||||
if err == nil {
|
||||
hostIP = hostIP.Unmap()
|
||||
|
||||
for _, cidrStr := range settings.InsecureAllowedCidrRanges {
|
||||
cidr, err := netip.ParsePrefix(cidrStr)
|
||||
if err != nil {
|
||||
slog.WarnContext(context.Background(), "error parsing OIDC connector CIDR prefix", "cidr", cidrStr, "err", err)
|
||||
continue
|
||||
}
|
||||
if cidr.Contains(hostIP) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if u.Scheme == "https" {
|
||||
switch u.Port() {
|
||||
default:
|
||||
return trace.BadParameter("invalid port in client redirect URL")
|
||||
case "", "443":
|
||||
}
|
||||
|
||||
var allowedHostnames []string
|
||||
if settings != nil {
|
||||
allowedHostnames = settings.AllowedHttpsHostnames
|
||||
for _, expression := range settings.AllowedHttpsHostnames {
|
||||
ok, err := utils.MatchString(u.Hostname(), expression)
|
||||
if err != nil {
|
||||
slog.WarnContext(context.Background(), "error compiling OIDC connector allowed HTTPS hostname regex", "regex", expression, "err", err)
|
||||
continue
|
||||
}
|
||||
if ok {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
ok, err := utils.SliceMatchesRegex(u.Hostname(), allowedHostnames)
|
||||
if err != nil {
|
||||
return trace.Wrap(err, "matching custom client redirect URL hostname")
|
||||
}
|
||||
if !ok {
|
||||
return trace.AccessDenied("unknown custom client redirect URL hostname")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
return trace.AccessDenied(unknownRedirectHostnameErrMsg)
|
||||
}
|
||||
|
||||
// populateGithubClaims builds a GithubClaims using queried
|
||||
|
||||
@@ -643,6 +643,9 @@ func TestValidateClientRedirect(t *testing.T) {
|
||||
"https://127.0.0.1:12345/callback",
|
||||
"https://localhost:12345/callback",
|
||||
"https://localhost/callback",
|
||||
"ftp://localhost/callback",
|
||||
"ftp://127.0.0.1/callback",
|
||||
"ftp://[::1]/callback",
|
||||
} {
|
||||
const ssoTestFlowFalse = false
|
||||
var defaultSettings *types.SSOClientRedirectSettings
|
||||
@@ -699,6 +702,60 @@ func TestValidateClientRedirect(t *testing.T) {
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("InsecureAllowedCidrRanges", func(t *testing.T) {
|
||||
for _, goodURL := range []string{
|
||||
"http://192.168.0.27/callback",
|
||||
"https://192.168.0.27/callback",
|
||||
"http://192.168.0.27:1337/callback",
|
||||
"https://192.168.0.27:1337/callback",
|
||||
"http://[2001:db8::aaaa:bbbb]/callback",
|
||||
"https://[2001:db8::aaaa:bbbb]/callback",
|
||||
"http://[2001:db8::aaaa:bbbb]:1337/callback",
|
||||
"https://[2001:db8::aaaa:bbbb]:1337/callback",
|
||||
"http://[2001:db8::1]/callback",
|
||||
"https://[2001:db8::1]/callback",
|
||||
"http://[2001:db8::1]:1337/callback",
|
||||
"https://[2001:db8::1]:1337/callback",
|
||||
} {
|
||||
const ssoTestFlowFalse = false
|
||||
settings := &types.SSOClientRedirectSettings{
|
||||
InsecureAllowedCidrRanges: []string{
|
||||
"192.168.0.0/24",
|
||||
"2001:db8::/96",
|
||||
},
|
||||
}
|
||||
require.NoError(t, ValidateClientRedirect(goodURL+"?secret_key=", ssoTestFlowFalse, settings))
|
||||
}
|
||||
|
||||
for _, badURL := range []string{
|
||||
"http://192.168.1.1/callback",
|
||||
"https://192.168.1.1/callback",
|
||||
"http://192.168.1.1:80/callback",
|
||||
"https://192.168.1.1:443/callback",
|
||||
"http://[2001:db8::1:aaaa:bbbb]/callback",
|
||||
"https://[2001:db8::1:aaaa:bbbb]/callback",
|
||||
"http://[2001:db8::1:aaaa:bbbb]:80/callback",
|
||||
"https://[2001:db8::1:aaaa:bbbb]:443/callback",
|
||||
"http://[2001:db9::]/callback",
|
||||
"https://[2001:db9::]/callback",
|
||||
"http://not.an.ip/callback",
|
||||
"https://not.an.ip/callback",
|
||||
"http://192.168.0.27/nocallback",
|
||||
"https://192.168.0.27/nocallback",
|
||||
"http://[2001:db8::1]/notacallback",
|
||||
"https://[2001:db8::1]/notacallback",
|
||||
} {
|
||||
const ssoTestFlowFalse = false
|
||||
settings := &types.SSOClientRedirectSettings{
|
||||
InsecureAllowedCidrRanges: []string{
|
||||
"192.168.0.0/24",
|
||||
"2001:db8::/96",
|
||||
},
|
||||
}
|
||||
require.Error(t, ValidateClientRedirect(badURL+"?secret_key=", ssoTestFlowFalse, settings))
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("SSOTestFlow", func(t *testing.T) {
|
||||
for _, goodURL := range []string{
|
||||
"http://127.0.0.1:12345/callback",
|
||||
|
||||
@@ -135,7 +135,12 @@ func NewRedirector(ctx context.Context, login SSHLoginSSO, config *RedirectorCon
|
||||
if err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
callbackURL.Scheme = "https"
|
||||
// Default to HTTPS if no scheme is specified.
|
||||
// This will allow users to specify an insecure HTTP URL but
|
||||
// the backend will verify if the callback URL is allowed.
|
||||
if callbackURL.Scheme == "" {
|
||||
callbackURL.Scheme = "https"
|
||||
}
|
||||
callbackAddr = callbackURL.String()
|
||||
}
|
||||
|
||||
|
||||
@@ -1246,6 +1246,9 @@ func (s *IdentityService) GetMFADevices(ctx context.Context, user string, withSe
|
||||
|
||||
// UpsertOIDCConnector upserts OIDC Connector
|
||||
func (s *IdentityService) UpsertOIDCConnector(ctx context.Context, connector types.OIDCConnector) (types.OIDCConnector, error) {
|
||||
if err := connector.Validate(); err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
rev := connector.GetRevision()
|
||||
value, err := services.MarshalOIDCConnector(connector)
|
||||
if err != nil {
|
||||
@@ -1267,6 +1270,9 @@ func (s *IdentityService) UpsertOIDCConnector(ctx context.Context, connector typ
|
||||
|
||||
// CreateOIDCConnector creates a new OIDC connector.
|
||||
func (s *IdentityService) CreateOIDCConnector(ctx context.Context, connector types.OIDCConnector) (types.OIDCConnector, error) {
|
||||
if err := connector.Validate(); err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
value, err := services.MarshalOIDCConnector(connector)
|
||||
if err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
@@ -1286,6 +1292,9 @@ func (s *IdentityService) CreateOIDCConnector(ctx context.Context, connector typ
|
||||
|
||||
// UpdateOIDCConnector updates an existing OIDC connector.
|
||||
func (s *IdentityService) UpdateOIDCConnector(ctx context.Context, connector types.OIDCConnector) (types.OIDCConnector, error) {
|
||||
if err := connector.Validate(); err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
value, err := services.MarshalOIDCConnector(connector)
|
||||
if err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
|
||||
Reference in New Issue
Block a user