From 210120b8e98b821e80d218d27a66a9e7838c565f Mon Sep 17 00:00:00 2001 From: Brian Bockelman Date: Fri, 16 Aug 2024 08:54:35 -0500 Subject: [PATCH 1/3] Selectively enable client X509 authentication When a requested object matches a pre-configured set of paths, then indicate to the cache it should turn on client X509 authentication. This fixes support for legacy OSDF namespaces which may require the cache to use client X509 authentication when requesting from the origin because a token is not otherwise available. --- config/resources/osdf.yaml | 5 +++++ director/director.go | 7 +++++++ docs/parameters.yaml | 13 +++++++++++++ param/parameters.go | 1 + param/parameters_struct.go | 2 ++ xrootd/launch.go | 2 ++ 6 files changed, 30 insertions(+) diff --git a/config/resources/osdf.yaml b/config/resources/osdf.yaml index de9c88037..da148ef01 100644 --- a/config/resources/osdf.yaml +++ b/config/resources/osdf.yaml @@ -26,3 +26,8 @@ Federation: Registry: RequireCacheApproval: true RequireOriginApproval: true +Director: + X509ClientAuthenticationPrefixes: + - /xenon/PROTECTED + - /user/ligo + - /igwn diff --git a/director/director.go b/director/director.go index b160fc361..2ec3a29a2 100644 --- a/director/director.go +++ b/director/director.go @@ -798,6 +798,13 @@ func redirectToOrigin(ginCtx *gin.Context) { ginCtx.Header("X-Pelican-Broker", brokerUrl.String()) } + for _, prefix := range param.Director_X509ClientAuthenticationPrefixes.GetStringSlice() { + if strings.HasPrefix(reqPath, prefix) { + ginCtx.Writer.Header().Add("X-Osdf-X509", "true") + break + } + } + // See note in RedirectToCache as to why we only add the authz query parameter to this URL, // not those in the `Link`. ginCtx.Redirect(http.StatusTemporaryRedirect, getFinalRedirectURL(redirectURL, reqParams)) diff --git a/docs/parameters.yaml b/docs/parameters.yaml index a4ce75510..37c87417a 100644 --- a/docs/parameters.yaml +++ b/docs/parameters.yaml @@ -1402,6 +1402,19 @@ type: bool default: false components: ["director"] --- +name: Director.X509ClientAuthenticationPrefixes +description: |+ + A list of object prefixes where the origin uses X.509 client authentication. + + If a cache requests an object starting with one of these prefixes, then it will be instructed by the director + to use X.509 client authentication if available. + + This setting allows for compatibility with specific legacy OSDF origins and is not needed for new origins. +type: stringSlice +default: none +components: ["director"] +hidden: true +--- ############################ # Registry-level configs # ############################ diff --git a/param/parameters.go b/param/parameters.go index 32360b1ef..82f8c6adb 100644 --- a/param/parameters.go +++ b/param/parameters.go @@ -279,6 +279,7 @@ var ( Director_CacheResponseHostnames = StringSliceParam{"Director.CacheResponseHostnames"} Director_FilteredServers = StringSliceParam{"Director.FilteredServers"} Director_OriginResponseHostnames = StringSliceParam{"Director.OriginResponseHostnames"} + Director_X509ClientAuthenticationPrefixes = StringSliceParam{"Director.X509ClientAuthenticationPrefixes"} Issuer_GroupRequirements = StringSliceParam{"Issuer.GroupRequirements"} Monitoring_AggregatePrefixes = StringSliceParam{"Monitoring.AggregatePrefixes"} Origin_ExportVolumes = StringSliceParam{"Origin.ExportVolumes"} diff --git a/param/parameters_struct.go b/param/parameters_struct.go index 32eb78faf..ac4d51a58 100644 --- a/param/parameters_struct.go +++ b/param/parameters_struct.go @@ -78,6 +78,7 @@ type Config struct { StatTimeout time.Duration `mapstructure:"stattimeout"` SupportContactEmail string `mapstructure:"supportcontactemail"` SupportContactUrl string `mapstructure:"supportcontacturl"` + X509ClientAuthenticationPrefixes []string `mapstructure:"x509clientauthenticationprefixes"` } `mapstructure:"director"` DisableHttpProxy bool `mapstructure:"disablehttpproxy"` DisableProxyFallback bool `mapstructure:"disableproxyfallback"` @@ -372,6 +373,7 @@ type configWithType struct { StatTimeout struct { Type string; Value time.Duration } SupportContactEmail struct { Type string; Value string } SupportContactUrl struct { Type string; Value string } + X509ClientAuthenticationPrefixes struct { Type string; Value []string } } DisableHttpProxy struct { Type string; Value bool } DisableProxyFallback struct { Type string; Value bool } diff --git a/xrootd/launch.go b/xrootd/launch.go index 76cce7924..a1ec277a6 100644 --- a/xrootd/launch.go +++ b/xrootd/launch.go @@ -84,6 +84,8 @@ func makeUnprivilegedXrootdLauncher(daemonName string, configPath string, isCach "XRD_PELICANBROKERSOCKET=" + filepath.Join(xrootdRun, "cache-reversal.sock"), "XRD_PLUGINCONFDIR=" + filepath.Join(xrootdRun, "cache-client.plugins.d"), "X509_CERT_FILE=" + filepath.Join(xrootdRun, "ca-bundle.crt"), + "XRD_PELICANCLIENTCERTFILE=" + filepath.Join(xrootdRun, "copied-tls-creds.crt"), + "XRD_PELICANCLIENTKEYFILE=" + filepath.Join(xrootdRun, "copied-tls-creds.crt"), } } return From ce74e85d507fe1d13691827cecdb6eb047e343f8 Mon Sep 17 00:00:00 2001 From: Brian Bockelman Date: Fri, 16 Aug 2024 13:40:37 -0500 Subject: [PATCH 2/3] Fix linter failures from new nil / len test. --- director/prom_query.go | 2 +- local_cache/local_cache.go | 2 +- registry/custom_reg_fields.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/director/prom_query.go b/director/prom_query.go index 8c4475c0f..59543eb6c 100644 --- a/director/prom_query.go +++ b/director/prom_query.go @@ -147,7 +147,7 @@ func parsePromRes(res promQLRes) (promParsed promQLParsed, err error) { ResultType: data.ResultType, } - if data.Result != nil && len(data.Result) > 0 { + if len(data.Result) > 0 { switch data.Result[0].(type) { case float64: // result: [unixtime, value] if len(data.Result) == 2 && (data.ResultType == "scalar" || data.ResultType == "string") { diff --git a/local_cache/local_cache.go b/local_cache/local_cache.go index fe3cd5f9b..40fb7af43 100644 --- a/local_cache/local_cache.go +++ b/local_cache/local_cache.go @@ -803,7 +803,7 @@ func (cr *cacheReader) peekError(ctx context.Context) (err error) { } func (cr *cacheReader) Read(p []byte) (n int, err error) { - if cr.buf != nil && len(cr.buf) > 0 { + if len(cr.buf) > 0 { bytesCopied := copy(p, cr.buf) if len(cr.buf) > bytesCopied { cr.buf = cr.buf[bytesCopied:] diff --git a/registry/custom_reg_fields.go b/registry/custom_reg_fields.go index 0cf78f3da..58c7d3559 100644 --- a/registry/custom_reg_fields.go +++ b/registry/custom_reg_fields.go @@ -282,7 +282,7 @@ func InitCustomRegistrationFields() error { return errors.New(fmt.Sprintf("Bad custom registration field, unsupported field type: %q with %q", conf.Name, conf.Type)) } if conf.Type == "enum" { - if (conf.Options == nil || len(conf.Options) == 0) && conf.OptionsUrl == "" { + if len(conf.Options) == 0 && conf.OptionsUrl == "" { return errors.New(fmt.Sprintf("Bad custom registration field, 'enum' type field does not have options or optionsUrl set: %q", conf.Name)) } } From 9e4dfd295282bd200edc333021bf7d026edb5d73 Mon Sep 17 00:00:00 2001 From: Justin Hiemstra Date: Mon, 19 Aug 2024 16:43:11 +0000 Subject: [PATCH 3/3] Add trailing / to x509 prefixes --- config/resources/osdf.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/config/resources/osdf.yaml b/config/resources/osdf.yaml index da148ef01..32bd8a6e0 100644 --- a/config/resources/osdf.yaml +++ b/config/resources/osdf.yaml @@ -28,6 +28,6 @@ Registry: RequireOriginApproval: true Director: X509ClientAuthenticationPrefixes: - - /xenon/PROTECTED - - /user/ligo - - /igwn + - /xenon/PROTECTED/ + - /user/ligo/ + - /igwn/