feat: add strip_email_domain to normalization of namespace
This commit is contained in:
parent
7e4709c13f
commit
4f1f235a2e
7
app.go
7
app.go
|
@ -107,9 +107,10 @@ type Config struct {
|
|||
}
|
||||
|
||||
type OIDCConfig struct {
|
||||
Issuer string
|
||||
ClientID string
|
||||
ClientSecret string
|
||||
Issuer string
|
||||
ClientID string
|
||||
ClientSecret string
|
||||
StripEmaildomain bool
|
||||
}
|
||||
|
||||
type DERPConfig struct {
|
||||
|
|
|
@ -63,6 +63,8 @@ func LoadConfig(path string) error {
|
|||
viper.SetDefault("cli.timeout", "5s")
|
||||
viper.SetDefault("cli.insecure", false)
|
||||
|
||||
viper.SetDefault("oidc.strip_email_domain", true)
|
||||
|
||||
if err := viper.ReadInConfig(); err != nil {
|
||||
return fmt.Errorf("fatal error reading config file: %w", err)
|
||||
}
|
||||
|
@ -323,9 +325,10 @@ func getHeadscaleConfig() headscale.Config {
|
|||
UnixSocketPermission: GetFileMode("unix_socket_permission"),
|
||||
|
||||
OIDC: headscale.OIDCConfig{
|
||||
Issuer: viper.GetString("oidc.issuer"),
|
||||
ClientID: viper.GetString("oidc.client_id"),
|
||||
ClientSecret: viper.GetString("oidc.client_secret"),
|
||||
Issuer: viper.GetString("oidc.issuer"),
|
||||
ClientID: viper.GetString("oidc.client_id"),
|
||||
ClientSecret: viper.GetString("oidc.client_secret"),
|
||||
StripEmaildomain: viper.GetBool("oidc.strip_email_domain"),
|
||||
},
|
||||
|
||||
CLI: headscale.CLIConfig{
|
||||
|
|
|
@ -180,3 +180,9 @@ unix_socket_permission: "0770"
|
|||
# client_id: "your-oidc-client-id"
|
||||
# client_secret: "your-oidc-client-secret"
|
||||
#
|
||||
# If `strip_email_domain` is set to `true`, the domain part of the username email address will be removed.
|
||||
# This will transform `first-name.last-name@example.com` to the namespace `first-name.last-name`
|
||||
# If `strip_email_domain` is set to `false` the domain part will NOT be removed resulting to the following
|
||||
# namespace: `first-name.last-name.example.com`
|
||||
#
|
||||
# strip_email_domain: true
|
||||
|
|
|
@ -268,10 +268,15 @@ func (n *Namespace) toProto() *v1.Namespace {
|
|||
|
||||
// NormalizeNamespaceName will replace forbidden chars in namespace
|
||||
// it can also return an error if the namespace doesn't respect RFC 952 and 1123.
|
||||
func NormalizeNamespaceName(name string) (string, error) {
|
||||
func NormalizeNamespaceName(name string, stripEmailDomain bool) (string, error) {
|
||||
name = strings.ToLower(name)
|
||||
name = strings.ReplaceAll(name, "@", ".")
|
||||
name = strings.ReplaceAll(name, "'", "")
|
||||
if stripEmailDomain {
|
||||
idx := strings.Index(name, "@")
|
||||
name = name[:idx]
|
||||
} else {
|
||||
name = strings.ReplaceAll(name, "@", ".")
|
||||
}
|
||||
name = invalidCharsInNamespaceRegex.ReplaceAllString(name, "-")
|
||||
|
||||
for _, elt := range strings.Split(name, ".") {
|
||||
|
|
|
@ -244,7 +244,8 @@ func (s *Suite) TestGetMapResponseUserProfiles(c *check.C) {
|
|||
|
||||
func TestNormalizeNamespaceName(t *testing.T) {
|
||||
type args struct {
|
||||
name string
|
||||
name string
|
||||
stripEmailDomain bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
|
@ -253,39 +254,63 @@ func TestNormalizeNamespaceName(t *testing.T) {
|
|||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "normalize simple name",
|
||||
args: args{name: "normalize-simple.name"},
|
||||
name: "normalize simple name",
|
||||
args: args{
|
||||
name: "normalize-simple.name",
|
||||
stripEmailDomain: false,
|
||||
},
|
||||
want: "normalize-simple.name",
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "normalize an email",
|
||||
args: args{name: "foo.bar@example.com"},
|
||||
name: "normalize an email",
|
||||
args: args{
|
||||
name: "foo.bar@example.com",
|
||||
stripEmailDomain: false,
|
||||
},
|
||||
want: "foo.bar.example.com",
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "normalize complex email",
|
||||
args: args{name: "foo.bar+complex-email@example.com"},
|
||||
name: "normalize an email domain should be removed",
|
||||
args: args{
|
||||
name: "foo.bar@example.com",
|
||||
stripEmailDomain: true,
|
||||
},
|
||||
want: "foo.bar",
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "normalize complex email",
|
||||
args: args{
|
||||
name: "foo.bar+complex-email@example.com",
|
||||
stripEmailDomain: false,
|
||||
},
|
||||
want: "foo.bar-complex-email.example.com",
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "namespace name with space",
|
||||
args: args{name: "name space"},
|
||||
name: "namespace name with space",
|
||||
args: args{
|
||||
name: "name space",
|
||||
stripEmailDomain: false,
|
||||
},
|
||||
want: "name-space",
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "namespace with quote",
|
||||
args: args{name: "Jamie's iPhone 5"},
|
||||
name: "namespace with quote",
|
||||
args: args{
|
||||
name: "Jamie's iPhone 5",
|
||||
stripEmailDomain: false,
|
||||
},
|
||||
want: "jamies-iphone-5",
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, err := NormalizeNamespaceName(tt.args.name)
|
||||
got, err := NormalizeNamespaceName(tt.args.name, tt.args.stripEmailDomain)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf(
|
||||
"NormalizeNamespaceName() error = %v, wantErr %v",
|
||||
|
|
2
oidc.go
2
oidc.go
|
@ -281,7 +281,7 @@ func (h *Headscale) OIDCCallback(ctx *gin.Context) {
|
|||
|
||||
now := time.Now().UTC()
|
||||
|
||||
namespaceName, err := NormalizeNamespaceName(claims.Email)
|
||||
namespaceName, err := NormalizeNamespaceName(claims.Email, h.cfg.OIDC.StripEmaildomain)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Caller().Msgf("couldn't normalize email")
|
||||
ctx.String(
|
||||
|
|
Loading…
Reference in New Issue