Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Replace ComputeExternalAddress by param Server.ExternalWebUrl and rename Server.Port and Server.Address #378

Merged
merged 10 commits into from
Nov 22, 2023
2 changes: 1 addition & 1 deletion cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ func init() {
if err := viper.BindPFlag("Debug", rootCmd.PersistentFlags().Lookup("debug")); err != nil {
panic(err)
}
if err := viper.BindPFlag("Server.Port", portFlag); err != nil {
if err := viper.BindPFlag("Server.WebPort", portFlag); err != nil {
panic(err)
}
}
21 changes: 10 additions & 11 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -243,14 +243,6 @@ func CleanupTempResources() {
})
}

func ComputeExternalAddress() string {
config_url := param.Server_ExternalAddress.GetString()
if config_url != "" {
return config_url
}
return fmt.Sprintf("%v:%v", param.Server_Hostname.GetString(), param.Server_Port.GetInt())
}

func getConfigBase() (string, error) {
home, err := os.UserHomeDir()
if err != nil {
Expand Down Expand Up @@ -461,13 +453,20 @@ func InitServer() error {
viper.SetDefault("Server.Hostname", hostname)
viper.SetDefault("Xrootd.Sitename", hostname)

port := param.Xrootd_Port.GetInt()
if port != 443 {
viper.SetDefault("Origin.Url", fmt.Sprintf("https://%v:%v", param.Server_Hostname.GetString(), port))
xrootdPort := param.Xrootd_Port.GetInt()
if xrootdPort != 443 {
viper.SetDefault("Origin.Url", fmt.Sprintf("https://%v:%v", param.Server_Hostname.GetString(), xrootdPort))
} else {
viper.SetDefault("Origin.Url", fmt.Sprintf("https://%v", param.Server_Hostname.GetString()))
}

webPort := param.Server_WebPort.GetInt()
viper.SetDefault("Server.ExternalWebUrl", fmt.Sprint("https://", hostname, ":", webPort))
externalAddressStr := param.Server_ExternalWebUrl.GetString()
if _, err = url.Parse(externalAddressStr); err != nil {
return errors.Wrap(err, fmt.Sprint("Invalid Server.ExternalWebUrl: ", externalAddressStr))
}

setupTransport()

tokenRefreshInterval := param.Monitoring_TokenRefreshInterval.GetDuration()
Expand Down
6 changes: 3 additions & 3 deletions config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,11 +127,11 @@ func TestInitConfig(t *testing.T) {
InitConfig() // Should set up pelican.yaml, osdf.yaml and defaults.yaml

// Check if server address is correct by defaults.yaml
assert.Equal(t, "0.0.0.0", param.Server_Address.GetString())
assert.Equal(t, "0.0.0.0", param.Server_WebHost.GetString())
// Check that Federation Discovery url is correct by osdf.yaml
assert.Equal(t, "osg-htc.org", param.Federation_DiscoveryUrl.GetString())

viper.Set("Server.Address", "1.1.1.1") // should write to temp config file
viper.Set("Server.WebHost", "1.1.1.1") // should write to temp config file
if err := viper.WriteConfigAs(tempCfgFile.Name()); err != nil {
t.Fatalf("Failed to write to config file: %v", err)
}
Expand All @@ -140,7 +140,7 @@ func TestInitConfig(t *testing.T) {
InitConfig()

// Check if server address overrides the default
assert.Equal(t, "1.1.1.1", param.Server_Address.GetString())
assert.Equal(t, "1.1.1.1", param.Server_WebHost.GetString())
viper.Reset()

//Test if prefix is not set, should not be able to find osdfYaml configuration
Expand Down
4 changes: 2 additions & 2 deletions config/resources/defaults.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ Debug: false
Logging:
Level: "Error"
Server:
Port: 8444
Address: "0.0.0.0"
WebPort: 8444
WebHost: "0.0.0.0"
Director:
DefaultResponse: cache
Origin:
Expand Down
2 changes: 1 addition & 1 deletion director/director_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ func VerifyDirectorSDToken(strToken string) (bool, error) {
func CreateDirectorScrapeToken() (string, error) {
// We assume this function is only called on a director server,
// the external address of which should be the director's URL
directorURL := "https://" + config.ComputeExternalAddress()
directorURL := param.Server_ExternalWebUrl.GetString()
tokenExpireTime := param.Monitoring_TokenExpiresIn.GetDuration()

ads := ListServerAds([]ServerType{OriginType, CacheType})
Expand Down
30 changes: 17 additions & 13 deletions docs/parameters.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -237,9 +237,11 @@ components: ["client"]
############################
name: Origin.Url
description: >-
The origin's configured URL, as reported to XRootD.
type: string
default: Hostname
The origin's configured URL, as reported to XRootD. This is the file transfer endpoint for the origin.

This Url must not have the same port number as the one in Server.ExternalWebUrl (if any) or Server.WebPort
type: url
default: https://${Server.Hostname}:${Xrootd.Port}
components: ["origin"]
---
name: Origin.ExportVolume
Expand Down Expand Up @@ -483,25 +485,27 @@ root_default: /etc/pelican/certificates/tls.key
default: "$ConfigBase/certificates/tls.key"
components: ["origin", "nsregistry", "director"]
---
name: Server.Port
name: Server.WebPort
description: >-
The port number the Pelican web interface will be bound to.
The port number the Pelican web interface and internal web APIs will be bound to.
type: int
default: 8444
components: ["nsregistry", "director", "origin"]
components: ["origin", "director", "nsregistry"]
---
name: Server.Address
name: Server.WebHost
description: >-
A string-encoded IP address that the origin is configured to listen on.
A string-encoded IP address that the Pelican web engine is configured to listen on.
type: string
default: 0.0.0.0
components: ["origin"]
default: "0.0.0.0"
components: ["origin", "director", "nsregistry"]
---
name: Server.ExternalAddress
name: Server.ExternalWebUrl
description: >-
A URL indicating the server's address as it appears externally.
A URL indicating the Pelican web interface and internal web APIs address as it appears externally.

This URL must not have the same port number as the one in Origin.Url (if any) or Xrootd.Port
type: url
default: none
default: https://${Server.Hostname}:${Server.WebPort}
components: ["origin", "director", "nsregistry"]
---
name: Server.Hostname
Expand Down
2 changes: 1 addition & 1 deletion oa4mp/serve.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ func ConfigureOA4MP() (launcher daemon.Launcher, err error) {
oconf := oa4mpConfig{
ClientID: oauth2Client.ClientID,
ClientSecret: oauth2Client.ClientSecret,
IssuerURL: "https://" + config.ComputeExternalAddress() + "/api/v1.0/issuer",
IssuerURL: param.Server_ExternalWebUrl.GetString() + "/api/v1.0/issuer",
JwksLocation: param.Server_IssuerJwks.GetString(),
ScitokensServerLocation: param.Issuer_ScitokensServerLocation.GetString(),
}
Expand Down
6 changes: 1 addition & 5 deletions origin_ui/advertise.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ package origin_ui
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"net/url"
Expand Down Expand Up @@ -76,11 +75,8 @@ func AdvertiseOrigin() error {
return errors.New("Origin name isn't set")
}

// TODO: waiting on a different branch to merge origin URL generation
// The checkdefaults func that runs before the origin is served checks for and
// parses the originUrl, so it should be safe to just grab it as a string here.
originUrl := param.Origin_Url.GetString()
originWebUrl := fmt.Sprintf("https://%s", config.ComputeExternalAddress())
originWebUrl := param.Server_ExternalWebUrl.GetString()

// Here we instantiate the namespaceAd slice, but we still need to define the namespace
namespaceUrl, err := url.Parse(param.Federation_NamespaceUrl.GetString())
Expand Down
8 changes: 2 additions & 6 deletions origin_ui/origin.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ import (
"math/rand"
"mime"
"net/http"
"net/url"
"os"
"os/signal"
"path"
Expand Down Expand Up @@ -91,7 +90,7 @@ func WaitUntilLogin(ctx context.Context) error {
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)

hostname := param.Server_Hostname.GetString()
port := param.Server_Port.GetInt()
port := param.Server_WebPort.GetInt()
isTTY := false
if term.IsTerminal(int(os.Stdout.Fd())) {
isTTY = true
Expand Down Expand Up @@ -182,15 +181,12 @@ func setLoginCookie(ctx *gin.Context, user string) {
return
}

issuerURL := url.URL{}
issuerURL.Scheme = "https"
issuerURL.Host = config.ComputeExternalAddress()
now := time.Now()
tok, err := jwt.NewBuilder().
// TODO: We might want to come up with some names broader than this for a
// generic token for Web APIs, like web_ui.access
Claim("scope", "prometheus.read").
Issuer(issuerURL.String()).
Issuer(param.Server_ExternalWebUrl.GetString()).
IssuedAt(now).
Expiration(now.Add(30 * time.Minute)).
NotBefore(now).
Expand Down
8 changes: 2 additions & 6 deletions web_ui/authorization.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,10 +144,7 @@ func IssuerCheck(c *gin.Context, strToken string, anyOfTheScopes []string) error
return errors.Wrap(err, "Invalid JWT")
}

// The server URL for tokens not used for xrootd access should be
// from ComputeExternalAddress() as this will give you the address (and port)
// of the web service on the server
serverURL := "https://" + config.ComputeExternalAddress()
serverURL := param.Server_ExternalWebUrl.GetString()
if serverURL != token.Issuer() {
if param.Origin_Url.GetString() == token.Issuer() {
return errors.New(fmt.Sprint("Wrong issuer; expect the issuer to be the server's web address but got Origin.URL, " + token.Issuer()))
Expand Down Expand Up @@ -217,8 +214,7 @@ func DirectorCheck(c *gin.Context, strToken string, anyOfTheScopes []string) err
// Create a token for accessing Prometheus /metrics endpoint on
// the server itself
func CreatePromMetricToken() (string, error) {
serverURL := "https://" + config.ComputeExternalAddress()

serverURL := param.Server_ExternalWebUrl.GetString()
tokenExpireTime := param.Monitoring_TokenExpiresIn.GetDuration()

tok, err := jwt.NewBuilder().
Expand Down
15 changes: 8 additions & 7 deletions web_ui/prometheus.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ import (
"github.com/grafana/regexp"
"github.com/mwitkow/go-conntrack"
"github.com/oklog/run"
pelican_config "github.com/pelicanplatform/pelican/config"
"github.com/pelicanplatform/pelican/director"
"github.com/pelicanplatform/pelican/param"
"github.com/prometheus/client_golang/prometheus"
Expand Down Expand Up @@ -161,9 +160,9 @@ func promQueryEngineAuthHandler(av1 *route.Router) gin.HandlerFunc {

// Configure director's Prometheus scraper to use HTTP service discovery for origins
func configDirectorPromScraper() (*config.ScrapeConfig, error) {
originDiscoveryUrl, err := url.Parse("https://" + pelican_config.ComputeExternalAddress())
originDiscoveryUrl, err := url.Parse(param.Server_ExternalWebUrl.GetString())
if err != nil {
return nil, fmt.Errorf("parse external URL https://%v: %w", pelican_config.ComputeExternalAddress(), err)
return nil, fmt.Errorf("parse external URL %v: %w", param.Server_ExternalWebUrl.GetString(), err)
}
sdToken, err := director.CreateDirectorSDToken()
if err != nil {
Expand Down Expand Up @@ -275,7 +274,7 @@ func (a LogrusAdapter) Log(keyvals ...interface{}) error {

func ConfigureEmbeddedPrometheus(engine *gin.Engine, isDirector bool) error {
cfg := flagConfig{}
ListenAddress := fmt.Sprintf("0.0.0.0:%v", param.Server_Port.GetInt())
ListenAddress := fmt.Sprintf("0.0.0.0:%v", param.Server_WebPort.GetInt())
cfg.webTimeout = model.Duration(5 * time.Minute)
cfg.serverStoragePath = param.Monitoring_DataLocation.GetString()

Expand Down Expand Up @@ -320,9 +319,9 @@ func ConfigureEmbeddedPrometheus(engine *gin.Engine, isDirector bool) error {

localStoragePath := cfg.serverStoragePath

external_url, err := url.Parse("https://" + pelican_config.ComputeExternalAddress())
external_url, err := url.Parse(param.Server_ExternalWebUrl.GetString())
if err != nil {
return fmt.Errorf("parse external URL https://%v: %w", pelican_config.ComputeExternalAddress(), err)
return fmt.Errorf("parse external URL %v: %w", param.Server_ExternalWebUrl.GetString(), err)
}

CORSOrigin, err := compileCORSRegexString(".*")
Expand Down Expand Up @@ -357,10 +356,12 @@ func ConfigureEmbeddedPrometheus(engine *gin.Engine, isDirector bool) error {
}
scrapeConfig.HTTPClientConfig = scraperHttpClientConfig
scrapeConfig.ServiceDiscoveryConfigs = make([]discovery.Config, 1)
// model.AddressLabel needs a hostname (w/ port), so we cut the protocol here
externalAddressWoProtocol, _ := strings.CutPrefix(param.Server_ExternalWebUrl.GetString(), "https://")
scrapeConfig.ServiceDiscoveryConfigs[0] = discovery.StaticConfig{
&targetgroup.Group{
Targets: []model.LabelSet{{
model.AddressLabel: model.LabelValue(pelican_config.ComputeExternalAddress()),
model.AddressLabel: model.LabelValue(externalAddressWoProtocol),
}},
},
}
Expand Down
14 changes: 5 additions & 9 deletions web_ui/prometheus_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ func TestPrometheusProtectionOriginHeaderScope(t *testing.T) {

viper.Reset()
viper.Set("Server.Hostname", "test-https")
viper.Set("Server.Port", "8444")
viper.Set("Server.WebPort", "8444")

av1 := route.New().WithPrefix("/api/v1.0/prometheus")

Expand Down Expand Up @@ -204,10 +204,6 @@ func TestPrometheusProtectionOriginHeaderScope(t *testing.T) {
}

// Create a token
issuerURL := url.URL{}
issuerURL.Host = config.ComputeExternalAddress()
issuerURL.Scheme = "https"

jti_bytes := make([]byte, 16)
_, err = rand.Read(jti_bytes)
if err != nil {
Expand All @@ -220,7 +216,7 @@ func TestPrometheusProtectionOriginHeaderScope(t *testing.T) {
Claim("scope", "prometheus.read").
Claim("wlcg.ver", "1.0").
JwtID(jti).
Issuer(issuerURL.String()).
Issuer(param.Server_ExternalWebUrl.GetString()).
Audience([]string{originUrl}).
Subject("sub").
Expiration(time.Now().Add(time.Minute)).
Expand Down Expand Up @@ -285,7 +281,7 @@ func TestPrometheusProtectionOriginHeaderScope(t *testing.T) {
Claim("scope", "prometheus.read").
Claim("wlcg.ver", "1.0").
JwtID(jti).
Issuer(issuerURL.String()).
Issuer(param.Server_ExternalWebUrl.GetString()).
Audience([]string{originUrl}).
Subject("sub").
Expiration(time.Now().Add(time.Minute)).
Expand Down Expand Up @@ -321,7 +317,7 @@ func TestPrometheusProtectionOriginHeaderScope(t *testing.T) {
Claim("scope", "not.prometheus").
Claim("wlcg.ver", "1.0").
JwtID(jti).
Issuer(issuerURL.String()).
Issuer(param.Server_ExternalWebUrl.GetString()).
Audience([]string{originUrl}).
Subject("sub").
Expiration(time.Now().Add(time.Minute)).
Expand Down Expand Up @@ -361,7 +357,7 @@ func TestPrometheusProtectionOriginHeaderScope(t *testing.T) {

now := time.Now()
tok, err = jwt.NewBuilder().
Issuer(issuerURL.String()).
Issuer(param.Server_ExternalWebUrl.GetString()).
Claim("scope", "prometheus.read").
Claim("wlcg.ver", "1.0").
IssuedAt(now).
Expand Down
2 changes: 1 addition & 1 deletion web_ui/ui.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ func RunEngine(engine *gin.Engine) {
certFile := param.Server_TLSCertificate.GetString()
keyFile := param.Server_TLSKey.GetString()

addr := fmt.Sprintf("%v:%v", param.Server_Address.GetString(), param.Server_Port.GetInt())
addr := fmt.Sprintf("%v:%v", param.Server_WebHost.GetString(), param.Server_WebPort.GetInt())

log.Debugln("Starting web engine at address", addr)
err := engine.RunTLS(addr, certFile, keyFile)
Expand Down